diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/atm/ueagle-atm.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index dee5f798946c..648c6b79ff41 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c | |||
@@ -167,6 +167,7 @@ struct uea_softc { | |||
167 | union cmv_dsc cmv_dsc; | 167 | union cmv_dsc cmv_dsc; |
168 | 168 | ||
169 | struct work_struct task; | 169 | struct work_struct task; |
170 | struct workqueue_struct *work_q; | ||
170 | u16 pageno; | 171 | u16 pageno; |
171 | u16 ovl; | 172 | u16 ovl; |
172 | 173 | ||
@@ -1830,7 +1831,7 @@ static int uea_start_reset(struct uea_softc *sc) | |||
1830 | /* start loading DSP */ | 1831 | /* start loading DSP */ |
1831 | sc->pageno = 0; | 1832 | sc->pageno = 0; |
1832 | sc->ovl = 0; | 1833 | sc->ovl = 0; |
1833 | schedule_work(&sc->task); | 1834 | queue_work(sc->work_q, &sc->task); |
1834 | 1835 | ||
1835 | /* wait for modem ready CMV */ | 1836 | /* wait for modem ready CMV */ |
1836 | ret = wait_cmv_ack(sc); | 1837 | ret = wait_cmv_ack(sc); |
@@ -2038,13 +2039,13 @@ static void uea_schedule_load_page_e1(struct uea_softc *sc, struct intr_pkt *int | |||
2038 | { | 2039 | { |
2039 | sc->pageno = intr->e1_bSwapPageNo; | 2040 | sc->pageno = intr->e1_bSwapPageNo; |
2040 | sc->ovl = intr->e1_bOvl >> 4 | intr->e1_bOvl << 4; | 2041 | sc->ovl = intr->e1_bOvl >> 4 | intr->e1_bOvl << 4; |
2041 | schedule_work(&sc->task); | 2042 | queue_work(sc->work_q, &sc->task); |
2042 | } | 2043 | } |
2043 | 2044 | ||
2044 | static void uea_schedule_load_page_e4(struct uea_softc *sc, struct intr_pkt *intr) | 2045 | static void uea_schedule_load_page_e4(struct uea_softc *sc, struct intr_pkt *intr) |
2045 | { | 2046 | { |
2046 | sc->pageno = intr->e4_bSwapPageNo; | 2047 | sc->pageno = intr->e4_bSwapPageNo; |
2047 | schedule_work(&sc->task); | 2048 | queue_work(sc->work_q, &sc->task); |
2048 | } | 2049 | } |
2049 | 2050 | ||
2050 | /* | 2051 | /* |
@@ -2117,6 +2118,13 @@ static int uea_boot(struct uea_softc *sc) | |||
2117 | init_waitqueue_head(&sc->sync_q); | 2118 | init_waitqueue_head(&sc->sync_q); |
2118 | init_waitqueue_head(&sc->cmv_ack_wait); | 2119 | init_waitqueue_head(&sc->cmv_ack_wait); |
2119 | 2120 | ||
2121 | sc->work_q = create_workqueue("ueagle-dsp"); | ||
2122 | if (!sc->work_q) { | ||
2123 | uea_err(INS_TO_USBDEV(sc), "cannot allocate workqueue\n"); | ||
2124 | uea_leaves(INS_TO_USBDEV(sc)); | ||
2125 | return -ENOMEM; | ||
2126 | } | ||
2127 | |||
2120 | if (UEA_CHIP_VERSION(sc) == ADI930) | 2128 | if (UEA_CHIP_VERSION(sc) == ADI930) |
2121 | load_XILINX_firmware(sc); | 2129 | load_XILINX_firmware(sc); |
2122 | 2130 | ||
@@ -2124,14 +2132,13 @@ static int uea_boot(struct uea_softc *sc) | |||
2124 | if (!intr) { | 2132 | if (!intr) { |
2125 | uea_err(INS_TO_USBDEV(sc), | 2133 | uea_err(INS_TO_USBDEV(sc), |
2126 | "cannot allocate interrupt package\n"); | 2134 | "cannot allocate interrupt package\n"); |
2127 | uea_leaves(INS_TO_USBDEV(sc)); | 2135 | goto err0; |
2128 | return -ENOMEM; | ||
2129 | } | 2136 | } |
2130 | 2137 | ||
2131 | sc->urb_int = usb_alloc_urb(0, GFP_KERNEL); | 2138 | sc->urb_int = usb_alloc_urb(0, GFP_KERNEL); |
2132 | if (!sc->urb_int) { | 2139 | if (!sc->urb_int) { |
2133 | uea_err(INS_TO_USBDEV(sc), "cannot allocate interrupt URB\n"); | 2140 | uea_err(INS_TO_USBDEV(sc), "cannot allocate interrupt URB\n"); |
2134 | goto err; | 2141 | goto err1; |
2135 | } | 2142 | } |
2136 | 2143 | ||
2137 | usb_fill_int_urb(sc->urb_int, sc->usb_dev, | 2144 | usb_fill_int_urb(sc->urb_int, sc->usb_dev, |
@@ -2144,7 +2151,7 @@ static int uea_boot(struct uea_softc *sc) | |||
2144 | if (ret < 0) { | 2151 | if (ret < 0) { |
2145 | uea_err(INS_TO_USBDEV(sc), | 2152 | uea_err(INS_TO_USBDEV(sc), |
2146 | "urb submition failed with error %d\n", ret); | 2153 | "urb submition failed with error %d\n", ret); |
2147 | goto err; | 2154 | goto err1; |
2148 | } | 2155 | } |
2149 | 2156 | ||
2150 | sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm"); | 2157 | sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm"); |
@@ -2158,10 +2165,12 @@ static int uea_boot(struct uea_softc *sc) | |||
2158 | 2165 | ||
2159 | err2: | 2166 | err2: |
2160 | usb_kill_urb(sc->urb_int); | 2167 | usb_kill_urb(sc->urb_int); |
2161 | err: | 2168 | err1: |
2162 | usb_free_urb(sc->urb_int); | 2169 | usb_free_urb(sc->urb_int); |
2163 | sc->urb_int = NULL; | 2170 | sc->urb_int = NULL; |
2164 | kfree(intr); | 2171 | kfree(intr); |
2172 | err0: | ||
2173 | destroy_workqueue(sc->work_q); | ||
2165 | uea_leaves(INS_TO_USBDEV(sc)); | 2174 | uea_leaves(INS_TO_USBDEV(sc)); |
2166 | return -ENOMEM; | 2175 | return -ENOMEM; |
2167 | } | 2176 | } |
@@ -2176,15 +2185,15 @@ static void uea_stop(struct uea_softc *sc) | |||
2176 | ret = kthread_stop(sc->kthread); | 2185 | ret = kthread_stop(sc->kthread); |
2177 | uea_dbg(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret); | 2186 | uea_dbg(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret); |
2178 | 2187 | ||
2179 | /* stop any pending boot process */ | ||
2180 | flush_scheduled_work(); | ||
2181 | |||
2182 | uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL); | 2188 | uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL); |
2183 | 2189 | ||
2184 | usb_kill_urb(sc->urb_int); | 2190 | usb_kill_urb(sc->urb_int); |
2185 | kfree(sc->urb_int->transfer_buffer); | 2191 | kfree(sc->urb_int->transfer_buffer); |
2186 | usb_free_urb(sc->urb_int); | 2192 | usb_free_urb(sc->urb_int); |
2187 | 2193 | ||
2194 | /* stop any pending boot process, when no one can schedule work */ | ||
2195 | destroy_workqueue(sc->work_q); | ||
2196 | |||
2188 | if (sc->dsp_firm) | 2197 | if (sc->dsp_firm) |
2189 | release_firmware(sc->dsp_firm); | 2198 | release_firmware(sc->dsp_firm); |
2190 | uea_leaves(INS_TO_USBDEV(sc)); | 2199 | uea_leaves(INS_TO_USBDEV(sc)); |