]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
staging: ozwpan: Update to latest drop from ATMEL.
authorTodd Poynter <tpoynter@nvidia.com>
Mon, 28 Oct 2013 18:40:01 +0000 (13:40 -0500)
committerJon Mayo <jmayo@nvidia.com>
Mon, 11 Nov 2013 18:07:09 +0000 (10:07 -0800)
Update the ozwpan driver to the latest drop from ATMEL.

Bug 1394137.

Change-Id: I9069c974cb665a8be68d43536f57c3b717b570a6
Signed-off-by: Todd Poynter <tpoynter@nvidia.com>
Reviewed-on: http://git-master/r/328583
GVS: Gerrit_Virtual_Submit
Reviewed-by: Jon Mayo <jmayo@nvidia.com>
28 files changed:
drivers/staging/ozwpan/Kbuild
drivers/staging/ozwpan/README
drivers/staging/ozwpan/TODO
drivers/staging/ozwpan/ozappif.h
drivers/staging/ozwpan/ozcdev.c
drivers/staging/ozwpan/ozcdev.h
drivers/staging/ozwpan/ozconfig.h [deleted file]
drivers/staging/ozwpan/ozeltbuf.c
drivers/staging/ozwpan/ozeltbuf.h
drivers/staging/ozwpan/ozevent.c [deleted file]
drivers/staging/ozwpan/ozevent.h [deleted file]
drivers/staging/ozwpan/ozeventdef.h [deleted file]
drivers/staging/ozwpan/ozeventtrace.h [new file with mode: 0644]
drivers/staging/ozwpan/ozhcd.c
drivers/staging/ozwpan/ozkobject.c [new file with mode: 0644]
drivers/staging/ozwpan/ozkobject.h [new file with mode: 0644]
drivers/staging/ozwpan/ozmain.c
drivers/staging/ozwpan/ozpd.c
drivers/staging/ozwpan/ozpd.h
drivers/staging/ozwpan/ozproto.c
drivers/staging/ozwpan/ozproto.h
drivers/staging/ozwpan/ozprotocol.h
drivers/staging/ozwpan/oztrace.c
drivers/staging/ozwpan/oztrace.h
drivers/staging/ozwpan/ozurbparanoia.c
drivers/staging/ozwpan/ozusbif.h
drivers/staging/ozwpan/ozusbsvc.c
drivers/staging/ozwpan/ozusbsvc1.c

index 6cc84cb3f0a6dfb2e27ebb336ba694b68fcc61f1..08bc7938692d385c0af062e339ed7913b9187d3d 100644 (file)
@@ -14,6 +14,6 @@ ozwpan-y := \
        ozcdev.o \
        ozurbparanoia.o \
        oztrace.o \
-       ozevent.o
+       ozkobject.o
 
 
index 7c055ec99544382cabfb95d31fac1545965db4cd..bb1a69b945418bf995fae5bb8da982d0037948a4 100644 (file)
@@ -9,7 +9,7 @@ technology.
 
 To operate the driver must be bound to a suitable network interface. This can
 be done when the module is loaded (specifying the name of the network interface
-as a parameter - e.g. 'insmod ozwpan g_net_dev=go0') or can be bound after
+as a paramter - e.g. 'insmod ozwpan g_net_dev=go0') or can be bound after
 loading using an ioctl call. See the ozappif.h file and the ioctls
 OZ_IOCTL_ADD_BINDING and OZ_IOCTL_REMOVE_BINDING.
 
index b4febd79a68dbff6c938c035095917fc38c99c85..c2d30a7112f30f8ae507e5a3e31b61b5d0c9184f 100644 (file)
@@ -1,14 +1,14 @@
 TODO:
-       - Convert event tracing code to in-kernel tracing infrastructure
-       - Check for remaining ioctl & check if that can be converted into
-         sysfs entries
-       - Convert debug prints to appropriate dev_debug or something better
-       - Modify Kconfig to add CONFIG option for enabling/disabling event
-         tracing.
+       - review user mode interface and determine if ioctls can be replaced
+         with something better. correctly export data structures to user mode
+         if ioctls are still required and allocate ioctl numbers from
+         ioctl-number.txt.
        - check USB HCD implementation is complete and correct.
+       - remove any debug and trace code.
        - code review by USB developer community.
        - testing with as many devices as possible.
 
 Please send any patches for this driver to
-Rupesh Gujare <rupesh.gujare@atmel.com>
+Rupesh Gujare <rgujare@ozmodevices.com>
+Chris Kelly <ckelly@ozmodevices.com>
 and Greg Kroah-Hartman <gregkh@linuxfoundation.org>.
index 449a6ba8233734ff337a8b81869d05e5d81d5104..ea1b271fdcdacd9bafd9fbb39e0cc89fbe081f36 100644 (file)
@@ -6,8 +6,6 @@
 #ifndef _OZAPPIF_H
 #define _OZAPPIF_H
 
-#include "ozeventdef.h"
-
 #define OZ_IOCTL_MAGIC 0xf4
 
 struct oz_mac_addr {
index 27d06666c81ab4ce12aab8b15ddf79884ee72e3e..f3238229b5b32354d72edd868e8a305076762744 100644 (file)
@@ -8,21 +8,21 @@
 #include <linux/cdev.h>
 #include <linux/uaccess.h>
 #include <linux/netdevice.h>
-#include <linux/etherdevice.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
-#include "ozconfig.h"
 #include "ozprotocol.h"
 #include "oztrace.h"
 #include "ozappif.h"
 #include "ozeltbuf.h"
 #include "ozpd.h"
 #include "ozproto.h"
-#include "ozevent.h"
-#include "ozcdev.h"
+#include "ozkobject.h"
 /*------------------------------------------------------------------------------
  */
 #define OZ_RD_BUF_SZ   256
+#define OZ_MODE_TFTP   0x1
+#define OZ_MODE_SERIAL 0x0
+
 struct oz_cdev {
        dev_t devnum;
        struct cdev cdev;
@@ -30,6 +30,8 @@ struct oz_cdev {
        spinlock_t lock;
        u8 active_addr[ETH_ALEN];
        struct oz_pd *active_pd;
+       atomic_t ref_count;
+       u8 mode;
 };
 
 /* Per PD context for the serial service stored in the PD. */
@@ -37,14 +39,34 @@ struct oz_serial_ctx {
        atomic_t ref_count;
        u8 tx_seq_num;
        u8 rx_seq_num;
+       u8 tx_done_seq_num;
+       u8 padding;
        u8 rd_buf[OZ_RD_BUF_SZ];
        int rd_in;
        int rd_out;
+       spinlock_t rd_lock;
+       int dg_len[OZ_RD_BUF_SZ/4];
+       int dg_in;
+       int dg_out;
 };
 /*------------------------------------------------------------------------------
  */
 static struct oz_cdev g_cdev;
-static struct class *g_oz_class;
+struct class *g_oz_class;
+struct device *g_oz_wpan_dev;
+/*------------------------------------------------------------------------------
+ * Context: softirq
+ */
+
+static void oz_cdev_elt_completion_callback(struct oz_pd *pd, long context)
+{
+       struct oz_serial_ctx *ctx;
+       spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
+       ctx = (struct oz_serial_ctx *)pd->app_ctx[OZ_APPID_SERIAL-1];
+       if (ctx)
+               ctx->tx_done_seq_num = (u8)context;
+       spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
+}
 /*------------------------------------------------------------------------------
  * Context: process and softirq
  */
@@ -63,7 +85,7 @@ static struct oz_serial_ctx *oz_cdev_claim_ctx(struct oz_pd *pd)
  */
 static void oz_cdev_release_ctx(struct oz_serial_ctx *ctx)
 {
-       if (atomic_dec_and_test(&ctx->ref_count)) {
+       if (ctx &&  atomic_dec_and_test(&ctx->ref_count)) {
                oz_trace("Dealloc serial context.\n");
                kfree(ctx);
        }
@@ -71,11 +93,13 @@ static void oz_cdev_release_ctx(struct oz_serial_ctx *ctx)
 /*------------------------------------------------------------------------------
  * Context: process
  */
-static int oz_cdev_open(struct inode *inode, struct file *filp)
+int oz_cdev_open(struct inode *inode, struct file *filp)
 {
        struct oz_cdev *dev;
-       oz_trace("oz_cdev_open()\n");
-       oz_trace("major = %d minor = %d\n", imajor(inode), iminor(inode));
+
+       if (!atomic_add_unless(&g_cdev.ref_count, 1, 1))
+               return -EBUSY;
+
        dev = container_of(inode->i_cdev, struct oz_cdev, cdev);
        filp->private_data = dev;
        return 0;
@@ -83,57 +107,114 @@ static int oz_cdev_open(struct inode *inode, struct file *filp)
 /*------------------------------------------------------------------------------
  * Context: process
  */
-static int oz_cdev_release(struct inode *inode, struct file *filp)
+int oz_cdev_release(struct inode *inode, struct file *filp)
 {
-       oz_trace("oz_cdev_release()\n");
+       atomic_dec(&g_cdev.ref_count);
        return 0;
 }
 /*------------------------------------------------------------------------------
  * Context: process
  */
-static ssize_t oz_cdev_read(struct file *filp, char __user *buf, size_t count,
+ssize_t oz_cdev_read(struct file *filp, char __user *buf, size_t count,
                loff_t *fpos)
 {
        int n;
        int ix;
-
+       int is_tftp;
        struct oz_pd *pd;
-       struct oz_serial_ctx *ctx;
+       struct oz_serial_ctx *ctx = 0;
 
        spin_lock_bh(&g_cdev.lock);
        pd = g_cdev.active_pd;
        if (pd)
                oz_pd_get(pd);
+       is_tftp = (g_cdev.mode & OZ_MODE_TFTP) ? 1 : 0;
        spin_unlock_bh(&g_cdev.lock);
-       if (pd == NULL)
+       if (pd == 0)
                return -1;
        ctx = oz_cdev_claim_ctx(pd);
-       if (ctx == NULL)
+       if (ctx == 0)
                goto out2;
-       n = ctx->rd_in - ctx->rd_out;
-       if (n < 0)
-               n += OZ_RD_BUF_SZ;
-       if (count > n)
+
+       spin_lock_bh(&ctx->rd_lock);
+
+       if (is_tftp) {
+               /* if n is non zero we have a datagram */
+               n = ctx->dg_len[ctx->dg_out];
+
+               if (n == 0) {
+                       count = 0;
+                       spin_unlock_bh(&ctx->rd_lock);
+                       goto out1;
+               }
+
+               ix = ctx->rd_out;
+               spin_unlock_bh(&ctx->rd_lock);
+
+               /* copy n bytes of datagram to user bufer */
+               if ((ix + n) < OZ_RD_BUF_SZ) {
+                       if (copy_to_user(buf, &ctx->rd_buf[ix], n)) {
+                               count = 0;
+                               goto out1;
+                       }
+                       spin_lock_bh(&ctx->rd_lock);
+                       ctx->rd_out += n;
+               } else {
+                       int b = (OZ_RD_BUF_SZ - ix);
+                       /* datagram maybe split in between the end and start of
+                        *  the buffer */
+                       if (copy_to_user(buf, &ctx->rd_buf[ix], b)) {
+                               count = 0;
+                               goto out1;
+                       }
+                       if (copy_to_user(&buf[b], ctx->rd_buf, n - b)) {
+                               count = 0;
+                               goto out1;
+                       }
+                       spin_lock_bh(&ctx->rd_lock);
+                       ctx->rd_out = n - (OZ_RD_BUF_SZ - ix);
+               }
+
                count = n;
-       ix = ctx->rd_out;
-       n = OZ_RD_BUF_SZ - ix;
-       if (n > count)
-               n = count;
-       if (copy_to_user(buf, &ctx->rd_buf[ix], n)) {
-               count = 0;
-               goto out1;
-       }
-       ix += n;
-       if (ix == OZ_RD_BUF_SZ)
-               ix = 0;
-       if (n < count) {
-               if (copy_to_user(&buf[n], ctx->rd_buf, count-n)) {
+
+               ctx->dg_len[ctx->dg_out] = 0;
+               ctx->dg_out++;
+               if ((OZ_RD_BUF_SZ/4) == ctx->dg_out)
+                       ctx->dg_out = 0;
+               spin_unlock_bh(&ctx->rd_lock);
+       } else {
+               n = ctx->rd_in - ctx->rd_out;
+               if (n < 0)
+                       n += OZ_RD_BUF_SZ;
+               if (count > n)
+                       count = n;
+
+               ix = ctx->rd_out;
+               spin_unlock_bh(&ctx->rd_lock);
+               n = OZ_RD_BUF_SZ - ix;
+               if (n > count)
+                       n = count;
+
+               if (copy_to_user(buf, &ctx->rd_buf[ix], n)) {
                        count = 0;
                        goto out1;
                }
-               ix = count-n;
+
+               ix += n;
+               if (ix == OZ_RD_BUF_SZ)
+                       ix = 0;
+               if (n < count) {
+                       if (copy_to_user(&buf[n], ctx->rd_buf, count-n)) {
+                               count = 0;
+                               goto out1;
+                       }
+                       ix = count-n;
+               }
+
+               spin_lock_bh(&ctx->rd_lock);
+               ctx->rd_out = ix;
+               spin_unlock_bh(&ctx->rd_lock);
        }
-       ctx->rd_out = ix;
 out1:
        oz_cdev_release_ctx(ctx);
 out2:
@@ -143,13 +224,14 @@ out2:
 /*------------------------------------------------------------------------------
  * Context: process
  */
-static ssize_t oz_cdev_write(struct file *filp, const char __user *buf,
-               size_t count, loff_t *fpos)
+ssize_t oz_cdev_write(struct file *filp, const char __user *buf, size_t count,
+               loff_t *fpos)
 {
        struct oz_pd *pd;
        struct oz_elt_buf *eb;
-       struct oz_elt_info *ei;
+       struct oz_elt_info *ei = 0;
        struct oz_elt *elt;
+       struct oz_ext_elt *ext_elt;
        struct oz_app_hdr *app_hdr;
        struct oz_serial_ctx *ctx;
 
@@ -158,35 +240,54 @@ static ssize_t oz_cdev_write(struct file *filp, const char __user *buf,
        if (pd)
                oz_pd_get(pd);
        spin_unlock_bh(&g_cdev.lock);
-       if (pd == NULL)
+       if (pd == 0)
                return -1;
+       if (!(pd->state & OZ_PD_S_CONNECTED))
+               return -ENXIO;
        eb = &pd->elt_buff;
        ei = oz_elt_info_alloc(eb);
-       if (ei == NULL) {
+       if (ei == 0) {
                count = 0;
                goto out;
        }
-       elt = (struct oz_elt *)ei->data;
-       app_hdr = (struct oz_app_hdr *)(elt+1);
-       elt->length = sizeof(struct oz_app_hdr) + count;
-       elt->type = OZ_ELT_APP_DATA;
-       ei->app_id = OZ_APPID_SERIAL;
-       ei->length = elt->length + sizeof(struct oz_elt);
-       app_hdr->app_id = OZ_APPID_SERIAL;
+       spin_lock_bh(&g_cdev.lock);
+       if (g_cdev.mode & OZ_MODE_TFTP) {
+               spin_unlock_bh(&g_cdev.lock);
+               ei->app_id = OZ_APPID_SERIAL;
+               ei->flags |= OZ_EI_F_EXT_ELM;
+               ext_elt = (struct oz_ext_elt *)ei->data;
+               app_hdr = (struct oz_app_hdr *)(ext_elt+1);
+               app_hdr->app_id = OZ_APPID_TFTP;
+               ext_elt->length = sizeof(struct oz_app_hdr) + count;
+               ext_elt->type = OZ_ELT_APP_DATA_EX;
+               ei->length = ext_elt->length + sizeof(struct oz_ext_elt);
+               ext_elt->length = cpu_to_le16(ext_elt->length);
+       } else {
+               spin_unlock_bh(&g_cdev.lock);
+               ei->app_id = OZ_APPID_SERIAL;
+               elt = (struct oz_elt *)ei->data;
+               app_hdr = (struct oz_app_hdr *)(elt+1);
+               app_hdr->app_id = OZ_APPID_SERIAL;
+               elt->length = sizeof(struct oz_app_hdr) + count;
+               elt->type = OZ_ELT_APP_DATA;
+               ei->length = elt->length + sizeof(struct oz_elt);
+       }
        if (copy_from_user(app_hdr+1, buf, count))
                goto out;
-       spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]);
+       spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
        ctx = (struct oz_serial_ctx *)pd->app_ctx[OZ_APPID_SERIAL-1];
        if (ctx) {
                app_hdr->elt_seq_num = ctx->tx_seq_num++;
                if (ctx->tx_seq_num == 0)
                        ctx->tx_seq_num = 1;
+               ei->callback = oz_cdev_elt_completion_callback;
+               ei->context = ctx->tx_seq_num;
                spin_lock(&eb->lock);
                if (oz_queue_elt_info(eb, 0, 0, ei) == 0)
-                       ei = NULL;
+                       ei = 0;
                spin_unlock(&eb->lock);
        }
-       spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
+       spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
 out:
        if (ei) {
                count = 0;
@@ -200,25 +301,43 @@ out:
 /*------------------------------------------------------------------------------
  * Context: process
  */
-static int oz_set_active_pd(const u8 *addr)
+int oz_set_active_pd(u8 *addr)
 {
        int rc = 0;
        struct oz_pd *pd;
        struct oz_pd *old_pd;
+       struct oz_serial_ctx *ctx;
        pd = oz_pd_find(addr);
        if (pd) {
                spin_lock_bh(&g_cdev.lock);
+               if (memcmp(g_cdev.active_addr, addr, ETH_ALEN) == 0) {
+                       spin_unlock_bh(&g_cdev.lock);
+                       return rc;
+               }
                memcpy(g_cdev.active_addr, addr, ETH_ALEN);
                old_pd = g_cdev.active_pd;
                g_cdev.active_pd = pd;
                spin_unlock_bh(&g_cdev.lock);
+
+               /*Reset buffer pointers if new device is selected*/
+               ctx = oz_cdev_claim_ctx(pd);
+               if (ctx != NULL) {
+                       spin_lock_bh(&ctx->rd_lock);
+                       ctx->dg_in = 0;
+                       ctx->dg_out = 0;
+                       ctx->dg_len[0] = 0;
+                       ctx->rd_out = 0;
+                       ctx->rd_in = 0;
+                       spin_unlock_bh(&ctx->rd_lock);
+               }
+
                if (old_pd)
                        oz_pd_put(old_pd);
        } else {
-               if (is_zero_ether_addr(addr)) {
+               if (!memcmp(addr, "\0\0\0\0\0\0", ETH_ALEN)) {
                        spin_lock_bh(&g_cdev.lock);
                        pd = g_cdev.active_pd;
-                       g_cdev.active_pd = NULL;
+                       g_cdev.active_pd = 0;
                        memset(g_cdev.active_addr, 0,
                                sizeof(g_cdev.active_addr));
                        spin_unlock_bh(&g_cdev.lock);
@@ -233,8 +352,53 @@ static int oz_set_active_pd(const u8 *addr)
 /*------------------------------------------------------------------------------
  * Context: process
  */
-static long oz_cdev_ioctl(struct file *filp, unsigned int cmd,
-                         unsigned long arg)
+void oz_get_active_pd(u8 *addr)
+{
+       spin_lock_bh(&g_cdev.lock);
+       memcpy(addr, g_cdev.active_addr, ETH_ALEN);
+       spin_unlock_bh(&g_cdev.lock);
+
+}
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+u8 oz_get_serial_mode(void)
+{
+       u8 serial_mode;
+
+       spin_lock_bh(&g_cdev.lock);
+       serial_mode = g_cdev.mode;
+       spin_unlock_bh(&g_cdev.lock);
+       return serial_mode;
+}
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+void oz_set_serial_mode(u8 mode)
+{
+       u8 addr[ETH_ALEN];
+       struct oz_pd *pd;
+       struct oz_serial_ctx *ctx;
+
+       oz_get_active_pd(addr);
+       pd = oz_pd_find(addr);
+       if (!pd)
+               return;
+       ctx = oz_cdev_claim_ctx(pd);
+       if (!ctx) {
+               oz_pd_put(pd);
+               return;
+       }
+       spin_lock_bh(&g_cdev.lock);
+       g_cdev.mode = mode;
+       spin_unlock_bh(&g_cdev.lock);
+       oz_cdev_release_ctx(ctx);
+       oz_pd_put(pd);
+}
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+long oz_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        int rc = 0;
        if (_IOC_TYPE(cmd) != OZ_IOCTL_MAGIC)
@@ -252,8 +416,6 @@ static long oz_cdev_ioctl(struct file *filp, unsigned int cmd,
        switch (cmd) {
        case OZ_IOCTL_GET_PD_LIST: {
                        struct oz_pd_list list;
-                       oz_trace("OZ_IOCTL_GET_PD_LIST\n");
-                       memset(&list, 0, sizeof(list));
                        list.count = oz_get_pd_list(list.addr, OZ_MAX_PDS);
                        if (copy_to_user((void __user *)arg, &list,
                                sizeof(list)))
@@ -262,7 +424,6 @@ static long oz_cdev_ioctl(struct file *filp, unsigned int cmd,
                break;
        case OZ_IOCTL_SET_ACTIVE_PD: {
                        u8 addr[ETH_ALEN];
-                       oz_trace("OZ_IOCTL_SET_ACTIVE_PD\n");
                        if (copy_from_user(addr, (void __user *)arg, ETH_ALEN))
                                return -EFAULT;
                        rc = oz_set_active_pd(addr);
@@ -270,7 +431,6 @@ static long oz_cdev_ioctl(struct file *filp, unsigned int cmd,
                break;
        case OZ_IOCTL_GET_ACTIVE_PD: {
                        u8 addr[ETH_ALEN];
-                       oz_trace("OZ_IOCTL_GET_ACTIVE_PD\n");
                        spin_lock_bh(&g_cdev.lock);
                        memcpy(addr, g_cdev.active_addr, ETH_ALEN);
                        spin_unlock_bh(&g_cdev.lock);
@@ -299,28 +459,34 @@ static long oz_cdev_ioctl(struct file *filp, unsigned int cmd,
 /*------------------------------------------------------------------------------
  * Context: process
  */
-static unsigned int oz_cdev_poll(struct file *filp, poll_table *wait)
+unsigned int oz_cdev_poll(struct file *filp, poll_table *wait)
 {
        unsigned int ret = 0;
        struct oz_cdev *dev = filp->private_data;
-       oz_trace("Poll called wait = %p\n", wait);
        spin_lock_bh(&dev->lock);
        if (dev->active_pd) {
                struct oz_serial_ctx *ctx = oz_cdev_claim_ctx(dev->active_pd);
+               spin_unlock_bh(&dev->lock);
                if (ctx) {
+                       spin_lock_bh(&ctx->rd_lock);
                        if (ctx->rd_in != ctx->rd_out)
                                ret |= POLLIN | POLLRDNORM;
+
+                       if (ctx->tx_seq_num == ctx->tx_done_seq_num)
+                               ret |= POLLOUT;
+                       spin_unlock_bh(&ctx->rd_lock);
                        oz_cdev_release_ctx(ctx);
                }
-       }
-       spin_unlock_bh(&dev->lock);
+       } else
+               spin_unlock_bh(&dev->lock);
+
        if (wait)
                poll_wait(filp, &dev->rdq, wait);
        return ret;
 }
 /*------------------------------------------------------------------------------
  */
-static const struct file_operations oz_fops = {
+const struct file_operations oz_fops = {
        .owner =        THIS_MODULE,
        .open =         oz_cdev_open,
        .release =      oz_cdev_release,
@@ -335,13 +501,10 @@ static const struct file_operations oz_fops = {
 int oz_cdev_register(void)
 {
        int err;
-       struct device *dev;
        memset(&g_cdev, 0, sizeof(g_cdev));
        err = alloc_chrdev_region(&g_cdev.devnum, 0, 1, "ozwpan");
        if (err < 0)
                goto out3;
-       oz_trace("Alloc dev number %d:%d\n", MAJOR(g_cdev.devnum),
-                       MINOR(g_cdev.devnum));
        cdev_init(&g_cdev.cdev, &oz_fops);
        g_cdev.cdev.owner = THIS_MODULE;
        g_cdev.cdev.ops = &oz_fops;
@@ -357,11 +520,13 @@ int oz_cdev_register(void)
                oz_trace("Failed to register ozmo_wpan class\n");
                goto out1;
        }
-       dev = device_create(g_oz_class, NULL, g_cdev.devnum, NULL, "ozwpan");
-       if (IS_ERR(dev)) {
+       g_oz_wpan_dev = device_create(g_oz_class, NULL, g_cdev.devnum, NULL,
+                                                               "ozwpan");
+       if (IS_ERR(g_oz_wpan_dev)) {
                oz_trace("Failed to create sysfs entry for cdev\n");
                goto out1;
        }
+       oz_create_sys_entry();
        return 0;
 out1:
        cdev_del(&g_cdev.cdev);
@@ -378,6 +543,7 @@ int oz_cdev_deregister(void)
        cdev_del(&g_cdev.cdev);
        unregister_chrdev_region(g_cdev.devnum, 1);
        if (g_oz_class) {
+               oz_destroy_sys_entry();
                device_destroy(g_oz_class, g_cdev.devnum);
                class_destroy(g_oz_class);
        }
@@ -388,7 +554,6 @@ int oz_cdev_deregister(void)
  */
 int oz_cdev_init(void)
 {
-       oz_event_log(OZ_EVT_SERVICE, 1, OZ_APPID_SERIAL, NULL, 0);
        oz_app_enable(OZ_APPID_SERIAL, 1);
        return 0;
 }
@@ -397,7 +562,6 @@ int oz_cdev_init(void)
  */
 void oz_cdev_term(void)
 {
-       oz_event_log(OZ_EVT_SERVICE, 2, OZ_APPID_SERIAL, NULL, 0);
        oz_app_enable(OZ_APPID_SERIAL, 0);
 }
 /*------------------------------------------------------------------------------
@@ -406,17 +570,17 @@ void oz_cdev_term(void)
 int oz_cdev_start(struct oz_pd *pd, int resume)
 {
        struct oz_serial_ctx *ctx;
-       struct oz_serial_ctx *old_ctx;
-       oz_event_log(OZ_EVT_SERVICE, 3, OZ_APPID_SERIAL, NULL, resume);
+       struct oz_serial_ctx *old_ctx = 0;
        if (resume) {
                oz_trace("Serial service resumed.\n");
                return 0;
        }
        ctx = kzalloc(sizeof(struct oz_serial_ctx), GFP_ATOMIC);
-       if (ctx == NULL)
+       if (ctx == 0)
                return -ENOMEM;
        atomic_set(&ctx->ref_count, 1);
        ctx->tx_seq_num = 1;
+       ctx->tx_done_seq_num = 1;
        spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
        old_ctx = pd->app_ctx[OZ_APPID_SERIAL-1];
        if (old_ctx) {
@@ -427,11 +591,10 @@ int oz_cdev_start(struct oz_pd *pd, int resume)
                spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
        }
        spin_lock(&g_cdev.lock);
-       if ((g_cdev.active_pd == NULL) &&
+       if ((g_cdev.active_pd == 0) &&
                (memcmp(pd->mac_addr, g_cdev.active_addr, ETH_ALEN) == 0)) {
                oz_pd_get(pd);
                g_cdev.active_pd = pd;
-               oz_trace("Active PD arrived.\n");
        }
        spin_unlock(&g_cdev.lock);
        oz_trace("Serial service started.\n");
@@ -443,26 +606,24 @@ int oz_cdev_start(struct oz_pd *pd, int resume)
 void oz_cdev_stop(struct oz_pd *pd, int pause)
 {
        struct oz_serial_ctx *ctx;
-       oz_event_log(OZ_EVT_SERVICE, 4, OZ_APPID_SERIAL, NULL, pause);
        if (pause) {
                oz_trace("Serial service paused.\n");
                return;
        }
        spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
        ctx = (struct oz_serial_ctx *)pd->app_ctx[OZ_APPID_SERIAL-1];
-       pd->app_ctx[OZ_APPID_SERIAL-1] = NULL;
+       pd->app_ctx[OZ_APPID_SERIAL-1] = 0;
        spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
        if (ctx)
                oz_cdev_release_ctx(ctx);
        spin_lock(&g_cdev.lock);
        if (pd == g_cdev.active_pd)
-               g_cdev.active_pd = NULL;
+               g_cdev.active_pd = 0;
        else
-               pd = NULL;
+               pd = 0;
        spin_unlock(&g_cdev.lock);
        if (pd) {
                oz_pd_put(pd);
-               oz_trace("Active PD departed.\n");
        }
        oz_trace("Serial service stopped.\n");
 }
@@ -478,14 +639,19 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt)
        int space;
        int copy_sz;
        int ix;
+       int is_tftp;
+
+       spin_lock_bh(&g_cdev.lock);
+       is_tftp = (g_cdev.mode & OZ_MODE_TFTP) ? 1 : 0;
+       spin_unlock_bh(&g_cdev.lock);
 
        ctx = oz_cdev_claim_ctx(pd);
-       if (ctx == NULL) {
+       if (ctx == 0) {
                oz_trace("Cannot claim serial context.\n");
                return;
        }
 
-       app_hdr = (struct oz_app_hdr *)(elt+1);
+       app_hdr = (struct oz_app_hdr *)(oz_elt_data(elt));
        /* If sequence number is non-zero then check it is not a duplicate.
         */
        if (app_hdr->elt_seq_num != 0) {
@@ -497,10 +663,11 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt)
                }
        }
        ctx->rx_seq_num = app_hdr->elt_seq_num;
-       len = elt->length - sizeof(struct oz_app_hdr);
-       data = ((u8 *)(elt+1)) + sizeof(struct oz_app_hdr);
+       len = oz_elt_data_len(elt) - sizeof(struct oz_app_hdr);
+       data = ((u8 *)(app_hdr + 1));
        if (len <= 0)
                goto out;
+       spin_lock_bh(&ctx->rd_lock);
        space = ctx->rd_out - ctx->rd_in - 1;
        if (space < 0)
                space += OZ_RD_BUF_SZ;
@@ -508,6 +675,19 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt)
                oz_trace("Not enough space:%d %d\n", len, space);
                len = space;
        }
+
+
+       if (is_tftp) {
+               if (len != 0) {
+                       /* remember length of datagram */
+                       ctx->dg_len[ctx->dg_in] = len;
+
+                       ctx->dg_in++;
+                       if ((OZ_RD_BUF_SZ/4) == ctx->dg_in)
+                               ctx->dg_in = 0;
+               }
+       }
+
        ix = ctx->rd_in;
        copy_sz = OZ_RD_BUF_SZ - ix;
        if (copy_sz > len)
@@ -522,7 +702,14 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt)
                ix = len;
        }
        ctx->rd_in = ix;
+       spin_unlock_bh(&ctx->rd_lock);
        wake_up(&g_cdev.rdq);
 out:
        oz_cdev_release_ctx(ctx);
 }
+/*------------------------------------------------------------------------------
+ * Context: softirq
+ */
+void oz_cdev_heartbeat(struct oz_pd *pd)
+{
+}
index dd11935a093f4c48e087dddcba8b29be58df1b89..0e40717824480140de79b98237526433e0dc869c 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef _OZCDEV_H
 #define _OZCDEV_H
 
+extern struct device *g_oz_wpan_dev;
 int oz_cdev_register(void);
 int oz_cdev_deregister(void);
 int oz_cdev_init(void);
@@ -13,5 +14,8 @@ void oz_cdev_term(void);
 int oz_cdev_start(struct oz_pd *pd, int resume);
 void oz_cdev_stop(struct oz_pd *pd, int pause);
 void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt);
+void oz_cdev_heartbeat(struct oz_pd *pd);
+int oz_set_active_pd(u8 *addr);
+void oz_get_active_pd(u8 *addr);
 
 #endif /* _OZCDEV_H */
diff --git a/drivers/staging/ozwpan/ozconfig.h b/drivers/staging/ozwpan/ozconfig.h
deleted file mode 100644 (file)
index 43e6373..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * ---------------------------------------------------------------------------*/
-#ifndef _OZCONFIG_H
-#define _OZCONFIG_H
-
-/* #define WANT_TRACE */
-#ifdef WANT_TRACE
-#define WANT_VERBOSE_TRACE
-#endif /* #ifdef WANT_TRACE */
-/* #define WANT_URB_PARANOIA */
-
-/* #define WANT_PRE_2_6_39 */
-#define WANT_EVENT_TRACE
-
-/* These defines determine what verbose trace is displayed. */
-#ifdef WANT_VERBOSE_TRACE
-/* #define WANT_TRACE_STREAM */
-/* #define WANT_TRACE_URB */
-/* #define WANT_TRACE_CTRL_DETAIL */
-#define WANT_TRACE_HUB
-/* #define WANT_TRACE_RX_FRAMES */
-/* #define WANT_TRACE_TX_FRAMES */
-#endif /* WANT_VERBOSE_TRACE */
-
-#endif /* _OZCONFIG_H */
index ac90fc7f5441e517422e9c27efc3b2dbef752fef..e86f28b8dfa5f99c8a63176fd6f7a851fa4c1890 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
-#include "ozconfig.h"
 #include "ozprotocol.h"
 #include "ozeltbuf.h"
 #include "ozpd.h"
@@ -64,7 +63,7 @@ void oz_elt_buf_term(struct oz_elt_buf *buf)
  */
 struct oz_elt_info *oz_elt_info_alloc(struct oz_elt_buf *buf)
 {
-       struct oz_elt_info *ei = NULL;
+       struct oz_elt_info *ei = 0;
        spin_lock_bh(&buf->lock);
        if (buf->free_elts && buf->elt_pool) {
                ei = container_of(buf->elt_pool, struct oz_elt_info, link);
@@ -82,9 +81,9 @@ struct oz_elt_info *oz_elt_info_alloc(struct oz_elt_buf *buf)
        if (ei) {
                ei->flags = 0;
                ei->app_id = 0;
-               ei->callback = NULL;
+               ei->callback = 0;
                ei->context = 0;
-               ei->stream = NULL;
+               ei->stream = 0;
                ei->magic = OZ_ELT_INFO_MAGIC_USED;
                INIT_LIST_HEAD(&ei->link);
                INIT_LIST_HEAD(&ei->link_order);
@@ -132,10 +131,8 @@ int oz_elt_stream_create(struct oz_elt_buf *buf, u8 id, int max_buf_count)
 {
        struct oz_elt_stream *st;
 
-       oz_trace("oz_elt_stream_create(0x%x)\n", id);
-
        st = kzalloc(sizeof(struct oz_elt_stream), GFP_ATOMIC | __GFP_ZERO);
-       if (st == NULL)
+       if (st == 0)
                return -ENOMEM;
        atomic_set(&st->ref_count, 1);
        st->id = id;
@@ -151,8 +148,8 @@ int oz_elt_stream_create(struct oz_elt_buf *buf, u8 id, int max_buf_count)
 int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id)
 {
        struct list_head *e;
-       struct oz_elt_stream *st = NULL;
-       oz_trace("oz_elt_stream_delete(0x%x)\n", id);
+       struct oz_elt_stream *st;
+
        spin_lock_bh(&buf->lock);
        e = buf->stream_list.next;
        while (e != &buf->stream_list) {
@@ -161,7 +158,7 @@ int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id)
                        list_del(e);
                        break;
                }
-               st = NULL;
+               st = 0;
        }
        if (!st) {
                spin_unlock_bh(&buf->lock);
@@ -175,9 +172,6 @@ int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id)
                list_del_init(&ei->link);
                list_del_init(&ei->link_order);
                st->buf_count -= ei->length;
-               oz_trace2(OZ_TRACE_STREAM, "Stream down: %d  %d %d\n",
-                       st->buf_count,
-                       ei->length, atomic_read(&st->ref_count));
                oz_elt_stream_put(st);
                oz_elt_info_free(buf, ei);
        }
@@ -208,7 +202,7 @@ void oz_elt_stream_put(struct oz_elt_stream *st)
 int oz_queue_elt_info(struct oz_elt_buf *buf, u8 isoc, u8 id,
        struct oz_elt_info *ei)
 {
-       struct oz_elt_stream *st = NULL;
+       struct oz_elt_stream *st = 0;
        struct list_head *e;
        if (id) {
                list_for_each(e, &buf->stream_list) {
@@ -242,8 +236,6 @@ int oz_queue_elt_info(struct oz_elt_buf *buf, u8 isoc, u8 id,
                st->buf_count += ei->length;
                /* Add to list in stream. */
                list_add_tail(&ei->link, &st->elt_list);
-               oz_trace2(OZ_TRACE_STREAM, "Stream up: %d  %d\n",
-                       st->buf_count, ei->length);
                /* Check if we have too much buffered for this stream. If so
                 * start dropping elements until we are back in bounds.
                 */
@@ -283,8 +275,12 @@ int oz_select_elts_for_tx(struct oz_elt_buf *buf, u8 isoc, unsigned *len,
                ei = container_of(e, struct oz_elt_info, link_order);
                e = e->next;
                if ((*len + ei->length) <= max_len) {
-                       app_hdr = (struct oz_app_hdr *)
-                               &ei->data[sizeof(struct oz_elt)];
+                       if (ei->flags & OZ_EI_F_EXT_ELM)
+                               app_hdr = (struct oz_app_hdr *)
+                                       &ei->data[sizeof(struct oz_ext_elt)];
+                       else
+                               app_hdr = (struct oz_app_hdr *)
+                                       &ei->data[sizeof(struct oz_elt)];
                        app_hdr->elt_seq_num = buf->tx_seq_num[ei->app_id]++;
                        if (buf->tx_seq_num[ei->app_id] == 0)
                                buf->tx_seq_num[ei->app_id] = 1;
@@ -293,11 +289,8 @@ int oz_select_elts_for_tx(struct oz_elt_buf *buf, u8 isoc, unsigned *len,
                        list_del(&ei->link_order);
                        if (ei->stream) {
                                ei->stream->buf_count -= ei->length;
-                               oz_trace2(OZ_TRACE_STREAM,
-                                       "Stream down: %d  %d\n",
-                                       ei->stream->buf_count, ei->length);
                                oz_elt_stream_put(ei->stream);
-                               ei->stream = NULL;
+                               ei->stream = 0;
                        }
                        INIT_LIST_HEAD(&ei->link_order);
                        list_add_tail(&ei->link, list);
@@ -319,7 +312,7 @@ int oz_are_elts_available(struct oz_elt_buf *buf)
  */
 void oz_trim_elt_pool(struct oz_elt_buf *buf)
 {
-       struct list_head *free = NULL;
+       struct list_head *free = 0;
        struct list_head *e;
        spin_lock_bh(&buf->lock);
        while (buf->free_elts > buf->max_free_elts) {
index 03c12f57b9bb3500ded4b0b9980ee0aebe9be600..2c184be4adab8c4d3393e1771411402205debf69 100644 (file)
@@ -23,7 +23,7 @@ struct oz_elt_stream {
        u8 id;
 };
 
-#define OZ_MAX_ELT_PAYLOAD     255
+#define OZ_MAX_ELT_PAYLOAD     1024
 struct oz_elt_info {
        struct list_head link;
        struct list_head link_order;
@@ -32,12 +32,13 @@ struct oz_elt_info {
        oz_elt_callback_t callback;
        long context;
        struct oz_elt_stream *stream;
-       u8 data[sizeof(struct oz_elt) + OZ_MAX_ELT_PAYLOAD];
+       u8 data[sizeof(struct oz_ext_elt) + OZ_MAX_ELT_PAYLOAD];
        int length;
        unsigned magic;
 };
 /* Flags values */
 #define OZ_EI_F_MARKED         0x1
+#define OZ_EI_F_EXT_ELM                0x2
 
 struct oz_elt_buf {
        spinlock_t lock;
diff --git a/drivers/staging/ozwpan/ozevent.c b/drivers/staging/ozwpan/ozevent.c
deleted file mode 100644 (file)
index 77e8675..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#include "ozconfig.h"
-#ifdef WANT_EVENT_TRACE
-#include <linux/module.h>
-#include <linux/debugfs.h>
-#include <linux/jiffies.h>
-#include <linux/uaccess.h>
-#include "oztrace.h"
-#include "ozevent.h"
-#include "ozappif.h"
-/*------------------------------------------------------------------------------
- * Although the event mask is logically part of the oz_evtdev structure, it is
- * needed outside of this file so define it separately to avoid the need to
- * export definition of struct oz_evtdev.
- */
-u32 g_evt_mask;
-/*------------------------------------------------------------------------------
- */
-#define OZ_MAX_EVTS    2048    /* Must be power of 2 */
-struct oz_evtdev {
-       struct dentry *root_dir;
-       int evt_in;
-       int evt_out;
-       int missed_events;
-       int present;
-       atomic_t users;
-       spinlock_t lock;
-       struct oz_event evts[OZ_MAX_EVTS];
-};
-
-static struct oz_evtdev g_evtdev;
-
-/*------------------------------------------------------------------------------
- * Context: process
- */
-void oz_event_init(void)
-{
-       /* Because g_evtdev is static external all fields initially zero so no
-        * need to reinitialized those.
-        */
-       oz_trace("Event tracing initialized\n");
-       spin_lock_init(&g_evtdev.lock);
-       atomic_set(&g_evtdev.users, 0);
-}
-/*------------------------------------------------------------------------------
- * Context: process
- */
-void oz_event_term(void)
-{
-       oz_trace("Event tracing terminated\n");
-}
-/*------------------------------------------------------------------------------
- * Context: any
- */
-void oz_event_log2(u8 evt, u8 ctx1, u16 ctx2, void *ctx3, unsigned ctx4)
-{
-       unsigned long irqstate;
-       int ix;
-       spin_lock_irqsave(&g_evtdev.lock, irqstate);
-       ix = (g_evtdev.evt_in + 1) & (OZ_MAX_EVTS - 1);
-       if (ix != g_evtdev.evt_out) {
-               struct oz_event *e = &g_evtdev.evts[g_evtdev.evt_in];
-               e->jiffies = jiffies;
-               e->evt = evt;
-               e->ctx1 = ctx1;
-               e->ctx2 = ctx2;
-               e->ctx3 = (__u32)(unsigned long)ctx3;
-               e->ctx4 = ctx4;
-               g_evtdev.evt_in = ix;
-       } else {
-               g_evtdev.missed_events++;
-       }
-       spin_unlock_irqrestore(&g_evtdev.lock, irqstate);
-}
-/*------------------------------------------------------------------------------
- * Context: process
- */
-#ifdef CONFIG_DEBUG_FS
-static void oz_events_clear(struct oz_evtdev *dev)
-{
-       unsigned long irqstate;
-       oz_trace("Clearing events\n");
-       spin_lock_irqsave(&dev->lock, irqstate);
-       dev->evt_in = dev->evt_out = 0;
-       dev->missed_events = 0;
-       spin_unlock_irqrestore(&dev->lock, irqstate);
-}
-/*------------------------------------------------------------------------------
- * Context: process
- */
-static int oz_events_open(struct inode *inode, struct file *filp)
-{
-       oz_trace("oz_evt_open()\n");
-       oz_trace("Open flags: 0x%x\n", filp->f_flags);
-       if (atomic_add_return(1, &g_evtdev.users) == 1) {
-               oz_events_clear(&g_evtdev);
-               return nonseekable_open(inode, filp);
-       } else {
-               atomic_dec(&g_evtdev.users);
-               return -EBUSY;
-       }
-}
-/*------------------------------------------------------------------------------
- * Context: process
- */
-static int oz_events_release(struct inode *inode, struct file *filp)
-{
-       oz_events_clear(&g_evtdev);
-       atomic_dec(&g_evtdev.users);
-       g_evt_mask = 0;
-       oz_trace("oz_evt_release()\n");
-       return 0;
-}
-/*------------------------------------------------------------------------------
- * Context: process
- */
-static ssize_t oz_events_read(struct file *filp, char __user *buf, size_t count,
-               loff_t *fpos)
-{
-       struct oz_evtdev *dev = &g_evtdev;
-       int rc = 0;
-       int nb_evts = count / sizeof(struct oz_event);
-       int n;
-       int sz;
-
-       n = dev->evt_in - dev->evt_out;
-       if (n < 0)
-               n += OZ_MAX_EVTS;
-       if (nb_evts > n)
-               nb_evts = n;
-       if (nb_evts == 0)
-               goto out;
-       n = OZ_MAX_EVTS - dev->evt_out;
-       if (n > nb_evts)
-               n = nb_evts;
-       sz = n * sizeof(struct oz_event);
-       if (copy_to_user(buf, &dev->evts[dev->evt_out], sz)) {
-               rc = -EFAULT;
-               goto out;
-       }
-       if (n == nb_evts)
-               goto out2;
-       n = nb_evts - n;
-       if (copy_to_user(buf + sz, dev->evts, n * sizeof(struct oz_event))) {
-               rc = -EFAULT;
-               goto out;
-       }
-out2:
-       dev->evt_out = (dev->evt_out + nb_evts) & (OZ_MAX_EVTS - 1);
-       rc = nb_evts * sizeof(struct oz_event);
-out:
-       return rc;
-}
-/*------------------------------------------------------------------------------
- */
-static const struct file_operations oz_events_fops = {
-       .owner =        THIS_MODULE,
-       .open =         oz_events_open,
-       .release =      oz_events_release,
-       .read =         oz_events_read,
-};
-/*------------------------------------------------------------------------------
- * Context: process
- */
-void oz_debugfs_init(void)
-{
-       struct dentry *parent;
-
-       parent = debugfs_create_dir("ozwpan", NULL);
-       if (parent  == NULL) {
-               oz_trace("Failed to create debugfs directory ozmo\n");
-               return;
-       } else {
-               g_evtdev.root_dir = parent;
-               if (debugfs_create_file("events", S_IRUSR, parent, NULL,
-                                               &oz_events_fops) == NULL)
-                       oz_trace("Failed to create file ozmo/events\n");
-               if (debugfs_create_x32("event_mask", S_IRUSR | S_IWUSR, parent,
-                                                       &g_evt_mask) == NULL)
-                       oz_trace("Failed to create file ozmo/event_mask\n");
-       }
-}
-/*------------------------------------------------------------------------------
- * Context: process
- */
-void oz_debugfs_remove(void)
-{
-       debugfs_remove_recursive(g_evtdev.root_dir);
-}
-#endif /* CONFIG_DEBUG_FS */
-#endif /* WANT_EVENT_TRACE */
diff --git a/drivers/staging/ozwpan/ozevent.h b/drivers/staging/ozwpan/ozevent.h
deleted file mode 100644 (file)
index 32f6f98..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZEVENT_H
-#define _OZEVENT_H
-#include "ozconfig.h"
-#include "ozeventdef.h"
-
-#ifdef WANT_EVENT_TRACE
-extern u32 g_evt_mask;
-void oz_event_init(void);
-void oz_event_term(void);
-void oz_event_log2(u8 evt, u8 ctx1, u16 ctx2, void *ctx3, unsigned ctx4);
-void oz_debugfs_init(void);
-void oz_debugfs_remove(void);
-#define oz_event_log(__evt, __ctx1, __ctx2, __ctx3, __ctx4) \
-       do { \
-               if ((1<<(__evt)) & g_evt_mask) \
-                       oz_event_log2(__evt, __ctx1, __ctx2, __ctx3, __ctx4); \
-       } while (0)
-
-#else
-#define oz_event_init()
-#define oz_event_term()
-#define oz_event_log(__evt, __ctx1, __ctx2, __ctx3, __ctx4)
-#define oz_debugfs_init()
-#define oz_debugfs_remove()
-#endif /* WANT_EVENT_TRACE */
-
-#endif /* _OZEVENT_H */
diff --git a/drivers/staging/ozwpan/ozeventdef.h b/drivers/staging/ozwpan/ozeventdef.h
deleted file mode 100644 (file)
index 4b93898..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZEVENTDEF_H
-#define _OZEVENTDEF_H
-
-#define OZ_EVT_RX_FRAME                0
-#define OZ_EVT_RX_PROCESS      1
-#define OZ_EVT_TX_FRAME                2
-#define OZ_EVT_TX_ISOC         3
-#define OZ_EVT_URB_SUBMIT      4
-#define OZ_EVT_URB_DONE                5
-#define OZ_EVT_URB_CANCEL      6
-#define OZ_EVT_CTRL_REQ                7
-#define OZ_EVT_CTRL_CNF                8
-#define OZ_EVT_CTRL_LOCAL      9
-#define OZ_EVT_CONNECT_REQ     10
-#define OZ_EVT_CONNECT_RSP     11
-#define OZ_EVT_EP_CREDIT       12
-#define OZ_EVT_EP_BUFFERING    13
-#define OZ_EVT_TX_ISOC_DONE    14
-#define OZ_EVT_TX_ISOC_DROP    15
-#define OZ_EVT_TIMER_CTRL      16
-#define OZ_EVT_TIMER           17
-#define OZ_EVT_PD_STATE                18
-#define OZ_EVT_SERVICE         19
-#define OZ_EVT_DEBUG           20
-
-struct oz_event {
-       __u32 jiffies;
-       __u8 evt;
-       __u8 ctx1;
-       __u16 ctx2;
-       __u32 ctx3;
-       __u32 ctx4;
-};
-
-#endif /* _OZEVENTDEF_H */
diff --git a/drivers/staging/ozwpan/ozeventtrace.h b/drivers/staging/ozwpan/ozeventtrace.h
new file mode 100644 (file)
index 0000000..def0878
--- /dev/null
@@ -0,0 +1,219 @@
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * -----------------------------------------------------------------------------
+ */
+
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ozwpan
+
+#if !defined(_OZEVENTTRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+
+#define _OZEVENTTRACE_H
+
+#include <linux/tracepoint.h>
+#include <linux/usb.h>
+
+#define MAX_URB_LEN 16
+#define MAX_FRAME_LEN 32
+#define MAX_MSG_LEN 128
+
+TRACE_EVENT(urb_in,
+
+       TP_PROTO(struct urb *oz_urb),
+
+       TP_ARGS(oz_urb),
+
+       TP_STRUCT__entry(
+       __field(uintptr_t, urb)
+       __field(u32, endpoint)
+       __field(u32, buffer_length)
+       __field(u32, inc_length)
+       __array(u8, buffer, MAX_URB_LEN)
+       ),
+
+       TP_fast_assign(
+               __entry->urb            =       (uintptr_t)oz_urb;
+               __entry->endpoint       =       usb_pipeendpoint(oz_urb->pipe);
+               if (usb_pipein(oz_urb->pipe))
+                       __entry->endpoint |= 0x80;
+               __entry->buffer_length = oz_urb->transfer_buffer_length;
+               __entry->inc_length = oz_urb->transfer_buffer_length
+                <= MAX_URB_LEN ? oz_urb->transfer_buffer_length : MAX_URB_LEN;
+               if ((__entry->endpoint == 0x00) ||
+                                       (__entry->endpoint == 0x80)) {
+                       __entry->buffer_length = 8;
+                       __entry->inc_length = 8;
+                       memcpy(__entry->buffer, oz_urb->setup_packet, 8);
+               } else {
+                       memcpy(__entry->buffer, oz_urb->transfer_buffer,
+                                               __entry->inc_length);
+               }
+       ),
+
+       TP_printk("%08x,%02x,%03x,%03x,"
+        "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+       (u32)__entry->urb, __entry->endpoint, __entry->buffer_length,
+       __entry->inc_length, __entry->buffer[0], __entry->buffer[1],
+       __entry->buffer[2], __entry->buffer[3], __entry->buffer[4],
+       __entry->buffer[5], __entry->buffer[6], __entry->buffer[7],
+       __entry->buffer[8], __entry->buffer[9], __entry->buffer[10],
+       __entry->buffer[11], __entry->buffer[12], __entry->buffer[13],
+       __entry->buffer[14], __entry->buffer[15])
+);
+
+TRACE_EVENT(urb_out,
+
+       TP_PROTO(struct urb *oz_urb, int status),
+
+       TP_ARGS(oz_urb, status),
+
+       TP_STRUCT__entry(
+       __field(uintptr_t, urb)
+       __field(u32, endpoint)
+       __field(u32, status)
+       __field(u32, actual_length)
+       __field(u32, inc_length)
+       __array(u8, buffer, MAX_URB_LEN)
+       ),
+
+       TP_fast_assign(
+               __entry->urb            =       (uintptr_t)oz_urb;
+               __entry->endpoint       =       usb_pipeendpoint(oz_urb->pipe);
+               __entry->status         =       status;
+               if (usb_pipein(oz_urb->pipe))
+                       __entry->endpoint |= 0x80;
+               __entry->actual_length = oz_urb->actual_length;
+               __entry->inc_length = oz_urb->actual_length
+                <= MAX_URB_LEN ? oz_urb->actual_length : MAX_URB_LEN;
+               if (usb_pipein(oz_urb->pipe))
+                       memcpy(__entry->buffer, oz_urb->transfer_buffer,
+                                               __entry->inc_length);
+       ),
+
+       TP_printk("%08x,%08x,%02x,%03x,%03x,"
+        "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+       (u32)__entry->urb, __entry->status, __entry->endpoint,
+       __entry->actual_length, __entry->inc_length, __entry->buffer[0],
+       __entry->buffer[1], __entry->buffer[2], __entry->buffer[3],
+       __entry->buffer[4], __entry->buffer[5], __entry->buffer[6],
+       __entry->buffer[7], __entry->buffer[8], __entry->buffer[9],
+       __entry->buffer[10], __entry->buffer[11], __entry->buffer[12],
+       __entry->buffer[13], __entry->buffer[14], __entry->buffer[15])
+);
+
+TRACE_EVENT(rx_frame,
+
+       TP_PROTO(struct sk_buff *skb),
+
+       TP_ARGS(skb),
+
+       TP_STRUCT__entry(
+       __field(u32, inc_len)
+       __field(u32, orig_len)
+       __array(u8, data, MAX_FRAME_LEN)
+       ),
+
+       TP_fast_assign(
+               __entry->orig_len       =       skb->len;
+               __entry->inc_len        =       skb->len < MAX_FRAME_LEN ?
+                                               skb->len : MAX_FRAME_LEN;
+               memcpy(__entry->data, (u8 *)skb_network_header(skb),
+                               __entry->inc_len);
+       ),
+
+       TP_printk("%03x,%03x,%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+       "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+       "%02x%02x%02x", __entry->orig_len,
+       __entry->inc_len, __entry->data[0], __entry->data[1],
+       __entry->data[2], __entry->data[3], __entry->data[4],
+       __entry->data[5], __entry->data[6], __entry->data[7],
+       __entry->data[8], __entry->data[9], __entry->data[10],
+       __entry->data[11], __entry->data[12], __entry->data[13],
+       __entry->data[14], __entry->data[15], __entry->data[16],
+       __entry->data[17], __entry->data[18], __entry->data[19],
+       __entry->data[20], __entry->data[21], __entry->data[22],
+       __entry->data[23], __entry->data[24], __entry->data[25],
+       __entry->data[26], __entry->data[27], __entry->data[28],
+       __entry->data[29], __entry->data[30], __entry->data[31])
+);
+
+TRACE_EVENT(tx_frame,
+
+       TP_PROTO(struct sk_buff *skb),
+
+       TP_ARGS(skb),
+
+       TP_STRUCT__entry(
+       __field(u32, inc_len)
+       __field(u32, orig_len)
+       __array(u8, data, MAX_FRAME_LEN)
+       ),
+
+       TP_fast_assign(
+               __entry->orig_len       =       skb->len - 14;
+               __entry->inc_len        =       __entry->orig_len
+                                                < MAX_FRAME_LEN ?
+                                               __entry->orig_len
+                                               : MAX_FRAME_LEN;
+               memcpy(__entry->data, (u8 *)skb_network_header(skb),
+                               __entry->inc_len);
+       ),
+
+       TP_printk("%03x,%03x,%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+       "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+       "%02x%02x%02x", __entry->orig_len,
+       __entry->inc_len, __entry->data[0], __entry->data[1],
+       __entry->data[2], __entry->data[3], __entry->data[4],
+       __entry->data[5], __entry->data[6], __entry->data[7],
+       __entry->data[8], __entry->data[9], __entry->data[10],
+       __entry->data[11], __entry->data[12], __entry->data[13],
+       __entry->data[14], __entry->data[15], __entry->data[16],
+       __entry->data[17], __entry->data[18], __entry->data[19],
+       __entry->data[20], __entry->data[21], __entry->data[22],
+       __entry->data[23], __entry->data[24], __entry->data[25],
+       __entry->data[26], __entry->data[27], __entry->data[28],
+       __entry->data[29], __entry->data[30], __entry->data[31])
+);
+
+DECLARE_EVENT_CLASS(debug_msg,
+
+       TP_PROTO(char *fmt, va_list arg),
+
+       TP_ARGS(fmt, arg),
+
+       TP_STRUCT__entry(
+       __array(char, msg, MAX_MSG_LEN)
+       ),
+
+       TP_fast_assign(
+               snprintf(__entry->msg, MAX_MSG_LEN, fmt, arg);
+       ),
+
+       TP_printk("%s", __entry->msg)
+);
+
+DEFINE_EVENT(debug_msg, hcd_msg_evt,
+       TP_PROTO(char *fmt, va_list arg),
+       TP_ARGS(fmt, arg)
+);
+
+DEFINE_EVENT(debug_msg, isoc_msg_evt,
+       TP_PROTO(char *fmt, va_list arg),
+       TP_ARGS(fmt, arg)
+);
+
+DEFINE_EVENT(debug_msg, info_msg_evt,
+       TP_PROTO(char *fmt, va_list arg),
+       TP_ARGS(fmt, arg)
+);
+
+
+#endif /*_OZEVENTTRACE_H*/
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE ozeventtrace
+#include <trace/define_trace.h>
index 8ac26f584fd49cc40f9359c52146f161bb978354..c26547b4e553aecbb7fed0bc5e7eaf2f37641915 100644 (file)
  */
 #include <linux/platform_device.h>
 #include <linux/usb.h>
-#include <linux/jiffies.h>
 #include <linux/slab.h>
 #include <linux/export.h>
 #include "linux/usb/hcd.h"
 #include <asm/unaligned.h>
-#include "ozconfig.h"
 #include "ozusbif.h"
 #include "oztrace.h"
 #include "ozurbparanoia.h"
-#include "ozevent.h"
-#include "ozhcd.h"
-/*------------------------------------------------------------------------------
- * Number of units of buffering to capture for an isochronous IN endpoint before
- * allowing data to be indicated up.
- */
-#define OZ_IN_BUFFERING_UNITS  50
+
+#define OZ_HUB_DEBOUNCE_TIMEOUT        1500
+
 /* Name of our platform device.
  */
 #define OZ_PLAT_DEV_NAME       "ozwpan"
@@ -51,6 +45,9 @@
 /* Get endpoint object from the containing link.
  */
 #define ep_from_link(__e) container_of((__e), struct oz_endpoint, link)
+/*EP0 timeout before ep0 request is again added to TX queue. (13*8 = 98mSec)
+ */
+#define EP0_TIMEOUT_COUNTER 13
 /*------------------------------------------------------------------------------
  * Used to link urbs together and also store some status information for each
  * urb.
@@ -62,7 +59,7 @@ struct oz_urb_link {
        struct oz_port *port;
        u8 req_id;
        u8 ep_num;
-       unsigned long submit_jiffies;
+       unsigned submit_counter;
 };
 
 /* Holds state information about a USB endpoint.
@@ -71,7 +68,8 @@ struct oz_endpoint {
        struct list_head urb_list;      /* List of oz_urb_link items. */
        struct list_head link;          /* For isoc ep, links in to isoc
                                           lists of oz_port. */
-       unsigned long last_jiffies;
+       struct timespec timestamp;
+       int credit2;
        int credit;
        int credit_ceiling;
        u8 ep_num;
@@ -81,6 +79,7 @@ struct oz_endpoint {
        int in_ix;
        int out_ix;
        int buffered_units;
+       u8 max_buffer_units;
        unsigned flags;
        int start_frame;
 };
@@ -88,6 +87,13 @@ struct oz_endpoint {
 #define OZ_F_EP_BUFFERING      0x1
 #define OZ_F_EP_HAVE_STREAM    0x2
 
+
+/* Buffer_size.
+Total size of buffer (in bytes) for the endpoint buffer for isochronous data,
+and for stashing BULK or INT data if a URB is not available.
+*/
+#define OZ_EP_BUFFER_SIZE_ISOC  (1024*24)
+#define OZ_EP_BUFFER_SIZE_INT   (512)
 /* Holds state information about a USB interface.
  */
 struct oz_interface {
@@ -189,6 +195,7 @@ static DEFINE_SPINLOCK(g_tasklet_lock);
 static struct tasklet_struct g_urb_process_tasklet;
 static struct tasklet_struct g_urb_cancel_tasklet;
 static atomic_t g_pending_urbs = ATOMIC_INIT(0);
+static atomic_t g_usb_frame_number = ATOMIC_INIT(0);
 static const struct hc_driver g_oz_hc_drv = {
        .description =          g_hcd_name,
        .product_desc =         "Ozmo Devices WPAN",
@@ -237,9 +244,14 @@ static inline struct oz_hcd *oz_hcd_private(struct usb_hcd *hcd)
 static int oz_get_port_from_addr(struct oz_hcd *ozhcd, u8 bus_addr)
 {
        int i;
-       for (i = 0; i < OZ_NB_PORTS; i++) {
-               if (ozhcd->ports[i].bus_addr == bus_addr)
-                       return i;
+
+       if (0 != bus_addr) {
+               for (i = 0; i < OZ_NB_PORTS; i++) {
+                       if (ozhcd->ports[i].bus_addr == bus_addr)
+                               return i;
+               }
+
+               return -1;
        }
        return ozhcd->conn_port;
 }
@@ -249,7 +261,7 @@ static int oz_get_port_from_addr(struct oz_hcd *ozhcd, u8 bus_addr)
  */
 static struct oz_urb_link *oz_alloc_urb_link(void)
 {
-       struct oz_urb_link *urbl = NULL;
+       struct oz_urb_link *urbl = 0;
        unsigned long irq_state;
        spin_lock_irqsave(&g_link_lock, irq_state);
        if (g_link_pool) {
@@ -258,7 +270,7 @@ static struct oz_urb_link *oz_alloc_urb_link(void)
                --g_link_pool_size;
        }
        spin_unlock_irqrestore(&g_link_lock, irq_state);
-       if (urbl == NULL)
+       if (urbl == 0)
                urbl = kmalloc(sizeof(struct oz_urb_link), GFP_ATOMIC);
        return urbl;
 }
@@ -275,11 +287,12 @@ static void oz_free_urb_link(struct oz_urb_link *urbl)
                if (g_link_pool_size < OZ_MAX_LINK_POOL_SIZE) {
                        urbl->link.next = g_link_pool;
                        g_link_pool = &urbl->link;
-                       urbl = NULL;
+                       urbl = 0;
                        g_link_pool_size++;
                }
                spin_unlock_irqrestore(&g_link_lock, irq_state);
-               kfree(urbl);
+               if (urbl)
+                       kfree(urbl);
        }
 }
 /*------------------------------------------------------------------------------
@@ -292,7 +305,7 @@ static void oz_empty_link_pool(void)
        unsigned long irq_state;
        spin_lock_irqsave(&g_link_lock, irq_state);
        e = g_link_pool;
-       g_link_pool = NULL;
+       g_link_pool = 0;
        g_link_pool_size = 0;
        spin_unlock_irqrestore(&g_link_lock, irq_state);
        while (e) {
@@ -327,7 +340,7 @@ static struct oz_endpoint *oz_ep_alloc(gfp_t mem_flags, int buffer_size)
  * disabled.
  * Context: softirq or process
  */
-static struct oz_urb_link *oz_uncancel_urb(struct oz_hcd *ozhcd, struct urb *urb)
+struct oz_urb_link *oz_uncancel_urb(struct oz_hcd *ozhcd, struct urb *urb)
 {
        struct oz_urb_link *urbl;
        struct list_head *e;
@@ -338,7 +351,7 @@ static struct oz_urb_link *oz_uncancel_urb(struct oz_hcd *ozhcd, struct urb *urb
                        return urbl;
                }
        }
-       return NULL;
+       return 0;
 }
 /*------------------------------------------------------------------------------
  * This is called when we have finished processing an urb. It unlinks it from
@@ -346,17 +359,32 @@ static struct oz_urb_link *oz_uncancel_urb(struct oz_hcd *ozhcd, struct urb *urb
  * Context: softirq or process
  */
 static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb,
-               int status, unsigned long submit_jiffies)
+               int status)
 {
        struct oz_hcd *ozhcd = oz_hcd_private(hcd);
        unsigned long irq_state;
-       struct oz_urb_link *cancel_urbl = NULL;
+       struct oz_urb_link *cancel_urbl = 0;
        spin_lock_irqsave(&g_tasklet_lock, irq_state);
+
+       if (usb_pipeisoc(urb->pipe)) {
+               if (status < 0) {
+                       int i;
+                       urb->transfer_buffer_length = 0;
+                       for (i = 0; i < urb->number_of_packets; i++) {
+                               urb->iso_frame_desc[i].actual_length = 0;
+                               urb->iso_frame_desc[i].status = status;
+                       }
+               } else {
+                       /* ISOC checks transfer_buffer_length */
+                       urb->transfer_buffer_length = urb->actual_length;
+               }
+       }
+       oz_trace_urb_out(urb, status);
        usb_hcd_unlink_urb_from_ep(hcd, urb);
        /* Clear hcpriv which will prevent it being put in the cancel list
         * in the event that an attempt is made to cancel it.
         */
-       urb->hcpriv = NULL;
+       urb->hcpriv = 0;
        /* Walk the cancel list in case the urb is already sitting there.
         * Since we process the cancel list in a tasklet rather than in
         * the dequeue function this could happen.
@@ -374,14 +402,7 @@ static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb,
        if (oz_forget_urb(urb)) {
                oz_trace("OZWPAN: ERROR Unknown URB %p\n", urb);
        } else {
-               static unsigned long last_time;
                atomic_dec(&g_pending_urbs);
-               oz_trace2(OZ_TRACE_URB,
-                       "%lu: giveback_urb(%p,%x) %lu %lu pending:%d\n",
-                       jiffies, urb, status, jiffies-submit_jiffies,
-                       jiffies-last_time, atomic_read(&g_pending_urbs));
-               last_time = jiffies;
-               oz_event_log(OZ_EVT_URB_DONE, 0, 0, urb, status);
                usb_hcd_giveback_urb(hcd, urb, status);
        }
        spin_lock(&g_tasklet_lock);
@@ -396,7 +417,6 @@ static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb,
  */
 static void oz_ep_free(struct oz_port *port, struct oz_endpoint *ep)
 {
-       oz_trace("oz_ep_free()\n");
        if (port) {
                struct list_head list;
                struct oz_hcd *ozhcd = port->ozhcd;
@@ -411,19 +431,17 @@ static void oz_ep_free(struct oz_port *port, struct oz_endpoint *ep)
                list_splice_tail(&list, &ozhcd->orphanage);
                spin_unlock_bh(&ozhcd->hcd_lock);
        }
-       oz_trace("Freeing endpoint memory\n");
        kfree(ep);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq
  */
-static void oz_complete_buffered_urb(struct oz_port *port,
-                       struct oz_endpoint *ep,
+void oz_complete_buffered_urb(struct oz_port *port, struct oz_endpoint *ep,
                        struct urb *urb)
 {
-       u8 data_len, available_space, copy_len;
+       int data_len, available_space, copy_len;
 
-       memcpy(&data_len, &ep->buffer[ep->out_ix], sizeof(u8));
+       data_len = ep->buffer[ep->out_ix];
        if (data_len <= urb->transfer_buffer_length)
                available_space = data_len;
        else
@@ -448,9 +466,7 @@ static void oz_complete_buffered_urb(struct oz_port *port,
                ep->out_ix = 0;
 
        ep->buffered_units--;
-       oz_trace("Trying to give back buffered frame of size=%d\n",
-                                               available_space);
-       oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
+       oz_complete_urb(port->ozhcd->hcd, urb, 0);
 }
 
 /*------------------------------------------------------------------------------
@@ -469,7 +485,7 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
        urbl = oz_alloc_urb_link();
        if (!urbl)
                return -ENOMEM;
-       urbl->submit_jiffies = jiffies;
+       urbl->submit_counter = 0;
        urbl->urb = urb;
        urbl->req_id = req_id;
        urbl->ep_num = ep_addr;
@@ -483,14 +499,25 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
        if (urb->unlinked) {
                spin_unlock_bh(&port->ozhcd->hcd_lock);
                oz_trace("urb %p unlinked so complete immediately\n", urb);
-               oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
+               oz_complete_urb(port->ozhcd->hcd, urb, 0);
                oz_free_urb_link(urbl);
                return 0;
        }
-       if (in_dir)
-               ep = port->in_ep[ep_addr];
-       else
-               ep = port->out_ep[ep_addr];
+       if (in_dir) {
+               if (port->in_ep[ep_addr]) {
+                       ep = port->in_ep[ep_addr];
+               } else {
+                       err = -EINVAL;
+                       goto out;
+               }
+       } else {
+               if (port->out_ep[ep_addr]) {
+                       ep = port->out_ep[ep_addr];
+               } else {
+                       err = -EINVAL;
+                       goto out;
+               }
+       }
 
        /*For interrupt endpoint check for buffered data
        * & complete urb
@@ -506,14 +533,13 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
        if (ep && port->hpd) {
                list_add_tail(&urbl->link, &ep->urb_list);
                if (!in_dir && ep_addr && (ep->credit < 0)) {
-                       ep->last_jiffies = jiffies;
+                       getrawmonotonic(&ep->timestamp);
                        ep->credit = 0;
-                       oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num,
-                                       0, NULL, ep->credit);
                }
        } else {
                err = -EPIPE;
        }
+out:
        spin_unlock_bh(&port->ozhcd->hcd_lock);
        if (err)
                oz_free_urb_link(urbl);
@@ -527,7 +553,7 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
 static int oz_dequeue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
                        struct urb *urb)
 {
-       struct oz_urb_link *urbl = NULL;
+       struct oz_urb_link *urbl = 0;
        struct oz_endpoint *ep;
        spin_lock_bh(&port->ozhcd->hcd_lock);
        if (in_dir)
@@ -542,7 +568,7 @@ static int oz_dequeue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
                                list_del_init(e);
                                break;
                        }
-                       urbl = NULL;
+                       urbl = 0;
                }
        }
        spin_unlock_bh(&port->ozhcd->hcd_lock);
@@ -558,8 +584,8 @@ static struct urb *oz_find_urb_by_id(struct oz_port *port, int ep_ix,
                u8 req_id)
 {
        struct oz_hcd *ozhcd = port->ozhcd;
-       struct urb *urb = NULL;
-       struct oz_urb_link *urbl = NULL;
+       struct urb *urb = 0;
+       struct oz_urb_link *urbl = 0;
        struct oz_endpoint *ep;
 
        spin_lock_bh(&ozhcd->hcd_lock);
@@ -582,6 +608,35 @@ static struct urb *oz_find_urb_by_id(struct oz_port *port, int ep_ix,
                oz_free_urb_link(urbl);
        return urb;
 }
+/*------------------------------------------------------------------------------
+ * Finds an urbl given request it, then set submit_count to 1, thus heartbeat
+ * count this value up to EP0_TIMEOUT.
+ */
+void oz_hcd_mark_urb_submitted(void *hport, int ep_ix, u8 req_id)
+{
+       struct oz_port *port = (struct oz_port *)hport;
+       struct oz_hcd *ozhcd = port->ozhcd;
+       struct oz_urb_link *urbl = 0;
+       struct oz_endpoint *ep;
+       unsigned long irq_state;
+       unsigned found = 0;
+       spin_lock_bh(&ozhcd->hcd_lock);
+       spin_lock_irqsave(&g_tasklet_lock, irq_state);
+       ep = port->out_ep[ep_ix];
+       if (ep) {
+               struct list_head *e;
+               list_for_each(e, &ep->urb_list) {
+                       urbl = container_of(e, struct oz_urb_link, link);
+                       if (urbl->req_id == req_id) {
+                               urbl->submit_counter = 1;
+                               found = 1;
+                               break;
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
+       spin_unlock_bh(&ozhcd->hcd_lock);
+}
 /*------------------------------------------------------------------------------
  * Pre-condition: Port lock must be held.
  * Context: softirq
@@ -632,13 +687,14 @@ static inline void oz_hcd_put(struct oz_hcd *ozhcd)
 void *oz_hcd_pd_arrived(void *hpd)
 {
        int i;
-       void *hport = NULL;
-       struct oz_hcd *ozhcd = NULL;
+       void *hport = 0;
+       struct oz_hcd *ozhcd = 0;
        struct oz_endpoint *ep;
-       oz_trace("oz_hcd_pd_arrived()\n");
+       static int n = OZ_NB_PORTS;
+       int j;
        ozhcd = oz_hcd_claim();
-       if (ozhcd == NULL)
-               return NULL;
+       if (ozhcd == 0)
+               return 0;
        /* Allocate an endpoint object in advance (before holding hcd lock) to
         * use for out endpoint 0.
         */
@@ -646,39 +702,45 @@ void *oz_hcd_pd_arrived(void *hpd)
        spin_lock_bh(&ozhcd->hcd_lock);
        if (ozhcd->conn_port >= 0) {
                spin_unlock_bh(&ozhcd->hcd_lock);
-               oz_trace("conn_port >= 0\n");
                goto out;
        }
+       j = n;
        for (i = 0; i < OZ_NB_PORTS; i++) {
-               struct oz_port *port = &ozhcd->ports[i];
+               struct oz_port *port;
+               if (++j >= OZ_NB_PORTS)
+                       j = 0;
+               port  = &ozhcd->ports[j];
                spin_lock(&port->port_lock);
                if ((port->flags & OZ_PORT_F_PRESENT) == 0) {
                        oz_acquire_port(port, hpd);
+                       port->bus_addr = 0;
+                       port->config_num = 0;
                        spin_unlock(&port->port_lock);
                        break;
                }
                spin_unlock(&port->port_lock);
        }
        if (i < OZ_NB_PORTS) {
-               oz_trace("Setting conn_port = %d\n", i);
-               ozhcd->conn_port = i;
+               ozhcd->conn_port = j;
                /* Attach out endpoint 0.
                 */
-               ozhcd->ports[i].out_ep[0] = ep;
-               ep = NULL;
-               hport = &ozhcd->ports[i];
+               ozhcd->ports[j].out_ep[0] = ep;
+               ep = 0;
+               hport = &ozhcd->ports[j];
                spin_unlock_bh(&ozhcd->hcd_lock);
                if (ozhcd->flags & OZ_HDC_F_SUSPENDED) {
-                       oz_trace("Resuming root hub\n");
+                       oz_trace_msg(H, "usb_hcd_resume_root_hub()\n");
                        usb_hcd_resume_root_hub(ozhcd->hcd);
                }
+               n = j;
+               oz_trace_msg(H, "usb_hcd_poll_rh()\n");
                usb_hcd_poll_rh_status(ozhcd->hcd);
        } else {
                spin_unlock_bh(&ozhcd->hcd_lock);
        }
 out:
        if (ep) /* ep is non-null if not used. */
-               oz_ep_free(NULL, ep);
+               oz_ep_free(0, ep);
        oz_hcd_put(ozhcd);
        return hport;
 }
@@ -693,22 +755,21 @@ void oz_hcd_pd_departed(void *hport)
        struct oz_port *port = (struct oz_port *)hport;
        struct oz_hcd *ozhcd;
        void *hpd;
-       struct oz_endpoint *ep = NULL;
+       struct oz_endpoint *ep = 0;
 
-       oz_trace("oz_hcd_pd_departed()\n");
-       if (port == NULL) {
-               oz_trace("oz_hcd_pd_departed() port = 0\n");
+       oz_trace("%s:\n", __func__);
+       if (port == 0) {
+               oz_trace("%s: port = 0\n", __func__);
                return;
        }
        ozhcd = port->ozhcd;
-       if (ozhcd == NULL)
+       if (ozhcd == 0)
                return;
        /* Check if this is the connection port - if so clear it.
         */
        spin_lock_bh(&ozhcd->hcd_lock);
        if ((ozhcd->conn_port >= 0) &&
                (port == &ozhcd->ports[ozhcd->conn_port])) {
-               oz_trace("Clearing conn_port\n");
                ozhcd->conn_port = -1;
        }
        spin_lock(&port->port_lock);
@@ -719,22 +780,24 @@ void oz_hcd_pd_departed(void *hport)
        oz_clean_endpoints_for_config(ozhcd->hcd, port);
        spin_lock_bh(&port->port_lock);
        hpd = port->hpd;
-       port->hpd = NULL;
+       port->hpd = 0;
        port->bus_addr = 0xff;
+       port->config_num = 0;
        port->flags &= ~(OZ_PORT_F_PRESENT | OZ_PORT_F_DYING);
        port->flags |= OZ_PORT_F_CHANGED;
-       port->status &= ~USB_PORT_STAT_CONNECTION;
+       port->status &= ~(USB_PORT_STAT_CONNECTION|USB_PORT_STAT_ENABLE);
        port->status |= (USB_PORT_STAT_C_CONNECTION << 16);
        /* If there is an endpont 0 then clear the pointer while we hold
         * the spinlock be we deallocate it after releasing the lock.
         */
        if (port->out_ep[0]) {
                ep = port->out_ep[0];
-               port->out_ep[0] = NULL;
+               port->out_ep[0] = 0;
        }
        spin_unlock_bh(&port->port_lock);
        if (ep)
                oz_ep_free(port, ep);
+       oz_trace_msg(H, "usb_hcd_poll_rh_status()\n");
        usb_hcd_poll_rh_status(ozhcd->hcd);
        oz_usb_put(hpd);
 }
@@ -759,16 +822,13 @@ void oz_hcd_pd_reset(void *hpd, void *hport)
 /*------------------------------------------------------------------------------
  * Context: softirq
  */
-void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, const u8 *desc,
+void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, u8 *desc,
                        int length, int offset, int total_size)
 {
        struct oz_port *port = (struct oz_port *)hport;
        struct urb *urb;
        int err = 0;
 
-       oz_event_log(OZ_EVT_CTRL_CNF, 0, req_id, NULL, status);
-       oz_trace("oz_hcd_get_desc_cnf length = %d offs = %d tot_size = %d\n",
-                       length, offset, total_size);
        urb = oz_find_urb_by_id(port, 0, req_id);
        if (!urb)
                return;
@@ -800,53 +860,8 @@ void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, const u8 *desc,
                }
        }
        urb->actual_length = total_size;
-       oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
-}
-/*------------------------------------------------------------------------------
- * Context: softirq
- */
-#ifdef WANT_TRACE
-static void oz_display_conf_type(u8 t)
-{
-       switch (t) {
-       case USB_REQ_GET_STATUS:
-               oz_trace("USB_REQ_GET_STATUS - cnf\n");
-               break;
-       case USB_REQ_CLEAR_FEATURE:
-               oz_trace("USB_REQ_CLEAR_FEATURE - cnf\n");
-               break;
-       case USB_REQ_SET_FEATURE:
-               oz_trace("USB_REQ_SET_FEATURE - cnf\n");
-               break;
-       case USB_REQ_SET_ADDRESS:
-               oz_trace("USB_REQ_SET_ADDRESS - cnf\n");
-               break;
-       case USB_REQ_GET_DESCRIPTOR:
-               oz_trace("USB_REQ_GET_DESCRIPTOR - cnf\n");
-               break;
-       case USB_REQ_SET_DESCRIPTOR:
-               oz_trace("USB_REQ_SET_DESCRIPTOR - cnf\n");
-               break;
-       case USB_REQ_GET_CONFIGURATION:
-               oz_trace("USB_REQ_GET_CONFIGURATION - cnf\n");
-               break;
-       case USB_REQ_SET_CONFIGURATION:
-               oz_trace("USB_REQ_SET_CONFIGURATION - cnf\n");
-               break;
-       case USB_REQ_GET_INTERFACE:
-               oz_trace("USB_REQ_GET_INTERFACE - cnf\n");
-               break;
-       case USB_REQ_SET_INTERFACE:
-               oz_trace("USB_REQ_SET_INTERFACE - cnf\n");
-               break;
-       case USB_REQ_SYNCH_FRAME:
-               oz_trace("USB_REQ_SYNCH_FRAME - cnf\n");
-               break;
-       }
+       oz_complete_urb(port->ozhcd->hcd, urb, 0);
 }
-#else
-#define oz_display_conf_type(__x)
-#endif /* WANT_TRACE */
 /*------------------------------------------------------------------------------
  * Context: softirq
  */
@@ -865,7 +880,7 @@ static void oz_hcd_complete_set_config(struct oz_port *port, struct urb *urb,
        } else {
                rc = -ENOMEM;
        }
-       oz_complete_urb(hcd, urb, rc, 0);
+       oz_complete_urb(hcd, urb, rc);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq
@@ -876,26 +891,29 @@ static void oz_hcd_complete_set_interface(struct oz_port *port, struct urb *urb,
        struct usb_hcd *hcd = port->ozhcd->hcd;
        int rc = 0;
        if (rcode == 0) {
-               struct usb_host_config *config;
-               struct usb_host_interface *intf;
-               oz_trace("Set interface %d alt %d\n", if_num, alt);
-               oz_clean_endpoints_for_interface(hcd, port, if_num);
-               config = &urb->dev->config[port->config_num-1];
-               intf = &config->intf_cache[if_num]->altsetting[alt];
-               if (oz_build_endpoints_for_interface(hcd, port, intf,
-                       GFP_ATOMIC))
+               if (port->config_num > 0) {
+                       struct usb_host_config *config;
+                       struct usb_host_interface *intf;
+
+                       oz_clean_endpoints_for_interface(hcd, port, if_num);
+                       config = &urb->dev->config[port->config_num-1];
+                       intf = &config->intf_cache[if_num]->altsetting[alt];
+                       if (oz_build_endpoints_for_interface(hcd, port, intf,
+                               GFP_ATOMIC))
+                               rc = -ENOMEM;
+                       else
+                               port->iface[if_num].alt = alt;
+               } else
                        rc = -ENOMEM;
-               else
-                       port->iface[if_num].alt = alt;
        } else {
                rc = -ENOMEM;
        }
-       oz_complete_urb(hcd, urb, rc, 0);
+       oz_complete_urb(hcd, urb, rc);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq
  */
-void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data,
+void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, u8 *data,
        int data_len)
 {
        struct oz_port *port = (struct oz_port *)hport;
@@ -905,11 +923,9 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data,
        unsigned windex;
        unsigned wvalue;
 
-       oz_event_log(OZ_EVT_CTRL_CNF, 0, req_id, NULL, rcode);
-       oz_trace("oz_hcd_control_cnf rcode=%u len=%d\n", rcode, data_len);
        urb = oz_find_urb_by_id(port, 0, req_id);
        if (!urb) {
-               oz_trace("URB not found\n");
+               oz_trace("URB not found: %p\n", urb);
                return;
        }
        setup = (struct usb_ctrlrequest *)urb->setup_packet;
@@ -917,7 +933,6 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data,
        wvalue = le16_to_cpu(setup->wValue);
        if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
                /* Standard requests */
-               oz_display_conf_type(setup->bRequest);
                switch (setup->bRequest) {
                case USB_REQ_SET_CONFIGURATION:
                        oz_hcd_complete_set_config(port, urb, rcode,
@@ -928,12 +943,11 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data,
                                (u8)windex, (u8)wvalue);
                        break;
                default:
-                       oz_complete_urb(hcd, urb, 0, 0);
+                       oz_complete_urb(hcd, urb, 0);
                }
 
        } else {
                int copy_len;
-               oz_trace("VENDOR-CLASS - cnf\n");
                if (data_len) {
                        if (data_len <= urb->transfer_buffer_length)
                                copy_len = data_len;
@@ -942,14 +956,13 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data,
                        memcpy(urb->transfer_buffer, data, copy_len);
                        urb->actual_length = copy_len;
                }
-               oz_complete_urb(hcd, urb, 0, 0);
+               oz_complete_urb(hcd, urb, 0);
        }
 }
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
  */
-static int oz_hcd_buffer_data(struct oz_endpoint *ep, const u8 *data,
-                             int data_len)
+static int oz_hcd_buffer_data(struct oz_endpoint *ep, u8 *data, int data_len)
 {
        int space;
        int copy_len;
@@ -959,7 +972,10 @@ static int oz_hcd_buffer_data(struct oz_endpoint *ep, const u8 *data,
        if (space < 0)
                space += ep->buffer_size;
        if (space < (data_len+1)) {
-               oz_trace("Buffer full\n");
+               oz_trace_msg(I, "EP:%02X u:%d FULL len:%d spc:%d\n",
+                               ep->ep_num | USB_DIR_IN,
+                               ep->buffered_units,
+                               data_len, space);
                return -1;
        }
        ep->buffer[ep->in_ix] = (u8)data_len;
@@ -984,14 +1000,14 @@ static int oz_hcd_buffer_data(struct oz_endpoint *ep, const u8 *data,
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
  */
-void oz_hcd_data_ind(void *hport, u8 endpoint, const u8 *data, int data_len)
+void oz_hcd_data_ind(void *hport, u8 endpoint, u8 *data, int data_len)
 {
        struct oz_port *port = (struct oz_port *)hport;
        struct oz_endpoint *ep;
        struct oz_hcd *ozhcd = port->ozhcd;
        spin_lock_bh(&ozhcd->hcd_lock);
        ep = port->in_ep[endpoint & USB_ENDPOINT_NUMBER_MASK];
-       if (ep == NULL)
+       if (ep == 0)
                goto done;
        switch (ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) {
        case USB_ENDPOINT_XFER_INT:
@@ -1012,15 +1028,35 @@ void oz_hcd_data_ind(void *hport, u8 endpoint, const u8 *data, int data_len)
                                copy_len = urb->transfer_buffer_length;
                        memcpy(urb->transfer_buffer, data, copy_len);
                        urb->actual_length = copy_len;
-                       oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
+                       oz_complete_urb(port->ozhcd->hcd, urb, 0);
                        return;
                } else {
-                       oz_trace("buffering frame as URB is not available\n");
                        oz_hcd_buffer_data(ep, data, data_len);
                }
                break;
        case USB_ENDPOINT_XFER_ISOC:
-               oz_hcd_buffer_data(ep, data, data_len);
+               if (oz_hcd_buffer_data(ep, data, data_len) != 0) {
+                       int len;
+                       int copy_len;
+                       while (ep->buffered_units > ep->max_buffer_units) {
+                               len = ep->buffer[ep->out_ix];
+                               if (++ep->out_ix == ep->buffer_size)
+                                       ep->out_ix = 0;
+                               copy_len = ep->buffer_size - ep->out_ix;
+                               if (copy_len > len)
+                                       copy_len = len;
+                               if (copy_len < len)
+                                       ep->out_ix = len - copy_len;
+                               else
+                                       ep->out_ix += copy_len;
+
+                               if (ep->out_ix == ep->buffer_size)
+                                       ep->out_ix = 0;
+
+                               ep->buffered_units--;
+                       }
+                       ep->flags |= OZ_F_EP_BUFFERING;
+               }
                break;
        }
 done:
@@ -1031,7 +1067,7 @@ done:
  */
 static inline int oz_usb_get_frame_number(void)
 {
-       return jiffies_to_msecs(get_jiffies_64());
+       return atomic_inc_return(&g_usb_frame_number);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq
@@ -1047,7 +1083,8 @@ int oz_hcd_heartbeat(void *hport)
        struct list_head *n;
        struct urb *urb;
        struct oz_endpoint *ep;
-       unsigned long now = jiffies;
+       struct timespec ts, delta;
+       getrawmonotonic(&ts);
        INIT_LIST_HEAD(&xfr_list);
        /* Check the OUT isoc endpoints to see if any URB data can be sent.
         */
@@ -1056,12 +1093,11 @@ int oz_hcd_heartbeat(void *hport)
                ep = ep_from_link(e);
                if (ep->credit < 0)
                        continue;
-               ep->credit += jiffies_to_msecs(now - ep->last_jiffies);
+               delta = timespec_sub(ts, ep->timestamp);
+               ep->credit += div64_u64(timespec_to_ns(&delta), NSEC_PER_MSEC);
                if (ep->credit > ep->credit_ceiling)
                        ep->credit = ep->credit_ceiling;
-               oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num, 0, NULL,
-                            ep->credit);
-               ep->last_jiffies = now;
+               ep->timestamp = ts;
                while (ep->credit && !list_empty(&ep->urb_list)) {
                        urbl = list_first_entry(&ep->urb_list,
                                struct oz_urb_link, link);
@@ -1069,49 +1105,44 @@ int oz_hcd_heartbeat(void *hport)
                        if ((ep->credit + 1) < urb->number_of_packets)
                                break;
                        ep->credit -= urb->number_of_packets;
-                       oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num, 0, NULL,
-                                    ep->credit);
-                       list_move_tail(&urbl->link, &xfr_list);
+                       if (ep->credit < 0)
+                               ep->credit = 0;
+                       list_del(&urbl->link);
+                       list_add_tail(&urbl->link, &xfr_list);
                }
        }
        spin_unlock_bh(&ozhcd->hcd_lock);
        /* Send to PD and complete URBs.
         */
        list_for_each_safe(e, n, &xfr_list) {
-               unsigned long t;
                urbl = container_of(e, struct oz_urb_link, link);
                urb = urbl->urb;
-               t = urbl->submit_jiffies;
                list_del_init(e);
                urb->error_count = 0;
                urb->start_frame = oz_usb_get_frame_number();
                oz_usb_send_isoc(port->hpd, urbl->ep_num, urb);
                oz_free_urb_link(urbl);
-               oz_complete_urb(port->ozhcd->hcd, urb, 0, t);
+               oz_complete_urb(port->ozhcd->hcd, urb, 0);
        }
        /* Check the IN isoc endpoints to see if any URBs can be completed.
         */
        spin_lock_bh(&ozhcd->hcd_lock);
        list_for_each(e, &port->isoc_in_ep) {
                struct oz_endpoint *ep = ep_from_link(e);
+
                if (ep->flags & OZ_F_EP_BUFFERING) {
-                       if (ep->buffered_units >= OZ_IN_BUFFERING_UNITS) {
+                       if (ep->buffered_units >= ep->max_buffer_units) {
                                ep->flags &= ~OZ_F_EP_BUFFERING;
                                ep->credit = 0;
-                               oz_event_log(OZ_EVT_EP_CREDIT,
-                                       ep->ep_num | USB_DIR_IN,
-                                       0, NULL, ep->credit);
-                               ep->last_jiffies = now;
+                               ep->credit2 = 0;
+                               ep->timestamp = ts;
                                ep->start_frame = 0;
-                               oz_event_log(OZ_EVT_EP_BUFFERING,
-                                       ep->ep_num | USB_DIR_IN, 0, NULL, 0);
                        }
                        continue;
                }
-               ep->credit += jiffies_to_msecs(now - ep->last_jiffies);
-               oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num | USB_DIR_IN,
-                       0, NULL, ep->credit);
-               ep->last_jiffies = now;
+               delta = timespec_sub(ts, ep->timestamp);
+               ep->credit += div64_u64(timespec_to_ns(&delta)+5000, NSEC_PER_MSEC);
+               ep->timestamp = ts;
                while (!list_empty(&ep->urb_list)) {
                        struct oz_urb_link *urbl =
                                list_first_entry(&ep->urb_list,
@@ -1120,8 +1151,6 @@ int oz_hcd_heartbeat(void *hport)
                        int len = 0;
                        int copy_len;
                        int i;
-                       if ((ep->credit + 1) < urb->number_of_packets)
-                               break;
                        if (ep->buffered_units < urb->number_of_packets)
                                break;
                        urb->actual_length = 0;
@@ -1152,10 +1181,32 @@ int oz_hcd_heartbeat(void *hport)
                        urb->error_count = 0;
                        urb->start_frame = ep->start_frame;
                        ep->start_frame += urb->number_of_packets;
-                       list_move_tail(&urbl->link, &xfr_list);
+                       list_del(&urbl->link);
+                       list_add_tail(&urbl->link, &xfr_list);
                        ep->credit -= urb->number_of_packets;
-                       oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num | USB_DIR_IN,
-                               0, NULL, ep->credit);
+                       ep->credit2 += urb->number_of_packets;
+               }
+               if (ep->buffered_units == 0) {
+                       oz_trace_msg(I, "EP:%02X Buffer under run\n",
+                                       ep->ep_num | USB_DIR_IN);
+                       ep->flags |= OZ_F_EP_BUFFERING;
+                       continue;
+               }
+               if (ep->credit2 >= 1000)
+               {
+                       static int buffered_units=-1;
+                       static int max_buffer_units=-1;
+                       {
+                               int diff = ep->buffered_units - buffered_units;
+                               oz_trace_msg(I, "u:%d o:%04d b:%d\n",
+                                               ep->credit2,
+                                               ep->credit2 + diff,
+                                               ep->buffered_units);
+
+                               buffered_units = ep->buffered_units;
+                               max_buffer_units = ep->max_buffer_units;
+                       }
+                       ep->credit2 = 0;
                }
        }
        if (!list_empty(&port->isoc_out_ep) || !list_empty(&port->isoc_in_ep))
@@ -1168,7 +1219,7 @@ int oz_hcd_heartbeat(void *hport)
                urb = urbl->urb;
                list_del_init(e);
                oz_free_urb_link(urbl);
-               oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
+               oz_complete_urb(port->ozhcd->hcd, urb, 0);
        }
        /* Check if there are any ep0 requests that have timed out.
         * If so resent to PD.
@@ -1180,11 +1231,15 @@ int oz_hcd_heartbeat(void *hport)
                spin_lock_bh(&ozhcd->hcd_lock);
                list_for_each_safe(e, n, &ep->urb_list) {
                        urbl = container_of(e, struct oz_urb_link, link);
-                       if (time_after(now, urbl->submit_jiffies+HZ/2)) {
-                               oz_trace("%ld: Request 0x%p timeout\n",
-                                               now, urbl->urb);
-                               urbl->submit_jiffies = now;
-                               list_move_tail(e, &xfr_list);
+                       if (urbl->submit_counter > EP0_TIMEOUT_COUNTER) {
+                               oz_trace_msg(M, "URB:%08X timeout %02X\n",
+                                       (unsigned int)((uintptr_t)urbl->urb),
+                                       urbl->req_id);
+                               list_del(e);
+                               list_add_tail(e, &xfr_list);
+                               urbl->submit_counter = 0;
+                       } else if (urbl->submit_counter) {
+                               urbl->submit_counter++;
                        }
                }
                if (!list_empty(&ep->urb_list))
@@ -1194,7 +1249,7 @@ int oz_hcd_heartbeat(void *hport)
                while (e != &xfr_list) {
                        urbl = container_of(e, struct oz_urb_link, link);
                        e = e->next;
-                       oz_trace("Resending request to PD.\n");
+                       oz_trace_msg(M, "Resending request to PD.\n");
                        oz_process_ep0_urb(ozhcd, urbl->urb, GFP_ATOMIC);
                        oz_free_urb_link(urbl);
                }
@@ -1210,9 +1265,17 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd,
 {
        struct oz_hcd *ozhcd = port->ozhcd;
        int i;
-       int if_ix = intf->desc.bInterfaceNumber;
+       int if_ix;
        int request_heartbeat = 0;
+
+       if (intf == NULL)
+               return -ENOMEM;
+
+       if_ix = intf->desc.bInterfaceNumber;
        oz_trace("interface[%d] = %p\n", if_ix, intf);
+       if (if_ix >= port->num_iface || port->iface == NULL)
+               return -ENOMEM;
+
        for (i = 0; i < intf->desc.bNumEndpoints; i++) {
                struct usb_host_endpoint *hep = &intf->endpoint[i];
                u8 ep_addr = hep->desc.bEndpointAddress;
@@ -1220,15 +1283,14 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd,
                struct oz_endpoint *ep;
                int buffer_size = 0;
 
-               oz_trace("%d bEndpointAddress = %x\n", i, ep_addr);
                if (ep_addr & USB_ENDPOINT_DIR_MASK) {
                        switch (hep->desc.bmAttributes &
                                                USB_ENDPOINT_XFERTYPE_MASK) {
                        case USB_ENDPOINT_XFER_ISOC:
-                               buffer_size = 24*1024;
+                               buffer_size = OZ_EP_BUFFER_SIZE_ISOC;
                                break;
                        case USB_ENDPOINT_XFER_INT:
-                               buffer_size = 128;
+                               buffer_size = OZ_EP_BUFFER_SIZE_INT;
                                break;
                        }
                }
@@ -1242,13 +1304,11 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd,
                ep->ep_num = ep_num;
                if ((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK)
                        == USB_ENDPOINT_XFER_ISOC) {
-                       oz_trace("wMaxPacketSize = %d\n",
-                               hep->desc.wMaxPacketSize);
                        ep->credit_ceiling = 200;
                        if (ep_addr & USB_ENDPOINT_DIR_MASK) {
+                               ep->max_buffer_units =
+                                        oz_get_up_max_buffer_units(port->hpd);
                                ep->flags |= OZ_F_EP_BUFFERING;
-                               oz_event_log(OZ_EVT_EP_BUFFERING,
-                                       ep->ep_num | USB_DIR_IN, 1, NULL, 0);
                        } else {
                                ep->flags |= OZ_F_EP_HAVE_STREAM;
                                if (oz_usb_stream_create(port->hpd, ep_num))
@@ -1304,17 +1364,19 @@ static void oz_clean_endpoints_for_interface(struct usb_hcd *hcd,
                 */
                if ((mask & (1<<i)) && port->out_ep[i]) {
                        e = &port->out_ep[i]->link;
-                       port->out_ep[i] = NULL;
+                       port->out_ep[i] = 0;
                        /* Remove from isoc list if present.
                         */
-                       list_move_tail(e, &ep_list);
+                       list_del(e);
+                       list_add_tail(e, &ep_list);
                }
                /* Gather IN endpoints.
                 */
                if ((mask & (1<<(i+OZ_NB_ENDPOINTS))) && port->in_ep[i]) {
                        e = &port->in_ep[i]->link;
-                       port->in_ep[i] = NULL;
-                       list_move_tail(e, &ep_list);
+                       port->in_ep[i] = 0;
+                       list_del(e);
+                       list_add_tail(e, &ep_list);
                }
        }
        spin_unlock_bh(&ozhcd->hcd_lock);
@@ -1372,9 +1434,8 @@ static void oz_clean_endpoints_for_config(struct usb_hcd *hcd,
                oz_clean_endpoints_for_interface(hcd, port, i);
        spin_lock_bh(&ozhcd->hcd_lock);
        if (port->iface) {
-               oz_trace("Freeing interfaces object.\n");
                kfree(port->iface);
-               port->iface = NULL;
+               port->iface = 0;
        }
        port->num_iface = 0;
        spin_unlock_bh(&ozhcd->hcd_lock);
@@ -1384,7 +1445,7 @@ static void oz_clean_endpoints_for_config(struct usb_hcd *hcd,
  */
 static void *oz_claim_hpd(struct oz_port *port)
 {
-       void *hpd = NULL;
+       void *hpd = 0;
        struct oz_hcd *ozhcd = port->ozhcd;
        spin_lock_bh(&ozhcd->hcd_lock);
        hpd = port->hpd;
@@ -1403,16 +1464,15 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
        unsigned windex;
        unsigned wvalue;
        unsigned wlength;
-       void *hpd = NULL;
+       void *hpd = 0;
        u8 req_id;
        int rc = 0;
        unsigned complete = 0;
 
        int port_ix = -1;
-       struct oz_port *port = NULL;
+       struct oz_port *port = 0;
 
-       oz_trace2(OZ_TRACE_URB, "%lu: oz_process_ep0_urb(%p)\n", jiffies, urb);
-       port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum);
+       port_ix = oz_get_port_from_addr(ozhcd, (usb_pipedevice(urb->pipe)));
        if (port_ix < 0) {
                rc = -EPIPE;
                goto out;
@@ -1432,17 +1492,10 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
        windex = le16_to_cpu(setup->wIndex);
        wvalue = le16_to_cpu(setup->wValue);
        wlength = le16_to_cpu(setup->wLength);
-       oz_trace2(OZ_TRACE_CTRL_DETAIL, "bRequestType = %x\n",
-               setup->bRequestType);
-       oz_trace2(OZ_TRACE_CTRL_DETAIL, "bRequest = %x\n", setup->bRequest);
-       oz_trace2(OZ_TRACE_CTRL_DETAIL, "wValue = %x\n", wvalue);
-       oz_trace2(OZ_TRACE_CTRL_DETAIL, "wIndex = %x\n", windex);
-       oz_trace2(OZ_TRACE_CTRL_DETAIL, "wLength = %x\n", wlength);
 
        req_id = port->next_req_id++;
        hpd = oz_claim_hpd(port);
-       if (hpd == NULL) {
-               oz_trace("Cannot claim port\n");
+       if (hpd == 0) {
                rc = -EPIPE;
                goto out;
        }
@@ -1452,34 +1505,23 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
                 */
                switch (setup->bRequest) {
                case USB_REQ_GET_DESCRIPTOR:
-                       oz_trace("USB_REQ_GET_DESCRIPTOR - req\n");
                        break;
                case USB_REQ_SET_ADDRESS:
-                       oz_event_log(OZ_EVT_CTRL_LOCAL, setup->bRequest,
-                               0, NULL, setup->bRequestType);
-                       oz_trace("USB_REQ_SET_ADDRESS - req\n");
-                       oz_trace("Port %d address is 0x%x\n", ozhcd->conn_port,
-                               (u8)le16_to_cpu(setup->wValue));
                        spin_lock_bh(&ozhcd->hcd_lock);
                        if (ozhcd->conn_port >= 0) {
                                ozhcd->ports[ozhcd->conn_port].bus_addr =
                                        (u8)le16_to_cpu(setup->wValue);
-                               oz_trace("Clearing conn_port\n");
                                ozhcd->conn_port = -1;
                        }
                        spin_unlock_bh(&ozhcd->hcd_lock);
                        complete = 1;
                        break;
                case USB_REQ_SET_CONFIGURATION:
-                       oz_trace("USB_REQ_SET_CONFIGURATION - req\n");
                        break;
                case USB_REQ_GET_CONFIGURATION:
                        /* We short circuit this case and reply directly since
                         * we have the selected configuration number cached.
                         */
-                       oz_event_log(OZ_EVT_CTRL_LOCAL, setup->bRequest, 0,
-                                    NULL, setup->bRequestType);
-                       oz_trace("USB_REQ_GET_CONFIGURATION - reply now\n");
                        if (urb->transfer_buffer_length >= 1) {
                                urb->actual_length = 1;
                                *((u8 *)urb->transfer_buffer) =
@@ -1493,22 +1535,16 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
                        /* We short circuit this case and reply directly since
                         * we have the selected interface alternative cached.
                         */
-                       oz_event_log(OZ_EVT_CTRL_LOCAL, setup->bRequest, 0,
-                                    NULL, setup->bRequestType);
-                       oz_trace("USB_REQ_GET_INTERFACE - reply now\n");
                        if (urb->transfer_buffer_length >= 1) {
                                urb->actual_length = 1;
                                *((u8 *)urb->transfer_buffer) =
                                        port->iface[(u8)windex].alt;
-                               oz_trace("interface = %d alt = %d\n",
-                                       windex, port->iface[(u8)windex].alt);
                                complete = 1;
                        } else {
                                rc = -EPIPE;
                        }
                        break;
                case USB_REQ_SET_INTERFACE:
-                       oz_trace("USB_REQ_SET_INTERFACE - req\n");
                        break;
                }
        }
@@ -1539,8 +1575,7 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
        oz_usb_put(hpd);
 out:
        if (rc || complete) {
-               oz_trace("Completing request locally\n");
-               oz_complete_urb(ozhcd->hcd, urb, rc, 0);
+               oz_complete_urb(ozhcd->hcd, urb, rc);
        } else {
                oz_usb_request_heartbeat(port->hpd);
        }
@@ -1565,14 +1600,14 @@ static int oz_urb_process(struct oz_hcd *ozhcd, struct urb *urb)
        /* Check if there is a device at the port - refuse if not.
         */
        if ((port->flags & OZ_PORT_F_PRESENT) == 0)
-               return -EPIPE;
+               return -ENODEV;
        ep_addr = usb_pipeendpoint(urb->pipe);
        if (ep_addr) {
                /* If the request is not for EP0 then queue it.
                 */
                if (oz_enqueue_ep_urb(port, ep_addr, usb_pipein(urb->pipe),
                        urb, 0))
-                       rc = -EPIPE;
+                       rc = -ENOENT;
        } else {
                oz_process_ep0_urb(ozhcd, urb, GFP_ATOMIC);
        }
@@ -1587,7 +1622,7 @@ static void oz_urb_process_tasklet(unsigned long unused)
        struct urb *urb;
        struct oz_hcd *ozhcd = oz_hcd_claim();
        int rc = 0;
-       if (ozhcd == NULL)
+       if (ozhcd == 0)
                return;
        /* This is called from a tasklet so is in softirq context but the urb
         * list is filled from any context so we need to lock
@@ -1604,7 +1639,7 @@ static void oz_urb_process_tasklet(unsigned long unused)
                oz_free_urb_link(urbl);
                rc = oz_urb_process(ozhcd, urb);
                if (rc)
-                       oz_complete_urb(ozhcd->hcd, urb, rc, 0);
+                       oz_complete_urb(ozhcd->hcd, urb, rc);
                spin_lock_irqsave(&g_tasklet_lock, irq_state);
        }
        spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
@@ -1621,18 +1656,18 @@ static void oz_urb_process_tasklet(unsigned long unused)
  */
 static void oz_urb_cancel(struct oz_port *port, u8 ep_num, struct urb *urb)
 {
-       struct oz_urb_link *urbl = NULL;
+       struct oz_urb_link *urbl = 0;
        struct list_head *e;
        struct oz_hcd *ozhcd;
        unsigned long irq_state;
        u8 ix;
-       if (port == NULL) {
-               oz_trace("ERRORERROR: oz_urb_cancel(%p) port is null\n", urb);
+       if (port == 0) {
+               oz_trace("%s: urb=%p port is null\n", __func__, urb);
                return;
        }
        ozhcd = port->ozhcd;
-       if (ozhcd == NULL) {
-               oz_trace("ERRORERROR: oz_urb_cancel(%p) ozhcd is null\n", urb);
+       if (ozhcd == 0) {
+               oz_trace("%s: urb=%p ozhcd is null\n", __func__, urb);
                return;
        }
 
@@ -1648,7 +1683,7 @@ static void oz_urb_cancel(struct oz_port *port, u8 ep_num, struct urb *urb)
                }
        }
        spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
-       urbl = NULL;
+       urbl = 0;
 
        /* Look in the orphanage.
         */
@@ -1657,12 +1692,12 @@ static void oz_urb_cancel(struct oz_port *port, u8 ep_num, struct urb *urb)
                urbl = container_of(e, struct oz_urb_link, link);
                if (urbl->urb == urb) {
                        list_del(e);
-                       oz_trace("Found urb in orphanage\n");
+                       oz_trace("Found urb in orphanage urb=%p\n", urb);
                        goto out;
                }
        }
        ix = (ep_num & 0xf);
-       urbl = NULL;
+       urbl = 0;
        if ((ep_num & USB_DIR_IN) && ix)
                urbl = oz_remove_urb(port->in_ep[ix], urb);
        else
@@ -1673,7 +1708,7 @@ out2:
        if (urbl) {
                urb->actual_length = 0;
                oz_free_urb_link(urbl);
-               oz_complete_urb(ozhcd->hcd, urb, -EPIPE, 0);
+               oz_complete_urb(ozhcd->hcd, urb, -ENOENT);
        }
 }
 /*------------------------------------------------------------------------------
@@ -1684,7 +1719,7 @@ static void oz_urb_cancel_tasklet(unsigned long unused)
        unsigned long irq_state;
        struct urb *urb;
        struct oz_hcd *ozhcd = oz_hcd_claim();
-       if (ozhcd == NULL)
+       if (ozhcd == 0)
                return;
        spin_lock_irqsave(&g_tasklet_lock, irq_state);
        while (!list_empty(&ozhcd->urb_cancel_list)) {
@@ -1713,7 +1748,7 @@ static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status)
                        urbl = list_first_entry(&ozhcd->orphanage,
                                struct oz_urb_link, link);
                        list_del(&urbl->link);
-                       oz_complete_urb(ozhcd->hcd, urbl->urb, status, 0);
+                       oz_complete_urb(ozhcd->hcd, urbl->urb, status);
                        oz_free_urb_link(urbl);
                }
        }
@@ -1723,7 +1758,6 @@ static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status)
  */
 static int oz_hcd_start(struct usb_hcd *hcd)
 {
-       oz_trace("oz_hcd_start()\n");
        hcd->power_budget = 200;
        hcd->state = HC_STATE_RUNNING;
        hcd->uses_new_polling = 1;
@@ -1734,29 +1768,15 @@ static int oz_hcd_start(struct usb_hcd *hcd)
  */
 static void oz_hcd_stop(struct usb_hcd *hcd)
 {
-       oz_trace("oz_hcd_stop()\n");
+       oz_trace("%s:\n", __func__);
 }
 /*------------------------------------------------------------------------------
  * Context: unknown
  */
 static void oz_hcd_shutdown(struct usb_hcd *hcd)
 {
-       oz_trace("oz_hcd_shutdown()\n");
+       oz_trace("%s:\n", __func__);
 }
-/*------------------------------------------------------------------------------
- * Context: any
- */
-#ifdef WANT_EVENT_TRACE
-static u8 oz_get_irq_ctx(void)
-{
-       u8 irq_info = 0;
-       if (in_interrupt())
-               irq_info |= 1;
-       if (in_irq())
-               irq_info |= 2;
-       return irq_info;
-}
-#endif /* WANT_EVENT_TRACE */
 /*------------------------------------------------------------------------------
  * Called to queue an urb for the device.
  * This function should return a non-zero error code if it fails the urb but
@@ -1772,39 +1792,34 @@ static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
        struct oz_port *port;
        unsigned long irq_state;
        struct oz_urb_link *urbl;
-       oz_trace2(OZ_TRACE_URB, "%lu: oz_hcd_urb_enqueue(%p)\n",
-               jiffies, urb);
-       oz_event_log(OZ_EVT_URB_SUBMIT, oz_get_irq_ctx(),
-               (u16)urb->number_of_packets, urb, urb->pipe);
-       if (unlikely(ozhcd == NULL)) {
-               oz_trace2(OZ_TRACE_URB, "%lu: Refused urb(%p) not ozhcd.\n",
-                       jiffies, urb);
-               return -EPIPE;
+       if (unlikely(ozhcd == 0)) {
+               oz_trace("Refused urb(%p) not ozhcd.\n", urb);
+               return -ENODEV;
        }
        if (unlikely(hcd->state != HC_STATE_RUNNING)) {
-               oz_trace2(OZ_TRACE_URB, "%lu: Refused urb(%p) not running.\n",
-                       jiffies, urb);
-               return -EPIPE;
+               oz_trace("Refused urb(%p) not running.\n", urb);
+               return -ENODEV;
        }
-       port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum);
+       port_ix = oz_get_port_from_addr(ozhcd, (usb_pipedevice(urb->pipe)));
        if (port_ix < 0)
-               return -EPIPE;
+               return -ENODEV;
        port =  &ozhcd->ports[port_ix];
-       if (port == NULL)
-               return -EPIPE;
+       if (port == 0)
+               return -ENODEV;
        if ((port->flags & OZ_PORT_F_PRESENT) == 0) {
                oz_trace("Refusing URB port_ix = %d devnum = %d\n",
                        port_ix, urb->dev->devnum);
-               return -EPIPE;
+               return -ENODEV;
        }
        urb->hcpriv = port;
        /* Put request in queue for processing by tasklet.
         */
        urbl = oz_alloc_urb_link();
-       if (unlikely(urbl == NULL))
+       if (unlikely(urbl == 0))
                return -ENOMEM;
        urbl->urb = urb;
        spin_lock_irqsave(&g_tasklet_lock, irq_state);
+       oz_trace_urb_in(urb);
        rc = usb_hcd_link_urb_to_ep(hcd, urb);
        if (unlikely(rc)) {
                spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
@@ -1823,27 +1838,24 @@ static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
 static struct oz_urb_link *oz_remove_urb(struct oz_endpoint *ep,
                                struct urb *urb)
 {
-       struct oz_urb_link *urbl = NULL;
+       struct oz_urb_link *urbl = 0;
        struct list_head *e;
-       if (unlikely(ep == NULL))
-               return NULL;
+       if (unlikely(ep == 0))
+               return 0;
        list_for_each(e, &ep->urb_list) {
                urbl = container_of(e, struct oz_urb_link, link);
                if (urbl->urb == urb) {
                        list_del_init(e);
                        if (usb_pipeisoc(urb->pipe)) {
+                               oz_trace_msg(M, "oz_remove_urb:%p\n", urb);
                                ep->credit -= urb->number_of_packets;
                                if (ep->credit < 0)
                                        ep->credit = 0;
-                               oz_event_log(OZ_EVT_EP_CREDIT,
-                                       usb_pipein(urb->pipe) ?
-                                       (ep->ep_num | USB_DIR_IN) : ep->ep_num,
-                                       0, NULL, ep->credit);
                        }
                        return urbl;
                }
        }
-       return NULL;
+       return 0;
 }
 /*------------------------------------------------------------------------------
  * Called to dequeue a previously submitted urb for the device.
@@ -1852,12 +1864,12 @@ static struct oz_urb_link *oz_remove_urb(struct oz_endpoint *ep,
 static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 {
        struct oz_hcd *ozhcd = oz_hcd_private(hcd);
-       struct oz_urb_link *urbl = NULL;
+       struct oz_urb_link *urbl = 0;
        int rc;
        unsigned long irq_state;
-       oz_trace2(OZ_TRACE_URB, "%lu: oz_hcd_urb_dequeue(%p)\n", jiffies, urb);
+
        urbl = oz_alloc_urb_link();
-       if (unlikely(urbl == NULL))
+       if (unlikely(urbl == 0))
                return -ENOMEM;
        spin_lock_irqsave(&g_tasklet_lock, irq_state);
        /* The following function checks the urb is still in the queue
@@ -1891,7 +1903,7 @@ static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 static void oz_hcd_endpoint_disable(struct usb_hcd *hcd,
                                struct usb_host_endpoint *ep)
 {
-       oz_trace("oz_hcd_endpoint_disable\n");
+       oz_trace("%s:\n", __func__);
 }
 /*------------------------------------------------------------------------------
  * Context: unknown
@@ -1899,14 +1911,13 @@ static void oz_hcd_endpoint_disable(struct usb_hcd *hcd,
 static void oz_hcd_endpoint_reset(struct usb_hcd *hcd,
                                struct usb_host_endpoint *ep)
 {
-       oz_trace("oz_hcd_endpoint_reset\n");
+       oz_trace("%s:\n", __func__);
 }
 /*------------------------------------------------------------------------------
  * Context: unknown
  */
 static int oz_hcd_get_frame_number(struct usb_hcd *hcd)
 {
-       oz_trace("oz_hcd_get_frame_number\n");
        return oz_usb_get_frame_number();
 }
 /*------------------------------------------------------------------------------
@@ -1919,19 +1930,24 @@ static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf)
        struct oz_hcd *ozhcd = oz_hcd_private(hcd);
        int i;
 
-       oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_status_data()\n");
        buf[0] = 0;
-
+       buf[1] = 0;
        spin_lock_bh(&ozhcd->hcd_lock);
        for (i = 0; i < OZ_NB_PORTS; i++) {
                if (ozhcd->ports[i].flags & OZ_PORT_F_CHANGED) {
-                       oz_trace2(OZ_TRACE_HUB, "Port %d changed\n", i);
-                       ozhcd->ports[i].flags &= ~OZ_PORT_F_CHANGED;
-                       buf[0] |= 1<<(i+1);
+                       if (i < 7)
+                               buf[0] |= 1<<(i+1);
+                       else
+                               buf[1] |= 1<<(i-7);
                }
        }
+       oz_trace_msg(H, "HUBSTS : %02X%02X\n",
+                               buf[1], buf[0]);
        spin_unlock_bh(&ozhcd->hcd_lock);
-       return buf[0] ? 1 : 0;
+       if (buf[1] != 0 || buf[0] != 0)
+               return 2;
+       else
+               return 1;
 }
 /*------------------------------------------------------------------------------
  * Context: process
@@ -1939,7 +1955,6 @@ static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf)
 static void oz_get_hub_descriptor(struct usb_hcd *hcd,
                                struct usb_hub_descriptor *desc)
 {
-       oz_trace2(OZ_TRACE_HUB, "GetHubDescriptor\n");
        memset(desc, 0, sizeof(*desc));
        desc->bDescriptorType = 0x29;
        desc->bDescLength = 9;
@@ -1958,59 +1973,59 @@ static int oz_set_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
        struct oz_hcd *ozhcd = oz_hcd_private(hcd);
        unsigned set_bits = 0;
        unsigned clear_bits = 0;
-       oz_trace2(OZ_TRACE_HUB, "SetPortFeature\n");
+
        if ((port_id < 1) || (port_id > OZ_NB_PORTS))
-               return -EPIPE;
+               return -ENODEV;
        port = &ozhcd->ports[port_id-1];
        switch (wvalue) {
        case USB_PORT_FEAT_CONNECTION:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_CONNECTION\n");
+               oz_trace("USB_PORT_FEAT_CONNECTION\n");
                break;
        case USB_PORT_FEAT_ENABLE:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_ENABLE\n");
+               oz_trace("USB_PORT_FEAT_ENABLE\n");
                break;
        case USB_PORT_FEAT_SUSPEND:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_SUSPEND\n");
+               oz_trace("USB_PORT_FEAT_SUSPEND\n");
                break;
        case USB_PORT_FEAT_OVER_CURRENT:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_OVER_CURRENT\n");
+               oz_trace("USB_PORT_FEAT_OVER_CURRENT\n");
                break;
        case USB_PORT_FEAT_RESET:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_RESET\n");
+               oz_trace("USB_PORT_FEAT_RESET\n");
                set_bits = USB_PORT_STAT_ENABLE | (USB_PORT_STAT_C_RESET<<16);
                clear_bits = USB_PORT_STAT_RESET;
                ozhcd->ports[port_id-1].bus_addr = 0;
                break;
        case USB_PORT_FEAT_POWER:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_POWER\n");
+               oz_trace("USB_PORT_FEAT_POWER\n");
                set_bits |= USB_PORT_STAT_POWER;
                break;
        case USB_PORT_FEAT_LOWSPEED:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_LOWSPEED\n");
+               oz_trace("USB_PORT_FEAT_LOWSPEED\n");
                break;
        case USB_PORT_FEAT_C_CONNECTION:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_CONNECTION\n");
+               oz_trace("USB_PORT_FEAT_C_CONNECTION\n");
                break;
        case USB_PORT_FEAT_C_ENABLE:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_ENABLE\n");
+               oz_trace("USB_PORT_FEAT_C_ENABLE\n");
                break;
        case USB_PORT_FEAT_C_SUSPEND:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_SUSPEND\n");
+               oz_trace("USB_PORT_FEAT_C_SUSPEND\n");
                break;
        case USB_PORT_FEAT_C_OVER_CURRENT:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n");
+               oz_trace("USB_PORT_FEAT_C_OVER_CURRENT\n");
                break;
        case USB_PORT_FEAT_C_RESET:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_RESET\n");
+               oz_trace("USB_PORT_FEAT_C_RESET\n");
                break;
        case USB_PORT_FEAT_TEST:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_TEST\n");
+               oz_trace("USB_PORT_FEAT_TEST\n");
                break;
        case USB_PORT_FEAT_INDICATOR:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_INDICATOR\n");
+               oz_trace("USB_PORT_FEAT_INDICATOR\n");
                break;
        default:
-               oz_trace2(OZ_TRACE_HUB, "Other %d\n", wvalue);
+               oz_trace("Other %d\n", wvalue);
                break;
        }
        if (set_bits || clear_bits) {
@@ -2019,8 +2034,9 @@ static int oz_set_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
                port->status |= set_bits;
                spin_unlock_bh(&port->port_lock);
        }
-       oz_trace2(OZ_TRACE_HUB, "Port[%d] status = 0x%x\n", port_id,
-               port->status);
+
+       oz_trace_msg(H, "Port[%d]: %08X\n", port_id,
+               ozhcd->ports[port_id-1].status);
        return err;
 }
 /*------------------------------------------------------------------------------
@@ -2033,60 +2049,60 @@ static int oz_clear_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
        u8 port_id = (u8)windex;
        struct oz_hcd *ozhcd = oz_hcd_private(hcd);
        unsigned clear_bits = 0;
-       oz_trace2(OZ_TRACE_HUB, "ClearPortFeature\n");
+
        if ((port_id < 1) || (port_id > OZ_NB_PORTS))
-               return -EPIPE;
+               return -ENODEV;
        port = &ozhcd->ports[port_id-1];
        switch (wvalue) {
        case USB_PORT_FEAT_CONNECTION:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_CONNECTION\n");
+               oz_trace("USB_PORT_FEAT_CONNECTION\n");
                break;
        case USB_PORT_FEAT_ENABLE:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_ENABLE\n");
+               oz_trace("USB_PORT_FEAT_ENABLE\n");
                clear_bits = USB_PORT_STAT_ENABLE;
                break;
        case USB_PORT_FEAT_SUSPEND:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_SUSPEND\n");
+               oz_trace("USB_PORT_FEAT_SUSPEND\n");
                break;
        case USB_PORT_FEAT_OVER_CURRENT:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_OVER_CURRENT\n");
+               oz_trace("USB_PORT_FEAT_OVER_CURRENT\n");
                break;
        case USB_PORT_FEAT_RESET:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_RESET\n");
+               oz_trace("USB_PORT_FEAT_RESET\n");
                break;
        case USB_PORT_FEAT_POWER:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_POWER\n");
+               oz_trace("USB_PORT_FEAT_POWER\n");
                clear_bits |= USB_PORT_STAT_POWER;
                break;
        case USB_PORT_FEAT_LOWSPEED:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_LOWSPEED\n");
+               oz_trace("USB_PORT_FEAT_LOWSPEED\n");
                break;
        case USB_PORT_FEAT_C_CONNECTION:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_CONNECTION\n");
+               oz_trace("USB_PORT_FEAT_C_CONNECTION\n");
                clear_bits = (USB_PORT_STAT_C_CONNECTION << 16);
                break;
        case USB_PORT_FEAT_C_ENABLE:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_ENABLE\n");
+               oz_trace("USB_PORT_FEAT_C_ENABLE\n");
                clear_bits = (USB_PORT_STAT_C_ENABLE << 16);
                break;
        case USB_PORT_FEAT_C_SUSPEND:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_SUSPEND\n");
+               oz_trace("USB_PORT_FEAT_C_SUSPEND\n");
                break;
        case USB_PORT_FEAT_C_OVER_CURRENT:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n");
+               oz_trace("USB_PORT_FEAT_C_OVER_CURRENT\n");
                break;
        case USB_PORT_FEAT_C_RESET:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_RESET\n");
+               oz_trace("USB_PORT_FEAT_C_RESET\n");
                clear_bits = (USB_PORT_FEAT_C_RESET << 16);
                break;
        case USB_PORT_FEAT_TEST:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_TEST\n");
+               oz_trace("USB_PORT_FEAT_TEST\n");
                break;
        case USB_PORT_FEAT_INDICATOR:
-               oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_INDICATOR\n");
+               oz_trace("USB_PORT_FEAT_INDICATOR\n");
                break;
        default:
-               oz_trace2(OZ_TRACE_HUB, "Other %d\n", wvalue);
+               oz_trace("Other %d\n", wvalue);
                break;
        }
        if (clear_bits) {
@@ -2094,7 +2110,8 @@ static int oz_clear_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
                port->status &= ~clear_bits;
                spin_unlock_bh(&port->port_lock);
        }
-       oz_trace2(OZ_TRACE_HUB, "Port[%d] status = 0x%x\n", port_id,
+
+       oz_trace_msg(H, "Port[%d]: %08X\n", port_id,
                ozhcd->ports[port_id-1].status);
        return err;
 }
@@ -2106,12 +2123,12 @@ static int oz_get_port_status(struct usb_hcd *hcd, u16 windex, char *buf)
        struct oz_hcd *ozhcd;
        u32 status = 0;
        if ((windex < 1) || (windex > OZ_NB_PORTS))
-               return -EPIPE;
+               return -ENODEV;
        ozhcd = oz_hcd_private(hcd);
-       oz_trace2(OZ_TRACE_HUB, "GetPortStatus windex = %d\n", windex);
+       ozhcd->ports[windex-1].flags &= ~OZ_PORT_F_CHANGED;
        status = ozhcd->ports[windex-1].status;
        put_unaligned(cpu_to_le32(status), (__le32 *)buf);
-       oz_trace2(OZ_TRACE_HUB, "Port[%d] status = %x\n", windex, status);
+       oz_trace_msg(H, "Port[%d]: %08X\n", windex, status);
        return 0;
 }
 /*------------------------------------------------------------------------------
@@ -2121,10 +2138,13 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
                                u16 windex, char *buf, u16 wlength)
 {
        int err = 0;
-       oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_control()\n");
+
+       oz_trace_msg(H, "HUBCTL: %04X %04X %04X %04X\n",
+               req_type, wvalue, windex, wlength);
+
        switch (req_type) {
        case ClearHubFeature:
-               oz_trace2(OZ_TRACE_HUB, "ClearHubFeature: %d\n", req_type);
+               oz_trace("ClearHubFeature: %d\n", req_type);
                break;
        case ClearPortFeature:
                err = oz_clear_port_feature(hcd, wvalue, windex);
@@ -2133,7 +2153,7 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
                oz_get_hub_descriptor(hcd, (struct usb_hub_descriptor *)buf);
                break;
        case GetHubStatus:
-               oz_trace2(OZ_TRACE_HUB, "GetHubStatus: req_type = 0x%x\n",
+               oz_trace("GetHubStatus: req_type = 0x%x\n",
                        req_type);
                put_unaligned(__constant_cpu_to_le32(0), (__le32 *)buf);
                break;
@@ -2141,13 +2161,13 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
                err = oz_get_port_status(hcd, windex, buf);
                break;
        case SetHubFeature:
-               oz_trace2(OZ_TRACE_HUB, "SetHubFeature: %d\n", req_type);
+               oz_trace("SetHubFeature: %d\n", req_type);
                break;
        case SetPortFeature:
                err = oz_set_port_feature(hcd, wvalue, windex);
                break;
        default:
-               oz_trace2(OZ_TRACE_HUB, "Other: %d\n", req_type);
+               oz_trace("Other: %d\n", req_type);
                break;
        }
        return err;
@@ -2158,7 +2178,7 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
 static int oz_hcd_bus_suspend(struct usb_hcd *hcd)
 {
        struct oz_hcd *ozhcd;
-       oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_suspend()\n");
+
        ozhcd = oz_hcd_private(hcd);
        spin_lock_bh(&ozhcd->hcd_lock);
        hcd->state = HC_STATE_SUSPENDED;
@@ -2172,7 +2192,7 @@ static int oz_hcd_bus_suspend(struct usb_hcd *hcd)
 static int oz_hcd_bus_resume(struct usb_hcd *hcd)
 {
        struct oz_hcd *ozhcd;
-       oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_resume()\n");
+
        ozhcd = oz_hcd_private(hcd);
        spin_lock_bh(&ozhcd->hcd_lock);
        ozhcd->flags &= ~OZ_HDC_F_SUSPENDED;
@@ -2184,7 +2204,7 @@ static int oz_hcd_bus_resume(struct usb_hcd *hcd)
  */
 static void oz_plat_shutdown(struct platform_device *dev)
 {
-       oz_trace("oz_plat_shutdown()\n");
+       oz_trace("%s:\n", __func__);
 }
 /*------------------------------------------------------------------------------
  * Context: process
@@ -2195,10 +2215,10 @@ static int oz_plat_probe(struct platform_device *dev)
        int err;
        struct usb_hcd *hcd;
        struct oz_hcd *ozhcd;
-       oz_trace("oz_plat_probe()\n");
+
        hcd = usb_create_hcd(&g_oz_hc_drv, &dev->dev, dev_name(&dev->dev));
-       if (hcd == NULL) {
-               oz_trace("Failed to created hcd object OK\n");
+       if (hcd == 0) {
+               oz_trace("Failed to created hcd object\n");
                return -ENOMEM;
        }
        ozhcd = oz_hcd_private(hcd);
@@ -2217,9 +2237,9 @@ static int oz_plat_probe(struct platform_device *dev)
                port->bus_addr = 0xff;
                spin_lock_init(&port->port_lock);
        }
-       err = usb_add_hcd(hcd, 0, 0);
+       err = usb_add_hcd(hcd, -1, 0);
        if (err) {
-               oz_trace("Failed to add hcd object OK\n");
+               oz_trace("Failed to add hcd object\n");
                usb_put_hcd(hcd);
                return -1;
        }
@@ -2235,17 +2255,15 @@ static int oz_plat_remove(struct platform_device *dev)
 {
        struct usb_hcd *hcd = platform_get_drvdata(dev);
        struct oz_hcd *ozhcd;
-       oz_trace("oz_plat_remove()\n");
-       if (hcd == NULL)
+
+       if (hcd == 0)
                return -1;
        ozhcd = oz_hcd_private(hcd);
        spin_lock_bh(&g_hcdlock);
        if (ozhcd == g_ozhcd)
-               g_ozhcd = NULL;
+               g_ozhcd = 0;
        spin_unlock_bh(&g_hcdlock);
-       oz_trace("Clearing orphanage\n");
-       oz_hcd_clear_orphanage(ozhcd, -EPIPE);
-       oz_trace("Removing hcd\n");
+       oz_hcd_clear_orphanage(ozhcd, -ENODEV);
        usb_remove_hcd(hcd);
        usb_put_hcd(hcd);
        oz_empty_link_pool();
@@ -2256,7 +2274,7 @@ static int oz_plat_remove(struct platform_device *dev)
  */
 static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg)
 {
-       oz_trace("oz_plat_suspend()\n");
+       oz_trace("%s:\n", __func__);
        return 0;
 }
 /*------------------------------------------------------------------------------
@@ -2264,7 +2282,7 @@ static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg)
  */
 static int oz_plat_resume(struct platform_device *dev)
 {
-       oz_trace("oz_plat_resume()\n");
+       oz_trace("%s:\n", __func__);
        return 0;
 }
 /*------------------------------------------------------------------------------
@@ -2275,22 +2293,20 @@ int oz_hcd_init(void)
        int err;
        if (usb_disabled())
                return -ENODEV;
+
        tasklet_init(&g_urb_process_tasklet, oz_urb_process_tasklet, 0);
        tasklet_init(&g_urb_cancel_tasklet, oz_urb_cancel_tasklet, 0);
        err = platform_driver_register(&g_oz_plat_drv);
-       oz_trace("platform_driver_register() returned %d\n", err);
        if (err)
                goto error;
        g_plat_dev = platform_device_alloc(OZ_PLAT_DEV_NAME, -1);
-       if (g_plat_dev == NULL) {
+       if (g_plat_dev == 0) {
                err = -ENOMEM;
                goto error1;
        }
-       oz_trace("platform_device_alloc() succeeded\n");
        err = platform_device_add(g_plat_dev);
        if (err)
                goto error2;
-       oz_trace("platform_device_add() succeeded\n");
        return 0;
 error2:
        platform_device_put(g_plat_dev);
@@ -2299,7 +2315,7 @@ error1:
 error:
        tasklet_disable(&g_urb_process_tasklet);
        tasklet_disable(&g_urb_cancel_tasklet);
-       oz_trace("oz_hcd_init() failed %d\n", err);
+       oz_trace("HCD Init failed: %d\n", err);
        return err;
 }
 /*------------------------------------------------------------------------------
@@ -2307,8 +2323,9 @@ error:
  */
 void oz_hcd_term(void)
 {
-       tasklet_kill(&g_urb_process_tasklet);
-       tasklet_kill(&g_urb_cancel_tasklet);
+       msleep(OZ_HUB_DEBOUNCE_TIMEOUT);
+       tasklet_disable(&g_urb_process_tasklet);
+       tasklet_disable(&g_urb_cancel_tasklet);
        platform_device_unregister(g_plat_dev);
        platform_driver_unregister(&g_oz_plat_drv);
        oz_trace("Pending urbs:%d\n", atomic_read(&g_pending_urbs));
diff --git a/drivers/staging/ozwpan/ozkobject.c b/drivers/staging/ozwpan/ozkobject.c
new file mode 100644 (file)
index 0000000..9b85ef5
--- /dev/null
@@ -0,0 +1,304 @@
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * -----------------------------------------------------------------------------
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/sysfs.h>
+#include <linux/version.h>
+#include "ozpd.h"
+#include "ozcdev.h"
+#include "ozproto.h"
+#include "oztrace.h"
+#include "ozkobject.h"
+#include "ozappif.h"
+
+static ssize_t devices_show(struct kobject *kobj, struct kobj_attribute *attr,
+                               char *buf)
+{
+       int i, count, s;
+       unsigned state;
+       int ret = 0;
+       u8 devices[(ETH_ALEN + sizeof(unsigned)) * OZ_MAX_PDS];
+
+       count = oz_get_pd_status_list(devices, OZ_MAX_PDS);
+       s = sprintf(buf, "Total: %d\n", count);
+       buf += s;
+       ret += s;
+       for (i = 0; i < count; i++) {
+               ret += sprintf(buf, "%pm", (void *)&devices[i * (ETH_ALEN +
+                                               sizeof(unsigned))]);
+               buf += (ETH_ALEN * 2);
+               ret += sprintf(buf++, "\t");
+               memcpy(&state, &devices[(i * (ETH_ALEN + sizeof(unsigned))) +
+                                               ETH_ALEN], sizeof(unsigned));
+               switch (state) {
+               case OZ_PD_S_IDLE:
+                       s = sprintf(buf, "IDLE\n");
+                       buf += s;
+                       ret += s;
+                       break;
+               case OZ_PD_S_CONNECTED:
+                       s = sprintf(buf, "CONNECTED\n");
+                       buf += s;
+                       ret += s;
+                       break;
+               case OZ_PD_S_STOPPED:
+                       s = sprintf(buf, "STOPPED\n");
+                       buf += s;
+                       ret += s;
+                       break;
+               case OZ_PD_S_SLEEP:
+                       s = sprintf(buf, "SLEEP\n");
+                       buf += s;
+                       ret += s;
+                       break;
+               }
+
+       }
+       return ret;
+}
+
+u8 oz_str_to_hex(const char *st)
+{
+       u8 t1 = 0;
+       char arr[3];
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+       char **pt = NULL;
+#endif
+
+       memcpy(arr, st, 2);
+       arr[2] = '\0';
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+       t1 = (u8) simple_strtoul(arr, pt, 16);
+#else
+       if (kstrtou8(arr, 16, &t1))
+               oz_trace("Invalid string received\n");
+#endif
+       return t1;
+}
+
+static ssize_t stop_store(struct kobject *kobj, struct kobj_attribute *attr,
+                               const char *buf, size_t count)
+{
+       int i;
+       u8 mac_addr[6];
+       struct oz_pd *pd;
+
+       if (count >= 12) {
+               for (i = 0; i < 6; i++) {
+                       mac_addr[i] = oz_str_to_hex(buf);
+                       buf += 2;
+               }
+
+               pd = oz_pd_find(mac_addr);
+               if (pd && (!(pd->state & OZ_PD_S_CONNECTED))) {
+                       oz_pd_stop(pd);
+                       oz_pd_put(pd);
+               } else
+                       oz_pd_put(pd);
+       }
+
+       return count;
+}
+
+static ssize_t select_show(struct kobject *kobj, struct kobj_attribute *attr,
+                               char *buf)
+{
+       int i;
+       int ret = 0;
+       u8 mac_addr[6];
+
+       oz_get_active_pd(mac_addr);
+
+       for (i = 0; i < 6; i++) {
+               ret += sprintf(buf, "%02x", mac_addr[i]);
+               buf += 2;
+       }
+       ret += sprintf(buf, "\n");
+       return ret;
+}
+
+static ssize_t select_store(struct kobject *kobj, struct kobj_attribute *attr,
+                               const char *buf, size_t count)
+{
+       int i;
+       u8 mac_addr[6];
+
+       if (count >= 12) {
+               for (i = 0; i < 6; i++) {
+                       mac_addr[i] = oz_str_to_hex(buf);
+                       buf += 2;
+               }
+
+               oz_set_active_pd(mac_addr);
+       }
+       return count;
+}
+
+static ssize_t bind_show(struct kobject *kobj, struct kobj_attribute *attr,
+                               char *buf)
+{
+       char nw_list[OZ_MAX_NW_IF * OZ_MAX_BINDING_LEN] = {0};
+       int count, i, s;
+       int ret = 0;
+
+       count = oz_get_binding_list(nw_list, OZ_MAX_NW_IF);
+       for (i = 0; i < count; i++) {
+               s = sprintf(buf, "%s\n", nw_list + (i * OZ_MAX_BINDING_LEN));
+               ret += s;
+               buf += s;
+       }
+               return ret;
+}
+
+static ssize_t bind_store(struct kobject *kobj, struct kobj_attribute *attr,
+                               const char *buf, size_t count)
+{
+       char name[OZ_MAX_BINDING_LEN];
+       char *p = NULL;
+
+       memcpy(name, buf + 2, count);
+       p = strstr(name, "\n");
+       if (p)
+               *p = '\0';
+
+       switch (*buf) {
+       case 'a':
+               oz_binding_add(name);
+               break;
+       case 'r':
+               oz_binding_remove(name);
+               break;
+       }
+       return count;
+}
+
+static ssize_t mode_show(struct kobject *kobj, struct kobj_attribute *attr,
+                               char *buf)
+{
+       u8 mode;
+       int ret;
+
+       mode = oz_get_serial_mode();
+       ret = sprintf(buf, "0x%02x\n", mode);
+       return ret;
+}
+
+static ssize_t mode_store(struct kobject *kobj, struct kobj_attribute *attr,
+                               const char *buf, size_t count)
+{
+       u8 new_mode;
+       if (count >= 4) {
+               new_mode = oz_str_to_hex(buf + 2);
+               oz_set_serial_mode(new_mode);
+       } else {
+               printk(KERN_ERR "Invalid mode\n");
+       }
+       return count;
+}
+
+static ssize_t debug_show(struct kobject *kobj, struct kobj_attribute *attr,
+                               char *buf)
+{
+       int ret = 0;
+       u32 debug = g_debug;
+       int i;
+
+       for (i = 0; i < 'Z'-'A'+1; i++) {
+               if (debug & (1<<i))
+                       *(buf + ret++) = 'A' + i;
+               }
+
+       return ret;
+}
+
+static ssize_t debug_store(struct kobject *kobj, struct kobj_attribute *attr,
+                               const char *buf, size_t count)
+{
+       u32 new_debug = 0;
+       const char *t = buf;
+
+       if (count > 1 && count < 33) {
+               while (*t) {
+                       char symbol = *t;
+                       if ('A' <= symbol && symbol <= 'Z')
+                               new_debug |= 1<<(symbol - 'A');
+                       t++;
+               }
+
+               if (0 != new_debug) {
+                       g_debug = new_debug;
+               }
+               else
+                       printk(KERN_ERR "Invalid debug\n");
+       } else {
+               if (1 == count && *t == '\0')
+                       g_debug = 0;
+       }
+       
+       return count;
+}
+
+static ssize_t fptr_show(struct kobject *kobj, struct kobj_attribute *attr,
+                               char *buf)
+{
+       int ret;
+
+       ret = sprintf(buf, "p->oz_protocol_init = 0x%p\n", oz_protocol_init);
+       return ret;
+
+}
+
+static struct kobj_attribute devices_attribute =
+       __ATTR(devices, 0400, devices_show, NULL);
+
+static struct kobj_attribute stop_attribute =
+       __ATTR(stop, 0200, NULL, stop_store);
+
+static struct kobj_attribute select_attribute =
+       __ATTR(select, 0600, select_show, select_store);
+
+static struct kobj_attribute bind_attribute =
+       __ATTR(bind, 0600, bind_show, bind_store);
+
+static struct kobj_attribute mode_attribute =
+       __ATTR(mode, 0600, mode_show, mode_store);
+
+static struct kobj_attribute debug_attribute =
+       __ATTR(debug, 0600, debug_show, debug_store);
+
+static struct kobj_attribute fptr_attribute =
+       __ATTR(fptr, 0400, fptr_show, NULL);
+
+static struct attribute *attrs[] = {
+       &devices_attribute.attr,
+       &stop_attribute.attr,
+       &select_attribute.attr,
+       &bind_attribute.attr,
+       &mode_attribute.attr,
+       &debug_attribute.attr,
+       &fptr_attribute.attr,
+       NULL,
+};
+
+static struct attribute_group attr_group = {
+       .attrs = attrs,
+};
+
+void oz_create_sys_entry(void)
+{
+       int retval;
+
+       retval = sysfs_create_group(&g_oz_wpan_dev->kobj, &attr_group);
+       if (retval)
+               oz_trace("Can not create attribute group\n");
+
+}
+
+void oz_destroy_sys_entry(void)
+{
+       sysfs_remove_group(&g_oz_wpan_dev->kobj, &attr_group);
+}
diff --git a/drivers/staging/ozwpan/ozkobject.h b/drivers/staging/ozwpan/ozkobject.h
new file mode 100644 (file)
index 0000000..0557228
--- /dev/null
@@ -0,0 +1,17 @@
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * -----------------------------------------------------------------------------
+ */
+
+#ifndef _OZKOBJECT_H
+#define _OZKOBJECT_H
+
+#define OZ_MAX_NW_IF   6
+
+void oz_create_sys_entry(void);
+void oz_destroy_sys_entry(void);
+void oz_set_serial_mode(u8 mode);
+u8 oz_get_serial_mode(void);
+
+#endif /* _OZKOBJECT_H */
index 57a0cbd585518e574e931588dbc92aaa7d296287..0b48cc8508ff1d56d37ecac6da857d50a64f5325 100644 (file)
 #include <linux/netdevice.h>
 #include <linux/errno.h>
 #include <linux/ieee80211.h>
-#include "ozconfig.h"
 #include "ozpd.h"
 #include "ozproto.h"
 #include "ozcdev.h"
 #include "oztrace.h"
-#include "ozevent.h"
 /*------------------------------------------------------------------------------
  * The name of the 802.11 mac device. Empty string is the default value but a
  * value can be supplied as a parameter to the module. An empty string means
  * bind to nothing. '*' means bind to all netcards - this includes non-802.11
  * netcards. Bindings can be added later using an IOCTL.
  */
-static char *g_net_dev = "";
+char *g_net_dev = "";
 /*------------------------------------------------------------------------------
  * Context: process
  */
 static int __init ozwpan_init(void)
 {
-       oz_event_init();
        oz_cdev_register();
        oz_protocol_init(g_net_dev);
        oz_app_enable(OZ_APPID_USB, 1);
        oz_apps_init();
-#ifdef CONFIG_DEBUG_FS
-       oz_debugfs_init();
-#endif
+       printk(KERN_DEBUG "p->oz_protocol_init = 0x%p\n", oz_protocol_init);
        return 0;
 }
 /*------------------------------------------------------------------------------
@@ -46,10 +41,6 @@ static void __exit ozwpan_exit(void)
        oz_protocol_term();
        oz_apps_term();
        oz_cdev_deregister();
-       oz_event_term();
-#ifdef CONFIG_DEBUG_FS
-       oz_debugfs_remove();
-#endif
 }
 /*------------------------------------------------------------------------------
  */
@@ -59,6 +50,6 @@ module_exit(ozwpan_exit);
 
 MODULE_AUTHOR("Chris Kelly");
 MODULE_DESCRIPTION("Ozmo Devices USB over WiFi hcd driver");
-MODULE_VERSION("1.0.13");
+MODULE_VERSION("1.2.3-rc2");
 MODULE_LICENSE("GPL");
 
index f8b9da080c4b65c5b079fcfe8d9eea9bdd5f41a6..e3bf27b6bee8ae3b51e4a149723260156d47ce9f 100644 (file)
@@ -9,13 +9,11 @@
 #include <linux/sched.h>
 #include <linux/netdevice.h>
 #include <linux/errno.h>
-#include "ozconfig.h"
 #include "ozprotocol.h"
 #include "ozeltbuf.h"
 #include "ozpd.h"
 #include "ozproto.h"
 #include "oztrace.h"
-#include "ozevent.h"
 #include "ozcdev.h"
 #include "ozusbsvc.h"
 #include <asm/unaligned.h>
@@ -24,6 +22,7 @@
 /*------------------------------------------------------------------------------
  */
 #define OZ_MAX_TX_POOL_SIZE    6
+#define AC_VO  0x106
 /*------------------------------------------------------------------------------
  */
 static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd);
@@ -46,7 +45,7 @@ static void oz_def_app_rx(struct oz_pd *pd, struct oz_elt *elt);
 static atomic_t g_submitted_isoc = ATOMIC_INIT(0);
 /* Application handler functions.
  */
-static const struct oz_app_if g_app_if[OZ_APPID_MAX] = {
+static struct oz_app_if g_app_if[OZ_APPID_MAX] = {
        {oz_usb_init,
        oz_usb_term,
        oz_usb_start,
@@ -61,8 +60,8 @@ static const struct oz_app_if g_app_if[OZ_APPID_MAX] = {
        oz_def_app_start,
        oz_def_app_stop,
        oz_def_app_rx,
-       NULL,
-       NULL,
+       0,
+       0,
        OZ_APPID_UNUSED1},
 
        {oz_def_app_init,
@@ -70,8 +69,8 @@ static const struct oz_app_if g_app_if[OZ_APPID_MAX] = {
        oz_def_app_start,
        oz_def_app_stop,
        oz_def_app_rx,
-       NULL,
-       NULL,
+       0,
+       0,
        OZ_APPID_UNUSED2},
 
        {oz_cdev_init,
@@ -79,9 +78,36 @@ static const struct oz_app_if g_app_if[OZ_APPID_MAX] = {
        oz_cdev_start,
        oz_cdev_stop,
        oz_cdev_rx,
-       NULL,
-       NULL,
+       0,
+       0,
        OZ_APPID_SERIAL},
+
+       {oz_def_app_init,
+       oz_def_app_term,
+       oz_def_app_start,
+       oz_def_app_stop,
+       oz_def_app_rx,
+       0,
+       0,
+       OZ_APPID_UNUSED3},
+
+       {oz_def_app_init,
+       oz_def_app_term,
+       oz_def_app_start,
+       oz_def_app_stop,
+       oz_def_app_rx,
+       0,
+       0,
+       OZ_APPID_UNUSED4},
+
+       {0,
+       0,
+       0,
+       0,
+       oz_cdev_rx,
+       0,
+       0,
+       OZ_APPID_TFTP},
 };
 /*------------------------------------------------------------------------------
  * Context: process
@@ -121,23 +147,6 @@ static void oz_def_app_rx(struct oz_pd *pd, struct oz_elt *elt)
 void oz_pd_set_state(struct oz_pd *pd, unsigned state)
 {
        pd->state = state;
-       oz_event_log(OZ_EVT_PD_STATE, 0, 0, NULL, state);
-#ifdef WANT_TRACE
-       switch (state) {
-       case OZ_PD_S_IDLE:
-               oz_trace("PD State: OZ_PD_S_IDLE\n");
-               break;
-       case OZ_PD_S_CONNECTED:
-               oz_trace("PD State: OZ_PD_S_CONNECTED\n");
-               break;
-       case OZ_PD_S_STOPPED:
-               oz_trace("PD State: OZ_PD_S_STOPPED\n");
-               break;
-       case OZ_PD_S_SLEEP:
-               oz_trace("PD State: OZ_PD_S_SLEEP\n");
-               break;
-       }
-#endif /* WANT_TRACE */
 }
 /*------------------------------------------------------------------------------
  * Context: softirq or process
@@ -157,11 +166,12 @@ void oz_pd_put(struct oz_pd *pd)
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
  */
-struct oz_pd *oz_pd_alloc(const u8 *mac_addr)
+struct oz_pd *oz_pd_alloc(u8 *mac_addr)
 {
        struct oz_pd *pd = kzalloc(sizeof(struct oz_pd), GFP_ATOMIC);
        if (pd) {
                int i;
+
                atomic_set(&pd->ref_count, 2);
                for (i = 0; i < OZ_APPID_MAX; i++)
                        spin_lock_init(&pd->app_lock[i]);
@@ -171,7 +181,7 @@ struct oz_pd *oz_pd_alloc(const u8 *mac_addr)
                memcpy(pd->mac_addr, mac_addr, ETH_ALEN);
                if (0 != oz_elt_buf_init(&pd->elt_buff)) {
                        kfree(pd);
-                       pd = NULL;
+                       pd = 0;
                }
                spin_lock_init(&pd->tx_frame_lock);
                INIT_LIST_HEAD(&pd->tx_queue);
@@ -179,19 +189,28 @@ struct oz_pd *oz_pd_alloc(const u8 *mac_addr)
                pd->last_sent_frame = &pd->tx_queue;
                spin_lock_init(&pd->stream_lock);
                INIT_LIST_HEAD(&pd->stream_list);
+               tasklet_init(&pd->heartbeat_tasklet, oz_pd_heartbeat_handler,
+                                                       (unsigned long)pd);
+               tasklet_init(&pd->timeout_tasklet, oz_pd_timeout_handler,
+                                                       (unsigned long)pd);
+               hrtimer_init(&pd->heartbeat, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+               hrtimer_init(&pd->timeout, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+               pd->heartbeat.function = oz_pd_heartbeat_event;
+               pd->timeout.function = oz_pd_timeout_event;
        }
        return pd;
 }
-/*------------------------------------------------------------------------------
- * Context: softirq or process
- */
-void oz_pd_destroy(struct oz_pd *pd)
+static void oz_pd_free(struct work_struct *work)
 {
+       struct oz_pd *pd;
        struct list_head *e;
        struct oz_tx_frame *f;
        struct oz_isoc_stream *st;
        struct oz_farewell *fwell;
+       pd = container_of(work, struct oz_pd, workitem);
        oz_trace("Destroying PD\n");
+       tasklet_kill(&pd->heartbeat_tasklet);
+       tasklet_kill(&pd->timeout_tasklet);
        /* Delete any streams.
         */
        e = pd->stream_list.next;
@@ -230,20 +249,42 @@ void oz_pd_destroy(struct oz_pd *pd)
                dev_put(pd->net_dev);
        kfree(pd);
 }
+
+
+/*------------------------------------------------------------------------------
+ * Context: softirq or Process
+ */
+void oz_pd_destroy(struct oz_pd *pd)
+{
+       int ret;
+
+       if (hrtimer_active(&pd->timeout))
+               hrtimer_cancel(&pd->timeout);
+       if (hrtimer_active(&pd->heartbeat))
+               hrtimer_cancel(&pd->heartbeat);
+
+       memset(&pd->workitem, 0, sizeof(pd->workitem));
+       INIT_WORK(&pd->workitem, oz_pd_free);
+       ret = schedule_work(&pd->workitem);
+
+       if (ret)
+               oz_trace("failed to schedule workitem\n");
+}
+
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
  */
 int oz_services_start(struct oz_pd *pd, u16 apps, int resume)
 {
-       const struct oz_app_if *ai;
+       struct oz_app_if *ai;
        int rc = 0;
        oz_trace("oz_services_start(0x%x) resume(%d)\n", apps, resume);
+       if (apps & (1<<OZ_APPID_TFTP))
+               apps |= 1<<OZ_APPID_SERIAL;
        for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) {
                if (apps & (1<<ai->app_id)) {
-                       if (ai->start(pd, resume)) {
+                       if (ai->start && ai->start(pd, resume)) {
                                rc = -1;
-                               oz_trace("Unabled to start service %d\n",
-                                       ai->app_id);
                                break;
                        }
                        oz_polling_lock_bh();
@@ -260,8 +301,10 @@ int oz_services_start(struct oz_pd *pd, u16 apps, int resume)
  */
 void oz_services_stop(struct oz_pd *pd, u16 apps, int pause)
 {
-       const struct oz_app_if *ai;
+       struct oz_app_if *ai;
        oz_trace("oz_stop_services(0x%x) pause(%d)\n", apps, pause);
+       if (apps & (1<<OZ_APPID_TFTP))
+               apps |= 1<<OZ_APPID_SERIAL;
        for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) {
                if (apps & (1<<ai->app_id)) {
                        oz_polling_lock_bh();
@@ -272,7 +315,8 @@ void oz_services_stop(struct oz_pd *pd, u16 apps, int pause)
                                pd->paused_apps &= ~(1<<ai->app_id);
                        }
                        oz_polling_unlock_bh();
-                       ai->stop(pd, pause);
+                       if (ai->stop)
+                               ai->stop(pd, pause);
                }
        }
 }
@@ -281,7 +325,7 @@ void oz_services_stop(struct oz_pd *pd, u16 apps, int pause)
  */
 void oz_pd_heartbeat(struct oz_pd *pd, u16 apps)
 {
-       const struct oz_app_if *ai;
+       struct oz_app_if *ai;
        int more = 0;
        for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) {
                if (ai->heartbeat && (apps & (1<<ai->app_id))) {
@@ -289,8 +333,8 @@ void oz_pd_heartbeat(struct oz_pd *pd, u16 apps)
                                more = 1;
                }
        }
-       if (more)
-               oz_pd_request_heartbeat(pd);
+       if ((!more) && (hrtimer_active(&pd->heartbeat)))
+               hrtimer_cancel(&pd->heartbeat);
        if (pd->mode & OZ_F_ISOC_ANYTIME) {
                int count = 8;
                while (count-- && (oz_send_isoc_frame(pd) >= 0))
@@ -303,9 +347,9 @@ void oz_pd_heartbeat(struct oz_pd *pd, u16 apps)
 void oz_pd_stop(struct oz_pd *pd)
 {
        u16 stop_apps = 0;
-       oz_trace("oz_pd_stop() State = 0x%x\n", pd->state);
-       oz_pd_indicate_farewells(pd);
+       oz_trace("%s: State = 0x%x\n", __func__, pd->state);
        oz_polling_lock_bh();
+       oz_pd_indicate_farewells(pd);
        stop_apps = pd->total_apps;
        pd->total_apps = 0;
        pd->paused_apps = 0;
@@ -315,9 +359,9 @@ void oz_pd_stop(struct oz_pd *pd)
        oz_pd_set_state(pd, OZ_PD_S_STOPPED);
        /* Remove from PD list.*/
        list_del(&pd->link);
+
+
        oz_polling_unlock_bh();
-       oz_trace("pd ref count = %d\n", atomic_read(&pd->ref_count));
-       oz_timer_delete(pd, 0);
        oz_pd_put(pd);
 }
 /*------------------------------------------------------------------------------
@@ -332,11 +376,8 @@ int oz_pd_sleep(struct oz_pd *pd)
                oz_polling_unlock_bh();
                return 0;
        }
-       if (pd->keep_alive_j && pd->session_id) {
+       if (pd->keep_alive && pd->session_id) {
                oz_pd_set_state(pd, OZ_PD_S_SLEEP);
-               pd->pulse_time_j = jiffies + pd->keep_alive_j;
-               oz_trace("Sleep Now %lu until %lu\n",
-                       jiffies, pd->pulse_time_j);
        } else {
                do_stop = 1;
        }
@@ -346,7 +387,7 @@ int oz_pd_sleep(struct oz_pd *pd)
                oz_pd_stop(pd);
        } else {
                oz_services_stop(pd, stop_apps, 1);
-               oz_timer_add(pd, OZ_TIMER_STOP, jiffies + pd->keep_alive_j, 1);
+               oz_timer_add(pd, OZ_TIMER_STOP, pd->keep_alive);
        }
        return do_stop;
 }
@@ -355,7 +396,7 @@ int oz_pd_sleep(struct oz_pd *pd)
  */
 static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd)
 {
-       struct oz_tx_frame *f = NULL;
+       struct oz_tx_frame *f = 0;
        spin_lock_bh(&pd->tx_frame_lock);
        if (pd->tx_pool) {
                f = container_of(pd->tx_pool, struct oz_tx_frame, link);
@@ -363,7 +404,7 @@ static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd)
                pd->tx_pool_count--;
        }
        spin_unlock_bh(&pd->tx_frame_lock);
-       if (f == NULL)
+       if (f == 0)
                f = kmalloc(sizeof(struct oz_tx_frame), GFP_ATOMIC);
        if (f) {
                f->total_size = sizeof(struct oz_hdr);
@@ -386,8 +427,6 @@ static void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f)
        } else {
                kfree(f);
        }
-       oz_trace2(OZ_TRACE_TX_FRAMES, "Releasing ISOC Frame isoc_nb= %d\n",
-                                               pd->nb_queued_isoc_frames);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq or process
@@ -399,15 +438,16 @@ static void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f)
                f->link.next = pd->tx_pool;
                pd->tx_pool = &f->link;
                pd->tx_pool_count++;
-               f = NULL;
+               f = 0;
        }
        spin_unlock_bh(&pd->tx_frame_lock);
-       kfree(f);
+       if (f)
+               kfree(f);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
  */
-static void oz_set_more_bit(struct sk_buff *skb)
+void oz_set_more_bit(struct sk_buff *skb)
 {
        struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb);
        oz_hdr->control |= OZ_F_MORE_DATA;
@@ -415,7 +455,7 @@ static void oz_set_more_bit(struct sk_buff *skb)
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
  */
-static void oz_set_last_pkt_nb(struct oz_pd *pd, struct sk_buff *skb)
+void oz_set_last_pkt_nb(struct oz_pd *pd, struct sk_buff *skb)
 {
        struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb);
        oz_hdr->last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK;
@@ -433,7 +473,7 @@ int oz_prepare_frame(struct oz_pd *pd, int empty)
        if (!empty && !oz_are_elts_available(&pd->elt_buff))
                return -1;
        f = oz_tx_frame_alloc(pd);
-       if (f == NULL)
+       if (f == 0)
                return -1;
        f->skb = NULL;
        f->hdr.control =
@@ -455,7 +495,7 @@ int oz_prepare_frame(struct oz_pd *pd, int empty)
  */
 static struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f)
 {
-       struct sk_buff *skb;
+       struct sk_buff *skb = 0;
        struct net_device *dev = pd->net_dev;
        struct oz_hdr *oz_hdr;
        struct oz_elt *elt;
@@ -464,14 +504,15 @@ static struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f)
         * as the space we need.
         */
        skb = alloc_skb(f->total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC);
-       if (skb == NULL)
-               return NULL;
+       if (skb == 0)
+               return 0;
        /* Reserve the head room for lower layers.
         */
        skb_reserve(skb, LL_RESERVED_SPACE(dev));
        skb_reset_network_header(skb);
        skb->dev = dev;
        skb->protocol = htons(OZ_ETHERTYPE);
+       skb->priority = AC_VO;
        if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr,
                dev->dev_addr, skb->len) < 0)
                goto fail;
@@ -492,7 +533,7 @@ static struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f)
        return skb;
 fail:
        kfree_skb(skb);
-       return NULL;
+       return 0;
 }
 /*------------------------------------------------------------------------------
  * Context: softirq or process
@@ -541,21 +582,14 @@ static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data)
                oz_set_last_pkt_nb(pd, skb);
                if ((int)atomic_read(&g_submitted_isoc) <
                                                        OZ_MAX_SUBMITTED_ISOC) {
+                       oz_trace_skb(skb, 'T');
                        if (dev_queue_xmit(skb) < 0) {
-                               oz_trace2(OZ_TRACE_TX_FRAMES,
-                                               "Dropping ISOC Frame\n");
-                               oz_event_log(OZ_EVT_TX_ISOC_DROP, 0, 0, NULL, 0);
                                return -1;
                        }
                        atomic_inc(&g_submitted_isoc);
-                       oz_trace2(OZ_TRACE_TX_FRAMES,
-                                       "Sending ISOC Frame, nb_isoc= %d\n",
-                                               pd->nb_queued_isoc_frames);
                        return 0;
                } else {
                        kfree_skb(skb);
-                       oz_trace2(OZ_TRACE_TX_FRAMES, "Dropping ISOC Frame>\n");
-                       oz_event_log(OZ_EVT_TX_ISOC_DROP, 0, 0, NULL, 0);
                        return -1;
                }
        }
@@ -563,18 +597,14 @@ static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data)
        pd->last_sent_frame = e;
        skb = oz_build_frame(pd, f);
        spin_unlock(&pd->tx_frame_lock);
+       if (skb == 0)
+               return -1;
+
        if (more_data)
                oz_set_more_bit(skb);
-       oz_trace2(OZ_TRACE_TX_FRAMES, "TX frame PN=0x%x\n", f->hdr.pkt_num);
-       if (skb) {
-               oz_event_log(OZ_EVT_TX_FRAME,
-                       0,
-                       (((u16)f->hdr.control)<<8)|f->hdr.last_pkt_num,
-                       NULL, f->hdr.pkt_num);
-               if (dev_queue_xmit(skb) < 0)
-                       return -1;
-
-       }
+       oz_trace_skb(skb, 'T');
+       if (dev_queue_xmit(skb) < 0)
+               return -1;
        return 0;
 }
 /*------------------------------------------------------------------------------
@@ -620,7 +650,7 @@ out:        oz_prepare_frame(pd, 1);
  */
 static int oz_send_isoc_frame(struct oz_pd *pd)
 {
-       struct sk_buff *skb;
+       struct sk_buff *skb = 0;
        struct net_device *dev = pd->net_dev;
        struct oz_hdr *oz_hdr;
        struct oz_elt *elt;
@@ -634,8 +664,7 @@ static int oz_send_isoc_frame(struct oz_pd *pd)
        if (list.next == &list)
                return 0;
        skb = alloc_skb(total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC);
-       if (skb == NULL) {
-               oz_trace("Cannot alloc skb\n");
+       if (skb == 0) {
                oz_elt_info_free_chain(&pd->elt_buff, &list);
                return -1;
        }
@@ -659,7 +688,7 @@ static int oz_send_isoc_frame(struct oz_pd *pd)
                memcpy(elt, ei->data, ei->length);
                elt = oz_next_elt(elt);
        }
-       oz_event_log(OZ_EVT_TX_ISOC, 0, 0, NULL, 0);
+       oz_trace_skb(skb, 'T');
        dev_queue_xmit(skb);
        oz_elt_info_free_chain(&pd->elt_buff, &list);
        return 0;
@@ -671,8 +700,8 @@ void oz_retire_tx_frames(struct oz_pd *pd, u8 lpn)
 {
        struct list_head *e;
        struct oz_tx_frame *f;
-       struct list_head *first = NULL;
-       struct list_head *last = NULL;
+       struct list_head *first = 0;
+       struct list_head *last = 0;
        u8 diff;
        u32 pkt_num;
 
@@ -684,9 +713,7 @@ void oz_retire_tx_frames(struct oz_pd *pd, u8 lpn)
                diff = (lpn - (pkt_num & OZ_LAST_PN_MASK)) & OZ_LAST_PN_MASK;
                if ((diff > OZ_LAST_PN_HALF_CYCLE) || (pkt_num == 0))
                        break;
-               oz_trace2(OZ_TRACE_TX_FRAMES, "Releasing pkt_num= %u, nb= %d\n",
-                                                pkt_num, pd->nb_queued_frames);
-               if (first == NULL)
+               if (first == 0)
                        first = e;
                last = e;
                e = e->next;
@@ -695,7 +722,7 @@ void oz_retire_tx_frames(struct oz_pd *pd, u8 lpn)
        if (first) {
                last->next->prev = &pd->tx_queue;
                pd->tx_queue.next = last->next;
-               last->next = NULL;
+               last->next = 0;
        }
        pd->last_sent_frame = &pd->tx_queue;
        spin_unlock(&pd->tx_frame_lock);
@@ -718,7 +745,7 @@ static struct oz_isoc_stream *pd_stream_find(struct oz_pd *pd, u8 ep_num)
                if (st->ep_num == ep_num)
                        return st;
        }
-       return NULL;
+       return 0;
 }
 /*------------------------------------------------------------------------------
  * Context: softirq
@@ -733,10 +760,11 @@ int oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num)
        spin_lock_bh(&pd->stream_lock);
        if (!pd_stream_find(pd, ep_num)) {
                list_add(&st->link, &pd->stream_list);
-               st = NULL;
+               st = 0;
        }
        spin_unlock_bh(&pd->stream_lock);
-       kfree(st);
+       if (st)
+               kfree(st);
        return 0;
 }
 /*------------------------------------------------------------------------------
@@ -744,7 +772,8 @@ int oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num)
  */
 static void oz_isoc_stream_free(struct oz_isoc_stream *st)
 {
-       kfree_skb(st->skb);
+       if (st->skb)
+               kfree_skb(st->skb);
        kfree(st);
 }
 /*------------------------------------------------------------------------------
@@ -768,25 +797,23 @@ int oz_isoc_stream_delete(struct oz_pd *pd, u8 ep_num)
 static void oz_isoc_destructor(struct sk_buff *skb)
 {
        atomic_dec(&g_submitted_isoc);
-       oz_event_log(OZ_EVT_TX_ISOC_DONE, atomic_read(&g_submitted_isoc),
-               0, skb, 0);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq
  */
-int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len)
+int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, u8 *data, int len)
 {
        struct net_device *dev = pd->net_dev;
        struct oz_isoc_stream *st;
        u8 nb_units = 0;
-       struct sk_buff *skb = NULL;
-       struct oz_hdr *oz_hdr = NULL;
+       struct sk_buff *skb = 0;
+       struct oz_hdr *oz_hdr = 0;
        int size = 0;
        spin_lock_bh(&pd->stream_lock);
        st = pd_stream_find(pd, ep_num);
        if (st) {
                skb = st->skb;
-               st->skb = NULL;
+               st->skb = 0;
                nb_units = st->nb_units;
                st->nb_units = 0;
                oz_hdr = st->oz_hdr;
@@ -799,7 +826,7 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len)
                /* Allocate enough space for max size frame. */
                skb = alloc_skb(pd->max_tx_size + OZ_ALLOCATED_SPACE(dev),
                                GFP_ATOMIC);
-               if (skb == NULL)
+               if (skb == 0)
                        return 0;
                /* Reserve the head room for lower layers. */
                skb_reserve(skb, LL_RESERVED_SPACE(dev));
@@ -807,7 +834,7 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len)
                skb->dev = dev;
                skb->protocol = htons(OZ_ETHERTYPE);
                /* For audio packet set priority to AC_VO */
-               skb->priority = 0x7;
+               skb->priority = AC_VO;
                size = sizeof(struct oz_hdr) + sizeof(struct oz_isoc_large);
                oz_hdr = (struct oz_hdr *)skb_put(skb, size);
        }
@@ -845,11 +872,19 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len)
                if (!(pd->mode & OZ_F_ISOC_ANYTIME)) {
                        struct oz_tx_frame *isoc_unit = NULL;
                        int nb = pd->nb_queued_isoc_frames;
+                       struct list_head *e;
+                       struct oz_tx_frame *f;
                        if (nb >= pd->isoc_latency) {
-                               oz_trace2(OZ_TRACE_TX_FRAMES,
-                                               "Dropping ISOC Unit nb= %d\n",
-                                                                       nb);
-                               goto out;
+                               spin_lock(&pd->tx_frame_lock);
+                               list_for_each(e, &pd->tx_queue) {
+                                       f = container_of(e, struct oz_tx_frame,
+                                                                       link);
+                                       if (f->skb != NULL) {
+                                               oz_tx_isoc_free(pd, f);
+                                               break;
+                                       }
+                               }
+                               spin_unlock(&pd->tx_frame_lock);
                        }
                        isoc_unit = oz_tx_frame_alloc(pd);
                        if (isoc_unit == NULL)
@@ -860,28 +895,19 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len)
                        list_add_tail(&isoc_unit->link, &pd->tx_queue);
                        pd->nb_queued_isoc_frames++;
                        spin_unlock_bh(&pd->tx_frame_lock);
-                       oz_trace2(OZ_TRACE_TX_FRAMES,
-                       "Added ISOC Frame to Tx Queue isoc_nb= %d, nb= %d\n",
-                       pd->nb_queued_isoc_frames, pd->nb_queued_frames);
-                       oz_event_log(OZ_EVT_TX_ISOC, nb_units, iso.frame_number,
-                                       skb, atomic_read(&g_submitted_isoc));
                        return 0;
                }
-
                /*In ANYTIME mode Xmit unit immediately*/
                if (atomic_read(&g_submitted_isoc) < OZ_MAX_SUBMITTED_ISOC) {
                        atomic_inc(&g_submitted_isoc);
-                       oz_event_log(OZ_EVT_TX_ISOC, nb_units, iso.frame_number,
-                                       skb, atomic_read(&g_submitted_isoc));
+                       oz_trace_skb(skb, 'T');
                        if (dev_queue_xmit(skb) < 0) {
-                               oz_event_log(OZ_EVT_TX_ISOC_DROP, 0, 0, NULL, 0);
                                return -1;
                        } else
                                return 0;
                }
 
-out:   oz_event_log(OZ_EVT_TX_ISOC_DROP, 0, 0, NULL, 0);
-       kfree_skb(skb);
+out:   kfree_skb(skb);
        return -1;
 
        }
@@ -913,7 +939,7 @@ void oz_apps_term(void)
  */
 void oz_handle_app_elt(struct oz_pd *pd, u8 app_id, struct oz_elt *elt)
 {
-       const struct oz_app_if *ai;
+       struct oz_app_if *ai;
        if (app_id == 0 || app_id > OZ_APPID_MAX)
                return;
        ai = &g_app_if[app_id-1];
@@ -925,19 +951,11 @@ void oz_handle_app_elt(struct oz_pd *pd, u8 app_id, struct oz_elt *elt)
 void oz_pd_indicate_farewells(struct oz_pd *pd)
 {
        struct oz_farewell *f;
-       const struct oz_app_if *ai = &g_app_if[OZ_APPID_USB-1];
-       while (1) {
-               oz_polling_lock_bh();
-               if (list_empty(&pd->farewell_list)) {
-                       oz_polling_unlock_bh();
-                       break;
-               }
+       struct oz_app_if *ai = &g_app_if[OZ_APPID_USB-1];
+       if (!(list_empty(&pd->farewell_list))) {
                f = list_first_entry(&pd->farewell_list,
-                               struct oz_farewell, link);
-               list_del(&f->link);
-               oz_polling_unlock_bh();
+                                               struct oz_farewell, link);
                if (ai->farewell)
                        ai->farewell(pd, f->ep_num, f->report, f->len);
-               kfree(f);
        }
 }
index fbf47cbab8a92ffc75ee616a24113beae69bcced..355f637e72c5e4b1854c4a118e2019215061f41d 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef _OZPD_H_
 #define _OZPD_H_
 
+#include <linux/interrupt.h>
 #include "ozeltbuf.h"
 
 /* PD state
@@ -21,6 +22,7 @@
 #define OZ_TIMER_HEARTBEAT     2
 #define OZ_TIMER_STOP          3
 
+#define ETH_STRING_LEN         17
 /* Data structure that hold information on a frame for transmisson. This is
  * built when the frame is first transmitted and is used to rebuild the frame
  * if a re-transmission is required.
@@ -47,7 +49,7 @@ struct oz_farewell {
        struct list_head link;
        u8 ep_num;
        u8 index;
-       u8 report[1];
+       u8 report[32];
        u8 len;
 };
 
@@ -68,18 +70,16 @@ struct oz_pd {
        u8              isoc_sent;
        u32             last_rx_pkt_num;
        u32             last_tx_pkt_num;
+       struct timespec last_rx_timestamp;
        u32             trigger_pkt_num;
-       unsigned long   pulse_time_j;
-       unsigned long   timeout_time_j;
-       unsigned long   pulse_period_j;
-       unsigned long   presleep_j;
-       unsigned long   keep_alive_j;
-       unsigned long   last_rx_time_j;
+       unsigned long   pulse_time;
+       ktime_t         pulse_period;
+       unsigned long   presleep;
+       unsigned long   keep_alive;
        struct oz_elt_buf elt_buff;
        void            *app_ctx[OZ_APPID_MAX];
        spinlock_t      app_lock[OZ_APPID_MAX];
        int             max_tx_size;
-       u8              heartbeat_requested;
        u8              mode;
        u8              ms_per_isoc;
        unsigned        isoc_latency;
@@ -95,11 +95,18 @@ struct oz_pd {
        spinlock_t      stream_lock;
        struct list_head stream_list;
        struct net_device *net_dev;
+       struct hrtimer  heartbeat;
+       struct hrtimer  timeout;
+       u8      timeout_type;
+       struct tasklet_struct   heartbeat_tasklet;
+       struct tasklet_struct   timeout_tasklet;
+       struct work_struct workitem;
+       u8      up_audio_buf;
 };
 
 #define OZ_MAX_QUEUED_FRAMES   4
 
-struct oz_pd *oz_pd_alloc(const u8 *mac_addr);
+struct oz_pd *oz_pd_alloc(u8 *mac_addr);
 void oz_pd_destroy(struct oz_pd *pd);
 void oz_pd_get(struct oz_pd *pd);
 void oz_pd_put(struct oz_pd *pd);
@@ -115,7 +122,7 @@ void oz_send_queued_frames(struct oz_pd *pd, int backlog);
 void oz_retire_tx_frames(struct oz_pd *pd, u8 lpn);
 int oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num);
 int oz_isoc_stream_delete(struct oz_pd *pd, u8 ep_num);
-int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len);
+int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, u8 *data, int len);
 void oz_handle_app_elt(struct oz_pd *pd, u8 app_id, struct oz_elt *elt);
 void oz_apps_init(void);
 void oz_apps_term(void);
index 3badf1537adb344deb47c868608d6a91230c9659..e222d0831f8f5f723b12ebd5050940cdf8557597 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/netdevice.h>
 #include <linux/errno.h>
 #include <linux/ieee80211.h>
-#include "ozconfig.h"
 #include "ozprotocol.h"
 #include "ozeltbuf.h"
 #include "ozpd.h"
@@ -18,7 +17,6 @@
 #include "ozusbsvc.h"
 #include "oztrace.h"
 #include "ozappif.h"
-#include "ozevent.h"
 #include <asm/unaligned.h>
 #include <linux/uaccess.h>
 #include <net/psnap.h>
 #define OZ_DO_STOP             1
 #define OZ_DO_SLEEP            2
 
-/* States of the timer.
- */
-#define OZ_TIMER_IDLE          0
-#define OZ_TIMER_SET           1
-#define OZ_TIMER_IN_HANDLER    2
-
 #define OZ_MAX_TIMER_POOL_SIZE 16
+/*------------------------------------------------------------------------------
+ * Number of units of buffering to capture for an isochronous IN endpoint before
+ * allowing data to be indicated up.
+ */
+#define OZ_IN_BUFFERING_UNITS  100
 
 /*------------------------------------------------------------------------------
  */
 struct oz_binding {
        struct packet_type ptype;
        char name[OZ_MAX_BINDING_LEN];
-       struct oz_binding *next;
-};
-
-struct oz_timer {
        struct list_head link;
-       struct oz_pd *pd;
-       unsigned long due_time;
-       int type;
 };
+
 /*------------------------------------------------------------------------------
  * Static external variables.
  */
 static DEFINE_SPINLOCK(g_polling_lock);
 static LIST_HEAD(g_pd_list);
-static struct oz_binding *g_binding ;
+static LIST_HEAD(g_binding);
 static DEFINE_SPINLOCK(g_binding_lock);
 static struct sk_buff_head g_rx_queue;
 static u8 g_session_id;
 static u16 g_apps = 0x1;
 static int g_processing_rx;
-static struct timer_list g_timer;
-static struct oz_timer *g_cur_timer;
-static struct list_head *g_timer_pool;
-static int g_timer_pool_count;
-static int g_timer_state = OZ_TIMER_IDLE;
-static LIST_HEAD(g_timer_list);
-/*------------------------------------------------------------------------------
- */
-static void oz_protocol_timer_start(void);
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
  */
@@ -98,7 +80,7 @@ static void oz_send_conn_rsp(struct oz_pd *pd, u8 status)
        int sz = sizeof(struct oz_hdr) + sizeof(struct oz_elt) +
                        sizeof(struct oz_elt_connect_rsp);
        skb = alloc_skb(sz + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC);
-       if (skb == NULL)
+       if (skb == 0)
                return;
        skb_reserve(skb, LL_RESERVED_SPACE(dev));
        skb_reset_network_header(skb);
@@ -116,7 +98,6 @@ static void oz_send_conn_rsp(struct oz_pd *pd, u8 status)
        oz_hdr->control = (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT);
        oz_hdr->last_pkt_num = 0;
        put_unaligned(0, &oz_hdr->pkt_num);
-       oz_event_log(OZ_EVT_CONNECT_RSP, 0, 0, NULL, 0);
        elt->type = OZ_ELT_CONNECT_RSP;
        elt->length = sizeof(struct oz_elt_connect_rsp);
        memset(body, 0, sizeof(struct oz_elt_connect_rsp));
@@ -126,7 +107,7 @@ static void oz_send_conn_rsp(struct oz_pd *pd, u8 status)
                body->session_id = pd->session_id;
                put_unaligned(cpu_to_le16(pd->total_apps), &body->apps);
        }
-       oz_trace("TX: OZ_ELT_CONNECT_RSP %d", status);
+       oz_trace_skb(skb, 'T');
        dev_queue_xmit(skb);
        return;
 }
@@ -139,39 +120,41 @@ static void pd_set_keepalive(struct oz_pd *pd, u8 kalive)
 
        switch (kalive & OZ_KALIVE_TYPE_MASK) {
        case OZ_KALIVE_SPECIAL:
-               pd->keep_alive_j =
-                       oz_ms_to_jiffies(keep_alive * 1000*60*60*24*20);
+               pd->keep_alive = (keep_alive*1000*60*60*24*20);
                break;
        case OZ_KALIVE_SECS:
-               pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000);
+               pd->keep_alive = (keep_alive*1000);
                break;
        case OZ_KALIVE_MINS:
-               pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000*60);
+               pd->keep_alive = (keep_alive*1000*60);
                break;
        case OZ_KALIVE_HOURS:
-               pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000*60*60);
+               pd->keep_alive = (keep_alive*1000*60*60);
                break;
        default:
-               pd->keep_alive_j = 0;
+               pd->keep_alive = 0;
        }
-       oz_trace("Keepalive = %lu jiffies\n", pd->keep_alive_j);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
  */
-static void pd_set_presleep(struct oz_pd *pd, u8 presleep)
+static void pd_set_presleep(struct oz_pd *pd, u8 presleep, u8 start_timer)
 {
        if (presleep)
-               pd->presleep_j = oz_ms_to_jiffies(presleep*100);
+               pd->presleep = presleep*100;
        else
-               pd->presleep_j = OZ_PRESLEEP_TOUT_J;
-       oz_trace("Presleep time = %lu jiffies\n", pd->presleep_j);
+               pd->presleep = OZ_PRESLEEP_TOUT;
+       if (start_timer) {
+               spin_unlock(&g_polling_lock);
+               oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep);
+               spin_lock(&g_polling_lock);
+       }
 }
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
  */
 static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt,
-                       const u8 *pd_addr, struct net_device *net_dev)
+                       u8 *pd_addr, struct net_device *net_dev)
 {
        struct oz_pd *pd;
        struct oz_elt_connect_req *body =
@@ -179,18 +162,18 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt,
        u8 rsp_status = OZ_STATUS_SUCCESS;
        u8 stop_needed = 0;
        u16 new_apps = g_apps;
-       struct net_device *old_net_dev = NULL;
-       struct oz_pd *free_pd = NULL;
+       struct net_device *old_net_dev = 0;
+       struct oz_pd *free_pd = 0;
        if (cur_pd) {
                pd = cur_pd;
                spin_lock_bh(&g_polling_lock);
        } else {
-               struct oz_pd *pd2 = NULL;
+               struct oz_pd *pd2 = 0;
                struct list_head *e;
                pd = oz_pd_alloc(pd_addr);
-               if (pd == NULL)
-                       return NULL;
-               pd->last_rx_time_j = jiffies;
+               if (pd == 0)
+                       return 0;
+               getnstimeofday(&pd->last_rx_timestamp);
                spin_lock_bh(&g_polling_lock);
                list_for_each(e, &g_pd_list) {
                        pd2 = container_of(e, struct oz_pd, link);
@@ -203,19 +186,20 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt,
                if (pd != pd2)
                        list_add_tail(&pd->link, &g_pd_list);
        }
-       if (pd == NULL) {
+       if (pd == 0) {
                spin_unlock_bh(&g_polling_lock);
-               return NULL;
+               return 0;
        }
        if (pd->net_dev != net_dev) {
                old_net_dev = pd->net_dev;
                dev_hold(net_dev);
                pd->net_dev = net_dev;
        }
-       oz_trace("Host vendor: %d\n", body->host_vendor);
        pd->max_tx_size = OZ_MAX_TX_SIZE;
        pd->mode = body->mode;
        pd->pd_info = body->pd_info;
+       pd->up_audio_buf = body->up_audio_buf > 0 ? body->up_audio_buf :
+                                                       OZ_IN_BUFFERING_UNITS;
        if (pd->mode & OZ_F_ISOC_NO_ELTS) {
                pd->ms_per_isoc = body->ms_per_isoc;
                if (!pd->ms_per_isoc)
@@ -236,12 +220,10 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt,
        }
        if (body->max_len_div16)
                pd->max_tx_size = ((u16)body->max_len_div16)<<4;
-       oz_trace("Max frame:%u Ms per isoc:%u\n",
-               pd->max_tx_size, pd->ms_per_isoc);
        pd->max_stream_buffering = 3*1024;
-       pd->timeout_time_j = jiffies + OZ_CONNECTION_TOUT_J;
-       pd->pulse_period_j = OZ_QUANTUM_J;
-       pd_set_presleep(pd, body->presleep);
+       pd->pulse_period = ktime_set(OZ_QUANTUM / MSEC_PER_SEC, (OZ_QUANTUM %
+                                       MSEC_PER_SEC) * NSEC_PER_MSEC);
+       pd_set_presleep(pd, body->presleep, 0);
        pd_set_keepalive(pd, body->keep_alive);
 
        new_apps &= le16_to_cpu(get_unaligned(&body->apps));
@@ -273,9 +255,6 @@ done:
                u16 resume_apps = new_apps & pd->paused_apps  & ~0x1;
                spin_unlock_bh(&g_polling_lock);
                oz_pd_set_state(pd, OZ_PD_S_CONNECTED);
-               oz_timer_delete(pd, OZ_TIMER_STOP);
-               oz_trace("new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n",
-                       new_apps, pd->total_apps, pd->paused_apps);
                if (start_apps) {
                        if (oz_services_start(pd, start_apps, 0))
                                rsp_status = OZ_STATUS_TOO_MANY_PDS;
@@ -294,7 +273,7 @@ done:
                if (stop_needed)
                        oz_pd_stop(pd);
                oz_pd_put(pd);
-               pd = NULL;
+               pd = 0;
        }
        if (old_net_dev)
                dev_put(old_net_dev);
@@ -306,7 +285,7 @@ done:
  * Context: softirq-serialized
  */
 static void oz_add_farewell(struct oz_pd *pd, u8 ep_num, u8 index,
-                       const u8 *report, u8 len)
+                       u8 *report, u8 len)
 {
        struct oz_farewell *f;
        struct oz_farewell *f2;
@@ -316,6 +295,7 @@ static void oz_add_farewell(struct oz_pd *pd, u8 ep_num, u8 index,
                return;
        f->ep_num = ep_num;
        f->index = index;
+       f->len = len;
        memcpy(f->report, report, len);
        oz_trace("RX: Adding farewell report\n");
        spin_lock(&g_polling_lock);
@@ -340,17 +320,13 @@ static void oz_rx_frame(struct sk_buff *skb)
        u8 *src_addr;
        struct oz_elt *elt;
        int length;
-       struct oz_pd *pd = NULL;
+       struct oz_pd *pd = 0;
        struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb);
+       struct timespec current_time;
        int dup = 0;
        u32 pkt_num;
 
-       oz_event_log(OZ_EVT_RX_PROCESS, 0,
-               (((u16)oz_hdr->control)<<8)|oz_hdr->last_pkt_num,
-               NULL, oz_hdr->pkt_num);
-       oz_trace2(OZ_TRACE_RX_FRAMES,
-               "RX frame PN=0x%x LPN=0x%x control=0x%x\n",
-               oz_hdr->pkt_num, oz_hdr->last_pkt_num, oz_hdr->control);
+       oz_trace_skb(skb, 'R');
        mac_hdr = skb_mac_header(skb);
        src_addr = &mac_hdr[ETH_ALEN] ;
        length = skb->len;
@@ -362,23 +338,27 @@ static void oz_rx_frame(struct sk_buff *skb)
                goto done;
        }
 
+
        pkt_num = le32_to_cpu(get_unaligned(&oz_hdr->pkt_num));
 
        pd = oz_pd_find(src_addr);
        if (pd) {
-               pd->last_rx_time_j = jiffies;
-               oz_timer_add(pd, OZ_TIMER_TOUT,
-                       pd->last_rx_time_j + pd->presleep_j, 1);
+               if (!(pd->state & OZ_PD_S_CONNECTED))
+                       oz_pd_set_state(pd, OZ_PD_S_CONNECTED);
+               getnstimeofday(&current_time);
+               if ((current_time.tv_sec != pd->last_rx_timestamp.tv_sec) ||
+                       (pd->presleep < MSEC_PER_SEC))  {
+                       oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep);
+                       pd->last_rx_timestamp = current_time;
+               }
                if (pkt_num != pd->last_rx_pkt_num) {
                        pd->last_rx_pkt_num = pkt_num;
                } else {
                        dup = 1;
-                       oz_trace("Duplicate frame\n");
                }
        }
 
        if (pd && !dup && ((pd->mode & OZ_MODE_MASK) == OZ_MODE_TRIGGERED)) {
-               oz_trace2(OZ_TRACE_RX_FRAMES, "Received TRIGGER Frame\n");
                pd->last_sent_frame = &pd->tx_queue;
                if (oz_hdr->control & OZ_F_ACK) {
                        /* Retire completed frames */
@@ -396,29 +376,25 @@ static void oz_rx_frame(struct sk_buff *skb)
        length -= sizeof(struct oz_hdr);
        elt = (struct oz_elt *)((u8 *)oz_hdr + sizeof(struct oz_hdr));
 
-       while (length >= sizeof(struct oz_elt)) {
-               length -= sizeof(struct oz_elt) + elt->length;
+       while (length >= oz_elt_hdr_len(elt)) {
+               length -= oz_elt_len(elt);
                if (length < 0)
                        break;
                switch (elt->type) {
                case OZ_ELT_CONNECT_REQ:
-                       oz_event_log(OZ_EVT_CONNECT_REQ, 0, 0, NULL, 0);
-                       oz_trace("RX: OZ_ELT_CONNECT_REQ\n");
                        pd = oz_connect_req(pd, elt, src_addr, skb->dev);
                        break;
                case OZ_ELT_DISCONNECT:
-                       oz_trace("RX: OZ_ELT_DISCONNECT\n");
                        if (pd)
                                oz_pd_sleep(pd);
                        break;
                case OZ_ELT_UPDATE_PARAM_REQ: {
                                struct oz_elt_update_param *body =
                                        (struct oz_elt_update_param *)(elt + 1);
-                               oz_trace("RX: OZ_ELT_UPDATE_PARAM_REQ\n");
                                if (pd && (pd->state & OZ_PD_S_CONNECTED)) {
                                        spin_lock(&g_polling_lock);
                                        pd_set_keepalive(pd, body->keepalive);
-                                       pd_set_presleep(pd, body->presleep);
+                                       pd_set_presleep(pd, body->presleep, 1);
                                        spin_unlock(&g_polling_lock);
                                }
                        }
@@ -426,16 +402,16 @@ static void oz_rx_frame(struct sk_buff *skb)
                case OZ_ELT_FAREWELL_REQ: {
                                struct oz_elt_farewell *body =
                                        (struct oz_elt_farewell *)(elt + 1);
-                               oz_trace("RX: OZ_ELT_FAREWELL_REQ\n");
                                oz_add_farewell(pd, body->ep_num,
                                        body->index, body->report,
                                        elt->length + 1 - sizeof(*body));
                        }
                        break;
                case OZ_ELT_APP_DATA:
+               case OZ_ELT_APP_DATA_EX:
                        if (pd && (pd->state & OZ_PD_S_CONNECTED)) {
                                struct oz_app_hdr *app_hdr =
-                                       (struct oz_app_hdr *)(elt+1);
+                                       (struct oz_app_hdr *)(oz_elt_data(elt));
                                if (dup)
                                        break;
                                oz_handle_app_elt(pd, app_hdr->app_id, elt);
@@ -456,14 +432,13 @@ done:
  */
 void oz_protocol_term(void)
 {
-       struct list_head *chain;
-       del_timer_sync(&g_timer);
+       struct oz_binding *b, *t;
+
        /* Walk the list of bindings and remove each one.
         */
        spin_lock_bh(&g_binding_lock);
-       while (g_binding) {
-               struct oz_binding *b = g_binding;
-               g_binding = b->next;
+       list_for_each_entry_safe(b, t, &g_binding, link) {
+               list_del(&b->link);
                spin_unlock_bh(&g_binding_lock);
                dev_remove_pack(&b->ptype);
                if (b->ptype.dev)
@@ -486,255 +461,115 @@ void oz_protocol_term(void)
                oz_pd_put(pd);
                spin_lock_bh(&g_polling_lock);
        }
-       chain = g_timer_pool;
-       g_timer_pool = NULL;
        spin_unlock_bh(&g_polling_lock);
-       while (chain) {
-               struct oz_timer *t = container_of(chain, struct oz_timer, link);
-               chain = chain->next;
-               kfree(t);
-       }
        oz_trace("Protocol stopped\n");
 }
 /*------------------------------------------------------------------------------
  * Context: softirq
  */
-static void oz_pd_handle_timer(struct oz_pd *pd, int type)
+void oz_pd_heartbeat_handler(unsigned long data)
 {
+       struct oz_pd *pd = (struct oz_pd *)data;
+       u16 apps = 0;
+       spin_lock_bh(&g_polling_lock);
+       if (pd->state & OZ_PD_S_CONNECTED)
+               apps = pd->total_apps;
+       spin_unlock_bh(&g_polling_lock);
+       if (apps)
+               oz_pd_heartbeat(pd, apps);
+
+       oz_pd_put(pd);
+}
+/*------------------------------------------------------------------------------
+ * Context: softirq
+ */
+void oz_pd_timeout_handler(unsigned long data)
+{
+       int type;
+       struct oz_pd *pd = (struct oz_pd *)data;
+
+       spin_lock_bh(&g_polling_lock);
+       type = pd->timeout_type;
+       spin_unlock_bh(&g_polling_lock);
        switch (type) {
        case OZ_TIMER_TOUT:
+               oz_trace_msg(M, "OZ_TIMER_TOUT:\n");
                oz_pd_sleep(pd);
                break;
        case OZ_TIMER_STOP:
+               oz_trace_msg(M, "OZ_TIMER_STOP:\n");
                oz_pd_stop(pd);
                break;
-       case OZ_TIMER_HEARTBEAT: {
-                       u16 apps = 0;
-                       spin_lock_bh(&g_polling_lock);
-                       pd->heartbeat_requested = 0;
-                       if (pd->state & OZ_PD_S_CONNECTED)
-                               apps = pd->total_apps;
-                       spin_unlock_bh(&g_polling_lock);
-                       if (apps)
-                               oz_pd_heartbeat(pd, apps);
-               }
-               break;
        }
+       oz_pd_put(pd);
 }
 /*------------------------------------------------------------------------------
- * Context: softirq
+ * Context: Interrupt
  */
-static void oz_protocol_timer(unsigned long arg)
+enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer)
 {
-       struct oz_timer *t;
-       struct oz_timer *t2;
        struct oz_pd *pd;
-       spin_lock_bh(&g_polling_lock);
-       if (!g_cur_timer) {
-               /* This happens if we remove the current timer but can't stop
-                * the timer from firing. In this case just get out.
-                */
-               oz_event_log(OZ_EVT_TIMER, 0, 0, NULL, 0);
-               spin_unlock_bh(&g_polling_lock);
-               return;
-       }
-       g_timer_state = OZ_TIMER_IN_HANDLER;
-       t = g_cur_timer;
-       g_cur_timer = NULL;
-       list_del(&t->link);
-       spin_unlock_bh(&g_polling_lock);
-       do {
-               pd = t->pd;
-               oz_event_log(OZ_EVT_TIMER, 0, t->type, NULL, 0);
-               oz_pd_handle_timer(pd, t->type);
-               spin_lock_bh(&g_polling_lock);
-               if (g_timer_pool_count < OZ_MAX_TIMER_POOL_SIZE) {
-                       t->link.next = g_timer_pool;
-                       g_timer_pool = &t->link;
-                       g_timer_pool_count++;
-                       t = NULL;
-               }
-               if (!list_empty(&g_timer_list)) {
-                       t2 =  container_of(g_timer_list.next,
-                               struct oz_timer, link);
-                       if (time_before_eq(t2->due_time, jiffies))
-                               list_del(&t2->link);
-                       else
-                               t2 = NULL;
-               } else {
-                       t2 = NULL;
-               }
-               spin_unlock_bh(&g_polling_lock);
-               oz_pd_put(pd);
-               kfree(t);
-               t = t2;
-       } while (t);
-       g_timer_state = OZ_TIMER_IDLE;
-       oz_protocol_timer_start();
+
+       pd = container_of(timer, struct oz_pd, heartbeat);
+       hrtimer_forward(timer,
+               hrtimer_get_expires(timer), pd->pulse_period);
+       oz_pd_get(pd);
+       tasklet_schedule(&pd->heartbeat_tasklet);
+       return HRTIMER_RESTART;
 }
 /*------------------------------------------------------------------------------
- * Context: softirq
+ * Context: Interrupt
  */
-static void oz_protocol_timer_start(void)
+enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer)
 {
-       spin_lock_bh(&g_polling_lock);
-       if (!list_empty(&g_timer_list)) {
-               g_cur_timer =
-                       container_of(g_timer_list.next, struct oz_timer, link);
-               if (g_timer_state == OZ_TIMER_SET) {
-                       oz_event_log(OZ_EVT_TIMER_CTRL, 3,
-                               (u16)g_cur_timer->type, NULL,
-                               (unsigned)g_cur_timer->due_time);
-                       mod_timer(&g_timer, g_cur_timer->due_time);
-               } else {
-                       oz_event_log(OZ_EVT_TIMER_CTRL, 4,
-                               (u16)g_cur_timer->type, NULL,
-                               (unsigned)g_cur_timer->due_time);
-                       g_timer.expires = g_cur_timer->due_time;
-                       g_timer.function = oz_protocol_timer;
-                       g_timer.data = 0;
-                       add_timer(&g_timer);
-               }
-               g_timer_state = OZ_TIMER_SET;
-       } else {
-               oz_trace("No queued timers\n");
-       }
-       spin_unlock_bh(&g_polling_lock);
+       struct oz_pd *pd;
+
+       pd = container_of(timer, struct oz_pd, timeout);
+       oz_pd_get(pd);
+       tasklet_schedule(&pd->timeout_tasklet);
+       return HRTIMER_NORESTART;
 }
 /*------------------------------------------------------------------------------
  * Context: softirq or process
  */
-void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time,
-               int remove)
+void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time)
 {
-       struct list_head *e;
-       struct oz_timer *t = NULL;
-       int restart_needed = 0;
-       oz_event_log(OZ_EVT_TIMER_CTRL, 1, (u16)type, NULL, (unsigned)due_time);
-       spin_lock(&g_polling_lock);
-       if (remove) {
-               list_for_each(e, &g_timer_list) {
-                       t = container_of(e, struct oz_timer, link);
-                       if ((t->pd == pd) && (t->type == type)) {
-                               if (g_cur_timer == t) {
-                                       restart_needed = 1;
-                                       g_cur_timer = NULL;
-                               }
-                               list_del(e);
-                               break;
-                       }
-                       t = NULL;
-               }
-       }
-       if (!t) {
-               if (g_timer_pool) {
-                       t = container_of(g_timer_pool, struct oz_timer, link);
-                       g_timer_pool = g_timer_pool->next;
-                       g_timer_pool_count--;
+       spin_lock_bh(&g_polling_lock);
+       switch (type) {
+       case OZ_TIMER_TOUT:
+       case OZ_TIMER_STOP:
+               if (hrtimer_active(&pd->timeout)) {
+                       hrtimer_set_expires(&pd->timeout, ktime_set(due_time /
+                       MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
+                                                       NSEC_PER_MSEC));
+                       hrtimer_start_expires(&pd->timeout, HRTIMER_MODE_REL);
                } else {
-                       t = kmalloc(sizeof(struct oz_timer), GFP_ATOMIC);
+                       hrtimer_start(&pd->timeout, ktime_set(due_time /
+                       MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
+                                       NSEC_PER_MSEC), HRTIMER_MODE_REL);
                }
-               if (t) {
-                       t->pd = pd;
-                       t->type = type;
-                       oz_pd_get(pd);
-               }
-       }
-       if (t) {
-               struct oz_timer *t2;
-               t->due_time = due_time;
-               list_for_each(e, &g_timer_list) {
-                       t2 = container_of(e, struct oz_timer, link);
-                       if (time_before(due_time, t2->due_time)) {
-                               if (t2 == g_cur_timer) {
-                                       g_cur_timer = NULL;
-                                       restart_needed = 1;
-                               }
-                               break;
-                       }
-               }
-               list_add_tail(&t->link, e);
-       }
-       if (g_timer_state == OZ_TIMER_IDLE)
-               restart_needed = 1;
-       else if (g_timer_state == OZ_TIMER_IN_HANDLER)
-               restart_needed = 0;
-       spin_unlock(&g_polling_lock);
-       if (restart_needed)
-               oz_protocol_timer_start();
-}
-/*------------------------------------------------------------------------------
- * Context: softirq or process
- */
-void oz_timer_delete(struct oz_pd *pd, int type)
-{
-       struct list_head *chain = NULL;
-       struct oz_timer *t;
-       struct oz_timer *n;
-       int restart_needed = 0;
-       int release = 0;
-       oz_event_log(OZ_EVT_TIMER_CTRL, 2, (u16)type, NULL, 0);
-       spin_lock(&g_polling_lock);
-       list_for_each_entry_safe(t, n, &g_timer_list, link) {
-               if ((t->pd == pd) && ((type == 0) || (t->type == type))) {
-                       if (g_cur_timer == t) {
-                               restart_needed = 1;
-                               g_cur_timer = NULL;
-                               del_timer(&g_timer);
-                       }
-                       list_del(&t->link);
-                       release++;
-                       if (g_timer_pool_count < OZ_MAX_TIMER_POOL_SIZE) {
-                               t->link.next = g_timer_pool;
-                               g_timer_pool = &t->link;
-                               g_timer_pool_count++;
-                       } else {
-                               t->link.next = chain;
-                               chain = &t->link;
-                       }
-                       if (type)
-                               break;
-               }
-       }
-       if (g_timer_state == OZ_TIMER_IN_HANDLER)
-               restart_needed = 0;
-       else if (restart_needed)
-               g_timer_state = OZ_TIMER_IDLE;
-       spin_unlock(&g_polling_lock);
-       if (restart_needed)
-               oz_protocol_timer_start();
-       while (release--)
-               oz_pd_put(pd);
-       while (chain) {
-               t = container_of(chain, struct oz_timer, link);
-               chain = chain->next;
-               kfree(t);
+               pd->timeout_type = type;
+               break;
+       case OZ_TIMER_HEARTBEAT:
+               if (!hrtimer_active(&pd->heartbeat))
+                       hrtimer_start(&pd->heartbeat, ktime_set(due_time /
+                       MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
+                                       NSEC_PER_MSEC), HRTIMER_MODE_REL);
+               break;
        }
+       spin_unlock_bh(&g_polling_lock);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq or process
  */
 void oz_pd_request_heartbeat(struct oz_pd *pd)
 {
-       unsigned long now = jiffies;
-       unsigned long t;
-       spin_lock(&g_polling_lock);
-       if (pd->heartbeat_requested) {
-               spin_unlock(&g_polling_lock);
-               return;
-       }
-       if (pd->pulse_period_j)
-               t = ((now / pd->pulse_period_j) + 1) * pd->pulse_period_j;
-       else
-               t = now + 1;
-       pd->heartbeat_requested = 1;
-       spin_unlock(&g_polling_lock);
-       oz_timer_add(pd, OZ_TIMER_HEARTBEAT, t, 0);
+       oz_timer_add(pd, OZ_TIMER_HEARTBEAT, OZ_QUANTUM);
 }
 /*------------------------------------------------------------------------------
  * Context: softirq or process
  */
-struct oz_pd *oz_pd_find(const u8 *mac_addr)
+struct oz_pd *oz_pd_find(u8 *mac_addr)
 {
        struct oz_pd *pd;
        struct list_head *e;
@@ -748,7 +583,7 @@ struct oz_pd *oz_pd_find(const u8 *mac_addr)
                }
        }
        spin_unlock_bh(&g_polling_lock);
-       return NULL;
+       return 0;
 }
 /*------------------------------------------------------------------------------
  * Context: process
@@ -770,9 +605,8 @@ void oz_app_enable(int app_id, int enable)
 static int oz_pkt_recv(struct sk_buff *skb, struct net_device *dev,
                struct packet_type *pt, struct net_device *orig_dev)
 {
-       oz_event_log(OZ_EVT_RX_FRAME, 0, 0, NULL, 0);
        skb = skb_share_check(skb, GFP_ATOMIC);
-       if (skb == NULL)
+       if (skb == 0)
                return 0;
        spin_lock_bh(&g_rx_queue.lock);
        if (g_processing_rx) {
@@ -802,7 +636,7 @@ static int oz_pkt_recv(struct sk_buff *skb, struct net_device *dev,
 /*------------------------------------------------------------------------------
  * Context: process
  */
-void oz_binding_add(char *net_dev)
+void oz_binding_add(const char *net_dev)
 {
        struct oz_binding *binding;
 
@@ -815,20 +649,19 @@ void oz_binding_add(char *net_dev)
                        oz_trace("Adding binding: %s\n", net_dev);
                        binding->ptype.dev =
                                dev_get_by_name(&init_net, net_dev);
-                       if (binding->ptype.dev == NULL) {
+                       if (binding->ptype.dev == 0) {
                                oz_trace("Netdev %s not found\n", net_dev);
                                kfree(binding);
-                               binding = NULL;
+                               binding = 0;
                        }
                } else {
                        oz_trace("Binding to all netcards\n");
-                       binding->ptype.dev = NULL;
+                       binding->ptype.dev = 0;
                }
                if (binding) {
                        dev_add_pack(&binding->ptype);
                        spin_lock_bh(&g_binding_lock);
-                       binding->next = g_binding;
-                       g_binding = binding;
+                       list_add_tail(&binding->link, &g_binding);
                        spin_unlock_bh(&g_binding_lock);
                }
        }
@@ -836,7 +669,7 @@ void oz_binding_add(char *net_dev)
 /*------------------------------------------------------------------------------
  * Context: process
  */
-static int compare_binding_name(char *s1, char *s2)
+static int compare_binding_name(const char *s1, const char *s2)
 {
        int i;
        for (i = 0; i < OZ_MAX_BINDING_LEN; i++) {
@@ -874,34 +707,49 @@ static void pd_stop_all_for_device(struct net_device *net_dev)
 /*------------------------------------------------------------------------------
  * Context: process
  */
-void oz_binding_remove(char *net_dev)
+void oz_binding_remove(const char *net_dev)
 {
-       struct oz_binding *binding;
-       struct oz_binding **link;
+       struct oz_binding *binding = NULL;
+       int found = 0;
+
        oz_trace("Removing binding: %s\n", net_dev);
        spin_lock_bh(&g_binding_lock);
-       binding = g_binding;
-       link = &g_binding;
-       while (binding) {
+       list_for_each_entry(binding, &g_binding, link) {
                if (compare_binding_name(binding->name, net_dev)) {
                        oz_trace("Binding '%s' found\n", net_dev);
-                       *link = binding->next;
+                       found = 1;
                        break;
-               } else {
-                       link = &binding;
-                       binding = binding->next;
                }
        }
        spin_unlock_bh(&g_binding_lock);
-       if (binding) {
+       if (found) {
                dev_remove_pack(&binding->ptype);
                if (binding->ptype.dev) {
                        dev_put(binding->ptype.dev);
                        pd_stop_all_for_device(binding->ptype.dev);
                }
+               list_del(&binding->link);
                kfree(binding);
        }
 }
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+int oz_get_binding_list(char *buf, int max_if)
+{
+       struct oz_binding *binding = 0;
+       int count = 0;
+
+       spin_lock_bh(&g_binding_lock);
+       list_for_each_entry(binding, &g_binding, link) {
+               if (count++ > max_if)
+                       break;
+               memcpy(buf, binding->name, OZ_MAX_BINDING_LEN);
+               buf += OZ_MAX_BINDING_LEN;
+       }
+       spin_unlock_bh(&g_binding_lock);
+       return count;
+}
 /*------------------------------------------------------------------------------
  * Context: process
  */
@@ -923,7 +771,7 @@ int oz_protocol_init(char *devs)
 {
        skb_queue_head_init(&g_rx_queue);
        if (devs && (devs[0] == '*')) {
-               oz_binding_add(NULL);
+               oz_binding_add(0);
        } else {
                char d[32];
                while (*devs) {
@@ -932,7 +780,6 @@ int oz_protocol_init(char *devs)
                                oz_binding_add(d);
                }
        }
-       init_timer(&g_timer);
        return 0;
 }
 /*------------------------------------------------------------------------------
@@ -953,6 +800,32 @@ int oz_get_pd_list(struct oz_mac_addr *addr, int max_count)
        spin_unlock_bh(&g_polling_lock);
        return count;
 }
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+int oz_get_pd_status_list(u8 *pd_list, int max_count)
+{
+       struct oz_pd *pd;
+       struct list_head *e;
+       int count = 0;
+
+       spin_lock_bh(&g_polling_lock);
+       list_for_each(e, &g_pd_list) {
+               if (count >= max_count)
+                       break;
+               pd = container_of(e, struct oz_pd, link);
+               if (pd_list) {
+                       memcpy(&pd_list[count * (ETH_ALEN + sizeof(pd->state))],
+                                               pd->mac_addr, ETH_ALEN);
+                       memcpy(&pd_list[(count * (ETH_ALEN + sizeof(pd->state)))
+                                       + ETH_ALEN],
+                                               &pd->state, sizeof(pd->state));
+                       count++;
+               }
+       }
+       spin_unlock_bh(&g_polling_lock);
+       return count;
+}
 /*------------------------------------------------------------------------------
 */
 void oz_polling_lock_bh(void)
index 93bb4c0172e0b69c0e27ed6ea20cccf931072e07..9b100a5b479c0f67b206ec5f65ca941d4a97af76 100644 (file)
@@ -7,28 +7,19 @@
 #define _OZPROTO_H
 
 #include <asm/byteorder.h>
-#include "ozconfig.h"
 #include "ozappif.h"
 
 #define OZ_ALLOCATED_SPACE(__x)        (LL_RESERVED_SPACE(__x)+(__x)->needed_tailroom)
 
-/* Converts millisecs to jiffies.
- */
-#define oz_ms_to_jiffies(__x)  msecs_to_jiffies(__x)
 
-/* Quantum milliseconds.
- */
-#define OZ_QUANTUM_MS          8
-/* Quantum jiffies
- */
-#define OZ_QUANTUM_J           (oz_ms_to_jiffies(OZ_QUANTUM_MS))
+/* Quantum in MS */
+#define OZ_QUANTUM             8
 /* Default timeouts.
  */
-#define OZ_CONNECTION_TOUT_J   (2*HZ)
-#define OZ_PRESLEEP_TOUT_J     (11*HZ)
+#define OZ_PRESLEEP_TOUT       11
 
 /* Maximun sizes of tx frames. */
-#define OZ_MAX_TX_SIZE         1514
+#define OZ_MAX_TX_SIZE         760
 
 /* Maximum number of uncompleted isoc frames that can be pending in network. */
 #define OZ_MAX_SUBMITTED_ISOC  16
@@ -62,14 +53,18 @@ int oz_protocol_init(char *devs);
 void oz_protocol_term(void);
 int oz_get_pd_list(struct oz_mac_addr *addr, int max_count);
 void oz_app_enable(int app_id, int enable);
-struct oz_pd *oz_pd_find(const u8 *mac_addr);
-void oz_binding_add(char *net_dev);
-void oz_binding_remove(char *net_dev);
-void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time,
-               int remove);
+struct oz_pd *oz_pd_find(u8 *mac_addr);
+void oz_binding_add(const char *net_dev);
+void oz_binding_remove(const char *net_dev);
+void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time);
 void oz_timer_delete(struct oz_pd *pd, int type);
 void oz_pd_request_heartbeat(struct oz_pd *pd);
 void oz_polling_lock_bh(void);
 void oz_polling_unlock_bh(void);
-
+void oz_pd_heartbeat_handler(unsigned long data);
+void oz_pd_timeout_handler(unsigned long data);
+enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer);
+enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer);
+int oz_get_pd_status_list(u8 *pd_list, int max_count);
+int oz_get_binding_list(char *buf, int max_if);
 #endif /* _OZPROTO_H */
index 17b09b9a5b0869b0442cbc14995ac6cfa6c7fdf4..ee76c2e2e3086875f61dcda591c539e74b348a24 100644 (file)
@@ -27,17 +27,51 @@ struct oz_elt {
        u8 length;
 } PACKED;
 
-#define oz_next_elt(__elt)     \
-       (struct oz_elt *)((u8 *)((__elt) + 1) + (__elt)->length)
+/* This is an extended element header.
+ */
+struct oz_ext_elt {
+       u8 type;
+       u16 length;
+} PACKED;
+
+
+
+#define oz_is_ext_elt(__elt) \
+       (((struct oz_elt *)(__elt))->type >= OZ_ELT_EXTENDED)
+
+#define oz_elt_hdr_len(__elt) \
+       (int)(oz_is_ext_elt(__elt) ? \
+               (sizeof(struct oz_ext_elt)) \
+       :       (sizeof(struct oz_elt)))
+
+#define oz_elt_data_len(__elt) \
+       (int)(oz_is_ext_elt(__elt) ? \
+               (le16_to_cpu((((struct oz_ext_elt *)(__elt))->length))) \
+       :       (__elt)->length)
+
+#define oz_elt_len(__elt) \
+       (oz_elt_hdr_len(__elt) + oz_elt_data_len(__elt))
+
+#define oz_elt_data(__elt) \
+       ((u8 *)(((u8 *)(__elt)) + oz_elt_hdr_len(__elt)))
+
+
+#define oz_next_elt(__elt) \
+       (struct oz_elt *)((u8 *)(__elt) + oz_elt_len(__elt))
+
 
 /* Protocol element IDs.
  */
+#define OZ_ELT_EXTENDED            0xC0
+#define OZ_ELT_ID_MASK         0x3F
 #define OZ_ELT_CONNECT_REQ     0x06
 #define OZ_ELT_CONNECT_RSP     0x07
 #define OZ_ELT_DISCONNECT      0x08
 #define OZ_ELT_UPDATE_PARAM_REQ        0x11
 #define OZ_ELT_FAREWELL_REQ    0x12
 #define OZ_ELT_APP_DATA                0x31
+#define OZ_ELT_APP_DATA_EX     (OZ_ELT_EXTENDED|OZ_ELT_APP_DATA)
+
 
 /* This is the Ozmo header which is the first Ozmo specific part
  * of a frame and comes after the MAC header.
@@ -83,7 +117,8 @@ struct oz_elt_connect_req {
        u16     apps;
        u8      max_len_div16;
        u8      ms_per_isoc;
-       u8      resv3[2];
+       u8      up_audio_buf;
+       u8      ms_per_elt;
 } PACKED;
 
 /* mode field bits.
@@ -142,7 +177,10 @@ struct oz_app_hdr {
 #define OZ_APPID_UNUSED1                       0x2
 #define OZ_APPID_UNUSED2                       0x3
 #define OZ_APPID_SERIAL                                0x4
-#define OZ_APPID_MAX                           OZ_APPID_SERIAL
+#define OZ_APPID_UNUSED3                       0x5
+#define OZ_APPID_UNUSED4                       0x6
+#define OZ_APPID_TFTP                          0x7
+#define OZ_APPID_MAX                           OZ_APPID_TFTP
 #define OZ_NB_APPS                             (OZ_APPID_MAX+1)
 
 /* USB header common to all elements for the  USB application.
index 353ead24fd7d02696fcae55fb2e8a04b1b627729..6bb22572dd2a3b3988f48b32065f8dff20e0448f 100644 (file)
  * Released under the GNU General Public License Version 2 (GPLv2).
  * -----------------------------------------------------------------------------
  */
-#include "ozconfig.h"
 #include "oztrace.h"
+#define CREATE_TRACE_POINTS
+#include "ozeventtrace.h"
 
-#ifdef WANT_VERBOSE_TRACE
-unsigned long trace_flags =
-       0
-#ifdef WANT_TRACE_STREAM
-       | OZ_TRACE_STREAM
-#endif /* WANT_TRACE_STREAM */
-#ifdef WANT_TRACE_URB
-       | OZ_TRACE_URB
-#endif /* WANT_TRACE_URB */
-
-#ifdef WANT_TRACE_CTRL_DETAIL
-       | OZ_TRACE_CTRL_DETAIL
-#endif /* WANT_TRACE_CTRL_DETAIL */
-
-#ifdef WANT_TRACE_HUB
-       | OZ_TRACE_HUB
-#endif /* WANT_TRACE_HUB */
-
-#ifdef WANT_TRACE_RX_FRAMES
-       | OZ_TRACE_RX_FRAMES
-#endif /* WANT_TRACE_RX_FRAMES */
-
-#ifdef WANT_TRACE_TX_FRAMES
-       | OZ_TRACE_TX_FRAMES
-#endif /* WANT_TRACE_TX_FRAMES */
-       ;
-#endif /* WANT_VERBOSE_TRACE */
+#define OZ_TRACE_DUMP_SKB_LEN_MAX 32
+#define OZ_TRACE_DUMP_URB_LEN_MAX 16
 
+u32 g_debug =
+#ifdef WANT_TRACE_DATA_FLOW
+       TRC_M|TRC_R|TRC_T|TRC_S|TRC_E|TRC_C;
+#else
+       0;
+#endif
+
+void (*func[]) (char *fmt, va_list arg) = {
+       trace_hcd_msg_evt,
+       trace_isoc_msg_evt,
+       trace_info_msg_evt
+};
+
+void oz_dump_data(char *buf, unsigned char *data, int len, int lmt)
+{
+       int i = 0;
+       if (len > lmt)
+               len = lmt;
+       while (len--) {
+               *buf = (*data>>4) + '0';
+               if (*data > (0xA0-1))
+                       *buf += 'A' - '9' - 1;
+               *++buf = (*data++&0xF) + '0';
+               if (*buf > '9')
+                       *buf += 'A' - '9' - 1;
+               if (buf++ && !(++i%4))
+                       *buf++ = ' ';
+       }
+       *buf++ = '\n';
+       *buf   = 0;
+}
+
+void oz_trace_f_urb_in(struct urb *urb)
+{
+       int  i = 0;
+       char buf[128*2];
+       int endpoint = usb_pipeendpoint(urb->pipe);
+
+       if (usb_pipein(urb->pipe))
+               endpoint |= 0x80;
+
+       if (endpoint == 0x00 || endpoint == 0x80) {
+               i += sprintf(&buf[i], "OZ S %08X %02X %02X ",
+                        (unsigned int)((uintptr_t)urb), endpoint,
+                       urb->transfer_buffer_length);
+
+               oz_dump_data(&buf[i], urb->setup_packet, 8, 8);
+
+       } else {
+               i += sprintf(&buf[i], "OZ S %08X %02X %02X ",
+                       (unsigned int)((uintptr_t)urb), endpoint,
+                       urb->transfer_buffer_length);
+               if (!usb_pipein(urb->pipe)) {
+                       oz_dump_data(&buf[i], (u8 *)(urb->transfer_buffer),
+                               urb->transfer_buffer_length,
+                               OZ_TRACE_DUMP_URB_LEN_MAX);
+
+               } else {
+                       oz_dump_data(&buf[i], NULL, 0, 0);
+               }
+
+       }
+       printk(buf);
+}
+
+void oz_trace_f_urb_out(struct urb *urb, int status)
+{
+       int  i = 0;
+       char buf[128*2];
+       int endpoint = usb_pipeendpoint(urb->pipe);
+       int length = urb->actual_length;
+
+       if (usb_pipeisoc(urb->pipe))
+               length = urb->transfer_buffer_length;
+
+       if (usb_pipein(urb->pipe))
+               endpoint |= 0x80;
+
+       if (status != 0) {
+               printk("OZ E %08X %08X\n",
+                       (unsigned int)((uintptr_t)urb), status);
+       } else {
+               i += sprintf(&buf[i], "OZ C %08X %02X %02X ",
+                       (unsigned int)((uintptr_t)urb),
+                       endpoint, urb->actual_length);
+
+               if (usb_pipein(urb->pipe)) {
+                       oz_dump_data(&buf[i],
+                       (u8 *)(urb->transfer_buffer),
+                       urb->actual_length,
+                       OZ_TRACE_DUMP_URB_LEN_MAX);
+               } else {
+                       oz_dump_data(&buf[i], NULL, 0, 0);
+               }
+               printk(buf);
+       }
+}
+
+void oz_trace_f_skb(struct sk_buff *skb, char dir)
+{
+       int  i = 0;
+       char buf[128*2];
+       int len = skb->len;
+
+       if (dir == 'T')
+               len -= 14;
+
+       i += sprintf(&buf[i], "OZ %c %04X ", dir, len);
+       oz_dump_data(&buf[i], (u8 *)skb_network_header(skb),
+                       len, OZ_TRACE_DUMP_SKB_LEN_MAX);
+       printk(buf);
+}
+
+void oz_trace_f_dbg(void)
+{
+}
+
+void trace_dbg_msg(int c, char *fmt, ...)
+{
+       va_list arg;
+
+       va_start(arg, fmt);
+       func[c](fmt, arg);
+       va_end(arg);
+}
+
+void trace_debug_log(char *log_type, ...)
+{
+       va_list arg;
+       char *fmt;
+
+       va_start(arg, log_type);
+       fmt = va_arg(arg, char *);
+       switch (*log_type) {
+       case 'H':
+               trace_hcd_msg_evt(fmt, arg);
+               break;
+       case 'I':
+               trace_isoc_msg_evt(fmt, arg);
+               break;
+        default:
+               trace_info_msg_evt(fmt, arg);
+               break;
+       }
+       va_end(arg);
+}
index 8293b24c5a779183df570b2e7d4cc1f987aee5f5..fe1322104c497b430de1e82d93fc7324d3eabfa2 100644 (file)
@@ -5,31 +5,93 @@
  */
 #ifndef _OZTRACE_H_
 #define _OZTRACE_H_
-#include "ozconfig.h"
-
-#define TRACE_PREFIX   KERN_ALERT "OZWPAN: "
-
-#ifdef WANT_TRACE
-#define oz_trace(...) printk(TRACE_PREFIX __VA_ARGS__)
-#ifdef WANT_VERBOSE_TRACE
-extern unsigned long trace_flags;
-#define oz_trace2(_flag, ...) \
-       do { if (trace_flags & _flag) printk(TRACE_PREFIX __VA_ARGS__); \
-       } while (0)
-#else
-#define oz_trace2(...)
-#endif /* #ifdef WANT_VERBOSE_TRACE */
-#else
-#define oz_trace(...)
-#define oz_trace2(...)
-#endif /* #ifdef WANT_TRACE */
-
-#define OZ_TRACE_STREAM                0x1
-#define OZ_TRACE_URB           0x2
-#define OZ_TRACE_CTRL_DETAIL   0x4
-#define OZ_TRACE_HUB           0x8
-#define OZ_TRACE_RX_FRAMES     0x10
-#define OZ_TRACE_TX_FRAMES     0x20
+#include <linux/usb.h>
+#include <linux/netdevice.h>
+#include "ozeventtrace.h"
+
+extern struct device *g_oz_wpan_dev;
+
+#define oz_trace(fmt, ...) \
+       do { dev_dbg(g_oz_wpan_dev, fmt, ##__VA_ARGS__); } while (0)
+
+void oz_trace_f_urb_out(struct urb *urb, int status);
+void oz_trace_f_urb_in(struct urb *urb);
+void oz_trace_f_skb(struct sk_buff *skb, char dir);
+void oz_trace_f_dbg(void);
+void trace_dbg_msg(int c, char *fmt, ...);
+void trace_debug_log(char *log_type, ...);
+
+extern u32 g_debug;
+
+#define TRC_A 0x00000001
+#define TRC_B 0x00000002
+#define TRC_C 0x00000004       /* urb Completion */
+#define TRC_D 0x00000008       /* Debug */
+#define TRC_E 0x00000010       /* urb Error */
+#define TRC_F 0x00000020
+#define TRC_G 0x00000040
+#define TRC_H 0x00000080       /* Hcd message */
+#define TRC_I 0x00000100       /* Isoc buffer depth */
+#define TRC_J 0x00000200
+#define TRC_K 0x00000400
+#define TRC_L 0x00000800
+#define TRC_M 0x00001000       /* Message */
+#define TRC_N 0x00002000
+#define TRC_O 0x00004000
+#define TRC_P 0x00008000
+#define TRC_Q 0x00010000
+#define TRC_R 0x00020000       /* Rx Ozmo frame */
+#define TRC_S 0x00040000       /* urb Submission */
+#define TRC_T 0x00080000       /* Tx ozmo frame */
+#define TRC_U 0x00100000
+#define TRC_V 0x00200000
+#define TRC_W 0x00400000
+#define TRC_X 0x00800000
+#define TRC_Y 0x01000000
+#define TRC_Z 0x02000000
+
+
+#define oz_trace_urb_out(u, s) \
+       do { if (!g_debug) \
+               trace_urb_out(u, s); \
+       else if ((g_debug & TRC_C) || ((g_debug & TRC_E) && (u->status != 0))) \
+               oz_trace_f_urb_out(u, s); } while (0)
+
+#define oz_trace_urb_in(u) \
+       do { if (!g_debug) \
+               trace_urb_in(u); \
+       else if (g_debug & TRC_S) \
+               oz_trace_f_urb_in(u); } while (0)
+
+#define oz_trace_skb(u, d) \
+       do { if ((!g_debug) && ('T' == d)) \
+               trace_tx_frame(u); \
+       else if ((!g_debug) && ('R' == d)) \
+               trace_rx_frame(u); \
+       else if ((('T' == d) && (g_debug & TRC_T)) || \
+                                       (('R' == d) && (g_debug & TRC_R))) \
+               oz_trace_f_skb(u, d); } while(0)
+
+#define oz_trace_msg(f, ...) \
+       do { if (!g_debug) \
+               trace_debug_log(#f, __VA_ARGS__); \
+       else if (g_debug & TRC_##f) \
+               printk("OZ " #f " " __VA_ARGS__); } while(0)
+
+enum {
+       TRACE_HCD_MSG,
+       TRACE_ISOC_MSG,
+       TRACE_INFO_MSG
+};
+
+#define trace_hcd_msg(fmt, ...)\
+       trace_dbg_msg(TRACE_HCD_MSG, fmt, ##__VA_ARGS__)
+
+#define trace_isoc_msg(fmt, ...)\
+       trace_dbg_msg(TRACE_ISOC_MSG, fmt, ##__VA_ARGS__)
+
+#define trace_info_msg(fmt, ...)\
+       trace_dbg_msg(TRACE_INFO_MSG, fmt, ##__VA_ARGS__)
 
 #endif /* Sentry */
 
index 55b9afbbe47b44449366c3059035575daa8f3160..b05519534444ec10c644bdba999ef2bd1f98bc0e 100644 (file)
@@ -4,7 +4,6 @@
  * -----------------------------------------------------------------------------
  */
 #include <linux/usb.h>
-#include "ozconfig.h"
 #ifdef WANT_URB_PARANOIA
 #include "ozurbparanoia.h"
 #include "oztrace.h"
@@ -22,7 +21,7 @@ void oz_remember_urb(struct urb *urb)
        spin_lock_irqsave(&g_urb_mem_lock, irq_state);
        if (g_nb_urbs < OZ_MAX_URBS) {
                g_urb_memory[g_nb_urbs++] = urb;
-               oz_trace("%lu: urb up = %d %p\n", jiffies, g_nb_urbs, urb);
+               oz_trace("urb up = %d %p\n", g_nb_urbs, urb);
        } else {
                oz_trace("ERROR urb buffer full\n");
        }
@@ -42,8 +41,8 @@ int oz_forget_urb(struct urb *urb)
                        if (--g_nb_urbs > i)
                                memcpy(&g_urb_memory[i], &g_urb_memory[i+1],
                                        (g_nb_urbs - i) * sizeof(struct urb *));
-                       oz_trace("%lu: urb down = %d %p\n",
-                               jiffies, g_nb_urbs, urb);
+                       oz_trace("urb down = %d %p\n",
+                               g_nb_urbs, urb);
                }
        }
        spin_unlock_irqrestore(&g_urb_mem_lock, irq_state);
index 8531438d758697a203628f37f8c04972e8f4351d..7c59b22f8b9f18e69964788b35d339daef755bcb 100644 (file)
@@ -21,7 +21,7 @@ int oz_usb_stream_delete(void *hpd, u8 ep_num);
 /* Request functions.
  */
 int oz_usb_control_req(void *hpd, u8 req_id, struct usb_ctrlrequest *setup,
-               const u8 *data, int data_len);
+               u8 *data, int data_len);
 int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type,
        u8 index, u16 windex, int offset, int len);
 int oz_usb_send_isoc(void *hpd, u8 ep_num, struct urb *urb);
@@ -30,14 +30,20 @@ void oz_usb_request_heartbeat(void *hpd);
 /* Confirmation functions.
  */
 void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status,
-       const u8 *desc, int length, int offset, int total_size);
+       u8 *desc, int length, int offset, int total_size);
 void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode,
-       const u8 *data, int data_len);
+       u8 *data, int data_len);
+
+void oz_hcd_mark_urb_submitted(void *hport, int ep_ix, u8 req_id);
 
 /* Indication functions.
  */
-void oz_hcd_data_ind(void *hport, u8 endpoint, const u8 *data, int data_len);
+void oz_hcd_data_ind(void *hport, u8 endpoint, u8 *data, int data_len);
 
 int oz_hcd_heartbeat(void *hport);
 
+/* Get information.
+ */
+u8 oz_get_up_max_buffer_units(void *hpd);
+
 #endif /* _OZUSBIF_H */
index 543a9415975c8479330bf2424bd62eb814ca5d95..3dae52f0af18dd0f773c5698d5b6709fbb7aaf40 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/errno.h>
 #include <linux/input.h>
 #include <asm/unaligned.h>
-#include "ozconfig.h"
 #include "ozprotocol.h"
 #include "ozeltbuf.h"
 #include "ozpd.h"
 #include "ozhcd.h"
 #include "oztrace.h"
 #include "ozusbsvc.h"
-#include "ozevent.h"
 /*------------------------------------------------------------------------------
  * This is called once when the driver is loaded to initialise the USB service.
  * Context: process
  */
 int oz_usb_init(void)
 {
-       oz_event_log(OZ_EVT_SERVICE, 1, OZ_APPID_USB, NULL, 0);
        return oz_hcd_init();
 }
 /*------------------------------------------------------------------------------
@@ -43,7 +40,6 @@ int oz_usb_init(void)
  */
 void oz_usb_term(void)
 {
-       oz_event_log(OZ_EVT_SERVICE, 2, OZ_APPID_USB, NULL, 0);
        oz_hcd_term();
 }
 /*------------------------------------------------------------------------------
@@ -54,8 +50,7 @@ int oz_usb_start(struct oz_pd *pd, int resume)
 {
        int rc = 0;
        struct oz_usb_ctx *usb_ctx;
-       struct oz_usb_ctx *old_ctx;
-       oz_event_log(OZ_EVT_SERVICE, 3, OZ_APPID_USB, NULL, resume);
+       struct oz_usb_ctx *old_ctx = 0;
        if (resume) {
                oz_trace("USB service resumed.\n");
                return 0;
@@ -65,7 +60,7 @@ int oz_usb_start(struct oz_pd *pd, int resume)
         * has a USB context then we will destroy it.
         */
        usb_ctx = kzalloc(sizeof(struct oz_usb_ctx), GFP_ATOMIC);
-       if (usb_ctx == NULL)
+       if (usb_ctx == 0)
                return -ENOMEM;
        atomic_set(&usb_ctx->ref_count, 1);
        usb_ctx->pd = pd;
@@ -76,12 +71,11 @@ int oz_usb_start(struct oz_pd *pd, int resume)
         */
        spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]);
        old_ctx = pd->app_ctx[OZ_APPID_USB-1];
-       if (old_ctx == NULL)
+       if (old_ctx == 0)
                pd->app_ctx[OZ_APPID_USB-1] = usb_ctx;
        oz_usb_get(pd->app_ctx[OZ_APPID_USB-1]);
        spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
        if (old_ctx) {
-               oz_trace("Already have USB context.\n");
                kfree(usb_ctx);
                usb_ctx = old_ctx;
        } else if (usb_ctx) {
@@ -98,10 +92,9 @@ int oz_usb_start(struct oz_pd *pd, int resume)
                oz_hcd_pd_reset(usb_ctx, usb_ctx->hport);
        } else {
                usb_ctx->hport = oz_hcd_pd_arrived(usb_ctx);
-               if (usb_ctx->hport == NULL) {
-                       oz_trace("USB hub returned null port.\n");
+               if (usb_ctx->hport == 0) {
                        spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]);
-                       pd->app_ctx[OZ_APPID_USB-1] = NULL;
+                       pd->app_ctx[OZ_APPID_USB-1] = 0;
                        spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
                        oz_usb_put(usb_ctx);
                        rc = -1;
@@ -117,17 +110,17 @@ int oz_usb_start(struct oz_pd *pd, int resume)
 void oz_usb_stop(struct oz_pd *pd, int pause)
 {
        struct oz_usb_ctx *usb_ctx;
-       oz_event_log(OZ_EVT_SERVICE, 4, OZ_APPID_USB, NULL, pause);
        if (pause) {
                oz_trace("USB service paused.\n");
                return;
        }
        spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]);
        usb_ctx = (struct oz_usb_ctx *)pd->app_ctx[OZ_APPID_USB-1];
-       pd->app_ctx[OZ_APPID_USB-1] = NULL;
+       pd->app_ctx[OZ_APPID_USB-1] = 0;
        spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
        if (usb_ctx) {
-               unsigned long tout = jiffies + HZ;
+               struct timespec ts, now;
+               getnstimeofday(&ts);
                oz_trace("USB service stopping...\n");
                usb_ctx->stopped = 1;
                /* At this point the reference count on the usb context should
@@ -136,10 +129,13 @@ void oz_usb_stop(struct oz_pd *pd, int pause)
                 * should get in but someone may already be in. So wait
                 * until they leave but timeout after 1 second.
                 */
-               while ((atomic_read(&usb_ctx->ref_count) > 2) &&
-                       time_before(jiffies, tout))
-                       ;
-               oz_trace("USB service stopped.\n");
+               while ((atomic_read(&usb_ctx->ref_count) > 2)) {
+                       getnstimeofday(&now);
+                       /*Approx 1 Sec. this is not perfect calculation*/
+                       if (now.tv_sec != ts.tv_sec)
+                               break;
+               }
+               oz_trace_msg(M, "USB service stopped.\n");
                oz_hcd_pd_departed(usb_ctx->hport);
                /* Release the reference taken in oz_usb_start.
                 */
@@ -165,7 +161,6 @@ void oz_usb_put(void *hpd)
 {
        struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
        if (atomic_dec_and_test(&usb_ctx->ref_count)) {
-               oz_trace("Dealloc USB context.\n");
                oz_pd_put(usb_ctx->pd);
                kfree(usb_ctx);
        }
@@ -182,7 +177,7 @@ int oz_usb_heartbeat(struct oz_pd *pd)
        if (usb_ctx)
                oz_usb_get(usb_ctx);
        spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
-       if (usb_ctx == NULL)
+       if (usb_ctx == 0)
                return rc;
        if (usb_ctx->stopped)
                goto done;
@@ -200,7 +195,6 @@ int oz_usb_stream_create(void *hpd, u8 ep_num)
 {
        struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
        struct oz_pd *pd = usb_ctx->pd;
-       oz_trace("oz_usb_stream_create(0x%x)\n", ep_num);
        if (pd->mode & OZ_F_ISOC_NO_ELTS) {
                oz_isoc_stream_create(pd, ep_num);
        } else {
@@ -222,7 +216,6 @@ int oz_usb_stream_delete(void *hpd, u8 ep_num)
        if (usb_ctx) {
                struct oz_pd *pd = usb_ctx->pd;
                if (pd) {
-                       oz_trace("oz_usb_stream_delete(0x%x)\n", ep_num);
                        if (pd->mode & OZ_F_ISOC_NO_ELTS) {
                                oz_isoc_stream_delete(pd, ep_num);
                        } else {
index 4e4b650fee3f50e9713c7ddd9649585e4104d308..a66d2adca4345f59a15a38ba48f02bcde703c994 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/errno.h>
 #include <linux/input.h>
 #include <asm/unaligned.h>
-#include "ozconfig.h"
 #include "ozprotocol.h"
 #include "ozeltbuf.h"
 #include "ozpd.h"
 #include "ozhcd.h"
 #include "oztrace.h"
 #include "ozusbsvc.h"
-#include "ozevent.h"
 /*------------------------------------------------------------------------------
  */
 #define MAX_ISOC_FIXED_DATA    (253-sizeof(struct oz_isoc_fixed))
+
+/*------------------------------------------------------------------------------
+ * Context: softirq
+ */
+static void oz_usb_setup_elt_completion_callback(struct oz_pd *pd, long context)
+{
+       struct oz_usb_ctx *ctx;
+       spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]);
+       ctx = (struct oz_usb_ctx *)pd->app_ctx[OZ_APPID_USB-1];
+       if (ctx) {
+               u8 req_id = (u8)context;
+               oz_hcd_mark_urb_submitted(ctx->hport, 0, req_id);
+       }
+       spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
+}
 /*------------------------------------------------------------------------------
  * Context: softirq
  */
@@ -63,16 +76,12 @@ int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type,
        struct oz_get_desc_req *body;
        struct oz_elt_buf *eb = &pd->elt_buff;
        struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
-       oz_trace("    req_type = 0x%x\n", req_type);
-       oz_trace("    desc_type = 0x%x\n", desc_type);
-       oz_trace("    index = 0x%x\n", index);
-       oz_trace("    windex = 0x%x\n", windex);
-       oz_trace("    offset = 0x%x\n", offset);
-       oz_trace("    len = 0x%x\n", len);
        if (len > 200)
                len = 200;
-       if (ei == NULL)
+       if (ei == 0)
                return -1;
+       ei->callback = oz_usb_setup_elt_completion_callback;
+       ei->context = req_id;
        elt = (struct oz_elt *)ei->data;
        elt->length = sizeof(struct oz_get_desc_req);
        body = (struct oz_get_desc_req *)(elt+1);
@@ -97,8 +106,10 @@ static int oz_usb_set_config_req(void *hpd, u8 req_id, u8 index)
        struct oz_elt_buf *eb = &pd->elt_buff;
        struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
        struct oz_set_config_req *body;
-       if (ei == NULL)
+       if (ei == 0)
                return -1;
+       ei->callback = oz_usb_setup_elt_completion_callback;
+       ei->context = req_id;
        elt = (struct oz_elt *)ei->data;
        elt->length = sizeof(struct oz_set_config_req);
        body = (struct oz_set_config_req *)(elt+1);
@@ -118,8 +129,10 @@ static int oz_usb_set_interface_req(void *hpd, u8 req_id, u8 index, u8 alt)
        struct oz_elt_buf *eb = &pd->elt_buff;
        struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
        struct oz_set_interface_req *body;
-       if (ei == NULL)
+       if (ei == 0)
                return -1;
+       ei->callback = oz_usb_setup_elt_completion_callback;
+       ei->context = req_id;
        elt = (struct oz_elt *)ei->data;
        elt->length = sizeof(struct oz_set_interface_req);
        body = (struct oz_set_interface_req *)(elt+1);
@@ -141,9 +154,11 @@ static int oz_usb_set_clear_feature_req(void *hpd, u8 req_id, u8 type,
        struct oz_elt_buf *eb = &pd->elt_buff;
        struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
        struct oz_feature_req *body;
-       if (ei == NULL)
+       if (ei == 0)
                return -1;
        elt = (struct oz_elt *)ei->data;
+       ei->callback = oz_usb_setup_elt_completion_callback;
+       ei->context = req_id;
        elt->length = sizeof(struct oz_feature_req);
        body = (struct oz_feature_req *)(elt+1);
        body->type = type;
@@ -157,7 +172,7 @@ static int oz_usb_set_clear_feature_req(void *hpd, u8 req_id, u8 type,
  * Context: tasklet
  */
 static int oz_usb_vendor_class_req(void *hpd, u8 req_id, u8 req_type,
-       u8 request, __le16 value, __le16 index, const u8 *data, int data_len)
+       u8 request, __le16 value, __le16 index, u8 *data, int data_len)
 {
        struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
        struct oz_pd *pd = usb_ctx->pd;
@@ -165,8 +180,10 @@ static int oz_usb_vendor_class_req(void *hpd, u8 req_id, u8 req_type,
        struct oz_elt_buf *eb = &pd->elt_buff;
        struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
        struct oz_vendor_class_req *body;
-       if (ei == NULL)
+       if (ei == 0)
                return -1;
+       ei->callback = oz_usb_setup_elt_completion_callback;
+       ei->context = req_id;
        elt = (struct oz_elt *)ei->data;
        elt->length = sizeof(struct oz_vendor_class_req) - 1 + data_len;
        body = (struct oz_vendor_class_req *)(elt+1);
@@ -184,16 +201,13 @@ static int oz_usb_vendor_class_req(void *hpd, u8 req_id, u8 req_type,
  * Context: tasklet
  */
 int oz_usb_control_req(void *hpd, u8 req_id, struct usb_ctrlrequest *setup,
-                       const u8 *data, int data_len)
+                       u8 *data, int data_len)
 {
        unsigned wvalue = le16_to_cpu(setup->wValue);
        unsigned windex = le16_to_cpu(setup->wIndex);
        unsigned wlength = le16_to_cpu(setup->wLength);
        int rc = 0;
-       oz_event_log(OZ_EVT_CTRL_REQ, setup->bRequest, req_id,
-               (void *)(((unsigned long)(setup->wValue))<<16 |
-                       ((unsigned long)setup->wIndex)),
-               setup->bRequestType);
+
        if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
                switch (setup->bRequest) {
                case USB_REQ_GET_DESCRIPTOR:
@@ -264,7 +278,7 @@ int oz_usb_send_isoc(void *hpd, u8 ep_num, struct urb *urb)
                int unit_count;
                int unit_size;
                int rem;
-               if (ei == NULL)
+               if (ei == 0)
                        return -1;
                rem = MAX_ISOC_FIXED_DATA;
                elt = (struct oz_elt *)ei->data;
@@ -305,7 +319,7 @@ int oz_usb_send_isoc(void *hpd, u8 ep_num, struct urb *urb)
 /*------------------------------------------------------------------------------
  * Context: softirq-serialized
  */
-static void oz_usb_handle_ep_data(struct oz_usb_ctx *usb_ctx,
+void oz_usb_handle_ep_data(struct oz_usb_ctx *usb_ctx,
        struct oz_usb_hdr *usb_hdr, int len)
 {
        struct oz_data *data_hdr = (struct oz_data *)usb_hdr;
@@ -359,7 +373,7 @@ void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt)
        if (usb_ctx)
                oz_usb_get(usb_ctx);
        spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
-       if (usb_ctx == NULL)
+       if (usb_ctx == 0)
                return; /* Context has gone so nothing to do. */
        if (usb_ctx->stopped)
                goto done;
@@ -381,7 +395,6 @@ void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt)
                        u16 offs = le16_to_cpu(get_unaligned(&body->offset));
                        u16 total_size =
                                le16_to_cpu(get_unaligned(&body->total_size));
-                       oz_trace("USB_REQ_GET_DESCRIPTOR - cnf\n");
                        oz_hcd_get_desc_cnf(usb_ctx->hport, body->req_id,
                                        body->rcode, body->data,
                                        data_len, offs, total_size);
@@ -391,14 +404,14 @@ void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt)
                        struct oz_set_config_rsp *body =
                                (struct oz_set_config_rsp *)usb_hdr;
                        oz_hcd_control_cnf(usb_ctx->hport, body->req_id,
-                               body->rcode, NULL, 0);
+                               body->rcode, 0, 0);
                }
                break;
        case OZ_SET_INTERFACE_RSP: {
                        struct oz_set_interface_rsp *body =
                                (struct oz_set_interface_rsp *)usb_hdr;
                        oz_hcd_control_cnf(usb_ctx->hport,
-                               body->req_id, body->rcode, NULL, 0);
+                               body->req_id, body->rcode, 0, 0);
                }
                break;
        case OZ_VENDOR_CLASS_RSP: {
@@ -427,7 +440,7 @@ void oz_usb_farewell(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len)
        if (usb_ctx)
                oz_usb_get(usb_ctx);
        spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
-       if (usb_ctx == NULL)
+       if (usb_ctx == 0)
                return; /* Context has gone so nothing to do. */
        if (!usb_ctx->stopped) {
                oz_trace("Farewell indicated ep = 0x%x\n", ep_num);
@@ -435,3 +448,11 @@ void oz_usb_farewell(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len)
        }
        oz_usb_put(usb_ctx);
 }
+/*------------------------------------------------------------------------------
+ * Context: softirq or process
+ */
+u8 oz_get_up_max_buffer_units(void *hpd)
+{
+       struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
+       return usb_ctx->pd->up_audio_buf;
+}