summaryrefslogtreecommitdiffstats
path: root/drivers/usb/uhci.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-07-28 23:18:56 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-07-28 23:18:56 +0000
commit4d657aa39d5bcae60c2c11bf8fb66692ddd1c9e7 (patch)
tree30f3b08741a4d4b98b16bd99ea2757ff715d1c11 /drivers/usb/uhci.c
parenteed6b7c84cc33f229f6fecd884d9a22af5bec514 (diff)
Merge with 2.4.0-test5 final.
Diffstat (limited to 'drivers/usb/uhci.c')
-rw-r--r--drivers/usb/uhci.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/drivers/usb/uhci.c b/drivers/usb/uhci.c
index a3d8d3d42..31be1c0e2 100644
--- a/drivers/usb/uhci.c
+++ b/drivers/usb/uhci.c
@@ -1296,6 +1296,7 @@ static int uhci_submit_urb(struct urb *urb)
struct uhci *uhci;
unsigned long flags;
struct urb *u;
+ int bustime;
if (!urb)
return -EINVAL;
@@ -1325,13 +1326,40 @@ static int uhci_submit_urb(struct urb *urb)
ret = uhci_submit_control(urb);
break;
case PIPE_INTERRUPT:
- ret = uhci_submit_interrupt(urb);
+ if (urb->bandwidth == 0) { /* not yet checked/allocated */
+ bustime = usb_check_bandwidth (urb->dev, urb);
+ if (bustime < 0)
+ ret = bustime;
+ else {
+ ret = uhci_submit_interrupt(urb);
+ if (ret == -EINPROGRESS)
+ usb_claim_bandwidth (urb->dev, urb, bustime, 0);
+ }
+ } else { /* bandwidth is already set */
+ ret = uhci_submit_interrupt(urb);
+ }
break;
case PIPE_BULK:
ret = uhci_submit_bulk(urb, u);
break;
case PIPE_ISOCHRONOUS:
- ret = uhci_submit_isochronous(urb);
+ if (urb->bandwidth == 0) { /* not yet checked/allocated */
+ if (urb->number_of_packets <= 0) {
+ ret = -EINVAL;
+ break;
+ }
+ bustime = usb_check_bandwidth (urb->dev, urb);
+ if (bustime < 0) {
+ ret = bustime;
+ break;
+ }
+
+ ret = uhci_submit_isochronous(urb);
+ if (ret == -EINPROGRESS)
+ usb_claim_bandwidth (urb->dev, urb, bustime, 1);
+ } else { /* bandwidth is already set */
+ ret = uhci_submit_isochronous(urb);
+ }
break;
}
@@ -1387,6 +1415,10 @@ static void uhci_transfer_result(struct urb *urb)
case PIPE_CONTROL:
case PIPE_BULK:
case PIPE_ISOCHRONOUS:
+ /* Release bandwidth for Interrupt or Isoc. transfers */
+ /* Spinlock needed ? */
+ if (urb->bandwidth)
+ usb_release_bandwidth (urb->dev, urb, 1);
uhci_unlink_generic(urb);
break;
case PIPE_INTERRUPT:
@@ -1394,8 +1426,13 @@ static void uhci_transfer_result(struct urb *urb)
urb->complete(urb);
if (urb->interval)
uhci_reset_interrupt(urb);
- else
+ else {
+ /* Release bandwidth for Interrupt or Isoc. transfers */
+ /* Spinlock needed ? */
+ if (urb->bandwidth)
+ usb_release_bandwidth (urb->dev, urb, 0);
uhci_unlink_generic(urb);
+ }
return; /* <-- Note the return */
}
@@ -1476,6 +1513,21 @@ static int uhci_unlink_urb(struct urb *urb)
if (usb_pipedevice(urb->pipe) == uhci->rh.devnum)
return rh_unlink_urb(urb);
+ /* Release bandwidth for Interrupt or Isoc. transfers */
+ /* Spinlock needed ? */
+ if (urb->bandwidth) {
+ switch (usb_pipetype(urb->pipe)) {
+ case PIPE_INTERRUPT:
+ usb_release_bandwidth (urb->dev, urb, 0);
+ break;
+ case PIPE_ISOCHRONOUS:
+ usb_release_bandwidth (urb->dev, urb, 1);
+ break;
+ default:
+ break;
+ }
+ }
+
if (urb->status == -EINPROGRESS) {
uhci_unlink_generic(urb);