From 229bab6bacc42295f13c0434772381a88ce2308b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 15 Mar 2010 11:26:56 +0300 Subject: [SCSI] dpt_i2o: several use after free issues adpt_i2o_delete_hba() calls kfree() so we have to save "pHba->next" before calling it. Also inside adpt_i2o_delete_hba() itself, there was another use after free bug which I fixed by moving the kfree() down a line. Signed-off-by: Dan Carpenter Signed-off-by: James Bottomley --- drivers/scsi/dpt_i2o.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') 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); -- cgit v1.2.2 From 4ec3fdbef17d0266826b56b33735dc9dada58c27 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 16 Mar 2010 16:23:57 +0100 Subject: [SCSI] be2iscsi: fix lock imbalance Stanse found that one error path in mgmt_invalidate_icds omits to unlock ctrl->mbox_lock. Fix that. Added in 756d29c8c7ed8887ed7d752371ce2f (Enable async mode for mcc rings) where the spinlock was moved. Signed-off-by: Jiri Slaby Acked-by: Jayamohan Kallickal Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_mgmt.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') 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); -- cgit v1.2.2 From 67221a4226a5fc48e413e2050db266bb171753c4 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 16 Mar 2010 16:23:58 +0100 Subject: [SCSI] lpfc: fix lock imbalances Stanse found that two error paths in lpfc_bsg_rport_els_cmp and lpfc_issue_ct_rsp_cmp omits to unlock phba->ct_ev_lock. It is because they wrongly unlock phba->hbalock instead. Fix that. Signed-off-by: Jiri Slaby Acked-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_bsg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') 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; } -- cgit v1.2.2 From bc0beb44f27dc068c1daefc79826c07e0b22ef6c Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 16 Mar 2010 16:23:59 +0100 Subject: [SCSI] qla2xxx: fix lock imbalance Stanse found that one error path in qla24xx_bsg_timeout omits to unlock ha->hardware_lock. Fix that. Signed-off-by: Jiri Slaby Acked-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') 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); -- cgit v1.2.2 From d7d05548a62c87ee55b0c81933669177f885aa8d Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 31 Mar 2010 14:41:35 -0500 Subject: [SCSI] iscsi_tcp: fix relogin/shutdown hang When I made this patch: b64e77f70b8c11766e967e3485331a9e6ef01390 it was to solve a problem where we were already on the waitqueue becuase a connection problem/logout caused us to be on there when we were cleaning up the session. If we happen to get on queue for more normal reasons like their just does not happen to be any send space at the same time we are closing the connection we hit a race and get stuck in the wait. We should not check if the waitqueue is active because we could race with the network code. If the network xmit code is just about to enter the prepare to wait when we check for the waitqueue to be active then we will miss each other and the network code will fall into the wait and we will not run wake_up. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 0ee725ced511..02143af7c1af 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -599,7 +599,7 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock); - if (sock->sk->sk_sleep && waitqueue_active(sock->sk->sk_sleep)) { + if (sock->sk->sk_sleep) { sock->sk->sk_err = EIO; wake_up_interruptible(sock->sk->sk_sleep); } -- cgit v1.2.2 From a8f23b03535359c5afeb77d937b89b8a4d87b2b2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 1 Apr 2010 18:55:16 +0300 Subject: [SCSI] wd7000: fix reset handler typo spin_unlock_irq() => spin_lock_irq() This was introduced back in 2005 at the very start of the git era by: df0ae2497ddefd72a87f3a3b34ff32455d7d4ae0 [SCSI] allow sleeping in ->eh_host_reset_handler() Signed-off-by: Dan Carpenter Signed-off-by: James Bottomley --- drivers/scsi/wd7000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') 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); -- cgit v1.2.2 From a71fa1fc43a29133f13ae6ada1a389ca298c0934 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 2 Apr 2010 15:50:24 +0900 Subject: [SCSI] ibmvscsi: fix DMA API misuse ibmvscsi uses dma_unmap_single() for buffers mapped via dma_map_sg(). It works however it's the API violation. The DMA debug facility complains about it: http://marc.info/?l=linux-scsi&m=127018555013151&w=2 Reported-by: Sachin Sant Tested-by: Sachin Sant Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvscsi.c | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) (limited to 'drivers/scsi') 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, -- cgit v1.2.2 From 490475a9938f3480e1ab3a67063e547cea41c295 Mon Sep 17 00:00:00 2001 From: Anil Veerabhadrappa Date: Thu, 8 Apr 2010 15:59:15 -0700 Subject: [SCSI] bnx2i: Bug fixes related to MTU change issue when there are active iscsi sessions bnx2i driver has to wait and cleanup all iscsi endpoints before returning from bnx2i_stop(). This is to make sure all chip resources are freed before chip is reset. As the requirements for 1G and 10G chipsets is different, added per-device 'hba_shutdown_tmo' parameter to adapter structure If the connections are not torn down by the daemon within this timeout period, 'cid's will be leaked in 10G device. 1G devices are more flexible and do not leak any resources because the whole chip ports gets reset when MTU is changed or ethtool selftest is run fixed a minor issue in bnx2i_ep_poll() which unnecessarily forced error return code when driver timed out waiting for TCP connect request to complete Signed-off-by: Anil Veerabhadrappa Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i.h | 2 ++ drivers/scsi/bnx2i/bnx2i_init.c | 13 ++++++++++++- drivers/scsi/bnx2i/bnx2i_iscsi.c | 13 ++++++++++--- 3 files changed, 24 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') 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); } -- cgit v1.2.2 From 1482338f6242dbaea46039c5f1b4604a472b364b Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 22 Apr 2010 11:02:14 -0700 Subject: scsi: fix operator precedence warning Fix operator precedence warning (from sparse), which results in the data value always being 0: drivers/scsi/qla4xxx/ql4_mbx.c:470:66: warning: right shift by bigger than source value Signed-off-by: Randy Dunlap Acked-by: Ravi Anand Cc: David C Somayajulu Cc: Karen Higgins Cc: Vikas Chaudhary Signed-off-by: Linus Torvalds --- drivers/scsi/qla4xxx/ql4_mbx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') 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; -- cgit v1.2.2 From 9a908c1aa4d3898f62e2cb8af6936b16503ab3e6 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Tue, 30 Mar 2010 13:35:38 -0300 Subject: [SCSI] advansys: fix narrow board error path Error handling on advansys_board_found is fixed, because it's buggy in the case we have an ASC_NARROW_BOARD set and failure happens on AscInitAsc1000Driver step: it was freeing items of wrong struct in the dvc_var union of struct asc_board, which could lead to an oops in the case we set some of the fields in struct of narrow board as code was choosing to always freeing wide board fields, and not everything was being freed/released properly. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: James Bottomley --- drivers/scsi/advansys.c | 50 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 14 deletions(-) (limited to 'drivers/scsi') 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 -- cgit v1.2.2 From 70b25f890ce9f0520c64075ce9225a5b020a513e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 15 Apr 2010 09:00:08 +0900 Subject: [SCSI] fix locking around blk_abort_request() blk_abort_request() expects queue lock to be held by the caller. Grab it before calling the function. Lack of this synchronization led to infinite loop on corrupt q->timeout_list. Signed-off-by: Tejun Heo Cc: stable@kernel.org Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_ata.c | 4 ++++ drivers/scsi/libsas/sas_scsi_host.c | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'drivers/scsi') 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); } -- cgit v1.2.2 From 96b1f96dcab87756c0a1e7ba76bc5dc2add82b88 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sat, 24 Apr 2010 16:21:19 -0500 Subject: [SCSI] libiscsi: regression: fix header digest errors This fixes a regression introduced with this commit: commit d3305f3407fa3e9452079ec6cc8379067456e4aa Author: Mike Christie Date: Thu Aug 20 15:10:58 2009 -0500 [SCSI] libiscsi: don't increment cmdsn if cmd is not sent in 2.6.32. When I moved the hdr->cmdsn after init_task, I added a bug when header digests are used. The problem is that the LLD may calculate the header digest in init_task, so if we then set the cmdsn after the init_task call we change what the digest will be calculated by the target. Signed-off-by: Mike Christie Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') 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++; -- cgit v1.2.2 From 5447ed6c968e7270b656afa273c2b79d15d82edd Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Sun, 25 Apr 2010 12:30:23 +0200 Subject: [SCSI] scsi_debug: virtual_gb ignores sector_size In the scsi_debug driver, the virtual_gb option ignores the sector_size, implicitly assuming that is 512 bytes. So if 'virtual_gb=1 sector_size=4096' the result is an 8 GB (virtual) disk. Signed-off-by: Douglas Gilbert Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') 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; } -- cgit v1.2.2 From c213e1407be6b04b144794399a91472e0ef92aec Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 4 May 2010 16:49:21 +0200 Subject: [SCSI] Enable retries for SYNCRONIZE_CACHE commands to fix I/O error Some arrays are giving I/O errors with ext3 filesystems when SYNCHRONIZE_CACHE gets a UNIT_ATTENTION. What is happening is that these commands have no retries, so the UNIT_ATTENTION causes the barrier to fail. We should be enable retries here to clear any transient error and allow the barrier to succeed. Signed-off-by: Hannes Reinecke Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') 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; } -- cgit v1.2.2 From 77a4229719e511a0d38d9c355317ae1469adeb54 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 4 May 2010 16:51:40 -0400 Subject: [SCSI] Retry commands with UNIT_ATTENTION sense codes to fix ext3/ext4 I/O error There's nastyness in the way we currently handle barriers (and discards): They're effectively filesystem commands, but they get processed as BLOCK_PC commands. Unfortunately BLOCK_PC commands are taken by SCSI to be SG_IO commands and the issuer expects to see and handle any returned errors, however trivial. This leads to a huge problem, because the block layer doesn't expect this to happen and any trivially retryable error on a barrier causes an immediate I/O error to the filesystem. The only real way to hack around this is to take the usual class of offending errors (unit attentions) and make them all retryable in the case of a REQ_HARDBARRIER. A correct fix would involve a rework of the entire block and SCSI submit system, and so is out of scope for a quick fix. Cc: Hannes Reinecke Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') 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: -- cgit v1.2.2