Merge branch 'for-2.6.38/drivers' of git://git.kernel.dk/linux-2.6-block
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Jan 2011 18:50:24 +0000 (10:50 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Jan 2011 18:50:24 +0000 (10:50 -0800)
* 'for-2.6.38/drivers' of git://git.kernel.dk/linux-2.6-block:
  cciss: reinstate proper FIFO order of command queue list
  floppy: replace NO_GEOM macro with a function

1  2 
drivers/block/cciss.c
drivers/block/cciss.h
drivers/block/floppy.c

diff --combined drivers/block/cciss.c
@@@ -26,6 -26,7 +26,6 @@@
  #include <linux/pci.h>
  #include <linux/kernel.h>
  #include <linux/slab.h>
 -#include <linux/smp_lock.h>
  #include <linux/delay.h>
  #include <linux/major.h>
  #include <linux/fs.h>
@@@ -65,8 -66,11 +65,8 @@@ MODULE_SUPPORTED_DEVICE("HP Smart Arra
  MODULE_VERSION("3.6.26");
  MODULE_LICENSE("GPL");
  
 -static int cciss_allow_hpsa;
 -module_param(cciss_allow_hpsa, int, S_IRUGO|S_IWUSR);
 -MODULE_PARM_DESC(cciss_allow_hpsa,
 -      "Prevent cciss driver from accessing hardware known to be "
 -      " supported by the hpsa driver");
 +static DEFINE_MUTEX(cciss_mutex);
 +static struct proc_dir_entry *proc_cciss;
  
  #include "cciss_cmd.h"
  #include "cciss.h"
@@@ -94,6 -98,18 +94,6 @@@ static const struct pci_device_id cciss
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSD,     0x103C, 0x3215},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x3237},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x323D},
 -      {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3241},
 -      {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3243},
 -      {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3245},
 -      {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3247},
 -      {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3249},
 -      {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324A},
 -      {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324B},
 -      {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3250},
 -      {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3251},
 -      {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3252},
 -      {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3253},
 -      {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3254},
        {0,}
  };
  
@@@ -114,8 -130,6 +114,8 @@@ static struct board_type products[] = 
        {0x409D0E11, "Smart Array 6400 EM", &SA5_access},
        {0x40910E11, "Smart Array 6i", &SA5_access},
        {0x3225103C, "Smart Array P600", &SA5_access},
 +      {0x3223103C, "Smart Array P800", &SA5_access},
 +      {0x3234103C, "Smart Array P400", &SA5_access},
        {0x3235103C, "Smart Array P400i", &SA5_access},
        {0x3211103C, "Smart Array E200i", &SA5_access},
        {0x3212103C, "Smart Array E200", &SA5_access},
        {0x3214103C, "Smart Array E200i", &SA5_access},
        {0x3215103C, "Smart Array E200i", &SA5_access},
        {0x3237103C, "Smart Array E500", &SA5_access},
 -/* controllers below this line are also supported by the hpsa driver. */
 -#define HPSA_BOUNDARY 0x3223103C
        {0x3223103C, "Smart Array P800", &SA5_access},
        {0x3234103C, "Smart Array P400", &SA5_access},
        {0x323D103C, "Smart Array P700m", &SA5_access},
 -      {0x3241103C, "Smart Array P212", &SA5_access},
 -      {0x3243103C, "Smart Array P410", &SA5_access},
 -      {0x3245103C, "Smart Array P410i", &SA5_access},
 -      {0x3247103C, "Smart Array P411", &SA5_access},
 -      {0x3249103C, "Smart Array P812", &SA5_access},
 -      {0x324A103C, "Smart Array P712m", &SA5_access},
 -      {0x324B103C, "Smart Array P711m", &SA5_access},
 -      {0x3250103C, "Smart Array", &SA5_access},
 -      {0x3251103C, "Smart Array", &SA5_access},
 -      {0x3252103C, "Smart Array", &SA5_access},
 -      {0x3253103C, "Smart Array", &SA5_access},
 -      {0x3254103C, "Smart Array", &SA5_access},
  };
  
  /* How long to wait (in milliseconds) for board to go into simple mode */
@@@ -238,9 -266,9 +238,9 @@@ static void set_performant_mode(ctlr_in
  /*
   * Enqueuing and dequeuing functions for cmdlists.
   */
- static inline void addQ(struct hlist_head *list, CommandList_struct *c)
+ static inline void addQ(struct list_head *list, CommandList_struct *c)
  {
-       hlist_add_head(&c->list, list);
+       list_add_tail(&c->list, list);
  }
  
  static inline void removeQ(CommandList_struct *c)
         * them off as 'stale' to prevent the driver from
         * falling over.
         */
-       if (WARN_ON(hlist_unhashed(&c->list))) {
+       if (WARN_ON(list_empty(&c->list))) {
                c->cmd_type = CMD_MSG_STALE;
                return;
        }
  
-       hlist_del_init(&c->list);
+       list_del_init(&c->list);
  }
  
  static void enqueue_cmd_and_start_io(ctlr_info_t *h,
@@@ -364,6 -392,8 +364,6 @@@ static const char *raid_label[] = { "0"
  #define ENG_GIG_FACTOR (ENG_GIG/512)
  #define ENGAGE_SCSI   "engage scsi"
  
 -static struct proc_dir_entry *proc_cciss;
 -
  static void cciss_seq_show_header(struct seq_file *seq)
  {
        ctlr_info_t *h = seq->private;
@@@ -905,7 -935,7 +905,7 @@@ static CommandList_struct *cmd_alloc(ct
  
        c->cmdindex = i;
  
-       INIT_HLIST_NODE(&c->list);
+       INIT_LIST_HEAD(&c->list);
        c->busaddr = (__u32) cmd_dma_handle;
        temp64.val = (__u64) err_dma_handle;
        c->ErrDesc.Addr.lower = temp64.val32.lower;
@@@ -944,7 -974,7 +944,7 @@@ static CommandList_struct *cmd_special_
        }
        memset(c->err_info, 0, sizeof(ErrorInfo_struct));
  
-       INIT_HLIST_NODE(&c->list);
+       INIT_LIST_HEAD(&c->list);
        c->busaddr = (__u32) cmd_dma_handle;
        temp64.val = (__u64) err_dma_handle;
        c->ErrDesc.Addr.lower = temp64.val32.lower;
@@@ -1029,9 -1059,9 +1029,9 @@@ static int cciss_unlocked_open(struct b
  {
        int ret;
  
 -      lock_kernel();
 +      mutex_lock(&cciss_mutex);
        ret = cciss_open(bdev, mode);
 -      unlock_kernel();
 +      mutex_unlock(&cciss_mutex);
  
        return ret;
  }
@@@ -1044,13 -1074,13 +1044,13 @@@ static int cciss_release(struct gendis
        ctlr_info_t *h;
        drive_info_struct *drv;
  
 -      lock_kernel();
 +      mutex_lock(&cciss_mutex);
        h = get_host(disk);
        drv = get_drv(disk);
        dev_dbg(&h->pdev->dev, "cciss_release %s\n", disk->disk_name);
        drv->usage_count--;
        h->usage_count--;
 -      unlock_kernel();
 +      mutex_unlock(&cciss_mutex);
        return 0;
  }
  
@@@ -1058,9 -1088,9 +1058,9 @@@ static int do_ioctl(struct block_devic
                    unsigned cmd, unsigned long arg)
  {
        int ret;
 -      lock_kernel();
 +      mutex_lock(&cciss_mutex);
        ret = cciss_ioctl(bdev, mode, cmd, arg);
 -      unlock_kernel();
 +      mutex_unlock(&cciss_mutex);
        return ret;
  }
  
@@@ -1152,7 -1182,6 +1152,7 @@@ static int cciss_ioctl32_big_passthru(s
        int err;
        u32 cp;
  
 +      memset(&arg64, 0, sizeof(arg64));
        err = 0;
        err |=
            copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
@@@ -1203,452 -1232,470 +1203,452 @@@ static void check_ioctl_unit_attention(
                        c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION)
                (void)check_for_unit_attention(h, c);
  }
 -/*
 - * ioctl
 - */
 -static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
 -                     unsigned int cmd, unsigned long arg)
 +
 +static int cciss_getpciinfo(ctlr_info_t *h, void __user *argp)
  {
 -      struct gendisk *disk = bdev->bd_disk;
 -      ctlr_info_t *h = get_host(disk);
 -      drive_info_struct *drv = get_drv(disk);
 -      void __user *argp = (void __user *)arg;
 +      cciss_pci_info_struct pciinfo;
  
 -      dev_dbg(&h->pdev->dev, "cciss_ioctl: Called with cmd=%x %lx\n",
 -              cmd, arg);
 -      switch (cmd) {
 -      case CCISS_GETPCIINFO:
 -              {
 -                      cciss_pci_info_struct pciinfo;
 -
 -                      if (!arg)
 -                              return -EINVAL;
 -                      pciinfo.domain = pci_domain_nr(h->pdev->bus);
 -                      pciinfo.bus = h->pdev->bus->number;
 -                      pciinfo.dev_fn = h->pdev->devfn;
 -                      pciinfo.board_id = h->board_id;
 -                      if (copy_to_user
 -                          (argp, &pciinfo, sizeof(cciss_pci_info_struct)))
 -                              return -EFAULT;
 -                      return 0;
 -              }
 -      case CCISS_GETINTINFO:
 -              {
 -                      cciss_coalint_struct intinfo;
 -                      if (!arg)
 -                              return -EINVAL;
 -                      intinfo.delay =
 -                          readl(&h->cfgtable->HostWrite.CoalIntDelay);
 -                      intinfo.count =
 -                          readl(&h->cfgtable->HostWrite.CoalIntCount);
 -                      if (copy_to_user
 -                          (argp, &intinfo, sizeof(cciss_coalint_struct)))
 -                              return -EFAULT;
 -                      return 0;
 -              }
 -      case CCISS_SETINTINFO:
 -              {
 -                      cciss_coalint_struct intinfo;
 -                      unsigned long flags;
 -                      int i;
 -
 -                      if (!arg)
 -                              return -EINVAL;
 -                      if (!capable(CAP_SYS_ADMIN))
 -                              return -EPERM;
 -                      if (copy_from_user
 -                          (&intinfo, argp, sizeof(cciss_coalint_struct)))
 -                              return -EFAULT;
 -                      if ((intinfo.delay == 0) && (intinfo.count == 0))
 -                              return -EINVAL;
 -                      spin_lock_irqsave(&h->lock, flags);
 -                      /* Update the field, and then ring the doorbell */
 -                      writel(intinfo.delay,
 -                             &(h->cfgtable->HostWrite.CoalIntDelay));
 -                      writel(intinfo.count,
 -                             &(h->cfgtable->HostWrite.CoalIntCount));
 -                      writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
 -
 -                      for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
 -                              if (!(readl(h->vaddr + SA5_DOORBELL)
 -                                    & CFGTBL_ChangeReq))
 -                                      break;
 -                              /* delay and try again */
 -                              udelay(1000);
 -                      }
 -                      spin_unlock_irqrestore(&h->lock, flags);
 -                      if (i >= MAX_IOCTL_CONFIG_WAIT)
 -                              return -EAGAIN;
 -                      return 0;
 -              }
 -      case CCISS_GETNODENAME:
 -              {
 -                      NodeName_type NodeName;
 -                      int i;
 -
 -                      if (!arg)
 -                              return -EINVAL;
 -                      for (i = 0; i < 16; i++)
 -                              NodeName[i] =
 -                                  readb(&h->cfgtable->ServerName[i]);
 -                      if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
 -                              return -EFAULT;
 -                      return 0;
 -              }
 -      case CCISS_SETNODENAME:
 -              {
 -                      NodeName_type NodeName;
 -                      unsigned long flags;
 -                      int i;
 +      if (!argp)
 +              return -EINVAL;
 +      pciinfo.domain = pci_domain_nr(h->pdev->bus);
 +      pciinfo.bus = h->pdev->bus->number;
 +      pciinfo.dev_fn = h->pdev->devfn;
 +      pciinfo.board_id = h->board_id;
 +      if (copy_to_user(argp, &pciinfo, sizeof(cciss_pci_info_struct)))
 +              return -EFAULT;
 +      return 0;
 +}
  
 -                      if (!arg)
 -                              return -EINVAL;
 -                      if (!capable(CAP_SYS_ADMIN))
 -                              return -EPERM;
 +static int cciss_getintinfo(ctlr_info_t *h, void __user *argp)
 +{
 +      cciss_coalint_struct intinfo;
  
 -                      if (copy_from_user
 -                          (NodeName, argp, sizeof(NodeName_type)))
 -                              return -EFAULT;
 +      if (!argp)
 +              return -EINVAL;
 +      intinfo.delay = readl(&h->cfgtable->HostWrite.CoalIntDelay);
 +      intinfo.count = readl(&h->cfgtable->HostWrite.CoalIntCount);
 +      if (copy_to_user
 +          (argp, &intinfo, sizeof(cciss_coalint_struct)))
 +              return -EFAULT;
 +      return 0;
 +}
  
 -                      spin_lock_irqsave(&h->lock, flags);
 +static int cciss_setintinfo(ctlr_info_t *h, void __user *argp)
 +{
 +      cciss_coalint_struct intinfo;
 +      unsigned long flags;
 +      int i;
  
 -                      /* Update the field, and then ring the doorbell */
 -                      for (i = 0; i < 16; i++)
 -                              writeb(NodeName[i],
 -                                     &h->cfgtable->ServerName[i]);
 +      if (!argp)
 +              return -EINVAL;
 +      if (!capable(CAP_SYS_ADMIN))
 +              return -EPERM;
 +      if (copy_from_user(&intinfo, argp, sizeof(intinfo)))
 +              return -EFAULT;
 +      if ((intinfo.delay == 0) && (intinfo.count == 0))
 +              return -EINVAL;
 +      spin_lock_irqsave(&h->lock, flags);
 +      /* Update the field, and then ring the doorbell */
 +      writel(intinfo.delay, &(h->cfgtable->HostWrite.CoalIntDelay));
 +      writel(intinfo.count, &(h->cfgtable->HostWrite.CoalIntCount));
 +      writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
  
 -                      writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
 +      for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
 +              if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
 +                      break;
 +              udelay(1000); /* delay and try again */
 +      }
 +      spin_unlock_irqrestore(&h->lock, flags);
 +      if (i >= MAX_IOCTL_CONFIG_WAIT)
 +              return -EAGAIN;
 +      return 0;
 +}
  
 -                      for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
 -                              if (!(readl(h->vaddr + SA5_DOORBELL)
 -                                    & CFGTBL_ChangeReq))
 -                                      break;
 -                              /* delay and try again */
 -                              udelay(1000);
 -                      }
 -                      spin_unlock_irqrestore(&h->lock, flags);
 -                      if (i >= MAX_IOCTL_CONFIG_WAIT)
 -                              return -EAGAIN;
 -                      return 0;
 -              }
 +static int cciss_getnodename(ctlr_info_t *h, void __user *argp)
 +{
 +      NodeName_type NodeName;
 +      int i;
  
 -      case CCISS_GETHEARTBEAT:
 -              {
 -                      Heartbeat_type heartbeat;
 -
 -                      if (!arg)
 -                              return -EINVAL;
 -                      heartbeat = readl(&h->cfgtable->HeartBeat);
 -                      if (copy_to_user
 -                          (argp, &heartbeat, sizeof(Heartbeat_type)))
 -                              return -EFAULT;
 -                      return 0;
 -              }
 -      case CCISS_GETBUSTYPES:
 -              {
 -                      BusTypes_type BusTypes;
 -
 -                      if (!arg)
 -                              return -EINVAL;
 -                      BusTypes = readl(&h->cfgtable->BusTypes);
 -                      if (copy_to_user
 -                          (argp, &BusTypes, sizeof(BusTypes_type)))
 -                              return -EFAULT;
 -                      return 0;
 -              }
 -      case CCISS_GETFIRMVER:
 -              {
 -                      FirmwareVer_type firmware;
 +      if (!argp)
 +              return -EINVAL;
 +      for (i = 0; i < 16; i++)
 +              NodeName[i] = readb(&h->cfgtable->ServerName[i]);
 +      if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
 +              return -EFAULT;
 +      return 0;
 +}
  
 -                      if (!arg)
 -                              return -EINVAL;
 -                      memcpy(firmware, h->firm_ver, 4);
 +static int cciss_setnodename(ctlr_info_t *h, void __user *argp)
 +{
 +      NodeName_type NodeName;
 +      unsigned long flags;
 +      int i;
  
 -                      if (copy_to_user
 -                          (argp, firmware, sizeof(FirmwareVer_type)))
 -                              return -EFAULT;
 -                      return 0;
 -              }
 -      case CCISS_GETDRIVVER:
 -              {
 -                      DriverVer_type DriverVer = DRIVER_VERSION;
 +      if (!argp)
 +              return -EINVAL;
 +      if (!capable(CAP_SYS_ADMIN))
 +              return -EPERM;
 +      if (copy_from_user(NodeName, argp, sizeof(NodeName_type)))
 +              return -EFAULT;
 +      spin_lock_irqsave(&h->lock, flags);
 +      /* Update the field, and then ring the doorbell */
 +      for (i = 0; i < 16; i++)
 +              writeb(NodeName[i], &h->cfgtable->ServerName[i]);
 +      writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
 +      for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
 +              if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
 +                      break;
 +              udelay(1000); /* delay and try again */
 +      }
 +      spin_unlock_irqrestore(&h->lock, flags);
 +      if (i >= MAX_IOCTL_CONFIG_WAIT)
 +              return -EAGAIN;
 +      return 0;
 +}
  
 -                      if (!arg)
 -                              return -EINVAL;
 +static int cciss_getheartbeat(ctlr_info_t *h, void __user *argp)
 +{
 +      Heartbeat_type heartbeat;
  
 -                      if (copy_to_user
 -                          (argp, &DriverVer, sizeof(DriverVer_type)))
 -                              return -EFAULT;
 -                      return 0;
 -              }
 +      if (!argp)
 +              return -EINVAL;
 +      heartbeat = readl(&h->cfgtable->HeartBeat);
 +      if (copy_to_user(argp, &heartbeat, sizeof(Heartbeat_type)))
 +              return -EFAULT;
 +      return 0;
 +}
  
 -      case CCISS_DEREGDISK:
 -      case CCISS_REGNEWD:
 -      case CCISS_REVALIDVOLS:
 -              return rebuild_lun_table(h, 0, 1);
 +static int cciss_getbustypes(ctlr_info_t *h, void __user *argp)
 +{
 +      BusTypes_type BusTypes;
  
 -      case CCISS_GETLUNINFO:{
 -                      LogvolInfo_struct luninfo;
 +      if (!argp)
 +              return -EINVAL;
 +      BusTypes = readl(&h->cfgtable->BusTypes);
 +      if (copy_to_user(argp, &BusTypes, sizeof(BusTypes_type)))
 +              return -EFAULT;
 +      return 0;
 +}
  
 -                      memcpy(&luninfo.LunID, drv->LunID,
 -                              sizeof(luninfo.LunID));
 -                      luninfo.num_opens = drv->usage_count;
 -                      luninfo.num_parts = 0;
 -                      if (copy_to_user(argp, &luninfo,
 -                                       sizeof(LogvolInfo_struct)))
 -                              return -EFAULT;
 -                      return 0;
 +static int cciss_getfirmver(ctlr_info_t *h, void __user *argp)
 +{
 +      FirmwareVer_type firmware;
 +
 +      if (!argp)
 +              return -EINVAL;
 +      memcpy(firmware, h->firm_ver, 4);
 +
 +      if (copy_to_user
 +          (argp, firmware, sizeof(FirmwareVer_type)))
 +              return -EFAULT;
 +      return 0;
 +}
 +
 +static int cciss_getdrivver(ctlr_info_t *h, void __user *argp)
 +{
 +      DriverVer_type DriverVer = DRIVER_VERSION;
 +
 +      if (!argp)
 +              return -EINVAL;
 +      if (copy_to_user(argp, &DriverVer, sizeof(DriverVer_type)))
 +              return -EFAULT;
 +      return 0;
 +}
 +
 +static int cciss_getluninfo(ctlr_info_t *h,
 +      struct gendisk *disk, void __user *argp)
 +{
 +      LogvolInfo_struct luninfo;
 +      drive_info_struct *drv = get_drv(disk);
 +
 +      if (!argp)
 +              return -EINVAL;
 +      memcpy(&luninfo.LunID, drv->LunID, sizeof(luninfo.LunID));
 +      luninfo.num_opens = drv->usage_count;
 +      luninfo.num_parts = 0;
 +      if (copy_to_user(argp, &luninfo, sizeof(LogvolInfo_struct)))
 +              return -EFAULT;
 +      return 0;
 +}
 +
 +static int cciss_passthru(ctlr_info_t *h, void __user *argp)
 +{
 +      IOCTL_Command_struct iocommand;
 +      CommandList_struct *c;
 +      char *buff = NULL;
 +      u64bit temp64;
 +      DECLARE_COMPLETION_ONSTACK(wait);
 +
 +      if (!argp)
 +              return -EINVAL;
 +
 +      if (!capable(CAP_SYS_RAWIO))
 +              return -EPERM;
 +
 +      if (copy_from_user
 +          (&iocommand, argp, sizeof(IOCTL_Command_struct)))
 +              return -EFAULT;
 +      if ((iocommand.buf_size < 1) &&
 +          (iocommand.Request.Type.Direction != XFER_NONE)) {
 +              return -EINVAL;
 +      }
 +      if (iocommand.buf_size > 0) {
 +              buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
 +              if (buff == NULL)
 +                      return -EFAULT;
 +      }
 +      if (iocommand.Request.Type.Direction == XFER_WRITE) {
 +              /* Copy the data into the buffer we created */
 +              if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) {
 +                      kfree(buff);
 +                      return -EFAULT;
                }
 -      case CCISS_PASSTHRU:
 -              {
 -                      IOCTL_Command_struct iocommand;
 -                      CommandList_struct *c;
 -                      char *buff = NULL;
 -                      u64bit temp64;
 -                      DECLARE_COMPLETION_ONSTACK(wait);
 -
 -                      if (!arg)
 -                              return -EINVAL;
 -
 -                      if (!capable(CAP_SYS_RAWIO))
 -                              return -EPERM;
 -
 -                      if (copy_from_user
 -                          (&iocommand, argp, sizeof(IOCTL_Command_struct)))
 -                              return -EFAULT;
 -                      if ((iocommand.buf_size < 1) &&
 -                          (iocommand.Request.Type.Direction != XFER_NONE)) {
 -                              return -EINVAL;
 -                      }
 -#if 0                         /* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */
 -                      /* Check kmalloc limits */
 -                      if (iocommand.buf_size > 128000)
 -                              return -EINVAL;
 -#endif
 -                      if (iocommand.buf_size > 0) {
 -                              buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
 -                              if (buff == NULL)
 -                                      return -EFAULT;
 -                      }
 -                      if (iocommand.Request.Type.Direction == XFER_WRITE) {
 -                              /* Copy the data into the buffer we created */
 -                              if (copy_from_user
 -                                  (buff, iocommand.buf, iocommand.buf_size)) {
 -                                      kfree(buff);
 -                                      return -EFAULT;
 -                              }
 -                      } else {
 -                              memset(buff, 0, iocommand.buf_size);
 -                      }
 -                      c = cmd_special_alloc(h);
 -                      if (!c) {
 -                              kfree(buff);
 -                              return -ENOMEM;
 -                      }
 -                      /* Fill in the command type */
 -                      c->cmd_type = CMD_IOCTL_PEND;
 -                      /* Fill in Command Header */
 -                      c->Header.ReplyQueue = 0;   /* unused in simple mode */
 -                      if (iocommand.buf_size > 0) /* buffer to fill */
 -                      {
 -                              c->Header.SGList = 1;
 -                              c->Header.SGTotal = 1;
 -                      } else /* no buffers to fill */
 -                      {
 -                              c->Header.SGList = 0;
 -                              c->Header.SGTotal = 0;
 -                      }
 -                      c->Header.LUN = iocommand.LUN_info;
 -                      /* use the kernel address the cmd block for tag */
 -                      c->Header.Tag.lower = c->busaddr;
 -
 -                      /* Fill in Request block */
 -                      c->Request = iocommand.Request;
 -
 -                      /* Fill in the scatter gather information */
 -                      if (iocommand.buf_size > 0) {
 -                              temp64.val = pci_map_single(h->pdev, buff,
 -                                      iocommand.buf_size,
 -                                      PCI_DMA_BIDIRECTIONAL);
 -                              c->SG[0].Addr.lower = temp64.val32.lower;
 -                              c->SG[0].Addr.upper = temp64.val32.upper;
 -                              c->SG[0].Len = iocommand.buf_size;
 -                              c->SG[0].Ext = 0;  /* we are not chaining */
 -                      }
 -                      c->waiting = &wait;
 +      } else {
 +              memset(buff, 0, iocommand.buf_size);
 +      }
 +      c = cmd_special_alloc(h);
 +      if (!c) {
 +              kfree(buff);
 +              return -ENOMEM;
 +      }
 +      /* Fill in the command type */
 +      c->cmd_type = CMD_IOCTL_PEND;
 +      /* Fill in Command Header */
 +      c->Header.ReplyQueue = 0;   /* unused in simple mode */
 +      if (iocommand.buf_size > 0) { /* buffer to fill */
 +              c->Header.SGList = 1;
 +              c->Header.SGTotal = 1;
 +      } else { /* no buffers to fill */
 +              c->Header.SGList = 0;
 +              c->Header.SGTotal = 0;
 +      }
 +      c->Header.LUN = iocommand.LUN_info;
 +      /* use the kernel address the cmd block for tag */
 +      c->Header.Tag.lower = c->busaddr;
  
 -                      enqueue_cmd_and_start_io(h, c);
 -                      wait_for_completion(&wait);
 +      /* Fill in Request block */
 +      c->Request = iocommand.Request;
  
 -                      /* unlock the buffers from DMA */
 -                      temp64.val32.lower = c->SG[0].Addr.lower;
 -                      temp64.val32.upper = c->SG[0].Addr.upper;
 -                      pci_unmap_single(h->pdev, (dma_addr_t) temp64.val,
 -                                       iocommand.buf_size,
 -                                       PCI_DMA_BIDIRECTIONAL);
 +      /* Fill in the scatter gather information */
 +      if (iocommand.buf_size > 0) {
 +              temp64.val = pci_map_single(h->pdev, buff,
 +                      iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
 +              c->SG[0].Addr.lower = temp64.val32.lower;
 +              c->SG[0].Addr.upper = temp64.val32.upper;
 +              c->SG[0].Len = iocommand.buf_size;
 +              c->SG[0].Ext = 0;  /* we are not chaining */
 +      }
 +      c->waiting = &wait;
  
 -                      check_ioctl_unit_attention(h, c);
 +      enqueue_cmd_and_start_io(h, c);
 +      wait_for_completion(&wait);
  
 -                      /* Copy the error information out */
 -                      iocommand.error_info = *(c->err_info);
 -                      if (copy_to_user
 -                          (argp, &iocommand, sizeof(IOCTL_Command_struct))) {
 -                              kfree(buff);
 -                              cmd_special_free(h, c);
 -                              return -EFAULT;
 -                      }
 +      /* unlock the buffers from DMA */
 +      temp64.val32.lower = c->SG[0].Addr.lower;
 +      temp64.val32.upper = c->SG[0].Addr.upper;
 +      pci_unmap_single(h->pdev, (dma_addr_t) temp64.val, iocommand.buf_size,
 +                       PCI_DMA_BIDIRECTIONAL);
 +      check_ioctl_unit_attention(h, c);
 +
 +      /* Copy the error information out */
 +      iocommand.error_info = *(c->err_info);
 +      if (copy_to_user(argp, &iocommand, sizeof(IOCTL_Command_struct))) {
 +              kfree(buff);
 +              cmd_special_free(h, c);
 +              return -EFAULT;
 +      }
  
 -                      if (iocommand.Request.Type.Direction == XFER_READ) {
 -                              /* Copy the data out of the buffer we created */
 -                              if (copy_to_user
 -                                  (iocommand.buf, buff, iocommand.buf_size)) {
 -                                      kfree(buff);
 -                                      cmd_special_free(h, c);
 -                                      return -EFAULT;
 -                              }
 -                      }
 +      if (iocommand.Request.Type.Direction == XFER_READ) {
 +              /* Copy the data out of the buffer we created */
 +              if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
                        kfree(buff);
                        cmd_special_free(h, c);
 -                      return 0;
 +                      return -EFAULT;
                }
 -      case CCISS_BIG_PASSTHRU:{
 -                      BIG_IOCTL_Command_struct *ioc;
 -                      CommandList_struct *c;
 -                      unsigned char **buff = NULL;
 -                      int *buff_size = NULL;
 -                      u64bit temp64;
 -                      BYTE sg_used = 0;
 -                      int status = 0;
 -                      int i;
 -                      DECLARE_COMPLETION_ONSTACK(wait);
 -                      __u32 left;
 -                      __u32 sz;
 -                      BYTE __user *data_ptr;
 -
 -                      if (!arg)
 -                              return -EINVAL;
 -                      if (!capable(CAP_SYS_RAWIO))
 -                              return -EPERM;
 -                      ioc = (BIG_IOCTL_Command_struct *)
 -                          kmalloc(sizeof(*ioc), GFP_KERNEL);
 -                      if (!ioc) {
 -                              status = -ENOMEM;
 -                              goto cleanup1;
 -                      }
 -                      if (copy_from_user(ioc, argp, sizeof(*ioc))) {
 +      }
 +      kfree(buff);
 +      cmd_special_free(h, c);
 +      return 0;
 +}
 +
 +static int cciss_bigpassthru(ctlr_info_t *h, void __user *argp)
 +{
 +      BIG_IOCTL_Command_struct *ioc;
 +      CommandList_struct *c;
 +      unsigned char **buff = NULL;
 +      int *buff_size = NULL;
 +      u64bit temp64;
 +      BYTE sg_used = 0;
 +      int status = 0;
 +      int i;
 +      DECLARE_COMPLETION_ONSTACK(wait);
 +      __u32 left;
 +      __u32 sz;
 +      BYTE __user *data_ptr;
 +
 +      if (!argp)
 +              return -EINVAL;
 +      if (!capable(CAP_SYS_RAWIO))
 +              return -EPERM;
 +      ioc = (BIG_IOCTL_Command_struct *)
 +          kmalloc(sizeof(*ioc), GFP_KERNEL);
 +      if (!ioc) {
 +              status = -ENOMEM;
 +              goto cleanup1;
 +      }
 +      if (copy_from_user(ioc, argp, sizeof(*ioc))) {
 +              status = -EFAULT;
 +              goto cleanup1;
 +      }
 +      if ((ioc->buf_size < 1) &&
 +          (ioc->Request.Type.Direction != XFER_NONE)) {
 +              status = -EINVAL;
 +              goto cleanup1;
 +      }
 +      /* Check kmalloc limits  using all SGs */
 +      if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
 +              status = -EINVAL;
 +              goto cleanup1;
 +      }
 +      if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
 +              status = -EINVAL;
 +              goto cleanup1;
 +      }
 +      buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
 +      if (!buff) {
 +              status = -ENOMEM;
 +              goto cleanup1;
 +      }
 +      buff_size = kmalloc(MAXSGENTRIES * sizeof(int), GFP_KERNEL);
 +      if (!buff_size) {
 +              status = -ENOMEM;
 +              goto cleanup1;
 +      }
 +      left = ioc->buf_size;
 +      data_ptr = ioc->buf;
 +      while (left) {
 +              sz = (left > ioc->malloc_size) ? ioc->malloc_size : left;
 +              buff_size[sg_used] = sz;
 +              buff[sg_used] = kmalloc(sz, GFP_KERNEL);
 +              if (buff[sg_used] == NULL) {
 +                      status = -ENOMEM;
 +                      goto cleanup1;
 +              }
 +              if (ioc->Request.Type.Direction == XFER_WRITE) {
 +                      if (copy_from_user(buff[sg_used], data_ptr, sz)) {
                                status = -EFAULT;
                                goto cleanup1;
                        }
 -                      if ((ioc->buf_size < 1) &&
 -                          (ioc->Request.Type.Direction != XFER_NONE)) {
 -                              status = -EINVAL;
 -                              goto cleanup1;
 -                      }
 -                      /* Check kmalloc limits  using all SGs */
 -                      if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
 -                              status = -EINVAL;
 -                              goto cleanup1;
 -                      }
 -                      if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
 -                              status = -EINVAL;
 -                              goto cleanup1;
 -                      }
 -                      buff =
 -                          kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
 -                      if (!buff) {
 -                              status = -ENOMEM;
 -                              goto cleanup1;
 -                      }
 -                      buff_size = kmalloc(MAXSGENTRIES * sizeof(int),
 -                                                 GFP_KERNEL);
 -                      if (!buff_size) {
 -                              status = -ENOMEM;
 -                              goto cleanup1;
 -                      }
 -                      left = ioc->buf_size;
 -                      data_ptr = ioc->buf;
 -                      while (left) {
 -                              sz = (left >
 -                                    ioc->malloc_size) ? ioc->
 -                                  malloc_size : left;
 -                              buff_size[sg_used] = sz;
 -                              buff[sg_used] = kmalloc(sz, GFP_KERNEL);
 -                              if (buff[sg_used] == NULL) {
 -                                      status = -ENOMEM;
 -                                      goto cleanup1;
 -                              }
 -                              if (ioc->Request.Type.Direction == XFER_WRITE) {
 -                                      if (copy_from_user
 -                                          (buff[sg_used], data_ptr, sz)) {
 -                                              status = -EFAULT;
 -                                              goto cleanup1;
 -                                      }
 -                              } else {
 -                                      memset(buff[sg_used], 0, sz);
 -                              }
 -                              left -= sz;
 -                              data_ptr += sz;
 -                              sg_used++;
 -                      }
 -                      c = cmd_special_alloc(h);
 -                      if (!c) {
 -                              status = -ENOMEM;
 -                              goto cleanup1;
 -                      }
 -                      c->cmd_type = CMD_IOCTL_PEND;
 -                      c->Header.ReplyQueue = 0;
 +              } else {
 +                      memset(buff[sg_used], 0, sz);
 +              }
 +              left -= sz;
 +              data_ptr += sz;
 +              sg_used++;
 +      }
 +      c = cmd_special_alloc(h);
 +      if (!c) {
 +              status = -ENOMEM;
 +              goto cleanup1;
 +      }
 +      c->cmd_type = CMD_IOCTL_PEND;
 +      c->Header.ReplyQueue = 0;
 +      c->Header.SGList = sg_used;
 +      c->Header.SGTotal = sg_used;
 +      c->Header.LUN = ioc->LUN_info;
 +      c->Header.Tag.lower = c->busaddr;
  
 -                      if (ioc->buf_size > 0) {
 -                              c->Header.SGList = sg_used;
 -                              c->Header.SGTotal = sg_used;
 -                      } else {
 -                              c->Header.SGList = 0;
 -                              c->Header.SGTotal = 0;
 -                      }
 -                      c->Header.LUN = ioc->LUN_info;
 -                      c->Header.Tag.lower = c->busaddr;
 -
 -                      c->Request = ioc->Request;
 -                      if (ioc->buf_size > 0) {
 -                              for (i = 0; i < sg_used; i++) {
 -                                      temp64.val =
 -                                          pci_map_single(h->pdev, buff[i],
 -                                                  buff_size[i],
 -                                                  PCI_DMA_BIDIRECTIONAL);
 -                                      c->SG[i].Addr.lower =
 -                                          temp64.val32.lower;
 -                                      c->SG[i].Addr.upper =
 -                                          temp64.val32.upper;
 -                                      c->SG[i].Len = buff_size[i];
 -                                      c->SG[i].Ext = 0;       /* we are not chaining */
 -                              }
 -                      }
 -                      c->waiting = &wait;
 -                      enqueue_cmd_and_start_io(h, c);
 -                      wait_for_completion(&wait);
 -                      /* unlock the buffers from DMA */
 -                      for (i = 0; i < sg_used; i++) {
 -                              temp64.val32.lower = c->SG[i].Addr.lower;
 -                              temp64.val32.upper = c->SG[i].Addr.upper;
 -                              pci_unmap_single(h->pdev,
 -                                      (dma_addr_t) temp64.val, buff_size[i],
 -                                      PCI_DMA_BIDIRECTIONAL);
 -                      }
 -                      check_ioctl_unit_attention(h, c);
 -                      /* Copy the error information out */
 -                      ioc->error_info = *(c->err_info);
 -                      if (copy_to_user(argp, ioc, sizeof(*ioc))) {
 +      c->Request = ioc->Request;
 +      for (i = 0; i < sg_used; i++) {
 +              temp64.val = pci_map_single(h->pdev, buff[i], buff_size[i],
 +                                  PCI_DMA_BIDIRECTIONAL);
 +              c->SG[i].Addr.lower = temp64.val32.lower;
 +              c->SG[i].Addr.upper = temp64.val32.upper;
 +              c->SG[i].Len = buff_size[i];
 +              c->SG[i].Ext = 0;       /* we are not chaining */
 +      }
 +      c->waiting = &wait;
 +      enqueue_cmd_and_start_io(h, c);
 +      wait_for_completion(&wait);
 +      /* unlock the buffers from DMA */
 +      for (i = 0; i < sg_used; i++) {
 +              temp64.val32.lower = c->SG[i].Addr.lower;
 +              temp64.val32.upper = c->SG[i].Addr.upper;
 +              pci_unmap_single(h->pdev,
 +                      (dma_addr_t) temp64.val, buff_size[i],
 +                      PCI_DMA_BIDIRECTIONAL);
 +      }
 +      check_ioctl_unit_attention(h, c);
 +      /* Copy the error information out */
 +      ioc->error_info = *(c->err_info);
 +      if (copy_to_user(argp, ioc, sizeof(*ioc))) {
 +              cmd_special_free(h, c);
 +              status = -EFAULT;
 +              goto cleanup1;
 +      }
 +      if (ioc->Request.Type.Direction == XFER_READ) {
 +              /* Copy the data out of the buffer we created */
 +              BYTE __user *ptr = ioc->buf;
 +              for (i = 0; i < sg_used; i++) {
 +                      if (copy_to_user(ptr, buff[i], buff_size[i])) {
                                cmd_special_free(h, c);
                                status = -EFAULT;
                                goto cleanup1;
                        }
 -                      if (ioc->Request.Type.Direction == XFER_READ) {
 -                              /* Copy the data out of the buffer we created */
 -                              BYTE __user *ptr = ioc->buf;
 -                              for (i = 0; i < sg_used; i++) {
 -                                      if (copy_to_user
 -                                          (ptr, buff[i], buff_size[i])) {
 -                                              cmd_special_free(h, c);
 -                                              status = -EFAULT;
 -                                              goto cleanup1;
 -                                      }
 -                                      ptr += buff_size[i];
 -                              }
 -                      }
 -                      cmd_special_free(h, c);
 -                      status = 0;
 -                    cleanup1:
 -                      if (buff) {
 -                              for (i = 0; i < sg_used; i++)
 -                                      kfree(buff[i]);
 -                              kfree(buff);
 -                      }
 -                      kfree(buff_size);
 -                      kfree(ioc);
 -                      return status;
 +                      ptr += buff_size[i];
                }
 +      }
 +      cmd_special_free(h, c);
 +      status = 0;
 +cleanup1:
 +      if (buff) {
 +              for (i = 0; i < sg_used; i++)
 +                      kfree(buff[i]);
 +              kfree(buff);
 +      }
 +      kfree(buff_size);
 +      kfree(ioc);
 +      return status;
 +}
 +
 +static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
 +      unsigned int cmd, unsigned long arg)
 +{
 +      struct gendisk *disk = bdev->bd_disk;
 +      ctlr_info_t *h = get_host(disk);
 +      void __user *argp = (void __user *)arg;
 +
 +      dev_dbg(&h->pdev->dev, "cciss_ioctl: Called with cmd=%x %lx\n",
 +              cmd, arg);
 +      switch (cmd) {
 +      case CCISS_GETPCIINFO:
 +              return cciss_getpciinfo(h, argp);
 +      case CCISS_GETINTINFO:
 +              return cciss_getintinfo(h, argp);
 +      case CCISS_SETINTINFO:
 +              return cciss_setintinfo(h, argp);
 +      case CCISS_GETNODENAME:
 +              return cciss_getnodename(h, argp);
 +      case CCISS_SETNODENAME:
 +              return cciss_setnodename(h, argp);
 +      case CCISS_GETHEARTBEAT:
 +              return cciss_getheartbeat(h, argp);
 +      case CCISS_GETBUSTYPES:
 +              return cciss_getbustypes(h, argp);
 +      case CCISS_GETFIRMVER:
 +              return cciss_getfirmver(h, argp);
 +      case CCISS_GETDRIVVER:
 +              return cciss_getdrivver(h, argp);
 +      case CCISS_DEREGDISK:
 +      case CCISS_REGNEWD:
 +      case CCISS_REVALIDVOLS:
 +              return rebuild_lun_table(h, 0, 1);
 +      case CCISS_GETLUNINFO:
 +              return cciss_getluninfo(h, disk, argp);
 +      case CCISS_PASSTHRU:
 +              return cciss_passthru(h, argp);
 +      case CCISS_BIG_PASSTHRU:
 +              return cciss_bigpassthru(h, argp);
  
        /* scsi_cmd_ioctl handles these, below, though some are not */
        /* very meaningful for cciss.  SG_IO is the main one people want. */
@@@ -2834,8 -2881,6 +2834,8 @@@ static int cciss_revalidate(struct gend
        InquiryData_struct *inq_buff = NULL;
  
        for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
 +              if (!h->drv[logvol])
 +                      continue;
                if (memcmp(h->drv[logvol]->LunID, drv->LunID,
                        sizeof(drv->LunID)) == 0) {
                        FOUND = 1;
@@@ -2888,8 -2933,8 +2888,8 @@@ static void start_io(ctlr_info_t *h
  {
        CommandList_struct *c;
  
-       while (!hlist_empty(&h->reqQ)) {
-               c = hlist_entry(h->reqQ.first, CommandList_struct, list);
+       while (!list_empty(&h->reqQ)) {
+               c = list_entry(h->reqQ.next, CommandList_struct, list);
                /* can't do anything if fifo is full */
                if ((h->access.fifo_full(h))) {
                        dev_warn(&h->pdev->dev, "fifo full\n");
@@@ -3402,11 -3447,10 +3402,10 @@@ static inline u32 process_nonindexed_cm
  {
        u32 tag;
        CommandList_struct *c = NULL;
-       struct hlist_node *tmp;
        __u32 busaddr_masked, tag_masked;
  
        tag = cciss_tag_discard_error_bits(raw_tag);
-       hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
+       list_for_each_entry(c, &h->cmpQ, list) {
                busaddr_masked = cciss_tag_discard_error_bits(c->busaddr);
                tag_masked = cciss_tag_discard_error_bits(tag);
                if (busaddr_masked == tag_masked) {
@@@ -3756,7 -3800,7 +3755,7 @@@ static void __devinit cciss_wait_for_mo
        for (i = 0; i < MAX_CONFIG_WAIT; i++) {
                if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
                        break;
 -              msleep(10);
 +              usleep_range(10000, 20000);
        }
  }
  
@@@ -3940,9 -3984,13 +3939,9 @@@ static int __devinit cciss_lookup_board
        *board_id = ((subsystem_device_id << 16) & 0xffff0000) |
                        subsystem_vendor_id;
  
 -      for (i = 0; i < ARRAY_SIZE(products); i++) {
 -              /* Stand aside for hpsa driver on request */
 -              if (cciss_allow_hpsa && products[i].board_id == HPSA_BOUNDARY)
 -                      return -ENODEV;
 +      for (i = 0; i < ARRAY_SIZE(products); i++)
                if (*board_id == products[i].board_id)
                        return i;
 -      }
        dev_warn(&pdev->dev, "unrecognized board ID: 0x%08x, ignoring.\n",
                *board_id);
        return -ENODEV;
@@@ -3973,31 -4021,18 +3972,31 @@@ static int __devinit cciss_pci_find_mem
        return -ENODEV;
  }
  
 -static int __devinit cciss_wait_for_board_ready(ctlr_info_t *h)
 +static int __devinit cciss_wait_for_board_state(struct pci_dev *pdev,
 +      void __iomem *vaddr, int wait_for_ready)
 +#define BOARD_READY 1
 +#define BOARD_NOT_READY 0
  {
 -      int i;
 +      int i, iterations;
        u32 scratchpad;
  
 -      for (i = 0; i < CCISS_BOARD_READY_ITERATIONS; i++) {
 -              scratchpad = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
 -              if (scratchpad == CCISS_FIRMWARE_READY)
 -                      return 0;
 +      if (wait_for_ready)
 +              iterations = CCISS_BOARD_READY_ITERATIONS;
 +      else
 +              iterations = CCISS_BOARD_NOT_READY_ITERATIONS;
 +
 +      for (i = 0; i < iterations; i++) {
 +              scratchpad = readl(vaddr + SA5_SCRATCHPAD_OFFSET);
 +              if (wait_for_ready) {
 +                      if (scratchpad == CCISS_FIRMWARE_READY)
 +                              return 0;
 +              } else {
 +                      if (scratchpad != CCISS_FIRMWARE_READY)
 +                              return 0;
 +              }
                msleep(CCISS_BOARD_READY_POLL_INTERVAL_MSECS);
        }
 -      dev_warn(&h->pdev->dev, "board not ready, timed out.\n");
 +      dev_warn(&pdev->dev, "board not ready, timed out.\n");
        return -ENODEV;
  }
  
@@@ -4046,11 -4081,6 +4045,11 @@@ static int __devinit cciss_find_cfgtabl
  static void __devinit cciss_get_max_perf_mode_cmds(struct ctlr_info *h)
  {
        h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands));
 +
 +      /* Limit commands in memory limited kdump scenario. */
 +      if (reset_devices && h->max_commands > 32)
 +              h->max_commands = 32;
 +
        if (h->max_commands < 16) {
                dev_warn(&h->pdev->dev, "Controller reports "
                        "max supported commands of %d, an obvious lie. "
@@@ -4168,7 -4198,7 +4167,7 @@@ static int __devinit cciss_pci_init(ctl
                err = -ENOMEM;
                goto err_out_free_res;
        }
 -      err = cciss_wait_for_board_ready(h);
 +      err = cciss_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY);
        if (err)
                goto err_out_free_res;
        err = cciss_find_cfgtables(h);
@@@ -4333,6 -4363,36 +4332,6 @@@ static __devinit int cciss_message(stru
  #define cciss_soft_reset_controller(p) cciss_message(p, 1, 0)
  #define cciss_noop(p) cciss_message(p, 3, 0)
  
 -static __devinit int cciss_reset_msi(struct pci_dev *pdev)
 -{
 -/* the #defines are stolen from drivers/pci/msi.h. */
 -#define msi_control_reg(base)         (base + PCI_MSI_FLAGS)
 -#define PCI_MSIX_FLAGS_ENABLE         (1 << 15)
 -
 -      int pos;
 -      u16 control = 0;
 -
 -      pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
 -      if (pos) {
 -              pci_read_config_word(pdev, msi_control_reg(pos), &control);
 -              if (control & PCI_MSI_FLAGS_ENABLE) {
 -                      dev_info(&pdev->dev, "resetting MSI\n");
 -                      pci_write_config_word(pdev, msi_control_reg(pos), control & ~PCI_MSI_FLAGS_ENABLE);
 -              }
 -      }
 -
 -      pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
 -      if (pos) {
 -              pci_read_config_word(pdev, msi_control_reg(pos), &control);
 -              if (control & PCI_MSIX_FLAGS_ENABLE) {
 -                      dev_info(&pdev->dev, "resetting MSI-X\n");
 -                      pci_write_config_word(pdev, msi_control_reg(pos), control & ~PCI_MSIX_FLAGS_ENABLE);
 -              }
 -      }
 -
 -      return 0;
 -}
 -
  static int cciss_controller_hard_reset(struct pci_dev *pdev,
        void * __iomem vaddr, bool use_doorbell)
  {
   * states or using the doorbell register. */
  static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
  {
 -      u16 saved_config_space[32];
        u64 cfg_offset;
        u32 cfg_base_addr;
        u64 cfg_base_addr_index;
        void __iomem *vaddr;
        unsigned long paddr;
        u32 misc_fw_support, active_transport;
 -      int rc, i;
 +      int rc;
        CfgTable_struct __iomem *cfgtable;
        bool use_doorbell;
        u32 board_id;
 +      u16 command_register;
  
        /* For controllers as old a the p600, this is very nearly
         * the same thing as
         * pci_set_power_state(pci_dev, PCI_D0);
         * pci_restore_state(pci_dev);
         *
 -       * but we can't use these nice canned kernel routines on
 -       * kexec, because they also check the MSI/MSI-X state in PCI
 -       * configuration space and do the wrong thing when it is
 -       * set/cleared.  Also, the pci_save/restore_state functions
 -       * violate the ordering requirements for restoring the
 -       * configuration space from the CCISS document (see the
 -       * comment below).  So we roll our own ....
 -       *
         * For controllers newer than the P600, the pci power state
         * method of resetting doesn't work so we have another way
         * using the doorbell register.
                return -ENODEV;
        }
  
 -      for (i = 0; i < 32; i++)
 -              pci_read_config_word(pdev, 2*i, &saved_config_space[i]);
 +      /* Save the PCI command register */
 +      pci_read_config_word(pdev, 4, &command_register);
 +      /* Turn the board off.  This is so that later pci_restore_state()
 +       * won't turn the board on before the rest of config space is ready.
 +       */
 +      pci_disable_device(pdev);
 +      pci_save_state(pdev);
  
        /* find the first memory BAR, so we can find the cfg table */
        rc = cciss_pci_find_memory_BAR(pdev, &paddr);
        rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell);
        if (rc)
                goto unmap_cfgtable;
 -
 -      /* Restore the PCI configuration space.  The Open CISS
 -       * Specification says, "Restore the PCI Configuration
 -       * Registers, offsets 00h through 60h. It is important to
 -       * restore the command register, 16-bits at offset 04h,
 -       * last. Do not restore the configuration status register,
 -       * 16-bits at offset 06h."  Note that the offset is 2*i.
 -       */
 -      for (i = 0; i < 32; i++) {
 -              if (i == 2 || i == 3)
 -                      continue;
 -              pci_write_config_word(pdev, 2*i, saved_config_space[i]);
 +      pci_restore_state(pdev);
 +      rc = pci_enable_device(pdev);
 +      if (rc) {
 +              dev_warn(&pdev->dev, "failed to enable device.\n");
 +              goto unmap_cfgtable;
        }
 -      wmb();
 -      pci_write_config_word(pdev, 4, saved_config_space[2]);
 +      pci_write_config_word(pdev, 4, command_register);
  
        /* Some devices (notably the HP Smart Array 5i Controller)
           need a little pause here */
        msleep(CCISS_POST_RESET_PAUSE_MSECS);
  
 +      /* Wait for board to become not ready, then ready. */
 +      dev_info(&pdev->dev, "Waiting for board to become ready.\n");
 +      rc = cciss_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY);
 +      if (rc) /* Don't bail, might be E500, etc. which can't be reset */
 +              dev_warn(&pdev->dev,
 +                      "failed waiting for board to become not ready\n");
 +      rc = cciss_wait_for_board_state(pdev, vaddr, BOARD_READY);
 +      if (rc) {
 +              dev_warn(&pdev->dev,
 +                      "failed waiting for board to become ready\n");
 +              goto unmap_cfgtable;
 +      }
 +      dev_info(&pdev->dev, "board ready.\n");
 +
        /* Controller should be in simple mode at this point.  If it's not,
         * It means we're on one of those controllers which doesn't support
         * the doorbell reset method and on which the PCI power management reset
@@@ -4532,6 -4589,8 +4531,6 @@@ static __devinit int cciss_init_reset_d
                return 0; /* just try to do the kdump anyhow. */
        if (rc)
                return -ENODEV;
 -      if (cciss_reset_msi(pdev))
 -              return -ENODEV;
  
        /* Now try to get the controller to respond to a no-op */
        for (i = 0; i < CCISS_POST_RESET_NOOP_RETRIES; i++) {
@@@ -4572,8 -4631,8 +4571,8 @@@ static int __devinit cciss_init_one(str
        h = hba[i];
        h->pdev = pdev;
        h->busy_initializing = 1;
-       INIT_HLIST_HEAD(&h->cmpQ);
-       INIT_HLIST_HEAD(&h->reqQ);
+       INIT_LIST_HEAD(&h->cmpQ);
+       INIT_LIST_HEAD(&h->reqQ);
        mutex_init(&h->busy_shutting_down);
  
        if (cciss_pci_init(h) != 0)
@@@ -4927,8 -4986,7 +4926,8 @@@ static void __exit cciss_cleanup(void
                }
        }
        kthread_stop(cciss_scan_thread);
 -      remove_proc_entry("driver/cciss", NULL);
 +      if (proc_cciss)
 +              remove_proc_entry("driver/cciss", NULL);
        bus_unregister(&cciss_bus_type);
  }
  
diff --combined drivers/block/cciss.h
@@@ -103,8 -103,8 +103,8 @@@ struct ctlr_inf
        struct access_method access;
  
        /* queue and queue Info */ 
-       struct hlist_head reqQ;
-       struct hlist_head cmpQ;
+       struct list_head reqQ;
+       struct list_head cmpQ;
        unsigned int Qdepth;
        unsigned int maxQsinceinit;
        unsigned int maxSG;
   * the above.
   */
  #define CCISS_BOARD_READY_WAIT_SECS (120)
 +#define CCISS_BOARD_NOT_READY_WAIT_SECS (10)
  #define CCISS_BOARD_READY_POLL_INTERVAL_MSECS (100)
  #define CCISS_BOARD_READY_ITERATIONS \
        ((CCISS_BOARD_READY_WAIT_SECS * 1000) / \
                CCISS_BOARD_READY_POLL_INTERVAL_MSECS)
 +#define CCISS_BOARD_NOT_READY_ITERATIONS \
 +      ((CCISS_BOARD_NOT_READY_WAIT_SECS * 1000) / \
 +              CCISS_BOARD_READY_POLL_INTERVAL_MSECS)
  #define CCISS_POST_RESET_PAUSE_MSECS (3000)
  #define CCISS_POST_RESET_NOOP_INTERVAL_MSECS (1000)
  #define CCISS_POST_RESET_NOOP_RETRIES (12)
diff --combined drivers/block/floppy.c
@@@ -178,6 -178,7 +178,6 @@@ static int print_unex = 1
  #include <linux/slab.h>
  #include <linux/mm.h>
  #include <linux/bio.h>
 -#include <linux/smp_lock.h>
  #include <linux/string.h>
  #include <linux/jiffies.h>
  #include <linux/fcntl.h>
   * It's been recommended that take about 1/4 of the default speed
   * in some more extreme cases.
   */
 +static DEFINE_MUTEX(floppy_mutex);
  static int slow_floppy;
  
  #include <asm/dma.h>
@@@ -258,8 -258,8 +258,8 @@@ static int irqdma_allocated
  #include <linux/completion.h>
  
  static struct request *current_req;
 -static struct request_queue *floppy_queue;
  static void do_fd_request(struct request_queue *q);
 +static int set_next_request(void);
  
  #ifndef fd_get_dma_residue
  #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)
@@@ -413,7 -413,6 +413,7 @@@ static struct gendisk *disks[N_DRIVE]
  static struct block_device *opened_bdev[N_DRIVE];
  static DEFINE_MUTEX(open_lock);
  static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
 +static int fdc_queue;
  
  /*
   * This struct defines the different floppy types.
@@@ -597,6 -596,11 +597,11 @@@ static unsigned char fsector_t;  /* sect
  static unsigned char in_sector_offset;        /* offset within physical sector,
                                         * expressed in units of 512 bytes */
  
+ static inline bool drive_no_geom(int drive)
+ {
+       return !current_type[drive] && !ITYPE(UDRS->fd_device);
+ }
  #ifndef fd_eject
  static inline int fd_eject(int drive)
  {
@@@ -891,8 -895,8 +896,8 @@@ static void unlock_fdc(void
        del_timer(&fd_timeout);
        cont = NULL;
        clear_bit(0, &fdc_busy);
 -      if (current_req || blk_peek_request(floppy_queue))
 -              do_fd_request(floppy_queue);
 +      if (current_req || set_next_request())
 +              do_fd_request(current_req->q);
        spin_unlock_irqrestore(&floppy_lock, flags);
        wake_up(&fdc_wait);
  }
@@@ -2244,8 -2248,8 +2249,8 @@@ static void floppy_end_request(struct r
   * logical buffer */
  static void request_done(int uptodate)
  {
 -      struct request_queue *q = floppy_queue;
        struct request *req = current_req;
 +      struct request_queue *q;
        unsigned long flags;
        int block;
        char msg[sizeof("request done ") + sizeof(int) * 3];
                return;
        }
  
 +      q = req->q;
 +
        if (uptodate) {
                /* maintain values for invalidation on geometry
                 * change */
@@@ -2814,28 -2816,6 +2819,28 @@@ static int make_raw_rw_request(void
        return 2;
  }
  
 +/*
 + * Round-robin between our available drives, doing one request from each
 + */
 +static int set_next_request(void)
 +{
 +      struct request_queue *q;
 +      int old_pos = fdc_queue;
 +
 +      do {
 +              q = disks[fdc_queue]->queue;
 +              if (++fdc_queue == N_DRIVE)
 +                      fdc_queue = 0;
 +              if (q) {
 +                      current_req = blk_fetch_request(q);
 +                      if (current_req)
 +                              break;
 +              }
 +      } while (fdc_queue != old_pos);
 +
 +      return current_req != NULL;
 +}
 +
  static void redo_fd_request(void)
  {
        int drive;
  
  do_request:
        if (!current_req) {
 -              struct request *req;
 +              int pending;
 +
 +              spin_lock_irq(&floppy_lock);
 +              pending = set_next_request();
 +              spin_unlock_irq(&floppy_lock);
  
 -              spin_lock_irq(floppy_queue->queue_lock);
 -              req = blk_fetch_request(floppy_queue);
 -              spin_unlock_irq(floppy_queue->queue_lock);
 -              if (!req) {
 +              if (!pending) {
                        do_floppy = NULL;
                        unlock_fdc();
                        return;
                }
 -              current_req = req;
        }
        drive = (long)current_req->rq_disk->private_data;
        set_fdc(drive);
@@@ -3578,9 -3558,9 +3583,9 @@@ static int fd_ioctl(struct block_devic
  {
        int ret;
  
 -      lock_kernel();
 +      mutex_lock(&floppy_mutex);
        ret = fd_locked_ioctl(bdev, mode, cmd, param);
 -      unlock_kernel();
 +      mutex_unlock(&floppy_mutex);
  
        return ret;
  }
@@@ -3641,7 -3621,7 +3646,7 @@@ static int floppy_release(struct gendis
  {
        int drive = (long)disk->private_data;
  
 -      lock_kernel();
 +      mutex_lock(&floppy_mutex);
        mutex_lock(&open_lock);
        if (UDRS->fd_ref < 0)
                UDRS->fd_ref = 0;
        if (!UDRS->fd_ref)
                opened_bdev[drive] = NULL;
        mutex_unlock(&open_lock);
 -      unlock_kernel();
 +      mutex_unlock(&floppy_mutex);
  
        return 0;
  }
@@@ -3670,7 -3650,7 +3675,7 @@@ static int floppy_open(struct block_dev
        int res = -EBUSY;
        char *tmp;
  
 -      lock_kernel();
 +      mutex_lock(&floppy_mutex);
        mutex_lock(&open_lock);
        old_dev = UDRS->fd_device;
        if (opened_bdev[drive] && opened_bdev[drive] != bdev)
                        goto out;
        }
        mutex_unlock(&open_lock);
 -      unlock_kernel();
 +      mutex_unlock(&floppy_mutex);
        return 0;
  out:
        if (UDRS->fd_ref < 0)
                opened_bdev[drive] = NULL;
  out2:
        mutex_unlock(&open_lock);
 -      unlock_kernel();
 +      mutex_unlock(&floppy_mutex);
        return res;
  }
  
@@@ -3782,7 -3762,7 +3787,7 @@@ static int check_floppy_change(struct g
        if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
            test_bit(FD_VERIFY_BIT, &UDRS->flags) ||
            test_bit(drive, &fake_change) ||
-           (!ITYPE(UDRS->fd_device) && !current_type[drive]))
+           drive_no_geom(drive))
                return 1;
        return 0;
  }
@@@ -3848,13 -3828,13 +3853,13 @@@ static int __floppy_read_block_0(struc
  static int floppy_revalidate(struct gendisk *disk)
  {
        int drive = (long)disk->private_data;
- #define NO_GEOM (!current_type[drive] && !ITYPE(UDRS->fd_device))
        int cf;
        int res = 0;
  
        if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
            test_bit(FD_VERIFY_BIT, &UDRS->flags) ||
-           test_bit(drive, &fake_change) || NO_GEOM) {
+           test_bit(drive, &fake_change) ||
+           drive_no_geom(drive)) {
                if (WARN(atomic_read(&usage_count) == 0,
                         "VFS: revalidate called on non-open device.\n"))
                        return -EFAULT;
                lock_fdc(drive, false);
                cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
                      test_bit(FD_VERIFY_BIT, &UDRS->flags));
-               if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)) {
+               if (!(cf || test_bit(drive, &fake_change) || drive_no_geom(drive))) {
                        process_fd_request();   /*already done by another thread */
                        return 0;
                }
                clear_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
                if (cf)
                        UDRS->generation++;
-               if (NO_GEOM) {
+               if (drive_no_geom(drive)) {
                        /* auto-sensing */
                        res = __floppy_read_block_0(opened_bdev[drive]);
                } else {
@@@ -4190,13 -4170,6 +4195,13 @@@ static int __init floppy_init(void
                        goto out_put_disk;
                }
  
 +              disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
 +              if (!disks[dr]->queue) {
 +                      err = -ENOMEM;
 +                      goto out_put_disk;
 +              }
 +
 +              blk_queue_max_hw_sectors(disks[dr]->queue, 64);
                disks[dr]->major = FLOPPY_MAJOR;
                disks[dr]->first_minor = TOMINOR(dr);
                disks[dr]->fops = &floppy_fops;
        if (err)
                goto out_unreg_blkdev;
  
 -      floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
 -      if (!floppy_queue) {
 -              err = -ENOMEM;
 -              goto out_unreg_driver;
 -      }
 -      blk_queue_max_hw_sectors(floppy_queue, 64);
 -
        blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
                            floppy_find, NULL, NULL);
  
  
                /* to be cleaned up... */
                disks[drive]->private_data = (void *)(long)drive;
 -              disks[drive]->queue = floppy_queue;
                disks[drive]->flags |= GENHD_FL_REMOVABLE;
                disks[drive]->driverfs_dev = &floppy_device[drive].dev;
                add_disk(disks[drive]);
  out_unreg_platform_dev:
        platform_device_unregister(&floppy_device[drive]);
  out_flush_work:
 -      flush_scheduled_work();
 +      flush_work_sync(&floppy_work);
        if (atomic_read(&usage_count))
                floppy_release_irq_and_dma();
  out_unreg_region:
        blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
 -      blk_cleanup_queue(floppy_queue);
 -out_unreg_driver:
        platform_driver_unregister(&floppy_driver);
  out_unreg_blkdev:
        unregister_blkdev(FLOPPY_MAJOR, "fd");
  out_put_disk:
        while (dr--) {
                del_timer(&motor_off_timer[dr]);
 +              if (disks[dr]->queue)
 +                      blk_cleanup_queue(disks[dr]->queue);
                put_disk(disks[dr]);
        }
        return err;
@@@ -4422,7 -4403,7 +4427,7 @@@ static int floppy_grab_irq_and_dma(void
         * We might have scheduled a free_irq(), wait it to
         * drain first:
         */
 -      flush_scheduled_work();
 +      flush_work_sync(&floppy_work);
  
        if (fd_request_irq()) {
                DPRINT("Unable to grab IRQ%d for the floppy driver\n",
@@@ -4573,12 -4554,12 +4578,12 @@@ static void __exit floppy_module_exit(v
                        device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
                        platform_device_unregister(&floppy_device[drive]);
                }
 +              blk_cleanup_queue(disks[drive]->queue);
                put_disk(disks[drive]);
        }
  
        del_timer_sync(&fd_timeout);
        del_timer_sync(&fd_timer);
 -      blk_cleanup_queue(floppy_queue);
  
        if (atomic_read(&usage_count))
                floppy_release_irq_and_dma();