aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
authorTilman Schmidt <tilman@imap.cc>2006-12-13 03:33:52 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-13 12:05:47 -0500
commit39f07223d400330b9e08aae4c77a391f2418023e (patch)
tree7e16bd15b0e4d87809024302df9c4a1d65a2d832 /drivers/isdn
parenteff3b634d9a0cccb6ca8b431819fa415f10804dc (diff)
[PATCH] isdn/gigaset: fix possible missing wakeup
Eliminate some possibilities for user processes writing to the Gigaset character device to be left sleeping indefinitely, by adding wakeup calls to error paths and properly disposing of pending write requests when the device is disconnected. It also removes unnecessary NULL checks before usb_free_urb() and usb_kill_urb() calls. Signed-off-by: Tilman Schmidt <tilman@imap.cc> Acked-by: Karsten Keil <kkeil@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c118
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
1909notqueued: /* 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