⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mptspi.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	nego = mptspi_getRP(starget);	pg1.RequestedParameters = cpu_to_le32(nego);	pg1.Reserved = 0;	pg1.Configuration = 0;	mptspi_write_spi_device_pg1(starget, &pg1);}struct work_queue_wrapper {	struct work_struct	work;	struct _MPT_SCSI_HOST	*hd;	int			disk;};static void mpt_work_wrapper(struct work_struct *work){	struct work_queue_wrapper *wqw =		container_of(work, struct work_queue_wrapper, work);	struct _MPT_SCSI_HOST *hd = wqw->hd;	MPT_ADAPTER *ioc = hd->ioc;	struct Scsi_Host *shost = ioc->sh;	struct scsi_device *sdev;	int disk = wqw->disk;	struct _CONFIG_PAGE_IOC_3 *pg3;	kfree(wqw);	mpt_findImVolumes(ioc);	pg3 = ioc->raid_data.pIocPg3;	if (!pg3)		return;	shost_for_each_device(sdev,shost) {		struct scsi_target *starget = scsi_target(sdev);		VirtTarget *vtarget = starget->hostdata;		/* only want to search RAID components */		if (sdev->channel != 1)			continue;		/* The id is the raid PhysDiskNum, even if		 * starget->id is the actual target address */		if(vtarget->id != disk)			continue;		starget_printk(KERN_INFO, vtarget->starget, MYIOC_s_FMT		    "Integrated RAID requests DV of new device\n", ioc->name);		mptspi_dv_device(hd, sdev);	}	shost_printk(KERN_INFO, shost, MYIOC_s_FMT	    "Integrated RAID detects new device %d\n", ioc->name, disk);	scsi_scan_target(&ioc->sh->shost_gendev, 1, disk, 0, 1);}static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk){	struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);	MPT_ADAPTER *ioc = hd->ioc;	if (!wqw) {		shost_printk(KERN_ERR, ioc->sh, MYIOC_s_FMT		    "Failed to act on RAID event for physical disk %d\n",		    ioc->name, disk);		return;	}	INIT_WORK(&wqw->work, mpt_work_wrapper);	wqw->hd = hd;	wqw->disk = disk;	schedule_work(&wqw->work);}static intmptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply){	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;	struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh);	if (hd && event ==  MPI_EVENT_INTEGRATED_RAID) {		int reason			= (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;		if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {			int disk = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;			mpt_dv_raid(hd, disk);		}	}	return mptscsih_event_process(ioc, pEvReply);}static intmptspi_deny_binding(struct scsi_target *starget){	struct _MPT_SCSI_HOST *hd =		(struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata;	return ((mptspi_is_raid(hd, starget->id)) &&		starget->channel == 0) ? 1 : 0;}static struct spi_function_template mptspi_transport_functions = {	.get_offset	= mptspi_read_parameters,	.set_offset	= mptspi_write_offset,	.show_offset	= 1,	.get_period	= mptspi_read_parameters,	.set_period	= mptspi_write_period,	.show_period	= 1,	.get_width	= mptspi_read_parameters,	.set_width	= mptspi_write_width,	.show_width	= 1,	.get_iu		= mptspi_read_parameters,	.set_iu		= mptspi_write_iu,	.show_iu	= 1,	.get_dt		= mptspi_read_parameters,	.set_dt		= mptspi_write_dt,	.show_dt	= 1,	.get_qas	= mptspi_read_parameters,	.set_qas	= mptspi_write_qas,	.show_qas	= 1,	.get_wr_flow	= mptspi_read_parameters,	.set_wr_flow	= mptspi_write_wr_flow,	.show_wr_flow	= 1,	.get_rd_strm	= mptspi_read_parameters,	.set_rd_strm	= mptspi_write_rd_strm,	.show_rd_strm	= 1,	.get_rti	= mptspi_read_parameters,	.set_rti	= mptspi_write_rti,	.show_rti	= 1,	.get_pcomp_en	= mptspi_read_parameters,	.set_pcomp_en	= mptspi_write_pcomp_en,	.show_pcomp_en	= 1,	.get_hold_mcs	= mptspi_read_parameters,	.set_hold_mcs	= mptspi_write_hold_mcs,	.show_hold_mcs	= 1,	.deny_binding	= mptspi_deny_binding,};/**************************************************************************** * Supported hardware */static struct pci_device_id mptspi_pci_table[] = {	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1030,		PCI_ANY_ID, PCI_ANY_ID },	{ PCI_VENDOR_ID_ATTO, MPI_MANUFACTPAGE_DEVID_53C1030,		PCI_ANY_ID, PCI_ANY_ID },	{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1035,		PCI_ANY_ID, PCI_ANY_ID },	{0}	/* Terminating entry */};MODULE_DEVICE_TABLE(pci, mptspi_pci_table);/* * renegotiate for a given target */static voidmptspi_dv_renegotiate_work(struct work_struct *work){	struct work_queue_wrapper *wqw =		container_of(work, struct work_queue_wrapper, work);	struct _MPT_SCSI_HOST *hd = wqw->hd;	struct scsi_device *sdev;	struct scsi_target *starget;	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;	u32 nego;	MPT_ADAPTER *ioc = hd->ioc;	kfree(wqw);	if (hd->spi_pending) {		shost_for_each_device(sdev, ioc->sh) {			if  (hd->spi_pending & (1 << sdev->id))				continue;			starget = scsi_target(sdev);			nego = mptspi_getRP(starget);			pg1.RequestedParameters = cpu_to_le32(nego);			pg1.Reserved = 0;			pg1.Configuration = 0;			mptspi_write_spi_device_pg1(starget, &pg1);		}	} else {		shost_for_each_device(sdev, ioc->sh)			mptspi_dv_device(hd, sdev);	}}static voidmptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd){	struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);	if (!wqw)		return;	INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work);	wqw->hd = hd;	schedule_work(&wqw->work);}/* * spi module reset handler */static intmptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase){	struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh);	int rc;	rc = mptscsih_ioc_reset(ioc, reset_phase);	if (reset_phase == MPT_IOC_POST_RESET)		mptspi_dv_renegotiate(hd);	return rc;}#ifdef CONFIG_PM/* * spi module resume handler */static intmptspi_resume(struct pci_dev *pdev){	MPT_ADAPTER 	*ioc = pci_get_drvdata(pdev);	struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh);	int rc;	rc = mptscsih_resume(pdev);	mptspi_dv_renegotiate(hd);	return rc;}#endif/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptspi_probe - Installs scsi devices per bus. *	@pdev: Pointer to pci_dev structure * *	Returns 0 for success, non-zero for failure. * */static intmptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id){	struct Scsi_Host	*sh;	MPT_SCSI_HOST		*hd;	MPT_ADAPTER 		*ioc;	unsigned long		 flags;	int			 ii;	int			 numSGE = 0;	int			 scale;	int			 ioc_cap;	int			error=0;	int			r;	if ((r = mpt_attach(pdev,id)) != 0)		return r;	ioc = pci_get_drvdata(pdev);	ioc->DoneCtx = mptspiDoneCtx;	ioc->TaskCtx = mptspiTaskCtx;	ioc->InternalCtx = mptspiInternalCtx;	/*  Added sanity check on readiness of the MPT adapter.	 */	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {		printk(MYIOC_s_WARN_FMT		  "Skipping because it's not operational!\n",		  ioc->name);		error = -ENODEV;		goto out_mptspi_probe;	}	if (!ioc->active) {		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",		  ioc->name);		error = -ENODEV;		goto out_mptspi_probe;	}	/*  Sanity check - ensure at least 1 port is INITIATOR capable	 */	ioc_cap = 0;	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {		if (ioc->pfacts[ii].ProtocolFlags &		    MPI_PORTFACTS_PROTOCOL_INITIATOR)			ioc_cap ++;	}	if (!ioc_cap) {		printk(MYIOC_s_WARN_FMT			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",			ioc->name, ioc);		return 0;	}	sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST));	if (!sh) {		printk(MYIOC_s_WARN_FMT			"Unable to register controller with SCSI subsystem\n",			ioc->name);		error = -1;		goto out_mptspi_probe;        }	spin_lock_irqsave(&ioc->FreeQlock, flags);	/* Attach the SCSI Host to the IOC structure	 */	ioc->sh = sh;	sh->io_port = 0;	sh->n_io_port = 0;	sh->irq = 0;	/* set 16 byte cdb's */	sh->max_cmd_len = 16;	/* Yikes!  This is important!	 * Otherwise, by default, linux	 * only scans target IDs 0-7!	 * pfactsN->MaxDevices unreliable	 * (not supported in early	 *	versions of the FW).	 * max_id = 1 + actual max id,	 * max_lun = 1 + actual last lun,	 *	see hosts.h :o(	 */	sh->max_id = ioc->devices_per_bus;	sh->max_lun = MPT_LAST_LUN + 1;	/*	 * If RAID Firmware Detected, setup virtual channel	 */	if (ioc->ir_firmware)		sh->max_channel = 1;	else		sh->max_channel = 0;	sh->this_id = ioc->pfacts[0].PortSCSIID;	/* Required entry.	 */	sh->unique_id = ioc->id;	/* Verify that we won't exceed the maximum	 * number of chain buffers	 * We can optimize:  ZZ = req_sz/sizeof(SGE)	 * For 32bit SGE's:	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ	 *               + (req_sz - 64)/sizeof(SGE)	 * A slightly different algorithm is required for	 * 64bit SGEs.	 */	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));	if (sizeof(dma_addr_t) == sizeof(u64)) {		numSGE = (scale - 1) *		  (ioc->facts.MaxChainDepth-1) + scale +		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +		  sizeof(u32));	} else {		numSGE = 1 + (scale - 1) *		  (ioc->facts.MaxChainDepth-1) + scale +		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +		  sizeof(u32));	}	if (numSGE < sh->sg_tablesize) {		/* Reset this value */		dprintk(ioc, printk(MYIOC_s_DEBUG_FMT		  "Resetting sg_tablesize to %d from %d\n",		  ioc->name, numSGE, sh->sg_tablesize));		sh->sg_tablesize = numSGE;	}	spin_unlock_irqrestore(&ioc->FreeQlock, flags);	hd = shost_priv(sh);	hd->ioc = ioc;	/* SCSI needs scsi_cmnd lookup table!	 * (with size equal to req_depth*PtrSz!)	 */	ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);	if (!ioc->ScsiLookup) {		error = -ENOMEM;		goto out_mptspi_probe;	}	spin_lock_init(&ioc->scsi_lookup_lock);	dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",		 ioc->name, ioc->ScsiLookup));	/* Clear the TM flags	 */	hd->tmPending = 0;	hd->tmState = TM_STATE_NONE;	hd->resetPending = 0;	hd->abortSCpnt = NULL;	/* Clear the pointer used to store	 * single-threaded commands, i.e., those	 * issued during a bus scan, dv and	 * configuration pages.	 */	hd->cmdPtr = NULL;	/* Initialize this SCSI Hosts' timers	 * To use, set the timer expires field	 * and add_timer	 */	init_timer(&hd->timer);	hd->timer.data = (unsigned long) hd;	hd->timer.function = mptscsih_timer_expired;	ioc->spi_data.Saf_Te = mpt_saf_te;	hd->negoNvram = MPT_SCSICFG_USE_NVRAM;	ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT		"saf_te %x\n",		ioc->name,		mpt_saf_te));	ioc->spi_data.noQas = 0;	init_waitqueue_head(&hd->scandv_waitq);	hd->scandv_wait_done = 0;	hd->last_queue_full = 0;	hd->spi_pending = 0;	/* Some versions of the firmware don't support page 0; without	 * that we can't get the parameters */	if (ioc->spi_data.sdp0length != 0)		sh->transportt = mptspi_transport_template;	error = scsi_add_host (sh, &ioc->pcidev->dev);	if(error) {		dprintk(ioc, printk(MYIOC_s_ERR_FMT		  "scsi_add_host failed\n", ioc->name));		goto out_mptspi_probe;	}	/*	 * issue internal bus reset	 */	if (ioc->spi_data.bus_reset)		mptscsih_TMHandler(hd,		    MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,		    0, 0, 0, 0, 5);	scsi_scan_host(sh);	return 0;out_mptspi_probe:	mptscsih_remove(pdev);	return error;}static struct pci_driver mptspi_driver = {	.name		= "mptspi",	.id_table	= mptspi_pci_table,	.probe		= mptspi_probe,	.remove		= __devexit_p(mptscsih_remove),	.shutdown	= mptscsih_shutdown,#ifdef CONFIG_PM	.suspend	= mptscsih_suspend,	.resume		= mptspi_resume,#endif};/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptspi_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer. * *	Returns 0 for success, non-zero for failure. */static int __initmptspi_init(void){	int error;	show_mptmod_ver(my_NAME, my_VERSION);	mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions);	if (!mptspi_transport_template)		return -ENODEV;	mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER);	mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);	mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);	mpt_event_register(mptspiDoneCtx, mptspi_event_process);	mpt_reset_register(mptspiDoneCtx, mptspi_ioc_reset);	error = pci_register_driver(&mptspi_driver);	if (error)		spi_release_transport(mptspi_transport_template);	return error;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptspi_exit - Unregisters MPT adapter(s) */static void __exitmptspi_exit(void){	pci_unregister_driver(&mptspi_driver);	mpt_reset_deregister(mptspiDoneCtx);	mpt_event_deregister(mptspiDoneCtx);	mpt_deregister(mptspiInternalCtx);	mpt_deregister(mptspiTaskCtx);	mpt_deregister(mptspiDoneCtx);	spi_release_transport(mptspi_transport_template);}module_init(mptspi_init);module_exit(mptspi_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -