diff options
Diffstat (limited to 'drivers/scsi/mpt3sas/mpt3sas_base.c')
-rw-r--r-- | drivers/scsi/mpt3sas/mpt3sas_base.c | 349 |
1 files changed, 229 insertions, 120 deletions
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 5779f313f6f8..c39955239d1c 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -141,7 +141,7 @@ _base_clear_outstanding_commands(struct MPT3SAS_ADAPTER *ioc); * @mpi_request:mf request pointer. * @sz: size of buffer. * - * @Returns - 1/0 Reset to be done or Not + * Return: 1/0 Reset to be done or Not */ u8 mpt3sas_base_check_cmd_timeout(struct MPT3SAS_ADAPTER *ioc, @@ -440,7 +440,7 @@ static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc, return; /* From smid we can get scsi_cmd, once we have sg_scmd, - * we just need to get sg_virt and sg_next to get virual + * we just need to get sg_virt and sg_next to get virtual * address associated with sgel->Address. */ @@ -600,7 +600,7 @@ static int mpt3sas_remove_dead_ioc_func(void *arg) * _base_sync_drv_fw_timestamp - Sync Drive-Fw TimeStamp. * @ioc: Per Adapter Object * - * Return nothing. + * Return: nothing. */ static void _base_sync_drv_fw_timestamp(struct MPT3SAS_ADAPTER *ioc) { @@ -704,7 +704,7 @@ _base_fault_reset_work(struct work_struct *work) /* * Call _scsih_flush_pending_cmds callback so that we flush all - * pending commands back to OS. This call is required to aovid + * pending commands back to OS. This call is required to avoid * deadlock at block layer. Dead IOC will fail to do diag reset, * and this call is safe since dead ioc will never return any * command back from HW. @@ -873,7 +873,7 @@ mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc , u16 fault_code) * @ioc: per adapter object * @fault_code: fault code * - * Return nothing. + * Return: nothing. */ void mpt3sas_base_coredump_info(struct MPT3SAS_ADAPTER *ioc, u16 fault_code) @@ -887,7 +887,7 @@ mpt3sas_base_coredump_info(struct MPT3SAS_ADAPTER *ioc, u16 fault_code) * @ioc: per adapter object * @caller: caller function name * - * Returns 0 for success, non-zero for failure. + * Return: 0 for success, non-zero for failure. */ int mpt3sas_base_wait_for_coredump_completion(struct MPT3SAS_ADAPTER *ioc, @@ -1359,11 +1359,11 @@ _base_sas_log_info(struct MPT3SAS_ADAPTER *ioc , u32 log_info) } /** - * _base_display_reply_info - + * _base_display_reply_info - handle reply descriptors depending on IOC Status * @ioc: per adapter object * @smid: system request message index * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) + * @reply: reply message frame (lower 32bit addr) */ static void _base_display_reply_info(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, @@ -1804,7 +1804,7 @@ _base_interrupt(int irq, void *bus_id) * @irqpoll: irq_poll object * @budget: irq poll weight * - * returns number of reply descriptors processed + * Return: number of reply descriptors processed */ static int _base_irqpoll(struct irq_poll *irqpoll, int budget) @@ -1826,7 +1826,7 @@ _base_irqpoll(struct irq_poll *irqpoll, int budget) enable_irq(reply_q->os_irq); /* * Go for one more round of processing the - * reply descriptor post queue incase if HBA + * reply descriptor post queue in case the HBA * Firmware has posted some reply descriptors * while reenabling the IRQ. */ @@ -1840,7 +1840,7 @@ _base_irqpoll(struct irq_poll *irqpoll, int budget) * _base_init_irqpolls - initliaze IRQ polls * @ioc: per adapter object * - * returns nothing + * Return: nothing */ static void _base_init_irqpolls(struct MPT3SAS_ADAPTER *ioc) @@ -1878,7 +1878,7 @@ _base_is_controller_msix_enabled(struct MPT3SAS_ADAPTER *ioc) * @ioc: per adapter object * @poll: poll over reply descriptor pools incase interrupt for * timed-out SCSI command got delayed - * Context: non ISR conext + * Context: non-ISR context * * Called when a Task Management request has completed. */ @@ -2104,7 +2104,16 @@ _base_build_sg(struct MPT3SAS_ADAPTER *ioc, void *psge, /** * _base_build_nvme_prp - This function is called for NVMe end devices to build - * a native SGL (NVMe PRP). The native SGL is built starting in the first PRP + * a native SGL (NVMe PRP). + * @ioc: per adapter object + * @smid: system request message index for getting asscociated SGL + * @nvme_encap_request: the NVMe request msg frame pointer + * @data_out_dma: physical address for WRITES + * @data_out_sz: data xfer size for WRITES + * @data_in_dma: physical address for READS + * @data_in_sz: data xfer size for READS + * + * The native SGL is built starting in the first PRP * entry of the NVMe message (PRP1). If the data buffer is small enough to be * described entirely using PRP1, then PRP2 is not used. If needed, PRP2 is * used to describe a larger data buffer. If the data buffer is too large to @@ -2133,7 +2142,7 @@ _base_build_sg(struct MPT3SAS_ADAPTER *ioc, void *psge, * Each 64-bit PRP entry comprises an address and an offset field. The address * always points at the beginning of a 4KB physical memory page, and the offset * describes where within that 4KB page the memory segment begins. Only the - * first element in a PRP list may contain a non-zero offest, implying that all + * first element in a PRP list may contain a non-zero offset, implying that all * memory segments following the first begin at the start of a 4KB page. * * Each PRP element normally describes 4KB of physical memory, with exceptions @@ -2147,14 +2156,6 @@ _base_build_sg(struct MPT3SAS_ADAPTER *ioc, void *psge, * Since PRP entries lack any indication of size, the overall data buffer length * is used to determine where the end of the data memory buffer is located, and * how many PRP entries are required to describe it. - * - * @ioc: per adapter object - * @smid: system request message index for getting asscociated SGL - * @nvme_encap_request: the NVMe request msg frame pointer - * @data_out_dma: physical address for WRITES - * @data_out_sz: data xfer size for WRITES - * @data_in_dma: physical address for READS - * @data_in_sz: data xfer size for READS */ static void _base_build_nvme_prp(struct MPT3SAS_ADAPTER *ioc, u16 smid, @@ -2311,8 +2312,8 @@ _base_build_nvme_prp(struct MPT3SAS_ADAPTER *ioc, u16 smid, } /** - * base_make_prp_nvme - - * Prepare PRPs(Physical Region Page)- SGLs specific to NVMe drives only + * base_make_prp_nvme - Prepare PRPs (Physical Region Page) - + * SGLs specific to NVMe drives only * * @ioc: per adapter object * @scmd: SCSI command from the mid-layer @@ -3155,7 +3156,7 @@ fall_back: * - loaded driver with default max_msix_vectors module parameter and * - system booted in non kdump mode * - * returns nothing. + * Return: nothing. */ static void _base_check_and_enable_high_iops_queues(struct MPT3SAS_ADAPTER *ioc, @@ -3364,14 +3365,14 @@ static int _base_diag_reset(struct MPT3SAS_ADAPTER *ioc); /** - * _base_check_for_fault_and_issue_reset - check if IOC is in fault state + * mpt3sas_base_check_for_fault_and_issue_reset - check if IOC is in fault state * and if it is in fault state then issue diag reset. * @ioc: per adapter object * - * Returns: 0 for success, non-zero for failure. + * Return: 0 for success, non-zero for failure. */ -static int -_base_check_for_fault_and_issue_reset(struct MPT3SAS_ADAPTER *ioc) +int +mpt3sas_base_check_for_fault_and_issue_reset(struct MPT3SAS_ADAPTER *ioc) { u32 ioc_state; int rc = -EFAULT; @@ -3385,12 +3386,14 @@ _base_check_for_fault_and_issue_reset(struct MPT3SAS_ADAPTER *ioc) if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { mpt3sas_print_fault_code(ioc, ioc_state & MPI2_DOORBELL_DATA_MASK); + mpt3sas_base_mask_interrupts(ioc); rc = _base_diag_reset(ioc); } else if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_COREDUMP) { mpt3sas_print_coredump_info(ioc, ioc_state & MPI2_DOORBELL_DATA_MASK); mpt3sas_base_wait_for_coredump_completion(ioc, __func__); + mpt3sas_base_mask_interrupts(ioc); rc = _base_diag_reset(ioc); } @@ -3472,7 +3475,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) r = _base_get_ioc_facts(ioc); if (r) { - rc = _base_check_for_fault_and_issue_reset(ioc); + rc = mpt3sas_base_check_for_fault_and_issue_reset(ioc); if (rc || (_base_get_ioc_facts(ioc))) goto out_fail; } @@ -3633,7 +3636,7 @@ mpt3sas_base_get_reply_virt_addr(struct MPT3SAS_ADAPTER *ioc, u32 phys_addr) * @ioc: per adapter object * @scmd: scsi_cmnd object * - * returns msix index of general reply queues, + * Return: msix index of general reply queues, * i.e. reply queue on which IO request's reply * should be posted by the HBA firmware. */ @@ -3663,7 +3666,7 @@ _base_get_msix_index(struct MPT3SAS_ADAPTER *ioc, * @ioc: per adapter object * @scmd: scsi_cmnd object * - * Returns: msix index of high iops reply queues. + * Return: msix index of high iops reply queues. * i.e. high iops reply queue on which IO request's * reply should be posted by the HBA firmware. */ @@ -3910,7 +3913,7 @@ _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock) * @ioc: per adapter object * @smid: system request message index * - * returns msix index. + * Return: msix index. */ static u8 _base_set_and_get_msix_index(struct MPT3SAS_ADAPTER *ioc, u16 smid) @@ -4005,7 +4008,7 @@ _base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, * _base_put_smid_hi_priority - send Task Management request to firmware * @ioc: per adapter object * @smid: system request message index - * @msix_task: msix_task will be same as msix of IO incase of task abort else 0. + * @msix_task: msix_task will be same as msix of IO in case of task abort else 0 */ static void _base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, @@ -4109,7 +4112,7 @@ _base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid) * @smid: system request message index * @handle: device handle, unused in this function, for function type match * - * Return nothing. + * Return: nothing. */ static void _base_put_smid_scsi_io_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, @@ -4131,7 +4134,7 @@ _base_put_smid_scsi_io_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, * @ioc: per adapter object * @smid: system request message index * @handle: device handle, unused in this function, for function type match - * Return nothing + * Return: nothing */ static void _base_put_smid_fast_path_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, @@ -4152,9 +4155,9 @@ _base_put_smid_fast_path_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, * firmware using Atomic Request Descriptor * @ioc: per adapter object * @smid: system request message index - * @msix_task: msix_task will be same as msix of IO incase of task abort else 0 + * @msix_task: msix_task will be same as msix of IO in case of task abort else 0 * - * Return nothing. + * Return: nothing. */ static void _base_put_smid_hi_priority_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, @@ -4176,7 +4179,7 @@ _base_put_smid_hi_priority_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, * @ioc: per adapter object * @smid: system request message index * - * Return nothing. + * Return: nothing. */ static void _base_put_smid_default_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid) @@ -4434,6 +4437,7 @@ _base_display_OEMs_branding(struct MPT3SAS_ADAPTER *ioc) ioc->pdev->subsystem_device); break; } + break; default: break; } @@ -4453,7 +4457,7 @@ _base_display_fwpkg_version(struct MPT3SAS_ADAPTER *ioc) Mpi26ComponentImageHeader_t *cmp_img_hdr; Mpi25FWUploadRequest_t *mpi_request; Mpi2FWUploadReply_t mpi_reply; - int r = 0; + int r = 0, issue_diag_reset = 0; u32 package_version = 0; void *fwpkg_data = NULL; dma_addr_t fwpkg_data_dma; @@ -4503,7 +4507,7 @@ _base_display_fwpkg_version(struct MPT3SAS_ADAPTER *ioc) ioc_err(ioc, "%s: timeout\n", __func__); _debug_dump_mf(mpi_request, sizeof(Mpi25FWUploadRequest_t)/4); - r = -ETIME; + issue_diag_reset = 1; } else { memset(&mpi_reply, 0, sizeof(Mpi2FWUploadReply_t)); if (ioc->base_cmds.status & MPT3_CMD_REPLY_VALID) { @@ -4543,11 +4547,18 @@ out: if (fwpkg_data) dma_free_coherent(&ioc->pdev->dev, data_length, fwpkg_data, fwpkg_data_dma); + if (issue_diag_reset) { + if (ioc->drv_internal_flags & MPT_DRV_INTERNAL_FIRST_PE_ISSUED) + return -EFAULT; + if (mpt3sas_base_check_for_fault_and_issue_reset(ioc)) + return -EFAULT; + r = -EAGAIN; + } return r; } /** - * _base_display_ioc_capabilities - Disply IOC's capabilities. + * _base_display_ioc_capabilities - Display IOC's capabilities. * @ioc: per adapter object */ static void @@ -4750,15 +4761,19 @@ out: * according to performance mode. * @ioc : per adapter object * - * Return nothing. + * Return: zero on success; otherwise return EAGAIN error code asking the + * caller to retry. */ -static void +static int _base_update_ioc_page1_inlinewith_perf_mode(struct MPT3SAS_ADAPTER *ioc) { Mpi2IOCPage1_t ioc_pg1; Mpi2ConfigReply_t mpi_reply; + int rc; - mpt3sas_config_get_ioc_pg1(ioc, &mpi_reply, &ioc->ioc_pg1_copy); + rc = mpt3sas_config_get_ioc_pg1(ioc, &mpi_reply, &ioc->ioc_pg1_copy); + if (rc) + return rc; memcpy(&ioc_pg1, &ioc->ioc_pg1_copy, sizeof(Mpi2IOCPage1_t)); switch (perf_mode) { @@ -4780,9 +4795,11 @@ _base_update_ioc_page1_inlinewith_perf_mode(struct MPT3SAS_ADAPTER *ioc) */ ioc_pg1.ProductSpecific = cpu_to_le32(0x80000000 | ((1 << MPT3SAS_HIGH_IOPS_REPLY_QUEUES/8) - 1)); - mpt3sas_config_set_ioc_pg1(ioc, &mpi_reply, &ioc_pg1); + rc = mpt3sas_config_set_ioc_pg1(ioc, &mpi_reply, &ioc_pg1); + if (rc) + return rc; ioc_info(ioc, "performance mode: balanced\n"); - return; + return 0; } fallthrough; case MPT_PERF_MODE_LATENCY: @@ -4793,7 +4810,9 @@ _base_update_ioc_page1_inlinewith_perf_mode(struct MPT3SAS_ADAPTER *ioc) ioc_pg1.CoalescingTimeout = cpu_to_le32(0xa); ioc_pg1.Flags |= cpu_to_le32(MPI2_IOCPAGE1_REPLY_COALESCING); ioc_pg1.ProductSpecific = 0; - mpt3sas_config_set_ioc_pg1(ioc, &mpi_reply, &ioc_pg1); + rc = mpt3sas_config_set_ioc_pg1(ioc, &mpi_reply, &ioc_pg1); + if (rc) + return rc; ioc_info(ioc, "performance mode: latency\n"); break; case MPT_PERF_MODE_IOPS: @@ -4805,9 +4824,12 @@ _base_update_ioc_page1_inlinewith_perf_mode(struct MPT3SAS_ADAPTER *ioc) le32_to_cpu(ioc_pg1.CoalescingTimeout)); ioc_pg1.Flags |= cpu_to_le32(MPI2_IOCPAGE1_REPLY_COALESCING); ioc_pg1.ProductSpecific = 0; - mpt3sas_config_set_ioc_pg1(ioc, &mpi_reply, &ioc_pg1); + rc = mpt3sas_config_set_ioc_pg1(ioc, &mpi_reply, &ioc_pg1); + if (rc) + return rc; break; } + return 0; } /** @@ -4815,9 +4837,9 @@ _base_update_ioc_page1_inlinewith_perf_mode(struct MPT3SAS_ADAPTER *ioc) * persistent pages * @ioc : per adapter object * - * Return nothing. + * Return: nothing. */ -static void +static int _base_get_event_diag_triggers(struct MPT3SAS_ADAPTER *ioc) { Mpi26DriverTriggerPage2_t trigger_pg2; @@ -4831,7 +4853,7 @@ _base_get_event_diag_triggers(struct MPT3SAS_ADAPTER *ioc) r = mpt3sas_config_get_driver_trigger_pg2(ioc, &mpi_reply, &trigger_pg2); if (r) - return; + return r; ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; @@ -4840,7 +4862,7 @@ _base_get_event_diag_triggers(struct MPT3SAS_ADAPTER *ioc) ioc_err(ioc, "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n", __func__, ioc_status)); - return; + return 0; } if (le16_to_cpu(trigger_pg2.NumMPIEventTrigger)) { @@ -4859,6 +4881,7 @@ _base_get_event_diag_triggers(struct MPT3SAS_ADAPTER *ioc) mpi_event_tg++; } } + return 0; } /** @@ -4866,9 +4889,9 @@ _base_get_event_diag_triggers(struct MPT3SAS_ADAPTER *ioc) * persistent pages * @ioc : per adapter object * - * Return nothing. + * Return: 0 on success; otherwise return failure status. */ -static void +static int _base_get_scsi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) { Mpi26DriverTriggerPage3_t trigger_pg3; @@ -4882,7 +4905,7 @@ _base_get_scsi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) r = mpt3sas_config_get_driver_trigger_pg3(ioc, &mpi_reply, &trigger_pg3); if (r) - return; + return r; ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; @@ -4891,7 +4914,7 @@ _base_get_scsi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) ioc_err(ioc, "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n", __func__, ioc_status)); - return; + return 0; } if (le16_to_cpu(trigger_pg3.NumSCSISenseTrigger)) { @@ -4910,6 +4933,7 @@ _base_get_scsi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) mpi_scsi_tg++; } } + return 0; } /** @@ -4917,9 +4941,9 @@ _base_get_scsi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) * persistent pages * @ioc : per adapter object * - * Return nothing. + * Return: 0 on success; otherwise return failure status. */ -static void +static int _base_get_mpi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) { Mpi26DriverTriggerPage4_t trigger_pg4; @@ -4933,7 +4957,7 @@ _base_get_mpi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) r = mpt3sas_config_get_driver_trigger_pg4(ioc, &mpi_reply, &trigger_pg4); if (r) - return; + return r; ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; @@ -4942,7 +4966,7 @@ _base_get_mpi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) ioc_err(ioc, "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n", __func__, ioc_status)); - return; + return 0; } if (le16_to_cpu(trigger_pg4.NumIOCStatusLogInfoTrigger)) { @@ -4963,6 +4987,7 @@ _base_get_mpi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) mpi_status_tg++; } } + return 0; } /** @@ -4970,9 +4995,9 @@ _base_get_mpi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) * persistent pages * @ioc : per adapter object * - * Return nothing. + * Return: nothing. */ -static void +static int _base_get_master_diag_triggers(struct MPT3SAS_ADAPTER *ioc) { Mpi26DriverTriggerPage1_t trigger_pg1; @@ -4983,7 +5008,7 @@ _base_get_master_diag_triggers(struct MPT3SAS_ADAPTER *ioc) r = mpt3sas_config_get_driver_trigger_pg1(ioc, &mpi_reply, &trigger_pg1); if (r) - return; + return r; ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; @@ -4992,25 +5017,30 @@ _base_get_master_diag_triggers(struct MPT3SAS_ADAPTER *ioc) ioc_err(ioc, "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n", __func__, ioc_status)); - return; + return 0; } if (le16_to_cpu(trigger_pg1.NumMasterTrigger)) ioc->diag_trigger_master.MasterData |= le32_to_cpu( trigger_pg1.MasterTriggers[0].MasterTriggerFlags); + return 0; } /** * _base_check_for_trigger_pages_support - checks whether HBA FW supports * driver trigger pages or not * @ioc : per adapter object + * @trigger_flags : address where trigger page0's TriggerFlags value is copied + * + * Return: trigger flags mask if HBA FW supports driver trigger pages; + * otherwise returns %-EFAULT if driver trigger pages are not supported by FW or + * return EAGAIN if diag reset occurred due to FW fault and asking the + * caller to retry the command. * - * Returns trigger flags mask if HBA FW supports driver trigger pages, - * otherwise returns EFAULT. */ static int -_base_check_for_trigger_pages_support(struct MPT3SAS_ADAPTER *ioc) +_base_check_for_trigger_pages_support(struct MPT3SAS_ADAPTER *ioc, u32 *trigger_flags) { Mpi26DriverTriggerPage0_t trigger_pg0; int r = 0; @@ -5020,14 +5050,15 @@ _base_check_for_trigger_pages_support(struct MPT3SAS_ADAPTER *ioc) r = mpt3sas_config_get_driver_trigger_pg0(ioc, &mpi_reply, &trigger_pg0); if (r) - return -EFAULT; + return r; ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; if (ioc_status != MPI2_IOCSTATUS_SUCCESS) return -EFAULT; - return le16_to_cpu(trigger_pg0.TriggerFlags); + *trigger_flags = le16_to_cpu(trigger_pg0.TriggerFlags); + return 0; } /** @@ -5035,12 +5066,14 @@ _base_check_for_trigger_pages_support(struct MPT3SAS_ADAPTER *ioc) * persistent pages. * @ioc : per adapter object * - * Return nothing. + * Return: zero on success; otherwise return EAGAIN error codes + * asking the caller to retry. */ -static void +static int _base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc) { int trigger_flags; + int r; /* * Default setting of master trigger. @@ -5048,9 +5081,16 @@ _base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc) ioc->diag_trigger_master.MasterData = (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET); - trigger_flags = _base_check_for_trigger_pages_support(ioc); - if (trigger_flags < 0) - return; + r = _base_check_for_trigger_pages_support(ioc, &trigger_flags); + if (r) { + if (r == -EAGAIN) + return r; + /* + * Don't go for error handling when FW doesn't support + * driver trigger pages. + */ + return 0; + } ioc->supports_trigger_pages = 1; @@ -5059,40 +5099,53 @@ _base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc) * if master trigger bit enabled in TriggerFlags. */ if ((u16)trigger_flags & - MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID) - _base_get_master_diag_triggers(ioc); + MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID) { + r = _base_get_master_diag_triggers(ioc); + if (r) + return r; + } /* * Retrieve event diag trigger values from driver trigger pg2 * if event trigger bit enabled in TriggerFlags. */ if ((u16)trigger_flags & - MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID) - _base_get_event_diag_triggers(ioc); + MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID) { + r = _base_get_event_diag_triggers(ioc); + if (r) + return r; + } /* * Retrieve scsi diag trigger values from driver trigger pg3 * if scsi trigger bit enabled in TriggerFlags. */ if ((u16)trigger_flags & - MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID) - _base_get_scsi_diag_triggers(ioc); + MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID) { + r = _base_get_scsi_diag_triggers(ioc); + if (r) + return r; + } /* * Retrieve mpi error diag trigger values from driver trigger pg4 * if loginfo trigger bit enabled in TriggerFlags. */ if ((u16)trigger_flags & - MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID) - _base_get_mpi_diag_triggers(ioc); + MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID) { + r = _base_get_mpi_diag_triggers(ioc); + if (r) + return r; + } + return 0; } /** * _base_update_diag_trigger_pages - Update the driver trigger pages after - * online FW update, incase updated FW supports driver + * online FW update, in case updated FW supports driver * trigger pages. * @ioc : per adapter object * - * Return nothing. + * Return: nothing. */ static void _base_update_diag_trigger_pages(struct MPT3SAS_ADAPTER *ioc) @@ -5119,23 +5172,33 @@ _base_update_diag_trigger_pages(struct MPT3SAS_ADAPTER *ioc) * _base_static_config_pages - static start of day config pages * @ioc: per adapter object */ -static void +static int _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) { Mpi2ConfigReply_t mpi_reply; u32 iounit_pg1_flags; int tg_flags = 0; + int rc; 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, - &ioc->manu_pg10); + rc = mpt3sas_config_get_manufacturing_pg0(ioc, &mpi_reply, + &ioc->manu_pg0); + if (rc) + return rc; + if (ioc->ir_firmware) { + rc = mpt3sas_config_get_manufacturing_pg10(ioc, &mpi_reply, + &ioc->manu_pg10); + if (rc) + return rc; + } /* * Ensure correct T10 PI operation if vendor left EEDPTagMode * flag unset in NVDATA. */ - mpt3sas_config_get_manufacturing_pg11(ioc, &mpi_reply, &ioc->manu_pg11); + rc = mpt3sas_config_get_manufacturing_pg11(ioc, &mpi_reply, + &ioc->manu_pg11); + if (rc) + return rc; if (!ioc->is_gen35_ioc && ioc->manu_pg11.EEDPTagMode == 0) { pr_err("%s: overriding NVDATA EEDPTagMode setting\n", ioc->name); @@ -5174,12 +5237,24 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) ioc_warn(ioc, "TimeSync Interval in Manuf page-11 is not enabled. Periodic Time-Sync will be disabled\n"); } - mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2); - mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3); - mpt3sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8); - mpt3sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0); - mpt3sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1); - mpt3sas_config_get_iounit_pg8(ioc, &mpi_reply, &ioc->iounit_pg8); + rc = mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2); + if (rc) + return rc; + rc = mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3); + if (rc) + return rc; + rc = mpt3sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8); + if (rc) + return rc; + rc = mpt3sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0); + if (rc) + return rc; + rc = mpt3sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1); + if (rc) + return rc; + rc = mpt3sas_config_get_iounit_pg8(ioc, &mpi_reply, &ioc->iounit_pg8); + if (rc) + return rc; _base_display_ioc_capabilities(ioc); /* @@ -5195,16 +5270,23 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) iounit_pg1_flags |= MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING; ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags); - mpt3sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1); + rc = mpt3sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1); + if (rc) + return rc; if (ioc->iounit_pg8.NumSensors) ioc->temp_sensors_count = ioc->iounit_pg8.NumSensors; - if (ioc->is_aero_ioc) - _base_update_ioc_page1_inlinewith_perf_mode(ioc); + if (ioc->is_aero_ioc) { + rc = _base_update_ioc_page1_inlinewith_perf_mode(ioc); + if (rc) + return rc; + } if (ioc->is_gen35_ioc) { - if (ioc->is_driver_loading) - _base_get_diag_triggers(ioc); - else { + if (ioc->is_driver_loading) { + rc = _base_get_diag_triggers(ioc); + if (rc) + return rc; + } else { /* * In case of online HBA FW update operation, * check whether updated FW supports the driver trigger @@ -5216,7 +5298,7 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) * and new FW doesn't support them then disable * support_trigger_pages flag. */ - tg_flags = _base_check_for_trigger_pages_support(ioc); + _base_check_for_trigger_pages_support(ioc, &tg_flags); if (!ioc->supports_trigger_pages && tg_flags != -EFAULT) _base_update_diag_trigger_pages(ioc); else if (ioc->supports_trigger_pages && @@ -5224,6 +5306,7 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) ioc->supports_trigger_pages = 0; } } + return 0; } /** @@ -6233,7 +6316,7 @@ _base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout) * _base_dump_reg_set - This function will print hexdump of register set. * @ioc: per adapter object * - * Returns nothing. + * Return: nothing. */ static inline void _base_dump_reg_set(struct MPT3SAS_ADAPTER *ioc) @@ -6467,7 +6550,7 @@ _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout) * * Return: Waits up to timeout seconds for the IOC to * become operational. Returns 0 if IOC is present - * and operational; otherwise returns -EFAULT. + * and operational; otherwise returns %-EFAULT. */ int @@ -6480,6 +6563,17 @@ mpt3sas_wait_for_ioc(struct MPT3SAS_ADAPTER *ioc, int timeout) ioc_state = mpt3sas_base_get_iocstate(ioc, 1); if (ioc_state == MPI2_IOC_STATE_OPERATIONAL) break; + + /* + * Watchdog thread will be started after IOC Initialization, so + * no need to wait here for IOC state to become operational + * when IOC Initialization is on. Instead the driver will + * return ETIME status, so that calling function can issue + * diag reset operation and retry the command. + */ + if (ioc->is_driver_loading) + return -ETIME; + ssleep(1); ioc_info(ioc, "%s: waiting for operational state(count=%d)\n", __func__, ++wait_state_count); @@ -7112,7 +7206,8 @@ mpt3sas_port_enable_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, if (ioc_status != MPI2_IOCSTATUS_SUCCESS) ioc->port_enable_failed = 1; - if (ioc->is_driver_loading) { + if (ioc->port_enable_cmds.status & MPT3_CMD_COMPLETE_ASYNC) { + ioc->port_enable_cmds.status &= ~MPT3_CMD_COMPLETE_ASYNC; if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { mpt3sas_port_enable_complete(ioc); return 1; @@ -7213,8 +7308,9 @@ mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc) ioc_err(ioc, "%s: failed obtaining a smid\n", __func__); return -EAGAIN; } - + ioc->drv_internal_flags |= MPT_DRV_INTERNAL_FIRST_PE_ISSUED; ioc->port_enable_cmds.status = MPT3_CMD_PENDING; + ioc->port_enable_cmds.status |= MPT3_CMD_COMPLETE_ASYNC; mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); ioc->port_enable_cmds.smid = smid; memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); @@ -7311,7 +7407,7 @@ _base_event_notification(struct MPT3SAS_ADAPTER *ioc) Mpi2EventNotificationRequest_t *mpi_request; u16 smid; int r = 0; - int i; + int i, issue_diag_reset = 0; dinitprintk(ioc, ioc_info(ioc, "%s\n", __func__)); @@ -7345,10 +7441,19 @@ _base_event_notification(struct MPT3SAS_ADAPTER *ioc) if (ioc->base_cmds.status & MPT3_CMD_RESET) r = -EFAULT; else - r = -ETIME; + issue_diag_reset = 1; + } else dinitprintk(ioc, ioc_info(ioc, "%s: complete\n", __func__)); ioc->base_cmds.status = MPT3_CMD_NOT_USED; + + if (issue_diag_reset) { + if (ioc->drv_internal_flags & MPT_DRV_INTERNAL_FIRST_PE_ISSUED) + return -EFAULT; + if (mpt3sas_base_check_for_fault_and_issue_reset(ioc)) + return -EFAULT; + r = -EAGAIN; + } return r; } @@ -7712,7 +7817,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc) if (!ioc->is_driver_loading) return r; - rc = _base_check_for_fault_and_issue_reset(ioc); + rc = mpt3sas_base_check_for_fault_and_issue_reset(ioc); if (rc || (_base_send_ioc_init(ioc))) return r; } @@ -7746,12 +7851,15 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc) return r; } - _base_static_config_pages(ioc); + rc = _base_static_config_pages(ioc); + if (r) + return r; + r = _base_event_notification(ioc); if (r) return r; - if (ioc->is_driver_loading) { + if (!ioc->shost_recovery) { if (ioc->is_warpdrive && ioc->manu_pg10.OEMIdentifier == 0x80) { @@ -7851,7 +7959,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) pci_set_drvdata(ioc->pdev, ioc->shost); r = _base_get_ioc_facts(ioc); if (r) { - rc = _base_check_for_fault_and_issue_reset(ioc); + rc = mpt3sas_base_check_for_fault_and_issue_reset(ioc); if (rc || (_base_get_ioc_facts(ioc))) goto out_free_resources; } @@ -7868,7 +7976,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) /* * In SAS3.0, * SCSI_IO, SMP_PASSTHRU, SATA_PASSTHRU, Target Assist, and - * Target Status - all require the IEEE formated scatter gather + * Target Status - all require the IEEE formatted scatter gather * elements. */ ioc->build_sg_scmd = &_base_build_sg_scmd_ieee; @@ -7923,7 +8031,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { r = _base_get_port_facts(ioc, i); if (r) { - rc = _base_check_for_fault_and_issue_reset(ioc); + rc = mpt3sas_base_check_for_fault_and_issue_reset(ioc); if (rc || (_base_get_port_facts(ioc, i))) goto out_free_resources; } @@ -8049,8 +8157,11 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) } } r = _base_make_ioc_operational(ioc); - if (r) - goto out_free_resources; + if (r == -EAGAIN) { + r = _base_make_ioc_operational(ioc); + if (r) + goto out_free_resources; + } /* * Copy current copy of IOCFacts in prev_fw_facts @@ -8168,8 +8279,6 @@ _base_clear_outstanding_mpt_commands(struct MPT3SAS_ADAPTER *ioc) ioc->start_scan_failed = MPI2_IOCSTATUS_INTERNAL_ERROR; ioc->start_scan = 0; - ioc->port_enable_cmds.status = - MPT3_CMD_NOT_USED; } else { complete(&ioc->port_enable_cmds.done); } |