aboutsummaryrefslogtreecommitdiff
path: root/drivers/infiniband/ulp/isert/ib_isert.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/ulp/isert/ib_isert.c')
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c191
1 files changed, 126 insertions, 65 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 41712f09651..588a5eca63d 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -242,21 +242,29 @@ isert_create_device_ib_res(struct isert_device *device)
isert_cq_event_callback,
(void *)&cq_desc[i],
ISER_MAX_RX_CQ_LEN, i);
- if (IS_ERR(device->dev_rx_cq[i]))
+ if (IS_ERR(device->dev_rx_cq[i])) {
+ ret = PTR_ERR(device->dev_rx_cq[i]);
+ device->dev_rx_cq[i] = NULL;
goto out_cq;
+ }
device->dev_tx_cq[i] = ib_create_cq(device->ib_device,
isert_cq_tx_callback,
isert_cq_event_callback,
(void *)&cq_desc[i],
ISER_MAX_TX_CQ_LEN, i);
- if (IS_ERR(device->dev_tx_cq[i]))
+ if (IS_ERR(device->dev_tx_cq[i])) {
+ ret = PTR_ERR(device->dev_tx_cq[i]);
+ device->dev_tx_cq[i] = NULL;
goto out_cq;
+ }
- if (ib_req_notify_cq(device->dev_rx_cq[i], IB_CQ_NEXT_COMP))
+ ret = ib_req_notify_cq(device->dev_rx_cq[i], IB_CQ_NEXT_COMP);
+ if (ret)
goto out_cq;
- if (ib_req_notify_cq(device->dev_tx_cq[i], IB_CQ_NEXT_COMP))
+ ret = ib_req_notify_cq(device->dev_tx_cq[i], IB_CQ_NEXT_COMP);
+ if (ret)
goto out_cq;
}
@@ -384,10 +392,11 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
isert_conn->state = ISER_CONN_INIT;
INIT_LIST_HEAD(&isert_conn->conn_accept_node);
init_completion(&isert_conn->conn_login_comp);
- init_waitqueue_head(&isert_conn->conn_wait);
- init_waitqueue_head(&isert_conn->conn_wait_comp_err);
+ init_completion(&isert_conn->conn_wait);
+ init_completion(&isert_conn->conn_wait_comp_err);
kref_init(&isert_conn->conn_kref);
kref_get(&isert_conn->conn_kref);
+ mutex_init(&isert_conn->conn_mutex);
cma_id->context = isert_conn;
isert_conn->conn_cm_id = cma_id;
@@ -540,15 +549,32 @@ isert_disconnect_work(struct work_struct *work)
struct isert_conn, conn_logout_work);
pr_debug("isert_disconnect_work(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
-
- isert_conn->state = ISER_CONN_DOWN;
+ mutex_lock(&isert_conn->conn_mutex);
+ if (isert_conn->state == ISER_CONN_UP)
+ isert_conn->state = ISER_CONN_TERMINATING;
if (isert_conn->post_recv_buf_count == 0 &&
atomic_read(&isert_conn->post_send_buf_count) == 0) {
- pr_debug("Calling wake_up(&isert_conn->conn_wait);\n");
- wake_up(&isert_conn->conn_wait);
+ mutex_unlock(&isert_conn->conn_mutex);
+ goto wake_up;
+ }
+ if (!isert_conn->conn_cm_id) {
+ mutex_unlock(&isert_conn->conn_mutex);
+ isert_put_conn(isert_conn);
+ return;
+ }
+ if (!isert_conn->logout_posted) {
+ pr_debug("Calling rdma_disconnect for !logout_posted from"
+ " isert_disconnect_work\n");
+ rdma_disconnect(isert_conn->conn_cm_id);
+ mutex_unlock(&isert_conn->conn_mutex);
+ iscsit_cause_connection_reinstatement(isert_conn->conn, 0);
+ goto wake_up;
}
+ mutex_unlock(&isert_conn->conn_mutex);
+wake_up:
+ complete(&isert_conn->conn_wait);
isert_put_conn(isert_conn);
}
@@ -934,16 +960,11 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
}
sequence_cmd:
- rc = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
+ rc = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
if (!rc && dump_payload == false && unsol_data)
iscsit_set_unsoliticed_dataout(cmd);
- if (rc == CMDSN_ERROR_CANNOT_RECOVER)
- return iscsit_add_reject_from_cmd(
- ISCSI_REASON_PROTOCOL_ERROR,
- 1, 0, (unsigned char *)hdr, cmd);
-
return 0;
}
@@ -1184,36 +1205,36 @@ isert_put_cmd(struct isert_cmd *isert_cmd)
{
struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd;
struct isert_conn *isert_conn = isert_cmd->conn;
- struct iscsi_conn *conn;
+ struct iscsi_conn *conn = isert_conn->conn;
pr_debug("Entering isert_put_cmd: %p\n", isert_cmd);
switch (cmd->iscsi_opcode) {
case ISCSI_OP_SCSI_CMD:
- conn = isert_conn->conn;
-
spin_lock_bh(&conn->cmd_lock);
if (!list_empty(&cmd->i_conn_node))
- list_del(&cmd->i_conn_node);
+ list_del_init(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);
if (cmd->data_direction == DMA_TO_DEVICE)
iscsit_stop_dataout_timer(cmd);
isert_unmap_cmd(isert_cmd, isert_conn);
- /*
- * Fall-through
- */
+ transport_generic_free_cmd(&cmd->se_cmd, 0);
+ break;
case ISCSI_OP_SCSI_TMFUNC:
+ spin_lock_bh(&conn->cmd_lock);
+ if (!list_empty(&cmd->i_conn_node))
+ list_del_init(&cmd->i_conn_node);
+ spin_unlock_bh(&conn->cmd_lock);
+
transport_generic_free_cmd(&cmd->se_cmd, 0);
break;
case ISCSI_OP_REJECT:
case ISCSI_OP_NOOP_OUT:
- conn = isert_conn->conn;
-
spin_lock_bh(&conn->cmd_lock);
if (!list_empty(&cmd->i_conn_node))
- list_del(&cmd->i_conn_node);
+ list_del_init(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);
/*
@@ -1222,6 +1243,9 @@ isert_put_cmd(struct isert_cmd *isert_cmd)
* associated cmd->se_cmd needs to be released.
*/
if (cmd->se_cmd.se_tfo != NULL) {
+ pr_debug("Calling transport_generic_free_cmd from"
+ " isert_put_cmd for 0x%02x\n",
+ cmd->iscsi_opcode);
transport_generic_free_cmd(&cmd->se_cmd, 0);
break;
}
@@ -1284,6 +1308,7 @@ isert_completion_rdma_read(struct iser_tx_desc *tx_desc,
}
cmd->write_data_done = se_cmd->data_length;
+ wr->send_wr_num = 0;
pr_debug("isert_do_rdma_read_comp, calling target_execute_cmd\n");
spin_lock_bh(&cmd->istate_lock);
@@ -1318,13 +1343,13 @@ isert_do_control_comp(struct work_struct *work)
atomic_dec(&isert_conn->post_send_buf_count);
cmd->i_state = ISTATE_SENT_STATUS;
- complete(&cmd->reject_comp);
isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev);
+ break;
case ISTATE_SEND_LOGOUTRSP:
pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n");
/*
* Call atomic_dec(&isert_conn->post_send_buf_count)
- * from isert_free_conn()
+ * from isert_wait_conn()
*/
isert_conn->logout_posted = true;
iscsit_logout_post_handler(cmd, cmd->conn);
@@ -1343,16 +1368,18 @@ isert_response_completion(struct iser_tx_desc *tx_desc,
struct ib_device *ib_dev)
{
struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd;
+ struct isert_rdma_wr *wr = &isert_cmd->rdma_wr;
if (cmd->i_state == ISTATE_SEND_TASKMGTRSP ||
- cmd->i_state == ISTATE_SEND_LOGOUTRSP) {
+ cmd->i_state == ISTATE_SEND_LOGOUTRSP ||
+ cmd->i_state == ISTATE_SEND_REJECT) {
isert_unmap_tx_desc(tx_desc, ib_dev);
INIT_WORK(&isert_cmd->comp_work, isert_do_control_comp);
queue_work(isert_comp_wq, &isert_cmd->comp_work);
return;
}
- atomic_dec(&isert_conn->post_send_buf_count);
+ atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count);
cmd->i_state = ISTATE_SENT_STATUS;
isert_completion_put(tx_desc, isert_cmd, ib_dev);
@@ -1390,7 +1417,7 @@ isert_send_completion(struct iser_tx_desc *tx_desc,
case ISER_IB_RDMA_READ:
pr_debug("isert_send_completion: Got ISER_IB_RDMA_READ:\n");
- atomic_dec(&isert_conn->post_send_buf_count);
+ atomic_sub(wr->send_wr_num, &isert_conn->post_send_buf_count);
isert_completion_rdma_read(tx_desc, isert_cmd);
break;
default:
@@ -1401,27 +1428,38 @@ isert_send_completion(struct iser_tx_desc *tx_desc,
}
static void
-isert_cq_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn)
+isert_cq_tx_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn)
{
struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+ struct isert_cmd *isert_cmd = tx_desc->isert_cmd;
+
+ if (!isert_cmd)
+ isert_unmap_tx_desc(tx_desc, ib_dev);
+ else
+ isert_completion_put(tx_desc, isert_cmd, ib_dev);
+}
+
+static void
+isert_cq_rx_comp_err(struct isert_conn *isert_conn)
+{
+ struct iscsi_conn *conn = isert_conn->conn;
- if (tx_desc) {
- struct isert_cmd *isert_cmd = tx_desc->isert_cmd;
+ if (isert_conn->post_recv_buf_count)
+ return;
- if (!isert_cmd)
- isert_unmap_tx_desc(tx_desc, ib_dev);
- else
- isert_completion_put(tx_desc, isert_cmd, ib_dev);
+ if (conn->sess) {
+ target_sess_cmd_list_set_waiting(conn->sess->se_sess);
+ target_wait_for_sess_cmds(conn->sess->se_sess);
}
- if (isert_conn->post_recv_buf_count == 0 &&
- atomic_read(&isert_conn->post_send_buf_count) == 0) {
- pr_debug("isert_cq_comp_err >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
- pr_debug("Calling wake_up from isert_cq_comp_err\n");
+ while (atomic_read(&isert_conn->post_send_buf_count))
+ msleep(3000);
- isert_conn->state = ISER_CONN_TERMINATING;
- wake_up(&isert_conn->conn_wait_comp_err);
- }
+ mutex_lock(&isert_conn->conn_mutex);
+ isert_conn->state = ISER_CONN_DOWN;
+ mutex_unlock(&isert_conn->conn_mutex);
+
+ complete(&isert_conn->conn_wait_comp_err);
}
static void
@@ -1446,7 +1484,7 @@ isert_cq_tx_work(struct work_struct *work)
pr_debug("TX wc.status != IB_WC_SUCCESS >>>>>>>>>>>>>>\n");
pr_debug("TX wc.status: 0x%08x\n", wc.status);
atomic_dec(&isert_conn->post_send_buf_count);
- isert_cq_comp_err(tx_desc, isert_conn);
+ isert_cq_tx_comp_err(tx_desc, isert_conn);
}
}
@@ -1488,7 +1526,7 @@ isert_cq_rx_work(struct work_struct *work)
pr_debug("RX wc.status: 0x%08x\n", wc.status);
isert_conn->post_recv_buf_count--;
- isert_cq_comp_err(NULL, isert_conn);
+ isert_cq_rx_comp_err(isert_conn);
}
}
@@ -1637,11 +1675,25 @@ isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
struct isert_cmd, iscsi_cmd);
struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr;
+ struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+ struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1];
+ struct iscsi_reject *hdr =
+ (struct iscsi_reject *)&isert_cmd->tx_desc.iscsi_header;
isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc);
- iscsit_build_reject(cmd, conn, (struct iscsi_reject *)
- &isert_cmd->tx_desc.iscsi_header);
+ iscsit_build_reject(cmd, conn, hdr);
isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc);
+
+ hton24(hdr->dlength, ISCSI_HDR_LEN);
+ isert_cmd->sense_buf_dma = ib_dma_map_single(ib_dev,
+ (void *)cmd->buf_ptr, ISCSI_HDR_LEN,
+ DMA_TO_DEVICE);
+ isert_cmd->sense_buf_len = ISCSI_HDR_LEN;
+ tx_dsg->addr = isert_cmd->sense_buf_dma;
+ tx_dsg->length = ISCSI_HDR_LEN;
+ tx_dsg->lkey = isert_conn->conn_mr->lkey;
+ isert_cmd->tx_desc.num_sge = 2;
+
isert_init_send_wr(isert_cmd, send_wr);
pr_debug("Posting Reject IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n");
@@ -1784,12 +1836,12 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc);
isert_init_send_wr(isert_cmd, &isert_cmd->tx_desc.send_wr);
- atomic_inc(&isert_conn->post_send_buf_count);
+ atomic_add(wr->send_wr_num + 1, &isert_conn->post_send_buf_count);
rc = ib_post_send(isert_conn->conn_qp, wr->send_wr, &wr_failed);
if (rc) {
pr_warn("ib_post_send() failed for IB_WR_RDMA_WRITE\n");
- atomic_dec(&isert_conn->post_send_buf_count);
+ atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count);
}
pr_debug("Posted RDMA_WRITE + Response for iSER Data READ\n");
return 1;
@@ -1892,12 +1944,12 @@ isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery)
data_left -= data_len;
}
- atomic_inc(&isert_conn->post_send_buf_count);
+ atomic_add(wr->send_wr_num, &isert_conn->post_send_buf_count);
rc = ib_post_send(isert_conn->conn_qp, wr->send_wr, &wr_failed);
if (rc) {
pr_warn("ib_post_send() failed for IB_WR_RDMA_READ\n");
- atomic_dec(&isert_conn->post_send_buf_count);
+ atomic_sub(wr->send_wr_num, &isert_conn->post_send_buf_count);
}
pr_debug("Posted RDMA_READ memory for ISER Data WRITE\n");
return 0;
@@ -2175,35 +2227,43 @@ isert_free_np(struct iscsi_np *np)
kfree(isert_np);
}
-static void isert_free_conn(struct iscsi_conn *conn)
+static void isert_wait_conn(struct iscsi_conn *conn)
{
struct isert_conn *isert_conn = conn->context;
- pr_debug("isert_free_conn: Starting \n");
+ pr_debug("isert_wait_conn: Starting \n");
/*
* Decrement post_send_buf_count for special case when called
* from isert_do_control_comp() -> iscsit_logout_post_handler()
*/
+ mutex_lock(&isert_conn->conn_mutex);
if (isert_conn->logout_posted)
atomic_dec(&isert_conn->post_send_buf_count);
- if (isert_conn->conn_cm_id)
+ if (isert_conn->conn_cm_id && isert_conn->state != ISER_CONN_DOWN) {
+ pr_debug("Calling rdma_disconnect from isert_wait_conn\n");
rdma_disconnect(isert_conn->conn_cm_id);
+ }
/*
* Only wait for conn_wait_comp_err if the isert_conn made it
* into full feature phase..
*/
- if (isert_conn->state > ISER_CONN_INIT) {
- pr_debug("isert_free_conn: Before wait_event comp_err %d\n",
- isert_conn->state);
- wait_event(isert_conn->conn_wait_comp_err,
- isert_conn->state == ISER_CONN_TERMINATING);
- pr_debug("isert_free_conn: After wait_event #1 >>>>>>>>>>>>\n");
+ if (isert_conn->state == ISER_CONN_INIT) {
+ mutex_unlock(&isert_conn->conn_mutex);
+ return;
}
+ if (isert_conn->state == ISER_CONN_UP)
+ isert_conn->state = ISER_CONN_TERMINATING;
+ mutex_unlock(&isert_conn->conn_mutex);
+
+ wait_for_completion(&isert_conn->conn_wait_comp_err);
+
+ wait_for_completion(&isert_conn->conn_wait);
+}
- pr_debug("isert_free_conn: wait_event conn_wait %d\n", isert_conn->state);
- wait_event(isert_conn->conn_wait, isert_conn->state == ISER_CONN_DOWN);
- pr_debug("isert_free_conn: After wait_event #2 >>>>>>>>>>>>>>>>>>>>\n");
+static void isert_free_conn(struct iscsi_conn *conn)
+{
+ struct isert_conn *isert_conn = conn->context;
isert_put_conn(isert_conn);
}
@@ -2215,6 +2275,7 @@ static struct iscsit_transport iser_target_transport = {
.iscsit_setup_np = isert_setup_np,
.iscsit_accept_np = isert_accept_np,
.iscsit_free_np = isert_free_np,
+ .iscsit_wait_conn = isert_wait_conn,
.iscsit_free_conn = isert_free_conn,
.iscsit_alloc_cmd = isert_alloc_cmd,
.iscsit_get_login_rx = isert_get_login_rx,