Commit 7560151b authored by Quinn Tran's avatar Quinn Tran Committed by Nicholas Bellinger

qla2xxx: Remove dependency on hardware_lock to reduce lock contention.

Sessions management (add, deleted, modify) currently are serialized
through the hardware_lock.  Hardware_lock is a high traffic lock.
This lock is accessed by both the transmit & receive sides.

Sessions management is now moved off to another lock call sess_lock.
This is done to reduce lock contention and increase traffic throughput.
Signed-off-by: default avatarQuinn Tran <quinn.tran@qlogic.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 193b50b9
...@@ -2929,6 +2929,7 @@ struct qlt_hw_data { ...@@ -2929,6 +2929,7 @@ struct qlt_hw_data {
uint32_t num_qfull_cmds_dropped; uint32_t num_qfull_cmds_dropped;
spinlock_t q_full_lock; spinlock_t q_full_lock;
uint32_t leak_exchg_thresh_hold; uint32_t leak_exchg_thresh_hold;
spinlock_t sess_lock;
}; };
#define MAX_QFULL_CMDS_ALLOC 8192 #define MAX_QFULL_CMDS_ALLOC 8192
......
...@@ -2336,6 +2336,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2336,6 +2336,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->tgt.enable_class_2 = ql2xenableclass2; ha->tgt.enable_class_2 = ql2xenableclass2;
INIT_LIST_HEAD(&ha->tgt.q_full_list); INIT_LIST_HEAD(&ha->tgt.q_full_list);
spin_lock_init(&ha->tgt.q_full_lock); spin_lock_init(&ha->tgt.q_full_lock);
spin_lock_init(&ha->tgt.sess_lock);
/* Clear our data area */ /* Clear our data area */
ha->bars = bars; ha->bars = bars;
......
...@@ -636,7 +636,7 @@ static void qlt_free_session_done(struct work_struct *work) ...@@ -636,7 +636,7 @@ static void qlt_free_session_done(struct work_struct *work)
wake_up_all(&tgt->waitQ); wake_up_all(&tgt->waitQ);
} }
/* ha->hardware_lock supposed to be held on entry */ /* ha->tgt.sess_lock supposed to be held on entry */
void qlt_unreg_sess(struct qla_tgt_sess *sess) void qlt_unreg_sess(struct qla_tgt_sess *sess)
{ {
struct scsi_qla_host *vha = sess->vha; struct scsi_qla_host *vha = sess->vha;
...@@ -652,7 +652,7 @@ void qlt_unreg_sess(struct qla_tgt_sess *sess) ...@@ -652,7 +652,7 @@ void qlt_unreg_sess(struct qla_tgt_sess *sess)
} }
EXPORT_SYMBOL(qlt_unreg_sess); EXPORT_SYMBOL(qlt_unreg_sess);
/* ha->hardware_lock supposed to be held on entry */
static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd) static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
{ {
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
...@@ -662,12 +662,15 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd) ...@@ -662,12 +662,15 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
int res = 0; int res = 0;
struct imm_ntfy_from_isp *n = (struct imm_ntfy_from_isp *)iocb; struct imm_ntfy_from_isp *n = (struct imm_ntfy_from_isp *)iocb;
struct atio_from_isp *a = (struct atio_from_isp *)iocb; struct atio_from_isp *a = (struct atio_from_isp *)iocb;
unsigned long flags;
loop_id = le16_to_cpu(n->u.isp24.nport_handle); loop_id = le16_to_cpu(n->u.isp24.nport_handle);
if (loop_id == 0xFFFF) { if (loop_id == 0xFFFF) {
/* Global event */ /* Global event */
atomic_inc(&vha->vha_tgt.qla_tgt->tgt_global_resets_count); atomic_inc(&vha->vha_tgt.qla_tgt->tgt_global_resets_count);
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
qlt_clear_tgt_db(vha->vha_tgt.qla_tgt); qlt_clear_tgt_db(vha->vha_tgt.qla_tgt);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
#if 0 /* FIXME: do we need to choose a session here? */ #if 0 /* FIXME: do we need to choose a session here? */
if (!list_empty(&ha->tgt.qla_tgt->sess_list)) { if (!list_empty(&ha->tgt.qla_tgt->sess_list)) {
sess = list_entry(ha->tgt.qla_tgt->sess_list.next, sess = list_entry(ha->tgt.qla_tgt->sess_list.next,
...@@ -694,7 +697,9 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd) ...@@ -694,7 +697,9 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
sess = NULL; sess = NULL;
#endif #endif
} else { } else {
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id); sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
} }
ql_dbg(ql_dbg_tgt, vha, 0xe000, ql_dbg(ql_dbg_tgt, vha, 0xe000,
...@@ -716,7 +721,7 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd) ...@@ -716,7 +721,7 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
iocb, QLA24XX_MGMT_SEND_NACK); iocb, QLA24XX_MGMT_SEND_NACK);
} }
/* ha->hardware_lock supposed to be held on entry */ /* ha->tgt.sess_lock supposed to be held on entry */
static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess, static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
bool immediate) bool immediate)
{ {
...@@ -760,7 +765,7 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess, ...@@ -760,7 +765,7 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
sess->expires - jiffies); sess->expires - jiffies);
} }
/* ha->hardware_lock supposed to be held on entry */ /* ha->tgt.sess_lock supposed to be held on entry */
static void qlt_clear_tgt_db(struct qla_tgt *tgt) static void qlt_clear_tgt_db(struct qla_tgt *tgt)
{ {
struct qla_tgt_sess *sess; struct qla_tgt_sess *sess;
...@@ -820,7 +825,7 @@ static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id, ...@@ -820,7 +825,7 @@ static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id,
return res; return res;
} }
/* ha->hardware_lock supposed to be held on entry */ /* ha->tgt.sess_lock supposed to be held on entry */
static void qlt_undelete_sess(struct qla_tgt_sess *sess) static void qlt_undelete_sess(struct qla_tgt_sess *sess)
{ {
BUG_ON(sess->deleted != QLA_SESS_DELETION_PENDING); BUG_ON(sess->deleted != QLA_SESS_DELETION_PENDING);
...@@ -838,7 +843,7 @@ static void qlt_del_sess_work_fn(struct delayed_work *work) ...@@ -838,7 +843,7 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
struct qla_tgt_sess *sess; struct qla_tgt_sess *sess;
unsigned long flags, elapsed; unsigned long flags, elapsed;
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->tgt.sess_lock, flags);
while (!list_empty(&tgt->del_sess_list)) { while (!list_empty(&tgt->del_sess_list)) {
sess = list_entry(tgt->del_sess_list.next, typeof(*sess), sess = list_entry(tgt->del_sess_list.next, typeof(*sess),
del_list_entry); del_list_entry);
...@@ -859,7 +864,7 @@ static void qlt_del_sess_work_fn(struct delayed_work *work) ...@@ -859,7 +864,7 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
break; break;
} }
} }
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
} }
/* /*
...@@ -877,7 +882,7 @@ static struct qla_tgt_sess *qlt_create_sess( ...@@ -877,7 +882,7 @@ static struct qla_tgt_sess *qlt_create_sess(
unsigned char be_sid[3]; unsigned char be_sid[3];
/* Check to avoid double sessions */ /* Check to avoid double sessions */
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->tgt.sess_lock, flags);
list_for_each_entry(sess, &vha->vha_tgt.qla_tgt->sess_list, list_for_each_entry(sess, &vha->vha_tgt.qla_tgt->sess_list,
sess_list_entry) { sess_list_entry) {
if (!memcmp(sess->port_name, fcport->port_name, WWN_SIZE)) { if (!memcmp(sess->port_name, fcport->port_name, WWN_SIZE)) {
...@@ -892,7 +897,7 @@ static struct qla_tgt_sess *qlt_create_sess( ...@@ -892,7 +897,7 @@ static struct qla_tgt_sess *qlt_create_sess(
/* Cannot undelete at this point */ /* Cannot undelete at this point */
if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
spin_unlock_irqrestore(&ha->hardware_lock, spin_unlock_irqrestore(&ha->tgt.sess_lock,
flags); flags);
return NULL; return NULL;
} }
...@@ -909,12 +914,12 @@ static struct qla_tgt_sess *qlt_create_sess( ...@@ -909,12 +914,12 @@ static struct qla_tgt_sess *qlt_create_sess(
qlt_do_generation_tick(vha, &sess->generation); qlt_do_generation_tick(vha, &sess->generation);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return sess; return sess;
} }
} }
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
sess = kzalloc(sizeof(*sess), GFP_KERNEL); sess = kzalloc(sizeof(*sess), GFP_KERNEL);
if (!sess) { if (!sess) {
...@@ -959,7 +964,7 @@ static struct qla_tgt_sess *qlt_create_sess( ...@@ -959,7 +964,7 @@ static struct qla_tgt_sess *qlt_create_sess(
} }
/* /*
* Take an extra reference to ->sess_kref here to handle qla_tgt_sess * Take an extra reference to ->sess_kref here to handle qla_tgt_sess
* access across ->hardware_lock reaquire. * access across ->tgt.sess_lock reaquire.
*/ */
kref_get(&sess->se_sess->sess_kref); kref_get(&sess->se_sess->sess_kref);
...@@ -967,11 +972,11 @@ static struct qla_tgt_sess *qlt_create_sess( ...@@ -967,11 +972,11 @@ static struct qla_tgt_sess *qlt_create_sess(
BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name)); BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));
memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->tgt.sess_lock, flags);
list_add_tail(&sess->sess_list_entry, &vha->vha_tgt.qla_tgt->sess_list); list_add_tail(&sess->sess_list_entry, &vha->vha_tgt.qla_tgt->sess_list);
vha->vha_tgt.qla_tgt->sess_count++; vha->vha_tgt.qla_tgt->sess_count++;
qlt_do_generation_tick(vha, &sess->generation); qlt_do_generation_tick(vha, &sess->generation);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b,
"qla_target(%d): %ssession for wwn %8phC (loop_id %d, " "qla_target(%d): %ssession for wwn %8phC (loop_id %d, "
...@@ -1002,23 +1007,23 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) ...@@ -1002,23 +1007,23 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
if (qla_ini_mode_enabled(vha)) if (qla_ini_mode_enabled(vha))
return; return;
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->tgt.sess_lock, flags);
if (tgt->tgt_stop) { if (tgt->tgt_stop) {
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return; return;
} }
sess = qlt_find_sess_by_port_name(tgt, fcport->port_name); sess = qlt_find_sess_by_port_name(tgt, fcport->port_name);
if (!sess) { if (!sess) {
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
mutex_lock(&vha->vha_tgt.tgt_mutex); mutex_lock(&vha->vha_tgt.tgt_mutex);
sess = qlt_create_sess(vha, fcport, false); sess = qlt_create_sess(vha, fcport, false);
mutex_unlock(&vha->vha_tgt.tgt_mutex); mutex_unlock(&vha->vha_tgt.tgt_mutex);
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->tgt.sess_lock, flags);
} else if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { } else if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
/* Point of no return */ /* Point of no return */
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return; return;
} else { } else {
kref_get(&sess->se_sess->sess_kref); kref_get(&sess->se_sess->sess_kref);
...@@ -1047,7 +1052,7 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) ...@@ -1047,7 +1052,7 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
sess->local = 0; sess->local = 0;
} }
ha->tgt.tgt_ops->put_sess(sess); ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
} }
/* /*
...@@ -1059,6 +1064,7 @@ qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen) ...@@ -1059,6 +1064,7 @@ qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
{ {
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
struct qla_tgt_sess *sess; struct qla_tgt_sess *sess;
unsigned long flags;
if (!vha->hw->tgt.tgt_ops) if (!vha->hw->tgt.tgt_ops)
return; return;
...@@ -1066,15 +1072,19 @@ qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen) ...@@ -1066,15 +1072,19 @@ qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
if (!tgt) if (!tgt)
return; return;
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
if (tgt->tgt_stop) { if (tgt->tgt_stop) {
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
return; return;
} }
sess = qlt_find_sess_by_port_name(tgt, fcport->port_name); sess = qlt_find_sess_by_port_name(tgt, fcport->port_name);
if (!sess) { if (!sess) {
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
return; return;
} }
if (max_gen - sess->generation < 0) { if (max_gen - sess->generation < 0) {
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf092, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf092,
"Ignoring stale deletion request for se_sess %p / sess %p" "Ignoring stale deletion request for se_sess %p / sess %p"
" for port %8phC, req_gen %d, sess_gen %d\n", " for port %8phC, req_gen %d, sess_gen %d\n",
...@@ -1087,6 +1097,7 @@ qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen) ...@@ -1087,6 +1097,7 @@ qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
sess->local = 1; sess->local = 1;
qlt_schedule_sess_for_deletion(sess, false); qlt_schedule_sess_for_deletion(sess, false);
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
} }
static inline int test_tgt_sess_count(struct qla_tgt *tgt) static inline int test_tgt_sess_count(struct qla_tgt *tgt)
...@@ -1144,10 +1155,10 @@ int qlt_stop_phase1(struct qla_tgt *tgt) ...@@ -1144,10 +1155,10 @@ int qlt_stop_phase1(struct qla_tgt *tgt)
* Lock is needed, because we still can get an incoming packet. * Lock is needed, because we still can get an incoming packet.
*/ */
mutex_lock(&vha->vha_tgt.tgt_mutex); mutex_lock(&vha->vha_tgt.tgt_mutex);
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->tgt.sess_lock, flags);
tgt->tgt_stop = 1; tgt->tgt_stop = 1;
qlt_clear_tgt_db(tgt); qlt_clear_tgt_db(tgt);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
mutex_unlock(&vha->vha_tgt.tgt_mutex); mutex_unlock(&vha->vha_tgt.tgt_mutex);
mutex_unlock(&qla_tgt_mutex); mutex_unlock(&qla_tgt_mutex);
...@@ -1595,6 +1606,7 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, ...@@ -1595,6 +1606,7 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
uint32_t tag = abts->exchange_addr_to_abort; uint32_t tag = abts->exchange_addr_to_abort;
uint8_t s_id[3]; uint8_t s_id[3];
int rc; int rc;
unsigned long flags;
if (le32_to_cpu(abts->fcp_hdr_le.parameter) & ABTS_PARAM_ABORT_SEQ) { if (le32_to_cpu(abts->fcp_hdr_le.parameter) & ABTS_PARAM_ABORT_SEQ) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf053, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf053,
...@@ -1622,6 +1634,7 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, ...@@ -1622,6 +1634,7 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
s_id[1] = abts->fcp_hdr_le.s_id[1]; s_id[1] = abts->fcp_hdr_le.s_id[1];
s_id[2] = abts->fcp_hdr_le.s_id[0]; s_id[2] = abts->fcp_hdr_le.s_id[0];
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id);
if (!sess) { if (!sess) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf012, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf012,
...@@ -1629,12 +1642,17 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, ...@@ -1629,12 +1642,17 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
vha->vp_idx); vha->vp_idx);
rc = qlt_sched_sess_work(vha->vha_tgt.qla_tgt, rc = qlt_sched_sess_work(vha->vha_tgt.qla_tgt,
QLA_TGT_SESS_WORK_ABORT, abts, sizeof(*abts)); QLA_TGT_SESS_WORK_ABORT, abts, sizeof(*abts));
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
if (rc != 0) { if (rc != 0) {
qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED,
false); false);
} }
return; return;
} }
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false);
...@@ -3765,9 +3783,9 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) ...@@ -3765,9 +3783,9 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
/* /*
* Drop extra session reference from qla_tgt_handle_cmd_for_atio*( * Drop extra session reference from qla_tgt_handle_cmd_for_atio*(
*/ */
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->tgt.sess_lock, flags);
ha->tgt.tgt_ops->put_sess(sess); ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return; return;
out_term: out_term:
...@@ -3782,8 +3800,11 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) ...@@ -3782,8 +3800,11 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
qlt_decr_num_pend_cmds(vha); qlt_decr_num_pend_cmds(vha);
percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
} }
static void qlt_do_work(struct work_struct *work) static void qlt_do_work(struct work_struct *work)
...@@ -4091,13 +4112,18 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb) ...@@ -4091,13 +4112,18 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb)
struct qla_tgt_sess *sess; struct qla_tgt_sess *sess;
uint32_t lun, unpacked_lun; uint32_t lun, unpacked_lun;
int fn; int fn;
unsigned long flags;
tgt = vha->vha_tgt.qla_tgt; tgt = vha->vha_tgt.qla_tgt;
lun = a->u.isp24.fcp_cmnd.lun; lun = a->u.isp24.fcp_cmnd.lun;
fn = a->u.isp24.fcp_cmnd.task_mgmt_flags; fn = a->u.isp24.fcp_cmnd.task_mgmt_flags;
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
a->u.isp24.fcp_hdr.s_id); a->u.isp24.fcp_hdr.s_id);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun);
if (!sess) { if (!sess) {
...@@ -4161,10 +4187,14 @@ static int qlt_abort_task(struct scsi_qla_host *vha, ...@@ -4161,10 +4187,14 @@ static int qlt_abort_task(struct scsi_qla_host *vha,
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
struct qla_tgt_sess *sess; struct qla_tgt_sess *sess;
int loop_id; int loop_id;
unsigned long flags;
loop_id = GET_TARGET_ID(ha, (struct atio_from_isp *)iocb); loop_id = GET_TARGET_ID(ha, (struct atio_from_isp *)iocb);
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id); sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
if (sess == NULL) { if (sess == NULL) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf025, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf025,
"qla_target(%d): task abort for unexisting " "qla_target(%d): task abort for unexisting "
...@@ -4311,6 +4341,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, ...@@ -4311,6 +4341,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
uint16_t wd3_lo; uint16_t wd3_lo;
int res = 0; int res = 0;
qlt_plogi_ack_t *pla; qlt_plogi_ack_t *pla;
unsigned long flags;
wwn = wwn_to_u64(iocb->u.isp24.port_name); wwn = wwn_to_u64(iocb->u.isp24.port_name);
...@@ -4334,9 +4365,12 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, ...@@ -4334,9 +4365,12 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
/* Mark all stale commands in qla_tgt_wq for deletion */ /* Mark all stale commands in qla_tgt_wq for deletion */
abort_cmds_for_s_id(vha, &port_id); abort_cmds_for_s_id(vha, &port_id);
if (wwn) if (wwn) {
spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
sess = qlt_find_sess_invalidate_other(tgt, wwn, sess = qlt_find_sess_invalidate_other(tgt, wwn,
port_id, loop_id, &conflict_sess); port_id, loop_id, &conflict_sess);
spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock, flags);
}
if (IS_SW_RESV_ADDR(port_id) || (!sess && !conflict_sess)) { if (IS_SW_RESV_ADDR(port_id) || (!sess && !conflict_sess)) {
res = 1; res = 1;
...@@ -4387,9 +4421,12 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, ...@@ -4387,9 +4421,12 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
case ELS_PRLI: case ELS_PRLI:
wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo); wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo);
if (wwn) if (wwn) {
spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
sess = qlt_find_sess_invalidate_other(tgt, wwn, port_id, sess = qlt_find_sess_invalidate_other(tgt, wwn, port_id,
loop_id, &conflict_sess); loop_id, &conflict_sess);
spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock, flags);
}
if (conflict_sess) { if (conflict_sess) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf09b, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf09b,
...@@ -5068,9 +5105,12 @@ static int __qlt_send_busy(struct scsi_qla_host *vha, ...@@ -5068,9 +5105,12 @@ static int __qlt_send_busy(struct scsi_qla_host *vha,
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
request_t *pkt; request_t *pkt;
struct qla_tgt_sess *sess = NULL; struct qla_tgt_sess *sess = NULL;
unsigned long flags;
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
atio->u.isp24.fcp_hdr.s_id); atio->u.isp24.fcp_hdr.s_id);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
if (!sess) { if (!sess) {
qlt_send_term_exchange(vha, NULL, atio, 1); qlt_send_term_exchange(vha, NULL, atio, 1);
return 0; return 0;
...@@ -5771,15 +5811,15 @@ static void qlt_abort_work(struct qla_tgt *tgt, ...@@ -5771,15 +5811,15 @@ static void qlt_abort_work(struct qla_tgt *tgt,
struct scsi_qla_host *vha = tgt->vha; struct scsi_qla_host *vha = tgt->vha;
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
struct qla_tgt_sess *sess = NULL; struct qla_tgt_sess *sess = NULL;
unsigned long flags; unsigned long flags = 0, flags2 = 0;
uint32_t be_s_id; uint32_t be_s_id;
uint8_t s_id[3]; uint8_t s_id[3];
int rc; int rc;
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->tgt.sess_lock, flags2);
if (tgt->tgt_stop) if (tgt->tgt_stop)
goto out_term; goto out_term2;
s_id[0] = prm->abts.fcp_hdr_le.s_id[2]; s_id[0] = prm->abts.fcp_hdr_le.s_id[2];
s_id[1] = prm->abts.fcp_hdr_le.s_id[1]; s_id[1] = prm->abts.fcp_hdr_le.s_id[1];
...@@ -5788,39 +5828,47 @@ static void qlt_abort_work(struct qla_tgt *tgt, ...@@ -5788,39 +5828,47 @@ static void qlt_abort_work(struct qla_tgt *tgt,
sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
(unsigned char *)&be_s_id); (unsigned char *)&be_s_id);
if (!sess) { if (!sess) {
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
sess = qlt_make_local_sess(vha, s_id); sess = qlt_make_local_sess(vha, s_id);
/* sess has got an extra creation ref */ /* sess has got an extra creation ref */
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->tgt.sess_lock, flags2);
if (!sess) if (!sess)
goto out_term; goto out_term2;
} else { } else {
if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
sess = NULL; sess = NULL;
goto out_term; goto out_term2;
} }
kref_get(&sess->se_sess->sess_kref); kref_get(&sess->se_sess->sess_kref);
} }
spin_lock_irqsave(&ha->hardware_lock, flags);
if (tgt->tgt_stop) if (tgt->tgt_stop)
goto out_term; goto out_term;
rc = __qlt_24xx_handle_abts(vha, &prm->abts, sess); rc = __qlt_24xx_handle_abts(vha, &prm->abts, sess);
if (rc != 0) if (rc != 0)
goto out_term; goto out_term;
spin_unlock_irqrestore(&ha->hardware_lock, flags);
ha->tgt.tgt_ops->put_sess(sess); ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
return; return;
out_term2:
spin_lock_irqsave(&ha->hardware_lock, flags);
out_term: out_term:
qlt_24xx_send_abts_resp(vha, &prm->abts, FCP_TMF_REJECTED, false); qlt_24xx_send_abts_resp(vha, &prm->abts, FCP_TMF_REJECTED, false);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (sess) if (sess)
ha->tgt.tgt_ops->put_sess(sess); ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
} }
static void qlt_tmr_work(struct qla_tgt *tgt, static void qlt_tmr_work(struct qla_tgt *tgt,
...@@ -5837,7 +5885,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt, ...@@ -5837,7 +5885,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
int fn; int fn;
void *iocb; void *iocb;
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->tgt.sess_lock, flags);
if (tgt->tgt_stop) if (tgt->tgt_stop)
goto out_term; goto out_term;
...@@ -5845,12 +5893,12 @@ static void qlt_tmr_work(struct qla_tgt *tgt, ...@@ -5845,12 +5893,12 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
s_id = prm->tm_iocb2.u.isp24.fcp_hdr.s_id; s_id = prm->tm_iocb2.u.isp24.fcp_hdr.s_id;
sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id);
if (!sess) { if (!sess) {
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
sess = qlt_make_local_sess(vha, s_id); sess = qlt_make_local_sess(vha, s_id);
/* sess has got an extra creation ref */ /* sess has got an extra creation ref */
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->tgt.sess_lock, flags);
if (!sess) if (!sess)
goto out_term; goto out_term;
} else { } else {
...@@ -5872,14 +5920,14 @@ static void qlt_tmr_work(struct qla_tgt *tgt, ...@@ -5872,14 +5920,14 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
goto out_term; goto out_term;
ha->tgt.tgt_ops->put_sess(sess); ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return; return;
out_term: out_term:
qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1); qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 0);
if (sess) if (sess)
ha->tgt.tgt_ops->put_sess(sess); ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
} }
static void qlt_sess_work_fn(struct work_struct *work) static void qlt_sess_work_fn(struct work_struct *work)
......
...@@ -344,9 +344,9 @@ static int tcm_qla2xxx_shutdown_session(struct se_session *se_sess) ...@@ -344,9 +344,9 @@ static int tcm_qla2xxx_shutdown_session(struct se_session *se_sess)
BUG_ON(!sess); BUG_ON(!sess);
vha = sess->vha; vha = sess->vha;
spin_lock_irqsave(&vha->hw->hardware_lock, flags); spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
target_sess_cmd_list_set_waiting(se_sess); target_sess_cmd_list_set_waiting(se_sess);
spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
return 1; return 1;
} }
...@@ -360,9 +360,9 @@ static void tcm_qla2xxx_close_session(struct se_session *se_sess) ...@@ -360,9 +360,9 @@ static void tcm_qla2xxx_close_session(struct se_session *se_sess)
BUG_ON(!sess); BUG_ON(!sess);
vha = sess->vha; vha = sess->vha;
spin_lock_irqsave(&vha->hw->hardware_lock, flags); spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
qlt_unreg_sess(sess); qlt_unreg_sess(sess);
spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
} }
static u32 tcm_qla2xxx_sess_get_index(struct se_session *se_sess) static u32 tcm_qla2xxx_sess_get_index(struct se_session *se_sess)
...@@ -647,7 +647,7 @@ static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd) ...@@ -647,7 +647,7 @@ static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd)
static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *,
struct tcm_qla2xxx_nacl *, struct qla_tgt_sess *); struct tcm_qla2xxx_nacl *, struct qla_tgt_sess *);
/* /*
* Expected to be called with struct qla_hw_data->hardware_lock held * Expected to be called with struct qla_hw_data->tgt.sess_lock held
*/ */
static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess) static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess)
{ {
...@@ -701,13 +701,13 @@ static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess) ...@@ -701,13 +701,13 @@ static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess)
if (!sess) if (!sess)
return; return;
assert_spin_locked(&sess->vha->hw->hardware_lock); assert_spin_locked(&sess->vha->hw->tgt.sess_lock);
kref_put(&sess->se_sess->sess_kref, tcm_qla2xxx_release_session); kref_put(&sess->se_sess->sess_kref, tcm_qla2xxx_release_session);
} }
static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess) static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess)
{ {
assert_spin_locked(&sess->vha->hw->hardware_lock); assert_spin_locked(&sess->vha->hw->tgt.sess_lock);
target_sess_cmd_list_set_waiting(sess->se_sess); target_sess_cmd_list_set_waiting(sess->se_sess);
} }
...@@ -1081,7 +1081,7 @@ static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg( ...@@ -1081,7 +1081,7 @@ static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg(
} }
/* /*
* Expected to be called with struct qla_hw_data->hardware_lock held * Expected to be called with struct qla_hw_data->tgt.sess_lock held
*/ */
static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id( static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id(
scsi_qla_host_t *vha, scsi_qla_host_t *vha,
...@@ -1120,7 +1120,7 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id( ...@@ -1120,7 +1120,7 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id(
} }
/* /*
* Expected to be called with struct qla_hw_data->hardware_lock held * Expected to be called with struct qla_hw_data->tgt.sess_lock held
*/ */
static void tcm_qla2xxx_set_sess_by_s_id( static void tcm_qla2xxx_set_sess_by_s_id(
struct tcm_qla2xxx_lport *lport, struct tcm_qla2xxx_lport *lport,
...@@ -1186,7 +1186,7 @@ static void tcm_qla2xxx_set_sess_by_s_id( ...@@ -1186,7 +1186,7 @@ static void tcm_qla2xxx_set_sess_by_s_id(
} }
/* /*
* Expected to be called with struct qla_hw_data->hardware_lock held * Expected to be called with struct qla_hw_data->tgt.sess_lock held
*/ */
static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id( static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id(
scsi_qla_host_t *vha, scsi_qla_host_t *vha,
...@@ -1225,7 +1225,7 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id( ...@@ -1225,7 +1225,7 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id(
} }
/* /*
* Expected to be called with struct qla_hw_data->hardware_lock held * Expected to be called with struct qla_hw_data->tgt.sess_lock held
*/ */
static void tcm_qla2xxx_set_sess_by_loop_id( static void tcm_qla2xxx_set_sess_by_loop_id(
struct tcm_qla2xxx_lport *lport, struct tcm_qla2xxx_lport *lport,
...@@ -1289,7 +1289,7 @@ static void tcm_qla2xxx_set_sess_by_loop_id( ...@@ -1289,7 +1289,7 @@ static void tcm_qla2xxx_set_sess_by_loop_id(
} }
/* /*
* Should always be called with qla_hw_data->hardware_lock held. * Should always be called with qla_hw_data->tgt.sess_lock held.
*/ */
static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *lport, static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *lport,
struct tcm_qla2xxx_nacl *nacl, struct qla_tgt_sess *sess) struct tcm_qla2xxx_nacl *nacl, struct qla_tgt_sess *sess)
...@@ -1405,12 +1405,12 @@ static int tcm_qla2xxx_check_initiator_node_acl( ...@@ -1405,12 +1405,12 @@ static int tcm_qla2xxx_check_initiator_node_acl(
* And now setup the new se_nacl and session pointers into our HW lport * And now setup the new se_nacl and session pointers into our HW lport
* mappings for fabric S_ID and LOOP_ID. * mappings for fabric S_ID and LOOP_ID.
*/ */
spin_lock_irqsave(&ha->hardware_lock, flags); spin_lock_irqsave(&ha->tgt.sess_lock, flags);
tcm_qla2xxx_set_sess_by_s_id(lport, se_nacl, nacl, se_sess, tcm_qla2xxx_set_sess_by_s_id(lport, se_nacl, nacl, se_sess,
qla_tgt_sess, s_id); qla_tgt_sess, s_id);
tcm_qla2xxx_set_sess_by_loop_id(lport, se_nacl, nacl, se_sess, tcm_qla2xxx_set_sess_by_loop_id(lport, se_nacl, nacl, se_sess,
qla_tgt_sess, loop_id); qla_tgt_sess, loop_id);
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
/* /*
* Finally register the new FC Nexus with TCM * Finally register the new FC Nexus with TCM
*/ */
......
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