Skip to content

Commit

Permalink
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/g…
Browse files Browse the repository at this point in the history
…it/jejb/scsi-rc-fixes-2.6

SCSI fixes on 20120224:
 "This is a set of assorted bug fixes for power management, mpt2sas,
  ipr, the rdac device handler and quite a big chunk for qla2xxx (plus a
  use after free of scsi_host in scsi_scan.c). "

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6:
  [SCSI] scsi_dh_rdac: Fix for unbalanced reference count
  [SCSI] scsi_pm: Fix bug in the SCSI power management handler
  [SCSI] scsi_scan: Fix 'Poison overwritten' warning caused by using freed 'shost'
  [SCSI] qla2xxx: Update version number to 8.03.07.13-k.
  [SCSI] qla2xxx: Proper detection of firmware abort error code for ISP82xx.
  [SCSI] qla2xxx: Remove resetting memory during device initialization for ISP82xx.
  [SCSI] qla2xxx: Complete mailbox command timedout to avoid initialization failures during next reset cycle.
  [SCSI] qla2xxx: Remove check for null fcport from host reset handler.
  [SCSI] qla2xxx: Correct out of bounds read of ISP2200 mailbox registers.
  [SCSI] qla2xxx: Remove errant clearing of MBX_INTERRUPT flag during CT-IOCB processing.
  [SCSI] qla2xxx: Clear options-flags while issuing stop-firmware mbx command.
  [SCSI] qla2xxx: Add an "is reset active" helper.
  [SCSI] qla2xxx: Add check for null fcport references in qla2xxx_queuecommand.
  [SCSI] qla2xxx: Propagate up abort failures.
  [SCSI] isci: Fix NULL ptr dereference when no firmware is being loaded
  [SCSI] ipr: fix eeh recovery for 64-bit adapters
  [SCSI] mpt2sas: Fix mismatch in mpt2sas_base_hard_reset_handler() mutex lock-unlock
  • Loading branch information
torvalds committed Feb 25, 2012
2 parents e98092b + 3569e53 commit 16bca1d
Show file tree
Hide file tree
Showing 17 changed files with 101 additions and 100 deletions.
25 changes: 14 additions & 11 deletions drivers/scsi/device_handler/scsi_dh_rdac.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,10 +364,7 @@ static void release_controller(struct kref *kref)
struct rdac_controller *ctlr;
ctlr = container_of(kref, struct rdac_controller, kref);

flush_workqueue(kmpath_rdacd);
spin_lock(&list_lock);
list_del(&ctlr->node);
spin_unlock(&list_lock);
kfree(ctlr);
}

Expand All @@ -376,20 +373,17 @@ static struct rdac_controller *get_controller(int index, char *array_name,
{
struct rdac_controller *ctlr, *tmp;

spin_lock(&list_lock);

list_for_each_entry(tmp, &ctlr_list, node) {
if ((memcmp(tmp->array_id, array_id, UNIQUE_ID_LEN) == 0) &&
(tmp->index == index) &&
(tmp->host == sdev->host)) {
kref_get(&tmp->kref);
spin_unlock(&list_lock);
return tmp;
}
}
ctlr = kmalloc(sizeof(*ctlr), GFP_ATOMIC);
if (!ctlr)
goto done;
return NULL;

/* initialize fields of controller */
memcpy(ctlr->array_id, array_id, UNIQUE_ID_LEN);
Expand All @@ -405,8 +399,7 @@ static struct rdac_controller *get_controller(int index, char *array_name,
INIT_WORK(&ctlr->ms_work, send_mode_select);
INIT_LIST_HEAD(&ctlr->ms_head);
list_add(&ctlr->node, &ctlr_list);
done:
spin_unlock(&list_lock);

return ctlr;
}

Expand Down Expand Up @@ -517,9 +510,12 @@ static int initialize_controller(struct scsi_device *sdev,
index = 0;
else
index = 1;

spin_lock(&list_lock);
h->ctlr = get_controller(index, array_name, array_id, sdev);
if (!h->ctlr)
err = SCSI_DH_RES_TEMP_UNAVAIL;
spin_unlock(&list_lock);
}
return err;
}
Expand Down Expand Up @@ -906,7 +902,9 @@ static int rdac_bus_attach(struct scsi_device *sdev)
return 0;

clean_ctlr:
spin_lock(&list_lock);
kref_put(&h->ctlr->kref, release_controller);
spin_unlock(&list_lock);

failed:
kfree(scsi_dh_data);
Expand All @@ -921,14 +919,19 @@ static void rdac_bus_detach( struct scsi_device *sdev )
struct rdac_dh_data *h;
unsigned long flags;

spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
scsi_dh_data = sdev->scsi_dh_data;
h = (struct rdac_dh_data *) scsi_dh_data->buf;
if (h->ctlr && h->ctlr->ms_queued)
flush_workqueue(kmpath_rdacd);

spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
sdev->scsi_dh_data = NULL;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);

h = (struct rdac_dh_data *) scsi_dh_data->buf;
spin_lock(&list_lock);
if (h->ctlr)
kref_put(&h->ctlr->kref, release_controller);
spin_unlock(&list_lock);
kfree(scsi_dh_data);
module_put(THIS_MODULE);
sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", RDAC_NAME);
Expand Down
24 changes: 18 additions & 6 deletions drivers/scsi/ipr.c
Original file line number Diff line number Diff line change
Expand Up @@ -4613,11 +4613,13 @@ static int __ipr_eh_host_reset(struct scsi_cmnd * scsi_cmd)
ENTER;
ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;

dev_err(&ioa_cfg->pdev->dev,
"Adapter being reset as a result of error recovery.\n");
if (!ioa_cfg->in_reset_reload) {
dev_err(&ioa_cfg->pdev->dev,
"Adapter being reset as a result of error recovery.\n");

if (WAIT_FOR_DUMP == ioa_cfg->sdt_state)
ioa_cfg->sdt_state = GET_DUMP;
if (WAIT_FOR_DUMP == ioa_cfg->sdt_state)
ioa_cfg->sdt_state = GET_DUMP;
}

rc = ipr_reset_reload(ioa_cfg, IPR_SHUTDOWN_ABBREV);

Expand Down Expand Up @@ -4907,7 +4909,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
struct ipr_ioa_cfg *ioa_cfg;
struct ipr_resource_entry *res;
struct ipr_cmd_pkt *cmd_pkt;
u32 ioasc;
u32 ioasc, int_reg;
int op_found = 0;

ENTER;
Expand All @@ -4920,7 +4922,17 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
*/
if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead)
return FAILED;
if (!res || !ipr_is_gscsi(res))
if (!res)
return FAILED;

/*
* If we are aborting a timed out op, chances are that the timeout was caused
* by a still not detected EEH error. In such cases, reading a register will
* trigger the EEH recovery infrastructure.
*/
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);

if (!ipr_is_gscsi(res))
return FAILED;

list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
Expand Down
4 changes: 3 additions & 1 deletion drivers/scsi/isci/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -1848,9 +1848,11 @@ static enum sci_status sci_oem_parameters_set(struct isci_host *ihost)
if (state == SCIC_RESET ||
state == SCIC_INITIALIZING ||
state == SCIC_INITIALIZED) {
u8 oem_version = pci_info->orom ? pci_info->orom->hdr.version :
ISCI_ROM_VER_1_0;

if (sci_oem_parameters_validate(&ihost->oem_parameters,
pci_info->orom->hdr.version))
oem_version))
return SCI_FAILURE_INVALID_PARAMETER_VALUE;

return SCI_SUCCESS;
Expand Down
3 changes: 2 additions & 1 deletion drivers/scsi/mpt2sas/mpt2sas_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -4548,7 +4548,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
printk(MPT2SAS_ERR_FMT "%s: pci error recovery reset\n",
ioc->name, __func__);
r = 0;
goto out;
goto out_unlocked;
}

if (mpt2sas_fwfault_debug)
Expand Down Expand Up @@ -4604,6 +4604,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
mutex_unlock(&ioc->reset_in_progress_mutex);

out_unlocked:
dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name,
__func__));
return r;
Expand Down
13 changes: 4 additions & 9 deletions drivers/scsi/qla2xxx/qla_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1036,8 +1036,7 @@ qla2x00_link_state_show(struct device *dev, struct device_attribute *attr,
vha->device_flags & DFLG_NO_CABLE)
len = snprintf(buf, PAGE_SIZE, "Link Down\n");
else if (atomic_read(&vha->loop_state) != LOOP_READY ||
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
qla2x00_reset_active(vha))
len = snprintf(buf, PAGE_SIZE, "Unknown Link State\n");
else {
len = snprintf(buf, PAGE_SIZE, "Link Up - ");
Expand Down Expand Up @@ -1359,8 +1358,7 @@ qla2x00_thermal_temp_show(struct device *dev,
return snprintf(buf, PAGE_SIZE, "\n");

temp = frac = 0;
if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
if (qla2x00_reset_active(vha))
ql_log(ql_log_warn, vha, 0x707b,
"ISP reset active.\n");
else if (!vha->hw->flags.eeh_busy)
Expand All @@ -1379,8 +1377,7 @@ qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr,
int rval = QLA_FUNCTION_FAILED;
uint16_t state[5];

if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags))
if (qla2x00_reset_active(vha))
ql_log(ql_log_warn, vha, 0x707c,
"ISP reset active.\n");
else if (!vha->hw->flags.eeh_busy)
Expand Down Expand Up @@ -1693,9 +1690,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
if (IS_FWI2_CAPABLE(ha)) {
rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma);
} else if (atomic_read(&base_vha->loop_state) == LOOP_READY &&
!test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) &&
!test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags) &&
!ha->dpc_active) {
!qla2x00_reset_active(vha) && !ha->dpc_active) {
/* Must be in a 'READY' state for statistics retrieval. */
rval = qla2x00_get_link_status(base_vha, base_vha->loop_id,
stats, stats_dma);
Expand Down
50 changes: 9 additions & 41 deletions drivers/scsi/qla2xxx/qla_bsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,6 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
goto exit_fcp_prio_cfg;
}

if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
ret = -EBUSY;
goto exit_fcp_prio_cfg;
}

/* Get the sub command */
oper = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];

Expand Down Expand Up @@ -646,13 +639,6 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
dma_addr_t rsp_data_dma;
uint32_t rsp_data_len;

if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
ql_log(ql_log_warn, vha, 0x7018, "Abort active or needed.\n");
return -EBUSY;
}

if (!vha->flags.online) {
ql_log(ql_log_warn, vha, 0x7019, "Host is not online.\n");
return -EIO;
Expand Down Expand Up @@ -874,13 +860,6 @@ qla84xx_reset(struct fc_bsg_job *bsg_job)
int rval = 0;
uint32_t flag;

if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
ql_log(ql_log_warn, vha, 0x702e, "Abort active or needed.\n");
return -EBUSY;
}

if (!IS_QLA84XX(ha)) {
ql_dbg(ql_dbg_user, vha, 0x702f, "Not 84xx, exiting.\n");
return -EINVAL;
Expand Down Expand Up @@ -922,11 +901,6 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_job)
uint32_t flag;
uint32_t fw_ver;

if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
return -EBUSY;

if (!IS_QLA84XX(ha)) {
ql_dbg(ql_dbg_user, vha, 0x7032,
"Not 84xx, exiting.\n");
Expand Down Expand Up @@ -1036,14 +1010,6 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
uint32_t data_len = 0;
uint32_t dma_direction = DMA_NONE;

if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
ql_log(ql_log_warn, vha, 0x7039,
"Abort active or needed.\n");
return -EBUSY;
}

if (!IS_QLA84XX(ha)) {
ql_log(ql_log_warn, vha, 0x703a,
"Not 84xx, exiting.\n");
Expand Down Expand Up @@ -1246,13 +1212,6 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job)

bsg_job->reply->reply_payload_rcv_len = 0;

if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
ql_log(ql_log_warn, vha, 0x7045, "abort active or needed.\n");
return -EBUSY;
}

if (!IS_IIDMA_CAPABLE(vha->hw)) {
ql_log(ql_log_info, vha, 0x7046, "iiDMA not supported.\n");
return -EINVAL;
Expand Down Expand Up @@ -1668,6 +1627,15 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
vha = shost_priv(host);
}

if (qla2x00_reset_active(vha)) {
ql_dbg(ql_dbg_user, vha, 0x709f,
"BSG: ISP abort active/needed -- cmd=%d.\n",
bsg_job->request->msgcode);
bsg_job->reply->result = (DID_ERROR << 16);
bsg_job->job_done(bsg_job);
return -EBUSY;
}

ql_dbg(ql_dbg_user, vha, 0x7000,
"Entered %s msgcode=0x%x.\n", __func__, bsg_job->request->msgcode);

Expand Down
3 changes: 2 additions & 1 deletion drivers/scsi/qla2xxx/qla_dbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
* | DPC Thread | 0x401c | |
* | Async Events | 0x5057 | 0x5052 |
* | Timer Routines | 0x6011 | 0x600e,0x600f |
* | User Space Interactions | 0x709e | |
* | User Space Interactions | 0x709e | 0x7018,0x702e |
* | | | 0x7039,0x7045 |
* | Task Management | 0x803c | 0x8025-0x8026 |
* | | | 0x800b,0x8039 |
* | AER/EEH | 0x900f | |
Expand Down
1 change: 1 addition & 0 deletions drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* ISP2100 HBAs.
*/
#define MAILBOX_REGISTER_COUNT_2100 8
#define MAILBOX_REGISTER_COUNT_2200 24
#define MAILBOX_REGISTER_COUNT 32

#define QLA2200A_RISC_ROM_VER 4
Expand Down
13 changes: 13 additions & 0 deletions drivers/scsi/qla2xxx/qla_inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,16 @@ qla2x00_hba_err_chk_enabled(srb_t *sp)
}
return 0;
}

static inline int
qla2x00_reset_active(scsi_qla_host_t *vha)
{
scsi_qla_host_t *base_vha = pci_get_drvdata(vha->hw->pdev);

/* Test appropriate base-vha and vha flags. */
return test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags) ||
test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
}
1 change: 0 additions & 1 deletion drivers/scsi/qla2xxx/qla_isr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2090,7 +2090,6 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
break;
case CT_IOCB_TYPE:
qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE);
clear_bit(MBX_INTERRUPT, &vha->hw->mbx_cmd_flags);
break;
case ELS_IOCB_TYPE:
qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE);
Expand Down
7 changes: 6 additions & 1 deletion drivers/scsi/qla2xxx/qla_mbx.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)

set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
/* Allow next mbx cmd to come in. */
complete(&ha->mbx_cmd_comp);
if (ha->isp_ops->abort_isp(vha)) {
/* Failed. retry later. */
set_bit(ISP_ABORT_NEEDED,
Expand All @@ -350,6 +352,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
ql_dbg(ql_dbg_mbx, base_vha, 0x101f,
"Finished abort_isp.\n");
goto mbx_done;
}
}
}
Expand All @@ -358,6 +361,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
/* Allow next mbx cmd to come in. */
complete(&ha->mbx_cmd_comp);

mbx_done:
if (rval) {
ql_dbg(ql_dbg_mbx, base_vha, 0x1020,
"**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, cmd=%x ****.\n",
Expand Down Expand Up @@ -2581,7 +2585,8 @@ qla2x00_stop_firmware(scsi_qla_host_t *vha)
ql_dbg(ql_dbg_mbx, vha, 0x10a1, "Entered %s.\n", __func__);

mcp->mb[0] = MBC_STOP_FIRMWARE;
mcp->out_mb = MBX_0;
mcp->mb[1] = 0;
mcp->out_mb = MBX_1|MBX_0;
mcp->in_mb = MBX_0;
mcp->tov = 5;
mcp->flags = 0;
Expand Down
Loading

0 comments on commit 16bca1d

Please sign in to comment.