speedtch usbatm.c,1.50,1.51

Duncan Sands duncan at infradead.org
Thu Nov 3 12:45:31 EST 2005


Update of /home/cvs/speedtch
In directory phoenix.infradead.org:/tmp/cvs-serv29234

Modified Files:
	usbatm.c 
Log Message:
Don't allow vccs to be opened after the device is disconnected.  Shoot down
any open vccs using vcc_release_async.  While there, add a memory barrier
between the clearing of the xx_channel lists and the re-enabling of the
tasklets.  Added a note about urb->status in the isoc case.  By the way,
in case anyone cares, isoc stuff doesn't work with the speedtouch, but
I understand why, and what to do.


Index: usbatm.c
===================================================================
RCS file: /home/cvs/speedtch/usbatm.c,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -r1.50 -r1.51
--- usbatm.c	30 Sep 2005 09:56:51 -0000	1.50
+++ usbatm.c	3 Nov 2005 17:45:27 -0000	1.51
@@ -285,11 +285,11 @@
 static inline struct usbatm_vcc_data *usbatm_find_vcc(struct usbatm_data *instance,
 						  short vpi, int vci)
 {
-	struct usbatm_vcc_data *vcc;
+	struct usbatm_vcc_data *vcc_data;
 
-	list_for_each_entry(vcc, &instance->vcc_list, list)
-		if ((vcc->vci == vci) && (vcc->vpi == vpi))
-			return vcc;
+	list_for_each_entry(vcc_data, &instance->vcc_list, list)
+		if ((vcc_data->vci == vci) && (vcc_data->vpi == vpi))
+			return vcc_data;
 	return NULL;
 }
 
@@ -492,7 +492,7 @@
 	while ((urb = usbatm_pop_urb(&instance->rx_channel))) {
 		vdbg("%s: processing urb 0x%p", __func__, urb);
 
-		if (usb_pipeisoc(urb->pipe)) {
+		if (usb_pipeisoc(urb->pipe)) {//QQ should we be doing this if urb->status != 0?  Because then the iso_frame_desc[i].status values may not have been written...
 			int i;
 			for (i = 0; i < urb->number_of_packets; i++)
 				if (!urb->iso_frame_desc[i].status)
@@ -687,6 +687,14 @@
 	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;
@@ -755,7 +763,13 @@
 		return -EINVAL;
 	}
 
-	down(&instance->serialize);	/* vs self, usbatm_atm_close */
+	down(&instance->serialize);	/* vs self, usbatm_atm_close, usbatm_usb_disconnect */
+
+	if (instance->device_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);
@@ -819,7 +833,7 @@
 
 	usbatm_cancel_send(instance, vcc);
 
-	down(&instance->serialize);	/* vs self, usbatm_atm_open */
+	down(&instance->serialize);	/* vs self, usbatm_atm_open, usbatm_usb_disconnect */
 
 	tasklet_disable(&instance->rx_channel.tasklet);
 	list_del(&vcc_data->list);
@@ -1146,6 +1160,8 @@
 	usb_set_intfdata(intf, NULL);
 
 	down(&instance->serialize);
+	instance->device_disconnected = 1;
+        usbatm_kill_vccs(instance);
 	if (instance->thread_pid >= 0)
 		kill_proc(instance->thread_pid, SIGTERM, 1);
 	up(&instance->serialize);
@@ -1161,22 +1177,24 @@
 	del_timer_sync(&instance->rx_channel.delay);
 	del_timer_sync(&instance->tx_channel.delay);
 
-	if (instance->atm_dev && instance->driver->atm_stop)
-		instance->driver->atm_stop(instance, instance->atm_dev);
-
-	if (instance->driver->unbind)
-		instance->driver->unbind(instance, 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);
 
+	mb();
+
 	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);
+
+	if (instance->driver->unbind)
+		instance->driver->unbind(instance, intf);
+
+	instance->driver_data = NULL;
+
 	for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
 		kfree(instance->urbs[i]->transfer_buffer);
 		usb_free_urb(instance->urbs[i]);




More information about the Usbatm-commits mailing list