From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S943972AbdEZQL3 (ORCPT ); Fri, 26 May 2017 12:11:29 -0400 Received: from mga14.intel.com ([192.55.52.115]:52433 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1948406AbdEZQL0 (ORCPT ); Fri, 26 May 2017 12:11:26 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.38,398,1491289200"; d="scan'208";a="973436492" From: Mika Westerberg To: Greg Kroah-Hartman Cc: Andreas Noever , Michael Jamet , Yehezkel Bernat , Lukas Wunner , Amir Levy , Andy Lutomirski , Mario.Limonciello@dell.com, Jared.Dominguez@dell.com, Andy Shevchenko , Mika Westerberg , linux-kernel@vger.kernel.org Subject: [PATCH v2 13/27] thunderbolt: Read vendor and device name from DROM Date: Fri, 26 May 2017 19:09:22 +0300 Message-Id: <20170526160936.54265-14-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170526160936.54265-1-mika.westerberg@linux.intel.com> References: <20170526160936.54265-1-mika.westerberg@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 Reviewed-by: Yehezkel Bernat Reviewed-by: Michael Jamet --- Documentation/ABI/testing/sysfs-bus-thunderbolt | 14 +++++++++ drivers/thunderbolt/eeprom.c | 42 +++++++++++++++++++++++++ drivers/thunderbolt/switch.c | 22 +++++++++++++ drivers/thunderbolt/tb.h | 4 +++ 4 files changed, 82 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-thunderbolt b/Documentation/ABI/testing/sysfs-bus-thunderbolt index a3dac3becd1e..2f352c787431 100644 --- a/Documentation/ABI/testing/sysfs-bus-thunderbolt +++ b/Documentation/ABI/testing/sysfs-bus-thunderbolt @@ -5,6 +5,13 @@ Contact: thunderbolt-software@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-software@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-software@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-software@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..8070f5966aac 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,42 @@ int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid) return 0; } +static const char *parse_name(const u8 *data, u8 len) +{ + char *name; + + name = kmemdup(data, len, GFP_KERNEL); + if (name) + name[len - 1] = '\0'; + return name; +} + +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 = parse_name(entry->data, + header->len - sizeof(*header)); + if (!sw->vendor_name) + return -ENOMEM; + break; + + case 2: + sw->device_name = parse_name(entry->data, + header->len - sizeof(*header)); + 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 +391,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 86ebce28e257..da63a75eebf4 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