speedtouch: more robust handling of receive urb failure: retry failed urbs whenever a new connection is opened. This should work well with pppd's persist option.
speedtouch.c | 133 +++++++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 88 insertions(+), 45 deletions(-) --- bollux-2.5/drivers/usb/misc/speedtouch.c.orig 2003-01-24 13:47:31.000000000 +0100 +++ bollux-2.5/drivers/usb/misc/speedtouch.c 2003-01-24 13:47:02.000000000 +0100 @@ -46,6 +46,7 @@ * */ +#include <asm/semaphore.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -137,6 +138,8 @@ */ struct udsl_instance_data { + struct semaphore serialize; + /* usb device part */ struct usb_device *usb_dev; struct udsl_data_ctx rcvbufs [UDSL_NUMBER_RCV_URBS]; @@ -150,6 +153,9 @@ struct atmsar_vcc_data *atmsar_vcc_list; /* receiving */ + spinlock_t spare_receivers_lock; + struct list_head spare_receivers; + spinlock_t completed_receivers_lock; struct list_head completed_receivers; @@ -422,6 +428,10 @@ PDEBUG ("udsl_atm_processqueue: submission failed\n"); /* fall through */ default: /* error or urb unlinked */ + PDEBUG ("udsl_atm_processqueue: adding to spare_receivers\n"); + spin_lock_irqsave (&instance->spare_receivers_lock, flags); + list_add (&ctx->list, &instance->spare_receivers); + spin_unlock_irqrestore (&instance->spare_receivers_lock, +flags); break; } @@ -437,6 +447,43 @@ * SAR driver entries * ****************************************************************************/ + +static void udsl_fire_receivers (struct udsl_instance_data *instance) +{ + struct list_head receivers, *pos, *n; + unsigned long flags; + + INIT_LIST_HEAD (&receivers); + + down (&instance->serialize); + + spin_lock_irqsave (&instance->spare_receivers_lock, flags); + list_splice_init (&instance->spare_receivers, &receivers); + spin_unlock_irqrestore (&instance->spare_receivers_lock, flags); + + list_for_each_safe (pos, n, &receivers) { + struct udsl_data_ctx *ctx = list_entry (pos, struct udsl_data_ctx, +list); + + PDEBUG ("udsl_fire_receivers: firing urb %p\n", ctx->urb); + + usb_fill_bulk_urb (ctx->urb, + instance->usb_dev, + usb_rcvbulkpipe (instance->usb_dev, +UDSL_ENDPOINT_DATA_IN), + (unsigned char *) ctx->skb->data, + UDSL_RECEIVE_BUFFER_SIZE, + udsl_usb_data_receive, ctx); + + if (usb_submit_urb (ctx->urb, GFP_KERNEL) < 0) { + PDEBUG ("udsl_fire_receivers: submit failed!\n"); + spin_lock_irqsave (&instance->spare_receivers_lock, flags); + list_move (pos, &instance->spare_receivers); + spin_unlock_irqrestore (&instance->spare_receivers_lock, +flags); + } + } + + up (&instance->serialize); +} + static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci) { struct udsl_atm_dev_data *dev_data; @@ -476,6 +523,9 @@ dev_data->atmsar_vcc->mtu = UDSL_MAX_AAL5_MRU; + if (instance->data_started) + udsl_fire_receivers (instance); + PDEBUG ("udsl_atm_open successfull\n"); return 0; } @@ -686,24 +736,7 @@ skb_queue_head_init (&instance->sndqueue); - for (i = 0, succes = 0; i < UDSL_NUMBER_RCV_URBS; i++) { - struct udsl_data_ctx *ctx = &(instance->rcvbufs[i]); - - usb_fill_bulk_urb (ctx->urb, - instance->usb_dev, - usb_rcvbulkpipe (instance->usb_dev, UDSL_ENDPOINT_DATA_IN), - (unsigned char *) ctx->skb->data, - UDSL_RECEIVE_BUFFER_SIZE, - udsl_usb_data_receive, ctx); - - if (usb_submit_urb (ctx->urb, GFP_KERNEL) < 0) - PDEBUG ("udsl_usb_data_init: Submit failed, loosing urb.\n"); - else - succes++; - } - - PDEBUG ("udsl_usb_data_init %d urb%s queued for receive\n", succes, - (succes != 1) ? "s" : ""); + udsl_fire_receivers (instance); for (i = 0, succes = 0; i < UDSL_NUMBER_SND_URBS; i++) { instance->send_ctx[i].urb = usb_alloc_urb (0, GFP_KERNEL); @@ -723,34 +756,9 @@ static int udsl_usb_data_exit (struct udsl_instance_data *instance) { - int i; - if (!instance->data_started) return 0; - tasklet_disable (&instance->recvqueue_tasklet); - - for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) - usb_unlink_urb (instance->rcvbufs[i].urb); - - INIT_LIST_HEAD (&instance->completed_receivers); - - tasklet_enable (&instance->recvqueue_tasklet); - tasklet_kill (&instance->recvqueue_tasklet); - - for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) { - struct udsl_usb_send_data_context *ctx = &(instance->send_ctx[i]); - - usb_unlink_urb (ctx->urb); - - if (ctx->skb) - ctx->vcc->pop (ctx->vcc, ctx->skb); - ctx->skb = NULL; - - usb_free_urb (ctx->urb); - - } - instance->data_started = 0; instance->atm_dev->signal = ATM_PHY_SIG_LOST; @@ -813,8 +821,13 @@ memset (instance, 0, sizeof (struct udsl_instance_data)); + init_MUTEX (&instance->serialize); + instance->usb_dev = dev; + spin_lock_init (&instance->spare_receivers_lock); + INIT_LIST_HEAD (&instance->spare_receivers); + spin_lock_init (&instance->completed_receivers_lock); INIT_LIST_HEAD (&instance->completed_receivers); @@ -838,6 +851,8 @@ ctx->instance = instance; + list_add (&ctx->list, &instance->spare_receivers); + PDEBUG ("skb->truesize = %d (asked for %d)\n", ctx->skb->truesize, UDSL_RECEIVE_BUFFER_SIZE); } @@ -902,9 +917,23 @@ return; } - /* unlinking receive buffers */ - udsl_usb_data_exit (instance); + tasklet_disable (&instance->recvqueue_tasklet); + + down (&instance->serialize); + /* no need to take the spinlock - recvqueue_tasklet is not running */ + INIT_LIST_HEAD (&instance->spare_receivers); + up (&instance->serialize); + + for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) + usb_unlink_urb (instance->rcvbufs[i].urb); + + /* no need to take the spinlock - no completion handlers running */ + INIT_LIST_HEAD (&instance->completed_receivers); + + tasklet_enable (&instance->recvqueue_tasklet); + tasklet_kill (&instance->recvqueue_tasklet); + PDEBUG ("udsl_usb_disconnect: freeing receivers\n"); for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) { struct udsl_data_ctx *ctx = &(instance->rcvbufs[i]); @@ -912,6 +941,20 @@ kfree_skb (ctx->skb); } + for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) { + struct udsl_usb_send_data_context *ctx = &(instance->send_ctx[i]); + + usb_unlink_urb (ctx->urb); + + if (ctx->skb) + ctx->vcc->pop (ctx->vcc, ctx->skb); + ctx->skb = NULL; + + usb_free_urb (ctx->urb); + + } + + /* removing atm device */ if (instance->atm_dev) udsl_atm_stopdevice (instance); ------------------------------------------------------- This SF.NET email is sponsored by: SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See! http://www.vasoftware.com _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel