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

📄 mptsas.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		schedule_work(&ev->work);		break;	case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:	/*	 * Persistent table is full.	 */		INIT_WORK(&ioc->mptscsih_persistTask,		    mptscsih_sas_persist_clear_table,		    (void *)ioc);		schedule_work(&ioc->mptscsih_persistTask);		break;	case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:	/* TODO */	case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:	/* TODO */	default:		break;	}}static voidmptscsih_send_raid_event(MPT_ADAPTER *ioc,		EVENT_DATA_RAID *raid_event_data){	struct mptsas_hotplug_event *ev;	int status = le32_to_cpu(raid_event_data->SettingsStatus);	int state = (status >> 8) & 0xff;	if (ioc->bus_type != SAS)		return;	ev = kmalloc(sizeof(*ev), GFP_ATOMIC);	if (!ev) {		printk(KERN_WARNING "mptsas: lost hotplug event\n");		return;	}	memset(ev,0,sizeof(struct mptsas_hotplug_event));	INIT_WORK(&ev->work, mptsas_hotplug_work, ev);	ev->ioc = ioc;	ev->id = raid_event_data->VolumeID;	ev->event_type = MPTSAS_IGNORE_EVENT;	switch (raid_event_data->ReasonCode) {	case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:		ev->event_type = MPTSAS_ADD_DEVICE;		break;	case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:		ioc->raid_data.isRaid = 1;		ev->phys_disk_num_valid = 1;		ev->phys_disk_num = raid_event_data->PhysDiskNum;		ev->event_type = MPTSAS_DEL_DEVICE;		break;	case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:		switch (state) {		case MPI_PD_STATE_ONLINE:			ioc->raid_data.isRaid = 1;			ev->phys_disk_num_valid = 1;			ev->phys_disk_num = raid_event_data->PhysDiskNum;			ev->event_type = MPTSAS_ADD_DEVICE;			break;		case MPI_PD_STATE_MISSING:		case MPI_PD_STATE_NOT_COMPATIBLE:		case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:		case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:		case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:			ev->event_type = MPTSAS_DEL_DEVICE;			break;		default:			break;		}		break;	case MPI_EVENT_RAID_RC_VOLUME_DELETED:		ev->event_type = MPTSAS_DEL_RAID;		break;	case MPI_EVENT_RAID_RC_VOLUME_CREATED:		ev->event_type = MPTSAS_ADD_RAID;		break;	case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:		switch (state) {		case MPI_RAIDVOL0_STATUS_STATE_FAILED:		case MPI_RAIDVOL0_STATUS_STATE_MISSING:			ev->event_type = MPTSAS_DEL_RAID;			break;		case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:		case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:			ev->event_type = MPTSAS_ADD_RAID;			break;		default:			break;		}		break;	default:		break;	}	schedule_work(&ev->work);}static voidmptscsih_send_discovery(MPT_ADAPTER *ioc,	EVENT_DATA_SAS_DISCOVERY *discovery_data){	struct mptsas_discovery_event *ev;	/*	 * DiscoveryStatus	 *	 * This flag will be non-zero when firmware	 * kicks off discovery, and return to zero	 * once its completed.	 */	if (discovery_data->DiscoveryStatus)		return;	ev = kmalloc(sizeof(*ev), GFP_ATOMIC);	if (!ev)		return;	memset(ev,0,sizeof(struct mptsas_discovery_event));	INIT_WORK(&ev->work, mptscsih_discovery_work, ev);	ev->ioc = ioc;	schedule_work(&ev->work);};static intmptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply){	int rc=1;	u8 event = le32_to_cpu(reply->Event) & 0xFF;	if (!ioc->sh)		goto out;	/*	 * sas_discovery_ignore_events	 *	 * This flag is to prevent anymore processing of	 * sas events once mptsas_remove function is called.	 */	if (ioc->sas_discovery_ignore_events) {		rc = mptscsih_event_process(ioc, reply);		goto out;	}	switch (event) {	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:		mptscsih_send_sas_event(ioc,			(EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);		break;	case MPI_EVENT_INTEGRATED_RAID:		mptscsih_send_raid_event(ioc,			(EVENT_DATA_RAID *)reply->Data);		break;	case MPI_EVENT_PERSISTENT_TABLE_FULL:		INIT_WORK(&ioc->mptscsih_persistTask,		    mptscsih_sas_persist_clear_table,		    (void *)ioc);		schedule_work(&ioc->mptscsih_persistTask);		break;	 case MPI_EVENT_SAS_DISCOVERY:		mptscsih_send_discovery(ioc,			(EVENT_DATA_SAS_DISCOVERY *)reply->Data);		break;	default:		rc = mptscsih_event_process(ioc, reply);		break;	} out:	return rc;}static intmptsas_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;	r = mpt_attach(pdev,id);	if (r)		return r;	ioc = pci_get_drvdata(pdev);	ioc->DoneCtx = mptsasDoneCtx;	ioc->TaskCtx = mptsasTaskCtx;	ioc->InternalCtx = mptsasInternalCtx;	/*  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_mptsas_probe;	}	if (!ioc->active) {		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",		  ioc->name);		error = -ENODEV;		goto out_mptsas_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(&mptsas_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_mptsas_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;	sh->max_id = ioc->pfacts->MaxDevices + 1;	sh->transportt = mptsas_transport_template;	sh->max_lun = MPT_LAST_LUN + 1;	sh->max_channel = 0;	sh->this_id = ioc->pfacts[0].PortSCSIID;	/* Required entry.	 */	sh->unique_id = ioc->id;	INIT_LIST_HEAD(&ioc->sas_topology);	mutex_init(&ioc->sas_topology_mutex);	mutex_init(&ioc->sas_discovery_mutex);	mutex_init(&ioc->sas_mgmt.mutex);	init_completion(&ioc->sas_mgmt.done);	/* 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((MYIOC_s_INFO_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 = (MPT_SCSI_HOST *) sh->hostdata;	hd->ioc = ioc;	/* SCSI needs scsi_cmnd lookup table!	 * (with size equal to req_depth*PtrSz!)	 */	hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);	if (!hd->ScsiLookup) {		error = -ENOMEM;		goto out_mptsas_probe;	}	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",		 ioc->name, hd->ScsiLookup));	/* Allocate memory for the device structures.	 * A non-Null pointer at an offset	 * indicates a device exists.	 * max_id = 1 + maximum id (hosts.h)	 */	hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);	if (!hd->Targets) {		error = -ENOMEM;		goto out_mptsas_probe;	}	dprintk((KERN_INFO "  vtarget @ %p\n", hd->Targets));	/* 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;	hd->mpt_pq_filter = mpt_pq_filter;	ioc->sas_data.ptClear = mpt_pt_clear;	if (ioc->sas_data.ptClear==1) {		mptbase_sas_persist_operation(		    ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);	}	ddvprintk((MYIOC_s_INFO_FMT		"mpt_pq_filter %x mpt_pq_filter %x\n",		ioc->name,		mpt_pq_filter,		mpt_pq_filter));	init_waitqueue_head(&hd->scandv_waitq);	hd->scandv_wait_done = 0;	hd->last_queue_full = 0;	error = scsi_add_host(sh, &ioc->pcidev->dev);	if (error) {		dprintk((KERN_ERR MYNAM		  "scsi_add_host failed\n"));		goto out_mptsas_probe;	}	mptsas_scan_sas_topology(ioc);	return 0;out_mptsas_probe:	mptscsih_remove(pdev);	return error;}static void __devexit mptsas_remove(struct pci_dev *pdev){	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);	struct mptsas_portinfo *p, *n;	ioc->sas_discovery_ignore_events=1;	sas_remove_host(ioc->sh);	mutex_lock(&ioc->sas_topology_mutex);	list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {		list_del(&p->list);		if (p->phy_info)			kfree(p->phy_info);		kfree(p);	}	mutex_unlock(&ioc->sas_topology_mutex);	mptscsih_remove(pdev);}static struct pci_device_id mptsas_pci_table[] = {	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,		PCI_ANY_ID, PCI_ANY_ID },	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,		PCI_ANY_ID, PCI_ANY_ID },	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,		PCI_ANY_ID, PCI_ANY_ID },	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,		PCI_ANY_ID, PCI_ANY_ID },	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,		PCI_ANY_ID, PCI_ANY_ID },	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,		PCI_ANY_ID, PCI_ANY_ID },	{0}	/* Terminating entry */};MODULE_DEVICE_TABLE(pci, mptsas_pci_table);static struct pci_driver mptsas_driver = {	.name		= "mptsas",	.id_table	= mptsas_pci_table,	.probe		= mptsas_probe,	.remove		= __devexit_p(mptsas_remove),	.shutdown	= mptscsih_shutdown,#ifdef CONFIG_PM	.suspend	= mptscsih_suspend,	.resume		= mptscsih_resume,#endif};static int __initmptsas_init(void){	show_mptmod_ver(my_NAME, my_VERSION);	mptsas_transport_template =	    sas_attach_transport(&mptsas_transport_functions);	if (!mptsas_transport_template)		return -ENODEV;	mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);	mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);	mptsasInternalCtx =		mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);	mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);	if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {		devtverboseprintk((KERN_INFO MYNAM		  ": Registered for IOC event notifications\n"));	}	if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {		dprintk((KERN_INFO MYNAM		  ": Registered for IOC reset notifications\n"));	}	return pci_register_driver(&mptsas_driver);}static void __exitmptsas_exit(void){	pci_unregister_driver(&mptsas_driver);	sas_release_transport(mptsas_transport_template);	mpt_reset_deregister(mptsasDoneCtx);	mpt_event_deregister(mptsasDoneCtx);	mpt_deregister(mptsasMgmtCtx);	mpt_deregister(mptsasInternalCtx);	mpt_deregister(mptsasTaskCtx);	mpt_deregister(mptsasDoneCtx);}module_init(mptsas_init);module_exit(mptsas_exit);

⌨️ 快捷键说明

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