diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-10 22:01:12 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-10 22:01:12 +0200 |
commit | 5f85942c2ea2ed59d8f19c954bbb0f5c1a2ebdd1 (patch) | |
tree | ffd0c606829178dd0be28c557685203f760438d8 /drivers/scsi/mpt3sas/mpt3sas_scsih.c | |
parent | Merge tag '4.18-fixes-smb3' of git://git.samba.org/sfrench/cifs-2.6 (diff) | |
parent | scsi: lpfc: update driver version to 12.0.0.4 (diff) | |
download | linux-5f85942c2ea2ed59d8f19c954bbb0f5c1a2ebdd1.tar.xz linux-5f85942c2ea2ed59d8f19c954bbb0f5c1a2ebdd1.zip |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This is mostly updates to the usual drivers: ufs, qedf, mpt3sas, lpfc,
xfcp, hisi_sas, cxlflash, qla2xxx.
In the absence of Nic, we're also taking target updates which are
mostly minor except for the tcmu refactor.
The only real core change to worry about is the removal of high page
bouncing (in sas, storvsc and iscsi). This has been well tested and no
problems have shown up so far"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (268 commits)
scsi: lpfc: update driver version to 12.0.0.4
scsi: lpfc: Fix port initialization failure.
scsi: lpfc: Fix 16gb hbas failing cq create.
scsi: lpfc: Fix crash in blk_mq layer when executing modprobe -r lpfc
scsi: lpfc: correct oversubscription of nvme io requests for an adapter
scsi: lpfc: Fix MDS diagnostics failure (Rx < Tx)
scsi: hisi_sas: Mark PHY as in reset for nexus reset
scsi: hisi_sas: Fix return value when get_free_slot() failed
scsi: hisi_sas: Terminate STP reject quickly for v2 hw
scsi: hisi_sas: Add v2 hw force PHY function for internal ATA command
scsi: hisi_sas: Include TMF elements in struct hisi_sas_slot
scsi: hisi_sas: Try wait commands before before controller reset
scsi: hisi_sas: Init disks after controller reset
scsi: hisi_sas: Create a scsi_host_template per HW module
scsi: hisi_sas: Reset disks when discovered
scsi: hisi_sas: Add LED feature for v3 hw
scsi: hisi_sas: Change common allocation mode of device id
scsi: hisi_sas: change slot index allocation mode
scsi: hisi_sas: Introduce hisi_sas_phy_set_linkrate()
scsi: hisi_sas: fix a typo in hisi_sas_task_prep()
...
Diffstat (limited to 'drivers/scsi/mpt3sas/mpt3sas_scsih.c')
-rw-r--r-- | drivers/scsi/mpt3sas/mpt3sas_scsih.c | 491 |
1 files changed, 339 insertions, 152 deletions
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 8cd3782fab49..b8d131a455d0 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; /** @@ -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); @@ -1362,6 +1362,30 @@ mpt3sas_scsih_expander_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) } /** + * 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 * @sas_address: sas address @@ -2608,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. @@ -2618,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; @@ -2665,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; @@ -2675,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); @@ -2721,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; @@ -2830,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); @@ -2864,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; } @@ -2888,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; @@ -2926,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; @@ -2937,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; } @@ -2953,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; @@ -2990,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; @@ -3001,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; } @@ -3535,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 @@ -3577,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 @@ -3640,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); @@ -3680,11 +3746,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)); @@ -3725,7 +3787,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", @@ -3806,8 +3868,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 +3921,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)); @@ -3903,8 +3963,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 +4039,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); } @@ -5618,10 +5678,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; @@ -5743,11 +5803,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); @@ -5891,52 +5952,6 @@ _scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, } /** - * _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 * @parent_sas_address: sas address of parent expander or sas host @@ -5953,6 +5968,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; @@ -6007,8 +6023,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 */ @@ -6055,12 +6084,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))) { @@ -6106,12 +6134,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, - 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); } @@ -6152,18 +6180,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; } } @@ -6845,8 +6871,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; @@ -6917,7 +6943,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], @@ -6928,13 +6954,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)) { @@ -6953,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); @@ -7205,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; @@ -7320,10 +7355,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; + } } /** @@ -7409,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 " @@ -7450,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 : " @@ -7527,6 +7612,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 * @fw_event: The fw_event_work object @@ -8360,12 +8483,23 @@ 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 == 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 +8511,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 +8523,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; @@ -8400,17 +8534,30 @@ 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 == 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; } } @@ -8419,6 +8566,52 @@ Mpi2SasDevicePage0_t *sas_device_pg0) } /** + * _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 * @@ -8449,15 +8642,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 +8675,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 +8712,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 +8770,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: @@ -8736,22 +8923,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) { @@ -8759,12 +8940,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; @@ -9286,6 +9467,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); @@ -9356,6 +9538,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; @@ -9433,8 +9618,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); @@ -9540,6 +9725,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: @@ -10513,6 +10699,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); @@ -11100,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(); } |