thunderbolt: Read vendor and device name from DROM
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.westerberg@linux.intel.com> Reviewed-by: Yehezkel Bernat <yehezkel.bernat@intel.com> Reviewed-by: Michael Jamet <michael.jamet@intel.com> Signed-off-by: Andreas Noever <andreas.noever@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
02b17a41ad
Коммит
72ee33907b
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче