From 3e69d3322b1700b568834724a56dd5d99c79ceea Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Fri, 13 Jan 2006 10:05:15 +0100 Subject: [PATCH] --- yaml --- r: 19207 b: refs/heads/master c: 0e42a627ec3d8defa0c43cff94b8f2080a070716 h: refs/heads/master i: 19205: 8218ab4fa3fe2659e07551e901bd606a42abdf7e 19203: 1f767d23dae084f51f9cf9cd2dbccc7ff8d90586 19199: bca27f50a4c6c5599eccbdda9be4f628e7b1f858 v: v3 --- [refs] | 2 +- trunk/drivers/usb/atm/usbatm.c | 66 ++++++++++++++++++++++++---------- trunk/drivers/usb/atm/usbatm.h | 1 + 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/[refs] b/[refs] index c99153d9e165..ad3ebc35d027 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 233c08e0ff303e659a9003d49b15608f59f08a64 +refs/heads/master: 0e42a627ec3d8defa0c43cff94b8f2080a070716 diff --git a/trunk/drivers/usb/atm/usbatm.c b/trunk/drivers/usb/atm/usbatm.c index 3ed5f02c36d3..e660a1ebf12b 100644 --- a/trunk/drivers/usb/atm/usbatm.c +++ b/trunk/drivers/usb/atm/usbatm.c @@ -602,8 +602,12 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) vdbg("%s called (skb 0x%p, len %u)", __func__, skb, skb->len); - if (!instance) { - dbg("%s: NULL data!", __func__); + /* racy disconnection check - fine */ + if (!instance || instance->disconnected) { +#ifdef DEBUG + if (printk_ratelimit()) + printk(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance"); +#endif err = -ENODEV; goto fail; } @@ -715,15 +719,19 @@ static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *pag atomic_read(&atm_dev->stats.aal5.rx_err), atomic_read(&atm_dev->stats.aal5.rx_drop)); - if (!left--) - switch (atm_dev->signal) { - case ATM_PHY_SIG_FOUND: - return sprintf(page, "Line up\n"); - case ATM_PHY_SIG_LOST: - return sprintf(page, "Line down\n"); - default: - return sprintf(page, "Line state unknown\n"); - } + if (!left--) { + if (instance->disconnected) + return sprintf(page, "Disconnected\n"); + else + switch (atm_dev->signal) { + case ATM_PHY_SIG_FOUND: + return sprintf(page, "Line up\n"); + case ATM_PHY_SIG_LOST: + return sprintf(page, "Line down\n"); + default: + return sprintf(page, "Line state unknown\n"); + } + } return 0; } @@ -757,6 +765,12 @@ static int usbatm_atm_open(struct atm_vcc *vcc) down(&instance->serialize); /* vs self, usbatm_atm_close, usbatm_usb_disconnect */ + if (instance->disconnected) { + atm_dbg(instance, "%s: disconnected!\n", __func__); + ret = -ENODEV; + goto fail; + } + if (usbatm_find_vcc(instance, vpi, vci)) { atm_dbg(instance, "%s: %hd/%d already in use!\n", __func__, vpi, vci); ret = -EADDRINUSE; @@ -845,6 +859,13 @@ static void usbatm_atm_close(struct atm_vcc *vcc) static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user * arg) { + struct usbatm_data *instance = atm_dev->dev_data; + + if (!instance || instance->disconnected) { + dbg("%s: %s!", __func__, instance ? "disconnected" : "NULL instance"); + return -ENODEV; + } + switch (cmd) { case ATM_QUERYLOOP: return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0; @@ -1129,6 +1150,7 @@ void usbatm_usb_disconnect(struct usb_interface *intf) { struct device *dev = &intf->dev; struct usbatm_data *instance = usb_get_intfdata(intf); + struct usbatm_vcc_data *vcc_data; int i; dev_dbg(dev, "%s entered\n", __func__); @@ -1141,12 +1163,18 @@ void usbatm_usb_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); down(&instance->serialize); + instance->disconnected = 1; if (instance->thread_pid >= 0) kill_proc(instance->thread_pid, SIGTERM, 1); up(&instance->serialize); wait_for_completion(&instance->thread_exited); + down(&instance->serialize); + list_for_each_entry(vcc_data, &instance->vcc_list, list) + vcc_release_async(vcc_data->vcc, -EPIPE); + up(&instance->serialize); + tasklet_disable(&instance->rx_channel.tasklet); tasklet_disable(&instance->tx_channel.tasklet); @@ -1156,6 +1184,14 @@ void usbatm_usb_disconnect(struct usb_interface *intf) del_timer_sync(&instance->rx_channel.delay); del_timer_sync(&instance->tx_channel.delay); + /* turn usbatm_[rt]x_process into something close to a no-op */ + /* no need to take the spinlock */ + INIT_LIST_HEAD(&instance->rx_channel.list); + INIT_LIST_HEAD(&instance->tx_channel.list); + + tasklet_enable(&instance->rx_channel.tasklet); + tasklet_enable(&instance->tx_channel.tasklet); + if (instance->atm_dev && instance->driver->atm_stop) instance->driver->atm_stop(instance, instance->atm_dev); @@ -1164,14 +1200,6 @@ void usbatm_usb_disconnect(struct usb_interface *intf) instance->driver_data = NULL; - /* turn usbatm_[rt]x_process into noop */ - /* no need to take the spinlock */ - INIT_LIST_HEAD(&instance->rx_channel.list); - INIT_LIST_HEAD(&instance->tx_channel.list); - - tasklet_enable(&instance->rx_channel.tasklet); - tasklet_enable(&instance->tx_channel.tasklet); - for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { kfree(instance->urbs[i]->transfer_buffer); usb_free_urb(instance->urbs[i]); diff --git a/trunk/drivers/usb/atm/usbatm.h b/trunk/drivers/usb/atm/usbatm.h index 4b923a83555e..1a31cf87bb1f 100644 --- a/trunk/drivers/usb/atm/usbatm.h +++ b/trunk/drivers/usb/atm/usbatm.h @@ -168,6 +168,7 @@ struct usbatm_data { struct kref refcount; struct semaphore serialize; + int disconnected; /* heavy init */ int thread_pid;