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

📄 megaraid_mbox.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		con_log(CL_ANN, (KERN_WARNING			"megaraid mailbox: max commands per lun reset to %d\n",			MBOX_MAX_SCSI_CMDS));		megaraid_cmd_per_lun = MBOX_MAX_SCSI_CMDS;	}	// register as a PCI hot-plug driver module	if ((rval = pci_module_init(&megaraid_pci_driver_g))) {		con_log(CL_ANN, (KERN_WARNING			"megaraid: could not register hotplug support.\n"));	}	return rval;}/** * megaraid_exit - driver unload entry point * * We simply unwrap the megaraid_init routine here */static void __exitmegaraid_exit(void){	con_log(CL_DLEVEL1, (KERN_NOTICE "megaraid: unloading framework\n"));	// unregister as PCI hotplug driver	pci_unregister_driver(&megaraid_pci_driver_g);	return;}/** * megaraid_probe_one - PCI hotplug entry point * @param pdev	: handle to this controller's PCI configuration space * @param id	: pci device id of the class of controllers * * This routine should be called whenever a new adapter is detected by the * PCI hotplug susbsytem. **/static int __devinitmegaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id){	adapter_t	*adapter;	// detected a new controller	con_log(CL_ANN, (KERN_INFO		"megaraid: probe new device %#4.04x:%#4.04x:%#4.04x:%#4.04x: ",		pdev->vendor, pdev->device, pdev->subsystem_vendor,		pdev->subsystem_device));	con_log(CL_ANN, ("bus %d:slot %d:func %d\n", pdev->bus->number,		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)));	if (pci_enable_device(pdev)) {		con_log(CL_ANN, (KERN_WARNING				"megaraid: pci_enable_device failed\n"));		return -ENODEV;	}	// Enable bus-mastering on this controller	pci_set_master(pdev);	// Allocate the per driver initialization structure	adapter = kmalloc(sizeof(adapter_t), GFP_KERNEL);	if (adapter == NULL) {		con_log(CL_ANN, (KERN_WARNING		"megaraid: out of memory, %s %d.\n", __FUNCTION__, __LINE__));		goto out_probe_one;	}	memset(adapter, 0, sizeof(adapter_t));	// set up PCI related soft state and other pre-known parameters	adapter->unique_id	= pdev->bus->number << 8 | pdev->devfn;	adapter->irq		= pdev->irq;	adapter->pdev		= pdev;	atomic_set(&adapter->being_detached, 0);	// Setup the default DMA mask. This would be changed later on	// depending on hardware capabilities	if (pci_set_dma_mask(adapter->pdev, 0xFFFFFFFF) != 0) {		con_log(CL_ANN, (KERN_WARNING			"megaraid: pci_set_dma_mask failed:%d\n", __LINE__));		goto out_free_adapter;	}	// Initialize the synchronization lock for kernel and LLD	spin_lock_init(&adapter->lock);	adapter->host_lock = &adapter->lock;	// Initialize the command queues: the list of free SCBs and the list	// of pending SCBs.	INIT_LIST_HEAD(&adapter->kscb_pool);	spin_lock_init(SCSI_FREE_LIST_LOCK(adapter));	INIT_LIST_HEAD(&adapter->pend_list);	spin_lock_init(PENDING_LIST_LOCK(adapter));	INIT_LIST_HEAD(&adapter->completed_list);	spin_lock_init(COMPLETED_LIST_LOCK(adapter));	// Start the mailbox based controller	if (megaraid_init_mbox(adapter) != 0) {		con_log(CL_ANN, (KERN_WARNING			"megaraid: maibox adapter did not initialize\n"));		goto out_free_adapter;	}	// Register with LSI Common Management Module	if (megaraid_cmm_register(adapter) != 0) {		con_log(CL_ANN, (KERN_WARNING		"megaraid: could not register with management module\n"));		goto out_fini_mbox;	}	// setup adapter handle in PCI soft state	pci_set_drvdata(pdev, adapter);	// attach with scsi mid-layer	if (megaraid_io_attach(adapter) != 0) {		con_log(CL_ANN, (KERN_WARNING "megaraid: io attach failed\n"));		goto out_cmm_unreg;	}	return 0;out_cmm_unreg:	pci_set_drvdata(pdev, NULL);	megaraid_cmm_unregister(adapter);out_fini_mbox:	megaraid_fini_mbox(adapter);out_free_adapter:	kfree(adapter);out_probe_one:	pci_disable_device(pdev);	return -ENODEV;}/** * megaraid_detach_one - release the framework resources and call LLD release * routine * @param pdev	: handle for our PCI cofiguration space * * This routine is called during driver unload. We free all the allocated * resources and call the corresponding LLD so that it can also release all * its resources. * * This routine is also called from the PCI hotplug system **/static voidmegaraid_detach_one(struct pci_dev *pdev){	adapter_t		*adapter;	struct Scsi_Host	*host;	// Start a rollback on this adapter	adapter = pci_get_drvdata(pdev);	if (!adapter) {		con_log(CL_ANN, (KERN_CRIT		"megaraid: Invalid detach on %#4.04x:%#4.04x:%#4.04x:%#4.04x\n",			pdev->vendor, pdev->device, pdev->subsystem_vendor,			pdev->subsystem_device));		return;	}	else {		con_log(CL_ANN, (KERN_NOTICE		"megaraid: detaching device %#4.04x:%#4.04x:%#4.04x:%#4.04x\n",			pdev->vendor, pdev->device, pdev->subsystem_vendor,			pdev->subsystem_device));	}	host = adapter->host;	// do not allow any more requests from the management module for this	// adapter.	// FIXME: How do we account for the request which might still be	// pending with us?	atomic_set(&adapter->being_detached, 1);	// detach from the IO sub-system	megaraid_io_detach(adapter);	// reset the device state in the PCI structure. We check this	// condition when we enter here. If the device state is NULL,	// that would mean the device has already been removed	pci_set_drvdata(pdev, NULL);	// Unregister from common management module	//	// FIXME: this must return success or failure for conditions if there	// is a command pending with LLD or not.	megaraid_cmm_unregister(adapter);	// finalize the mailbox based controller and release all resources	megaraid_fini_mbox(adapter);	kfree(adapter);	scsi_host_put(host);	pci_disable_device(pdev);	return;}/** * megaraid_mbox_shutdown - PCI shutdown for megaraid HBA * @param device	: generice driver model device * * Shutdown notification, perform flush cache */static voidmegaraid_mbox_shutdown(struct device *device){	adapter_t		*adapter = pci_get_drvdata(to_pci_dev(device));	static int		counter;	if (!adapter) {		con_log(CL_ANN, (KERN_WARNING			"megaraid: null device in shutdown\n"));		return;	}	// flush caches now	con_log(CL_ANN, (KERN_INFO "megaraid: flushing adapter %d...",		counter++));	megaraid_mbox_flush_cache(adapter);	con_log(CL_ANN, ("done\n"));}/** * megaraid_io_attach - attach a device with the IO subsystem * @param adapter	: controller's soft state * * Attach this device with the IO subsystem **/static intmegaraid_io_attach(adapter_t *adapter){	struct Scsi_Host	*host;	// Initialize SCSI Host structure	host = scsi_host_alloc(&megaraid_template_g, 8);	if (!host) {		con_log(CL_ANN, (KERN_WARNING			"megaraid mbox: scsi_register failed\n"));		return -1;	}	SCSIHOST2ADAP(host)	= (caddr_t)adapter;	adapter->host		= host;	// export the parameters required by the mid-layer	scsi_assign_lock(host, adapter->host_lock);	scsi_set_device(host, &adapter->pdev->dev);	host->irq		= adapter->irq;	host->unique_id		= adapter->unique_id;	host->can_queue		= adapter->max_cmds;	host->this_id		= adapter->init_id;	host->sg_tablesize	= adapter->sglen;	host->max_sectors	= adapter->max_sectors;	host->cmd_per_lun	= adapter->cmd_per_lun;	host->max_channel	= adapter->max_channel;	host->max_id		= adapter->max_target;	host->max_lun		= adapter->max_lun;	// notify mid-layer about the new controller	if (scsi_add_host(host, &adapter->pdev->dev)) {		con_log(CL_ANN, (KERN_WARNING			"megaraid mbox: scsi_add_host failed\n"));		scsi_host_put(host);		return -1;	}	scsi_scan_host(host);	return 0;}/** * megaraid_io_detach - detach a device from the IO subsystem * @param adapter	: controller's soft state * * Detach this device from the IO subsystem **/static voidmegaraid_io_detach(adapter_t *adapter){	struct Scsi_Host	*host;	con_log(CL_DLEVEL1, (KERN_INFO "megaraid: io detach\n"));	host = adapter->host;	scsi_remove_host(host);	return;}/* * START: Mailbox Low Level Driver * * This is section specific to the single mailbox based controllers *//** * megaraid_init_mbox - initialize controller * @param adapter	- our soft state * * . Allocate 16-byte aligned mailbox memory for firmware handshake * . Allocate controller's memory resources * . Find out all initialization data * . Allocate memory required for all the commands * . Use internal library of FW routines, build up complete soft state */static int __initmegaraid_init_mbox(adapter_t *adapter){	struct pci_dev		*pdev;	mraid_device_t		*raid_dev;	int			i;	adapter->ito	= MBOX_TIMEOUT;	pdev		= adapter->pdev;	/*	 * Allocate and initialize the init data structure for mailbox	 * controllers	 */	raid_dev = kmalloc(sizeof(mraid_device_t), GFP_KERNEL);	if (raid_dev == NULL) return -1;	memset(raid_dev, 0, sizeof(mraid_device_t));	/*	 * Attach the adapter soft state to raid device soft state	 */	adapter->raid_device	= (caddr_t)raid_dev;	raid_dev->fast_load	= megaraid_fast_load;	// our baseport	raid_dev->baseport = pci_resource_start(pdev, 0);	if (pci_request_regions(pdev, "MegaRAID: LSI Logic Corporation") != 0) {		con_log(CL_ANN, (KERN_WARNING				"megaraid: mem region busy\n"));		goto out_free_raid_dev;	}	raid_dev->baseaddr = ioremap_nocache(raid_dev->baseport, 128);	if (!raid_dev->baseaddr) {		con_log(CL_ANN, (KERN_WARNING			"megaraid: could not map hba memory\n") );		goto out_release_regions;	}	//	// Setup the rest of the soft state using the library of FW routines	//	// request IRQ and register the interrupt service routine	if (request_irq(adapter->irq, megaraid_isr, SA_SHIRQ, "megaraid",		adapter)) {		con_log(CL_ANN, (KERN_WARNING			"megaraid: Couldn't register IRQ %d!\n", adapter->irq));		goto out_iounmap;	}	// initialize the mutual exclusion lock for the mailbox	spin_lock_init(&raid_dev->mailbox_lock);	// allocate memory required for commands	if (megaraid_alloc_cmd_packets(adapter) != 0) {		goto out_free_irq;	}	// Product info	if (megaraid_mbox_product_info(adapter) != 0) {		goto out_alloc_cmds;	}	// Do we support extended CDBs	adapter->max_cdb_sz = 10;	if (megaraid_mbox_extended_cdb(adapter) == 0) {		adapter->max_cdb_sz = 16;	}	/*	 * Do we support cluster environment, if we do, what is the initiator	 * id.	 * NOTE: In a non-cluster aware firmware environment, the LLD should	 * return 7 as initiator id.	 */	adapter->ha		= 0;	adapter->init_id	= -1;	if (megaraid_mbox_support_ha(adapter, &adapter->init_id) == 0) {		adapter->ha = 1;	}	/*	 * Prepare the device ids array to have the mapping between the kernel	 * device address and megaraid device address.	 * We export the physical devices on their actual addresses. The	 * logical drives are exported on a virtual SCSI channel	 */	megaraid_mbox_setup_device_map(adapter);	// If the firmware supports random deletion, update the device id map	if (megaraid_mbox_support_random_del(adapter)) {		// Change the logical drives numbers in device_ids array one		// slot in device_ids is reserved for target id, that's why		// "<=" below		for (i = 0; i <= MAX_LOGICAL_DRIVES_40LD; i++) {			adapter->device_ids[adapter->max_channel][i] += 0x80;		}		adapter->device_ids[adapter->max_channel][adapter->init_id] =			0xFF;		raid_dev->random_del_supported = 1;	}	/*	 * find out the maximum number of scatter-gather elements supported by	 * this firmware	 */	adapter->sglen = megaraid_mbox_get_max_sg(adapter);	// enumerate RAID and SCSI channels so that all devices on SCSI	// channels can later be exported, including disk devices	megaraid_mbox_enum_raid_scsi(adapter);	/*	 * Other parameters required by upper layer	 *	 * maximum number of sectors per IO command	 */	adapter->max_sectors = megaraid_max_sectors;	/*	 * number of queued commands per LUN.	 */	adapter->cmd_per_lun = megaraid_cmd_per_lun;	/*	 * Allocate resources required to issue FW calls, when sysfs is	 * accessed	 */	if (megaraid_sysfs_alloc_resources(adapter) != 0) {		goto out_alloc_cmds;	}	// Set the DMA mask to 64-bit. All supported controllers as capable of	// DMA in this range	if (pci_set_dma_mask(adapter->pdev, 0xFFFFFFFFFFFFFFFFULL) != 0) {		con_log(CL_ANN, (KERN_WARNING			"megaraid: could not set DMA mask for 64-bit.\n"));		goto out_free_sysfs_res;	}	// setup tasklet for DPC	tasklet_init(&adapter->dpc_h, megaraid_mbox_dpc,			(unsigned long)adapter);	con_log(CL_DLEVEL1, (KERN_INFO		"megaraid mbox hba successfully initialized\n"));	return 0;out_free_sysfs_res:	megaraid_sysfs_free_resources(adapter);out_alloc_cmds:	megaraid_free_cmd_packets(adapter);out_free_irq:	free_irq(adapter->irq, adapter);out_iounmap:	iounmap(raid_dev->baseaddr);out_release_regions:	pci_release_regions(pdev);out_free_raid_dev:	kfree(raid_dev);

⌨️ 快捷键说明

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