aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/atm/ueagle-atm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/atm/ueagle-atm.c')
-rw-r--r--drivers/usb/atm/ueagle-atm.c31
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
2044static void uea_schedule_load_page_e4(struct uea_softc *sc, struct intr_pkt *intr) 2045static 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
2159err2: 2166err2:
2160 usb_kill_urb(sc->urb_int); 2167 usb_kill_urb(sc->urb_int);
2161err: 2168err1:
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);
2172err0:
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));