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 <ben@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
Attachment:
signature.asc
Description: This is a digitally signed message part