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

📄 megaraid_mbox.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		goto out_free_adapter;	}	// Initialize the synchronization lock for kernel and LLD	spin_lock_init(&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 pci_dev *pdev){	adapter_t		*adapter = pci_get_drvdata(pdev);	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;	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, DMA_64BIT_MASK) != 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);	return -1;}/** * megaraid_fini_mbox - undo controller initialization * @param adapter	: our soft state */static voidmegaraid_fini_mbox(adapter_t *adapter){	mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);	// flush all caches	megaraid_mbox_flush_cache(adapter);	tasklet_kill(&adapter->dpc_h);	megaraid_sysfs_free_resources(adapter);	megaraid_free_cmd_packets(adapter);	free_irq(adapter->irq, adapter);	iounmap(raid_dev->baseaddr);	pci_release_regions(adapter->pdev);	kfree(raid_dev);	return;}/** * megaraid_alloc_cmd_packets - allocate shared mailbox * @param adapter	: soft state of the raid controller * * Allocate and align the shared mailbox. This maibox is used to issue * all the commands. For IO based controllers, the mailbox is also regsitered * with the FW. Allocate memory for all commands as well. * This is our big allocator */static intmegaraid_alloc_cmd_packets(adapter_t *adapter){	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);	struct pci_dev		*pdev;	unsigned long		align;	scb_t			*scb;	mbox_ccb_t		*ccb;	struct mraid_pci_blk	*epthru_pci_blk;	struct mraid_pci_blk	*sg_pci_blk;	struct mraid_pci_blk	*mbox_pci_blk;	int			i;	pdev = adapter->pdev;	/*	 * Setup the mailbox	 * Allocate the common 16-byte aligned memory for the handshake	 * mailbox.	 */	raid_dev->una_mbox64 = pci_alloc_consistent(adapter->pdev,			sizeof(mbox64_t), &raid_dev->una_mbox64_dma);	if (!raid_dev->una_mbox64) {		con_log(CL_ANN, (KERN_WARNING			"megaraid: out of memory, %s %d\n", __FUNCTION__,			__LINE__));		return -1;	}	memset(raid_dev->una_mbox64, 0, sizeof(mbox64_t));	/*	 * Align the mailbox at 16-byte boundary	 */	raid_dev->mbox	= &raid_dev->una_mbox64->mbox32;	raid_dev->mbox	= (mbox_t *)((((unsigned long)raid_dev->mbox) + 15) &				(~0UL ^ 0xFUL));	raid_dev->mbox64 = (mbox64_t *)(((unsigned long)raid_dev->mbox) - 8);	align = ((void *)raid_dev->mbox -			((void *)&raid_dev->una_mbox64->mbox32));	raid_dev->mbox_dma = (unsigned long)raid_dev->una_mbox64_dma + 8 +			align;	// Allocate memory for commands issued internally	adapter->ibuf = pci_alloc_consistent(pdev, MBOX_IBUF_SIZE,				&adapter->ibuf_dma_h);	if (!adapter->ibuf) {		con_log(CL_ANN, (KERN_WARNING

⌨️ 快捷键说明

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