summaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/advansys.c50
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c1
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h2
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c13
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c13
-rw-r--r--drivers/scsi/dpt_i2o.c15
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c29
-rw-r--r--drivers/scsi/libiscsi.c2
-rw-r--r--drivers/scsi/libsas/sas_ata.c4
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c1
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c2
-rw-r--r--drivers/scsi/scsi_debug.c3
-rw-r--r--drivers/scsi/scsi_error.c15
-rw-r--r--drivers/scsi/sd.c1
-rw-r--r--drivers/scsi/wd7000.c2
17 files changed, 103 insertions, 58 deletions
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 9201afe65609..7f87979da22d 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -4724,6 +4724,10 @@ static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
BUG_ON((unsigned long)asc_dvc->overrun_buf & 7);
asc_dvc->overrun_dma = dma_map_single(board->dev, asc_dvc->overrun_buf,
ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
+ if (dma_mapping_error(board->dev, asc_dvc->overrun_dma)) {
+ warn_code = -ENOMEM;
+ goto err_dma_map;
+ }
phy_addr = cpu_to_le32(asc_dvc->overrun_dma);
AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
(uchar *)&phy_addr, 1);
@@ -4739,14 +4743,23 @@ static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
- return warn_code;
+ warn_code = UW_ERR;
+ goto err_mcode_start;
}
if (AscStartChip(iop_base) != 1) {
asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
- return warn_code;
+ warn_code = UW_ERR;
+ goto err_mcode_start;
}
return warn_code;
+
+err_mcode_start:
+ dma_unmap_single(board->dev, asc_dvc->overrun_dma,
+ ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
+err_dma_map:
+ asc_dvc->overrun_dma = 0;
+ return warn_code;
}
static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
@@ -4802,6 +4815,8 @@ static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
}
release_firmware(fw);
warn_code |= AscInitMicroCodeVar(asc_dvc);
+ if (!asc_dvc->overrun_dma)
+ return warn_code;
asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
AscEnableInterrupt(iop_base);
return warn_code;
@@ -7978,9 +7993,10 @@ static int advansys_reset(struct scsi_cmnd *scp)
status = AscInitAsc1000Driver(asc_dvc);
/* Refer to ASC_IERR_* definitions for meaning of 'err_code'. */
- if (asc_dvc->err_code) {
+ if (asc_dvc->err_code || !asc_dvc->overrun_dma) {
scmd_printk(KERN_INFO, scp, "SCSI bus reset error: "
- "0x%x\n", asc_dvc->err_code);
+ "0x%x, status: 0x%x\n", asc_dvc->err_code,
+ status);
ret = FAILED;
} else if (status) {
scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: "
@@ -12311,7 +12327,7 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,
asc_dvc_varp->overrun_buf = kzalloc(ASC_OVERRUN_BSIZE, GFP_KERNEL);
if (!asc_dvc_varp->overrun_buf) {
ret = -ENOMEM;
- goto err_free_wide_mem;
+ goto err_free_irq;
}
warn_code = AscInitAsc1000Driver(asc_dvc_varp);
@@ -12320,30 +12336,36 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost,
"warn 0x%x, error 0x%x\n",
asc_dvc_varp->init_state, warn_code,
asc_dvc_varp->err_code);
- if (asc_dvc_varp->err_code) {
+ if (!asc_dvc_varp->overrun_dma) {
ret = -ENODEV;
- kfree(asc_dvc_varp->overrun_buf);
+ goto err_free_mem;
}
}
} else {
- if (advansys_wide_init_chip(shost))
+ if (advansys_wide_init_chip(shost)) {
ret = -ENODEV;
+ goto err_free_mem;
+ }
}
- if (ret)
- goto err_free_wide_mem;
-
ASC_DBG_PRT_SCSI_HOST(2, shost);
ret = scsi_add_host(shost, boardp->dev);
if (ret)
- goto err_free_wide_mem;
+ goto err_free_mem;
scsi_scan_host(shost);
return 0;
- err_free_wide_mem:
- advansys_wide_free_mem(boardp);
+ err_free_mem:
+ if (ASC_NARROW_BOARD(boardp)) {
+ if (asc_dvc_varp->overrun_dma)
+ dma_unmap_single(boardp->dev, asc_dvc_varp->overrun_dma,
+ ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
+ kfree(asc_dvc_varp->overrun_buf);
+ } else
+ advansys_wide_free_mem(boardp);
+ err_free_irq:
free_irq(boardp->irq, shost);
err_free_dma:
#ifdef CONFIG_ISA
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index 72617b650a7e..e641922f20bc 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -169,6 +169,7 @@ unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba,
SE_DEBUG(DBG_LVL_1,
"Failed to allocate memory for"
"mgmt_invalidate_icds \n");
+ spin_unlock(&ctrl->mbox_lock);
return -1;
}
nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 6cf9dc37d78b..6b624e767d3b 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -362,6 +362,7 @@ struct bnx2i_hba {
u32 num_ccell;
int ofld_conns_active;
+ wait_queue_head_t eh_wait;
int max_active_conns;
struct iscsi_cid_queue cid_que;
@@ -381,6 +382,7 @@ struct bnx2i_hba {
spinlock_t lock; /* protects hba structure access */
struct mutex net_dev_lock;/* sync net device access */
+ int hba_shutdown_tmo;
/*
* PCI related info.
*/
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 6d8172e781cf..5d9296c599f6 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -177,11 +177,22 @@ void bnx2i_stop(void *handle)
struct bnx2i_hba *hba = handle;
/* check if cleanup happened in GOING_DOWN context */
- clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
if (!test_and_clear_bit(ADAPTER_STATE_GOING_DOWN,
&hba->adapter_state))
iscsi_host_for_each_session(hba->shost,
bnx2i_drop_session);
+
+ /* Wait for all endpoints to be torn down, Chip will be reset once
+ * control returns to network driver. So it is required to cleanup and
+ * release all connection resources before returning from this routine.
+ */
+ wait_event_interruptible_timeout(hba->eh_wait,
+ (hba->ofld_conns_active == 0),
+ hba->hba_shutdown_tmo);
+ /* This flag should be cleared last so that ep_disconnect() gracefully
+ * cleans up connection context
+ */
+ clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
}
/**
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index f2e9b18fe76c..fa68ab34b998 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -820,6 +820,11 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic)
spin_lock_init(&hba->lock);
mutex_init(&hba->net_dev_lock);
+ init_waitqueue_head(&hba->eh_wait);
+ if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type))
+ hba->hba_shutdown_tmo = 240 * HZ;
+ else /* 5706/5708/5709 */
+ hba->hba_shutdown_tmo = 30 * HZ;
if (iscsi_host_add(shost, &hba->pcidev->dev))
goto free_dump_mem;
@@ -1658,8 +1663,8 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
*/
hba = bnx2i_check_route(dst_addr);
- if (!hba) {
- rc = -ENOMEM;
+ if (!hba || test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state)) {
+ rc = -EINVAL;
goto check_busy;
}
@@ -1804,7 +1809,7 @@ static int bnx2i_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
(bnx2i_ep->state ==
EP_STATE_CONNECT_COMPL)),
msecs_to_jiffies(timeout_ms));
- if (!rc || (bnx2i_ep->state == EP_STATE_OFLD_FAILED))
+ if (bnx2i_ep->state == EP_STATE_OFLD_FAILED)
rc = -1;
if (rc > 0)
@@ -1957,6 +1962,8 @@ return_bnx2i_ep:
if (!hba->ofld_conns_active)
bnx2i_unreg_dev_all();
+
+ wake_up_interruptible(&hba->eh_wait);
}
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 496764349c41..0435d044c9da 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -188,7 +188,8 @@ MODULE_DEVICE_TABLE(pci,dptids);
static int adpt_detect(struct scsi_host_template* sht)
{
struct pci_dev *pDev = NULL;
- adpt_hba* pHba;
+ adpt_hba *pHba;
+ adpt_hba *next;
PINFO("Detecting Adaptec I2O RAID controllers...\n");
@@ -206,7 +207,8 @@ static int adpt_detect(struct scsi_host_template* sht)
}
/* In INIT state, Activate IOPs */
- for (pHba = hba_chain; pHba; pHba = pHba->next) {
+ for (pHba = hba_chain; pHba; pHba = next) {
+ next = pHba->next;
// Activate does get status , init outbound, and get hrt
if (adpt_i2o_activate_hba(pHba) < 0) {
adpt_i2o_delete_hba(pHba);
@@ -243,7 +245,8 @@ rebuild_sys_tab:
PDEBUG("HBA's in OPERATIONAL state\n");
printk("dpti: If you have a lot of devices this could take a few minutes.\n");
- for (pHba = hba_chain; pHba; pHba = pHba->next) {
+ for (pHba = hba_chain; pHba; pHba = next) {
+ next = pHba->next;
printk(KERN_INFO"%s: Reading the hardware resource table.\n", pHba->name);
if (adpt_i2o_lct_get(pHba) < 0){
adpt_i2o_delete_hba(pHba);
@@ -263,7 +266,8 @@ rebuild_sys_tab:
adpt_sysfs_class = NULL;
}
- for (pHba = hba_chain; pHba; pHba = pHba->next) {
+ for (pHba = hba_chain; pHba; pHba = next) {
+ next = pHba->next;
if (adpt_scsi_host_alloc(pHba, sht) < 0){
adpt_i2o_delete_hba(pHba);
continue;
@@ -1229,11 +1233,10 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
}
}
pci_dev_put(pHba->pDev);
- kfree(pHba);
-
if (adpt_sysfs_class)
device_destroy(adpt_sysfs_class,
MKDEV(DPTI_I2O_MAJOR, pHba->unit));
+ kfree(pHba);
if(hba_count <= 0){
unregister_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER);
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index ff5ec5ac1fb5..88bad0e81bdd 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -323,16 +323,6 @@ static void set_srp_direction(struct scsi_cmnd *cmd,
srp_cmd->buf_fmt = fmt;
}
-static void unmap_sg_list(int num_entries,
- struct device *dev,
- struct srp_direct_buf *md)
-{
- int i;
-
- for (i = 0; i < num_entries; ++i)
- dma_unmap_single(dev, md[i].va, md[i].len, DMA_BIDIRECTIONAL);
-}
-
/**
* unmap_cmd_data: - Unmap data pointed in srp_cmd based on the format
* @cmd: srp_cmd whose additional_data member will be unmapped
@@ -350,24 +340,9 @@ static void unmap_cmd_data(struct srp_cmd *cmd,
if (out_fmt == SRP_NO_DATA_DESC && in_fmt == SRP_NO_DATA_DESC)
return;
- else if (out_fmt == SRP_DATA_DESC_DIRECT ||
- in_fmt == SRP_DATA_DESC_DIRECT) {
- struct srp_direct_buf *data =
- (struct srp_direct_buf *) cmd->add_data;
- dma_unmap_single(dev, data->va, data->len, DMA_BIDIRECTIONAL);
- } else {
- struct srp_indirect_buf *indirect =
- (struct srp_indirect_buf *) cmd->add_data;
- int num_mapped = indirect->table_desc.len /
- sizeof(struct srp_direct_buf);
- if (num_mapped <= MAX_INDIRECT_BUFS) {
- unmap_sg_list(num_mapped, dev, &indirect->desc_list[0]);
- return;
- }
-
- unmap_sg_list(num_mapped, dev, evt_struct->ext_list);
- }
+ if (evt_struct->cmnd)
+ scsi_dma_unmap(evt_struct->cmnd);
}
static int map_sg_list(struct scsi_cmnd *cmd, int nseg,
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 6d5ae4474bb3..633e09036357 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -471,12 +471,12 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
WARN_ON(hdrlength >= 256);
hdr->hlength = hdrlength & 0xFF;
+ hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
if (session->tt->init_task && session->tt->init_task(task))
return -EIO;
task->state = ISCSI_TASK_RUNNING;
- hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
session->cmdsn++;
conn->scsicmd_pdus_cnt++;
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index b00efd19aadb..88f744672576 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -395,11 +395,15 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev,
void sas_ata_task_abort(struct sas_task *task)
{
struct ata_queued_cmd *qc = task->uldd_task;
+ struct request_queue *q = qc->scsicmd->device->request_queue;
struct completion *waiting;
+ unsigned long flags;
/* Bounce SCSI-initiated commands to the SCSI EH */
if (qc->scsicmd) {
+ spin_lock_irqsave(q->queue_lock, flags);
blk_abort_request(qc->scsicmd->request);
+ spin_unlock_irqrestore(q->queue_lock, flags);
scsi_schedule_eh(qc->scsicmd->device->host);
return;
}
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 2660e1b4569a..822835055cef 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -1030,6 +1030,8 @@ int __sas_task_abort(struct sas_task *task)
void sas_task_abort(struct sas_task *task)
{
struct scsi_cmnd *sc = task->uldd_task;
+ struct request_queue *q = sc->device->request_queue;
+ unsigned long flags;
/* Escape for libsas internal commands */
if (!sc) {
@@ -1044,7 +1046,9 @@ void sas_task_abort(struct sas_task *task)
return;
}
+ spin_lock_irqsave(q->queue_lock, flags);
blk_abort_request(sc->request);
+ spin_unlock_irqrestore(q->queue_lock, flags);
scsi_schedule_eh(sc->device->host);
}
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index ec3723831e89..d62b3e467926 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -433,7 +433,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba,
dd_data = cmdiocbq->context1;
/* normal completion and timeout crossed paths, already done */
if (!dd_data) {
- spin_unlock_irqrestore(&phba->hbalock, flags);
+ spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
return;
}
@@ -1196,7 +1196,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,
dd_data = cmdiocbq->context1;
/* normal completion and timeout crossed paths, already done */
if (!dd_data) {
- spin_unlock_irqrestore(&phba->hbalock, flags);
+ spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
return;
}
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 359e9a71a021..1c7ef55966fb 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -2393,6 +2393,7 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
return 0;
done:
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (bsg_job->request->msgcode == FC_BSG_HST_CT)
kfree(sp->fcport);
kfree(sp->ctx);
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 09d6d4b76f39..caeb7d10ae04 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -467,7 +467,7 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
if (conn_err_detail)
*conn_err_detail = mbox_sts[5];
if (tcp_source_port_num)
- *tcp_source_port_num = (uint16_t) mbox_sts[6] >> 16;
+ *tcp_source_port_num = (uint16_t) (mbox_sts[6] >> 16);
if (connection_id)
*connection_id = (uint16_t) mbox_sts[6] & 0x00FF;
status = QLA_SUCCESS;
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 3e10c306de94..3a5bfd10b2cb 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -957,7 +957,8 @@ static int resp_start_stop(struct scsi_cmnd * scp,
static sector_t get_sdebug_capacity(void)
{
if (scsi_debug_virtual_gb > 0)
- return 2048 * 1024 * (sector_t)scsi_debug_virtual_gb;
+ return (sector_t)scsi_debug_virtual_gb *
+ (1073741824 / scsi_debug_sector_size);
else
return sdebug_store_sectors;
}
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index d45c69ca5737..7ad53fa42766 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -302,7 +302,20 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
if (scmd->device->allow_restart &&
(sshdr.asc == 0x04) && (sshdr.ascq == 0x02))
return FAILED;
- return SUCCESS;
+
+ if (blk_barrier_rq(scmd->request))
+ /*
+ * barrier requests should always retry on UA
+ * otherwise block will get a spurious error
+ */
+ return NEEDS_RETRY;
+ else
+ /*
+ * for normal (non barrier) commands, pass the
+ * UA upwards for a determination in the
+ * completion functions
+ */
+ return SUCCESS;
/* these three are not supported */
case COPY_ABORTED:
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 8b827f37b03e..de6c60320f6f 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1040,6 +1040,7 @@ static void sd_prepare_flush(struct request_queue *q, struct request *rq)
{
rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->timeout = SD_TIMEOUT;
+ rq->retries = SD_MAX_RETRIES;
rq->cmd[0] = SYNCHRONIZE_CACHE;
rq->cmd_len = 10;
}
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index d0b7d2ff9ac5..333580bf37c5 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -1587,7 +1587,7 @@ static int wd7000_host_reset(struct scsi_cmnd *SCpnt)
{
Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
- spin_unlock_irq(SCpnt->device->host->host_lock);
+ spin_lock_irq(SCpnt->device->host->host_lock);
if (wd7000_adapter_reset(host) < 0) {
spin_unlock_irq(SCpnt->device->host->host_lock);