aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/tcm_fc
diff options
context:
space:
mode:
authorAndy Grover <agrover@redhat.com>2011-07-20 15:13:28 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2011-07-22 05:37:48 -0400
commit05d1c7c0d0db4cc25548d9aadebb416888a82327 (patch)
tree290243526d188a7f6a683b0e13a63c7207471fa1 /drivers/target/tcm_fc
parente22a7f075226c51f3f71b922e9eeb4f99fac1475 (diff)
target: Make all control CDBs scatter-gather
Previously, some control CDBs did not allocate memory in pages for their data buffer, but just did a kmalloc. This patch makes all cdbs allocate pages. This has the benefit of streamlining some paths that had to behave differently when we used two allocation methods. The downside is that all accesses to the data buffer need to kmap it before use, and need to handle data in page-sized chunks if more than a page is needed for a given command's data buffer. Finally, note that cdbs with no data buffers are handled a little differently. Before, SCSI_NON_DATA_CDBs would not call get_mem at all (they'd be in the final else in transport_allocate_resources) but now these will make it into generic_get_mem, but just not allocate any buffers. Signed-off-by: Andy Grover <agrover@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target/tcm_fc')
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c4
-rw-r--r--drivers/target/tcm_fc/tfc_io.c61
2 files changed, 19 insertions, 46 deletions
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index a00951c80324..1017f56bbbcc 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -71,9 +71,9 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
71 caller, cmd, cmd->cdb); 71 caller, cmd, cmd->cdb);
72 printk(KERN_INFO "%s: cmd %p lun %d\n", caller, cmd, cmd->lun); 72 printk(KERN_INFO "%s: cmd %p lun %d\n", caller, cmd, cmd->lun);
73 73
74 printk(KERN_INFO "%s: cmd %p se_num %u buf %p len %u se_cmd_flags <0x%x>\n", 74 printk(KERN_INFO "%s: cmd %p se_num %u len %u se_cmd_flags <0x%x>\n",
75 caller, cmd, se_cmd->t_tasks_se_num, 75 caller, cmd, se_cmd->t_tasks_se_num,
76 se_cmd->t_task_buf, se_cmd->data_length, se_cmd->se_cmd_flags); 76 se_cmd->data_length, se_cmd->se_cmd_flags);
77 77
78 list_for_each_entry(mem, &se_cmd->t_mem_list, se_list) 78 list_for_each_entry(mem, &se_cmd->t_mem_list, se_list)
79 printk(KERN_INFO "%s: cmd %p mem %p page %p " 79 printk(KERN_INFO "%s: cmd %p mem %p page %p "
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c
index 8560182f0dad..837660728563 100644
--- a/drivers/target/tcm_fc/tfc_io.c
+++ b/drivers/target/tcm_fc/tfc_io.c
@@ -92,19 +92,15 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
92 remaining = se_cmd->data_length; 92 remaining = se_cmd->data_length;
93 93
94 /* 94 /*
95 * Setup to use first mem list entry if any. 95 * Setup to use first mem list entry, unless no data.
96 */ 96 */
97 if (se_cmd->t_tasks_se_num) { 97 BUG_ON(remaining && list_empty(&se_cmd->t_mem_list));
98 if (remaining) {
98 mem = list_first_entry(&se_cmd->t_mem_list, 99 mem = list_first_entry(&se_cmd->t_mem_list,
99 struct se_mem, se_list); 100 struct se_mem, se_list);
100 mem_len = mem->se_len; 101 mem_len = mem->se_len;
101 mem_off = mem->se_off; 102 mem_off = mem->se_off;
102 page = mem->se_page; 103 page = mem->se_page;
103 } else {
104 mem = NULL;
105 mem_len = remaining;
106 mem_off = 0;
107 page = NULL;
108 } 104 }
109 105
110 /* no scatter/gather in skb for odd word length due to fc_seq_send() */ 106 /* no scatter/gather in skb for odd word length due to fc_seq_send() */
@@ -145,18 +141,7 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
145 tlen = min(mem_len, frame_len); 141 tlen = min(mem_len, frame_len);
146 142
147 if (use_sg) { 143 if (use_sg) {
148 if (!mem) { 144 off_in_page = mem_off;
149 BUG_ON(!se_cmd->t_task_buf);
150 page_addr = se_cmd->t_task_buf + mem_off;
151 /*
152 * In this case, offset is 'offset_in_page' of
153 * (t_task_buf + mem_off) instead of 'mem_off'.
154 */
155 off_in_page = offset_in_page(page_addr);
156 page = virt_to_page(page_addr);
157 tlen = min(tlen, PAGE_SIZE - off_in_page);
158 } else
159 off_in_page = mem_off;
160 BUG_ON(!page); 145 BUG_ON(!page);
161 get_page(page); 146 get_page(page);
162 skb_fill_page_desc(fp_skb(fp), 147 skb_fill_page_desc(fp_skb(fp),
@@ -166,7 +151,7 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
166 fp_skb(fp)->data_len += tlen; 151 fp_skb(fp)->data_len += tlen;
167 fp_skb(fp)->truesize += 152 fp_skb(fp)->truesize +=
168 PAGE_SIZE << compound_order(page); 153 PAGE_SIZE << compound_order(page);
169 } else if (mem) { 154 } else {
170 BUG_ON(!page); 155 BUG_ON(!page);
171 from = kmap_atomic(page + (mem_off >> PAGE_SHIFT), 156 from = kmap_atomic(page + (mem_off >> PAGE_SHIFT),
172 KM_SOFTIRQ0); 157 KM_SOFTIRQ0);
@@ -177,10 +162,6 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
177 memcpy(to, from, tlen); 162 memcpy(to, from, tlen);
178 kunmap_atomic(page_addr, KM_SOFTIRQ0); 163 kunmap_atomic(page_addr, KM_SOFTIRQ0);
179 to += tlen; 164 to += tlen;
180 } else {
181 from = se_cmd->t_task_buf + mem_off;
182 memcpy(to, from, tlen);
183 to += tlen;
184 } 165 }
185 166
186 mem_off += tlen; 167 mem_off += tlen;
@@ -305,19 +286,15 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
305 frame_len = se_cmd->data_length - rel_off; 286 frame_len = se_cmd->data_length - rel_off;
306 287
307 /* 288 /*
308 * Setup to use first mem list entry if any. 289 * Setup to use first mem list entry, unless no data.
309 */ 290 */
310 if (se_cmd->t_tasks_se_num) { 291 BUG_ON(frame_len && list_empty(&se_cmd->t_mem_list));
292 if (frame_len) {
311 mem = list_first_entry(&se_cmd->t_mem_list, 293 mem = list_first_entry(&se_cmd->t_mem_list,
312 struct se_mem, se_list); 294 struct se_mem, se_list);
313 mem_len = mem->se_len; 295 mem_len = mem->se_len;
314 mem_off = mem->se_off; 296 mem_off = mem->se_off;
315 page = mem->se_page; 297 page = mem->se_page;
316 } else {
317 mem = NULL;
318 page = NULL;
319 mem_off = 0;
320 mem_len = frame_len;
321 } 298 }
322 299
323 while (frame_len) { 300 while (frame_len) {
@@ -340,19 +317,15 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
340 317
341 tlen = min(mem_len, frame_len); 318 tlen = min(mem_len, frame_len);
342 319
343 if (mem) { 320 to = kmap_atomic(page + (mem_off >> PAGE_SHIFT),
344 to = kmap_atomic(page + (mem_off >> PAGE_SHIFT), 321 KM_SOFTIRQ0);
345 KM_SOFTIRQ0); 322 page_addr = to;
346 page_addr = to; 323 to += mem_off & ~PAGE_MASK;
347 to += mem_off & ~PAGE_MASK; 324 tlen = min(tlen, (size_t)(PAGE_SIZE -
348 tlen = min(tlen, (size_t)(PAGE_SIZE - 325 (mem_off & ~PAGE_MASK)));
349 (mem_off & ~PAGE_MASK))); 326 memcpy(to, from, tlen);
350 memcpy(to, from, tlen); 327 kunmap_atomic(page_addr, KM_SOFTIRQ0);
351 kunmap_atomic(page_addr, KM_SOFTIRQ0); 328
352 } else {
353 to = se_cmd->t_task_buf + mem_off;
354 memcpy(to, from, tlen);
355 }
356 from += tlen; 329 from += tlen;
357 frame_len -= tlen; 330 frame_len -= tlen;
358 mem_off += tlen; 331 mem_off += tlen;