enum dma_data_direction dir)
 {
        const bool vmalloced_buf = is_vmalloc_addr(buf);
-       const int desc_len = vmalloced_buf ? PAGE_SIZE : master->max_dma_len;
-       const int sgs = DIV_ROUND_UP(len, desc_len);
+       int desc_len;
+       int sgs;
        struct page *vm_page;
        void *sg_buf;
        size_t min;
        int i, ret;
 
+       if (vmalloced_buf) {
+               desc_len = PAGE_SIZE;
+               sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
+       } else {
+               desc_len = master->max_dma_len;
+               sgs = DIV_ROUND_UP(len, desc_len);
+       }
+
        ret = sg_alloc_table(sgt, sgs, GFP_KERNEL);
        if (ret != 0)
                return ret;
 
        for (i = 0; i < sgs; i++) {
-               min = min_t(size_t, len, desc_len);
 
                if (vmalloced_buf) {
+                       min = min_t(size_t,
+                                   len, desc_len - offset_in_page(buf));
                        vm_page = vmalloc_to_page(buf);
                        if (!vm_page) {
                                sg_free_table(sgt);
                        sg_set_page(&sgt->sgl[i], vm_page,
                                    min, offset_in_page(buf));
                } else {
+                       min = min_t(size_t, len, desc_len);
                        sg_buf = buf;
                        sg_set_buf(&sgt->sgl[i], sg_buf, min);
                }