Merge by hand (conflicts between pending drivers and kfree cleanups)
authorJames Bottomley <jejb@mulgrave.(none)>
Tue, 8 Nov 2005 17:50:26 +0000 (12:50 -0500)
committerJames Bottomley <jejb@mulgrave.(none)>
Tue, 8 Nov 2005 17:50:26 +0000 (12:50 -0500)
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
1  2 
drivers/block/cciss.c
drivers/scsi/ide-scsi.c
drivers/scsi/ips.c
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/raid_class.c
include/linux/pci_ids.h

diff --combined drivers/block/cciss.c
index a97c80b57737528b3e5cf6b1da2f351584dc14ca,482786068ff9630ad0f2605ce8d40e8ab7afcbf3..e239a6c2923052c4271f5d6414d7eec87f85b508
@@@ -148,6 -148,7 +148,7 @@@ static struct board_type products[] = 
  static ctlr_info_t *hba[MAX_CTLR];
  
  static void do_cciss_request(request_queue_t *q);
+ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs);
  static int cciss_open(struct inode *inode, struct file *filep);
  static int cciss_release(struct inode *inode, struct file *filep);
  static int cciss_ioctl(struct inode *inode, struct file *filep, 
@@@ -1096,11 -1097,14 +1097,11 @@@ static int cciss_ioctl(struct inode *in
  cleanup1:
                if (buff) {
                        for(i=0; i<sg_used; i++)
 -                              if(buff[i] != NULL)
 -                                      kfree(buff[i]);
 +                              kfree(buff[i]);
                        kfree(buff);
                }
 -              if (buff_size)
 -                      kfree(buff_size);
 -              if (ioc)
 -                      kfree(ioc);
 +              kfree(buff_size);
 +              kfree(ioc);
                return(status);
        }
        default:
@@@ -1583,6 -1587,24 +1584,24 @@@ static int fill_cmd(CommandList_struct 
                }
        } else if (cmd_type == TYPE_MSG) {
                switch (cmd) {
+               case 0: /* ABORT message */
+                       c->Request.CDBLen = 12;
+                       c->Request.Type.Attribute = ATTR_SIMPLE;
+                       c->Request.Type.Direction = XFER_WRITE;
+                       c->Request.Timeout = 0;
+                       c->Request.CDB[0] = cmd; /* abort */
+                       c->Request.CDB[1] = 0;   /* abort a command */
+                       /* buff contains the tag of the command to abort */
+                       memcpy(&c->Request.CDB[4], buff, 8);
+                       break;
+               case 1: /* RESET message */
+                       c->Request.CDBLen = 12;
+                       c->Request.Type.Attribute = ATTR_SIMPLE;
+                       c->Request.Type.Direction = XFER_WRITE;
+                       c->Request.Timeout = 0;
+                       memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
+                       c->Request.CDB[0] = cmd;  /* reset */
+                       c->Request.CDB[1] = 0x04; /* reset a LUN */
                case 3: /* No-Op message */
                        c->Request.CDBLen = 1;
                        c->Request.Type.Attribute = ATTR_SIMPLE;
@@@ -1869,6 -1891,52 +1888,52 @@@ static unsigned long pollcomplete(int c
        /* Invalid address to tell caller we ran out of time */
        return 1;
  }
+ static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete)
+ {
+       /* We get in here if sendcmd() is polling for completions
+          and gets some command back that it wasn't expecting -- 
+          something other than that which it just sent down.  
+          Ordinarily, that shouldn't happen, but it can happen when 
+          the scsi tape stuff gets into error handling mode, and
+          starts using sendcmd() to try to abort commands and 
+          reset tape drives.  In that case, sendcmd may pick up
+          completions of commands that were sent to logical drives
+          through the block i/o system, or cciss ioctls completing, etc. 
+          In that case, we need to save those completions for later
+          processing by the interrupt handler.
+       */
+ #ifdef CONFIG_CISS_SCSI_TAPE
+       struct sendcmd_reject_list *srl = &hba[ctlr]->scsi_rejects;     
+       /* If it's not the scsi tape stuff doing error handling, (abort */
+       /* or reset) then we don't expect anything weird. */
+       if (cmd != CCISS_RESET_MSG && cmd != CCISS_ABORT_MSG) {
+ #endif
+               printk( KERN_WARNING "cciss cciss%d: SendCmd "
+                     "Invalid command list address returned! (%lx)\n",
+                       ctlr, complete);
+               /* not much we can do. */
+ #ifdef CONFIG_CISS_SCSI_TAPE
+               return 1;
+       }
+       /* We've sent down an abort or reset, but something else
+          has completed */
+       if (srl->ncompletions >= (NR_CMDS + 2)) {
+               /* Uh oh.  No room to save it for later... */
+               printk(KERN_WARNING "cciss%d: Sendcmd: Invalid command addr, "
+                       "reject list overflow, command lost!\n", ctlr);
+               return 1;
+       }
+       /* Save it for later */
+       srl->complete[srl->ncompletions] = complete;
+       srl->ncompletions++;
+ #endif
+       return 0;
+ }
  /*
   * Send a command to the controller, and wait for it to complete.  
   * Only used at init time. 
@@@ -1891,7 -1959,7 +1956,7 @@@ static int sendcmd
        unsigned long complete;
        ctlr_info_t *info_p= hba[ctlr];
        u64bit buff_dma_handle;
-       int status;
+       int status, done = 0;
  
        if ((c = cmd_alloc(info_p, 1)) == NULL) {
                printk(KERN_WARNING "cciss: unable to get memory");
@@@ -1913,7 -1981,9 +1978,9 @@@ resend_cmd1
          info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF);
        
        /* Make sure there is room in the command FIFO */
-         /* Actually it should be completely empty at this time. */
+         /* Actually it should be completely empty at this time */
+       /* unless we are in here doing error handling for the scsi */
+       /* tape side of the driver. */
          for (i = 200000; i > 0; i--) 
        {
                /* if fifo isn't full go */
           * Send the cmd
           */
          info_p->access.submit_command(info_p, c);
-         complete = pollcomplete(ctlr);
+       done = 0;
+       do {
+               complete = pollcomplete(ctlr);
  
  #ifdef CCISS_DEBUG
-       printk(KERN_DEBUG "cciss: command completed\n");
+               printk(KERN_DEBUG "cciss: command completed\n");
  #endif /* CCISS_DEBUG */
  
-       if (complete != 1) {
+               if (complete == 1) {
+                       printk( KERN_WARNING
+                               "cciss cciss%d: SendCmd Timeout out, "
+                               "No command list address returned!\n",
+                               ctlr);
+                       status = IO_ERROR;
+                       done = 1;
+                       break;
+               }
+               /* This will need to change for direct lookup completions */
                if ( (complete & CISS_ERROR_BIT)
                     && (complete & ~CISS_ERROR_BIT) == c->busaddr)
                     {
                                                status = IO_ERROR;
                                                goto cleanup1;
                                        }
+                               } else if (c->err_info->CommandStatus == CMD_UNABORTABLE) {
+                                       printk(KERN_WARNING "cciss%d: command could not be aborted.\n", ctlr);
+                                       status = IO_ERROR;
+                                       goto cleanup1;
                                }
                                printk(KERN_WARNING "ciss ciss%d: sendcmd"
                                " Error %x \n", ctlr, 
                                goto cleanup1;
                        }
                }
+               /* This will need changing for direct lookup completions */
                  if (complete != c->busaddr) {
-                         printk( KERN_WARNING "cciss cciss%d: SendCmd "
-                       "Invalid command list address returned! (%lx)\n",
-                                 ctlr, complete);
-                       status = IO_ERROR;
-                       goto cleanup1;
-                 }
-         } else {
-                 printk( KERN_WARNING
-                         "cciss cciss%d: SendCmd Timeout out, "
-                         "No command list address returned!\n",
-                         ctlr);
-               status = IO_ERROR;
-         }
+                       if (add_sendcmd_reject(cmd, ctlr, complete) != 0) {
+                               BUG(); /* we are pretty much hosed if we get here. */
+                       }
+                       continue;
+                 } else
+                       done = 1;
+         } while (!done);
                
  cleanup1:     
        /* unlock the data buffer from DMA */
        buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
        pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val,
                                c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
+ #ifdef CONFIG_CISS_SCSI_TAPE
+       /* if we saved some commands for later, process them now. */
+       if (info_p->scsi_rejects.ncompletions > 0)
+               do_cciss_intr(0, info_p, NULL);
+ #endif
        cmd_free(info_p, c, 1);
        return (status);
  } 
@@@ -2335,6 -2421,48 +2418,48 @@@ startio
        start_io(h);
  }
  
+ static inline unsigned long get_next_completion(ctlr_info_t *h)
+ {
+ #ifdef CONFIG_CISS_SCSI_TAPE
+       /* Any rejects from sendcmd() lying around? Process them first */
+       if (h->scsi_rejects.ncompletions == 0)
+               return h->access.command_completed(h);
+       else {
+               struct sendcmd_reject_list *srl;
+               int n;
+               srl = &h->scsi_rejects;
+               n = --srl->ncompletions;
+               /* printk("cciss%d: processing saved reject\n", h->ctlr); */
+               printk("p");
+               return srl->complete[n];
+       }
+ #else
+       return h->access.command_completed(h);
+ #endif
+ }
+ static inline int interrupt_pending(ctlr_info_t *h)
+ {
+ #ifdef CONFIG_CISS_SCSI_TAPE
+       return ( h->access.intr_pending(h) 
+               || (h->scsi_rejects.ncompletions > 0));
+ #else
+       return h->access.intr_pending(h);
+ #endif
+ }
+ static inline long interrupt_not_for_us(ctlr_info_t *h)
+ {
+ #ifdef CONFIG_CISS_SCSI_TAPE
+       return (((h->access.intr_pending(h) == 0) || 
+                (h->interrupts_enabled == 0)) 
+             && (h->scsi_rejects.ncompletions == 0));
+ #else
+       return (((h->access.intr_pending(h) == 0) || 
+                (h->interrupts_enabled == 0)));
+ #endif
+ }
  static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
  {
        ctlr_info_t *h = dev_id;
        int j;
        int start_queue = h->next_to_run;
  
-       /* Is this interrupt for us? */
-       if (( h->access.intr_pending(h) == 0) || (h->interrupts_enabled == 0))
+       if (interrupt_not_for_us(h))
                return IRQ_NONE;
        /*
         * If there are completed commands in the completion queue,
         * we had better do something about it.
         */
        spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
-       while( h->access.intr_pending(h))
-       {
-               while((a = h->access.command_completed(h)) != FIFO_EMPTY) 
-               {
+       while (interrupt_pending(h)) {
+               while((a = get_next_completion(h)) != FIFO_EMPTY) {
                        a1 = a;
                        if ((a & 0x04)) {
                                a2 = (a >> 3);
@@@ -2963,7 -3087,15 +3084,15 @@@ static int __devinit cciss_init_one(str
                  printk( KERN_ERR "cciss: out of memory");
                goto clean4;
        }
+ #ifdef CONFIG_CISS_SCSI_TAPE
+       hba[i]->scsi_rejects.complete = 
+               kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) * 
+                       (NR_CMDS + 5), GFP_KERNEL);
+       if (hba[i]->scsi_rejects.complete == NULL) {
+                 printk( KERN_ERR "cciss: out of memory");
+               goto clean4;
+       }
+ #endif
        spin_lock_init(&hba[i]->lock);
  
        /* Initialize the pdev driver private data. 
        return(1);
  
  clean4:
 -      if(hba[i]->cmd_pool_bits)
 -                      kfree(hba[i]->cmd_pool_bits);
+ #ifdef CONFIG_CISS_SCSI_TAPE
+       if(hba[i]->scsi_rejects.complete)
+               kfree(hba[i]->scsi_rejects.complete);
+ #endif
 +      kfree(hba[i]->cmd_pool_bits);
        if(hba[i]->cmd_pool)
                pci_free_consistent(hba[i]->pdev,
                        NR_CMDS * sizeof(CommandList_struct),
@@@ -3103,6 -3240,9 +3236,9 @@@ static void __devexit cciss_remove_one 
        pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct),
                hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle);
        kfree(hba[i]->cmd_pool_bits);
+ #ifdef CONFIG_CISS_SCSI_TAPE
+       kfree(hba[i]->scsi_rejects.complete);
+ #endif
        release_io_mem(hba[i]);
        free_hba(i);
  }     
diff --combined drivers/scsi/ide-scsi.c
index c888af4a45629cf8fa138dabcc99646f8199723d,50d0cec5477754d9a208e5241063a41fd6d5cfb1..3553da0e1cd5c213fac3466b2e08a51399c5feed
@@@ -331,9 -331,9 +331,9 @@@ static int idescsi_check_condition(ide_
        rq = kmalloc (sizeof (struct request), GFP_ATOMIC);
        buf = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC);
        if (pc == NULL || rq == NULL || buf == NULL) {
 -              if (pc) kfree(pc);
 -              if (rq) kfree(rq);
 -              if (buf) kfree(buf);
 +              kfree(buf);
 +              kfree(rq);
 +              kfree(pc);
                return -ENOMEM;
        }
        memset (pc, 0, sizeof (idescsi_pc_t));
@@@ -395,6 -395,7 +395,7 @@@ static int idescsi_end_request (ide_dri
        int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
        struct Scsi_Host *host;
        u8 *scsi_buf;
+       int errors = rq->errors;
        unsigned long flags;
  
        if (!(rq->flags & (REQ_SPECIAL|REQ_SENSE))) {
                        printk (KERN_WARNING "ide-scsi: %s: timed out for %lu\n",
                                        drive->name, pc->scsi_cmd->serial_number);
                pc->scsi_cmd->result = DID_TIME_OUT << 16;
-       } else if (rq->errors >= ERROR_MAX) {
+       } else if (errors >= ERROR_MAX) {
                pc->scsi_cmd->result = DID_ERROR << 16;
                if (log)
                        printk ("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->scsi_cmd->serial_number);
-       } else if (rq->errors) {
+       } else if (errors) {
                if (log)
                        printk ("ide-scsi: %s: check condition for %lu\n", drive->name, pc->scsi_cmd->serial_number);
                if (!idescsi_check_condition(drive, rq))
@@@ -949,8 -950,8 +950,8 @@@ static int idescsi_queue (struct scsi_c
        spin_lock_irq(host->host_lock);
        return 0;
  abort:
 -      if (pc) kfree (pc);
 -      if (rq) kfree (rq);
 +      kfree (pc);
 +      kfree (rq);
        cmd->result = DID_ERROR << 16;
        done(cmd);
        return 0;
diff --combined drivers/scsi/ips.c
index cd9b95db5a7d419ba29f82d6fd8aa45233d2b146,d0c51a2d40ba03d5cb599a2ed0846bd7d684c3d3..cae3262a29570f19f0ef97b5f9e799394a63618a
  /*          - Remove 3 unused "inline" functions                             */
  /* 7.12.xx  - Use STATIC functions whereever possible                        */
  /*          - Clean up deprecated MODULE_PARM calls                          */
+ /* 7.12.05  - Remove Version Matching per IBM request                        */
  /*****************************************************************************/
  
  /*
@@@ -210,7 -211,7 +211,7 @@@ module_param(ips, charp, 0)
   * DRIVER_VER
   */
  #define IPS_VERSION_HIGH        "7.12"
- #define IPS_VERSION_LOW         ".02 "
+ #define IPS_VERSION_LOW         ".05 "
  
  #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__)
  #warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
@@@ -347,8 -348,6 +348,6 @@@ static int ips_proc_info(struct Scsi_Ho
  static int ips_host_info(ips_ha_t *, char *, off_t, int);
  static void copy_mem_info(IPS_INFOSTR *, char *, int);
  static int copy_info(IPS_INFOSTR *, char *, ...);
- static int ips_get_version_info(ips_ha_t * ha, dma_addr_t, int intr);
- static void ips_version_check(ips_ha_t * ha, int intr);
  static int ips_abort_init(ips_ha_t * ha, int index);
  static int ips_init_phase2(int index);
  
@@@ -406,8 -405,6 +405,6 @@@ static Scsi_Host_Template ips_driver_te
  #endif
  };
  
- static IPS_DEFINE_COMPAT_TABLE( Compatable ); /* Version Compatability Table      */
  
  /* This table describes all ServeRAID Adapters */
  static struct  pci_device_id  ips_pci_table[] = {
@@@ -4517,8 -4514,10 +4514,8 @@@ ips_free(ips_ha_t * ha
                        ha->enq = NULL;
                }
  
 -              if (ha->conf) {
 -                      kfree(ha->conf);
 -                      ha->conf = NULL;
 -              }
 +              kfree(ha->conf);
 +              ha->conf = NULL;
  
                if (ha->adapt) {
                        pci_free_consistent(ha->pcidev,
                        ha->logical_drive_info = NULL;
                }
  
 -              if (ha->nvram) {
 -                      kfree(ha->nvram);
 -                      ha->nvram = NULL;
 -              }
 +              kfree(ha->nvram);
 +              ha->nvram = NULL;
  
 -              if (ha->subsys) {
 -                      kfree(ha->subsys);
 -                      ha->subsys = NULL;
 -              }
 +              kfree(ha->subsys);
 +              ha->subsys = NULL;
  
                if (ha->ioctl_data) {
                        pci_free_consistent(ha->pcidev, ha->ioctl_len,
@@@ -5930,7 -5933,7 +5927,7 @@@ ips_write_driver_status(ips_ha_t * ha, 
        strncpy((char *) ha->nvram->bios_high, ha->bios_version, 4);
        strncpy((char *) ha->nvram->bios_low, ha->bios_version + 4, 4);
  
-       ips_version_check(ha, intr);    /* Check BIOS/FW/Driver Versions */
+       ha->nvram->versioning = 0;      /* Indicate the Driver Does Not Support Versioning */
  
        /* now update the page */
        if (!ips_readwrite_page5(ha, TRUE, intr)) {
@@@ -6847,135 -6850,6 +6844,6 @@@ ips_verify_bios_memio(ips_ha_t * ha, ch
                return (0);
  }
  
- /*---------------------------------------------------------------------------*/
- /*   Routine Name: ips_version_check                                         */
- /*                                                                           */
- /*   Dependencies:                                                           */
- /*     Assumes that ips_read_adapter_status() is called first filling in     */
- /*     the data for SubSystem Parameters.                                    */
- /*     Called from ips_write_driver_status() so it also assumes NVRAM Page 5 */
- /*     Data is available.                                                    */
- /*                                                                           */
- /*---------------------------------------------------------------------------*/
- static void
- ips_version_check(ips_ha_t * ha, int intr)
- {
-       IPS_VERSION_DATA *VersionInfo;
-       uint8_t FirmwareVersion[IPS_COMPAT_ID_LENGTH + 1];
-       uint8_t BiosVersion[IPS_COMPAT_ID_LENGTH + 1];
-       int MatchError;
-       int rc;
-       char BiosString[10];
-       char FirmwareString[10];
-       METHOD_TRACE("ips_version_check", 1);
-       VersionInfo = ( IPS_VERSION_DATA * ) ha->ioctl_data;
-       memset(FirmwareVersion, 0, IPS_COMPAT_ID_LENGTH + 1);
-       memset(BiosVersion, 0, IPS_COMPAT_ID_LENGTH + 1);
-       /* Get the Compatible BIOS Version from NVRAM Page 5 */
-       memcpy(BiosVersion, ha->nvram->BiosCompatibilityID,
-              IPS_COMPAT_ID_LENGTH);
-       rc = IPS_FAILURE;
-       if (ha->subsys->param[4] & IPS_GET_VERSION_SUPPORT) {   /* If Versioning is Supported */
-               /* Get the Version Info with a Get Version Command */
-               memset( VersionInfo, 0, sizeof (IPS_VERSION_DATA));
-               rc = ips_get_version_info(ha, ha->ioctl_busaddr, intr);
-               if (rc == IPS_SUCCESS)
-                       memcpy(FirmwareVersion, VersionInfo->compatibilityId,
-                              IPS_COMPAT_ID_LENGTH);
-       }
-       if (rc != IPS_SUCCESS) {        /* If Data Not Obtainable from a GetVersion Command */
-               /* Get the Firmware Version from Enquiry Data */
-               memcpy(FirmwareVersion, ha->enq->CodeBlkVersion,
-                      IPS_COMPAT_ID_LENGTH);
-       }
-       /* printk(KERN_WARNING "Adapter's BIOS Version  = %s\n", BiosVersion);          */
-       /* printk(KERN_WARNING "BIOS Compatible Version = %s\n", IPS_COMPAT_BIOS);      */
-       /* printk(KERN_WARNING "Adapter's Firmware Version  = %s\n", FirmwareVersion);  */
-       /* printk(KERN_WARNING "Firmware Compatible Version = %s \n", Compatable[ ha->nvram->adapter_type ]); */
-       MatchError = 0;
-       if (strncmp
-           (FirmwareVersion, Compatable[ha->nvram->adapter_type],
-            IPS_COMPAT_ID_LENGTH) != 0)
-               MatchError = 1;
-       if (strncmp(BiosVersion, IPS_COMPAT_BIOS, IPS_COMPAT_ID_LENGTH) != 0)
-               MatchError = 1;
-       ha->nvram->versioning = 1;      /* Indicate the Driver Supports Versioning */
-       if (MatchError) {
-               ha->nvram->version_mismatch = 1;
-               if (ips_cd_boot == 0) {
-                       strncpy(&BiosString[0], ha->nvram->bios_high, 4);
-                       strncpy(&BiosString[4], ha->nvram->bios_low, 4);
-                       BiosString[8] = 0;
-                       strncpy(&FirmwareString[0], ha->enq->CodeBlkVersion, 8);
-                       FirmwareString[8] = 0;
-                       IPS_PRINTK(KERN_WARNING, ha->pcidev,
-                                  "Warning ! ! ! ServeRAID Version Mismatch\n");
-                       IPS_PRINTK(KERN_WARNING, ha->pcidev,
-                                  "Bios = %s, Firmware = %s, Device Driver = %s%s\n",
-                                  BiosString, FirmwareString, IPS_VERSION_HIGH,
-                                  IPS_VERSION_LOW);
-                       IPS_PRINTK(KERN_WARNING, ha->pcidev,
-                                  "These levels should match to avoid possible compatibility problems.\n");
-               }
-       } else {
-               ha->nvram->version_mismatch = 0;
-       }
-       return;
- }
- /*---------------------------------------------------------------------------*/
- /*   Routine Name: ips_get_version_info                                      */
- /*                                                                           */
- /*   Routine Description:                                                    */
- /*     Issue an internal GETVERSION Command                                  */
- /*                                                                           */
- /*   Return Value:                                                           */
- /*     0 if Successful, else non-zero                                        */
- /*---------------------------------------------------------------------------*/
- static int
- ips_get_version_info(ips_ha_t * ha, dma_addr_t Buffer, int intr)
- {
-       ips_scb_t *scb;
-       int rc;
-       METHOD_TRACE("ips_get_version_info", 1);
-       scb = &ha->scbs[ha->max_cmds - 1];
-       ips_init_scb(ha, scb);
-       scb->timeout = ips_cmd_timeout;
-       scb->cdb[0] = IPS_CMD_GET_VERSION_INFO;
-       scb->cmd.version_info.op_code = IPS_CMD_GET_VERSION_INFO;
-       scb->cmd.version_info.command_id = IPS_COMMAND_ID(ha, scb);
-       scb->cmd.version_info.reserved = 0;
-       scb->cmd.version_info.count = sizeof (IPS_VERSION_DATA);
-       scb->cmd.version_info.reserved2 = 0;
-       scb->data_len = sizeof (IPS_VERSION_DATA);
-       scb->data_busaddr = Buffer;
-       scb->cmd.version_info.buffer_addr = Buffer;
-       scb->flags = 0;
-       /* issue command */
-       rc = ips_send_wait(ha, scb, ips_cmd_timeout, intr);
-       return (rc);
- }
  /****************************************************************************/
  /*                                                                          */
  /* Routine Name: ips_abort_init                                             */
index 1a3d195a2d366d3994a39bc525bf5a0e5b69fe20,670c7a44ab6799a6122d353186715b8e755b1e5d..4b5d420d2f4d36c017e01a3541d7d277c890f67b
@@@ -533,8 -533,6 +533,6 @@@ megaraid_probe_one(struct pci_dev *pdev
  
        // Initialize the synchronization lock for kernel and LLD
        spin_lock_init(&adapter->lock);
-       adapter->host_lock = &adapter->lock;
  
        // Initialize the command queues: the list of free SCBs and the list
        // of pending SCBs.
@@@ -715,9 -713,6 +713,6 @@@ megaraid_io_attach(adapter_t *adapter
        SCSIHOST2ADAP(host)     = (caddr_t)adapter;
        adapter->host           = host;
  
-       // export the parameters required by the mid-layer
-       scsi_assign_lock(host, adapter->host_lock);
        host->irq               = adapter->irq;
        host->unique_id         = adapter->unique_id;
        host->can_queue         = adapter->max_cmds;
@@@ -1560,10 -1555,6 +1555,6 @@@ megaraid_queue_command(struct scsi_cmn
        scp->scsi_done  = done;
        scp->result     = 0;
  
-       assert_spin_locked(adapter->host_lock);
-       spin_unlock(adapter->host_lock);
        /*
         * Allocate and build a SCB request
         * if_busy flag will be set if megaraid_mbox_build_cmd() command could
         * return 0 in that case, and we would do the callback right away.
         */
        if_busy = 0;
-       scb     = megaraid_mbox_build_cmd(adapter, scp, &if_busy);
-       if (scb) {
-               megaraid_mbox_runpendq(adapter, scb);
-       }
-       spin_lock(adapter->host_lock);
+       scb = megaraid_mbox_build_cmd(adapter, scp, &if_busy);
        if (!scb) {     // command already completed
                done(scp);
                return 0;
        }
  
+       megaraid_mbox_runpendq(adapter, scb);
        return if_busy;
  }
  
  /**
   * megaraid_mbox_build_cmd - transform the mid-layer scsi command to megaraid
   * firmware lingua
@@@ -2546,9 -2530,7 +2530,7 @@@ megaraid_mbox_dpc(unsigned long devp
                megaraid_dealloc_scb(adapter, scb);
  
                // send the scsi packet back to kernel
-               spin_lock(adapter->host_lock);
                scp->scsi_done(scp);
-               spin_unlock(adapter->host_lock);
        }
  
        return;
   * aborted. All the commands issued to the F/W must complete.
   **/
  static int
__megaraid_abort_handler(struct scsi_cmnd *scp)
+ megaraid_abort_handler(struct scsi_cmnd *scp)
  {
        adapter_t               *adapter;
        mraid_device_t          *raid_dev;
        adapter         = SCP2ADAPTER(scp);
        raid_dev        = ADAP2RAIDDEV(adapter);
  
-       assert_spin_locked(adapter->host_lock);
        con_log(CL_ANN, (KERN_WARNING
                "megaraid: aborting-%ld cmd=%x <c=%d t=%d l=%d>\n",
                scp->serial_number, scp->cmnd[0], SCP2CHANNEL(scp),
        // traverse through the list of all SCB, since driver does not
        // maintain these SCBs on any list
        found = 0;
+       spin_lock_irq(&adapter->lock);
        for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
                scb = adapter->kscb_list + i;
  
                        }
                }
        }
+       spin_unlock_irq(&adapter->lock);
  
        if (!found) {
                con_log(CL_ANN, (KERN_WARNING
        return FAILED;
  }
  
- static int
- megaraid_abort_handler(struct scsi_cmnd *scp)
- {
-       adapter_t       *adapter;
-       int rc;
-       adapter         = SCP2ADAPTER(scp);
-       spin_lock_irq(adapter->host_lock);
-       rc = __megaraid_abort_handler(scp);
-       spin_unlock_irq(adapter->host_lock);
-       return rc;
- }
  /**
   * megaraid_reset_handler - device reset hadler for mailbox based driver
   * @scp               : reference command
   * host
   **/
  static int
__megaraid_reset_handler(struct scsi_cmnd *scp)
+ megaraid_reset_handler(struct scsi_cmnd *scp)
  {
        adapter_t       *adapter;
        scb_t           *scb;
        adapter         = SCP2ADAPTER(scp);
        raid_dev        = ADAP2RAIDDEV(adapter);
  
-       assert_spin_locked(adapter->host_lock);
-       con_log(CL_ANN, (KERN_WARNING "megaraid: reseting the host...\n"));
        // return failure if adapter is not responding
        if (raid_dev->hw_error) {
                con_log(CL_ANN, (KERN_NOTICE
                        adapter->outstanding_cmds, MBOX_RESET_WAIT));
        }
  
-       spin_unlock(adapter->host_lock);
        recovery_window = MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT;
  
        recovering = adapter->outstanding_cmds;
                msleep(1000);
        }
  
-       spin_lock(adapter->host_lock);
+       spin_lock(&adapter->lock);
  
        // If still outstanding commands, bail out
        if (adapter->outstanding_cmds) {
  
                raid_dev->hw_error = 1;
  
-               return FAILED;
+               rval = FAILED;
+               goto out;
        }
        else {
                con_log(CL_ANN, (KERN_NOTICE
  
  
        // If the controller supports clustering, reset reservations
-       if (!adapter->ha) return SUCCESS;
+       if (!adapter->ha) {
+               rval = SUCCESS;
+               goto out;
+       }
  
        // clear reservations if any
        raw_mbox[0] = CLUSTER_CMD;
                                "megaraid: reservation reset failed\n"));
        }
  
+  out:
+       spin_unlock_irq(&adapter->lock);
        return rval;
  }
  
- static int
- megaraid_reset_handler(struct scsi_cmnd *cmd)
- {
-       int rc;
-       spin_lock_irq(cmd->device->host->host_lock);
-       rc = __megaraid_reset_handler(cmd);
-       spin_unlock_irq(cmd->device->host->host_lock);
-       return rc;
- }
  /*
   * START: internal commands library
   *
@@@ -3776,9 -3729,9 +3729,9 @@@ wait_till_fw_empty(adapter_t *adapter
        /*
         * Set the quiescent flag to stop issuing cmds to FW.
         */
-       spin_lock_irqsave(adapter->host_lock, flags);
+       spin_lock_irqsave(&adapter->lock, flags);
        adapter->quiescent++;
-       spin_unlock_irqrestore(adapter->host_lock, flags);
+       spin_unlock_irqrestore(&adapter->lock, flags);
  
        /*
         * Wait till there are no more cmds outstanding at FW. Try for at most
@@@ -3937,8 -3890,9 +3890,8 @@@ megaraid_sysfs_free_resources(adapter_
  {
        mraid_device_t  *raid_dev = ADAP2RAIDDEV(adapter);
  
 -      if (raid_dev->sysfs_uioc) kfree(raid_dev->sysfs_uioc);
 -
 -      if (raid_dev->sysfs_mbox64) kfree(raid_dev->sysfs_mbox64);
 +      kfree(raid_dev->sysfs_uioc);
 +      kfree(raid_dev->sysfs_mbox64);
  
        if (raid_dev->sysfs_buffer) {
                pci_free_consistent(adapter->pdev, PAGE_SIZE,
index caa0c3629626c3a6102d28df8164521964a228ca,a9f99c68556f0cdeff85d1d6bab5e0999028591d..5b1c12041a4fd054ffb00bed6bb9eefda1665930
@@@ -1,11 -1,17 +1,19 @@@
  /*
-  * RAID Attributes
+  * raid_class.c - implementation of a simple raid visualisation class
+  *
+  * Copyright (c) 2005 - James Bottomley <James.Bottomley@steeleye.com>
+  *
+  * This file is licensed under GPLv2
+  *
+  * This class is designed to allow raid attributes to be visualised and
+  * manipulated in a form independent of the underlying raid.  Ultimately this
+  * should work for both hardware and software raids.
   */
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/list.h>
 +#include <linux/slab.h>
 +#include <linux/string.h>
  #include <linux/raid_class.h>
  #include <scsi/scsi_device.h>
  #include <scsi/scsi_host.h>
@@@ -24,7 -30,7 +32,7 @@@ struct raid_internal 
  
  struct raid_component {
        struct list_head node;
-       struct device *dev;
+       struct class_device cdev;
        int num;
  };
  
@@@ -74,11 -80,10 +82,10 @@@ static int raid_setup(struct transport_
  
        BUG_ON(class_get_devdata(cdev));
  
-       rd = kmalloc(sizeof(*rd), GFP_KERNEL);
+       rd = kzalloc(sizeof(*rd), GFP_KERNEL);
        if (!rd)
                return -ENOMEM;
  
-       memset(rd, 0, sizeof(*rd));
        INIT_LIST_HEAD(&rd->component_list);
        class_set_devdata(cdev, rd);
                
@@@ -90,15 -95,15 +97,15 @@@ static int raid_remove(struct transport
  {
        struct raid_data *rd = class_get_devdata(cdev);
        struct raid_component *rc, *next;
+       dev_printk(KERN_ERR, dev, "RAID REMOVE\n");
        class_set_devdata(cdev, NULL);
        list_for_each_entry_safe(rc, next, &rd->component_list, node) {
-               char buf[40];
-               snprintf(buf, sizeof(buf), "component-%d", rc->num);
                list_del(&rc->node);
-               sysfs_remove_link(&cdev->kobj, buf);
-               kfree(rc);
+               dev_printk(KERN_ERR, rc->cdev.dev, "RAID COMPONENT REMOVE\n");
+               class_device_unregister(&rc->cdev);
        }
-       kfree(class_get_devdata(cdev));
+       dev_printk(KERN_ERR, dev, "RAID REMOVE DONE\n");
+       kfree(rd);
        return 0;
  }
  
@@@ -112,10 -117,11 +119,11 @@@ static struct 
        enum raid_state value;
        char            *name;
  } raid_states[] = {
-       { RAID_ACTIVE, "active" },
-       { RAID_DEGRADED, "degraded" },
-       { RAID_RESYNCING, "resyncing" },
-       { RAID_OFFLINE, "offline" },
+       { RAID_STATE_UNKNOWN, "unknown" },
+       { RAID_STATE_ACTIVE, "active" },
+       { RAID_STATE_DEGRADED, "degraded" },
+       { RAID_STATE_RESYNCING, "resyncing" },
+       { RAID_STATE_OFFLINE, "offline" },
  };
  
  static const char *raid_state_name(enum raid_state state)
        return name;
  }
  
+ static struct {
+       enum raid_level value;
+       char *name;
+ } raid_levels[] = {
+       { RAID_LEVEL_UNKNOWN, "unknown" },
+       { RAID_LEVEL_LINEAR, "linear" },
+       { RAID_LEVEL_0, "raid0" },
+       { RAID_LEVEL_1, "raid1" },
+       { RAID_LEVEL_3, "raid3" },
+       { RAID_LEVEL_4, "raid4" },
+       { RAID_LEVEL_5, "raid5" },
+       { RAID_LEVEL_6, "raid6" },
+ };
+ static const char *raid_level_name(enum raid_level level)
+ {
+       int i;
+       char *name = NULL;
+       for (i = 0; i < sizeof(raid_levels)/sizeof(raid_levels[0]); i++) {
+               if (raid_levels[i].value == level) {
+                       name = raid_levels[i].name;
+                       break;
+               }
+       }
+       return name;
+ }
  
  #define raid_attr_show_internal(attr, fmt, var, code)                 \
  static ssize_t raid_show_##attr(struct class_device *cdev, char *buf) \
@@@ -161,11 -194,22 +196,22 @@@ static CLASS_DEVICE_ATTR(attr, S_IRUGO
  
  #define raid_attr_ro(attr)    raid_attr_ro_internal(attr, )
  #define raid_attr_ro_fn(attr) raid_attr_ro_internal(attr, ATTR_CODE(attr))
- #define raid_attr_ro_state(attr)      raid_attr_ro_states(attr, attr, ATTR_CODE(attr))
+ #define raid_attr_ro_state(attr)      raid_attr_ro_states(attr, attr, )
+ #define raid_attr_ro_state_fn(attr)   raid_attr_ro_states(attr, attr, ATTR_CODE(attr))
  
- raid_attr_ro(level);
+ raid_attr_ro_state(level);
  raid_attr_ro_fn(resync);
- raid_attr_ro_state(state);
+ raid_attr_ro_state_fn(state);
+ static void raid_component_release(struct class_device *cdev)
+ {
+       struct raid_component *rc = container_of(cdev, struct raid_component,
+                                                cdev);
+       dev_printk(KERN_ERR, rc->cdev.dev, "COMPONENT RELEASE\n");
+       put_device(rc->cdev.dev);
+       kfree(rc);
+ }
  
  void raid_component_add(struct raid_template *r,struct device *raid_dev,
                        struct device *component_dev)
                                                      raid_dev);
        struct raid_component *rc;
        struct raid_data *rd = class_get_devdata(cdev);
-       char buf[40];
  
-       rc = kmalloc(sizeof(*rc), GFP_KERNEL);
+       rc = kzalloc(sizeof(*rc), GFP_KERNEL);
        if (!rc)
                return;
  
        INIT_LIST_HEAD(&rc->node);
-       rc->dev = component_dev;
+       class_device_initialize(&rc->cdev);
+       rc->cdev.release = raid_component_release;
+       rc->cdev.dev = get_device(component_dev);
        rc->num = rd->component_count++;
  
-       snprintf(buf, sizeof(buf), "component-%d", rc->num);
+       snprintf(rc->cdev.class_id, sizeof(rc->cdev.class_id),
+                "component-%d", rc->num);
        list_add_tail(&rc->node, &rd->component_list);
-       sysfs_create_link(&cdev->kobj, &component_dev->kobj, buf);
+       rc->cdev.parent = cdev;
+       rc->cdev.class = &raid_class.class;
+       class_device_add(&rc->cdev);
  }
  EXPORT_SYMBOL(raid_component_add);
  
  struct raid_template *
  raid_class_attach(struct raid_function_template *ft)
  {
-       struct raid_internal *i = kmalloc(sizeof(struct raid_internal),
+       struct raid_internal *i = kzalloc(sizeof(struct raid_internal),
                                          GFP_KERNEL);
        int count = 0;
  
        if (unlikely(!i))
                return NULL;
  
-       memset(i, 0, sizeof(*i));
        i->f = ft;
  
        i->r.raid_attrs.ac.class = &raid_class.class;
diff --combined include/linux/pci_ids.h
index 9a96f05883935a32955b216fcc3184bf162b0a85,641095920aab3b6acad3c58a9c554b87ca93e9de..914b55f4abbb2ed1841d44fb1b9b527dc8537cba
  #define PCI_DEVICE_ID_IBM_SNIPE               0x0180
  #define PCI_DEVICE_ID_IBM_CITRINE             0x028C
  #define PCI_DEVICE_ID_IBM_GEMSTONE            0xB166
+ #define PCI_DEVICE_ID_IBM_OBSIDIAN            0x02BD
  #define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1       0x0031
  #define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2       0x0219
  #define PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX               0x021A
  #define PCI_DEVICE_ID_MATROX_MIL      0x0519
  #define PCI_DEVICE_ID_MATROX_MYS      0x051A
  #define PCI_DEVICE_ID_MATROX_MIL_2    0x051b
 +#define PCI_DEVICE_ID_MATROX_MYS_AGP  0x051e
  #define PCI_DEVICE_ID_MATROX_MIL_2_AGP        0x051f
  #define PCI_DEVICE_ID_MATROX_MGA_IMP  0x0d10
  #define PCI_DEVICE_ID_MATROX_G100_MM  0x1000
  #define PCI_DEVICE_ID_TIGON3_5704     0x1648
  #define PCI_DEVICE_ID_TIGON3_5704S_2  0x1649
  #define PCI_DEVICE_ID_NX2_5706                0x164a
 +#define PCI_DEVICE_ID_NX2_5708                0x164c
  #define PCI_DEVICE_ID_TIGON3_5702FE   0x164d
  #define PCI_DEVICE_ID_TIGON3_5705     0x1653
  #define PCI_DEVICE_ID_TIGON3_5705_2   0x1654
  #define PCI_DEVICE_ID_TIGON3_5703X    0x16a7
  #define PCI_DEVICE_ID_TIGON3_5704S    0x16a8
  #define PCI_DEVICE_ID_NX2_5706S               0x16aa
 +#define PCI_DEVICE_ID_NX2_5708S               0x16ac
  #define PCI_DEVICE_ID_TIGON3_5702A3   0x16c6
  #define PCI_DEVICE_ID_TIGON3_5703A3   0x16c7
  #define PCI_DEVICE_ID_TIGON3_5781     0x16dd
  #define PCI_DEVICE_ID_ADAPTEC2_7899B  0x00c1
  #define PCI_DEVICE_ID_ADAPTEC2_7899D  0x00c3
  #define PCI_DEVICE_ID_ADAPTEC2_7899P  0x00cf
+ #define PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN   0x0500
  #define PCI_DEVICE_ID_ADAPTEC2_SCAMP  0x0503