diff options
Diffstat (limited to 'drivers/scsi/mpt3sas/mpt3sas_scsih.c')
| -rw-r--r-- | drivers/scsi/mpt3sas/mpt3sas_scsih.c | 176 |
1 files changed, 72 insertions, 104 deletions
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 8e24ebcebfe5..7092d0debef3 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -52,10 +52,8 @@ #include <linux/delay.h> #include <linux/pci.h> #include <linux/interrupt.h> -#include <linux/aer.h> #include <linux/raid_class.h> -#include <linux/blk-mq-pci.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "mpt3sas_base.h" @@ -197,6 +195,14 @@ struct sense_info { #define MPT3SAS_PORT_ENABLE_COMPLETE (0xFFFD) #define MPT3SAS_ABRT_TASK_SET (0xFFFE) #define MPT3SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF) + +/* + * SAS Log info code for a NCQ collateral abort after an NCQ error: + * IOC_LOGINFO_PREFIX_PL | PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR + * See: drivers/message/fusion/lsi/mpi_log_sas.h + */ +#define IOC_LOGINFO_SATA_NCQ_FAIL_AFTER_ERR 0x31080000 + /** * struct fw_event_work - firmware event struct * @list: link list framework @@ -303,8 +309,8 @@ struct _scsi_io_transfer { /** * _scsih_set_debug_level - global setting of ioc->logging_level. - * @val: ? - * @kp: ? + * @val: value of the parameter to be set + * @kp: pointer to kernel_param structure * * Note: The logging levels are defined in mpt3sas_debug.h. */ @@ -2027,14 +2033,14 @@ scsih_target_destroy(struct scsi_target *starget) } /** - * scsih_slave_alloc - device add routine + * scsih_sdev_init - device add routine * @sdev: scsi device struct * * Return: 0 if ok. Any other return is assumed to be an error and * the device is ignored. */ static int -scsih_slave_alloc(struct scsi_device *sdev) +scsih_sdev_init(struct scsi_device *sdev) { struct Scsi_Host *shost; struct MPT3SAS_ADAPTER *ioc; @@ -2109,11 +2115,11 @@ scsih_slave_alloc(struct scsi_device *sdev) } /** - * scsih_slave_destroy - device destroy routine + * scsih_sdev_destroy - device destroy routine * @sdev: scsi device struct */ static void -scsih_slave_destroy(struct scsi_device *sdev) +scsih_sdev_destroy(struct scsi_device *sdev) { struct MPT3SAS_TARGET *sas_target_priv_data; struct scsi_target *starget; @@ -2432,8 +2438,7 @@ _scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc, } raid_device->num_pds = num_pds; - sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds * - sizeof(Mpi2RaidVol0PhysDisk_t)); + sz = struct_size(vol_pg0, PhysDisk, num_pds); vol_pg0 = kzalloc(sz, GFP_KERNEL); if (!vol_pg0) { dfailprintk(ioc, @@ -2499,14 +2504,15 @@ _scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev) } /** - * scsih_slave_configure - device configure routine. + * scsih_sdev_configure - device configure routine. * @sdev: scsi device struct + * @lim: queue limits * * Return: 0 if ok. Any other return is assumed to be an error and * the device is ignored. */ static int -scsih_slave_configure(struct scsi_device *sdev) +scsih_sdev_configure(struct scsi_device *sdev, struct queue_limits *lim) { struct Scsi_Host *shost = sdev->host; struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); @@ -2611,8 +2617,7 @@ scsih_slave_configure(struct scsi_device *sdev) raid_device->num_pds, ds); if (shost->max_sectors > MPT3SAS_RAID_MAX_SECTORS) { - blk_queue_max_hw_sectors(sdev->request_queue, - MPT3SAS_RAID_MAX_SECTORS); + lim->max_hw_sectors = MPT3SAS_RAID_MAX_SECTORS; sdev_printk(KERN_INFO, sdev, "Set queue's max_sector to: %u\n", MPT3SAS_RAID_MAX_SECTORS); @@ -2677,20 +2682,12 @@ scsih_slave_configure(struct scsi_device *sdev) pcie_device->connector_name); if (pcie_device->nvme_mdts) - blk_queue_max_hw_sectors(sdev->request_queue, - pcie_device->nvme_mdts/512); + lim->max_hw_sectors = pcie_device->nvme_mdts / 512; pcie_device_put(pcie_device); spin_unlock_irqrestore(&ioc->pcie_device_lock, flags); mpt3sas_scsih_change_queue_depth(sdev, qdepth); - /* Enable QUEUE_FLAG_NOMERGES flag, so that IOs won't be - ** merged and can eliminate holes created during merging - ** operation. - **/ - blk_queue_flag_set(QUEUE_FLAG_NOMERGES, - sdev->request_queue); - blk_queue_virt_boundary(sdev->request_queue, - ioc->page_size - 1); + lim->virt_boundary_mask = ioc->page_size - 1; return 0; } @@ -2714,7 +2711,7 @@ scsih_slave_configure(struct scsi_device *sdev) ssp_target = 1; if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SEP) { - sdev_printk(KERN_WARNING, sdev, + sdev_printk(KERN_INFO, sdev, "set ignore_delay_remove for handle(0x%04x)\n", sas_device_priv_data->sas_target->handle); sas_device_priv_data->ignore_delay_remove = 1; @@ -2757,7 +2754,7 @@ scsih_slave_configure(struct scsi_device *sdev) /** * scsih_bios_param - fetch head, sector, cylinder info for a disk * @sdev: scsi device struct - * @bdev: pointer to block device context + * @unused: pointer to gendisk * @capacity: device size (in 512 byte sectors) * @params: three element array to place output: * params[0] number of heads (max 255) @@ -2765,7 +2762,7 @@ scsih_slave_configure(struct scsi_device *sdev) * params[2] number of cylinders */ static int -scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev, +scsih_bios_param(struct scsi_device *sdev, struct gendisk *unused, sector_t capacity, int params[]) { int heads; @@ -5825,6 +5822,17 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) scmd->result = DID_TRANSPORT_DISRUPTED << 16; goto out; } + if (log_info == IOC_LOGINFO_SATA_NCQ_FAIL_AFTER_ERR) { + /* + * This is a ATA NCQ command aborted due to another NCQ + * command failure. We must retry this command + * immediately but without incrementing its retry + * counter. + */ + WARN_ON_ONCE(xfer_cnt != 0); + scmd->result = DID_IMM_RETRY << 16; + break; + } if (log_info == 0x31110630) { if (scmd->retries > 2) { scmd->result = DID_NO_CONNECT << 16; @@ -5967,8 +5975,7 @@ _scsih_update_vphys_after_reset(struct MPT3SAS_ADAPTER *ioc) /* * Read SASIOUnitPage0 to get each HBA Phy's data. */ - sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + - (ioc->sas_hba.num_phys * sizeof(Mpi2SasIOUnit0PhyData_t)); + sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys); sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); if (!sas_iounit_pg0) { ioc_err(ioc, "failure at %s:%d/%s()!\n", @@ -6146,8 +6153,7 @@ _scsih_get_port_table_after_reset(struct MPT3SAS_ADAPTER *ioc, u64 attached_sas_addr; u8 found = 0, port_count = 0, port_id; - sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys - * sizeof(Mpi2SasIOUnit0PhyData_t)); + sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys); sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); if (!sas_iounit_pg0) { ioc_err(ioc, "failure at %s:%d/%s()!\n", @@ -6580,8 +6586,7 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) ioc_info(ioc, "updating handles for sas_host(0x%016llx)\n", (u64)ioc->sas_hba.sas_address)); - sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys - * sizeof(Mpi2SasIOUnit0PhyData_t)); + sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys); sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); if (!sas_iounit_pg0) { ioc_err(ioc, "failure at %s:%d/%s()!\n", @@ -6732,8 +6737,7 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc) ioc->sas_hba.num_phys = num_phys; /* sas_iounit page 0 */ - sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys * - sizeof(Mpi2SasIOUnit0PhyData_t)); + sz = struct_size(sas_iounit_pg0, PhyData, ioc->sas_hba.num_phys); sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); if (!sas_iounit_pg0) { ioc_err(ioc, "failure at %s:%d/%s()!\n", @@ -6755,8 +6759,7 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc) } /* sas_iounit page 1 */ - sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * - sizeof(Mpi2SasIOUnit1PhyData_t)); + sz = struct_size(sas_iounit_pg1, PhyData, ioc->sas_hba.num_phys); sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); if (!sas_iounit_pg1) { ioc_err(ioc, "failure at %s:%d/%s()!\n", @@ -10377,8 +10380,8 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) Mpi2ExpanderPage0_t expander_pg0; Mpi2SasDevicePage0_t sas_device_pg0; Mpi26PCIeDevicePage0_t pcie_device_pg0; - Mpi2RaidVolPage1_t *volume_pg1; - Mpi2RaidVolPage0_t *volume_pg0; + Mpi2RaidVolPage1_t volume_pg1; + Mpi2RaidVolPage0_t volume_pg0; Mpi2RaidPhysDiskPage0_t pd_pg0; Mpi2EventIrConfigElement_t element; Mpi2ConfigReply_t mpi_reply; @@ -10393,16 +10396,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) u8 retry_count; unsigned long flags; - volume_pg0 = kzalloc(sizeof(*volume_pg0), GFP_KERNEL); - if (!volume_pg0) - return; - - volume_pg1 = kzalloc(sizeof(*volume_pg1), GFP_KERNEL); - if (!volume_pg1) { - kfree(volume_pg0); - return; - } - ioc_info(ioc, "scan devices: start\n"); _scsih_sas_host_refresh(ioc); @@ -10512,7 +10505,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) /* volumes */ handle = 0xFFFF; while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, - volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { + &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { @@ -10520,15 +10513,15 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) ioc_status, le32_to_cpu(mpi_reply.IOCLogInfo)); break; } - handle = le16_to_cpu(volume_pg1->DevHandle); + handle = le16_to_cpu(volume_pg1.DevHandle); spin_lock_irqsave(&ioc->raid_device_lock, flags); raid_device = _scsih_raid_device_find_by_wwid(ioc, - le64_to_cpu(volume_pg1->WWID)); + le64_to_cpu(volume_pg1.WWID)); spin_unlock_irqrestore(&ioc->raid_device_lock, flags); if (raid_device) continue; if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, - volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, + &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, sizeof(Mpi2RaidVolPage0_t))) continue; ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & @@ -10538,17 +10531,17 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) ioc_status, le32_to_cpu(mpi_reply.IOCLogInfo)); break; } - if (volume_pg0->VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL || - volume_pg0->VolumeState == MPI2_RAID_VOL_STATE_ONLINE || - volume_pg0->VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) { + if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL || + volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE || + volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) { memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t)); element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED; - element.VolDevHandle = volume_pg1->DevHandle; + element.VolDevHandle = volume_pg1.DevHandle; ioc_info(ioc, "\tBEFORE adding volume: handle (0x%04x)\n", - volume_pg1->DevHandle); + volume_pg1.DevHandle); _scsih_sas_volume_add(ioc, &element); ioc_info(ioc, "\tAFTER adding volume: handle (0x%04x)\n", - volume_pg1->DevHandle); + volume_pg1.DevHandle); } } @@ -10637,9 +10630,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) handle, (u64)le64_to_cpu(pcie_device_pg0.WWID)); } - kfree(volume_pg0); - kfree(volume_pg1); - ioc_info(ioc, "\tpcie devices: pcie end devices complete\n"); ioc_info(ioc, "scan devices: complete\n"); } @@ -10819,8 +10809,7 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) break; case MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: _scsih_pcie_topology_change_event(ioc, fw_event); - ioc->current_event = NULL; - return; + break; } out: fw_event_work_put(fw_event); @@ -11351,6 +11340,7 @@ static void scsih_remove(struct pci_dev *pdev) } mpt3sas_base_detach(ioc); + mpt3sas_ctl_release(ioc); spin_lock(&gioc_lock); list_del(&ioc->list); spin_unlock(&gioc_lock); @@ -11917,7 +11907,7 @@ static void scsih_map_queues(struct Scsi_Host *shost) */ map->queue_offset = qoff; if (i != HCTX_TYPE_POLL) - blk_mq_pci_map_queues(map, ioc->pdev, offset); + blk_mq_map_hw_queues(map, &ioc->pdev->dev, offset); else blk_mq_map_queues(map); @@ -11926,16 +11916,16 @@ static void scsih_map_queues(struct Scsi_Host *shost) } /* shost template for SAS 2.0 HBA devices */ -static struct scsi_host_template mpt2sas_driver_template = { +static const struct scsi_host_template mpt2sas_driver_template = { .module = THIS_MODULE, .name = "Fusion MPT SAS Host", .proc_name = MPT2SAS_DRIVER_NAME, .queuecommand = scsih_qcmd, .target_alloc = scsih_target_alloc, - .slave_alloc = scsih_slave_alloc, - .slave_configure = scsih_slave_configure, + .sdev_init = scsih_sdev_init, + .sdev_configure = scsih_sdev_configure, .target_destroy = scsih_target_destroy, - .slave_destroy = scsih_slave_destroy, + .sdev_destroy = scsih_sdev_destroy, .scan_finished = scsih_scan_finished, .scan_start = scsih_scan_start, .change_queue_depth = scsih_change_queue_depth, @@ -11964,16 +11954,16 @@ static struct raid_function_template mpt2sas_raid_functions = { }; /* shost template for SAS 3.0 HBA devices */ -static struct scsi_host_template mpt3sas_driver_template = { +static const struct scsi_host_template mpt3sas_driver_template = { .module = THIS_MODULE, .name = "Fusion MPT SAS Host", .proc_name = MPT3SAS_DRIVER_NAME, .queuecommand = scsih_qcmd, .target_alloc = scsih_target_alloc, - .slave_alloc = scsih_slave_alloc, - .slave_configure = scsih_slave_configure, + .sdev_init = scsih_sdev_init, + .sdev_configure = scsih_sdev_configure, .target_destroy = scsih_target_destroy, - .slave_destroy = scsih_slave_destroy, + .sdev_destroy = scsih_sdev_destroy, .scan_finished = scsih_scan_finished, .scan_start = scsih_scan_start, .change_queue_depth = scsih_change_queue_depth, @@ -12259,6 +12249,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* misc semaphores and spin locks */ mutex_init(&ioc->reset_in_progress_mutex); + mutex_init(&ioc->hostdiag_unlock_mutex); /* initializing pci_access_mutex lock */ mutex_init(&ioc->pci_access_mutex); spin_lock_init(&ioc->ioc_reset_in_progress_lock); @@ -12327,10 +12318,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC); /* event thread */ - snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), - "fw_event_%s%d", ioc->driver_name, ioc->id); ioc->firmware_event_thread = alloc_ordered_workqueue( - ioc->firmware_event_name, 0); + "fw_event_%s%d", 0, ioc->driver_name, ioc->id); if (!ioc->firmware_event_thread) { ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); @@ -12591,29 +12580,6 @@ scsih_pci_mmio_enabled(struct pci_dev *pdev) return PCI_ERS_RESULT_RECOVERED; } -/** - * scsih_ncq_prio_supp - Check for NCQ command priority support - * @sdev: scsi device struct - * - * This is called when a user indicates they would like to enable - * ncq command priorities. This works only on SATA devices. - */ -bool scsih_ncq_prio_supp(struct scsi_device *sdev) -{ - struct scsi_vpd *vpd; - bool ncq_prio_supp = false; - - rcu_read_lock(); - vpd = rcu_dereference(sdev->vpd_pg89); - if (!vpd || vpd->len < 214) - goto out; - - ncq_prio_supp = (vpd->data[213] >> 4) & 1; -out: - rcu_read_unlock(); - - return ncq_prio_supp; -} /* * The pci device ids are defined in mpi/mpi2_cnfg.h. */ @@ -12762,7 +12728,7 @@ static const struct pci_device_id mpt3sas_pci_table[] = { }; MODULE_DEVICE_TABLE(pci, mpt3sas_pci_table); -static struct pci_error_handlers _mpt3sas_err_handler = { +static const struct pci_error_handlers _mpt3sas_err_handler = { .error_detected = scsih_pci_error_detected, .mmio_enabled = scsih_pci_mmio_enabled, .slot_reset = scsih_pci_slot_reset, @@ -12914,8 +12880,10 @@ _mpt3sas_init(void) mpt3sas_ctl_init(hbas_to_enumerate); error = pci_register_driver(&mpt3sas_driver); - if (error) + if (error) { + mpt3sas_ctl_exit(hbas_to_enumerate); scsih_exit(); + } return error; } @@ -12930,10 +12898,10 @@ _mpt3sas_exit(void) pr_info("mpt3sas version %s unloading\n", MPT3SAS_DRIVER_VERSION); - mpt3sas_ctl_exit(hbas_to_enumerate); - pci_unregister_driver(&mpt3sas_driver); + mpt3sas_ctl_exit(hbas_to_enumerate); + scsih_exit(); } |
