netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tilman Schmidt <tilman-ZTO5kqT2PaM@public.gmane.org>
To: David Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>,
	netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: isdn4linux-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp@public.gmane.org,
	Karsten Keil <isdn-iHCpqvpFUx0uJkBD2foKsQ@public.gmane.org>,
	Karsten Keil <keil-shG/GajIFYqbacvFa/9K2g@public.gmane.org>,
	Hansjoerg Lipp <hjlipp-S0/GAf8tV78@public.gmane.org>,
	i4ldeveloper-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp@public.gmane.org
Subject: [PATCH 06/11] gigaset: improve error recovery
Date: Wed,  7 Oct 2009 00:18:51 +0200 (CEST)	[thread overview]
Message-ID: <20091006-patch-gigaset-06.tilman@imap.cc> (raw)
In-Reply-To: <20091006-patch-gigaset-00.tilman-ZTO5kqT2PaM@public.gmane.org>

When the Gigaset base stops responding, try resetting the USB
connection to recover.

Impact: error handling improvement
Signed-off-by: Tilman Schmidt <tilman-ZTO5kqT2PaM@public.gmane.org>
---
 drivers/isdn/gigaset/bas-gigaset.c |   69 +++++++++++++++++++++++------------
 1 files changed, 45 insertions(+), 24 deletions(-)

diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 9e7108a..5ed1d99 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -134,6 +134,7 @@ struct bas_cardstate {
 #define BS_ATRDPEND	0x040	/* urb_cmd_in in use */
 #define BS_ATWRPEND	0x080	/* urb_cmd_out in use */
 #define BS_SUSPEND	0x100	/* USB port suspended */
+#define BS_RESETTING	0x200	/* waiting for HD_RESET_INTERRUPT_PIPE_ACK */
 
 
 static struct gigaset_driver *driver = NULL;
@@ -319,6 +320,21 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
 	return -EINVAL;
 }
 
+/* set/clear bits in base connection state, return previous state
+ */
+static inline int update_basstate(struct bas_cardstate *ucs,
+				  int set, int clear)
+{
+	unsigned long flags;
+	int state;
+
+	spin_lock_irqsave(&ucs->lock, flags);
+	state = ucs->basstate;
+	ucs->basstate = (state & ~clear) | set;
+	spin_unlock_irqrestore(&ucs->lock, flags);
+	return state;
+}
+
 /* error_hangup
  * hang up any existing connection because of an unrecoverable error
  * This function may be called from any context and takes care of scheduling
@@ -350,12 +366,9 @@ static inline void error_hangup(struct bc_state *bcs)
  */
 static inline void error_reset(struct cardstate *cs)
 {
-	/* close AT command channel to recover (ignore errors) */
-	req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT);
-
-	//FIXME try to recover without bothering the user
-	dev_err(cs->dev,
-	    "unrecoverable error - please disconnect Gigaset base to reset\n");
+	/* reset interrupt pipe to recover (ignore errors) */
+	update_basstate(cs->hw.bas, BS_RESETTING, 0);
+	req_submit(cs->bcs, HD_RESET_INTERRUPT_PIPE, 0, BAS_TIMEOUT);
 }
 
 /* check_pending
@@ -398,8 +411,13 @@ static void check_pending(struct bas_cardstate *ucs)
 	case HD_DEVICE_INIT_ACK:		/* no reply expected */
 		ucs->pending = 0;
 		break;
-	/* HD_READ_ATMESSAGE, HD_WRITE_ATMESSAGE, HD_RESET_INTERRUPTPIPE
-	 * are handled separately and should never end up here
+	case HD_RESET_INTERRUPT_PIPE:
+		if (!(ucs->basstate & BS_RESETTING))
+			ucs->pending = 0;
+		break;
+	/*
+	 * HD_READ_ATMESSAGE and HD_WRITE_ATMESSAGE are handled separately
+	 * and should never end up here
 	 */
 	default:
 		dev_warn(&ucs->interface->dev,
@@ -449,21 +467,6 @@ static void cmd_in_timeout(unsigned long data)
 	error_reset(cs);
 }
 
-/* set/clear bits in base connection state, return previous state
- */
-inline static int update_basstate(struct bas_cardstate *ucs,
-				  int set, int clear)
-{
-	unsigned long flags;
-	int state;
-
-	spin_lock_irqsave(&ucs->lock, flags);
-	state = ucs->basstate;
-	ucs->basstate = (state & ~clear) | set;
-	spin_unlock_irqrestore(&ucs->lock, flags);
-	return state;
-}
-
 /* read_ctrl_callback
  * USB completion handler for control pipe input
  * called by the USB subsystem in interrupt context
@@ -762,7 +765,8 @@ static void read_int_callback(struct urb *urb)
 		break;
 
 	case HD_RESET_INTERRUPT_PIPE_ACK:
-		gig_dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK");
+		update_basstate(ucs, 0, BS_RESETTING);
+		dev_notice(cs->dev, "interrupt pipe reset\n");
 		break;
 
 	case HD_SUSPEND_END:
@@ -1429,6 +1433,7 @@ static void req_timeout(unsigned long data)
 
 	case HD_CLOSE_ATCHANNEL:
 		dev_err(bcs->cs->dev, "timeout closing AT channel\n");
+		error_reset(bcs->cs);
 		break;
 
 	case HD_CLOSE_B2CHANNEL:
@@ -1438,6 +1443,13 @@ static void req_timeout(unsigned long data)
 		error_reset(bcs->cs);
 		break;
 
+	case HD_RESET_INTERRUPT_PIPE:
+		/* error recovery escalation */
+		dev_err(bcs->cs->dev,
+			"reset interrupt pipe timeout, attempting USB reset\n");
+		usb_queue_reset_device(bcs->cs->hw.bas->interface);
+		break;
+
 	default:
 		dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n",
 			 pending);
@@ -1930,6 +1942,15 @@ static int gigaset_write_cmd(struct cardstate *cs,
 		goto notqueued;
 	}
 
+	/* translate "+++" escape sequence sent as a single separate command
+	 * into "close AT channel" command for error recovery
+	 * The next command will reopen the AT channel automatically.
+	 */
+	if (len == 3 && !memcmp(buf, "+++", 3)) {
+		rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT);
+		goto notqueued;
+	}
+
 	if (len > IF_WRITEBUF)
 		len = IF_WRITEBUF;
 	if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
-- 
1.6.2.1.214.ge986c

  parent reply	other threads:[~2009-10-06 22:18 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-10-06 22:18 [PATCH 00/11] Gigaset driver patches for 2.6.32 (v3) Tilman Schmidt
2009-10-06 22:18 ` [PATCH 01/11] gigaset: fix reject/hangup handling Tilman Schmidt
2009-10-06 22:18 ` [PATCH 02/11] gigaset: linearize skb Tilman Schmidt
2009-10-06 22:18 ` [PATCH 03/11] gigaset: handle isoc frame errors more gracefully Tilman Schmidt
2009-10-06 22:18 ` [PATCH 04/11] gigaset: announce if built with debugging Tilman Schmidt
2009-10-06 22:18 ` [PATCH 05/11] gigaset: fix device ERROR response handling Tilman Schmidt
2009-10-06 22:19 ` [PATCH 08/11] gigaset: add kerneldoc comments Tilman Schmidt
     [not found] ` <20091006-patch-gigaset-00.tilman-ZTO5kqT2PaM@public.gmane.org>
2009-10-06 22:18   ` Tilman Schmidt [this message]
2009-10-06 22:18   ` [PATCH 07/11] gigaset: correct debugging output selection Tilman Schmidt
2009-10-06 22:19   ` [PATCH 09/11] gigaset: prepare for CAPI implementation Tilman Schmidt
2009-10-06 22:19   ` [PATCH 11/11] gigaset: add Kernel CAPI interface (v3) Tilman Schmidt
2009-10-07  6:39   ` [PATCH 00/11] Gigaset driver patches for 2.6.32 (v3) David Miller
     [not found]     ` <1254904188.9411@nb-hp>
2009-10-07  8:30       ` David Miller
2009-10-06 22:19 ` [PATCH 10/11] gigaset: allow building without I4L Tilman Schmidt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20091006-patch-gigaset-06.tilman@imap.cc \
    --to=tilman-zto5kqt2pam@public.gmane.org \
    --cc=davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org \
    --cc=hjlipp-S0/GAf8tV78@public.gmane.org \
    --cc=i4ldeveloper-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp@public.gmane.org \
    --cc=isdn-iHCpqvpFUx0uJkBD2foKsQ@public.gmane.org \
    --cc=isdn4linux-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp@public.gmane.org \
    --cc=keil-shG/GajIFYqbacvFa/9K2g@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).