hba_mod.c

来自「6440linuxDriver的源代码」· C语言 代码 · 共 1,621 行 · 第 1/3 页

C
1,621 行
字号
	struct mv_adp_desc *hba_desc;	struct mv_mod_desc *mod_desc;		hba_desc = __dev_to_desc(dev);	BUG_ON(NULL == hba_desc);	mod_desc = __get_lowest_module(hba_desc);	if (NULL == mod_desc)		return -1;	mod_desc->ops->module_start(mod_desc->extension);        /*	 * TBD : A hack due to CORE's module start process	 */	mod_desc = __get_highest_module(hba_desc);	if (NULL == mod_desc)		return -1;	mod_desc->ops->module_start(mod_desc->extension);	return 0;}static void __hba_module_stop(struct mv_adp_desc *hba_desc){	struct mv_mod_desc *mod_desc;	mod_desc = __get_highest_module(hba_desc);	if (NULL == mod_desc)		return;	/* starting from highest module, unlike module_start */	while (mod_desc) {		if ((MV_MOD_STARTED == mod_desc->status)) {			mod_desc->ops->module_stop(mod_desc->extension);			mod_desc->status = MV_MOD_INITED;		}		mod_desc = mod_desc->child;	}}/* stop all HBAs if dev == NULL */void mv_hba_stop(struct pci_dev *dev){	struct mv_adp_desc *hba_desc;		if (dev) {		hba_desc = __dev_to_desc(dev);		__hba_module_stop(hba_desc);	} else {		list_for_each_entry(hba_desc, &mv_online_adapter_list, hba_entry)			__hba_module_stop(hba_desc);	}}void mv_hba_release(struct pci_dev *dev){	struct mv_adp_desc *hba_desc;	hba_desc = __dev_to_desc(dev);	if (NULL != hba_desc) {		__unmap_pci_addr(hba_desc->dev, hba_desc->Base_Address);		mv_release_module_resource(hba_desc);		mv_hba_release_modmm(hba_desc->dev);	}}int mv_hba_init(struct pci_dev *dev, MV_U32 max_io){	struct mv_adp_desc *hba_desc;	struct mv_mod_desc *mod_desc;	int    dbg_ret = 0;		hba_desc = mv_hba_init_modmm(dev);	if (NULL == hba_desc)		goto ext_err_init;	if (register_online_modules(hba_desc))		goto ext_err_modmm;	hba_desc->max_io = max_io;	hba_desc->id     = __mv_get_adapter_count() - 1;	if (mv_alloc_module_resource(hba_desc))		goto ext_err_modmm;		if (pci_read_config_byte(hba_desc->dev, 				 PCI_REVISION_ID, 				 &hba_desc->Revision_Id)) {		printk("%s : Failed to get hba's revision id.\n", 		       mv_product_name);		goto ext_err_pci;	}		hba_desc->Vendor_Id = dev->vendor;	hba_desc->Device_Id = dev->device;	__map_pci_addr(dev, hba_desc->Base_Address);		spin_lock_init(&hba_desc->lock);	MV_DBG(DMSG_HBA, "%s : HBA ext struct init'ed at %p.\n", 	       mv_product_name, hba_desc);	mod_desc = __get_lowest_module(hba_desc);	if (NULL == mod_desc)		goto ext_err_pci;	while (mod_desc) {		if (MV_MOD_INITED != mod_desc->status)			continue;		mod_desc->ops->module_initialize(mod_desc,						 mod_desc->extension_size,						 hba_desc->max_io);		/* there's no support for sibling module at the moment  */		mod_desc = mod_desc->parent;	}	return 0;ext_err_pci:	++dbg_ret;	mv_release_module_resource(hba_desc);ext_err_modmm:	++dbg_ret;	mv_hba_release_modmm(dev);ext_err_init:        ++dbg_ret;	return dbg_ret;}static MV_U32 __hba_get_res_desc(enum Resource_Type type, MV_U16 maxIo){	MV_U32 size = 0;	if (type == RESOURCE_CACHED_MEMORY) {		/* Fixed memory */		size = OFFSET_OF(HBA_Extension, Memory_Pool);		size = ROUNDING(size, 8);#ifdef SUPPORT_EVENT		size += sizeof(Driver_Event_Entry) * MAX_EVENTS;		MV_ASSERT(size == ROUNDING(size, 8));#endif /* SUPPORT_EVENT */	}	return size;}static void __hba_ops_initialize(struct   mv_mod_desc *mod_desc,				 MV_U32   size,				 MV_U16   max_io){	PHBA_Extension phba;	MV_PTR_INTEGER temp;	MV_U32 i;	MV_U32 sg_num;#ifdef SUPPORT_EVENT	PDriver_Event_Entry pEvent = NULL;#endif /* SUPPORT_EVENT */    	phba     = (PHBA_Extension) mod_desc->extension;	temp     = (MV_PTR_INTEGER) phba->Memory_Pool;	WARN_ON(sizeof(MV_Request) != ROUNDING(sizeof(MV_Request), 8));	/* 	 * Initialize data structure however following variables have been 	 * set already.	 *	Device_Extension	 *	Is_Dump	 */	phba->State    = DRIVER_STATUS_IDLE;	phba->Io_Count = 0;	phba->Max_Io   = max_io;	phba->desc     = mod_desc;	init_completion(&phba->cmpl);	spin_lock_init(&phba->lock);	spin_lock_init(&phba->irq_lock);	temp = ROUNDING(((MV_PTR_INTEGER) temp), 8);	if (max_io > 1)		sg_num   = MAX_SG_ENTRY;	else		sg_num   = MAX_SG_ENTRY_REDUCED;	phba->req_pool = (MV_PVOID) res_reserve_req_pool(MODULE_HBA,							 max_io,							 sg_num);#ifdef SUPPORT_EVENT	INIT_LIST_HEAD(&phba->Stored_Events);	INIT_LIST_HEAD(&phba->Free_Events);	phba->Num_Stored_Events = 0;	phba->SequenceNumber = 0;	/* Event sequence number */	MV_ASSERT(sizeof(Driver_Event_Entry) == 		  ROUNDING(sizeof(Driver_Event_Entry), 8));	temp = ROUNDING(((MV_PTR_INTEGER) temp), 8);	for (i = 0; i < MAX_EVENTS; i++) {		pEvent = (PDriver_Event_Entry) temp;		list_add_tail(&pEvent->Queue_Pointer, &phba->Free_Events);		temp += sizeof(Driver_Event_Entry);	}#endif /* SUPPORT_EVENT */}static void __hba_ops_start(MV_PVOID extension){	struct Scsi_Host *host = NULL;	struct hba_extension *hba;	int ret;	hba = (struct hba_extension *) extension;	host = scsi_host_alloc(&mv_driver_template, sizeof(void *));	if (NULL == host) {		printk("%s : Unable to allocate a scsi host.\n", 		       mv_product_name);		goto err_out;	}	*((MV_PVOID *) host->hostdata) = extension;	hba->host = host;	hba->dev  = hba->desc->hba_desc->dev;	host->irq          = hba->dev->irq;	host->max_id       = MV_MAX_TARGET_NUMBER;	host->max_lun      = MV_MAX_LUN_NUMBER;	host->max_channel  = 0;	host->max_cmd_len  = 16;#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15)	host->transportt   = &mv_transport_template;#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 16) */#if USE_MSI	pci_enable_msi(hba->dev);#endif /* USE_MSI */#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 19)	ret = request_irq(hba->dev->irq, mv_intr_handler, IRQF_SHARED,			  mv_driver_name, hba);#else	ret = request_irq(hba->dev->irq, mv_intr_handler, SA_SHIRQ,			  mv_driver_name, hba);#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 19) */	if (ret < 0) {		printk("%s : Error upon requesting IRQ %d.\n", 		       mv_product_name, hba->dev->irq);		goto  err_request_irq;	}	hba->desc->status = MV_MOD_STARTED;	HBA_ModuleStarted(hba->desc);		/* wait for MODULE(CORE,RAID,HBA) init */	if (0 == wait_for_completion_timeout(&hba->cmpl, 25*HZ))		goto err_wait_cmpl;		hba_house_keeper_run();	if (scsi_add_host(host, &hba->dev->dev))		goto err_wait_cmpl;		scsi_scan_host(host);	if (mv_register_chdev(hba))		printk("Unable to register character device interface.\n");	return;err_wait_cmpl:	printk("Timeout waiting for module start.\n");	free_irq(hba->dev->irq, hba);err_request_irq:	scsi_host_put(host);	hba->host = NULL;err_out:	return;}extern void hba_send_shutdown_req(PHBA_Extension phba);static void __hba_ops_stop(MV_PVOID extension){	PHBA_Extension hba = (PHBA_Extension) extension;	mv_unregister_chdev(hba);	if (DRIVER_STATUS_STARTED == hba->State) {		scsi_remove_host(hba->host);		scsi_host_put(hba->host);		hba->host = NULL;		hba_send_shutdown_req(hba);		free_irq(hba->dev->irq, hba);	}	res_release_req_pool(hba->req_pool);	WARN_ON(hba->Io_Count != 0);}#ifdef SUPPORT_EVENTstatic MV_BOOLEAN add_event(IN MV_PVOID extension,			    IN MV_U32 eventID,			    IN MV_U16 deviceID,			    IN MV_U8 severityLevel,			    IN MV_U8 param_cnt,			    IN MV_PVOID params){	struct hba_extension * hba = (struct hba_extension *) extension;	PDriver_Event_Entry pEvent;	static MV_U32 sequenceNo = 1;	if (param_cnt > MAX_EVENT_PARAMS)		return MV_FALSE;	if (list_empty(&hba->Free_Events)) {		/* No free entry, we need to reuse the oldest entry from 		 * Stored_Events.		 */		MV_ASSERT(!list_empty(&hba->Stored_Events));		MV_ASSERT(hba->Num_Stored_Events == MAX_EVENTS);		pEvent = List_GetFirstEntry((&hba->Stored_Events), Driver_Event_Entry, Queue_Pointer);	}	else	{		pEvent = List_GetFirstEntry((&hba->Free_Events), Driver_Event_Entry, Queue_Pointer);		hba->Num_Stored_Events++;		MV_ASSERT(hba->Num_Stored_Events <= MAX_EVENTS);	}	pEvent->Event.AdapterID  = hba->desc->hba_desc->id;	pEvent->Event.EventID    = eventID; 	pEvent->Event.SequenceNo = sequenceNo++;	pEvent->Event.Severity   = severityLevel;	pEvent->Event.DeviceID   = deviceID;//	pEvent->Event.Param_Cnt  = param_cnt;	pEvent->Event.TimeStamp  = ossw_get_time_in_sec();	if (param_cnt > 0 && params != NULL)		MV_CopyMemory( (MV_PVOID)pEvent->Event.Params, (MV_PVOID)params, param_cnt * 4 );	list_add_tail(&pEvent->Queue_Pointer, &hba->Stored_Events);	return MV_TRUE;}static void get_event(MV_PVOID This, PMV_Request pReq){	struct hba_extension * hba = (struct hba_extension *) This;	PEventRequest pEventReq = (PEventRequest)pReq->Data_Buffer;	PDriver_Event_Entry pfirst_event;	MV_U8 count = 0;	pEventReq->Count = 0;		if ( hba->Num_Stored_Events > 0 )	{			MV_DASSERT( !list_empty(&hba->Stored_Events) );		while (!list_empty(&hba->Stored_Events) &&		       (count < MAX_EVENTS_RETURNED)) {			pfirst_event = List_GetFirstEntry((&hba->Stored_Events), Driver_Event_Entry, Queue_Pointer);			MV_CopyMemory(&pEventReq->Events[count], 				      &pfirst_event->Event, 				      sizeof(DriverEvent));			hba->Num_Stored_Events--;			list_add_tail(&pfirst_event->Queue_Pointer, 				      &hba->Free_Events );			count++;		}		pEventReq->Count = count;	}	pReq->Scsi_Status = REQ_STATUS_SUCCESS;	return;}#else /* SUPPORT_EVENT */static inline MV_BOOLEAN add_event(IN MV_PVOID extension,				   IN MV_U32 eventID,				   IN MV_U16 deviceID,				   IN MV_U8 severityLevel,				   IN MV_U8 param_cnt,				   IN MV_PVOID params) {}static inline void get_event(MV_PVOID This, PMV_Request pReq) {}#endif /* SUPPORT_EVENT */static void __hba_ops_notify(MV_PVOID This, 			     enum Module_Event event, 			     struct mod_notif_param *event_param){	switch (event) {	case EVENT_LOG_GENERATED:		add_event(This,			  event_param->event_id,			  event_param->dev_id,			  event_param->severity_lvl,			  event_param->param_count,			  event_param->p_param);		break;	case EVENT_DEVICE_REMOVAL:	case EVENT_DEVICE_ARRIVAL:		hba_msg_insert(This,			       event,			       (event_param == NULL)?0:event_param->lo);		break;	default:		break;	}}static void mvGetAdapterInfo(MV_PVOID This, PMV_Request pReq){	PHBA_Extension hba = (PHBA_Extension)This;	struct mv_adp_desc *hba_desc;	PAdapter_Info pAdInfo;	/* initialize */	hba_desc = hba->desc->hba_desc;	pAdInfo = (PAdapter_Info)pReq->Data_Buffer;	MV_ZeroMemory(pAdInfo, sizeof(Adapter_Info));	pAdInfo->DriverVersion.VerMajor = VER_MAJOR;	pAdInfo->DriverVersion.VerMinor = VER_MINOR;	pAdInfo->DriverVersion.VerOEM =   VER_OEM;	pAdInfo->DriverVersion.VerBuild = VER_BUILD;	pAdInfo->SystemIOBusNumber = hba_desc->Adapter_Bus_Number;	pAdInfo->SlotNumber        = hba_desc->Adapter_Device_Number;	pAdInfo->VenDevID          = hba_desc->Vendor_Id;	pAdInfo->SubVenDevID       = hba_desc->Device_Id;	if (hba_desc->Device_Id == DEVICE_ID_THORLITE_2S1P ||	     hba_desc->Device_Id == DEVICE_ID_THORLITE_2S1P_WITH_FLASH)		pAdInfo->PortCount = 3;	else if (hba_desc->Device_Id == DEVICE_ID_THORLITE_0S1P)		pAdInfo->PortCount = 1;	else		pAdInfo->PortCount = 5;	pAdInfo->AlarmSupport    = MV_FALSE;	pAdInfo->MaxBlockPerPD   = MAX_BLOCK_PER_HD_SUPPORTED;	pAdInfo->MaxHD           = MAX_DEVICE_SUPPORTED_PERFORMANCE;	pAdInfo->MaxExpander     = MAX_EXPANDER_SUPPORTED_PERFORMANCE;	pAdInfo->MaxPM           = MAX_PM_SUPPORTED;	pAdInfo->MaxLogicalDrive = MAX_LD_SUPPORTED_PERFORMANCE;#ifdef RAID_DRIVER	pAdInfo->AlarmSupport    = MV_FALSE;        pAdInfo->MaxTotalBlocks  = MAX_BLOCK_SUPPORTED_PERFORMANCE;        pAdInfo->MaxBlockPerPD   = MAX_BLOCK_PER_HD_SUPPORTED;        pAdInfo->MaxLogicalDrive = MAX_LD_SUPPORTED_PERFORMANCE;#if BGA_REBUILD_SUPPORT	pAdInfo->Features        |= FEATURE_BGA_REBUILD_SUPPORT;#endif /* BGA_REBUILD_SUPPORT */#if BGA_BKINIT_SUPPORT	pAdInfo->Features        |= FEATURE_BGA_BKINIT_SUPPORT;#endif /* BGA_BKINIT_SUPPORT */#if BGA_SYNC_SUPPORT	pAdInfo->Features        |= FEATURE_BGA_SYNC_SUPPORT;#endif /* BGA_SYNC_SUPPORT */#if BGA_MIGRATION_SUPPORT	pAdInfo->Features        |= FEATURE_BGA_MIGRATION_SUPPORT;#endif /* BGA_MIGRATION_SUPPORT */#endif /* RAID_DRIVER */	/* About Logical Driver Mode */#ifdef SUPPORT_RAID6	pAdInfo->LogicalDriverMode = SUPPORT_LD_MODE_RAID0 | 					SUPPORT_LD_MODE_RAID1 |					SUPPORT_LD_MODE_RAID5 |					SUPPORT_LD_MODE_RAID10 |					SUPPORT_LD_MODE_RAID1E |					SUPPORT_LD_MODE_RAID50;#elif defined(RAID_DRIVER)	pAdInfo->LogicalDriverMode = SUPPORT_LD_MODE_RAID0 |					SUPPORT_LD_MODE_RAID1 |					SUPPORT_LD_MODE_RAID10;#else	pAdInfo->LogicalDriverMode = 0;#endif /* SUPPORT_RAID6 */	pReq->Scsi_Status = REQ_STATUS_SUCCESS;}static void __hba_ops_send_request(MV_PVOID this, PMV_Request req){	PHBA_Extension phba = (PHBA_Extension) this;	switch (req->Cdb[0])	{	case APICDB0_ADAPTER:		if (req->Cdb[1] == APICDB1_ADAPTER_GETINFO)			mvGetAdapterInfo(phba, req);		else			req->Scsi_Status = REQ_STATUS_INVALID_REQUEST;		req->Completion(req->Cmd_Initiator, req);		break;	case APICDB0_EVENT:		if (req->Cdb[1] == APICDB1_EVENT_GETEVENT)			get_event(phba, req);		else			req->Scsi_Status = REQ_STATUS_INVALID_REQUEST;		req->Completion(req->Cmd_Initiator, req);		break;	default:		/* submit to child layer */		phba->desc->child->ops->module_sendrequest(			phba->desc->child->extension,			req);		break;	}}static struct mv_module_ops hba_module_interface = {	.module_id              = MODULE_HBA,	.get_res_desc           = __hba_get_res_desc,	.module_initialize      = __hba_ops_initialize,	.module_start           = __hba_ops_start,	.module_stop            = __hba_ops_stop,	.module_notification    = __hba_ops_notify,	.module_sendrequest     = __hba_ops_send_request,};struct mv_module_ops *mv_hba_register_module(void){	return &hba_module_interface;}

⌨️ 快捷键说明

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