summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Poynter <tpoynter@nvidia.com>2013-10-28 13:40:01 -0500
committerHarshada Kale <hkale@nvidia.com>2013-11-06 02:55:27 -0800
commit2d4cd9f05640c44bf87342525e5352899aca42e1 (patch)
tree6fa6e7ac468d08a5fc987c35293ffb2c96299cc4
parentf9dede308e2f85da438b2ca39a888077f29c25e4 (diff)
staging: ozwpan: Update to latest drop from ATMEL.
Update the ozwpan driver to the latest drop from ATMEL. Bug 1394137. Change-Id: I9069c974cb665a8be68d43536f57c3b717b570a6 Signed-off-by: Todd Poynter <tpoynter@nvidia.com> Reviewed-on: http://git-master/r/304456 GVS: Gerrit_Virtual_Submit Reviewed-by: Mitch Luban <mluban@nvidia.com> Reviewed-by: Toby Butzon <tbutzon@nvidia.com>
-rw-r--r--drivers/staging/ozwpan/Kbuild2
-rw-r--r--drivers/staging/ozwpan/ozappif.h20
-rw-r--r--drivers/staging/ozwpan/ozcdev.c336
-rw-r--r--drivers/staging/ozwpan/ozcdev.h3
-rw-r--r--drivers/staging/ozwpan/ozconfig.h27
-rw-r--r--drivers/staging/ozwpan/ozeltbuf.c21
-rw-r--r--drivers/staging/ozwpan/ozeltbuf.h5
-rw-r--r--drivers/staging/ozwpan/ozevent.c116
-rw-r--r--drivers/staging/ozwpan/ozevent.h31
-rw-r--r--drivers/staging/ozwpan/ozeventdef.h47
-rw-r--r--drivers/staging/ozwpan/ozeventtrace.h219
-rw-r--r--drivers/staging/ozwpan/ozhcd.c698
-rw-r--r--drivers/staging/ozwpan/ozkobject.c304
-rw-r--r--drivers/staging/ozwpan/ozkobject.h17
-rw-r--r--drivers/staging/ozwpan/ozmain.c7
-rw-r--r--drivers/staging/ozwpan/ozpd.c319
-rw-r--r--drivers/staging/ozwpan/ozpd.h27
-rw-r--r--drivers/staging/ozwpan/ozproto.c483
-rw-r--r--drivers/staging/ozwpan/ozproto.h37
-rw-r--r--drivers/staging/ozwpan/ozprotocol.h53
-rw-r--r--drivers/staging/ozwpan/oztrace.c178
-rw-r--r--drivers/staging/ozwpan/oztrace.h112
-rw-r--r--drivers/staging/ozwpan/ozurbparanoia.c7
-rw-r--r--drivers/staging/ozwpan/ozusbif.h6
-rw-r--r--drivers/staging/ozwpan/ozusbsvc.c27
-rw-r--r--drivers/staging/ozwpan/ozusbsvc1.c47
26 files changed, 1996 insertions, 1153 deletions
diff --git a/drivers/staging/ozwpan/Kbuild b/drivers/staging/ozwpan/Kbuild
index 6cc84cb3f0a6..08bc7938692d 100644
--- a/drivers/staging/ozwpan/Kbuild
+++ b/drivers/staging/ozwpan/Kbuild
@@ -14,6 +14,6 @@ ozwpan-y := \
ozcdev.o \
ozurbparanoia.o \
oztrace.o \
- ozevent.o
+ ozkobject.o
diff --git a/drivers/staging/ozwpan/ozappif.h b/drivers/staging/ozwpan/ozappif.h
index af0273293872..ea1b271fdcda 100644
--- a/drivers/staging/ozwpan/ozappif.h
+++ b/drivers/staging/ozwpan/ozappif.h
@@ -6,18 +6,16 @@
#ifndef _OZAPPIF_H
#define _OZAPPIF_H
-#include "ozeventdef.h"
-
#define OZ_IOCTL_MAGIC 0xf4
struct oz_mac_addr {
- unsigned char a[6];
+ __u8 a[6];
};
#define OZ_MAX_PDS 8
struct oz_pd_list {
- int count;
+ __u32 count;
struct oz_mac_addr addr[OZ_MAX_PDS];
};
@@ -27,20 +25,12 @@ 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_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
+#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
#endif /* _OZAPPIF_H */
diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c
index 1c380d687963..f3238229b5b3 100644
--- a/drivers/staging/ozwpan/ozcdev.c
+++ b/drivers/staging/ozwpan/ozcdev.c
@@ -10,17 +10,19 @@
#include <linux/netdevice.h>
#include <linux/poll.h>
#include <linux/sched.h>
-#include "ozconfig.h"
#include "ozprotocol.h"
#include "oztrace.h"
#include "ozappif.h"
#include "ozeltbuf.h"
#include "ozpd.h"
#include "ozproto.h"
-#include "ozevent.h"
+#include "ozkobject.h"
/*------------------------------------------------------------------------------
*/
#define OZ_RD_BUF_SZ 256
+#define OZ_MODE_TFTP 0x1
+#define OZ_MODE_SERIAL 0x0
+
struct oz_cdev {
dev_t devnum;
struct cdev cdev;
@@ -28,6 +30,8 @@ struct oz_cdev {
spinlock_t lock;
u8 active_addr[ETH_ALEN];
struct oz_pd *active_pd;
+ atomic_t ref_count;
+ u8 mode;
};
/* Per PD context for the serial service stored in the PD. */
@@ -35,16 +39,34 @@ struct oz_serial_ctx {
atomic_t ref_count;
u8 tx_seq_num;
u8 rx_seq_num;
+ u8 tx_done_seq_num;
+ u8 padding;
u8 rd_buf[OZ_RD_BUF_SZ];
int rd_in;
int rd_out;
+ spinlock_t rd_lock;
+ int dg_len[OZ_RD_BUF_SZ/4];
+ int dg_in;
+ int dg_out;
};
/*------------------------------------------------------------------------------
*/
-int g_taction;
+static struct oz_cdev g_cdev;
+struct class *g_oz_class;
+struct device *g_oz_wpan_dev;
/*------------------------------------------------------------------------------
+ * Context: softirq
*/
-static struct oz_cdev g_cdev;
+
+static void oz_cdev_elt_completion_callback(struct oz_pd *pd, long context)
+{
+ struct oz_serial_ctx *ctx;
+ spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
+ ctx = (struct oz_serial_ctx *)pd->app_ctx[OZ_APPID_SERIAL-1];
+ if (ctx)
+ ctx->tx_done_seq_num = (u8)context;
+ spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
+}
/*------------------------------------------------------------------------------
* Context: process and softirq
*/
@@ -63,7 +85,7 @@ static struct oz_serial_ctx *oz_cdev_claim_ctx(struct oz_pd *pd)
*/
static void oz_cdev_release_ctx(struct oz_serial_ctx *ctx)
{
- if (atomic_dec_and_test(&ctx->ref_count)) {
+ if (ctx && atomic_dec_and_test(&ctx->ref_count)) {
oz_trace("Dealloc serial context.\n");
kfree(ctx);
}
@@ -74,8 +96,10 @@ 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;
- oz_trace("oz_cdev_open()\n");
- oz_trace("major = %d minor = %d\n", imajor(inode), iminor(inode));
+
+ if (!atomic_add_unless(&g_cdev.ref_count, 1, 1))
+ return -EBUSY;
+
dev = container_of(inode->i_cdev, struct oz_cdev, cdev);
filp->private_data = dev;
return 0;
@@ -85,7 +109,7 @@ int oz_cdev_open(struct inode *inode, struct file *filp)
*/
int oz_cdev_release(struct inode *inode, struct file *filp)
{
- oz_trace("oz_cdev_release()\n");
+ atomic_dec(&g_cdev.ref_count);
return 0;
}
/*------------------------------------------------------------------------------
@@ -96,7 +120,7 @@ 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 = 0;
@@ -104,36 +128,93 @@ ssize_t oz_cdev_read(struct file *filp, char __user *buf, size_t count,
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 == 0)
return -1;
ctx = oz_cdev_claim_ctx(pd);
if (ctx == 0)
goto out2;
- n = ctx->rd_in - ctx->rd_out;
- if (n < 0)
- n += OZ_RD_BUF_SZ;
- if (count > n)
+
+ spin_lock_bh(&ctx->rd_lock);
+
+ if (is_tftp) {
+ /* if n is non zero we have a datagram */
+ n = ctx->dg_len[ctx->dg_out];
+
+ if (n == 0) {
+ count = 0;
+ spin_unlock_bh(&ctx->rd_lock);
+ goto out1;
+ }
+
+ ix = ctx->rd_out;
+ spin_unlock_bh(&ctx->rd_lock);
+
+ /* copy n bytes of datagram to user bufer */
+ if ((ix + n) < OZ_RD_BUF_SZ) {
+ if (copy_to_user(buf, &ctx->rd_buf[ix], n)) {
+ count = 0;
+ goto out1;
+ }
+ spin_lock_bh(&ctx->rd_lock);
+ ctx->rd_out += n;
+ } else {
+ int b = (OZ_RD_BUF_SZ - ix);
+ /* datagram maybe split in between the end and start of
+ * the buffer */
+ if (copy_to_user(buf, &ctx->rd_buf[ix], b)) {
+ count = 0;
+ goto out1;
+ }
+ if (copy_to_user(&buf[b], ctx->rd_buf, n - b)) {
+ count = 0;
+ goto out1;
+ }
+ spin_lock_bh(&ctx->rd_lock);
+ ctx->rd_out = n - (OZ_RD_BUF_SZ - ix);
+ }
+
count = n;
- ix = ctx->rd_out;
- n = OZ_RD_BUF_SZ - ix;
- if (n > count)
- n = count;
- if (copy_to_user(buf, &ctx->rd_buf[ix], n)) {
- count = 0;
- goto out1;
- }
- ix += n;
- if (ix == OZ_RD_BUF_SZ)
- ix = 0;
- if (n < count) {
- if (copy_to_user(&buf[n], ctx->rd_buf, count-n)) {
+
+ ctx->dg_len[ctx->dg_out] = 0;
+ ctx->dg_out++;
+ if ((OZ_RD_BUF_SZ/4) == ctx->dg_out)
+ ctx->dg_out = 0;
+ spin_unlock_bh(&ctx->rd_lock);
+ } else {
+ n = ctx->rd_in - ctx->rd_out;
+ if (n < 0)
+ n += OZ_RD_BUF_SZ;
+ if (count > n)
+ count = n;
+
+ ix = ctx->rd_out;
+ spin_unlock_bh(&ctx->rd_lock);
+ n = OZ_RD_BUF_SZ - ix;
+ if (n > count)
+ n = count;
+
+ if (copy_to_user(buf, &ctx->rd_buf[ix], n)) {
count = 0;
goto out1;
}
- ix = count-n;
+
+ ix += n;
+ if (ix == OZ_RD_BUF_SZ)
+ ix = 0;
+ if (n < count) {
+ if (copy_to_user(&buf[n], ctx->rd_buf, count-n)) {
+ count = 0;
+ goto out1;
+ }
+ ix = count-n;
+ }
+
+ spin_lock_bh(&ctx->rd_lock);
+ ctx->rd_out = ix;
+ spin_unlock_bh(&ctx->rd_lock);
}
- ctx->rd_out = ix;
out1:
oz_cdev_release_ctx(ctx);
out2:
@@ -150,6 +231,7 @@ ssize_t oz_cdev_write(struct file *filp, const char __user *buf, size_t count,
struct oz_elt_buf *eb;
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;
@@ -160,33 +242,52 @@ ssize_t oz_cdev_write(struct file *filp, const char __user *buf, size_t count,
spin_unlock_bh(&g_cdev.lock);
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 == 0) {
count = 0;
goto out;
}
- elt = (struct oz_elt *)ei->data;
- app_hdr = (struct oz_app_hdr *)(elt+1);
- elt->length = sizeof(struct oz_app_hdr) + count;
- elt->type = OZ_ELT_APP_DATA;
- ei->app_id = OZ_APPID_SERIAL;
- ei->length = elt->length + sizeof(struct oz_elt);
- app_hdr->app_id = OZ_APPID_SERIAL;
+ spin_lock_bh(&g_cdev.lock);
+ if (g_cdev.mode & OZ_MODE_TFTP) {
+ spin_unlock_bh(&g_cdev.lock);
+ ei->app_id = OZ_APPID_SERIAL;
+ ei->flags |= OZ_EI_F_EXT_ELM;
+ ext_elt = (struct oz_ext_elt *)ei->data;
+ app_hdr = (struct oz_app_hdr *)(ext_elt+1);
+ app_hdr->app_id = OZ_APPID_TFTP;
+ ext_elt->length = sizeof(struct oz_app_hdr) + count;
+ ext_elt->type = OZ_ELT_APP_DATA_EX;
+ ei->length = ext_elt->length + sizeof(struct oz_ext_elt);
+ ext_elt->length = cpu_to_le16(ext_elt->length);
+ } else {
+ spin_unlock_bh(&g_cdev.lock);
+ ei->app_id = OZ_APPID_SERIAL;
+ elt = (struct oz_elt *)ei->data;
+ app_hdr = (struct oz_app_hdr *)(elt+1);
+ app_hdr->app_id = OZ_APPID_SERIAL;
+ elt->length = sizeof(struct oz_app_hdr) + count;
+ elt->type = OZ_ELT_APP_DATA;
+ ei->length = elt->length + sizeof(struct oz_elt);
+ }
if (copy_from_user(app_hdr+1, buf, count))
goto out;
- spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]);
+ spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
ctx = (struct oz_serial_ctx *)pd->app_ctx[OZ_APPID_SERIAL-1];
if (ctx) {
app_hdr->elt_seq_num = ctx->tx_seq_num++;
if (ctx->tx_seq_num == 0)
ctx->tx_seq_num = 1;
+ ei->callback = oz_cdev_elt_completion_callback;
+ ei->context = ctx->tx_seq_num;
spin_lock(&eb->lock);
if (oz_queue_elt_info(eb, 0, 0, ei) == 0)
ei = 0;
spin_unlock(&eb->lock);
}
- spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
+ spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
out:
if (ei) {
count = 0;
@@ -200,22 +301,40 @@ out:
/*------------------------------------------------------------------------------
* Context: process
*/
-static int oz_set_active_pd(u8 *addr)
+int oz_set_active_pd(u8 *addr)
{
int rc = 0;
struct oz_pd *pd;
struct oz_pd *old_pd;
+ struct oz_serial_ctx *ctx;
pd = oz_pd_find(addr);
if (pd) {
spin_lock_bh(&g_cdev.lock);
+ if (memcmp(g_cdev.active_addr, addr, ETH_ALEN) == 0) {
+ spin_unlock_bh(&g_cdev.lock);
+ return rc;
+ }
memcpy(g_cdev.active_addr, addr, ETH_ALEN);
old_pd = g_cdev.active_pd;
g_cdev.active_pd = pd;
spin_unlock_bh(&g_cdev.lock);
+
+ /*Reset buffer pointers if new device is selected*/
+ ctx = oz_cdev_claim_ctx(pd);
+ if (ctx != NULL) {
+ spin_lock_bh(&ctx->rd_lock);
+ ctx->dg_in = 0;
+ ctx->dg_out = 0;
+ ctx->dg_len[0] = 0;
+ ctx->rd_out = 0;
+ ctx->rd_in = 0;
+ spin_unlock_bh(&ctx->rd_lock);
+ }
+
if (old_pd)
oz_pd_put(old_pd);
} else {
- if (!memcmp(addr, "\0\0\0\0\0\0", sizeof(addr))) {
+ if (!memcmp(addr, "\0\0\0\0\0\0", ETH_ALEN)) {
spin_lock_bh(&g_cdev.lock);
pd = g_cdev.active_pd;
g_cdev.active_pd = 0;
@@ -233,6 +352,52 @@ static int oz_set_active_pd(u8 *addr)
/*------------------------------------------------------------------------------
* 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
+ */
long oz_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int rc = 0;
@@ -251,7 +416,6 @@ 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;
- 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)))
@@ -260,7 +424,6 @@ 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);
@@ -268,7 +431,6 @@ 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);
@@ -276,20 +438,6 @@ 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;
@@ -315,17 +463,23 @@ unsigned int oz_cdev_poll(struct file *filp, poll_table *wait)
{
unsigned int ret = 0;
struct oz_cdev *dev = filp->private_data;
- oz_trace("Poll called wait = %p\n", wait);
spin_lock_bh(&dev->lock);
if (dev->active_pd) {
struct oz_serial_ctx *ctx = oz_cdev_claim_ctx(dev->active_pd);
+ spin_unlock_bh(&dev->lock);
if (ctx) {
+ spin_lock_bh(&ctx->rd_lock);
if (ctx->rd_in != ctx->rd_out)
ret |= POLLIN | POLLRDNORM;
+
+ if (ctx->tx_seq_num == ctx->tx_done_seq_num)
+ ret |= POLLOUT;
+ spin_unlock_bh(&ctx->rd_lock);
oz_cdev_release_ctx(ctx);
}
- }
- spin_unlock_bh(&dev->lock);
+ } else
+ spin_unlock_bh(&dev->lock);
+
if (wait)
poll_wait(filp, &dev->rdq, wait);
return ret;
@@ -350,16 +504,36 @@ 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)
- return err;
- oz_trace("Alloc dev number %d:%d\n", MAJOR(g_cdev.devnum),
- MINOR(g_cdev.devnum));
+ goto out3;
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");
+ 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");
+ 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
@@ -368,6 +542,11 @@ 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;
}
/*------------------------------------------------------------------------------
@@ -375,7 +554,6 @@ 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;
}
@@ -384,7 +562,6 @@ 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);
}
/*------------------------------------------------------------------------------
@@ -394,7 +571,6 @@ int oz_cdev_start(struct oz_pd *pd, int resume)
{
struct oz_serial_ctx *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;
@@ -404,6 +580,7 @@ int oz_cdev_start(struct oz_pd *pd, int resume)
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) {
@@ -418,7 +595,6 @@ int oz_cdev_start(struct oz_pd *pd, int resume)
(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");
@@ -430,7 +606,6 @@ 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;
@@ -449,7 +624,6 @@ void oz_cdev_stop(struct oz_pd *pd, int pause)
spin_unlock(&g_cdev.lock);
if (pd) {
oz_pd_put(pd);
- oz_trace("Active PD departed.\n");
}
oz_trace("Serial service stopped.\n");
}
@@ -465,6 +639,11 @@ 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 == 0) {
@@ -472,7 +651,7 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt)
return;
}
- app_hdr = (struct oz_app_hdr *)(elt+1);
+ app_hdr = (struct oz_app_hdr *)(oz_elt_data(elt));
/* If sequence number is non-zero then check it is not a duplicate.
*/
if (app_hdr->elt_seq_num != 0) {
@@ -484,10 +663,11 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt)
}
}
ctx->rx_seq_num = app_hdr->elt_seq_num;
- len = elt->length - sizeof(struct oz_app_hdr);
- data = ((u8 *)(elt+1)) + sizeof(struct oz_app_hdr);
+ len = oz_elt_data_len(elt) - sizeof(struct oz_app_hdr);
+ data = ((u8 *)(app_hdr + 1));
if (len <= 0)
goto out;
+ spin_lock_bh(&ctx->rd_lock);
space = ctx->rd_out - ctx->rd_in - 1;
if (space < 0)
space += OZ_RD_BUF_SZ;
@@ -495,6 +675,19 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt)
oz_trace("Not enough space:%d %d\n", len, space);
len = space;
}
+
+
+ if (is_tftp) {
+ if (len != 0) {
+ /* remember length of datagram */
+ ctx->dg_len[ctx->dg_in] = len;
+
+ ctx->dg_in++;
+ if ((OZ_RD_BUF_SZ/4) == ctx->dg_in)
+ ctx->dg_in = 0;
+ }
+ }
+
ix = ctx->rd_in;
copy_sz = OZ_RD_BUF_SZ - ix;
if (copy_sz > len)
@@ -509,6 +702,7 @@ 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 698014bb8d72..0e4071782448 100644
--- a/drivers/staging/ozwpan/ozcdev.h
+++ b/drivers/staging/ozwpan/ozcdev.h
@@ -6,6 +6,7 @@
#ifndef _OZCDEV_H
#define _OZCDEV_H
+extern struct device *g_oz_wpan_dev;
int oz_cdev_register(void);
int oz_cdev_deregister(void);
int oz_cdev_init(void);
@@ -14,5 +15,7 @@ int oz_cdev_start(struct oz_pd *pd, int resume);
void oz_cdev_stop(struct oz_pd *pd, int pause);
void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt);
void oz_cdev_heartbeat(struct oz_pd *pd);
+int oz_set_active_pd(u8 *addr);
+void oz_get_active_pd(u8 *addr);
#endif /* _OZCDEV_H */
diff --git a/drivers/staging/ozwpan/ozconfig.h b/drivers/staging/ozwpan/ozconfig.h
deleted file mode 100644
index 43e6373a009c..000000000000
--- a/drivers/staging/ozwpan/ozconfig.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * ---------------------------------------------------------------------------*/
-#ifndef _OZCONFIG_H
-#define _OZCONFIG_H
-
-/* #define WANT_TRACE */
-#ifdef WANT_TRACE
-#define WANT_VERBOSE_TRACE
-#endif /* #ifdef WANT_TRACE */
-/* #define WANT_URB_PARANOIA */
-
-/* #define WANT_PRE_2_6_39 */
-#define WANT_EVENT_TRACE
-
-/* These defines determine what verbose trace is displayed. */
-#ifdef WANT_VERBOSE_TRACE
-/* #define WANT_TRACE_STREAM */
-/* #define WANT_TRACE_URB */
-/* #define WANT_TRACE_CTRL_DETAIL */
-#define WANT_TRACE_HUB
-/* #define WANT_TRACE_RX_FRAMES */
-/* #define WANT_TRACE_TX_FRAMES */
-#endif /* WANT_VERBOSE_TRACE */
-
-#endif /* _OZCONFIG_H */
diff --git a/drivers/staging/ozwpan/ozeltbuf.c b/drivers/staging/ozwpan/ozeltbuf.c
index 988f522475d9..e86f28b8dfa5 100644
--- a/drivers/staging/ozwpan/ozeltbuf.c
+++ b/drivers/staging/ozwpan/ozeltbuf.c
@@ -6,7 +6,6 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/netdevice.h>
-#include "ozconfig.h"
#include "ozprotocol.h"
#include "ozeltbuf.h"
#include "ozpd.h"
@@ -132,8 +131,6 @@ 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 == 0)
return -ENOMEM;
@@ -152,7 +149,7 @@ int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id)
{
struct list_head *e;
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) {
@@ -175,9 +172,6 @@ int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id)
list_del_init(&ei->link);
list_del_init(&ei->link_order);
st->buf_count -= ei->length;
- oz_trace2(OZ_TRACE_STREAM, "Stream down: %d %d %d\n",
- st->buf_count,
- ei->length, atomic_read(&st->ref_count));
oz_elt_stream_put(st);
oz_elt_info_free(buf, ei);
}
@@ -242,8 +236,6 @@ int oz_queue_elt_info(struct oz_elt_buf *buf, u8 isoc, u8 id,
st->buf_count += ei->length;
/* Add to list in stream. */
list_add_tail(&ei->link, &st->elt_list);
- oz_trace2(OZ_TRACE_STREAM, "Stream up: %d %d\n",
- st->buf_count, ei->length);
/* Check if we have too much buffered for this stream. If so
* start dropping elements until we are back in bounds.
*/
@@ -283,8 +275,12 @@ int oz_select_elts_for_tx(struct oz_elt_buf *buf, u8 isoc, unsigned *len,
ei = container_of(e, struct oz_elt_info, link_order);
e = e->next;
if ((*len + ei->length) <= max_len) {
- app_hdr = (struct oz_app_hdr *)
- &ei->data[sizeof(struct oz_elt)];
+ if (ei->flags & OZ_EI_F_EXT_ELM)
+ app_hdr = (struct oz_app_hdr *)
+ &ei->data[sizeof(struct oz_ext_elt)];
+ else
+ app_hdr = (struct oz_app_hdr *)
+ &ei->data[sizeof(struct oz_elt)];
app_hdr->elt_seq_num = buf->tx_seq_num[ei->app_id]++;
if (buf->tx_seq_num[ei->app_id] == 0)
buf->tx_seq_num[ei->app_id] = 1;
@@ -293,9 +289,6 @@ 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 = 0;
}
diff --git a/drivers/staging/ozwpan/ozeltbuf.h b/drivers/staging/ozwpan/ozeltbuf.h
index 03c12f57b9bb..2c184be4adab 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 255
+#define OZ_MAX_ELT_PAYLOAD 1024
struct oz_elt_info {
struct list_head link;
struct list_head link_order;
@@ -32,12 +32,13 @@ struct oz_elt_info {
oz_elt_callback_t callback;
long context;
struct oz_elt_stream *stream;
- u8 data[sizeof(struct oz_elt) + OZ_MAX_ELT_PAYLOAD];
+ u8 data[sizeof(struct oz_ext_elt) + OZ_MAX_ELT_PAYLOAD];
int length;
unsigned magic;
};
/* Flags values */
#define OZ_EI_F_MARKED 0x1
+#define OZ_EI_F_EXT_ELM 0x2
struct oz_elt_buf {
spinlock_t lock;
diff --git a/drivers/staging/ozwpan/ozevent.c b/drivers/staging/ozwpan/ozevent.c
deleted file mode 100644
index 73703d3e96bd..000000000000
--- a/drivers/staging/ozwpan/ozevent.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#include "ozconfig.h"
-#ifdef WANT_EVENT_TRACE
-#include <linux/jiffies.h>
-#include <linux/uaccess.h>
-#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
deleted file mode 100644
index f033d014c6f3..000000000000
--- a/drivers/staging/ozwpan/ozevent.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZEVENT_H
-#define _OZEVENT_H
-#include "ozconfig.h"
-#include "ozeventdef.h"
-
-#ifdef WANT_EVENT_TRACE
-extern 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
deleted file mode 100644
index a880288bab11..000000000000
--- a/drivers/staging/ozwpan/ozeventdef.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZEVENTDEF_H
-#define _OZEVENTDEF_H
-
-#define OZ_EVT_RX_FRAME 0
-#define OZ_EVT_RX_PROCESS 1
-#define OZ_EVT_TX_FRAME 2
-#define OZ_EVT_TX_ISOC 3
-#define OZ_EVT_URB_SUBMIT 4
-#define OZ_EVT_URB_DONE 5
-#define OZ_EVT_URB_CANCEL 6
-#define OZ_EVT_CTRL_REQ 7
-#define OZ_EVT_CTRL_CNF 8
-#define OZ_EVT_CTRL_LOCAL 9
-#define OZ_EVT_CONNECT_REQ 10
-#define OZ_EVT_CONNECT_RSP 11
-#define OZ_EVT_EP_CREDIT 12
-#define OZ_EVT_EP_BUFFERING 13
-#define OZ_EVT_TX_ISOC_DONE 14
-#define OZ_EVT_TX_ISOC_DROP 15
-#define OZ_EVT_TIMER_CTRL 16
-#define OZ_EVT_TIMER 17
-#define OZ_EVT_PD_STATE 18
-#define OZ_EVT_SERVICE 19
-#define OZ_EVT_DEBUG 20
-
-struct oz_event {
- 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
new file mode 100644
index 000000000000..def0878b3fc1
--- /dev/null
+++ b/drivers/staging/ozwpan/ozeventtrace.h
@@ -0,0 +1,219 @@
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * -----------------------------------------------------------------------------
+ */
+
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ozwpan
+
+#if !defined(_OZEVENTTRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+
+#define _OZEVENTTRACE_H
+
+#include <linux/tracepoint.h>
+#include <linux/usb.h>
+
+#define MAX_URB_LEN 16
+#define MAX_FRAME_LEN 32
+#define MAX_MSG_LEN 128
+
+TRACE_EVENT(urb_in,
+
+ TP_PROTO(struct urb *oz_urb),
+
+ TP_ARGS(oz_urb),
+
+ TP_STRUCT__entry(
+ __field(uintptr_t, urb)
+ __field(u32, endpoint)
+ __field(u32, buffer_length)
+ __field(u32, inc_length)
+ __array(u8, buffer, MAX_URB_LEN)
+ ),
+
+ TP_fast_assign(
+ __entry->urb = (uintptr_t)oz_urb;
+ __entry->endpoint = usb_pipeendpoint(oz_urb->pipe);
+ if (usb_pipein(oz_urb->pipe))
+ __entry->endpoint |= 0x80;
+ __entry->buffer_length = oz_urb->transfer_buffer_length;
+ __entry->inc_length = oz_urb->transfer_buffer_length
+ <= MAX_URB_LEN ? oz_urb->transfer_buffer_length : MAX_URB_LEN;
+ if ((__entry->endpoint == 0x00) ||
+ (__entry->endpoint == 0x80)) {
+ __entry->buffer_length = 8;
+ __entry->inc_length = 8;
+ memcpy(__entry->buffer, oz_urb->setup_packet, 8);
+ } else {
+ memcpy(__entry->buffer, oz_urb->transfer_buffer,
+ __entry->inc_length);
+ }
+ ),
+
+ TP_printk("%08x,%02x,%03x,%03x,"
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ (u32)__entry->urb, __entry->endpoint, __entry->buffer_length,
+ __entry->inc_length, __entry->buffer[0], __entry->buffer[1],
+ __entry->buffer[2], __entry->buffer[3], __entry->buffer[4],
+ __entry->buffer[5], __entry->buffer[6], __entry->buffer[7],
+ __entry->buffer[8], __entry->buffer[9], __entry->buffer[10],
+ __entry->buffer[11], __entry->buffer[12], __entry->buffer[13],
+ __entry->buffer[14], __entry->buffer[15])
+);
+
+TRACE_EVENT(urb_out,
+
+ TP_PROTO(struct urb *oz_urb, int status),
+
+ TP_ARGS(oz_urb, status),
+
+ TP_STRUCT__entry(
+ __field(uintptr_t, urb)
+ __field(u32, endpoint)
+ __field(u32, status)
+ __field(u32, actual_length)
+ __field(u32, inc_length)
+ __array(u8, buffer, MAX_URB_LEN)
+ ),
+
+ TP_fast_assign(
+ __entry->urb = (uintptr_t)oz_urb;
+ __entry->endpoint = usb_pipeendpoint(oz_urb->pipe);
+ __entry->status = status;
+ if (usb_pipein(oz_urb->pipe))
+ __entry->endpoint |= 0x80;
+ __entry->actual_length = oz_urb->actual_length;
+ __entry->inc_length = oz_urb->actual_length
+ <= MAX_URB_LEN ? oz_urb->actual_length : MAX_URB_LEN;
+ if (usb_pipein(oz_urb->pipe))
+ memcpy(__entry->buffer, oz_urb->transfer_buffer,
+ __entry->inc_length);
+ ),
+
+ TP_printk("%08x,%08x,%02x,%03x,%03x,"
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ (u32)__entry->urb, __entry->status, __entry->endpoint,
+ __entry->actual_length, __entry->inc_length, __entry->buffer[0],
+ __entry->buffer[1], __entry->buffer[2], __entry->buffer[3],
+ __entry->buffer[4], __entry->buffer[5], __entry->buffer[6],
+ __entry->buffer[7], __entry->buffer[8], __entry->buffer[9],
+ __entry->buffer[10], __entry->buffer[11], __entry->buffer[12],
+ __entry->buffer[13], __entry->buffer[14], __entry->buffer[15])
+);
+
+TRACE_EVENT(rx_frame,
+
+ TP_PROTO(struct sk_buff *skb),
+
+ TP_ARGS(skb),
+
+ TP_STRUCT__entry(
+ __field(u32, inc_len)
+ __field(u32, orig_len)
+ __array(u8, data, MAX_FRAME_LEN)
+ ),
+
+ TP_fast_assign(
+ __entry->orig_len = skb->len;
+ __entry->inc_len = skb->len < MAX_FRAME_LEN ?
+ skb->len : MAX_FRAME_LEN;
+ memcpy(__entry->data, (u8 *)skb_network_header(skb),
+ __entry->inc_len);
+ ),
+
+ TP_printk("%03x,%03x,%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+ "%02x%02x%02x", __entry->orig_len,
+ __entry->inc_len, __entry->data[0], __entry->data[1],
+ __entry->data[2], __entry->data[3], __entry->data[4],
+ __entry->data[5], __entry->data[6], __entry->data[7],
+ __entry->data[8], __entry->data[9], __entry->data[10],
+ __entry->data[11], __entry->data[12], __entry->data[13],
+ __entry->data[14], __entry->data[15], __entry->data[16],
+ __entry->data[17], __entry->data[18], __entry->data[19],
+ __entry->data[20], __entry->data[21], __entry->data[22],
+ __entry->data[23], __entry->data[24], __entry->data[25],
+ __entry->data[26], __entry->data[27], __entry->data[28],
+ __entry->data[29], __entry->data[30], __entry->data[31])
+);
+
+TRACE_EVENT(tx_frame,
+
+ TP_PROTO(struct sk_buff *skb),
+
+ TP_ARGS(skb),
+
+ TP_STRUCT__entry(
+ __field(u32, inc_len)
+ __field(u32, orig_len)
+ __array(u8, data, MAX_FRAME_LEN)
+ ),
+
+ TP_fast_assign(
+ __entry->orig_len = skb->len - 14;
+ __entry->inc_len = __entry->orig_len
+ < MAX_FRAME_LEN ?
+ __entry->orig_len
+ : MAX_FRAME_LEN;
+ memcpy(__entry->data, (u8 *)skb_network_header(skb),
+ __entry->inc_len);
+ ),
+
+ TP_printk("%03x,%03x,%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+ "%02x%02x%02x", __entry->orig_len,
+ __entry->inc_len, __entry->data[0], __entry->data[1],
+ __entry->data[2], __entry->data[3], __entry->data[4],
+ __entry->data[5], __entry->data[6], __entry->data[7],
+ __entry->data[8], __entry->data[9], __entry->data[10],
+ __entry->data[11], __entry->data[12], __entry->data[13],
+ __entry->data[14], __entry->data[15], __entry->data[16],
+ __entry->data[17], __entry->data[18], __entry->data[19],
+ __entry->data[20], __entry->data[21], __entry->data[22],
+ __entry->data[23], __entry->data[24], __entry->data[25],
+ __entry->data[26], __entry->data[27], __entry->data[28],
+ __entry->data[29], __entry->data[30], __entry->data[31])
+);
+
+DECLARE_EVENT_CLASS(debug_msg,
+
+ TP_PROTO(char *fmt, va_list arg),
+
+ TP_ARGS(fmt, arg),
+
+ TP_STRUCT__entry(
+ __array(char, msg, MAX_MSG_LEN)
+ ),
+
+ TP_fast_assign(
+ snprintf(__entry->msg, MAX_MSG_LEN, fmt, arg);
+ ),
+
+ TP_printk("%s", __entry->msg)
+);
+
+DEFINE_EVENT(debug_msg, hcd_msg_evt,
+ TP_PROTO(char *fmt, va_list arg),
+ TP_ARGS(fmt, arg)
+);
+
+DEFINE_EVENT(debug_msg, isoc_msg_evt,
+ TP_PROTO(char *fmt, va_list arg),
+ TP_ARGS(fmt, arg)
+);
+
+DEFINE_EVENT(debug_msg, info_msg_evt,
+ TP_PROTO(char *fmt, va_list arg),
+ TP_ARGS(fmt, arg)
+);
+
+
+#endif /*_OZEVENTTRACE_H*/
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE ozeventtrace
+#include <trace/define_trace.h>
diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c
index 750b14eb505e..c26547b4e553 100644
--- a/drivers/staging/ozwpan/ozhcd.c
+++ b/drivers/staging/ozwpan/ozhcd.c
@@ -26,21 +26,16 @@
*/
#include <linux/platform_device.h>
#include <linux/usb.h>
-#include <linux/jiffies.h>
#include <linux/slab.h>
#include <linux/export.h>
#include "linux/usb/hcd.h"
#include <asm/unaligned.h>
-#include "ozconfig.h"
#include "ozusbif.h"
#include "oztrace.h"
#include "ozurbparanoia.h"
-#include "ozevent.h"
-/*------------------------------------------------------------------------------
- * Number of units of buffering to capture for an isochronous IN endpoint before
- * allowing data to be indicated up.
- */
-#define OZ_IN_BUFFERING_UNITS 50
+
+#define OZ_HUB_DEBOUNCE_TIMEOUT 1500
+
/* Name of our platform device.
*/
#define OZ_PLAT_DEV_NAME "ozwpan"
@@ -50,6 +45,9 @@
/* Get endpoint object from the containing link.
*/
#define ep_from_link(__e) container_of((__e), struct oz_endpoint, link)
+/*EP0 timeout before ep0 request is again added to TX queue. (13*8 = 98mSec)
+ */
+#define EP0_TIMEOUT_COUNTER 13
/*------------------------------------------------------------------------------
* Used to link urbs together and also store some status information for each
* urb.
@@ -61,7 +59,7 @@ struct oz_urb_link {
struct oz_port *port;
u8 req_id;
u8 ep_num;
- unsigned long submit_jiffies;
+ unsigned submit_counter;
};
/* Holds state information about a USB endpoint.
@@ -70,7 +68,8 @@ struct oz_endpoint {
struct list_head urb_list; /* List of oz_urb_link items. */
struct list_head link; /* For isoc ep, links in to isoc
lists of oz_port. */
- unsigned long last_jiffies;
+ struct timespec timestamp;
+ int credit2;
int credit;
int credit_ceiling;
u8 ep_num;
@@ -80,6 +79,7 @@ struct oz_endpoint {
int in_ix;
int out_ix;
int buffered_units;
+ u8 max_buffer_units;
unsigned flags;
int start_frame;
};
@@ -87,6 +87,13 @@ struct oz_endpoint {
#define OZ_F_EP_BUFFERING 0x1
#define OZ_F_EP_HAVE_STREAM 0x2
+
+/* Buffer_size.
+Total size of buffer (in bytes) for the endpoint buffer for isochronous data,
+and for stashing BULK or INT data if a URB is not available.
+*/
+#define OZ_EP_BUFFER_SIZE_ISOC (1024*24)
+#define OZ_EP_BUFFER_SIZE_INT (512)
/* Holds state information about a USB interface.
*/
struct oz_interface {
@@ -188,6 +195,7 @@ static DEFINE_SPINLOCK(g_tasklet_lock);
static struct tasklet_struct g_urb_process_tasklet;
static struct tasklet_struct g_urb_cancel_tasklet;
static atomic_t g_pending_urbs = ATOMIC_INIT(0);
+static atomic_t g_usb_frame_number = ATOMIC_INIT(0);
static const struct hc_driver g_oz_hc_drv = {
.description = g_hcd_name,
.product_desc = "Ozmo Devices WPAN",
@@ -236,9 +244,14 @@ static inline struct oz_hcd *oz_hcd_private(struct usb_hcd *hcd)
static int oz_get_port_from_addr(struct oz_hcd *ozhcd, u8 bus_addr)
{
int i;
- for (i = 0; i < OZ_NB_PORTS; i++) {
- if (ozhcd->ports[i].bus_addr == bus_addr)
- return i;
+
+ if (0 != bus_addr) {
+ for (i = 0; i < OZ_NB_PORTS; i++) {
+ if (ozhcd->ports[i].bus_addr == bus_addr)
+ return i;
+ }
+
+ return -1;
}
return ozhcd->conn_port;
}
@@ -346,12 +359,27 @@ struct oz_urb_link *oz_uncancel_urb(struct oz_hcd *ozhcd, struct urb *urb)
* Context: softirq or process
*/
static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb,
- int status, unsigned long submit_jiffies)
+ int status)
{
struct oz_hcd *ozhcd = oz_hcd_private(hcd);
unsigned long irq_state;
struct oz_urb_link *cancel_urbl = 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.
@@ -374,14 +402,7 @@ static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb,
if (oz_forget_urb(urb)) {
oz_trace("OZWPAN: ERROR Unknown URB %p\n", urb);
} else {
- static unsigned long last_time;
atomic_dec(&g_pending_urbs);
- oz_trace2(OZ_TRACE_URB,
- "%lu: giveback_urb(%p,%x) %lu %lu pending:%d\n",
- jiffies, urb, status, jiffies-submit_jiffies,
- jiffies-last_time, atomic_read(&g_pending_urbs));
- last_time = jiffies;
- oz_event_log(OZ_EVT_URB_DONE, 0, 0, urb, status);
usb_hcd_giveback_urb(hcd, urb, status);
}
spin_lock(&g_tasklet_lock);
@@ -396,7 +417,6 @@ static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb,
*/
static void oz_ep_free(struct oz_port *port, struct oz_endpoint *ep)
{
- oz_trace("oz_ep_free()\n");
if (port) {
struct list_head list;
struct oz_hcd *ozhcd = port->ozhcd;
@@ -411,12 +431,47 @@ 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
+ */
static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
struct urb *urb, u8 req_id)
{
@@ -430,7 +485,7 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
urbl = oz_alloc_urb_link();
if (!urbl)
return -ENOMEM;
- urbl->submit_jiffies = jiffies;
+ urbl->submit_counter = 0;
urbl->urb = urb;
urbl->req_id = req_id;
urbl->ep_num = ep_addr;
@@ -444,25 +499,47 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
if (urb->unlinked) {
spin_unlock_bh(&port->ozhcd->hcd_lock);
oz_trace("urb %p unlinked so complete immediately\n", urb);
- oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
+ oz_complete_urb(port->ozhcd->hcd, urb, 0);
oz_free_urb_link(urbl);
return 0;
}
- if (in_dir)
- ep = port->in_ep[ep_addr];
- else
- ep = port->out_ep[ep_addr];
+ if (in_dir) {
+ if (port->in_ep[ep_addr]) {
+ ep = port->in_ep[ep_addr];
+ } else {
+ err = -EINVAL;
+ goto out;
+ }
+ } else {
+ if (port->out_ep[ep_addr]) {
+ ep = port->out_ep[ep_addr];
+ } else {
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
+ /*For interrupt endpoint check for buffered data
+ * & complete urb
+ */
+ 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 (ep && port->hpd) {
list_add_tail(&urbl->link, &ep->urb_list);
if (!in_dir && ep_addr && (ep->credit < 0)) {
- ep->last_jiffies = jiffies;
+ getrawmonotonic(&ep->timestamp);
ep->credit = 0;
- oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num,
- 0, 0, ep->credit);
}
} else {
err = -EPIPE;
}
+out:
spin_unlock_bh(&port->ozhcd->hcd_lock);
if (err)
oz_free_urb_link(urbl);
@@ -532,6 +609,35 @@ static struct urb *oz_find_urb_by_id(struct oz_port *port, int ep_ix,
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
*/
@@ -584,7 +690,8 @@ void *oz_hcd_pd_arrived(void *hpd)
void *hport = 0;
struct oz_hcd *ozhcd = 0;
struct oz_endpoint *ep;
- oz_trace("oz_hcd_pd_arrived()\n");
+ static int n = OZ_NB_PORTS;
+ int j;
ozhcd = oz_hcd_claim();
if (ozhcd == 0)
return 0;
@@ -595,32 +702,38 @@ void *oz_hcd_pd_arrived(void *hpd)
spin_lock_bh(&ozhcd->hcd_lock);
if (ozhcd->conn_port >= 0) {
spin_unlock_bh(&ozhcd->hcd_lock);
- oz_trace("conn_port >= 0\n");
goto out;
}
+ j = n;
for (i = 0; i < OZ_NB_PORTS; i++) {
- struct oz_port *port = &ozhcd->ports[i];
+ struct oz_port *port;
+ if (++j >= OZ_NB_PORTS)
+ j = 0;
+ port = &ozhcd->ports[j];
spin_lock(&port->port_lock);
if ((port->flags & OZ_PORT_F_PRESENT) == 0) {
oz_acquire_port(port, hpd);
+ port->bus_addr = 0;
+ port->config_num = 0;
spin_unlock(&port->port_lock);
break;
}
spin_unlock(&port->port_lock);
}
if (i < OZ_NB_PORTS) {
- oz_trace("Setting conn_port = %d\n", i);
- ozhcd->conn_port = i;
+ ozhcd->conn_port = j;
/* Attach out endpoint 0.
*/
- ozhcd->ports[i].out_ep[0] = ep;
+ ozhcd->ports[j].out_ep[0] = ep;
ep = 0;
- hport = &ozhcd->ports[i];
+ hport = &ozhcd->ports[j];
spin_unlock_bh(&ozhcd->hcd_lock);
if (ozhcd->flags & OZ_HDC_F_SUSPENDED) {
- oz_trace("Resuming root hub\n");
+ oz_trace_msg(H, "usb_hcd_resume_root_hub()\n");
usb_hcd_resume_root_hub(ozhcd->hcd);
}
+ n = j;
+ oz_trace_msg(H, "usb_hcd_poll_rh()\n");
usb_hcd_poll_rh_status(ozhcd->hcd);
} else {
spin_unlock_bh(&ozhcd->hcd_lock);
@@ -644,9 +757,9 @@ void oz_hcd_pd_departed(void *hport)
void *hpd;
struct oz_endpoint *ep = 0;
- oz_trace("oz_hcd_pd_departed()\n");
+ oz_trace("%s:\n", __func__);
if (port == 0) {
- oz_trace("oz_hcd_pd_departed() port = 0\n");
+ oz_trace("%s: port = 0\n", __func__);
return;
}
ozhcd = port->ozhcd;
@@ -657,7 +770,6 @@ void oz_hcd_pd_departed(void *hport)
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);
@@ -670,9 +782,10 @@ void oz_hcd_pd_departed(void *hport)
hpd = port->hpd;
port->hpd = 0;
port->bus_addr = 0xff;
+ port->config_num = 0;
port->flags &= ~(OZ_PORT_F_PRESENT | OZ_PORT_F_DYING);
port->flags |= OZ_PORT_F_CHANGED;
- port->status &= ~USB_PORT_STAT_CONNECTION;
+ port->status &= ~(USB_PORT_STAT_CONNECTION|USB_PORT_STAT_ENABLE);
port->status |= (USB_PORT_STAT_C_CONNECTION << 16);
/* If there is an endpont 0 then clear the pointer while we hold
* the spinlock be we deallocate it after releasing the lock.
@@ -684,6 +797,7 @@ void oz_hcd_pd_departed(void *hport)
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);
}
@@ -715,9 +829,6 @@ void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, u8 *desc,
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;
@@ -749,53 +860,8 @@ void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, u8 *desc,
}
}
urb->actual_length = total_size;
- oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
-}
-/*------------------------------------------------------------------------------
- * Context: softirq
- */
-#ifdef WANT_TRACE
-static void oz_display_conf_type(u8 t)
-{
- switch (t) {
- case USB_REQ_GET_STATUS:
- oz_trace("USB_REQ_GET_STATUS - cnf\n");
- break;
- case USB_REQ_CLEAR_FEATURE:
- oz_trace("USB_REQ_CLEAR_FEATURE - cnf\n");
- break;
- case USB_REQ_SET_FEATURE:
- oz_trace("USB_REQ_SET_FEATURE - cnf\n");
- break;
- case USB_REQ_SET_ADDRESS:
- oz_trace("USB_REQ_SET_ADDRESS - cnf\n");
- break;
- case USB_REQ_GET_DESCRIPTOR:
- oz_trace("USB_REQ_GET_DESCRIPTOR - cnf\n");
- break;
- case USB_REQ_SET_DESCRIPTOR:
- oz_trace("USB_REQ_SET_DESCRIPTOR - cnf\n");
- break;
- case USB_REQ_GET_CONFIGURATION:
- oz_trace("USB_REQ_GET_CONFIGURATION - cnf\n");
- break;
- case USB_REQ_SET_CONFIGURATION:
- oz_trace("USB_REQ_SET_CONFIGURATION - cnf\n");
- break;
- case USB_REQ_GET_INTERFACE:
- oz_trace("USB_REQ_GET_INTERFACE - cnf\n");
- break;
- case USB_REQ_SET_INTERFACE:
- oz_trace("USB_REQ_SET_INTERFACE - cnf\n");
- break;
- case USB_REQ_SYNCH_FRAME:
- oz_trace("USB_REQ_SYNCH_FRAME - cnf\n");
- break;
- }
+ oz_complete_urb(port->ozhcd->hcd, urb, 0);
}
-#else
-#define oz_display_conf_type(__x)
-#endif /* WANT_TRACE */
/*------------------------------------------------------------------------------
* Context: softirq
*/
@@ -814,7 +880,7 @@ static void oz_hcd_complete_set_config(struct oz_port *port, struct urb *urb,
} else {
rc = -ENOMEM;
}
- oz_complete_urb(hcd, urb, rc, 0);
+ oz_complete_urb(hcd, urb, rc);
}
/*------------------------------------------------------------------------------
* Context: softirq
@@ -825,21 +891,24 @@ static void oz_hcd_complete_set_interface(struct oz_port *port, struct urb *urb,
struct usb_hcd *hcd = port->ozhcd->hcd;
int rc = 0;
if (rcode == 0) {
- struct usb_host_config *config;
- struct usb_host_interface *intf;
- oz_trace("Set interface %d alt %d\n", if_num, alt);
- oz_clean_endpoints_for_interface(hcd, port, if_num);
- config = &urb->dev->config[port->config_num-1];
- intf = &config->intf_cache[if_num]->altsetting[alt];
- if (oz_build_endpoints_for_interface(hcd, port, intf,
- GFP_ATOMIC))
+ if (port->config_num > 0) {
+ struct usb_host_config *config;
+ struct usb_host_interface *intf;
+
+ oz_clean_endpoints_for_interface(hcd, port, if_num);
+ config = &urb->dev->config[port->config_num-1];
+ intf = &config->intf_cache[if_num]->altsetting[alt];
+ if (oz_build_endpoints_for_interface(hcd, port, intf,
+ GFP_ATOMIC))
+ rc = -ENOMEM;
+ else
+ port->iface[if_num].alt = alt;
+ } else
rc = -ENOMEM;
- else
- port->iface[if_num].alt = alt;
} else {
rc = -ENOMEM;
}
- oz_complete_urb(hcd, urb, rc, 0);
+ oz_complete_urb(hcd, urb, rc);
}
/*------------------------------------------------------------------------------
* Context: softirq
@@ -854,11 +923,9 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, 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\n");
+ oz_trace("URB not found: %p\n", urb);
return;
}
setup = (struct usb_ctrlrequest *)urb->setup_packet;
@@ -866,7 +933,6 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, 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,
@@ -877,20 +943,20 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, u8 *data,
(u8)windex, (u8)wvalue);
break;
default:
- oz_complete_urb(hcd, urb, 0, 0);
+ oz_complete_urb(hcd, urb, 0);
}
} else {
int copy_len;
- oz_trace("VENDOR-CLASS - cnf\n");
- if (data_len <= urb->transfer_buffer_length)
- copy_len = data_len;
- else
- copy_len = urb->transfer_buffer_length;
- if (copy_len)
+ if (data_len) {
+ if (data_len <= urb->transfer_buffer_length)
+ copy_len = data_len;
+ else
+ copy_len = urb->transfer_buffer_length;
memcpy(urb->transfer_buffer, data, copy_len);
- urb->actual_length = copy_len;
- oz_complete_urb(hcd, urb, 0, 0);
+ urb->actual_length = copy_len;
+ }
+ oz_complete_urb(hcd, urb, 0);
}
}
/*------------------------------------------------------------------------------
@@ -906,7 +972,10 @@ static int oz_hcd_buffer_data(struct oz_endpoint *ep, u8 *data, int data_len)
if (space < 0)
space += ep->buffer_size;
if (space < (data_len+1)) {
- oz_trace("Buffer full\n");
+ oz_trace_msg(I, "EP:%02X u:%d FULL len:%d spc:%d\n",
+ ep->ep_num | USB_DIR_IN,
+ ep->buffered_units,
+ data_len, space);
return -1;
}
ep->buffer[ep->in_ix] = (u8)data_len;
@@ -959,12 +1028,35 @@ void oz_hcd_data_ind(void *hport, u8 endpoint, u8 *data, int data_len)
copy_len = urb->transfer_buffer_length;
memcpy(urb->transfer_buffer, data, copy_len);
urb->actual_length = copy_len;
- oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
+ oz_complete_urb(port->ozhcd->hcd, urb, 0);
return;
+ } else {
+ oz_hcd_buffer_data(ep, data, data_len);
}
break;
case USB_ENDPOINT_XFER_ISOC:
- oz_hcd_buffer_data(ep, data, data_len);
+ if (oz_hcd_buffer_data(ep, data, data_len) != 0) {
+ int len;
+ int copy_len;
+ while (ep->buffered_units > ep->max_buffer_units) {
+ len = ep->buffer[ep->out_ix];
+ if (++ep->out_ix == ep->buffer_size)
+ ep->out_ix = 0;
+ copy_len = ep->buffer_size - ep->out_ix;
+ if (copy_len > len)
+ copy_len = len;
+ if (copy_len < len)
+ ep->out_ix = len - copy_len;
+ else
+ ep->out_ix += copy_len;
+
+ if (ep->out_ix == ep->buffer_size)
+ ep->out_ix = 0;
+
+ ep->buffered_units--;
+ }
+ ep->flags |= OZ_F_EP_BUFFERING;
+ }
break;
}
done:
@@ -975,7 +1067,7 @@ done:
*/
static inline int oz_usb_get_frame_number(void)
{
- return jiffies_to_msecs(get_jiffies_64());
+ return atomic_inc_return(&g_usb_frame_number);
}
/*------------------------------------------------------------------------------
* Context: softirq
@@ -991,7 +1083,8 @@ int oz_hcd_heartbeat(void *hport)
struct list_head *n;
struct urb *urb;
struct oz_endpoint *ep;
- unsigned long now = jiffies;
+ struct timespec ts, delta;
+ getrawmonotonic(&ts);
INIT_LIST_HEAD(&xfr_list);
/* Check the OUT isoc endpoints to see if any URB data can be sent.
*/
@@ -1000,20 +1093,20 @@ int oz_hcd_heartbeat(void *hport)
ep = ep_from_link(e);
if (ep->credit < 0)
continue;
- ep->credit += (now - ep->last_jiffies);
+ delta = timespec_sub(ts, ep->timestamp);
+ ep->credit += div64_u64(timespec_to_ns(&delta), NSEC_PER_MSEC);
if (ep->credit > ep->credit_ceiling)
ep->credit = ep->credit_ceiling;
- oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num, 0, 0, ep->credit);
- ep->last_jiffies = now;
+ ep->timestamp = ts;
while (ep->credit && !list_empty(&ep->urb_list)) {
urbl = list_first_entry(&ep->urb_list,
struct oz_urb_link, link);
urb = urbl->urb;
- if (ep->credit < urb->number_of_packets)
+ if ((ep->credit + 1) < urb->number_of_packets)
break;
ep->credit -= urb->number_of_packets;
- oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num, 0, 0,
- ep->credit);
+ if (ep->credit < 0)
+ ep->credit = 0;
list_del(&urbl->link);
list_add_tail(&urbl->link, &xfr_list);
}
@@ -1022,40 +1115,34 @@ int oz_hcd_heartbeat(void *hport)
/* Send to PD and complete URBs.
*/
list_for_each_safe(e, n, &xfr_list) {
- unsigned long t;
urbl = container_of(e, struct oz_urb_link, link);
urb = urbl->urb;
- t = urbl->submit_jiffies;
list_del_init(e);
urb->error_count = 0;
urb->start_frame = oz_usb_get_frame_number();
oz_usb_send_isoc(port->hpd, urbl->ep_num, urb);
oz_free_urb_link(urbl);
- oz_complete_urb(port->ozhcd->hcd, urb, 0, t);
+ oz_complete_urb(port->ozhcd->hcd, urb, 0);
}
/* Check the IN isoc endpoints to see if any URBs can be completed.
*/
spin_lock_bh(&ozhcd->hcd_lock);
list_for_each(e, &port->isoc_in_ep) {
struct oz_endpoint *ep = ep_from_link(e);
+
if (ep->flags & OZ_F_EP_BUFFERING) {
- if (ep->buffered_units * OZ_IN_BUFFERING_UNITS) {
+ if (ep->buffered_units >= ep->max_buffer_units) {
ep->flags &= ~OZ_F_EP_BUFFERING;
ep->credit = 0;
- oz_event_log(OZ_EVT_EP_CREDIT,
- ep->ep_num | USB_DIR_IN,
- 0, 0, ep->credit);
- ep->last_jiffies = now;
+ ep->credit2 = 0;
+ ep->timestamp = ts;
ep->start_frame = 0;
- oz_event_log(OZ_EVT_EP_BUFFERING,
- ep->ep_num | USB_DIR_IN, 0, 0, 0);
}
continue;
}
- 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;
+ delta = timespec_sub(ts, ep->timestamp);
+ ep->credit += div64_u64(timespec_to_ns(&delta)+5000, NSEC_PER_MSEC);
+ ep->timestamp = ts;
while (!list_empty(&ep->urb_list)) {
struct oz_urb_link *urbl =
list_first_entry(&ep->urb_list,
@@ -1064,8 +1151,6 @@ 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;
@@ -1099,8 +1184,29 @@ int oz_hcd_heartbeat(void *hport)
list_del(&urbl->link);
list_add_tail(&urbl->link, &xfr_list);
ep->credit -= urb->number_of_packets;
- oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num | USB_DIR_IN,
- 0, 0, ep->credit);
+ ep->credit2 += urb->number_of_packets;
+ }
+ if (ep->buffered_units == 0) {
+ oz_trace_msg(I, "EP:%02X Buffer under run\n",
+ ep->ep_num | USB_DIR_IN);
+ ep->flags |= OZ_F_EP_BUFFERING;
+ continue;
+ }
+ if (ep->credit2 >= 1000)
+ {
+ static int buffered_units=-1;
+ static int max_buffer_units=-1;
+ {
+ int diff = ep->buffered_units - buffered_units;
+ oz_trace_msg(I, "u:%d o:%04d b:%d\n",
+ ep->credit2,
+ ep->credit2 + diff,
+ ep->buffered_units);
+
+ buffered_units = ep->buffered_units;
+ max_buffer_units = ep->max_buffer_units;
+ }
+ ep->credit2 = 0;
}
}
if (!list_empty(&port->isoc_out_ep) || !list_empty(&port->isoc_in_ep))
@@ -1113,7 +1219,7 @@ int oz_hcd_heartbeat(void *hport)
urb = urbl->urb;
list_del_init(e);
oz_free_urb_link(urbl);
- oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
+ oz_complete_urb(port->ozhcd->hcd, urb, 0);
}
/* Check if there are any ep0 requests that have timed out.
* If so resent to PD.
@@ -1125,12 +1231,15 @@ int oz_hcd_heartbeat(void *hport)
spin_lock_bh(&ozhcd->hcd_lock);
list_for_each_safe(e, n, &ep->urb_list) {
urbl = container_of(e, struct oz_urb_link, link);
- if (time_after(now, urbl->submit_jiffies+HZ/2)) {
- oz_trace("%ld: Request 0x%p timeout\n",
- now, urbl->urb);
- urbl->submit_jiffies = now;
+ if (urbl->submit_counter > EP0_TIMEOUT_COUNTER) {
+ oz_trace_msg(M, "URB:%08X timeout %02X\n",
+ (unsigned int)((uintptr_t)urbl->urb),
+ urbl->req_id);
list_del(e);
list_add_tail(e, &xfr_list);
+ urbl->submit_counter = 0;
+ } else if (urbl->submit_counter) {
+ urbl->submit_counter++;
}
}
if (!list_empty(&ep->urb_list))
@@ -1140,7 +1249,7 @@ int oz_hcd_heartbeat(void *hport)
while (e != &xfr_list) {
urbl = container_of(e, struct oz_urb_link, link);
e = e->next;
- oz_trace("Resending request to PD.\n");
+ oz_trace_msg(M, "Resending request to PD.\n");
oz_process_ep0_urb(ozhcd, urbl->urb, GFP_ATOMIC);
oz_free_urb_link(urbl);
}
@@ -1156,9 +1265,17 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd,
{
struct oz_hcd *ozhcd = port->ozhcd;
int i;
- int if_ix = intf->desc.bInterfaceNumber;
+ int if_ix;
int request_heartbeat = 0;
+
+ if (intf == NULL)
+ return -ENOMEM;
+
+ if_ix = intf->desc.bInterfaceNumber;
oz_trace("interface[%d] = %p\n", if_ix, intf);
+ if (if_ix >= port->num_iface || port->iface == NULL)
+ return -ENOMEM;
+
for (i = 0; i < intf->desc.bNumEndpoints; i++) {
struct usb_host_endpoint *hep = &intf->endpoint[i];
u8 ep_addr = hep->desc.bEndpointAddress;
@@ -1166,11 +1283,16 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd,
struct oz_endpoint *ep;
int buffer_size = 0;
- oz_trace("%d bEndpointAddress = %x\n", i, ep_addr);
- if ((ep_addr & USB_ENDPOINT_DIR_MASK) &&
- ((hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_ISOC)) {
- buffer_size = 24*1024;
+ 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;
+ }
}
ep = oz_ep_alloc(mem_flags, buffer_size);
@@ -1182,13 +1304,11 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd,
ep->ep_num = ep_num;
if ((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_ISOC) {
- oz_trace("wMaxPacketSize = %d\n",
- hep->desc.wMaxPacketSize);
ep->credit_ceiling = 200;
if (ep_addr & USB_ENDPOINT_DIR_MASK) {
+ ep->max_buffer_units =
+ oz_get_up_max_buffer_units(port->hpd);
ep->flags |= OZ_F_EP_BUFFERING;
- oz_event_log(OZ_EVT_EP_BUFFERING,
- ep->ep_num | USB_DIR_IN, 1, 0, 0);
} else {
ep->flags |= OZ_F_EP_HAVE_STREAM;
if (oz_usb_stream_create(port->hpd, ep_num))
@@ -1314,7 +1434,6 @@ 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 = 0;
}
@@ -1353,8 +1472,7 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
int port_ix = -1;
struct oz_port *port = 0;
- oz_trace2(OZ_TRACE_URB, "%lu: oz_process_ep0_urb(%p)\n", jiffies, urb);
- port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum);
+ port_ix = oz_get_port_from_addr(ozhcd, (usb_pipedevice(urb->pipe)));
if (port_ix < 0) {
rc = -EPIPE;
goto out;
@@ -1374,17 +1492,10 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
windex = le16_to_cpu(setup->wIndex);
wvalue = le16_to_cpu(setup->wValue);
wlength = le16_to_cpu(setup->wLength);
- oz_trace2(OZ_TRACE_CTRL_DETAIL, "bRequestType = %x\n",
- setup->bRequestType);
- oz_trace2(OZ_TRACE_CTRL_DETAIL, "bRequest = %x\n", setup->bRequest);
- oz_trace2(OZ_TRACE_CTRL_DETAIL, "wValue = %x\n", wvalue);
- oz_trace2(OZ_TRACE_CTRL_DETAIL, "wIndex = %x\n", windex);
- oz_trace2(OZ_TRACE_CTRL_DETAIL, "wLength = %x\n", wlength);
req_id = port->next_req_id++;
hpd = oz_claim_hpd(port);
if (hpd == 0) {
- oz_trace("Cannot claim port\n");
rc = -EPIPE;
goto out;
}
@@ -1394,34 +1505,23 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
*/
switch (setup->bRequest) {
case USB_REQ_GET_DESCRIPTOR:
- oz_trace("USB_REQ_GET_DESCRIPTOR - req\n");
break;
case USB_REQ_SET_ADDRESS:
- oz_event_log(OZ_EVT_CTRL_LOCAL, setup->bRequest,
- 0, 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 curcuit this case and reply directly since
+ /* We short circuit this case and reply directly since
* we have the selected configuration number cached.
*/
- oz_event_log(OZ_EVT_CTRL_LOCAL, setup->bRequest, 0, 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) =
@@ -1432,25 +1532,19 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
}
break;
case USB_REQ_GET_INTERFACE:
- /* We short curcuit this case and reply directly since
+ /* We short circuit this case and reply directly since
* we have the selected interface alternative cached.
*/
- oz_event_log(OZ_EVT_CTRL_LOCAL, setup->bRequest, 0, 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;
}
}
@@ -1458,12 +1552,13 @@ 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 tranmitted. If the request were
+ * submitted it to be transmitted. 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
@@ -1480,8 +1575,7 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
oz_usb_put(hpd);
out:
if (rc || complete) {
- oz_trace("Completing request locally\n");
- oz_complete_urb(ozhcd->hcd, urb, rc, 0);
+ oz_complete_urb(ozhcd->hcd, urb, rc);
} else {
oz_usb_request_heartbeat(port->hpd);
}
@@ -1506,14 +1600,14 @@ static int oz_urb_process(struct oz_hcd *ozhcd, struct urb *urb)
/* Check if there is a device at the port - refuse if not.
*/
if ((port->flags & OZ_PORT_F_PRESENT) == 0)
- return -EPIPE;
+ return -ENODEV;
ep_addr = usb_pipeendpoint(urb->pipe);
if (ep_addr) {
/* If the request is not for EP0 then queue it.
*/
if (oz_enqueue_ep_urb(port, ep_addr, usb_pipein(urb->pipe),
urb, 0))
- rc = -EPIPE;
+ rc = -ENOENT;
} else {
oz_process_ep0_urb(ozhcd, urb, GFP_ATOMIC);
}
@@ -1545,7 +1639,7 @@ static void oz_urb_process_tasklet(unsigned long unused)
oz_free_urb_link(urbl);
rc = oz_urb_process(ozhcd, urb);
if (rc)
- oz_complete_urb(ozhcd->hcd, urb, rc, 0);
+ oz_complete_urb(ozhcd->hcd, urb, rc);
spin_lock_irqsave(&g_tasklet_lock, irq_state);
}
spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
@@ -1568,12 +1662,12 @@ static void oz_urb_cancel(struct oz_port *port, u8 ep_num, struct urb *urb)
unsigned long irq_state;
u8 ix;
if (port == 0) {
- oz_trace("ERRORERROR: oz_urb_cancel(%p) port is null\n", urb);
+ oz_trace("%s: urb=%p port is null\n", __func__, urb);
return;
}
ozhcd = port->ozhcd;
if (ozhcd == 0) {
- oz_trace("ERRORERROR: oz_urb_cancel(%p) ozhcd is null\n", urb);
+ oz_trace("%s: urb=%p ozhcd is null\n", __func__, urb);
return;
}
@@ -1598,7 +1692,7 @@ static void oz_urb_cancel(struct oz_port *port, u8 ep_num, struct urb *urb)
urbl = container_of(e, struct oz_urb_link, link);
if (urbl->urb == urb) {
list_del(e);
- oz_trace("Found urb in orphanage\n");
+ oz_trace("Found urb in orphanage urb=%p\n", urb);
goto out;
}
}
@@ -1614,7 +1708,7 @@ out2:
if (urbl) {
urb->actual_length = 0;
oz_free_urb_link(urbl);
- oz_complete_urb(ozhcd->hcd, urb, -EPIPE, 0);
+ oz_complete_urb(ozhcd->hcd, urb, -ENOENT);
}
}
/*------------------------------------------------------------------------------
@@ -1654,7 +1748,7 @@ static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status)
urbl = list_first_entry(&ozhcd->orphanage,
struct oz_urb_link, link);
list_del(&urbl->link);
- oz_complete_urb(ozhcd->hcd, urbl->urb, status, 0);
+ oz_complete_urb(ozhcd->hcd, urbl->urb, status);
oz_free_urb_link(urbl);
}
}
@@ -1664,7 +1758,6 @@ static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status)
*/
static int oz_hcd_start(struct usb_hcd *hcd)
{
- oz_trace("oz_hcd_start()\n");
hcd->power_budget = 200;
hcd->state = HC_STATE_RUNNING;
hcd->uses_new_polling = 1;
@@ -1675,29 +1768,15 @@ static int oz_hcd_start(struct usb_hcd *hcd)
*/
static void oz_hcd_stop(struct usb_hcd *hcd)
{
- oz_trace("oz_hcd_stop()\n");
+ oz_trace("%s:\n", __func__);
}
/*------------------------------------------------------------------------------
* Context: unknown
*/
static void oz_hcd_shutdown(struct usb_hcd *hcd)
{
- oz_trace("oz_hcd_shutdown()\n");
-}
-/*------------------------------------------------------------------------------
- * 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;
+ oz_trace("%s:\n", __func__);
}
-#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
@@ -1713,30 +1792,24 @@ static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
struct oz_port *port;
unsigned long irq_state;
struct oz_urb_link *urbl;
- oz_trace2(OZ_TRACE_URB, "%lu: oz_hcd_urb_enqueue(%p)\n",
- jiffies, urb);
- oz_event_log(OZ_EVT_URB_SUBMIT, oz_get_irq_ctx(),
- (u16)urb->number_of_packets, urb, urb->pipe);
if (unlikely(ozhcd == 0)) {
- oz_trace2(OZ_TRACE_URB, "%lu: Refused urb(%p) not ozhcd.\n",
- jiffies, urb);
- return -EPIPE;
+ oz_trace("Refused urb(%p) not ozhcd.\n", urb);
+ return -ENODEV;
}
if (unlikely(hcd->state != HC_STATE_RUNNING)) {
- oz_trace2(OZ_TRACE_URB, "%lu: Refused urb(%p) not running.\n",
- jiffies, urb);
- return -EPIPE;
+ oz_trace("Refused urb(%p) not running.\n", urb);
+ return -ENODEV;
}
- port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum);
+ port_ix = oz_get_port_from_addr(ozhcd, (usb_pipedevice(urb->pipe)));
if (port_ix < 0)
- return -EPIPE;
+ return -ENODEV;
port = &ozhcd->ports[port_ix];
if (port == 0)
- return -EPIPE;
+ return -ENODEV;
if ((port->flags & OZ_PORT_F_PRESENT) == 0) {
oz_trace("Refusing URB port_ix = %d devnum = %d\n",
port_ix, urb->dev->devnum);
- return -EPIPE;
+ return -ENODEV;
}
urb->hcpriv = port;
/* Put request in queue for processing by tasklet.
@@ -1746,6 +1819,7 @@ static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
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);
@@ -1773,13 +1847,10 @@ static struct oz_urb_link *oz_remove_urb(struct oz_endpoint *ep,
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;
}
@@ -1796,7 +1867,7 @@ static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
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 == 0))
return -ENOMEM;
@@ -1832,7 +1903,7 @@ static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
static void oz_hcd_endpoint_disable(struct usb_hcd *hcd,
struct usb_host_endpoint *ep)
{
- oz_trace("oz_hcd_endpoint_disable\n");
+ oz_trace("%s:\n", __func__);
}
/*------------------------------------------------------------------------------
* Context: unknown
@@ -1840,14 +1911,13 @@ static void oz_hcd_endpoint_disable(struct usb_hcd *hcd,
static void oz_hcd_endpoint_reset(struct usb_hcd *hcd,
struct usb_host_endpoint *ep)
{
- oz_trace("oz_hcd_endpoint_reset\n");
+ oz_trace("%s:\n", __func__);
}
/*------------------------------------------------------------------------------
* Context: unknown
*/
static int oz_hcd_get_frame_number(struct usb_hcd *hcd)
{
- oz_trace("oz_hcd_get_frame_number\n");
return oz_usb_get_frame_number();
}
/*------------------------------------------------------------------------------
@@ -1860,19 +1930,24 @@ static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf)
struct oz_hcd *ozhcd = oz_hcd_private(hcd);
int i;
- oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_status_data()\n");
buf[0] = 0;
-
+ buf[1] = 0;
spin_lock_bh(&ozhcd->hcd_lock);
for (i = 0; i < OZ_NB_PORTS; i++) {
if (ozhcd->ports[i].flags & OZ_PORT_F_CHANGED) {
- oz_trace2(OZ_TRACE_HUB, "Port %d changed\n", i);
- ozhcd->ports[i].flags &= ~OZ_PORT_F_CHANGED;
- buf[0] |= 1<<(i+1);
+ if (i < 7)
+ buf[0] |= 1<<(i+1);
+ else
+ buf[1] |= 1<<(i-7);
}
}
+ oz_trace_msg(H, "HUBSTS : %02X%02X\n",
+ buf[1], buf[0]);
spin_unlock_bh(&ozhcd->hcd_lock);
- return buf[0] ? 1 : 0;
+ if (buf[1] != 0 || buf[0] != 0)
+ return 2;
+ else
+ return 1;
}
/*------------------------------------------------------------------------------
* Context: process
@@ -1880,7 +1955,6 @@ static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf)
static void oz_get_hub_descriptor(struct usb_hcd *hcd,
struct usb_hub_descriptor *desc)
{
- oz_trace2(OZ_TRACE_HUB, "GetHubDescriptor\n");
memset(desc, 0, sizeof(*desc));
desc->bDescriptorType = 0x29;
desc->bDescLength = 9;
@@ -1899,59 +1973,59 @@ static int oz_set_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
struct oz_hcd *ozhcd = oz_hcd_private(hcd);
unsigned set_bits = 0;
unsigned clear_bits = 0;
- oz_trace2(OZ_TRACE_HUB, "SetPortFeature\n");
+
if ((port_id < 1) || (port_id > OZ_NB_PORTS))
- return -EPIPE;
+ return -ENODEV;
port = &ozhcd->ports[port_id-1];
switch (wvalue) {
case USB_PORT_FEAT_CONNECTION:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_CONNECTION\n");
+ oz_trace("USB_PORT_FEAT_CONNECTION\n");
break;
case USB_PORT_FEAT_ENABLE:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_ENABLE\n");
+ oz_trace("USB_PORT_FEAT_ENABLE\n");
break;
case USB_PORT_FEAT_SUSPEND:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_SUSPEND\n");
+ oz_trace("USB_PORT_FEAT_SUSPEND\n");
break;
case USB_PORT_FEAT_OVER_CURRENT:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_OVER_CURRENT\n");
+ oz_trace("USB_PORT_FEAT_OVER_CURRENT\n");
break;
case USB_PORT_FEAT_RESET:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_RESET\n");
+ oz_trace("USB_PORT_FEAT_RESET\n");
set_bits = USB_PORT_STAT_ENABLE | (USB_PORT_STAT_C_RESET<<16);
clear_bits = USB_PORT_STAT_RESET;
ozhcd->ports[port_id-1].bus_addr = 0;
break;
case USB_PORT_FEAT_POWER:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_POWER\n");
+ oz_trace("USB_PORT_FEAT_POWER\n");
set_bits |= USB_PORT_STAT_POWER;
break;
case USB_PORT_FEAT_LOWSPEED:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_LOWSPEED\n");
+ oz_trace("USB_PORT_FEAT_LOWSPEED\n");
break;
case USB_PORT_FEAT_C_CONNECTION:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_CONNECTION\n");
+ oz_trace("USB_PORT_FEAT_C_CONNECTION\n");
break;
case USB_PORT_FEAT_C_ENABLE:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_ENABLE\n");
+ oz_trace("USB_PORT_FEAT_C_ENABLE\n");
break;
case USB_PORT_FEAT_C_SUSPEND:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_SUSPEND\n");
+ oz_trace("USB_PORT_FEAT_C_SUSPEND\n");
break;
case USB_PORT_FEAT_C_OVER_CURRENT:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n");
+ oz_trace("USB_PORT_FEAT_C_OVER_CURRENT\n");
break;
case USB_PORT_FEAT_C_RESET:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_RESET\n");
+ oz_trace("USB_PORT_FEAT_C_RESET\n");
break;
case USB_PORT_FEAT_TEST:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_TEST\n");
+ oz_trace("USB_PORT_FEAT_TEST\n");
break;
case USB_PORT_FEAT_INDICATOR:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_INDICATOR\n");
+ oz_trace("USB_PORT_FEAT_INDICATOR\n");
break;
default:
- oz_trace2(OZ_TRACE_HUB, "Other %d\n", wvalue);
+ oz_trace("Other %d\n", wvalue);
break;
}
if (set_bits || clear_bits) {
@@ -1960,8 +2034,9 @@ static int oz_set_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
port->status |= set_bits;
spin_unlock_bh(&port->port_lock);
}
- oz_trace2(OZ_TRACE_HUB, "Port[%d] status = 0x%x\n", port_id,
- port->status);
+
+ oz_trace_msg(H, "Port[%d]: %08X\n", port_id,
+ ozhcd->ports[port_id-1].status);
return err;
}
/*------------------------------------------------------------------------------
@@ -1974,60 +2049,60 @@ static int oz_clear_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
u8 port_id = (u8)windex;
struct oz_hcd *ozhcd = oz_hcd_private(hcd);
unsigned clear_bits = 0;
- oz_trace2(OZ_TRACE_HUB, "ClearPortFeature\n");
+
if ((port_id < 1) || (port_id > OZ_NB_PORTS))
- return -EPIPE;
+ return -ENODEV;
port = &ozhcd->ports[port_id-1];
switch (wvalue) {
case USB_PORT_FEAT_CONNECTION:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_CONNECTION\n");
+ oz_trace("USB_PORT_FEAT_CONNECTION\n");
break;
case USB_PORT_FEAT_ENABLE:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_ENABLE\n");
+ oz_trace("USB_PORT_FEAT_ENABLE\n");
clear_bits = USB_PORT_STAT_ENABLE;
break;
case USB_PORT_FEAT_SUSPEND:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_SUSPEND\n");
+ oz_trace("USB_PORT_FEAT_SUSPEND\n");
break;
case USB_PORT_FEAT_OVER_CURRENT:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_OVER_CURRENT\n");
+ oz_trace("USB_PORT_FEAT_OVER_CURRENT\n");
break;
case USB_PORT_FEAT_RESET:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_RESET\n");
+ oz_trace("USB_PORT_FEAT_RESET\n");
break;
case USB_PORT_FEAT_POWER:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_POWER\n");
+ oz_trace("USB_PORT_FEAT_POWER\n");
clear_bits |= USB_PORT_STAT_POWER;
break;
case USB_PORT_FEAT_LOWSPEED:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_LOWSPEED\n");
+ oz_trace("USB_PORT_FEAT_LOWSPEED\n");
break;
case USB_PORT_FEAT_C_CONNECTION:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_CONNECTION\n");
+ oz_trace("USB_PORT_FEAT_C_CONNECTION\n");
clear_bits = (USB_PORT_STAT_C_CONNECTION << 16);
break;
case USB_PORT_FEAT_C_ENABLE:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_ENABLE\n");
+ oz_trace("USB_PORT_FEAT_C_ENABLE\n");
clear_bits = (USB_PORT_STAT_C_ENABLE << 16);
break;
case USB_PORT_FEAT_C_SUSPEND:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_SUSPEND\n");
+ oz_trace("USB_PORT_FEAT_C_SUSPEND\n");
break;
case USB_PORT_FEAT_C_OVER_CURRENT:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n");
+ oz_trace("USB_PORT_FEAT_C_OVER_CURRENT\n");
break;
case USB_PORT_FEAT_C_RESET:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_RESET\n");
+ oz_trace("USB_PORT_FEAT_C_RESET\n");
clear_bits = (USB_PORT_FEAT_C_RESET << 16);
break;
case USB_PORT_FEAT_TEST:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_TEST\n");
+ oz_trace("USB_PORT_FEAT_TEST\n");
break;
case USB_PORT_FEAT_INDICATOR:
- oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_INDICATOR\n");
+ oz_trace("USB_PORT_FEAT_INDICATOR\n");
break;
default:
- oz_trace2(OZ_TRACE_HUB, "Other %d\n", wvalue);
+ oz_trace("Other %d\n", wvalue);
break;
}
if (clear_bits) {
@@ -2035,7 +2110,8 @@ static int oz_clear_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
port->status &= ~clear_bits;
spin_unlock_bh(&port->port_lock);
}
- oz_trace2(OZ_TRACE_HUB, "Port[%d] status = 0x%x\n", port_id,
+
+ oz_trace_msg(H, "Port[%d]: %08X\n", port_id,
ozhcd->ports[port_id-1].status);
return err;
}
@@ -2047,12 +2123,12 @@ static int oz_get_port_status(struct usb_hcd *hcd, u16 windex, char *buf)
struct oz_hcd *ozhcd;
u32 status = 0;
if ((windex < 1) || (windex > OZ_NB_PORTS))
- return -EPIPE;
+ return -ENODEV;
ozhcd = oz_hcd_private(hcd);
- oz_trace2(OZ_TRACE_HUB, "GetPortStatus windex = %d\n", windex);
+ ozhcd->ports[windex-1].flags &= ~OZ_PORT_F_CHANGED;
status = ozhcd->ports[windex-1].status;
put_unaligned(cpu_to_le32(status), (__le32 *)buf);
- oz_trace2(OZ_TRACE_HUB, "Port[%d] status = %x\n", windex, status);
+ oz_trace_msg(H, "Port[%d]: %08X\n", windex, status);
return 0;
}
/*------------------------------------------------------------------------------
@@ -2062,10 +2138,13 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
u16 windex, char *buf, u16 wlength)
{
int err = 0;
- oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_control()\n");
+
+ oz_trace_msg(H, "HUBCTL: %04X %04X %04X %04X\n",
+ req_type, wvalue, windex, wlength);
+
switch (req_type) {
case ClearHubFeature:
- oz_trace2(OZ_TRACE_HUB, "ClearHubFeature: %d\n", req_type);
+ oz_trace("ClearHubFeature: %d\n", req_type);
break;
case ClearPortFeature:
err = oz_clear_port_feature(hcd, wvalue, windex);
@@ -2074,7 +2153,7 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
oz_get_hub_descriptor(hcd, (struct usb_hub_descriptor *)buf);
break;
case GetHubStatus:
- oz_trace2(OZ_TRACE_HUB, "GetHubStatus: req_type = 0x%x\n",
+ oz_trace("GetHubStatus: req_type = 0x%x\n",
req_type);
put_unaligned(__constant_cpu_to_le32(0), (__le32 *)buf);
break;
@@ -2082,13 +2161,13 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
err = oz_get_port_status(hcd, windex, buf);
break;
case SetHubFeature:
- oz_trace2(OZ_TRACE_HUB, "SetHubFeature: %d\n", req_type);
+ oz_trace("SetHubFeature: %d\n", req_type);
break;
case SetPortFeature:
err = oz_set_port_feature(hcd, wvalue, windex);
break;
default:
- oz_trace2(OZ_TRACE_HUB, "Other: %d\n", req_type);
+ oz_trace("Other: %d\n", req_type);
break;
}
return err;
@@ -2099,7 +2178,7 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
static int oz_hcd_bus_suspend(struct usb_hcd *hcd)
{
struct oz_hcd *ozhcd;
- oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_suspend()\n");
+
ozhcd = oz_hcd_private(hcd);
spin_lock_bh(&ozhcd->hcd_lock);
hcd->state = HC_STATE_SUSPENDED;
@@ -2113,7 +2192,7 @@ static int oz_hcd_bus_suspend(struct usb_hcd *hcd)
static int oz_hcd_bus_resume(struct usb_hcd *hcd)
{
struct oz_hcd *ozhcd;
- oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_resume()\n");
+
ozhcd = oz_hcd_private(hcd);
spin_lock_bh(&ozhcd->hcd_lock);
ozhcd->flags &= ~OZ_HDC_F_SUSPENDED;
@@ -2125,7 +2204,7 @@ static int oz_hcd_bus_resume(struct usb_hcd *hcd)
*/
static void oz_plat_shutdown(struct platform_device *dev)
{
- oz_trace("oz_plat_shutdown()\n");
+ oz_trace("%s:\n", __func__);
}
/*------------------------------------------------------------------------------
* Context: process
@@ -2136,10 +2215,10 @@ static int oz_plat_probe(struct platform_device *dev)
int err;
struct usb_hcd *hcd;
struct oz_hcd *ozhcd;
- oz_trace("oz_plat_probe()\n");
+
hcd = usb_create_hcd(&g_oz_hc_drv, &dev->dev, dev_name(&dev->dev));
if (hcd == 0) {
- oz_trace("Failed to created hcd object OK\n");
+ oz_trace("Failed to created hcd object\n");
return -ENOMEM;
}
ozhcd = oz_hcd_private(hcd);
@@ -2158,9 +2237,9 @@ static int oz_plat_probe(struct platform_device *dev)
port->bus_addr = 0xff;
spin_lock_init(&port->port_lock);
}
- err = usb_add_hcd(hcd, 0, 0);
+ err = usb_add_hcd(hcd, -1, 0);
if (err) {
- oz_trace("Failed to add hcd object OK\n");
+ oz_trace("Failed to add hcd object\n");
usb_put_hcd(hcd);
return -1;
}
@@ -2176,7 +2255,7 @@ static int oz_plat_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct oz_hcd *ozhcd;
- oz_trace("oz_plat_remove()\n");
+
if (hcd == 0)
return -1;
ozhcd = oz_hcd_private(hcd);
@@ -2184,9 +2263,7 @@ static int oz_plat_remove(struct platform_device *dev)
if (ozhcd == g_ozhcd)
g_ozhcd = 0;
spin_unlock_bh(&g_hcdlock);
- oz_trace("Clearing orphanage\n");
- oz_hcd_clear_orphanage(ozhcd, -EPIPE);
- oz_trace("Removing hcd\n");
+ oz_hcd_clear_orphanage(ozhcd, -ENODEV);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
oz_empty_link_pool();
@@ -2197,7 +2274,7 @@ static int oz_plat_remove(struct platform_device *dev)
*/
static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg)
{
- oz_trace("oz_plat_suspend()\n");
+ oz_trace("%s:\n", __func__);
return 0;
}
/*------------------------------------------------------------------------------
@@ -2205,7 +2282,7 @@ static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg)
*/
static int oz_plat_resume(struct platform_device *dev)
{
- oz_trace("oz_plat_resume()\n");
+ oz_trace("%s:\n", __func__);
return 0;
}
/*------------------------------------------------------------------------------
@@ -2216,10 +2293,10 @@ 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);
@@ -2227,11 +2304,9 @@ int oz_hcd_init(void)
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);
@@ -2240,7 +2315,7 @@ error1:
error:
tasklet_disable(&g_urb_process_tasklet);
tasklet_disable(&g_urb_cancel_tasklet);
- oz_trace("oz_hcd_init() failed %d\n", err);
+ oz_trace("HCD Init failed: %d\n", err);
return err;
}
/*------------------------------------------------------------------------------
@@ -2248,6 +2323,7 @@ error:
*/
void oz_hcd_term(void)
{
+ msleep(OZ_HUB_DEBOUNCE_TIMEOUT);
tasklet_disable(&g_urb_process_tasklet);
tasklet_disable(&g_urb_cancel_tasklet);
platform_device_unregister(g_plat_dev);
diff --git a/drivers/staging/ozwpan/ozkobject.c b/drivers/staging/ozwpan/ozkobject.c
new file mode 100644
index 000000000000..9b85ef55da15
--- /dev/null
+++ b/drivers/staging/ozwpan/ozkobject.c
@@ -0,0 +1,304 @@
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * -----------------------------------------------------------------------------
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/sysfs.h>
+#include <linux/version.h>
+#include "ozpd.h"
+#include "ozcdev.h"
+#include "ozproto.h"
+#include "oztrace.h"
+#include "ozkobject.h"
+#include "ozappif.h"
+
+static ssize_t devices_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
+{
+ int i, count, s;
+ unsigned state;
+ int ret = 0;
+ u8 devices[(ETH_ALEN + sizeof(unsigned)) * OZ_MAX_PDS];
+
+ count = oz_get_pd_status_list(devices, OZ_MAX_PDS);
+ s = sprintf(buf, "Total: %d\n", count);
+ buf += s;
+ ret += s;
+ for (i = 0; i < count; i++) {
+ ret += sprintf(buf, "%pm", (void *)&devices[i * (ETH_ALEN +
+ sizeof(unsigned))]);
+ buf += (ETH_ALEN * 2);
+ ret += sprintf(buf++, "\t");
+ memcpy(&state, &devices[(i * (ETH_ALEN + sizeof(unsigned))) +
+ ETH_ALEN], sizeof(unsigned));
+ switch (state) {
+ case OZ_PD_S_IDLE:
+ s = sprintf(buf, "IDLE\n");
+ buf += s;
+ ret += s;
+ break;
+ case OZ_PD_S_CONNECTED:
+ s = sprintf(buf, "CONNECTED\n");
+ buf += s;
+ ret += s;
+ break;
+ case OZ_PD_S_STOPPED:
+ s = sprintf(buf, "STOPPED\n");
+ buf += s;
+ ret += s;
+ break;
+ case OZ_PD_S_SLEEP:
+ s = sprintf(buf, "SLEEP\n");
+ buf += s;
+ ret += s;
+ break;
+ }
+
+ }
+ return ret;
+}
+
+u8 oz_str_to_hex(const char *st)
+{
+ u8 t1 = 0;
+ char arr[3];
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+ char **pt = NULL;
+#endif
+
+ memcpy(arr, st, 2);
+ arr[2] = '\0';
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+ t1 = (u8) simple_strtoul(arr, pt, 16);
+#else
+ if (kstrtou8(arr, 16, &t1))
+ oz_trace("Invalid string received\n");
+#endif
+ return t1;
+}
+
+static ssize_t stop_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int i;
+ u8 mac_addr[6];
+ struct oz_pd *pd;
+
+ if (count >= 12) {
+ for (i = 0; i < 6; i++) {
+ mac_addr[i] = oz_str_to_hex(buf);
+ buf += 2;
+ }
+
+ pd = oz_pd_find(mac_addr);
+ if (pd && (!(pd->state & OZ_PD_S_CONNECTED))) {
+ oz_pd_stop(pd);
+ oz_pd_put(pd);
+ } else
+ oz_pd_put(pd);
+ }
+
+ return count;
+}
+
+static ssize_t select_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
+{
+ int i;
+ int ret = 0;
+ u8 mac_addr[6];
+
+ oz_get_active_pd(mac_addr);
+
+ for (i = 0; i < 6; i++) {
+ ret += sprintf(buf, "%02x", mac_addr[i]);
+ buf += 2;
+ }
+ ret += sprintf(buf, "\n");
+ return ret;
+}
+
+static ssize_t select_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int i;
+ u8 mac_addr[6];
+
+ if (count >= 12) {
+ for (i = 0; i < 6; i++) {
+ mac_addr[i] = oz_str_to_hex(buf);
+ buf += 2;
+ }
+
+ oz_set_active_pd(mac_addr);
+ }
+ return count;
+}
+
+static ssize_t bind_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
+{
+ char nw_list[OZ_MAX_NW_IF * OZ_MAX_BINDING_LEN] = {0};
+ int count, i, s;
+ int ret = 0;
+
+ count = oz_get_binding_list(nw_list, OZ_MAX_NW_IF);
+ for (i = 0; i < count; i++) {
+ s = sprintf(buf, "%s\n", nw_list + (i * OZ_MAX_BINDING_LEN));
+ ret += s;
+ buf += s;
+ }
+ return ret;
+}
+
+static ssize_t bind_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ char name[OZ_MAX_BINDING_LEN];
+ char *p = NULL;
+
+ memcpy(name, buf + 2, count);
+ p = strstr(name, "\n");
+ if (p)
+ *p = '\0';
+
+ switch (*buf) {
+ case 'a':
+ oz_binding_add(name);
+ break;
+ case 'r':
+ oz_binding_remove(name);
+ break;
+ }
+ return count;
+}
+
+static ssize_t mode_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
+{
+ u8 mode;
+ int ret;
+
+ mode = oz_get_serial_mode();
+ ret = sprintf(buf, "0x%02x\n", mode);
+ return ret;
+}
+
+static ssize_t mode_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ u8 new_mode;
+ if (count >= 4) {
+ new_mode = oz_str_to_hex(buf + 2);
+ oz_set_serial_mode(new_mode);
+ } else {
+ printk(KERN_ERR "Invalid mode\n");
+ }
+ return count;
+}
+
+static ssize_t debug_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
+{
+ int ret = 0;
+ u32 debug = g_debug;
+ int i;
+
+ for (i = 0; i < 'Z'-'A'+1; i++) {
+ if (debug & (1<<i))
+ *(buf + ret++) = 'A' + i;
+ }
+
+ return ret;
+}
+
+static ssize_t debug_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ u32 new_debug = 0;
+ const char *t = buf;
+
+ if (count > 1 && count < 33) {
+ while (*t) {
+ char symbol = *t;
+ if ('A' <= symbol && symbol <= 'Z')
+ new_debug |= 1<<(symbol - 'A');
+ t++;
+ }
+
+ if (0 != new_debug) {
+ g_debug = new_debug;
+ }
+ else
+ printk(KERN_ERR "Invalid debug\n");
+ } else {
+ if (1 == count && *t == '\0')
+ g_debug = 0;
+ }
+
+ return count;
+}
+
+static ssize_t fptr_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
+{
+ int ret;
+
+ ret = sprintf(buf, "p->oz_protocol_init = 0x%p\n", oz_protocol_init);
+ return ret;
+
+}
+
+static struct kobj_attribute devices_attribute =
+ __ATTR(devices, 0400, devices_show, NULL);
+
+static struct kobj_attribute stop_attribute =
+ __ATTR(stop, 0200, NULL, stop_store);
+
+static struct kobj_attribute select_attribute =
+ __ATTR(select, 0600, select_show, select_store);
+
+static struct kobj_attribute bind_attribute =
+ __ATTR(bind, 0600, bind_show, bind_store);
+
+static struct kobj_attribute mode_attribute =
+ __ATTR(mode, 0600, mode_show, mode_store);
+
+static struct kobj_attribute debug_attribute =
+ __ATTR(debug, 0600, debug_show, debug_store);
+
+static struct kobj_attribute fptr_attribute =
+ __ATTR(fptr, 0400, fptr_show, NULL);
+
+static struct attribute *attrs[] = {
+ &devices_attribute.attr,
+ &stop_attribute.attr,
+ &select_attribute.attr,
+ &bind_attribute.attr,
+ &mode_attribute.attr,
+ &debug_attribute.attr,
+ &fptr_attribute.attr,
+ NULL,
+};
+
+static struct attribute_group attr_group = {
+ .attrs = attrs,
+};
+
+void oz_create_sys_entry(void)
+{
+ int retval;
+
+ retval = sysfs_create_group(&g_oz_wpan_dev->kobj, &attr_group);
+ if (retval)
+ oz_trace("Can not create attribute group\n");
+
+}
+
+void oz_destroy_sys_entry(void)
+{
+ sysfs_remove_group(&g_oz_wpan_dev->kobj, &attr_group);
+}
diff --git a/drivers/staging/ozwpan/ozkobject.h b/drivers/staging/ozwpan/ozkobject.h
new file mode 100644
index 000000000000..0557228001d4
--- /dev/null
+++ b/drivers/staging/ozwpan/ozkobject.h
@@ -0,0 +1,17 @@
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * -----------------------------------------------------------------------------
+ */
+
+#ifndef _OZKOBJECT_H
+#define _OZKOBJECT_H
+
+#define OZ_MAX_NW_IF 6
+
+void oz_create_sys_entry(void);
+void oz_destroy_sys_entry(void);
+void oz_set_serial_mode(u8 mode);
+u8 oz_get_serial_mode(void);
+
+#endif /* _OZKOBJECT_H */
diff --git a/drivers/staging/ozwpan/ozmain.c b/drivers/staging/ozwpan/ozmain.c
index aaf2ccc0bcfb..0b48cc8508ff 100644
--- a/drivers/staging/ozwpan/ozmain.c
+++ b/drivers/staging/ozwpan/ozmain.c
@@ -10,12 +10,10 @@
#include <linux/netdevice.h>
#include <linux/errno.h>
#include <linux/ieee80211.h>
-#include "ozconfig.h"
#include "ozpd.h"
#include "ozproto.h"
#include "ozcdev.h"
#include "oztrace.h"
-#include "ozevent.h"
/*------------------------------------------------------------------------------
* The name of the 802.11 mac device. Empty string is the default value but a
* value can be supplied as a parameter to the module. An empty string means
@@ -28,11 +26,11 @@ char *g_net_dev = "";
*/
static int __init ozwpan_init(void)
{
- oz_event_init();
oz_cdev_register();
oz_protocol_init(g_net_dev);
oz_app_enable(OZ_APPID_USB, 1);
oz_apps_init();
+ printk(KERN_DEBUG "p->oz_protocol_init = 0x%p\n", oz_protocol_init);
return 0;
}
/*------------------------------------------------------------------------------
@@ -43,7 +41,6 @@ static void __exit ozwpan_exit(void)
oz_protocol_term();
oz_apps_term();
oz_cdev_deregister();
- oz_event_term();
}
/*------------------------------------------------------------------------------
*/
@@ -53,6 +50,6 @@ module_exit(ozwpan_exit);
MODULE_AUTHOR("Chris Kelly");
MODULE_DESCRIPTION("Ozmo Devices USB over WiFi hcd driver");
-MODULE_VERSION("1.0.8");
+MODULE_VERSION("1.2.3-rc2");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c
index 04cd57f2a6da..e3bf27b6bee8 100644
--- a/drivers/staging/ozwpan/ozpd.c
+++ b/drivers/staging/ozwpan/ozpd.c
@@ -9,13 +9,11 @@
#include <linux/sched.h>
#include <linux/netdevice.h>
#include <linux/errno.h>
-#include "ozconfig.h"
#include "ozprotocol.h"
#include "ozeltbuf.h"
#include "ozpd.h"
#include "ozproto.h"
#include "oztrace.h"
-#include "ozevent.h"
#include "ozcdev.h"
#include "ozusbsvc.h"
#include <asm/unaligned.h>
@@ -24,18 +22,17 @@
/*------------------------------------------------------------------------------
*/
#define OZ_MAX_TX_POOL_SIZE 6
-/* Maximum number of uncompleted isoc frames that can be pending.
- */
-#define OZ_MAX_SUBMITTED_ISOC 16
+#define AC_VO 0x106
/*------------------------------------------------------------------------------
*/
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);
@@ -84,6 +81,33 @@ static struct oz_app_if g_app_if[OZ_APPID_MAX] = {
0,
0,
OZ_APPID_SERIAL},
+
+ {oz_def_app_init,
+ oz_def_app_term,
+ oz_def_app_start,
+ oz_def_app_stop,
+ oz_def_app_rx,
+ 0,
+ 0,
+ OZ_APPID_UNUSED3},
+
+ {oz_def_app_init,
+ oz_def_app_term,
+ oz_def_app_start,
+ oz_def_app_stop,
+ oz_def_app_rx,
+ 0,
+ 0,
+ OZ_APPID_UNUSED4},
+
+ {0,
+ 0,
+ 0,
+ 0,
+ oz_cdev_rx,
+ 0,
+ 0,
+ OZ_APPID_TFTP},
};
/*------------------------------------------------------------------------------
* Context: process
@@ -123,23 +147,6 @@ static void oz_def_app_rx(struct oz_pd *pd, struct oz_elt *elt)
void oz_pd_set_state(struct oz_pd *pd, unsigned state)
{
pd->state = state;
- oz_event_log(OZ_EVT_PD_STATE, 0, 0, 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
@@ -164,6 +171,7 @@ 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,19 +189,28 @@ struct oz_pd *oz_pd_alloc(u8 *mac_addr)
pd->last_sent_frame = &pd->tx_queue;
spin_lock_init(&pd->stream_lock);
INIT_LIST_HEAD(&pd->stream_list);
+ tasklet_init(&pd->heartbeat_tasklet, oz_pd_heartbeat_handler,
+ (unsigned long)pd);
+ tasklet_init(&pd->timeout_tasklet, oz_pd_timeout_handler,
+ (unsigned long)pd);
+ hrtimer_init(&pd->heartbeat, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ hrtimer_init(&pd->timeout, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ pd->heartbeat.function = oz_pd_heartbeat_event;
+ pd->timeout.function = oz_pd_timeout_event;
}
return pd;
}
-/*------------------------------------------------------------------------------
- * Context: softirq or process
- */
-void oz_pd_destroy(struct oz_pd *pd)
+static void oz_pd_free(struct work_struct *work)
{
+ struct oz_pd *pd;
struct list_head *e;
struct oz_tx_frame *f;
struct oz_isoc_stream *st;
struct oz_farewell *fwell;
+ pd = container_of(work, struct oz_pd, workitem);
oz_trace("Destroying PD\n");
+ tasklet_kill(&pd->heartbeat_tasklet);
+ tasklet_kill(&pd->timeout_tasklet);
/* Delete any streams.
*/
e = pd->stream_list.next;
@@ -208,6 +225,8 @@ void oz_pd_destroy(struct oz_pd *pd)
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);
@@ -230,6 +249,28 @@ void oz_pd_destroy(struct oz_pd *pd)
dev_put(pd->net_dev);
kfree(pd);
}
+
+
+/*------------------------------------------------------------------------------
+ * Context: softirq or Process
+ */
+void oz_pd_destroy(struct oz_pd *pd)
+{
+ int ret;
+
+ if (hrtimer_active(&pd->timeout))
+ hrtimer_cancel(&pd->timeout);
+ if (hrtimer_active(&pd->heartbeat))
+ hrtimer_cancel(&pd->heartbeat);
+
+ memset(&pd->workitem, 0, sizeof(pd->workitem));
+ INIT_WORK(&pd->workitem, oz_pd_free);
+ ret = schedule_work(&pd->workitem);
+
+ if (ret)
+ oz_trace("failed to schedule workitem\n");
+}
+
/*------------------------------------------------------------------------------
* Context: softirq-serialized
*/
@@ -238,12 +279,12 @@ int oz_services_start(struct oz_pd *pd, u16 apps, int resume)
struct oz_app_if *ai;
int rc = 0;
oz_trace("oz_services_start(0x%x) resume(%d)\n", apps, resume);
+ if (apps & (1<<OZ_APPID_TFTP))
+ apps |= 1<<OZ_APPID_SERIAL;
for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) {
if (apps & (1<<ai->app_id)) {
- if (ai->start(pd, resume)) {
+ if (ai->start && ai->start(pd, resume)) {
rc = -1;
- oz_trace("Unabled to start service %d\n",
- ai->app_id);
break;
}
oz_polling_lock_bh();
@@ -262,6 +303,8 @@ void oz_services_stop(struct oz_pd *pd, u16 apps, int pause)
{
struct oz_app_if *ai;
oz_trace("oz_stop_services(0x%x) pause(%d)\n", apps, pause);
+ if (apps & (1<<OZ_APPID_TFTP))
+ apps |= 1<<OZ_APPID_SERIAL;
for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) {
if (apps & (1<<ai->app_id)) {
oz_polling_lock_bh();
@@ -272,7 +315,8 @@ void oz_services_stop(struct oz_pd *pd, u16 apps, int pause)
pd->paused_apps &= ~(1<<ai->app_id);
}
oz_polling_unlock_bh();
- ai->stop(pd, pause);
+ if (ai->stop)
+ ai->stop(pd, pause);
}
}
}
@@ -289,8 +333,8 @@ void oz_pd_heartbeat(struct oz_pd *pd, u16 apps)
more = 1;
}
}
- if (more)
- oz_pd_request_heartbeat(pd);
+ if ((!more) && (hrtimer_active(&pd->heartbeat)))
+ hrtimer_cancel(&pd->heartbeat);
if (pd->mode & OZ_F_ISOC_ANYTIME) {
int count = 8;
while (count-- && (oz_send_isoc_frame(pd) >= 0))
@@ -303,9 +347,9 @@ void oz_pd_heartbeat(struct oz_pd *pd, u16 apps)
void oz_pd_stop(struct oz_pd *pd)
{
u16 stop_apps = 0;
- oz_trace("oz_pd_stop() State = 0x%x\n", pd->state);
- oz_pd_indicate_farewells(pd);
+ oz_trace("%s: State = 0x%x\n", __func__, pd->state);
oz_polling_lock_bh();
+ oz_pd_indicate_farewells(pd);
stop_apps = pd->total_apps;
pd->total_apps = 0;
pd->paused_apps = 0;
@@ -315,9 +359,9 @@ void oz_pd_stop(struct oz_pd *pd)
oz_pd_set_state(pd, OZ_PD_S_STOPPED);
/* Remove from PD list.*/
list_del(&pd->link);
+
+
oz_polling_unlock_bh();
- oz_trace("pd ref count = %d\n", atomic_read(&pd->ref_count));
- oz_timer_delete(pd, 0);
oz_pd_put(pd);
}
/*------------------------------------------------------------------------------
@@ -332,11 +376,8 @@ int oz_pd_sleep(struct oz_pd *pd)
oz_polling_unlock_bh();
return 0;
}
- if (pd->keep_alive_j && pd->session_id) {
+ if (pd->keep_alive && pd->session_id) {
oz_pd_set_state(pd, OZ_PD_S_SLEEP);
- pd->pulse_time_j = jiffies + pd->keep_alive_j;
- oz_trace("Sleep Now %lu until %lu\n",
- jiffies, pd->pulse_time_j);
} else {
do_stop = 1;
}
@@ -346,7 +387,7 @@ int oz_pd_sleep(struct oz_pd *pd)
oz_pd_stop(pd);
} else {
oz_services_stop(pd, stop_apps, 1);
- oz_timer_add(pd, OZ_TIMER_STOP, jiffies + pd->keep_alive_j, 1);
+ oz_timer_add(pd, OZ_TIMER_STOP, pd->keep_alive);
}
return do_stop;
}
@@ -375,6 +416,21 @@ static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd)
/*------------------------------------------------------------------------------
* 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
+ */
static void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f)
{
spin_lock_bh(&pd->tx_frame_lock);
@@ -389,6 +445,22 @@ static void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *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
*/
int oz_prepare_frame(struct oz_pd *pd, int empty)
@@ -403,6 +475,7 @@ int oz_prepare_frame(struct oz_pd *pd, int empty)
f = oz_tx_frame_alloc(pd);
if (f == 0)
return -1;
+ f->skb = NULL;
f->hdr.control =
(OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ACK_REQUESTED;
++pd->last_tx_pkt_num;
@@ -439,6 +512,7 @@ static struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f)
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;
@@ -486,33 +560,51 @@ 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;
}
- 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);
- 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)
+
+ 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;
+ 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;
return 0;
}
/*------------------------------------------------------------------------------
@@ -520,21 +612,38 @@ 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)
{
- 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);
- }
+ 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;
}
- } 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
@@ -556,7 +665,6 @@ static int oz_send_isoc_frame(struct oz_pd *pd)
return 0;
skb = alloc_skb(total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC);
if (skb == 0) {
- oz_trace("Cannot alloc skb\n");
oz_elt_info_free_chain(&pd->elt_buff, &list);
return -1;
}
@@ -580,7 +688,7 @@ static int oz_send_isoc_frame(struct oz_pd *pd)
memcpy(elt, ei->data, ei->length);
elt = oz_next_elt(elt);
}
- oz_event_log(OZ_EVT_TX_ISOC, 0, 0, 0, 0);
+ oz_trace_skb(skb, 'T');
dev_queue_xmit(skb);
oz_elt_info_free_chain(&pd->elt_buff, &list);
return 0;
@@ -603,7 +711,7 @@ 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)
+ if ((diff > OZ_LAST_PN_HALF_CYCLE) || (pkt_num == 0))
break;
if (first == 0)
first = e;
@@ -689,8 +797,6 @@ 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
@@ -727,6 +833,8 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, u8 *data, int len)
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);
}
@@ -756,21 +864,52 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, 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) {
- kfree_skb(skb);
- return -1;
+ 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;
}
+ /*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_event_log(OZ_EVT_TX_ISOC, nb_units, iso.frame_number,
- skb, atomic_read(&g_submitted_isoc));
- if (dev_queue_xmit(skb) < 0)
+ oz_trace_skb(skb, 'T');
+ if (dev_queue_xmit(skb) < 0) {
return -1;
- } else {
- oz_event_log(OZ_EVT_TX_ISOC_DROP, 0, 0, 0, 0);
- kfree_skb(skb);
+ } else
+ return 0;
}
+
+out: kfree_skb(skb);
+ return -1;
+
}
return 0;
}
@@ -813,18 +952,10 @@ void oz_pd_indicate_farewells(struct oz_pd *pd)
{
struct oz_farewell *f;
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;
- }
+ if (!(list_empty(&pd->farewell_list))) {
f = list_first_entry(&pd->farewell_list,
- struct oz_farewell, link);
- list_del(&f->link);
- oz_polling_unlock_bh();
+ struct oz_farewell, link);
if (ai->farewell)
ai->farewell(pd, f->ep_num, f->report, f->len);
- kfree(f);
}
}
diff --git a/drivers/staging/ozwpan/ozpd.h b/drivers/staging/ozwpan/ozpd.h
index afc77f0260f0..355f637e72c5 100644
--- a/drivers/staging/ozwpan/ozpd.h
+++ b/drivers/staging/ozwpan/ozpd.h
@@ -6,6 +6,7 @@
#ifndef _OZPD_H_
#define _OZPD_H_
+#include <linux/interrupt.h>
#include "ozeltbuf.h"
/* PD state
@@ -21,6 +22,7 @@
#define OZ_TIMER_HEARTBEAT 2
#define OZ_TIMER_STOP 3
+#define ETH_STRING_LEN 17
/* Data structure that hold information on a frame for transmisson. This is
* built when the frame is first transmitted and is used to rebuild the frame
* if a re-transmission is required.
@@ -29,6 +31,7 @@ struct oz_tx_frame {
struct list_head link;
struct list_head elt_list;
struct oz_hdr hdr;
+ struct sk_buff *skb;
int total_size;
};
@@ -46,7 +49,7 @@ struct oz_farewell {
struct list_head link;
u8 ep_num;
u8 index;
- u8 report[1];
+ u8 report[32];
u8 len;
};
@@ -67,22 +70,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_j;
- unsigned long timeout_time_j;
- unsigned long pulse_period_j;
- unsigned long presleep_j;
- unsigned long keep_alive_j;
- unsigned long last_rx_time_j;
+ unsigned long pulse_time;
+ ktime_t pulse_period;
+ unsigned long presleep;
+ unsigned long keep_alive;
struct oz_elt_buf elt_buff;
void *app_ctx[OZ_APPID_MAX];
spinlock_t app_lock[OZ_APPID_MAX];
int max_tx_size;
- u8 heartbeat_requested;
u8 mode;
u8 ms_per_isoc;
+ unsigned isoc_latency;
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;
@@ -92,6 +95,13 @@ 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
@@ -118,4 +128,3 @@ 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 ad857eeabbb7..e222d0831f8f 100644
--- a/drivers/staging/ozwpan/ozproto.c
+++ b/drivers/staging/ozwpan/ozproto.c
@@ -10,7 +10,6 @@
#include <linux/netdevice.h>
#include <linux/errno.h>
#include <linux/ieee80211.h>
-#include "ozconfig.h"
#include "ozprotocol.h"
#include "ozeltbuf.h"
#include "ozpd.h"
@@ -18,7 +17,6 @@
#include "ozusbsvc.h"
#include "oztrace.h"
#include "ozappif.h"
-#include "ozevent.h"
#include <asm/unaligned.h>
#include <linux/uaccess.h>
#include <net/psnap.h>
@@ -30,48 +28,32 @@
#define OZ_DO_STOP 1
#define OZ_DO_SLEEP 2
-/* States of the timer.
- */
-#define OZ_TIMER_IDLE 0
-#define OZ_TIMER_SET 1
-#define OZ_TIMER_IN_HANDLER 2
-
#define OZ_MAX_TIMER_POOL_SIZE 16
+/*------------------------------------------------------------------------------
+ * Number of units of buffering to capture for an isochronous IN endpoint before
+ * allowing data to be indicated up.
+ */
+#define OZ_IN_BUFFERING_UNITS 100
/*------------------------------------------------------------------------------
*/
struct oz_binding {
struct packet_type ptype;
char name[OZ_MAX_BINDING_LEN];
- struct oz_binding *next;
-};
-
-struct oz_timer {
struct list_head link;
- struct oz_pd *pd;
- unsigned long due_time;
- int type;
};
+
/*------------------------------------------------------------------------------
* Static external variables.
*/
static DEFINE_SPINLOCK(g_polling_lock);
static LIST_HEAD(g_pd_list);
-static struct oz_binding *g_binding ;
+static LIST_HEAD(g_binding);
static DEFINE_SPINLOCK(g_binding_lock);
static struct sk_buff_head g_rx_queue;
static u8 g_session_id;
static u16 g_apps = 0x1;
static int g_processing_rx;
-static struct timer_list g_timer;
-static struct oz_timer *g_cur_timer;
-static struct list_head *g_timer_pool;
-static int g_timer_pool_count;
-static int g_timer_state = OZ_TIMER_IDLE;
-static LIST_HEAD(g_timer_list);
-/*------------------------------------------------------------------------------
- */
-static void oz_protocol_timer_start(void);
/*------------------------------------------------------------------------------
* Context: softirq-serialized
*/
@@ -116,7 +98,6 @@ static void oz_send_conn_rsp(struct oz_pd *pd, u8 status)
oz_hdr->control = (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT);
oz_hdr->last_pkt_num = 0;
put_unaligned(0, &oz_hdr->pkt_num);
- oz_event_log(OZ_EVT_CONNECT_RSP, 0, 0, 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));
@@ -126,7 +107,7 @@ static void oz_send_conn_rsp(struct oz_pd *pd, u8 status)
body->session_id = pd->session_id;
put_unaligned(cpu_to_le16(pd->total_apps), &body->apps);
}
- oz_trace("TX: OZ_ELT_CONNECT_RSP %d", status);
+ oz_trace_skb(skb, 'T');
dev_queue_xmit(skb);
return;
}
@@ -139,33 +120,35 @@ static void pd_set_keepalive(struct oz_pd *pd, u8 kalive)
switch (kalive & OZ_KALIVE_TYPE_MASK) {
case OZ_KALIVE_SPECIAL:
- pd->keep_alive_j =
- oz_ms_to_jiffies(keep_alive * 1000*60*60*24*20);
+ pd->keep_alive = (keep_alive*1000*60*60*24*20);
break;
case OZ_KALIVE_SECS:
- pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000);
+ pd->keep_alive = (keep_alive*1000);
break;
case OZ_KALIVE_MINS:
- pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000*60);
+ pd->keep_alive = (keep_alive*1000*60);
break;
case OZ_KALIVE_HOURS:
- pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000*60*60);
+ pd->keep_alive = (keep_alive*1000*60*60);
break;
default:
- pd->keep_alive_j = 0;
+ pd->keep_alive = 0;
}
- oz_trace("Keepalive = %lu jiffies\n", pd->keep_alive_j);
}
/*------------------------------------------------------------------------------
* Context: softirq-serialized
*/
-static void pd_set_presleep(struct oz_pd *pd, u8 presleep)
+static void pd_set_presleep(struct oz_pd *pd, u8 presleep, u8 start_timer)
{
if (presleep)
- pd->presleep_j = oz_ms_to_jiffies(presleep*100);
+ pd->presleep = presleep*100;
else
- pd->presleep_j = OZ_PRESLEEP_TOUT_J;
- oz_trace("Presleep time = %lu jiffies\n", pd->presleep_j);
+ pd->presleep = OZ_PRESLEEP_TOUT;
+ if (start_timer) {
+ spin_unlock(&g_polling_lock);
+ oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep);
+ spin_lock(&g_polling_lock);
+ }
}
/*------------------------------------------------------------------------------
* Context: softirq-serialized
@@ -190,7 +173,7 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt,
pd = oz_pd_alloc(pd_addr);
if (pd == 0)
return 0;
- pd->last_rx_time_j = jiffies;
+ getnstimeofday(&pd->last_rx_timestamp);
spin_lock_bh(&g_polling_lock);
list_for_each(e, &g_pd_list) {
pd2 = container_of(e, struct oz_pd, link);
@@ -212,24 +195,35 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt,
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->timeout_time_j = jiffies + OZ_CONNECTION_TOUT_J;
- pd->pulse_period_j = OZ_QUANTUM_J;
- pd_set_presleep(pd, body->presleep);
+ pd->pulse_period = ktime_set(OZ_QUANTUM / MSEC_PER_SEC, (OZ_QUANTUM %
+ MSEC_PER_SEC) * NSEC_PER_MSEC);
+ pd_set_presleep(pd, body->presleep, 0);
pd_set_keepalive(pd, body->keep_alive);
new_apps &= le16_to_cpu(get_unaligned(&body->apps));
@@ -261,9 +255,6 @@ done:
u16 resume_apps = new_apps & pd->paused_apps & ~0x1;
spin_unlock_bh(&g_polling_lock);
oz_pd_set_state(pd, OZ_PD_S_CONNECTED);
- oz_timer_delete(pd, OZ_TIMER_STOP);
- oz_trace("new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n",
- new_apps, pd->total_apps, pd->paused_apps);
if (start_apps) {
if (oz_services_start(pd, start_apps, 0))
rsp_status = OZ_STATUS_TOO_MANY_PDS;
@@ -304,6 +295,7 @@ static void oz_add_farewell(struct oz_pd *pd, u8 ep_num, u8 index,
return;
f->ep_num = ep_num;
f->index = index;
+ f->len = len;
memcpy(f->report, report, len);
oz_trace("RX: Adding farewell report\n");
spin_lock(&g_polling_lock);
@@ -330,15 +322,11 @@ static void oz_rx_frame(struct sk_buff *skb)
int length;
struct oz_pd *pd = 0;
struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb);
+ struct timespec current_time;
int dup = 0;
u32 pkt_num;
- oz_event_log(OZ_EVT_RX_PROCESS, 0,
- (((u16)oz_hdr->control)<<8)|oz_hdr->last_pkt_num,
- 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);
+ oz_trace_skb(skb, 'R');
mac_hdr = skb_mac_header(skb);
src_addr = &mac_hdr[ETH_ALEN] ;
length = skb->len;
@@ -350,18 +338,23 @@ static void oz_rx_frame(struct sk_buff *skb)
goto done;
}
+
pkt_num = le32_to_cpu(get_unaligned(&oz_hdr->pkt_num));
pd = oz_pd_find(src_addr);
if (pd) {
- pd->last_rx_time_j = jiffies;
- oz_timer_add(pd, OZ_TIMER_TOUT,
- pd->last_rx_time_j + pd->presleep_j, 1);
+ if (!(pd->state & OZ_PD_S_CONNECTED))
+ oz_pd_set_state(pd, OZ_PD_S_CONNECTED);
+ getnstimeofday(&current_time);
+ if ((current_time.tv_sec != pd->last_rx_timestamp.tv_sec) ||
+ (pd->presleep < MSEC_PER_SEC)) {
+ oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep);
+ pd->last_rx_timestamp = current_time;
+ }
if (pkt_num != pd->last_rx_pkt_num) {
pd->last_rx_pkt_num = pkt_num;
} else {
dup = 1;
- oz_trace("Duplicate frame\n");
}
}
@@ -376,8 +369,6 @@ 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);
}
}
@@ -385,29 +376,25 @@ static void oz_rx_frame(struct sk_buff *skb)
length -= sizeof(struct oz_hdr);
elt = (struct oz_elt *)((u8 *)oz_hdr + sizeof(struct oz_hdr));
- while (length >= sizeof(struct oz_elt)) {
- length -= sizeof(struct oz_elt) + elt->length;
+ while (length >= oz_elt_hdr_len(elt)) {
+ length -= oz_elt_len(elt);
if (length < 0)
break;
switch (elt->type) {
case OZ_ELT_CONNECT_REQ:
- oz_event_log(OZ_EVT_CONNECT_REQ, 0, 0, 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);
+ pd_set_presleep(pd, body->presleep, 1);
spin_unlock(&g_polling_lock);
}
}
@@ -415,16 +402,16 @@ static void oz_rx_frame(struct sk_buff *skb)
case OZ_ELT_FAREWELL_REQ: {
struct oz_elt_farewell *body =
(struct oz_elt_farewell *)(elt + 1);
- oz_trace("RX: OZ_ELT_FAREWELL_REQ\n");
oz_add_farewell(pd, body->ep_num,
body->index, body->report,
elt->length + 1 - sizeof(*body));
}
break;
case OZ_ELT_APP_DATA:
+ case OZ_ELT_APP_DATA_EX:
if (pd && (pd->state & OZ_PD_S_CONNECTED)) {
struct oz_app_hdr *app_hdr =
- (struct oz_app_hdr *)(elt+1);
+ (struct oz_app_hdr *)(oz_elt_data(elt));
if (dup)
break;
oz_handle_app_elt(pd, app_hdr->app_id, elt);
@@ -445,14 +432,13 @@ done:
*/
void oz_protocol_term(void)
{
- struct list_head *chain = 0;
- del_timer_sync(&g_timer);
+ struct oz_binding *b, *t;
+
/* Walk the list of bindings and remove each one.
*/
spin_lock_bh(&g_binding_lock);
- while (g_binding) {
- struct oz_binding *b = g_binding;
- g_binding = b->next;
+ list_for_each_entry_safe(b, t, &g_binding, link) {
+ list_del(&b->link);
spin_unlock_bh(&g_binding_lock);
dev_remove_pack(&b->ptype);
if (b->ptype.dev)
@@ -475,251 +461,110 @@ 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
*/
-static void oz_pd_handle_timer(struct oz_pd *pd, int type)
+void oz_pd_heartbeat_handler(unsigned long data)
{
+ struct oz_pd *pd = (struct oz_pd *)data;
+ u16 apps = 0;
+ spin_lock_bh(&g_polling_lock);
+ if (pd->state & OZ_PD_S_CONNECTED)
+ apps = pd->total_apps;
+ spin_unlock_bh(&g_polling_lock);
+ if (apps)
+ oz_pd_heartbeat(pd, apps);
+
+ oz_pd_put(pd);
+}
+/*------------------------------------------------------------------------------
+ * Context: softirq
+ */
+void oz_pd_timeout_handler(unsigned long data)
+{
+ int type;
+ struct oz_pd *pd = (struct oz_pd *)data;
+
+ spin_lock_bh(&g_polling_lock);
+ type = pd->timeout_type;
+ spin_unlock_bh(&g_polling_lock);
switch (type) {
case OZ_TIMER_TOUT:
+ oz_trace_msg(M, "OZ_TIMER_TOUT:\n");
oz_pd_sleep(pd);
break;
case OZ_TIMER_STOP:
+ oz_trace_msg(M, "OZ_TIMER_STOP:\n");
oz_pd_stop(pd);
break;
- case OZ_TIMER_HEARTBEAT: {
- u16 apps = 0;
- spin_lock_bh(&g_polling_lock);
- pd->heartbeat_requested = 0;
- if (pd->state & OZ_PD_S_CONNECTED)
- apps = pd->total_apps;
- spin_unlock_bh(&g_polling_lock);
- if (apps)
- oz_pd_heartbeat(pd, apps);
- }
- break;
}
+ oz_pd_put(pd);
}
/*------------------------------------------------------------------------------
- * Context: softirq
+ * Context: Interrupt
*/
-static void oz_protocol_timer(unsigned long arg)
+enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer)
{
- struct oz_timer *t;
- struct oz_timer *t2;
struct oz_pd *pd;
- spin_lock_bh(&g_polling_lock);
- if (!g_cur_timer) {
- /* This happens if we remove the current timer but can't stop
- * the timer from firing. In this case just get out.
- */
- oz_event_log(OZ_EVT_TIMER, 0, 0, 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();
+
+ pd = container_of(timer, struct oz_pd, heartbeat);
+ hrtimer_forward(timer,
+ hrtimer_get_expires(timer), pd->pulse_period);
+ oz_pd_get(pd);
+ tasklet_schedule(&pd->heartbeat_tasklet);
+ return HRTIMER_RESTART;
}
/*------------------------------------------------------------------------------
- * Context: softirq
+ * Context: Interrupt
*/
-static void oz_protocol_timer_start(void)
+enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer)
{
- spin_lock_bh(&g_polling_lock);
- if (!list_empty(&g_timer_list)) {
- g_cur_timer =
- container_of(g_timer_list.next, struct oz_timer, link);
- if (g_timer_state == OZ_TIMER_SET) {
- oz_event_log(OZ_EVT_TIMER_CTRL, 3,
- (u16)g_cur_timer->type, 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);
+ struct oz_pd *pd;
+
+ pd = container_of(timer, struct oz_pd, timeout);
+ oz_pd_get(pd);
+ tasklet_schedule(&pd->timeout_tasklet);
+ return HRTIMER_NORESTART;
}
/*------------------------------------------------------------------------------
* Context: softirq or process
*/
-void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time,
- int remove)
+void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time)
{
- struct list_head *e;
- struct oz_timer *t = 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--;
+ spin_lock_bh(&g_polling_lock);
+ switch (type) {
+ case OZ_TIMER_TOUT:
+ case OZ_TIMER_STOP:
+ if (hrtimer_active(&pd->timeout)) {
+ hrtimer_set_expires(&pd->timeout, ktime_set(due_time /
+ MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
+ NSEC_PER_MSEC));
+ hrtimer_start_expires(&pd->timeout, HRTIMER_MODE_REL);
} else {
- t = kmalloc(sizeof(struct oz_timer), GFP_ATOMIC);
- }
- if (t) {
- t->pd = pd;
- t->type = type;
- oz_pd_get(pd);
+ hrtimer_start(&pd->timeout, ktime_set(due_time /
+ MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
+ NSEC_PER_MSEC), HRTIMER_MODE_REL);
}
+ 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;
}
- 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);
- }
+ spin_unlock_bh(&g_polling_lock);
}
/*------------------------------------------------------------------------------
* Context: softirq or process
*/
void oz_pd_request_heartbeat(struct oz_pd *pd)
{
- unsigned long now = jiffies;
- unsigned long t;
- spin_lock(&g_polling_lock);
- if (pd->heartbeat_requested) {
- spin_unlock(&g_polling_lock);
- return;
- }
- if (pd->pulse_period_j)
- t = ((now / pd->pulse_period_j) + 1) * pd->pulse_period_j;
- else
- t = now + 1;
- pd->heartbeat_requested = 1;
- spin_unlock(&g_polling_lock);
- oz_timer_add(pd, OZ_TIMER_HEARTBEAT, t, 0);
+ oz_timer_add(pd, OZ_TIMER_HEARTBEAT, OZ_QUANTUM);
}
/*------------------------------------------------------------------------------
* Context: softirq or process
@@ -760,7 +605,6 @@ 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 == 0)
return 0;
@@ -792,11 +636,11 @@ static int oz_pkt_recv(struct sk_buff *skb, struct net_device *dev,
/*------------------------------------------------------------------------------
* Context: process
*/
-void oz_binding_add(char *net_dev)
+void oz_binding_add(const char *net_dev)
{
struct oz_binding *binding;
- binding = kmalloc(sizeof(struct oz_binding), GFP_ATOMIC);
+ binding = kmalloc(sizeof(struct oz_binding), GFP_KERNEL);
if (binding) {
binding->ptype.type = __constant_htons(OZ_ETHERTYPE);
binding->ptype.func = oz_pkt_recv;
@@ -817,8 +661,7 @@ void oz_binding_add(char *net_dev)
if (binding) {
dev_add_pack(&binding->ptype);
spin_lock_bh(&g_binding_lock);
- binding->next = g_binding;
- g_binding = binding;
+ list_add_tail(&binding->link, &g_binding);
spin_unlock_bh(&g_binding_lock);
}
}
@@ -826,7 +669,7 @@ void oz_binding_add(char *net_dev)
/*------------------------------------------------------------------------------
* Context: process
*/
-static int compare_binding_name(char *s1, char *s2)
+static int compare_binding_name(const char *s1, const char *s2)
{
int i;
for (i = 0; i < OZ_MAX_BINDING_LEN; i++) {
@@ -864,37 +707,52 @@ static void pd_stop_all_for_device(struct net_device *net_dev)
/*------------------------------------------------------------------------------
* Context: process
*/
-void oz_binding_remove(char *net_dev)
+void oz_binding_remove(const char *net_dev)
{
- struct oz_binding *binding = 0;
- struct oz_binding **link;
+ struct oz_binding *binding = NULL;
+ int found = 0;
+
oz_trace("Removing binding: %s\n", net_dev);
spin_lock_bh(&g_binding_lock);
- binding = g_binding;
- link = &g_binding;
- while (binding) {
+ list_for_each_entry(binding, &g_binding, link) {
if (compare_binding_name(binding->name, net_dev)) {
oz_trace("Binding '%s' found\n", net_dev);
- *link = binding->next;
+ found = 1;
break;
- } else {
- link = &binding;
- binding = binding->next;
}
}
spin_unlock_bh(&g_binding_lock);
- if (binding) {
+ if (found) {
dev_remove_pack(&binding->ptype);
if (binding->ptype.dev) {
dev_put(binding->ptype.dev);
pd_stop_all_for_device(binding->ptype.dev);
}
+ list_del(&binding->link);
kfree(binding);
}
}
/*------------------------------------------------------------------------------
* Context: process
*/
+int oz_get_binding_list(char *buf, int max_if)
+{
+ struct oz_binding *binding = 0;
+ int count = 0;
+
+ spin_lock_bh(&g_binding_lock);
+ list_for_each_entry(binding, &g_binding, link) {
+ if (count++ > max_if)
+ break;
+ memcpy(buf, binding->name, OZ_MAX_BINDING_LEN);
+ buf += OZ_MAX_BINDING_LEN;
+ }
+ spin_unlock_bh(&g_binding_lock);
+ return count;
+}
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
static char *oz_get_next_device_name(char *s, char *dname, int max_size)
{
while (*s == ',')
@@ -922,7 +780,6 @@ int oz_protocol_init(char *devs)
oz_binding_add(d);
}
}
- init_timer(&g_timer);
return 0;
}
/*------------------------------------------------------------------------------
@@ -944,6 +801,32 @@ int oz_get_pd_list(struct oz_mac_addr *addr, int max_count)
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 89aea28bd8d5..9b100a5b479c 100644
--- a/drivers/staging/ozwpan/ozproto.h
+++ b/drivers/staging/ozwpan/ozproto.h
@@ -7,28 +7,25 @@
#define _OZPROTO_H
#include <asm/byteorder.h>
-#include "ozconfig.h"
#include "ozappif.h"
#define OZ_ALLOCATED_SPACE(__x) (LL_RESERVED_SPACE(__x)+(__x)->needed_tailroom)
-/* Converts millisecs to jiffies.
- */
-#define oz_ms_to_jiffies(__x) (((__x)*1000)/HZ)
-/* Quantum milliseconds.
- */
-#define OZ_QUANTUM_MS 8
-/* Quantum jiffies
- */
-#define OZ_QUANTUM_J (oz_ms_to_jiffies(OZ_QUANTUM_MS))
+/* Quantum in MS */
+#define OZ_QUANTUM 8
/* Default timeouts.
*/
-#define OZ_CONNECTION_TOUT_J (2*HZ)
-#define OZ_PRESLEEP_TOUT_J (11*HZ)
+#define OZ_PRESLEEP_TOUT 11
/* Maximun sizes of tx frames. */
-#define OZ_MAX_TX_SIZE 1514
+#define OZ_MAX_TX_SIZE 760
+
+/* Maximum number of uncompleted isoc frames that can be pending in network. */
+#define OZ_MAX_SUBMITTED_ISOC 16
+
+/* Maximum number of uncompleted isoc frames that can be pending in Tx Queue. */
+#define OZ_MAX_TX_QUEUE_ISOC 32
/* Application handler functions.
*/
@@ -57,13 +54,17 @@ 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(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_binding_add(const char *net_dev);
+void oz_binding_remove(const char *net_dev);
+void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time);
void oz_timer_delete(struct oz_pd *pd, int type);
void oz_pd_request_heartbeat(struct oz_pd *pd);
void oz_polling_lock_bh(void);
void oz_polling_unlock_bh(void);
-
+void oz_pd_heartbeat_handler(unsigned long data);
+void oz_pd_timeout_handler(unsigned long data);
+enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer);
+enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer);
+int oz_get_pd_status_list(u8 *pd_list, int max_count);
+int oz_get_binding_list(char *buf, int max_if);
#endif /* _OZPROTO_H */
diff --git a/drivers/staging/ozwpan/ozprotocol.h b/drivers/staging/ozwpan/ozprotocol.h
index b3e7d77f3fff..ee76c2e2e308 100644
--- a/drivers/staging/ozwpan/ozprotocol.h
+++ b/drivers/staging/ozwpan/ozprotocol.h
@@ -27,17 +27,51 @@ struct oz_elt {
u8 length;
} PACKED;
-#define oz_next_elt(__elt) \
- (struct oz_elt *)((u8 *)((__elt) + 1) + (__elt)->length)
+/* This is an extended element header.
+ */
+struct oz_ext_elt {
+ u8 type;
+ u16 length;
+} PACKED;
+
+
+
+#define oz_is_ext_elt(__elt) \
+ (((struct oz_elt *)(__elt))->type >= OZ_ELT_EXTENDED)
+
+#define oz_elt_hdr_len(__elt) \
+ (int)(oz_is_ext_elt(__elt) ? \
+ (sizeof(struct oz_ext_elt)) \
+ : (sizeof(struct oz_elt)))
+
+#define oz_elt_data_len(__elt) \
+ (int)(oz_is_ext_elt(__elt) ? \
+ (le16_to_cpu((((struct oz_ext_elt *)(__elt))->length))) \
+ : (__elt)->length)
+
+#define oz_elt_len(__elt) \
+ (oz_elt_hdr_len(__elt) + oz_elt_data_len(__elt))
+
+#define oz_elt_data(__elt) \
+ ((u8 *)(((u8 *)(__elt)) + oz_elt_hdr_len(__elt)))
+
+
+#define oz_next_elt(__elt) \
+ (struct oz_elt *)((u8 *)(__elt) + oz_elt_len(__elt))
+
/* Protocol element IDs.
*/
+#define OZ_ELT_EXTENDED 0xC0
+#define OZ_ELT_ID_MASK 0x3F
#define OZ_ELT_CONNECT_REQ 0x06
#define OZ_ELT_CONNECT_RSP 0x07
#define OZ_ELT_DISCONNECT 0x08
#define OZ_ELT_UPDATE_PARAM_REQ 0x11
#define OZ_ELT_FAREWELL_REQ 0x12
#define OZ_ELT_APP_DATA 0x31
+#define OZ_ELT_APP_DATA_EX (OZ_ELT_EXTENDED|OZ_ELT_APP_DATA)
+
/* This is the Ozmo header which is the first Ozmo specific part
* of a frame and comes after the MAC header.
@@ -65,6 +99,10 @@ 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 {
@@ -73,13 +111,14 @@ struct oz_elt_connect_req {
u8 pd_info;
u8 session_id;
u8 presleep;
- u8 resv2;
+ u8 ms_isoc_latency;
u8 host_vendor;
u8 keep_alive;
u16 apps;
u8 max_len_div16;
u8 ms_per_isoc;
- u8 resv3[2];
+ u8 up_audio_buf;
+ u8 ms_per_elt;
} PACKED;
/* mode field bits.
@@ -89,6 +128,7 @@ 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.
*/
@@ -137,7 +177,10 @@ struct oz_app_hdr {
#define OZ_APPID_UNUSED1 0x2
#define OZ_APPID_UNUSED2 0x3
#define OZ_APPID_SERIAL 0x4
-#define OZ_APPID_MAX OZ_APPID_SERIAL
+#define OZ_APPID_UNUSED3 0x5
+#define OZ_APPID_UNUSED4 0x6
+#define OZ_APPID_TFTP 0x7
+#define OZ_APPID_MAX OZ_APPID_TFTP
#define OZ_NB_APPS (OZ_APPID_MAX+1)
/* USB header common to all elements for the USB application.
diff --git a/drivers/staging/ozwpan/oztrace.c b/drivers/staging/ozwpan/oztrace.c
index 353ead24fd7d..6bb22572dd2a 100644
--- a/drivers/staging/ozwpan/oztrace.c
+++ b/drivers/staging/ozwpan/oztrace.c
@@ -3,34 +3,156 @@
* Released under the GNU General Public License Version 2 (GPLv2).
* -----------------------------------------------------------------------------
*/
-#include "ozconfig.h"
#include "oztrace.h"
+#define CREATE_TRACE_POINTS
+#include "ozeventtrace.h"
-#ifdef WANT_VERBOSE_TRACE
-unsigned long trace_flags =
- 0
-#ifdef WANT_TRACE_STREAM
- | OZ_TRACE_STREAM
-#endif /* WANT_TRACE_STREAM */
-#ifdef WANT_TRACE_URB
- | OZ_TRACE_URB
-#endif /* WANT_TRACE_URB */
-
-#ifdef WANT_TRACE_CTRL_DETAIL
- | OZ_TRACE_CTRL_DETAIL
-#endif /* WANT_TRACE_CTRL_DETAIL */
-
-#ifdef WANT_TRACE_HUB
- | OZ_TRACE_HUB
-#endif /* WANT_TRACE_HUB */
-
-#ifdef WANT_TRACE_RX_FRAMES
- | OZ_TRACE_RX_FRAMES
-#endif /* WANT_TRACE_RX_FRAMES */
-
-#ifdef WANT_TRACE_TX_FRAMES
- | OZ_TRACE_TX_FRAMES
-#endif /* WANT_TRACE_TX_FRAMES */
- ;
-#endif /* WANT_VERBOSE_TRACE */
+#define OZ_TRACE_DUMP_SKB_LEN_MAX 32
+#define OZ_TRACE_DUMP_URB_LEN_MAX 16
+u32 g_debug =
+#ifdef WANT_TRACE_DATA_FLOW
+ TRC_M|TRC_R|TRC_T|TRC_S|TRC_E|TRC_C;
+#else
+ 0;
+#endif
+
+void (*func[]) (char *fmt, va_list arg) = {
+ trace_hcd_msg_evt,
+ trace_isoc_msg_evt,
+ trace_info_msg_evt
+};
+
+void oz_dump_data(char *buf, unsigned char *data, int len, int lmt)
+{
+ int i = 0;
+ if (len > lmt)
+ len = lmt;
+ while (len--) {
+ *buf = (*data>>4) + '0';
+ if (*data > (0xA0-1))
+ *buf += 'A' - '9' - 1;
+ *++buf = (*data++&0xF) + '0';
+ if (*buf > '9')
+ *buf += 'A' - '9' - 1;
+ if (buf++ && !(++i%4))
+ *buf++ = ' ';
+ }
+ *buf++ = '\n';
+ *buf = 0;
+}
+
+void oz_trace_f_urb_in(struct urb *urb)
+{
+ int i = 0;
+ char buf[128*2];
+ int endpoint = usb_pipeendpoint(urb->pipe);
+
+ if (usb_pipein(urb->pipe))
+ endpoint |= 0x80;
+
+ if (endpoint == 0x00 || endpoint == 0x80) {
+ i += sprintf(&buf[i], "OZ S %08X %02X %02X ",
+ (unsigned int)((uintptr_t)urb), endpoint,
+ urb->transfer_buffer_length);
+
+ oz_dump_data(&buf[i], urb->setup_packet, 8, 8);
+
+ } else {
+ i += sprintf(&buf[i], "OZ S %08X %02X %02X ",
+ (unsigned int)((uintptr_t)urb), endpoint,
+ urb->transfer_buffer_length);
+ if (!usb_pipein(urb->pipe)) {
+ oz_dump_data(&buf[i], (u8 *)(urb->transfer_buffer),
+ urb->transfer_buffer_length,
+ OZ_TRACE_DUMP_URB_LEN_MAX);
+
+ } else {
+ oz_dump_data(&buf[i], NULL, 0, 0);
+ }
+
+ }
+ printk(buf);
+}
+
+void oz_trace_f_urb_out(struct urb *urb, int status)
+{
+ int i = 0;
+ char buf[128*2];
+ int endpoint = usb_pipeendpoint(urb->pipe);
+ int length = urb->actual_length;
+
+ if (usb_pipeisoc(urb->pipe))
+ length = urb->transfer_buffer_length;
+
+ if (usb_pipein(urb->pipe))
+ endpoint |= 0x80;
+
+ if (status != 0) {
+ printk("OZ E %08X %08X\n",
+ (unsigned int)((uintptr_t)urb), status);
+ } else {
+ i += sprintf(&buf[i], "OZ C %08X %02X %02X ",
+ (unsigned int)((uintptr_t)urb),
+ endpoint, urb->actual_length);
+
+ if (usb_pipein(urb->pipe)) {
+ oz_dump_data(&buf[i],
+ (u8 *)(urb->transfer_buffer),
+ urb->actual_length,
+ OZ_TRACE_DUMP_URB_LEN_MAX);
+ } else {
+ oz_dump_data(&buf[i], NULL, 0, 0);
+ }
+ printk(buf);
+ }
+}
+
+void oz_trace_f_skb(struct sk_buff *skb, char dir)
+{
+ int i = 0;
+ char buf[128*2];
+ int len = skb->len;
+
+ if (dir == 'T')
+ len -= 14;
+
+ i += sprintf(&buf[i], "OZ %c %04X ", dir, len);
+ oz_dump_data(&buf[i], (u8 *)skb_network_header(skb),
+ len, OZ_TRACE_DUMP_SKB_LEN_MAX);
+ printk(buf);
+}
+
+void oz_trace_f_dbg(void)
+{
+}
+
+void trace_dbg_msg(int c, char *fmt, ...)
+{
+ va_list arg;
+
+ va_start(arg, fmt);
+ func[c](fmt, arg);
+ va_end(arg);
+}
+
+void trace_debug_log(char *log_type, ...)
+{
+ va_list arg;
+ char *fmt;
+
+ va_start(arg, log_type);
+ fmt = va_arg(arg, char *);
+ switch (*log_type) {
+ case 'H':
+ trace_hcd_msg_evt(fmt, arg);
+ break;
+ case 'I':
+ trace_isoc_msg_evt(fmt, arg);
+ break;
+ default:
+ trace_info_msg_evt(fmt, arg);
+ break;
+ }
+ va_end(arg);
+}
diff --git a/drivers/staging/ozwpan/oztrace.h b/drivers/staging/ozwpan/oztrace.h
index 8293b24c5a77..fe1322104c49 100644
--- a/drivers/staging/ozwpan/oztrace.h
+++ b/drivers/staging/ozwpan/oztrace.h
@@ -5,31 +5,93 @@
*/
#ifndef _OZTRACE_H_
#define _OZTRACE_H_
-#include "ozconfig.h"
-
-#define TRACE_PREFIX KERN_ALERT "OZWPAN: "
-
-#ifdef WANT_TRACE
-#define oz_trace(...) printk(TRACE_PREFIX __VA_ARGS__)
-#ifdef WANT_VERBOSE_TRACE
-extern unsigned long trace_flags;
-#define oz_trace2(_flag, ...) \
- do { if (trace_flags & _flag) printk(TRACE_PREFIX __VA_ARGS__); \
- } while (0)
-#else
-#define oz_trace2(...)
-#endif /* #ifdef WANT_VERBOSE_TRACE */
-#else
-#define oz_trace(...)
-#define oz_trace2(...)
-#endif /* #ifdef WANT_TRACE */
-
-#define OZ_TRACE_STREAM 0x1
-#define OZ_TRACE_URB 0x2
-#define OZ_TRACE_CTRL_DETAIL 0x4
-#define OZ_TRACE_HUB 0x8
-#define OZ_TRACE_RX_FRAMES 0x10
-#define OZ_TRACE_TX_FRAMES 0x20
+#include <linux/usb.h>
+#include <linux/netdevice.h>
+#include "ozeventtrace.h"
+
+extern struct device *g_oz_wpan_dev;
+
+#define oz_trace(fmt, ...) \
+ do { dev_dbg(g_oz_wpan_dev, fmt, ##__VA_ARGS__); } while (0)
+
+void oz_trace_f_urb_out(struct urb *urb, int status);
+void oz_trace_f_urb_in(struct urb *urb);
+void oz_trace_f_skb(struct sk_buff *skb, char dir);
+void oz_trace_f_dbg(void);
+void trace_dbg_msg(int c, char *fmt, ...);
+void trace_debug_log(char *log_type, ...);
+
+extern u32 g_debug;
+
+#define TRC_A 0x00000001
+#define TRC_B 0x00000002
+#define TRC_C 0x00000004 /* urb Completion */
+#define TRC_D 0x00000008 /* Debug */
+#define TRC_E 0x00000010 /* urb Error */
+#define TRC_F 0x00000020
+#define TRC_G 0x00000040
+#define TRC_H 0x00000080 /* Hcd message */
+#define TRC_I 0x00000100 /* Isoc buffer depth */
+#define TRC_J 0x00000200
+#define TRC_K 0x00000400
+#define TRC_L 0x00000800
+#define TRC_M 0x00001000 /* Message */
+#define TRC_N 0x00002000
+#define TRC_O 0x00004000
+#define TRC_P 0x00008000
+#define TRC_Q 0x00010000
+#define TRC_R 0x00020000 /* Rx Ozmo frame */
+#define TRC_S 0x00040000 /* urb Submission */
+#define TRC_T 0x00080000 /* Tx ozmo frame */
+#define TRC_U 0x00100000
+#define TRC_V 0x00200000
+#define TRC_W 0x00400000
+#define TRC_X 0x00800000
+#define TRC_Y 0x01000000
+#define TRC_Z 0x02000000
+
+
+#define oz_trace_urb_out(u, s) \
+ do { if (!g_debug) \
+ trace_urb_out(u, s); \
+ else if ((g_debug & TRC_C) || ((g_debug & TRC_E) && (u->status != 0))) \
+ oz_trace_f_urb_out(u, s); } while (0)
+
+#define oz_trace_urb_in(u) \
+ do { if (!g_debug) \
+ trace_urb_in(u); \
+ else if (g_debug & TRC_S) \
+ oz_trace_f_urb_in(u); } while (0)
+
+#define oz_trace_skb(u, d) \
+ do { if ((!g_debug) && ('T' == d)) \
+ trace_tx_frame(u); \
+ else if ((!g_debug) && ('R' == d)) \
+ trace_rx_frame(u); \
+ else if ((('T' == d) && (g_debug & TRC_T)) || \
+ (('R' == d) && (g_debug & TRC_R))) \
+ oz_trace_f_skb(u, d); } while(0)
+
+#define oz_trace_msg(f, ...) \
+ do { if (!g_debug) \
+ trace_debug_log(#f, __VA_ARGS__); \
+ else if (g_debug & TRC_##f) \
+ printk("OZ " #f " " __VA_ARGS__); } while(0)
+
+enum {
+ TRACE_HCD_MSG,
+ TRACE_ISOC_MSG,
+ TRACE_INFO_MSG
+};
+
+#define trace_hcd_msg(fmt, ...)\
+ trace_dbg_msg(TRACE_HCD_MSG, fmt, ##__VA_ARGS__)
+
+#define trace_isoc_msg(fmt, ...)\
+ trace_dbg_msg(TRACE_ISOC_MSG, fmt, ##__VA_ARGS__)
+
+#define trace_info_msg(fmt, ...)\
+ trace_dbg_msg(TRACE_INFO_MSG, fmt, ##__VA_ARGS__)
#endif /* Sentry */
diff --git a/drivers/staging/ozwpan/ozurbparanoia.c b/drivers/staging/ozwpan/ozurbparanoia.c
index 55b9afbbe47b..b05519534444 100644
--- a/drivers/staging/ozwpan/ozurbparanoia.c
+++ b/drivers/staging/ozwpan/ozurbparanoia.c
@@ -4,7 +4,6 @@
* -----------------------------------------------------------------------------
*/
#include <linux/usb.h>
-#include "ozconfig.h"
#ifdef WANT_URB_PARANOIA
#include "ozurbparanoia.h"
#include "oztrace.h"
@@ -22,7 +21,7 @@ void oz_remember_urb(struct urb *urb)
spin_lock_irqsave(&g_urb_mem_lock, irq_state);
if (g_nb_urbs < OZ_MAX_URBS) {
g_urb_memory[g_nb_urbs++] = urb;
- oz_trace("%lu: urb up = %d %p\n", jiffies, g_nb_urbs, urb);
+ oz_trace("urb up = %d %p\n", g_nb_urbs, urb);
} else {
oz_trace("ERROR urb buffer full\n");
}
@@ -42,8 +41,8 @@ int oz_forget_urb(struct urb *urb)
if (--g_nb_urbs > i)
memcpy(&g_urb_memory[i], &g_urb_memory[i+1],
(g_nb_urbs - i) * sizeof(struct urb *));
- oz_trace("%lu: urb down = %d %p\n",
- jiffies, g_nb_urbs, urb);
+ oz_trace("urb down = %d %p\n",
+ g_nb_urbs, urb);
}
}
spin_unlock_irqrestore(&g_urb_mem_lock, irq_state);
diff --git a/drivers/staging/ozwpan/ozusbif.h b/drivers/staging/ozwpan/ozusbif.h
index 3acf5980d7cc..7c59b22f8b9f 100644
--- a/drivers/staging/ozwpan/ozusbif.h
+++ b/drivers/staging/ozwpan/ozusbif.h
@@ -34,10 +34,16 @@ void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status,
void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode,
u8 *data, int data_len);
+void oz_hcd_mark_urb_submitted(void *hport, int ep_ix, u8 req_id);
+
/* Indication functions.
*/
void oz_hcd_data_ind(void *hport, u8 endpoint, 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 9e74f9602384..3dae52f0af18 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 implemenation of this service uses ozhcd.c to implement a USB HCD.
+ * The implementation of this service uses ozhcd.c to implement a USB HCD.
* -----------------------------------------------------------------------------
*/
#include <linux/init.h>
@@ -18,7 +18,6 @@
#include <linux/errno.h>
#include <linux/input.h>
#include <asm/unaligned.h>
-#include "ozconfig.h"
#include "ozprotocol.h"
#include "ozeltbuf.h"
#include "ozpd.h"
@@ -27,14 +26,12 @@
#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();
}
/*------------------------------------------------------------------------------
@@ -43,7 +40,6 @@ 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();
}
/*------------------------------------------------------------------------------
@@ -55,7 +51,6 @@ 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 = 0;
- oz_event_log(OZ_EVT_SERVICE, 3, OZ_APPID_USB, 0, resume);
if (resume) {
oz_trace("USB service resumed.\n");
return 0;
@@ -81,7 +76,6 @@ int oz_usb_start(struct oz_pd *pd, int resume)
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) {
@@ -99,7 +93,6 @@ int oz_usb_start(struct oz_pd *pd, int resume)
} else {
usb_ctx->hport = oz_hcd_pd_arrived(usb_ctx);
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] = 0;
spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
@@ -117,7 +110,6 @@ 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;
@@ -127,7 +119,8 @@ void oz_usb_stop(struct oz_pd *pd, int pause)
pd->app_ctx[OZ_APPID_USB-1] = 0;
spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
if (usb_ctx) {
- unsigned long tout = jiffies + HZ;
+ struct timespec ts, now;
+ getnstimeofday(&ts);
oz_trace("USB service stopping...\n");
usb_ctx->stopped = 1;
/* At this point the reference count on the usb context should
@@ -136,10 +129,13 @@ void oz_usb_stop(struct oz_pd *pd, int pause)
* should get in but someone may already be in. So wait
* until they leave but timeout after 1 second.
*/
- while ((atomic_read(&usb_ctx->ref_count) > 2) &&
- time_before(jiffies, tout))
- ;
- oz_trace("USB service stopped.\n");
+ while ((atomic_read(&usb_ctx->ref_count) > 2)) {
+ getnstimeofday(&now);
+ /*Approx 1 Sec. this is not perfect calculation*/
+ if (now.tv_sec != ts.tv_sec)
+ break;
+ }
+ oz_trace_msg(M, "USB service stopped.\n");
oz_hcd_pd_departed(usb_ctx->hport);
/* Release the reference taken in oz_usb_start.
*/
@@ -165,7 +161,6 @@ void oz_usb_put(void *hpd)
{
struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
if (atomic_dec_and_test(&usb_ctx->ref_count)) {
- oz_trace("Dealloc USB context.\n");
oz_pd_put(usb_ctx->pd);
kfree(usb_ctx);
}
@@ -200,7 +195,6 @@ int oz_usb_stream_create(void *hpd, u8 ep_num)
{
struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
struct oz_pd *pd = usb_ctx->pd;
- oz_trace("oz_usb_stream_create(0x%x)\n", ep_num);
if (pd->mode & OZ_F_ISOC_NO_ELTS) {
oz_isoc_stream_create(pd, ep_num);
} else {
@@ -222,7 +216,6 @@ int oz_usb_stream_delete(void *hpd, u8 ep_num)
if (usb_ctx) {
struct oz_pd *pd = usb_ctx->pd;
if (pd) {
- oz_trace("oz_usb_stream_delete(0x%x)\n", ep_num);
if (pd->mode & OZ_F_ISOC_NO_ELTS) {
oz_isoc_stream_delete(pd, ep_num);
} else {
diff --git a/drivers/staging/ozwpan/ozusbsvc1.c b/drivers/staging/ozwpan/ozusbsvc1.c
index 66bd576bb5e9..a66d2adca434 100644
--- a/drivers/staging/ozwpan/ozusbsvc1.c
+++ b/drivers/staging/ozwpan/ozusbsvc1.c
@@ -13,7 +13,6 @@
#include <linux/errno.h>
#include <linux/input.h>
#include <asm/unaligned.h>
-#include "ozconfig.h"
#include "ozprotocol.h"
#include "ozeltbuf.h"
#include "ozpd.h"
@@ -22,10 +21,24 @@
#include "ozhcd.h"
#include "oztrace.h"
#include "ozusbsvc.h"
-#include "ozevent.h"
/*------------------------------------------------------------------------------
*/
#define MAX_ISOC_FIXED_DATA (253-sizeof(struct oz_isoc_fixed))
+
+/*------------------------------------------------------------------------------
+ * Context: softirq
+ */
+static void oz_usb_setup_elt_completion_callback(struct oz_pd *pd, long context)
+{
+ struct oz_usb_ctx *ctx;
+ spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]);
+ ctx = (struct oz_usb_ctx *)pd->app_ctx[OZ_APPID_USB-1];
+ if (ctx) {
+ u8 req_id = (u8)context;
+ oz_hcd_mark_urb_submitted(ctx->hport, 0, req_id);
+ }
+ spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
+}
/*------------------------------------------------------------------------------
* Context: softirq
*/
@@ -63,16 +76,12 @@ int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type,
struct oz_get_desc_req *body;
struct oz_elt_buf *eb = &pd->elt_buff;
struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
- oz_trace(" req_type = 0x%x\n", req_type);
- oz_trace(" desc_type = 0x%x\n", desc_type);
- oz_trace(" index = 0x%x\n", index);
- oz_trace(" windex = 0x%x\n", windex);
- oz_trace(" offset = 0x%x\n", offset);
- oz_trace(" len = 0x%x\n", len);
if (len > 200)
len = 200;
if (ei == 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);
@@ -99,6 +108,8 @@ 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);
@@ -120,6 +131,8 @@ 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);
@@ -144,6 +157,8 @@ 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;
@@ -167,6 +182,8 @@ 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);
@@ -190,10 +207,7 @@ int oz_usb_control_req(void *hpd, u8 req_id, struct usb_ctrlrequest *setup,
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:
@@ -381,7 +395,6 @@ void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt)
u16 offs = le16_to_cpu(get_unaligned(&body->offset));
u16 total_size =
le16_to_cpu(get_unaligned(&body->total_size));
- oz_trace("USB_REQ_GET_DESCRIPTOR - cnf\n");
oz_hcd_get_desc_cnf(usb_ctx->hport, body->req_id,
body->rcode, body->data,
data_len, offs, total_size);
@@ -435,3 +448,11 @@ void oz_usb_farewell(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len)
}
oz_usb_put(usb_ctx);
}
+/*------------------------------------------------------------------------------
+ * Context: softirq or process
+ */
+u8 oz_get_up_max_buffer_units(void *hpd)
+{
+ struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
+ return usb_ctx->pd->up_audio_buf;
+}