diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_base.c')
| -rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 172 | 
1 files changed, 122 insertions, 50 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 0ec1ed389c2..57bcd5c9dcf 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -95,6 +95,10 @@ int mpt2sas_fwfault_debug;  MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "      "and halt firmware - (default=0)"); +static int disable_discovery = -1; +module_param(disable_discovery, int, 0); +MODULE_PARM_DESC(disable_discovery, " disable discovery "); +  /**   * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.   * @@ -1238,7 +1242,7 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)  	u64 pio_chip = 0;  	u64 chip_phys = 0; -	dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", +	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n",  	    ioc->name, __func__));  	ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM); @@ -1307,6 +1311,9 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)  	printk(MPT2SAS_INFO_FMT "ioport(0x%016llx), size(%d)\n",  	    ioc->name, (unsigned long long)pio_chip, pio_sz); +	/* Save PCI configuration state for recovery from PCI AER/EEH errors */ +	pci_save_state(pdev); +  	return 0;   out_fail: @@ -1861,7 +1868,7 @@ _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)  static void  _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)  { -	dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, +	dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,  	    __func__));  	if (ioc->request) { @@ -1947,7 +1954,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)  	u32 retry_sz;  	u16 max_request_credit; -	dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, +	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,  	    __func__));  	retry_sz = 0; @@ -2374,7 +2381,7 @@ _base_wait_for_doorbell_int(struct MPT2SAS_ADAPTER *ioc, int timeout,  	do {  		int_status = readl(&ioc->chip->HostInterruptStatus);  		if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { -			dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " +			dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "  			    "successfull count(%d), timeout(%d)\n", ioc->name,  			    __func__, count, timeout));  			return 0; @@ -2415,7 +2422,7 @@ _base_wait_for_doorbell_ack(struct MPT2SAS_ADAPTER *ioc, int timeout,  	do {  		int_status = readl(&ioc->chip->HostInterruptStatus);  		if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) { -			dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " +			dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "  			    "successfull count(%d), timeout(%d)\n", ioc->name,  			    __func__, count, timeout));  			return 0; @@ -2463,7 +2470,7 @@ _base_wait_for_doorbell_not_used(struct MPT2SAS_ADAPTER *ioc, int timeout,  	do {  		doorbell_reg = readl(&ioc->chip->Doorbell);  		if (!(doorbell_reg & MPI2_DOORBELL_USED)) { -			dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " +			dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "  			    "successfull count(%d), timeout(%d)\n", ioc->name,  			    __func__, count, timeout));  			return 0; @@ -2637,9 +2644,9 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,  	if (ioc->logging_level & MPT_DEBUG_INIT) {  		mfp = (u32 *)reply; -		printk(KERN_DEBUG "\toffset:data\n"); +		printk(KERN_INFO "\toffset:data\n");  		for (i = 0; i < reply_bytes/4; i++) -			printk(KERN_DEBUG "\t[0x%02x]:%08x\n", i*4, +			printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,  			    le32_to_cpu(mfp[i]));  	}  	return 0; @@ -2672,7 +2679,7 @@ mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc,  	void *request;  	u16 wait_state_count; -	dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, +	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,  	    __func__));  	mutex_lock(&ioc->base_cmds.mutex); @@ -2777,7 +2784,7 @@ mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,  	void *request;  	u16 wait_state_count; -	dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, +	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,  	    __func__));  	mutex_lock(&ioc->base_cmds.mutex); @@ -2865,7 +2872,7 @@ _base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)  	Mpi2PortFactsReply_t mpi_reply, *pfacts;  	int mpi_reply_sz, mpi_request_sz, r; -	dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, +	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,  	    __func__));  	mpi_reply_sz = sizeof(Mpi2PortFactsReply_t); @@ -2907,7 +2914,7 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  	Mpi2IOCFactsReply_t mpi_reply, *facts;  	int mpi_reply_sz, mpi_request_sz, r; -	dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, +	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,  	    __func__));  	mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t); @@ -2979,7 +2986,7 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  	struct timeval current_time;  	u16 ioc_status; -	dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, +	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,  	    __func__));  	memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t)); @@ -3040,9 +3047,9 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  		int i;  		mfp = (u32 *)&mpi_request; -		printk(KERN_DEBUG "\toffset:data\n"); +		printk(KERN_INFO "\toffset:data\n");  		for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++) -			printk(KERN_DEBUG "\t[0x%02x]:%08x\n", i*4, +			printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,  			    le32_to_cpu(mfp[i]));  	} @@ -3121,7 +3128,7 @@ _base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  			r = -ETIME;  		goto out;  	} else -		dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: complete\n", +		dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n",  		    ioc->name, __func__));  	ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_OPERATIONAL, @@ -3181,7 +3188,7 @@ _base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  	int r = 0;  	int i; -	dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, +	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,  	    __func__));  	if (ioc->base_cmds.status & MPT2_CMD_PENDING) { @@ -3219,7 +3226,7 @@ _base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  		else  			r = -ETIME;  	} else -		dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: complete\n", +		dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n",  		    ioc->name, __func__));  	ioc->base_cmds.status = MPT2_CMD_NOT_USED;  	return r; @@ -3281,7 +3288,7 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  	_base_save_msix_table(ioc); -	drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "clear interrupts\n", +	drsprintk(ioc, printk(MPT2SAS_INFO_FMT "clear interrupts\n",  	    ioc->name));  	count = 0; @@ -3289,7 +3296,7 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  		/* Write magic sequence to WriteSequence register  		 * Loop until in diagnostic mode  		 */ -		drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "write magic " +		drsprintk(ioc, printk(MPT2SAS_INFO_FMT "write magic "  		    "sequence\n", ioc->name));  		writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);  		writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence); @@ -3309,7 +3316,7 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  			goto out;  		host_diagnostic = readl(&ioc->chip->HostDiagnostic); -		drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "wrote magic " +		drsprintk(ioc, printk(MPT2SAS_INFO_FMT "wrote magic "  		    "sequence: count(%d), host_diagnostic(0x%08x)\n",  		    ioc->name, count, host_diagnostic)); @@ -3317,7 +3324,7 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  	hcb_size = readl(&ioc->chip->HCBSize); -	drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "diag reset: issued\n", +	drsprintk(ioc, printk(MPT2SAS_INFO_FMT "diag reset: issued\n",  	    ioc->name));  	writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER,  	     &ioc->chip->HostDiagnostic); @@ -3344,29 +3351,29 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  	if (host_diagnostic & MPI2_DIAG_HCB_MODE) { -		drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "restart the adapter " +		drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter "  		    "assuming the HCB Address points to good F/W\n",  		    ioc->name));  		host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK;  		host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW;  		writel(host_diagnostic, &ioc->chip->HostDiagnostic); -		drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT +		drsprintk(ioc, printk(MPT2SAS_INFO_FMT  		    "re-enable the HCDW\n", ioc->name));  		writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE,  		    &ioc->chip->HCBSize);  	} -	drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "restart the adapter\n", +	drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter\n",  	    ioc->name));  	writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET,  	    &ioc->chip->HostDiagnostic); -	drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "disable writes to the " +	drsprintk(ioc, printk(MPT2SAS_INFO_FMT "disable writes to the "  	    "diagnostic register\n", ioc->name));  	writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence); -	drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "Wait for FW to go to the " +	drsprintk(ioc, printk(MPT2SAS_INFO_FMT "Wait for FW to go to the "  	    "READY state\n", ioc->name));  	ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20,  	    sleep_flag); @@ -3398,19 +3405,23 @@ _base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,      enum reset_type type)  {  	u32 ioc_state; +	int rc; -	dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, +	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,  	    __func__)); +	if (ioc->pci_error_recovery) +		return 0; +  	ioc_state = mpt2sas_base_get_iocstate(ioc, 0); -	dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: ioc_state(0x%08x)\n", +	dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: ioc_state(0x%08x)\n",  	    ioc->name, __func__, ioc_state));  	if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY)  		return 0;  	if (ioc_state & MPI2_DOORBELL_USED) { -		dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "unexpected doorbell " +		dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "  		    "active!\n", ioc->name));  		goto issue_diag_reset;  	} @@ -3426,11 +3437,15 @@ _base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,  	if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL)  		if (!(_base_send_ioc_reset(ioc, -		    MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) +		    MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) { +			ioc->ioc_reset_count++;  			return 0; +	}   issue_diag_reset: -	return _base_diag_reset(ioc, CAN_SLEEP); +	rc = _base_diag_reset(ioc, CAN_SLEEP); +	ioc->ioc_reset_count++; +	return rc;  }  /** @@ -3449,7 +3464,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  	u16 smid;  	struct _tr_list *delayed_tr, *delayed_tr_next; -	dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, +	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,  	    __func__));  	/* clean the delayed target reset list */ @@ -3459,6 +3474,12 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  		kfree(delayed_tr);  	} +	list_for_each_entry_safe(delayed_tr, delayed_tr_next, +	    &ioc->delayed_tr_volume_list, list) { +		list_del(&delayed_tr->list); +		kfree(delayed_tr); +	} +  	/* initialize the scsi lookup free list */  	spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);  	INIT_LIST_HEAD(&ioc->free_list); @@ -3520,6 +3541,13 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  	if (sleep_flag == CAN_SLEEP)  		_base_static_config_pages(ioc); +	if (ioc->wait_for_port_enable_to_complete) { +		if (diag_buffer_enable != 0) +			mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable); +		if (disable_discovery > 0) +			return r; +	} +  	r = _base_send_port_enable(ioc, sleep_flag);  	if (r)  		return r; @@ -3538,7 +3566,7 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc)  {  	struct pci_dev *pdev = ioc->pdev; -	dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, +	dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,  	    __func__));  	_base_mask_interrupts(ioc); @@ -3571,7 +3599,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)  {  	int r, i; -	dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, +	dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,  	    __func__));  	r = mpt2sas_base_map_resources(ioc); @@ -3606,6 +3634,17 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)  	init_waitqueue_head(&ioc->reset_wq); +	/* allocate memory pd handle bitmask list */ +	ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8); +	if (ioc->facts.MaxDevHandle % 8) +		ioc->pd_handles_sz++; +	ioc->pd_handles = kzalloc(ioc->pd_handles_sz, +	    GFP_KERNEL); +	if (!ioc->pd_handles) { +		r = -ENOMEM; +		goto out_free_resources; +	} +  	ioc->fwfault_debug = mpt2sas_fwfault_debug;  	/* base internal command bits */ @@ -3635,11 +3674,20 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)  	/* ctl module internal command bits */  	ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); +	ioc->ctl_cmds.sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);  	ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;  	mutex_init(&ioc->ctl_cmds.mutex);  	if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply ||  	    !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply || +	    !ioc->config_cmds.reply || !ioc->ctl_cmds.reply || +	    !ioc->ctl_cmds.sense) { +		r = -ENOMEM; +		goto out_free_resources; +	} + +	if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply || +	    !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply ||  	    !ioc->config_cmds.reply || !ioc->ctl_cmds.reply) {  		r = -ENOMEM;  		goto out_free_resources; @@ -3667,8 +3715,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)  		goto out_free_resources;  	mpt2sas_base_start_watchdog(ioc); -	if (diag_buffer_enable != 0) -		mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);  	return 0;   out_free_resources: @@ -3677,12 +3723,14 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)  	mpt2sas_base_free_resources(ioc);  	_base_release_memory_pools(ioc);  	pci_set_drvdata(ioc->pdev, NULL); +	kfree(ioc->pd_handles);  	kfree(ioc->tm_cmds.reply);  	kfree(ioc->transport_cmds.reply);  	kfree(ioc->scsih_cmds.reply);  	kfree(ioc->config_cmds.reply);  	kfree(ioc->base_cmds.reply);  	kfree(ioc->ctl_cmds.reply); +	kfree(ioc->ctl_cmds.sense);  	kfree(ioc->pfacts);  	ioc->ctl_cmds.reply = NULL;  	ioc->base_cmds.reply = NULL; @@ -3705,15 +3753,17 @@ void  mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)  { -	dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, +	dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,  	    __func__));  	mpt2sas_base_stop_watchdog(ioc);  	mpt2sas_base_free_resources(ioc);  	_base_release_memory_pools(ioc);  	pci_set_drvdata(ioc->pdev, NULL); +	kfree(ioc->pd_handles);  	kfree(ioc->pfacts);  	kfree(ioc->ctl_cmds.reply); +	kfree(ioc->ctl_cmds.sense);  	kfree(ioc->base_cmds.reply);  	kfree(ioc->tm_cmds.reply);  	kfree(ioc->transport_cmds.reply); @@ -3738,11 +3788,11 @@ _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)  {  	switch (reset_phase) {  	case MPT2_IOC_PRE_RESET: -		dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " +		dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "  		    "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));  		break;  	case MPT2_IOC_AFTER_RESET: -		dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " +		dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "  		    "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));  		if (ioc->transport_cmds.status & MPT2_CMD_PENDING) {  			ioc->transport_cmds.status |= MPT2_CMD_RESET; @@ -3762,7 +3812,7 @@ _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)  		}  		break;  	case MPT2_IOC_DONE_RESET: -		dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " +		dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "  		    "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));  		break;  	} @@ -3804,7 +3854,7 @@ _wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)  		return;  	/* wait for pending commands to complete */ -	wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 3 * HZ); +	wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ);  }  /** @@ -3822,19 +3872,37 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,  	int r;  	unsigned long flags; -	dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, +	dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,  	    __func__)); +	if (ioc->pci_error_recovery) { +		printk(MPT2SAS_ERR_FMT "%s: pci error recovery reset\n", +		    ioc->name, __func__); +		r = 0; +		goto out; +	} +  	if (mpt2sas_fwfault_debug)  		mpt2sas_halt_firmware(ioc); -	spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); -	if (ioc->shost_recovery) { -		spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); -		printk(MPT2SAS_ERR_FMT "%s: busy\n", -		    ioc->name, __func__); -		return -EBUSY; +	/* TODO - What we really should be doing is pulling +	 * out all the code associated with NO_SLEEP; its never used. +	 * That is legacy code from mpt fusion driver, ported over. +	 * I will leave this BUG_ON here for now till its been resolved. +	 */ +	BUG_ON(sleep_flag == NO_SLEEP); + +	/* wait for an active reset in progress to complete */ +	if (!mutex_trylock(&ioc->reset_in_progress_mutex)) { +		do { +			ssleep(1); +		} while (ioc->shost_recovery == 1); +		dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name, +		    __func__)); +		return ioc->ioc_reset_in_progress_status;  	} + +	spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);  	ioc->shost_recovery = 1;  	spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); @@ -3849,13 +3917,17 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,  	if (!r)  		_base_reset_handler(ioc, MPT2_IOC_DONE_RESET);   out: -	dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: %s\n", +	dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %s\n",  	    ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));  	spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); +	ioc->ioc_reset_in_progress_status = r;  	ioc->shost_recovery = 0;  	complete(&ioc->shost_recovery_done);  	spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); +	mutex_unlock(&ioc->reset_in_progress_mutex); +	dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name, +	    __func__));  	return r;  }  |