aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/atm/ueagle-atm.c
diff options
context:
space:
mode:
authorStanislaw Gruszka <stf_xl@wp.pl>2007-08-20 17:21:10 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-10-12 17:55:17 -0400
commit04ea02f5746a2e01a38edae2de3eafc40eac17aa (patch)
tree07e2276adebcd5df23a73b755a885bdf95d83d5d /drivers/usb/atm/ueagle-atm.c
parent503add467d4dd2355fe16ebffa7f6d5e9fcd10a8 (diff)
UEAGLE: Avoid keyboard driver blocking
Ueagle-atm driver load DSP firmware in function, which is running from common workqueue. In some (error) circumstances loading firmware may sleep for long periods (even 60 seconds, depending on timeout). This block keyboard driver, which also use common workqueue. To fix problem use custom workqueue in ueagle-atm. Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
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 dee5f798946..648c6b79ff4 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));