mutex_unlock(&obj->mm.lock);
 }
 
-static unsigned int swiotlb_max_size(void)
-{
-#if IS_ENABLED(CONFIG_SWIOTLB)
-       return rounddown(swiotlb_nr_tbl() << IO_TLB_SHIFT, PAGE_SIZE);
-#else
-       return 0;
-#endif
-}
-
 static void i915_sg_trim(struct sg_table *orig_st)
 {
        struct sg_table new_st;
        GEM_BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS);
        GEM_BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS);
 
-       max_segment = swiotlb_max_size();
+       max_segment = swiotlb_max_segment();
        if (!max_segment)
                max_segment = rounddown(UINT_MAX, PAGE_SIZE);
 
 
 
 #ifdef CONFIG_SWIOTLB
 extern void __init swiotlb_free(void);
+unsigned int swiotlb_max_segment(void);
 #else
 static inline void swiotlb_free(void) { }
+static inline unsigned int swiotlb_max_segment(void) { return 0; }
 #endif
 
 extern void swiotlb_print_info(void);
 extern int is_swiotlb_buffer(phys_addr_t paddr);
+extern void swiotlb_set_max_segment(unsigned int);
 
 #endif /* __LINUX_SWIOTLB_H */
 
 static unsigned int *io_tlb_list;
 static unsigned int io_tlb_index;
 
+/*
+ * Max segment that we can provide which (if pages are contingous) will
+ * not be bounced (unless SWIOTLB_FORCE is set).
+ */
+unsigned int max_segment;
+
 /*
  * We need to save away the original address corresponding to a mapped entry
  * for the sync operations.
 }
 EXPORT_SYMBOL_GPL(swiotlb_nr_tbl);
 
+unsigned int swiotlb_max_segment(void)
+{
+       return max_segment;
+}
+EXPORT_SYMBOL_GPL(swiotlb_max_segment);
+
+void swiotlb_set_max_segment(unsigned int val)
+{
+       if (swiotlb_force == SWIOTLB_FORCE)
+               max_segment = 1;
+       else
+               max_segment = rounddown(val, PAGE_SIZE);
+}
+
 /* default to 64MB */
 #define IO_TLB_DEFAULT_SIZE (64UL<<20)
 unsigned long swiotlb_size_or_default(void)
        if (verbose)
                swiotlb_print_info();
 
+       swiotlb_set_max_segment(io_tlb_nslabs << IO_TLB_SHIFT);
        return 0;
 }
 
        rc = swiotlb_late_init_with_tbl(vstart, io_tlb_nslabs);
        if (rc)
                free_pages((unsigned long)vstart, order);
+
        return rc;
 }
 
 
        late_alloc = 1;
 
+       swiotlb_set_max_segment(io_tlb_nslabs << IO_TLB_SHIFT);
+
        return 0;
 
 cleanup4:
        io_tlb_end = 0;
        io_tlb_start = 0;
        io_tlb_nslabs = 0;
+       max_segment = 0;
        return -ENOMEM;
 }
 
                                   PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
        }
        io_tlb_nslabs = 0;
+       max_segment = 0;
 }
 
 int is_swiotlb_buffer(phys_addr_t paddr)