[PATCH] USBATM: shutdown open connections when disconnected This patch causes vcc_release_async to be applied to any open vcc's when the modem is disconnected. This signals a socket shutdown, letting the socket user know that the game is up. I wrote this patch because of reports that pppd would keep connections open forever when the modem is disconnected. This patch does not fix that problem, but it's a step in the right direction. It doesn't help because the pppoatm module doesn't yet monitor state changes on the ATM socket, so simply never realises that the ATM connection has gone down (meaning it doesn't tell the ppp layer). But at least there is a socket state change now. Unfortunately this patch may create problems for those rare users like me who use routed IP or some other non-ppp connection method that goes via the ATM ARP daemon: the daemon is buggy, and with this patch will crash when the modem is disconnected. Users with a buggy atmarpd can simply restart it after disconnecting the modem.
Signed-off-by: Duncan Sands <[EMAIL PROTECTED]> Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]> --- commit 0e42a627ec3d8defa0c43cff94b8f2080a070716 tree 5b22c24b224de444ddc6fd9b874a86624d41c227 parent 233c08e0ff303e659a9003d49b15608f59f08a64 author Duncan Sands <[EMAIL PROTECTED]> Fri, 13 Jan 2006 10:05:15 +0100 committer Greg Kroah-Hartman <[EMAIL PROTECTED]> Tue, 31 Jan 2006 17:23:39 -0800 drivers/usb/atm/usbatm.c | 66 +++++++++++++++++++++++++++++++++------------- drivers/usb/atm/usbatm.h | 1 + 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 3ed5f02..e660a1e 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -602,8 +602,12 @@ static int usbatm_atm_send(struct atm_vc 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 a 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_vc 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_ 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_in { 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_in 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_in 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_in 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/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h index 4b923a8..1a31cf8 100644 --- a/drivers/usb/atm/usbatm.h +++ b/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; ------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Do you grep through log files for problems? Stop! Download the new AJAX search engine that makes searching your log files as easy as surfing the web. DOWNLOAD SPLUNK! http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642 _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel