staging: usbip: replace usbip_u{dbg,err,info} and printk with dev_ and pr_
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / usbip / stub_main.c
blobe9085d6639450d9835a4d6e86e1adad8f7e294ac
1 /*
2 * Copyright (C) 2003-2008 Takahiro Hirofuchi
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.
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.
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.
20 #include <linux/string.h>
22 #include "usbip_common.h"
23 #include "stub.h"
25 #define DRIVER_AUTHOR "Takahiro Hirofuchi"
26 #define DRIVER_DESC "USB/IP Host Driver"
28 /* stub_priv is allocated from stub_priv_cache */
29 struct kmem_cache *stub_priv_cache;
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.
36 #define MAX_BUSID 16
37 static struct bus_id_priv busid_table[MAX_BUSID];
38 static spinlock_t busid_table_lock;
40 int match_busid(const char *busid)
42 int i;
44 spin_lock(&busid_table_lock);
46 for (i = 0; i < MAX_BUSID; i++)
47 if (busid_table[i].name[0])
48 if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
49 /* already registerd */
50 spin_unlock(&busid_table_lock);
51 return 0;
54 spin_unlock(&busid_table_lock);
56 return 1;
59 struct bus_id_priv *get_busid_priv(const char *busid)
61 int i;
63 spin_lock(&busid_table_lock);
65 for (i = 0; i < MAX_BUSID; i++)
66 if (busid_table[i].name[0])
67 if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
68 /* already registerd */
69 spin_unlock(&busid_table_lock);
70 return &(busid_table[i]);
73 spin_unlock(&busid_table_lock);
75 return NULL;
78 static ssize_t show_match_busid(struct device_driver *drv, char *buf)
80 int i;
81 char *out = buf;
83 spin_lock(&busid_table_lock);
85 for (i = 0; i < MAX_BUSID; i++)
86 if (busid_table[i].name[0])
87 out += sprintf(out, "%s ", busid_table[i].name);
89 spin_unlock(&busid_table_lock);
91 out += sprintf(out, "\n");
93 return out - buf;
96 static int add_match_busid(char *busid)
98 int i;
100 if (!match_busid(busid))
101 return 0;
103 spin_lock(&busid_table_lock);
105 for (i = 0; i < MAX_BUSID; i++)
106 if (!busid_table[i].name[0]) {
107 strncpy(busid_table[i].name, busid, BUSID_SIZE);
108 if ((busid_table[i].status != STUB_BUSID_ALLOC) &&
109 (busid_table[i].status != STUB_BUSID_REMOV))
110 busid_table[i].status = STUB_BUSID_ADDED;
111 spin_unlock(&busid_table_lock);
112 return 0;
115 spin_unlock(&busid_table_lock);
117 return -1;
120 int del_match_busid(char *busid)
122 int i;
124 spin_lock(&busid_table_lock);
126 for (i = 0; i < MAX_BUSID; i++)
127 if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
128 /* found */
129 if (busid_table[i].status == STUB_BUSID_OTHER)
130 memset(busid_table[i].name, 0, BUSID_SIZE);
131 if ((busid_table[i].status != STUB_BUSID_OTHER) &&
132 (busid_table[i].status != STUB_BUSID_ADDED)) {
133 busid_table[i].status = STUB_BUSID_REMOV;
135 spin_unlock(&busid_table_lock);
136 return 0;
139 spin_unlock(&busid_table_lock);
141 return -1;
144 static void init_busid_table(void)
146 int i;
148 for (i = 0; i < MAX_BUSID; i++) {
149 memset(busid_table[i].name, 0, BUSID_SIZE);
150 busid_table[i].status = STUB_BUSID_OTHER;
151 busid_table[i].interf_count = 0;
152 busid_table[i].sdev = NULL;
153 busid_table[i].shutdown_busid = 0;
156 spin_lock_init(&busid_table_lock);
159 static ssize_t store_match_busid(struct device_driver *dev, const char *buf,
160 size_t count)
162 int len;
163 char busid[BUSID_SIZE];
165 if (count < 5)
166 return -EINVAL;
168 /* strnlen() does not include \0 */
169 len = strnlen(buf + 4, BUSID_SIZE);
171 /* busid needs to include \0 termination */
172 if (!(len < BUSID_SIZE))
173 return -EINVAL;
175 strncpy(busid, buf + 4, BUSID_SIZE);
177 if (!strncmp(buf, "add ", 4)) {
178 if (add_match_busid(busid) < 0)
179 return -ENOMEM;
180 else {
181 pr_debug("add busid %s\n", busid);
182 return count;
184 } else if (!strncmp(buf, "del ", 4)) {
185 if (del_match_busid(busid) < 0)
186 return -ENODEV;
187 else {
188 pr_debug("del busid %s\n", busid);
189 return count;
191 } else
192 return -EINVAL;
194 static DRIVER_ATTR(match_busid, S_IRUSR|S_IWUSR, show_match_busid,
195 store_match_busid);
197 static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead)
199 struct stub_priv *priv, *tmp;
201 list_for_each_entry_safe(priv, tmp, listhead, list) {
202 list_del(&priv->list);
203 return priv;
206 return NULL;
209 static struct stub_priv *stub_priv_pop(struct stub_device *sdev)
211 unsigned long flags;
212 struct stub_priv *priv;
214 spin_lock_irqsave(&sdev->priv_lock, flags);
216 priv = stub_priv_pop_from_listhead(&sdev->priv_init);
217 if (priv) {
218 spin_unlock_irqrestore(&sdev->priv_lock, flags);
219 return priv;
222 priv = stub_priv_pop_from_listhead(&sdev->priv_tx);
223 if (priv) {
224 spin_unlock_irqrestore(&sdev->priv_lock, flags);
225 return priv;
228 priv = stub_priv_pop_from_listhead(&sdev->priv_free);
229 if (priv) {
230 spin_unlock_irqrestore(&sdev->priv_lock, flags);
231 return priv;
234 spin_unlock_irqrestore(&sdev->priv_lock, flags);
235 return NULL;
238 void stub_device_cleanup_urbs(struct stub_device *sdev)
240 struct stub_priv *priv;
242 dev_dbg(&sdev->udev->dev, "free sdev %p\n", sdev);
244 while ((priv = stub_priv_pop(sdev))) {
245 struct urb *urb = priv->urb;
247 dev_dbg(&sdev->udev->dev, "free urb %p\n", urb);
248 usb_kill_urb(urb);
250 kmem_cache_free(stub_priv_cache, priv);
252 kfree(urb->transfer_buffer);
253 kfree(urb->setup_packet);
255 usb_free_urb(urb);
259 static int __init usb_stub_init(void)
261 int ret;
263 stub_priv_cache = kmem_cache_create("stub_priv",
264 sizeof(struct stub_priv), 0,
265 SLAB_HWCACHE_ALIGN, NULL);
267 if (!stub_priv_cache) {
268 pr_err("create stub_priv_cache error\n");
269 return -ENOMEM;
272 ret = usb_register(&stub_driver);
273 if (ret) {
274 pr_err("usb_register failed %d\n", ret);
275 goto error_usb_register;
278 pr_info(DRIVER_DESC " " USBIP_VERSION "\n");
280 init_busid_table();
282 ret = driver_create_file(&stub_driver.drvwrap.driver,
283 &driver_attr_match_busid);
285 if (ret) {
286 pr_err("create driver sysfs\n");
287 goto error_create_file;
290 return ret;
291 error_create_file:
292 usb_deregister(&stub_driver);
293 error_usb_register:
294 kmem_cache_destroy(stub_priv_cache);
295 return ret;
298 static void __exit usb_stub_exit(void)
300 driver_remove_file(&stub_driver.drvwrap.driver,
301 &driver_attr_match_busid);
304 * deregister() calls stub_disconnect() for all devices. Device
305 * specific data is cleared in stub_disconnect().
307 usb_deregister(&stub_driver);
309 kmem_cache_destroy(stub_priv_cache);
312 module_init(usb_stub_init);
313 module_exit(usb_stub_exit);
315 MODULE_AUTHOR(DRIVER_AUTHOR);
316 MODULE_DESCRIPTION(DRIVER_DESC);
317 MODULE_LICENSE("GPL");
318 MODULE_VERSION(USBIP_VERSION);