aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/tcm_qla2xxx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/tcm_qla2xxx.c')
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c206
1 files changed, 104 insertions, 102 deletions
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index abe7f79bb789..8fa0056b56dd 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -255,6 +255,7 @@ static void tcm_qla2xxx_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd)
static void tcm_qla2xxx_complete_free(struct work_struct *work)
{
struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
+ unsigned long flags;
cmd->cmd_in_wq = 0;
@@ -265,9 +266,36 @@ static void tcm_qla2xxx_complete_free(struct work_struct *work)
cmd->trc_flags |= TRC_CMD_FREE;
cmd->cmd_sent_to_fw = 0;
+ spin_lock_irqsave(&cmd->sess->sess_cmd_lock, flags);
+ list_del_init(&cmd->sess_cmd_list);
+ spin_unlock_irqrestore(&cmd->sess->sess_cmd_lock, flags);
+
transport_generic_free_cmd(&cmd->se_cmd, 0);
}
+static struct qla_tgt_cmd *tcm_qla2xxx_get_cmd(struct fc_port *sess)
+{
+ struct se_session *se_sess = sess->se_sess;
+ struct qla_tgt_cmd *cmd;
+ int tag, cpu;
+
+ tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
+ if (tag < 0)
+ return NULL;
+
+ cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag];
+ memset(cmd, 0, sizeof(struct qla_tgt_cmd));
+ cmd->se_cmd.map_tag = tag;
+ cmd->se_cmd.map_cpu = cpu;
+
+ return cmd;
+}
+
+static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd)
+{
+ target_free_tag(cmd->sess->se_sess, &cmd->se_cmd);
+}
+
/*
* Called from qla_target_template->free_cmd(), and will call
* tcm_qla2xxx_release_cmd via normal struct target_core_fabric_ops
@@ -340,15 +368,10 @@ static void tcm_qla2xxx_put_sess(struct fc_port *sess)
static void tcm_qla2xxx_close_session(struct se_session *se_sess)
{
struct fc_port *sess = se_sess->fabric_sess_ptr;
- struct scsi_qla_host *vha;
- unsigned long flags;
BUG_ON(!sess);
- vha = sess->vha;
- spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
- target_sess_cmd_list_set_waiting(se_sess);
- spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+ target_stop_session(se_sess);
sess->explicit_logout = 1;
tcm_qla2xxx_put_sess(sess);
@@ -428,13 +451,14 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
struct se_portal_group *se_tpg;
struct tcm_qla2xxx_tpg *tpg;
#endif
- int flags = TARGET_SCF_ACK_KREF;
+ int rc, target_flags = TARGET_SCF_ACK_KREF;
+ unsigned long flags;
if (bidi)
- flags |= TARGET_SCF_BIDI_OP;
+ target_flags |= TARGET_SCF_BIDI_OP;
if (se_cmd->cpuid != WORK_CPU_UNBOUND)
- flags |= TARGET_SCF_USE_CPUID;
+ target_flags |= TARGET_SCF_USE_CPUID;
sess = cmd->sess;
if (!sess) {
@@ -456,11 +480,24 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
return 0;
}
#endif
-
cmd->qpair->tgt_counters.qla_core_sbt_cmd++;
- return target_submit_cmd(se_cmd, se_sess, cdb, &cmd->sense_buffer[0],
- cmd->unpacked_lun, data_length, fcp_task_attr,
- data_dir, flags);
+
+ spin_lock_irqsave(&sess->sess_cmd_lock, flags);
+ list_add_tail(&cmd->sess_cmd_list, &sess->sess_cmd_list);
+ spin_unlock_irqrestore(&sess->sess_cmd_lock, flags);
+
+ rc = target_init_cmd(se_cmd, se_sess, &cmd->sense_buffer[0],
+ cmd->unpacked_lun, data_length, fcp_task_attr,
+ data_dir, target_flags);
+ if (rc)
+ return rc;
+
+ if (target_submit_prep(se_cmd, cdb, NULL, 0, NULL, 0, NULL, 0,
+ GFP_KERNEL))
+ return 0;
+
+ target_submit(se_cmd);
+ return 0;
}
static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
@@ -551,13 +588,11 @@ static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, u64 lun,
struct fc_port *sess = mcmd->sess;
struct se_cmd *se_cmd = &mcmd->se_cmd;
int transl_tmr_func = 0;
- int flags = TARGET_SCF_ACK_KREF;
switch (tmr_func) {
case QLA_TGT_ABTS:
pr_debug("%ld: ABTS received\n", sess->vha->host_no);
transl_tmr_func = TMR_ABORT_TASK;
- flags |= TARGET_SCF_LOOKUP_LUN_FROM_TAG;
break;
case QLA_TGT_2G_ABORT_TASK:
pr_debug("%ld: 2G Abort Task received\n", sess->vha->host_no);
@@ -590,31 +625,26 @@ static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, u64 lun,
}
return target_submit_tmr(se_cmd, sess->se_sess, NULL, lun, mcmd,
- transl_tmr_func, GFP_ATOMIC, tag, flags);
+ transl_tmr_func, GFP_ATOMIC, tag, TARGET_SCF_ACK_KREF);
}
static struct qla_tgt_cmd *tcm_qla2xxx_find_cmd_by_tag(struct fc_port *sess,
uint64_t tag)
{
- struct qla_tgt_cmd *cmd = NULL;
- struct se_cmd *secmd;
+ struct qla_tgt_cmd *cmd;
unsigned long flags;
if (!sess->se_sess)
return NULL;
- spin_lock_irqsave(&sess->se_sess->sess_cmd_lock, flags);
- list_for_each_entry(secmd, &sess->se_sess->sess_cmd_list, se_cmd_list) {
- /* skip task management functions, including tmr->task_cmd */
- if (secmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
- continue;
-
- if (secmd->tag == tag) {
- cmd = container_of(secmd, struct qla_tgt_cmd, se_cmd);
- break;
- }
+ spin_lock_irqsave(&sess->sess_cmd_lock, flags);
+ list_for_each_entry(cmd, &sess->sess_cmd_list, sess_cmd_list) {
+ if (cmd->se_cmd.tag == tag)
+ goto done;
}
- spin_unlock_irqrestore(&sess->se_sess->sess_cmd_lock, flags);
+ cmd = NULL;
+done:
+ spin_unlock_irqrestore(&sess->sess_cmd_lock, flags);
return cmd;
}
@@ -623,7 +653,6 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
{
struct qla_tgt_cmd *cmd = container_of(se_cmd,
struct qla_tgt_cmd, se_cmd);
- struct scsi_qla_host *vha = cmd->vha;
if (cmd->aborted) {
/* Cmd can loop during Q-full. tcm_qla2xxx_aborted_task
@@ -636,7 +665,6 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
cmd->se_cmd.transport_state,
cmd->se_cmd.t_state,
cmd->se_cmd.se_cmd_flags);
- vha->hw->tgt.tgt_ops->free_cmd(cmd);
return 0;
}
@@ -664,7 +692,6 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
{
struct qla_tgt_cmd *cmd = container_of(se_cmd,
struct qla_tgt_cmd, se_cmd);
- struct scsi_qla_host *vha = cmd->vha;
int xmit_type = QLA_TGT_XMIT_STATUS;
if (cmd->aborted) {
@@ -678,7 +705,6 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
cmd, kref_read(&cmd->se_cmd.cmd_kref),
cmd->se_cmd.transport_state, cmd->se_cmd.t_state,
cmd->se_cmd.se_cmd_flags);
- vha->hw->tgt.tgt_ops->free_cmd(cmd);
return 0;
}
cmd->bufflen = se_cmd->data_length;
@@ -744,11 +770,19 @@ static void tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd)
static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd)
{
- struct qla_tgt_cmd *cmd = container_of(se_cmd,
- struct qla_tgt_cmd, se_cmd);
+ struct qla_tgt_cmd *cmd;
+ unsigned long flags;
- if (qlt_abort_cmd(cmd))
+ if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
return;
+
+ cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd);
+
+ spin_lock_irqsave(&cmd->sess->sess_cmd_lock, flags);
+ list_del_init(&cmd->sess_cmd_list);
+ spin_unlock_irqrestore(&cmd->sess->sess_cmd_lock, flags);
+
+ qlt_abort_cmd(cmd);
}
static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *,
@@ -797,7 +831,7 @@ static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct fc_port *sess)
static void tcm_qla2xxx_shutdown_sess(struct fc_port *sess)
{
- target_sess_cmd_list_set_waiting(sess->se_sess);
+ target_stop_session(sess->se_sess);
}
static int tcm_qla2xxx_init_nodeacl(struct se_node_acl *se_nacl,
@@ -827,7 +861,7 @@ static ssize_t tcm_qla2xxx_tpg_attrib_##name##_show( \
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, \
struct tcm_qla2xxx_tpg, se_tpg); \
\
- return sprintf(page, "%u\n", tpg->tpg_attrib.name); \
+ return sprintf(page, "%d\n", tpg->tpg_attrib.name); \
} \
\
static ssize_t tcm_qla2xxx_tpg_attrib_##name##_store( \
@@ -881,40 +915,17 @@ static struct configfs_attribute *tcm_qla2xxx_tpg_attrib_attrs[] = {
/* End items for tcm_qla2xxx_tpg_attrib_cit */
-static ssize_t tcm_qla2xxx_tpg_enable_show(struct config_item *item,
- char *page)
-{
- struct se_portal_group *se_tpg = to_tpg(item);
- struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
- struct tcm_qla2xxx_tpg, se_tpg);
-
- return snprintf(page, PAGE_SIZE, "%d\n",
- atomic_read(&tpg->lport_tpg_enabled));
-}
-
-static ssize_t tcm_qla2xxx_tpg_enable_store(struct config_item *item,
- const char *page, size_t count)
+static int tcm_qla2xxx_enable_tpg(struct se_portal_group *se_tpg,
+ bool enable)
{
- struct se_portal_group *se_tpg = to_tpg(item);
struct se_wwn *se_wwn = se_tpg->se_tpg_wwn;
struct tcm_qla2xxx_lport *lport = container_of(se_wwn,
struct tcm_qla2xxx_lport, lport_wwn);
struct scsi_qla_host *vha = lport->qla_vha;
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
struct tcm_qla2xxx_tpg, se_tpg);
- unsigned long op;
- int rc;
- rc = kstrtoul(page, 0, &op);
- if (rc < 0) {
- pr_err("kstrtoul() returned %d\n", rc);
- return -EINVAL;
- }
- if ((op != 1) && (op != 0)) {
- pr_err("Illegal value for tpg_enable: %lu\n", op);
- return -EINVAL;
- }
- if (op) {
+ if (enable) {
if (atomic_read(&tpg->lport_tpg_enabled))
return -EEXIST;
@@ -922,13 +933,14 @@ static ssize_t tcm_qla2xxx_tpg_enable_store(struct config_item *item,
qlt_enable_vha(vha);
} else {
if (!atomic_read(&tpg->lport_tpg_enabled))
- return count;
+ return 0;
atomic_set(&tpg->lport_tpg_enabled, 0);
qlt_stop_phase1(vha->vha_tgt.qla_tgt);
+ qlt_stop_phase2(vha->vha_tgt.qla_tgt);
}
- return count;
+ return 0;
}
static ssize_t tcm_qla2xxx_tpg_dynamic_sessions_show(struct config_item *item,
@@ -969,12 +981,10 @@ static ssize_t tcm_qla2xxx_tpg_fabric_prot_type_show(struct config_item *item,
return sprintf(page, "%d\n", tpg->tpg_attrib.fabric_prot_type);
}
-CONFIGFS_ATTR(tcm_qla2xxx_tpg_, enable);
CONFIGFS_ATTR_RO(tcm_qla2xxx_tpg_, dynamic_sessions);
CONFIGFS_ATTR(tcm_qla2xxx_tpg_, fabric_prot_type);
static struct configfs_attribute *tcm_qla2xxx_tpg_attrs[] = {
- &tcm_qla2xxx_tpg_attr_enable,
&tcm_qla2xxx_tpg_attr_dynamic_sessions,
&tcm_qla2xxx_tpg_attr_fabric_prot_type,
NULL,
@@ -1048,35 +1058,17 @@ static void tcm_qla2xxx_drop_tpg(struct se_portal_group *se_tpg)
kfree(tpg);
}
-static ssize_t tcm_qla2xxx_npiv_tpg_enable_show(struct config_item *item,
- char *page)
+static int tcm_qla2xxx_npiv_enable_tpg(struct se_portal_group *se_tpg,
+ bool enable)
{
- return tcm_qla2xxx_tpg_enable_show(item, page);
-}
-
-static ssize_t tcm_qla2xxx_npiv_tpg_enable_store(struct config_item *item,
- const char *page, size_t count)
-{
- struct se_portal_group *se_tpg = to_tpg(item);
struct se_wwn *se_wwn = se_tpg->se_tpg_wwn;
struct tcm_qla2xxx_lport *lport = container_of(se_wwn,
struct tcm_qla2xxx_lport, lport_wwn);
struct scsi_qla_host *vha = lport->qla_vha;
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
struct tcm_qla2xxx_tpg, se_tpg);
- unsigned long op;
- int rc;
- rc = kstrtoul(page, 0, &op);
- if (rc < 0) {
- pr_err("kstrtoul() returned %d\n", rc);
- return -EINVAL;
- }
- if ((op != 1) && (op != 0)) {
- pr_err("Illegal value for tpg_enable: %lu\n", op);
- return -EINVAL;
- }
- if (op) {
+ if (enable) {
if (atomic_read(&tpg->lport_tpg_enabled))
return -EEXIST;
@@ -1084,22 +1076,16 @@ static ssize_t tcm_qla2xxx_npiv_tpg_enable_store(struct config_item *item,
qlt_enable_vha(vha);
} else {
if (!atomic_read(&tpg->lport_tpg_enabled))
- return count;
+ return 0;
atomic_set(&tpg->lport_tpg_enabled, 0);
qlt_stop_phase1(vha->vha_tgt.qla_tgt);
+ qlt_stop_phase2(vha->vha_tgt.qla_tgt);
}
- return count;
+ return 0;
}
-CONFIGFS_ATTR(tcm_qla2xxx_npiv_tpg_, enable);
-
-static struct configfs_attribute *tcm_qla2xxx_npiv_tpg_attrs[] = {
- &tcm_qla2xxx_npiv_tpg_attr_enable,
- NULL,
-};
-
static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg(struct se_wwn *wwn,
const char *name)
{
@@ -1369,8 +1355,6 @@ static void tcm_qla2xxx_free_session(struct fc_port *sess)
struct se_session *se_sess;
struct tcm_qla2xxx_lport *lport;
- BUG_ON(in_interrupt());
-
se_sess = sess->se_sess;
if (!se_sess) {
pr_err("struct fc_port->se_sess is NULL\n");
@@ -1544,11 +1528,13 @@ static void tcm_qla2xxx_update_sess(struct fc_port *sess, port_id_t s_id,
/*
* Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.
*/
-static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
+static const struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
.find_cmd_by_tag = tcm_qla2xxx_find_cmd_by_tag,
.handle_cmd = tcm_qla2xxx_handle_cmd,
.handle_data = tcm_qla2xxx_handle_data,
.handle_tmr = tcm_qla2xxx_handle_tmr,
+ .get_cmd = tcm_qla2xxx_get_cmd,
+ .rel_cmd = tcm_qla2xxx_rel_cmd,
.free_cmd = tcm_qla2xxx_free_cmd,
.free_mcmd = tcm_qla2xxx_free_mcmd,
.free_session = tcm_qla2xxx_free_session,
@@ -1842,6 +1828,7 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = {
.fabric_make_wwn = tcm_qla2xxx_make_lport,
.fabric_drop_wwn = tcm_qla2xxx_drop_lport,
.fabric_make_tpg = tcm_qla2xxx_make_tpg,
+ .fabric_enable_tpg = tcm_qla2xxx_enable_tpg,
.fabric_drop_tpg = tcm_qla2xxx_drop_tpg,
.fabric_init_nodeacl = tcm_qla2xxx_init_nodeacl,
@@ -1882,11 +1869,11 @@ static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
.fabric_make_wwn = tcm_qla2xxx_npiv_make_lport,
.fabric_drop_wwn = tcm_qla2xxx_npiv_drop_lport,
.fabric_make_tpg = tcm_qla2xxx_npiv_make_tpg,
+ .fabric_enable_tpg = tcm_qla2xxx_npiv_enable_tpg,
.fabric_drop_tpg = tcm_qla2xxx_drop_tpg,
.fabric_init_nodeacl = tcm_qla2xxx_init_nodeacl,
.tfc_wwn_attrs = tcm_qla2xxx_wwn_attrs,
- .tfc_tpg_base_attrs = tcm_qla2xxx_npiv_tpg_attrs,
};
static int tcm_qla2xxx_register_configfs(void)
@@ -1933,6 +1920,21 @@ static int __init tcm_qla2xxx_init(void)
{
int ret;
+ BUILD_BUG_ON(sizeof(struct abts_recv_from_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct abts_resp_from_24xx_fw) != 64);
+ BUILD_BUG_ON(sizeof(struct atio7_fcp_cmnd) != 32);
+ BUILD_BUG_ON(sizeof(struct atio_from_isp) != 64);
+ BUILD_BUG_ON(sizeof(struct ba_acc_le) != 12);
+ BUILD_BUG_ON(sizeof(struct ba_rjt_le) != 4);
+ BUILD_BUG_ON(sizeof(struct ctio7_from_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct ctio7_to_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct ctio_crc2_to_fw) != 64);
+ BUILD_BUG_ON(sizeof(struct ctio_crc_from_fw) != 64);
+ BUILD_BUG_ON(sizeof(struct ctio_to_2xxx) != 64);
+ BUILD_BUG_ON(sizeof(struct fcp_hdr) != 24);
+ BUILD_BUG_ON(sizeof(struct fcp_hdr_le) != 24);
+ BUILD_BUG_ON(sizeof(struct nack_to_isp) != 64);
+
ret = tcm_qla2xxx_register_configfs();
if (ret < 0)
return ret;