diff options
Diffstat (limited to 'drivers/usb/atm/ueagle-atm.c')
-rw-r--r-- | drivers/usb/atm/ueagle-atm.c | 56 |
1 files changed, 31 insertions, 25 deletions
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index ea071a5b6eee..e71521ce3010 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c | |||
@@ -168,7 +168,6 @@ struct uea_softc { | |||
168 | union cmv_dsc cmv_dsc; | 168 | union cmv_dsc cmv_dsc; |
169 | 169 | ||
170 | struct work_struct task; | 170 | struct work_struct task; |
171 | struct workqueue_struct *work_q; | ||
172 | u16 pageno; | 171 | u16 pageno; |
173 | u16 ovl; | 172 | u16 ovl; |
174 | 173 | ||
@@ -1284,7 +1283,7 @@ static void uea_set_bulk_timeout(struct uea_softc *sc, u32 dsrate) | |||
1284 | 1283 | ||
1285 | /* in bulk mode the modem have problem with high rate | 1284 | /* in bulk mode the modem have problem with high rate |
1286 | * changing internal timing could improve things, but the | 1285 | * changing internal timing could improve things, but the |
1287 | * value is misterious. | 1286 | * value is mysterious. |
1288 | * ADI930 don't support it (-EPIPE error). | 1287 | * ADI930 don't support it (-EPIPE error). |
1289 | */ | 1288 | */ |
1290 | 1289 | ||
@@ -1744,7 +1743,7 @@ static int uea_send_cmvs_e1(struct uea_softc *sc) | |||
1744 | goto out; | 1743 | goto out; |
1745 | } | 1744 | } |
1746 | } else { | 1745 | } else { |
1747 | /* This realy should not happen */ | 1746 | /* This really should not happen */ |
1748 | uea_err(INS_TO_USBDEV(sc), "bad cmvs version %d\n", ver); | 1747 | uea_err(INS_TO_USBDEV(sc), "bad cmvs version %d\n", ver); |
1749 | goto out; | 1748 | goto out; |
1750 | } | 1749 | } |
@@ -1799,7 +1798,7 @@ static int uea_send_cmvs_e4(struct uea_softc *sc) | |||
1799 | goto out; | 1798 | goto out; |
1800 | } | 1799 | } |
1801 | } else { | 1800 | } else { |
1802 | /* This realy should not happen */ | 1801 | /* This really should not happen */ |
1803 | uea_err(INS_TO_USBDEV(sc), "bad cmvs version %d\n", ver); | 1802 | uea_err(INS_TO_USBDEV(sc), "bad cmvs version %d\n", ver); |
1804 | goto out; | 1803 | goto out; |
1805 | } | 1804 | } |
@@ -1830,7 +1829,7 @@ static int uea_start_reset(struct uea_softc *sc) | |||
1830 | 1829 | ||
1831 | /* mask interrupt */ | 1830 | /* mask interrupt */ |
1832 | sc->booting = 1; | 1831 | sc->booting = 1; |
1833 | /* We need to set this here because, a ack timeout could have occured, | 1832 | /* We need to set this here because, a ack timeout could have occurred, |
1834 | * but before we start the reboot, the ack occurs and set this to 1. | 1833 | * but before we start the reboot, the ack occurs and set this to 1. |
1835 | * So we will failed to wait Ready CMV. | 1834 | * So we will failed to wait Ready CMV. |
1836 | */ | 1835 | */ |
@@ -1879,7 +1878,7 @@ static int uea_start_reset(struct uea_softc *sc) | |||
1879 | /* start loading DSP */ | 1878 | /* start loading DSP */ |
1880 | sc->pageno = 0; | 1879 | sc->pageno = 0; |
1881 | sc->ovl = 0; | 1880 | sc->ovl = 0; |
1882 | queue_work(sc->work_q, &sc->task); | 1881 | schedule_work(&sc->task); |
1883 | 1882 | ||
1884 | /* wait for modem ready CMV */ | 1883 | /* wait for modem ready CMV */ |
1885 | ret = wait_cmv_ack(sc); | 1884 | ret = wait_cmv_ack(sc); |
@@ -2091,14 +2090,14 @@ static void uea_schedule_load_page_e1(struct uea_softc *sc, | |||
2091 | { | 2090 | { |
2092 | sc->pageno = intr->e1_bSwapPageNo; | 2091 | sc->pageno = intr->e1_bSwapPageNo; |
2093 | sc->ovl = intr->e1_bOvl >> 4 | intr->e1_bOvl << 4; | 2092 | sc->ovl = intr->e1_bOvl >> 4 | intr->e1_bOvl << 4; |
2094 | queue_work(sc->work_q, &sc->task); | 2093 | schedule_work(&sc->task); |
2095 | } | 2094 | } |
2096 | 2095 | ||
2097 | static void uea_schedule_load_page_e4(struct uea_softc *sc, | 2096 | static void uea_schedule_load_page_e4(struct uea_softc *sc, |
2098 | struct intr_pkt *intr) | 2097 | struct intr_pkt *intr) |
2099 | { | 2098 | { |
2100 | sc->pageno = intr->e4_bSwapPageNo; | 2099 | sc->pageno = intr->e4_bSwapPageNo; |
2101 | queue_work(sc->work_q, &sc->task); | 2100 | schedule_work(&sc->task); |
2102 | } | 2101 | } |
2103 | 2102 | ||
2104 | /* | 2103 | /* |
@@ -2170,13 +2169,6 @@ static int uea_boot(struct uea_softc *sc) | |||
2170 | 2169 | ||
2171 | init_waitqueue_head(&sc->sync_q); | 2170 | init_waitqueue_head(&sc->sync_q); |
2172 | 2171 | ||
2173 | sc->work_q = create_workqueue("ueagle-dsp"); | ||
2174 | if (!sc->work_q) { | ||
2175 | uea_err(INS_TO_USBDEV(sc), "cannot allocate workqueue\n"); | ||
2176 | uea_leaves(INS_TO_USBDEV(sc)); | ||
2177 | return -ENOMEM; | ||
2178 | } | ||
2179 | |||
2180 | if (UEA_CHIP_VERSION(sc) == ADI930) | 2172 | if (UEA_CHIP_VERSION(sc) == ADI930) |
2181 | load_XILINX_firmware(sc); | 2173 | load_XILINX_firmware(sc); |
2182 | 2174 | ||
@@ -2206,8 +2198,11 @@ static int uea_boot(struct uea_softc *sc) | |||
2206 | goto err1; | 2198 | goto err1; |
2207 | } | 2199 | } |
2208 | 2200 | ||
2209 | sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm"); | 2201 | /* Create worker thread, but don't start it here. Start it after |
2210 | if (sc->kthread == ERR_PTR(-ENOMEM)) { | 2202 | * all usbatm generic initialization is done. |
2203 | */ | ||
2204 | sc->kthread = kthread_create(uea_kthread, sc, "ueagle-atm"); | ||
2205 | if (IS_ERR(sc->kthread)) { | ||
2211 | uea_err(INS_TO_USBDEV(sc), "failed to create thread\n"); | 2206 | uea_err(INS_TO_USBDEV(sc), "failed to create thread\n"); |
2212 | goto err2; | 2207 | goto err2; |
2213 | } | 2208 | } |
@@ -2222,7 +2217,6 @@ err1: | |||
2222 | sc->urb_int = NULL; | 2217 | sc->urb_int = NULL; |
2223 | kfree(intr); | 2218 | kfree(intr); |
2224 | err0: | 2219 | err0: |
2225 | destroy_workqueue(sc->work_q); | ||
2226 | uea_leaves(INS_TO_USBDEV(sc)); | 2220 | uea_leaves(INS_TO_USBDEV(sc)); |
2227 | return -ENOMEM; | 2221 | return -ENOMEM; |
2228 | } | 2222 | } |
@@ -2243,8 +2237,8 @@ static void uea_stop(struct uea_softc *sc) | |||
2243 | kfree(sc->urb_int->transfer_buffer); | 2237 | kfree(sc->urb_int->transfer_buffer); |
2244 | usb_free_urb(sc->urb_int); | 2238 | usb_free_urb(sc->urb_int); |
2245 | 2239 | ||
2246 | /* stop any pending boot process, when no one can schedule work */ | 2240 | /* flush the work item, when no one can schedule it */ |
2247 | destroy_workqueue(sc->work_q); | 2241 | flush_work_sync(&sc->task); |
2248 | 2242 | ||
2249 | if (sc->dsp_firm) | 2243 | if (sc->dsp_firm) |
2250 | release_firmware(sc->dsp_firm); | 2244 | release_firmware(sc->dsp_firm); |
@@ -2301,7 +2295,7 @@ out: | |||
2301 | return ret; | 2295 | return ret; |
2302 | } | 2296 | } |
2303 | 2297 | ||
2304 | static DEVICE_ATTR(stat_status, S_IWUGO | S_IRUGO, read_status, reboot); | 2298 | static DEVICE_ATTR(stat_status, S_IWUSR | S_IRUGO, read_status, reboot); |
2305 | 2299 | ||
2306 | static ssize_t read_human_status(struct device *dev, | 2300 | static ssize_t read_human_status(struct device *dev, |
2307 | struct device_attribute *attr, char *buf) | 2301 | struct device_attribute *attr, char *buf) |
@@ -2364,8 +2358,7 @@ out: | |||
2364 | return ret; | 2358 | return ret; |
2365 | } | 2359 | } |
2366 | 2360 | ||
2367 | static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO, | 2361 | static DEVICE_ATTR(stat_human_status, S_IRUGO, read_human_status, NULL); |
2368 | read_human_status, NULL); | ||
2369 | 2362 | ||
2370 | static ssize_t read_delin(struct device *dev, struct device_attribute *attr, | 2363 | static ssize_t read_delin(struct device *dev, struct device_attribute *attr, |
2371 | char *buf) | 2364 | char *buf) |
@@ -2397,7 +2390,7 @@ out: | |||
2397 | return ret; | 2390 | return ret; |
2398 | } | 2391 | } |
2399 | 2392 | ||
2400 | static DEVICE_ATTR(stat_delin, S_IWUGO | S_IRUGO, read_delin, NULL); | 2393 | static DEVICE_ATTR(stat_delin, S_IRUGO, read_delin, NULL); |
2401 | 2394 | ||
2402 | #define UEA_ATTR(name, reset) \ | 2395 | #define UEA_ATTR(name, reset) \ |
2403 | \ | 2396 | \ |
@@ -2625,6 +2618,7 @@ static struct usbatm_driver uea_usbatm_driver = { | |||
2625 | static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) | 2618 | static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) |
2626 | { | 2619 | { |
2627 | struct usb_device *usb = interface_to_usbdev(intf); | 2620 | struct usb_device *usb = interface_to_usbdev(intf); |
2621 | int ret; | ||
2628 | 2622 | ||
2629 | uea_enters(usb); | 2623 | uea_enters(usb); |
2630 | uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) Rev (%#X): %s\n", | 2624 | uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) Rev (%#X): %s\n", |
@@ -2638,7 +2632,19 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
2638 | if (UEA_IS_PREFIRM(id)) | 2632 | if (UEA_IS_PREFIRM(id)) |
2639 | return uea_load_firmware(usb, UEA_CHIP_VERSION(id)); | 2633 | return uea_load_firmware(usb, UEA_CHIP_VERSION(id)); |
2640 | 2634 | ||
2641 | return usbatm_usb_probe(intf, id, &uea_usbatm_driver); | 2635 | ret = usbatm_usb_probe(intf, id, &uea_usbatm_driver); |
2636 | if (ret == 0) { | ||
2637 | struct usbatm_data *usbatm = usb_get_intfdata(intf); | ||
2638 | struct uea_softc *sc = usbatm->driver_data; | ||
2639 | |||
2640 | /* Ensure carrier is initialized to off as early as possible */ | ||
2641 | UPDATE_ATM_SIGNAL(ATM_PHY_SIG_LOST); | ||
2642 | |||
2643 | /* Only start the worker thread when all init is done */ | ||
2644 | wake_up_process(sc->kthread); | ||
2645 | } | ||
2646 | |||
2647 | return ret; | ||
2642 | } | 2648 | } |
2643 | 2649 | ||
2644 | static void uea_disconnect(struct usb_interface *intf) | 2650 | static void uea_disconnect(struct usb_interface *intf) |