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