Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Or Gerlitz and committed by
Roland Dreier
2c4ce609 f470f8d4

+52 -15
+2 -1
drivers/infiniband/ulp/iser/iscsi_iser.h
··· 257 257 struct list_head conn_list; /* entry in ig conn list */ 258 258 259 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 262 unsigned int rx_desc_head; 262 263 struct iser_rx_desc *rx_descs; 263 264 struct ib_recv_wr rx_wr[ISER_MIN_POSTED_RX];
+24 -7
drivers/infiniband/ulp/iser/iser_initiator.c
··· 221 221 struct iser_device *device = ib_conn->device; 222 222 223 223 if (ib_conn->login_buf) { 224 - ib_dma_unmap_single(device->ib_device, ib_conn->login_dma, 225 - ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE); 224 + if (ib_conn->login_req_dma) 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 232 kfree(ib_conn->login_buf); 227 233 } 228 234 ··· 400 394 unsigned long data_seg_len; 401 395 int err = 0; 402 396 struct iser_device *device; 397 + struct iser_conn *ib_conn = iser_conn->ib_conn; 403 398 404 399 /* build the tx desc regd header and add it to the tx desc dto */ 405 400 mdesc->type = ISCSI_TX_CONTROL; ··· 416 409 iser_err("data present on non login task!!!\n"); 417 410 goto send_control_error; 418 411 } 419 - memcpy(iser_conn->ib_conn->login_buf, task->data, 412 + 413 + ib_dma_sync_single_for_cpu(device->ib_device, 414 + ib_conn->login_req_dma, task->data_count, 415 + DMA_TO_DEVICE); 416 + 417 + memcpy(iser_conn->ib_conn->login_req_buf, task->data, 420 418 task->data_count); 421 - tx_dsg->addr = iser_conn->ib_conn->login_dma; 419 + 420 + ib_dma_sync_single_for_device(device->ib_device, 421 + ib_conn->login_req_dma, task->data_count, 422 + DMA_TO_DEVICE); 423 + 424 + tx_dsg->addr = iser_conn->ib_conn->login_req_dma; 422 425 tx_dsg->length = task->data_count; 423 426 tx_dsg->lkey = device->mr->lkey; 424 427 mdesc->num_sge = 2; ··· 462 445 int rx_buflen, outstanding, count, err; 463 446 464 447 /* differentiate between login to all other PDUs */ 465 - if ((char *)rx_desc == ib_conn->login_buf) { 466 - rx_dma = ib_conn->login_dma; 448 + if ((char *)rx_desc == ib_conn->login_resp_buf) { 449 + rx_dma = ib_conn->login_resp_dma; 467 450 rx_buflen = ISER_RX_LOGIN_SIZE; 468 451 } else { 469 452 rx_dma = rx_desc->dma_addr; ··· 490 473 * for the posted rx bufs refcount to become zero handles everything */ 491 474 conn->ib_conn->post_recv_buf_count--; 492 475 493 - if (rx_dma == ib_conn->login_dma) 476 + if (rx_dma == ib_conn->login_resp_dma) 494 477 return; 495 478 496 479 outstanding = ib_conn->post_recv_buf_count;
+26 -7
drivers/infiniband/ulp/iser/iser_verbs.c
··· 155 155 { 156 156 struct iser_device *device; 157 157 struct ib_qp_init_attr init_attr; 158 - int ret = -ENOMEM; 158 + int req_err, resp_err, ret = -ENOMEM; 159 159 struct ib_fmr_pool_param params; 160 160 161 161 BUG_ON(ib_conn->device == NULL); 162 162 163 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 167 if (!ib_conn->login_buf) 167 168 goto out_err; 168 169 169 - ib_conn->login_dma = ib_dma_map_single(ib_conn->device->ib_device, 170 - (void *)ib_conn->login_buf, ISER_RX_LOGIN_SIZE, 171 - DMA_FROM_DEVICE); 170 + ib_conn->login_req_buf = ib_conn->login_buf; 171 + ib_conn->login_resp_buf = ib_conn->login_buf + ISCSI_DEF_MAX_RECV_SEG_LEN; 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 192 ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) + 174 193 (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)), ··· 677 658 struct ib_sge sge; 678 659 int ib_ret; 679 660 680 - sge.addr = ib_conn->login_dma; 661 + sge.addr = ib_conn->login_resp_dma; 681 662 sge.length = ISER_RX_LOGIN_SIZE; 682 663 sge.lkey = ib_conn->device->mr->lkey; 683 664 684 - rx_wr.wr_id = (unsigned long)ib_conn->login_buf; 665 + rx_wr.wr_id = (unsigned long)ib_conn->login_resp_buf; 685 666 rx_wr.sg_list = &sge; 686 667 rx_wr.num_sge = 1; 687 668 rx_wr.next = NULL;