diff --git a/drivers/input/usb_kbd.c b/drivers/input/usb_kbd.c index 8c08aba..655d0c7 100644 --- a/drivers/input/usb_kbd.c +++ b/drivers/input/usb_kbd.c @@ -274,7 +274,7 @@ struct usb_kbd_pdata *data = container_of(poller, struct usb_kbd_pdata, poller); struct usb_device *usbdev = data->usbdev; - int diff, tout; + int diff, tout, ret; if (data->lock) return; @@ -284,7 +284,10 @@ goto exit; data->last_poll = get_time_ns(); - if (0 > data->do_poll(data)) { + ret = data->do_poll(data); + if (ret == -EAGAIN) + goto exit; + if (ret < 0) { /* exit and lock forever */ dev_err(&usbdev->dev, "usb_submit_int_msg() failed. Keyboard disconnect?\n"); diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index a3fb1e8..ce229f2 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -84,10 +84,25 @@ static int host_busnum = 1; +static inline int usb_host_acquire(struct usb_host *host) +{ + if (host->sem) + return -EAGAIN; + host->sem++; + return 0; +} + +static inline void usb_host_release(struct usb_host *host) +{ + if (host->sem > 0) + host->sem--; +} + int usb_register_host(struct usb_host *host) { list_add_tail(&host->list, &host_list); host->busnum = host_busnum++; + host->sem = 0; asynch_allowed = 1; return 0; } @@ -563,8 +578,17 @@ void *buffer, int transfer_len, int interval) { struct usb_host *host = dev->host; + int ret; - return host->submit_int_msg(dev, pipe, buffer, transfer_len, interval); + ret = usb_host_acquire(host); + if (ret) + return ret; + + ret = host->submit_int_msg(dev, pipe, buffer, transfer_len, interval); + + usb_host_release(host); + + return ret; } /* @@ -590,6 +614,10 @@ return -1; } + ret = usb_host_acquire(host); + if (ret) + return ret; + /* set setup command */ setup_packet->requesttype = requesttype; setup_packet->request = request; @@ -603,6 +631,9 @@ ret = host->submit_control_msg(dev, pipe, data, size, setup_packet, timeout); + + usb_host_release(host); + if (ret) return ret; @@ -623,8 +654,15 @@ if (len < 0) return -1; + ret = usb_host_acquire(host); + if (ret) + return ret; + dev->status = USB_ST_NOT_PROC; /* not yet processed */ ret = host->submit_bulk_msg(dev, pipe, data, len, timeout); + + usb_host_release(host); + if (ret) return ret; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b43b6c7..91c6d73 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -51,8 +51,6 @@ int periodic_schedules; struct QH *periodic_queue; uint32_t *periodic_list; - int sem; - struct device_d *usedby; }; struct int_queue { @@ -138,20 +136,6 @@ #define ehci_is_TDI() (ehci->flags & EHCI_HAS_TT) -static void inline ehci_reentrance_detect(struct ehci_priv *ehci, - struct usb_device *dev, - const char *fname) -{ - if (ehci->sem) - dev_err(&dev->dev, "%s: re-entrance %d (%s:%s)\n", - fname, - ehci->sem, - ehci->usedby->driver->name, - ehci->usedby->name); - ehci->sem++; - ehci->usedby = &dev->dev; -} - static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec) { uint32_t result; @@ -688,7 +672,7 @@ * root */ ehci_powerup_fixup(ehci); - mdelay_non_interruptible(50); + mdelay(50); ehci->portreset |= 1 << port; /* terminate the reset */ ehci_writel(status_reg, reg & ~EHCI_PS_PR); @@ -751,7 +735,7 @@ goto unknown; } - mdelay_non_interruptible(1); + mdelay(1); len = min3(srclen, (int)le16_to_cpu(req->length), length); if (srcptr != NULL && len > 0) memcpy(buffer, srcptr, len); @@ -888,7 +872,7 @@ ehci_writel(&ehci->hcor->or_configflag, cmd); /* unblock posted write */ cmd = ehci_readl(&ehci->hcor->or_usbcmd); - mdelay_non_interruptible(5); + mdelay(5); ehci->rootdev = 0; @@ -904,18 +888,12 @@ { struct usb_host *host = dev->host; struct ehci_priv *ehci = to_ehci(host); - int ret; - - ehci_reentrance_detect(ehci, dev, __func__); if (usb_pipetype(pipe) != PIPE_BULK) { dev_dbg(ehci->dev, "non-bulk pipe (type=%lu)", usb_pipetype(pipe)); - ehci->sem--; return -1; } - ret = ehci_submit_async(dev, pipe, buffer, length, NULL); - ehci->sem--; - return ret; + return ehci_submit_async(dev, pipe, buffer, length, NULL); } static int @@ -924,9 +902,6 @@ { struct usb_host *host = dev->host; struct ehci_priv *ehci = to_ehci(host); - int ret; - - ehci_reentrance_detect(ehci, dev, __func__); if (usb_pipetype(pipe) != PIPE_CONTROL) { dev_dbg(ehci->dev, "non-control pipe (type=%lu)", usb_pipetype(pipe)); @@ -936,13 +911,9 @@ if (usb_pipedevice(pipe) == ehci->rootdev) { if (ehci->rootdev == 0) dev->speed = USB_SPEED_HIGH; - ret = ehci_submit_root(dev, pipe, buffer, length, setup); - ehci->sem--; - return ret; + return ehci_submit_root(dev, pipe, buffer, length, setup); } - ret = ehci_submit_async(dev, pipe, buffer, length, setup); - ehci->sem--; - return ret; + return ehci_submit_async(dev, pipe, buffer, length, setup); } static int @@ -983,7 +954,9 @@ printf("EHCI failed: timeout when enabling periodic list\n"); return -ETIMEDOUT; } - mdelay_non_interruptible(1); + + mdelay(1); + return 0; } @@ -1265,8 +1238,6 @@ void *backbuffer; int result = 0, ret; - ehci_reentrance_detect(ehci, dev, __func__); - dev_dbg(ehci->dev, "dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d", dev, pipe, buffer, length, interval); @@ -1274,10 +1245,8 @@ DMA_BIDIRECTIONAL); queue = ehci_create_int_queue(dev, pipe, 1, length, buffer, interval); - if (!queue) { - ehci->sem--; + if (!queue) return -EINVAL; - } start = get_time_ns(); while ((backbuffer = ehci_poll_int_queue(dev, queue)) == NULL) @@ -1303,7 +1272,6 @@ ret = ehci_destroy_int_queue(dev, queue); if (!result) result = ret; - ehci->sem--; return result; } diff --git a/include/usb/usb.h b/include/usb/usb.h index 8f3ce2a..aedc527 100644 --- a/include/usb/usb.h +++ b/include/usb/usb.h @@ -152,6 +152,7 @@ struct device_d *hw_dev; int busnum; struct usb_device *root_dev; + int sem; }; int usb_register_host(struct usb_host *);