summaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c141
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c48
-rw-r--r--drivers/scsi/scsi_error.c2
-rw-r--r--drivers/scsi/scsi_lib.c6
-rw-r--r--drivers/scsi/scsi_sysfs.c2
-rw-r--r--drivers/scsi/st.c2
7 files changed, 146 insertions, 57 deletions
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 0e6ee3ca3..e9ae6b924 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -68,7 +68,7 @@
* | | | 0xd101-0xd1fe |
* | | | 0xd214-0xd2fe |
* | Target Mode | 0xe079 | |
- * | Target Mode Management | 0xf072 | 0xf002 |
+ * | Target Mode Management | 0xf080 | 0xf002 |
* | | | 0xf046-0xf049 |
* | Target Mode Task Management | 0x1000b | |
* ----------------------------------------------------------------------
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 285cb204f..998498e23 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2924,6 +2924,7 @@ qla2x00_rport_del(void *data)
struct fc_rport *rport;
scsi_qla_host_t *vha = fcport->vha;
unsigned long flags;
+ unsigned long vha_flags;
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
rport = fcport->drport ? fcport->drport: fcport->rport;
@@ -2935,7 +2936,9 @@ qla2x00_rport_del(void *data)
* Release the target mode FC NEXUS in qla_target.c code
* if target mod is enabled.
*/
+ spin_lock_irqsave(&vha->hw->hardware_lock, vha_flags);
qlt_fc_port_deleted(vha, fcport);
+ spin_unlock_irqrestore(&vha->hw->hardware_lock, vha_flags);
}
}
@@ -3303,6 +3306,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
* Create target mode FC NEXUS in qla_target.c if target mode is
* enabled..
*/
+
qlt_fc_port_added(vha, fcport);
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
@@ -3460,20 +3464,43 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
continue;
- if (fcport->scan_state == QLA_FCPORT_SCAN &&
- atomic_read(&fcport->state) == FCS_ONLINE) {
- qla2x00_mark_device_lost(vha, fcport,
- ql2xplogiabsentdevice, 0);
- if (fcport->loop_id != FC_NO_LOOP_ID &&
- (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
- fcport->port_type != FCT_INITIATOR &&
- fcport->port_type != FCT_BROADCAST) {
- ha->isp_ops->fabric_logout(vha,
- fcport->loop_id,
- fcport->d_id.b.domain,
- fcport->d_id.b.area,
- fcport->d_id.b.al_pa);
- qla2x00_clear_loop_id(fcport);
+ if (fcport->scan_state == QLA_FCPORT_SCAN) {
+ if (qla_ini_mode_enabled(base_vha) &&
+ atomic_read(&fcport->state) == FCS_ONLINE) {
+ qla2x00_mark_device_lost(vha, fcport,
+ ql2xplogiabsentdevice, 0);
+ if (fcport->loop_id != FC_NO_LOOP_ID &&
+ (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
+ fcport->port_type != FCT_INITIATOR &&
+ fcport->port_type != FCT_BROADCAST) {
+ ha->isp_ops->fabric_logout(vha,
+ fcport->loop_id,
+ fcport->d_id.b.domain,
+ fcport->d_id.b.area,
+ fcport->d_id.b.al_pa);
+ qla2x00_clear_loop_id(fcport);
+ }
+ } else if (!qla_ini_mode_enabled(base_vha)) {
+ /*
+ * In target mode, explicitly kill
+ * sessions and log out of devices
+ * that are gone, so that we don't
+ * end up with an initiator using the
+ * wrong ACL (if the fabric recycles
+ * an FC address and we have a stale
+ * session around) and so that we don't
+ * report initiators that are no longer
+ * on the fabric.
+ */
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf077,
+ "port gone, logging out/killing session: "
+ "%8phC state 0x%x flags 0x%x fc4_type 0x%x "
+ "scan_state %d\n",
+ fcport->port_name,
+ atomic_read(&fcport->state),
+ fcport->flags, fcport->fc4_type,
+ fcport->scan_state);
+ qlt_fc_port_deleted(vha, fcport);
}
}
}
@@ -3494,6 +3521,28 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
(fcport->flags & FCF_LOGIN_NEEDED) == 0)
continue;
+ /*
+ * If we're not an initiator, skip looking for devices
+ * and logging in. There's no reason for us to do it,
+ * and it seems to actively cause problems in target
+ * mode if we race with the initiator logging into us
+ * (we might get the "port ID used" status back from
+ * our login command and log out the initiator, which
+ * seems to cause havoc).
+ */
+ if (!qla_ini_mode_enabled(base_vha)) {
+ if (fcport->scan_state == QLA_FCPORT_FOUND) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf078,
+ "port %8phC state 0x%x flags 0x%x fc4_type 0x%x "
+ "scan_state %d (initiator mode disabled; skipping "
+ "login)\n", fcport->port_name,
+ atomic_read(&fcport->state),
+ fcport->flags, fcport->fc4_type,
+ fcport->scan_state);
+ }
+ continue;
+ }
+
if (fcport->loop_id == FC_NO_LOOP_ID) {
fcport->loop_id = next_loopid;
rval = qla2x00_find_new_loop_id(
@@ -3520,16 +3569,38 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
break;
- /* Find a new loop ID to use. */
- fcport->loop_id = next_loopid;
- rval = qla2x00_find_new_loop_id(base_vha, fcport);
- if (rval != QLA_SUCCESS) {
- /* Ran out of IDs to use */
- break;
- }
+ /*
+ * If we're not an initiator, skip looking for devices
+ * and logging in. There's no reason for us to do it,
+ * and it seems to actively cause problems in target
+ * mode if we race with the initiator logging into us
+ * (we might get the "port ID used" status back from
+ * our login command and log out the initiator, which
+ * seems to cause havoc).
+ */
+ if (qla_ini_mode_enabled(base_vha)) {
+ /* Find a new loop ID to use. */
+ fcport->loop_id = next_loopid;
+ rval = qla2x00_find_new_loop_id(base_vha,
+ fcport);
+ if (rval != QLA_SUCCESS) {
+ /* Ran out of IDs to use */
+ break;
+ }
- /* Login and update database */
- qla2x00_fabric_dev_login(vha, fcport, &next_loopid);
+ /* Login and update database */
+ qla2x00_fabric_dev_login(vha, fcport,
+ &next_loopid);
+ } else {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf079,
+ "new port %8phC state 0x%x flags 0x%x fc4_type "
+ "0x%x scan_state %d (initiator mode disabled; "
+ "skipping login)\n",
+ fcport->port_name,
+ atomic_read(&fcport->state),
+ fcport->flags, fcport->fc4_type,
+ fcport->scan_state);
+ }
list_move_tail(&fcport->list, &vha->vp_fcports);
}
@@ -3725,11 +3796,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
fcport->fp_speed = new_fcport->fp_speed;
/*
- * If address the same and state FCS_ONLINE, nothing
- * changed.
+ * If address the same and state FCS_ONLINE
+ * (or in target mode), nothing changed.
*/
if (fcport->d_id.b24 == new_fcport->d_id.b24 &&
- atomic_read(&fcport->state) == FCS_ONLINE) {
+ (atomic_read(&fcport->state) == FCS_ONLINE ||
+ !qla_ini_mode_enabled(base_vha))) {
break;
}
@@ -3749,6 +3821,22 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
* Log it out if still logged in and mark it for
* relogin later.
*/
+ if (!qla_ini_mode_enabled(base_vha)) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080,
+ "port changed FC ID, %8phC"
+ " old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n",
+ fcport->port_name,
+ fcport->d_id.b.domain,
+ fcport->d_id.b.area,
+ fcport->d_id.b.al_pa,
+ fcport->loop_id,
+ new_fcport->d_id.b.domain,
+ new_fcport->d_id.b.area,
+ new_fcport->d_id.b.al_pa);
+ fcport->d_id.b24 = new_fcport->d_id.b24;
+ break;
+ }
+
fcport->d_id.b24 = new_fcport->d_id.b24;
fcport->flags |= FCF_LOGIN_NEEDED;
if (fcport->loop_id != FC_NO_LOOP_ID &&
@@ -3768,6 +3856,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
if (found)
continue;
/* If device was not in our fcports list, then add it. */
+ new_fcport->scan_state = QLA_FCPORT_FOUND;
list_add_tail(&new_fcport->list, new_fcports);
/* Allocate a new replacement fcport. */
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index fe8a8d157..496a733d0 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -113,6 +113,7 @@ static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha,
static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
struct atio_from_isp *atio, uint16_t status, int qfull);
static void qlt_disable_vha(struct scsi_qla_host *vha);
+static void qlt_clear_tgt_db(struct qla_tgt *tgt);
/*
* Global Variables
*/
@@ -431,10 +432,10 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
loop_id = le16_to_cpu(n->u.isp24.nport_handle);
if (loop_id == 0xFFFF) {
-#if 0 /* FIXME: Re-enable Global event handling.. */
/* Global event */
- atomic_inc(&ha->tgt.qla_tgt->tgt_global_resets_count);
- qlt_clear_tgt_db(ha->tgt.qla_tgt);
+ atomic_inc(&vha->vha_tgt.qla_tgt->tgt_global_resets_count);
+ qlt_clear_tgt_db(vha->vha_tgt.qla_tgt);
+#if 0 /* FIXME: do we need to choose a session here? */
if (!list_empty(&ha->tgt.qla_tgt->sess_list)) {
sess = list_entry(ha->tgt.qla_tgt->sess_list.next,
typeof(*sess), sess_list_entry);
@@ -782,25 +783,20 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport)
{
- struct qla_hw_data *ha = vha->hw;
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
struct qla_tgt_sess *sess;
- unsigned long flags;
if (!vha->hw->tgt.tgt_ops)
return;
- if (!tgt || (fcport->port_type != FCT_INITIATOR))
+ if (!tgt)
return;
- spin_lock_irqsave(&ha->hardware_lock, flags);
if (tgt->tgt_stop) {
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
return;
}
sess = qlt_find_sess_by_port_name(tgt, fcport->port_name);
if (!sess) {
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
return;
}
@@ -808,7 +804,6 @@ void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport)
sess->local = 1;
qlt_schedule_sess_for_deletion(sess, false);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
static inline int test_tgt_sess_count(struct qla_tgt *tgt)
@@ -2347,9 +2342,10 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
res = qlt_build_ctio_crc2_pkt(&prm, vha);
else
res = qlt_24xx_build_ctio_pkt(&prm, vha);
- if (unlikely(res != 0))
+ if (unlikely(res != 0)) {
+ vha->req->cnt += full_req_cnt;
goto out_unmap_unlock;
-
+ }
pkt = (struct ctio7_to_24xx *)prm.pkt;
@@ -2487,8 +2483,11 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
else
res = qlt_24xx_build_ctio_pkt(&prm, vha);
- if (unlikely(res != 0))
+ if (unlikely(res != 0)) {
+ vha->req->cnt += prm.req_cnt;
goto out_unlock_free_unmap;
+ }
+
pkt = (struct ctio7_to_24xx *)prm.pkt;
pkt->u.status0.flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DATA_OUT |
CTIO7_FLAGS_STATUS_MODE_0);
@@ -2717,7 +2716,7 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
static void qlt_send_term_exchange(struct scsi_qla_host *vha,
struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked)
{
- unsigned long flags;
+ unsigned long flags = 0;
int rc;
if (qlt_issue_marker(vha, ha_locked) < 0)
@@ -2733,17 +2732,18 @@ static void qlt_send_term_exchange(struct scsi_qla_host *vha,
rc = __qlt_send_term_exchange(vha, cmd, atio);
if (rc == -ENOMEM)
qlt_alloc_qfull_cmd(vha, atio, 0, 0);
- spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
done:
if (cmd && ((cmd->state != QLA_TGT_STATE_ABORTED) ||
!cmd->cmd_sent_to_fw)) {
- if (!ha_locked && !in_interrupt())
- msleep(250); /* just in case */
-
- qlt_unmap_sg(vha, cmd);
+ if (cmd->sg_mapped)
+ qlt_unmap_sg(vha, cmd);
vha->hw->tgt.tgt_ops->free_cmd(cmd);
}
+
+ if (!ha_locked)
+ spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
+
return;
}
@@ -3347,6 +3347,11 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
cmd->loop_id = sess->loop_id;
cmd->conf_compl_supported = sess->conf_compl_supported;
+ cmd->cmd_flags = 0;
+ cmd->jiffies_at_alloc = get_jiffies_64();
+
+ cmd->reset_count = vha->hw->chip_reset;
+
return cmd;
}
@@ -3453,11 +3458,6 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
return -ENOMEM;
}
- cmd->cmd_flags = 0;
- cmd->jiffies_at_alloc = get_jiffies_64();
-
- cmd->reset_count = vha->hw->chip_reset;
-
cmd->cmd_in_wq = 1;
cmd->cmd_flags |= BIT_0;
INIT_WORK(&cmd->work, qlt_do_work);
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index c95a4e943..59c31bf88 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -944,7 +944,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
scmd->sdb.length);
scmd->sdb.table.sgl = &ses->sense_sgl;
scmd->sc_data_direction = DMA_FROM_DEVICE;
- scmd->sdb.table.nents = 1;
+ scmd->sdb.table.nents = scmd->sdb.table.orig_nents = 1;
scmd->cmnd[0] = REQUEST_SENSE;
scmd->cmnd[4] = scmd->sdb.length;
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index b1a263137..448ebdaa3 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -583,7 +583,7 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask)
static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq)
{
- if (mq && sdb->table.nents <= SCSI_MAX_SG_SEGMENTS)
+ if (mq && sdb->table.orig_nents <= SCSI_MAX_SG_SEGMENTS)
return;
__sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free);
}
@@ -597,8 +597,8 @@ static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq)
if (mq) {
if (nents <= SCSI_MAX_SG_SEGMENTS) {
- sdb->table.nents = nents;
- sg_init_table(sdb->table.sgl, sdb->table.nents);
+ sdb->table.nents = sdb->table.orig_nents = nents;
+ sg_init_table(sdb->table.sgl, nents);
return 0;
}
first_chunk = sdb->table.sgl;
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 1ac38e73d..9ad41168d 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -859,7 +859,7 @@ sdev_store_queue_depth(struct device *dev, struct device_attribute *attr,
depth = simple_strtoul(buf, NULL, 0);
- if (depth < 1 || depth > sht->can_queue)
+ if (depth < 1 || depth > sdev->host->can_queue)
return -EINVAL;
retval = sht->change_queue_depth(sdev, depth);
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 9a1c34205..525ab4c1f 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -1274,9 +1274,9 @@ static int st_open(struct inode *inode, struct file *filp)
spin_lock(&st_use_lock);
STp->in_use = 0;
spin_unlock(&st_use_lock);
- scsi_tape_put(STp);
if (resumed)
scsi_autopm_put_device(STp->device);
+ scsi_tape_put(STp);
return retval;
}