Skip to content

Commit

Permalink
[SCSI] hpsa: Fix p1210m LUN assignment.
Browse files Browse the repository at this point in the history
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: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Stephen M. Cameron authored and James Bottomley committed Feb 17, 2010
1 parent f8b01eb commit 339b2b1
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 20 deletions.
117 changes: 97 additions & 20 deletions drivers/scsi/hpsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
};
Expand Down Expand Up @@ -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. */
}
Expand Down Expand Up @@ -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 "
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/scsi/hpsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 339b2b1

Please sign in to comment.