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