diff options
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r-- | drivers/message/fusion/Kconfig | 1 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.c | 382 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.h | 9 | ||||
-rw-r--r-- | drivers/message/fusion/mptfc.c | 3 | ||||
-rw-r--r-- | drivers/message/fusion/mptsas.c | 72 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 153 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.h | 1 | ||||
-rw-r--r-- | drivers/message/fusion/mptspi.c | 9 |
8 files changed, 565 insertions, 65 deletions
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index c88cc75..4494e0f 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -37,6 +37,7 @@ config FUSION_FC LSIFC929 LSIFC929X LSIFC929XL + Brocade FC 410/420 config FUSION_SAS tristate "Fusion MPT ScsiHost drivers for SAS" diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 5a10c87..04f75e2 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -161,6 +161,7 @@ static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); static void mpt_timer_expired(unsigned long data); +static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc); static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag); @@ -1131,6 +1132,248 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) return -1; } +/** + * mpt_get_product_name - returns product string + * @vendor: pci vendor id + * @device: pci device id + * @revision: pci revision id + * @prod_name: string returned + * + * Returns product string displayed when driver loads, + * in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product + * + **/ +static void +mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name) +{ + char *product_str = NULL; + + if (vendor == PCI_VENDOR_ID_BROCADE) { + switch (device) + { + case MPI_MANUFACTPAGE_DEVICEID_FC949E: + switch (revision) + { + case 0x00: + product_str = "BRE040 A0"; + break; + case 0x01: + product_str = "BRE040 A1"; + break; + default: + product_str = "BRE040"; + break; + } + break; + } + goto out; + } + + switch (device) + { + case MPI_MANUFACTPAGE_DEVICEID_FC909: + product_str = "LSIFC909 B1"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC919: + product_str = "LSIFC919 B0"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC929: + product_str = "LSIFC929 B0"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC919X: + if (revision < 0x80) + product_str = "LSIFC919X A0"; + else + product_str = "LSIFC919XL A1"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC929X: + if (revision < 0x80) + product_str = "LSIFC929X A0"; + else + product_str = "LSIFC929XL A1"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC939X: + product_str = "LSIFC939X A1"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC949X: + product_str = "LSIFC949X A1"; + break; + case MPI_MANUFACTPAGE_DEVICEID_FC949E: + switch (revision) + { + case 0x00: + product_str = "LSIFC949E A0"; + break; + case 0x01: + product_str = "LSIFC949E A1"; + break; + default: + product_str = "LSIFC949E"; + break; + } + break; + case MPI_MANUFACTPAGE_DEVID_53C1030: + switch (revision) + { + case 0x00: + product_str = "LSI53C1030 A0"; + break; + case 0x01: + product_str = "LSI53C1030 B0"; + break; + case 0x03: + product_str = "LSI53C1030 B1"; + break; + case 0x07: + product_str = "LSI53C1030 B2"; + break; + case 0x08: + product_str = "LSI53C1030 C0"; + break; + case 0x80: + product_str = "LSI53C1030T A0"; + break; + case 0x83: + product_str = "LSI53C1030T A2"; + break; + case 0x87: + product_str = "LSI53C1030T A3"; + break; + case 0xc1: + product_str = "LSI53C1020A A1"; + break; + default: + product_str = "LSI53C1030"; + break; + } + break; + case MPI_MANUFACTPAGE_DEVID_1030_53C1035: + switch (revision) + { + case 0x03: + product_str = "LSI53C1035 A2"; + break; + case 0x04: + product_str = "LSI53C1035 B0"; + break; + default: + product_str = "LSI53C1035"; + break; + } + break; + case MPI_MANUFACTPAGE_DEVID_SAS1064: + switch (revision) + { + case 0x00: + product_str = "LSISAS1064 A1"; + break; + case 0x01: + product_str = "LSISAS1064 A2"; + break; + case 0x02: + product_str = "LSISAS1064 A3"; + break; + case 0x03: + product_str = "LSISAS1064 A4"; + break; + default: + product_str = "LSISAS1064"; + break; + } + break; + case MPI_MANUFACTPAGE_DEVID_SAS1064E: + switch (revision) + { + case 0x00: + product_str = "LSISAS1064E A0"; + break; + case 0x01: + product_str = "LSISAS1064E B0"; + break; + case 0x02: + product_str = "LSISAS1064E B1"; + break; + case 0x04: + product_str = "LSISAS1064E B2"; + break; + case 0x08: + product_str = "LSISAS1064E B3"; + break; + default: + product_str = "LSISAS1064E"; + break; + } + break; + case MPI_MANUFACTPAGE_DEVID_SAS1068: + switch (revision) + { + case 0x00: + product_str = "LSISAS1068 A0"; + break; + case 0x01: + product_str = "LSISAS1068 B0"; + break; + case 0x02: + product_str = "LSISAS1068 B1"; + break; + default: + product_str = "LSISAS1068"; + break; + } + break; + case MPI_MANUFACTPAGE_DEVID_SAS1068E: + switch (revision) + { + case 0x00: + product_str = "LSISAS1068E A0"; + break; + case 0x01: + product_str = "LSISAS1068E B0"; + break; + case 0x02: + product_str = "LSISAS1068E B1"; + break; + case 0x04: + product_str = "LSISAS1068E B2"; + break; + case 0x08: + product_str = "LSISAS1068E B3"; + break; + default: + product_str = "LSISAS1068E"; + break; + } + break; + case MPI_MANUFACTPAGE_DEVID_SAS1078: + switch (revision) + { + case 0x00: + product_str = "LSISAS1078 A0"; + break; + case 0x01: + product_str = "LSISAS1078 B0"; + break; + case 0x02: + product_str = "LSISAS1078 C0"; + break; + case 0x03: + product_str = "LSISAS1078 C1"; + break; + case 0x04: + product_str = "LSISAS1078 C2"; + break; + default: + product_str = "LSISAS1078"; + break; + } + break; + } + + out: + if (product_str) + sprintf(prod_name, "%s", product_str); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_attach - Install a PCI intelligent MPT adapter. @@ -1274,23 +1517,23 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->pio_chip = (SYSIF_REGS __iomem *)pmem; } - if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) { - ioc->prod_name = "LSIFC909"; - ioc->bus_type = FC; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) { - ioc->prod_name = "LSIFC929"; - ioc->bus_type = FC; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) { - ioc->prod_name = "LSIFC919"; - ioc->bus_type = FC; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) { - pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name); + + switch (pdev->device) + { + case MPI_MANUFACTPAGE_DEVICEID_FC939X: + case MPI_MANUFACTPAGE_DEVICEID_FC949X: + ioc->errata_flag_1064 = 1; + case MPI_MANUFACTPAGE_DEVICEID_FC909: + case MPI_MANUFACTPAGE_DEVICEID_FC929: + case MPI_MANUFACTPAGE_DEVICEID_FC919: + case MPI_MANUFACTPAGE_DEVICEID_FC949E: ioc->bus_type = FC; + break; + + case MPI_MANUFACTPAGE_DEVICEID_FC929X: if (revision < XL_929) { - ioc->prod_name = "LSIFC929X"; /* 929X Chip Fix. Set Split transactions level * for PCIX. Set MOST bits to zero. */ @@ -1298,75 +1541,46 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) pcixcmd &= 0x8F; pci_write_config_byte(pdev, 0x6a, pcixcmd); } else { - ioc->prod_name = "LSIFC929XL"; /* 929XL Chip Fix. Set MMRBC to 0x08. */ pci_read_config_byte(pdev, 0x6a, &pcixcmd); pcixcmd |= 0x08; pci_write_config_byte(pdev, 0x6a, pcixcmd); } - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) { - ioc->prod_name = "LSIFC919X"; ioc->bus_type = FC; + break; + + case MPI_MANUFACTPAGE_DEVICEID_FC919X: /* 919X Chip Fix. Set Split transactions level * for PCIX. Set MOST bits to zero. */ pci_read_config_byte(pdev, 0x6a, &pcixcmd); pcixcmd &= 0x8F; pci_write_config_byte(pdev, 0x6a, pcixcmd); - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) { - ioc->prod_name = "LSIFC939X"; - ioc->bus_type = FC; - ioc->errata_flag_1064 = 1; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) { - ioc->prod_name = "LSIFC949X"; ioc->bus_type = FC; - ioc->errata_flag_1064 = 1; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) { - ioc->prod_name = "LSIFC949E"; - ioc->bus_type = FC; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { - ioc->prod_name = "LSI53C1030"; - ioc->bus_type = SPI; + break; + + case MPI_MANUFACTPAGE_DEVID_53C1030: /* 1030 Chip Fix. Disable Split transactions * for PCIX. Set MOST bits to zero if Rev < C0( = 8). */ - pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); if (revision < C0_1030) { pci_read_config_byte(pdev, 0x6a, &pcixcmd); pcixcmd &= 0x8F; pci_write_config_byte(pdev, 0x6a, pcixcmd); } - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) { - ioc->prod_name = "LSI53C1035"; + + case MPI_MANUFACTPAGE_DEVID_1030_53C1035: ioc->bus_type = SPI; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) { - ioc->prod_name = "LSISAS1064"; - ioc->bus_type = SAS; - ioc->errata_flag_1064 = 1; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) { - ioc->prod_name = "LSISAS1068"; - ioc->bus_type = SAS; + break; + + case MPI_MANUFACTPAGE_DEVID_SAS1064: + case MPI_MANUFACTPAGE_DEVID_SAS1068: ioc->errata_flag_1064 = 1; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) { - ioc->prod_name = "LSISAS1064E"; - ioc->bus_type = SAS; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) { - ioc->prod_name = "LSISAS1068E"; - ioc->bus_type = SAS; - } - else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { - ioc->prod_name = "LSISAS1078"; + + case MPI_MANUFACTPAGE_DEVID_SAS1064E: + case MPI_MANUFACTPAGE_DEVID_SAS1068E: + case MPI_MANUFACTPAGE_DEVID_SAS1078: ioc->bus_type = SAS; } @@ -1880,6 +2094,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) } GetIoUnitPage2(ioc); + mpt_get_manufacturing_pg_0(ioc); } /* @@ -2138,8 +2353,8 @@ MptDisplayIocCapabilities(MPT_ADAPTER *ioc) int i = 0; printk(KERN_INFO "%s: ", ioc->name); - if (ioc->prod_name && strlen(ioc->prod_name) > 3) - printk("%s: ", ioc->prod_name+3); + if (ioc->prod_name) + printk("%s: ", ioc->prod_name); printk("Capabilities={"); if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) { @@ -5190,6 +5405,49 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc) return; } +static void +mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc) +{ + CONFIGPARMS cfg; + ConfigPageHeader_t hdr; + dma_addr_t buf_dma; + ManufacturingPage0_t *pbuf = NULL; + + memset(&cfg, 0 , sizeof(CONFIGPARMS)); + memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); + + hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING; + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.timeout = 10; + + if (mpt_config(ioc, &cfg) != 0) + goto out; + + if (!cfg.cfghdr.hdr->PageLength) + goto out; + + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma); + if (!pbuf) + goto out; + + cfg.physAddr = buf_dma; + + if (mpt_config(ioc, &cfg) != 0) + goto out; + + memcpy(ioc->board_name, pbuf->BoardName, sizeof(ioc->board_name)); + memcpy(ioc->board_assembly, pbuf->BoardAssembly, sizeof(ioc->board_assembly)); + memcpy(ioc->board_tracer, pbuf->BoardTracerNumber, sizeof(ioc->board_tracer)); + + out: + + if (pbuf) + pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * SendEventNotification - Send EventNotification (on or off) request to adapter diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 05eb6e5..98eb9c6 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -537,7 +537,14 @@ typedef struct _MPT_ADAPTER int id; /* Unique adapter id N {0,1,2,...} */ int pci_irq; /* This irq */ char name[MPT_NAME_LENGTH]; /* "iocN" */ - char *prod_name; /* "LSIFC9x9" */ + char prod_name[MPT_NAME_LENGTH]; /* "LSIFC9x9" */ + char board_name[16]; + char board_assembly[16]; + char board_tracer[16]; + u16 nvdata_version_persistent; + u16 nvdata_version_default; + u8 io_missing_delay; + u8 device_missing_delay; SYSIF_REGS __iomem *chip; /* == c8817000 (mmap) */ SYSIF_REGS __iomem *pio_chip; /* Programmed IO (downloadboot) */ u8 bus_type; diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index b766445..f2ebaa9 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -130,6 +130,7 @@ static struct scsi_host_template mptfc_driver_template = { .max_sectors = 8192, .cmd_per_lun = 7, .use_clustering = ENABLE_CLUSTERING, + .shost_attrs = mptscsih_host_attrs, }; /**************************************************************************** @@ -153,6 +154,8 @@ static struct pci_device_id mptfc_pci_table[] = { PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E, PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_BROCADE, MPI_MANUFACTPAGE_DEVICEID_FC949E, + PCI_ANY_ID, PCI_ANY_ID }, {0} /* Terminating entry */ }; MODULE_DEVICE_TABLE(pci, mptfc_pci_table); diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 9e5424e..d506646 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -1119,6 +1119,7 @@ static struct scsi_host_template mptsas_driver_template = { .max_sectors = 8192, .cmd_per_lun = 7, .use_clustering = ENABLE_CLUSTERING, + .shost_attrs = mptscsih_host_attrs, }; static int mptsas_get_linkerrors(struct sas_phy *phy) @@ -1390,6 +1391,11 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) goto out_free_consistent; } + ioc->nvdata_version_persistent = + le16_to_cpu(buffer->NvdataVersionPersistent); + ioc->nvdata_version_default = + le16_to_cpu(buffer->NvdataVersionDefault); + for (i = 0; i < port_info->num_phys; i++) { mptsas_print_phy_data(&buffer->PhyData[i]); port_info->phy_info[i].phy_id = i; @@ -1410,6 +1416,63 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) } static int +mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc) +{ + ConfigExtendedPageHeader_t hdr; + CONFIGPARMS cfg; + SasIOUnitPage1_t *buffer; + dma_addr_t dma_handle; + int error; + u16 device_missing_delay; + + memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t)); + memset(&cfg, 0, sizeof(CONFIGPARMS)); + + cfg.cfghdr.ehdr = &hdr; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.timeout = 10; + cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; + cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION; + cfg.cfghdr.ehdr->PageNumber = 1; + + error = mpt_config(ioc, &cfg); + if (error) + goto out; + if (!hdr.ExtPageLength) { + error = -ENXIO; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + &dma_handle); + if (!buffer) { + error = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + error = mpt_config(ioc, &cfg); + if (error) + goto out_free_consistent; + + ioc->io_missing_delay = + le16_to_cpu(buffer->IODeviceMissingDelay); + device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay); + ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ? + (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 : + device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK; + + out_free_consistent: + pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + buffer, dma_handle); + out: + return error; +} + +static int mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, u32 form, u32 form_specific) { @@ -1990,6 +2053,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) if (error) goto out_free_port_info; + mptsas_sas_io_unit_pg1(ioc); mutex_lock(&ioc->sas_topology_mutex); ioc->handle = hba->phy_info[0].handle; port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle); @@ -3237,6 +3301,8 @@ static struct pci_driver mptsas_driver = { static int __init mptsas_init(void) { + int error; + show_mptmod_ver(my_NAME, my_VERSION); mptsas_transport_template = @@ -3260,7 +3326,11 @@ mptsas_init(void) ": Registered for IOC reset notifications\n")); } - return pci_register_driver(&mptsas_driver); + error = pci_register_driver(&mptsas_driver); + if (error) + sas_release_transport(mptsas_transport_template); + + return error; } static void __exit diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index d356173..fd3aa26 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -3187,6 +3187,159 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) mptscsih_do_cmd(hd, &iocmd); } +static ssize_t +mptscsih_version_fw_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_ADAPTER *ioc = hd->ioc; + + return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", + (ioc->facts.FWVersion.Word & 0xFF000000) >> 24, + (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, + (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, + ioc->facts.FWVersion.Word & 0x000000FF); +} +static CLASS_DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL); + +static ssize_t +mptscsih_version_bios_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_ADAPTER *ioc = hd->ioc; + + return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", + (ioc->biosVersion & 0xFF000000) >> 24, + (ioc->biosVersion & 0x00FF0000) >> 16, + (ioc->biosVersion & 0x0000FF00) >> 8, + ioc->biosVersion & 0x000000FF); +} +static CLASS_DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL); + +static ssize_t +mptscsih_version_mpi_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_ADAPTER *ioc = hd->ioc; + + return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion); +} +static CLASS_DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL); + +static ssize_t +mptscsih_version_product_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_ADAPTER *ioc = hd->ioc; + + return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name); +} +static CLASS_DEVICE_ATTR(version_product, S_IRUGO, + mptscsih_version_product_show, NULL); + +static ssize_t +mptscsih_version_nvdata_persistent_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_ADAPTER *ioc = hd->ioc; + + return snprintf(buf, PAGE_SIZE, "%02xh\n", + ioc->nvdata_version_persistent); +} +static CLASS_DEVICE_ATTR(version_nvdata_persistent, S_IRUGO, + mptscsih_version_nvdata_persistent_show, NULL); + +static ssize_t +mptscsih_version_nvdata_default_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_ADAPTER *ioc = hd->ioc; + + return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default); +} +static CLASS_DEVICE_ATTR(version_nvdata_default, S_IRUGO, + mptscsih_version_nvdata_default_show, NULL); + +static ssize_t +mptscsih_board_name_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_ADAPTER *ioc = hd->ioc; + + return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name); +} +static CLASS_DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL); + +static ssize_t +mptscsih_board_assembly_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_ADAPTER *ioc = hd->ioc; + + return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly); +} +static CLASS_DEVICE_ATTR(board_assembly, S_IRUGO, + mptscsih_board_assembly_show, NULL); + +static ssize_t +mptscsih_board_tracer_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_ADAPTER *ioc = hd->ioc; + + return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer); +} +static CLASS_DEVICE_ATTR(board_tracer, S_IRUGO, + mptscsih_board_tracer_show, NULL); + +static ssize_t +mptscsih_io_delay_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_ADAPTER *ioc = hd->ioc; + + return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay); +} +static CLASS_DEVICE_ATTR(io_delay, S_IRUGO, + mptscsih_io_delay_show, NULL); + +static ssize_t +mptscsih_device_delay_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_ADAPTER *ioc = hd->ioc; + + return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay); +} +static CLASS_DEVICE_ATTR(device_delay, S_IRUGO, + mptscsih_device_delay_show, NULL); + +struct class_device_attribute *mptscsih_host_attrs[] = { + &class_device_attr_version_fw, + &class_device_attr_version_bios, + &class_device_attr_version_mpi, + &class_device_attr_version_product, + &class_device_attr_version_nvdata_persistent, + &class_device_attr_version_nvdata_default, + &class_device_attr_board_name, + &class_device_attr_board_assembly, + &class_device_attr_board_tracer, + &class_device_attr_io_delay, + &class_device_attr_device_delay, + NULL, +}; +EXPORT_SYMBOL(mptscsih_host_attrs); + EXPORT_SYMBOL(mptscsih_remove); EXPORT_SYMBOL(mptscsih_shutdown); #ifdef CONFIG_PM diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 8eccdfe..67b088d 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -129,3 +129,4 @@ extern void mptscsih_timer_expired(unsigned long data); extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id); extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id); +extern struct class_device_attribute *mptscsih_host_attrs[]; diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 6b3e0c0..947fe29 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -821,6 +821,7 @@ static struct scsi_host_template mptspi_driver_template = { .max_sectors = 8192, .cmd_per_lun = 7, .use_clustering = ENABLE_CLUSTERING, + .shost_attrs = mptscsih_host_attrs, }; static int mptspi_write_spi_device_pg1(struct scsi_target *starget, @@ -1523,6 +1524,8 @@ static struct pci_driver mptspi_driver = { static int __init mptspi_init(void) { + int error; + show_mptmod_ver(my_NAME, my_VERSION); mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions); @@ -1543,7 +1546,11 @@ mptspi_init(void) ": Registered for IOC reset notifications\n")); } - return pci_register_driver(&mptspi_driver); + error = pci_register_driver(&mptspi_driver); + if (error) + spi_release_transport(mptspi_transport_template); + + return error; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |