On Sat, 2010-07-03 at 14:04 +0100, Ben Hutchings wrote: > On Thu, 2010-07-01 at 15:07 +0100, Luís Picciochi Oliveira wrote: > > Hi > > This patch seems to have fixed it. Here are the results of my testing: [...] > Right. So I'll need to do something a bit smarter to cover all devices.
Can you test the attached patch against the Debian package of 2.6.32? Ben. -- Ben Hutchings Once a job is fouled up, anything done to improve it makes it worse.
From d67957b9696ed37425244ce25b2b9ed61df1de87 Mon Sep 17 00:00:00 2001 From: Ben Hutchings <b...@decadent.org.uk> Date: Sat, 17 Jul 2010 15:49:58 +0100 Subject: [PATCH] rndis_host: Poll status and control channels concurrently --- drivers/net/usb/rndis_host.c | 42 +++++++++++++++++++++++++++++------------- 1 files changed, 29 insertions(+), 13 deletions(-) diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 52faca1..e0f1399 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -90,6 +90,11 @@ static void rndis_msg_indicate(struct usbnet *dev, struct rndis_indicate *msg, } } +static void rndis_notif_complete(struct urb *urb) +{ + /* don't care */ +} + /* * RPC done RNDIS-style. Caller guarantees: * - message is properly byteswapped @@ -104,9 +109,9 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen) { struct cdc_state *info = (void *) &dev->data; struct usb_cdc_notification notification; + struct urb *notif_urb; int master_ifnum; int retval; - int partial; unsigned count; __le32 rsp; u32 xid = 0, msg_len, request_id; @@ -135,14 +140,19 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen) return retval; /* Some devices don't respond on the control channel until - * polled on the status channel, so do that first. */ - retval = usb_interrupt_msg( - dev->udev, - usb_rcvintpipe(dev->udev, dev->status->desc.bEndpointAddress), - ¬ification, sizeof(notification), &partial, - RNDIS_CONTROL_TIMEOUT_MS); - if (unlikely(retval < 0)) - return retval; + * polled on the status channel, so poll that as well. */ + notif_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!notif_urb) + return -ENOMEM; + usb_fill_int_urb(notif_urb, dev->udev, + usb_rcvintpipe(dev->udev, + dev->status->desc.bEndpointAddress), + ¬ification, sizeof(notification), + rndis_notif_complete, NULL, + dev->status->desc.bInterval); + retval = usb_submit_urb(notif_urb, GFP_KERNEL); + if (retval) + goto out_free; /* Poll the control channel; the request probably completed immediately */ rsp = buf->msg_type | RNDIS_MSG_COMPLETION; @@ -161,14 +171,15 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen) if (likely(buf->msg_type == rsp)) { if (likely(request_id == xid)) { if (unlikely(rsp == RNDIS_MSG_RESET_C)) - return 0; + goto out_kill; if (likely(RNDIS_STATUS_SUCCESS == buf->status)) - return 0; + goto out_kill; dev_dbg(&info->control->dev, "rndis reply status %08x\n", le32_to_cpu(buf->status)); - return -EL3RST; + retval = -EL3RST; + goto out_kill; } dev_dbg(&info->control->dev, "rndis reply id %d expected %d\n", @@ -211,7 +222,12 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen) msleep(20); } dev_dbg(&info->control->dev, "rndis response timeout\n"); - return -ETIMEDOUT; + retval = -ETIMEDOUT; +out_kill: + usb_kill_urb(notif_urb); +out_free: + usb_free_urb(notif_urb); + return retval; } EXPORT_SYMBOL_GPL(rndis_command); -- 1.7.1
signature.asc
Description: This is a digitally signed message part