------------------------------------------------------------------------
r5427 | ogerlitz | 2006-02-16 14:55:12 +0200 (Thu, 16 Feb 2006) | 4 lines

various cleanups in the SG handling code

Signed-off-by: Or Gerlitz <[EMAIL PROTECTED]>

------------------------------------------------------------------------
r5426 | ogerlitz | 2006-02-16 14:52:23 +0200 (Thu, 16 Feb 2006) | 4 lines

fixes for the rare case of SGs which are unaligned for RDMA

Signed-off-by: Or Gerlitz <[EMAIL PROTECTED]>

------------------------------------------------------------------------

Index: iser_memory.c
===================================================================
--- iser_memory.c       (revision 5415)
+++ iser_memory.c       (revision 5426)
@@ -40,16 +40,7 @@
 
 #include "iscsi_iser.h"
 
-/**
- * iser_page_to_virt - Translates page descriptor to virtual kernel address
- * returns virtual kernel address
- */
-inline void *
-iser_page_to_virt(struct page *page)
-{
-    return phys_to_virt(page_to_phys(page));
-}
-
+#define ISER_KMALLOC_THRESHOLD 0x20000 /* 128K - kmalloc limit */
 /**
  * Decrements the reference count for the
  * registered buffer & releases it
@@ -141,22 +132,26 @@ void iser_start_rdma_unaligned_sg(struct
        struct iser_data_buf *p_mem = &p_iser_task->data[cmd_dir];
        unsigned long  cmd_data_len = iser_sg_size(p_mem);
 
-       mem = kmalloc(cmd_data_len, GFP_KERNEL | __GFP_NOFAIL);
+       if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
+               mem = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOFAIL,
+                     long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
+       else
+               mem = kmalloc(cmd_data_len, GFP_KERNEL | __GFP_NOFAIL);
+
        if (mem == NULL) {
                iser_bug("Failed to allocate mem size %d %d for copying 
sglist\n",
                         p_mem->size,(int)cmd_data_len);
        }
 
        if (cmd_dir == ISER_DIR_OUT) {
-               /* copy the sglist to p */
-               /* iser_data_buf_memcpy() */
+               /* copy the unaligned sg the buffer which is used for RDMA */
                struct scatterlist *p_sg = (struct scatterlist *)p_mem->p_buf;
                int i;
                char *p;
 
                for (p = mem, i = 0; i < p_mem->size; i++) {
                        memcpy(p,
-                              iser_page_to_virt(p_sg[i].page)+ p_sg[i].offset,
+                              page_address(p_sg[i].page) + p_sg[i].offset,
                               p_sg[i].length);
                        p += p_sg[i].length;
                }
@@ -207,17 +202,21 @@ void iser_finalize_rdma_unaligned_sg(str
                dma_unmap_single(dma_device, dma_addr, size, DMA_FROM_DEVICE);
                /* copy back read RDMA to unaligned sg */
                mem     = p_mem_copy->p_buf;
-               p_sg    = (struct scatterlist 
*)&p_iser_task->data[ISER_DIR_IN].p_buf;
+               p_sg    = (struct scatterlist 
*)p_iser_task->data[ISER_DIR_IN].p_buf;
                sg_size = p_iser_task->data[ISER_DIR_IN].size;
 
                for (p = mem, i = 0; i < sg_size; i++){
-                       memcpy(iser_page_to_virt(p_sg[i].page)+p_sg[i].offset,
+                       memcpy(page_address(p_sg[i].page) + p_sg[i].offset,
                               p,
                               p_sg[i].length);
                        p += p_sg[i].length;
                }
 
-               kfree(p_mem_copy->p_buf);
+               if (size > ISER_KMALLOC_THRESHOLD)
+                       free_pages((unsigned long)p_mem_copy->p_buf,
+                         long_log2(roundup_pow_of_two((int)size)) - 
PAGE_SHIFT);
+               else
+                       kfree(p_mem_copy->p_buf);
                p_mem_copy->p_buf = NULL;
        }
 
@@ -226,7 +225,11 @@ void iser_finalize_rdma_unaligned_sg(str
                size     = p_mem_copy->size;
                dma_addr = p_mem_copy->dma_addr;
                dma_unmap_single(dma_device, dma_addr, size, DMA_TO_DEVICE);
-               kfree(p_mem_copy->p_buf);
+               if (size > ISER_KMALLOC_THRESHOLD)
+                       free_pages((unsigned long)p_mem_copy->p_buf,
+                         long_log2(roundup_pow_of_two((int)size)) - 
PAGE_SHIFT);
+               else
+                       kfree(p_mem_copy->p_buf);
                p_mem_copy->p_buf = NULL;
        }
 }

Index: iscsi_iser.h
===================================================================
--- iscsi_iser.h        (revision 5426)
+++ iscsi_iser.h        (revision 5427)
@@ -173,11 +173,11 @@ enum iser_buf_type {
 };
 
 struct iser_data_buf {
-       void               *p_buf;
-       unsigned int       size;
-       enum iser_buf_type type;
-       dma_addr_t         dma_addr;
-       unsigned int       dma_nents;
+       enum iser_buf_type type;      /* single or scatterlist                */
+       void               *p_buf;    /* single -> data  scatterlist -> sg    */
+       unsigned int       size;      /* data len for single, nentries for sg */
+       dma_addr_t         dma_addr;  /* returned by dma_map_single           */
+       unsigned int       dma_nents; /* returned by dma_map_sg for           */
 };
 
 /* fwd declarations */
Index: iser_memory.c
===================================================================
--- iser_memory.c       (revision 5426)
+++ iser_memory.c       (revision 5427)
@@ -98,29 +98,21 @@ void iser_reg_single(struct iser_adaptor
        p_regd_buf->direction = direction;
 }
 
-static int iser_sg_subset_len(struct iser_data_buf *p_data,
-                             int skip_entries,
-                             int count_entries)
+
+/**
+ * iser_sg_size - returns the total data length in an sg list
+ */
+int iser_sg_size(struct iser_data_buf *p_data)
 {
        struct scatterlist *p_sg = (struct scatterlist *)p_data->p_buf;
-       int i, last_entry, total_len = 0;
+       int i, total_len=0;
 
-       last_entry = skip_entries + count_entries;
-       for (i = skip_entries; i < last_entry; i++)
+       for (i = 0; i < p_data->dma_nents; i++)
                total_len += sg_dma_len(&p_sg[i]);
        return total_len;
 }
 
 /**
- * iser_sg_size - returns the total data length in sg list
- */
-int iser_sg_size(struct iser_data_buf *p_mem)
-{
-       return
-               iser_sg_subset_len(p_mem, 0, p_mem->dma_nents);
-}
-
-/**
  * iser_start_rdma_unaligned_sg
  */
 void iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task  *p_iser_task,
@@ -130,7 +122,7 @@ void iser_start_rdma_unaligned_sg(struct
        struct device *dma_device;
        char *mem = NULL;
        struct iser_data_buf *p_mem = &p_iser_task->data[cmd_dir];
-       unsigned long  cmd_data_len = iser_sg_size(p_mem);
+       unsigned long  cmd_data_len = p_iser_task->data_len[cmd_dir];
 
        if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
                mem = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOFAIL,
@@ -247,8 +239,7 @@ void iser_finalize_rdma_unaligned_sg(str
  * consecutive elements. Also, it handles one entry SG.
  */
 static int iser_sg_to_page_vec(struct iser_data_buf *p_data,
-                              struct iser_page_vec *page_vec,
-                              int skip, int cnt)
+                              struct iser_page_vec *page_vec)
 {
        struct scatterlist *p_sg = (struct scatterlist *)p_data->p_buf;
        dma_addr_t first_addr, last_addr, page;
@@ -259,9 +250,9 @@ static int iser_sg_to_page_vec(struct is
 
        /* compute the offset of first element */
        /* FIXME page_vec->offset type should be dma_addr_t */
-       page_vec->offset = (u64) p_sg[skip].offset;
+       page_vec->offset = (u64) p_sg[0].offset;
 
-       for (i = skip; i < skip + cnt; i++) {
+       for (i = 0; i < p_data->dma_nents; i++) {
                total_sz += sg_dma_len(&p_sg[i]);
 
                first_addr = sg_dma_address(&p_sg[i]);
@@ -271,7 +262,7 @@ static int iser_sg_to_page_vec(struct is
                end_aligned   = !(last_addr  & ~PAGE_MASK);
 
                /* continue to collect page fragments till aligned or SG ends */
-               while (!end_aligned && (i + 1 < skip + cnt)) {
+               while (!end_aligned && (i + 1 < p_data->dma_nents)) {
                        i++;
                        total_sz += sg_dma_len(&p_sg[i]);
                        last_addr = sg_dma_address(&p_sg[i]) + 
sg_dma_len(&p_sg[i]);
@@ -330,19 +321,16 @@ static int iser_single_to_page_vec(struc
  * the number of entries which are aligned correctly. Supports the case where
  * consecutive SG elements are actually fragments of the same physcial page.
  */
-static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *p_data,
-                                             int skip)
+static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *p_data)
 {
        struct scatterlist *p_sg;
        dma_addr_t end_addr, next_addr;
        int i, cnt;
        unsigned int ret_len = 0;
 
-       if (p_data->type == ISER_BUF_TYPE_SINGLE)
-               return 1;
        p_sg = (struct scatterlist *)p_data->p_buf;
 
-       for (cnt = 0, i = skip; i < p_data->dma_nents; i++, cnt++) {
+       for (cnt = 0, i = 0; i < p_data->dma_nents; i++, cnt++) {
                /* iser_dbg("Checking sg iobuf [%d]: phys=0x%08lX "
                   "offset: %ld sz: %ld\n", i,
                   (unsigned long)page_to_phys(p_sg[i].page),
@@ -393,15 +381,11 @@ static void iser_data_buf_dump(struct is
  * iser_page_vec_alloc - allocate page_vec covering a given data buffer
  */
 static struct iser_page_vec *iser_page_vec_alloc(struct iser_data_buf *p_data,
-                                                int skip, int cnt)
+                                                int total_size)
 {
        struct iser_page_vec *page_vec;
-       int npages, total_size;
+       int npages;
 
-       if (p_data->type == ISER_BUF_TYPE_SINGLE)
-               total_size = p_data->size;
-       else
-               total_size = iser_sg_subset_len(p_data, skip, cnt);
        npages = total_size / PAGE_SIZE + 2;
 
        page_vec = kmalloc(sizeof(struct iser_page_vec) +
@@ -431,8 +415,7 @@ static void iser_dump_page_vec(struct is
 }
 
 static void iser_page_vec_build(struct iser_data_buf *p_data,
-                               struct iser_page_vec *page_vec,
-                               int skip, int cnt)
+                               struct iser_page_vec *page_vec)
 {
        int page_vec_len = 0;
 
@@ -441,9 +424,9 @@ static void iser_page_vec_build(struct i
                page_vec_len = iser_single_to_page_vec(p_data, page_vec);
        } else {
                iser_dbg("Translating sg sz: %d\n", p_data->dma_nents);
-               page_vec_len = iser_sg_to_page_vec(p_data,page_vec, skip,cnt);
-               iser_dbg("sg size %d skip %d cnt %d page_vec_len %d\n",
-                        p_data->dma_nents,skip,cnt,page_vec_len);
+               page_vec_len = iser_sg_to_page_vec(p_data,page_vec);
+               iser_dbg("sg len %d page_vec_len %d\n",
+                        p_data->dma_nents,page_vec_len);
        }
        page_vec->length = page_vec_len;
 
@@ -470,7 +453,7 @@ int iser_reg_rdma_mem(struct iscsi_iser_
        struct iser_data_buf *p_mem = &p_iser_task->data[cmd_dir];
        struct iser_page_vec *page_vec;
        struct iser_regd_buf *p_regd_buf;
-       int cnt_to_reg = 0;
+       int aligned_len;
        int err;
 
        p_regd_buf = &p_iser_task->rdma_regd[cmd_dir];
@@ -478,31 +461,23 @@ int iser_reg_rdma_mem(struct iscsi_iser_
        iser_dbg("p_mem %p p_mem->type %d\n", p_mem,p_mem->type);
 
        if (p_mem->type != ISER_BUF_TYPE_SINGLE) {
-               int aligned_len;
-
-               iser_dbg("converting sg to page_vec\n");
-               aligned_len = iser_data_buf_aligned_len(p_mem,0);
-               if (aligned_len == p_mem->size)
-                       cnt_to_reg = aligned_len;
-               else {
-                       iser_err("can't reg for rdma, alignment violation\n");
+               aligned_len = iser_data_buf_aligned_len(p_mem);
+               if (aligned_len != p_mem->size) {
+                       iser_err("rdma alignment violation %d/%d aligned\n",
+                                aligned_len, p_mem->size);
                        iser_data_buf_dump(p_mem);
                        /* allocate copy buf, if we are writing, copy the */
-                       /* unaligned scatterlist, anyway dma map the copy */
+                       /* unaligned scatterlist, dma map the copy        */
                        iser_start_rdma_unaligned_sg(p_iser_task, cmd_dir);
-                       p_regd_buf->virt_addr = 
p_iser_task->data_copy[cmd_dir].p_buf;
                        p_mem = &p_iser_task->data_copy[cmd_dir];
                }
-       } else {
-               iser_dbg("converting single to page_vec\n");
-               p_regd_buf->virt_addr = p_mem->p_buf;
        }
 
-       page_vec = iser_page_vec_alloc(p_mem,0,cnt_to_reg);
+       page_vec = iser_page_vec_alloc(p_mem, p_iser_task->data_len[cmd_dir]);
        if(!page_vec)
                return -ENOMEM;
 
-       iser_page_vec_build(p_mem, page_vec,0,cnt_to_reg);
+       iser_page_vec_build(p_mem, page_vec);
        err = iser_reg_page_vec(p_iser_conn,page_vec,&p_regd_buf->reg);
        kfree(page_vec);
        if(err)

_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to