Skip to content

Commit

Permalink
USB: centralize -EREMOTEIO handling
Browse files Browse the repository at this point in the history
This patch (as969) continues the ongoing changes to the way HCDs
report URB statuses.  The programming interface has been simplified by
making usbcore responsible for clearing urb->hcpriv and for setting
-EREMOTEIO status when an URB with the URB_SHORT_NOT_OK flag ends up
as a short transfer.

By moving the work out of the HCDs, this removes a fair amount of
repeated code.

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>
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Oct 12, 2007
1 parent ee7d1f3 commit b0d9efb
Show file tree
Hide file tree
Showing 9 changed files with 18 additions and 60 deletions.
9 changes: 7 additions & 2 deletions drivers/usb/core/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
spin_unlock_irq(&hcd_root_hub_lock);
if (status)
return status;
urb->hcpriv = hcd; /* Indicate it's queued */

cmd = (struct usb_ctrlrequest *) urb->setup_packet;
typeReq = (cmd->bRequestType << 8) | cmd->bRequest;
Expand Down Expand Up @@ -579,7 +580,6 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
hcd->poll_pending = 0;
hcd->status_urb = NULL;
urb->status = 0;
urb->hcpriv = NULL;
urb->actual_length = length;
memcpy(urb->transfer_buffer, buffer, length);

Expand Down Expand Up @@ -675,7 +675,6 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
del_timer (&hcd->rh_timer);
if (urb == hcd->status_urb) {
hcd->status_urb = NULL;
urb->hcpriv = NULL;
usb_hcd_unlink_urb_from_ep(hcd, urb);

spin_unlock(&hcd_root_hub_lock);
Expand Down Expand Up @@ -1192,6 +1191,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
if (unlikely(status)) {
usbmon_urb_submit_error(&hcd->self, urb, status);
unmap_urb_for_dma(hcd, urb);
urb->hcpriv = NULL;
INIT_LIST_HEAD(&urb->urb_list);
atomic_dec(&urb->use_count);
if (urb->reject)
Expand Down Expand Up @@ -1265,6 +1265,11 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
unmap_urb_for_dma(hcd, urb);
usbmon_urb_complete (&hcd->self, urb);
usb_unanchor_urb(urb);
urb->hcpriv = NULL;
if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
urb->actual_length < urb->transfer_buffer_length &&
!urb->status))
urb->status = -EREMOTEIO;

/* pass ownership to the completion handler */
urb->complete (urb);
Expand Down
9 changes: 2 additions & 7 deletions drivers/usb/gadget/dummy_hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1099,8 +1099,7 @@ transfer (struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit)
*
* partially filling a buffer optionally blocks queue advances
* (so completion handlers can clean up the queue) but we don't
* need to emulate such data-in-flight. so we only show part
* of the URB_SHORT_NOT_OK effect: completion status.
* need to emulate such data-in-flight.
*/
if (is_short) {
if (host_len == dev_len) {
Expand All @@ -1111,10 +1110,7 @@ transfer (struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit)
if (dev_len > host_len)
maybe_set_status (urb, -EOVERFLOW);
else
maybe_set_status (urb,
(urb->transfer_flags
& URB_SHORT_NOT_OK)
? -EREMOTEIO : 0);
maybe_set_status (urb, 0);
} else if (!to_host) {
maybe_set_status (urb, 0);
if (host_len > dev_len)
Expand Down Expand Up @@ -1516,7 +1512,6 @@ static void dummy_timer (unsigned long _dum)
continue;

return_urb:
urb->hcpriv = NULL;
list_del (&urbp->urbp_list);
kfree (urbp);
if (ep)
Expand Down
7 changes: 4 additions & 3 deletions drivers/usb/host/ehci-q.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,6 @@ __acquires(ehci->lock)
}

spin_lock (&urb->lock);
urb->hcpriv = NULL;
switch (urb->status) {
case -EINPROGRESS: /* success */
urb->status = 0;
Expand Down Expand Up @@ -395,8 +394,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* remove it from the queue */
spin_lock (&urb->lock);
qtd_copy_status (ehci, urb, qtd->length, token);
do_status = (urb->status == -EREMOTEIO)
&& usb_pipecontrol (urb->pipe);
if (unlikely(urb->status == -EREMOTEIO)) {
do_status = usb_pipecontrol(urb->pipe);
urb->status = 0;
}
spin_unlock (&urb->lock);

if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
Expand Down
8 changes: 1 addition & 7 deletions drivers/usb/host/isp116x-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,6 @@ __releases(isp116x->lock) __acquires(isp116x->lock)
{
unsigned i;

urb->hcpriv = NULL;
ep->error_count = 0;

if (usb_pipecontrol(urb->pipe))
Expand Down Expand Up @@ -446,12 +445,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
if (PTD_GET_ACTIVE(ptd)
|| (cc != TD_CC_NOERROR && cc < 0x0E))
break;
if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
urb->actual_length <
urb->transfer_buffer_length)
status = -EREMOTEIO;
else
status = 0;
status = 0;
ep->nextpid = 0;
break;
default:
Expand Down
11 changes: 0 additions & 11 deletions drivers/usb/host/ohci-q.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,10 @@ __acquires(ohci->lock)
// ASSERT (urb->hcpriv != 0);

urb_free_priv (ohci, urb->hcpriv);
urb->hcpriv = NULL;

spin_lock (&urb->lock);
if (likely (urb->status == -EINPROGRESS))
urb->status = 0;
/* report short control reads right even though the data TD always
* has TD_R set. (much simpler, but creates the 1-td limit.)
*/
if (unlikely (urb->transfer_flags & URB_SHORT_NOT_OK)
&& unlikely (usb_pipecontrol (urb->pipe))
&& urb->actual_length < urb->transfer_buffer_length
&& usb_pipein (urb->pipe)
&& urb->status == 0) {
urb->status = -EREMOTEIO;
}
spin_unlock (&urb->lock);

switch (usb_pipetype (urb->pipe)) {
Expand Down
7 changes: 1 addition & 6 deletions drivers/usb/host/r8a66597-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,6 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)

if (urb) {
urb->status = -ENODEV;
urb->hcpriv = NULL;
usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597),
urb);

Expand Down Expand Up @@ -1134,7 +1133,6 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock)
if (usb_pipeisoc(urb->pipe))
urb->start_frame = r8a66597_get_frame(hcd);

urb->hcpriv = NULL;
usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb);

spin_unlock(&r8a66597->lock);
Expand Down Expand Up @@ -1202,9 +1200,6 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
td->zero_packet = 1;
if (rcv_len < bufsize) {
td->short_packet = 1;
if (urb->transfer_buffer_length != urb->actual_length &&
urb->transfer_flags & URB_SHORT_NOT_OK)
status = -EREMOTEIO;
}
if (usb_pipeisoc(urb->pipe)) {
urb->iso_frame_desc[td->iso_cnt].actual_length = size;
Expand All @@ -1214,7 +1209,7 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
}

/* check transfer finish */
if (check_transfer_finish(td, urb)) {
if (finish || check_transfer_finish(td, urb)) {
pipe_stop(r8a66597, td->pipe);
pipe_irq_disable(r8a66597, pipenum);
finish = 1;
Expand Down
14 changes: 3 additions & 11 deletions drivers/usb/host/sl811-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,6 @@ static void finish_request(
spin_lock(&urb->lock);
if (urb->status == -EINPROGRESS)
urb->status = status;
urb->hcpriv = NULL;
spin_unlock(&urb->lock);

usb_hcd_unlink_urb_from_ep(sl811_to_hcd(sl811), urb);
Expand Down Expand Up @@ -545,17 +544,10 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank)
sl811_read_buf(sl811, SL811HS_PACKET_BUF(bank == 0),
buf, len);
usb_dotoggle(udev, ep->epnum, 0);
if (urb->actual_length == urb->transfer_buffer_length)
if (urb->actual_length == urb->transfer_buffer_length
|| len < ep->maxpacket)
urbstat = 0;
else if (len < ep->maxpacket) {
if (urb->transfer_flags & URB_SHORT_NOT_OK)
urbstat = -EREMOTEIO;
else
urbstat = 0;
}
if (usb_pipecontrol(urb->pipe)
&& (urbstat == -EREMOTEIO
|| urbstat == 0)) {
if (usb_pipecontrol(urb->pipe) && urbstat == 0) {

/* NOTE if the status stage STALLs (why?),
* this reports the wrong urb status.
Expand Down
5 changes: 0 additions & 5 deletions drivers/usb/host/u132-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,6 @@ static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
struct usb_hcd *hcd = u132_to_hcd(u132);
urb->error_count = 0;
urb->status = status;
urb->hcpriv = NULL;
spin_lock_irqsave(&endp->queue_lock.slock, irqs);
usb_hcd_unlink_urb_from_ep(hcd, urb);
endp->queue_next += 1;
Expand Down Expand Up @@ -560,7 +559,6 @@ static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
struct usb_hcd *hcd = u132_to_hcd(u132);
urb->error_count = 0;
urb->status = status;
urb->hcpriv = NULL;
spin_lock_irqsave(&endp->queue_lock.slock, irqs);
usb_hcd_unlink_urb_from_ep(hcd, urb);
endp->queue_next += 1;
Expand Down Expand Up @@ -2430,7 +2428,6 @@ static int dequeue_from_overflow_chain(struct u132 *u132,
list_del(scan);
endp->queue_size -= 1;
urb->error_count = 0;
urb->hcpriv = NULL;
usb_hcd_giveback_urb(hcd, urb);
return 0;
} else
Expand Down Expand Up @@ -2472,7 +2469,6 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
endp->edset_flush = 1;
u132_endp_queue_work(u132, endp, 0);
spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
urb->hcpriv = NULL;
return 0;
} else {
spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
Expand Down Expand Up @@ -2517,7 +2513,6 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
irqs);
kfree(urbq);
} urb->error_count = 0;
urb->hcpriv = NULL;
usb_hcd_giveback_urb(hcd, urb);
return 0;
} else if (list_empty(&endp->urb_more)) {
Expand Down
8 changes: 0 additions & 8 deletions drivers/usb/host/uhci-q.c
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,6 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci,
uhci_free_td(uhci, td);
}

urbp->urb->hcpriv = NULL;
kmem_cache_free(uhci_up_cachep, urbp);
}

Expand Down Expand Up @@ -1494,13 +1493,6 @@ __acquires(uhci->lock)
* unlinked first. Regardless, don't confuse people with a
* negative length. */
urb->actual_length = max(urb->actual_length, 0);

/* Report erroneous short transfers */
if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
urb->actual_length <
urb->transfer_buffer_length &&
urb->status == 0))
urb->status = -EREMOTEIO;
}

/* When giving back the first URB in an Isochronous queue,
Expand Down

0 comments on commit b0d9efb

Please sign in to comment.