USB: add urb->unlinked field
This patch (as970) adds a new urb->unlinked field, which is used to store the status of unlinked URBs since we can't use urb->status for that purpose any more. To help simplify the HCDs, usbcore will check urb->unlinked before calling the completion handler; if the value is set it will automatically override the status reported by the HCD. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: David Brownell <david-b@pacbell.net> CC: Olav Kongas <ok@artecdesign.ee> CC: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> CC: Tony Olech <tony.olech@elandigitalsystems.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Родитель
b0d9efba3e
Коммит
eb23105462
|
@ -532,8 +532,7 @@ error:
|
|||
|
||||
/* any errors get returned through the urb completion */
|
||||
spin_lock_irq(&hcd_root_hub_lock);
|
||||
if (urb->status == -EINPROGRESS)
|
||||
urb->status = status;
|
||||
urb->status = status;
|
||||
usb_hcd_unlink_urb_from_ep(hcd, urb);
|
||||
|
||||
/* This peculiar use of spinlocks echoes what real HC drivers do.
|
||||
|
@ -1024,6 +1023,7 @@ int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb)
|
|||
switch (hcd->state) {
|
||||
case HC_STATE_RUNNING:
|
||||
case HC_STATE_RESUMING:
|
||||
urb->unlinked = 0;
|
||||
list_add_tail(&urb->urb_list, &urb->ep->urb_list);
|
||||
break;
|
||||
default:
|
||||
|
@ -1071,9 +1071,9 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
|
|||
/* Any status except -EINPROGRESS means something already started to
|
||||
* unlink this URB from the hardware. So there's no more work to do.
|
||||
*/
|
||||
if (urb->status != -EINPROGRESS)
|
||||
if (urb->unlinked)
|
||||
return -EBUSY;
|
||||
urb->status = status;
|
||||
urb->unlinked = status;
|
||||
|
||||
/* IRQ setup can easily be broken so that USB controllers
|
||||
* never get completion IRQs ... maybe even the ones we need to
|
||||
|
@ -1259,6 +1259,10 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
|
|||
* (and is done using urb->hcpriv). It also released all HCD locks;
|
||||
* the device driver won't cause problems if it frees, modifies,
|
||||
* or resubmits this URB.
|
||||
*
|
||||
* If @urb was unlinked, the value of @urb->status will be overridden by
|
||||
* @urb->unlinked. Erroneous short transfers are detected in case
|
||||
* the HCD hasn't checked for them.
|
||||
*/
|
||||
void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
|
||||
{
|
||||
|
@ -1266,7 +1270,9 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
|
|||
usbmon_urb_complete (&hcd->self, urb);
|
||||
usb_unanchor_urb(urb);
|
||||
urb->hcpriv = NULL;
|
||||
if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
|
||||
if (unlikely(urb->unlinked))
|
||||
urb->status = urb->unlinked;
|
||||
else if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
|
||||
urb->actual_length < urb->transfer_buffer_length &&
|
||||
!urb->status))
|
||||
urb->status = -EREMOTEIO;
|
||||
|
@ -1305,8 +1311,7 @@ rescan:
|
|||
list_for_each_entry (urb, &ep->urb_list, urb_list) {
|
||||
int is_in;
|
||||
|
||||
/* the urb may already have been unlinked */
|
||||
if (urb->status != -EINPROGRESS)
|
||||
if (urb->unlinked)
|
||||
continue;
|
||||
usb_get_urb (urb);
|
||||
is_in = usb_urb_dir_in(urb);
|
||||
|
|
|
@ -1029,8 +1029,7 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
|||
static void maybe_set_status (struct urb *urb, int status)
|
||||
{
|
||||
spin_lock (&urb->lock);
|
||||
if (urb->status == -EINPROGRESS)
|
||||
urb->status = status;
|
||||
urb->status = status;
|
||||
spin_unlock (&urb->lock);
|
||||
}
|
||||
|
||||
|
@ -1257,10 +1256,9 @@ restart:
|
|||
int type;
|
||||
|
||||
urb = urbp->urb;
|
||||
if (urb->status != -EINPROGRESS) {
|
||||
/* likely it was just unlinked */
|
||||
if (urb->unlinked)
|
||||
goto return_urb;
|
||||
} else if (dum->rh_state != DUMMY_RH_RUNNING)
|
||||
else if (dum->rh_state != DUMMY_RH_RUNNING)
|
||||
continue;
|
||||
type = usb_pipetype (urb->pipe);
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ static void qtd_copy_status (
|
|||
urb->actual_length += length - QTD_LENGTH (token);
|
||||
|
||||
/* don't modify error codes */
|
||||
if (unlikely (urb->status != -EINPROGRESS))
|
||||
if (unlikely(urb->unlinked))
|
||||
return;
|
||||
|
||||
/* force cleanup after short read; not always an error */
|
||||
|
@ -232,21 +232,14 @@ __acquires(ehci->lock)
|
|||
}
|
||||
|
||||
spin_lock (&urb->lock);
|
||||
switch (urb->status) {
|
||||
case -EINPROGRESS: /* success */
|
||||
urb->status = 0;
|
||||
default: /* fault */
|
||||
COUNT (ehci->stats.complete);
|
||||
break;
|
||||
case -EREMOTEIO: /* fault or normal */
|
||||
if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
|
||||
if (unlikely(urb->unlinked)) {
|
||||
COUNT(ehci->stats.unlink);
|
||||
} else {
|
||||
if (likely(urb->status == -EINPROGRESS ||
|
||||
(urb->status == -EREMOTEIO &&
|
||||
!(urb->transfer_flags & URB_SHORT_NOT_OK))))
|
||||
urb->status = 0;
|
||||
COUNT (ehci->stats.complete);
|
||||
break;
|
||||
case -ECONNRESET: /* canceled */
|
||||
case -ENOENT:
|
||||
COUNT (ehci->stats.unlink);
|
||||
break;
|
||||
COUNT(ehci->stats.complete);
|
||||
}
|
||||
spin_unlock (&urb->lock);
|
||||
|
||||
|
@ -364,7 +357,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
|||
* for the urb faulted (including short read) or
|
||||
* its urb was canceled. we may patch qh or qtds.
|
||||
*/
|
||||
if (likely (urb->status == -EINPROGRESS))
|
||||
if (likely(urb->status == -EINPROGRESS &&
|
||||
!urb->unlinked))
|
||||
continue;
|
||||
|
||||
/* issue status after short control reads */
|
||||
|
@ -395,7 +389,8 @@ halt:
|
|||
spin_lock (&urb->lock);
|
||||
qtd_copy_status (ehci, urb, qtd->length, token);
|
||||
if (unlikely(urb->status == -EREMOTEIO)) {
|
||||
do_status = usb_pipecontrol(urb->pipe);
|
||||
do_status = (!urb->unlinked &&
|
||||
usb_pipecontrol(urb->pipe));
|
||||
urb->status = 0;
|
||||
}
|
||||
spin_unlock (&urb->lock);
|
||||
|
|
|
@ -455,11 +455,10 @@ static void postproc_atl_queue(struct isp116x *isp116x)
|
|||
done:
|
||||
if (status != -EINPROGRESS) {
|
||||
spin_lock(&urb->lock);
|
||||
if (urb->status == -EINPROGRESS)
|
||||
urb->status = status;
|
||||
urb->status = status;
|
||||
spin_unlock(&urb->lock);
|
||||
}
|
||||
if (urb->status != -EINPROGRESS)
|
||||
if (urb->status != -EINPROGRESS || urb->unlinked)
|
||||
finish_request(isp116x, ep, urb);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -758,8 +758,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
|
|||
cc = TD_CC_NOERROR;
|
||||
if (cc != TD_CC_NOERROR && cc < 0x0E) {
|
||||
spin_lock (&urb->lock);
|
||||
if (urb->status == -EINPROGRESS)
|
||||
urb->status = cc_to_error [cc];
|
||||
urb->status = cc_to_error[cc];
|
||||
spin_unlock (&urb->lock);
|
||||
}
|
||||
|
||||
|
@ -972,7 +971,7 @@ rescan_this:
|
|||
urb = td->urb;
|
||||
urb_priv = td->urb->hcpriv;
|
||||
|
||||
if (urb->status == -EINPROGRESS) {
|
||||
if (!urb->unlinked) {
|
||||
prev = &td->hwNextTD;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1118,7 +1118,7 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock)
|
|||
r8a66597->timeout_map &= ~(1 << pipenum);
|
||||
|
||||
if (likely(td)) {
|
||||
if (td->set_address && urb->status != 0)
|
||||
if (td->set_address && (urb->status != 0 || urb->unlinked))
|
||||
r8a66597->address_map &= ~(1 << urb->setup_packet[2]);
|
||||
|
||||
pipe_toggle_save(r8a66597, td->pipe, urb);
|
||||
|
@ -1225,8 +1225,7 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
|
|||
}
|
||||
|
||||
if (finish && pipenum != 0) {
|
||||
if (td->urb->status == -EINPROGRESS)
|
||||
td->urb->status = status;
|
||||
td->urb->status = status;
|
||||
finish_request(r8a66597, td, pipenum, urb);
|
||||
}
|
||||
}
|
||||
|
@ -1308,32 +1307,24 @@ static void check_next_phase(struct r8a66597 *r8a66597)
|
|||
switch (td->type) {
|
||||
case USB_PID_IN:
|
||||
case USB_PID_OUT:
|
||||
if (urb->status != -EINPROGRESS) {
|
||||
finish = 1;
|
||||
break;
|
||||
}
|
||||
if (check_transfer_finish(td, urb))
|
||||
td->type = USB_PID_ACK;
|
||||
break;
|
||||
case USB_PID_SETUP:
|
||||
if (urb->status != -EINPROGRESS)
|
||||
finish = 1;
|
||||
else if (urb->transfer_buffer_length == urb->actual_length) {
|
||||
if (urb->transfer_buffer_length == urb->actual_length)
|
||||
td->type = USB_PID_ACK;
|
||||
urb->status = 0;
|
||||
} else if (usb_pipeout(urb->pipe))
|
||||
else if (usb_pipeout(urb->pipe))
|
||||
td->type = USB_PID_OUT;
|
||||
else
|
||||
td->type = USB_PID_IN;
|
||||
break;
|
||||
case USB_PID_ACK:
|
||||
finish = 1;
|
||||
if (urb->status == -EINPROGRESS)
|
||||
urb->status = 0;
|
||||
urb->status = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (finish)
|
||||
if (finish || urb->unlinked)
|
||||
finish_request(r8a66597, td, 0, urb);
|
||||
else
|
||||
start_transfer(r8a66597, td);
|
||||
|
@ -1418,8 +1409,7 @@ static void irq_pipe_empty(struct r8a66597 *r8a66597)
|
|||
if ((tmp & INBUFM) == 0) {
|
||||
disable_irq_empty(r8a66597, pipenum);
|
||||
pipe_irq_disable(r8a66597, pipenum);
|
||||
if (td->urb->status == -EINPROGRESS)
|
||||
td->urb->status = 0;
|
||||
td->urb->status = 0;
|
||||
finish_request(r8a66597, td, pipenum, td->urb);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -436,8 +436,7 @@ static void finish_request(
|
|||
ep->nextpid = USB_PID_SETUP;
|
||||
|
||||
spin_lock(&urb->lock);
|
||||
if (urb->status == -EINPROGRESS)
|
||||
urb->status = status;
|
||||
urb->status = status;
|
||||
spin_unlock(&urb->lock);
|
||||
|
||||
usb_hcd_unlink_urb_from_ep(sl811_to_hcd(sl811), urb);
|
||||
|
@ -598,7 +597,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank)
|
|||
bank, status, ep, urbstat);
|
||||
}
|
||||
|
||||
if (urb && (urbstat != -EINPROGRESS || urb->status != -EINPROGRESS))
|
||||
if (urb && (urbstat != -EINPROGRESS || urb->unlinked))
|
||||
finish_request(sl811, ep, urb, urbstat);
|
||||
}
|
||||
|
||||
|
|
|
@ -645,12 +645,12 @@ static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
|
||||
return;
|
||||
} else if (u132->going > 0) {
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed urb="
|
||||
"%p status=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed "
|
||||
"urb=%p\n", urb);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
|
||||
return;
|
||||
} else if (urb->status == -EINPROGRESS) {
|
||||
} else if (!urb->unlinked) {
|
||||
struct u132_ring *ring = endp->ring;
|
||||
u8 *u = urb->transfer_buffer + urb->actual_length;
|
||||
u8 *b = buf;
|
||||
|
@ -716,8 +716,8 @@ static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
|
||||
"s=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
|
||||
"unlinked=%d\n", urb, urb->unlinked);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, urb->status);
|
||||
return;
|
||||
|
@ -744,12 +744,12 @@ static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
|
||||
return;
|
||||
} else if (u132->going > 0) {
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed urb="
|
||||
"%p status=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed "
|
||||
"urb=%p\n", urb);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
|
||||
return;
|
||||
} else if (urb->status == -EINPROGRESS) {
|
||||
} else if (!urb->unlinked) {
|
||||
struct u132_ring *ring = endp->ring;
|
||||
urb->actual_length += len;
|
||||
endp->toggle_bits = toggle_bits;
|
||||
|
@ -768,8 +768,8 @@ static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
|
||||
"s=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
|
||||
"unlinked=%d\n", urb, urb->unlinked);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, urb->status);
|
||||
return;
|
||||
|
@ -797,12 +797,12 @@ static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
|
||||
return;
|
||||
} else if (u132->going > 0) {
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed urb="
|
||||
"%p status=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed "
|
||||
"urb=%p\n", urb);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
|
||||
return;
|
||||
} else if (urb->status == -EINPROGRESS) {
|
||||
} else if (!urb->unlinked) {
|
||||
struct u132_ring *ring = endp->ring;
|
||||
u8 *u = urb->transfer_buffer + urb->actual_length;
|
||||
u8 *b = buf;
|
||||
|
@ -871,8 +871,8 @@ static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
|
||||
"s=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
|
||||
"unlinked=%d\n", urb, urb->unlinked);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, urb->status);
|
||||
return;
|
||||
|
@ -898,18 +898,18 @@ static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
|
||||
return;
|
||||
} else if (u132->going > 0) {
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed urb="
|
||||
"%p status=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed "
|
||||
"urb=%p\n", urb);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
|
||||
return;
|
||||
} else if (urb->status == -EINPROGRESS) {
|
||||
} else if (!urb->unlinked) {
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, 0);
|
||||
return;
|
||||
} else {
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
|
||||
"s=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
|
||||
"unlinked=%d\n", urb, urb->unlinked);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, urb->status);
|
||||
return;
|
||||
|
@ -936,12 +936,12 @@ static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
|
||||
return;
|
||||
} else if (u132->going > 0) {
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed urb="
|
||||
"%p status=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed "
|
||||
"urb=%p\n", urb);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
|
||||
return;
|
||||
} else if (urb->status == -EINPROGRESS) {
|
||||
} else if (!urb->unlinked) {
|
||||
struct u132_ring *ring = endp->ring;
|
||||
u8 *u = urb->transfer_buffer;
|
||||
u8 *b = buf;
|
||||
|
@ -980,8 +980,8 @@ static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
|
||||
"s=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
|
||||
"unlinked=%d\n", urb, urb->unlinked);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, urb->status);
|
||||
return;
|
||||
|
@ -1007,18 +1007,18 @@ static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
|
||||
return;
|
||||
} else if (u132->going > 0) {
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed urb="
|
||||
"%p status=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed "
|
||||
"urb=%p\n", urb);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
|
||||
return;
|
||||
} else if (urb->status == -EINPROGRESS) {
|
||||
} else if (!urb->unlinked) {
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, 0);
|
||||
return;
|
||||
} else {
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
|
||||
"s=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
|
||||
"unlinked=%d\n", urb, urb->unlinked);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, urb->status);
|
||||
return;
|
||||
|
@ -1045,12 +1045,12 @@ static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
|
||||
return;
|
||||
} else if (u132->going > 0) {
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed urb="
|
||||
"%p status=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed "
|
||||
"urb=%p\n", urb);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
|
||||
return;
|
||||
} else if (urb->status == -EINPROGRESS) {
|
||||
} else if (!urb->unlinked) {
|
||||
if (usb_pipein(urb->pipe)) {
|
||||
int retval;
|
||||
struct u132_ring *ring = endp->ring;
|
||||
|
@ -1077,8 +1077,8 @@ static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
|
||||
"s=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
|
||||
"unlinked=%d\n", urb, urb->unlinked);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, urb->status);
|
||||
return;
|
||||
|
@ -1106,20 +1106,20 @@ static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
|
||||
return;
|
||||
} else if (u132->going > 0) {
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed urb="
|
||||
"%p status=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed "
|
||||
"urb=%p\n", urb);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
|
||||
return;
|
||||
} else if (urb->status == -EINPROGRESS) {
|
||||
} else if (!urb->unlinked) {
|
||||
u132->addr[0].address = 0;
|
||||
endp->usb_addr = udev->usb_addr;
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, 0);
|
||||
return;
|
||||
} else {
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
|
||||
"s=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
|
||||
"unlinked=%d\n", urb, urb->unlinked);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, urb->status);
|
||||
return;
|
||||
|
@ -1145,12 +1145,12 @@ static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
|
||||
return;
|
||||
} else if (u132->going > 0) {
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed urb="
|
||||
"%p status=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed "
|
||||
"urb=%p\n", urb);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
|
||||
return;
|
||||
} else if (urb->status == -EINPROGRESS) {
|
||||
} else if (!urb->unlinked) {
|
||||
int retval;
|
||||
struct u132_ring *ring = endp->ring;
|
||||
up(&u132->scheduler_lock);
|
||||
|
@ -1162,8 +1162,8 @@ static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, retval);
|
||||
return;
|
||||
} else {
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
|
||||
"s=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
|
||||
"unlinked=%d\n", urb, urb->unlinked);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, urb->status);
|
||||
return;
|
||||
|
@ -1189,18 +1189,18 @@ static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
|
||||
return;
|
||||
} else if (u132->going > 0) {
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed urb="
|
||||
"%p status=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed "
|
||||
"urb=%p\n", urb);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
|
||||
return;
|
||||
} else if (urb->status == -EINPROGRESS) {
|
||||
} else if (!urb->unlinked) {
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, 0);
|
||||
return;
|
||||
} else {
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
|
||||
"s=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
|
||||
"unlinked=%d\n", urb, urb->unlinked);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, urb->status);
|
||||
return;
|
||||
|
@ -1227,12 +1227,12 @@ static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
|
||||
return;
|
||||
} else if (u132->going > 0) {
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed urb="
|
||||
"%p status=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed "
|
||||
"urb=%p\n", urb);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
|
||||
return;
|
||||
} else if (urb->status == -EINPROGRESS) {
|
||||
} else if (!urb->unlinked) {
|
||||
int retval;
|
||||
struct u132_ring *ring = endp->ring;
|
||||
u8 *u = urb->transfer_buffer;
|
||||
|
@ -1251,8 +1251,8 @@ static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, retval);
|
||||
return;
|
||||
} else {
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
|
||||
"s=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
|
||||
"unlinked=%d\n", urb, urb->unlinked);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, urb->status);
|
||||
return;
|
||||
|
@ -1279,12 +1279,12 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
|
||||
return;
|
||||
} else if (u132->going > 0) {
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed urb="
|
||||
"%p status=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed "
|
||||
"urb=%p\n", urb);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
|
||||
return;
|
||||
} else if (urb->status == -EINPROGRESS) {
|
||||
} else if (!urb->unlinked) {
|
||||
int retval;
|
||||
struct u132_ring *ring = endp->ring;
|
||||
up(&u132->scheduler_lock);
|
||||
|
@ -1296,8 +1296,8 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
|
|||
u132_hcd_giveback_urb(u132, endp, urb, retval);
|
||||
return;
|
||||
} else {
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
|
||||
"s=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
|
||||
"unlinked=%d\n", urb, urb->unlinked);
|
||||
up(&u132->scheduler_lock);
|
||||
u132_hcd_giveback_urb(u132, endp, urb, urb->status);
|
||||
return;
|
||||
|
@ -2279,8 +2279,8 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
|
|||
, u132->going);
|
||||
return -ENODEV;
|
||||
} else if (u132->going > 0) {
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed urb="
|
||||
"%p status=%d\n", urb, urb->status);
|
||||
dev_err(&u132->platform_dev->dev, "device is being removed "
|
||||
"urb=%p\n", urb);
|
||||
return -ESHUTDOWN;
|
||||
} else {
|
||||
u8 usb_addr = usb_pipedevice(urb->pipe);
|
||||
|
|
|
@ -120,8 +120,8 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
|
|||
out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : ""));
|
||||
out += sprintf(out, " Actlen=%d", urbp->urb->actual_length);
|
||||
|
||||
if (urbp->urb->status != -EINPROGRESS)
|
||||
out += sprintf(out, " Status=%d", urbp->urb->status);
|
||||
if (urbp->urb->unlinked)
|
||||
out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked);
|
||||
out += sprintf(out, "\n");
|
||||
|
||||
i = nactive = ninactive = 0;
|
||||
|
|
|
@ -1557,15 +1557,12 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
|
|||
break;
|
||||
|
||||
spin_lock(&urb->lock);
|
||||
if (urb->status == -EINPROGRESS) /* Not dequeued */
|
||||
urb->status = status;
|
||||
else
|
||||
status = ECONNRESET; /* Not -ECONNRESET */
|
||||
urb->status = status;
|
||||
spin_unlock(&urb->lock);
|
||||
|
||||
/* Dequeued but completed URBs can't be given back unless
|
||||
* the QH is stopped or has finished unlinking. */
|
||||
if (status == ECONNRESET) {
|
||||
if (urb->unlinked) {
|
||||
if (QH_FINISHED_UNLINKING(qh))
|
||||
qh->is_stopped = 1;
|
||||
else if (!qh->is_stopped)
|
||||
|
@ -1588,7 +1585,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
|
|||
restart:
|
||||
list_for_each_entry(urbp, &qh->queue, node) {
|
||||
urb = urbp->urb;
|
||||
if (urb->status != -EINPROGRESS) {
|
||||
if (urb->unlinked) {
|
||||
|
||||
/* Fix up the TD links and save the toggles for
|
||||
* non-Isochronous queues. For Isochronous queues,
|
||||
|
|
|
@ -1245,6 +1245,7 @@ struct urb
|
|||
void *hcpriv; /* private data for host controller */
|
||||
atomic_t use_count; /* concurrent submissions counter */
|
||||
u8 reject; /* submissions will fail */
|
||||
int unlinked; /* unlink error code */
|
||||
|
||||
/* public: documented fields in the urb that can be used by drivers */
|
||||
struct list_head urb_list; /* list head for use by the urb's
|
||||
|
|
Загрузка…
Ссылка в новой задаче