From f97258264752500ce7a49ad0bca1f8b1afafa9f1 Mon Sep 17 00:00:00 2001 From: Kenneth Kwak Date: Tue, 24 Jun 2014 21:43:08 -0700 Subject: Revert "staging:ozwpan: Merge from main" DO NOT INTEGRATE Bug 1466757 This reverts commit 5303a5b7be5e1973152f9899c3b240f4118aa0ca. Change-Id: I6274a3ae3699ac78a6facd4d57b72681b85511a5 Signed-off-by: Kenneth Kwak Reviewed-on: http://git-master/r/428085 Reviewed-by: Peter Kim Tested-by: Peter Kim --- drivers/staging/ozwpan/Kbuild | 2 +- drivers/staging/ozwpan/Makefile | 25 - drivers/staging/ozwpan/ozappif.h | 20 +- drivers/staging/ozwpan/ozcdev.c | 374 ++++----------- drivers/staging/ozwpan/ozcdev.h | 3 - drivers/staging/ozwpan/ozconfig.h | 27 ++ drivers/staging/ozwpan/ozeltbuf.c | 39 +- drivers/staging/ozwpan/ozeltbuf.h | 5 +- drivers/staging/ozwpan/ozevent.c | 116 +++++ drivers/staging/ozwpan/ozevent.h | 31 ++ drivers/staging/ozwpan/ozeventdef.h | 47 ++ drivers/staging/ozwpan/ozeventtrace.h | 219 --------- drivers/staging/ozwpan/ozhcd.c | 829 +++++++++++++++------------------ drivers/staging/ozwpan/ozkobject.c | 304 ------------ drivers/staging/ozwpan/ozkobject.h | 17 - drivers/staging/ozwpan/ozmain.c | 10 +- drivers/staging/ozwpan/ozpd.c | 394 ++++++---------- drivers/staging/ozwpan/ozpd.h | 31 +- drivers/staging/ozwpan/ozproto.c | 540 ++++++++++++--------- drivers/staging/ozwpan/ozproto.h | 39 +- drivers/staging/ozwpan/ozprotocol.h | 55 +-- drivers/staging/ozwpan/oztrace.c | 179 ++----- drivers/staging/ozwpan/oztrace.h | 114 +---- drivers/staging/ozwpan/ozurbparanoia.c | 7 +- drivers/staging/ozwpan/ozusbif.h | 18 +- drivers/staging/ozwpan/ozusbsvc.c | 57 +-- drivers/staging/ozwpan/ozusbsvc1.c | 59 +-- 27 files changed, 1321 insertions(+), 2240 deletions(-) delete mode 100644 drivers/staging/ozwpan/Makefile create mode 100644 drivers/staging/ozwpan/ozconfig.h create mode 100644 drivers/staging/ozwpan/ozevent.c create mode 100644 drivers/staging/ozwpan/ozevent.h create mode 100644 drivers/staging/ozwpan/ozeventdef.h delete mode 100644 drivers/staging/ozwpan/ozeventtrace.h delete mode 100644 drivers/staging/ozwpan/ozkobject.c delete mode 100644 drivers/staging/ozwpan/ozkobject.h diff --git a/drivers/staging/ozwpan/Kbuild b/drivers/staging/ozwpan/Kbuild index 08bc7938692d..6cc84cb3f0a6 100644 --- a/drivers/staging/ozwpan/Kbuild +++ b/drivers/staging/ozwpan/Kbuild @@ -14,6 +14,6 @@ ozwpan-y := \ ozcdev.o \ ozurbparanoia.o \ oztrace.o \ - ozkobject.o + ozevent.o diff --git a/drivers/staging/ozwpan/Makefile b/drivers/staging/ozwpan/Makefile deleted file mode 100644 index d2fdf8a1b5cf..000000000000 --- a/drivers/staging/ozwpan/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# ----------------------------------------------------------------------------- -# Copyright .o) 2011 Ozmo I.o -# Released under the GNU General Publ.o L.oense Version 2 (GPLv2). -# ----------------------------------------------------------------------------- -ifneq ($(KERNELRELEASE),) -# If invoked from kbuild. -obj-m := ozwpan.o -ozwpan-y := ozusbsvc.o ozusbsvc1.o ozurbparanoia.o oztrace.o ozproto.o ozpd.o ozmain.o ozkobject.o ozhcd.o ozeltbuf.o ozcdev.o - -else -# If invoked dir.otly. -KDIR := /lib/modules/$(shell uname -r)/build -PWD := $(shell pwd) - -default: - $(MAKE) -C $(KDIR) M=$(PWD) modules EXTRA_CFLAGS="-I$(PWD)" - -debug: OZ_CFLAGS=-DWANT_TRACE_DATA_FLOW -debug: - $(MAKE) -C $(KDIR) M=$(PWD) modules EXTRA_CFLAGS="$(OZ_CFLAGS) -I$(PWD)" -less_debug: - $(MAKE) -C $(KDIR) M=$(PWD) modules EXTRA_CFLAGS="-DDEBUG -I$(PWD)" - -endif - diff --git a/drivers/staging/ozwpan/ozappif.h b/drivers/staging/ozwpan/ozappif.h index ea1b271fdcda..af0273293872 100644 --- a/drivers/staging/ozwpan/ozappif.h +++ b/drivers/staging/ozwpan/ozappif.h @@ -6,16 +6,18 @@ #ifndef _OZAPPIF_H #define _OZAPPIF_H +#include "ozeventdef.h" + #define OZ_IOCTL_MAGIC 0xf4 struct oz_mac_addr { - __u8 a[6]; + unsigned char a[6]; }; #define OZ_MAX_PDS 8 struct oz_pd_list { - __u32 count; + int count; struct oz_mac_addr addr[OZ_MAX_PDS]; }; @@ -25,12 +27,20 @@ struct oz_binding_info { char name[OZ_MAX_BINDING_LEN]; }; +struct oz_test { + int action; +}; + #define OZ_IOCTL_GET_PD_LIST _IOR(OZ_IOCTL_MAGIC, 0, struct oz_pd_list) #define OZ_IOCTL_SET_ACTIVE_PD _IOW(OZ_IOCTL_MAGIC, 1, struct oz_mac_addr) #define OZ_IOCTL_GET_ACTIVE_PD _IOR(OZ_IOCTL_MAGIC, 2, struct oz_mac_addr) -#define OZ_IOCTL_ADD_BINDING _IOW(OZ_IOCTL_MAGIC, 3, struct oz_binding_info) -#define OZ_IOCTL_REMOVE_BINDING _IOW(OZ_IOCTL_MAGIC, 4, struct oz_binding_info) -#define OZ_IOCTL_MAX 5 +#define OZ_IOCTL_CLEAR_EVENTS _IO(OZ_IOCTL_MAGIC, 3) +#define OZ_IOCTL_GET_EVENTS _IOR(OZ_IOCTL_MAGIC, 4, struct oz_evtlist) +#define OZ_IOCTL_ADD_BINDING _IOW(OZ_IOCTL_MAGIC, 5, struct oz_binding_info) +#define OZ_IOCTL_TEST _IOWR(OZ_IOCTL_MAGIC, 6, struct oz_test) +#define OZ_IOCTL_SET_EVENT_MASK _IOW(OZ_IOCTL_MAGIC, 7, unsigned long) +#define OZ_IOCTL_REMOVE_BINDING _IOW(OZ_IOCTL_MAGIC, 8, struct oz_binding_info) +#define OZ_IOCTL_MAX 9 #endif /* _OZAPPIF_H */ diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c index 9785eaa86b94..1c380d687963 100644 --- a/drivers/staging/ozwpan/ozcdev.c +++ b/drivers/staging/ozwpan/ozcdev.c @@ -8,23 +8,19 @@ #include #include #include -#include #include #include +#include "ozconfig.h" #include "ozprotocol.h" #include "oztrace.h" #include "ozappif.h" #include "ozeltbuf.h" #include "ozpd.h" #include "ozproto.h" -#include "ozcdev.h" -#include "ozkobject.h" +#include "ozevent.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; @@ -32,8 +28,6 @@ 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. */ @@ -41,34 +35,16 @@ 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; -struct class *g_oz_class; -struct device *g_oz_wpan_dev; +int g_taction; /*------------------------------------------------------------------------------ - * 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]); -} +static struct oz_cdev g_cdev; /*------------------------------------------------------------------------------ * Context: process and softirq */ @@ -87,7 +63,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 (ctx && atomic_dec_and_test(&ctx->ref_count)) { + if (atomic_dec_and_test(&ctx->ref_count)) { oz_trace("Dealloc serial context.\n"); kfree(ctx); } @@ -98,10 +74,8 @@ static void oz_cdev_release_ctx(struct oz_serial_ctx *ctx) int oz_cdev_open(struct inode *inode, struct file *filp) { struct oz_cdev *dev; - - if (!atomic_add_unless(&g_cdev.ref_count, 1, 1)) - return -EBUSY; - + oz_trace("oz_cdev_open()\n"); + oz_trace("major = %d minor = %d\n", imajor(inode), iminor(inode)); dev = container_of(inode->i_cdev, struct oz_cdev, cdev); filp->private_data = dev; return 0; @@ -111,7 +85,7 @@ int oz_cdev_open(struct inode *inode, struct file *filp) */ int oz_cdev_release(struct inode *inode, struct file *filp) { - atomic_dec(&g_cdev.ref_count); + oz_trace("oz_cdev_release()\n"); return 0; } /*------------------------------------------------------------------------------ @@ -122,101 +96,44 @@ ssize_t oz_cdev_read(struct file *filp, char __user *buf, size_t count, { 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; - - 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); - } - + n = ctx->rd_in - ctx->rd_out; + if (n < 0) + n += OZ_RD_BUF_SZ; + if (count > n) 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)) { + 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)) { 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)) { - count = 0; - goto out1; - } - ix = count-n; - } - - spin_lock_bh(&ctx->rd_lock); - ctx->rd_out = ix; - spin_unlock_bh(&ctx->rd_lock); + ix = count-n; } + ctx->rd_out = ix; out1: oz_cdev_release_ctx(ctx); out2: @@ -231,68 +148,45 @@ ssize_t oz_cdev_write(struct file *filp, const char __user *buf, size_t count, { 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; - if (count > sizeof(ei->data) - sizeof(*elt) - sizeof(*app_hdr)) - return -EINVAL; - spin_lock_bh(&g_cdev.lock); pd = g_cdev.active_pd; 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; } - 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); - } + 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; if (copy_from_user(app_hdr+1, buf, count)) goto out; - spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]); + spin_lock_bh(&pd->app_lock[OZ_APPID_USB-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_SERIAL-1]); + spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]); out: if (ei) { count = 0; @@ -306,43 +200,25 @@ out: /*------------------------------------------------------------------------------ * Context: process */ -int oz_set_active_pd(const u8 *addr) +static 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", sizeof(addr))) { 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); @@ -354,52 +230,6 @@ int oz_set_active_pd(const u8 *addr) } return rc; } -/*------------------------------------------------------------------------------ - * Context: process - */ -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 */ @@ -421,7 +251,7 @@ long oz_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) switch (cmd) { case OZ_IOCTL_GET_PD_LIST: { struct oz_pd_list list; - memset(&list, 0, sizeof(list)); + oz_trace("OZ_IOCTL_GET_PD_LIST\n"); list.count = oz_get_pd_list(list.addr, OZ_MAX_PDS); if (copy_to_user((void __user *)arg, &list, sizeof(list))) @@ -430,6 +260,7 @@ long oz_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 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); @@ -437,6 +268,7 @@ long oz_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 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); @@ -444,6 +276,20 @@ long oz_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EFAULT; } break; +#ifdef WANT_EVENT_TRACE + case OZ_IOCTL_CLEAR_EVENTS: + oz_events_clear(); + break; + case OZ_IOCTL_GET_EVENTS: + rc = oz_events_copy((void __user *)arg); + break; + case OZ_IOCTL_SET_EVENT_MASK: + if (copy_from_user(&g_evt_mask, (void __user *)arg, + sizeof(unsigned long))) { + return -EFAULT; + } + break; +#endif /* WANT_EVENT_TRACE */ case OZ_IOCTL_ADD_BINDING: case OZ_IOCTL_REMOVE_BINDING: { struct oz_binding_info b; @@ -469,23 +315,17 @@ 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); } - } else - spin_unlock_bh(&dev->lock); - + } + spin_unlock_bh(&dev->lock); if (wait) poll_wait(filp, &dev->rdq, wait); return ret; @@ -510,38 +350,16 @@ int oz_cdev_register(void) memset(&g_cdev, 0, sizeof(g_cdev)); err = alloc_chrdev_region(&g_cdev.devnum, 0, 1, "ozwpan"); if (err < 0) - goto out3; + return err; + 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; spin_lock_init(&g_cdev.lock); init_waitqueue_head(&g_cdev.rdq); err = cdev_add(&g_cdev.cdev, g_cdev.devnum, 1); - if (err < 0) { - oz_trace("Failed to add cdev\n"); - goto out2; - } - g_oz_class = class_create(THIS_MODULE, "ozmo_wpan"); - if (IS_ERR(g_oz_class)) { - oz_trace("Failed to register ozmo_wpan class\n"); - err = PTR_ERR(g_oz_class); - goto out1; - } - 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"); - err = PTR_ERR(g_oz_wpan_dev); - goto out1; - } - oz_create_sys_entry(); return 0; -out1: - cdev_del(&g_cdev.cdev); -out2: - unregister_chrdev_region(g_cdev.devnum, 1); -out3: - return err; } /*------------------------------------------------------------------------------ * Context: process @@ -550,11 +368,6 @@ 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); - } return 0; } /*------------------------------------------------------------------------------ @@ -562,6 +375,7 @@ int oz_cdev_deregister(void) */ int oz_cdev_init(void) { + oz_event_log(OZ_EVT_SERVICE, 1, OZ_APPID_SERIAL, 0, 0); oz_app_enable(OZ_APPID_SERIAL, 1); return 0; } @@ -570,6 +384,7 @@ int oz_cdev_init(void) */ void oz_cdev_term(void) { + oz_event_log(OZ_EVT_SERVICE, 2, OZ_APPID_SERIAL, 0, 0); oz_app_enable(OZ_APPID_SERIAL, 0); } /*------------------------------------------------------------------------------ @@ -578,17 +393,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; + struct oz_serial_ctx *old_ctx = 0; + oz_event_log(OZ_EVT_SERVICE, 3, OZ_APPID_SERIAL, 0, resume); 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) { @@ -599,10 +414,11 @@ 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"); @@ -614,24 +430,26 @@ 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, 0, 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"); } @@ -647,19 +465,14 @@ 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 *)(oz_elt_data(elt)); + app_hdr = (struct oz_app_hdr *)(elt+1); /* If sequence number is non-zero then check it is not a duplicate. */ if (app_hdr->elt_seq_num != 0) { @@ -671,11 +484,10 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt) } } ctx->rx_seq_num = app_hdr->elt_seq_num; - len = oz_elt_data_len(elt) - sizeof(struct oz_app_hdr); - data = ((u8 *)(app_hdr + 1)); + len = elt->length - sizeof(struct oz_app_hdr); + data = ((u8 *)(elt+1)) + sizeof(struct oz_app_hdr); 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; @@ -683,19 +495,6 @@ 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) @@ -710,7 +509,6 @@ 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); diff --git a/drivers/staging/ozwpan/ozcdev.h b/drivers/staging/ozwpan/ozcdev.h index d0dc3dc5d5f1..698014bb8d72 100644 --- a/drivers/staging/ozwpan/ozcdev.h +++ b/drivers/staging/ozwpan/ozcdev.h @@ -6,7 +6,6 @@ #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); @@ -15,7 +14,5 @@ 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(const 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 new file mode 100644 index 000000000000..43e6373a009c --- /dev/null +++ b/drivers/staging/ozwpan/ozconfig.h @@ -0,0 +1,27 @@ +/* ----------------------------------------------------------------------------- + * 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 */ diff --git a/drivers/staging/ozwpan/ozeltbuf.c b/drivers/staging/ozwpan/ozeltbuf.c index a52fecef85fb..988f522475d9 100644 --- a/drivers/staging/ozwpan/ozeltbuf.c +++ b/drivers/staging/ozwpan/ozeltbuf.c @@ -6,6 +6,7 @@ #include #include #include +#include "ozconfig.h" #include "ozprotocol.h" #include "ozeltbuf.h" #include "ozpd.h" @@ -63,7 +64,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); @@ -81,9 +82,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); @@ -131,8 +132,10 @@ 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; @@ -148,8 +151,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; - + struct oz_elt_stream *st; + oz_trace("oz_elt_stream_delete(0x%x)\n", id); spin_lock_bh(&buf->lock); e = buf->stream_list.next; while (e != &buf->stream_list) { @@ -158,7 +161,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); @@ -172,6 +175,9 @@ 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); } @@ -202,7 +208,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) { @@ -236,6 +242,8 @@ 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. */ @@ -275,12 +283,8 @@ 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) { - 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 = (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; @@ -289,8 +293,11 @@ 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); @@ -312,7 +319,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) { diff --git a/drivers/staging/ozwpan/ozeltbuf.h b/drivers/staging/ozwpan/ozeltbuf.h index 2c184be4adab..03c12f57b9bb 100644 --- a/drivers/staging/ozwpan/ozeltbuf.h +++ b/drivers/staging/ozwpan/ozeltbuf.h @@ -23,7 +23,7 @@ struct oz_elt_stream { u8 id; }; -#define OZ_MAX_ELT_PAYLOAD 1024 +#define OZ_MAX_ELT_PAYLOAD 255 struct oz_elt_info { struct list_head link; struct list_head link_order; @@ -32,13 +32,12 @@ struct oz_elt_info { oz_elt_callback_t callback; long context; struct oz_elt_stream *stream; - u8 data[sizeof(struct oz_ext_elt) + OZ_MAX_ELT_PAYLOAD]; + u8 data[sizeof(struct oz_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 new file mode 100644 index 000000000000..73703d3e96bd --- /dev/null +++ b/drivers/staging/ozwpan/ozevent.c @@ -0,0 +1,116 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 2011 Ozmo Inc + * Released under the GNU General Public License Version 2 (GPLv2). + * ----------------------------------------------------------------------------- + */ +#include "ozconfig.h" +#ifdef WANT_EVENT_TRACE +#include +#include +#include "oztrace.h" +#include "ozevent.h" +/*------------------------------------------------------------------------------ + */ +unsigned long g_evt_mask = 0xffffffff; +/*------------------------------------------------------------------------------ + */ +#define OZ_MAX_EVTS 2048 /* Must be power of 2 */ +DEFINE_SPINLOCK(g_eventlock); +static int g_evt_in; +static int g_evt_out; +static int g_missed_events; +static struct oz_event g_events[OZ_MAX_EVTS]; +/*------------------------------------------------------------------------------ + * Context: process + */ +void oz_event_init(void) +{ + oz_trace("Event tracing initialized\n"); + g_evt_in = g_evt_out = 0; + g_missed_events = 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_eventlock, irqstate); + ix = (g_evt_in + 1) & (OZ_MAX_EVTS - 1); + if (ix != g_evt_out) { + struct oz_event *e = &g_events[g_evt_in]; + e->jiffies = jiffies; + e->evt = evt; + e->ctx1 = ctx1; + e->ctx2 = ctx2; + e->ctx3 = ctx3; + e->ctx4 = ctx4; + g_evt_in = ix; + } else { + g_missed_events++; + } + spin_unlock_irqrestore(&g_eventlock, irqstate); +} +/*------------------------------------------------------------------------------ + * Context: process + */ +int oz_events_copy(struct oz_evtlist __user *lst) +{ + int first; + int ix; + struct hdr { + int count; + int missed; + } hdr; + ix = g_evt_out; + hdr.count = g_evt_in - ix; + if (hdr.count < 0) + hdr.count += OZ_MAX_EVTS; + if (hdr.count > OZ_EVT_LIST_SZ) + hdr.count = OZ_EVT_LIST_SZ; + hdr.missed = g_missed_events; + g_missed_events = 0; + if (copy_to_user((void __user *)lst, &hdr, sizeof(hdr))) + return -EFAULT; + first = OZ_MAX_EVTS - ix; + if (first > hdr.count) + first = hdr.count; + if (first) { + int sz = first*sizeof(struct oz_event); + void __user *p = (void __user *)lst->evts; + if (copy_to_user(p, &g_events[ix], sz)) + return -EFAULT; + if (hdr.count > first) { + p = (void __user *)&lst->evts[first]; + sz = (hdr.count-first)*sizeof(struct oz_event); + if (copy_to_user(p, g_events, sz)) + return -EFAULT; + } + } + ix += hdr.count; + if (ix >= OZ_MAX_EVTS) + ix -= OZ_MAX_EVTS; + g_evt_out = ix; + return 0; +} +/*------------------------------------------------------------------------------ + * Context: process + */ +void oz_events_clear(void) +{ + unsigned long irqstate; + spin_lock_irqsave(&g_eventlock, irqstate); + g_evt_in = g_evt_out = 0; + g_missed_events = 0; + spin_unlock_irqrestore(&g_eventlock, irqstate); +} +#endif /* WANT_EVENT_TRACE */ + diff --git a/drivers/staging/ozwpan/ozevent.h b/drivers/staging/ozwpan/ozevent.h new file mode 100644 index 000000000000..f033d014c6f3 --- /dev/null +++ b/drivers/staging/ozwpan/ozevent.h @@ -0,0 +1,31 @@ +/* ----------------------------------------------------------------------------- + * 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 unsigned long 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); +#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) +int oz_events_copy(struct oz_evtlist __user *lst); +void oz_events_clear(void); +#else +#define oz_event_init() +#define oz_event_term() +#define oz_event_log(__evt, __ctx1, __ctx2, __ctx3, __ctx4) +#define oz_events_copy(__lst) +#define oz_events_clear() +#endif /* WANT_EVENT_TRACE */ + +#endif /* _OZEVENT_H */ diff --git a/drivers/staging/ozwpan/ozeventdef.h b/drivers/staging/ozwpan/ozeventdef.h new file mode 100644 index 000000000000..a880288bab11 --- /dev/null +++ b/drivers/staging/ozwpan/ozeventdef.h @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------------- + * 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 { + unsigned long jiffies; + unsigned char evt; + unsigned char ctx1; + unsigned short ctx2; + void *ctx3; + unsigned ctx4; +}; + +#define OZ_EVT_LIST_SZ 64 +struct oz_evtlist { + int count; + int missed; + struct oz_event evts[OZ_EVT_LIST_SZ]; +}; + +#endif /* _OZEVENTDEF_H */ diff --git a/drivers/staging/ozwpan/ozeventtrace.h b/drivers/staging/ozwpan/ozeventtrace.h deleted file mode 100644 index def0878b3fc1..000000000000 --- a/drivers/staging/ozwpan/ozeventtrace.h +++ /dev/null @@ -1,219 +0,0 @@ -/* ----------------------------------------------------------------------------- - * 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 -#include - -#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 diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c index 42c8a0880740..750b14eb505e 100644 --- a/drivers/staging/ozwpan/ozhcd.c +++ b/drivers/staging/ozwpan/ozhcd.c @@ -26,17 +26,21 @@ */ #include #include +#include #include #include #include "linux/usb/hcd.h" #include +#include "ozconfig.h" #include "ozusbif.h" #include "oztrace.h" #include "ozurbparanoia.h" -#include "ozhcd.h" - -#define OZ_HUB_DEBOUNCE_TIMEOUT 1500 - +#include "ozevent.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 /* Name of our platform device. */ #define OZ_PLAT_DEV_NAME "ozwpan" @@ -46,9 +50,6 @@ /* 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. @@ -60,7 +61,7 @@ struct oz_urb_link { struct oz_port *port; u8 req_id; u8 ep_num; - unsigned submit_counter; + unsigned long submit_jiffies; }; /* Holds state information about a USB endpoint. @@ -69,8 +70,7 @@ 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. */ - struct timespec timestamp; - int credit2; + unsigned long last_jiffies; int credit; int credit_ceiling; u8 ep_num; @@ -80,7 +80,6 @@ struct oz_endpoint { int in_ix; int out_ix; int buffered_units; - u8 max_buffer_units; unsigned flags; int start_frame; }; @@ -88,13 +87,6 @@ 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 { @@ -196,7 +188,6 @@ 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", @@ -245,14 +236,9 @@ 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; - - if (0 != bus_addr) { - for (i = 0; i < OZ_NB_PORTS; i++) { - if (ozhcd->ports[i].bus_addr == bus_addr) - return i; - } - - return -1; + for (i = 0; i < OZ_NB_PORTS; i++) { + if (ozhcd->ports[i].bus_addr == bus_addr) + return i; } return ozhcd->conn_port; } @@ -262,7 +248,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) { @@ -271,7 +257,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; } @@ -288,7 +274,7 @@ 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); @@ -306,7 +292,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) { @@ -352,7 +338,7 @@ 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 @@ -360,32 +346,17 @@ 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) + int status, unsigned long submit_jiffies) { 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. @@ -403,7 +374,14 @@ 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); @@ -418,6 +396,7 @@ 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; @@ -432,44 +411,9 @@ 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 - */ -void oz_complete_buffered_urb(struct oz_port *port, struct oz_endpoint *ep, - struct urb *urb) -{ - int data_len, available_space, copy_len; - - data_len = ep->buffer[ep->out_ix]; - if (data_len <= urb->transfer_buffer_length) - available_space = data_len; - else - available_space = urb->transfer_buffer_length; - - if (++ep->out_ix == ep->buffer_size) - ep->out_ix = 0; - copy_len = ep->buffer_size - ep->out_ix; - if (copy_len >= available_space) - copy_len = available_space; - memcpy(urb->transfer_buffer, &ep->buffer[ep->out_ix], copy_len); - - if (copy_len < available_space) { - memcpy((urb->transfer_buffer + copy_len), ep->buffer, - (available_space - copy_len)); - ep->out_ix = available_space - copy_len; - } else { - ep->out_ix += copy_len; - } - urb->actual_length = available_space; - if (ep->out_ix == ep->buffer_size) - ep->out_ix = 0; - - ep->buffered_units--; - oz_complete_urb(port->ozhcd->hcd, urb, 0); -} - /*------------------------------------------------------------------------------ * Context: softirq */ @@ -486,7 +430,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_counter = 0; + urbl->submit_jiffies = jiffies; urbl->urb = urb; urbl->req_id = req_id; urbl->ep_num = ep_addr; @@ -500,47 +444,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); + oz_complete_urb(port->ozhcd->hcd, urb, 0, 0); oz_free_urb_link(urbl); return 0; } - 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 - */ - if (((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) - && ep->buffered_units > 0) { - oz_free_urb_link(urbl); - spin_unlock_bh(&port->ozhcd->hcd_lock); - oz_complete_buffered_urb(port, ep, urb); - return 0; - } - + if (in_dir) + ep = port->in_ep[ep_addr]; + else + ep = port->out_ep[ep_addr]; if (ep && port->hpd) { list_add_tail(&urbl->link, &ep->urb_list); if (!in_dir && ep_addr && (ep->credit < 0)) { - getrawmonotonic(&ep->timestamp); + ep->last_jiffies = jiffies; ep->credit = 0; + oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num, + 0, 0, ep->credit); } } else { err = -EPIPE; } -out: spin_unlock_bh(&port->ozhcd->hcd_lock); if (err) oz_free_urb_link(urbl); @@ -554,7 +476,7 @@ out: 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) @@ -569,7 +491,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); @@ -585,8 +507,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); @@ -609,35 +531,6 @@ 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 @@ -688,14 +581,13 @@ 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; - static int n = OZ_NB_PORTS; - int j; + oz_trace("oz_hcd_pd_arrived()\n"); 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. */ @@ -703,45 +595,39 @@ 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; - if (++j >= OZ_NB_PORTS) - j = 0; - port = &ozhcd->ports[j]; + struct oz_port *port = &ozhcd->ports[i]; 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) { - ozhcd->conn_port = j; + oz_trace("Setting conn_port = %d\n", i); + ozhcd->conn_port = i; /* Attach out endpoint 0. */ - ozhcd->ports[j].out_ep[0] = ep; - ep = NULL; - hport = &ozhcd->ports[j]; + ozhcd->ports[i].out_ep[0] = ep; + ep = 0; + hport = &ozhcd->ports[i]; spin_unlock_bh(&ozhcd->hcd_lock); if (ozhcd->flags & OZ_HDC_F_SUSPENDED) { - oz_trace_msg(H, "usb_hcd_resume_root_hub()\n"); + oz_trace("Resuming 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; } @@ -756,21 +642,22 @@ 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("%s:\n", __func__); - if (port == NULL) { - oz_trace("%s: port = 0\n", __func__); + oz_trace("oz_hcd_pd_departed()\n"); + if (port == 0) { + oz_trace("oz_hcd_pd_departed() port = 0\n"); 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); @@ -781,24 +668,22 @@ 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|USB_PORT_STAT_ENABLE); + port->status &= ~USB_PORT_STAT_CONNECTION; 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); } @@ -823,13 +708,16 @@ 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, 0, 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; @@ -861,8 +749,53 @@ 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); + 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; + } +} +#else +#define oz_display_conf_type(__x) +#endif /* WANT_TRACE */ /*------------------------------------------------------------------------------ * Context: softirq */ @@ -881,7 +814,7 @@ static void oz_hcd_complete_set_config(struct oz_port *port, struct urb *urb, } else { rc = -ENOMEM; } - oz_complete_urb(hcd, urb, rc); + oz_complete_urb(hcd, urb, rc, 0); } /*------------------------------------------------------------------------------ * Context: softirq @@ -892,29 +825,26 @@ 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) { - 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 + 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)) rc = -ENOMEM; + else + port->iface[if_num].alt = alt; } else { rc = -ENOMEM; } - oz_complete_urb(hcd, urb, rc); + oz_complete_urb(hcd, urb, rc, 0); } /*------------------------------------------------------------------------------ * 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; @@ -924,9 +854,11 @@ 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, 0, 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: %p\n", urb); + oz_trace("URB not found\n"); return; } setup = (struct usb_ctrlrequest *)urb->setup_packet; @@ -934,6 +866,7 @@ 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, @@ -944,27 +877,26 @@ 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); + oz_complete_urb(hcd, urb, 0, 0); } } else { int copy_len; - if (data_len) { - if (data_len <= urb->transfer_buffer_length) - copy_len = data_len; - else - copy_len = urb->transfer_buffer_length; + oz_trace("VENDOR-CLASS - cnf\n"); + if (data_len <= urb->transfer_buffer_length) + copy_len = data_len; + else + copy_len = urb->transfer_buffer_length; + if (copy_len) memcpy(urb->transfer_buffer, data, copy_len); - urb->actual_length = copy_len; - } - oz_complete_urb(hcd, urb, 0); + urb->actual_length = copy_len; + oz_complete_urb(hcd, urb, 0, 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; @@ -974,10 +906,7 @@ 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_msg(I, "EP:%02X u:%d FULL len:%d spc:%d\n", - ep->ep_num | USB_DIR_IN, - ep->buffered_units, - data_len, space); + oz_trace("Buffer full\n"); return -1; } ep->buffer[ep->in_ix] = (u8)data_len; @@ -1002,14 +931,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: @@ -1030,35 +959,12 @@ 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); + oz_complete_urb(port->ozhcd->hcd, urb, 0, 0); return; - } else { - oz_hcd_buffer_data(ep, data, data_len); } break; case USB_ENDPOINT_XFER_ISOC: - 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; - } + oz_hcd_buffer_data(ep, data, data_len); break; } done: @@ -1069,7 +975,7 @@ done: */ static inline int oz_usb_get_frame_number(void) { - return atomic_inc_return(&g_usb_frame_number); + return jiffies_to_msecs(get_jiffies_64()); } /*------------------------------------------------------------------------------ * Context: softirq @@ -1085,8 +991,7 @@ int oz_hcd_heartbeat(void *hport) struct list_head *n; struct urb *urb; struct oz_endpoint *ep; - struct timespec ts, delta; - getrawmonotonic(&ts); + unsigned long now = jiffies; INIT_LIST_HEAD(&xfr_list); /* Check the OUT isoc endpoints to see if any URB data can be sent. */ @@ -1095,55 +1000,62 @@ int oz_hcd_heartbeat(void *hport) ep = ep_from_link(e); if (ep->credit < 0) continue; - delta = timespec_sub(ts, ep->timestamp); - ep->credit += div64_u64(timespec_to_ns(&delta), NSEC_PER_MSEC); + ep->credit += (now - ep->last_jiffies); if (ep->credit > ep->credit_ceiling) ep->credit = ep->credit_ceiling; - ep->timestamp = ts; + oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num, 0, 0, ep->credit); + ep->last_jiffies = now; while (ep->credit && !list_empty(&ep->urb_list)) { urbl = list_first_entry(&ep->urb_list, struct oz_urb_link, link); urb = urbl->urb; - if ((ep->credit + 1) < urb->number_of_packets) + if (ep->credit < urb->number_of_packets) break; ep->credit -= urb->number_of_packets; - if (ep->credit < 0) - ep->credit = 0; - list_move_tail(&urbl->link, &xfr_list); + oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num, 0, 0, + ep->credit); + 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); + oz_complete_urb(port->ozhcd->hcd, urb, 0, t); } /* 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 >= ep->max_buffer_units) { + if (ep->buffered_units * OZ_IN_BUFFERING_UNITS) { ep->flags &= ~OZ_F_EP_BUFFERING; ep->credit = 0; - ep->credit2 = 0; - ep->timestamp = ts; + oz_event_log(OZ_EVT_EP_CREDIT, + ep->ep_num | USB_DIR_IN, + 0, 0, ep->credit); + ep->last_jiffies = now; ep->start_frame = 0; + oz_event_log(OZ_EVT_EP_BUFFERING, + ep->ep_num | USB_DIR_IN, 0, 0, 0); } continue; } - delta = timespec_sub(ts, ep->timestamp); - ep->credit += div64_u64(timespec_to_ns(&delta)+5000, NSEC_PER_MSEC); - ep->timestamp = ts; + ep->credit += (now - ep->last_jiffies); + oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num | USB_DIR_IN, + 0, 0, ep->credit); + ep->last_jiffies = now; while (!list_empty(&ep->urb_list)) { struct oz_urb_link *urbl = list_first_entry(&ep->urb_list, @@ -1152,6 +1064,8 @@ int oz_hcd_heartbeat(void *hport) int len = 0; int copy_len; int i; + if (ep->credit < urb->number_of_packets) + break; if (ep->buffered_units < urb->number_of_packets) break; urb->actual_length = 0; @@ -1182,31 +1096,11 @@ 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; - 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; + oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num | USB_DIR_IN, + 0, 0, ep->credit); } } if (!list_empty(&port->isoc_out_ep) || !list_empty(&port->isoc_in_ep)) @@ -1219,7 +1113,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); + oz_complete_urb(port->ozhcd->hcd, urb, 0, 0); } /* Check if there are any ep0 requests that have timed out. * If so resent to PD. @@ -1231,14 +1125,12 @@ 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 (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_move_tail(e, &xfr_list); - urbl->submit_counter = 0; - } else if (urbl->submit_counter) { - urbl->submit_counter++; + 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_del(e); + list_add_tail(e, &xfr_list); } } if (!list_empty(&ep->urb_list)) @@ -1248,7 +1140,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_msg(M, "Resending request to PD.\n"); + oz_trace("Resending request to PD.\n"); oz_process_ep0_urb(ozhcd, urbl->urb, GFP_ATOMIC); oz_free_urb_link(urbl); } @@ -1264,17 +1156,9 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd, { struct oz_hcd *ozhcd = port->ozhcd; int i; - int if_ix; + int if_ix = intf->desc.bInterfaceNumber; 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; @@ -1282,16 +1166,11 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd, struct oz_endpoint *ep; int buffer_size = 0; - if (ep_addr & USB_ENDPOINT_DIR_MASK) { - switch (hep->desc.bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) { - case USB_ENDPOINT_XFER_ISOC: - buffer_size = OZ_EP_BUFFER_SIZE_ISOC; - break; - case USB_ENDPOINT_XFER_INT: - buffer_size = OZ_EP_BUFFER_SIZE_INT; - break; - } + oz_trace("%d bEndpointAddress = %x\n", i, ep_addr); + if ((ep_addr & USB_ENDPOINT_DIR_MASK) && + ((hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_ISOC)) { + buffer_size = 24*1024; } ep = oz_ep_alloc(mem_flags, buffer_size); @@ -1303,11 +1182,13 @@ 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, 0, 0); } else { ep->flags |= OZ_F_EP_HAVE_STREAM; if (oz_usb_stream_create(port->hpd, ep_num)) @@ -1363,17 +1244,19 @@ static void oz_clean_endpoints_for_interface(struct usb_hcd *hcd, */ if ((mask & (1<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); @@ -1431,8 +1314,9 @@ 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); @@ -1442,7 +1326,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; @@ -1461,15 +1345,16 @@ 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; - port_ix = oz_get_port_from_addr(ozhcd, (usb_pipedevice(urb->pipe))); + 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); if (port_ix < 0) { rc = -EPIPE; goto out; @@ -1489,10 +1374,17 @@ 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) { + if (hpd == 0) { + oz_trace("Cannot claim port\n"); rc = -EPIPE; goto out; } @@ -1502,23 +1394,34 @@ 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, 0, 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 short curcuit this case and reply directly since * we have the selected configuration number cached. */ + oz_event_log(OZ_EVT_CTRL_LOCAL, setup->bRequest, 0, 0, + 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) = @@ -1529,19 +1432,25 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, } break; case USB_REQ_GET_INTERFACE: - /* We short circuit this case and reply directly since + /* We short curcuit this case and reply directly since * we have the selected interface alternative cached. */ + oz_event_log(OZ_EVT_CTRL_LOCAL, setup->bRequest, 0, 0, + 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; } } @@ -1549,13 +1458,12 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, int data_len = 0; if ((setup->bRequestType & USB_DIR_IN) == 0) data_len = wlength; - urb->actual_length = data_len; if (oz_usb_control_req(port->hpd, req_id, setup, urb->transfer_buffer, data_len)) { rc = -ENOMEM; } else { /* Note: we are queuing the request after we have - * submitted it to be transmitted. If the request were + * submitted it to be tranmitted. If the request were * to complete before we queued it then it would not * be found in the queue. It seems impossible for * this to happen but if it did the request would @@ -1572,7 +1480,8 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, oz_usb_put(hpd); out: if (rc || complete) { - oz_complete_urb(ozhcd->hcd, urb, rc); + oz_trace("Completing request locally\n"); + oz_complete_urb(ozhcd->hcd, urb, rc, 0); } else { oz_usb_request_heartbeat(port->hpd); } @@ -1597,14 +1506,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 -ENODEV; + return -EPIPE; 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 = -ENOENT; + rc = -EPIPE; } else { oz_process_ep0_urb(ozhcd, urb, GFP_ATOMIC); } @@ -1619,7 +1528,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 @@ -1636,7 +1545,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); + oz_complete_urb(ozhcd->hcd, urb, rc, 0); spin_lock_irqsave(&g_tasklet_lock, irq_state); } spin_unlock_irqrestore(&g_tasklet_lock, irq_state); @@ -1653,18 +1562,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("%s: urb=%p port is null\n", __func__, urb); + if (port == 0) { + oz_trace("ERRORERROR: oz_urb_cancel(%p) port is null\n", urb); return; } ozhcd = port->ozhcd; - if (ozhcd == NULL) { - oz_trace("%s: urb=%p ozhcd is null\n", __func__, urb); + if (ozhcd == 0) { + oz_trace("ERRORERROR: oz_urb_cancel(%p) ozhcd is null\n", urb); return; } @@ -1680,7 +1589,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. */ @@ -1689,12 +1598,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 urb=%p\n", urb); + oz_trace("Found urb in orphanage\n"); 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 @@ -1705,7 +1614,7 @@ out2: if (urbl) { urb->actual_length = 0; oz_free_urb_link(urbl); - oz_complete_urb(ozhcd->hcd, urb, -ENOENT); + oz_complete_urb(ozhcd->hcd, urb, -EPIPE, 0); } } /*------------------------------------------------------------------------------ @@ -1716,7 +1625,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)) { @@ -1745,7 +1654,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); + oz_complete_urb(ozhcd->hcd, urbl->urb, status, 0); oz_free_urb_link(urbl); } } @@ -1755,6 +1664,7 @@ 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; @@ -1765,15 +1675,29 @@ static int oz_hcd_start(struct usb_hcd *hcd) */ static void oz_hcd_stop(struct usb_hcd *hcd) { - oz_trace("%s:\n", __func__); + oz_trace("oz_hcd_stop()\n"); } /*------------------------------------------------------------------------------ * Context: unknown */ static void oz_hcd_shutdown(struct usb_hcd *hcd) { - oz_trace("%s:\n", __func__); + oz_trace("oz_hcd_shutdown()\n"); } +/*------------------------------------------------------------------------------ + * 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 @@ -1789,34 +1713,39 @@ 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; - if (unlikely(ozhcd == NULL)) { - oz_trace("Refused urb(%p) not ozhcd.\n", urb); - return -ENODEV; + 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 == 0)) { + oz_trace2(OZ_TRACE_URB, "%lu: Refused urb(%p) not ozhcd.\n", + jiffies, urb); + return -EPIPE; } if (unlikely(hcd->state != HC_STATE_RUNNING)) { - oz_trace("Refused urb(%p) not running.\n", urb); - return -ENODEV; + oz_trace2(OZ_TRACE_URB, "%lu: Refused urb(%p) not running.\n", + jiffies, urb); + return -EPIPE; } - port_ix = oz_get_port_from_addr(ozhcd, (usb_pipedevice(urb->pipe))); + port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum); if (port_ix < 0) - return -ENODEV; + return -EPIPE; port = &ozhcd->ports[port_ix]; - if (port == NULL) - return -ENODEV; + if (port == 0) + return -EPIPE; if ((port->flags & OZ_PORT_F_PRESENT) == 0) { oz_trace("Refusing URB port_ix = %d devnum = %d\n", port_ix, urb->dev->devnum); - return -ENODEV; + return -EPIPE; } 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); @@ -1835,19 +1764,22 @@ 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)) + 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, 0, ep->credit); } return urbl; } @@ -1861,12 +1793,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 @@ -1900,7 +1832,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("%s:\n", __func__); + oz_trace("oz_hcd_endpoint_disable\n"); } /*------------------------------------------------------------------------------ * Context: unknown @@ -1908,13 +1840,14 @@ 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("%s:\n", __func__); + oz_trace("oz_hcd_endpoint_reset\n"); } /*------------------------------------------------------------------------------ * 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(); } /*------------------------------------------------------------------------------ @@ -1927,24 +1860,19 @@ 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) { - if (i < 7) - buf[0] |= 1<<(i+1); - else - buf[1] |= 1<<(i-7); + oz_trace2(OZ_TRACE_HUB, "Port %d changed\n", i); + ozhcd->ports[i].flags &= ~OZ_PORT_F_CHANGED; + buf[0] |= 1<<(i+1); } } - oz_trace_msg(H, "HUBSTS : %02X%02X\n", - (unsigned char)(buf[1]), (unsigned char)(buf[0])); spin_unlock_bh(&ozhcd->hcd_lock); - if (buf[1] != 0 || buf[0] != 0) - return 2; - else - return 0; + return buf[0] ? 1 : 0; } /*------------------------------------------------------------------------------ * Context: process @@ -1952,6 +1880,7 @@ 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; @@ -1970,65 +1899,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; - void *hpd; - + oz_trace2(OZ_TRACE_HUB, "SetPortFeature\n"); if ((port_id < 1) || (port_id > OZ_NB_PORTS)) - return -ENODEV; + return -EPIPE; port = &ozhcd->ports[port_id-1]; switch (wvalue) { case USB_PORT_FEAT_CONNECTION: - oz_trace("USB_PORT_FEAT_CONNECTION\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_CONNECTION\n"); break; case USB_PORT_FEAT_ENABLE: - oz_trace("USB_PORT_FEAT_ENABLE\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_ENABLE\n"); break; case USB_PORT_FEAT_SUSPEND: - oz_trace("USB_PORT_FEAT_SUSPEND\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_SUSPEND\n"); break; case USB_PORT_FEAT_OVER_CURRENT: - oz_trace("USB_PORT_FEAT_OVER_CURRENT\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_OVER_CURRENT\n"); break; case USB_PORT_FEAT_RESET: - oz_trace("USB_PORT_FEAT_RESET\n"); + oz_trace2(OZ_TRACE_HUB, "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; - hpd = oz_claim_hpd(&ozhcd->ports[port_id-1]); - if (hpd != NULL) { - oz_usb_reset_device(hpd); - oz_usb_put(hpd); - } break; case USB_PORT_FEAT_POWER: - oz_trace("USB_PORT_FEAT_POWER\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_POWER\n"); set_bits |= USB_PORT_STAT_POWER; break; case USB_PORT_FEAT_LOWSPEED: - oz_trace("USB_PORT_FEAT_LOWSPEED\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_LOWSPEED\n"); break; case USB_PORT_FEAT_C_CONNECTION: - oz_trace("USB_PORT_FEAT_C_CONNECTION\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_CONNECTION\n"); break; case USB_PORT_FEAT_C_ENABLE: - oz_trace("USB_PORT_FEAT_C_ENABLE\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_ENABLE\n"); break; case USB_PORT_FEAT_C_SUSPEND: - oz_trace("USB_PORT_FEAT_C_SUSPEND\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_SUSPEND\n"); break; case USB_PORT_FEAT_C_OVER_CURRENT: - oz_trace("USB_PORT_FEAT_C_OVER_CURRENT\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n"); break; case USB_PORT_FEAT_C_RESET: - oz_trace("USB_PORT_FEAT_C_RESET\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_RESET\n"); break; case USB_PORT_FEAT_TEST: - oz_trace("USB_PORT_FEAT_TEST\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_TEST\n"); break; case USB_PORT_FEAT_INDICATOR: - oz_trace("USB_PORT_FEAT_INDICATOR\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_INDICATOR\n"); break; default: - oz_trace("Other %d\n", wvalue); + oz_trace2(OZ_TRACE_HUB, "Other %d\n", wvalue); break; } if (set_bits || clear_bits) { @@ -2037,9 +1960,8 @@ 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_trace_msg(H, "Port[%d]: %08X\n", port_id, - ozhcd->ports[port_id-1].status); + oz_trace2(OZ_TRACE_HUB, "Port[%d] status = 0x%x\n", port_id, + port->status); return err; } /*------------------------------------------------------------------------------ @@ -2052,60 +1974,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 -ENODEV; + return -EPIPE; port = &ozhcd->ports[port_id-1]; switch (wvalue) { case USB_PORT_FEAT_CONNECTION: - oz_trace("USB_PORT_FEAT_CONNECTION\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_CONNECTION\n"); break; case USB_PORT_FEAT_ENABLE: - oz_trace("USB_PORT_FEAT_ENABLE\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_ENABLE\n"); clear_bits = USB_PORT_STAT_ENABLE; break; case USB_PORT_FEAT_SUSPEND: - oz_trace("USB_PORT_FEAT_SUSPEND\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_SUSPEND\n"); break; case USB_PORT_FEAT_OVER_CURRENT: - oz_trace("USB_PORT_FEAT_OVER_CURRENT\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_OVER_CURRENT\n"); break; case USB_PORT_FEAT_RESET: - oz_trace("USB_PORT_FEAT_RESET\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_RESET\n"); break; case USB_PORT_FEAT_POWER: - oz_trace("USB_PORT_FEAT_POWER\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_POWER\n"); clear_bits |= USB_PORT_STAT_POWER; break; case USB_PORT_FEAT_LOWSPEED: - oz_trace("USB_PORT_FEAT_LOWSPEED\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_LOWSPEED\n"); break; case USB_PORT_FEAT_C_CONNECTION: - oz_trace("USB_PORT_FEAT_C_CONNECTION\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_CONNECTION\n"); clear_bits = (USB_PORT_STAT_C_CONNECTION << 16); break; case USB_PORT_FEAT_C_ENABLE: - oz_trace("USB_PORT_FEAT_C_ENABLE\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_ENABLE\n"); clear_bits = (USB_PORT_STAT_C_ENABLE << 16); break; case USB_PORT_FEAT_C_SUSPEND: - oz_trace("USB_PORT_FEAT_C_SUSPEND\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_SUSPEND\n"); break; case USB_PORT_FEAT_C_OVER_CURRENT: - oz_trace("USB_PORT_FEAT_C_OVER_CURRENT\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n"); break; case USB_PORT_FEAT_C_RESET: - oz_trace("USB_PORT_FEAT_C_RESET\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_RESET\n"); clear_bits = (USB_PORT_FEAT_C_RESET << 16); break; case USB_PORT_FEAT_TEST: - oz_trace("USB_PORT_FEAT_TEST\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_TEST\n"); break; case USB_PORT_FEAT_INDICATOR: - oz_trace("USB_PORT_FEAT_INDICATOR\n"); + oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_INDICATOR\n"); break; default: - oz_trace("Other %d\n", wvalue); + oz_trace2(OZ_TRACE_HUB, "Other %d\n", wvalue); break; } if (clear_bits) { @@ -2113,8 +2035,7 @@ 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_trace_msg(H, "Port[%d]: %08X\n", port_id, + oz_trace2(OZ_TRACE_HUB, "Port[%d] status = 0x%x\n", port_id, ozhcd->ports[port_id-1].status); return err; } @@ -2126,12 +2047,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 -ENODEV; + return -EPIPE; ozhcd = oz_hcd_private(hcd); - ozhcd->ports[windex-1].flags &= ~OZ_PORT_F_CHANGED; + oz_trace2(OZ_TRACE_HUB, "GetPortStatus windex = %d\n", windex); status = ozhcd->ports[windex-1].status; put_unaligned(cpu_to_le32(status), (__le32 *)buf); - oz_trace_msg(H, "Port[%d]: %08X\n", windex, status); + oz_trace2(OZ_TRACE_HUB, "Port[%d] status = %x\n", windex, status); return 0; } /*------------------------------------------------------------------------------ @@ -2141,13 +2062,10 @@ 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_trace_msg(H, "HUBCTL: %04X %04X %04X %04X\n", - req_type, wvalue, windex, wlength); - + oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_control()\n"); switch (req_type) { case ClearHubFeature: - oz_trace("ClearHubFeature: %d\n", req_type); + oz_trace2(OZ_TRACE_HUB, "ClearHubFeature: %d\n", req_type); break; case ClearPortFeature: err = oz_clear_port_feature(hcd, wvalue, windex); @@ -2156,7 +2074,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_trace("GetHubStatus: req_type = 0x%x\n", + oz_trace2(OZ_TRACE_HUB, "GetHubStatus: req_type = 0x%x\n", req_type); put_unaligned(__constant_cpu_to_le32(0), (__le32 *)buf); break; @@ -2164,13 +2082,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_trace("SetHubFeature: %d\n", req_type); + oz_trace2(OZ_TRACE_HUB, "SetHubFeature: %d\n", req_type); break; case SetPortFeature: err = oz_set_port_feature(hcd, wvalue, windex); break; default: - oz_trace("Other: %d\n", req_type); + oz_trace2(OZ_TRACE_HUB, "Other: %d\n", req_type); break; } return err; @@ -2181,7 +2099,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; @@ -2195,7 +2113,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; @@ -2207,7 +2125,7 @@ static int oz_hcd_bus_resume(struct usb_hcd *hcd) */ static void oz_plat_shutdown(struct platform_device *dev) { - oz_trace("%s:\n", __func__); + oz_trace("oz_plat_shutdown()\n"); } /*------------------------------------------------------------------------------ * Context: process @@ -2218,10 +2136,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\n"); + if (hcd == 0) { + oz_trace("Failed to created hcd object OK\n"); return -ENOMEM; } ozhcd = oz_hcd_private(hcd); @@ -2240,9 +2158,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, -1, 0); + err = usb_add_hcd(hcd, 0, 0); if (err) { - oz_trace("Failed to add hcd object\n"); + oz_trace("Failed to add hcd object OK\n"); usb_put_hcd(hcd); return -1; } @@ -2258,15 +2176,17 @@ static int oz_plat_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct oz_hcd *ozhcd; - - if (hcd == NULL) + oz_trace("oz_plat_remove()\n"); + 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_hcd_clear_orphanage(ozhcd, -ENODEV); + oz_trace("Clearing orphanage\n"); + oz_hcd_clear_orphanage(ozhcd, -EPIPE); + oz_trace("Removing hcd\n"); usb_remove_hcd(hcd); usb_put_hcd(hcd); oz_empty_link_pool(); @@ -2277,7 +2197,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("%s:\n", __func__); + oz_trace("oz_plat_suspend()\n"); return 0; } /*------------------------------------------------------------------------------ @@ -2285,7 +2205,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("%s:\n", __func__); + oz_trace("oz_plat_resume()\n"); return 0; } /*------------------------------------------------------------------------------ @@ -2296,20 +2216,22 @@ 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); @@ -2318,7 +2240,7 @@ error1: error: tasklet_disable(&g_urb_process_tasklet); tasklet_disable(&g_urb_cancel_tasklet); - oz_trace("HCD Init failed: %d\n", err); + oz_trace("oz_hcd_init() failed %d\n", err); return err; } /*------------------------------------------------------------------------------ @@ -2326,9 +2248,8 @@ error: */ void oz_hcd_term(void) { - msleep(OZ_HUB_DEBOUNCE_TIMEOUT); - tasklet_kill(&g_urb_process_tasklet); - tasklet_kill(&g_urb_cancel_tasklet); + 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 deleted file mode 100644 index 9b85ef55da15..000000000000 --- a/drivers/staging/ozwpan/ozkobject.c +++ /dev/null @@ -1,304 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#include -#include -#include -#include -#include -#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< 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 deleted file mode 100644 index 0557228001d4..000000000000 --- a/drivers/staging/ozwpan/ozkobject.h +++ /dev/null @@ -1,17 +0,0 @@ -/* ----------------------------------------------------------------------------- - * 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 */ diff --git a/drivers/staging/ozwpan/ozmain.c b/drivers/staging/ozwpan/ozmain.c index 61b83f86ef63..aaf2ccc0bcfb 100644 --- a/drivers/staging/ozwpan/ozmain.c +++ b/drivers/staging/ozwpan/ozmain.c @@ -10,10 +10,12 @@ #include #include #include +#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 @@ -26,12 +28,11 @@ char *g_net_dev = ""; */ static int __init ozwpan_init(void) { - if (oz_protocol_init(g_net_dev)) - return -1; + oz_event_init(); oz_cdev_register(); + oz_protocol_init(g_net_dev); oz_app_enable(OZ_APPID_USB, 1); oz_apps_init(); - printk(KERN_DEBUG "p->oz_protocol_init = 0x%p\n", oz_protocol_init); return 0; } /*------------------------------------------------------------------------------ @@ -42,6 +43,7 @@ static void __exit ozwpan_exit(void) oz_protocol_term(); oz_apps_term(); oz_cdev_deregister(); + oz_event_term(); } /*------------------------------------------------------------------------------ */ @@ -51,6 +53,6 @@ module_exit(ozwpan_exit); MODULE_AUTHOR("Chris Kelly"); MODULE_DESCRIPTION("Ozmo Devices USB over WiFi hcd driver"); -MODULE_VERSION("1.2.3-rc9"); +MODULE_VERSION("1.0.8"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c index e9a3de041b8c..04cd57f2a6da 100644 --- a/drivers/staging/ozwpan/ozpd.c +++ b/drivers/staging/ozwpan/ozpd.c @@ -9,11 +9,13 @@ #include #include #include +#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 @@ -22,17 +24,18 @@ /*------------------------------------------------------------------------------ */ #define OZ_MAX_TX_POOL_SIZE 6 -#define AC_VO 0x106 +/* Maximum number of uncompleted isoc frames that can be pending. + */ +#define OZ_MAX_SUBMITTED_ISOC 16 /*------------------------------------------------------------------------------ */ static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd); static void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f); -static void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f); static struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f); static int oz_send_isoc_frame(struct oz_pd *pd); static void oz_retire_frame(struct oz_pd *pd, struct oz_tx_frame *f); static void oz_isoc_stream_free(struct oz_isoc_stream *st); -static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data); +static int oz_send_next_queued_frame(struct oz_pd *pd, int *more_data); static void oz_isoc_destructor(struct sk_buff *skb); static int oz_def_app_init(void); static void oz_def_app_term(void); @@ -45,7 +48,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, @@ -60,8 +63,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, @@ -69,8 +72,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, @@ -78,36 +81,9 @@ 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, - NULL, - NULL, - OZ_APPID_UNUSED3}, - - {oz_def_app_init, - oz_def_app_term, - oz_def_app_start, - oz_def_app_stop, - oz_def_app_rx, - NULL, - NULL, - OZ_APPID_UNUSED4}, - - {NULL, - NULL, - NULL, - NULL, - oz_cdev_rx, - NULL, - NULL, - OZ_APPID_TFTP}, }; /*------------------------------------------------------------------------------ * Context: process @@ -147,6 +123,23 @@ 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, 0, 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 @@ -166,12 +159,11 @@ 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]); @@ -181,7 +173,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); @@ -189,28 +181,19 @@ 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; } -static void oz_pd_free(struct work_struct *work) +/*------------------------------------------------------------------------------ + * Context: softirq or process + */ +void oz_pd_destroy(struct oz_pd *pd) { - 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; @@ -225,8 +208,6 @@ static void oz_pd_free(struct work_struct *work) while (e != &pd->tx_queue) { f = container_of(e, struct oz_tx_frame, link); e = e->next; - if (f->skb != NULL) - kfree_skb(f->skb); oz_retire_frame(pd, f); } oz_elt_buf_term(&pd->elt_buff); @@ -249,42 +230,20 @@ static void oz_pd_free(struct work_struct *work) 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<app_id)) { - if (ai->start && ai->start(pd, resume)) { + if (ai->start(pd, resume)) { rc = -1; + oz_trace("Unabled to start service %d\n", + ai->app_id); break; } oz_polling_lock_bh(); @@ -301,10 +260,8 @@ 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<app_id)) { oz_polling_lock_bh(); @@ -315,8 +272,7 @@ void oz_services_stop(struct oz_pd *pd, u16 apps, int pause) pd->paused_apps &= ~(1<app_id); } oz_polling_unlock_bh(); - if (ai->stop) - ai->stop(pd, pause); + ai->stop(pd, pause); } } } @@ -325,7 +281,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<app_id))) { @@ -333,8 +289,8 @@ void oz_pd_heartbeat(struct oz_pd *pd, u16 apps) more = 1; } } - if ((!more) && (hrtimer_active(&pd->heartbeat))) - hrtimer_cancel(&pd->heartbeat); + if (more) + oz_pd_request_heartbeat(pd); if (pd->mode & OZ_F_ISOC_ANYTIME) { int count = 8; while (count-- && (oz_send_isoc_frame(pd) >= 0)) @@ -347,9 +303,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("%s: State = 0x%x\n", __func__, pd->state); - oz_polling_lock_bh(); + oz_trace("oz_pd_stop() State = 0x%x\n", pd->state); oz_pd_indicate_farewells(pd); + oz_polling_lock_bh(); stop_apps = pd->total_apps; pd->total_apps = 0; pd->paused_apps = 0; @@ -359,9 +315,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); } /*------------------------------------------------------------------------------ @@ -376,10 +332,11 @@ int oz_pd_sleep(struct oz_pd *pd) oz_polling_unlock_bh(); return 0; } - if (pd->keep_alive && pd->session_id) { - if (pd->keep_alive >= OZ_KALIVE_INFINITE) - oz_pd_indicate_farewells(pd); + if (pd->keep_alive_j && 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; } @@ -389,7 +346,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, pd->keep_alive); + oz_timer_add(pd, OZ_TIMER_STOP, jiffies + pd->keep_alive_j, 1); } return do_stop; } @@ -398,7 +355,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); @@ -406,7 +363,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); @@ -415,21 +372,6 @@ static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd) } return f; } -/*------------------------------------------------------------------------------ - * Context: softirq or process - */ -static void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f) -{ - pd->nb_queued_isoc_frames--; - list_del_init(&f->link); - if (pd->tx_pool_count < OZ_MAX_TX_POOL_SIZE) { - f->link.next = pd->tx_pool; - pd->tx_pool = &f->link; - pd->tx_pool_count++; - } else { - kfree(f); - } -} /*------------------------------------------------------------------------------ * Context: softirq or process */ @@ -440,28 +382,12 @@ 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); if (f) kfree(f); } -/*------------------------------------------------------------------------------ - * Context: softirq-serialized - */ -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; -} -/*------------------------------------------------------------------------------ - * Context: softirq-serialized - */ -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; -} /*------------------------------------------------------------------------------ * Context: softirq */ @@ -475,9 +401,8 @@ 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 = (OZ_PROTOCOL_VERSION<last_tx_pkt_num; @@ -497,7 +422,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; @@ -506,15 +431,14 @@ 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; @@ -535,7 +459,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 @@ -562,51 +486,33 @@ static void oz_retire_frame(struct oz_pd *pd, struct oz_tx_frame *f) /*------------------------------------------------------------------------------ * Context: softirq-serialized */ -static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data) +static int oz_send_next_queued_frame(struct oz_pd *pd, int *more_data) { struct sk_buff *skb; struct oz_tx_frame *f; struct list_head *e; + *more_data = 0; spin_lock(&pd->tx_frame_lock); e = pd->last_sent_frame->next; if (e == &pd->tx_queue) { spin_unlock(&pd->tx_frame_lock); return -1; } - f = container_of(e, struct oz_tx_frame, link); - - if (f->skb != NULL) { - skb = f->skb; - oz_tx_isoc_free(pd, f); - spin_unlock(&pd->tx_frame_lock); - if (more_data) - oz_set_more_bit(skb); - 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) { - return -1; - } - atomic_inc(&g_submitted_isoc); - return 0; - } else { - kfree_skb(skb); - return -1; - } - } - pd->last_sent_frame = e; + if (e->next != &pd->tx_queue) + *more_data = 1; + f = container_of(e, struct oz_tx_frame, link); 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_trace_skb(skb, 'T'); - if (dev_queue_xmit(skb) < 0) - return -1; + 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, + 0, f->hdr.pkt_num); + if (dev_queue_xmit(skb) < 0) + return -1; + } return 0; } /*------------------------------------------------------------------------------ @@ -614,45 +520,28 @@ static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data) */ void oz_send_queued_frames(struct oz_pd *pd, int backlog) { - while (oz_prepare_frame(pd, 0) >= 0) - backlog++; - - switch (pd->mode & (OZ_F_ISOC_NO_ELTS | OZ_F_ISOC_ANYTIME)) { - - case OZ_F_ISOC_NO_ELTS: { - backlog += pd->nb_queued_isoc_frames; - if (backlog <= 0) - goto out; - if (backlog > OZ_MAX_SUBMITTED_ISOC) - backlog = OZ_MAX_SUBMITTED_ISOC; - break; - } - case OZ_NO_ELTS_ANYTIME: { - if ((backlog <= 0) && (pd->isoc_sent == 0)) - goto out; - break; - } - default: { - if (backlog <= 0) - goto out; - break; + int more; + if (backlog < OZ_MAX_QUEUED_FRAMES) { + if (oz_send_next_queued_frame(pd, &more) >= 0) { + while (more && oz_send_next_queued_frame(pd, &more)) + ; + } else { + if (((pd->mode & OZ_F_ISOC_ANYTIME) == 0) + || (pd->isoc_sent == 0)) { + if (oz_prepare_frame(pd, 1) >= 0) + oz_send_next_queued_frame(pd, &more); + } } + } else { + oz_send_next_queued_frame(pd, &more); } - while (backlog--) { - if (oz_send_next_queued_frame(pd, backlog) < 0) - break; - } - return; - -out: oz_prepare_frame(pd, 1); - oz_send_next_queued_frame(pd, 0); } /*------------------------------------------------------------------------------ * Context: softirq */ 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; @@ -666,7 +555,8 @@ 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) { + if (skb == 0) { + oz_trace("Cannot alloc skb\n"); oz_elt_info_free_chain(&pd->elt_buff, &list); return -1; } @@ -690,7 +580,7 @@ static int oz_send_isoc_frame(struct oz_pd *pd) memcpy(elt, ei->data, ei->length); elt = oz_next_elt(elt); } - oz_trace_skb(skb, 'T'); + oz_event_log(OZ_EVT_TX_ISOC, 0, 0, 0, 0); dev_queue_xmit(skb); oz_elt_info_free_chain(&pd->elt_buff, &list); return 0; @@ -702,8 +592,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; @@ -713,9 +603,9 @@ void oz_retire_tx_frames(struct oz_pd *pd, u8 lpn) f = container_of(e, struct oz_tx_frame, link); pkt_num = le32_to_cpu(get_unaligned(&f->hdr.pkt_num)); diff = (lpn - (pkt_num & OZ_LAST_PN_MASK)) & OZ_LAST_PN_MASK; - if ((diff > OZ_LAST_PN_HALF_CYCLE) || (pkt_num == 0)) + if (diff > OZ_LAST_PN_HALF_CYCLE) break; - if (first == NULL) + if (first == 0) first = e; last = e; e = e->next; @@ -724,7 +614,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); @@ -747,7 +637,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 @@ -762,7 +652,7 @@ 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); if (st) @@ -799,23 +689,25 @@ 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; @@ -828,22 +720,19 @@ 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)); skb_reset_network_header(skb); skb->dev = dev; skb->protocol = htons(OZ_ETHERTYPE); - /* For audio packet set priority to AC_VO */ - skb->priority = AC_VO; size = sizeof(struct oz_hdr) + sizeof(struct oz_isoc_large); oz_hdr = (struct oz_hdr *)skb_put(skb, size); } memcpy(skb_put(skb, len), data, len); size += len; - if ((++nb_units < pd->ms_per_isoc) - && ((pd->max_tx_size - size) > len)) { + if (++nb_units < pd->ms_per_isoc) { spin_lock_bh(&pd->stream_lock); st->skb = skb; st->nb_units = nb_units; @@ -867,52 +756,21 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len) memcpy(oz_hdr, &oz, sizeof(oz)); memcpy(oz_hdr+1, &iso, sizeof(iso)); if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, - dev->dev_addr, skb->len) < 0) - goto out; - - skb->destructor = oz_isoc_destructor; - /*Queue for Xmit if mode is not ANYTIME*/ - 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) { - 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) - goto out; - isoc_unit->hdr = oz; - isoc_unit->skb = skb; - spin_lock_bh(&pd->tx_frame_lock); - list_add_tail(&isoc_unit->link, &pd->tx_queue); - pd->nb_queued_isoc_frames++; - spin_unlock_bh(&pd->tx_frame_lock); - return 0; + dev->dev_addr, skb->len) < 0) { + kfree_skb(skb); + return -1; } - /*In ANYTIME mode Xmit unit immediately*/ if (atomic_read(&g_submitted_isoc) < OZ_MAX_SUBMITTED_ISOC) { + skb->destructor = oz_isoc_destructor; atomic_inc(&g_submitted_isoc); - oz_trace_skb(skb, 'T'); - if (dev_queue_xmit(skb) < 0) { + oz_event_log(OZ_EVT_TX_ISOC, nb_units, iso.frame_number, + skb, atomic_read(&g_submitted_isoc)); + if (dev_queue_xmit(skb) < 0) return -1; - } else - return 0; + } else { + oz_event_log(OZ_EVT_TX_ISOC_DROP, 0, 0, 0, 0); + kfree_skb(skb); } - -out: kfree_skb(skb); - return -1; - } return 0; } @@ -942,7 +800,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]; @@ -954,9 +812,19 @@ 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]; - list_for_each_entry(f, &pd->farewell_list, link) { + 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; + } + f = list_first_entry(&pd->farewell_list, + struct oz_farewell, link); + list_del(&f->link); + oz_polling_unlock_bh(); if (ai->farewell) ai->farewell(pd, f->ep_num, f->report, f->len); + kfree(f); } } diff --git a/drivers/staging/ozwpan/ozpd.h b/drivers/staging/ozwpan/ozpd.h index d75f0afa20ed..afc77f0260f0 100644 --- a/drivers/staging/ozwpan/ozpd.h +++ b/drivers/staging/ozwpan/ozpd.h @@ -6,7 +6,6 @@ #ifndef _OZPD_H_ #define _OZPD_H_ -#include #include "ozeltbuf.h" /* PD state @@ -22,7 +21,6 @@ #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. @@ -31,7 +29,6 @@ struct oz_tx_frame { struct list_head link; struct list_head elt_list; struct oz_hdr hdr; - struct sk_buff *skb; int total_size; }; @@ -49,7 +46,7 @@ struct oz_farewell { struct list_head link; u8 ep_num; u8 index; - u8 report[32]; + u8 report[1]; u8 len; }; @@ -70,22 +67,22 @@ 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; - ktime_t pulse_period; - unsigned long presleep; - unsigned long keep_alive; + 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; 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; unsigned max_stream_buffering; int nb_queued_frames; - int nb_queued_isoc_frames; struct list_head *tx_pool; int tx_pool_count; spinlock_t tx_frame_lock; @@ -95,18 +92,11 @@ 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); @@ -122,9 +112,10 @@ 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); #endif /* Sentry */ + diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c index c116e5250f6b..ad857eeabbb7 100644 --- a/drivers/staging/ozwpan/ozproto.c +++ b/drivers/staging/ozwpan/ozproto.c @@ -10,6 +10,7 @@ #include #include #include +#include "ozconfig.h" #include "ozprotocol.h" #include "ozeltbuf.h" #include "ozpd.h" @@ -17,6 +18,7 @@ #include "ozusbsvc.h" #include "oztrace.h" #include "ozappif.h" +#include "ozevent.h" #include #include #include @@ -28,32 +30,48 @@ #define OZ_DO_STOP 1 #define OZ_DO_SLEEP 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. +/* States of the timer. */ -#define OZ_IN_BUFFERING_UNITS 100 +#define OZ_TIMER_IDLE 0 +#define OZ_TIMER_SET 1 +#define OZ_TIMER_IN_HANDLER 2 + +#define OZ_MAX_TIMER_POOL_SIZE 16 /*------------------------------------------------------------------------------ */ struct oz_binding { struct packet_type ptype; char name[OZ_MAX_BINDING_LEN]; - struct list_head link; + 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 LIST_HEAD(g_binding); +static struct oz_binding *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 */ @@ -80,7 +98,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); @@ -96,8 +114,9 @@ static void oz_send_conn_rsp(struct oz_pd *pd, u8 status) return; } oz_hdr->control = (OZ_PROTOCOL_VERSION<last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK; + oz_hdr->last_pkt_num = 0; put_unaligned(0, &oz_hdr->pkt_num); + oz_event_log(OZ_EVT_CONNECT_RSP, 0, 0, 0, 0); elt->type = OZ_ELT_CONNECT_RSP; elt->length = sizeof(struct oz_elt_connect_rsp); memset(body, 0, sizeof(struct oz_elt_connect_rsp)); @@ -107,7 +126,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_skb(skb, 'T'); + oz_trace("TX: OZ_ELT_CONNECT_RSP %d", status); dev_queue_xmit(skb); return; } @@ -120,41 +139,39 @@ static void pd_set_keepalive(struct oz_pd *pd, u8 kalive) switch (kalive & OZ_KALIVE_TYPE_MASK) { case OZ_KALIVE_SPECIAL: - pd->keep_alive = (keep_alive * OZ_KALIVE_INFINITE); + pd->keep_alive_j = + oz_ms_to_jiffies(keep_alive * 1000*60*60*24*20); break; case OZ_KALIVE_SECS: - pd->keep_alive = (keep_alive*1000); + pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000); break; case OZ_KALIVE_MINS: - pd->keep_alive = (keep_alive*1000*60); + pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000*60); break; case OZ_KALIVE_HOURS: - pd->keep_alive = (keep_alive*1000*60*60); + pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000*60*60); break; default: - pd->keep_alive = 0; + pd->keep_alive_j = 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, u8 start_timer) +static void pd_set_presleep(struct oz_pd *pd, u8 presleep) { if (presleep) - pd->presleep = presleep*100; + pd->presleep_j = oz_ms_to_jiffies(presleep*100); else - 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); - } + pd->presleep_j = OZ_PRESLEEP_TOUT_J; + oz_trace("Presleep time = %lu jiffies\n", pd->presleep_j); } /*------------------------------------------------------------------------------ * 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, u32 pkt_num) + u8 *pd_addr, struct net_device *net_dev) { struct oz_pd *pd; struct oz_elt_connect_req *body = @@ -162,18 +179,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; - getnstimeofday(&pd->last_rx_timestamp); + if (pd == 0) + return 0; + pd->last_rx_time_j = jiffies; spin_lock_bh(&g_polling_lock); list_for_each(e, &g_pd_list) { pd2 = container_of(e, struct oz_pd, link); @@ -186,44 +203,33 @@ 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->mode |= OZ_F_ISOC_ANYTIME; pd->ms_per_isoc = body->ms_per_isoc; if (!pd->ms_per_isoc) pd->ms_per_isoc = 4; - - switch (body->ms_isoc_latency & OZ_LATENCY_MASK) { - case OZ_ONE_MS_LATENCY: - pd->isoc_latency = (body->ms_isoc_latency & - ~OZ_LATENCY_MASK) / pd->ms_per_isoc; - break; - case OZ_TEN_MS_LATENCY: - pd->isoc_latency = ((body->ms_isoc_latency & - ~OZ_LATENCY_MASK) * 10) / pd->ms_per_isoc; - break; - default: - pd->isoc_latency = OZ_MAX_TX_QUEUE_ISOC; - } } 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->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->timeout_time_j = jiffies + OZ_CONNECTION_TOUT_J; + pd->pulse_period_j = OZ_QUANTUM_J; + pd_set_presleep(pd, body->presleep); pd_set_keepalive(pd, body->keep_alive); new_apps &= le16_to_cpu(get_unaligned(&body->apps)); @@ -255,6 +261,9 @@ 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; @@ -268,17 +277,12 @@ done: } else { spin_unlock_bh(&g_polling_lock); } - - /* CONNECT_REQ was sent without AR bit, - but firmware does check LPN field to identify correcponding - CONNECT_RSP field. */ - pd->trigger_pkt_num = pkt_num; oz_send_conn_rsp(pd, rsp_status); if (rsp_status != OZ_STATUS_SUCCESS) { if (stop_needed) oz_pd_stop(pd); oz_pd_put(pd); - pd = NULL; + pd = 0; } if (old_net_dev) dev_put(old_net_dev); @@ -290,7 +294,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; @@ -300,7 +304,6 @@ 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); @@ -325,13 +328,17 @@ 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_trace_skb(skb, 'R'); + oz_event_log(OZ_EVT_RX_PROCESS, 0, + (((u16)oz_hdr->control)<<8)|oz_hdr->last_pkt_num, + 0, 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); mac_hdr = skb_mac_header(skb); src_addr = &mac_hdr[ETH_ALEN] ; length = skb->len; @@ -343,23 +350,18 @@ 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) { - if (!(pd->state & OZ_PD_S_CONNECTED)) - oz_pd_set_state(pd, OZ_PD_S_CONNECTED); - getnstimeofday(¤t_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; - } + pd->last_rx_time_j = jiffies; + oz_timer_add(pd, OZ_TIMER_TOUT, + pd->last_rx_time_j + pd->presleep_j, 1); if (pkt_num != pd->last_rx_pkt_num) { pd->last_rx_pkt_num = pkt_num; } else { dup = 1; + oz_trace("Duplicate frame\n"); } } @@ -374,6 +376,8 @@ static void oz_rx_frame(struct sk_buff *skb) int backlog = pd->nb_queued_frames; pd->trigger_pkt_num = pkt_num; /* Send queued frames */ + while (oz_prepare_frame(pd, 0) >= 0) + ; oz_send_queued_frames(pd, backlog); } } @@ -381,26 +385,29 @@ 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 >= oz_elt_hdr_len(elt)) { - length -= oz_elt_len(elt); + while (length >= sizeof(struct oz_elt)) { + length -= sizeof(struct oz_elt) + elt->length; if (length < 0) break; switch (elt->type) { case OZ_ELT_CONNECT_REQ: - pd = oz_connect_req(pd, elt, src_addr, skb->dev, - pkt_num); + oz_event_log(OZ_EVT_CONNECT_REQ, 0, 0, 0, 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, 1); + pd_set_presleep(pd, body->presleep); spin_unlock(&g_polling_lock); } } @@ -408,16 +415,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 *)(oz_elt_data(elt)); + (struct oz_app_hdr *)(elt+1); if (dup) break; oz_handle_app_elt(pd, app_hdr->app_id, elt); @@ -438,13 +445,14 @@ done: */ void oz_protocol_term(void) { - struct oz_binding *b, *t; - + struct list_head *chain = 0; + del_timer_sync(&g_timer); /* Walk the list of bindings and remove each one. */ spin_lock_bh(&g_binding_lock); - list_for_each_entry_safe(b, t, &g_binding, link) { - list_del(&b->link); + while (g_binding) { + struct oz_binding *b = g_binding; + g_binding = b->next; spin_unlock_bh(&g_binding_lock); dev_remove_pack(&b->ptype); if (b->ptype.dev) @@ -467,115 +475,256 @@ void oz_protocol_term(void) oz_pd_put(pd); spin_lock_bh(&g_polling_lock); } + chain = g_timer_pool; + g_timer_pool = 0; 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 */ -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) +static void oz_pd_handle_timer(struct oz_pd *pd, int type) { - 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: Interrupt + * Context: softirq */ -enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer) +static void oz_protocol_timer(unsigned long arg) { + struct oz_timer *t; + struct oz_timer *t2; struct oz_pd *pd; - - 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; + 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, 0, 0); + spin_unlock_bh(&g_polling_lock); + return; + } + g_timer_state = OZ_TIMER_IN_HANDLER; + t = g_cur_timer; + g_cur_timer = 0; + list_del(&t->link); + spin_unlock_bh(&g_polling_lock); + do { + pd = t->pd; + oz_event_log(OZ_EVT_TIMER, 0, t->type, 0, 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 = 0; + } + 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 = 0; + } else { + t2 = 0; + } + spin_unlock_bh(&g_polling_lock); + oz_pd_put(pd); + if (t) + kfree(t); + t = t2; + } while (t); + g_timer_state = OZ_TIMER_IDLE; + oz_protocol_timer_start(); } /*------------------------------------------------------------------------------ - * Context: Interrupt + * Context: softirq */ -enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer) +static void oz_protocol_timer_start(void) { - struct oz_pd *pd; - - pd = container_of(timer, struct oz_pd, timeout); - oz_pd_get(pd); - tasklet_schedule(&pd->timeout_tasklet); - return HRTIMER_NORESTART; + 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, 0, + (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, 0, + (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); } /*------------------------------------------------------------------------------ * Context: softirq or process */ -void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time) +void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time, + int remove) { - 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); + struct list_head *e; + struct oz_timer *t = 0; + int restart_needed = 0; + oz_event_log(OZ_EVT_TIMER_CTRL, 1, (u16)type, 0, (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 = 0; + } + list_del(e); + break; + } + t = 0; + } + } + 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--; } else { - hrtimer_start(&pd->timeout, ktime_set(due_time / - MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * - NSEC_PER_MSEC), HRTIMER_MODE_REL); + t = kmalloc(sizeof(struct oz_timer), GFP_ATOMIC); + } + if (t) { + t->pd = pd; + t->type = type; + oz_pd_get(pd); } - 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); + 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 = 0; + 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 = 0; + 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, 0, 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 = 0; + 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); + } } /*------------------------------------------------------------------------------ * Context: softirq or process */ void oz_pd_request_heartbeat(struct oz_pd *pd) { - oz_timer_add(pd, OZ_TIMER_HEARTBEAT, OZ_QUANTUM); + 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); } /*------------------------------------------------------------------------------ * 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; @@ -611,8 +760,9 @@ 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, 0, 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) { @@ -642,33 +792,33 @@ static int oz_pkt_recv(struct sk_buff *skb, struct net_device *dev, /*------------------------------------------------------------------------------ * Context: process */ -void oz_binding_add(const char *net_dev) +void oz_binding_add(char *net_dev) { struct oz_binding *binding; - binding = kmalloc(sizeof(struct oz_binding), GFP_KERNEL); + binding = kmalloc(sizeof(struct oz_binding), GFP_ATOMIC); if (binding) { binding->ptype.type = __constant_htons(OZ_ETHERTYPE); binding->ptype.func = oz_pkt_recv; memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN); if (net_dev && *net_dev) { - oz_trace_msg(M, "Adding binding: '%s'\n", 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) { - oz_trace_msg(M, "Netdev '%s' not found\n", - net_dev); + if (binding->ptype.dev == 0) { + oz_trace("Netdev %s not found\n", net_dev); kfree(binding); - binding = NULL; + binding = 0; } } else { - oz_trace_msg(M, "Binding to all netcards\n"); - binding->ptype.dev = NULL; + oz_trace("Binding to all netcards\n"); + binding->ptype.dev = 0; } if (binding) { dev_add_pack(&binding->ptype); spin_lock_bh(&g_binding_lock); - list_add_tail(&binding->link, &g_binding); + binding->next = g_binding; + g_binding = binding; spin_unlock_bh(&g_binding_lock); } } @@ -676,7 +826,7 @@ void oz_binding_add(const char *net_dev) /*------------------------------------------------------------------------------ * Context: process */ -static int compare_binding_name(const char *s1, const char *s2) +static int compare_binding_name(char *s1, char *s2) { int i; for (i = 0; i < OZ_MAX_BINDING_LEN; i++) { @@ -714,49 +864,34 @@ static void pd_stop_all_for_device(struct net_device *net_dev) /*------------------------------------------------------------------------------ * Context: process */ -void oz_binding_remove(const char *net_dev) +void oz_binding_remove(char *net_dev) { - struct oz_binding *binding; - int found = 0; - - oz_trace_msg(M, "Removing binding: '%s'\n", net_dev); + struct oz_binding *binding = 0; + struct oz_binding **link; + oz_trace("Removing binding: %s\n", net_dev); spin_lock_bh(&g_binding_lock); - list_for_each_entry(binding, &g_binding, link) { + binding = g_binding; + link = &g_binding; + while (binding) { if (compare_binding_name(binding->name, net_dev)) { - oz_trace_msg(M, "Binding '%s' found\n", net_dev); - found = 1; + oz_trace("Binding '%s' found\n", net_dev); + *link = binding->next; break; + } else { + link = &binding; + binding = binding->next; } } spin_unlock_bh(&g_binding_lock); - if (found) { + if (binding) { 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 */ @@ -778,7 +913,7 @@ int oz_protocol_init(char *devs) { skb_queue_head_init(&g_rx_queue); if (devs && (devs[0] == '*')) { - return -1; + oz_binding_add(0); } else { char d[32]; while (*devs) { @@ -787,6 +922,7 @@ int oz_protocol_init(char *devs) oz_binding_add(d); } } + init_timer(&g_timer); return 0; } /*------------------------------------------------------------------------------ @@ -807,32 +943,6 @@ 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) diff --git a/drivers/staging/ozwpan/ozproto.h b/drivers/staging/ozwpan/ozproto.h index 64ac30c7fb54..89aea28bd8d5 100644 --- a/drivers/staging/ozwpan/ozproto.h +++ b/drivers/staging/ozwpan/ozproto.h @@ -7,25 +7,28 @@ #define _OZPROTO_H #include +#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) (((__x)*1000)/HZ) -/* Quantum in MS */ -#define OZ_QUANTUM 8 +/* Quantum milliseconds. + */ +#define OZ_QUANTUM_MS 8 +/* Quantum jiffies + */ +#define OZ_QUANTUM_J (oz_ms_to_jiffies(OZ_QUANTUM_MS)) /* Default timeouts. */ -#define OZ_PRESLEEP_TOUT 11 +#define OZ_CONNECTION_TOUT_J (2*HZ) +#define OZ_PRESLEEP_TOUT_J (11*HZ) /* Maximun sizes of tx frames. */ -#define OZ_MAX_TX_SIZE 760 - -/* Maximum number of uncompleted isoc frames that can be pending in network. */ -#define OZ_MAX_SUBMITTED_ISOC 16 - -/* Maximum number of uncompleted isoc frames that can be pending in Tx Queue. */ -#define OZ_MAX_TX_QUEUE_ISOC 32 +#define OZ_MAX_TX_SIZE 1514 /* Application handler functions. */ @@ -53,18 +56,14 @@ 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(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); +struct oz_pd *oz_pd_find(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); 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 */ diff --git a/drivers/staging/ozwpan/ozprotocol.h b/drivers/staging/ozwpan/ozprotocol.h index 5cb989c90a58..b3e7d77f3fff 100644 --- a/drivers/staging/ozwpan/ozprotocol.h +++ b/drivers/staging/ozwpan/ozprotocol.h @@ -27,51 +27,17 @@ struct oz_elt { u8 length; } PACKED; -/* 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)) - +#define oz_next_elt(__elt) \ + (struct oz_elt *)((u8 *)((__elt) + 1) + (__elt)->length) /* 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. @@ -99,10 +65,6 @@ struct oz_hdr { #define OZ_LAST_PN_HALF_CYCLE 127 -#define OZ_LATENCY_MASK 0xc0 -#define OZ_ONE_MS_LATENCY 0x40 -#define OZ_TEN_MS_LATENCY 0x80 - /* Connect request data structure. */ struct oz_elt_connect_req { @@ -111,14 +73,13 @@ struct oz_elt_connect_req { u8 pd_info; u8 session_id; u8 presleep; - u8 ms_isoc_latency; + u8 resv2; u8 host_vendor; u8 keep_alive; u16 apps; u8 max_len_div16; u8 ms_per_isoc; - u8 up_audio_buf; - u8 ms_per_elt; + u8 resv3[2]; } PACKED; /* mode field bits. @@ -128,7 +89,6 @@ struct oz_elt_connect_req { #define OZ_MODE_MASK 0xf #define OZ_F_ISOC_NO_ELTS 0x40 #define OZ_F_ISOC_ANYTIME 0x80 -#define OZ_NO_ELTS_ANYTIME 0xc0 /* Keep alive field. */ @@ -139,8 +99,6 @@ struct oz_elt_connect_req { #define OZ_KALIVE_MINS 0x80 #define OZ_KALIVE_HOURS 0xc0 -#define OZ_KALIVE_INFINITE (1000*60*60*24*20) - /* Connect response data structure. */ struct oz_elt_connect_rsp { @@ -179,10 +137,7 @@ struct oz_app_hdr { #define OZ_APPID_UNUSED1 0x2 #define OZ_APPID_UNUSED2 0x3 #define OZ_APPID_SERIAL 0x4 -#define OZ_APPID_UNUSED3 0x5 -#define OZ_APPID_UNUSED4 0x6 -#define OZ_APPID_TFTP 0x7 -#define OZ_APPID_MAX OZ_APPID_TFTP +#define OZ_APPID_MAX OZ_APPID_SERIAL #define OZ_NB_APPS (OZ_APPID_MAX+1) /* USB header common to all elements for the USB application. diff --git a/drivers/staging/ozwpan/oztrace.c b/drivers/staging/ozwpan/oztrace.c index 4503c5dfa091..353ead24fd7d 100644 --- a/drivers/staging/ozwpan/oztrace.c +++ b/drivers/staging/ozwpan/oztrace.c @@ -3,157 +3,34 @@ * Released under the GNU General Public License Version 2 (GPLv2). * ----------------------------------------------------------------------------- */ +#include "ozconfig.h" #include "oztrace.h" -#define CREATE_TRACE_POINTS -#include "ozeventtrace.h" -#define OZ_TRACE_DUMP_SKB_LEN_MAX 32 -#define OZ_TRACE_DUMP_URB_LEN_MAX 16 +#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 */ -u32 g_debug = -#ifdef WANT_TRACE_DATA_FLOW - TRC_FLG(M)|TRC_FLG(R)|TRC_FLG(T)| - TRC_FLG(S)|TRC_FLG(E)|TRC_FLG(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); -} diff --git a/drivers/staging/ozwpan/oztrace.h b/drivers/staging/ozwpan/oztrace.h index ab1d5cb96c1c..8293b24c5a77 100644 --- a/drivers/staging/ozwpan/oztrace.h +++ b/drivers/staging/ozwpan/oztrace.h @@ -5,95 +5,31 @@ */ #ifndef _OZTRACE_H_ #define _OZTRACE_H_ -#include -#include -#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 'A' -#define TRC_B 'B' -#define TRC_C 'C' /* urb Completion */ -#define TRC_D 'D' /* Debug */ -#define TRC_E 'E' /* urb Error */ -#define TRC_F 'F' -#define TRC_G 'G' -#define TRC_H 'H' /* Hcd message */ -#define TRC_I 'I' /* Isoc buffer depth */ -#define TRC_J 'J' -#define TRC_K 'K' -#define TRC_L 'L' -#define TRC_M 'M' /* Message */ -#define TRC_N 'N' -#define TRC_O 'O' -#define TRC_P 'P' -#define TRC_Q 'Q' -#define TRC_R 'R' /* Rx Ozmo frame */ -#define TRC_S 'S' /* urb Submission */ -#define TRC_T 'T' /* Tx ozmo frame */ -#define TRC_U 'U' -#define TRC_V 'V' -#define TRC_W 'W' -#define TRC_X 'X' -#define TRC_Y 'Y' -#define TRC_Z 'Z' - -#define TRC_FLG(f) (1<<((TRC_##f)-'A')) - -#define oz_trace_urb_out(u, s) \ - do { if (!g_debug) \ - trace_urb_out(u, s); \ - else if ((g_debug & TRC_FLG(C)) ||\ - ((g_debug & TRC_FLG(E)) && (s != 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_FLG(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_FLG(T))) || \ - (('R' == d) && (g_debug & TRC_FLG(R)))) \ - oz_trace_f_skb(u, d); } while(0) - -#define oz_trace_msg(f, ...) \ - do { if (!g_debug) \ - trace_debug_log(TRC_##f, __VA_ARGS__); \ - else if (g_debug & TRC_FLG(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__) +#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 #endif /* Sentry */ diff --git a/drivers/staging/ozwpan/ozurbparanoia.c b/drivers/staging/ozwpan/ozurbparanoia.c index b05519534444..55b9afbbe47b 100644 --- a/drivers/staging/ozwpan/ozurbparanoia.c +++ b/drivers/staging/ozwpan/ozurbparanoia.c @@ -4,6 +4,7 @@ * ----------------------------------------------------------------------------- */ #include +#include "ozconfig.h" #ifdef WANT_URB_PARANOIA #include "ozurbparanoia.h" #include "oztrace.h" @@ -21,7 +22,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("urb up = %d %p\n", g_nb_urbs, urb); + oz_trace("%lu: urb up = %d %p\n", jiffies, g_nb_urbs, urb); } else { oz_trace("ERROR urb buffer full\n"); } @@ -41,8 +42,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("urb down = %d %p\n", - g_nb_urbs, urb); + oz_trace("%lu: urb down = %d %p\n", + jiffies, g_nb_urbs, urb); } } spin_unlock_irqrestore(&g_urb_mem_lock, irq_state); diff --git a/drivers/staging/ozwpan/ozusbif.h b/drivers/staging/ozwpan/ozusbif.h index b1d58e16992a..3acf5980d7cc 100644 --- a/drivers/staging/ozwpan/ozusbif.h +++ b/drivers/staging/ozwpan/ozusbif.h @@ -13,10 +13,6 @@ void oz_usb_get(void *hpd); void oz_usb_put(void *hpd); -/* Reset device. -*/ -void oz_usb_reset_device(void *hpd); - /* Stream functions. */ int oz_usb_stream_create(void *hpd, u8 ep_num); @@ -25,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); @@ -34,20 +30,14 @@ 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); - -void oz_hcd_mark_urb_submitted(void *hport, int ep_ix, u8 req_id); + u8 *data, int data_len); /* 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 */ diff --git a/drivers/staging/ozwpan/ozusbsvc.c b/drivers/staging/ozwpan/ozusbsvc.c index c763c089ebc9..9e74f9602384 100644 --- a/drivers/staging/ozwpan/ozusbsvc.c +++ b/drivers/staging/ozwpan/ozusbsvc.c @@ -7,7 +7,7 @@ * The implementation of this service is split into two parts the first of which * is protocol independent and the second contains protocol specific details. * This split is to allow alternative protocols to be defined. - * The implementation of this service uses ozhcd.c to implement a USB HCD. + * The implemenation of this service uses ozhcd.c to implement a USB HCD. * ----------------------------------------------------------------------------- */ #include @@ -18,6 +18,7 @@ #include #include #include +#include "ozconfig.h" #include "ozprotocol.h" #include "ozeltbuf.h" #include "ozpd.h" @@ -26,12 +27,14 @@ #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, 0, 0); return oz_hcd_init(); } /*------------------------------------------------------------------------------ @@ -40,24 +43,9 @@ int oz_usb_init(void) */ void oz_usb_term(void) { + oz_event_log(OZ_EVT_SERVICE, 2, OZ_APPID_USB, 0, 0); oz_hcd_term(); } -/*------------------------------------------------------------------------------ - * This is called when HCD received FEAT_RESET request from hub. - * If PD is in sleep, it then removes PD as it is unable to respond any host - * action. - */ -void oz_usb_reset_device(void *hpd) -{ - struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; - struct oz_pd *pd = usb_ctx->pd; - oz_pd_get(pd); - if (pd && (!(pd->state & OZ_PD_S_CONNECTED))) { - oz_trace_msg(M, "Remove device\n"); - oz_pd_stop(pd); - } - oz_pd_put(pd); -} /*------------------------------------------------------------------------------ * This is called when the USB service is started or resumed for a PD. * Context: softirq @@ -66,7 +54,8 @@ 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; + struct oz_usb_ctx *old_ctx = 0; + oz_event_log(OZ_EVT_SERVICE, 3, OZ_APPID_USB, 0, resume); if (resume) { oz_trace("USB service resumed.\n"); return 0; @@ -76,7 +65,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; @@ -87,11 +76,12 @@ 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) { @@ -108,9 +98,10 @@ 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) { + if (usb_ctx->hport == 0) { + oz_trace("USB hub returned null port.\n"); 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; @@ -126,17 +117,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, 0, 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) { - struct timespec ts, now; - getnstimeofday(&ts); + unsigned long tout = jiffies + HZ; oz_trace("USB service stopping...\n"); usb_ctx->stopped = 1; /* At this point the reference count on the usb context should @@ -145,13 +136,10 @@ 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)) { - 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"); + while ((atomic_read(&usb_ctx->ref_count) > 2) && + time_before(jiffies, tout)) + ; + oz_trace("USB service stopped.\n"); oz_hcd_pd_departed(usb_ctx->hport); /* Release the reference taken in oz_usb_start. */ @@ -177,6 +165,7 @@ 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); } @@ -193,7 +182,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; @@ -211,6 +200,7 @@ 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 { @@ -232,6 +222,7 @@ 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 { diff --git a/drivers/staging/ozwpan/ozusbsvc1.c b/drivers/staging/ozwpan/ozusbsvc1.c index 609d7119051a..66bd576bb5e9 100644 --- a/drivers/staging/ozwpan/ozusbsvc1.c +++ b/drivers/staging/ozwpan/ozusbsvc1.c @@ -13,6 +13,7 @@ #include #include #include +#include "ozconfig.h" #include "ozprotocol.h" #include "ozeltbuf.h" #include "ozpd.h" @@ -21,24 +22,10 @@ #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 */ @@ -76,12 +63,16 @@ 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 == 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); @@ -108,8 +99,6 @@ static int oz_usb_set_config_req(void *hpd, u8 req_id, u8 index) struct oz_set_config_req *body; 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); @@ -131,8 +120,6 @@ static int oz_usb_set_interface_req(void *hpd, u8 req_id, u8 index, u8 alt) struct oz_set_interface_req *body; 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); @@ -157,8 +144,6 @@ static int oz_usb_set_clear_feature_req(void *hpd, u8 req_id, u8 type, 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; @@ -172,7 +157,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; @@ -182,8 +167,6 @@ static int oz_usb_vendor_class_req(void *hpd, u8 req_id, u8 req_type, struct oz_vendor_class_req *body; 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); @@ -201,13 +184,16 @@ 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: @@ -259,14 +245,10 @@ int oz_usb_send_isoc(void *hpd, u8 ep_num, struct urb *urb) struct usb_iso_packet_descriptor *desc; if (pd->mode & OZ_F_ISOC_NO_ELTS) { - urb->actual_length = 0; for (i = 0; i < urb->number_of_packets; i++) { u8 *data; desc = &urb->iso_frame_desc[i]; data = ((u8 *)urb->transfer_buffer)+desc->offset; - desc->status = 0; - desc->actual_length = desc->length; - urb->actual_length += desc->length; oz_send_isoc_unit(pd, ep_num, data, desc->length); } return 0; @@ -387,9 +369,7 @@ void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt) if (usb_hdr->elt_seq_num != 0) { if (((usb_ctx->rx_seq_num - usb_hdr->elt_seq_num) & 0x80) == 0) /* Reject duplicate element. */ - oz_trace_msg(M, "USB seq overlap %02X %02X\n", - usb_ctx->rx_seq_num, - usb_hdr->elt_seq_num); + goto done; } usb_ctx->rx_seq_num = usb_hdr->elt_seq_num; switch (usb_hdr->type) { @@ -401,6 +381,7 @@ 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); @@ -454,11 +435,3 @@ 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; -} -- cgit v1.2.3