aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/message.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 17:40:30 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 17:40:30 -0400
commit1f9bd4c96a8e918a86e083706e0d3eb7f030b9a3 (patch)
treea840b35ca8c193cb0ec5579de3fac4e4e7f47f11 /drivers/usb/core/message.c
parent00463c1633b6d6a2178d2dc794c0a70ac2f9ce6b (diff)
parent7f38aa0f04259d37f26e1e906607f1ebb39c0c5c (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6: (129 commits) [PATCH] USB Storage: fix Rio Karma eject support build error USB: Airprime driver improvements to allow full speed EvDO transfers USB: remove OTG build warning USB: EHCI update VIA workaround USB: force root hub resume after power loss USB: ohci_usb can oops on shutdown USB: Dealias -110 code (more complete) USB: Remove unneeded void * casts in core files USB: u132-hcd: host controller driver for ELAN U132 adapter USB: ftdi-elan: client driver for ELAN Uxxx adapters usb serial: support Alcor Micro Corp. USB 2.0 TO RS-232 through pl2303 driver USB: Moschip 7840 USB-Serial Driver USB: add PlayStation 2 Trance Vibrator driver USB: Add ADU support for Ontrak ADU devices aircable: fix printk format warnings Add AIRcable USB Bluetooth Dongle Driver cypress_m8: implement graceful failure handling cypress_m8: improve control endpoint error handling cypress_m8: use usb_fill_int_urb where appropriate cypress_m8: use appropriate URB polling interval ...
Diffstat (limited to 'drivers/usb/core/message.c')
-rw-r--r--drivers/usb/core/message.c148
1 files changed, 98 insertions, 50 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 4cc8d3e67db7..85b1cd18336f 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -23,59 +23,44 @@ static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs)
23} 23}
24 24
25 25
26static void timeout_kill(unsigned long data) 26/*
27{ 27 * Starts urb and waits for completion or timeout. Note that this call
28 struct urb *urb = (struct urb *) data; 28 * is NOT interruptible. Many device driver i/o requests should be
29 29 * interruptible and therefore these drivers should implement their
30 usb_unlink_urb(urb); 30 * own interruptible routines.
31} 31 */
32 32static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
33// Starts urb and waits for completion or timeout
34// note that this call is NOT interruptible, while
35// many device driver i/o requests should be interruptible
36static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
37{ 33{
38 struct completion done; 34 struct completion done;
39 struct timer_list timer; 35 unsigned long expire;
40 int status; 36 int status;
41 37
42 init_completion(&done); 38 init_completion(&done);
43 urb->context = &done; 39 urb->context = &done;
44 urb->actual_length = 0; 40 urb->actual_length = 0;
45 status = usb_submit_urb(urb, GFP_NOIO); 41 status = usb_submit_urb(urb, GFP_NOIO);
46 42 if (unlikely(status))
47 if (status == 0) { 43 goto out;
48 if (timeout > 0) { 44
49 init_timer(&timer); 45 expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
50 timer.expires = jiffies + msecs_to_jiffies(timeout); 46 if (!wait_for_completion_timeout(&done, expire)) {
51 timer.data = (unsigned long)urb; 47
52 timer.function = timeout_kill; 48 dev_dbg(&urb->dev->dev,
53 /* grr. timeout _should_ include submit delays. */ 49 "%s timed out on ep%d%s len=%d/%d\n",
54 add_timer(&timer); 50 current->comm,
55 } 51 usb_pipeendpoint(urb->pipe),
56 wait_for_completion(&done); 52 usb_pipein(urb->pipe) ? "in" : "out",
53 urb->actual_length,
54 urb->transfer_buffer_length);
55
56 usb_kill_urb(urb);
57 status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;
58 } else
57 status = urb->status; 59 status = urb->status;
58 /* note: HCDs return ETIMEDOUT for other reasons too */ 60out:
59 if (status == -ECONNRESET) {
60 dev_dbg(&urb->dev->dev,
61 "%s timed out on ep%d%s len=%d/%d\n",
62 current->comm,
63 usb_pipeendpoint(urb->pipe),
64 usb_pipein(urb->pipe) ? "in" : "out",
65 urb->actual_length,
66 urb->transfer_buffer_length
67 );
68 if (urb->actual_length > 0)
69 status = 0;
70 else
71 status = -ETIMEDOUT;
72 }
73 if (timeout > 0)
74 del_timer_sync(&timer);
75 }
76
77 if (actual_length) 61 if (actual_length)
78 *actual_length = urb->actual_length; 62 *actual_length = urb->actual_length;
63
79 usb_free_urb(urb); 64 usb_free_urb(urb);
80 return status; 65 return status;
81} 66}
@@ -263,7 +248,7 @@ static void sg_clean (struct usb_sg_request *io)
263 248
264static void sg_complete (struct urb *urb, struct pt_regs *regs) 249static void sg_complete (struct urb *urb, struct pt_regs *regs)
265{ 250{
266 struct usb_sg_request *io = (struct usb_sg_request *) urb->context; 251 struct usb_sg_request *io = urb->context;
267 252
268 spin_lock (&io->lock); 253 spin_lock (&io->lock);
269 254
@@ -999,8 +984,8 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
999 ep = dev->ep_in[epnum]; 984 ep = dev->ep_in[epnum];
1000 dev->ep_in[epnum] = NULL; 985 dev->ep_in[epnum] = NULL;
1001 } 986 }
1002 if (ep && dev->bus && dev->bus->op && dev->bus->op->disable) 987 if (ep && dev->bus)
1003 dev->bus->op->disable(dev, ep); 988 usb_hcd_endpoint_disable(dev, ep);
1004} 989}
1005 990
1006/** 991/**
@@ -1381,9 +1366,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
1381 if (cp && configuration == 0) 1366 if (cp && configuration == 0)
1382 dev_warn(&dev->dev, "config 0 descriptor??\n"); 1367 dev_warn(&dev->dev, "config 0 descriptor??\n");
1383 1368
1384 if (dev->state == USB_STATE_SUSPENDED)
1385 return -EHOSTUNREACH;
1386
1387 /* Allocate memory for new interfaces before doing anything else, 1369 /* Allocate memory for new interfaces before doing anything else,
1388 * so that if we run out then nothing will have changed. */ 1370 * so that if we run out then nothing will have changed. */
1389 n = nintf = 0; 1371 n = nintf = 0;
@@ -1418,6 +1400,11 @@ free_interfaces:
1418 configuration, -i); 1400 configuration, -i);
1419 } 1401 }
1420 1402
1403 /* Wake up the device so we can send it the Set-Config request */
1404 ret = usb_autoresume_device(dev, 1);
1405 if (ret)
1406 goto free_interfaces;
1407
1421 /* if it's already configured, clear out old state first. 1408 /* if it's already configured, clear out old state first.
1422 * getting rid of old interfaces means unbinding their drivers. 1409 * getting rid of old interfaces means unbinding their drivers.
1423 */ 1410 */
@@ -1437,6 +1424,7 @@ free_interfaces:
1437 dev->actconfig = cp; 1424 dev->actconfig = cp;
1438 if (!cp) { 1425 if (!cp) {
1439 usb_set_device_state(dev, USB_STATE_ADDRESS); 1426 usb_set_device_state(dev, USB_STATE_ADDRESS);
1427 usb_autosuspend_device(dev, 1);
1440 goto free_interfaces; 1428 goto free_interfaces;
1441 } 1429 }
1442 usb_set_device_state(dev, USB_STATE_CONFIGURED); 1430 usb_set_device_state(dev, USB_STATE_CONFIGURED);
@@ -1505,8 +1493,68 @@ free_interfaces:
1505 usb_create_sysfs_intf_files (intf); 1493 usb_create_sysfs_intf_files (intf);
1506 } 1494 }
1507 1495
1496 usb_autosuspend_device(dev, 1);
1497 return 0;
1498}
1499
1500struct set_config_request {
1501 struct usb_device *udev;
1502 int config;
1503 struct work_struct work;
1504};
1505
1506/* Worker routine for usb_driver_set_configuration() */
1507static void driver_set_config_work(void *_req)
1508{
1509 struct set_config_request *req = _req;
1510
1511 usb_lock_device(req->udev);
1512 usb_set_configuration(req->udev, req->config);
1513 usb_unlock_device(req->udev);
1514 usb_put_dev(req->udev);
1515 kfree(req);
1516}
1517
1518/**
1519 * usb_driver_set_configuration - Provide a way for drivers to change device configurations
1520 * @udev: the device whose configuration is being updated
1521 * @config: the configuration being chosen.
1522 * Context: In process context, must be able to sleep
1523 *
1524 * Device interface drivers are not allowed to change device configurations.
1525 * This is because changing configurations will destroy the interface the
1526 * driver is bound to and create new ones; it would be like a floppy-disk
1527 * driver telling the computer to replace the floppy-disk drive with a
1528 * tape drive!
1529 *
1530 * Still, in certain specialized circumstances the need may arise. This
1531 * routine gets around the normal restrictions by using a work thread to
1532 * submit the change-config request.
1533 *
1534 * Returns 0 if the request was succesfully queued, error code otherwise.
1535 * The caller has no way to know whether the queued request will eventually
1536 * succeed.
1537 */
1538int usb_driver_set_configuration(struct usb_device *udev, int config)
1539{
1540 struct set_config_request *req;
1541
1542 req = kmalloc(sizeof(*req), GFP_KERNEL);
1543 if (!req)
1544 return -ENOMEM;
1545 req->udev = udev;
1546 req->config = config;
1547 INIT_WORK(&req->work, driver_set_config_work, req);
1548
1549 usb_get_dev(udev);
1550 if (!schedule_work(&req->work)) {
1551 usb_put_dev(udev);
1552 kfree(req);
1553 return -EINVAL;
1554 }
1508 return 0; 1555 return 0;
1509} 1556}
1557EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
1510 1558
1511// synchronous request completion model 1559// synchronous request completion model
1512EXPORT_SYMBOL(usb_control_msg); 1560EXPORT_SYMBOL(usb_control_msg);