1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2003-2008 Takahiro Hirofuchi 4 */ 5 6#include <linux/string.h> 7#include <linux/module.h> 8#include <linux/device.h> 9#include <linux/scatterlist.h> 10 11#include "usbip_common.h" 12#include "stub.h" 13 14#define DRIVER_AUTHOR "Takahiro Hirofuchi" 15#define DRIVER_DESC "USB/IP Host Driver" 16 17struct kmem_cache *stub_priv_cache; 18 19/* 20 * busid_tables defines matching busids that usbip can grab. A user can change 21 * dynamically what device is locally used and what device is exported to a 22 * remote host. 23 */ 24#define MAX_BUSID 16 25static struct bus_id_priv busid_table[MAX_BUSID]; 26static DEFINE_SPINLOCK(busid_table_lock); 27 28static void init_busid_table(void) 29{ 30 int i; 31 32 /* 33 * This also sets the bus_table[i].status to 34 * STUB_BUSID_OTHER, which is 0. 35 */ 36 memset(busid_table, 0, sizeof(busid_table)); 37 38 for (i = 0; i < MAX_BUSID; i++) 39 spin_lock_init(&busid_table[i].busid_lock); 40} 41 42/* 43 * Find the index of the busid by name. 44 * Must be called with busid_table_lock held. 45 */ 46static int get_busid_idx(const char *busid) 47{ 48 int i; 49 int idx = -1; 50 51 for (i = 0; i < MAX_BUSID; i++) { 52 spin_lock(&busid_table[i].busid_lock); 53 if (busid_table[i].name[0]) 54 if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) { 55 idx = i; 56 spin_unlock(&busid_table[i].busid_lock); 57 break; 58 } 59 spin_unlock(&busid_table[i].busid_lock); 60 } 61 return idx; 62} 63 64/* Returns holding busid_lock. Should call put_busid_priv() to unlock */ 65struct bus_id_priv *get_busid_priv(const char *busid) 66{ 67 int idx; 68 struct bus_id_priv *bid = NULL; 69 70 spin_lock(&busid_table_lock); 71 idx = get_busid_idx(busid); 72 if (idx >= 0) { 73 bid = &(busid_table[idx]); 74 /* get busid_lock before returning */ 75 spin_lock(&bid->busid_lock); 76 } 77 spin_unlock(&busid_table_lock); 78 79 return bid; 80} 81 82void put_busid_priv(struct bus_id_priv *bid) 83{ 84 if (bid) 85 spin_unlock(&bid->busid_lock); 86} 87 88static int add_match_busid(char *busid) 89{ 90 int i; 91 int ret = -1; 92 93 spin_lock(&busid_table_lock); 94 /* already registered? */ 95 if (get_busid_idx(busid) >= 0) { 96 ret = 0; 97 goto out; 98 } 99 100 for (i = 0; i < MAX_BUSID; i++) { 101 spin_lock(&busid_table[i].busid_lock); 102 if (!busid_table[i].name[0]) { 103 strscpy(busid_table[i].name, busid, BUSID_SIZE); 104 if ((busid_table[i].status != STUB_BUSID_ALLOC) && 105 (busid_table[i].status != STUB_BUSID_REMOV)) 106 busid_table[i].status = STUB_BUSID_ADDED; 107 ret = 0; 108 spin_unlock(&busid_table[i].busid_lock); 109 break; 110 } 111 spin_unlock(&busid_table[i].busid_lock); 112 } 113 114out: 115 spin_unlock(&busid_table_lock); 116 117 return ret; 118} 119 120int del_match_busid(char *busid) 121{ 122 int idx; 123 int ret = -1; 124 125 spin_lock(&busid_table_lock); 126 idx = get_busid_idx(busid); 127 if (idx < 0) 128 goto out; 129 130 /* found */ 131 ret = 0; 132 133 spin_lock(&busid_table[idx].busid_lock); 134 135 if (busid_table[idx].status == STUB_BUSID_OTHER) 136 memset(busid_table[idx].name, 0, BUSID_SIZE); 137 138 if ((busid_table[idx].status != STUB_BUSID_OTHER) && 139 (busid_table[idx].status != STUB_BUSID_ADDED)) 140 busid_table[idx].status = STUB_BUSID_REMOV; 141 142 spin_unlock(&busid_table[idx].busid_lock); 143out: 144 spin_unlock(&busid_table_lock); 145 146 return ret; 147} 148 149static ssize_t match_busid_show(struct device_driver *drv, char *buf) 150{ 151 int i; 152 char *out = buf; 153 154 spin_lock(&busid_table_lock); 155 for (i = 0; i < MAX_BUSID; i++) { 156 spin_lock(&busid_table[i].busid_lock); 157 if (busid_table[i].name[0]) 158 out += sprintf(out, "%s ", busid_table[i].name); 159 spin_unlock(&busid_table[i].busid_lock); 160 } 161 spin_unlock(&busid_table_lock); 162 out += sprintf(out, "\n"); 163 164 return out - buf; 165} 166 167static ssize_t match_busid_store(struct device_driver *dev, const char *buf, 168 size_t count) 169{ 170 char busid[BUSID_SIZE]; 171 172 if (count < 5) 173 return -EINVAL; 174 175 /* busid needs to include \0 termination */ 176 if (strscpy(busid, buf + 4, BUSID_SIZE) < 0) 177 return -EINVAL; 178 179 if (!strncmp(buf, "add ", 4)) { 180 if (add_match_busid(busid) < 0) 181 return -ENOMEM; 182 183 pr_debug("add busid %s\n", busid); 184 return count; 185 } 186 187 if (!strncmp(buf, "del ", 4)) { 188 if (del_match_busid(busid) < 0) 189 return -ENODEV; 190 191 pr_debug("del busid %s\n", busid); 192 return count; 193 } 194 195 return -EINVAL; 196} 197static DRIVER_ATTR_RW(match_busid); 198 199static int do_rebind(char *busid, struct bus_id_priv *busid_priv) 200{ 201 int ret = 0; 202 203 /* device_attach() callers should hold parent lock for USB */ 204 if (busid_priv->udev->dev.parent) 205 device_lock(busid_priv->udev->dev.parent); 206 ret = device_attach(&busid_priv->udev->dev); 207 if (busid_priv->udev->dev.parent) 208 device_unlock(busid_priv->udev->dev.parent); 209 if (ret < 0) 210 dev_err(&busid_priv->udev->dev, "rebind failed\n"); 211 return ret; 212} 213 214static void stub_device_rebind(void) 215{ 216#if IS_MODULE(CONFIG_USBIP_HOST) 217 struct bus_id_priv *busid_priv; 218 int i; 219 220 /* update status to STUB_BUSID_OTHER so probe ignores the device */ 221 spin_lock(&busid_table_lock); 222 for (i = 0; i < MAX_BUSID; i++) { 223 if (busid_table[i].name[0] && 224 busid_table[i].shutdown_busid) { 225 busid_priv = &(busid_table[i]); 226 busid_priv->status = STUB_BUSID_OTHER; 227 } 228 } 229 spin_unlock(&busid_table_lock); 230 231 /* now run rebind - no need to hold locks. driver files are removed */ 232 for (i = 0; i < MAX_BUSID; i++) { 233 if (busid_table[i].name[0] && 234 busid_table[i].shutdown_busid) { 235 busid_priv = &(busid_table[i]); 236 do_rebind(busid_table[i].name, busid_priv); 237 } 238 } 239#endif 240} 241 242static ssize_t rebind_store(struct device_driver *dev, const char *buf, 243 size_t count) 244{ 245 int ret; 246 int len; 247 struct bus_id_priv *bid; 248 249 /* buf length should be less that BUSID_SIZE */ 250 len = strnlen(buf, BUSID_SIZE); 251 252 if (!(len < BUSID_SIZE)) 253 return -EINVAL; 254 255 bid = get_busid_priv(buf); 256 if (!bid) 257 return -ENODEV; 258 259 /* mark the device for deletion so probe ignores it during rescan */ 260 bid->status = STUB_BUSID_OTHER; 261 /* release the busid lock */ 262 put_busid_priv(bid); 263 264 ret = do_rebind((char *) buf, bid); 265 if (ret < 0) 266 return ret; 267 268 /* delete device from busid_table */ 269 del_match_busid((char *) buf); 270 271 return count; 272} 273 274static DRIVER_ATTR_WO(rebind); 275 276static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead) 277{ 278 struct stub_priv *priv, *tmp; 279 280 list_for_each_entry_safe(priv, tmp, listhead, list) { 281 list_del_init(&priv->list); 282 return priv; 283 } 284 285 return NULL; 286} 287 288void stub_free_priv_and_urb(struct stub_priv *priv) 289{ 290 struct urb *urb; 291 int i; 292 293 for (i = 0; i < priv->num_urbs; i++) { 294 urb = priv->urbs[i]; 295 296 if (!urb) 297 return; 298 299 kfree(urb->setup_packet); 300 urb->setup_packet = NULL; 301 302 303 if (urb->transfer_buffer && !priv->sgl) { 304 kfree(urb->transfer_buffer); 305 urb->transfer_buffer = NULL; 306 } 307 308 if (urb->num_sgs) { 309 sgl_free(urb->sg); 310 urb->sg = NULL; 311 urb->num_sgs = 0; 312 } 313 314 usb_free_urb(urb); 315 } 316 if (!list_empty(&priv->list)) 317 list_del(&priv->list); 318 if (priv->sgl) 319 sgl_free(priv->sgl); 320 kfree(priv->urbs); 321 kmem_cache_free(stub_priv_cache, priv); 322} 323 324static struct stub_priv *stub_priv_pop(struct stub_device *sdev) 325{ 326 unsigned long flags; 327 struct stub_priv *priv; 328 329 spin_lock_irqsave(&sdev->priv_lock, flags); 330 331 priv = stub_priv_pop_from_listhead(&sdev->priv_init); 332 if (priv) 333 goto done; 334 335 priv = stub_priv_pop_from_listhead(&sdev->priv_tx); 336 if (priv) 337 goto done; 338 339 priv = stub_priv_pop_from_listhead(&sdev->priv_free); 340 341done: 342 spin_unlock_irqrestore(&sdev->priv_lock, flags); 343 344 return priv; 345} 346 347void stub_device_cleanup_urbs(struct stub_device *sdev) 348{ 349 struct stub_priv *priv; 350 int i; 351 352 dev_dbg(&sdev->udev->dev, "Stub device cleaning up urbs\n"); 353 354 while ((priv = stub_priv_pop(sdev))) { 355 for (i = 0; i < priv->num_urbs; i++) 356 usb_kill_urb(priv->urbs[i]); 357 358 stub_free_priv_and_urb(priv); 359 } 360} 361 362static int __init usbip_host_init(void) 363{ 364 int ret; 365 366 init_busid_table(); 367 368 stub_priv_cache = KMEM_CACHE(stub_priv, SLAB_HWCACHE_ALIGN); 369 if (!stub_priv_cache) { 370 pr_err("kmem_cache_create failed\n"); 371 return -ENOMEM; 372 } 373 374 ret = usb_register_device_driver(&stub_driver, THIS_MODULE); 375 if (ret) { 376 pr_err("usb_register failed %d\n", ret); 377 goto err_usb_register; 378 } 379 380 ret = driver_create_file(&stub_driver.driver, 381 &driver_attr_match_busid); 382 if (ret) { 383 pr_err("driver_create_file failed\n"); 384 goto err_create_file; 385 } 386 387 ret = driver_create_file(&stub_driver.driver, 388 &driver_attr_rebind); 389 if (ret) { 390 pr_err("driver_create_file failed\n"); 391 goto err_create_file; 392 } 393 394 return ret; 395 396err_create_file: 397 usb_deregister_device_driver(&stub_driver); 398err_usb_register: 399 kmem_cache_destroy(stub_priv_cache); 400 return ret; 401} 402 403static void __exit usbip_host_exit(void) 404{ 405 driver_remove_file(&stub_driver.driver, 406 &driver_attr_match_busid); 407 408 driver_remove_file(&stub_driver.driver, 409 &driver_attr_rebind); 410 411 /* 412 * deregister() calls stub_disconnect() for all devices. Device 413 * specific data is cleared in stub_disconnect(). 414 */ 415 usb_deregister_device_driver(&stub_driver); 416 417 /* initiate scan to attach devices */ 418 stub_device_rebind(); 419 420 kmem_cache_destroy(stub_priv_cache); 421} 422 423module_init(usbip_host_init); 424module_exit(usbip_host_exit); 425 426MODULE_AUTHOR(DRIVER_AUTHOR); 427MODULE_DESCRIPTION(DRIVER_DESC); 428MODULE_LICENSE("GPL"); 429