diff options
Diffstat (limited to 'drivers/scsi/mpi3mr/mpi3mr_fw.c')
-rw-r--r-- | drivers/scsi/mpi3mr/mpi3mr_fw.c | 121 |
1 files changed, 53 insertions, 68 deletions
diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index f1ab76351bd8..5ed31fe57474 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -1036,6 +1036,36 @@ static const char *mpi3mr_reset_type_name(u16 reset_type) } /** + * mpi3mr_is_fault_recoverable - Read fault code and decide + * whether the controller can be recoverable + * @mrioc: Adapter instance reference + * Return: true if fault is recoverable, false otherwise. + */ +static inline bool mpi3mr_is_fault_recoverable(struct mpi3mr_ioc *mrioc) +{ + u32 fault; + + fault = (readl(&mrioc->sysif_regs->fault) & + MPI3_SYSIF_FAULT_CODE_MASK); + + switch (fault) { + case MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED: + case MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED: + ioc_warn(mrioc, + "controller requires system power cycle, marking controller as unrecoverable\n"); + return false; + case MPI3_SYSIF_FAULT_CODE_INSUFFICIENT_PCI_SLOT_POWER: + ioc_warn(mrioc, + "controller faulted due to insufficient power,\n" + " try by connecting it to a different slot\n"); + return false; + default: + break; + } + return true; +} + +/** * mpi3mr_print_fault_info - Display fault information * @mrioc: Adapter instance reference * @@ -1373,6 +1403,11 @@ retry_bring_ioc_ready: ioc_info(mrioc, "ioc_status(0x%08x), ioc_config(0x%08x), ioc_info(0x%016llx) at the bringup\n", ioc_status, ioc_config, base_info); + if (!mpi3mr_is_fault_recoverable(mrioc)) { + mrioc->unrecoverable = 1; + goto out_device_not_present; + } + /*The timeout value is in 2sec unit, changing it to seconds*/ mrioc->ready_timeout = ((base_info & MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_MASK) >> @@ -2734,6 +2769,11 @@ static void mpi3mr_watchdog_work(struct work_struct *work) mpi3mr_print_fault_info(mrioc); mrioc->diagsave_timeout = 0; + if (!mpi3mr_is_fault_recoverable(mrioc)) { + mrioc->unrecoverable = 1; + goto schedule_work; + } + switch (trigger_data.fault) { case MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED: case MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED: @@ -4186,17 +4226,6 @@ retry_init: mpi3mr_read_tsu_interval(mrioc); mpi3mr_print_ioc_info(mrioc); - if (!mrioc->cfg_page) { - dprint_init(mrioc, "allocating config page buffers\n"); - mrioc->cfg_page_sz = MPI3MR_DEFAULT_CFG_PAGE_SZ; - mrioc->cfg_page = dma_alloc_coherent(&mrioc->pdev->dev, - mrioc->cfg_page_sz, &mrioc->cfg_page_dma, GFP_KERNEL); - if (!mrioc->cfg_page) { - retval = -1; - goto out_failed_noretry; - } - } - dprint_init(mrioc, "allocating host diag buffers\n"); mpi3mr_alloc_diag_bufs(mrioc); @@ -4768,11 +4797,7 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) mrioc->admin_req_base, mrioc->admin_req_dma); mrioc->admin_req_base = NULL; } - if (mrioc->cfg_page) { - dma_free_coherent(&mrioc->pdev->dev, mrioc->cfg_page_sz, - mrioc->cfg_page, mrioc->cfg_page_dma); - mrioc->cfg_page = NULL; - } + if (mrioc->pel_seqnum_virt) { dma_free_coherent(&mrioc->pdev->dev, mrioc->pel_seqnum_sz, mrioc->pel_seqnum_virt, mrioc->pel_seqnum_dma); @@ -5392,55 +5417,6 @@ out: return retval; } - -/** - * mpi3mr_free_config_dma_memory - free memory for config page - * @mrioc: Adapter instance reference - * @mem_desc: memory descriptor structure - * - * Check whether the size of the buffer specified by the memory - * descriptor is greater than the default page size if so then - * free the memory pointed by the descriptor. - * - * Return: Nothing. - */ -static void mpi3mr_free_config_dma_memory(struct mpi3mr_ioc *mrioc, - struct dma_memory_desc *mem_desc) -{ - if ((mem_desc->size > mrioc->cfg_page_sz) && mem_desc->addr) { - dma_free_coherent(&mrioc->pdev->dev, mem_desc->size, - mem_desc->addr, mem_desc->dma_addr); - mem_desc->addr = NULL; - } -} - -/** - * mpi3mr_alloc_config_dma_memory - Alloc memory for config page - * @mrioc: Adapter instance reference - * @mem_desc: Memory descriptor to hold dma memory info - * - * This function allocates new dmaable memory or provides the - * default config page dmaable memory based on the memory size - * described by the descriptor. - * - * Return: 0 on success, non-zero on failure. - */ -static int mpi3mr_alloc_config_dma_memory(struct mpi3mr_ioc *mrioc, - struct dma_memory_desc *mem_desc) -{ - if (mem_desc->size > mrioc->cfg_page_sz) { - mem_desc->addr = dma_alloc_coherent(&mrioc->pdev->dev, - mem_desc->size, &mem_desc->dma_addr, GFP_KERNEL); - if (!mem_desc->addr) - return -ENOMEM; - } else { - mem_desc->addr = mrioc->cfg_page; - mem_desc->dma_addr = mrioc->cfg_page_dma; - memset(mem_desc->addr, 0, mrioc->cfg_page_sz); - } - return 0; -} - /** * mpi3mr_post_cfg_req - Issue config requests and wait * @mrioc: Adapter instance reference @@ -5596,8 +5572,12 @@ static int mpi3mr_process_cfg_req(struct mpi3mr_ioc *mrioc, cfg_req->page_length = cfg_hdr->page_length; cfg_req->page_version = cfg_hdr->page_version; } - if (mpi3mr_alloc_config_dma_memory(mrioc, &mem_desc)) - goto out; + + mem_desc.addr = dma_alloc_coherent(&mrioc->pdev->dev, + mem_desc.size, &mem_desc.dma_addr, GFP_KERNEL); + + if (!mem_desc.addr) + return retval; mpi3mr_add_sg_single(&cfg_req->sgl, sgl_flags, mem_desc.size, mem_desc.dma_addr); @@ -5626,7 +5606,12 @@ static int mpi3mr_process_cfg_req(struct mpi3mr_ioc *mrioc, } out: - mpi3mr_free_config_dma_memory(mrioc, &mem_desc); + if (mem_desc.addr) { + dma_free_coherent(&mrioc->pdev->dev, mem_desc.size, + mem_desc.addr, mem_desc.dma_addr); + mem_desc.addr = NULL; + } + return retval; } |