usb4_port.c (7069B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * USB4 port device 4 * 5 * Copyright (C) 2021, Intel Corporation 6 * Author: Mika Westerberg <mika.westerberg@linux.intel.com> 7 */ 8 9#include <linux/pm_runtime.h> 10#include <linux/component.h> 11#include <linux/property.h> 12 13#include "tb.h" 14 15static int connector_bind(struct device *dev, struct device *connector, void *data) 16{ 17 int ret; 18 19 ret = sysfs_create_link(&dev->kobj, &connector->kobj, "connector"); 20 if (ret) 21 return ret; 22 23 ret = sysfs_create_link(&connector->kobj, &dev->kobj, dev_name(dev)); 24 if (ret) 25 sysfs_remove_link(&dev->kobj, "connector"); 26 27 return ret; 28} 29 30static void connector_unbind(struct device *dev, struct device *connector, void *data) 31{ 32 sysfs_remove_link(&connector->kobj, dev_name(dev)); 33 sysfs_remove_link(&dev->kobj, "connector"); 34} 35 36static const struct component_ops connector_ops = { 37 .bind = connector_bind, 38 .unbind = connector_unbind, 39}; 40 41static ssize_t link_show(struct device *dev, struct device_attribute *attr, 42 char *buf) 43{ 44 struct usb4_port *usb4 = tb_to_usb4_port_device(dev); 45 struct tb_port *port = usb4->port; 46 struct tb *tb = port->sw->tb; 47 const char *link; 48 49 if (mutex_lock_interruptible(&tb->lock)) 50 return -ERESTARTSYS; 51 52 if (tb_is_upstream_port(port)) 53 link = port->sw->link_usb4 ? "usb4" : "tbt"; 54 else if (tb_port_has_remote(port)) 55 link = port->remote->sw->link_usb4 ? "usb4" : "tbt"; 56 else 57 link = "none"; 58 59 mutex_unlock(&tb->lock); 60 61 return sysfs_emit(buf, "%s\n", link); 62} 63static DEVICE_ATTR_RO(link); 64 65static struct attribute *common_attrs[] = { 66 &dev_attr_link.attr, 67 NULL 68}; 69 70static const struct attribute_group common_group = { 71 .attrs = common_attrs, 72}; 73 74static int usb4_port_offline(struct usb4_port *usb4) 75{ 76 struct tb_port *port = usb4->port; 77 int ret; 78 79 ret = tb_acpi_power_on_retimers(port); 80 if (ret) 81 return ret; 82 83 ret = usb4_port_router_offline(port); 84 if (ret) { 85 tb_acpi_power_off_retimers(port); 86 return ret; 87 } 88 89 ret = tb_retimer_scan(port, false); 90 if (ret) { 91 usb4_port_router_online(port); 92 tb_acpi_power_off_retimers(port); 93 } 94 95 return ret; 96} 97 98static void usb4_port_online(struct usb4_port *usb4) 99{ 100 struct tb_port *port = usb4->port; 101 102 usb4_port_router_online(port); 103 tb_acpi_power_off_retimers(port); 104} 105 106static ssize_t offline_show(struct device *dev, 107 struct device_attribute *attr, char *buf) 108{ 109 struct usb4_port *usb4 = tb_to_usb4_port_device(dev); 110 111 return sysfs_emit(buf, "%d\n", usb4->offline); 112} 113 114static ssize_t offline_store(struct device *dev, 115 struct device_attribute *attr, const char *buf, size_t count) 116{ 117 struct usb4_port *usb4 = tb_to_usb4_port_device(dev); 118 struct tb_port *port = usb4->port; 119 struct tb *tb = port->sw->tb; 120 bool val; 121 int ret; 122 123 ret = kstrtobool(buf, &val); 124 if (ret) 125 return ret; 126 127 pm_runtime_get_sync(&usb4->dev); 128 129 if (mutex_lock_interruptible(&tb->lock)) { 130 ret = -ERESTARTSYS; 131 goto out_rpm; 132 } 133 134 if (val == usb4->offline) 135 goto out_unlock; 136 137 /* Offline mode works only for ports that are not connected */ 138 if (tb_port_has_remote(port)) { 139 ret = -EBUSY; 140 goto out_unlock; 141 } 142 143 if (val) { 144 ret = usb4_port_offline(usb4); 145 if (ret) 146 goto out_unlock; 147 } else { 148 usb4_port_online(usb4); 149 tb_retimer_remove_all(port); 150 } 151 152 usb4->offline = val; 153 tb_port_dbg(port, "%s offline mode\n", val ? "enter" : "exit"); 154 155out_unlock: 156 mutex_unlock(&tb->lock); 157out_rpm: 158 pm_runtime_mark_last_busy(&usb4->dev); 159 pm_runtime_put_autosuspend(&usb4->dev); 160 161 return ret ? ret : count; 162} 163static DEVICE_ATTR_RW(offline); 164 165static ssize_t rescan_store(struct device *dev, 166 struct device_attribute *attr, const char *buf, size_t count) 167{ 168 struct usb4_port *usb4 = tb_to_usb4_port_device(dev); 169 struct tb_port *port = usb4->port; 170 struct tb *tb = port->sw->tb; 171 bool val; 172 int ret; 173 174 ret = kstrtobool(buf, &val); 175 if (ret) 176 return ret; 177 178 if (!val) 179 return count; 180 181 pm_runtime_get_sync(&usb4->dev); 182 183 if (mutex_lock_interruptible(&tb->lock)) { 184 ret = -ERESTARTSYS; 185 goto out_rpm; 186 } 187 188 /* Must be in offline mode already */ 189 if (!usb4->offline) { 190 ret = -EINVAL; 191 goto out_unlock; 192 } 193 194 tb_retimer_remove_all(port); 195 ret = tb_retimer_scan(port, true); 196 197out_unlock: 198 mutex_unlock(&tb->lock); 199out_rpm: 200 pm_runtime_mark_last_busy(&usb4->dev); 201 pm_runtime_put_autosuspend(&usb4->dev); 202 203 return ret ? ret : count; 204} 205static DEVICE_ATTR_WO(rescan); 206 207static struct attribute *service_attrs[] = { 208 &dev_attr_offline.attr, 209 &dev_attr_rescan.attr, 210 NULL 211}; 212 213static umode_t service_attr_is_visible(struct kobject *kobj, 214 struct attribute *attr, int n) 215{ 216 struct device *dev = kobj_to_dev(kobj); 217 struct usb4_port *usb4 = tb_to_usb4_port_device(dev); 218 219 /* 220 * Always need some platform help to cycle the modes so that 221 * retimers can be accessed through the sideband. 222 */ 223 return usb4->can_offline ? attr->mode : 0; 224} 225 226static const struct attribute_group service_group = { 227 .attrs = service_attrs, 228 .is_visible = service_attr_is_visible, 229}; 230 231static const struct attribute_group *usb4_port_device_groups[] = { 232 &common_group, 233 &service_group, 234 NULL 235}; 236 237static void usb4_port_device_release(struct device *dev) 238{ 239 struct usb4_port *usb4 = container_of(dev, struct usb4_port, dev); 240 241 kfree(usb4); 242} 243 244struct device_type usb4_port_device_type = { 245 .name = "usb4_port", 246 .groups = usb4_port_device_groups, 247 .release = usb4_port_device_release, 248}; 249 250/** 251 * usb4_port_device_add() - Add USB4 port device 252 * @port: Lane 0 adapter port to add the USB4 port 253 * 254 * Creates and registers a USB4 port device for @port. Returns the new 255 * USB4 port device pointer or ERR_PTR() in case of error. 256 */ 257struct usb4_port *usb4_port_device_add(struct tb_port *port) 258{ 259 struct usb4_port *usb4; 260 int ret; 261 262 usb4 = kzalloc(sizeof(*usb4), GFP_KERNEL); 263 if (!usb4) 264 return ERR_PTR(-ENOMEM); 265 266 usb4->port = port; 267 usb4->dev.type = &usb4_port_device_type; 268 usb4->dev.parent = &port->sw->dev; 269 dev_set_name(&usb4->dev, "usb4_port%d", port->port); 270 271 ret = device_register(&usb4->dev); 272 if (ret) { 273 put_device(&usb4->dev); 274 return ERR_PTR(ret); 275 } 276 277 if (dev_fwnode(&usb4->dev)) { 278 ret = component_add(&usb4->dev, &connector_ops); 279 if (ret) { 280 dev_err(&usb4->dev, "failed to add component\n"); 281 device_unregister(&usb4->dev); 282 } 283 } 284 285 pm_runtime_no_callbacks(&usb4->dev); 286 pm_runtime_set_active(&usb4->dev); 287 pm_runtime_enable(&usb4->dev); 288 pm_runtime_set_autosuspend_delay(&usb4->dev, TB_AUTOSUSPEND_DELAY); 289 pm_runtime_mark_last_busy(&usb4->dev); 290 pm_runtime_use_autosuspend(&usb4->dev); 291 292 return usb4; 293} 294 295/** 296 * usb4_port_device_remove() - Removes USB4 port device 297 * @usb4: USB4 port device 298 * 299 * Unregisters the USB4 port device from the system. The device will be 300 * released when the last reference is dropped. 301 */ 302void usb4_port_device_remove(struct usb4_port *usb4) 303{ 304 if (dev_fwnode(&usb4->dev)) 305 component_del(&usb4->dev, &connector_ops); 306 device_unregister(&usb4->dev); 307} 308 309/** 310 * usb4_port_device_resume() - Resumes USB4 port device 311 * @usb4: USB4 port device 312 * 313 * Used to resume USB4 port device after sleep state. 314 */ 315int usb4_port_device_resume(struct usb4_port *usb4) 316{ 317 return usb4->offline ? usb4_port_offline(usb4) : 0; 318}