]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/block/cciss.c
cciss: fix problem that deleting multiple logical drives could cause a panic
[linux-2.6-omap-h63xx.git] / drivers / block / cciss.c
index 4023885353e095e75d179f7ed8f649cd1abbb5a2..9f7c543cc04b265344b0e37443c4349147e88574 100644 (file)
@@ -96,6 +96,8 @@ static const struct pci_device_id cciss_pci_device_id[] = {
        {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_ANY_ID,      PCI_ANY_ID, PCI_ANY_ID,
                PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
        {0,}
@@ -133,6 +135,8 @@ static struct board_type products[] = {
        {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},
        {0xFFFF103C, "Unknown Smart Array", &SA5_access},
 };
 
@@ -1366,6 +1370,7 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk,
        disk->first_minor = drv_index << NWD_SHIFT;
        disk->fops = &cciss_fops;
        disk->private_data = &h->drv[drv_index];
+       disk->driverfs_dev = &h->pdev->dev;
 
        /* Set up queue information */
        blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask);
@@ -1688,6 +1693,11 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time)
        for (i = 0; i <= h->highest_lun; i++) {
                int j;
                drv_found = 0;
+
+               /* skip holes in the array from already deleted drives */
+               if (h->drv[i].raid_level == -1)
+                       continue;
+
                for (j = 0; j < num_luns; j++) {
                        memcpy(&lunid, &ld_buff->LUN[j][0], 4);
                        lunid = le32_to_cpu(lunid);
@@ -2842,7 +2852,7 @@ static void do_cciss_request(struct request_queue *q)
                h->maxSG = seg;
 
 #ifdef CCISS_DEBUG
-       printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n",
+       printk(KERN_DEBUG "cciss: Submitting %lu sectors in %d segments\n",
               creq->nr_sectors, seg);
 #endif                         /* CCISS_DEBUG */
 
@@ -3192,7 +3202,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 
        c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */
 #ifdef CCISS_DEBUG
-       printk("address 0 = %x\n", c->paddr);
+       printk("address 0 = %lx\n", c->paddr);
 #endif                         /* CCISS_DEBUG */
        c->vaddr = remap_pci_mem(c->paddr, 0x250);
 
@@ -3219,7 +3229,8 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 #endif                         /* CCISS_DEBUG */
        cfg_base_addr_index = find_PCI_BAR_index(pdev, cfg_base_addr);
 #ifdef CCISS_DEBUG
-       printk("cfg base address index = %x\n", cfg_base_addr_index);
+       printk("cfg base address index = %llx\n",
+               (unsigned long long)cfg_base_addr_index);
 #endif                         /* CCISS_DEBUG */
        if (cfg_base_addr_index == -1) {
                printk(KERN_WARNING "cciss: Cannot find cfg_base_addr_index\n");
@@ -3229,7 +3240,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 
        cfg_offset = readl(c->vaddr + SA5_CTMEM_OFFSET);
 #ifdef CCISS_DEBUG
-       printk("cfg offset = %x\n", cfg_offset);
+       printk("cfg offset = %llx\n", (unsigned long long)cfg_offset);
 #endif                         /* CCISS_DEBUG */
        c->cfgtable = remap_pci_mem(pci_resource_start(pdev,
                                                       cfg_base_addr_index) +
@@ -3404,7 +3415,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        int i;
        int j = 0;
        int rc;
-       int dac;
+       int dac, return_code;
+       InquiryData_struct *inq_buff = NULL;
 
        i = alloc_cciss_hba();
        if (i < 0)
@@ -3510,6 +3522,25 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        /* Turn the interrupts on so we can service requests */
        hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
 
+       /* Get the firmware version */
+       inq_buff = kzalloc(sizeof(InquiryData_struct), GFP_KERNEL);
+       if (inq_buff == NULL) {
+               printk(KERN_ERR "cciss: out of memory\n");
+               goto clean4;
+       }
+
+       return_code = sendcmd_withirq(CISS_INQUIRY, i, inq_buff,
+               sizeof(InquiryData_struct), 0, 0 , 0, TYPE_CMD);
+       if (return_code == IO_OK) {
+               hba[i]->firm_ver[0] = inq_buff->data_byte[32];
+               hba[i]->firm_ver[1] = inq_buff->data_byte[33];
+               hba[i]->firm_ver[2] = inq_buff->data_byte[34];
+               hba[i]->firm_ver[3] = inq_buff->data_byte[35];
+       } else {         /* send command failed */
+               printk(KERN_WARNING "cciss: unable to determine firmware"
+                       " version of controller\n");
+       }
+
        cciss_procinit(i);
 
        hba[i]->cciss_max_sectors = 2048;
@@ -3520,6 +3551,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        return 1;
 
 clean4:
+       kfree(inq_buff);
 #ifdef CONFIG_CISS_SCSI_TAPE
        kfree(hba[i]->scsi_rejects.complete);
 #endif