thunderbolt: Add link_speed and link_width to XDomain
Link speed and link width are needed for checking expected values in case of using a loopback service. Signed-off-by: Isaac Hazan <isaac.hazan@intel.com> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Acked-by: Yehezkel Bernat <YehezkelShB@gmail.com> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
47844ecb8c
Коммит
4210d50f0b
|
@ -1,3 +1,31 @@
|
||||||
|
What: /sys/bus/thunderbolt/devices/<xdomain>/rx_speed
|
||||||
|
Date: Feb 2021
|
||||||
|
KernelVersion: 5.11
|
||||||
|
Contact: Isaac Hazan <isaac.hazan@intel.com>
|
||||||
|
Description: This attribute reports the XDomain RX speed per lane.
|
||||||
|
All RX lanes run at the same speed.
|
||||||
|
|
||||||
|
What: /sys/bus/thunderbolt/devices/<xdomain>/rx_lanes
|
||||||
|
Date: Feb 2021
|
||||||
|
KernelVersion: 5.11
|
||||||
|
Contact: Isaac Hazan <isaac.hazan@intel.com>
|
||||||
|
Description: This attribute reports the number of RX lanes the XDomain
|
||||||
|
is using simultaneously through its upstream port.
|
||||||
|
|
||||||
|
What: /sys/bus/thunderbolt/devices/<xdomain>/tx_speed
|
||||||
|
Date: Feb 2021
|
||||||
|
KernelVersion: 5.11
|
||||||
|
Contact: Isaac Hazan <isaac.hazan@intel.com>
|
||||||
|
Description: This attribute reports the XDomain TX speed per lane.
|
||||||
|
All TX lanes run at the same speed.
|
||||||
|
|
||||||
|
What: /sys/bus/thunderbolt/devices/<xdomain>/tx_lanes
|
||||||
|
Date: Feb 2021
|
||||||
|
KernelVersion: 5.11
|
||||||
|
Contact: Isaac Hazan <isaac.hazan@intel.com>
|
||||||
|
Description: This attribute reports number of TX lanes the XDomain
|
||||||
|
is using simultaneously through its upstream port.
|
||||||
|
|
||||||
What: /sys/bus/thunderbolt/devices/.../domainX/boot_acl
|
What: /sys/bus/thunderbolt/devices/.../domainX/boot_acl
|
||||||
Date: Jun 2018
|
Date: Jun 2018
|
||||||
KernelVersion: 4.17
|
KernelVersion: 4.17
|
||||||
|
|
|
@ -932,7 +932,14 @@ int tb_port_get_link_speed(struct tb_port *port)
|
||||||
return speed == LANE_ADP_CS_1_CURRENT_SPEED_GEN3 ? 20 : 10;
|
return speed == LANE_ADP_CS_1_CURRENT_SPEED_GEN3 ? 20 : 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tb_port_get_link_width(struct tb_port *port)
|
/**
|
||||||
|
* tb_port_get_link_width() - Get current link width
|
||||||
|
* @port: Port to check (USB4 or CIO)
|
||||||
|
*
|
||||||
|
* Returns link width. Return values can be 1 (Single-Lane), 2 (Dual-Lane)
|
||||||
|
* or negative errno in case of failure.
|
||||||
|
*/
|
||||||
|
int tb_port_get_link_width(struct tb_port *port)
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
|
@ -862,6 +862,7 @@ struct tb_port *tb_next_port_on_path(struct tb_port *start, struct tb_port *end,
|
||||||
(p) = tb_next_port_on_path((src), (dst), (p)))
|
(p) = tb_next_port_on_path((src), (dst), (p)))
|
||||||
|
|
||||||
int tb_port_get_link_speed(struct tb_port *port);
|
int tb_port_get_link_speed(struct tb_port *port);
|
||||||
|
int tb_port_get_link_width(struct tb_port *port);
|
||||||
|
|
||||||
int tb_switch_find_vse_cap(struct tb_switch *sw, enum tb_switch_vse_cap vsec);
|
int tb_switch_find_vse_cap(struct tb_switch *sw, enum tb_switch_vse_cap vsec);
|
||||||
int tb_switch_find_cap(struct tb_switch *sw, enum tb_switch_cap cap);
|
int tb_switch_find_cap(struct tb_switch *sw, enum tb_switch_cap cap);
|
||||||
|
|
|
@ -942,6 +942,43 @@ static void tb_xdomain_restore_paths(struct tb_xdomain *xd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct tb_switch *tb_xdomain_parent(struct tb_xdomain *xd)
|
||||||
|
{
|
||||||
|
return tb_to_switch(xd->dev.parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tb_xdomain_update_link_attributes(struct tb_xdomain *xd)
|
||||||
|
{
|
||||||
|
bool change = false;
|
||||||
|
struct tb_port *port;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
port = tb_port_at(xd->route, tb_xdomain_parent(xd));
|
||||||
|
|
||||||
|
ret = tb_port_get_link_speed(port);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (xd->link_speed != ret)
|
||||||
|
change = true;
|
||||||
|
|
||||||
|
xd->link_speed = ret;
|
||||||
|
|
||||||
|
ret = tb_port_get_link_width(port);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (xd->link_width != ret)
|
||||||
|
change = true;
|
||||||
|
|
||||||
|
xd->link_width = ret;
|
||||||
|
|
||||||
|
if (change)
|
||||||
|
kobject_uevent(&xd->dev.kobj, KOBJ_CHANGE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void tb_xdomain_get_uuid(struct work_struct *work)
|
static void tb_xdomain_get_uuid(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct tb_xdomain *xd = container_of(work, typeof(*xd),
|
struct tb_xdomain *xd = container_of(work, typeof(*xd),
|
||||||
|
@ -1053,6 +1090,8 @@ static void tb_xdomain_get_properties(struct work_struct *work)
|
||||||
xd->properties = dir;
|
xd->properties = dir;
|
||||||
xd->property_block_gen = gen;
|
xd->property_block_gen = gen;
|
||||||
|
|
||||||
|
tb_xdomain_update_link_attributes(xd);
|
||||||
|
|
||||||
tb_xdomain_restore_paths(xd);
|
tb_xdomain_restore_paths(xd);
|
||||||
|
|
||||||
mutex_unlock(&xd->lock);
|
mutex_unlock(&xd->lock);
|
||||||
|
@ -1159,9 +1198,35 @@ static ssize_t unique_id_show(struct device *dev, struct device_attribute *attr,
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(unique_id);
|
static DEVICE_ATTR_RO(unique_id);
|
||||||
|
|
||||||
|
static ssize_t speed_show(struct device *dev, struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct tb_xdomain *xd = container_of(dev, struct tb_xdomain, dev);
|
||||||
|
|
||||||
|
return sprintf(buf, "%u.0 Gb/s\n", xd->link_speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(rx_speed, 0444, speed_show, NULL);
|
||||||
|
static DEVICE_ATTR(tx_speed, 0444, speed_show, NULL);
|
||||||
|
|
||||||
|
static ssize_t lanes_show(struct device *dev, struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct tb_xdomain *xd = container_of(dev, struct tb_xdomain, dev);
|
||||||
|
|
||||||
|
return sprintf(buf, "%u\n", xd->link_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(rx_lanes, 0444, lanes_show, NULL);
|
||||||
|
static DEVICE_ATTR(tx_lanes, 0444, lanes_show, NULL);
|
||||||
|
|
||||||
static struct attribute *xdomain_attrs[] = {
|
static struct attribute *xdomain_attrs[] = {
|
||||||
&dev_attr_device.attr,
|
&dev_attr_device.attr,
|
||||||
&dev_attr_device_name.attr,
|
&dev_attr_device_name.attr,
|
||||||
|
&dev_attr_rx_lanes.attr,
|
||||||
|
&dev_attr_rx_speed.attr,
|
||||||
|
&dev_attr_tx_lanes.attr,
|
||||||
|
&dev_attr_tx_speed.attr,
|
||||||
&dev_attr_unique_id.attr,
|
&dev_attr_unique_id.attr,
|
||||||
&dev_attr_vendor.attr,
|
&dev_attr_vendor.attr,
|
||||||
&dev_attr_vendor_name.attr,
|
&dev_attr_vendor_name.attr,
|
||||||
|
|
|
@ -179,6 +179,8 @@ void tb_unregister_property_dir(const char *key, struct tb_property_dir *dir);
|
||||||
* @lock: Lock to serialize access to the following fields of this structure
|
* @lock: Lock to serialize access to the following fields of this structure
|
||||||
* @vendor_name: Name of the vendor (or %NULL if not known)
|
* @vendor_name: Name of the vendor (or %NULL if not known)
|
||||||
* @device_name: Name of the device (or %NULL if not known)
|
* @device_name: Name of the device (or %NULL if not known)
|
||||||
|
* @link_speed: Speed of the link in Gb/s
|
||||||
|
* @link_width: Width of the link (1 or 2)
|
||||||
* @is_unplugged: The XDomain is unplugged
|
* @is_unplugged: The XDomain is unplugged
|
||||||
* @resume: The XDomain is being resumed
|
* @resume: The XDomain is being resumed
|
||||||
* @needs_uuid: If the XDomain does not have @remote_uuid it will be
|
* @needs_uuid: If the XDomain does not have @remote_uuid it will be
|
||||||
|
@ -223,6 +225,8 @@ struct tb_xdomain {
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
const char *vendor_name;
|
const char *vendor_name;
|
||||||
const char *device_name;
|
const char *device_name;
|
||||||
|
unsigned int link_speed;
|
||||||
|
unsigned int link_width;
|
||||||
bool is_unplugged;
|
bool is_unplugged;
|
||||||
bool resume;
|
bool resume;
|
||||||
bool needs_uuid;
|
bool needs_uuid;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче