netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] ISDN patches for 2.6.35
@ 2010-05-23  0:24 Tilman Schmidt
       [not found] ` <20100522-patch-gigaset-00.tilman-ZTO5kqT2PaM@public.gmane.org>
  2010-05-23  0:43 ` [PATCH 0/7] ISDN patches for 2.6.35 David Miller
  0 siblings, 2 replies; 10+ messages in thread
From: Tilman Schmidt @ 2010-05-23  0:24 UTC (permalink / raw)
  To: Karsten Keil, David Miller
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Karsten Keil, Hansjoerg Lipp,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	i4ldeveloper-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp

Karsten, David,

following are seven patches to the CAPI subsystem and the Gigaset
driver I'd like to see included in kernel release 2.6.35.
The first three respond to user reports about an observed hang of
the userspace command "capiinit stop".
The others are cleanups from the ongoing driver development.

Thanks,
Tilman

Tilman Schmidt (7):
  Documentation/isdn: CAPI controller interface amendment
  isdn/capi: make reset_ctr op truly optional
  isdn/gigaset: remove dummy CAPI method implementations
  isdn/gigaset: adjust usb_gigaset tty write buffer limit
  isdn/gigaset: avoid copying AT commands twice
  isdn/gigaset: ignore irrelevant device responses
  isdn/gigaset: drop obsolete FIXME comment

 Documentation/isdn/INTERFACE.CAPI  |    8 +-
 drivers/isdn/capi/kcapi.c          |    6 +
 drivers/isdn/gigaset/bas-gigaset.c |   51 ++-----------
 drivers/isdn/gigaset/capi.c        |   28 -------
 drivers/isdn/gigaset/common.c      |    2 
 drivers/isdn/gigaset/ev-layer.c    |  142 ++++++++++++-------------------------
 drivers/isdn/gigaset/gigaset.h     |    9 --
 drivers/isdn/gigaset/interface.c   |   36 +++++++--
 drivers/isdn/gigaset/ser-gigaset.c |   27 +------
 drivers/isdn/gigaset/usb-gigaset.c |   29 +------
 10 files changed, 117 insertions(+), 221 deletions(-)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/7] Documentation/isdn: CAPI controller interface amendment
       [not found] ` <20100522-patch-gigaset-00.tilman-ZTO5kqT2PaM@public.gmane.org>
@ 2010-05-23  0:24   ` Tilman Schmidt
  2010-05-23  0:25   ` [PATCH 2/7] isdn/capi: make reset_ctr op truly optional Tilman Schmidt
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Tilman Schmidt @ 2010-05-23  0:24 UTC (permalink / raw)
  To: Karsten Keil, David Miller
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Karsten Keil, Hansjoerg Lipp,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	i4ldeveloper-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp

Mention that the CAPI controller methods load_firmware() and
reset_ctr() are asynchronous, and should signal completion.

Impact: documentation
Signed-off-by: Tilman Schmidt <tilman-ZTO5kqT2PaM@public.gmane.org>
---
 Documentation/isdn/INTERFACE.CAPI |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/Documentation/isdn/INTERFACE.CAPI b/Documentation/isdn/INTERFACE.CAPI
index f172091..309eb5e 100644
--- a/Documentation/isdn/INTERFACE.CAPI
+++ b/Documentation/isdn/INTERFACE.CAPI
@@ -113,12 +113,16 @@ char *driver_name
 int (*load_firmware)(struct capi_ctr *ctrlr, capiloaddata *ldata)
 	(optional) pointer to a callback function for sending firmware and
 	configuration data to the device
+	The function may return before the operation has completed.
+	Completion must be signalled by a call to capi_ctr_ready().
 	Return value: 0 on success, error code on error
 	Called in process context.
 
 void (*reset_ctr)(struct capi_ctr *ctrlr)
-	(optional) pointer to a callback function for performing a reset on
-	the device, releasing all registered applications
+	(optional) pointer to a callback function for stopping the device,
+	releasing all registered applications
+	The function may return before the operation has completed.
+	Completion must be signalled by a call to capi_ctr_down().
 	Called in process context.
 
 void (*register_appl)(struct capi_ctr *ctrlr, u16 applid,
-- 
1.6.5.3.298.g39add

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/7] isdn/capi: make reset_ctr op truly optional
       [not found] ` <20100522-patch-gigaset-00.tilman-ZTO5kqT2PaM@public.gmane.org>
  2010-05-23  0:24   ` [PATCH 1/7] Documentation/isdn: CAPI controller interface amendment Tilman Schmidt
@ 2010-05-23  0:25   ` Tilman Schmidt
  2010-05-23  0:25   ` [PATCH 3/7] isdn/gigaset: remove dummy CAPI method implementations Tilman Schmidt
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Tilman Schmidt @ 2010-05-23  0:25 UTC (permalink / raw)
  To: Karsten Keil, David Miller
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Karsten Keil, Hansjoerg Lipp,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	i4ldeveloper-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp

The CAPI controller operation reset_ctr is marked as optional, and
not all drivers do implement it. Add a check to the kernel CAPI
whether it exists before trying to call it.

Impact: oops prevention
Signed-off-by: Tilman Schmidt <tilman-ZTO5kqT2PaM@public.gmane.org>
---
 drivers/isdn/capi/kcapi.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index bd00dce..bde3c88 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -1147,6 +1147,12 @@ load_unlock_out:
 		if (ctr->state == CAPI_CTR_DETECTED)
 			goto reset_unlock_out;
 
+		if (ctr->reset_ctr == NULL) {
+			printk(KERN_DEBUG "kcapi: reset: no reset function\n");
+			retval = -ESRCH;
+			goto reset_unlock_out;
+		}
+
 		ctr->reset_ctr(ctr);
 
 		retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED);
-- 
1.6.5.3.298.g39add

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/7] isdn/gigaset: remove dummy CAPI method implementations
       [not found] ` <20100522-patch-gigaset-00.tilman-ZTO5kqT2PaM@public.gmane.org>
  2010-05-23  0:24   ` [PATCH 1/7] Documentation/isdn: CAPI controller interface amendment Tilman Schmidt
  2010-05-23  0:25   ` [PATCH 2/7] isdn/capi: make reset_ctr op truly optional Tilman Schmidt
@ 2010-05-23  0:25   ` Tilman Schmidt
  2010-05-23  0:26   ` [PATCH 4/7] isdn/gigaset: adjust usb_gigaset tty write buffer limit Tilman Schmidt
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Tilman Schmidt @ 2010-05-23  0:25 UTC (permalink / raw)
  To: Karsten Keil, David Miller
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Karsten Keil, Hansjoerg Lipp,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	i4ldeveloper-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp

Dummy implementations for the optional CAPI controller operations
load_firmware and reset_ctr can cause userspace callers to hang
indefinitely. It's better not to implement them at all.

Impact: bugfix
Signed-off-by: Tilman Schmidt <tilman-ZTO5kqT2PaM@public.gmane.org>
---
 drivers/isdn/gigaset/capi.c |   28 ++--------------------------
 1 files changed, 2 insertions(+), 26 deletions(-)

diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 964a55f..e72f86b 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -933,30 +933,6 @@ void gigaset_isdn_stop(struct cardstate *cs)
  */
 
 /*
- * load firmware
- */
-static int gigaset_load_firmware(struct capi_ctr *ctr, capiloaddata *data)
-{
-	struct cardstate *cs = ctr->driverdata;
-
-	/* AVM specific operation, not needed for Gigaset -- ignore */
-	dev_notice(cs->dev, "load_firmware ignored\n");
-
-	return 0;
-}
-
-/*
- * reset (deactivate) controller
- */
-static void gigaset_reset_ctr(struct capi_ctr *ctr)
-{
-	struct cardstate *cs = ctr->driverdata;
-
-	/* AVM specific operation, not needed for Gigaset -- ignore */
-	dev_notice(cs->dev, "reset_ctr ignored\n");
-}
-
-/*
  * register CAPI application
  */
 static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl,
@@ -2213,8 +2189,8 @@ int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
 	iif->ctr.driverdata    = cs;
 	strncpy(iif->ctr.name, isdnid, sizeof(iif->ctr.name));
 	iif->ctr.driver_name   = "gigaset";
-	iif->ctr.load_firmware = gigaset_load_firmware;
-	iif->ctr.reset_ctr     = gigaset_reset_ctr;
+	iif->ctr.load_firmware = NULL;
+	iif->ctr.reset_ctr     = NULL;
 	iif->ctr.register_appl = gigaset_register_appl;
 	iif->ctr.release_appl  = gigaset_release_appl;
 	iif->ctr.send_message  = gigaset_send_message;
-- 
1.6.5.3.298.g39add

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/7] isdn/gigaset: adjust usb_gigaset tty write buffer limit
       [not found] ` <20100522-patch-gigaset-00.tilman-ZTO5kqT2PaM@public.gmane.org>
                     ` (2 preceding siblings ...)
  2010-05-23  0:25   ` [PATCH 3/7] isdn/gigaset: remove dummy CAPI method implementations Tilman Schmidt
@ 2010-05-23  0:26   ` Tilman Schmidt
  2010-05-23  0:26   ` [PATCH 5/7] isdn/gigaset: avoid copying AT commands twice Tilman Schmidt
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Tilman Schmidt @ 2010-05-23  0:26 UTC (permalink / raw)
  To: Karsten Keil, David Miller
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Karsten Keil, Hansjoerg Lipp,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	i4ldeveloper-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp

The usb_gigaset driver's write buffer limit was different from those
of the other hardware modules for no good reason. Set it to the same
value as the others, derived from the Siemens documentation.

Impact: cosmetic
Signed-off-by: Tilman Schmidt <tilman-ZTO5kqT2PaM@public.gmane.org>
---
 drivers/isdn/gigaset/usb-gigaset.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index 76dbb20..f65cf7d 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -39,7 +39,8 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode");
 #define GIGASET_MODULENAME "usb_gigaset"
 #define GIGASET_DEVNAME    "ttyGU"
 
-#define IF_WRITEBUF 2000	/* arbitrary limit */
+/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */
+#define IF_WRITEBUF 264
 
 /* Values for the Gigaset M105 Data */
 #define USB_M105_VENDOR_ID	0x0681
-- 
1.6.5.3.298.g39add

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 5/7] isdn/gigaset: avoid copying AT commands twice
       [not found] ` <20100522-patch-gigaset-00.tilman-ZTO5kqT2PaM@public.gmane.org>
                     ` (3 preceding siblings ...)
  2010-05-23  0:26   ` [PATCH 4/7] isdn/gigaset: adjust usb_gigaset tty write buffer limit Tilman Schmidt
@ 2010-05-23  0:26   ` Tilman Schmidt
  2010-05-23  0:27   ` [PATCH 6/7] isdn/gigaset: ignore irrelevant device responses Tilman Schmidt
  2010-05-23  0:27   ` [PATCH 7/7] isdn/gigaset: drop obsolete FIXME comment Tilman Schmidt
  6 siblings, 0 replies; 10+ messages in thread
From: Tilman Schmidt @ 2010-05-23  0:26 UTC (permalink / raw)
  To: Karsten Keil, David Miller
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Karsten Keil, Hansjoerg Lipp,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	i4ldeveloper-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp

Change the Gigaset driver's internal write_cmd interface to accept a
cmdbuf structure instead of a string. This avoids copying formatted
AT commands a second time.

Impact: optimization
Signed-off-by: Tilman Schmidt <tilman-ZTO5kqT2PaM@public.gmane.org>
---
 drivers/isdn/gigaset/bas-gigaset.c |   51 +++++-------------------
 drivers/isdn/gigaset/ev-layer.c    |   75 ++++++++++++++++-------------------
 drivers/isdn/gigaset/gigaset.h     |    4 +-
 drivers/isdn/gigaset/interface.c   |   36 ++++++++++++++---
 drivers/isdn/gigaset/ser-gigaset.c |   27 ++----------
 drivers/isdn/gigaset/usb-gigaset.c |   26 ++----------
 6 files changed, 85 insertions(+), 134 deletions(-)

diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 47a5ffe..2dab531 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -1913,65 +1913,41 @@ static int start_cbsend(struct cardstate *cs)
  * USB transmission is started if necessary.
  * parameters:
  *	cs		controller state structure
- *	buf		command string to send
- *	len		number of bytes to send (max. IF_WRITEBUF)
- *	wake_tasklet	tasklet to run when transmission is completed
- *			(NULL if none)
+ *	cb		command buffer structure
  * return value:
  *	number of bytes queued on success
  *	error code < 0 on error
  */
-static int gigaset_write_cmd(struct cardstate *cs,
-			     const unsigned char *buf, int len,
-			     struct tasklet_struct *wake_tasklet)
+static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb)
 {
-	struct cmdbuf_t *cb;
 	unsigned long flags;
 	int rc;
 
 	gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
 			     DEBUG_TRANSCMD : DEBUG_LOCKCMD,
-			   "CMD Transmit", len, buf);
-
-	if (len <= 0) {
-		/* nothing to do */
-		rc = 0;
-		goto notqueued;
-	}
+			   "CMD Transmit", cb->len, cb->buf);
 
 	/* 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)) {
+	if (cb->len == 3 && !memcmp(cb->buf, "+++", 3)) {
+		kfree(cb);
 		rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT);
-		goto notqueued;
-	}
-
-	if (len > IF_WRITEBUF)
-		len = IF_WRITEBUF;
-	cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
-	if (!cb) {
-		dev_err(cs->dev, "%s: out of memory\n", __func__);
-		rc = -ENOMEM;
-		goto notqueued;
+		if (cb->wake_tasklet)
+			tasklet_schedule(cb->wake_tasklet);
+		return rc < 0 ? rc : cb->len;
 	}
 
-	memcpy(cb->buf, buf, len);
-	cb->len = len;
-	cb->offset = 0;
-	cb->next = NULL;
-	cb->wake_tasklet = wake_tasklet;
-
 	spin_lock_irqsave(&cs->cmdlock, flags);
 	cb->prev = cs->lastcmdbuf;
 	if (cs->lastcmdbuf)
 		cs->lastcmdbuf->next = cb;
 	else {
 		cs->cmdbuf = cb;
-		cs->curlen = len;
+		cs->curlen = cb->len;
 	}
-	cs->cmdbytes += len;
+	cs->cmdbytes += cb->len;
 	cs->lastcmdbuf = cb;
 	spin_unlock_irqrestore(&cs->cmdlock, flags);
 
@@ -1988,12 +1964,7 @@ static int gigaset_write_cmd(struct cardstate *cs,
 	}
 	rc = start_cbsend(cs);
 	spin_unlock_irqrestore(&cs->lock, flags);
-	return rc < 0 ? rc : len;
-
-notqueued:			/* request handled without queuing */
-	if (wake_tasklet)
-		tasklet_schedule(wake_tasklet);
-	return rc;
+	return rc < 0 ? rc : cb->len;
 }
 
 /* gigaset_write_room
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index 206c380..84a8901 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -799,48 +799,27 @@ static void schedule_init(struct cardstate *cs, int state)
 static void send_command(struct cardstate *cs, const char *cmd, int cid,
 			 int dle, gfp_t kmallocflags)
 {
-	size_t cmdlen, buflen;
-	char *cmdpos, *cmdbuf, *cmdtail;
+	struct cmdbuf_t *cb;
+	size_t buflen;
 
-	cmdlen = strlen(cmd);
-	buflen = 11 + cmdlen;
-	if (unlikely(buflen <= cmdlen)) {
-		dev_err(cs->dev, "integer overflow in buflen\n");
+	buflen = strlen(cmd) + 12; /* DLE ( A T 1 2 3 4 5 <cmd> DLE ) \0 */
+	cb = kmalloc(sizeof(struct cmdbuf_t) + buflen, kmallocflags);
+	if (!cb) {
+		dev_err(cs->dev, "%s: out of memory\n", __func__);
 		return;
 	}
-
-	cmdbuf = kmalloc(buflen, kmallocflags);
-	if (unlikely(!cmdbuf)) {
-		dev_err(cs->dev, "out of memory\n");
-		return;
-	}
-
-	cmdpos = cmdbuf + 9;
-	cmdtail = cmdpos + cmdlen;
-	memcpy(cmdpos, cmd, cmdlen);
-
-	if (cid > 0 && cid <= 65535) {
-		do {
-			*--cmdpos = '0' + cid % 10;
-			cid /= 10;
-			++cmdlen;
-		} while (cid);
-	}
-
-	cmdlen += 2;
-	*--cmdpos = 'T';
-	*--cmdpos = 'A';
-
-	if (dle) {
-		cmdlen += 4;
-		*--cmdpos = '(';
-		*--cmdpos = 0x10;
-		*cmdtail++ = 0x10;
-		*cmdtail++ = ')';
-	}
-
-	cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL);
-	kfree(cmdbuf);
+	if (cid > 0 && cid <= 65535)
+		cb->len = snprintf(cb->buf, buflen,
+				  dle ? "\020(AT%d%s\020)" : "AT%d%s",
+				  cid, cmd);
+	else
+		cb->len = snprintf(cb->buf, buflen,
+				  dle ? "\020(AT%s\020)" : "AT%s",
+				  cmd);
+	cb->offset = 0;
+	cb->next = NULL;
+	cb->wake_tasklet = NULL;
+	cs->ops->write_cmd(cs, cb);
 }
 
 static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid)
@@ -1242,8 +1221,22 @@ static void do_action(int action, struct cardstate *cs,
 		break;
 	case ACT_HUPMODEM:
 		/* send "+++" (hangup in unimodem mode) */
-		if (cs->connected)
-			cs->ops->write_cmd(cs, "+++", 3, NULL);
+		if (cs->connected) {
+			struct cmdbuf_t *cb;
+
+			cb = kmalloc(sizeof(struct cmdbuf_t) + 3, GFP_ATOMIC);
+			if (!cb) {
+				dev_err(cs->dev, "%s: out of memory\n",
+					__func__);
+				return;
+			}
+			memcpy(cb->buf, "+++", 3);
+			cb->len = 3;
+			cb->offset = 0;
+			cb->next = NULL;
+			cb->wake_tasklet = NULL;
+			cs->ops->write_cmd(cs, cb);
+		}
 		break;
 	case ACT_RING:
 		/* get fresh AT state structure for new CID */
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index d32efb6..eb2fdac 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -575,9 +575,7 @@ struct bas_bc_state {
 struct gigaset_ops {
 	/* Called from ev-layer.c/interface.c for sending AT commands to the
 	   device */
-	int (*write_cmd)(struct cardstate *cs,
-			 const unsigned char *buf, int len,
-			 struct tasklet_struct *wake_tasklet);
+	int (*write_cmd)(struct cardstate *cs, struct cmdbuf_t *cb);
 
 	/* Called from interface.c for additional device control */
 	int (*write_room)(struct cardstate *cs);
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index c9f28dd..f45d686 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -339,7 +339,8 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file,
 static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
 	struct cardstate *cs;
-	int retval = -ENODEV;
+	struct cmdbuf_t *cb;
+	int retval;
 
 	cs = (struct cardstate *) tty->driver_data;
 	if (!cs) {
@@ -355,18 +356,39 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
 	if (!cs->connected) {
 		gig_dbg(DEBUG_IF, "not connected");
 		retval = -ENODEV;
-	} else if (!cs->open_count)
+		goto done;
+	}
+	if (!cs->open_count) {
 		dev_warn(cs->dev, "%s: device not opened\n", __func__);
-	else if (cs->mstate != MS_LOCKED) {
+		retval = -ENODEV;
+		goto done;
+	}
+	if (cs->mstate != MS_LOCKED) {
 		dev_warn(cs->dev, "can't write to unlocked device\n");
 		retval = -EBUSY;
-	} else {
-		retval = cs->ops->write_cmd(cs, buf, count,
-					    &cs->if_wake_tasklet);
+		goto done;
+	}
+	if (count <= 0) {
+		/* nothing to do */
+		retval = 0;
+		goto done;
 	}
 
-	mutex_unlock(&cs->mutex);
+	cb = kmalloc(sizeof(struct cmdbuf_t) + count, GFP_KERNEL);
+	if (!cb) {
+		dev_err(cs->dev, "%s: out of memory\n", __func__);
+		retval = -ENOMEM;
+		goto done;
+	}
 
+	memcpy(cb->buf, buf, count);
+	cb->len = count;
+	cb->offset = 0;
+	cb->next = NULL;
+	cb->wake_tasklet = &cs->if_wake_tasklet;
+	retval = cs->ops->write_cmd(cs, cb);
+done:
+	mutex_unlock(&cs->mutex);
 	return retval;
 }
 
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index e96c058..d151dcb 100644
--- a/drivers/isdn/gigaset/ser-gigaset.c
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -241,30 +241,13 @@ static void flush_send_queue(struct cardstate *cs)
  * return value:
  *	number of bytes queued, or error code < 0
  */
-static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
-			     int len, struct tasklet_struct *wake_tasklet)
+static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb)
 {
-	struct cmdbuf_t *cb;
 	unsigned long flags;
 
 	gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
 				DEBUG_TRANSCMD : DEBUG_LOCKCMD,
-			   "CMD Transmit", len, buf);
-
-	if (len <= 0)
-		return 0;
-
-	cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
-	if (!cb) {
-		dev_err(cs->dev, "%s: out of memory!\n", __func__);
-		return -ENOMEM;
-	}
-
-	memcpy(cb->buf, buf, len);
-	cb->len = len;
-	cb->offset = 0;
-	cb->next = NULL;
-	cb->wake_tasklet = wake_tasklet;
+			   "CMD Transmit", cb->len, cb->buf);
 
 	spin_lock_irqsave(&cs->cmdlock, flags);
 	cb->prev = cs->lastcmdbuf;
@@ -272,9 +255,9 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
 		cs->lastcmdbuf->next = cb;
 	else {
 		cs->cmdbuf = cb;
-		cs->curlen = len;
+		cs->curlen = cb->len;
 	}
-	cs->cmdbytes += len;
+	cs->cmdbytes += cb->len;
 	cs->lastcmdbuf = cb;
 	spin_unlock_irqrestore(&cs->cmdlock, flags);
 
@@ -282,7 +265,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
 	if (cs->connected)
 		tasklet_schedule(&cs->write_tasklet);
 	spin_unlock_irqrestore(&cs->lock, flags);
-	return len;
+	return cb->len;
 }
 
 /*
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index f65cf7d..4a66338 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -494,29 +494,13 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
 }
 
 /* Send command to device. */
-static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
-			     int len, struct tasklet_struct *wake_tasklet)
+static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb)
 {
-	struct cmdbuf_t *cb;
 	unsigned long flags;
 
 	gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
 			     DEBUG_TRANSCMD : DEBUG_LOCKCMD,
-			   "CMD Transmit", len, buf);
-
-	if (len <= 0)
-		return 0;
-	cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
-	if (!cb) {
-		dev_err(cs->dev, "%s: out of memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	memcpy(cb->buf, buf, len);
-	cb->len = len;
-	cb->offset = 0;
-	cb->next = NULL;
-	cb->wake_tasklet = wake_tasklet;
+			   "CMD Transmit", cb->len, cb->buf);
 
 	spin_lock_irqsave(&cs->cmdlock, flags);
 	cb->prev = cs->lastcmdbuf;
@@ -524,9 +508,9 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
 		cs->lastcmdbuf->next = cb;
 	else {
 		cs->cmdbuf = cb;
-		cs->curlen = len;
+		cs->curlen = cb->len;
 	}
-	cs->cmdbytes += len;
+	cs->cmdbytes += cb->len;
 	cs->lastcmdbuf = cb;
 	spin_unlock_irqrestore(&cs->cmdlock, flags);
 
@@ -534,7 +518,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
 	if (cs->connected)
 		tasklet_schedule(&cs->write_tasklet);
 	spin_unlock_irqrestore(&cs->lock, flags);
-	return len;
+	return cb->len;
 }
 
 static int gigaset_write_room(struct cardstate *cs)
-- 
1.6.5.3.298.g39add

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 6/7] isdn/gigaset: ignore irrelevant device responses
       [not found] ` <20100522-patch-gigaset-00.tilman-ZTO5kqT2PaM@public.gmane.org>
                     ` (4 preceding siblings ...)
  2010-05-23  0:26   ` [PATCH 5/7] isdn/gigaset: avoid copying AT commands twice Tilman Schmidt
@ 2010-05-23  0:27   ` Tilman Schmidt
  2010-05-23  0:27   ` [PATCH 7/7] isdn/gigaset: drop obsolete FIXME comment Tilman Schmidt
  6 siblings, 0 replies; 10+ messages in thread
From: Tilman Schmidt @ 2010-05-23  0:27 UTC (permalink / raw)
  To: Karsten Keil, David Miller
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Karsten Keil, Hansjoerg Lipp,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	i4ldeveloper-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp

Downgrade the Gigaset driver's reaction to unknown AT responses from
the device from warning to debug level, and remove the handling of
some device responses which aren't relevant for the driver's
operation.

Signed-off-by: Tilman Schmidt <tilman-ZTO5kqT2PaM@public.gmane.org>
---
 drivers/isdn/gigaset/ev-layer.c |   67 ++++++++------------------------------
 drivers/isdn/gigaset/gigaset.h  |    5 +--
 2 files changed, 16 insertions(+), 56 deletions(-)

diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index 84a8901..78c7844 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -35,53 +35,40 @@
 #define RT_RING		2
 #define RT_NUMBER	3
 #define RT_STRING	4
-#define RT_HEX		5
 #define RT_ZCAU		6
 
 /* Possible ASCII responses */
 #define RSP_OK		0
-#define RSP_BUSY	1
-#define RSP_CONNECT	2
+#define RSP_ERROR	1
 #define RSP_ZGCI	3
 #define RSP_RING	4
-#define RSP_ZAOC	5
-#define RSP_ZCSTR	6
-#define RSP_ZCFGT	7
-#define RSP_ZCFG	8
-#define RSP_ZCCR	9
-#define RSP_EMPTY	10
-#define RSP_ZLOG	11
-#define RSP_ZCAU	12
-#define RSP_ZMWI	13
-#define RSP_ZABINFO	14
-#define RSP_ZSMLSTCHG	15
+#define RSP_ZVLS	5
+#define RSP_ZCAU	6
+
+/* responses with values to store in at_state */
+/* - numeric */
 #define RSP_VAR		100
 #define RSP_ZSAU	(RSP_VAR + VAR_ZSAU)
 #define RSP_ZDLE	(RSP_VAR + VAR_ZDLE)
-#define RSP_ZVLS	(RSP_VAR + VAR_ZVLS)
 #define RSP_ZCTP	(RSP_VAR + VAR_ZCTP)
+/* - string */
 #define RSP_STR		(RSP_VAR + VAR_NUM)
 #define RSP_NMBR	(RSP_STR + STR_NMBR)
 #define RSP_ZCPN	(RSP_STR + STR_ZCPN)
 #define RSP_ZCON	(RSP_STR + STR_ZCON)
 #define RSP_ZBC		(RSP_STR + STR_ZBC)
 #define RSP_ZHLC	(RSP_STR + STR_ZHLC)
-#define RSP_ERROR	-1	/* ERROR              */
+
 #define RSP_WRONG_CID	-2	/* unknown cid in cmd */
-#define RSP_UNKNOWN	-4	/* unknown response   */
-#define RSP_FAIL	-5	/* internal error     */
 #define RSP_INVAL	-6	/* invalid response   */
+#define RSP_NODEV	-9	/* device not connected */
 
 #define RSP_NONE	-19
 #define RSP_STRING	-20
 #define RSP_NULL	-21
-#define RSP_RETRYFAIL	-22
-#define RSP_RETRY	-23
-#define RSP_SKIP	-24
 #define RSP_INIT	-27
 #define RSP_ANY		-26
 #define RSP_LAST	-28
-#define RSP_NODEV	-9
 
 /* actions for process_response */
 #define ACT_NOTHING		0
@@ -259,13 +246,6 @@ struct reply_t gigaset_tab_nocid[] =
 
 /* misc. */
 {RSP_ERROR,	 -1,  -1, -1,			 -1, -1, {ACT_ERROR} },
-{RSP_ZCFGT,	 -1,  -1, -1,			 -1, -1, {ACT_DEBUG} },
-{RSP_ZCFG,	 -1,  -1, -1,			 -1, -1, {ACT_DEBUG} },
-{RSP_ZLOG,	 -1,  -1, -1,			 -1, -1, {ACT_DEBUG} },
-{RSP_ZMWI,	 -1,  -1, -1,			 -1, -1, {ACT_DEBUG} },
-{RSP_ZABINFO,	 -1,  -1, -1,			 -1, -1, {ACT_DEBUG} },
-{RSP_ZSMLSTCHG,	 -1,  -1, -1,			 -1, -1, {ACT_DEBUG} },
-
 {RSP_ZCAU,	 -1,  -1, -1,			 -1, -1, {ACT_ZCAU} },
 {RSP_NONE,	 -1,  -1, -1,			 -1, -1, {ACT_DEBUG} },
 {RSP_ANY,	 -1,  -1, -1,			 -1, -1, {ACT_WARN} },
@@ -363,10 +343,6 @@ struct reply_t gigaset_tab_cid[] =
 
 /* misc. */
 {RSP_ZCON,	 -1,  -1, -1,			 -1, -1, {ACT_DEBUG} },
-{RSP_ZCCR,	 -1,  -1, -1,			 -1, -1, {ACT_DEBUG} },
-{RSP_ZAOC,	 -1,  -1, -1,			 -1, -1, {ACT_DEBUG} },
-{RSP_ZCSTR,	 -1,  -1, -1,			 -1, -1, {ACT_DEBUG} },
-
 {RSP_ZCAU,	 -1,  -1, -1,			 -1, -1, {ACT_ZCAU} },
 {RSP_NONE,	 -1,  -1, -1,			 -1, -1, {ACT_DEBUG} },
 {RSP_ANY,	 -1,  -1, -1,			 -1, -1, {ACT_WARN} },
@@ -389,20 +365,11 @@ static const struct resp_type_t {
 	{"ZVLS",	RSP_ZVLS,	RT_NUMBER},
 	{"ZCTP",	RSP_ZCTP,	RT_NUMBER},
 	{"ZDLE",	RSP_ZDLE,	RT_NUMBER},
-	{"ZCFGT",	RSP_ZCFGT,	RT_NUMBER},
-	{"ZCCR",	RSP_ZCCR,	RT_NUMBER},
-	{"ZMWI",	RSP_ZMWI,	RT_NUMBER},
 	{"ZHLC",	RSP_ZHLC,	RT_STRING},
 	{"ZBC",		RSP_ZBC,	RT_STRING},
 	{"NMBR",	RSP_NMBR,	RT_STRING},
 	{"ZCPN",	RSP_ZCPN,	RT_STRING},
 	{"ZCON",	RSP_ZCON,	RT_STRING},
-	{"ZAOC",	RSP_ZAOC,	RT_STRING},
-	{"ZCSTR",	RSP_ZCSTR,	RT_STRING},
-	{"ZCFG",	RSP_ZCFG,	RT_HEX},
-	{"ZLOG",	RSP_ZLOG,	RT_NOTHING},
-	{"ZABINFO",	RSP_ZABINFO,	RT_NOTHING},
-	{"ZSMLSTCHG",	RSP_ZSMLSTCHG,	RT_NOTHING},
 	{NULL,		0,		0}
 };
 
@@ -590,10 +557,10 @@ void gigaset_handle_modem_response(struct cardstate *cs)
 					break;
 
 			if (!rt->response) {
-				event->type = RSP_UNKNOWN;
-				dev_warn(cs->dev,
-					 "unknown modem response: %s\n",
-					 argv[curarg]);
+				event->type = RSP_NONE;
+				gig_dbg(DEBUG_EVENT,
+					"unknown modem response: '%s'\n",
+					argv[curarg]);
 				break;
 			}
 
@@ -657,14 +624,8 @@ void gigaset_handle_modem_response(struct cardstate *cs)
 				curarg = params - 1;
 			break;
 		case RT_NUMBER:
-		case RT_HEX:
 			if (curarg < params) {
-				if (param_type == RT_HEX)
-					event->parameter =
-						isdn_gethex(argv[curarg]);
-				else
-					event->parameter =
-						isdn_getnum(argv[curarg]);
+				event->parameter = isdn_getnum(argv[curarg]);
 				++curarg;
 			} else
 				event->parameter = -1;
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 6afc300..3347470 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -198,9 +198,8 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
 /* variables in struct at_state_t */
 #define VAR_ZSAU	0
 #define VAR_ZDLE	1
-#define VAR_ZVLS	2
-#define VAR_ZCTP	3
-#define VAR_NUM		4
+#define VAR_ZCTP	2
+#define VAR_NUM		3
 
 #define STR_NMBR	0
 #define STR_ZCPN	1
-- 
1.6.5.3.298.g39add

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 7/7] isdn/gigaset: drop obsolete FIXME comment
       [not found] ` <20100522-patch-gigaset-00.tilman-ZTO5kqT2PaM@public.gmane.org>
                     ` (5 preceding siblings ...)
  2010-05-23  0:27   ` [PATCH 6/7] isdn/gigaset: ignore irrelevant device responses Tilman Schmidt
@ 2010-05-23  0:27   ` Tilman Schmidt
  6 siblings, 0 replies; 10+ messages in thread
From: Tilman Schmidt @ 2010-05-23  0:27 UTC (permalink / raw)
  To: Karsten Keil, David Miller
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, Karsten Keil, Hansjoerg Lipp,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	i4ldeveloper-JX7+OpRa80SjiSfgN6Y1Ib39b6g2fGNp

Drop a FIXME comment with nothing left to fix.

Impact: cosmetic
Signed-off-by: Tilman Schmidt <tilman-ZTO5kqT2PaM@public.gmane.org>
---
 drivers/isdn/gigaset/common.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index f6f45f2..32f5a2c 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -801,8 +801,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
 	spin_unlock_irqrestore(&cs->lock, flags);
 	setup_timer(&cs->timer, timer_tick, (unsigned long) cs);
 	cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK);
-	/* FIXME: can jiffies increase too much until the timer is added?
-	 * Same problem(?) with mod_timer() in timer_tick(). */
 	add_timer(&cs->timer);
 
 	gig_dbg(DEBUG_INIT, "cs initialized");
-- 
1.6.5.3.298.g39add

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/7] ISDN patches for 2.6.35
  2010-05-23  0:24 [PATCH 0/7] ISDN patches for 2.6.35 Tilman Schmidt
       [not found] ` <20100522-patch-gigaset-00.tilman-ZTO5kqT2PaM@public.gmane.org>
@ 2010-05-23  0:43 ` David Miller
  2010-05-23  1:02   ` Tilman Schmidt
  1 sibling, 1 reply; 10+ messages in thread
From: David Miller @ 2010-05-23  0:43 UTC (permalink / raw)
  To: tilman; +Cc: isdn, hjlipp, keil, i4ldeveloper, netdev, linux-kernel

From: Tilman Schmidt <tilman@imap.cc>
Date: Sun, 23 May 2010 02:24:12 +0200 (CEST)

> Karsten, David,
> 
> following are seven patches to the CAPI subsystem and the Gigaset
> driver I'd like to see included in kernel release 2.6.35.
> The first three respond to user reports about an observed hang of
> the userspace command "capiinit stop".
> The others are cleanups from the ongoing driver development.

What the heck about "no more cleanups or new features for networking"
do you not understand?

When the merge window is openned, this is not a signal to you to send
changes to me.  You should have stuff in weeks ahead of that time.

I'm willing to take bug fixes only at this point so you'll need to
respin this series.

And Tilman, of all people you really should know better.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/7] ISDN patches for 2.6.35
  2010-05-23  0:43 ` [PATCH 0/7] ISDN patches for 2.6.35 David Miller
@ 2010-05-23  1:02   ` Tilman Schmidt
  0 siblings, 0 replies; 10+ messages in thread
From: Tilman Schmidt @ 2010-05-23  1:02 UTC (permalink / raw)
  To: David Miller; +Cc: isdn, hjlipp, keil, i4ldeveloper, netdev, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 720 bytes --]

Am 23.05.2010 02:43 schrieb David Miller:
> What the heck about "no more cleanups or new features for networking"
> do you not understand?

Sorry, I must have missed the posting where you wrote this. I just
came back from a short holiday to find ~5k unread postings in LKML,
including the announcement of 2.6.34, and I guess I inadvertently
deleted the message you're referring to above.

> I'm willing to take bug fixes only at this point so you'll need to
> respin this series.

Will do.

Regards,
Tilman

-- 
Tilman Schmidt                    E-Mail: tilman@imap.cc
Bonn, Germany
Diese Nachricht besteht zu 100% aus wiederverwerteten Bits.
Ungeöffnet mindestens haltbar bis: (siehe Rückseite)


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 259 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2010-05-23  1:14 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-23  0:24 [PATCH 0/7] ISDN patches for 2.6.35 Tilman Schmidt
     [not found] ` <20100522-patch-gigaset-00.tilman-ZTO5kqT2PaM@public.gmane.org>
2010-05-23  0:24   ` [PATCH 1/7] Documentation/isdn: CAPI controller interface amendment Tilman Schmidt
2010-05-23  0:25   ` [PATCH 2/7] isdn/capi: make reset_ctr op truly optional Tilman Schmidt
2010-05-23  0:25   ` [PATCH 3/7] isdn/gigaset: remove dummy CAPI method implementations Tilman Schmidt
2010-05-23  0:26   ` [PATCH 4/7] isdn/gigaset: adjust usb_gigaset tty write buffer limit Tilman Schmidt
2010-05-23  0:26   ` [PATCH 5/7] isdn/gigaset: avoid copying AT commands twice Tilman Schmidt
2010-05-23  0:27   ` [PATCH 6/7] isdn/gigaset: ignore irrelevant device responses Tilman Schmidt
2010-05-23  0:27   ` [PATCH 7/7] isdn/gigaset: drop obsolete FIXME comment Tilman Schmidt
2010-05-23  0:43 ` [PATCH 0/7] ISDN patches for 2.6.35 David Miller
2010-05-23  1:02   ` Tilman Schmidt

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).