diff options
Diffstat (limited to 'drivers/scsi')
29 files changed, 277 insertions, 117 deletions
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index febbd83e2ecd..24e57e770432 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -6291,18 +6291,17 @@ static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time) static uchar AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset) { - EXT_MSG sdtr_buf; - uchar sdtr_period_index; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - sdtr_buf.msg_type = EXTENDED_MESSAGE; - sdtr_buf.msg_len = MS_SDTR_LEN; - sdtr_buf.msg_req = EXTENDED_SDTR; - sdtr_buf.xfer_period = sdtr_period; + PortAddr iop_base = asc_dvc->iop_base; + uchar sdtr_period_index = AscGetSynPeriodIndex(asc_dvc, sdtr_period); + EXT_MSG sdtr_buf = { + .msg_type = EXTENDED_MESSAGE, + .msg_len = MS_SDTR_LEN, + .msg_req = EXTENDED_SDTR, + .xfer_period = sdtr_period, + .req_ack_offset = sdtr_offset, + }; sdtr_offset &= ASC_SYN_MAX_OFFSET; - sdtr_buf.req_ack_offset = sdtr_offset; - sdtr_period_index = AscGetSynPeriodIndex(asc_dvc, sdtr_period); + if (sdtr_period_index <= asc_dvc->max_sdtr_index) { AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG, (uchar *)&sdtr_buf, @@ -11030,6 +11029,9 @@ static int advansys_board_found(struct Scsi_Host *shost, unsigned int iop, ASC_DBG(2, "AdvInitGetConfig()\n"); ret = AdvInitGetConfig(pdev, shost) ? -ENODEV : 0; +#else + share_irq = 0; + ret = -ENODEV; #endif /* CONFIG_PCI */ } diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 499e369eabf0..8bc1625337f6 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -191,6 +191,7 @@ struct bnx2fc_hba { struct bnx2fc_cmd_mgr *cmd_mgr; spinlock_t hba_lock; struct mutex hba_mutex; + struct mutex hba_stats_mutex; unsigned long adapter_state; #define ADAPTER_STATE_UP 0 #define ADAPTER_STATE_GOING_DOWN 1 diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 67405c628864..d0b227ffbd5f 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -641,15 +641,17 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost) if (!fw_stats) return NULL; + mutex_lock(&hba->hba_stats_mutex); + bnx2fc_stats = fc_get_host_stats(shost); init_completion(&hba->stat_req_done); if (bnx2fc_send_stat_req(hba)) - return bnx2fc_stats; + goto unlock_stats_mutex; rc = wait_for_completion_timeout(&hba->stat_req_done, (2 * HZ)); if (!rc) { BNX2FC_HBA_DBG(lport, "FW stat req timed out\n"); - return bnx2fc_stats; + goto unlock_stats_mutex; } BNX2FC_STATS(hba, rx_stat2, fc_crc_cnt); bnx2fc_stats->invalid_crc_count += hba->bfw_stats.fc_crc_cnt; @@ -671,6 +673,9 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost) memcpy(&hba->prev_stats, hba->stats_buffer, sizeof(struct fcoe_statistics_params)); + +unlock_stats_mutex: + mutex_unlock(&hba->hba_stats_mutex); return bnx2fc_stats; } @@ -1302,6 +1307,7 @@ static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic) } spin_lock_init(&hba->hba_lock); mutex_init(&hba->hba_mutex); + mutex_init(&hba->hba_stats_mutex); hba->cnic = cnic; diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c index 622bdabc8894..dab195f04da7 100644 --- a/drivers/scsi/csiostor/csio_hw.c +++ b/drivers/scsi/csiostor/csio_hw.c @@ -1769,7 +1769,6 @@ csio_hw_use_fwconfig(struct csio_hw *hw, int reset, u32 *fw_cfg_param) goto bye; } - mempool_free(mbp, hw->mb_mempool); if (finicsum != cfcsum) { csio_warn(hw, "Config File checksum mismatch: csum=%#x, computed=%#x\n", @@ -1780,6 +1779,10 @@ csio_hw_use_fwconfig(struct csio_hw *hw, int reset, u32 *fw_cfg_param) rv = csio_hw_validate_caps(hw, mbp); if (rv != 0) goto bye; + + mempool_free(mbp, hw->mb_mempool); + mbp = NULL; + /* * Note that we're operating with parameters * not supplied by the driver, rather than from hard-wired diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index d4cda5e9600e..21c8d210c456 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -180,11 +180,14 @@ static u8 adpt_read_blink_led(adpt_hba* host) *============================================================================ */ +#ifdef MODULE static struct pci_device_id dptids[] = { { PCI_DPT_VENDOR_ID, PCI_DPT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, { PCI_DPT_VENDOR_ID, PCI_DPT_RAPTOR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, { 0, } }; +#endif + MODULE_DEVICE_TABLE(pci,dptids); static int adpt_detect(struct scsi_host_template* sht) diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index eefe14d453db..b87ab38a4530 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -1768,7 +1768,7 @@ struct scsi_host_template fdomain_driver_template = { }; #ifndef PCMCIA -#ifdef CONFIG_PCI +#if defined(CONFIG_PCI) && defined(MODULE) static struct pci_device_id fdomain_pci_tbl[] = { { PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index f8d2478b11cc..87e081f8a386 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -538,7 +538,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, printk(KERN_ERR "53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks); return -1; } - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY); + while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) + { + // FIXME - no timeout + } #ifndef SCSI_G_NCR5380_MEM { diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 8fae03215a85..543c10266984 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -366,7 +366,7 @@ enum ibmvfc_fcp_rsp_info_codes { }; struct ibmvfc_fcp_rsp_info { - __be16 reserved; + u8 reserved[3]; u8 rsp_code; u8 reserved2[4]; }__attribute__((packed, aligned (2))); diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index 6a926bae76b2..7a91cf3ff173 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -110,11 +110,6 @@ #define i91u_MAXQUEUE 2 #define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.04a" -#define I950_DEVICE_ID 0x9500 /* Initio's inic-950 product ID */ -#define I940_DEVICE_ID 0x9400 /* Initio's inic-940 product ID */ -#define I935_DEVICE_ID 0x9401 /* Initio's inic-935 product ID */ -#define I920_DEVICE_ID 0x0002 /* Initio's other product ID */ - #ifdef DEBUG_i91u static unsigned int i91u_debug = DEBUG_DEFAULT; #endif @@ -127,17 +122,6 @@ static int setup_debug = 0; static void i91uSCBPost(u8 * pHcb, u8 * pScb); -/* PCI Devices supported by this driver */ -static struct pci_device_id i91u_pci_devices[] = { - { PCI_VENDOR_ID_INIT, I950_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_INIT, I940_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_INIT, I935_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_INIT, I920_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_DOMEX, I920_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { } -}; -MODULE_DEVICE_TABLE(pci, i91u_pci_devices); - #define DEBUG_INTERRUPT 0 #define DEBUG_QUEUE 0 #define DEBUG_STATE 0 diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 7a58128a0000..2f61d8cd5882 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -835,8 +835,10 @@ static void ipr_sata_eh_done(struct ipr_cmnd *ipr_cmd) qc->err_mask |= AC_ERR_OTHER; sata_port->ioasa.status |= ATA_BUSY; - list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); ata_qc_complete(qc); + if (ipr_cmd->eh_comp) + complete(ipr_cmd->eh_comp); + list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); } /** @@ -5864,8 +5866,10 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd) res->in_erp = 0; } scsi_dma_unmap(ipr_cmd->scsi_cmd); - list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); scsi_cmd->scsi_done(scsi_cmd); + if (ipr_cmd->eh_comp) + complete(ipr_cmd->eh_comp); + list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); } /** @@ -6255,8 +6259,10 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, } scsi_dma_unmap(ipr_cmd->scsi_cmd); - list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); scsi_cmd->scsi_done(scsi_cmd); + if (ipr_cmd->eh_comp) + complete(ipr_cmd->eh_comp); + list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); } /** @@ -6282,8 +6288,10 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd) scsi_dma_unmap(scsi_cmd); spin_lock_irqsave(ipr_cmd->hrrq->lock, lock_flags); - list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); scsi_cmd->scsi_done(scsi_cmd); + if (ipr_cmd->eh_comp) + complete(ipr_cmd->eh_comp); + list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); spin_unlock_irqrestore(ipr_cmd->hrrq->lock, lock_flags); } else { spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index efce04df2109..9f0b00c38658 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1695,6 +1695,15 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) */ switch (session->state) { case ISCSI_STATE_FAILED: + /* + * cmds should fail during shutdown, if the session + * state is bad, allowing completion to happen + */ + if (unlikely(system_state != SYSTEM_RUNNING)) { + reason = FAILURE_SESSION_FAILED; + sc->result = DID_NO_CONNECT << 16; + break; + } case ISCSI_STATE_IN_RECOVERY: reason = FAILURE_SESSION_IN_RECOVERY; sc->result = DID_IMM_RETRY << 16; @@ -1980,6 +1989,19 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) if (session->state != ISCSI_STATE_LOGGED_IN) { /* + * During shutdown, if session is prematurely disconnected, + * recovery won't happen and there will be hung cmds. Not + * handling cmds would trigger EH, also bad in this case. + * Instead, handle cmd, allow completion to happen and let + * upper layer to deal with the result. + */ + if (unlikely(system_state != SYSTEM_RUNNING)) { + sc->result = DID_NO_CONNECT << 16; + ISCSI_DBG_EH(session, "sc on shutdown, handled\n"); + rc = BLK_EH_HANDLED; + goto done; + } + /* * We are probably in the middle of iscsi recovery so let * that complete and handle the error. */ @@ -2083,7 +2105,7 @@ done: task->last_timeout = jiffies; spin_unlock(&session->frwd_lock); ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ? - "timer reset" : "nh"); + "timer reset" : "shutdown or nh"); return rc; } diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 022bb6e10d98..12886f96b286 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -282,6 +282,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp) phy->phy->minimum_linkrate = dr->pmin_linkrate; phy->phy->maximum_linkrate = dr->pmax_linkrate; phy->phy->negotiated_linkrate = phy->linkrate; + phy->phy->enabled = (phy->linkrate != SAS_PHY_DISABLED); skip: if (new_phy) @@ -675,7 +676,7 @@ int sas_smp_get_phy_events(struct sas_phy *phy) res = smp_execute_task(dev, req, RPEL_REQ_SIZE, resp, RPEL_RESP_SIZE); - if (!res) + if (res) goto out; phy->invalid_dword_count = scsi_to_u32(&resp[12]); @@ -684,6 +685,7 @@ int sas_smp_get_phy_events(struct sas_phy *phy) phy->phy_reset_problem_count = scsi_to_u32(&resp[24]); out: + kfree(req); kfree(resp); return res; diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 519dac4e341e..9a8c2f97ed70 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -222,6 +222,7 @@ out_done: static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) { struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host); + struct domain_device *dev = cmd_to_domain_dev(cmd); struct sas_task *task = TO_SAS_TASK(cmd); /* At this point, we only get called following an actual abort @@ -230,6 +231,14 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) */ sas_end_task(cmd, task); + if (dev_is_sata(dev)) { + /* defer commands to libata so that libata EH can + * handle ata qcs correctly + */ + list_move_tail(&cmd->eh_entry, &sas_ha->eh_ata_q); + return; + } + /* now finish the command and move it on to the error * handler done list, this also takes it off the * error handler pending list. @@ -237,22 +246,6 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q); } -static void sas_eh_defer_cmd(struct scsi_cmnd *cmd) -{ - struct domain_device *dev = cmd_to_domain_dev(cmd); - struct sas_ha_struct *ha = dev->port->ha; - struct sas_task *task = TO_SAS_TASK(cmd); - - if (!dev_is_sata(dev)) { - sas_eh_finish_cmd(cmd); - return; - } - - /* report the timeout to libata */ - sas_end_task(cmd, task); - list_move_tail(&cmd->eh_entry, &ha->eh_ata_q); -} - static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd) { struct scsi_cmnd *cmd, *n; @@ -260,7 +253,7 @@ static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd list_for_each_entry_safe(cmd, n, error_q, eh_entry) { if (cmd->device->sdev_target == my_cmd->device->sdev_target && cmd->device->lun == my_cmd->device->lun) - sas_eh_defer_cmd(cmd); + sas_eh_finish_cmd(cmd); } } @@ -622,12 +615,12 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * case TASK_IS_DONE: SAS_DPRINTK("%s: task 0x%p is done\n", __func__, task); - sas_eh_defer_cmd(cmd); + sas_eh_finish_cmd(cmd); continue; case TASK_IS_ABORTED: SAS_DPRINTK("%s: task 0x%p is aborted\n", __func__, task); - sas_eh_defer_cmd(cmd); + sas_eh_finish_cmd(cmd); continue; case TASK_IS_AT_LU: SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); @@ -638,7 +631,7 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * "recovered\n", SAS_ADDR(task->dev), cmd->device->lun); - sas_eh_defer_cmd(cmd); + sas_eh_finish_cmd(cmd); sas_scsi_clear_queue_lu(work_q, cmd); goto Again; } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 8379fbbc60db..ef43847153ea 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -13493,6 +13493,9 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, case LPFC_Q_CREATE_VERSION_1: bf_set(lpfc_mbx_wq_create_wqe_count, &wq_create->u.request_1, wq->entry_count); + bf_set(lpfc_mbox_hdr_version, &shdr->request, + LPFC_Q_CREATE_VERSION_1); + switch (wq->entry_size) { default: case 64: diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c index 14c0334f41e4..26c67c42985c 100644 --- a/drivers/scsi/mac_esp.c +++ b/drivers/scsi/mac_esp.c @@ -55,6 +55,7 @@ struct mac_esp_priv { int error; }; static struct esp *esp_chips[2]; +static DEFINE_SPINLOCK(esp_chips_lock); #define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \ platform_get_drvdata((struct platform_device *) \ @@ -562,15 +563,18 @@ static int esp_mac_probe(struct platform_device *dev) } host->irq = IRQ_MAC_SCSI; - esp_chips[dev->id] = esp; - mb(); - if (esp_chips[!dev->id] == NULL) { - err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL); - if (err < 0) { - esp_chips[dev->id] = NULL; - goto fail_free_priv; - } + + /* The request_irq() call is intended to succeed for the first device + * and fail for the second device. + */ + err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL); + spin_lock(&esp_chips_lock); + if (err < 0 && esp_chips[!dev->id] == NULL) { + spin_unlock(&esp_chips_lock); + goto fail_free_priv; } + esp_chips[dev->id] = esp; + spin_unlock(&esp_chips_lock); err = scsi_esp_register(esp, &dev->dev); if (err) @@ -579,8 +583,13 @@ static int esp_mac_probe(struct platform_device *dev) return 0; fail_free_irq: - if (esp_chips[!dev->id] == NULL) + spin_lock(&esp_chips_lock); + esp_chips[dev->id] = NULL; + if (esp_chips[!dev->id] == NULL) { + spin_unlock(&esp_chips_lock); free_irq(host->irq, esp); + } else + spin_unlock(&esp_chips_lock); fail_free_priv: kfree(mep); fail_free_command_block: @@ -599,9 +608,13 @@ static int esp_mac_remove(struct platform_device *dev) scsi_esp_unregister(esp); + spin_lock(&esp_chips_lock); esp_chips[dev->id] = NULL; - if (!(esp_chips[0] || esp_chips[1])) + if (esp_chips[!dev->id] == NULL) { + spin_unlock(&esp_chips_lock); free_irq(irq, NULL); + } else + spin_unlock(&esp_chips_lock); kfree(mep); diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index e111c3d8c5d6..b868ef3b2ca3 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -3886,19 +3886,6 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) return 0; } - /* - * Bug work around for firmware SATL handling. The loop - * is based on atomic operations and ensures consistency - * since we're lockless at this point - */ - do { - if (test_bit(0, &sas_device_priv_data->ata_command_pending)) { - scmd->result = SAM_STAT_BUSY; - scmd->scsi_done(scmd); - return 0; - } - } while (_scsih_set_satl_pending(scmd, true)); - sas_target_priv_data = sas_device_priv_data->sas_target; /* invalid device handle */ @@ -3924,6 +3911,19 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) sas_device_priv_data->block) return SCSI_MLQUEUE_DEVICE_BUSY; + /* + * Bug work around for firmware SATL handling. The loop + * is based on atomic operations and ensures consistency + * since we're lockless at this point + */ + do { + if (test_bit(0, &sas_device_priv_data->ata_command_pending)) { + scmd->result = SAM_STAT_BUSY; + scmd->scsi_done(scmd); + return 0; + } + } while (_scsih_set_satl_pending(scmd, true)); + if (scmd->sc_data_direction == DMA_FROM_DEVICE) mpi_control = MPI2_SCSIIO_CONTROL_READ; else if (scmd->sc_data_direction == DMA_TO_DEVICE) @@ -3945,6 +3945,7 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) if (!smid) { pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", ioc->name, __func__); + _scsih_set_satl_pending(scmd, false); goto out; } mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); @@ -3975,6 +3976,7 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) if (mpi_request->DataLength) { if (ioc->build_sg_scmd(ioc, scmd, smid)) { mpt3sas_base_free_smid(ioc, smid); + _scsih_set_satl_pending(scmd, false); goto out; } } else diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c index 02360de6b7e0..39285070f3b5 100644 --- a/drivers/scsi/mvumi.c +++ b/drivers/scsi/mvumi.c @@ -2629,7 +2629,7 @@ static void mvumi_shutdown(struct pci_dev *pdev) mvumi_flush_cache(mhba); } -static int mvumi_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused mvumi_suspend(struct pci_dev *pdev, pm_message_t state) { struct mvumi_hba *mhba = NULL; @@ -2648,7 +2648,7 @@ static int mvumi_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } -static int mvumi_resume(struct pci_dev *pdev) +static int __maybe_unused mvumi_resume(struct pci_dev *pdev) { int ret; struct mvumi_hba *mhba = NULL; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e197c6f39de2..aa18c729d23a 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -365,6 +365,7 @@ qla24xx_abort_sp_done(void *data, void *ptr, int res) srb_t *sp = (srb_t *)ptr; struct srb_iocb *abt = &sp->u.iocb_cmd; + del_timer(&sp->u.iocb_cmd.timer); complete(&abt->u.abt.comp); } diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index e6faa0b050d1..824e27eec7a1 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -5502,7 +5502,7 @@ static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha, fc_port_t *fcport; int rc; - fcport = kzalloc(sizeof(*fcport), GFP_KERNEL); + fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); if (!fcport) { ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06f, "qla_target(%d): Allocation of tmp FC port failed", diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 60720e5b1ebc..6b61b09b3226 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -180,7 +180,7 @@ static struct { {"HITACHI", "6586-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"HITACHI", "6588-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP VA7400 */ - {"HP", "OPEN-", "*", BLIST_REPORTLUN2}, /* HP XP Arrays */ + {"HP", "OPEN-", "*", BLIST_REPORTLUN2 | BLIST_TRY_VPD_PAGES}, /* HP XP Arrays */ {"HP", "NetRAID-4M", NULL, BLIST_FORCELUN}, {"HP", "HSV100", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD}, {"HP", "C1557A", NULL, BLIST_FORCELUN}, @@ -589,17 +589,12 @@ int scsi_get_device_flags_keyed(struct scsi_device *sdev, int key) { struct scsi_dev_info_list *devinfo; - int err; devinfo = scsi_dev_info_list_find(vendor, model, key); if (!IS_ERR(devinfo)) return devinfo->flags; - err = PTR_ERR(devinfo); - if (err != -ENOENT) - return err; - - /* nothing found, return nothing */ + /* key or device not found: return nothing */ if (key != SCSI_DEVINFO_GLOBAL) return 0; diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c index 4d655b568269..5711d58f9e81 100644 --- a/drivers/scsi/scsi_dh.c +++ b/drivers/scsi/scsi_dh.c @@ -56,10 +56,13 @@ static const struct scsi_dh_blist scsi_dh_blist[] = { {"IBM", "1815", "rdac", }, {"IBM", "1818", "rdac", }, {"IBM", "3526", "rdac", }, + {"IBM", "3542", "rdac", }, + {"IBM", "3552", "rdac", }, {"SGI", "TP9", "rdac", }, {"SGI", "IS", "rdac", }, - {"STK", "OPENstorage D280", "rdac", }, + {"STK", "OPENstorage", "rdac", }, {"STK", "FLEXLINE 380", "rdac", }, + {"STK", "BladeCtlr", "rdac", }, {"SUN", "CSM", "rdac", }, {"SUN", "LCSM100", "rdac", }, {"SUN", "STK6580_6780", "rdac", }, diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index ee65f3324d71..367dde6a6e17 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1420,6 +1420,85 @@ static int media_not_present(struct scsi_disk *sdkp, return 0; } +/** + * sd_check_events - check media events + * @disk: kernel device descriptor + * @clearing: disk events currently being cleared + * + * Returns mask of DISK_EVENT_*. + * + * Note: this function is invoked from the block subsystem. + **/ +static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing) +{ + struct scsi_disk *sdkp = scsi_disk(disk); + struct scsi_device *sdp = sdkp->device; + struct scsi_sense_hdr *sshdr = NULL; + int retval; + + SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_check_events\n")); + + /* Simply return for embedded storage media such as UFS */ + if (!sdp->removable) + goto out; + + /* + * If the device is offline, don't send any commands - just pretend as + * if the command failed. If the device ever comes back online, we + * can deal with it then. It is only because of unrecoverable errors + * that we would ever take a device offline in the first place. + */ + if (!scsi_device_online(sdp)) { + set_media_not_present(sdkp); + goto out; + } + + /* + * Using TEST_UNIT_READY enables differentiation between drive with + * no cartridge loaded - NOT READY, drive with changed cartridge - + * UNIT ATTENTION, or with same cartridge - GOOD STATUS. + * + * Drives that auto spin down. eg iomega jaz 1G, will be started + * by sd_spinup_disk() from sd_revalidate_disk(), which happens whenever + * sd_revalidate() is called. + */ + retval = -ENODEV; + + if (scsi_block_when_processing_errors(sdp)) { + sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL); + retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES, + sshdr); + } + + /* failed to execute TUR, assume media not present */ + if (host_byte(retval)) { + set_media_not_present(sdkp); + goto out; + } + + if (media_not_present(sdkp, sshdr)) + goto out; + + /* + * For removable scsi disk we have to recognise the presence + * of a disk in the drive. + */ + if (!sdkp->media_present) + sdp->changed = 1; + sdkp->media_present = 1; +out: + /* + * sdp->changed is set under the following conditions: + * + * Medium present state has changed in either direction. + * Device has indicated UNIT_ATTENTION. + */ + kfree(sshdr); + retval = sdp->changed ? DISK_EVENT_MEDIA_CHANGE : 0; + sdp->changed = 0; + return retval; +} + static int sd_sync_cache(struct scsi_disk *sdkp) { int retries, res; @@ -1612,6 +1691,7 @@ static const struct block_device_operations sd_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = sd_compat_ioctl, #endif + .check_events = sd_check_events, .revalidate_disk = sd_revalidate_disk, .unlock_native_capacity = sd_unlock_native_capacity, .pr_ops = &sd_pr_ops, @@ -1873,6 +1953,8 @@ sd_spinup_disk(struct scsi_disk *sdkp) break; /* standby */ if (sshdr.asc == 4 && sshdr.ascq == 0xc) break; /* unavailable */ + if (sshdr.asc == 4 && sshdr.ascq == 0x1b) + break; /* sanitize in progress */ /* * Issue command to spin up drive when not ready */ diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index 044d06410d4c..01168acc864d 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -546,7 +546,6 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, ecomp = &edev->component[components++]; if (!IS_ERR(ecomp)) { - ses_get_power_status(edev, ecomp); if (addl_desc_ptr) ses_process_descriptor( ecomp, diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 3bc15d2664a1..3906be2836ba 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -535,6 +535,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) } else count = (old_hdr->result == 0) ? 0 : -EIO; sg_finish_rem_req(srp); + sg_remove_request(sfp, srp); retval = count; free_old_hdr: kfree(old_hdr); @@ -575,6 +576,7 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp) } err_out: err2 = sg_finish_rem_req(srp); + sg_remove_request(sfp, srp); return err ? : err2 ? : count; } @@ -674,18 +676,14 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) * is a non-zero input_size, so emit a warning. */ if (hp->dxfer_direction == SG_DXFER_TO_FROM_DEV) { - static char cmd[TASK_COMM_LEN]; - if (strcmp(current->comm, cmd)) { - printk_ratelimited(KERN_WARNING - "sg_write: data in/out %d/%d bytes " - "for SCSI command 0x%x-- guessing " - "data in;\n program %s not setting " - "count and/or reply_len properly\n", - old_hdr.reply_len - (int)SZ_SG_HEADER, - input_size, (unsigned int) cmnd[0], - current->comm); - strcpy(cmd, current->comm); - } + printk_ratelimited(KERN_WARNING + "sg_write: data in/out %d/%d bytes " + "for SCSI command 0x%x-- guessing " + "data in;\n program %s not setting " + "count and/or reply_len properly\n", + old_hdr.reply_len - (int)SZ_SG_HEADER, + input_size, (unsigned int) cmnd[0], + current->comm); } k = sg_common_write(sfp, srp, cmnd, sfp->timeout, blocking); return (k < 0) ? k : count; @@ -784,11 +782,15 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, "sg_common_write: scsi opcode=0x%02x, cmd_size=%d\n", (int) cmnd[0], (int) hp->cmd_len)); + if (hp->dxfer_len >= SZ_256M) + return -EINVAL; + k = sg_start_req(srp, cmnd); if (k) { SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sfp->parentdp, "sg_common_write: start_req err=%d\n", k)); sg_finish_rem_req(srp); + sg_remove_request(sfp, srp); return k; /* probably out of space --> ENOMEM */ } if (atomic_read(&sdp->detaching)) { @@ -801,6 +803,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, } sg_finish_rem_req(srp); + sg_remove_request(sfp, srp); return -ENODEV; } @@ -1293,6 +1296,7 @@ sg_rq_end_io_usercontext(struct work_struct *work) struct sg_fd *sfp = srp->parentfp; sg_finish_rem_req(srp); + sg_remove_request(sfp, srp); kref_put(&sfp->f_ref, sg_remove_sfp); } @@ -1834,8 +1838,6 @@ sg_finish_rem_req(Sg_request *srp) else sg_remove_scat(sfp, req_schp); - sg_remove_request(sfp, srp); - return ret; } @@ -1901,7 +1903,7 @@ retry: num = (rem_sz > scatter_elem_sz_prev) ? scatter_elem_sz_prev : rem_sz; - schp->pages[k] = alloc_pages(gfp_mask, order); + schp->pages[k] = alloc_pages(gfp_mask | __GFP_ZERO, order); if (!schp->pages[k]) goto out; @@ -2072,11 +2074,12 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id) if ((1 == resp->done) && (!resp->sg_io_owned) && ((-1 == pack_id) || (resp->header.pack_id == pack_id))) { resp->done = 2; /* guard against other readers */ - break; + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); + return resp; } } write_unlock_irqrestore(&sfp->rq_list_lock, iflags); - return resp; + return NULL; } /* always adds to end of list */ @@ -2182,12 +2185,17 @@ sg_remove_sfp_usercontext(struct work_struct *work) struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work); struct sg_device *sdp = sfp->parentdp; Sg_request *srp; + unsigned long iflags; /* Cleanup any responses which were never read(). */ + write_lock_irqsave(&sfp->rq_list_lock, iflags); while (!list_empty(&sfp->rq_list)) { srp = list_first_entry(&sfp->rq_list, Sg_request, entry); sg_finish_rem_req(srp); + list_del(&srp->entry); + srp->parentfp = NULL; } + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); if (sfp->reserve.bufflen > 0) { SCSI_LOG_TIMEOUT(6, sg_printk(KERN_INFO, sdp, diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c index 3b3b56f4a830..82ed99848378 100644 --- a/drivers/scsi/sim710.c +++ b/drivers/scsi/sim710.c @@ -176,8 +176,7 @@ static struct eisa_device_id sim710_eisa_ids[] = { }; MODULE_DEVICE_TABLE(eisa, sim710_eisa_ids); -static __init int -sim710_eisa_probe(struct device *dev) +static int sim710_eisa_probe(struct device *dev) { struct eisa_device *edev = to_eisa_device(dev); unsigned long io_addr = edev->base_addr; diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 5e4e1ba96f10..351d81dc2200 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -890,10 +890,11 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, case TEST_UNIT_READY: break; default: - set_host_byte(scmnd, DID_TARGET_FAILURE); + set_host_byte(scmnd, DID_ERROR); } break; case SRB_STATUS_INVALID_LUN: + set_host_byte(scmnd, DID_NO_CONNECT); do_work = true; process_err_fn = storvsc_remove_lun; break; diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 105d861a2325..aaddf2fff99c 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -2596,7 +2596,7 @@ bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host, int ufs_qcom_testbus_config(struct ufs_qcom_host *host) { int reg = 0; - int offset, ret = 0, testbus_sel_offset = 19; + int offset = 0, ret = 0, testbus_sel_offset = 19; u32 mask = TEST_BUS_SUB_SEL_MASK; unsigned long flags; struct ufs_hba *hba; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9bf7f57d9a17..6d43254d84b9 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3,7 +3,7 @@ * * This code is based on drivers/scsi/ufs/ufshcd.c * Copyright (C) 2011-2013 Samsung India Software Operations - * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * Authors: * Santosh Yaraganavi <santosh.sy@samsung.com> @@ -635,6 +635,7 @@ static void __ufshcd_cmd_log(struct ufs_hba *hba, char *str, char *cmd_type, entry.str = str; entry.lba = lba; + entry.cmd_id = cmd_id; entry.transfer_len = transfer_len; entry.doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); entry.tag = tag; @@ -8431,7 +8432,8 @@ static void ufshcd_hba_exit(struct ufs_hba *hba) if (ufshcd_is_clkscaling_supported(hba)) { if (hba->devfreq) ufshcd_suspend_clkscaling(hba); - destroy_workqueue(hba->clk_scaling.workq); + if (hba->clk_scaling.workq) + destroy_workqueue(hba->clk_scaling.workq); } ufshcd_disable_clocks(hba, false); ufshcd_setup_hba_vreg(hba, false); diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 03a2aadf0d3c..8ef905cbfc9c 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -28,6 +28,7 @@ #include <scsi/scsi_device.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_tcq.h> +#include <scsi/scsi_devinfo.h> #include <linux/seqlock.h> #define VIRTIO_SCSI_MEMPOOL_SZ 64 @@ -704,6 +705,28 @@ static int virtscsi_device_reset(struct scsi_cmnd *sc) return virtscsi_tmf(vscsi, cmd); } +static int virtscsi_device_alloc(struct scsi_device *sdevice) +{ + /* + * Passed through SCSI targets (e.g. with qemu's 'scsi-block') + * may have transfer limits which come from the host SCSI + * controller or something on the host side other than the + * target itself. + * + * To make this work properly, the hypervisor can adjust the + * target's VPD information to advertise these limits. But + * for that to work, the guest has to look at the VPD pages, + * which we won't do by default if it is an SPC-2 device, even + * if it does actually support it. + * + * So, set the blist to always try to read the VPD pages. + */ + sdevice->sdev_bflags = BLIST_TRY_VPD_PAGES; + + return 0; +} + + /** * virtscsi_change_queue_depth() - Change a virtscsi target's queue depth * @sdev: Virtscsi target whose queue depth to change @@ -775,6 +798,7 @@ static struct scsi_host_template virtscsi_host_template_single = { .change_queue_depth = virtscsi_change_queue_depth, .eh_abort_handler = virtscsi_abort, .eh_device_reset_handler = virtscsi_device_reset, + .slave_alloc = virtscsi_device_alloc, .can_queue = 1024, .dma_boundary = UINT_MAX, @@ -795,6 +819,7 @@ static struct scsi_host_template virtscsi_host_template_multi = { .eh_abort_handler = virtscsi_abort, .eh_device_reset_handler = virtscsi_device_reset, + .slave_alloc = virtscsi_device_alloc, .can_queue = 1024, .dma_boundary = UINT_MAX, .use_clustering = ENABLE_CLUSTERING, |
