diff options
Diffstat (limited to 'drivers/message/fusion/mptsas.c')
| -rw-r--r-- | drivers/message/fusion/mptsas.c | 92 | 
1 files changed, 65 insertions, 27 deletions
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 83a5115f025..711fcb5cec8 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -92,6 +92,11 @@ static int max_lun = MPTSAS_MAX_LUN;  module_param(max_lun, int, 0);  MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); +static int mpt_loadtime_max_sectors = 8192; +module_param(mpt_loadtime_max_sectors, int, 0); +MODULE_PARM_DESC(mpt_loadtime_max_sectors, +		" Maximum sector define for Host Bus Adaptor.Range 64 to 8192 default=8192"); +  static u8	mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;  static u8	mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;  static u8	mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */ @@ -285,10 +290,11 @@ mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,  	spin_lock_irqsave(&ioc->fw_event_lock, flags);  	list_add_tail(&fw_event->list, &ioc->fw_event_list);  	INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work); -	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n", -	    ioc->name, __func__, fw_event)); -	queue_delayed_work(ioc->fw_event_q, &fw_event->work, -	    delay); +	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)" +		"on cpuid %d\n", ioc->name, __func__, +		fw_event, smp_processor_id())); +	queue_delayed_work_on(smp_processor_id(), ioc->fw_event_q, +	    &fw_event->work, delay);  	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);  } @@ -300,14 +306,15 @@ mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,  	unsigned long flags;  	spin_lock_irqsave(&ioc->fw_event_lock, flags);  	devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task " -	    "(fw_event=0x%p)\n", ioc->name, __func__, fw_event)); +	    "(fw_event=0x%p)on cpuid %d\n", ioc->name, __func__, +		fw_event, smp_processor_id()));  	fw_event->retries++; -	queue_delayed_work(ioc->fw_event_q, &fw_event->work, -	    msecs_to_jiffies(delay)); +	queue_delayed_work_on(smp_processor_id(), ioc->fw_event_q, +	    &fw_event->work, msecs_to_jiffies(delay));  	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);  } -/* free memory assoicated to a sas firmware event */ +/* free memory associated to a sas firmware event */  static void  mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)  { @@ -1094,7 +1101,7 @@ mptsas_block_io_starget(struct scsi_target *starget)  /**   * mptsas_target_reset_queue   * - * Receive request for TARGET_RESET after recieving an firmware + * Receive request for TARGET_RESET after receiving an firmware   * event NOT_RESPONDING_EVENT, then put command in link list   * and queue if task_queue already in use.   * @@ -1146,7 +1153,7 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc,   *   * This function will delete scheduled target reset from the list and   * try to send next target reset. This will be called from completion - * context of any Task managment command. + * context of any Task management command.   */  void @@ -1403,7 +1410,7 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,  /**   *	mptsas_add_end_device - report a new end device to sas transport layer   *	@ioc: Pointer to MPT_ADAPTER structure - *	@phy_info: decribes attached device + *	@phy_info: describes attached device   *   *	return (0) success (1) failure   * @@ -1481,7 +1488,7 @@ mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)  /**   *	mptsas_del_end_device - report a deleted end device to sas transport layer   *	@ioc: Pointer to MPT_ADAPTER structure - *	@phy_info: decribes attached device + *	@phy_info: describes attached device   *   **/  static void @@ -1889,7 +1896,7 @@ mptsas_slave_alloc(struct scsi_device *sdev)  }  static int -mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) +mptsas_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt)  {  	MPT_SCSI_HOST	*hd;  	MPT_ADAPTER	*ioc; @@ -1897,11 +1904,11 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))  	if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {  		SCpnt->result = DID_NO_CONNECT << 16; -		done(SCpnt); +		SCpnt->scsi_done(SCpnt);  		return 0;  	} -	hd = shost_priv(SCpnt->device->host); +	hd = shost_priv(shost);  	ioc = hd->ioc;  	if (ioc->sas_discovery_quiesce_io) @@ -1910,7 +1917,7 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))  	if (ioc->debug_level & MPT_DEBUG_SCSI)  		scsi_print_command(SCpnt); -	return mptscsih_qcmd(SCpnt,done); +	return mptscsih_qcmd(SCpnt);  }  /** @@ -1941,6 +1948,15 @@ static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc)  		goto done;  	} +	/* In case if IOC is in reset from internal context. +	*  Do not execute EEH for the same IOC. SML should to reset timer. +	*/ +	if (ioc->ioc_reset_in_progress) { +		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: ioc is in reset," +		    "SML need to reset the timer (sc=%p)\n", +		    ioc->name, __func__, sc)); +		rc = BLK_EH_RESET_TIMER; +	}  	vdevice = sc->device->hostdata;  	if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD  		|| vdevice->vtarget->deleted)) { @@ -1959,7 +1975,7 @@ done:  static struct scsi_host_template mptsas_driver_template = {  	.module				= THIS_MODULE,  	.proc_name			= "mptsas", -	.proc_info			= mptscsih_proc_info, +	.show_info			= mptscsih_show_info,  	.name				= "MPT SAS Host",  	.info				= mptscsih_info,  	.queuecommand			= mptsas_qcmd, @@ -1971,7 +1987,6 @@ static struct scsi_host_template mptsas_driver_template = {  	.change_queue_depth 		= mptscsih_change_queue_depth,  	.eh_abort_handler		= mptscsih_abort,  	.eh_device_reset_handler	= mptscsih_dev_reset, -	.eh_bus_reset_handler		= mptscsih_bus_reset,  	.eh_host_reset_handler		= mptscsih_host_reset,  	.bios_param			= mptscsih_bios_param,  	.can_queue			= MPT_SAS_CAN_QUEUE, @@ -2218,10 +2233,10 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,  	}  	/* do we need to support multiple segments? */ -	if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { -		printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n", -		    ioc->name, __func__, req->bio->bi_vcnt, blk_rq_bytes(req), -		    rsp->bio->bi_vcnt, blk_rq_bytes(rsp)); +	if (bio_multiple_segments(req->bio) || +	    bio_multiple_segments(rsp->bio)) { +		printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u, rsp %u\n", +		    ioc->name, __func__, blk_rq_bytes(req), blk_rq_bytes(rsp));  		return -EINVAL;  	} @@ -3061,6 +3076,9 @@ static int mptsas_probe_one_phy(struct device *dev,  	case MPI_SAS_IOUNIT0_RATE_3_0:  		phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;  		break; +	case MPI_SAS_IOUNIT0_RATE_6_0: +		phy->negotiated_linkrate = SAS_LINK_RATE_6_0_GBPS; +		break;  	case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:  	case MPI_SAS_IOUNIT0_RATE_UNKNOWN:  	default: @@ -3689,7 +3707,8 @@ mptsas_send_link_status_event(struct fw_event_work *fw_event)  	}  	if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 || -	    link_rate == MPI_SAS_IOUNIT0_RATE_3_0) { +	    link_rate == MPI_SAS_IOUNIT0_RATE_3_0 || +	    link_rate == MPI_SAS_IOUNIT0_RATE_6_0) {  		if (!port_info) {  			if (ioc->old_sas_discovery_protocal) { @@ -5007,7 +5026,6 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)  			(ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)) {  			VirtTarget *vtarget = NULL;  			u8		id, channel; -			u32	 log_info = le32_to_cpu(reply->IOCLogInfo);  			id = sas_event_data->TargetID;  			channel = sas_event_data->Bus; @@ -5018,7 +5036,8 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)  				    "LogInfo (0x%x) available for "  				   "INTERNAL_DEVICE_RESET"  				   "fw_id %d fw_channel %d\n", ioc->name, -				   log_info, id, channel)); +				   le32_to_cpu(reply->IOCLogInfo), +				   id, channel));  				if (vtarget->raidVolume) {  					devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT  					"Skipping Raid Volume for inDMD\n", @@ -5137,6 +5156,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)  	ioc->TaskCtx = mptsasTaskCtx;  	ioc->InternalCtx = mptsasInternalCtx;  	ioc->schedule_target_reset = &mptsas_schedule_target_reset; +	ioc->schedule_dead_ioc_flush_running_cmds = +				&mptscsih_flush_running_cmds;  	/*  Added sanity check on readiness of the MPT adapter.  	 */  	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { @@ -5234,6 +5255,21 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)  		sh->sg_tablesize = numSGE;  	} +	if (mpt_loadtime_max_sectors) { +		if (mpt_loadtime_max_sectors < 64 || +			mpt_loadtime_max_sectors > 8192) { +			printk(MYIOC_s_INFO_FMT "Invalid value passed for" +				"mpt_loadtime_max_sectors %d." +				"Range from 64 to 8192\n", ioc->name, +				mpt_loadtime_max_sectors); +		} +		mpt_loadtime_max_sectors &=  0xFFFFFFFE; +		dprintk(ioc, printk(MYIOC_s_DEBUG_FMT +			"Resetting max sector to %d from %d\n", +		  ioc->name, mpt_loadtime_max_sectors, sh->max_sectors)); +		sh->max_sectors = mpt_loadtime_max_sectors; +	} +  	hd = shost_priv(sh);  	hd->ioc = ioc; @@ -5294,7 +5330,7 @@ mptsas_shutdown(struct pci_dev *pdev)  	mptsas_cleanup_fw_event_q(ioc);  } -static void __devexit mptsas_remove(struct pci_dev *pdev) +static void mptsas_remove(struct pci_dev *pdev)  {  	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);  	struct mptsas_portinfo *p, *n; @@ -5338,6 +5374,8 @@ static struct pci_device_id mptsas_pci_table[] = {  		PCI_ANY_ID, PCI_ANY_ID },  	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,  		PCI_ANY_ID, PCI_ANY_ID }, +	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068_820XELP, +		PCI_ANY_ID, PCI_ANY_ID },  	{0}	/* Terminating entry */  };  MODULE_DEVICE_TABLE(pci, mptsas_pci_table); @@ -5347,7 +5385,7 @@ static struct pci_driver mptsas_driver = {  	.name		= "mptsas",  	.id_table	= mptsas_pci_table,  	.probe		= mptsas_probe, -	.remove		= __devexit_p(mptsas_remove), +	.remove		= mptsas_remove,  	.shutdown	= mptsas_shutdown,  #ifdef CONFIG_PM  	.suspend	= mptscsih_suspend,  | 
