[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#655387: [PATCH net v2] cdc_ether: Ignore bogus union descriptor for RNDIS devices



Hi Iker,

David Miller wrote:
> From: Bjørn Mork <bjorn@mork.no>
> Date: Thu, 26 Apr 2012 14:35:10 +0200

>> The same comments as for v1 regarding testing applies.  This is build
>> tested only.  Should go through some functional testing before being
>> applied.
>
> Well?  Is anyone gonna test this?

Looks like it's up to you, unless some firmware upgrade already
made the problem go away.

It works like this:

 0. prerequisites:

	apt-get install git build-essential

 1. grab the kernel history, if you don't already have it:

	git clone \
	  git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

 2. add point releases:

	cd linux
	git remote add stable \
	  git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
	git fetch stable

 3. configure, build, test:

	git checkout stable/linux-3.2.y
	cp /boot/config-$(uname -r) .config; # current configuration
	make localmodconfig; # optional: minimize configuration
	scripts/config --disable DEBUG_INFO
	make deb-pkg; # optionally with -j<num> for parallel build
	dpkg -i ../<name of package>; # as root
	reboot
	... test test test ...

   Hopefully it reproduces the problem.  So:

 4. try the patch (attached):

	cd linux
	git am -3sc /path/to/the/patch
	make deb-pkg; # maybe with -j4
	dpkg -i ../<name of package>; # as root
	reboot
	... test test test ...

If you get a chance to try it, please report the result to Dave by
replying-to-all to his message (i.e., not this one).  If you have any
questions, please don't hesitate to ask.

Thanks and hope that helps,
Jonathan
From: Bjørn Mork <bjorn@mork.no>
Date: Thu, 26 Apr 2012 14:35:10 +0200
Subject: cdc_ether: Ignore bogus union descriptor for RNDIS devices

Some RNDIS devices include a bogus CDC Union descriptor pointing
to non-existing interfaces.  The RNDIS code is already prepared
to handle devices without a CDC Union descriptor by hardwiring
the driver to use interfaces 0 and 1, which is correct for the
devices with the bogus descriptor as well. So we can reuse the
existing workaround.

Cc: Markus Kolb <linux-201011@tower-net.de>
Cc: Iker Salmón San Millán <shaola@esdebian.org>
Cc: Jonathan Nieder <jrnieder@gmail.com>
Cc: Oliver Neukum <oliver@neukum.org>
Cc: 655387@bugs.debian.org
Cc: stable@vger.kernel.org
Signed-off-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
 drivers/net/usb/cdc_ether.c |   14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 4fd41443a9b0..eac4886afc36 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -83,6 +83,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
 	struct cdc_state		*info = (void *) &dev->data;
 	int				status;
 	int				rndis;
+	bool				android_rndis_quirk = false;
 	struct usb_driver		*driver = driver_of(intf);
 	struct usb_cdc_mdlm_desc	*desc = NULL;
 	struct usb_cdc_mdlm_detail_desc *detail = NULL;
@@ -195,6 +196,11 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
 					info->control,
 					info->u->bSlaveInterface0,
 					info->data);
+				/* fall back to hard-wiring for RNDIS */
+				if (rndis) {
+					android_rndis_quirk = true;
+					goto next_desc;
+				}
 				goto bad_desc;
 			}
 			if (info->control != intf) {
@@ -271,11 +277,15 @@ next_desc:
 	/* Microsoft ActiveSync based and some regular RNDIS devices lack the
 	 * CDC descriptors, so we'll hard-wire the interfaces and not check
 	 * for descriptors.
+	 *
+	 * Some Android RNDIS devices have a CDC Union descriptor pointing
+	 * to non-existing interfaces.  Ignore that and attempt the same
+	 * hard-wired 0 and 1 interfaces.
 	 */
-	if (rndis && !info->u) {
+	if (rndis && (!info->u || android_rndis_quirk)) {
 		info->control = usb_ifnum_to_if(dev->udev, 0);
 		info->data = usb_ifnum_to_if(dev->udev, 1);
-		if (!info->control || !info->data) {
+		if (!info->control || !info->data || info->control != intf) {
 			dev_dbg(&intf->dev,
 				"rndis: master #0/%p slave #1/%p\n",
 				info->control,
-- 
1.7.10.1


Reply to: