From cf6bf9710cabba1fe94a4349f4eb8db623c77ebc Mon Sep 17 00:00:00 2001 From: Chaitra P B Date: Tue, 24 Apr 2018 05:28:30 -0400 Subject: scsi: mpt3sas: Bug fix for big endian systems. This patch fixes sparse warnings and bugs on big endian systems. Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 59 +++++++++++++++++------------------- 1 file changed, 28 insertions(+), 31 deletions(-) (limited to 'drivers/scsi/mpt3sas/mpt3sas_scsih.c') diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 8cd3782fab49..0319b34ebf6c 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -157,8 +157,8 @@ MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 "); /* raid transport support */ -struct raid_template *mpt3sas_raid_template; -struct raid_template *mpt2sas_raid_template; +static struct raid_template *mpt3sas_raid_template; +static struct raid_template *mpt2sas_raid_template; /** @@ -3725,7 +3725,7 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, if (!delayed_sc) return _scsih_check_for_pending_tm(ioc, smid); INIT_LIST_HEAD(&delayed_sc->list); - delayed_sc->handle = mpi_request_tm->DevHandle; + delayed_sc->handle = le16_to_cpu(mpi_request_tm->DevHandle); list_add_tail(&delayed_sc->list, &ioc->delayed_sc_list); dewtprintk(ioc, pr_info(MPT3SAS_FMT "DELAYED:sc:handle(0x%04x), (open)\n", @@ -3903,8 +3903,8 @@ _scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, * Context - processed in interrupt context. */ static void -_scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event, - u32 event_context) +_scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, U16 event, + U32 event_context) { Mpi2EventAckRequest_t *ack_request; int i = smid - ioc->internal_smid; @@ -3979,13 +3979,13 @@ _scsih_issue_delayed_sas_io_unit_ctrl(struct MPT3SAS_ADAPTER *ioc, dewtprintk(ioc, pr_info(MPT3SAS_FMT "sc_send:handle(0x%04x), (open), smid(%d), cb(%d)\n", - ioc->name, le16_to_cpu(handle), smid, + ioc->name, handle, smid, ioc->tm_sas_control_cb_idx)); mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t)); mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; - mpi_request->DevHandle = handle; + mpi_request->DevHandle = cpu_to_le16(handle); mpt3sas_base_put_smid_default(ioc, smid); } @@ -6108,7 +6108,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, if (sas_device_pg0.EnclosureHandle) { encl_pg0_rc = mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - sas_device_pg0.EnclosureHandle); + le16_to_cpu(sas_device_pg0.EnclosureHandle)); if (encl_pg0_rc) pr_info(MPT3SAS_FMT "Enclosure Pg0 read failed for handle(0x%04x)\n", @@ -6917,7 +6917,7 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) if (pcie_device->enclosure_handle != 0) pcie_device->slot = le16_to_cpu(pcie_device_pg0.Slot); - if (le16_to_cpu(pcie_device_pg0.Flags) & + if (le32_to_cpu(pcie_device_pg0.Flags) & MPI26_PCIEDEV0_FLAGS_ENCL_LEVEL_VALID) { pcie_device->enclosure_level = pcie_device_pg0.EnclosureLevel; memcpy(&pcie_device->connector_name[0], @@ -8364,8 +8364,9 @@ Mpi2SasDevicePage0_t *sas_device_pg0) spin_lock_irqsave(&ioc->sas_device_lock, flags); list_for_each_entry(sas_device, &ioc->sas_device_list, list) { - if ((sas_device->sas_address == sas_device_pg0->SASAddress) && - (sas_device->slot == sas_device_pg0->Slot)) { + if ((sas_device->sas_address == le64_to_cpu( + sas_device_pg0->SASAddress)) && (sas_device->slot == + le16_to_cpu(sas_device_pg0->Slot))) { sas_device->responding = 1; starget = sas_device->starget; if (starget && starget->hostdata) { @@ -8377,7 +8378,7 @@ Mpi2SasDevicePage0_t *sas_device_pg0) if (starget) { starget_printk(KERN_INFO, starget, "handle(0x%04x), sas_addr(0x%016llx)\n", - sas_device_pg0->DevHandle, + le16_to_cpu(sas_device_pg0->DevHandle), (unsigned long long) sas_device->sas_address); @@ -8389,7 +8390,7 @@ Mpi2SasDevicePage0_t *sas_device_pg0) sas_device->enclosure_logical_id, sas_device->slot); } - if (sas_device_pg0->Flags & + if (le16_to_cpu(sas_device_pg0->Flags) & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { sas_device->enclosure_level = sas_device_pg0->EnclosureLevel; @@ -8403,14 +8404,16 @@ Mpi2SasDevicePage0_t *sas_device_pg0) _scsih_get_enclosure_logicalid_chassis_slot(ioc, sas_device_pg0, sas_device); - if (sas_device->handle == sas_device_pg0->DevHandle) + if (sas_device->handle == le16_to_cpu( + sas_device_pg0->DevHandle)) goto out; pr_info("\thandle changed from(0x%04x)!!!\n", sas_device->handle); - sas_device->handle = sas_device_pg0->DevHandle; + sas_device->handle = le16_to_cpu( + sas_device_pg0->DevHandle); if (sas_target_priv_data) sas_target_priv_data->handle = - sas_device_pg0->DevHandle; + le16_to_cpu(sas_device_pg0->DevHandle); goto out; } } @@ -8449,15 +8452,10 @@ _scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc) MPI2_IOCSTATUS_MASK; if (ioc_status != MPI2_IOCSTATUS_SUCCESS) break; - handle = sas_device_pg0.DevHandle = - le16_to_cpu(sas_device_pg0.DevHandle); + handle = le16_to_cpu(sas_device_pg0.DevHandle); device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); if (!(_scsih_is_end_device(device_info))) continue; - sas_device_pg0.SASAddress = - le64_to_cpu(sas_device_pg0.SASAddress); - sas_device_pg0.Slot = le16_to_cpu(sas_device_pg0.Slot); - sas_device_pg0.Flags = le16_to_cpu(sas_device_pg0.Flags); _scsih_mark_responding_sas_device(ioc, &sas_device_pg0); } @@ -8487,8 +8485,9 @@ _scsih_mark_responding_pcie_device(struct MPT3SAS_ADAPTER *ioc, spin_lock_irqsave(&ioc->pcie_device_lock, flags); list_for_each_entry(pcie_device, &ioc->pcie_device_list, list) { - if ((pcie_device->wwid == pcie_device_pg0->WWID) && - (pcie_device->slot == pcie_device_pg0->Slot)) { + if ((pcie_device->wwid == le64_to_cpu(pcie_device_pg0->WWID)) + && (pcie_device->slot == le16_to_cpu( + pcie_device_pg0->Slot))) { pcie_device->responding = 1; starget = pcie_device->starget; if (starget && starget->hostdata) { @@ -8523,14 +8522,16 @@ _scsih_mark_responding_pcie_device(struct MPT3SAS_ADAPTER *ioc, pcie_device->connector_name[0] = '\0'; } - if (pcie_device->handle == pcie_device_pg0->DevHandle) + if (pcie_device->handle == le16_to_cpu( + pcie_device_pg0->DevHandle)) goto out; pr_info("\thandle changed from(0x%04x)!!!\n", pcie_device->handle); - pcie_device->handle = pcie_device_pg0->DevHandle; + pcie_device->handle = le16_to_cpu( + pcie_device_pg0->DevHandle); if (sas_target_priv_data) sas_target_priv_data->handle = - pcie_device_pg0->DevHandle; + le16_to_cpu(pcie_device_pg0->DevHandle); goto out; } } @@ -8579,10 +8580,6 @@ _scsih_search_responding_pcie_devices(struct MPT3SAS_ADAPTER *ioc) device_info = le32_to_cpu(pcie_device_pg0.DeviceInfo); if (!(_scsih_is_nvme_device(device_info))) continue; - pcie_device_pg0.WWID = le64_to_cpu(pcie_device_pg0.WWID), - pcie_device_pg0.Slot = le16_to_cpu(pcie_device_pg0.Slot); - pcie_device_pg0.Flags = le32_to_cpu(pcie_device_pg0.Flags); - pcie_device_pg0.DevHandle = handle; _scsih_mark_responding_pcie_device(ioc, &pcie_device_pg0); } out: -- cgit v1.2.3 From 95540b8eaf30d224ba0723f5a109aa52fd996c6f Mon Sep 17 00:00:00 2001 From: Chaitra P B Date: Tue, 24 Apr 2018 05:28:35 -0400 Subject: scsi: mpt3sas: Added support for SAS Device Discovery Error Event. The SAS Device Discovery Error Event is sent to the host when discovery for a particular device is failed during discovery, even after maximum retries by the IOC. Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 4 ++++ drivers/scsi/mpt3sas/mpt3sas_scsih.c | 42 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) (limited to 'drivers/scsi/mpt3sas/mpt3sas_scsih.c') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 379a4127b059..ea07533f6676 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -1030,6 +1030,9 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc, case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION: desc = "Cable Event"; break; + case MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR: + desc = "SAS Device Discovery Error"; + break; case MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE: desc = "PCIE Device Status Change"; break; @@ -6599,6 +6602,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED); _base_unmask_events(ioc, MPI2_EVENT_TEMP_THRESHOLD); _base_unmask_events(ioc, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION); + _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR); if (ioc->hba_mpi_version_belonged == MPI26_VERSION) { if (ioc->is_gen35_ioc) { _base_unmask_events(ioc, diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 0319b34ebf6c..05ce0227a0a2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -7526,6 +7526,44 @@ _scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc, } } +/** + * _scsih_sas_device_discovery_error_event - display SAS device discovery error + * events + * @ioc: per adapter object + * @fw_event: The fw_event_work object + * Context: user. + * + * Return nothing. + */ +static void +_scsih_sas_device_discovery_error_event(struct MPT3SAS_ADAPTER *ioc, + struct fw_event_work *fw_event) +{ + Mpi25EventDataSasDeviceDiscoveryError_t *event_data = + (Mpi25EventDataSasDeviceDiscoveryError_t *)fw_event->event_data; + + switch (event_data->ReasonCode) { + case MPI25_EVENT_SAS_DISC_ERR_SMP_FAILED: + pr_warn(MPT3SAS_FMT "SMP command sent to the expander" + "(handle:0x%04x, sas_address:0x%016llx," + "physical_port:0x%02x) has failed", + ioc->name, le16_to_cpu(event_data->DevHandle), + (unsigned long long)le64_to_cpu(event_data->SASAddress), + event_data->PhysicalPort); + break; + case MPI25_EVENT_SAS_DISC_ERR_SMP_TIMEOUT: + pr_warn(MPT3SAS_FMT "SMP command sent to the expander" + "(handle:0x%04x, sas_address:0x%016llx," + "physical_port:0x%02x) has timed out", + ioc->name, le16_to_cpu(event_data->DevHandle), + (unsigned long long)le64_to_cpu(event_data->SASAddress), + event_data->PhysicalPort); + break; + default: + break; + } +} + /** * _scsih_pcie_enumeration_event - handle enumeration events * @ioc: per adapter object @@ -9353,6 +9391,9 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) case MPI2_EVENT_SAS_DISCOVERY: _scsih_sas_discovery_event(ioc, fw_event); break; + case MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR: + _scsih_sas_device_discovery_error_event(ioc, fw_event); + break; case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: _scsih_sas_broadcast_primitive_event(ioc, fw_event); break; @@ -9537,6 +9578,7 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: case MPI2_EVENT_IR_OPERATION_STATUS: case MPI2_EVENT_SAS_DISCOVERY: + case MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR: case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: case MPI2_EVENT_IR_PHYSICAL_DISK: case MPI2_EVENT_PCIE_ENUMERATION: -- cgit v1.2.3 From 79eb96d6ca6971e79a3770991a12a16fde871e90 Mon Sep 17 00:00:00 2001 From: Chaitra P B Date: Tue, 24 Apr 2018 05:28:37 -0400 Subject: scsi: mpt3sas: Allow processing of events during driver unload. Events were not processed during driver unload, hence unloading of driver doesn't complete when drives are disconnected while unloading of driver. So don't block events in ISR path, i,e., remove the flag ioc->remove_host so that events are getting processed during driver unload. Thus allowing driver unload to complete by processing drive removal events during driver unload. Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/scsi/mpt3sas/mpt3sas_scsih.c') diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 05ce0227a0a2..29ba7e863e74 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -3680,11 +3680,7 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 ioc_state; struct _sc_list *delayed_sc; - if (ioc->remove_host) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host has been removed\n", __func__, ioc->name)); - return 1; - } else if (ioc->pci_error_recovery) { + if (ioc->pci_error_recovery) { dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: host in pci error recovery\n", __func__, ioc->name)); @@ -3806,8 +3802,7 @@ _scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) u16 smid; struct _tr_list *delayed_tr; - if (ioc->shost_recovery || ioc->remove_host || - ioc->pci_error_recovery) { + if (ioc->pci_error_recovery) { dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", __func__, ioc->name)); @@ -3860,8 +3855,7 @@ _scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, Mpi2SCSITaskManagementReply_t *mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (ioc->shost_recovery || ioc->remove_host || - ioc->pci_error_recovery) { + if (ioc->shost_recovery || ioc->pci_error_recovery) { dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", __func__, ioc->name)); @@ -9471,8 +9465,8 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u16 sz; Mpi26EventDataActiveCableExcept_t *ActiveCableEventData; - /* events turned off due to host reset or driver unloading */ - if (ioc->remove_host || ioc->pci_error_recovery) + /* events turned off due to host reset */ + if (ioc->pci_error_recovery) return 1; mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); -- cgit v1.2.3 From 22a923c315ba09a83ef88ff1d968413d9dd8fb75 Mon Sep 17 00:00:00 2001 From: Chaitra P B Date: Tue, 24 Apr 2018 05:28:38 -0400 Subject: scsi: mpt3sas: Cache enclosure pages during enclosure add. In function _scsih_add_device, for each device connected to an enclosure, driver reads the enclosure page(To get details like enclosure handle, enclosure logical ID, enclosure level etc.) With this patch, instead of reading enclosure page everytime, driver maintains a list for enclosure device(During enclosure add event, enclosure device is added to the list and removed from the list on delete events) and uses the enclosure page from the list. Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 22 +++ drivers/scsi/mpt3sas/mpt3sas_base.h | 14 ++ drivers/scsi/mpt3sas/mpt3sas_scsih.c | 296 +++++++++++++++++++++++------------ 3 files changed, 236 insertions(+), 96 deletions(-) (limited to 'drivers/scsi/mpt3sas/mpt3sas_scsih.c') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index ea07533f6676..25bc36fdb380 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -4089,6 +4089,27 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) ioc->temp_sensors_count = ioc->iounit_pg8.NumSensors; } +/** + * mpt3sas_free_enclosure_list - release memory + * @ioc: per adapter object + * + * Free memory allocated during encloure add. + * + * Return nothing. + */ +void +mpt3sas_free_enclosure_list(struct MPT3SAS_ADAPTER *ioc) +{ + struct _enclosure_node *enclosure_dev, *enclosure_dev_next; + + /* Free enclosure list */ + list_for_each_entry_safe(enclosure_dev, + enclosure_dev_next, &ioc->enclosure_list, list) { + list_del(&enclosure_dev->list); + kfree(enclosure_dev); + } +} + /** * _base_release_memory_pools - release memory * @ioc: per adapter object @@ -6669,6 +6690,7 @@ mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc) mpt3sas_base_stop_watchdog(ioc); mpt3sas_base_free_resources(ioc); _base_release_memory_pools(ioc); + mpt3sas_free_enclosure_list(ioc); pci_set_drvdata(ioc->pdev, NULL); kfree(ioc->cpu_msix_table); if (ioc->is_warpdrive) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index eeeb3b711144..3fafee666789 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -741,6 +741,17 @@ struct _sas_node { struct list_head sas_port_list; }; + +/** + * struct _enclosure_node - enclosure information + * @list: list of enclosures + * @pg0: enclosure pg0; + */ +struct _enclosure_node { + struct list_head list; + Mpi2SasEnclosurePage0_t pg0; +}; + /** * enum reset_type - reset state * @FORCE_BIG_HAMMER: issue diagnostic reset @@ -1013,6 +1024,7 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); * @iounit_pg8: static iounit page 8 * @sas_hba: sas host object * @sas_expander_list: expander object list + * @enclosure_list: enclosure object list * @sas_node_lock: * @sas_device_list: sas device object list * @sas_device_init_list: sas device object list (used only at init time) @@ -1218,6 +1230,7 @@ struct MPT3SAS_ADAPTER { /* sas hba, expander, and device list */ struct _sas_node sas_hba; struct list_head sas_expander_list; + struct list_head enclosure_list; spinlock_t sas_node_lock; struct list_head sas_device_list; struct list_head sas_device_init_list; @@ -1391,6 +1404,7 @@ int mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc); void mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc); int mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc); void mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc); +void mpt3sas_free_enclosure_list(struct MPT3SAS_ADAPTER *ioc); int mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, enum reset_type type); diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 29ba7e863e74..27cc2e827472 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -1361,6 +1361,30 @@ mpt3sas_scsih_expander_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) return r; } +/** + * mpt3sas_scsih_enclosure_find_by_handle - exclosure device search + * @ioc: per adapter object + * @handle: enclosure handle (assigned by firmware) + * Context: Calling function should acquire ioc->sas_device_lock + * + * This searches for enclosure device based on handle, then returns the + * enclosure object. + */ +static struct _enclosure_node * +mpt3sas_scsih_enclosure_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) +{ + struct _enclosure_node *enclosure_dev, *r; + + r = NULL; + list_for_each_entry(enclosure_dev, &ioc->enclosure_list, list) { + if (le16_to_cpu(enclosure_dev->pg0.EnclosureHandle) != handle) + continue; + r = enclosure_dev; + goto out; + } +out: + return r; +} /** * mpt3sas_scsih_expander_find_by_sas_address - expander device search * @ioc: per adapter object @@ -5612,10 +5636,10 @@ static int _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) { struct _sas_node *sas_expander; + struct _enclosure_node *enclosure_dev; Mpi2ConfigReply_t mpi_reply; Mpi2ExpanderPage0_t expander_pg0; Mpi2ExpanderPage1_t expander_pg1; - Mpi2SasEnclosurePage0_t enclosure_pg0; u32 ioc_status; u16 parent_handle; u64 sas_address, sas_address_parent = 0; @@ -5737,11 +5761,12 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) } if (sas_expander->enclosure_handle) { - if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply, - &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - sas_expander->enclosure_handle))) + enclosure_dev = + mpt3sas_scsih_enclosure_find_by_handle(ioc, + sas_expander->enclosure_handle); + if (enclosure_dev) sas_expander->enclosure_logical_id = - le64_to_cpu(enclosure_pg0.EnclosureLogicalID); + le64_to_cpu(enclosure_dev->pg0.EnclosureLogicalID); } _scsih_expander_node_add(ioc, sas_expander); @@ -5884,52 +5909,6 @@ _scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, return rc; } -/** - * _scsih_get_enclosure_logicalid_chassis_slot - get device's - * EnclosureLogicalID and ChassisSlot information. - * @ioc: per adapter object - * @sas_device_pg0: SAS device page0 - * @sas_device: per sas device object - * - * Returns nothing. - */ -static void -_scsih_get_enclosure_logicalid_chassis_slot(struct MPT3SAS_ADAPTER *ioc, - Mpi2SasDevicePage0_t *sas_device_pg0, struct _sas_device *sas_device) -{ - Mpi2ConfigReply_t mpi_reply; - Mpi2SasEnclosurePage0_t enclosure_pg0; - - if (!sas_device_pg0 || !sas_device) - return; - - sas_device->enclosure_handle = - le16_to_cpu(sas_device_pg0->EnclosureHandle); - sas_device->is_chassis_slot_valid = 0; - - if (!le16_to_cpu(sas_device_pg0->EnclosureHandle)) - return; - - if (mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply, - &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - le16_to_cpu(sas_device_pg0->EnclosureHandle))) { - pr_err(MPT3SAS_FMT - "Enclosure Pg0 read failed for handle(0x%04x)\n", - ioc->name, le16_to_cpu(sas_device_pg0->EnclosureHandle)); - return; - } - - sas_device->enclosure_logical_id = - le64_to_cpu(enclosure_pg0.EnclosureLogicalID); - - if (le16_to_cpu(enclosure_pg0.Flags) & - MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) { - sas_device->is_chassis_slot_valid = 1; - sas_device->chassis_slot = enclosure_pg0.ChassisSlot; - } -} - - /** * _scsih_check_device - checking device responsiveness * @ioc: per adapter object @@ -5947,6 +5926,7 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t sas_device_pg0; struct _sas_device *sas_device; + struct _enclosure_node *enclosure_dev = NULL; u32 ioc_status; unsigned long flags; u64 sas_address; @@ -6001,8 +5981,21 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, sas_device->connector_name[0] = '\0'; } - _scsih_get_enclosure_logicalid_chassis_slot(ioc, - &sas_device_pg0, sas_device); + sas_device->enclosure_handle = + le16_to_cpu(sas_device_pg0.EnclosureHandle); + sas_device->is_chassis_slot_valid = 0; + enclosure_dev = mpt3sas_scsih_enclosure_find_by_handle(ioc, + sas_device->enclosure_handle); + if (enclosure_dev) { + sas_device->enclosure_logical_id = + le64_to_cpu(enclosure_dev->pg0.EnclosureLogicalID); + if (le16_to_cpu(enclosure_dev->pg0.Flags) & + MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) { + sas_device->is_chassis_slot_valid = 1; + sas_device->chassis_slot = + enclosure_dev->pg0.ChassisSlot; + } + } } /* check if device is present */ @@ -6049,12 +6042,11 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, { Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2SasEnclosurePage0_t enclosure_pg0; struct _sas_device *sas_device; + struct _enclosure_node *enclosure_dev = NULL; u32 ioc_status; u64 sas_address; u32 device_info; - int encl_pg0_rc = -1; if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { @@ -6100,12 +6092,12 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, } if (sas_device_pg0.EnclosureHandle) { - encl_pg0_rc = mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply, - &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - le16_to_cpu(sas_device_pg0.EnclosureHandle)); - if (encl_pg0_rc) - pr_info(MPT3SAS_FMT - "Enclosure Pg0 read failed for handle(0x%04x)\n", + enclosure_dev = + mpt3sas_scsih_enclosure_find_by_handle(ioc, + le16_to_cpu(sas_device_pg0.EnclosureHandle)); + if (enclosure_dev == NULL) + pr_info(MPT3SAS_FMT "Enclosure handle(0x%04x)" + "doesn't match with enclosure device!\n", ioc->name, sas_device_pg0.EnclosureHandle); } @@ -6146,18 +6138,16 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, sas_device->enclosure_level = 0; sas_device->connector_name[0] = '\0'; } - - /* get enclosure_logical_id & chassis_slot */ + /* get enclosure_logical_id & chassis_slot*/ sas_device->is_chassis_slot_valid = 0; - if (encl_pg0_rc == 0) { + if (enclosure_dev) { sas_device->enclosure_logical_id = - le64_to_cpu(enclosure_pg0.EnclosureLogicalID); - - if (le16_to_cpu(enclosure_pg0.Flags) & + le64_to_cpu(enclosure_dev->pg0.EnclosureLogicalID); + if (le16_to_cpu(enclosure_dev->pg0.Flags) & MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) { sas_device->is_chassis_slot_valid = 1; sas_device->chassis_slot = - enclosure_pg0.ChassisSlot; + enclosure_dev->pg0.ChassisSlot; } } @@ -6839,8 +6829,8 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) Mpi26PCIeDevicePage0_t pcie_device_pg0; Mpi26PCIeDevicePage2_t pcie_device_pg2; Mpi2ConfigReply_t mpi_reply; - Mpi2SasEnclosurePage0_t enclosure_pg0; struct _pcie_device *pcie_device; + struct _enclosure_node *enclosure_dev; u32 pcie_device_type; u32 ioc_status; u64 wwid; @@ -6922,13 +6912,14 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) } /* get enclosure_logical_id */ - if (pcie_device->enclosure_handle && - !(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply, - &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - pcie_device->enclosure_handle))) - pcie_device->enclosure_logical_id = - le64_to_cpu(enclosure_pg0.EnclosureLogicalID); - + if (pcie_device->enclosure_handle) { + enclosure_dev = + mpt3sas_scsih_enclosure_find_by_handle(ioc, + pcie_device->enclosure_handle); + if (enclosure_dev) + pcie_device->enclosure_logical_id = + le64_to_cpu(enclosure_dev->pg0.EnclosureLogicalID); + } /* TODO -- Add device name once FW supports it */ if (mpt3sas_config_get_pcie_device_pg2(ioc, &mpi_reply, &pcie_device_pg2, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)) { @@ -7314,10 +7305,60 @@ static void _scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { + Mpi2ConfigReply_t mpi_reply; + struct _enclosure_node *enclosure_dev = NULL; + Mpi2EventDataSasEnclDevStatusChange_t *event_data = + (Mpi2EventDataSasEnclDevStatusChange_t *)fw_event->event_data; + int rc; + u16 enclosure_handle = le16_to_cpu(event_data->EnclosureHandle); + if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) _scsih_sas_enclosure_dev_status_change_event_debug(ioc, (Mpi2EventDataSasEnclDevStatusChange_t *) fw_event->event_data); + if (ioc->shost_recovery) + return; + + if (enclosure_handle) + enclosure_dev = + mpt3sas_scsih_enclosure_find_by_handle(ioc, + enclosure_handle); + switch (event_data->ReasonCode) { + case MPI2_EVENT_SAS_ENCL_RC_ADDED: + if (!enclosure_dev) { + enclosure_dev = + kzalloc(sizeof(struct _enclosure_node), + GFP_KERNEL); + if (!enclosure_dev) { + pr_info(MPT3SAS_FMT + "failure at %s:%d/%s()!\n", ioc->name, + __FILE__, __LINE__, __func__); + return; + } + rc = mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply, + &enclosure_dev->pg0, + MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, + enclosure_handle); + + if (rc || (le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK)) { + kfree(enclosure_dev); + return; + } + + list_add_tail(&enclosure_dev->list, + &ioc->enclosure_list); + } + break; + case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING: + if (enclosure_dev) { + list_del(&enclosure_dev->list); + kfree(enclosure_dev); + } + break; + default: + break; + } } /** @@ -8392,8 +8433,18 @@ Mpi2SasDevicePage0_t *sas_device_pg0) struct MPT3SAS_TARGET *sas_target_priv_data = NULL; struct scsi_target *starget; struct _sas_device *sas_device = NULL; + struct _enclosure_node *enclosure_dev = NULL; unsigned long flags; + if (sas_device_pg0->EnclosureHandle) { + enclosure_dev = + mpt3sas_scsih_enclosure_find_by_handle(ioc, + le16_to_cpu(sas_device_pg0->EnclosureHandle)); + if (enclosure_dev == NULL) + pr_info(MPT3SAS_FMT "Enclosure handle(0x%04x)" + "doesn't match with enclosure device!\n", + ioc->name, sas_device_pg0->EnclosureHandle); + } spin_lock_irqsave(&ioc->sas_device_lock, flags); list_for_each_entry(sas_device, &ioc->sas_device_list, list) { if ((sas_device->sas_address == le64_to_cpu( @@ -8433,8 +8484,19 @@ Mpi2SasDevicePage0_t *sas_device_pg0) sas_device->connector_name[0] = '\0'; } - _scsih_get_enclosure_logicalid_chassis_slot(ioc, - sas_device_pg0, sas_device); + sas_device->enclosure_handle = + le16_to_cpu(sas_device_pg0->EnclosureHandle); + sas_device->is_chassis_slot_valid = 0; + if (enclosure_dev) { + sas_device->enclosure_logical_id = le64_to_cpu( + enclosure_dev->pg0.EnclosureLogicalID); + if (le16_to_cpu(enclosure_dev->pg0.Flags) & + MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) { + sas_device->is_chassis_slot_valid = 1; + sas_device->chassis_slot = + enclosure_dev->pg0.ChassisSlot; + } + } if (sas_device->handle == le16_to_cpu( sas_device_pg0->DevHandle)) @@ -8453,6 +8515,52 @@ Mpi2SasDevicePage0_t *sas_device_pg0) spin_unlock_irqrestore(&ioc->sas_device_lock, flags); } +/** + * _scsih_create_enclosure_list_after_reset - Free Existing list, + * And create enclosure list by scanning all Enclosure Page(0)s + * @ioc: per adapter object + * + * Return nothing. + */ +static void +_scsih_create_enclosure_list_after_reset(struct MPT3SAS_ADAPTER *ioc) +{ + struct _enclosure_node *enclosure_dev; + Mpi2ConfigReply_t mpi_reply; + u16 enclosure_handle; + int rc; + + /* Free existing enclosure list */ + mpt3sas_free_enclosure_list(ioc); + + /* Re constructing enclosure list after reset*/ + enclosure_handle = 0xFFFF; + do { + enclosure_dev = + kzalloc(sizeof(struct _enclosure_node), GFP_KERNEL); + if (!enclosure_dev) { + pr_err(MPT3SAS_FMT + "failure at %s:%d/%s()!\n", ioc->name, + __FILE__, __LINE__, __func__); + return; + } + rc = mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply, + &enclosure_dev->pg0, + MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE, + enclosure_handle); + + if (rc || (le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK)) { + kfree(enclosure_dev); + return; + } + list_add_tail(&enclosure_dev->list, + &ioc->enclosure_list); + enclosure_handle = + le16_to_cpu(enclosure_dev->pg0.EnclosureHandle); + } while (1); +} + /** * _scsih_search_responding_sas_devices - * @ioc: per adapter object @@ -8765,22 +8873,16 @@ _scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, { struct _sas_node *sas_expander = NULL; unsigned long flags; - int i, encl_pg0_rc = -1; - Mpi2ConfigReply_t mpi_reply; - Mpi2SasEnclosurePage0_t enclosure_pg0; + int i; + struct _enclosure_node *enclosure_dev = NULL; u16 handle = le16_to_cpu(expander_pg0->DevHandle); + u16 enclosure_handle = le16_to_cpu(expander_pg0->EnclosureHandle); u64 sas_address = le64_to_cpu(expander_pg0->SASAddress); - if (le16_to_cpu(expander_pg0->EnclosureHandle)) { - encl_pg0_rc = mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply, - &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - le16_to_cpu(expander_pg0->EnclosureHandle)); - if (encl_pg0_rc) - pr_info(MPT3SAS_FMT - "Enclosure Pg0 read failed for handle(0x%04x)\n", - ioc->name, - le16_to_cpu(expander_pg0->EnclosureHandle)); - } + if (enclosure_handle) + enclosure_dev = + mpt3sas_scsih_enclosure_find_by_handle(ioc, + enclosure_handle); spin_lock_irqsave(&ioc->sas_node_lock, flags); list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { @@ -8788,12 +8890,12 @@ _scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, continue; sas_expander->responding = 1; - if (!encl_pg0_rc) + if (enclosure_dev) { sas_expander->enclosure_logical_id = - le64_to_cpu(enclosure_pg0.EnclosureLogicalID); - - sas_expander->enclosure_handle = - le16_to_cpu(expander_pg0->EnclosureHandle); + le64_to_cpu(enclosure_dev->pg0.EnclosureLogicalID); + sas_expander->enclosure_handle = + le16_to_cpu(expander_pg0->EnclosureHandle); + } if (sas_expander->handle == handle) goto out; @@ -9315,6 +9417,7 @@ mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase) if ((!ioc->is_driver_loading) && !(disable_discovery > 0 && !ioc->sas_hba.num_phys)) { _scsih_prep_device_scan(ioc); + _scsih_create_enclosure_list_after_reset(ioc); _scsih_search_responding_sas_devices(ioc); _scsih_search_responding_pcie_devices(ioc); _scsih_search_responding_raid_devices(ioc); @@ -10546,6 +10649,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) INIT_LIST_HEAD(&ioc->sas_device_list); INIT_LIST_HEAD(&ioc->sas_device_init_list); INIT_LIST_HEAD(&ioc->sas_expander_list); + INIT_LIST_HEAD(&ioc->enclosure_list); INIT_LIST_HEAD(&ioc->pcie_device_list); INIT_LIST_HEAD(&ioc->pcie_device_init_list); INIT_LIST_HEAD(&ioc->fw_event_list); -- cgit v1.2.3 From c1a6c5ac4278d406c112cc2f038e6e506feadff9 Mon Sep 17 00:00:00 2001 From: Chaitra P B Date: Tue, 24 Apr 2018 05:28:41 -0400 Subject: scsi: mpt3sas: For NVME device, issue a protocol level reset 1) Manufacturing Page 11 contains parameters to control internal firmware behavior. Based on AddlFlags2 field FW/Driver behaviour can be changed, (flag tm_custom_handling is used for this) a) For PCIe device, protocol level reset should be used if flag tm_custom_handling is 0. Since Abort Task Set, LUN reset and Target reset will result in a protocol level reset. Drivers should issue only one type of this reset, if that fails then it should escalate to a controller reset (diag reset/OCR). b) If the driver has control over the TM reset timeout value, then driver should use the value exposed in PCIe Device Page 2 for pcie device (field ControllerResetTO). Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 13 ++++++ drivers/scsi/mpt3sas/mpt3sas_base.h | 26 ++++++++++-- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 22 +++++++++-- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 76 ++++++++++++++++++++++++++++++------ 4 files changed, 116 insertions(+), 21 deletions(-) (limited to 'drivers/scsi/mpt3sas/mpt3sas_scsih.c') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 270b39f60c6d..bf04fa90f433 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -4142,6 +4142,7 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) Mpi2ConfigReply_t mpi_reply; u32 iounit_pg1_flags; + ioc->nvme_abort_timeout = 30; mpt3sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0); if (ioc->ir_firmware) mpt3sas_config_get_manufacturing_pg10(ioc, &mpi_reply, @@ -4160,6 +4161,18 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) mpt3sas_config_set_manufacturing_pg11(ioc, &mpi_reply, &ioc->manu_pg11); } + if (ioc->manu_pg11.AddlFlags2 & NVME_TASK_MNGT_CUSTOM_MASK) + ioc->tm_custom_handling = 1; + else { + ioc->tm_custom_handling = 0; + if (ioc->manu_pg11.NVMeAbortTO < NVME_TASK_ABORT_MIN_TIMEOUT) + ioc->nvme_abort_timeout = NVME_TASK_ABORT_MIN_TIMEOUT; + else if (ioc->manu_pg11.NVMeAbortTO > + NVME_TASK_ABORT_MAX_TIMEOUT) + ioc->nvme_abort_timeout = NVME_TASK_ABORT_MAX_TIMEOUT; + else + ioc->nvme_abort_timeout = ioc->manu_pg11.NVMeAbortTO; + } mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2); mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3); diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 0eceebbdc5d5..7a9f0ac30359 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -146,8 +146,12 @@ #define NVME_CMD_PRP1_OFFSET 24 /* PRP1 offset in NVMe cmd */ #define NVME_CMD_PRP2_OFFSET 32 /* PRP2 offset in NVMe cmd */ #define NVME_ERROR_RESPONSE_SIZE 16 /* Max NVME Error Response */ +#define NVME_TASK_ABORT_MIN_TIMEOUT 6 +#define NVME_TASK_ABORT_MAX_TIMEOUT 60 +#define NVME_TASK_MNGT_CUSTOM_MASK (0x0010) #define NVME_PRP_PAGE_SIZE 4096 /* Page size */ + /* * reset phases */ @@ -363,7 +367,15 @@ struct Mpi2ManufacturingPage11_t { u8 EEDPTagMode; /* 09h */ u8 Reserved3; /* 0Ah */ u8 Reserved4; /* 0Bh */ - __le32 Reserved5[23]; /* 0Ch-60h*/ + __le32 Reserved5[8]; /* 0Ch-2Ch */ + u16 AddlFlags2; /* 2Ch */ + u8 AddlFlags3; /* 2Eh */ + u8 Reserved6; /* 2Fh */ + __le32 Reserved7[7]; /* 30h - 4Bh */ + u8 NVMeAbortTO; /* 4Ch */ + u8 Reserved8; /* 4Dh */ + u16 Reserved9; /* 4Eh */ + __le32 Reserved10[4]; /* 50h - 60h */ }; /** @@ -573,6 +585,7 @@ struct _pcie_device { u8 enclosure_level; u8 connector_name[4]; u8 *serial_number; + u8 reset_timeout; struct kref refcount; }; /** @@ -1211,6 +1224,10 @@ struct MPT3SAS_ADAPTER { void *event_log; u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; + u8 tm_custom_handling; + u8 nvme_abort_timeout; + + /* static config pages */ struct mpt3sas_facts facts; struct mpt3sas_port_facts *pfacts; @@ -1473,10 +1490,11 @@ u8 mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply); void mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase); -int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout); +int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, u64 lun, + u8 type, u16 smid_task, u16 msix_task, u8 timeout, u8 tr_method); int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout); + u64 lun, u8 type, u16 smid_task, u16 msix_task, + u8 timeout, u8 tr_method); void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index c1b17d64c95f..3269ef43f07e 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -644,9 +644,10 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, MPI2RequestHeader_t *mpi_request = NULL, *request; MPI2DefaultReply_t *mpi_reply; Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request = NULL; + struct _pcie_device *pcie_device = NULL; u32 ioc_state; u16 smid; - unsigned long timeout; + u8 timeout; u8 issue_reset; u32 sz, sz_arg; void *psge; @@ -659,6 +660,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, long ret; u16 wait_state_count; u16 device_handle = MPT3SAS_INVALID_DEVICE_HANDLE; + u8 tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE; issue_reset = 0; @@ -1074,14 +1076,26 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, ioc->name, le16_to_cpu(mpi_request->FunctionDependent1)); mpt3sas_halt_firmware(ioc); - mpt3sas_scsih_issue_locked_tm(ioc, - le16_to_cpu(mpi_request->FunctionDependent1), 0, - MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 0, 30); + pcie_device = mpt3sas_get_pdev_by_handle(ioc, + le16_to_cpu(mpi_request->FunctionDependent1)); + if (pcie_device && (!ioc->tm_custom_handling)) + mpt3sas_scsih_issue_locked_tm(ioc, + le16_to_cpu(mpi_request->FunctionDependent1), + 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, + 0, pcie_device->reset_timeout, + tr_method); + else + mpt3sas_scsih_issue_locked_tm(ioc, + le16_to_cpu(mpi_request->FunctionDependent1), + 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, + 0, 30, MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET); } else mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); } out: + if (pcie_device) + pcie_device_put(pcie_device); /* free memory associated with sg buffers */ if (data_in) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 27cc2e827472..3dd70de58132 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -1088,7 +1088,7 @@ _scsih_pcie_device_remove(struct MPT3SAS_ADAPTER *ioc, pcie_device->slot); if (pcie_device->connector_name[0] != '\0') pr_info(MPT3SAS_FMT - "removing enclosure level(0x%04x), connector name( %s)\n", + "removing enclosure level(0x%04x), connector name( %s)\n", ioc->name, pcie_device->enclosure_level, pcie_device->connector_name); @@ -2632,6 +2632,7 @@ mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) * @smid_task: smid assigned to the task * @msix_task: MSIX table index supplied by the OS * @timeout: timeout in seconds + * @tr_method: Target Reset Method * Context: user * * A generic API for sending task management requests to firmware. @@ -2642,8 +2643,8 @@ mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) * Return SUCCESS or FAILED. */ int -mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout) +mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, u64 lun, + u8 type, u16 smid_task, u16 msix_task, u8 timeout, u8 tr_method) { Mpi2SCSITaskManagementRequest_t *mpi_request; Mpi2SCSITaskManagementReply_t *mpi_reply; @@ -2689,8 +2690,8 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, } dtmprintk(ioc, pr_info(MPT3SAS_FMT - "sending tm: handle(0x%04x), task_type(0x%02x), smid(%d)\n", - ioc->name, handle, type, smid_task)); + "sending tm: handle(0x%04x), task_type(0x%02x), smid(%d), timeout(%d), tr_method(0x%x)\n", + ioc->name, handle, type, smid_task, timeout, tr_method)); ioc->tm_cmds.status = MPT3_CMD_PENDING; mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); ioc->tm_cmds.smid = smid; @@ -2699,6 +2700,7 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; mpi_request->DevHandle = cpu_to_le16(handle); mpi_request->TaskType = type; + mpi_request->MsgFlags = tr_method; mpi_request->TaskMID = cpu_to_le16(smid_task); int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN); mpt3sas_scsih_set_tm_flag(ioc, handle); @@ -2745,13 +2747,14 @@ out: } int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout) + u64 lun, u8 type, u16 smid_task, u16 msix_task, + u8 timeout, u8 tr_method) { int ret; mutex_lock(&ioc->tm_cmds.mutex); ret = mpt3sas_scsih_issue_tm(ioc, handle, lun, type, smid_task, - msix_task, timeout); + msix_task, timeout, tr_method); mutex_unlock(&ioc->tm_cmds.mutex); return ret; @@ -2854,6 +2857,8 @@ scsih_abort(struct scsi_cmnd *scmd) u16 handle; int r; + u8 timeout = 30; + struct _pcie_device *pcie_device = NULL; sdev_printk(KERN_INFO, scmd->device, "attempting task abort! scmd(%p)\n", scmd); _scsih_tm_display_info(ioc, scmd); @@ -2888,15 +2893,20 @@ scsih_abort(struct scsi_cmnd *scmd) mpt3sas_halt_firmware(ioc); handle = sas_device_priv_data->sas_target->handle; + pcie_device = mpt3sas_get_pdev_by_handle(ioc, handle); + if (pcie_device && (!ioc->tm_custom_handling)) + timeout = ioc->nvme_abort_timeout; r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, - st->smid, st->msix_io, 30); + st->smid, st->msix_io, timeout, 0); /* Command must be cleared after abort */ if (r == SUCCESS && st->cb_idx != 0xFF) r = FAILED; out: sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n", ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); + if (pcie_device) + pcie_device_put(pcie_device); return r; } @@ -2912,7 +2922,10 @@ scsih_dev_reset(struct scsi_cmnd *scmd) struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); struct MPT3SAS_DEVICE *sas_device_priv_data; struct _sas_device *sas_device = NULL; + struct _pcie_device *pcie_device = NULL; u16 handle; + u8 tr_method = 0; + u8 tr_timeout = 30; int r; struct scsi_target *starget = scmd->device->sdev_target; @@ -2950,8 +2963,16 @@ scsih_dev_reset(struct scsi_cmnd *scmd) goto out; } + pcie_device = mpt3sas_get_pdev_by_handle(ioc, handle); + + if (pcie_device && (!ioc->tm_custom_handling)) { + tr_timeout = pcie_device->reset_timeout; + tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE; + } else + tr_method = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->lun, - MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 0, 30); + MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 0, + tr_timeout, tr_method); /* Check for busy commands after reset */ if (r == SUCCESS && atomic_read(&scmd->device->device_busy)) r = FAILED; @@ -2961,6 +2982,8 @@ scsih_dev_reset(struct scsi_cmnd *scmd) if (sas_device) sas_device_put(sas_device); + if (pcie_device) + pcie_device_put(pcie_device); return r; } @@ -2977,7 +3000,10 @@ scsih_target_reset(struct scsi_cmnd *scmd) struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); struct MPT3SAS_DEVICE *sas_device_priv_data; struct _sas_device *sas_device = NULL; + struct _pcie_device *pcie_device = NULL; u16 handle; + u8 tr_method = 0; + u8 tr_timeout = 30; int r; struct scsi_target *starget = scmd->device->sdev_target; struct MPT3SAS_TARGET *target_priv_data = starget->hostdata; @@ -3014,8 +3040,16 @@ scsih_target_reset(struct scsi_cmnd *scmd) goto out; } + pcie_device = mpt3sas_get_pdev_by_handle(ioc, handle); + + if (pcie_device && (!ioc->tm_custom_handling)) { + tr_timeout = pcie_device->reset_timeout; + tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE; + } else + tr_method = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; r = mpt3sas_scsih_issue_locked_tm(ioc, handle, 0, - MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 0, 30); + MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 0, + tr_timeout, tr_method); /* Check for busy commands after reset */ if (r == SUCCESS && atomic_read(&starget->target_busy)) r = FAILED; @@ -3025,7 +3059,8 @@ scsih_target_reset(struct scsi_cmnd *scmd) if (sas_device) sas_device_put(sas_device); - + if (pcie_device) + pcie_device_put(pcie_device); return r; } @@ -3559,6 +3594,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) unsigned long flags; struct _tr_list *delayed_tr; u32 ioc_state; + u8 tr_method = 0; if (ioc->pci_error_recovery) { dewtprintk(ioc, pr_info(MPT3SAS_FMT @@ -3601,6 +3637,11 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) sas_address = pcie_device->wwid; } spin_unlock_irqrestore(&ioc->pcie_device_lock, flags); + if (pcie_device && (!ioc->tm_custom_handling)) + tr_method = + MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE; + else + tr_method = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; } if (sas_target_priv_data) { dewtprintk(ioc, pr_info(MPT3SAS_FMT @@ -3664,6 +3705,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; mpi_request->DevHandle = cpu_to_le16(handle); mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; + mpi_request->MsgFlags = tr_method; set_bit(handle, ioc->device_remove_in_progress); mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL); @@ -6938,6 +6980,11 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) } pcie_device->nvme_mdts = le32_to_cpu(pcie_device_pg2.MaximumDataTransferSize); + if (pcie_device_pg2.ControllerResetTO) + pcie_device->reset_timeout = + pcie_device_pg2.ControllerResetTO; + else + pcie_device->reset_timeout = 30; if (ioc->wait_for_discovery_to_complete) _scsih_pcie_device_init_add(ioc, pcie_device); @@ -7190,6 +7237,9 @@ _scsih_pcie_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc, case MPI26_EVENT_PCIDEV_STAT_RC_ASYNC_NOTIFICATION: reason_str = "internal async notification"; break; + case MPI26_EVENT_PCIDEV_STAT_RC_PCIE_HOT_RESET_FAILED: + reason_str = "pcie hot reset failed"; + break; default: reason_str = "unknown reason"; break; @@ -7444,7 +7494,7 @@ _scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc, spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); r = mpt3sas_scsih_issue_tm(ioc, handle, lun, MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, st->smid, - st->msix_io, 30); + st->msix_io, 30, 0); if (r == FAILED) { sdev_printk(KERN_WARNING, sdev, "mpt3sas_scsih_issue_tm: FAILED when sending " @@ -7485,7 +7535,7 @@ _scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc, r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, st->smid, - st->msix_io, 30); + st->msix_io, 30, 0); if (r == FAILED || st->cb_idx != 0xFF) { sdev_printk(KERN_WARNING, sdev, "mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : " -- cgit v1.2.3 From 87b3576e9eaba85644c643bb55b485b5330a2af5 Mon Sep 17 00:00:00 2001 From: Chaitra P B Date: Tue, 24 Apr 2018 05:28:42 -0400 Subject: scsi: mpt3sas: fix possible memory leak. In ioctl exit path driver refers ioc_list to free memory associated with diag buffers and event_log pointer used to save events by driver. If ctl_exit() func is called after unregistering driver, then ioc_list will be empty and hence driver will not be able to free the allocated memory which in turn causes memory leak. So call ctl_exit() function before unregistering mpt3sas driver. Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/mpt3sas/mpt3sas_scsih.c') diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 3dd70de58132..b8d131a455d0 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -11287,10 +11287,10 @@ _mpt3sas_exit(void) pr_info("mpt3sas version %s unloading\n", MPT3SAS_DRIVER_VERSION); - pci_unregister_driver(&mpt3sas_driver); - mpt3sas_ctl_exit(hbas_to_enumerate); + pci_unregister_driver(&mpt3sas_driver); + scsih_exit(); } -- cgit v1.2.3