Merge tag 'pm-5.20-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[linux-2.6-block.git] / drivers / thunderbolt / usb4_port.c
CommitLineData
cae5f515
MW
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
cae5f515 9#include <linux/pm_runtime.h>
5dddb416
HK
10#include <linux/component.h>
11#include <linux/property.h>
cae5f515
MW
12
13#include "tb.h"
14
5dddb416
HK
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
cae5f515
MW
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
3fb10ea4
RM
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
cae5f515
MW
231static const struct attribute_group *usb4_port_device_groups[] = {
232 &common_group,
3fb10ea4 233 &service_group,
cae5f515
MW
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
5dddb416
HK
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
cae5f515
MW
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{
5dddb416
HK
304 if (dev_fwnode(&usb4->dev))
305 component_del(&usb4->dev, &connector_ops);
cae5f515
MW
306 device_unregister(&usb4->dev);
307}
3fb10ea4
RM
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}