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

📄 aic94xx_init.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
struct kmem_cache *asd_dma_token_cache;struct kmem_cache *asd_ascb_cache;static int asd_create_global_caches(void){	if (!asd_dma_token_cache) {		asd_dma_token_cache			= kmem_cache_create(ASD_DRIVER_NAME "_dma_token",					    sizeof(struct asd_dma_tok),					    0,					    SLAB_HWCACHE_ALIGN,					    NULL);		if (!asd_dma_token_cache) {			asd_printk("couldn't create dma token cache\n");			return -ENOMEM;		}	}	if (!asd_ascb_cache) {		asd_ascb_cache = kmem_cache_create(ASD_DRIVER_NAME "_ascb",						   sizeof(struct asd_ascb),						   0,						   SLAB_HWCACHE_ALIGN,						   NULL);		if (!asd_ascb_cache) {			asd_printk("couldn't create ascb cache\n");			goto Err;		}	}	return 0;Err:	kmem_cache_destroy(asd_dma_token_cache);	asd_dma_token_cache = NULL;	return -ENOMEM;}static void asd_destroy_global_caches(void){	if (asd_dma_token_cache)		kmem_cache_destroy(asd_dma_token_cache);	asd_dma_token_cache = NULL;	if (asd_ascb_cache)		kmem_cache_destroy(asd_ascb_cache);	asd_ascb_cache = NULL;}static int asd_register_sas_ha(struct asd_ha_struct *asd_ha){	int i;	struct asd_sas_phy   **sas_phys =		kmalloc(ASD_MAX_PHYS * sizeof(struct asd_sas_phy), GFP_KERNEL);	struct asd_sas_port  **sas_ports =		kmalloc(ASD_MAX_PHYS * sizeof(struct asd_sas_port), GFP_KERNEL);	if (!sas_phys || !sas_ports) {		kfree(sas_phys);		kfree(sas_ports);		return -ENOMEM;	}	asd_ha->sas_ha.sas_ha_name = (char *) asd_ha->name;	asd_ha->sas_ha.lldd_module = THIS_MODULE;	asd_ha->sas_ha.sas_addr = &asd_ha->hw_prof.sas_addr[0];	for (i = 0; i < ASD_MAX_PHYS; i++) {		sas_phys[i] = &asd_ha->phys[i].sas_phy;		sas_ports[i] = &asd_ha->ports[i];	}	asd_ha->sas_ha.sas_phy = sas_phys;	asd_ha->sas_ha.sas_port= sas_ports;	asd_ha->sas_ha.num_phys= ASD_MAX_PHYS;	asd_ha->sas_ha.lldd_queue_size = asd_ha->seq.can_queue;	asd_ha->sas_ha.lldd_max_execute_num = lldd_max_execute_num;	return sas_register_ha(&asd_ha->sas_ha);}static int asd_unregister_sas_ha(struct asd_ha_struct *asd_ha){	int err;	err = sas_unregister_ha(&asd_ha->sas_ha);	sas_remove_host(asd_ha->sas_ha.core.shost);	scsi_remove_host(asd_ha->sas_ha.core.shost);	scsi_host_put(asd_ha->sas_ha.core.shost);	kfree(asd_ha->sas_ha.sas_phy);	kfree(asd_ha->sas_ha.sas_port);	return err;}static int __devinit asd_pci_probe(struct pci_dev *dev,				   const struct pci_device_id *id){	struct asd_pcidev_struct *asd_dev;	unsigned asd_id = (unsigned) id->driver_data;	struct asd_ha_struct *asd_ha;	struct Scsi_Host *shost;	int err;	if (asd_id >= ARRAY_SIZE(asd_pcidev_data)) {		asd_printk("wrong driver_data in PCI table\n");		return -ENODEV;	}	if ((err = pci_enable_device(dev))) {		asd_printk("couldn't enable device %s\n", pci_name(dev));		return err;	}	pci_set_master(dev);	err = -ENOMEM;	shost = scsi_host_alloc(&aic94xx_sht, sizeof(void *));	if (!shost)		goto Err;	asd_dev = &asd_pcidev_data[asd_id];	asd_ha = kzalloc(sizeof(*asd_ha), GFP_KERNEL);	if (!asd_ha) {		asd_printk("out of memory\n");		goto Err_put;	}	asd_ha->pcidev = dev;	asd_ha->sas_ha.dev = &asd_ha->pcidev->dev;	asd_ha->sas_ha.lldd_ha = asd_ha;	asd_ha->name = asd_dev->name;	asd_printk("found %s, device %s\n", asd_ha->name, pci_name(dev));	SHOST_TO_SAS_HA(shost) = &asd_ha->sas_ha;	asd_ha->sas_ha.core.shost = shost;	shost->transportt = aic94xx_transport_template;	shost->max_id = ~0;	shost->max_lun = ~0;	shost->max_cmd_len = 16;	err = scsi_add_host(shost, &dev->dev);	if (err)		goto Err_free;	err = asd_dev->setup(asd_ha);	if (err)		goto Err_remove;	err = -ENODEV;	if (!pci_set_dma_mask(dev, DMA_64BIT_MASK)	    && !pci_set_consistent_dma_mask(dev, DMA_64BIT_MASK))		;	else if (!pci_set_dma_mask(dev, DMA_32BIT_MASK)		 && !pci_set_consistent_dma_mask(dev, DMA_32BIT_MASK))		;	else {		asd_printk("no suitable DMA mask for %s\n", pci_name(dev));		goto Err_remove;	}	pci_set_drvdata(dev, asd_ha);	err = asd_map_ha(asd_ha);	if (err)		goto Err_remove;	err = asd_create_ha_caches(asd_ha);        if (err)		goto Err_unmap;	err = asd_init_hw(asd_ha);	if (err)		goto Err_free_cache;	asd_printk("device %s: SAS addr %llx, PCBA SN %s, %d phys, %d enabled "		   "phys, flash %s, BIOS %s%d\n",		   pci_name(dev), SAS_ADDR(asd_ha->hw_prof.sas_addr),		   asd_ha->hw_prof.pcba_sn, asd_ha->hw_prof.max_phys,		   asd_ha->hw_prof.num_phys,		   asd_ha->hw_prof.flash.present ? "present" : "not present",		   asd_ha->hw_prof.bios.present ? "build " : "not present",		   asd_ha->hw_prof.bios.bld);	shost->can_queue = asd_ha->seq.can_queue;	if (use_msi)		pci_enable_msi(asd_ha->pcidev);	err = request_irq(asd_ha->pcidev->irq, asd_hw_isr, IRQF_SHARED,			  ASD_DRIVER_NAME, asd_ha);	if (err) {		asd_printk("couldn't get irq %d for %s\n",			   asd_ha->pcidev->irq, pci_name(asd_ha->pcidev));		goto Err_irq;	}	asd_enable_ints(asd_ha);	err = asd_init_post_escbs(asd_ha);	if (err) {		asd_printk("couldn't post escbs for %s\n",			   pci_name(asd_ha->pcidev));		goto Err_escbs;	}	ASD_DPRINTK("escbs posted\n");	err = asd_create_dev_attrs(asd_ha);	if (err)		goto Err_dev_attrs;	err = asd_register_sas_ha(asd_ha);	if (err)		goto Err_reg_sas;	scsi_scan_host(shost);	return 0;Err_reg_sas:	asd_remove_dev_attrs(asd_ha);Err_dev_attrs:Err_escbs:	asd_disable_ints(asd_ha);	free_irq(dev->irq, asd_ha);Err_irq:	if (use_msi)		pci_disable_msi(dev);	asd_chip_hardrst(asd_ha);Err_free_cache:	asd_destroy_ha_caches(asd_ha);Err_unmap:	asd_unmap_ha(asd_ha);Err_remove:	scsi_remove_host(shost);Err_free:	kfree(asd_ha);Err_put:	scsi_host_put(shost);Err:	pci_disable_device(dev);	return err;}static void asd_free_queues(struct asd_ha_struct *asd_ha){	unsigned long flags;	LIST_HEAD(pending);	struct list_head *n, *pos;	spin_lock_irqsave(&asd_ha->seq.pend_q_lock, flags);	asd_ha->seq.pending = 0;	list_splice_init(&asd_ha->seq.pend_q, &pending);	spin_unlock_irqrestore(&asd_ha->seq.pend_q_lock, flags);	if (!list_empty(&pending))		ASD_DPRINTK("Uh-oh! Pending is not empty!\n");	list_for_each_safe(pos, n, &pending) {		struct asd_ascb *ascb = list_entry(pos, struct asd_ascb, list);		/*		 * Delete unexpired ascb timers.  This may happen if we issue		 * a CONTROL PHY scb to an adapter and rmmod before the scb		 * times out.  Apparently we don't wait for the CONTROL PHY		 * to complete, so it doesn't matter if we kill the timer.		 */		del_timer_sync(&ascb->timer);		WARN_ON(ascb->scb->header.opcode != CONTROL_PHY);		list_del_init(pos);		ASD_DPRINTK("freeing from pending\n");		asd_ascb_free(ascb);	}}static void asd_turn_off_leds(struct asd_ha_struct *asd_ha){	u8 phy_mask = asd_ha->hw_prof.enabled_phys;	u8 i;	for_each_phy(phy_mask, phy_mask, i) {		asd_turn_led(asd_ha, i, 0);		asd_control_led(asd_ha, i, 0);	}}static void __devexit asd_pci_remove(struct pci_dev *dev){	struct asd_ha_struct *asd_ha = pci_get_drvdata(dev);	if (!asd_ha)		return;	asd_unregister_sas_ha(asd_ha);	asd_disable_ints(asd_ha);	asd_remove_dev_attrs(asd_ha);	/* XXX more here as needed */	free_irq(dev->irq, asd_ha);	if (use_msi)		pci_disable_msi(asd_ha->pcidev);	asd_turn_off_leds(asd_ha);	asd_chip_hardrst(asd_ha);	asd_free_queues(asd_ha);	asd_destroy_ha_caches(asd_ha);	asd_unmap_ha(asd_ha);	kfree(asd_ha);	pci_disable_device(dev);	return;}static void asd_scan_start(struct Scsi_Host *shost){	struct asd_ha_struct *asd_ha;	int err;	asd_ha = SHOST_TO_SAS_HA(shost)->lldd_ha;	err = asd_enable_phys(asd_ha, asd_ha->hw_prof.enabled_phys);	if (err)		asd_printk("Couldn't enable phys, err:%d\n", err);}static int asd_scan_finished(struct Scsi_Host *shost, unsigned long time){	/* give the phy enabling interrupt event time to come in (1s	 * is empirically about all it takes) */	if (time < HZ)		return 0;	/* Wait for discovery to finish */	scsi_flush_work(shost);	return 1;}static ssize_t asd_version_show(struct device_driver *driver, char *buf){	return snprintf(buf, PAGE_SIZE, "%s\n", ASD_DRIVER_VERSION);}static DRIVER_ATTR(version, S_IRUGO, asd_version_show, NULL);static int asd_create_driver_attrs(struct device_driver *driver){	return driver_create_file(driver, &driver_attr_version);}static void asd_remove_driver_attrs(struct device_driver *driver){	driver_remove_file(driver, &driver_attr_version);}static struct sas_domain_function_template aic94xx_transport_functions = {	.lldd_dev_found		= asd_dev_found,	.lldd_dev_gone		= asd_dev_gone,	.lldd_execute_task	= asd_execute_task,	.lldd_abort_task	= asd_abort_task,	.lldd_abort_task_set	= asd_abort_task_set,	.lldd_clear_aca		= asd_clear_aca,	.lldd_clear_task_set	= asd_clear_task_set,	.lldd_I_T_nexus_reset	= NULL,	.lldd_lu_reset		= asd_lu_reset,	.lldd_query_task	= asd_query_task,	.lldd_clear_nexus_port	= asd_clear_nexus_port,	.lldd_clear_nexus_ha	= asd_clear_nexus_ha,	.lldd_control_phy	= asd_control_phy,};static const struct pci_device_id aic94xx_pci_table[] __devinitdata = {	{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x410),0, 0, 1},	{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x412),0, 0, 1},	{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x416),0, 0, 1},	{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x41E),0, 0, 1},	{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x41F),0, 0, 1},	{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x430),0, 0, 2},	{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x432),0, 0, 2},	{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x43E),0, 0, 2},	{PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x43F),0, 0, 2},	{}};MODULE_DEVICE_TABLE(pci, aic94xx_pci_table);static struct pci_driver aic94xx_pci_driver = {	.name		= ASD_DRIVER_NAME,	.id_table	= aic94xx_pci_table,	.probe		= asd_pci_probe,	.remove		= __devexit_p(asd_pci_remove),};static int __init aic94xx_init(void){	int err;	asd_printk("%s version %s loaded\n", ASD_DRIVER_DESCRIPTION,		   ASD_DRIVER_VERSION);	err = asd_create_global_caches();	if (err)		return err;	aic94xx_transport_template =		sas_domain_attach_transport(&aic94xx_transport_functions);	if (!aic94xx_transport_template)		goto out_destroy_caches;	err = pci_register_driver(&aic94xx_pci_driver);	if (err)		goto out_release_transport;	err = asd_create_driver_attrs(&aic94xx_pci_driver.driver);	if (err)		goto out_unregister_pcidrv;	return err; out_unregister_pcidrv:	pci_unregister_driver(&aic94xx_pci_driver); out_release_transport:	sas_release_transport(aic94xx_transport_template); out_destroy_caches:	asd_destroy_global_caches();	return err;}static void __exit aic94xx_exit(void){	asd_remove_driver_attrs(&aic94xx_pci_driver.driver);	pci_unregister_driver(&aic94xx_pci_driver);	sas_release_transport(aic94xx_transport_template);	asd_release_firmware();	asd_destroy_global_caches();	asd_printk("%s version %s unloaded\n", ASD_DRIVER_DESCRIPTION,		   ASD_DRIVER_VERSION);}module_init(aic94xx_init);module_exit(aic94xx_exit);MODULE_AUTHOR("Luben Tuikov <luben_tuikov@adaptec.com>");MODULE_DESCRIPTION(ASD_DRIVER_DESCRIPTION);MODULE_LICENSE("GPL v2");MODULE_VERSION(ASD_DRIVER_VERSION);

⌨️ 快捷键说明

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