speedtch usbatm.c,1.51,1.52 usbatm.h,1.23,1.24
Duncan Sands
duncan at infradead.org
Mon Nov 7 14:12:24 EST 2005
Update of /home/cvs/speedtch
In directory phoenix.infradead.org:/tmp/cvs-serv1326
Modified Files:
usbatm.c usbatm.h
Log Message:
Make more use of the information that we are disconnected.
Index: usbatm.c
===================================================================
RCS file: /home/cvs/speedtch/usbatm.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -r1.51 -r1.52
--- usbatm.c 3 Nov 2005 17:45:27 -0000 1.51
+++ usbatm.c 7 Nov 2005 19:12:20 -0000 1.52
@@ -166,10 +166,10 @@
/* ATM */
-static void usbatm_atm_dev_close(struct atm_dev *dev);
+static void usbatm_atm_dev_close(struct atm_dev *atm_dev);
static int usbatm_atm_open(struct atm_vcc *vcc);
static void usbatm_atm_close(struct atm_vcc *vcc);
-static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg);
+static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user * arg);
static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page);
@@ -599,10 +599,11 @@
vdbg("%s called (skb 0x%p, len %u)", __func__, skb, skb->len);
- if (!instance) {
+ /* racy disconnection check - fine */
+ if (!instance || instance->disconnected) {
#ifdef DEBUG
if (printk_ratelimit())
- printk(KERN_DEBUG "%s: NULL data!\n", __func__);
+ printk(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance");
#endif
err = -ENODEV;
goto fail;
@@ -674,27 +675,19 @@
** ATM **
**********/
-static void usbatm_atm_dev_close(struct atm_dev *dev)
+static void usbatm_atm_dev_close(struct atm_dev *atm_dev)
{
- struct usbatm_data *instance = dev->dev_data;
+ struct usbatm_data *instance = atm_dev->dev_data;
dbg("%s", __func__);
if (!instance)
return;
- dev->dev_data = NULL;
+ atm_dev->dev_data = NULL; /* catch bugs */
usbatm_put_instance(instance); /* taken in usbatm_atm_init */
}
-static void usbatm_kill_vccs(struct usbatm_data *instance) /* caller must hold instance->serialize */
-{
- struct usbatm_vcc_data *vcc_data;
-
- list_for_each_entry(vcc_data, &instance->vcc_list, list)
- vcc_release_async(vcc_data->vcc, -EPIPE);
-}
-
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page)
{
struct usbatm_data *instance = atm_dev->dev_data;
@@ -723,15 +716,19 @@
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;
}
@@ -765,7 +762,7 @@
down(&instance->serialize); /* vs self, usbatm_atm_close, usbatm_usb_disconnect */
- if (instance->device_disconnected) {
+ if (instance->disconnected) {
atm_dbg(instance, "%s: disconnected!\n", __func__);
ret = -ENODEV;
goto fail;
@@ -856,9 +853,16 @@
atm_dbg(instance, "%s successful\n", __func__);
}
-static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd,
+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;
@@ -872,7 +876,10 @@
struct atm_dev *atm_dev;
int ret, i;
- /* ATM init */
+ /* ATM init. The ATM initialization scheme suffers from an intrinsic race
+ * condition: callbacks we register can be executed at once, before we have
+ * initialized the struct atm_dev. To protect against this, all callbacks
+ * abort if atm_dev->dev_data is NULL. */
atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL);
if (!atm_dev) {
usb_err(instance, "%s: failed to register ATM device!\n", __func__);
@@ -893,8 +900,9 @@
goto fail;
}
- /* ready for ATM callbacks */
usbatm_get_instance(instance); /* dropped in usbatm_atm_dev_close */
+
+ /* ready for ATM callbacks */
mb();
atm_dev->dev_data = instance;
@@ -1148,6 +1156,7 @@
{
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__);
@@ -1160,14 +1169,18 @@
usb_set_intfdata(intf, NULL);
down(&instance->serialize);
- instance->device_disconnected = 1;
- usbatm_kill_vccs(instance);
+ 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);
@@ -1177,7 +1190,7 @@
del_timer_sync(&instance->rx_channel.delay);
del_timer_sync(&instance->tx_channel.delay);
- /* turn usbatm_[rt]x_process into noop */
+ /* 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);
Index: usbatm.h
===================================================================
RCS file: /home/cvs/speedtch/usbatm.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- usbatm.h 3 Nov 2005 17:39:11 -0000 1.23
+++ usbatm.h 7 Nov 2005 19:12:21 -0000 1.24
@@ -174,7 +174,7 @@
struct kref refcount;
struct semaphore serialize;
- int device_disconnected;
+ int disconnected;
/* heavy init */
int thread_pid;
More information about the Usbatm-commits
mailing list