diff options
Diffstat (limited to 'drivers/scsi/aacraid/linit.c')
| -rw-r--r-- | drivers/scsi/aacraid/linit.c | 538 |
1 files changed, 356 insertions, 182 deletions
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index a7f42a17b5c..4921ed19a02 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1,11 +1,12 @@ /* * Adaptec AAC series RAID controller driver - * (c) Copyright 2001 Red Hat Inc. <alan@redhat.com> + * (c) Copyright 2001 Red Hat Inc. * * 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,12 +38,13 @@ #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> #include <linux/syscalls.h> #include <linux/delay.h> #include <linux/kthread.h> -#include <asm/semaphore.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.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"); @@ -76,6 +77,7 @@ MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, " MODULE_LICENSE("GPL"); MODULE_VERSION(AAC_DRIVER_FULL_VERSION); +static DEFINE_MUTEX(aac_mutex); static LIST_HEAD(aac_devices); static int aac_cfg_major = -1; char aac_driver_version[] = AAC_DRIVER_FULL_VERSION; @@ -86,7 +88,7 @@ char aac_driver_version[] = AAC_DRIVER_FULL_VERSION; * * Note: The last field is used to index into aac_drivers below. */ -static struct pci_device_id aac_pci_tbl[] = { +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 */ @@ -154,32 +156,36 @@ static struct pci_device_id aac_pci_tbl[] = { { 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); /* - * dmb - For now we add the number of channels to this structure. + * dmb - For now we add the number of channels to this structure. * In the future we should add a fib that reports the number of channels * for the card. At that time we can remove the channels from here */ static struct aac_driver_ident aac_drivers[] = { - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 2/Si (Iguana/PERC2Si) */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Opal/PERC3Di) */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Si (SlimFast/PERC3Si */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Iguana FlipChip/PERC3DiF */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Viper/PERC3DiV) */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Lexus/PERC3DiL) */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Jaguar/PERC3DiJ) */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Dagger/PERC3DiD) */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* PERC 3/Di (Boxster/PERC3DiB) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* catapult */ - { aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* tomcat */ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec 2120S (Crusader) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec 2200S (Vulcan) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec 2200S (Vulcan-2m) */ - { aac_rx_init, "aacraid", "Legend ", "Legend S220 ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend S220 (Legend Crusader) */ - { aac_rx_init, "aacraid", "Legend ", "Legend S230 ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend S230 (Legend Vulcan) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* PERC 2/Si (Iguana/PERC2Si) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* PERC 3/Di (Opal/PERC3Di) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* PERC 3/Si (SlimFast/PERC3Si */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* PERC 3/Di (Iguana FlipChip/PERC3DiF */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* PERC 3/Di (Viper/PERC3DiV) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* PERC 3/Di (Lexus/PERC3DiL) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* PERC 3/Di (Jaguar/PERC3DiJ) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* PERC 3/Di (Dagger/PERC3DiD) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* PERC 3/Di (Boxster/PERC3DiB) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* catapult */ + { aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* tomcat */ + { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec 2120S (Crusader) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec 2200S (Vulcan) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Adaptec 2200S (Vulcan-2m) */ + { aac_rx_init, "aacraid", "Legend ", "Legend S220 ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend S220 (Legend Crusader) */ + { aac_rx_init, "aacraid", "Legend ", "Legend S230 ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend S230 (Legend Vulcan) */ { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3230S ", 2 }, /* Adaptec 3230S (Harrier) */ { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3240S ", 2 }, /* Adaptec 3240S (Tornado) */ @@ -224,11 +230,15 @@ static struct aac_driver_ident aac_drivers[] = { { aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4, AAC_QUIRK_34SG }, /* Dell PERC2/QC */ { aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4, AAC_QUIRK_34SG }, /* HP NetRAID-4M */ - { aac_rx_init, "aacraid", "DELL ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell Catchall */ - { aac_rx_init, "aacraid", "Legend ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend Catchall */ + { aac_rx_init, "aacraid", "DELL ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Dell Catchall */ + { 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 */ }; /** @@ -239,9 +249,9 @@ static struct aac_driver_ident aac_drivers[] = { * Queues a command for execution by the associated Host Adapter. * * 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; @@ -258,7 +268,9 @@ static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd } cmd->SCp.phase = AAC_OWNER_LOWLEVEL; return (aac_scsi_cmd(cmd) ? FAILED : 0); -} +} + +static DEF_SCSI_QCMD(aac_queuecommand) /** * aac_info - Returns the host adapter name @@ -275,9 +287,9 @@ static const char *aac_info(struct Scsi_Host *shost) /** * aac_get_driver_ident - * @devtype: index into lookup table + * @devtype: index into lookup table * - * Returns a pointer to the entry in the driver lookup table. + * Returns a pointer to the entry in the driver lookup table. */ struct aac_driver_ident* aac_get_driver_ident(int devtype) @@ -292,21 +304,21 @@ struct aac_driver_ident* aac_get_driver_ident(int devtype) * @capacity: the sector capacity of the disk * @geom: geometry block to fill in * - * Return the Heads/Sectors/Cylinders BIOS Disk Parameters for Disk. - * The default disk geometry is 64 heads, 32 sectors, and the appropriate - * number of cylinders so as not to exceed drive capacity. In order for + * Return the Heads/Sectors/Cylinders BIOS Disk Parameters for Disk. + * The default disk geometry is 64 heads, 32 sectors, and the appropriate + * number of cylinders so as not to exceed drive capacity. In order for * disks equal to or larger than 1 GB to be addressable by the BIOS - * without exceeding the BIOS limitation of 1024 cylinders, Extended - * Translation should be enabled. With Extended Translation enabled, - * drives between 1 GB inclusive and 2 GB exclusive are given a disk - * geometry of 128 heads and 32 sectors, and drives above 2 GB inclusive - * are given a disk geometry of 255 heads and 63 sectors. However, if - * the BIOS detects that the Extended Translation setting does not match - * the geometry in the partition table, then the translation inferred - * from the partition table will be used by the BIOS, and a warning may + * without exceeding the BIOS limitation of 1024 cylinders, Extended + * Translation should be enabled. With Extended Translation enabled, + * drives between 1 GB inclusive and 2 GB exclusive are given a disk + * geometry of 128 heads and 32 sectors, and drives above 2 GB inclusive + * are given a disk geometry of 255 heads and 63 sectors. However, if + * the BIOS detects that the Extended Translation setting does not match + * the geometry in the partition table, then the translation inferred + * from the partition table will be used by the BIOS, and a warning may * be displayed. */ - + static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int *geom) { @@ -333,10 +345,10 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, param->cylinders = cap_to_cyls(capacity, param->heads * param->sectors); - /* + /* * Read the first 1024 bytes from the disk device, if the boot * sector partition table is valid, search for a partition table - * entry whose end_head matches one of the standard geometry + * entry whose end_head matches one of the standard geometry * translations ( 64/32, 128/32, 255/63 ). */ buf = scsi_bios_ptable(bdev); @@ -401,30 +413,46 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, static int aac_slave_configure(struct scsi_device *sdev) { + struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata; + if (aac->jbod && (sdev->type == TYPE_DISK)) + sdev->removable = 1; if ((sdev->type == TYPE_DISK) && - (sdev_channel(sdev) != CONTAINER_CHANNEL)) { + (sdev_channel(sdev) != CONTAINER_CHANNEL) && + (!aac->jbod || sdev->inq_periph_qual) && + (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))) { if (expose_physicals == 0) return -ENXIO; - if (expose_physicals < 0) { - struct aac_dev *aac = - (struct aac_dev *)sdev->host->hostdata; - if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) - sdev->no_uld_attach = 1; - } + if (expose_physicals < 0) + sdev->no_uld_attach = 1; } if (sdev->tagged_supported && (sdev->type == TYPE_DISK) && - (sdev_channel(sdev) == CONTAINER_CHANNEL)) { + (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) && + !sdev->no_uld_attach) { struct scsi_device * dev; struct Scsi_Host *host = sdev->host; unsigned num_lsu = 0; unsigned num_one = 0; unsigned depth; + unsigned cid; + /* + * Firmware has an individual device recovery time typically + * of 35 seconds, give us a margin. + */ + if (sdev->request_queue->rq_timeout < (45 * HZ)) + blk_queue_rq_timeout(sdev->request_queue, 45*HZ); + for (cid = 0; cid < aac->maximum_num_containers; ++cid) + if (aac->fsa_dev[cid].valid) + ++num_lsu; __shost_for_each_device(dev, host) { if (dev->tagged_supported && (dev->type == TYPE_DISK) && - (sdev_channel(dev) == CONTAINER_CHANNEL)) - ++num_lsu; - else + (!aac->raid_scsi_mode || + (sdev_channel(sdev) != 2)) && + !dev->no_uld_attach) { + if ((sdev_channel(dev) != CONTAINER_CHANNEL) + || !aac->fsa_dev[sdev_id(dev)].valid) + ++num_lsu; + } else ++num_one; } if (num_lsu == 0) @@ -435,9 +463,6 @@ static int aac_slave_configure(struct scsi_device *sdev) else if (depth < 2) depth = 2; scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth); - if (!(((struct aac_dev *)host->hostdata)->adapter_info.options & - AAC_OPT_NEW_COMM)) - blk_queue_max_segment_size(sdev->request_queue, 65536); } else scsi_adjust_queue_depth(sdev, 0, 1); @@ -453,8 +478,12 @@ static int aac_slave_configure(struct scsi_device *sdev) * total capacity and the queue depth supported by the target device. */ -static int aac_change_queue_depth(struct scsi_device *sdev, int depth) +static int aac_change_queue_depth(struct scsi_device *sdev, int depth, + int reason) { + if (reason != SCSI_QDEPTH_DEFAULT) + return -EOPNOTSUPP; + if (sdev->tagged_supported && (sdev->type == TYPE_DISK) && (sdev_channel(sdev) == CONTAINER_CHANNEL)) { struct scsi_device * dev; @@ -481,9 +510,36 @@ static int aac_change_queue_depth(struct scsi_device *sdev, int depth) return sdev->queue_depth; } +static ssize_t aac_show_raid_level(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + struct aac_dev *aac = (struct aac_dev *)(sdev->host->hostdata); + if (sdev_channel(sdev) != CONTAINER_CHANNEL) + return snprintf(buf, PAGE_SIZE, sdev->no_uld_attach + ? "Hidden\n" : + ((aac->jbod && (sdev->type == TYPE_DISK)) ? "JBOD\n" : "")); + return snprintf(buf, PAGE_SIZE, "%s\n", + get_container_type(aac->fsa_dev[sdev_id(sdev)].type)); +} + +static struct device_attribute aac_raid_level_attr = { + .attr = { + .name = "level", + .mode = S_IRUGO, + }, + .show = aac_show_raid_level +}; + +static struct device_attribute *aac_dev_attrs[] = { + &aac_raid_level_attr, + NULL, +}; + static int aac_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_do_ioctl(dev, cmd, arg); } @@ -506,17 +562,33 @@ static int aac_eh_abort(struct scsi_cmnd* cmd) break; case INQUIRY: case READ_CAPACITY: - case TEST_UNIT_READY: /* Mark associated FIB to not complete, eh handler does this */ for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { struct fib * fib = &aac->fibs[count]; if (fib->hw_fib_va->header.XferState && + (fib->flags & FIB_CONTEXT_FLAG) && (fib->callback_data == cmd)) { fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER; ret = SUCCESS; } } + break; + case TEST_UNIT_READY: + /* Mark associated FIB to not complete, eh handler does this */ + for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { + struct scsi_cmnd * command; + struct fib * fib = &aac->fibs[count]; + if ((fib->hw_fib_va->header.XferState & cpu_to_le32(Async | NoResponseExpected)) && + (fib->flags & FIB_CONTEXT_FLAG) && + ((command = fib->callback_data)) && + (command->device == cmd->device)) { + fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; + command->SCp.phase = AAC_OWNER_ERROR_HANDLER; + if (command == cmd) + ret = SUCCESS; + } + } } return ret; } @@ -539,12 +611,13 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { struct fib * fib = &aac->fibs[count]; if (fib->hw_fib_va->header.XferState && + (fib->flags & FIB_CONTEXT_FLAG) && (fib->callback_data == cmd)) { fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER; } } - printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", + printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", AAC_DRIVERNAME); if ((count = aac_check_health(aac))) @@ -583,9 +656,14 @@ 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 & - le32_to_cpu(AAC_OPTION_MU_RESET|AAC_OPTION_IGNORE_RESET)) == - le32_to_cpu(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 & + AAC_OPTION_IGNORE_RESET))) aac_reset_adapter(aac, 2); /* Bypass wait for command quiesce */ return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */ } @@ -608,6 +686,7 @@ static int aac_cfg_open(struct inode *inode, struct file *file) unsigned minor_number = iminor(inode); int err = -ENODEV; + mutex_lock(&aac_mutex); /* BKL pushdown: nothing else protects this list */ list_for_each_entry(aac, &aac_devices, entry) { if (aac->id == minor_number) { file->private_data = aac; @@ -615,6 +694,7 @@ static int aac_cfg_open(struct inode *inode, struct file *file) break; } } + mutex_unlock(&aac_mutex); return err; } @@ -632,21 +712,26 @@ static int aac_cfg_open(struct inode *inode, struct file *file) * Bugs: Needs locking against parallel ioctls lower down * Bugs: Needs to handle hot plugging */ - -static int aac_cfg_ioctl(struct inode *inode, struct file *file, + +static long aac_cfg_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - if (!capable(CAP_SYS_ADMIN)) + int ret; + if (!capable(CAP_SYS_RAWIO)) return -EPERM; - return aac_do_ioctl(file->private_data, cmd, (void __user *)arg); + mutex_lock(&aac_mutex); + ret = aac_do_ioctl(file->private_data, cmd, (void __user *)arg); + mutex_unlock(&aac_mutex); + + return ret; } #ifdef CONFIG_COMPAT static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long arg) { long ret; - lock_kernel(); - switch (cmd) { + mutex_lock(&aac_mutex); + switch (cmd) { case FSACTL_MINIPORT_REV_CHECK: case FSACTL_SENDFIB: case FSACTL_OPEN_GET_ADAPTER_FIB: @@ -656,14 +741,14 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long case FSACTL_QUERY_DISK: case FSACTL_DELETE_DISK: case FSACTL_FORCE_DELETE_DISK: - case FSACTL_GET_CONTAINERS: + case FSACTL_GET_CONTAINERS: case FSACTL_SEND_LARGE_FIB: ret = aac_do_ioctl(dev, cmd, (void __user *)arg); break; case FSACTL_GET_NEXT_ADAPTER_FIB: { struct fib_ioctl __user *f; - + f = compat_alloc_user_space(sizeof(*f)); ret = 0; if (clear_user(f, sizeof(*f))) @@ -676,31 +761,33 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long } default: - ret = -ENOIOCTLCMD; + ret = -ENOIOCTLCMD; break; - } - unlock_kernel(); + } + mutex_unlock(&aac_mutex); return ret; } 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); } static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long arg) { - if (!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_RAWIO)) return -EPERM; - return aac_compat_do_ioctl((struct aac_dev *)file->private_data, cmd, arg); + return aac_compat_do_ioctl(file->private_data, cmd, arg); } #endif -static ssize_t aac_show_model(struct class_device *class_dev, - char *buf) +static ssize_t aac_show_model(struct device *device, + struct device_attribute *attr, char *buf) { - struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; + struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata; int len; if (dev->supplement_adapter_info.AdapterTypeText[0]) { @@ -716,10 +803,10 @@ static ssize_t aac_show_model(struct class_device *class_dev, return len; } -static ssize_t aac_show_vendor(struct class_device *class_dev, - char *buf) +static ssize_t aac_show_vendor(struct device *device, + struct device_attribute *attr, char *buf) { - struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; + struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata; int len; if (dev->supplement_adapter_info.AdapterTypeText[0]) { @@ -735,92 +822,127 @@ static ssize_t aac_show_vendor(struct class_device *class_dev, return len; } -static ssize_t aac_show_kernel_version(struct class_device *class_dev, - char *buf) +static ssize_t aac_show_flags(struct device *cdev, + struct device_attribute *attr, char *buf) { - struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; + int len = 0; + struct aac_dev *dev = (struct aac_dev*)class_to_shost(cdev)->hostdata; + + if (nblank(dprintk(x))) + len = snprintf(buf, PAGE_SIZE, "dprintk\n"); +#ifdef AAC_DETAILED_STATUS_INFO + len += snprintf(buf + len, PAGE_SIZE - len, + "AAC_DETAILED_STATUS_INFO\n"); +#endif + if (dev->raw_io_interface && dev->raw_io_64) + len += snprintf(buf + len, PAGE_SIZE - len, + "SAI_READ_CAPACITY_16\n"); + if (dev->jbod) + len += snprintf(buf + len, PAGE_SIZE - len, "SUPPORTED_JBOD\n"); + if (dev->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_POWER_MANAGEMENT) + len += snprintf(buf + len, PAGE_SIZE - len, + "SUPPORTED_POWER_MANAGEMENT\n"); + if (dev->msi) + len += snprintf(buf + len, PAGE_SIZE - len, "PCI_HAS_MSI\n"); + return len; +} + +static ssize_t aac_show_kernel_version(struct device *device, + struct device_attribute *attr, + char *buf) +{ + struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata; int len, tmp; tmp = le32_to_cpu(dev->adapter_info.kernelrev); - len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n", + len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n", tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff, le32_to_cpu(dev->adapter_info.kernelbuild)); return len; } -static ssize_t aac_show_monitor_version(struct class_device *class_dev, - char *buf) +static ssize_t aac_show_monitor_version(struct device *device, + struct device_attribute *attr, + char *buf) { - struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; + struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata; int len, tmp; tmp = le32_to_cpu(dev->adapter_info.monitorrev); - len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n", + len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n", tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff, le32_to_cpu(dev->adapter_info.monitorbuild)); return len; } -static ssize_t aac_show_bios_version(struct class_device *class_dev, - char *buf) +static ssize_t aac_show_bios_version(struct device *device, + struct device_attribute *attr, + char *buf) { - struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; + struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata; int len, tmp; tmp = le32_to_cpu(dev->adapter_info.biosrev); - len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n", + len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n", tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff, le32_to_cpu(dev->adapter_info.biosbuild)); return len; } -ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf) +static ssize_t aac_show_serial_number(struct device *device, + struct device_attribute *attr, char *buf) { - struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; + struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata; 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)+2-len], - buf, len)) - len = snprintf(buf, PAGE_SIZE, "%.*s\n", + sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo)-len], + buf, len-1)) + 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 class_device *class_dev, char *buf) +static ssize_t aac_show_max_channel(struct device *device, + struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", - class_to_shost(class_dev)->max_channel); + class_to_shost(device)->max_channel); } -static ssize_t aac_show_max_id(struct class_device *class_dev, char *buf) +static ssize_t aac_show_max_id(struct device *device, + struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", - class_to_shost(class_dev)->max_id); + class_to_shost(device)->max_id); } -static ssize_t aac_store_reset_adapter(struct class_device *class_dev, - const char *buf, size_t count) +static ssize_t aac_store_reset_adapter(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { int retval = -EACCES; if (!capable(CAP_SYS_ADMIN)) return retval; - retval = aac_reset_adapter((struct aac_dev*)class_to_shost(class_dev)->hostdata, buf[0] == '!'); + retval = aac_reset_adapter((struct aac_dev*)class_to_shost(device)->hostdata, buf[0] == '!'); if (retval >= 0) retval = count; return retval; } -static ssize_t aac_show_reset_adapter(struct class_device *class_dev, - char *buf) +static ssize_t aac_show_reset_adapter(struct device *device, + struct device_attribute *attr, + char *buf) { - struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; + struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata; int len, tmp; tmp = aac_adapter_check_health(dev); @@ -830,63 +952,70 @@ static ssize_t aac_show_reset_adapter(struct class_device *class_dev, return len; } -static struct class_device_attribute aac_model = { +static struct device_attribute aac_model = { .attr = { .name = "model", .mode = S_IRUGO, }, .show = aac_show_model, }; -static struct class_device_attribute aac_vendor = { +static struct device_attribute aac_vendor = { .attr = { .name = "vendor", .mode = S_IRUGO, }, .show = aac_show_vendor, }; -static struct class_device_attribute aac_kernel_version = { +static struct device_attribute aac_flags = { + .attr = { + .name = "flags", + .mode = S_IRUGO, + }, + .show = aac_show_flags, +}; +static struct device_attribute aac_kernel_version = { .attr = { .name = "hba_kernel_version", .mode = S_IRUGO, }, .show = aac_show_kernel_version, }; -static struct class_device_attribute aac_monitor_version = { +static struct device_attribute aac_monitor_version = { .attr = { .name = "hba_monitor_version", .mode = S_IRUGO, }, .show = aac_show_monitor_version, }; -static struct class_device_attribute aac_bios_version = { +static struct device_attribute aac_bios_version = { .attr = { .name = "hba_bios_version", .mode = S_IRUGO, }, .show = aac_show_bios_version, }; -static struct class_device_attribute aac_serial_number = { +static struct device_attribute aac_serial_number = { .attr = { .name = "serial_number", .mode = S_IRUGO, }, .show = aac_show_serial_number, }; -static struct class_device_attribute aac_max_channel = { +static struct device_attribute aac_max_channel = { .attr = { .name = "max_channel", .mode = S_IRUGO, }, .show = aac_show_max_channel, }; -static struct class_device_attribute aac_max_id = { +static struct device_attribute aac_max_id = { .attr = { .name = "max_id", .mode = S_IRUGO, }, .show = aac_show_max_id, }; -static struct class_device_attribute aac_reset = { +static struct device_attribute aac_reset = { .attr = { .name = "reset_host", .mode = S_IWUSR|S_IRUGO, @@ -895,9 +1024,10 @@ static struct class_device_attribute aac_reset = { .show = aac_show_reset_adapter, }; -static struct class_device_attribute *aac_attrs[] = { +static struct device_attribute *aac_attrs[] = { &aac_model, &aac_vendor, + &aac_flags, &aac_kernel_version, &aac_monitor_version, &aac_bios_version, @@ -908,55 +1038,73 @@ static struct class_device_attribute *aac_attrs[] = { NULL }; +ssize_t aac_get_serial_number(struct device *device, char *buf) +{ + return aac_show_serial_number(device, &aac_serial_number, buf); +} static const struct file_operations aac_cfg_fops = { .owner = THIS_MODULE, - .ioctl = aac_cfg_ioctl, + .unlocked_ioctl = aac_cfg_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = aac_compat_cfg_ioctl, #endif .open = aac_cfg_open, + .llseek = noop_llseek, }; static struct scsi_host_template aac_driver_template = { .module = THIS_MODULE, - .name = "AAC", + .name = "AAC", .proc_name = AAC_DRIVERNAME, - .info = aac_info, - .ioctl = aac_ioctl, + .info = aac_info, + .ioctl = aac_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = aac_compat_ioctl, #endif - .queuecommand = aac_queuecommand, - .bios_param = aac_biosparm, + .queuecommand = aac_queuecommand, + .bios_param = aac_biosparm, .shost_attrs = aac_attrs, .slave_configure = aac_slave_configure, .change_queue_depth = aac_change_queue_depth, + .sdev_attrs = aac_dev_attrs, .eh_abort_handler = aac_eh_abort, .eh_host_reset_handler = aac_eh_reset, - .can_queue = AAC_NUM_IO_FIB, - .this_id = MAXIMUM_NUM_CONTAINERS, - .sg_tablesize = 16, - .max_sectors = 128, + .can_queue = AAC_NUM_IO_FIB, + .this_id = MAXIMUM_NUM_CONTAINERS, + .sg_tablesize = 16, + .max_sectors = 128, #if (AAC_NUM_IO_FIB > 256) .cmd_per_lun = 256, -#else - .cmd_per_lun = AAC_NUM_IO_FIB, -#endif +#else + .cmd_per_lun = AAC_NUM_IO_FIB, +#endif .use_clustering = ENABLE_CLUSTERING, - .emulated = 1, + .emulated = 1, + .no_write_same = 1, }; static void __aac_shutdown(struct aac_dev * aac) { - kthread_stop(aac->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); + if (aac->msi) + 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; @@ -964,6 +1112,8 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, struct list_head *insert = &aac_devices; 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) @@ -972,23 +1122,27 @@ 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; error = -ENODEV; - if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) || - pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) - goto out_disable_pdev; /* * If the quirk31 bit is set, the adapter needs adapter * to driver communication memory to be allocated below 2gig */ - if (aac_drivers[index].quirks & AAC_QUIRK_31BIT) - if (pci_set_dma_mask(pdev, DMA_31BIT_MASK) || - pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK)) - goto out_disable_pdev; - + if (aac_drivers[index].quirks & AAC_QUIRK_31BIT) + dmamask = DMA_BIT_MASK(31); + else + dmamask = DMA_BIT_MASK(32); + + if (pci_set_dma_mask(pdev, dmamask) || + pci_set_consistent_dma_mask(pdev, dmamask)) + goto out_disable_pdev; + pci_set_master(pdev); shost = scsi_host_alloc(&aac_driver_template, sizeof(struct aac_dev)); @@ -996,19 +1150,19 @@ 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->scsi_host_ptr = shost; + aac->base_start = pci_resource_start(pdev, 0); + aac->scsi_host_ptr = shost; aac->pdev = pdev; aac->name = aac_driver_template.name; aac->id = shost->unique_id; - aac->cardtype = index; + 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); @@ -1020,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 */ @@ -1027,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; } @@ -1036,45 +1206,49 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, * address space. */ if (aac_drivers[index].quirks & AAC_QUIRK_31BIT) - if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) goto out_deinit; - + aac->maximum_num_channels = aac_drivers[index].channels; error = aac_get_adapter_info(aac); if (error < 0) goto out_deinit; /* - * Lets override negotiations and drop the maximum SG limit to 34 - */ - if ((aac_drivers[index].quirks & AAC_QUIRK_34SG) && - (aac->scsi_host_ptr->sg_tablesize > 34)) { - aac->scsi_host_ptr->sg_tablesize = 34; - aac->scsi_host_ptr->max_sectors - = (aac->scsi_host_ptr->sg_tablesize * 8) + 112; - } - - if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) && - (aac->scsi_host_ptr->sg_tablesize > 17)) { - aac->scsi_host_ptr->sg_tablesize = 17; - aac->scsi_host_ptr->max_sectors - = (aac->scsi_host_ptr->sg_tablesize * 8) + 112; - } + * Lets override negotiations and drop the maximum SG limit to 34 + */ + if ((aac_drivers[index].quirks & AAC_QUIRK_34SG) && + (shost->sg_tablesize > 34)) { + shost->sg_tablesize = 34; + shost->max_sectors = (shost->sg_tablesize * 8) + 112; + } + + if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) && + (shost->sg_tablesize > 17)) { + shost->sg_tablesize = 17; + shost->max_sectors = (shost->sg_tablesize * 8) + 112; + } + + error = pci_set_dma_max_seg_size(pdev, + (aac->adapter_info.options & AAC_OPT_NEW_COMM) ? + (shost->max_sectors << 9) : 65536); + if (error) + goto out_deinit; /* - * Firware printf works only with older firmware. + * Firmware printf works only with older firmware. */ - if (aac_drivers[index].quirks & AAC_QUIRK_34SG) + if (aac_drivers[index].quirks & AAC_QUIRK_34SG) aac->printf_enabled = 1; else aac->printf_enabled = 0; - - /* + + /* * max channel will be the physical channels plus 1 virtual channel * all containers are on the virtual channel 0 (CONTAINER_CHANNEL) * physical channels are address by their actual physical number+1 */ - if ((aac->nondasd_support == 1) || expose_physicals) + if (aac->nondasd_support || expose_physicals || aac->jbod) shost->max_channel = aac->maximum_num_channels; else shost->max_channel = 0; @@ -1132,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; @@ -1146,10 +1320,10 @@ static void __devexit aac_remove_one(struct pci_dev *pdev) kfree(aac->queues); aac_adapter_ioremap(aac, 0); - + kfree(aac->fibs); kfree(aac->fsa_dev); - + list_del(&aac->entry); scsi_host_put(shost); pci_disable_device(pdev); @@ -1163,14 +1337,14 @@ 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), - .shutdown = aac_shutdown, + .remove = aac_remove_one, + .shutdown = aac_shutdown, }; static int __init aac_init(void) { int error; - + printk(KERN_INFO "Adaptec %s driver %s\n", AAC_DRIVERNAME, aac_driver_version); @@ -1181,7 +1355,7 @@ static int __init aac_init(void) aac_cfg_major = register_chrdev( 0, "aac", &aac_cfg_fops); if (aac_cfg_major < 0) { printk(KERN_WARNING - "aacraid: unable to register \"aac\" device.\n"); + "aacraid: unable to register \"aac\" device.\n"); } return 0; |
