| From: |
| Patrick Mansfield <patmans@us.ibm.com> |
| To: |
| linux-scsi@vger.kernel.org |
| Subject: |
| [PATCH] add more scsi_device sysfs attributes |
| Date: |
| Tue, 3 Dec 2002 15:57:43 -0800 |
Hi -
This patch adds some scsi_device sysfs specific macros (based on some
in the usb source), and adds more scsi_device sysfs attributes.
It modifies the current output of the "type" attribute to be
the numeric value of the type, and adds a few other attributes.
It is easy to add or remove scsi_device attributes with this patch.
Example sysfs with this patch:
[patman@elm3a50 patman]$ ls /sysfs/bus/scsi/devices/0:0:0:0
0:0:0:0:gen current_queue_depth name power vendor
access_count device_blocked new_queue_depth rev
block model online type
And results of catting each file above (block and 0:0:0:0:gen are
not files):
/sysfs/bus/scsi/devices/0:0:0:0/access_count: '2'
/sysfs/bus/scsi/devices/0:0:0:0/current_queue_depth: '253'
/sysfs/bus/scsi/devices/0:0:0:0/device_blocked: '0'
/sysfs/bus/scsi/devices/0:0:0:0/model: 'ST318203LC !#'
/sysfs/bus/scsi/devices/0:0:0:0/name: 'SIBM-PSG ST318203LC !#LRA6701300007027J5ZL'
/sysfs/bus/scsi/devices/0:0:0:0/new_queue_depth: '253'
/sysfs/bus/scsi/devices/0:0:0:0/online: '1'
/sysfs/bus/scsi/devices/0:0:0:0/power: '0'
/sysfs/bus/scsi/devices/0:0:0:0/rev: 'B222'
/sysfs/bus/scsi/devices/0:0:0:0/type: '0'
/sysfs/bus/scsi/devices/0:0:0:0/vendor: 'IBM-PSG '
The online bit field is writable, although setting it to 0 is not useful.
--- 1.1/drivers/scsi/scsi_sysfs.c Thu Nov 28 10:54:06 2002
+++ edited/drivers/scsi/scsi_sysfs.c Tue Dec 3 08:53:21 2002
@@ -132,39 +132,115 @@
}
-/**
- * scsi_device_type_read - copy out the SCSI type
- * @dev: device to check
- * @page: copy data into this area
- * @count: number of bytes to copy
- * @off: start at this offset in page
- *
- * Return:
- * number of bytes written into page.
- **/
-static ssize_t scsi_device_type_read(struct device *dev, char *page,
- size_t count, loff_t off)
-{
- struct scsi_device *sdev = to_scsi_device(dev);
- const char *type;
+/*
+ * show_function: macro to create an attr function that can be used to
+ * show a non-bit field.
+ */
+#define show_function(field, format_string) \
+static ssize_t \
+show_##field (struct device *dev, char *buf, size_t count, loff_t off) \
+{ \
+ struct scsi_device *sdev; \
+ if (off) \
+ return 0; \
+ sdev = to_scsi_device(dev); \
+ return snprintf (buf, count, format_string, sdev->field); \
+} \
- if (off)
- return 0;
+/*
+ * sdev_rd_attr: macro to create a function and attribute variable for a
+ * read only field.
+ */
+#define sdev_rd_attr(field, format_string) \
+ show_function(field, format_string) \
+static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL)
- if ((sdev->type > MAX_SCSI_DEVICE_CODE) ||
- (scsi_device_types[(int)sdev->type] == NULL))
- type = "Unknown";
- else
- type = scsi_device_types[(int)sdev->type];
- return snprintf(page, count, "%s\n", type);
+/*
+ * sdev_rd_attr: create a function and attribute variable for a
+ * read/write field.
+ */
+#define sdev_rw_attr(field, format_string) \
+ show_function(field, format_string) \
+ \
+static ssize_t \
+store_##field (struct device *dev, const char *buf, size_t count, loff_t off)\
+{ \
+ struct scsi_device *sdev; \
+ \
+ if (off) \
+ return 0; \
+ sdev = to_scsi_device(dev); \
+ return snscanf (buf, count, format_string, &sdev->field); \
+} \
+static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, show_##field, store_##field)
+
+/*
+ * sdev_rd_attr: create a function and attribute variable for a
+ * read/write bit field.
+ */
+#define sdev_rw_attr_bit(field) \
+ show_function(field, "%d\n") \
+ \
+static ssize_t \
+store_##field (struct device *dev, const char *buf, size_t count, loff_t off)\
+{ \
+ int ret; \
+ struct scsi_device *sdev; \
+ \
+ if (off) \
+ return 0; \
+ ret = scsi_sdev_check_buf_bit(buf); \
+ if (ret >= 0) { \
+ sdev = to_scsi_device(dev); \
+ sdev->field = ret; \
+ ret = count; \
+ } \
+ return ret; \
+} \
+static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, show_##field, store_##field)
+
+/*
+ * scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1",
+ * else return -EINVAL.
+ */
+static int scsi_sdev_check_buf_bit(const char *buf)
+{
+ if ((buf[1] == '\0') || ((buf[1] == '\n') && (buf[2] == '\0'))) {
+ if (buf[0] == '1')
+ return 1;
+ else if (buf[0] == '0')
+ return 0;
+ else
+ return -EINVAL;
+ } else
+ return -EINVAL;
}
/*
- * Create dev_attr_type. This is different from the dev_attr_type in scsi
- * upper level drivers.
+ * Create the actual show/store functions and data structures.
*/
-static DEVICE_ATTR(type,S_IRUGO,scsi_device_type_read,NULL);
+sdev_rd_attr (device_blocked, "%d\n");
+sdev_rd_attr (current_queue_depth, "%d\n");
+sdev_rd_attr (new_queue_depth, "%d\n");
+sdev_rd_attr (type, "%d\n");
+sdev_rd_attr (access_count, "%d\n");
+sdev_rd_attr (vendor, "%.8s\n");
+sdev_rd_attr (model, "%.16s\n");
+sdev_rd_attr (rev, "%.4s\n");
+sdev_rw_attr_bit (online);
+
+static struct device_attribute * const sdev_attrs[] = {
+ &dev_attr_device_blocked,
+ &dev_attr_current_queue_depth,
+ &dev_attr_new_queue_depth,
+ &dev_attr_type,
+ &dev_attr_access_count,
+ &dev_attr_vendor,
+ &dev_attr_model,
+ &dev_attr_rev,
+ &dev_attr_online,
+};
/**
* scsi_device_register - register a scsi device with the scsi bus
@@ -175,7 +251,7 @@
**/
int scsi_device_register(struct scsi_device *sdev)
{
- int error = 0;
+ int error = 0, i;
sprintf(sdev->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d",
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
@@ -186,9 +262,12 @@
if (error)
return error;
- error = device_create_file(&sdev->sdev_driverfs_dev, &dev_attr_type);
+ for (i = 0; !error && i < ARRAY_SIZE(sdev_attrs); i++)
+ error = device_create_file(&sdev->sdev_driverfs_dev,
+ sdev_attrs[i]);
+
if (error)
- device_unregister(&sdev->sdev_driverfs_dev);
+ scsi_device_unregister(sdev);
return error;
}
@@ -199,6 +278,9 @@
**/
void scsi_device_unregister(struct scsi_device *sdev)
{
- device_remove_file(&sdev->sdev_driverfs_dev, &dev_attr_type);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sdev_attrs); i++)
+ device_remove_file(&sdev->sdev_driverfs_dev, sdev_attrs[i]);
device_unregister(&sdev->sdev_driverfs_dev);
}
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html