diff options
| author | Dave Carroll <david.carroll@microsemi.com> | 2018-12-07 17:28:47 -0500 |
|---|---|---|
| committer | Martin K. Petersen <martin.petersen@oracle.com> | 2018-12-19 22:23:34 -0500 |
| commit | cd128244162c8afbf50e93b88daa02b05faa4c0a (patch) | |
| tree | efc21b4b7bb34aaa1184f7ff1e539605ea670fd6 /drivers/scsi/smartpqi | |
| parent | 02133b68d51d09bd91b0d2c1fa5318e2f23e4559 (diff) | |
scsi: smartpqi: add sysfs attributes
- add sysfs device attributes, unique_id, lunid and path_info.
Reviewed-by: Scott Teel <scott.teel@microsemi.com>
Reviewed-by: Kevin Barnett <kevin.barnett@microsemi.com>
Signed-off-by: Dave Carroll <david.carroll@microsemi.com>
Signed-off-by: Don Brace <don.brace@microsemi.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/smartpqi')
| -rw-r--r-- | drivers/scsi/smartpqi/smartpqi.h | 3 | ||||
| -rw-r--r-- | drivers/scsi/smartpqi/smartpqi_init.c | 232 |
2 files changed, 235 insertions, 0 deletions
diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h index fcc4b937de71..a39c324dedab 100644 --- a/drivers/scsi/smartpqi/smartpqi.h +++ b/drivers/scsi/smartpqi/smartpqi.h | |||
| @@ -852,6 +852,7 @@ struct pqi_scsi_dev { | |||
| 852 | u8 scsi3addr[8]; | 852 | u8 scsi3addr[8]; |
| 853 | __be64 wwid; | 853 | __be64 wwid; |
| 854 | u8 volume_id[16]; | 854 | u8 volume_id[16]; |
| 855 | u8 unique_id[16]; | ||
| 855 | u8 is_physical_device : 1; | 856 | u8 is_physical_device : 1; |
| 856 | u8 is_external_raid_device : 1; | 857 | u8 is_external_raid_device : 1; |
| 857 | u8 target_lun_valid : 1; | 858 | u8 target_lun_valid : 1; |
| @@ -898,6 +899,8 @@ struct pqi_scsi_dev { | |||
| 898 | #define CISS_VPD_LV_DEVICE_GEOMETRY 0xc1 /* vendor-specific page */ | 899 | #define CISS_VPD_LV_DEVICE_GEOMETRY 0xc1 /* vendor-specific page */ |
| 899 | #define CISS_VPD_LV_BYPASS_STATUS 0xc2 /* vendor-specific page */ | 900 | #define CISS_VPD_LV_BYPASS_STATUS 0xc2 /* vendor-specific page */ |
| 900 | #define CISS_VPD_LV_STATUS 0xc3 /* vendor-specific page */ | 901 | #define CISS_VPD_LV_STATUS 0xc3 /* vendor-specific page */ |
| 902 | #define SCSI_VPD_HEADER_SZ 4 | ||
| 903 | #define SCSI_VPD_DEVICE_ID_IDX 8 /* Index of page id in page */ | ||
| 901 | 904 | ||
| 902 | #define VPD_PAGE (1 << 8) | 905 | #define VPD_PAGE (1 << 8) |
| 903 | 906 | ||
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 2a90d515b972..f6c83cb155b0 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c | |||
| @@ -573,6 +573,79 @@ static inline int pqi_scsi_inquiry(struct pqi_ctrl_info *ctrl_info, | |||
| 573 | buffer, buffer_length, vpd_page, NULL, NO_TIMEOUT); | 573 | buffer, buffer_length, vpd_page, NULL, NO_TIMEOUT); |
| 574 | } | 574 | } |
| 575 | 575 | ||
| 576 | static bool pqi_vpd_page_supported(struct pqi_ctrl_info *ctrl_info, | ||
| 577 | u8 *scsi3addr, u16 vpd_page) | ||
| 578 | { | ||
| 579 | int rc; | ||
| 580 | int i; | ||
| 581 | int pages; | ||
| 582 | unsigned char *buf, bufsize; | ||
| 583 | |||
| 584 | buf = kzalloc(256, GFP_KERNEL); | ||
| 585 | if (!buf) | ||
| 586 | return false; | ||
| 587 | |||
| 588 | /* Get the size of the page list first */ | ||
| 589 | rc = pqi_scsi_inquiry(ctrl_info, scsi3addr, | ||
| 590 | VPD_PAGE | SCSI_VPD_SUPPORTED_PAGES, | ||
| 591 | buf, SCSI_VPD_HEADER_SZ); | ||
| 592 | if (rc != 0) | ||
| 593 | goto exit_unsupported; | ||
| 594 | |||
| 595 | pages = buf[3]; | ||
| 596 | if ((pages + SCSI_VPD_HEADER_SZ) <= 255) | ||
| 597 | bufsize = pages + SCSI_VPD_HEADER_SZ; | ||
| 598 | else | ||
| 599 | bufsize = 255; | ||
| 600 | |||
| 601 | /* Get the whole VPD page list */ | ||
| 602 | rc = pqi_scsi_inquiry(ctrl_info, scsi3addr, | ||
| 603 | VPD_PAGE | SCSI_VPD_SUPPORTED_PAGES, | ||
| 604 | buf, bufsize); | ||
| 605 | if (rc != 0) | ||
| 606 | goto exit_unsupported; | ||
| 607 | |||
| 608 | pages = buf[3]; | ||
| 609 | for (i = 1; i <= pages; i++) | ||
| 610 | if (buf[3 + i] == vpd_page) | ||
| 611 | goto exit_supported; | ||
| 612 | |||
| 613 | exit_unsupported: | ||
| 614 | kfree(buf); | ||
| 615 | return false; | ||
| 616 | |||
| 617 | exit_supported: | ||
| 618 | kfree(buf); | ||
| 619 | return true; | ||
| 620 | } | ||
| 621 | |||
| 622 | static int pqi_get_device_id(struct pqi_ctrl_info *ctrl_info, | ||
| 623 | u8 *scsi3addr, u8 *device_id, int buflen) | ||
| 624 | { | ||
| 625 | int rc; | ||
| 626 | unsigned char *buf; | ||
| 627 | |||
| 628 | if (!pqi_vpd_page_supported(ctrl_info, scsi3addr, SCSI_VPD_DEVICE_ID)) | ||
| 629 | return 1; /* function not supported */ | ||
| 630 | |||
| 631 | buf = kzalloc(64, GFP_KERNEL); | ||
| 632 | if (!buf) | ||
| 633 | return -ENOMEM; | ||
| 634 | |||
| 635 | rc = pqi_scsi_inquiry(ctrl_info, scsi3addr, | ||
| 636 | VPD_PAGE | SCSI_VPD_DEVICE_ID, | ||
| 637 | buf, 64); | ||
| 638 | if (rc == 0) { | ||
| 639 | if (buflen > 16) | ||
| 640 | buflen = 16; | ||
| 641 | memcpy(device_id, &buf[SCSI_VPD_DEVICE_ID_IDX], buflen); | ||
| 642 | } | ||
| 643 | |||
| 644 | kfree(buf); | ||
| 645 | |||
| 646 | return rc; | ||
| 647 | } | ||
| 648 | |||
| 576 | static int pqi_identify_physical_device(struct pqi_ctrl_info *ctrl_info, | 649 | static int pqi_identify_physical_device(struct pqi_ctrl_info *ctrl_info, |
| 577 | struct pqi_scsi_dev *device, | 650 | struct pqi_scsi_dev *device, |
| 578 | struct bmic_identify_physical_device *buffer, | 651 | struct bmic_identify_physical_device *buffer, |
| @@ -1244,6 +1317,14 @@ static int pqi_get_device_info(struct pqi_ctrl_info *ctrl_info, | |||
| 1244 | } | 1317 | } |
| 1245 | } | 1318 | } |
| 1246 | 1319 | ||
| 1320 | if (pqi_get_device_id(ctrl_info, device->scsi3addr, | ||
| 1321 | device->unique_id, sizeof(device->unique_id)) < 0) | ||
| 1322 | dev_warn(&ctrl_info->pci_dev->dev, | ||
| 1323 | "Can't get device id for scsi %d:%d:%d:%d\n", | ||
| 1324 | ctrl_info->scsi_host->host_no, | ||
| 1325 | device->bus, device->target, | ||
| 1326 | device->lun); | ||
| 1327 | |||
| 1247 | out: | 1328 | out: |
| 1248 | kfree(buffer); | 1329 | kfree(buffer); |
| 1249 | 1330 | ||
| @@ -1775,6 +1856,12 @@ static inline bool pqi_skip_device(u8 *scsi3addr) | |||
| 1775 | return false; | 1856 | return false; |
| 1776 | } | 1857 | } |
| 1777 | 1858 | ||
| 1859 | static inline bool pqi_expose_device(struct pqi_scsi_dev *device) | ||
| 1860 | { | ||
| 1861 | return !device->is_physical_device || | ||
| 1862 | !pqi_skip_device(device->scsi3addr); | ||
| 1863 | } | ||
| 1864 | |||
| 1778 | static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) | 1865 | static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info) |
| 1779 | { | 1866 | { |
| 1780 | int i; | 1867 | int i; |
| @@ -5722,6 +5809,145 @@ static struct device_attribute *pqi_shost_attrs[] = { | |||
| 5722 | NULL | 5809 | NULL |
| 5723 | }; | 5810 | }; |
| 5724 | 5811 | ||
| 5812 | static ssize_t pqi_unique_id_show(struct device *dev, | ||
| 5813 | struct device_attribute *attr, char *buffer) | ||
| 5814 | { | ||
| 5815 | struct pqi_ctrl_info *ctrl_info; | ||
| 5816 | struct scsi_device *sdev; | ||
| 5817 | struct pqi_scsi_dev *device; | ||
| 5818 | unsigned long flags; | ||
| 5819 | unsigned char uid[16]; | ||
| 5820 | |||
| 5821 | sdev = to_scsi_device(dev); | ||
| 5822 | ctrl_info = shost_to_hba(sdev->host); | ||
| 5823 | |||
| 5824 | spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); | ||
| 5825 | |||
| 5826 | device = sdev->hostdata; | ||
| 5827 | if (!device) { | ||
| 5828 | spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, | ||
| 5829 | flags); | ||
| 5830 | return -ENODEV; | ||
| 5831 | } | ||
| 5832 | memcpy(uid, device->unique_id, sizeof(uid)); | ||
| 5833 | |||
| 5834 | spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); | ||
| 5835 | |||
| 5836 | return snprintf(buffer, PAGE_SIZE, "%16phN", uid); | ||
| 5837 | } | ||
| 5838 | |||
| 5839 | static ssize_t pqi_lunid_show(struct device *dev, | ||
| 5840 | struct device_attribute *attr, char *buffer) | ||
| 5841 | { | ||
| 5842 | struct pqi_ctrl_info *ctrl_info; | ||
| 5843 | struct scsi_device *sdev; | ||
| 5844 | struct pqi_scsi_dev *device; | ||
| 5845 | unsigned long flags; | ||
| 5846 | u8 lunid[8]; | ||
| 5847 | |||
| 5848 | sdev = to_scsi_device(dev); | ||
| 5849 | ctrl_info = shost_to_hba(sdev->host); | ||
| 5850 | |||
| 5851 | spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); | ||
| 5852 | |||
| 5853 | device = sdev->hostdata; | ||
| 5854 | if (!device) { | ||
| 5855 | spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, | ||
| 5856 | flags); | ||
| 5857 | return -ENODEV; | ||
| 5858 | } | ||
| 5859 | memcpy(lunid, device->scsi3addr, sizeof(lunid)); | ||
| 5860 | |||
| 5861 | spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); | ||
| 5862 | |||
| 5863 | return snprintf(buffer, PAGE_SIZE, "0x%8phN\n", lunid); | ||
| 5864 | } | ||
| 5865 | |||
| 5866 | #define MAX_PATHS 8 | ||
| 5867 | static ssize_t pqi_path_info_show(struct device *dev, | ||
| 5868 | struct device_attribute *attr, char *buf) | ||
| 5869 | { | ||
| 5870 | struct pqi_ctrl_info *ctrl_info; | ||
| 5871 | struct scsi_device *sdev; | ||
| 5872 | struct pqi_scsi_dev *device; | ||
| 5873 | unsigned long flags; | ||
| 5874 | int i; | ||
| 5875 | int output_len = 0; | ||
| 5876 | u8 box; | ||
| 5877 | u8 bay; | ||
| 5878 | u8 path_map_index = 0; | ||
| 5879 | char *active; | ||
| 5880 | unsigned char phys_connector[2]; | ||
| 5881 | |||
| 5882 | sdev = to_scsi_device(dev); | ||
| 5883 | ctrl_info = shost_to_hba(sdev->host); | ||
| 5884 | |||
| 5885 | spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); | ||
| 5886 | |||
| 5887 | device = sdev->hostdata; | ||
| 5888 | if (!device) { | ||
| 5889 | spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, | ||
| 5890 | flags); | ||
| 5891 | return -ENODEV; | ||
| 5892 | } | ||
| 5893 | |||
| 5894 | bay = device->bay; | ||
| 5895 | for (i = 0; i < MAX_PATHS; i++) { | ||
| 5896 | path_map_index = 1<<i; | ||
| 5897 | if (i == device->active_path_index) | ||
| 5898 | active = "Active"; | ||
| 5899 | else if (device->path_map & path_map_index) | ||
| 5900 | active = "Inactive"; | ||
| 5901 | else | ||
| 5902 | continue; | ||
| 5903 | |||
| 5904 | output_len += scnprintf(buf + output_len, | ||
| 5905 | PAGE_SIZE - output_len, | ||
| 5906 | "[%d:%d:%d:%d] %20.20s ", | ||
| 5907 | ctrl_info->scsi_host->host_no, | ||
| 5908 | device->bus, device->target, | ||
| 5909 | device->lun, | ||
| 5910 | scsi_device_type(device->devtype)); | ||
| 5911 | |||
| 5912 | if (device->devtype == TYPE_RAID || | ||
| 5913 | pqi_is_logical_device(device)) | ||
| 5914 | goto end_buffer; | ||
| 5915 | |||
| 5916 | memcpy(&phys_connector, &device->phys_connector[i], | ||
| 5917 | sizeof(phys_connector)); | ||
| 5918 | if (phys_connector[0] < '0') | ||
| 5919 | phys_connector[0] = '0'; | ||
| 5920 | if (phys_connector[1] < '0') | ||
| 5921 | phys_connector[1] = '0'; | ||
| 5922 | |||
| 5923 | output_len += scnprintf(buf + output_len, | ||
| 5924 | PAGE_SIZE - output_len, | ||
| 5925 | "PORT: %.2s ", phys_connector); | ||
| 5926 | |||
| 5927 | box = device->box[i]; | ||
| 5928 | if (box != 0 && box != 0xFF) | ||
| 5929 | output_len += scnprintf(buf + output_len, | ||
| 5930 | PAGE_SIZE - output_len, | ||
| 5931 | "BOX: %hhu ", box); | ||
| 5932 | |||
| 5933 | if ((device->devtype == TYPE_DISK || | ||
| 5934 | device->devtype == TYPE_ZBC) && | ||
| 5935 | pqi_expose_device(device)) | ||
| 5936 | output_len += scnprintf(buf + output_len, | ||
| 5937 | PAGE_SIZE - output_len, | ||
| 5938 | "BAY: %hhu ", bay); | ||
| 5939 | |||
| 5940 | end_buffer: | ||
| 5941 | output_len += scnprintf(buf + output_len, | ||
| 5942 | PAGE_SIZE - output_len, | ||
| 5943 | "%s\n", active); | ||
| 5944 | } | ||
| 5945 | |||
| 5946 | spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags); | ||
| 5947 | return output_len; | ||
| 5948 | } | ||
| 5949 | |||
| 5950 | |||
| 5725 | static ssize_t pqi_sas_address_show(struct device *dev, | 5951 | static ssize_t pqi_sas_address_show(struct device *dev, |
| 5726 | struct device_attribute *attr, char *buffer) | 5952 | struct device_attribute *attr, char *buffer) |
| 5727 | { | 5953 | { |
| @@ -5798,12 +6024,18 @@ static ssize_t pqi_raid_level_show(struct device *dev, | |||
| 5798 | return snprintf(buffer, PAGE_SIZE, "%s\n", raid_level); | 6024 | return snprintf(buffer, PAGE_SIZE, "%s\n", raid_level); |
| 5799 | } | 6025 | } |
| 5800 | 6026 | ||
| 6027 | static DEVICE_ATTR(lunid, 0444, pqi_lunid_show, NULL); | ||
| 6028 | static DEVICE_ATTR(unique_id, 0444, pqi_unique_id_show, NULL); | ||
| 6029 | static DEVICE_ATTR(path_info, 0444, pqi_path_info_show, NULL); | ||
| 5801 | static DEVICE_ATTR(sas_address, 0444, pqi_sas_address_show, NULL); | 6030 | static DEVICE_ATTR(sas_address, 0444, pqi_sas_address_show, NULL); |
| 5802 | static DEVICE_ATTR(ssd_smart_path_enabled, 0444, | 6031 | static DEVICE_ATTR(ssd_smart_path_enabled, 0444, |
| 5803 | pqi_ssd_smart_path_enabled_show, NULL); | 6032 | pqi_ssd_smart_path_enabled_show, NULL); |
| 5804 | static DEVICE_ATTR(raid_level, 0444, pqi_raid_level_show, NULL); | 6033 | static DEVICE_ATTR(raid_level, 0444, pqi_raid_level_show, NULL); |
| 5805 | 6034 | ||
| 5806 | static struct device_attribute *pqi_sdev_attrs[] = { | 6035 | static struct device_attribute *pqi_sdev_attrs[] = { |
| 6036 | &dev_attr_lunid, | ||
| 6037 | &dev_attr_unique_id, | ||
| 6038 | &dev_attr_path_info, | ||
| 5807 | &dev_attr_sas_address, | 6039 | &dev_attr_sas_address, |
| 5808 | &dev_attr_ssd_smart_path_enabled, | 6040 | &dev_attr_ssd_smart_path_enabled, |
| 5809 | &dev_attr_raid_level, | 6041 | &dev_attr_raid_level, |
