diff options
Diffstat (limited to 'drivers/isdn/gigaset')
-rw-r--r-- | drivers/isdn/gigaset/bas-gigaset.c | 118 |
1 files changed, 52 insertions, 66 deletions
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 63b629b1cdb2..b5e7f9c7d74e 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c | |||
@@ -1853,20 +1853,24 @@ static int gigaset_write_cmd(struct cardstate *cs, | |||
1853 | { | 1853 | { |
1854 | struct cmdbuf_t *cb; | 1854 | struct cmdbuf_t *cb; |
1855 | unsigned long flags; | 1855 | unsigned long flags; |
1856 | int status; | 1856 | int rc; |
1857 | 1857 | ||
1858 | gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? | 1858 | gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? |
1859 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, | 1859 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, |
1860 | "CMD Transmit", len, buf); | 1860 | "CMD Transmit", len, buf); |
1861 | 1861 | ||
1862 | if (len <= 0) | 1862 | if (len <= 0) { |
1863 | return 0; /* nothing to do */ | 1863 | /* nothing to do */ |
1864 | rc = 0; | ||
1865 | goto notqueued; | ||
1866 | } | ||
1864 | 1867 | ||
1865 | if (len > IF_WRITEBUF) | 1868 | if (len > IF_WRITEBUF) |
1866 | len = IF_WRITEBUF; | 1869 | len = IF_WRITEBUF; |
1867 | if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { | 1870 | if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { |
1868 | dev_err(cs->dev, "%s: out of memory\n", __func__); | 1871 | dev_err(cs->dev, "%s: out of memory\n", __func__); |
1869 | return -ENOMEM; | 1872 | rc = -ENOMEM; |
1873 | goto notqueued; | ||
1870 | } | 1874 | } |
1871 | 1875 | ||
1872 | memcpy(cb->buf, buf, len); | 1876 | memcpy(cb->buf, buf, len); |
@@ -1891,11 +1895,21 @@ static int gigaset_write_cmd(struct cardstate *cs, | |||
1891 | if (unlikely(!cs->connected)) { | 1895 | if (unlikely(!cs->connected)) { |
1892 | spin_unlock_irqrestore(&cs->lock, flags); | 1896 | spin_unlock_irqrestore(&cs->lock, flags); |
1893 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); | 1897 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); |
1898 | /* flush command queue */ | ||
1899 | spin_lock_irqsave(&cs->cmdlock, flags); | ||
1900 | while (cs->cmdbuf != NULL) | ||
1901 | complete_cb(cs); | ||
1902 | spin_unlock_irqrestore(&cs->cmdlock, flags); | ||
1894 | return -ENODEV; | 1903 | return -ENODEV; |
1895 | } | 1904 | } |
1896 | status = start_cbsend(cs); | 1905 | rc = start_cbsend(cs); |
1897 | spin_unlock_irqrestore(&cs->lock, flags); | 1906 | spin_unlock_irqrestore(&cs->lock, flags); |
1898 | return status < 0 ? status : len; | 1907 | return rc < 0 ? rc : len; |
1908 | |||
1909 | notqueued: /* request handled without queuing */ | ||
1910 | if (wake_tasklet) | ||
1911 | tasklet_schedule(wake_tasklet); | ||
1912 | return rc; | ||
1899 | } | 1913 | } |
1900 | 1914 | ||
1901 | /* gigaset_write_room | 1915 | /* gigaset_write_room |
@@ -1964,20 +1978,15 @@ static int gigaset_freebcshw(struct bc_state *bcs) | |||
1964 | 1978 | ||
1965 | /* kill URBs and tasklets before freeing - better safe than sorry */ | 1979 | /* kill URBs and tasklets before freeing - better safe than sorry */ |
1966 | atomic_set(&ubc->running, 0); | 1980 | atomic_set(&ubc->running, 0); |
1967 | for (i = 0; i < BAS_OUTURBS; ++i) | 1981 | gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__); |
1968 | if (ubc->isoouturbs[i].urb) { | 1982 | for (i = 0; i < BAS_OUTURBS; ++i) { |
1969 | gig_dbg(DEBUG_INIT, "%s: killing iso out URB %d", | 1983 | usb_kill_urb(ubc->isoouturbs[i].urb); |
1970 | __func__, i); | 1984 | usb_free_urb(ubc->isoouturbs[i].urb); |
1971 | usb_kill_urb(ubc->isoouturbs[i].urb); | 1985 | } |
1972 | usb_free_urb(ubc->isoouturbs[i].urb); | 1986 | for (i = 0; i < BAS_INURBS; ++i) { |
1973 | } | 1987 | usb_kill_urb(ubc->isoinurbs[i]); |
1974 | for (i = 0; i < BAS_INURBS; ++i) | 1988 | usb_free_urb(ubc->isoinurbs[i]); |
1975 | if (ubc->isoinurbs[i]) { | 1989 | } |
1976 | gig_dbg(DEBUG_INIT, "%s: killing iso in URB %d", | ||
1977 | __func__, i); | ||
1978 | usb_kill_urb(ubc->isoinurbs[i]); | ||
1979 | usb_free_urb(ubc->isoinurbs[i]); | ||
1980 | } | ||
1981 | tasklet_kill(&ubc->sent_tasklet); | 1990 | tasklet_kill(&ubc->sent_tasklet); |
1982 | tasklet_kill(&ubc->rcvd_tasklet); | 1991 | tasklet_kill(&ubc->rcvd_tasklet); |
1983 | kfree(ubc->isooutbuf); | 1992 | kfree(ubc->isooutbuf); |
@@ -2099,55 +2108,32 @@ static void freeurbs(struct cardstate *cs) | |||
2099 | struct bas_bc_state *ubc; | 2108 | struct bas_bc_state *ubc; |
2100 | int i, j; | 2109 | int i, j; |
2101 | 2110 | ||
2111 | gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__); | ||
2102 | for (j = 0; j < 2; ++j) { | 2112 | for (j = 0; j < 2; ++j) { |
2103 | ubc = cs->bcs[j].hw.bas; | 2113 | ubc = cs->bcs[j].hw.bas; |
2104 | for (i = 0; i < BAS_OUTURBS; ++i) | 2114 | for (i = 0; i < BAS_OUTURBS; ++i) { |
2105 | if (ubc->isoouturbs[i].urb) { | 2115 | usb_kill_urb(ubc->isoouturbs[i].urb); |
2106 | usb_kill_urb(ubc->isoouturbs[i].urb); | 2116 | usb_free_urb(ubc->isoouturbs[i].urb); |
2107 | gig_dbg(DEBUG_INIT, | 2117 | ubc->isoouturbs[i].urb = NULL; |
2108 | "%s: isoc output URB %d/%d unlinked", | 2118 | } |
2109 | __func__, j, i); | 2119 | for (i = 0; i < BAS_INURBS; ++i) { |
2110 | usb_free_urb(ubc->isoouturbs[i].urb); | 2120 | usb_kill_urb(ubc->isoinurbs[i]); |
2111 | ubc->isoouturbs[i].urb = NULL; | 2121 | usb_free_urb(ubc->isoinurbs[i]); |
2112 | } | 2122 | ubc->isoinurbs[i] = NULL; |
2113 | for (i = 0; i < BAS_INURBS; ++i) | 2123 | } |
2114 | if (ubc->isoinurbs[i]) { | ||
2115 | usb_kill_urb(ubc->isoinurbs[i]); | ||
2116 | gig_dbg(DEBUG_INIT, | ||
2117 | "%s: isoc input URB %d/%d unlinked", | ||
2118 | __func__, j, i); | ||
2119 | usb_free_urb(ubc->isoinurbs[i]); | ||
2120 | ubc->isoinurbs[i] = NULL; | ||
2121 | } | ||
2122 | } | ||
2123 | if (ucs->urb_int_in) { | ||
2124 | usb_kill_urb(ucs->urb_int_in); | ||
2125 | gig_dbg(DEBUG_INIT, "%s: interrupt input URB unlinked", | ||
2126 | __func__); | ||
2127 | usb_free_urb(ucs->urb_int_in); | ||
2128 | ucs->urb_int_in = NULL; | ||
2129 | } | ||
2130 | if (ucs->urb_cmd_out) { | ||
2131 | usb_kill_urb(ucs->urb_cmd_out); | ||
2132 | gig_dbg(DEBUG_INIT, "%s: command output URB unlinked", | ||
2133 | __func__); | ||
2134 | usb_free_urb(ucs->urb_cmd_out); | ||
2135 | ucs->urb_cmd_out = NULL; | ||
2136 | } | ||
2137 | if (ucs->urb_cmd_in) { | ||
2138 | usb_kill_urb(ucs->urb_cmd_in); | ||
2139 | gig_dbg(DEBUG_INIT, "%s: command input URB unlinked", | ||
2140 | __func__); | ||
2141 | usb_free_urb(ucs->urb_cmd_in); | ||
2142 | ucs->urb_cmd_in = NULL; | ||
2143 | } | ||
2144 | if (ucs->urb_ctrl) { | ||
2145 | usb_kill_urb(ucs->urb_ctrl); | ||
2146 | gig_dbg(DEBUG_INIT, "%s: control output URB unlinked", | ||
2147 | __func__); | ||
2148 | usb_free_urb(ucs->urb_ctrl); | ||
2149 | ucs->urb_ctrl = NULL; | ||
2150 | } | 2124 | } |
2125 | usb_kill_urb(ucs->urb_int_in); | ||
2126 | usb_free_urb(ucs->urb_int_in); | ||
2127 | ucs->urb_int_in = NULL; | ||
2128 | usb_kill_urb(ucs->urb_cmd_out); | ||
2129 | usb_free_urb(ucs->urb_cmd_out); | ||
2130 | ucs->urb_cmd_out = NULL; | ||
2131 | usb_kill_urb(ucs->urb_cmd_in); | ||
2132 | usb_free_urb(ucs->urb_cmd_in); | ||
2133 | ucs->urb_cmd_in = NULL; | ||
2134 | usb_kill_urb(ucs->urb_ctrl); | ||
2135 | usb_free_urb(ucs->urb_ctrl); | ||
2136 | ucs->urb_ctrl = NULL; | ||
2151 | } | 2137 | } |
2152 | 2138 | ||
2153 | /* gigaset_probe | 2139 | /* gigaset_probe |