diff options
Diffstat (limited to 'drivers/infiniband/ulp/srpt/ib_srpt.c')
-rw-r--r-- | drivers/infiniband/ulp/srpt/ib_srpt.c | 178 |
1 files changed, 76 insertions, 102 deletions
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index cf23c46185b..c09d41b1a2f 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1269,7 +1269,6 @@ static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch) return ioctx; BUG_ON(ioctx->ch != ch); - kref_init(&ioctx->kref); spin_lock_init(&ioctx->spinlock); ioctx->state = SRPT_STATE_NEW; ioctx->n_rbuf = 0; @@ -1291,39 +1290,6 @@ static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch) } /** - * srpt_put_send_ioctx() - Free up resources. - */ -static void srpt_put_send_ioctx(struct srpt_send_ioctx *ioctx) -{ - struct srpt_rdma_ch *ch; - unsigned long flags; - - BUG_ON(!ioctx); - ch = ioctx->ch; - BUG_ON(!ch); - - WARN_ON(srpt_get_cmd_state(ioctx) != SRPT_STATE_DONE); - - srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx); - transport_generic_free_cmd(&ioctx->cmd, 0); - - if (ioctx->n_rbuf > 1) { - kfree(ioctx->rbufs); - ioctx->rbufs = NULL; - ioctx->n_rbuf = 0; - } - - spin_lock_irqsave(&ch->spinlock, flags); - list_add(&ioctx->free_list, &ch->free_list); - spin_unlock_irqrestore(&ch->spinlock, flags); -} - -static void srpt_put_send_ioctx_kref(struct kref *kref) -{ - srpt_put_send_ioctx(container_of(kref, struct srpt_send_ioctx, kref)); -} - -/** * srpt_abort_cmd() - Abort a SCSI command. * @ioctx: I/O context associated with the SCSI command. * @context: Preferred execution context. @@ -1359,8 +1325,14 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx) } spin_unlock_irqrestore(&ioctx->spinlock, flags); - if (state == SRPT_STATE_DONE) + if (state == SRPT_STATE_DONE) { + struct srpt_rdma_ch *ch = ioctx->ch; + + BUG_ON(ch->sess == NULL); + + target_put_sess_cmd(ch->sess, &ioctx->cmd); goto out; + } pr_debug("Aborting cmd with state %d and tag %lld\n", state, ioctx->tag); @@ -1395,11 +1367,11 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx) spin_lock_irqsave(&ioctx->cmd.t_state_lock, flags); ioctx->cmd.transport_state |= CMD_T_LUN_STOP; spin_unlock_irqrestore(&ioctx->cmd.t_state_lock, flags); - kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); + target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); break; case SRPT_STATE_MGMT_RSP_SENT: srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); - kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); + target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); break; default: WARN_ON("ERROR: unexpected command state"); @@ -1457,11 +1429,13 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch, && state != SRPT_STATE_DONE)) pr_debug("state = %d\n", state); - if (state != SRPT_STATE_DONE) - kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); - else + if (state != SRPT_STATE_DONE) { + srpt_unmap_sg_to_ib_sge(ch, ioctx); + transport_generic_free_cmd(&ioctx->cmd, 0); + } else { printk(KERN_ERR "IB completion has been received too late for" " wr_id = %u.\n", ioctx->ioctx.index); + } } /** @@ -1712,10 +1686,10 @@ out_err: static int srpt_check_stop_free(struct se_cmd *cmd) { - struct srpt_send_ioctx *ioctx; + struct srpt_send_ioctx *ioctx = container_of(cmd, + struct srpt_send_ioctx, cmd); - ioctx = container_of(cmd, struct srpt_send_ioctx, cmd); - return kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); + return target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); } /** @@ -1730,12 +1704,12 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, uint64_t unpacked_lun; u64 data_len; enum dma_data_direction dir; - int ret; + sense_reason_t ret; + int rc; BUG_ON(!send_ioctx); srp_cmd = recv_ioctx->ioctx.buf; - kref_get(&send_ioctx->kref); cmd = &send_ioctx->cmd; send_ioctx->tag = srp_cmd->tag; @@ -1755,40 +1729,26 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, break; } - ret = srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len); - if (ret) { + if (srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len)) { printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n", srp_cmd->tag); - cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); + ret = TCM_INVALID_CDB_FIELD; goto send_sense; } - cmd->data_length = data_len; - cmd->data_direction = dir; unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun, sizeof(srp_cmd->lun)); - if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0) { - kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); + rc = target_submit_cmd(cmd, ch->sess, srp_cmd->cdb, + &send_ioctx->sense_data[0], unpacked_lun, data_len, + MSG_SIMPLE_TAG, dir, TARGET_SCF_ACK_KREF); + if (rc != 0) { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto send_sense; } - ret = target_setup_cmd_from_cdb(cmd, srp_cmd->cdb); - if (ret < 0) { - kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); - if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) { - srpt_queue_status(cmd); - return 0; - } else - goto send_sense; - } - - transport_handle_cdb_direct(cmd); return 0; send_sense: - transport_send_check_condition_and_sense(cmd, cmd->scsi_sense_reason, - 0); + transport_send_check_condition_and_sense(cmd, ret, 0); return -1; } @@ -1865,9 +1825,11 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, { struct srp_tsk_mgmt *srp_tsk; struct se_cmd *cmd; + struct se_session *sess = ch->sess; uint64_t unpacked_lun; + uint32_t tag = 0; int tcm_tmr; - int res; + int rc; BUG_ON(!send_ioctx); @@ -1882,39 +1844,32 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, send_ioctx->tag = srp_tsk->tag; tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func); if (tcm_tmr < 0) { - send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; send_ioctx->cmd.se_tmr_req->response = TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED; - goto process_tmr; - } - res = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL); - if (res < 0) { - send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; - goto process_tmr; + goto fail; } - unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun, sizeof(srp_tsk->lun)); - res = transport_lookup_tmr_lun(&send_ioctx->cmd, unpacked_lun); - if (res) { - pr_debug("rejecting TMR for LUN %lld\n", unpacked_lun); - send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; - send_ioctx->cmd.se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; - goto process_tmr; - } - - if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) - srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag); - -process_tmr: - kref_get(&send_ioctx->kref); - if (!(send_ioctx->cmd.se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)) - transport_generic_handle_tmr(&send_ioctx->cmd); - else - transport_send_check_condition_and_sense(cmd, - cmd->scsi_sense_reason, 0); + if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) { + rc = srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag); + if (rc < 0) { + send_ioctx->cmd.se_tmr_req->response = + TMR_TASK_DOES_NOT_EXIST; + goto fail; + } + tag = srp_tsk->task_tag; + } + rc = target_submit_tmr(&send_ioctx->cmd, sess, NULL, unpacked_lun, + srp_tsk, tcm_tmr, GFP_KERNEL, tag, + TARGET_SCF_ACK_KREF); + if (rc != 0) { + send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; + goto fail; + } + return; +fail: + transport_send_check_condition_and_sense(cmd, 0, 0); // XXX: } /** @@ -1956,10 +1911,6 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch, } } - transport_init_se_cmd(&send_ioctx->cmd, &srpt_target->tf_ops, ch->sess, - 0, DMA_NONE, MSG_SIMPLE_TAG, - send_ioctx->sense_data); - switch (srp_cmd->opcode) { case SRP_CMD: srpt_handle_cmd(ch, recv_ioctx, send_ioctx); @@ -2365,6 +2316,7 @@ static void srpt_release_channel_work(struct work_struct *w) { struct srpt_rdma_ch *ch; struct srpt_device *sdev; + struct se_session *se_sess; ch = container_of(w, struct srpt_rdma_ch, release_work); pr_debug("ch = %p; ch->sess = %p; release_done = %p\n", ch, ch->sess, @@ -2373,8 +2325,13 @@ static void srpt_release_channel_work(struct work_struct *w) sdev = ch->sport->sdev; BUG_ON(!sdev); - transport_deregister_session_configfs(ch->sess); - transport_deregister_session(ch->sess); + se_sess = ch->sess; + BUG_ON(!se_sess); + + target_wait_for_sess_cmds(se_sess, 0); + + transport_deregister_session_configfs(se_sess); + transport_deregister_session(se_sess); ch->sess = NULL; srpt_destroy_ch_ib(ch); @@ -3099,7 +3056,7 @@ static int srpt_queue_response(struct se_cmd *cmd) ioctx->tag); srpt_unmap_sg_to_ib_sge(ch, ioctx); srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); - kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); + target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); } out: @@ -3490,6 +3447,23 @@ static u32 srpt_tpg_get_inst_index(struct se_portal_group *se_tpg) static void srpt_release_cmd(struct se_cmd *se_cmd) { + struct srpt_send_ioctx *ioctx = container_of(se_cmd, + struct srpt_send_ioctx, cmd); + struct srpt_rdma_ch *ch = ioctx->ch; + unsigned long flags; + + WARN_ON(ioctx->state != SRPT_STATE_DONE); + WARN_ON(ioctx->mapped_sg_count != 0); + + if (ioctx->n_rbuf > 1) { + kfree(ioctx->rbufs); + ioctx->rbufs = NULL; + ioctx->n_rbuf = 0; + } + + spin_lock_irqsave(&ch->spinlock, flags); + list_add(&ioctx->free_list, &ch->free_list); + spin_unlock_irqrestore(&ch->spinlock, flags); } /** |