diff mbox

[net,stable-3.8] net: cdc_ncm, cdc_mbim: allow user to prefer NCM for backwards compatibility

Message ID 1363259113-6909-1-git-send-email-bjorn@mork.no
State Accepted, archived
Delegated to: David Miller
Headers show

Commit Message

Bjørn Mork March 14, 2013, 11:05 a.m. UTC
commit bd329e1 ("net: cdc_ncm: do not bind to NCM compatible MBIM devices")
introduced a new policy, preferring MBIM for dual NCM/MBIM functions if
the cdc_mbim driver was enabled.  This caused a regression for users
wanting to use NCM.

Devices implementing NCM backwards compatibility according to section
3.2 of the MBIM v1.0 specification allow either NCM or MBIM on a single
USB function, using different altsettings.  The cdc_ncm and cdc_mbim
drivers will both probe such functions, and must agree on a common
policy for selecting either MBIM or NCM.  Until now, this policy has
been set at build time based on CONFIG_USB_NET_CDC_MBIM.

Use a module parameter to set the system policy at runtime, allowing the
user to prefer NCM on systems with the cdc_mbim driver.

Cc: Greg Suarez <gsuarez@smithmicro.com>
Cc: Alexey Orishko <alexey.orishko@stericsson.com>
Reported-by: Geir Haatveit <nospam@haatveit.nu>
Reported-by: Tommi Kyntola <kynde@ts.ray.fi>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=54791
Signed-off-by: Bjørn Mork <bjorn@mork.no>
---

We now have two users independently reporting this as a 3.8 regression,
so something needs to be done.  I am not sure if adding a new module
parameter is acceptable for stable, but this problem is definitely a
regression and no other solutions came up in response to my RFC.

The only real alternative I see for stable, is disabling MBIM support
on any dual NCM/MBIM function.  Which of course will be a regression
for any user wanting MBIM, making it unacceptable.


 drivers/net/usb/cdc_mbim.c  |   11 +---------
 drivers/net/usb/cdc_ncm.c   |   49 ++++++++++++++++++++++++++++---------------
 include/linux/usb/cdc_ncm.h |    1 +
 3 files changed, 34 insertions(+), 27 deletions(-)

Comments

Ben Hutchings March 15, 2013, 5:22 a.m. UTC | #1
On Thu, 2013-03-14 at 12:05 +0100, Bjørn Mork wrote:
> commit bd329e1 ("net: cdc_ncm: do not bind to NCM compatible MBIM devices")
> introduced a new policy, preferring MBIM for dual NCM/MBIM functions if
> the cdc_mbim driver was enabled.  This caused a regression for users
> wanting to use NCM.
> 
> Devices implementing NCM backwards compatibility according to section
> 3.2 of the MBIM v1.0 specification allow either NCM or MBIM on a single
> USB function, using different altsettings.  The cdc_ncm and cdc_mbim
> drivers will both probe such functions, and must agree on a common
> policy for selecting either MBIM or NCM.  Until now, this policy has
> been set at build time based on CONFIG_USB_NET_CDC_MBIM.
> 
> Use a module parameter to set the system policy at runtime, allowing the
> user to prefer NCM on systems with the cdc_mbim driver.
> 
> Cc: Greg Suarez <gsuarez@smithmicro.com>
> Cc: Alexey Orishko <alexey.orishko@stericsson.com>
> Reported-by: Geir Haatveit <nospam@haatveit.nu>
> Reported-by: Tommi Kyntola <kynde@ts.ray.fi>
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=54791
> Signed-off-by: Bjørn Mork <bjorn@mork.no>
> ---
> 
> We now have two users independently reporting this as a 3.8 regression,
> so something needs to be done.  I am not sure if adding a new module
> parameter is acceptable for stable, but this problem is definitely a
> regression and no other solutions came up in response to my RFC.
> 
> The only real alternative I see for stable, is disabling MBIM support
> on any dual NCM/MBIM function.  Which of course will be a regression
> for any user wanting MBIM, making it unacceptable.
[...]

It definitely makes sense for this to be a run-time parameter.  And the
default seems correct for custom kernels.

For a distribution kernel - at least for Debian, where we can't assume
kernel and userland are always updated together - I think the
compile-time default should be false, and the userland package
(presumably ModemManager?) can install a modprobe.conf file to override
that once it can handle MBIM.  We handled KMS transitions in a similar
way.  I don't know that it's worth having a Kconfig option for that,
though.

Ben.
Bjørn Mork March 15, 2013, 7:02 a.m. UTC | #2
Ben Hutchings <ben@decadent.org.uk> writes:

> On Thu, 2013-03-14 at 12:05 +0100, Bjørn Mork wrote:
>> commit bd329e1 ("net: cdc_ncm: do not bind to NCM compatible MBIM devices")
>> introduced a new policy, preferring MBIM for dual NCM/MBIM functions if
>> the cdc_mbim driver was enabled.  This caused a regression for users
>> wanting to use NCM.
>> 
>> Devices implementing NCM backwards compatibility according to section
>> 3.2 of the MBIM v1.0 specification allow either NCM or MBIM on a single
>> USB function, using different altsettings.  The cdc_ncm and cdc_mbim
>> drivers will both probe such functions, and must agree on a common
>> policy for selecting either MBIM or NCM.  Until now, this policy has
>> been set at build time based on CONFIG_USB_NET_CDC_MBIM.
>> 
>> Use a module parameter to set the system policy at runtime, allowing the
>> user to prefer NCM on systems with the cdc_mbim driver.
>> 
>> Cc: Greg Suarez <gsuarez@smithmicro.com>
>> Cc: Alexey Orishko <alexey.orishko@stericsson.com>
>> Reported-by: Geir Haatveit <nospam@haatveit.nu>
>> Reported-by: Tommi Kyntola <kynde@ts.ray.fi>
>> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=54791
>> Signed-off-by: Bjørn Mork <bjorn@mork.no>
>> ---
>> 
>> We now have two users independently reporting this as a 3.8 regression,
>> so something needs to be done.  I am not sure if adding a new module
>> parameter is acceptable for stable, but this problem is definitely a
>> regression and no other solutions came up in response to my RFC.
>> 
>> The only real alternative I see for stable, is disabling MBIM support
>> on any dual NCM/MBIM function.  Which of course will be a regression
>> for any user wanting MBIM, making it unacceptable.
> [...]
>
> It definitely makes sense for this to be a run-time parameter.  And the
> default seems correct for custom kernels.
>
> For a distribution kernel - at least for Debian, where we can't assume
> kernel and userland are always updated together - I think the
> compile-time default should be false, and the userland package
> (presumably ModemManager?) can install a modprobe.conf file to override
> that once it can handle MBIM.  We handled KMS transitions in a similar
> way.  I don't know that it's worth having a Kconfig option for that,
> though.

We could consider always defaulting to NCM.  That would remove the
ugliest parts of the code as well.  Should I send a new version with
such a change?

Bundling a modprobe.conf file to enable MBIM with userland tools
supporting it is a great idea, and sounds feasible for custom built
systems as well.

(BTW, if there is any doubt about it, I feel really bad about my recent
request to enable MBIM in Debian, where I wrote "enabling the driver
will not prevent any existing solution from working.".  At the time, I
had not seen any of these dual NCM/MBIM functions and I just didn't
think about the problems such devices would run into. Sorry about
that. I guess I owe you one more...)


Bjørn
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ben Hutchings March 16, 2013, 5:51 p.m. UTC | #3
On Fri, 2013-03-15 at 08:02 +0100, Bjørn Mork wrote:
> Ben Hutchings <ben@decadent.org.uk> writes:
> 
> > On Thu, 2013-03-14 at 12:05 +0100, Bjørn Mork wrote:
> >> commit bd329e1 ("net: cdc_ncm: do not bind to NCM compatible MBIM devices")
> >> introduced a new policy, preferring MBIM for dual NCM/MBIM functions if
> >> the cdc_mbim driver was enabled.  This caused a regression for users
> >> wanting to use NCM.
> >> 
> >> Devices implementing NCM backwards compatibility according to section
> >> 3.2 of the MBIM v1.0 specification allow either NCM or MBIM on a single
> >> USB function, using different altsettings.  The cdc_ncm and cdc_mbim
> >> drivers will both probe such functions, and must agree on a common
> >> policy for selecting either MBIM or NCM.  Until now, this policy has
> >> been set at build time based on CONFIG_USB_NET_CDC_MBIM.
> >> 
> >> Use a module parameter to set the system policy at runtime, allowing the
> >> user to prefer NCM on systems with the cdc_mbim driver.
> >> 
> >> Cc: Greg Suarez <gsuarez@smithmicro.com>
> >> Cc: Alexey Orishko <alexey.orishko@stericsson.com>
> >> Reported-by: Geir Haatveit <nospam@haatveit.nu>
> >> Reported-by: Tommi Kyntola <kynde@ts.ray.fi>
> >> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=54791
> >> Signed-off-by: Bjørn Mork <bjorn@mork.no>
> >> ---
> >> 
> >> We now have two users independently reporting this as a 3.8 regression,
> >> so something needs to be done.  I am not sure if adding a new module
> >> parameter is acceptable for stable, but this problem is definitely a
> >> regression and no other solutions came up in response to my RFC.
> >> 
> >> The only real alternative I see for stable, is disabling MBIM support
> >> on any dual NCM/MBIM function.  Which of course will be a regression
> >> for any user wanting MBIM, making it unacceptable.
> > [...]
> >
> > It definitely makes sense for this to be a run-time parameter.  And the
> > default seems correct for custom kernels.
> >
> > For a distribution kernel - at least for Debian, where we can't assume
> > kernel and userland are always updated together - I think the
> > compile-time default should be false, and the userland package
> > (presumably ModemManager?) can install a modprobe.conf file to override
> > that once it can handle MBIM.  We handled KMS transitions in a similar
> > way.  I don't know that it's worth having a Kconfig option for that,
> > though.
> 
> We could consider always defaulting to NCM.  That would remove the
> ugliest parts of the code as well.  Should I send a new version with
> such a change?

We could, but I fear that would annoy people building custom kernels.

> Bundling a modprobe.conf file to enable MBIM with userland tools
> supporting it is a great idea, and sounds feasible for custom built
> systems as well.

Using unpatched Linux & ModemManager (or other userland) needs to just
work.  So if Linux is going to have MBIM disabled by default then
upstream ModemManager needs to ship and install that modprobe.conf file.

> (BTW, if there is any doubt about it, I feel really bad about my recent
> request to enable MBIM in Debian, where I wrote "enabling the driver
> will not prevent any existing solution from working.".  At the time, I
> had not seen any of these dual NCM/MBIM functions and I just didn't
> think about the problems such devices would run into. Sorry about
> that. I guess I owe you one more...)

It's called experimental for a reason. :-)

Ben.
David Miller March 17, 2013, 4 p.m. UTC | #4
From: Bjørn Mork <bjorn@mork.no>
Date: Thu, 14 Mar 2013 12:05:13 +0100

> commit bd329e1 ("net: cdc_ncm: do not bind to NCM compatible MBIM devices")
> introduced a new policy, preferring MBIM for dual NCM/MBIM functions if
> the cdc_mbim driver was enabled.  This caused a regression for users
> wanting to use NCM.
> 
> Devices implementing NCM backwards compatibility according to section
> 3.2 of the MBIM v1.0 specification allow either NCM or MBIM on a single
> USB function, using different altsettings.  The cdc_ncm and cdc_mbim
> drivers will both probe such functions, and must agree on a common
> policy for selecting either MBIM or NCM.  Until now, this policy has
> been set at build time based on CONFIG_USB_NET_CDC_MBIM.
> 
> Use a module parameter to set the system policy at runtime, allowing the
> user to prefer NCM on systems with the cdc_mbim driver.
> 
> Cc: Greg Suarez <gsuarez@smithmicro.com>
> Cc: Alexey Orishko <alexey.orishko@stericsson.com>
> Reported-by: Geir Haatveit <nospam@haatveit.nu>
> Reported-by: Tommi Kyntola <kynde@ts.ray.fi>
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=54791
> Signed-off-by: Bjørn Mork <bjorn@mork.no>

Ok, this is fine as a solution for now, applied and queued up for -stable.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index 248d2dc..16c8429 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -68,18 +68,9 @@  static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
 	struct cdc_ncm_ctx *ctx;
 	struct usb_driver *subdriver = ERR_PTR(-ENODEV);
 	int ret = -ENODEV;
-	u8 data_altsetting = CDC_NCM_DATA_ALTSETTING_NCM;
+	u8 data_altsetting = cdc_ncm_select_altsetting(dev, intf);
 	struct cdc_mbim_state *info = (void *)&dev->data;
 
-	/* see if interface supports MBIM alternate setting */
-	if (intf->num_altsetting == 2) {
-		if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
-			usb_set_interface(dev->udev,
-					  intf->cur_altsetting->desc.bInterfaceNumber,
-					  CDC_NCM_COMM_ALTSETTING_MBIM);
-		data_altsetting = CDC_NCM_DATA_ALTSETTING_MBIM;
-	}
-
 	/* Probably NCM, defer for cdc_ncm_bind */
 	if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
 		goto err;
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 61b74a2..4709fa3 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -55,6 +55,14 @@ 
 
 #define	DRIVER_VERSION				"14-Mar-2012"
 
+#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
+static bool prefer_mbim = true;
+#else
+static bool prefer_mbim;
+#endif
+module_param(prefer_mbim, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(prefer_mbim, "Prefer MBIM setting on dual NCM/MBIM functions");
+
 static void cdc_ncm_txpath_bh(unsigned long param);
 static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
 static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer);
@@ -550,9 +558,12 @@  void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
 }
 EXPORT_SYMBOL_GPL(cdc_ncm_unbind);
 
-static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
+/* Select the MBIM altsetting iff it is preferred and available,
+ * returning the number of the corresponding data interface altsetting
+ */
+u8 cdc_ncm_select_altsetting(struct usbnet *dev, struct usb_interface *intf)
 {
-	int ret;
+	struct usb_host_interface *alt;
 
 	/* The MBIM spec defines a NCM compatible default altsetting,
 	 * which we may have matched:
@@ -568,23 +579,27 @@  static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
 	 *   endpoint descriptors, shall be constructed according to
 	 *   the rules given in section 6 (USB Device Model) of this
 	 *   specification."
-	 *
-	 * Do not bind to such interfaces, allowing cdc_mbim to handle
-	 * them
 	 */
-#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
-	if ((intf->num_altsetting == 2) &&
-	    !usb_set_interface(dev->udev,
-			       intf->cur_altsetting->desc.bInterfaceNumber,
-			       CDC_NCM_COMM_ALTSETTING_MBIM)) {
-		if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
-			return -ENODEV;
-		else
-			usb_set_interface(dev->udev,
-					  intf->cur_altsetting->desc.bInterfaceNumber,
-					  CDC_NCM_COMM_ALTSETTING_NCM);
+	if (prefer_mbim && intf->num_altsetting == 2) {
+		alt = usb_altnum_to_altsetting(intf, CDC_NCM_COMM_ALTSETTING_MBIM);
+		if (alt && cdc_ncm_comm_intf_is_mbim(alt) &&
+		    !usb_set_interface(dev->udev,
+				       intf->cur_altsetting->desc.bInterfaceNumber,
+				       CDC_NCM_COMM_ALTSETTING_MBIM))
+			return CDC_NCM_DATA_ALTSETTING_MBIM;
 	}
-#endif
+	return CDC_NCM_DATA_ALTSETTING_NCM;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_select_altsetting);
+
+static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int ret;
+
+	/* MBIM backwards compatible function? */
+	cdc_ncm_select_altsetting(dev, intf);
+	if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+		return -ENODEV;
 
 	/* NCM data altsetting is always 1 */
 	ret = cdc_ncm_bind_common(dev, intf, 1);
diff --git a/include/linux/usb/cdc_ncm.h b/include/linux/usb/cdc_ncm.h
index 3b8f9d4..cc25b70 100644
--- a/include/linux/usb/cdc_ncm.h
+++ b/include/linux/usb/cdc_ncm.h
@@ -127,6 +127,7 @@  struct cdc_ncm_ctx {
 	u16 connected;
 };
 
+extern u8 cdc_ncm_select_altsetting(struct usbnet *dev, struct usb_interface *intf);
 extern int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting);
 extern void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf);
 extern struct sk_buff *cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign);