aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
authorTilman Schmidt <tilman@imap.cc>2010-07-05 10:18:43 -0400
committerDavid S. Miller <davem@davemloft.net>2010-07-07 19:57:51 -0400
commite3628dd176ba3ed329991ef042c29aae60617630 (patch)
tree77e47e95ba38276557702a5bfc8e319bc9100b7c /drivers/isdn
parentb3251d8045f87eec5d565603345d262cee134fa6 (diff)
isdn/gigaset: avoid copying AT commands twice
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@imap.cc> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c51
-rw-r--r--drivers/isdn/gigaset/ev-layer.c75
-rw-r--r--drivers/isdn/gigaset/gigaset.h4
-rw-r--r--drivers/isdn/gigaset/interface.c36
-rw-r--r--drivers/isdn/gigaset/ser-gigaset.c27
-rw-r--r--drivers/isdn/gigaset/usb-gigaset.c26
6 files changed, 85 insertions, 134 deletions
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 47a5ffec55a3..2dab5313913b 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)
1913 * USB transmission is started if necessary. 1913 * USB transmission is started if necessary.
1914 * parameters: 1914 * parameters:
1915 * cs controller state structure 1915 * cs controller state structure
1916 * buf command string to send 1916 * cb command buffer structure
1917 * len number of bytes to send (max. IF_WRITEBUF)
1918 * wake_tasklet tasklet to run when transmission is completed
1919 * (NULL if none)
1920 * return value: 1917 * return value:
1921 * number of bytes queued on success 1918 * number of bytes queued on success
1922 * error code < 0 on error 1919 * error code < 0 on error
1923 */ 1920 */
1924static int gigaset_write_cmd(struct cardstate *cs, 1921static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb)
1925 const unsigned char *buf, int len,
1926 struct tasklet_struct *wake_tasklet)
1927{ 1922{
1928 struct cmdbuf_t *cb;
1929 unsigned long flags; 1923 unsigned long flags;
1930 int rc; 1924 int rc;
1931 1925
1932 gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? 1926 gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
1933 DEBUG_TRANSCMD : DEBUG_LOCKCMD, 1927 DEBUG_TRANSCMD : DEBUG_LOCKCMD,
1934 "CMD Transmit", len, buf); 1928 "CMD Transmit", cb->len, cb->buf);
1935
1936 if (len <= 0) {
1937 /* nothing to do */
1938 rc = 0;
1939 goto notqueued;
1940 }
1941 1929
1942 /* translate "+++" escape sequence sent as a single separate command 1930 /* translate "+++" escape sequence sent as a single separate command
1943 * into "close AT channel" command for error recovery 1931 * into "close AT channel" command for error recovery
1944 * The next command will reopen the AT channel automatically. 1932 * The next command will reopen the AT channel automatically.
1945 */ 1933 */
1946 if (len == 3 && !memcmp(buf, "+++", 3)) { 1934 if (cb->len == 3 && !memcmp(cb->buf, "+++", 3)) {
1935 kfree(cb);
1947 rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT); 1936 rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT);
1948 goto notqueued; 1937 if (cb->wake_tasklet)
1949 } 1938 tasklet_schedule(cb->wake_tasklet);
1950 1939 return rc < 0 ? rc : cb->len;
1951 if (len > IF_WRITEBUF)
1952 len = IF_WRITEBUF;
1953 cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
1954 if (!cb) {
1955 dev_err(cs->dev, "%s: out of memory\n", __func__);
1956 rc = -ENOMEM;
1957 goto notqueued;
1958 } 1940 }
1959 1941
1960 memcpy(cb->buf, buf, len);
1961 cb->len = len;
1962 cb->offset = 0;
1963 cb->next = NULL;
1964 cb->wake_tasklet = wake_tasklet;
1965
1966 spin_lock_irqsave(&cs->cmdlock, flags); 1942 spin_lock_irqsave(&cs->cmdlock, flags);
1967 cb->prev = cs->lastcmdbuf; 1943 cb->prev = cs->lastcmdbuf;
1968 if (cs->lastcmdbuf) 1944 if (cs->lastcmdbuf)
1969 cs->lastcmdbuf->next = cb; 1945 cs->lastcmdbuf->next = cb;
1970 else { 1946 else {
1971 cs->cmdbuf = cb; 1947 cs->cmdbuf = cb;
1972 cs->curlen = len; 1948 cs->curlen = cb->len;
1973 } 1949 }
1974 cs->cmdbytes += len; 1950 cs->cmdbytes += cb->len;
1975 cs->lastcmdbuf = cb; 1951 cs->lastcmdbuf = cb;
1976 spin_unlock_irqrestore(&cs->cmdlock, flags); 1952 spin_unlock_irqrestore(&cs->cmdlock, flags);
1977 1953
@@ -1988,12 +1964,7 @@ static int gigaset_write_cmd(struct cardstate *cs,
1988 } 1964 }
1989 rc = start_cbsend(cs); 1965 rc = start_cbsend(cs);
1990 spin_unlock_irqrestore(&cs->lock, flags); 1966 spin_unlock_irqrestore(&cs->lock, flags);
1991 return rc < 0 ? rc : len; 1967 return rc < 0 ? rc : cb->len;
1992
1993notqueued: /* request handled without queuing */
1994 if (wake_tasklet)
1995 tasklet_schedule(wake_tasklet);
1996 return rc;
1997} 1968}
1998 1969
1999/* gigaset_write_room 1970/* gigaset_write_room
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index ceaef9a04a42..0d5984a86795 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -797,48 +797,27 @@ static void schedule_init(struct cardstate *cs, int state)
797static void send_command(struct cardstate *cs, const char *cmd, int cid, 797static void send_command(struct cardstate *cs, const char *cmd, int cid,
798 int dle, gfp_t kmallocflags) 798 int dle, gfp_t kmallocflags)
799{ 799{
800 size_t cmdlen, buflen; 800 struct cmdbuf_t *cb;
801 char *cmdpos, *cmdbuf, *cmdtail; 801 size_t buflen;
802 802
803 cmdlen = strlen(cmd); 803 buflen = strlen(cmd) + 12; /* DLE ( A T 1 2 3 4 5 <cmd> DLE ) \0 */
804 buflen = 11 + cmdlen; 804 cb = kmalloc(sizeof(struct cmdbuf_t) + buflen, kmallocflags);
805 if (unlikely(buflen <= cmdlen)) { 805 if (!cb) {
806 dev_err(cs->dev, "integer overflow in buflen\n"); 806 dev_err(cs->dev, "%s: out of memory\n", __func__);
807 return; 807 return;
808 } 808 }
809 809 if (cid > 0 && cid <= 65535)
810 cmdbuf = kmalloc(buflen, kmallocflags); 810 cb->len = snprintf(cb->buf, buflen,
811 if (unlikely(!cmdbuf)) { 811 dle ? "\020(AT%d%s\020)" : "AT%d%s",
812 dev_err(cs->dev, "out of memory\n"); 812 cid, cmd);
813 return; 813 else
814 } 814 cb->len = snprintf(cb->buf, buflen,
815 815 dle ? "\020(AT%s\020)" : "AT%s",
816 cmdpos = cmdbuf + 9; 816 cmd);
817 cmdtail = cmdpos + cmdlen; 817 cb->offset = 0;
818 memcpy(cmdpos, cmd, cmdlen); 818 cb->next = NULL;
819 819 cb->wake_tasklet = NULL;
820 if (cid > 0 && cid <= 65535) { 820 cs->ops->write_cmd(cs, cb);
821 do {
822 *--cmdpos = '0' + cid % 10;
823 cid /= 10;
824 ++cmdlen;
825 } while (cid);
826 }
827
828 cmdlen += 2;
829 *--cmdpos = 'T';
830 *--cmdpos = 'A';
831
832 if (dle) {
833 cmdlen += 4;
834 *--cmdpos = '(';
835 *--cmdpos = 0x10;
836 *cmdtail++ = 0x10;
837 *cmdtail++ = ')';
838 }
839
840 cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL);
841 kfree(cmdbuf);
842} 821}
843 822
844static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid) 823static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid)
@@ -1240,8 +1219,22 @@ static void do_action(int action, struct cardstate *cs,
1240 break; 1219 break;
1241 case ACT_HUPMODEM: 1220 case ACT_HUPMODEM:
1242 /* send "+++" (hangup in unimodem mode) */ 1221 /* send "+++" (hangup in unimodem mode) */
1243 if (cs->connected) 1222 if (cs->connected) {
1244 cs->ops->write_cmd(cs, "+++", 3, NULL); 1223 struct cmdbuf_t *cb;
1224
1225 cb = kmalloc(sizeof(struct cmdbuf_t) + 3, GFP_ATOMIC);
1226 if (!cb) {
1227 dev_err(cs->dev, "%s: out of memory\n",
1228 __func__);
1229 return;
1230 }
1231 memcpy(cb->buf, "+++", 3);
1232 cb->len = 3;
1233 cb->offset = 0;
1234 cb->next = NULL;
1235 cb->wake_tasklet = NULL;
1236 cs->ops->write_cmd(cs, cb);
1237 }
1245 break; 1238 break;
1246 case ACT_RING: 1239 case ACT_RING:
1247 /* get fresh AT state structure for new CID */ 1240 /* get fresh AT state structure for new CID */
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 8738b0821fc9..904c9473effc 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -574,9 +574,7 @@ struct bas_bc_state {
574struct gigaset_ops { 574struct gigaset_ops {
575 /* Called from ev-layer.c/interface.c for sending AT commands to the 575 /* Called from ev-layer.c/interface.c for sending AT commands to the
576 device */ 576 device */
577 int (*write_cmd)(struct cardstate *cs, 577 int (*write_cmd)(struct cardstate *cs, struct cmdbuf_t *cb);
578 const unsigned char *buf, int len,
579 struct tasklet_struct *wake_tasklet);
580 578
581 /* Called from interface.c for additional device control */ 579 /* Called from interface.c for additional device control */
582 int (*write_room)(struct cardstate *cs); 580 int (*write_room)(struct cardstate *cs);
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index c9f28dd40d5c..f45d68620161 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,
339static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) 339static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
340{ 340{
341 struct cardstate *cs; 341 struct cardstate *cs;
342 int retval = -ENODEV; 342 struct cmdbuf_t *cb;
343 int retval;
343 344
344 cs = (struct cardstate *) tty->driver_data; 345 cs = (struct cardstate *) tty->driver_data;
345 if (!cs) { 346 if (!cs) {
@@ -355,18 +356,39 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
355 if (!cs->connected) { 356 if (!cs->connected) {
356 gig_dbg(DEBUG_IF, "not connected"); 357 gig_dbg(DEBUG_IF, "not connected");
357 retval = -ENODEV; 358 retval = -ENODEV;
358 } else if (!cs->open_count) 359 goto done;
360 }
361 if (!cs->open_count) {
359 dev_warn(cs->dev, "%s: device not opened\n", __func__); 362 dev_warn(cs->dev, "%s: device not opened\n", __func__);
360 else if (cs->mstate != MS_LOCKED) { 363 retval = -ENODEV;
364 goto done;
365 }
366 if (cs->mstate != MS_LOCKED) {
361 dev_warn(cs->dev, "can't write to unlocked device\n"); 367 dev_warn(cs->dev, "can't write to unlocked device\n");
362 retval = -EBUSY; 368 retval = -EBUSY;
363 } else { 369 goto done;
364 retval = cs->ops->write_cmd(cs, buf, count, 370 }
365 &cs->if_wake_tasklet); 371 if (count <= 0) {
372 /* nothing to do */
373 retval = 0;
374 goto done;
366 } 375 }
367 376
368 mutex_unlock(&cs->mutex); 377 cb = kmalloc(sizeof(struct cmdbuf_t) + count, GFP_KERNEL);
378 if (!cb) {
379 dev_err(cs->dev, "%s: out of memory\n", __func__);
380 retval = -ENOMEM;
381 goto done;
382 }
369 383
384 memcpy(cb->buf, buf, count);
385 cb->len = count;
386 cb->offset = 0;
387 cb->next = NULL;
388 cb->wake_tasklet = &cs->if_wake_tasklet;
389 retval = cs->ops->write_cmd(cs, cb);
390done:
391 mutex_unlock(&cs->mutex);
370 return retval; 392 return retval;
371} 393}
372 394
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index e96c0586886c..d151dcbf770d 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)
241 * return value: 241 * return value:
242 * number of bytes queued, or error code < 0 242 * number of bytes queued, or error code < 0
243 */ 243 */
244static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, 244static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb)
245 int len, struct tasklet_struct *wake_tasklet)
246{ 245{
247 struct cmdbuf_t *cb;
248 unsigned long flags; 246 unsigned long flags;
249 247
250 gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? 248 gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
251 DEBUG_TRANSCMD : DEBUG_LOCKCMD, 249 DEBUG_TRANSCMD : DEBUG_LOCKCMD,
252 "CMD Transmit", len, buf); 250 "CMD Transmit", cb->len, cb->buf);
253
254 if (len <= 0)
255 return 0;
256
257 cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
258 if (!cb) {
259 dev_err(cs->dev, "%s: out of memory!\n", __func__);
260 return -ENOMEM;
261 }
262
263 memcpy(cb->buf, buf, len);
264 cb->len = len;
265 cb->offset = 0;
266 cb->next = NULL;
267 cb->wake_tasklet = wake_tasklet;
268 251
269 spin_lock_irqsave(&cs->cmdlock, flags); 252 spin_lock_irqsave(&cs->cmdlock, flags);
270 cb->prev = cs->lastcmdbuf; 253 cb->prev = cs->lastcmdbuf;
@@ -272,9 +255,9 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
272 cs->lastcmdbuf->next = cb; 255 cs->lastcmdbuf->next = cb;
273 else { 256 else {
274 cs->cmdbuf = cb; 257 cs->cmdbuf = cb;
275 cs->curlen = len; 258 cs->curlen = cb->len;
276 } 259 }
277 cs->cmdbytes += len; 260 cs->cmdbytes += cb->len;
278 cs->lastcmdbuf = cb; 261 cs->lastcmdbuf = cb;
279 spin_unlock_irqrestore(&cs->cmdlock, flags); 262 spin_unlock_irqrestore(&cs->cmdlock, flags);
280 263
@@ -282,7 +265,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
282 if (cs->connected) 265 if (cs->connected)
283 tasklet_schedule(&cs->write_tasklet); 266 tasklet_schedule(&cs->write_tasklet);
284 spin_unlock_irqrestore(&cs->lock, flags); 267 spin_unlock_irqrestore(&cs->lock, flags);
285 return len; 268 return cb->len;
286} 269}
287 270
288/* 271/*
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index f65cf7db216b..4a66338f4e7d 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)
494} 494}
495 495
496/* Send command to device. */ 496/* Send command to device. */
497static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, 497static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb)
498 int len, struct tasklet_struct *wake_tasklet)
499{ 498{
500 struct cmdbuf_t *cb;
501 unsigned long flags; 499 unsigned long flags;
502 500
503 gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? 501 gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
504 DEBUG_TRANSCMD : DEBUG_LOCKCMD, 502 DEBUG_TRANSCMD : DEBUG_LOCKCMD,
505 "CMD Transmit", len, buf); 503 "CMD Transmit", cb->len, cb->buf);
506
507 if (len <= 0)
508 return 0;
509 cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
510 if (!cb) {
511 dev_err(cs->dev, "%s: out of memory\n", __func__);
512 return -ENOMEM;
513 }
514
515 memcpy(cb->buf, buf, len);
516 cb->len = len;
517 cb->offset = 0;
518 cb->next = NULL;
519 cb->wake_tasklet = wake_tasklet;
520 504
521 spin_lock_irqsave(&cs->cmdlock, flags); 505 spin_lock_irqsave(&cs->cmdlock, flags);
522 cb->prev = cs->lastcmdbuf; 506 cb->prev = cs->lastcmdbuf;
@@ -524,9 +508,9 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
524 cs->lastcmdbuf->next = cb; 508 cs->lastcmdbuf->next = cb;
525 else { 509 else {
526 cs->cmdbuf = cb; 510 cs->cmdbuf = cb;
527 cs->curlen = len; 511 cs->curlen = cb->len;
528 } 512 }
529 cs->cmdbytes += len; 513 cs->cmdbytes += cb->len;
530 cs->lastcmdbuf = cb; 514 cs->lastcmdbuf = cb;
531 spin_unlock_irqrestore(&cs->cmdlock, flags); 515 spin_unlock_irqrestore(&cs->cmdlock, flags);
532 516
@@ -534,7 +518,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
534 if (cs->connected) 518 if (cs->connected)
535 tasklet_schedule(&cs->write_tasklet); 519 tasklet_schedule(&cs->write_tasklet);
536 spin_unlock_irqrestore(&cs->lock, flags); 520 spin_unlock_irqrestore(&cs->lock, flags);
537 return len; 521 return cb->len;
538} 522}
539 523
540static int gigaset_write_room(struct cardstate *cs) 524static int gigaset_write_room(struct cardstate *cs)