aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h8
-rw-r--r--drivers/infiniband/ulp/iser/iser_initiator.c8
-rw-r--r--drivers/infiniband/ulp/iser/iser_memory.c209
3 files changed, 137 insertions, 88 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index a39645a54d82..262ba1f8ee50 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -222,12 +222,9 @@ enum iser_data_dir {
222 * @size: num entries of this sg 222 * @size: num entries of this sg
223 * @data_len: total beffer byte len 223 * @data_len: total beffer byte len
224 * @dma_nents: returned by dma_map_sg 224 * @dma_nents: returned by dma_map_sg
225 * @copy_buf: allocated copy buf for SGs unaligned
226 * for rdma which are copied
227 * @orig_sg: pointer to the original sg list (in case 225 * @orig_sg: pointer to the original sg list (in case
228 * we used a copy) 226 * we used a copy)
229 * @sg_single: SG-ified clone of a non SG SC or 227 * @orig_size: num entris of orig sg list
230 * unaligned SG
231 */ 228 */
232struct iser_data_buf { 229struct iser_data_buf {
233 struct scatterlist *sg; 230 struct scatterlist *sg;
@@ -235,8 +232,7 @@ struct iser_data_buf {
235 unsigned long data_len; 232 unsigned long data_len;
236 unsigned int dma_nents; 233 unsigned int dma_nents;
237 struct scatterlist *orig_sg; 234 struct scatterlist *orig_sg;
238 char *copy_buf; 235 unsigned int orig_size;
239 struct scatterlist sg_single;
240 }; 236 };
241 237
242/* fwd declarations */ 238/* fwd declarations */
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index b2e3b77340b5..3e2118e8ed87 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -674,28 +674,28 @@ void iser_task_rdma_finalize(struct iscsi_iser_task *iser_task)
674 /* if we were reading, copy back to unaligned sglist, 674 /* if we were reading, copy back to unaligned sglist,
675 * anyway dma_unmap and free the copy 675 * anyway dma_unmap and free the copy
676 */ 676 */
677 if (iser_task->data[ISER_DIR_IN].copy_buf) { 677 if (iser_task->data[ISER_DIR_IN].orig_sg) {
678 is_rdma_data_aligned = 0; 678 is_rdma_data_aligned = 0;
679 iser_finalize_rdma_unaligned_sg(iser_task, 679 iser_finalize_rdma_unaligned_sg(iser_task,
680 &iser_task->data[ISER_DIR_IN], 680 &iser_task->data[ISER_DIR_IN],
681 ISER_DIR_IN); 681 ISER_DIR_IN);
682 } 682 }
683 683
684 if (iser_task->data[ISER_DIR_OUT].copy_buf) { 684 if (iser_task->data[ISER_DIR_OUT].orig_sg) {
685 is_rdma_data_aligned = 0; 685 is_rdma_data_aligned = 0;
686 iser_finalize_rdma_unaligned_sg(iser_task, 686 iser_finalize_rdma_unaligned_sg(iser_task,
687 &iser_task->data[ISER_DIR_OUT], 687 &iser_task->data[ISER_DIR_OUT],
688 ISER_DIR_OUT); 688 ISER_DIR_OUT);
689 } 689 }
690 690
691 if (iser_task->prot[ISER_DIR_IN].copy_buf) { 691 if (iser_task->prot[ISER_DIR_IN].orig_sg) {
692 is_rdma_prot_aligned = 0; 692 is_rdma_prot_aligned = 0;
693 iser_finalize_rdma_unaligned_sg(iser_task, 693 iser_finalize_rdma_unaligned_sg(iser_task,
694 &iser_task->prot[ISER_DIR_IN], 694 &iser_task->prot[ISER_DIR_IN],
695 ISER_DIR_IN); 695 ISER_DIR_IN);
696 } 696 }
697 697
698 if (iser_task->prot[ISER_DIR_OUT].copy_buf) { 698 if (iser_task->prot[ISER_DIR_OUT].orig_sg) {
699 is_rdma_prot_aligned = 0; 699 is_rdma_prot_aligned = 0;
700 iser_finalize_rdma_unaligned_sg(iser_task, 700 iser_finalize_rdma_unaligned_sg(iser_task,
701 &iser_task->prot[ISER_DIR_OUT], 701 &iser_task->prot[ISER_DIR_OUT],
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
index abc979e62ae1..f0cdc961eb11 100644
--- a/drivers/infiniband/ulp/iser/iser_memory.c
+++ b/drivers/infiniband/ulp/iser/iser_memory.c
@@ -39,7 +39,112 @@
39 39
40#include "iscsi_iser.h" 40#include "iscsi_iser.h"
41 41
42#define ISER_KMALLOC_THRESHOLD 0x20000 /* 128K - kmalloc limit */ 42static void
43iser_free_bounce_sg(struct iser_data_buf *data)
44{
45 struct scatterlist *sg;
46 int count;
47
48 for_each_sg(data->sg, sg, data->size, count)
49 __free_page(sg_page(sg));
50
51 kfree(data->sg);
52
53 data->sg = data->orig_sg;
54 data->size = data->orig_size;
55 data->orig_sg = NULL;
56 data->orig_size = 0;
57}
58
59static int
60iser_alloc_bounce_sg(struct iser_data_buf *data)
61{
62 struct scatterlist *sg;
63 struct page *page;
64 unsigned long length = data->data_len;
65 int i = 0, nents = DIV_ROUND_UP(length, PAGE_SIZE);
66
67 sg = kcalloc(nents, sizeof(*sg), GFP_ATOMIC);
68 if (!sg)
69 goto err;
70
71 sg_init_table(sg, nents);
72 while (length) {
73 u32 page_len = min_t(u32, length, PAGE_SIZE);
74
75 page = alloc_page(GFP_ATOMIC);
76 if (!page)
77 goto err;
78
79 sg_set_page(&sg[i], page, page_len, 0);
80 length -= page_len;
81 i++;
82 }
83
84 data->orig_sg = data->sg;
85 data->orig_size = data->size;
86 data->sg = sg;
87 data->size = nents;
88
89 return 0;
90
91err:
92 for (; i > 0; i--)
93 __free_page(sg_page(&sg[i - 1]));
94 kfree(sg);
95
96 return -ENOMEM;
97}
98
99static void
100iser_copy_bounce(struct iser_data_buf *data, bool to_buffer)
101{
102 struct scatterlist *osg, *bsg = data->sg;
103 void *oaddr, *baddr;
104 unsigned int left = data->data_len;
105 unsigned int bsg_off = 0;
106 int i;
107
108 for_each_sg(data->orig_sg, osg, data->orig_size, i) {
109 unsigned int copy_len, osg_off = 0;
110
111 oaddr = kmap_atomic(sg_page(osg)) + osg->offset;
112 copy_len = min(left, osg->length);
113 while (copy_len) {
114 unsigned int len = min(copy_len, bsg->length - bsg_off);
115
116 baddr = kmap_atomic(sg_page(bsg)) + bsg->offset;
117 if (to_buffer)
118 memcpy(baddr + bsg_off, oaddr + osg_off, len);
119 else
120 memcpy(oaddr + osg_off, baddr + bsg_off, len);
121
122 kunmap_atomic(baddr - bsg->offset);
123 osg_off += len;
124 bsg_off += len;
125 copy_len -= len;
126
127 if (bsg_off >= bsg->length) {
128 bsg = sg_next(bsg);
129 bsg_off = 0;
130 }
131 }
132 kunmap_atomic(oaddr - osg->offset);
133 left -= osg_off;
134 }
135}
136
137static inline void
138iser_copy_from_bounce(struct iser_data_buf *data)
139{
140 iser_copy_bounce(data, false);
141}
142
143static inline void
144iser_copy_to_bounce(struct iser_data_buf *data)
145{
146 iser_copy_bounce(data, true);
147}
43 148
44struct fast_reg_descriptor * 149struct fast_reg_descriptor *
45iser_reg_desc_get(struct ib_conn *ib_conn) 150iser_reg_desc_get(struct ib_conn *ib_conn)
@@ -75,52 +180,32 @@ static int iser_start_rdma_unali