diff options
Diffstat (limited to 'drivers/scsi/aacraid/linit.c')
| -rw-r--r-- | drivers/scsi/aacraid/linit.c | 89 | 
1 files changed, 64 insertions, 25 deletions
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 29c0ed1cf50..4921ed19a02 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -5,7 +5,8 @@   * based on the old aacraid driver that is..   * Adaptec aacraid device driver for Linux.   * - * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2010 Adaptec, Inc. + *               2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by @@ -37,6 +38,7 @@  #include <linux/module.h>  #include <linux/moduleparam.h>  #include <linux/pci.h> +#include <linux/pci-aspm.h>  #include <linux/slab.h>  #include <linux/mutex.h>  #include <linux/spinlock.h> @@ -54,11 +56,10 @@  #include "aacraid.h" -#define AAC_DRIVER_VERSION		"1.1-5" +#define AAC_DRIVER_VERSION		"1.2-0"  #ifndef AAC_DRIVER_BRANCH  #define AAC_DRIVER_BRANCH		""  #endif -#define AAC_DRIVER_BUILD_DATE		__DATE__ " " __TIME__  #define AAC_DRIVERNAME			"aacraid"  #ifdef AAC_DRIVER_BUILD @@ -66,7 +67,7 @@  #define str(x) _str(x)  #define AAC_DRIVER_FULL_VERSION	AAC_DRIVER_VERSION "[" str(AAC_DRIVER_BUILD) "]" AAC_DRIVER_BRANCH  #else -#define AAC_DRIVER_FULL_VERSION	AAC_DRIVER_VERSION AAC_DRIVER_BRANCH " " AAC_DRIVER_BUILD_DATE +#define AAC_DRIVER_FULL_VERSION	AAC_DRIVER_VERSION AAC_DRIVER_BRANCH  #endif  MODULE_AUTHOR("Red Hat Inc and Adaptec"); @@ -87,13 +88,7 @@ char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;   *   * Note: The last field is used to index into aac_drivers below.   */ -#ifdef DECLARE_PCI_DEVICE_TABLE -static DECLARE_PCI_DEVICE_TABLE(aac_pci_tbl) = { -#elif defined(__devinitconst) -static const struct pci_device_id aac_pci_tbl[] __devinitconst = { -#else -static const struct pci_device_id aac_pci_tbl[] __devinitdata = { -#endif +static const struct pci_device_id aac_pci_tbl[] = {  	{ 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */  	{ 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */  	{ 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si (SlimFast/PERC3Si */ @@ -161,6 +156,10 @@ static const struct pci_device_id aac_pci_tbl[] __devinitdata = {  	{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */  	{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */  	{ 0x9005, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 61 }, /* Adaptec NEMER/ARK Catch All */ +	{ 0x9005, 0x028b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 62 }, /* Adaptec PMC Series 6 (Tupelo) */ +	{ 0x9005, 0x028c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 63 }, /* Adaptec PMC Series 7 (Denali) */ +	{ 0x9005, 0x028d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 64 }, /* Adaptec PMC Series 8 */ +	{ 0x9005, 0x028f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 65 }, /* Adaptec PMC Series 9 */  	{ 0,}  };  MODULE_DEVICE_TABLE(pci, aac_pci_tbl); @@ -235,7 +234,11 @@ static struct aac_driver_ident aac_drivers[] = {  	{ aac_rx_init, "aacraid",  "Legend  ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend Catchall */  	{ aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Catch All */  	{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Rocket Catch All */ -	{ aac_nark_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec NEMER/ARK Catch All */ +	{ aac_nark_init, "aacraid", "ADAPTEC ", "RAID           ", 2 }, /* Adaptec NEMER/ARK Catch All */ +	{ aac_src_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec PMC Series 6 (Tupelo) */ +	{ aac_srcv_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec PMC Series 7 (Denali) */ +	{ aac_srcv_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec PMC Series 8 */ +	{ aac_srcv_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec PMC Series 9 */  };  /** @@ -248,7 +251,7 @@ static struct aac_driver_ident aac_drivers[] = {   *	TODO: unify with aac_scsi_cmd().   */ -static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) +static int aac_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))  {  	struct Scsi_Host *host = cmd->device->host;  	struct aac_dev *dev = (struct aac_dev *)host->hostdata; @@ -267,6 +270,8 @@ static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd  	return (aac_scsi_cmd(cmd) ? FAILED : 0);  } +static DEF_SCSI_QCMD(aac_queuecommand) +  /**   *	aac_info		-	Returns the host adapter name   *	@shost:		Scsi host to report on @@ -651,8 +656,10 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)  	 * This adapter needs a blind reset, only do so for Adapters that  	 * support a register, instead of a commanded, reset.  	 */ -	if ((aac->supplement_adapter_info.SupportedOptions2 & -	   AAC_OPTION_MU_RESET) && +	if (((aac->supplement_adapter_info.SupportedOptions2 & +	  AAC_OPTION_MU_RESET) || +	  (aac->supplement_adapter_info.SupportedOptions2 & +	  AAC_OPTION_DOORBELL_RESET)) &&  	  aac_check_reset &&  	  ((aac_check_reset != 1) ||  	   !(aac->supplement_adapter_info.SupportedOptions2 & @@ -764,6 +771,8 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long  static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)  {  	struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata; +	if (!capable(CAP_SYS_RAWIO)) +		return -EPERM;  	return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg);  } @@ -888,16 +897,17 @@ static ssize_t aac_show_serial_number(struct device *device,  	int len = 0;  	if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0) -		len = snprintf(buf, PAGE_SIZE, "%06X\n", +		len = snprintf(buf, 16, "%06X\n",  		  le32_to_cpu(dev->adapter_info.serial[0]));  	if (len &&  	  !memcmp(&dev->supplement_adapter_info.MfgPcbaSerialNo[  	    sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo)-len],  	  buf, len-1)) -		len = snprintf(buf, PAGE_SIZE, "%.*s\n", +		len = snprintf(buf, 16, "%.*s\n",  		  (int)sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo),  		  dev->supplement_adapter_info.MfgPcbaSerialNo); -	return len; + +	return min(len, 16);  }  static ssize_t aac_show_max_channel(struct device *device, @@ -1071,12 +1081,22 @@ static struct scsi_host_template aac_driver_template = {  #endif  	.use_clustering			= ENABLE_CLUSTERING,  	.emulated			= 1, +	.no_write_same			= 1,  };  static void __aac_shutdown(struct aac_dev * aac)  { -	if (aac->aif_thread) +	if (aac->aif_thread) { +		int i; +		/* Clear out events first */ +		for (i = 0; i < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i++) { +			struct fib *fib = &aac->fibs[i]; +			if (!(fib->hw_fib_va->header.XferState & cpu_to_le32(NoResponseExpected | Async)) && +			    (fib->hw_fib_va->header.XferState & cpu_to_le32(ResponseExpected))) +				up(&fib->event_wait); +		}  		kthread_stop(aac->thread); +	}  	aac_send_shutdown(aac);  	aac_adapter_disable_int(aac);  	free_irq(aac->pdev->irq, aac); @@ -1084,8 +1104,7 @@ static void __aac_shutdown(struct aac_dev * aac)  		pci_disable_msi(aac->pdev);  } -static int __devinit aac_probe_one(struct pci_dev *pdev, -		const struct pci_device_id *id) +static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)  {  	unsigned index = id->driver_data;  	struct Scsi_Host *shost; @@ -1094,6 +1113,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,  	int error = -ENODEV;  	int unique_id = 0;  	u64 dmamask; +	extern int aac_sync_mode;  	list_for_each_entry(aac, &aac_devices, entry) {  		if (aac->id > unique_id) @@ -1102,6 +1122,9 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,  		unique_id++;  	} +	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | +			       PCIE_LINK_STATE_CLKPM); +  	error = pci_enable_device(pdev);  	if (error)  		goto out; @@ -1127,11 +1150,11 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,  		goto out_disable_pdev;  	shost->irq = pdev->irq; -	shost->base = pci_resource_start(pdev, 0);  	shost->unique_id = unique_id;  	shost->max_cmd_len = 16;  	aac = (struct aac_dev *)shost->hostdata; +	aac->base_start = pci_resource_start(pdev, 0);  	aac->scsi_host_ptr = shost;  	aac->pdev = pdev;  	aac->name = aac_driver_template.name; @@ -1139,7 +1162,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,  	aac->cardtype = index;  	INIT_LIST_HEAD(&aac->entry); -	aac->fibs = kmalloc(sizeof(struct fib) * (shost->can_queue + AAC_NUM_MGT_FIB), GFP_KERNEL); +	aac->fibs = kzalloc(sizeof(struct fib) * (shost->can_queue + AAC_NUM_MGT_FIB), GFP_KERNEL);  	if (!aac->fibs)  		goto out_free_host;  	spin_lock_init(&aac->fib_lock); @@ -1151,6 +1174,21 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,  	if ((*aac_drivers[index].init)(aac))  		goto out_unmap; +	if (aac->sync_mode) { +		if (aac_sync_mode) +			printk(KERN_INFO "%s%d: Sync. mode enforced " +				"by driver parameter. This will cause " +				"a significant performance decrease!\n", +				aac->name, +				aac->id); +		else +			printk(KERN_INFO "%s%d: Async. mode not supported " +				"by current driver, sync. mode enforced." +				"\nPlease update driver to get full performance.\n", +				aac->name, +				aac->id); +	} +  	/*  	 *	Start any kernel threads needed  	 */ @@ -1158,6 +1196,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,  	if (IS_ERR(aac->thread)) {  		printk(KERN_ERR "aacraid: Unable to create command thread.\n");  		error = PTR_ERR(aac->thread); +		aac->thread = NULL;  		goto out_deinit;  	} @@ -1267,7 +1306,7 @@ static void aac_shutdown(struct pci_dev *dev)  	__aac_shutdown((struct aac_dev *)shost->hostdata);  } -static void __devexit aac_remove_one(struct pci_dev *pdev) +static void aac_remove_one(struct pci_dev *pdev)  {  	struct Scsi_Host *shost = pci_get_drvdata(pdev);  	struct aac_dev *aac = (struct aac_dev *)shost->hostdata; @@ -1298,7 +1337,7 @@ static struct pci_driver aac_pci_driver = {  	.name		= AAC_DRIVERNAME,  	.id_table	= aac_pci_tbl,  	.probe		= aac_probe_one, -	.remove		= __devexit_p(aac_remove_one), +	.remove		= aac_remove_one,  	.shutdown	= aac_shutdown,  };  | 
