Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd128244 authored by Dave Carroll's avatar Dave Carroll Committed by Martin K. Petersen
Browse files

scsi: smartpqi: add sysfs attributes



- add sysfs device attributes, unique_id, lunid and path_info.

Reviewed-by: default avatarScott Teel <scott.teel@microsemi.com>
Reviewed-by: default avatarKevin Barnett <kevin.barnett@microsemi.com>
Signed-off-by: default avatarDave Carroll <david.carroll@microsemi.com>
Signed-off-by: default avatarDon Brace <don.brace@microsemi.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 02133b68
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -852,6 +852,7 @@ struct pqi_scsi_dev {
	u8	scsi3addr[8];
	u8	scsi3addr[8];
	__be64	wwid;
	__be64	wwid;
	u8	volume_id[16];
	u8	volume_id[16];
	u8	unique_id[16];
	u8	is_physical_device : 1;
	u8	is_physical_device : 1;
	u8	is_external_raid_device : 1;
	u8	is_external_raid_device : 1;
	u8	target_lun_valid : 1;
	u8	target_lun_valid : 1;
@@ -898,6 +899,8 @@ struct pqi_scsi_dev {
#define CISS_VPD_LV_DEVICE_GEOMETRY	0xc1	/* vendor-specific page */
#define CISS_VPD_LV_DEVICE_GEOMETRY	0xc1	/* vendor-specific page */
#define CISS_VPD_LV_BYPASS_STATUS	0xc2	/* vendor-specific page */
#define CISS_VPD_LV_BYPASS_STATUS	0xc2	/* vendor-specific page */
#define CISS_VPD_LV_STATUS		0xc3	/* vendor-specific page */
#define CISS_VPD_LV_STATUS		0xc3	/* vendor-specific page */
#define SCSI_VPD_HEADER_SZ		4
#define SCSI_VPD_DEVICE_ID_IDX		8	/* Index of page id in page */


#define VPD_PAGE	(1 << 8)
#define VPD_PAGE	(1 << 8)


+232 −0
Original line number Original line Diff line number Diff line
@@ -573,6 +573,79 @@ static inline int pqi_scsi_inquiry(struct pqi_ctrl_info *ctrl_info,
		buffer, buffer_length, vpd_page, NULL, NO_TIMEOUT);
		buffer, buffer_length, vpd_page, NULL, NO_TIMEOUT);
}
}


static bool pqi_vpd_page_supported(struct pqi_ctrl_info *ctrl_info,
	u8 *scsi3addr, u16 vpd_page)
{
	int rc;
	int i;
	int pages;
	unsigned char *buf, bufsize;

	buf = kzalloc(256, GFP_KERNEL);
	if (!buf)
		return false;

	/* Get the size of the page list first */
	rc = pqi_scsi_inquiry(ctrl_info, scsi3addr,
				VPD_PAGE | SCSI_VPD_SUPPORTED_PAGES,
				buf, SCSI_VPD_HEADER_SZ);
	if (rc != 0)
		goto exit_unsupported;

	pages = buf[3];
	if ((pages + SCSI_VPD_HEADER_SZ) <= 255)
		bufsize = pages + SCSI_VPD_HEADER_SZ;
	else
		bufsize = 255;

	/* Get the whole VPD page list */
	rc = pqi_scsi_inquiry(ctrl_info, scsi3addr,
				VPD_PAGE | SCSI_VPD_SUPPORTED_PAGES,
				buf, bufsize);
	if (rc != 0)
		goto exit_unsupported;

	pages = buf[3];
	for (i = 1; i <= pages; i++)
		if (buf[3 + i] == vpd_page)
			goto exit_supported;

exit_unsupported:
	kfree(buf);
	return false;

exit_supported:
	kfree(buf);
	return true;
}

static int pqi_get_device_id(struct pqi_ctrl_info *ctrl_info,
	u8 *scsi3addr, u8 *device_id, int buflen)
{
	int rc;
	unsigned char *buf;

	if (!pqi_vpd_page_supported(ctrl_info, scsi3addr, SCSI_VPD_DEVICE_ID))
		return 1; /* function not supported */

	buf = kzalloc(64, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	rc = pqi_scsi_inquiry(ctrl_info, scsi3addr,
				VPD_PAGE | SCSI_VPD_DEVICE_ID,
				buf, 64);
	if (rc == 0) {
		if (buflen > 16)
			buflen = 16;
		memcpy(device_id, &buf[SCSI_VPD_DEVICE_ID_IDX], buflen);
	}

	kfree(buf);

	return rc;
}

static int pqi_identify_physical_device(struct pqi_ctrl_info *ctrl_info,
static int pqi_identify_physical_device(struct pqi_ctrl_info *ctrl_info,
	struct pqi_scsi_dev *device,
	struct pqi_scsi_dev *device,
	struct bmic_identify_physical_device *buffer,
	struct bmic_identify_physical_device *buffer,
@@ -1244,6 +1317,14 @@ static int pqi_get_device_info(struct pqi_ctrl_info *ctrl_info,
		}
		}
	}
	}


	if (pqi_get_device_id(ctrl_info, device->scsi3addr,
		device->unique_id, sizeof(device->unique_id)) < 0)
		dev_warn(&ctrl_info->pci_dev->dev,
			"Can't get device id for scsi %d:%d:%d:%d\n",
			ctrl_info->scsi_host->host_no,
			device->bus, device->target,
			device->lun);

out:
out:
	kfree(buffer);
	kfree(buffer);


@@ -1775,6 +1856,12 @@ static inline bool pqi_skip_device(u8 *scsi3addr)
	return false;
	return false;
}
}


static inline bool pqi_expose_device(struct pqi_scsi_dev *device)
{
	return !device->is_physical_device ||
		!pqi_skip_device(device->scsi3addr);
}

static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info)
static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info)
{
{
	int i;
	int i;
@@ -5722,6 +5809,145 @@ static struct device_attribute *pqi_shost_attrs[] = {
	NULL
	NULL
};
};


static ssize_t pqi_unique_id_show(struct device *dev,
	struct device_attribute *attr, char *buffer)
{
	struct pqi_ctrl_info *ctrl_info;
	struct scsi_device *sdev;
	struct pqi_scsi_dev *device;
	unsigned long flags;
	unsigned char uid[16];

	sdev = to_scsi_device(dev);
	ctrl_info = shost_to_hba(sdev->host);

	spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);

	device = sdev->hostdata;
	if (!device) {
		spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock,
			flags);
		return -ENODEV;
	}
	memcpy(uid, device->unique_id, sizeof(uid));

	spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);

	return snprintf(buffer, PAGE_SIZE, "%16phN", uid);
}

static ssize_t pqi_lunid_show(struct device *dev,
	struct device_attribute *attr, char *buffer)
{
	struct pqi_ctrl_info *ctrl_info;
	struct scsi_device *sdev;
	struct pqi_scsi_dev *device;
	unsigned long flags;
	u8 lunid[8];

	sdev = to_scsi_device(dev);
	ctrl_info = shost_to_hba(sdev->host);

	spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);

	device = sdev->hostdata;
	if (!device) {
		spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock,
			flags);
		return -ENODEV;
	}
	memcpy(lunid, device->scsi3addr, sizeof(lunid));

	spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);

	return snprintf(buffer, PAGE_SIZE, "0x%8phN\n", lunid);
}

#define MAX_PATHS 8
static ssize_t pqi_path_info_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{
	struct pqi_ctrl_info *ctrl_info;
	struct scsi_device *sdev;
	struct pqi_scsi_dev *device;
	unsigned long flags;
	int i;
	int output_len = 0;
	u8 box;
	u8 bay;
	u8 path_map_index = 0;
	char *active;
	unsigned char phys_connector[2];

	sdev = to_scsi_device(dev);
	ctrl_info = shost_to_hba(sdev->host);

	spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);

	device = sdev->hostdata;
	if (!device) {
		spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock,
			flags);
		return -ENODEV;
	}

	bay = device->bay;
	for (i = 0; i < MAX_PATHS; i++) {
		path_map_index = 1<<i;
		if (i == device->active_path_index)
			active = "Active";
		else if (device->path_map & path_map_index)
			active = "Inactive";
		else
			continue;

		output_len += scnprintf(buf + output_len,
					PAGE_SIZE - output_len,
					"[%d:%d:%d:%d] %20.20s ",
					ctrl_info->scsi_host->host_no,
					device->bus, device->target,
					device->lun,
					scsi_device_type(device->devtype));

		if (device->devtype == TYPE_RAID ||
			pqi_is_logical_device(device))
			goto end_buffer;

		memcpy(&phys_connector, &device->phys_connector[i],
			sizeof(phys_connector));
		if (phys_connector[0] < '0')
			phys_connector[0] = '0';
		if (phys_connector[1] < '0')
			phys_connector[1] = '0';

		output_len += scnprintf(buf + output_len,
					PAGE_SIZE - output_len,
					"PORT: %.2s ", phys_connector);

		box = device->box[i];
		if (box != 0 && box != 0xFF)
			output_len += scnprintf(buf + output_len,
						PAGE_SIZE - output_len,
						"BOX: %hhu ", box);

		if ((device->devtype == TYPE_DISK ||
			device->devtype == TYPE_ZBC) &&
			pqi_expose_device(device))
			output_len += scnprintf(buf + output_len,
						PAGE_SIZE - output_len,
						"BAY: %hhu ", bay);

end_buffer:
		output_len += scnprintf(buf + output_len,
					PAGE_SIZE - output_len,
					"%s\n", active);
	}

	spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
	return output_len;
}


static ssize_t pqi_sas_address_show(struct device *dev,
static ssize_t pqi_sas_address_show(struct device *dev,
	struct device_attribute *attr, char *buffer)
	struct device_attribute *attr, char *buffer)
{
{
@@ -5798,12 +6024,18 @@ static ssize_t pqi_raid_level_show(struct device *dev,
	return snprintf(buffer, PAGE_SIZE, "%s\n", raid_level);
	return snprintf(buffer, PAGE_SIZE, "%s\n", raid_level);
}
}


static DEVICE_ATTR(lunid, 0444, pqi_lunid_show, NULL);
static DEVICE_ATTR(unique_id, 0444, pqi_unique_id_show, NULL);
static DEVICE_ATTR(path_info, 0444, pqi_path_info_show, NULL);
static DEVICE_ATTR(sas_address, 0444, pqi_sas_address_show, NULL);
static DEVICE_ATTR(sas_address, 0444, pqi_sas_address_show, NULL);
static DEVICE_ATTR(ssd_smart_path_enabled, 0444,
static DEVICE_ATTR(ssd_smart_path_enabled, 0444,
	pqi_ssd_smart_path_enabled_show, NULL);
	pqi_ssd_smart_path_enabled_show, NULL);
static DEVICE_ATTR(raid_level, 0444, pqi_raid_level_show, NULL);
static DEVICE_ATTR(raid_level, 0444, pqi_raid_level_show, NULL);


static struct device_attribute *pqi_sdev_attrs[] = {
static struct device_attribute *pqi_sdev_attrs[] = {
	&dev_attr_lunid,
	&dev_attr_unique_id,
	&dev_attr_path_info,
	&dev_attr_sas_address,
	&dev_attr_sas_address,
	&dev_attr_ssd_smart_path_enabled,
	&dev_attr_ssd_smart_path_enabled,
	&dev_attr_raid_level,
	&dev_attr_raid_level,