diff options
author | Tilman Schmidt <tilman@imap.cc> | 2010-07-05 10:18:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-07-07 19:57:51 -0400 |
commit | e3628dd176ba3ed329991ef042c29aae60617630 (patch) | |
tree | 77e47e95ba38276557702a5bfc8e319bc9100b7c /drivers/isdn/gigaset/bas-gigaset.c | |
parent | b3251d8045f87eec5d565603345d262cee134fa6 (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/gigaset/bas-gigaset.c')
-rw-r--r-- | drivers/isdn/gigaset/bas-gigaset.c | 51 |
1 files changed, 11 insertions, 40 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 | */ |
1924 | static int gigaset_write_cmd(struct cardstate *cs, | 1921 | static 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 | |||
1993 | notqueued: /* 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 |