Linux 6.9-rc1
[linux-2.6-microblaze.git] / drivers / thunderbolt / usb4_port.c
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
13 static 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 }
35 static DEVICE_ATTR_RO(link);
36
37 static struct attribute *common_attrs[] = {
38         &dev_attr_link.attr,
39         NULL
40 };
41
42 static const struct attribute_group common_group = {
43         .attrs = common_attrs,
44 };
45
46 static 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
70 static 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
78 static 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
86 static 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
127 out_unlock:
128         mutex_unlock(&tb->lock);
129 out_rpm:
130         pm_runtime_mark_last_busy(&usb4->dev);
131         pm_runtime_put_autosuspend(&usb4->dev);
132
133         return ret ? ret : count;
134 }
135 static DEVICE_ATTR_RW(offline);
136
137 static 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
169 out_unlock:
170         mutex_unlock(&tb->lock);
171 out_rpm:
172         pm_runtime_mark_last_busy(&usb4->dev);
173         pm_runtime_put_autosuspend(&usb4->dev);
174
175         return ret ? ret : count;
176 }
177 static DEVICE_ATTR_WO(rescan);
178
179 static struct attribute *service_attrs[] = {
180         &dev_attr_offline.attr,
181         &dev_attr_rescan.attr,
182         NULL
183 };
184
185 static 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
198 static const struct attribute_group service_group = {
199         .attrs = service_attrs,
200         .is_visible = service_attr_is_visible,
201 };
202
203 static const struct attribute_group *usb4_port_device_groups[] = {
204         &common_group,
205         &service_group,
206         NULL
207 };
208
209 static 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
216 struct 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  */
229 struct 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  */
266 void 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  */
277 int usb4_port_device_resume(struct usb4_port *usb4)
278 {
279         return usb4->offline ? usb4_port_offline(usb4) : 0;
280 }