diff options
Diffstat (limited to 'drivers/scsi/hpsa.c')
-rw-r--r-- | drivers/scsi/hpsa.c | 117 |
1 files changed, 81 insertions, 36 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 4f7cdb28bd38..9abe81021484 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -81,11 +81,8 @@ MODULE_DESCRIPTION("Driver for HP Smart Array Controller version " \ MODULE_SUPPORTED_DEVICE("HP Smart Array Controllers"); MODULE_VERSION(HPSA_DRIVER_VERSION); MODULE_LICENSE("GPL"); +MODULE_ALIAS("cciss"); -static int hpsa_allow_any; -module_param(hpsa_allow_any, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(hpsa_allow_any, - "Allow hpsa driver to access unknown HP Smart Array hardware"); static int hpsa_simple_mode; module_param(hpsa_simple_mode, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(hpsa_simple_mode, @@ -148,6 +145,8 @@ static const struct pci_device_id hpsa_pci_device_id[] = { {PCI_VENDOR_ID_HP, 0x333f, 0x103c, 0x333f}, {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 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,} }; @@ -158,6 +157,26 @@ MODULE_DEVICE_TABLE(pci, hpsa_pci_device_id); * access = Address of the struct of function pointers */ 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}, {0x3243103C, "Smart Array P410", &SA5_access}, {0x3245103C, "Smart Array P410i", &SA5_access}, @@ -278,7 +297,8 @@ static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr, u64 *cfg_offset); static int hpsa_pci_find_memory_BAR(struct pci_dev *pdev, 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, unsigned char lunaddr[], int reply_queue); @@ -866,6 +886,16 @@ static ssize_t host_show_ctlr_num(struct device *dev, 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(lunid, S_IRUGO, lunid_show, NULL); static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL); @@ -891,6 +921,8 @@ static DEVICE_ATTR(lockup_detected, S_IRUGO, host_show_lockup_detected, NULL); static DEVICE_ATTR(ctlr_num, S_IRUGO, host_show_ctlr_num, NULL); +static DEVICE_ATTR(legacy_board, S_IRUGO, + host_show_legacy_board, NULL); static struct device_attribute *hpsa_sdev_attrs[] = { &dev_attr_raid_level, @@ -912,6 +944,7 @@ static struct device_attribute *hpsa_shost_attrs[] = { &dev_attr_raid_offload_debug, &dev_attr_lockup_detected, &dev_attr_ctlr_num, + &dev_attr_legacy_board, NULL, }; @@ -3565,7 +3598,7 @@ static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical, memset(scsi3addr, 0, sizeof(scsi3addr)); if (fill_cmd(c, logical ? HPSA_REPORT_LOG : HPSA_REPORT_PHYS, h, buf, bufsize, 0, scsi3addr, TYPE_CMD)) { - rc = -1; + rc = -EAGAIN; goto out; } if (extended_response) @@ -3578,16 +3611,19 @@ static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical, if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { hpsa_scsi_interpret_error(h, c); - rc = -1; + rc = -EIO; } else { struct ReportLUNdata *rld = buf; if (rld->extended_response_flag != extended_response) { - dev_err(&h->pdev->dev, - "report luns requested format %u, got %u\n", - extended_response, - rld->extended_response_flag); - rc = -1; + if (!h->legacy_board) { + dev_err(&h->pdev->dev, + "report luns requested format %u, got %u\n", + extended_response, + rld->extended_response_flag); + rc = -EINVAL; + } else + rc = -EOPNOTSUPP; } } out: @@ -3603,7 +3639,7 @@ static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h, rc = hpsa_scsi_do_report_luns(h, 0, buf, bufsize, HPSA_REPORT_PHYS_EXTENDED); - if (!rc || !hpsa_allow_any) + if (!rc || rc != -EOPNOTSUPP) return rc; /* REPORT PHYS EXTENDED is not supported */ @@ -3791,7 +3827,7 @@ static int hpsa_update_device_info(struct ctlr_info *h, memset(this_device->device_id, 0, sizeof(this_device->device_id)); if (hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8, - sizeof(this_device->device_id))) + sizeof(this_device->device_id)) < 0) dev_err(&h->pdev->dev, "hpsa%d: %s: can't get device id for host %d:C0:T%d:L%d\t%s\t%.16s\n", h->ctlr, __func__, @@ -3809,6 +3845,16 @@ static int hpsa_update_device_info(struct ctlr_info *h, if (h->fw_support & MISC_FW_RAID_OFFLOAD_BASIC) hpsa_get_ioaccel_status(h, scsi3addr, this_device); volume_offline = hpsa_volume_offline(h, scsi3addr); + if (volume_offline == HPSA_VPD_LV_STATUS_UNSUPPORTED && + h->legacy_board) { + /* + * Legacy boards might not support volume status + */ + dev_info(&h->pdev->dev, + "C0:T%d:L%d Volume status not available, assuming online.\n", + this_device->target, this_device->lun); + volume_offline = 0; + } this_device->volume_offline = volume_offline; if (volume_offline == HPSA_LV_FAILED) { rc = HPSA_LV_FAILED; @@ -6571,7 +6617,6 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, default: dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd); BUG(); - return -1; } } else if (cmd_type == TYPE_MSG) { switch (cmd) { @@ -7232,7 +7277,8 @@ static int hpsa_interrupt_mode(struct ctlr_info *h) 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; u32 subsystem_vendor_id, subsystem_device_id; @@ -7242,17 +7288,24 @@ static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id) *board_id = ((subsystem_device_id << 16) & 0xffff0000) | subsystem_vendor_id; + if (legacy_board) + *legacy_board = false; 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; + 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 && - subsystem_vendor_id != PCI_VENDOR_ID_COMPAQ) || - !hpsa_allow_any) { - dev_warn(&pdev->dev, "unrecognized board ID: " - "0x%08x, ignoring.\n", *board_id); - return -ENODEV; - } + dev_warn(&pdev->dev, "unrecognized board ID: 0x%08x\n", *board_id); + if (legacy_board) + *legacy_board = true; return ARRAY_SIZE(products) - 1; /* generic unknown smart array */ } @@ -7555,13 +7608,14 @@ static void hpsa_free_pci_init(struct ctlr_info *h) static int hpsa_pci_init(struct ctlr_info *h) { 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) return prod_index; h->product_name = products[prod_index].product_name; h->access = *(products[prod_index].access); - + h->legacy_board = legacy_board; pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM); @@ -8241,7 +8295,7 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (number_of_controllers == 0) 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) { dev_warn(&pdev->dev, "Board ID not found\n"); return rc; @@ -9443,14 +9497,6 @@ hpsa_sas_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) return -EINVAL; } -/* SMP = Serial Management Protocol */ -static int -hpsa_sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, -struct request *req) -{ - return -EINVAL; -} - static struct sas_function_template hpsa_sas_transport_functions = { .get_linkerrors = hpsa_sas_get_linkerrors, .get_enclosure_identifier = hpsa_sas_get_enclosure_identifier, @@ -9460,7 +9506,6 @@ static struct sas_function_template hpsa_sas_transport_functions = { .phy_setup = hpsa_sas_phy_setup, .phy_release = hpsa_sas_phy_release, .set_phy_speed = hpsa_sas_phy_speed, - .smp_handler = hpsa_sas_smp_handler, }; /* |