Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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