xref: /openbmc/linux/drivers/usb/usbip/vhci_sysfs.c (revision bbecb07f)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2003-2008 Takahiro Hirofuchi
4  * Copyright (C) 2015-2016 Nobuo Iwata
5  */
6 
7 #include <linux/kthread.h>
8 #include <linux/file.h>
9 #include <linux/net.h>
10 #include <linux/platform_device.h>
11 #include <linux/slab.h>
12 
13 #include "usbip_common.h"
14 #include "vhci.h"
15 
16 /* TODO: refine locking ?*/
17 
18 /*
19  * output example:
20  * hub port sta spd dev      socket           local_busid
21  * hs  0000 004 000 00000000         c5a7bb80 1-2.3
22  * ................................................
23  * ss  0008 004 000 00000000         d8cee980 2-3.4
24  * ................................................
25  *
26  * IP address can be retrieved from a socket pointer address by looking
27  * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a
28  * port number and its peer IP address.
29  */
30 static void port_show_vhci(char **out, int hub, int port, struct vhci_device *vdev)
31 {
32 	if (hub == HUB_SPEED_HIGH)
33 		*out += sprintf(*out, "hs  %04u %03u ",
34 				      port, vdev->ud.status);
35 	else /* hub == HUB_SPEED_SUPER */
36 		*out += sprintf(*out, "ss  %04u %03u ",
37 				      port, vdev->ud.status);
38 
39 	if (vdev->ud.status == VDEV_ST_USED) {
40 		*out += sprintf(*out, "%03u %08x ",
41 				      vdev->speed, vdev->devid);
42 		*out += sprintf(*out, "%16p %s",
43 				      vdev->ud.tcp_socket,
44 				      dev_name(&vdev->udev->dev));
45 
46 	} else {
47 		*out += sprintf(*out, "000 00000000 ");
48 		*out += sprintf(*out, "0000000000000000 0-0");
49 	}
50 
51 	*out += sprintf(*out, "\n");
52 }
53 
54 /* Sysfs entry to show port status */
55 static ssize_t status_show_vhci(int pdev_nr, char *out)
56 {
57 	struct platform_device *pdev = vhcis[pdev_nr].pdev;
58 	struct vhci *vhci;
59 	struct usb_hcd *hcd;
60 	struct vhci_hcd *vhci_hcd;
61 	char *s = out;
62 	int i;
63 	unsigned long flags;
64 
65 	if (!pdev || !out) {
66 		usbip_dbg_vhci_sysfs("show status error\n");
67 		return 0;
68 	}
69 
70 	hcd = platform_get_drvdata(pdev);
71 	vhci_hcd = hcd_to_vhci_hcd(hcd);
72 	vhci = vhci_hcd->vhci;
73 
74 	spin_lock_irqsave(&vhci->lock, flags);
75 
76 	for (i = 0; i < VHCI_HC_PORTS; i++) {
77 		struct vhci_device *vdev = &vhci->vhci_hcd_hs->vdev[i];
78 
79 		spin_lock(&vdev->ud.lock);
80 		port_show_vhci(&out, HUB_SPEED_HIGH,
81 			       pdev_nr * VHCI_PORTS + i, vdev);
82 		spin_unlock(&vdev->ud.lock);
83 	}
84 
85 	for (i = 0; i < VHCI_HC_PORTS; i++) {
86 		struct vhci_device *vdev = &vhci->vhci_hcd_ss->vdev[i];
87 
88 		spin_lock(&vdev->ud.lock);
89 		port_show_vhci(&out, HUB_SPEED_SUPER,
90 			       pdev_nr * VHCI_PORTS + VHCI_HC_PORTS + i, vdev);
91 		spin_unlock(&vdev->ud.lock);
92 	}
93 
94 	spin_unlock_irqrestore(&vhci->lock, flags);
95 
96 	return out - s;
97 }
98 
99 static ssize_t status_show_not_ready(int pdev_nr, char *out)
100 {
101 	char *s = out;
102 	int i = 0;
103 
104 	for (i = 0; i < VHCI_HC_PORTS; i++) {
105 		out += sprintf(out, "hs  %04u %03u ",
106 				    (pdev_nr * VHCI_PORTS) + i,
107 				    VDEV_ST_NOTASSIGNED);
108 		out += sprintf(out, "000 00000000 0000000000000000 0-0");
109 		out += sprintf(out, "\n");
110 	}
111 
112 	for (i = 0; i < VHCI_HC_PORTS; i++) {
113 		out += sprintf(out, "ss  %04u %03u ",
114 				    (pdev_nr * VHCI_PORTS) + VHCI_HC_PORTS + i,
115 				    VDEV_ST_NOTASSIGNED);
116 		out += sprintf(out, "000 00000000 0000000000000000 0-0");
117 		out += sprintf(out, "\n");
118 	}
119 	return out - s;
120 }
121 
122 static int status_name_to_id(const char *name)
123 {
124 	char *c;
125 	long val;
126 	int ret;
127 
128 	c = strchr(name, '.');
129 	if (c == NULL)
130 		return 0;
131 
132 	ret = kstrtol(c+1, 10, &val);
133 	if (ret < 0)
134 		return ret;
135 
136 	return val;
137 }
138 
139 static ssize_t status_show(struct device *dev,
140 			   struct device_attribute *attr, char *out)
141 {
142 	char *s = out;
143 	int pdev_nr;
144 
145 	out += sprintf(out,
146 		       "hub port sta spd dev      socket           local_busid\n");
147 
148 	pdev_nr = status_name_to_id(attr->attr.name);
149 	if (pdev_nr < 0)
150 		out += status_show_not_ready(pdev_nr, out);
151 	else
152 		out += status_show_vhci(pdev_nr, out);
153 
154 	return out - s;
155 }
156 
157 static ssize_t nports_show(struct device *dev, struct device_attribute *attr,
158 			   char *out)
159 {
160 	char *s = out;
161 
162 	/*
163 	 * Half the ports are for SPEED_HIGH and half for SPEED_SUPER, thus the * 2.
164 	 */
165 	out += sprintf(out, "%d\n", VHCI_PORTS * vhci_num_controllers);
166 	return out - s;
167 }
168 static DEVICE_ATTR_RO(nports);
169 
170 /* Sysfs entry to shutdown a virtual connection */
171 static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport)
172 {
173 	struct vhci_device *vdev = &vhci_hcd->vdev[rhport];
174 	struct vhci *vhci = vhci_hcd->vhci;
175 	unsigned long flags;
176 
177 	usbip_dbg_vhci_sysfs("enter\n");
178 
179 	/* lock */
180 	spin_lock_irqsave(&vhci->lock, flags);
181 	spin_lock(&vdev->ud.lock);
182 
183 	if (vdev->ud.status == VDEV_ST_NULL) {
184 		pr_err("not connected %d\n", vdev->ud.status);
185 
186 		/* unlock */
187 		spin_unlock(&vdev->ud.lock);
188 		spin_unlock_irqrestore(&vhci->lock, flags);
189 
190 		return -EINVAL;
191 	}
192 
193 	/* unlock */
194 	spin_unlock(&vdev->ud.lock);
195 	spin_unlock_irqrestore(&vhci->lock, flags);
196 
197 	usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN);
198 
199 	return 0;
200 }
201 
202 static int valid_port(__u32 pdev_nr, __u32 rhport)
203 {
204 	if (pdev_nr >= vhci_num_controllers) {
205 		pr_err("pdev %u\n", pdev_nr);
206 		return 0;
207 	}
208 	if (rhport >= VHCI_HC_PORTS) {
209 		pr_err("rhport %u\n", rhport);
210 		return 0;
211 	}
212 	return 1;
213 }
214 
215 static ssize_t store_detach(struct device *dev, struct device_attribute *attr,
216 			    const char *buf, size_t count)
217 {
218 	__u32 port = 0, pdev_nr = 0, rhport = 0;
219 	struct usb_hcd *hcd;
220 	struct vhci_hcd *vhci_hcd;
221 	int ret;
222 
223 	if (kstrtoint(buf, 10, &port) < 0)
224 		return -EINVAL;
225 
226 	pdev_nr = port_to_pdev_nr(port);
227 	rhport = port_to_rhport(port);
228 
229 	if (!valid_port(pdev_nr, rhport))
230 		return -EINVAL;
231 
232 	hcd = platform_get_drvdata(vhcis[pdev_nr].pdev);
233 	if (hcd == NULL) {
234 		dev_err(dev, "port is not ready %u\n", port);
235 		return -EAGAIN;
236 	}
237 
238 	usbip_dbg_vhci_sysfs("rhport %d\n", rhport);
239 
240 	if ((port / VHCI_HC_PORTS) % 2)
241 		vhci_hcd = hcd_to_vhci_hcd(hcd)->vhci->vhci_hcd_ss;
242 	else
243 		vhci_hcd = hcd_to_vhci_hcd(hcd)->vhci->vhci_hcd_hs;
244 
245 	ret = vhci_port_disconnect(vhci_hcd, rhport);
246 	if (ret < 0)
247 		return -EINVAL;
248 
249 	usbip_dbg_vhci_sysfs("Leave\n");
250 
251 	return count;
252 }
253 static DEVICE_ATTR(detach, S_IWUSR, NULL, store_detach);
254 
255 static int valid_args(__u32 pdev_nr, __u32 rhport, enum usb_device_speed speed)
256 {
257 	if (!valid_port(pdev_nr, rhport)) {
258 		return 0;
259 	}
260 
261 	switch (speed) {
262 	case USB_SPEED_LOW:
263 	case USB_SPEED_FULL:
264 	case USB_SPEED_HIGH:
265 	case USB_SPEED_WIRELESS:
266 	case USB_SPEED_SUPER:
267 		break;
268 	default:
269 		pr_err("Failed attach request for unsupported USB speed: %s\n",
270 			usb_speed_string(speed));
271 		return 0;
272 	}
273 
274 	return 1;
275 }
276 
277 /* Sysfs entry to establish a virtual connection */
278 /*
279  * To start a new USB/IP attachment, a userland program needs to setup a TCP
280  * connection and then write its socket descriptor with remote device
281  * information into this sysfs file.
282  *
283  * A remote device is virtually attached to the root-hub port of @rhport with
284  * @speed. @devid is embedded into a request to specify the remote device in a
285  * server host.
286  *
287  * write() returns 0 on success, else negative errno.
288  */
289 static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
290 			    const char *buf, size_t count)
291 {
292 	struct socket *socket;
293 	int sockfd = 0;
294 	__u32 port = 0, pdev_nr = 0, rhport = 0, devid = 0, speed = 0;
295 	struct usb_hcd *hcd;
296 	struct vhci_hcd *vhci_hcd;
297 	struct vhci_device *vdev;
298 	struct vhci *vhci;
299 	int err;
300 	unsigned long flags;
301 
302 	/*
303 	 * @rhport: port number of vhci_hcd
304 	 * @sockfd: socket descriptor of an established TCP connection
305 	 * @devid: unique device identifier in a remote host
306 	 * @speed: usb device speed in a remote host
307 	 */
308 	if (sscanf(buf, "%u %u %u %u", &port, &sockfd, &devid, &speed) != 4)
309 		return -EINVAL;
310 	pdev_nr = port_to_pdev_nr(port);
311 	rhport = port_to_rhport(port);
312 
313 	usbip_dbg_vhci_sysfs("port(%u) pdev(%d) rhport(%u)\n",
314 			     port, pdev_nr, rhport);
315 	usbip_dbg_vhci_sysfs("sockfd(%u) devid(%u) speed(%u)\n",
316 			     sockfd, devid, speed);
317 
318 	/* check received parameters */
319 	if (!valid_args(pdev_nr, rhport, speed))
320 		return -EINVAL;
321 
322 	hcd = platform_get_drvdata(vhcis[pdev_nr].pdev);
323 	if (hcd == NULL) {
324 		dev_err(dev, "port %d is not ready\n", port);
325 		return -EAGAIN;
326 	}
327 
328 	vhci_hcd = hcd_to_vhci_hcd(hcd);
329 	vhci = vhci_hcd->vhci;
330 
331 	if (speed == USB_SPEED_SUPER)
332 		vdev = &vhci->vhci_hcd_ss->vdev[rhport];
333 	else
334 		vdev = &vhci->vhci_hcd_hs->vdev[rhport];
335 
336 	/* Extract socket from fd. */
337 	socket = sockfd_lookup(sockfd, &err);
338 	if (!socket)
339 		return -EINVAL;
340 
341 	/* now need lock until setting vdev status as used */
342 
343 	/* begin a lock */
344 	spin_lock_irqsave(&vhci->lock, flags);
345 	spin_lock(&vdev->ud.lock);
346 
347 	if (vdev->ud.status != VDEV_ST_NULL) {
348 		/* end of the lock */
349 		spin_unlock(&vdev->ud.lock);
350 		spin_unlock_irqrestore(&vhci->lock, flags);
351 
352 		sockfd_put(socket);
353 
354 		dev_err(dev, "port %d already used\n", rhport);
355 		/*
356 		 * Will be retried from userspace
357 		 * if there's another free port.
358 		 */
359 		return -EBUSY;
360 	}
361 
362 	dev_info(dev, "pdev(%u) rhport(%u) sockfd(%d)\n",
363 		 pdev_nr, rhport, sockfd);
364 	dev_info(dev, "devid(%u) speed(%u) speed_str(%s)\n",
365 		 devid, speed, usb_speed_string(speed));
366 
367 	vdev->devid         = devid;
368 	vdev->speed         = speed;
369 	vdev->ud.tcp_socket = socket;
370 	vdev->ud.status     = VDEV_ST_NOTASSIGNED;
371 
372 	spin_unlock(&vdev->ud.lock);
373 	spin_unlock_irqrestore(&vhci->lock, flags);
374 	/* end the lock */
375 
376 	vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx");
377 	vdev->ud.tcp_tx = kthread_get_run(vhci_tx_loop, &vdev->ud, "vhci_tx");
378 
379 	rh_port_connect(vdev, speed);
380 
381 	return count;
382 }
383 static DEVICE_ATTR(attach, S_IWUSR, NULL, store_attach);
384 
385 #define MAX_STATUS_NAME 16
386 
387 struct status_attr {
388 	struct device_attribute attr;
389 	char name[MAX_STATUS_NAME+1];
390 };
391 
392 static struct status_attr *status_attrs;
393 
394 static void set_status_attr(int id)
395 {
396 	struct status_attr *status;
397 
398 	status = status_attrs + id;
399 	if (id == 0)
400 		strcpy(status->name, "status");
401 	else
402 		snprintf(status->name, MAX_STATUS_NAME+1, "status.%d", id);
403 	status->attr.attr.name = status->name;
404 	status->attr.attr.mode = S_IRUGO;
405 	status->attr.show = status_show;
406 	sysfs_attr_init(&status->attr.attr);
407 }
408 
409 static int init_status_attrs(void)
410 {
411 	int id;
412 
413 	status_attrs = kcalloc(vhci_num_controllers, sizeof(struct status_attr),
414 			       GFP_KERNEL);
415 	if (status_attrs == NULL)
416 		return -ENOMEM;
417 
418 	for (id = 0; id < vhci_num_controllers; id++)
419 		set_status_attr(id);
420 
421 	return 0;
422 }
423 
424 static void finish_status_attrs(void)
425 {
426 	kfree(status_attrs);
427 }
428 
429 struct attribute_group vhci_attr_group = {
430 	.attrs = NULL,
431 };
432 
433 int vhci_init_attr_group(void)
434 {
435 	struct attribute **attrs;
436 	int ret, i;
437 
438 	attrs = kcalloc((vhci_num_controllers + 5), sizeof(struct attribute *),
439 			GFP_KERNEL);
440 	if (attrs == NULL)
441 		return -ENOMEM;
442 
443 	ret = init_status_attrs();
444 	if (ret) {
445 		kfree(attrs);
446 		return ret;
447 	}
448 	*attrs = &dev_attr_nports.attr;
449 	*(attrs + 1) = &dev_attr_detach.attr;
450 	*(attrs + 2) = &dev_attr_attach.attr;
451 	*(attrs + 3) = &dev_attr_usbip_debug.attr;
452 	for (i = 0; i < vhci_num_controllers; i++)
453 		*(attrs + i + 4) = &((status_attrs + i)->attr.attr);
454 	vhci_attr_group.attrs = attrs;
455 	return 0;
456 }
457 
458 void vhci_finish_attr_group(void)
459 {
460 	finish_status_attrs();
461 	kfree(vhci_attr_group.attrs);
462 }
463