Re: Fibocom L831-EAU and cdc_mbim

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

 



Andreas Böhler <news@xxxxxxxxxxx> writes:

> I recently bought a Thinkpad T470 notebook and added the Fibocom
> L831-EAU WWAN card. It's mbim-based, but unfortunately I can't get it
> to work correctly. In fact I'm experiencing similar issues to Patrick
> Chilton, who reported this behaviour a few months ago also on this
> list: https://www.spinics.net/lists/linux-usb/msg158286.html
>
> After a new boot, the card works for me for a few minutes, then all
> transfers stall. Finally, I receive the infamous 'cdc_mbim 1-6:1.0:
> nonzero urb status received: -EPIPE' message in my system log.
>
> I also tried to disable MBIM by adding an option to modprobe. During
> connect, pppd then just hangs up (again similar to what Patrick
> Chilton experienced).
>
> I'm on Arch Linux and Kernel 4.12.13, I tried with and without
> NetworkManager/ModemManager.
>
> Any ideas how I might be able to debug this?

Are you able to test the attached patch?  It should apply cleanly to any
of the 4.9, 4.12 and 4.13 stable trees.

Let me just admit that this is a long shot.  I don't actually understand
what happens here.  But I believe the problem started appearing with
v4.9, which had two patches touching this part of the driver in
suspicious ways.  One of those patches have already been reverted due to
other issues.  But the second is still present.  And I can't see
anything else which could possibly explain the problems.

If you can test this patch, then we can either confirm or refute this
theory.



Bjørn

>From 8fade48507bf4a017420acbe00b96ee2dc003efe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@xxxxxxx>
Date: Mon, 18 Sep 2017 12:07:21 +0200
Subject: [PATCH] Revert "cdc-wdm: Clear read pipeline in case of error"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This reverts commit c1da59dad0ebd3f9bd238f3fff82b1f7ffda7829.

Some modem firmwares got stuck in an error state with the queued
error handling, never sending any data which would clear the
driver internal error state.

Fixes: c1da59dad0eb ("cdc-wdm: Clear read pipeline in case of error")
Signed-off-by: Bjørn Mork <bjorn@xxxxxxx>
---
 drivers/usb/class/cdc-wdm.c | 39 ++++++++++-----------------------------
 1 file changed, 10 insertions(+), 29 deletions(-)

diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 5aacea1978a5..2b88eaa4089d 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -150,9 +150,6 @@ static void wdm_out_callback(struct urb *urb)
 	wake_up(&desc->wait);
 }
 
-/* forward declaration */
-static int service_outstanding_interrupt(struct wdm_device *desc);
-
 static void wdm_in_callback(struct urb *urb)
 {
 	struct wdm_device *desc = urb->context;
@@ -187,13 +184,7 @@ static void wdm_in_callback(struct urb *urb)
 		}
 	}
 
-	/*
-	 * only set a new error if there is no previous error.
-	 * Errors are only cleared during read/open
-	 */
-	if (desc->rerr  == 0)
-		desc->rerr = status;
-
+	desc->rerr = status;
 	if (length + desc->length > desc->wMaxCommand) {
 		/* The buffer would overflow */
 		set_bit(WDM_OVERFLOW, &desc->flags);
@@ -206,19 +197,9 @@ static void wdm_in_callback(struct urb *urb)
 		}
 	}
 skip_error:
-	set_bit(WDM_READ, &desc->flags);
 	wake_up(&desc->wait);
 
-	if (desc->rerr) {
-		/*
-		 * Since there was an error, userspace may decide to not read
-		 * any data after poll'ing.
-		 * We should respond to further attempts from the device to send
-		 * data, so that we can get unstuck.
-		 */
-		service_outstanding_interrupt(desc);
-	}
-
+	set_bit(WDM_READ, &desc->flags);
 	spin_unlock(&desc->iuspin);
 }
 
@@ -441,14 +422,17 @@ static ssize_t wdm_write
 }
 
 /*
- * Submit the read urb if resp_count is non-zero.
+ * clear WDM_READ flag and possibly submit the read urb if resp_count
+ * is non-zero.
  *
  * Called with desc->iuspin locked
  */
-static int service_outstanding_interrupt(struct wdm_device *desc)
+static int clear_wdm_read_flag(struct wdm_device *desc)
 {
 	int rv = 0;
 
+	clear_bit(WDM_READ, &desc->flags);
+
 	/* submit read urb only if the device is waiting for it */
 	if (!desc->resp_count || !--desc->resp_count)
 		goto out;
@@ -540,8 +524,7 @@ static ssize_t wdm_read
 
 		if (!desc->reslength) { /* zero length read */
 			dev_dbg(&desc->intf->dev, "zero length - clearing WDM_READ\n");
-			clear_bit(WDM_READ, &desc->flags);
-			rv = service_outstanding_interrupt(desc);
+			rv = clear_wdm_read_flag(desc);
 			spin_unlock_irq(&desc->iuspin);
 			if (rv < 0)
 				goto err;
@@ -566,10 +549,8 @@ static ssize_t wdm_read
 
 	desc->length -= cntr;
 	/* in case we had outstanding data */
-	if (!desc->length) {
-		clear_bit(WDM_READ, &desc->flags);
-		service_outstanding_interrupt(desc);
-	}
+	if (!desc->length)
+		clear_wdm_read_flag(desc);
 	spin_unlock_irq(&desc->iuspin);
 	rv = cntr;
 
-- 
2.11.0


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux