diff options
author | Or Gerlitz <ogerlitz@mellanox.com> | 2011-11-03 18:19:46 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2011-11-04 12:30:52 -0400 |
commit | 2c4ce609347f2a45792c8d9ebb5af11217766cb6 (patch) | |
tree | a78125a35d5a277d395003651b4241eafc7dd52d /drivers/infiniband | |
parent | f470f8d4e702593ee1d0852871ad80373bce707b (diff) |
IB/iser: Use separate buffers for the login request/response
The driver counted on the transactional nature of iSCSI login/text
flows and used the same buffer for both the request and the response.
We also went further and did DMA mapping only once, with
DMA_FROM_DEVICE, which violates the DMA mapping API. Fix that by
using different buffers, one for requests and one for responses, and
use the correct DMA mapping direction for each.
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/ulp/iser/iscsi_iser.h | 3 | ||||
-rw-r--r-- | drivers/infiniband/ulp/iser/iser_initiator.c | 31 | ||||
-rw-r--r-- | drivers/infiniband/ulp/iser/iser_verbs.c | 33 |
3 files changed, 52 insertions, 15 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h index db6f3ce9f3bf..2982a14a0557 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h | |||
@@ -257,7 +257,8 @@ struct iser_conn { | |||
257 | struct list_head conn_list; /* entry in ig conn list */ | 257 | struct list_head conn_list; /* entry in ig conn list */ |
258 | 258 | ||
259 | char *login_buf; | 259 | char *login_buf; |
260 | u64 login_dma; | 260 | char *login_req_buf, *login_resp_buf; |
261 | u64 login_req_dma, login_resp_dma; | ||
261 | unsigned int rx_desc_head; | 262 | unsigned int rx_desc_head; |
262 | struct iser_rx_desc *rx_descs; | 263 | struct iser_rx_desc *rx_descs; |
263 | struct ib_recv_wr rx_wr[ISER_MIN_POSTED_RX]; | 264 | struct ib_recv_wr rx_wr[ISER_MIN_POSTED_RX]; |
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c index f299de6b419b..a607542fc796 100644 --- a/drivers/infiniband/ulp/iser/iser_initiator.c +++ b/drivers/infiniband/ulp/iser/iser_initiator.c | |||
@@ -221,8 +221,14 @@ void iser_free_rx_descriptors(struct iser_conn *ib_conn) | |||
221 | struct iser_device *device = ib_conn->device; | 221 | struct iser_device *device = ib_conn->device; |
222 | 222 | ||
223 | if (ib_conn->login_buf) { | 223 | if (ib_conn->login_buf) { |
224 | ib_dma_unmap_single(device->ib_device, ib_conn->login_dma, | 224 | if (ib_conn->login_req_dma) |
225 | ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE); | 225 | ib_dma_unmap_single(device->ib_device, |
226 | ib_conn->login_req_dma, | ||
227 | ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE); | ||
228 | if (ib_conn->login_resp_dma) | ||
229 | ib_dma_unmap_single(device->ib_device, | ||
230 | ib_conn->login_resp_dma, | ||
231 | ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE); | ||
226 | kfree(ib_conn->login_buf); | 232 | kfree(ib_conn->login_buf); |
227 | } | 233 | } |
228 | 234 | ||
@@ -394,6 +400,7 @@ int iser_send_control(struct iscsi_conn *conn, | |||
394 | unsigned long data_seg_len; | 400 | unsigned long data_seg_len; |
395 | int err = 0; | 401 | int err = 0; |
396 | struct iser_device *device; | 402 | struct iser_device *device; |
403 | struct iser_conn *ib_conn = iser_conn->ib_conn; | ||
397 | 404 | ||
398 | /* build the tx desc regd header and add it to the tx desc dto */ | 405 | /* build the tx desc regd header and add it to the tx desc dto */ |
399 | mdesc->type = ISCSI_TX_CONTROL; | 406 | mdesc->type = ISCSI_TX_CONTROL; |
@@ -409,9 +416,19 @@ int iser_send_control(struct iscsi_conn *conn, | |||
409 | iser_err("data present on non login task!!!\n"); | 416 | iser_err("data present on non login task!!!\n"); |
410 | goto send_control_error; | 417 | goto send_control_error; |
411 | } | 418 | } |
412 | memcpy(iser_conn->ib_conn->login_buf, task->data, | 419 | |
420 | ib_dma_sync_single_for_cpu(device->ib_device, | ||
421 | ib_conn->login_req_dma, task->data_count, | ||
422 | DMA_TO_DEVICE); | ||
423 | |||
424 | memcpy(iser_conn->ib_conn->login_req_buf, task->data, | ||
413 | task->data_count); | 425 | task->data_count); |
414 | tx_dsg->addr = iser_conn->ib_conn->login_dma; | 426 | |
427 | ib_dma_sync_single_for_device(device->ib_device, | ||
428 | ib_conn->login_req_dma, task->data_count, | ||
429 | DMA_TO_DEVICE); | ||
430 | |||
431 | tx_dsg->addr = iser_conn->ib_conn->login_req_dma; | ||
415 | tx_dsg->length = task->data_count; | 432 | tx_dsg->length = task->data_count; |
416 | tx_dsg->lkey = device->mr->lkey; | 433 | tx_dsg->lkey = device->mr->lkey; |
417 | mdesc->num_sge = 2; | 434 | mdesc->num_sge = 2; |
@@ -445,8 +462,8 @@ void iser_rcv_completion(struct iser_rx_desc *rx_desc, | |||
445 | int rx_buflen, outstanding, count, err; | 462 | int rx_buflen, outstanding, count, err; |
446 | 463 | ||
447 | /* differentiate between login to all other PDUs */ | 464 | /* differentiate between login to all other PDUs */ |
448 | if ((char *)rx_desc == ib_conn->login_buf) { | 465 | if ((char *)rx_desc == ib_conn->login_resp_buf) { |
449 | rx_dma = ib_conn->login_dma; | 466 | rx_dma = ib_conn->login_resp_dma; |
450 | rx_buflen = ISER_RX_LOGIN_SIZE; | 467 | rx_buflen = ISER_RX_LOGIN_SIZE; |
451 | } else { | 468 | } else { |
452 | rx_dma = rx_desc->dma_addr; | 469 | rx_dma = rx_desc->dma_addr; |
@@ -473,7 +490,7 @@ void iser_rcv_completion(struct iser_rx_desc *rx_desc, | |||
473 | * for the posted rx bufs refcount to become zero handles everything */ | 490 | * for the posted rx bufs refcount to become zero handles everything */ |
474 | conn->ib_conn->post_recv_buf_count--; | 491 | conn->ib_conn->post_recv_buf_count--; |
475 | 492 | ||
476 | if (rx_dma == ib_conn->login_dma) | 493 | if (rx_dma == ib_conn->login_resp_dma) |
477 | return; | 494 | return; |
478 | 495 | ||
479 | outstanding = ib_conn->post_recv_buf_count; | 496 | outstanding = ib_conn->post_recv_buf_count; |
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index ede1475bee09..e28877c4ce15 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c | |||
@@ -155,20 +155,39 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) | |||
155 | { | 155 | { |
156 | struct iser_device *device; | 156 | struct iser_device *device; |
157 | struct ib_qp_init_attr init_attr; | 157 | struct ib_qp_init_attr init_attr; |
158 | int ret = -ENOMEM; | 158 | int req_err, resp_err, ret = -ENOMEM; |
159 | struct ib_fmr_pool_param params; | 159 | struct ib_fmr_pool_param params; |
160 | 160 | ||
161 | BUG_ON(ib_conn->device == NULL); | 161 | BUG_ON(ib_conn->device == NULL); |
162 | 162 | ||
163 | device = ib_conn->device; | 163 | device = ib_conn->device; |
164 | 164 | ||
165 | ib_conn->login_buf = kmalloc(ISER_RX_LOGIN_SIZE, GFP_KERNEL); | 165 | ib_conn->login_buf = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN + |
166 | ISER_RX_LOGIN_SIZE, GFP_KERNEL); | ||
166 | if (!ib_conn->login_buf) | 167 | if (!ib_conn->login_buf) |
167 | goto out_err; | 168 | goto out_err; |
168 | 169 | ||
169 | ib_conn->login_dma = ib_dma_map_single(ib_conn->device->ib_device, | 170 | ib_conn->login_req_buf = ib_conn->login_buf; |
170 | (void *)ib_conn->login_buf, ISER_RX_LOGIN_SIZE, | 171 | ib_conn->login_resp_buf = ib_conn->login_buf + ISCSI_DEF_MAX_RECV_SEG_LEN; |
171 | DMA_FROM_DEVICE); | 172 | |
173 | ib_conn->login_req_dma = ib_dma_map_single(ib_conn->device->ib_device, | ||
174 | (void *)ib_conn->login_req_buf, | ||
175 | ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE); | ||
176 | |||
177 | ib_conn->login_resp_dma = ib_dma_map_single(ib_conn->device->ib_device, | ||
178 | (void *)ib_conn->login_resp_buf, | ||
179 | ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE); | ||
180 | |||
181 | req_err = ib_dma_mapping_error(device->ib_device, ib_conn->login_req_dma); | ||
182 | resp_err = ib_dma_mapping_error(device->ib_device, ib_conn->login_resp_dma); | ||
183 | |||
184 | if (req_err || resp_err) { | ||
185 | if (req_err) | ||
186 | ib_conn->login_req_dma = 0; | ||
187 | if (resp_err) | ||
188 | ib_conn->login_resp_dma = 0; | ||
189 | goto out_err; | ||
190 | } | ||
172 | 191 | ||
173 | ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) + | 192 | ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) + |
174 | (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)), | 193 | (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)), |
@@ -658,11 +677,11 @@ int iser_post_recvl(struct iser_conn *ib_conn) | |||
658 | struct ib_sge sge; | 677 | struct ib_sge sge; |
659 | int ib_ret; | 678 | int ib_ret; |
660 | 679 | ||
661 | sge.addr = ib_conn->login_dma; | 680 | sge.addr = ib_conn->login_resp_dma; |
662 | sge.length = ISER_RX_LOGIN_SIZE; | 681 | sge.length = ISER_RX_LOGIN_SIZE; |
663 | sge.lkey = ib_conn->device->mr->lkey; | 682 | sge.lkey = ib_conn->device->mr->lkey; |
664 | 683 | ||
665 | rx_wr.wr_id = (unsigned long)ib_conn->login_buf; | 684 | rx_wr.wr_id = (unsigned long)ib_conn->login_resp_buf; |
666 | rx_wr.sg_list = &sge; | 685 | rx_wr.sg_list = &sge; |
667 | rx_wr.num_sge = 1; | 686 | rx_wr.num_sge = 1; |
668 | rx_wr.next = NULL; | 687 | rx_wr.next = NULL; |