The device DROM contains name of the vendor and device among other
things. Extract this information and expose it to the userspace via two
new attributes.

Signed-off-by: Mika Westerberg <mika.westerb...@linux.intel.com>
Reviewed-by: Yehezkel Bernat <yehezkel.ber...@intel.com>
Reviewed-by: Michael Jamet <michael.ja...@intel.com>
---
 Documentation/ABI/testing/sysfs-bus-thunderbolt | 14 +++++++++++
 drivers/thunderbolt/eeprom.c                    | 32 +++++++++++++++++++++++++
 drivers/thunderbolt/switch.c                    | 22 +++++++++++++++++
 drivers/thunderbolt/tb.h                        |  4 ++++
 4 files changed, 72 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-bus-thunderbolt 
b/Documentation/ABI/testing/sysfs-bus-thunderbolt
index 9f1bd0086938..29a516f53d2c 100644
--- a/Documentation/ABI/testing/sysfs-bus-thunderbolt
+++ b/Documentation/ABI/testing/sysfs-bus-thunderbolt
@@ -5,6 +5,13 @@ Contact:       thunderbolt-softw...@lists.01.org
 Description:   This attribute contains id of this device extracted from
                the device DROM.
 
+What:          /sys/bus/thunderbolt/devices/.../device_name
+Date:          Sep 2017
+KernelVersion: 4.13
+Contact:       thunderbolt-softw...@lists.01.org
+Description:   This attribute contains name of this device extracted from
+               the device DROM.
+
 What:          /sys/bus/thunderbolt/devices/.../vendor
 Date:          Sep 2017
 KernelVersion: 4.13
@@ -12,6 +19,13 @@ Contact:     thunderbolt-softw...@lists.01.org
 Description:   This attribute contains vendor id of this device extracted
                from the device DROM.
 
+What:          /sys/bus/thunderbolt/devices/.../vendor_name
+Date:          Sep 2017
+KernelVersion: 4.13
+Contact:       thunderbolt-softw...@lists.01.org
+Description:   This attribute contains vendor name of this device extracted
+               from the device DROM.
+
 What:          /sys/bus/thunderbolt/devices/.../unique_id
 Date:          Sep 2017
 KernelVersion: 4.13
diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
index 5c7d80a109b1..d40a5f07fc4c 100644
--- a/drivers/thunderbolt/eeprom.c
+++ b/drivers/thunderbolt/eeprom.c
@@ -204,6 +204,11 @@ struct tb_drom_entry_header {
        enum tb_drom_entry_type type:1;
 } __packed;
 
+struct tb_drom_entry_generic {
+       struct tb_drom_entry_header header;
+       u8 data[0];
+} __packed;
+
 struct tb_drom_entry_port {
        /* BYTES 0-1 */
        struct tb_drom_entry_header header;
@@ -295,6 +300,32 @@ int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid)
        return 0;
 }
 
+static int tb_drom_parse_entry_generic(struct tb_switch *sw,
+               struct tb_drom_entry_header *header)
+{
+       const struct tb_drom_entry_generic *entry =
+               (const struct tb_drom_entry_generic *)header;
+
+       switch (header->index) {
+       case 1:
+               /* Length includes 2 bytes header so remove it before copy */
+               sw->vendor_name = kstrndup(entry->data,
+                       header->len - sizeof(*header), GFP_KERNEL);
+               if (!sw->vendor_name)
+                       return -ENOMEM;
+               break;
+
+       case 2:
+               sw->device_name = kstrndup(entry->data,
+                       header->len - sizeof(*header), GFP_KERNEL);
+               if (!sw->device_name)
+                       return -ENOMEM;
+               break;
+       }
+
+       return 0;
+}
+
 static int tb_drom_parse_entry_port(struct tb_switch *sw,
                                    struct tb_drom_entry_header *header)
 {
@@ -350,6 +381,7 @@ static int tb_drom_parse_entries(struct tb_switch *sw)
 
                switch (entry->type) {
                case TB_DROM_ENTRY_GENERIC:
+                       res = tb_drom_parse_entry_generic(sw, entry);
                        break;
                case TB_DROM_ENTRY_PORT:
                        res = tb_drom_parse_entry_port(sw, entry);
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 0ce8b600a23f..0a592ccb7923 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -319,6 +319,15 @@ static ssize_t device_show(struct device *dev, struct 
device_attribute *attr,
 }
 static DEVICE_ATTR_RO(device);
 
+static ssize_t
+device_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct tb_switch *sw = tb_to_switch(dev);
+
+       return sprintf(buf, "%s\n", sw->device_name ? sw->device_name : "");
+}
+static DEVICE_ATTR_RO(device_name);
+
 static ssize_t vendor_show(struct device *dev, struct device_attribute *attr,
                           char *buf)
 {
@@ -328,6 +337,15 @@ static ssize_t vendor_show(struct device *dev, struct 
device_attribute *attr,
 }
 static DEVICE_ATTR_RO(vendor);
 
+static ssize_t
+vendor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct tb_switch *sw = tb_to_switch(dev);
+
+       return sprintf(buf, "%s\n", sw->vendor_name ? sw->vendor_name : "");
+}
+static DEVICE_ATTR_RO(vendor_name);
+
 static ssize_t unique_id_show(struct device *dev, struct device_attribute 
*attr,
                              char *buf)
 {
@@ -339,7 +357,9 @@ static DEVICE_ATTR_RO(unique_id);
 
 static struct attribute *switch_attrs[] = {
        &dev_attr_device.attr,
+       &dev_attr_device_name.attr,
        &dev_attr_vendor.attr,
+       &dev_attr_vendor_name.attr,
        &dev_attr_unique_id.attr,
        NULL,
 };
@@ -358,6 +378,8 @@ static void tb_switch_release(struct device *dev)
        struct tb_switch *sw = tb_to_switch(dev);
 
        kfree(sw->uuid);
+       kfree(sw->device_name);
+       kfree(sw->vendor_name);
        kfree(sw->ports);
        kfree(sw->drom);
        kfree(sw);
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index 350c3f21924e..5e66dce53c65 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -23,6 +23,8 @@
  * @uuid: UUID of the switch (or %NULL if not supported)
  * @vendor: Vendor ID of the switch
  * @device: Device ID of the switch
+ * @vendor_name: Name of the vendor (or %NULL if not known)
+ * @device_name: Name of the device (or %NULL if not known)
  * @cap_plug_events: Offset to the plug events capability (%0 if not found)
  * @is_unplugged: The switch is going away
  * @drom: DROM of the switch (%NULL if not found)
@@ -36,6 +38,8 @@ struct tb_switch {
        uuid_be *uuid;
        u16 vendor;
        u16 device;
+       const char *vendor_name;
+       const char *device_name;
        int cap_plug_events;
        bool is_unplugged;
        u8 *drom;
-- 
2.11.0

Reply via email to