scsi: hpsa: add support for legacy boards
Add support for legacy boards, ensuring to enable the driver for those boards only when 'hpsa_allow_any' is set. The attribute 'legacy_board' is set to '1' if the device is a legacy board, and '0' otherwise. Signed-off-by: Hannes Reinecke <hare@suse.com> Acked-by: Don Brace <don.brace@microsemi.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
committed by
Martin K. Petersen
parent
9ff870417e
commit
135ae6edeb
@@ -148,6 +148,8 @@ static const struct pci_device_id hpsa_pci_device_id[] = {
|
|||||||
{PCI_VENDOR_ID_HP, 0x333f, 0x103c, 0x333f},
|
{PCI_VENDOR_ID_HP, 0x333f, 0x103c, 0x333f},
|
||||||
{PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
|
{PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
|
||||||
PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
|
PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
|
||||||
|
{PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
|
||||||
|
PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
|
||||||
{0,}
|
{0,}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -158,6 +160,26 @@ MODULE_DEVICE_TABLE(pci, hpsa_pci_device_id);
|
|||||||
* access = Address of the struct of function pointers
|
* access = Address of the struct of function pointers
|
||||||
*/
|
*/
|
||||||
static struct board_type products[] = {
|
static struct board_type products[] = {
|
||||||
|
{0x40700E11, "Smart Array 5300", &SA5A_access},
|
||||||
|
{0x40800E11, "Smart Array 5i", &SA5B_access},
|
||||||
|
{0x40820E11, "Smart Array 532", &SA5B_access},
|
||||||
|
{0x40830E11, "Smart Array 5312", &SA5B_access},
|
||||||
|
{0x409A0E11, "Smart Array 641", &SA5A_access},
|
||||||
|
{0x409B0E11, "Smart Array 642", &SA5A_access},
|
||||||
|
{0x409C0E11, "Smart Array 6400", &SA5A_access},
|
||||||
|
{0x409D0E11, "Smart Array 6400 EM", &SA5A_access},
|
||||||
|
{0x40910E11, "Smart Array 6i", &SA5A_access},
|
||||||
|
{0x3225103C, "Smart Array P600", &SA5A_access},
|
||||||
|
{0x3223103C, "Smart Array P800", &SA5A_access},
|
||||||
|
{0x3234103C, "Smart Array P400", &SA5A_access},
|
||||||
|
{0x3235103C, "Smart Array P400i", &SA5A_access},
|
||||||
|
{0x3211103C, "Smart Array E200i", &SA5A_access},
|
||||||
|
{0x3212103C, "Smart Array E200", &SA5A_access},
|
||||||
|
{0x3213103C, "Smart Array E200i", &SA5A_access},
|
||||||
|
{0x3214103C, "Smart Array E200i", &SA5A_access},
|
||||||
|
{0x3215103C, "Smart Array E200i", &SA5A_access},
|
||||||
|
{0x3237103C, "Smart Array E500", &SA5A_access},
|
||||||
|
{0x323D103C, "Smart Array P700m", &SA5A_access},
|
||||||
{0x3241103C, "Smart Array P212", &SA5_access},
|
{0x3241103C, "Smart Array P212", &SA5_access},
|
||||||
{0x3243103C, "Smart Array P410", &SA5_access},
|
{0x3243103C, "Smart Array P410", &SA5_access},
|
||||||
{0x3245103C, "Smart Array P410i", &SA5_access},
|
{0x3245103C, "Smart Array P410i", &SA5_access},
|
||||||
@@ -278,7 +300,8 @@ static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr,
|
|||||||
u64 *cfg_offset);
|
u64 *cfg_offset);
|
||||||
static int hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
|
static int hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
|
||||||
unsigned long *memory_bar);
|
unsigned long *memory_bar);
|
||||||
static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id);
|
static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id,
|
||||||
|
bool *legacy_board);
|
||||||
static int wait_for_device_to_become_ready(struct ctlr_info *h,
|
static int wait_for_device_to_become_ready(struct ctlr_info *h,
|
||||||
unsigned char lunaddr[],
|
unsigned char lunaddr[],
|
||||||
int reply_queue);
|
int reply_queue);
|
||||||
@@ -866,6 +889,16 @@ static ssize_t host_show_ctlr_num(struct device *dev,
|
|||||||
return snprintf(buf, 20, "%d\n", h->ctlr);
|
return snprintf(buf, 20, "%d\n", h->ctlr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t host_show_legacy_board(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct ctlr_info *h;
|
||||||
|
struct Scsi_Host *shost = class_to_shost(dev);
|
||||||
|
|
||||||
|
h = shost_to_hba(shost);
|
||||||
|
return snprintf(buf, 20, "%d\n", h->legacy_board ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
|
static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
|
||||||
static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL);
|
static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL);
|
||||||
static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL);
|
static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL);
|
||||||
@@ -891,6 +924,8 @@ static DEVICE_ATTR(lockup_detected, S_IRUGO,
|
|||||||
host_show_lockup_detected, NULL);
|
host_show_lockup_detected, NULL);
|
||||||
static DEVICE_ATTR(ctlr_num, S_IRUGO,
|
static DEVICE_ATTR(ctlr_num, S_IRUGO,
|
||||||
host_show_ctlr_num, NULL);
|
host_show_ctlr_num, NULL);
|
||||||
|
static DEVICE_ATTR(legacy_board, S_IRUGO,
|
||||||
|
host_show_legacy_board, NULL);
|
||||||
|
|
||||||
static struct device_attribute *hpsa_sdev_attrs[] = {
|
static struct device_attribute *hpsa_sdev_attrs[] = {
|
||||||
&dev_attr_raid_level,
|
&dev_attr_raid_level,
|
||||||
@@ -912,6 +947,7 @@ static struct device_attribute *hpsa_shost_attrs[] = {
|
|||||||
&dev_attr_raid_offload_debug,
|
&dev_attr_raid_offload_debug,
|
||||||
&dev_attr_lockup_detected,
|
&dev_attr_lockup_detected,
|
||||||
&dev_attr_ctlr_num,
|
&dev_attr_ctlr_num,
|
||||||
|
&dev_attr_legacy_board,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -7232,7 +7268,8 @@ static int hpsa_interrupt_mode(struct ctlr_info *h)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
|
static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id,
|
||||||
|
bool *legacy_board)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
u32 subsystem_vendor_id, subsystem_device_id;
|
u32 subsystem_vendor_id, subsystem_device_id;
|
||||||
@@ -7242,9 +7279,22 @@ static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
|
|||||||
*board_id = ((subsystem_device_id << 16) & 0xffff0000) |
|
*board_id = ((subsystem_device_id << 16) & 0xffff0000) |
|
||||||
subsystem_vendor_id;
|
subsystem_vendor_id;
|
||||||
|
|
||||||
|
if (legacy_board)
|
||||||
|
*legacy_board = false;
|
||||||
for (i = 0; i < ARRAY_SIZE(products); i++)
|
for (i = 0; i < ARRAY_SIZE(products); i++)
|
||||||
if (*board_id == products[i].board_id)
|
if (*board_id == products[i].board_id) {
|
||||||
|
if (products[i].access != &SA5A_access &&
|
||||||
|
products[i].access != &SA5B_access)
|
||||||
return i;
|
return i;
|
||||||
|
if (hpsa_allow_any) {
|
||||||
|
dev_warn(&pdev->dev,
|
||||||
|
"legacy board ID: 0x%08x\n",
|
||||||
|
*board_id);
|
||||||
|
if (legacy_board)
|
||||||
|
*legacy_board = true;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((subsystem_vendor_id != PCI_VENDOR_ID_HP &&
|
if ((subsystem_vendor_id != PCI_VENDOR_ID_HP &&
|
||||||
subsystem_vendor_id != PCI_VENDOR_ID_COMPAQ) ||
|
subsystem_vendor_id != PCI_VENDOR_ID_COMPAQ) ||
|
||||||
@@ -7253,6 +7303,8 @@ static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
|
|||||||
"0x%08x, ignoring.\n", *board_id);
|
"0x%08x, ignoring.\n", *board_id);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
if (legacy_board)
|
||||||
|
*legacy_board = true;
|
||||||
return ARRAY_SIZE(products) - 1; /* generic unknown smart array */
|
return ARRAY_SIZE(products) - 1; /* generic unknown smart array */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7555,13 +7607,14 @@ static void hpsa_free_pci_init(struct ctlr_info *h)
|
|||||||
static int hpsa_pci_init(struct ctlr_info *h)
|
static int hpsa_pci_init(struct ctlr_info *h)
|
||||||
{
|
{
|
||||||
int prod_index, err;
|
int prod_index, err;
|
||||||
|
bool legacy_board;
|
||||||
|
|
||||||
prod_index = hpsa_lookup_board_id(h->pdev, &h->board_id);
|
prod_index = hpsa_lookup_board_id(h->pdev, &h->board_id, &legacy_board);
|
||||||
if (prod_index < 0)
|
if (prod_index < 0)
|
||||||
return prod_index;
|
return prod_index;
|
||||||
h->product_name = products[prod_index].product_name;
|
h->product_name = products[prod_index].product_name;
|
||||||
h->access = *(products[prod_index].access);
|
h->access = *(products[prod_index].access);
|
||||||
|
h->legacy_board = legacy_board;
|
||||||
pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S |
|
pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S |
|
||||||
PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
|
PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
|
||||||
|
|
||||||
@@ -8241,7 +8294,7 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||||||
if (number_of_controllers == 0)
|
if (number_of_controllers == 0)
|
||||||
printk(KERN_INFO DRIVER_NAME "\n");
|
printk(KERN_INFO DRIVER_NAME "\n");
|
||||||
|
|
||||||
rc = hpsa_lookup_board_id(pdev, &board_id);
|
rc = hpsa_lookup_board_id(pdev, &board_id, NULL);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
dev_warn(&pdev->dev, "Board ID not found\n");
|
dev_warn(&pdev->dev, "Board ID not found\n");
|
||||||
return rc;
|
return rc;
|
||||||
|
|||||||
@@ -293,6 +293,7 @@ struct ctlr_info {
|
|||||||
int drv_req_rescan;
|
int drv_req_rescan;
|
||||||
int raid_offload_debug;
|
int raid_offload_debug;
|
||||||
int discovery_polling;
|
int discovery_polling;
|
||||||
|
int legacy_board;
|
||||||
struct ReportLUNdata *lastlogicals;
|
struct ReportLUNdata *lastlogicals;
|
||||||
int needs_abort_tags_swizzled;
|
int needs_abort_tags_swizzled;
|
||||||
struct workqueue_struct *resubmit_wq;
|
struct workqueue_struct *resubmit_wq;
|
||||||
@@ -447,6 +448,23 @@ static void SA5_intr_mask(struct ctlr_info *h, unsigned long val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Variant of the above; 0x04 turns interrupts off...
|
||||||
|
*/
|
||||||
|
static void SA5B_intr_mask(struct ctlr_info *h, unsigned long val)
|
||||||
|
{
|
||||||
|
if (val) { /* Turn interrupts on */
|
||||||
|
h->interrupts_enabled = 1;
|
||||||
|
writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
|
||||||
|
(void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
|
||||||
|
} else { /* Turn them off */
|
||||||
|
h->interrupts_enabled = 0;
|
||||||
|
writel(SA5B_INTR_OFF,
|
||||||
|
h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
|
||||||
|
(void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val)
|
static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val)
|
||||||
{
|
{
|
||||||
if (val) { /* turn on interrupts */
|
if (val) { /* turn on interrupts */
|
||||||
@@ -549,6 +567,14 @@ static bool SA5_ioaccel_mode1_intr_pending(struct ctlr_info *h)
|
|||||||
true : false;
|
true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true if an interrupt is pending..
|
||||||
|
*/
|
||||||
|
static bool SA5B_intr_pending(struct ctlr_info *h)
|
||||||
|
{
|
||||||
|
return readl(h->vaddr + SA5_INTR_STATUS) & SA5B_INTR_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
#define IOACCEL_MODE1_REPLY_QUEUE_INDEX 0x1A0
|
#define IOACCEL_MODE1_REPLY_QUEUE_INDEX 0x1A0
|
||||||
#define IOACCEL_MODE1_PRODUCER_INDEX 0x1B8
|
#define IOACCEL_MODE1_PRODUCER_INDEX 0x1B8
|
||||||
#define IOACCEL_MODE1_CONSUMER_INDEX 0x1BC
|
#define IOACCEL_MODE1_CONSUMER_INDEX 0x1BC
|
||||||
@@ -587,6 +613,21 @@ static struct access_method SA5_access = {
|
|||||||
.command_completed = SA5_completed,
|
.command_completed = SA5_completed,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Duplicate entry of the above to mark unsupported boards */
|
||||||
|
static struct access_method SA5A_access = {
|
||||||
|
.submit_command = SA5_submit_command,
|
||||||
|
.set_intr_mask = SA5_intr_mask,
|
||||||
|
.intr_pending = SA5_intr_pending,
|
||||||
|
.command_completed = SA5_completed,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct access_method SA5B_access = {
|
||||||
|
.submit_command = SA5_submit_command,
|
||||||
|
.set_intr_mask = SA5B_intr_mask,
|
||||||
|
.intr_pending = SA5B_intr_pending,
|
||||||
|
.command_completed = SA5_completed,
|
||||||
|
};
|
||||||
|
|
||||||
static struct access_method SA5_ioaccel_mode1_access = {
|
static struct access_method SA5_ioaccel_mode1_access = {
|
||||||
.submit_command = SA5_submit_command,
|
.submit_command = SA5_submit_command,
|
||||||
.set_intr_mask = SA5_performant_intr_mask,
|
.set_intr_mask = SA5_performant_intr_mask,
|
||||||
|
|||||||
Reference in New Issue
Block a user