ChangeSet 1.1043.1.4, 2003/02/16 09:38:10-08:00, [EMAIL PROTECTED]

[PATCH] USB speedtouch: infrastructure for new speedtouch send path

Put in infrastructure for the new send code.  The only code changes are in the
udsl_usb_probe and udsl_usb_disconnect functions, changed to initialize/finalize the
new fields (plus cleaned up a bit).  I couldn't resist a real code change while I was
there: freeing the memory used by the ATM after shutting it down, rather than before!
This doesn't make any difference since the shutdown routine doesn't work - so it still
oopses.  I will fix the shutdown routine later.


diff -Nru a/drivers/usb/misc/speedtouch.c b/drivers/usb/misc/speedtouch.c
--- a/drivers/usb/misc/speedtouch.c     Tue Feb 18 16:43:27 2003
+++ b/drivers/usb/misc/speedtouch.c     Tue Feb 18 16:43:27 2003
@@ -90,7 +90,9 @@
 
 #define UDSL_NUMBER_RCV_URBS           1
 #define UDSL_NUMBER_SND_URBS           1
+#define UDSL_NUMBER_SND_BUFS           (2*UDSL_NUMBER_SND_URBS)
 #define UDSL_RCV_BUFFER_SIZE           (1*64) /* ATM cells */
+#define UDSL_SND_BUFFER_SIZE           (2*64) /* ATM cells */
 /* max should be (1500 IP mtu + 2 ppp bytes + 32 * 5 cellheader overhead) for
  * PPPoA and (1500 + 14 + 32*5 cellheader overhead) for PPPoE */
 #define UDSL_MAX_AAL5_MRU              2048
@@ -123,10 +125,19 @@
        struct udsl_instance_data *instance;
 };
 
+struct udsl_send_buffer {
+       struct list_head list;
+       unsigned char *base;
+       unsigned char *free_start;
+       unsigned int free_cells;
+};
+
 struct udsl_usb_send_data_context {
-       struct urb *urb;
+       struct list_head list;
+       struct udsl_send_buffer *buffer;
        struct sk_buff *skb;
        struct atm_vcc *vcc;
+       struct urb *urb;
        struct udsl_instance_data *instance;
 };
 
@@ -139,13 +150,10 @@
 
        /* usb device part */
        struct usb_device *usb_dev;
-       struct sk_buff_head sndqueue;
-       struct udsl_usb_send_data_context send_ctx [UDSL_NUMBER_SND_URBS];
        int firmware_loaded;
 
        /* atm device part */
        struct atm_dev *atm_dev;
-
        struct atmsar_vcc_data *atmsar_vcc_list;
 
        /* receiving */
@@ -158,6 +166,21 @@
        struct list_head completed_receivers;
 
        struct tasklet_struct receive_tasklet;
+
+       /* sending */
+       struct udsl_usb_send_data_context send_ctx [UDSL_NUMBER_SND_URBS];
+       struct udsl_send_buffer all_buffers [UDSL_NUMBER_SND_BUFS];
+
+       struct sk_buff_head sndqueue;
+
+       spinlock_t send_lock;
+       struct list_head spare_senders;
+       struct list_head spare_buffers;
+
+       struct tasklet_struct send_tasklet;
+       struct sk_buff *current_skb;
+       struct udsl_send_buffer *current_buffer;
+       struct list_head filled_buffers;
 };
 
 static const char udsl_driver_name [] = "Alcatel SpeedTouch USB";
@@ -371,6 +394,15 @@
 }
 
 
+/***********
+**  send  **
+***********/
+
+static void udsl_process_send (unsigned long data)
+{
+}
+
+
 /************
 **   ATM   **
 ************/
@@ -770,7 +802,7 @@
        struct udsl_instance_data *instance;
        unsigned char mac_str [13];
        unsigned char mac [6];
-       int i, err;
+       int i;
 
        PDEBUG ("Trying device with Vendor=0x%x, Product=0x%x, ifnum %d\n",
                dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
@@ -785,8 +817,7 @@
        /* instance init */
        if (!(instance = kmalloc (sizeof (struct udsl_instance_data), GFP_KERNEL))) {
                PDEBUG ("No memory for Instance data!\n");
-               err = -ENOMEM;
-               goto fail_instance;
+               return -ENOMEM;
        }
 
        memset (instance, 0, sizeof (struct udsl_instance_data));
@@ -805,20 +836,25 @@
 
        skb_queue_head_init (&instance->sndqueue);
 
-       /* receive urb init */
+       spin_lock_init (&instance->send_lock);
+       INIT_LIST_HEAD (&instance->spare_senders);
+       INIT_LIST_HEAD (&instance->spare_buffers);
+
+       tasklet_init (&instance->send_tasklet, udsl_process_send, (unsigned long) 
+instance);
+       INIT_LIST_HEAD (&instance->filled_buffers);
+
+       /* receive init */
        for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) {
                struct udsl_receiver *rcv = &(instance->all_receivers[i]);
 
                if (!(rcv->skb = dev_alloc_skb (UDSL_RCV_BUFFER_SIZE * 
ATM_CELL_SIZE))) {
                        PDEBUG ("No memory for skb %d!\n", i);
-                       err = -ENOMEM;
-                       goto fail_urbs;
+                       goto fail;
                }
 
                if (!(rcv->urb = usb_alloc_urb (0, GFP_KERNEL))) {
                        PDEBUG ("No memory for receive urb %d!\n", i);
-                       err = -ENOMEM;
-                       goto fail_urbs;
+                       goto fail;
                }
 
                rcv->instance = instance;
@@ -828,23 +864,35 @@
                PDEBUG ("skb->truesize = %d (asked for %d)\n", rcv->skb->truesize, 
UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE);
        }
 
+       /* send init */
        for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) {
                struct udsl_usb_send_data_context *snd = &(instance->send_ctx[i]);
 
                if (!(snd->urb = usb_alloc_urb (0, GFP_KERNEL))) {
                        PDEBUG ("No memory for send urb %d!\n", i);
-                       err = -ENOMEM;
-                       goto fail_urbs;
+                       goto fail;
                }
 
                snd->instance = instance;
+
+               list_add (&snd->list, &instance->spare_senders);
+       }
+
+       for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++) {
+               struct udsl_send_buffer *buf = &(instance->all_buffers[i]);
+
+               if (!(buf->base = kmalloc (UDSL_SND_BUFFER_SIZE * ATM_CELL_SIZE, 
+GFP_KERNEL))) {
+                       PDEBUG ("No memory for send buffer %d!\n", i);
+                       goto fail;
+               }
+
+               list_add (&buf->list, &instance->spare_buffers);
        }
 
        /* atm init */
        if (!(instance->atm_dev = atm_dev_register (udsl_driver_name, 
&udsl_atm_devops, -1, 0))) {
                PDEBUG ("failed to register ATM device!\n");
-               err = -ENOMEM;
-               goto fail_atm;
+               goto fail;
        }
 
        instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX;
@@ -871,14 +919,12 @@
 
        return 0;
 
-fail_atm:
-fail_urbs:
-       for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) {
-               struct udsl_usb_send_data_context *snd = &(instance->send_ctx[i]);
+fail:
+       for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++)
+               kfree (instance->all_buffers[i].base);
 
-               if (snd->urb)
-                       usb_free_urb (snd->urb);
-       }
+       for (i = 0; i < UDSL_NUMBER_SND_URBS; i++)
+               usb_free_urb (instance->send_ctx[i].urb);
 
        for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) {
                struct udsl_receiver *rcv = &(instance->all_receivers[i]);
@@ -886,12 +932,12 @@
                if (rcv->skb)
                        kfree_skb (rcv->skb);
 
-               if (rcv->urb)
-                       usb_free_urb (rcv->urb);
+               usb_free_urb (rcv->urb);
        }
+
        kfree (instance);
-fail_instance:
-       return err;
+
+       return -ENOMEM;
 }
 
 static void udsl_usb_disconnect (struct usb_interface *intf)
@@ -900,7 +946,7 @@
        struct list_head *pos;
        unsigned long flags;
        unsigned int count = 0;
-       int i;
+       int result, i;
 
        PDEBUG ("disconnecting\n");
 
@@ -913,8 +959,9 @@
 
        tasklet_disable (&instance->receive_tasklet);
 
+       /* flush spare receivers */
        down (&instance->serialize); /* vs udsl_fire_receivers */
-       /* no need to take the spinlock - receive_tasklet is not running */
+       /* no need to take the spinlock */
        list_for_each (pos, &instance->spare_receivers)
                if (++count > UDSL_NUMBER_RCV_URBS)
                        panic (__FILE__ ": memory corruption detected at line %d!\n", 
__LINE__);
@@ -926,7 +973,8 @@
        count = UDSL_NUMBER_RCV_URBS - count;
 
        for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++)
-               usb_unlink_urb (instance->all_receivers[i].urb);
+               if ((result = usb_unlink_urb (instance->all_receivers[i].urb)) < 0)
+                       PDEBUG ("udsl_usb_disconnect: usb_unlink_urb on receive urb %d 
+returned %d\n", i, result);
 
        /* wait for completion handlers to finish */
        do {
@@ -943,12 +991,11 @@
                if (completed == count)
                        break;
 
-               /* not all urbs completed */
                yield ();
        } while (1);
 
-       PDEBUG ("udsl_usb_disconnect: flushing %u completed receivers\n", count);
-       /* no need to take the spinlock - no completion handlers running */
+       PDEBUG ("udsl_usb_disconnect: flushing\n");
+       /* no need to take the spinlock */
        INIT_LIST_HEAD (&instance->completed_receivers);
 
        tasklet_enable (&instance->receive_tasklet);
@@ -962,24 +1009,49 @@
                kfree_skb (rcv->skb);
        }
 
-       for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) {
-               struct udsl_usb_send_data_context *ctx = &(instance->send_ctx[i]);
+       udsl_atm_stopdevice (instance);
 
-               usb_unlink_urb (ctx->urb);
+       tasklet_disable (&instance->send_tasklet);
 
-               if (ctx->skb)
-                       ctx->vcc->pop (ctx->vcc, ctx->skb);
-               ctx->skb = NULL;
+       for (i = 0; i < UDSL_NUMBER_SND_URBS; i++)
+               if ((result = usb_unlink_urb (instance->send_ctx[i].urb)) < 0)
+                       PDEBUG ("udsl_usb_disconnect: usb_unlink_urb on send urb %d 
+returned %d\n", i, result);
 
-               usb_free_urb (ctx->urb);
+       /* wait for completion handlers to finish */
+       do {
+               count = 0;
+               spin_lock_irqsave (&instance->send_lock, flags);
+               list_for_each (pos, &instance->spare_senders)
+                       if (++count > UDSL_NUMBER_SND_URBS)
+                               panic (__FILE__ ": memory corruption detected at line 
+%d!\n", __LINE__);
+               spin_unlock_irqrestore (&instance->send_lock, flags);
 
-       }
+               PDEBUG ("udsl_usb_disconnect: found %u spare senders\n", count);
 
+               if (count == UDSL_NUMBER_SND_URBS)
+                       break;
+
+               yield ();
+       } while (1);
+
+       PDEBUG ("udsl_usb_disconnect: flushing\n");
+       /* no need to take the spinlock */
+       INIT_LIST_HEAD (&instance->spare_senders);
+       INIT_LIST_HEAD (&instance->spare_buffers);
+       instance->current_buffer = NULL;
+
+       tasklet_enable (&instance->receive_tasklet);
+       tasklet_kill (&instance->receive_tasklet);
+
+       PDEBUG ("udsl_usb_disconnect: freeing senders\n");
+       for (i = 0; i < UDSL_NUMBER_SND_URBS; i++)
+               usb_free_urb (instance->send_ctx[i].urb);
 
-       /* removing atm device */
-       if (instance->atm_dev)
-               udsl_atm_stopdevice (instance);
+       PDEBUG ("udsl_usb_disconnect: freeing buffers\n");
+       for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++)
+               kfree (instance->all_buffers[i].base);
 
+       PDEBUG ("udsl_usb_disconnect: freeing instance\n");
        kfree (instance);
 }
 



-------------------------------------------------------
This SF.net email is sponsored by: SlickEdit Inc. Develop an edge.
The most comprehensive and flexible code editor you can use.
Code faster. C/C++, C#, Java, HTML, XML, many more. FREE 30-Day Trial.
www.slickedit.com/sourceforge
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to