1 /* 2 * Copyright (C) 2003-2008 Takahiro Hirofuchi 3 * 4 * This is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 17 * USA. 18 */ 19 20 #include <linux/string.h> 21 #include <linux/module.h> 22 #include <linux/device.h> 23 24 #include "usbip_common.h" 25 #include "stub.h" 26 27 #define DRIVER_AUTHOR "Takahiro Hirofuchi" 28 #define DRIVER_DESC "USB/IP Host Driver" 29 30 struct kmem_cache *stub_priv_cache; 31 /* 32 * busid_tables defines matching busids that usbip can grab. A user can change 33 * dynamically what device is locally used and what device is exported to a 34 * remote host. 35 */ 36 #define MAX_BUSID 16 37 static struct bus_id_priv busid_table[MAX_BUSID]; 38 static spinlock_t busid_table_lock; 39 40 static void init_busid_table(void) 41 { 42 /* 43 * This also sets the bus_table[i].status to 44 * STUB_BUSID_OTHER, which is 0. 45 */ 46 memset(busid_table, 0, sizeof(busid_table)); 47 48 spin_lock_init(&busid_table_lock); 49 } 50 51 /* 52 * Find the index of the busid by name. 53 * Must be called with busid_table_lock held. 54 */ 55 static int get_busid_idx(const char *busid) 56 { 57 int i; 58 int idx = -1; 59 60 for (i = 0; i < MAX_BUSID; i++) 61 if (busid_table[i].name[0]) 62 if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) { 63 idx = i; 64 break; 65 } 66 return idx; 67 } 68 69 struct bus_id_priv *get_busid_priv(const char *busid) 70 { 71 int idx; 72 struct bus_id_priv *bid = NULL; 73 74 spin_lock(&busid_table_lock); 75 idx = get_busid_idx(busid); 76 if (idx >= 0) 77 bid = &(busid_table[idx]); 78 spin_unlock(&busid_table_lock); 79 80 return bid; 81 } 82 83 static int add_match_busid(char *busid) 84 { 85 int i; 86 int ret = -1; 87 88 spin_lock(&busid_table_lock); 89 /* already registered? */ 90 if (get_busid_idx(busid) >= 0) { 91 ret = 0; 92 goto out; 93 } 94 95 for (i = 0; i < MAX_BUSID; i++) 96 if (!busid_table[i].name[0]) { 97 strlcpy(busid_table[i].name, busid, BUSID_SIZE); 98 if ((busid_table[i].status != STUB_BUSID_ALLOC) && 99 (busid_table[i].status != STUB_BUSID_REMOV)) 100 busid_table[i].status = STUB_BUSID_ADDED; 101 ret = 0; 102 break; 103 } 104 105 out: 106 spin_unlock(&busid_table_lock); 107 108 return ret; 109 } 110 111 int del_match_busid(char *busid) 112 { 113 int idx; 114 int ret = -1; 115 116 spin_lock(&busid_table_lock); 117 idx = get_busid_idx(busid); 118 if (idx < 0) 119 goto out; 120 121 /* found */ 122 ret = 0; 123 124 if (busid_table[idx].status == STUB_BUSID_OTHER) 125 memset(busid_table[idx].name, 0, BUSID_SIZE); 126 127 if ((busid_table[idx].status != STUB_BUSID_OTHER) && 128 (busid_table[idx].status != STUB_BUSID_ADDED)) 129 busid_table[idx].status = STUB_BUSID_REMOV; 130 131 out: 132 spin_unlock(&busid_table_lock); 133 134 return ret; 135 } 136 137 static ssize_t match_busid_show(struct device_driver *drv, char *buf) 138 { 139 int i; 140 char *out = buf; 141 142 spin_lock(&busid_table_lock); 143 for (i = 0; i < MAX_BUSID; i++) 144 if (busid_table[i].name[0]) 145 out += sprintf(out, "%s ", busid_table[i].name); 146 spin_unlock(&busid_table_lock); 147 out += sprintf(out, "\n"); 148 149 return out - buf; 150 } 151 152 static ssize_t match_busid_store(struct device_driver *dev, const char *buf, 153 size_t count) 154 { 155 int len; 156 char busid[BUSID_SIZE]; 157 158 if (count < 5) 159 return -EINVAL; 160 161 /* busid needs to include \0 termination */ 162 len = strlcpy(busid, buf + 4, BUSID_SIZE); 163 if (sizeof(busid) <= len) 164 return -EINVAL; 165 166 if (!strncmp(buf, "add ", 4)) { 167 if (add_match_busid(busid) < 0) 168 return -ENOMEM; 169 170 pr_debug("add busid %s\n", busid); 171 return count; 172 } 173 174 if (!strncmp(buf, "del ", 4)) { 175 if (del_match_busid(busid) < 0) 176 return -ENODEV; 177 178 pr_debug("del busid %s\n", busid); 179 return count; 180 } 181 182 return -EINVAL; 183 } 184 static DRIVER_ATTR_RW(match_busid); 185 186 static ssize_t rebind_store(struct device_driver *dev, const char *buf, 187 size_t count) 188 { 189 int ret; 190 int len; 191 struct bus_id_priv *bid; 192 193 /* buf length should be less that BUSID_SIZE */ 194 len = strnlen(buf, BUSID_SIZE); 195 196 if (!(len < BUSID_SIZE)) 197 return -EINVAL; 198 199 bid = get_busid_priv(buf); 200 if (!bid) 201 return -ENODEV; 202 203 ret = device_attach(&bid->udev->dev); 204 if (ret < 0) { 205 dev_err(&bid->udev->dev, "rebind failed\n"); 206 return ret; 207 } 208 209 return count; 210 } 211 212 static DRIVER_ATTR_WO(rebind); 213 214 static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead) 215 { 216 struct stub_priv *priv, *tmp; 217 218 list_for_each_entry_safe(priv, tmp, listhead, list) { 219 list_del(&priv->list); 220 return priv; 221 } 222 223 return NULL; 224 } 225 226 static struct stub_priv *stub_priv_pop(struct stub_device *sdev) 227 { 228 unsigned long flags; 229 struct stub_priv *priv; 230 231 spin_lock_irqsave(&sdev->priv_lock, flags); 232 233 priv = stub_priv_pop_from_listhead(&sdev->priv_init); 234 if (priv) 235 goto done; 236 237 priv = stub_priv_pop_from_listhead(&sdev->priv_tx); 238 if (priv) 239 goto done; 240 241 priv = stub_priv_pop_from_listhead(&sdev->priv_free); 242 243 done: 244 spin_unlock_irqrestore(&sdev->priv_lock, flags); 245 246 return priv; 247 } 248 249 void stub_device_cleanup_urbs(struct stub_device *sdev) 250 { 251 struct stub_priv *priv; 252 struct urb *urb; 253 254 dev_dbg(&sdev->udev->dev, "free sdev %p\n", sdev); 255 256 while ((priv = stub_priv_pop(sdev))) { 257 urb = priv->urb; 258 dev_dbg(&sdev->udev->dev, "free urb %p\n", urb); 259 usb_kill_urb(urb); 260 261 kmem_cache_free(stub_priv_cache, priv); 262 263 kfree(urb->transfer_buffer); 264 urb->transfer_buffer = NULL; 265 266 kfree(urb->setup_packet); 267 urb->setup_packet = NULL; 268 269 usb_free_urb(urb); 270 } 271 } 272 273 static int __init usbip_host_init(void) 274 { 275 int ret; 276 277 init_busid_table(); 278 279 stub_priv_cache = KMEM_CACHE(stub_priv, SLAB_HWCACHE_ALIGN); 280 if (!stub_priv_cache) { 281 pr_err("kmem_cache_create failed\n"); 282 return -ENOMEM; 283 } 284 285 ret = usb_register_device_driver(&stub_driver, THIS_MODULE); 286 if (ret) { 287 pr_err("usb_register failed %d\n", ret); 288 goto err_usb_register; 289 } 290 291 ret = driver_create_file(&stub_driver.drvwrap.driver, 292 &driver_attr_match_busid); 293 if (ret) { 294 pr_err("driver_create_file failed\n"); 295 goto err_create_file; 296 } 297 298 ret = driver_create_file(&stub_driver.drvwrap.driver, 299 &driver_attr_rebind); 300 if (ret) { 301 pr_err("driver_create_file failed\n"); 302 goto err_create_file; 303 } 304 305 pr_info(DRIVER_DESC " v" USBIP_VERSION "\n"); 306 return ret; 307 308 err_create_file: 309 usb_deregister_device_driver(&stub_driver); 310 err_usb_register: 311 kmem_cache_destroy(stub_priv_cache); 312 return ret; 313 } 314 315 static void __exit usbip_host_exit(void) 316 { 317 driver_remove_file(&stub_driver.drvwrap.driver, 318 &driver_attr_match_busid); 319 320 driver_remove_file(&stub_driver.drvwrap.driver, 321 &driver_attr_rebind); 322 323 /* 324 * deregister() calls stub_disconnect() for all devices. Device 325 * specific data is cleared in stub_disconnect(). 326 */ 327 usb_deregister_device_driver(&stub_driver); 328 329 kmem_cache_destroy(stub_priv_cache); 330 } 331 332 module_init(usbip_host_init); 333 module_exit(usbip_host_exit); 334 335 MODULE_AUTHOR(DRIVER_AUTHOR); 336 MODULE_DESCRIPTION(DRIVER_DESC); 337 MODULE_LICENSE("GPL"); 338 MODULE_VERSION(USBIP_VERSION); 339