Commit 339b2b14 authored by Stephen M. Cameron's avatar Stephen M. Cameron Committed by James Bottomley

[SCSI] hpsa: Fix p1210m LUN assignment.

The p1210m responsds to SCSI report LUNs, unlike traditional Smart
Array controllers.  This means that the bus, target, and lun
assignments done by the driver cannot be arbitrary, but must match
what SCSI REPORT LUNS returns.
Signed-off-by: default avatarStephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent f8b01eb9
......@@ -458,6 +458,15 @@ static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[])
return (scsi3addr[3] & 0xC0) == 0x40;
}
static inline int is_scsi_rev_5(struct ctlr_info *h)
{
if (!h->hba_inquiry_data)
return 0;
if ((h->hba_inquiry_data[2] & 0x07) == 5)
return 1;
return 0;
}
static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
"UNKNOWN"
};
......@@ -1525,22 +1534,44 @@ static void figure_bus_target_lun(struct ctlr_info *h,
if (is_logical_dev_addr_mode(lunaddrbytes)) {
/* logical device */
lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
if (is_msa2xxx(h, device)) {
*bus = 1;
*target = (lunid >> 16) & 0x3fff;
*lun = lunid & 0x00ff;
} else {
if (unlikely(is_scsi_rev_5(h))) {
/* p1210m, logical drives lun assignments
* match SCSI REPORT LUNS data.
*/
lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
*bus = 0;
*lun = 0;
*target = lunid & 0x3fff;
*target = 0;
*lun = (lunid & 0x3fff) + 1;
} else {
/* not p1210m... */
lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
if (is_msa2xxx(h, device)) {
/* msa2xxx way, put logicals on bus 1
* and match target/lun numbers box
* reports.
*/
*bus = 1;
*target = (lunid >> 16) & 0x3fff;
*lun = lunid & 0x00ff;
} else {
/* Traditional smart array way. */
*bus = 0;
*lun = 0;
*target = lunid & 0x3fff;
}
}
} else {
/* physical device */
if (is_hba_lunid(lunaddrbytes))
*bus = 3;
if (unlikely(is_scsi_rev_5(h))) {
*bus = 0; /* put p1210m ctlr at 0,0,0 */
*target = 0;
*lun = 0;
return;
} else
*bus = 3; /* traditional smartarray */
else
*bus = 2;
*bus = 2; /* physical disk */
*target = -1;
*lun = -1; /* we will fill these in later. */
}
......@@ -1580,6 +1611,9 @@ static int add_msa2xxx_enclosure_device(struct ctlr_info *h,
if (is_hba_lunid(scsi3addr))
return 0; /* Don't add the RAID controller here. */
if (is_scsi_rev_5(h))
return 0; /* p1210m doesn't need to do this. */
#define MAX_MSA2XXX_ENCLOSURES 32
if (*nmsa2xxx_enclosures >= MAX_MSA2XXX_ENCLOSURES) {
dev_warn(&h->pdev->dev, "Maximum number of MSA2XXX "
......@@ -1643,6 +1677,31 @@ static int hpsa_gather_lun_info(struct ctlr_info *h,
return 0;
}
u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position, int i,
int nphysicals, int nlogicals, struct ReportLUNdata *physdev_list,
struct ReportLUNdata *logdev_list)
{
/* Helper function, figure out where the LUN ID info is coming from
* given index i, lists of physical and logical devices, where in
* the list the raid controller is supposed to appear (first or last)
*/
int logicals_start = nphysicals + (raid_ctlr_position == 0);
int last_device = nphysicals + nlogicals + (raid_ctlr_position == 0);
if (i == raid_ctlr_position)
return RAID_CTLR_LUNID;
if (i < logicals_start)
return &physdev_list->LUN[i - (raid_ctlr_position == 0)][0];
if (i < last_device)
return &logdev_list->LUN[i - nphysicals -
(raid_ctlr_position == 0)][0];
BUG();
return NULL;
}
static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
{
/* the idea here is we could get notified
......@@ -1666,6 +1725,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
int reportlunsize = sizeof(*physdev_list) + HPSA_MAX_PHYS_LUN * 8;
int i, nmsa2xxx_enclosures, ndevs_to_allocate;
int bus, target, lun;
int raid_ctlr_position;
DECLARE_BITMAP(lunzerobits, HPSA_MAX_TARGETS_PER_CTLR);
currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_SCSI_DEVS_PER_HBA,
......@@ -1703,23 +1763,22 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
ndev_allocated++;
}
if (unlikely(is_scsi_rev_5(h)))
raid_ctlr_position = 0;
else
raid_ctlr_position = nphysicals + nlogicals;
/* adjust our table of devices */
nmsa2xxx_enclosures = 0;
for (i = 0; i < nphysicals + nlogicals + 1; i++) {
u8 *lunaddrbytes;
/* Figure out where the LUN ID info is coming from */
if (i < nphysicals)
lunaddrbytes = &physdev_list->LUN[i][0];
else
if (i < nphysicals + nlogicals)
lunaddrbytes =
&logdev_list->LUN[i-nphysicals][0];
else /* jam in the RAID controller at the end */
lunaddrbytes = RAID_CTLR_LUNID;
lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position,
i, nphysicals, nlogicals, physdev_list, logdev_list);
/* skip masked physical devices. */
if (lunaddrbytes[3] & 0xC0 && i < nphysicals)
if (lunaddrbytes[3] & 0xC0 &&
i < nphysicals + (raid_ctlr_position == 0))
continue;
/* Get device type, vendor, model, device id */
......@@ -3349,6 +3408,22 @@ static int hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)
return err;
}
static void __devinit hpsa_hba_inquiry(struct ctlr_info *h)
{
int rc;
#define HBA_INQUIRY_BYTE_COUNT 64
h->hba_inquiry_data = kmalloc(HBA_INQUIRY_BYTE_COUNT, GFP_KERNEL);
if (!h->hba_inquiry_data)
return;
rc = hpsa_scsi_do_inquiry(h, RAID_CTLR_LUNID, 0,
h->hba_inquiry_data, HBA_INQUIRY_BYTE_COUNT);
if (rc != 0) {
kfree(h->hba_inquiry_data);
h->hba_inquiry_data = NULL;
}
}
static int __devinit hpsa_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
......@@ -3458,6 +3533,7 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
h->access.set_intr_mask(h, HPSA_INTR_ON);
hpsa_put_ctlr_into_performant_mode(h);
hpsa_hba_inquiry(h);
hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */
h->busy_initializing = 0;
return 1;
......@@ -3550,6 +3626,7 @@ static void __devexit hpsa_remove_one(struct pci_dev *pdev)
h->reply_pool, h->reply_pool_dhandle);
kfree(h->cmd_pool_bits);
kfree(h->blockFetchTable);
kfree(h->hba_inquiry_data);
/*
* Deliberately omit pci_disable_device(): it does something nasty to
* Smart Array controllers that pci_enable_device does not undo
......
......@@ -120,6 +120,7 @@ struct ctlr_info {
size_t reply_pool_size;
unsigned char reply_pool_wraparound;
u32 *blockFetchTable;
unsigned char *hba_inquiry_data;
};
#define HPSA_ABORT_MSG 0
#define HPSA_DEVICE_RESET_MSG 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment