Merge branch 'for-3.2/drivers' of git://git.kernel.dk/linux-block
[pandora-kernel.git] / drivers / scsi / hpsa.c
index ec61bdb..bbdc9f9 100644 (file)
@@ -676,6 +676,16 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno,
        BUG_ON(entry < 0 || entry >= HPSA_MAX_SCSI_DEVS_PER_HBA);
        removed[*nremoved] = h->dev[entry];
        (*nremoved)++;
+
+       /*
+        * New physical devices won't have target/lun assigned yet
+        * so we need to preserve the values in the slot we are replacing.
+        */
+       if (new_entry->target == -1) {
+               new_entry->target = h->dev[entry]->target;
+               new_entry->lun = h->dev[entry]->lun;
+       }
+
        h->dev[entry] = new_entry;
        added[*nadded] = new_entry;
        (*nadded)++;
@@ -1548,10 +1558,17 @@ static inline void hpsa_set_bus_target_lun(struct hpsa_scsi_dev_t *device,
 }
 
 static int hpsa_update_device_info(struct ctlr_info *h,
-       unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device)
+       unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device,
+       unsigned char *is_OBDR_device)
 {
-#define OBDR_TAPE_INQ_SIZE 49
+
+#define OBDR_SIG_OFFSET 43
+#define OBDR_TAPE_SIG "$DR-10"
+#define OBDR_SIG_LEN (sizeof(OBDR_TAPE_SIG) - 1)
+#define OBDR_TAPE_INQ_SIZE (OBDR_SIG_OFFSET + OBDR_SIG_LEN)
+
        unsigned char *inq_buff;
+       unsigned char *obdr_sig;
 
        inq_buff = kzalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
        if (!inq_buff)
@@ -1583,6 +1600,16 @@ static int hpsa_update_device_info(struct ctlr_info *h,
        else
                this_device->raid_level = RAID_UNKNOWN;
 
+       if (is_OBDR_device) {
+               /* See if this is a One-Button-Disaster-Recovery device
+                * by looking for "$DR-10" at offset 43 in inquiry data.
+                */
+               obdr_sig = &inq_buff[OBDR_SIG_OFFSET];
+               *is_OBDR_device = (this_device->devtype == TYPE_ROM &&
+                                       strncmp(obdr_sig, OBDR_TAPE_SIG,
+                                               OBDR_SIG_LEN) == 0);
+       }
+
        kfree(inq_buff);
        return 0;
 
@@ -1716,7 +1743,7 @@ static int add_msa2xxx_enclosure_device(struct ctlr_info *h,
                return 0;
        }
 
-       if (hpsa_update_device_info(h, scsi3addr, this_device))
+       if (hpsa_update_device_info(h, scsi3addr, this_device, NULL))
                return 0;
        (*nmsa2xxx_enclosures)++;
        hpsa_set_bus_target_lun(this_device, bus, target, 0);
@@ -1808,7 +1835,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
         */
        struct ReportLUNdata *physdev_list = NULL;
        struct ReportLUNdata *logdev_list = NULL;
-       unsigned char *inq_buff = NULL;
        u32 nphysicals = 0;
        u32 nlogicals = 0;
        u32 ndev_allocated = 0;
@@ -1824,11 +1850,9 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
                GFP_KERNEL);
        physdev_list = kzalloc(reportlunsize, GFP_KERNEL);
        logdev_list = kzalloc(reportlunsize, GFP_KERNEL);
-       inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
        tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL);
 
-       if (!currentsd || !physdev_list || !logdev_list ||
-               !inq_buff || !tmpdevice) {
+       if (!currentsd || !physdev_list || !logdev_list || !tmpdevice) {
                dev_err(&h->pdev->dev, "out of memory\n");
                goto out;
        }
@@ -1863,7 +1887,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
        /* adjust our table of devices */
        nmsa2xxx_enclosures = 0;
        for (i = 0; i < nphysicals + nlogicals + 1; i++) {
-               u8 *lunaddrbytes;
+               u8 *lunaddrbytes, is_OBDR = 0;
 
                /* Figure out where the LUN ID info is coming from */
                lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position,
@@ -1874,7 +1898,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
                        continue;
 
                /* Get device type, vendor, model, device id */
-               if (hpsa_update_device_info(h, lunaddrbytes, tmpdevice))
+               if (hpsa_update_device_info(h, lunaddrbytes, tmpdevice,
+                                                       &is_OBDR))
                        continue; /* skip it if we can't talk to it. */
                figure_bus_target_lun(h, lunaddrbytes, &bus, &target, &lun,
                        tmpdevice);
@@ -1898,7 +1923,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
                hpsa_set_bus_target_lun(this_device, bus, target, lun);
 
                switch (this_device->devtype) {
-               case TYPE_ROM: {
+               case TYPE_ROM:
                        /* We don't *really* support actual CD-ROM devices,
                         * just "One Button Disaster Recovery" tape drive
                         * which temporarily pretends to be a CD-ROM drive.
@@ -1906,15 +1931,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
                         * device by checking for "$DR-10" in bytes 43-48 of
                         * the inquiry data.
                         */
-                               char obdr_sig[7];
-#define OBDR_TAPE_SIG "$DR-10"
-                               strncpy(obdr_sig, &inq_buff[43], 6);
-                               obdr_sig[6] = '\0';
-                               if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
-                                       /* Not OBDR device, ignore it. */
-                                       break;
-                       }
-                       ncurrent++;
+                       if (is_OBDR)
+                               ncurrent++;
                        break;
                case TYPE_DISK:
                        if (i < nphysicals)
@@ -1947,7 +1965,6 @@ out:
        for (i = 0; i < ndev_allocated; i++)
                kfree(currentsd[i]);
        kfree(currentsd);
-       kfree(inq_buff);
        kfree(physdev_list);
        kfree(logdev_list);
 }
@@ -3283,6 +3300,13 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
                pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
                pmcsr |= PCI_D0;
                pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+
+               /*
+                * The P600 requires a small delay when changing states.
+                * Otherwise we may think the board did not reset and we bail.
+                * This for kdump only and is particular to the P600.
+                */
+               msleep(500);
        }
        return 0;
 }
@@ -3421,10 +3445,8 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
        } else {
                use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
                if (use_doorbell) {
-                       dev_warn(&pdev->dev, "Controller claims that "
-                               "'Bit 2 doorbell reset' is "
-                               "supported, but not 'bit 5 doorbell reset'.  "
-                               "Firmware update is recommended.\n");
+                       dev_warn(&pdev->dev, "Soft reset not supported. "
+                               "Firmware update is required.\n");
                        rc = -ENOTSUPP; /* try soft reset */
                        goto unmap_cfgtable;
                }