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;  }  | 
