Commit 2c4ce609 authored by Or Gerlitz's avatar Or Gerlitz Committed by Roland Dreier

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: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent f470f8d4
...@@ -257,7 +257,8 @@ struct iser_conn { ...@@ -257,7 +257,8 @@ struct iser_conn {
struct list_head conn_list; /* entry in ig conn list */ struct list_head conn_list; /* entry in ig conn list */
char *login_buf; char *login_buf;
u64 login_dma; char *login_req_buf, *login_resp_buf;
u64 login_req_dma, login_resp_dma;
unsigned int rx_desc_head; unsigned int rx_desc_head;
struct iser_rx_desc *rx_descs; struct iser_rx_desc *rx_descs;
struct ib_recv_wr rx_wr[ISER_MIN_POSTED_RX]; struct ib_recv_wr rx_wr[ISER_MIN_POSTED_RX];
......
...@@ -221,8 +221,14 @@ void iser_free_rx_descriptors(struct iser_conn *ib_conn) ...@@ -221,8 +221,14 @@ void iser_free_rx_descriptors(struct iser_conn *ib_conn)
struct iser_device *device = ib_conn->device; struct iser_device *device = ib_conn->device;
if (ib_conn->login_buf) { if (ib_conn->login_buf) {
ib_dma_unmap_single(device->ib_device, ib_conn->login_dma, if (ib_conn->login_req_dma)
ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE); ib_dma_unmap_single(device->ib_device,
ib_conn->login_req_dma,
ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE);
if (ib_conn->login_resp_dma)
ib_dma_unmap_single(device->ib_device,
ib_conn->login_resp_dma,
ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
kfree(ib_conn->login_buf); kfree(ib_conn->login_buf);
} }
...@@ -394,6 +400,7 @@ int iser_send_control(struct iscsi_conn *conn, ...@@ -394,6 +400,7 @@ int iser_send_control(struct iscsi_conn *conn,
unsigned long data_seg_len; unsigned long data_seg_len;
int err = 0; int err = 0;
struct iser_device *device; struct iser_device *device;
struct iser_conn *ib_conn = iser_conn->ib_conn;
/* build the tx desc regd header and add it to the tx desc dto */ /* build the tx desc regd header and add it to the tx desc dto */
mdesc->type = ISCSI_TX_CONTROL; mdesc->type = ISCSI_TX_CONTROL;
...@@ -409,9 +416,19 @@ int iser_send_control(struct iscsi_conn *conn, ...@@ -409,9 +416,19 @@ int iser_send_control(struct iscsi_conn *conn,
iser_err("data present on non login task!!!\n"); iser_err("data present on non login task!!!\n");
goto send_control_error; goto send_control_error;
} }
memcpy(iser_conn->ib_conn->login_buf, task->data,
ib_dma_sync_single_for_cpu(device->ib_device,
ib_conn->login_req_dma, task->data_count,
DMA_TO_DEVICE);
memcpy(iser_conn->ib_conn->login_req_buf, task->data,
task->data_count); task->data_count);
tx_dsg->addr = iser_conn->ib_conn->login_dma;
ib_dma_sync_single_for_device(device->ib_device,
ib_conn->login_req_dma, task->data_count,
DMA_TO_DEVICE);
tx_dsg->addr = iser_conn->ib_conn->login_req_dma;
tx_dsg->length = task->data_count; tx_dsg->length = task->data_count;
tx_dsg->lkey = device->mr->lkey; tx_dsg->lkey = device->mr->lkey;
mdesc->num_sge = 2; mdesc->num_sge = 2;
...@@ -445,8 +462,8 @@ void iser_rcv_completion(struct iser_rx_desc *rx_desc, ...@@ -445,8 +462,8 @@ void iser_rcv_completion(struct iser_rx_desc *rx_desc,
int rx_buflen, outstanding, count, err; int rx_buflen, outstanding, count, err;
/* differentiate between login to all other PDUs */ /* differentiate between login to all other PDUs */
if ((char *)rx_desc == ib_conn->login_buf) { if ((char *)rx_desc == ib_conn->login_resp_buf) {
rx_dma = ib_conn->login_dma; rx_dma = ib_conn->login_resp_dma;
rx_buflen = ISER_RX_LOGIN_SIZE; rx_buflen = ISER_RX_LOGIN_SIZE;
} else { } else {
rx_dma = rx_desc->dma_addr; rx_dma = rx_desc->dma_addr;
...@@ -473,7 +490,7 @@ void iser_rcv_completion(struct iser_rx_desc *rx_desc, ...@@ -473,7 +490,7 @@ void iser_rcv_completion(struct iser_rx_desc *rx_desc,
* for the posted rx bufs refcount to become zero handles everything */ * for the posted rx bufs refcount to become zero handles everything */
conn->ib_conn->post_recv_buf_count--; conn->ib_conn->post_recv_buf_count--;
if (rx_dma == ib_conn->login_dma) if (rx_dma == ib_conn->login_resp_dma)
return; return;
outstanding = ib_conn->post_recv_buf_count; outstanding = ib_conn->post_recv_buf_count;
......
...@@ -155,20 +155,39 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) ...@@ -155,20 +155,39 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn)
{ {
struct iser_device *device; struct iser_device *device;
struct ib_qp_init_attr init_attr; struct ib_qp_init_attr init_attr;
int ret = -ENOMEM; int req_err, resp_err, ret = -ENOMEM;
struct ib_fmr_pool_param params; struct ib_fmr_pool_param params;
BUG_ON(ib_conn->device == NULL); BUG_ON(ib_conn->device == NULL);
device = ib_conn->device; device = ib_conn->device;
ib_conn->login_buf = kmalloc(ISER_RX_LOGIN_SIZE, GFP_KERNEL); ib_conn->login_buf = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN +
ISER_RX_LOGIN_SIZE, GFP_KERNEL);
if (!ib_conn->login_buf) if (!ib_conn->login_buf)
goto out_err; goto out_err;
ib_conn->login_dma = ib_dma_map_single(ib_conn->device->ib_device, ib_conn->login_req_buf = ib_conn->login_buf;
(void *)ib_conn->login_buf, ISER_RX_LOGIN_SIZE, ib_conn->login_resp_buf = ib_conn->login_buf + ISCSI_DEF_MAX_RECV_SEG_LEN;
DMA_FROM_DEVICE);
ib_conn->login_req_dma = ib_dma_map_single(ib_conn->device->ib_device,
(void *)ib_conn->login_req_buf,
ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE);
ib_conn->login_resp_dma = ib_dma_map_single(ib_conn->device->ib_device,
(void *)ib_conn->login_resp_buf,
ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
req_err = ib_dma_mapping_error(device->ib_device, ib_conn->login_req_dma);
resp_err = ib_dma_mapping_error(device->ib_device, ib_conn->login_resp_dma);
if (req_err || resp_err) {
if (req_err)
ib_conn->login_req_dma = 0;
if (resp_err)
ib_conn->login_resp_dma = 0;
goto out_err;
}
ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) + ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) +
(sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)), (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)),
...@@ -658,11 +677,11 @@ int iser_post_recvl(struct iser_conn *ib_conn) ...@@ -658,11 +677,11 @@ int iser_post_recvl(struct iser_conn *ib_conn)
struct ib_sge sge; struct ib_sge sge;
int ib_ret; int ib_ret;
sge.addr = ib_conn->login_dma; sge.addr = ib_conn->login_resp_dma;
sge.length = ISER_RX_LOGIN_SIZE; sge.length = ISER_RX_LOGIN_SIZE;
sge.lkey = ib_conn->device->mr->lkey; sge.lkey = ib_conn->device->mr->lkey;
rx_wr.wr_id = (unsigned long)ib_conn->login_buf; rx_wr.wr_id = (unsigned long)ib_conn->login_resp_buf;
rx_wr.sg_list = &sge; rx_wr.sg_list = &sge;
rx_wr.num_sge = 1; rx_wr.num_sge = 1;
rx_wr.next = NULL; rx_wr.next = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment