Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux...
David Vrabel [Fri, 2 Jan 2009 13:17:13 +0000 (13:17 +0000)]
Conflicts:

drivers/uwb/wlp/eda.c

75 files changed:
Documentation/ABI/testing/sysfs-class-uwb_rc
Documentation/usb/wusb-cbaf
drivers/usb/host/hwa-hc.c
drivers/usb/host/whci/Kbuild
drivers/usb/host/whci/asl.c
drivers/usb/host/whci/debug.c [new file with mode: 0644]
drivers/usb/host/whci/hcd.c
drivers/usb/host/whci/hw.c
drivers/usb/host/whci/int.c
drivers/usb/host/whci/pzl.c
drivers/usb/host/whci/qset.c
drivers/usb/host/whci/whcd.h
drivers/usb/host/whci/whci-hc.h
drivers/usb/host/whci/wusb.c
drivers/usb/wusbcore/cbaf.c
drivers/usb/wusbcore/crypto.c
drivers/usb/wusbcore/dev-sysfs.c
drivers/usb/wusbcore/devconnect.c
drivers/usb/wusbcore/mmc.c
drivers/usb/wusbcore/pal.c
drivers/usb/wusbcore/reservation.c
drivers/usb/wusbcore/rh.c
drivers/usb/wusbcore/security.c
drivers/usb/wusbcore/wa-nep.c
drivers/usb/wusbcore/wa-rpipe.c
drivers/usb/wusbcore/wa-xfer.c
drivers/usb/wusbcore/wusbhc.h
drivers/uwb/Makefile
drivers/uwb/address.c
drivers/uwb/allocator.c [new file with mode: 0644]
drivers/uwb/beacon.c
drivers/uwb/driver.c
drivers/uwb/drp-avail.c
drivers/uwb/drp-ie.c
drivers/uwb/drp.c
drivers/uwb/est.c
drivers/uwb/hwa-rc.c
drivers/uwb/i1480/dfu/dfu.c
drivers/uwb/i1480/dfu/mac.c
drivers/uwb/i1480/dfu/usb.c
drivers/uwb/i1480/i1480u-wlp/lc.c
drivers/uwb/i1480/i1480u-wlp/netdev.c
drivers/uwb/i1480/i1480u-wlp/rx.c
drivers/uwb/i1480/i1480u-wlp/sysfs.c
drivers/uwb/i1480/i1480u-wlp/tx.c
drivers/uwb/ie-rcv.c [new file with mode: 0644]
drivers/uwb/ie.c
drivers/uwb/lc-dev.c
drivers/uwb/lc-rc.c
drivers/uwb/neh.c
drivers/uwb/pal.c
drivers/uwb/radio.c [new file with mode: 0644]
drivers/uwb/reset.c
drivers/uwb/rsv.c
drivers/uwb/umc-bus.c
drivers/uwb/umc-dev.c
drivers/uwb/uwb-debug.c
drivers/uwb/uwb-internal.h
drivers/uwb/uwbd.c
drivers/uwb/whc-rc.c
drivers/uwb/whci.c
drivers/uwb/wlp/eda.c
drivers/uwb/wlp/messages.c
drivers/uwb/wlp/sysfs.c
drivers/uwb/wlp/txrx.c
drivers/uwb/wlp/wlp-internal.h
drivers/uwb/wlp/wlp-lc.c
drivers/uwb/wlp/wss-lc.c
include/linux/usb/wusb-wa.h
include/linux/uwb.h
include/linux/uwb/debug-cmd.h
include/linux/uwb/debug.h [deleted file]
include/linux/uwb/spec.h
include/linux/uwb/umc.h
include/linux/wlp.h

index a0d18db..6a5fd07 100644 (file)
@@ -32,14 +32,16 @@ Contact:        linux-usb@vger.kernel.org
 Description:
                 Write:
 
-                <channel> [<bpst offset>]
+                <channel>
 
-                to start beaconing on a specific channel, or stop
-                beaconing if <channel> is -1.  Valid channels depends
-                on the radio controller's supported band groups.
+                to force a specific channel to be used when beaconing,
+                or, if <channel> is -1, to prohibit beaconing.  If
+                <channel> is 0, then the default channel selection
+                algorithm will be used.  Valid channels depends on the
+                radio controller's supported band groups.
 
-                <bpst offset> may be used to try and join a specific
-                beacon group if more than one was found during a scan.
+                Reading returns the currently active channel, or -1 if
+                the radio controller is not beaconing.
 
 What:           /sys/class/uwb_rc/uwbN/scan
 Date:           July 2008
index 2e78b70..426ddaa 100644 (file)
@@ -80,12 +80,6 @@ case $1 in
     start)
         for dev in ${2:-$hdevs}
           do
-          uwb_rc=$(readlink -f $dev/uwb_rc)
-          if cat $uwb_rc/beacon | grep -q -- "-1"
-              then
-              echo 13 0 > $uwb_rc/beacon
-              echo I: started beaconing on ch 13 on $(basename $uwb_rc) >&2
-          fi
           echo $host_CHID > $dev/wusb_chid
           echo I: started host $(basename $dev) >&2
         done
@@ -95,9 +89,6 @@ case $1 in
           do
           echo 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > $dev/wusb_chid
           echo I: stopped host $(basename $dev) >&2
-          uwb_rc=$(readlink -f $dev/uwb_rc)
-          echo -1 | cat > $uwb_rc/beacon
-          echo I: stopped beaconing on $(basename $uwb_rc) >&2
         done
         ;;
     set-chid)
index 64be4d8..8582236 100644 (file)
@@ -54,7 +54,6 @@
  *                      DWA).
  */
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/workqueue.h>
 #include "../wusbcore/wa-hc.h"
 #include "../wusbcore/wusbhc.h"
 
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
-
 struct hwahc {
        struct wusbhc wusbhc;   /* has to be 1st */
        struct wahc wa;
-       u8 buffer[16];          /* for misc usb transactions */
 };
 
-/**
+/*
  * FIXME should be wusbhc
  *
  * NOTE: we need to cache the Cluster ID because later...there is no
@@ -126,7 +121,6 @@ static int hwahc_op_reset(struct usb_hcd *usb_hcd)
        struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
        struct device *dev = &hwahc->wa.usb_iface->dev;
 
-       d_fnstart(4, dev, "(hwahc %p)\n", hwahc);
        mutex_lock(&wusbhc->mutex);
        wa_nep_disarm(&hwahc->wa);
        result = __wa_set_feature(&hwahc->wa, WA_RESET);
@@ -134,7 +128,6 @@ static int hwahc_op_reset(struct usb_hcd *usb_hcd)
                dev_err(dev, "error commanding HC to reset: %d\n", result);
                goto error_unlock;
        }
-       d_printf(3, dev, "reset: waiting for device to change state\n");
        result = __wa_wait_status(&hwahc->wa, WA_STATUS_RESETTING, 0);
        if (result < 0) {
                dev_err(dev, "error waiting for HC to reset: %d\n", result);
@@ -142,7 +135,6 @@ static int hwahc_op_reset(struct usb_hcd *usb_hcd)
        }
 error_unlock:
        mutex_unlock(&wusbhc->mutex);
-       d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result);
        return result;
 }
 
@@ -155,15 +147,9 @@ static int hwahc_op_start(struct usb_hcd *usb_hcd)
        int result;
        struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd);
        struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
-       struct device *dev = &hwahc->wa.usb_iface->dev;
 
-       /* Set up a Host Info WUSB Information Element */
-       d_fnstart(4, dev, "(hwahc %p)\n", hwahc);
        result = -ENOSPC;
        mutex_lock(&wusbhc->mutex);
-       /* Start the numbering from the top so that the bottom
-        * range of the unauth addr space is used for devices,
-        * the top for HCs; use 0xfe - RC# */
        addr = wusb_cluster_id_get();
        if (addr == 0)
                goto error_cluster_id_get;
@@ -171,22 +157,14 @@ static int hwahc_op_start(struct usb_hcd *usb_hcd)
        if (result < 0)
                goto error_set_cluster_id;
 
-       result = wa_nep_arm(&hwahc->wa, GFP_KERNEL);
-       if (result < 0) {
-               dev_err(dev, "cannot listen to notifications: %d\n", result);
-               goto error_stop;
-       }
        usb_hcd->uses_new_polling = 1;
        usb_hcd->poll_rh = 1;
        usb_hcd->state = HC_STATE_RUNNING;
        result = 0;
 out:
        mutex_unlock(&wusbhc->mutex);
-       d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result);
        return result;
 
-error_stop:
-       __wa_stop(&hwahc->wa);
 error_set_cluster_id:
        wusb_cluster_id_put(wusbhc->cluster_id);
 error_cluster_id_get:
@@ -194,39 +172,6 @@ error_cluster_id_get:
 
 }
 
-/*
- * FIXME: break this function up
- */
-static int __hwahc_op_wusbhc_start(struct wusbhc *wusbhc)
-{
-       int result;
-       struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
-       struct device *dev = &hwahc->wa.usb_iface->dev;
-
-       /* Set up a Host Info WUSB Information Element */
-       d_fnstart(4, dev, "(hwahc %p)\n", hwahc);
-       result = -ENOSPC;
-
-       result = __wa_set_feature(&hwahc->wa, WA_ENABLE);
-       if (result < 0) {
-               dev_err(dev, "error commanding HC to start: %d\n", result);
-               goto error_stop;
-       }
-       result = __wa_wait_status(&hwahc->wa, WA_ENABLE, WA_ENABLE);
-       if (result < 0) {
-               dev_err(dev, "error waiting for HC to start: %d\n", result);
-               goto error_stop;
-       }
-       result = 0;
-out:
-       d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result);
-       return result;
-
-error_stop:
-       result = __wa_clear_feature(&hwahc->wa, WA_ENABLE);
-       goto out;
-}
-
 static int hwahc_op_suspend(struct usb_hcd *usb_hcd, pm_message_t msg)
 {
        struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd);
@@ -246,18 +191,6 @@ static int hwahc_op_resume(struct usb_hcd *usb_hcd)
        return -ENOSYS;
 }
 
-static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc)
-{
-       int result;
-       struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
-       struct device *dev = &hwahc->wa.usb_iface->dev;
-
-       d_fnstart(4, dev, "(hwahc %p)\n", hwahc);
-       /* Nothing for now */
-       d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result);
-       return;
-}
-
 /*
  * No need to abort pipes, as when this is called, all the children
  * has been disconnected and that has done it [through
@@ -266,21 +199,11 @@ static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc)
  */
 static void hwahc_op_stop(struct usb_hcd *usb_hcd)
 {
-       int result;
        struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd);
-       struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
-       struct wahc *wa = &hwahc->wa;
-       struct device *dev = &wa->usb_iface->dev;
 
-       d_fnstart(4, dev, "(hwahc %p)\n", hwahc);
        mutex_lock(&wusbhc->mutex);
-       wusbhc_stop(wusbhc);
-       wa_nep_disarm(&hwahc->wa);
-       result = __wa_stop(&hwahc->wa);
        wusb_cluster_id_put(wusbhc->cluster_id);
        mutex_unlock(&wusbhc->mutex);
-       d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result);
-       return;
 }
 
 static int hwahc_op_get_frame_number(struct usb_hcd *usb_hcd)
@@ -325,6 +248,54 @@ static void hwahc_op_endpoint_disable(struct usb_hcd *usb_hcd,
        rpipe_ep_disable(&hwahc->wa, ep);
 }
 
+static int __hwahc_op_wusbhc_start(struct wusbhc *wusbhc)
+{
+       int result;
+       struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
+       struct device *dev = &hwahc->wa.usb_iface->dev;
+
+       result = __wa_set_feature(&hwahc->wa, WA_ENABLE);
+       if (result < 0) {
+               dev_err(dev, "error commanding HC to start: %d\n", result);
+               goto error_stop;
+       }
+       result = __wa_wait_status(&hwahc->wa, WA_ENABLE, WA_ENABLE);
+       if (result < 0) {
+               dev_err(dev, "error waiting for HC to start: %d\n", result);
+               goto error_stop;
+       }
+       result = wa_nep_arm(&hwahc->wa, GFP_KERNEL);
+       if (result < 0) {
+               dev_err(dev, "cannot listen to notifications: %d\n", result);
+               goto error_stop;
+       }
+       return result;
+
+error_stop:
+       __wa_clear_feature(&hwahc->wa, WA_ENABLE);
+       return result;
+}
+
+static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc, int delay)
+{
+       struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
+       struct wahc *wa = &hwahc->wa;
+       u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber;
+       int ret;
+
+       ret = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0),
+                             WUSB_REQ_CHAN_STOP,
+                             USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                             delay * 1000,
+                             iface_no,
+                             NULL, 0, 1000 /* FIXME: arbitrary */);
+       if (ret == 0)
+               msleep(delay);
+
+       wa_nep_disarm(&hwahc->wa);
+       __wa_stop(&hwahc->wa);
+}
+
 /*
  * Set the UWB MAS allocation for the WUSB cluster
  *
@@ -581,11 +552,11 @@ static int wa_fill_descr(struct wahc *wa)
        itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength);
        while (itr_size >= sizeof(*hdr)) {
                hdr = (struct usb_descriptor_header *) itr;
-               d_printf(3, dev, "Extra device descriptor: "
-                        "type %02x/%u bytes @ %zu (%zu left)\n",
-                        hdr->bDescriptorType, hdr->bLength,
-                        (itr - usb_dev->rawdescriptors[actconfig_idx]),
-                        itr_size);
+               dev_dbg(dev, "Extra device descriptor: "
+                       "type %02x/%u bytes @ %zu (%zu left)\n",
+                       hdr->bDescriptorType, hdr->bLength,
+                       (itr - usb_dev->rawdescriptors[actconfig_idx]),
+                       itr_size);
                if (hdr->bDescriptorType == USB_DT_WIRE_ADAPTER)
                        goto found;
                itr += hdr->bLength;
@@ -794,7 +765,6 @@ static void hwahc_destroy(struct hwahc *hwahc)
 {
        struct wusbhc *wusbhc = &hwahc->wusbhc;
 
-       d_fnstart(1, NULL, "(hwahc %p)\n", hwahc);
        mutex_lock(&wusbhc->mutex);
        __wa_destroy(&hwahc->wa);
        wusbhc_destroy(&hwahc->wusbhc);
@@ -804,7 +774,6 @@ static void hwahc_destroy(struct hwahc *hwahc)
        usb_put_intf(hwahc->wa.usb_iface);
        usb_put_dev(hwahc->wa.usb_dev);
        mutex_unlock(&wusbhc->mutex);
-       d_fnend(1, NULL, "(hwahc %p) = void\n", hwahc);
 }
 
 static void hwahc_init(struct hwahc *hwahc)
@@ -821,7 +790,6 @@ static int hwahc_probe(struct usb_interface *usb_iface,
        struct hwahc *hwahc;
        struct device *dev = &usb_iface->dev;
 
-       d_fnstart(4, dev, "(%p, %p)\n", usb_iface, id);
        result = -ENOMEM;
        usb_hcd = usb_create_hcd(&hwahc_hc_driver, &usb_iface->dev, "wusb-hwa");
        if (usb_hcd == NULL) {
@@ -848,7 +816,6 @@ static int hwahc_probe(struct usb_interface *usb_iface,
                dev_err(dev, "Cannot setup phase B of WUSBHC: %d\n", result);
                goto error_wusbhc_b_create;
        }
-       d_fnend(4, dev, "(%p, %p) = 0\n", usb_iface, id);
        return 0;
 
 error_wusbhc_b_create:
@@ -858,7 +825,6 @@ error_add_hcd:
 error_hwahc_create:
        usb_put_hcd(usb_hcd);
 error_alloc:
-       d_fnend(4, dev, "(%p, %p) = %d\n", usb_iface, id, result);
        return result;
 }
 
@@ -872,16 +838,12 @@ static void hwahc_disconnect(struct usb_interface *usb_iface)
        wusbhc = usb_hcd_to_wusbhc(usb_hcd);
        hwahc = container_of(wusbhc, struct hwahc, wusbhc);
 
-       d_fnstart(1, NULL, "(hwahc %p [usb_iface %p])\n", hwahc, usb_iface);
        wusbhc_b_destroy(&hwahc->wusbhc);
        usb_remove_hcd(usb_hcd);
        hwahc_destroy(hwahc);
        usb_put_hcd(usb_hcd);
-       d_fnend(1, NULL, "(hwahc %p [usb_iface %p]) = void\n", hwahc,
-               usb_iface);
 }
 
-/** USB device ID's that we handle */
 static struct usb_device_id hwahc_id_table[] = {
        /* FIXME: use class labels for this */
        { USB_INTERFACE_INFO(0xe0, 0x02, 0x01), },
@@ -898,18 +860,7 @@ static struct usb_driver hwahc_driver = {
 
 static int __init hwahc_driver_init(void)
 {
-       int result;
-       result = usb_register(&hwahc_driver);
-       if (result < 0) {
-               printk(KERN_ERR "WA-CDS: Cannot register USB driver: %d\n",
-                      result);
-               goto error_usb_register;
-       }
-       return 0;
-
-error_usb_register:
-       return result;
-
+       return usb_register(&hwahc_driver);
 }
 module_init(hwahc_driver_init);
 
index 26a3871..11e5040 100644 (file)
@@ -2,6 +2,7 @@ obj-$(CONFIG_USB_WHCI_HCD) += whci-hcd.o
 
 whci-hcd-y := \
        asl.o   \
+       debug.o \
        hcd.o   \
        hw.o    \
        init.o  \
index 4d7078e..577c0d2 100644 (file)
 #include <linux/dma-mapping.h>
 #include <linux/uwb/umc.h>
 #include <linux/usb.h>
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
 
 #include "../../wusbcore/wusbhc.h"
 
 #include "whcd.h"
 
-#if D_LOCAL >= 4
-static void dump_asl(struct whc *whc, const char *tag)
-{
-       struct device *dev = &whc->umc->dev;
-       struct whc_qset *qset;
-
-       d_printf(4, dev, "ASL %s\n", tag);
-
-       list_for_each_entry(qset, &whc->async_list, list_node) {
-               dump_qset(qset, dev);
-       }
-}
-#else
-static inline void dump_asl(struct whc *whc, const char *tag)
-{
-}
-#endif
-
-
 static void qset_get_next_prev(struct whc *whc, struct whc_qset *qset,
                               struct whc_qset **next, struct whc_qset **prev)
 {
@@ -179,11 +158,26 @@ void asl_stop(struct whc *whc)
                      1000, "stop ASL");
 }
 
+/**
+ * asl_update - request an ASL update and wait for the hardware to be synced
+ * @whc: the WHCI HC
+ * @wusbcmd: WUSBCMD value to start the update.
+ *
+ * If the WUSB HC is inactive (i.e., the ASL is stopped) then the
+ * update must be skipped as the hardware may not respond to update
+ * requests.
+ */
 void asl_update(struct whc *whc, uint32_t wusbcmd)
 {
-       whc_write_wusbcmd(whc, wusbcmd, wusbcmd);
-       wait_event(whc->async_list_wq,
-                  (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0);
+       struct wusbhc *wusbhc = &whc->wusbhc;
+
+       mutex_lock(&wusbhc->mutex);
+       if (wusbhc->active) {
+               whc_write_wusbcmd(whc, wusbcmd, wusbcmd);
+               wait_event(whc->async_list_wq,
+                          (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0);
+       }
+       mutex_unlock(&wusbhc->mutex);
 }
 
 /**
@@ -202,8 +196,6 @@ void scan_async_work(struct work_struct *work)
 
        spin_lock_irq(&whc->lock);
 
-       dump_asl(whc, "before processing");
-
        /*
         * Transerve the software list backwards so new qsets can be
         * safely inserted into the ASL without making it non-circular.
@@ -217,8 +209,6 @@ void scan_async_work(struct work_struct *work)
                update |= process_qset(whc, qset);
        }
 
-       dump_asl(whc, "after processing");
-
        spin_unlock_irq(&whc->lock);
 
        if (update) {
diff --git a/drivers/usb/host/whci/debug.c b/drivers/usb/host/whci/debug.c
new file mode 100644 (file)
index 0000000..cf2d459
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Wireless Host Controller (WHC) debug.
+ *
+ * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include "../../wusbcore/wusbhc.h"
+
+#include "whcd.h"
+
+struct whc_dbg {
+       struct dentry *di_f;
+       struct dentry *asl_f;
+       struct dentry *pzl_f;
+};
+
+void qset_print(struct seq_file *s, struct whc_qset *qset)
+{
+       struct whc_std *std;
+       struct urb *urb = NULL;
+       int i;
+
+       seq_printf(s, "qset %08x\n", (u32)qset->qset_dma);
+       seq_printf(s, "  -> %08x\n", (u32)qset->qh.link);
+       seq_printf(s, "  info: %08x %08x %08x\n",
+               qset->qh.info1, qset->qh.info2,  qset->qh.info3);
+       seq_printf(s, "  sts: %04x errs: %d\n", qset->qh.status, qset->qh.err_count);
+       seq_printf(s, "  TD: sts: %08x opts: %08x\n",
+               qset->qh.overlay.qtd.status, qset->qh.overlay.qtd.options);
+
+       for (i = 0; i < WHCI_QSET_TD_MAX; i++) {
+               seq_printf(s, "  %c%c TD[%d]: sts: %08x opts: %08x ptr: %08x\n",
+                       i == qset->td_start ? 'S' : ' ',
+                       i == qset->td_end ? 'E' : ' ',
+                       i, qset->qtd[i].status, qset->qtd[i].options,
+                       (u32)qset->qtd[i].page_list_ptr);
+       }
+       seq_printf(s, "  ntds: %d\n", qset->ntds);
+       list_for_each_entry(std, &qset->stds, list_node) {
+               if (urb != std->urb) {
+                       urb = std->urb;
+                       seq_printf(s, "  urb %p transferred: %d bytes\n", urb,
+                               urb->actual_length);
+               }
+               if (std->qtd)
+                       seq_printf(s, "    sTD[%td]: %zu bytes @ %08x\n",
+                               std->qtd - &qset->qtd[0],
+                               std->len, std->num_pointers ?
+                               (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr);
+               else
+                       seq_printf(s, "    sTD[-]: %zd bytes @ %08x\n",
+                               std->len, std->num_pointers ?
+                               (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr);
+       }
+}
+
+static int di_print(struct seq_file *s, void *p)
+{
+       struct whc *whc = s->private;
+       char buf[72];
+       int d;
+
+       for (d = 0; d < whc->n_devices; d++) {
+               struct di_buf_entry *di = &whc->di_buf[d];
+
+               bitmap_scnprintf(buf, sizeof(buf),
+                                (unsigned long *)di->availability_info, UWB_NUM_MAS);
+
+               seq_printf(s, "DI[%d]\n", d);
+               seq_printf(s, "  availability: %s\n", buf);
+               seq_printf(s, "  %c%c key idx: %d dev addr: %d\n",
+                          (di->addr_sec_info & WHC_DI_SECURE) ? 'S' : ' ',
+                          (di->addr_sec_info & WHC_DI_DISABLE) ? 'D' : ' ',
+                          (di->addr_sec_info & WHC_DI_KEY_IDX_MASK) >> 8,
+                          (di->addr_sec_info & WHC_DI_DEV_ADDR_MASK));
+       }
+       return 0;
+}
+
+static int asl_print(struct seq_file *s, void *p)
+{
+       struct whc *whc = s->private;
+       struct whc_qset *qset;
+
+       list_for_each_entry(qset, &whc->async_list, list_node) {
+               qset_print(s, qset);
+       }
+
+       return 0;
+}
+
+static int pzl_print(struct seq_file *s, void *p)
+{
+       struct whc *whc = s->private;
+       struct whc_qset *qset;
+       int period;
+
+       for (period = 0; period < 5; period++) {
+               seq_printf(s, "Period %d\n", period);
+               list_for_each_entry(qset, &whc->periodic_list[period], list_node) {
+                       qset_print(s, qset);
+               }
+       }
+       return 0;
+}
+
+static int di_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, di_print, inode->i_private);
+}
+
+static int asl_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, asl_print, inode->i_private);
+}
+
+static int pzl_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, pzl_print, inode->i_private);
+}
+
+static struct file_operations di_fops = {
+       .open    = di_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = single_release,
+       .owner   = THIS_MODULE,
+};
+
+static struct file_operations asl_fops = {
+       .open    = asl_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = single_release,
+       .owner   = THIS_MODULE,
+};
+
+static struct file_operations pzl_fops = {
+       .open    = pzl_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = single_release,
+       .owner   = THIS_MODULE,
+};
+
+void whc_dbg_init(struct whc *whc)
+{
+       if (whc->wusbhc.pal.debugfs_dir == NULL)
+               return;
+
+       whc->dbg = kzalloc(sizeof(struct whc_dbg), GFP_KERNEL);
+       if (whc->dbg == NULL)
+               return;
+
+       whc->dbg->di_f = debugfs_create_file("di", 0444,
+                                             whc->wusbhc.pal.debugfs_dir, whc,
+                                             &di_fops);
+       whc->dbg->asl_f = debugfs_create_file("asl", 0444,
+                                             whc->wusbhc.pal.debugfs_dir, whc,
+                                             &asl_fops);
+       whc->dbg->pzl_f = debugfs_create_file("pzl", 0444,
+                                             whc->wusbhc.pal.debugfs_dir, whc,
+                                             &pzl_fops);
+}
+
+void whc_dbg_clean_up(struct whc *whc)
+{
+       if (whc->dbg) {
+               debugfs_remove(whc->dbg->pzl_f);
+               debugfs_remove(whc->dbg->asl_f);
+               debugfs_remove(whc->dbg->di_f);
+               kfree(whc->dbg);
+       }
+}
index ef3ad4d..1569afd 100644 (file)
@@ -15,7 +15,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/uwb/umc.h>
@@ -92,8 +91,6 @@ static void whc_stop(struct usb_hcd *usb_hcd)
 
        mutex_lock(&wusbhc->mutex);
 
-       wusbhc_stop(wusbhc);
-
        /* stop HC */
        le_writel(0, whc->base + WUSBINTR);
        whc_write_wusbcmd(whc, WUSBCMD_RUN, 0);
@@ -276,6 +273,8 @@ static int whc_probe(struct umc_dev *umc)
                goto error_wusbhc_b_create;
        }
 
+       whc_dbg_init(whc);
+
        return 0;
 
 error_wusbhc_b_create:
@@ -299,6 +298,7 @@ static void whc_remove(struct umc_dev *umc)
        struct whc *whc = wusbhc_to_whc(wusbhc);
 
        if (usb_hcd) {
+               whc_dbg_clean_up(whc);
                wusbhc_b_destroy(wusbhc);
                usb_remove_hcd(usb_hcd);
                wusbhc_destroy(wusbhc);
index ac86e59..d498e72 100644 (file)
@@ -50,6 +50,7 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len)
        unsigned long flags;
        dma_addr_t dma_addr;
        int t;
+       int ret = 0;
 
        mutex_lock(&whc->mutex);
 
@@ -61,7 +62,8 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len)
                dev_err(&whc->umc->dev, "generic command timeout (%04x/%04x)\n",
                        le_readl(whc->base + WUSBGENCMDSTS),
                        le_readl(whc->base + WUSBGENCMDPARAMS));
-               return -ETIMEDOUT;
+               ret = -ETIMEDOUT;
+               goto out;
        }
 
        if (addr) {
@@ -80,8 +82,8 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len)
                  whc->base + WUSBGENCMDSTS);
 
        spin_unlock_irqrestore(&whc->lock, flags);
-
+out:
        mutex_unlock(&whc->mutex);
 
-       return 0;
+       return ret;
 }
index fce0117..6aae700 100644 (file)
@@ -15,7 +15,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/uwb/umc.h>
index 8d62df0..2ae5abf 100644 (file)
 #include <linux/dma-mapping.h>
 #include <linux/uwb/umc.h>
 #include <linux/usb.h>
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
 
 #include "../../wusbcore/wusbhc.h"
 
 #include "whcd.h"
 
-#if D_LOCAL >= 4
-static void dump_pzl(struct whc *whc, const char *tag)
-{
-       struct device *dev = &whc->umc->dev;
-       struct whc_qset *qset;
-       int period = 0;
-
-       d_printf(4, dev, "PZL %s\n", tag);
-
-       for (period = 0; period < 5; period++) {
-               d_printf(4, dev, "Period %d\n", period);
-               list_for_each_entry(qset, &whc->periodic_list[period], list_node) {
-                       dump_qset(qset, dev);
-               }
-       }
-}
-#else
-static inline void dump_pzl(struct whc *whc, const char *tag)
-{
-}
-#endif
-
 static void update_pzl_pointers(struct whc *whc, int period, u64 addr)
 {
        switch (period) {
@@ -195,11 +171,26 @@ void pzl_stop(struct whc *whc)
                      1000, "stop PZL");
 }
 
+/**
+ * pzl_update - request a PZL update and wait for the hardware to be synced
+ * @whc: the WHCI HC
+ * @wusbcmd: WUSBCMD value to start the update.
+ *
+ * If the WUSB HC is inactive (i.e., the PZL is stopped) then the
+ * update must be skipped as the hardware may not respond to update
+ * requests.
+ */
 void pzl_update(struct whc *whc, uint32_t wusbcmd)
 {
-       whc_write_wusbcmd(whc, wusbcmd, wusbcmd);
-       wait_event(whc->periodic_list_wq,
-                  (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0);
+       struct wusbhc *wusbhc = &whc->wusbhc;
+
+       mutex_lock(&wusbhc->mutex);
+       if (wusbhc->active) {
+               whc_write_wusbcmd(whc, wusbcmd, wusbcmd);
+               wait_event(whc->periodic_list_wq,
+                          (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0);
+       }
+       mutex_unlock(&wusbhc->mutex);
 }
 
 static void update_pzl_hw_view(struct whc *whc)
@@ -235,8 +226,6 @@ void scan_periodic_work(struct work_struct *work)
 
        spin_lock_irq(&whc->lock);
 
-       dump_pzl(whc, "before processing");
-
        for (period = 4; period >= 0; period--) {
                list_for_each_entry_safe(qset, t, &whc->periodic_list[period], list_node) {
                        if (!qset->in_hw_list)
@@ -248,8 +237,6 @@ void scan_periodic_work(struct work_struct *work)
        if (update & (WHC_UPDATE_ADDED | WHC_UPDATE_REMOVED))
                update_pzl_hw_view(whc);
 
-       dump_pzl(whc, "after processing");
-
        spin_unlock_irq(&whc->lock);
 
        if (update) {
index 0420037..7be7431 100644 (file)
 
 #include "whcd.h"
 
-void dump_qset(struct whc_qset *qset, struct device *dev)
-{
-       struct whc_std *std;
-       struct urb *urb = NULL;
-       int i;
-
-       dev_dbg(dev, "qset %08x\n", (u32)qset->qset_dma);
-       dev_dbg(dev, "  -> %08x\n", (u32)qset->qh.link);
-       dev_dbg(dev, "  info: %08x %08x %08x\n",
-               qset->qh.info1, qset->qh.info2,  qset->qh.info3);
-       dev_dbg(dev, "  sts: %04x errs: %d\n", qset->qh.status, qset->qh.err_count);
-       dev_dbg(dev, "  TD: sts: %08x opts: %08x\n",
-               qset->qh.overlay.qtd.status, qset->qh.overlay.qtd.options);
-
-       for (i = 0; i < WHCI_QSET_TD_MAX; i++) {
-               dev_dbg(dev, "  %c%c TD[%d]: sts: %08x opts: %08x ptr: %08x\n",
-                       i == qset->td_start ? 'S' : ' ',
-                       i == qset->td_end ? 'E' : ' ',
-                       i, qset->qtd[i].status, qset->qtd[i].options,
-                       (u32)qset->qtd[i].page_list_ptr);
-       }
-       dev_dbg(dev, "  ntds: %d\n", qset->ntds);
-       list_for_each_entry(std, &qset->stds, list_node) {
-               if (urb != std->urb) {
-                       urb = std->urb;
-                       dev_dbg(dev, "  urb %p transferred: %d bytes\n", urb,
-                               urb->actual_length);
-               }
-               if (std->qtd)
-                       dev_dbg(dev, "    sTD[%td]: %zu bytes @ %08x\n",
-                               std->qtd - &qset->qtd[0],
-                               std->len, std->num_pointers ?
-                               (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr);
-               else
-                       dev_dbg(dev, "    sTD[-]: %zd bytes @ %08x\n",
-                               std->len, std->num_pointers ?
-                               (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr);
-       }
-}
-
 struct whc_qset *qset_alloc(struct whc *whc, gfp_t mem_flags)
 {
        struct whc_qset *qset;
index 1d2a53b..0f3540f 100644 (file)
@@ -21,6 +21,7 @@
 #define __WHCD_H
 
 #include <linux/uwb/whci.h>
+#include <linux/uwb/umc.h>
 #include <linux/workqueue.h>
 
 #include "whci-hc.h"
@@ -28,6 +29,7 @@
 /* Generic command timeout. */
 #define WHC_GENCMD_TIMEOUT_MS 100
 
+struct whc_dbg;
 
 struct whc {
        struct wusbhc wusbhc;
@@ -69,6 +71,8 @@ struct whc {
        struct list_head periodic_removed_list;
        wait_queue_head_t periodic_list_wq;
        struct work_struct periodic_work;
+
+       struct whc_dbg *dbg;
 };
 
 #define wusbhc_to_whc(w) (container_of((w), struct whc, wusbhc))
@@ -136,7 +140,7 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len);
 
 /* wusb.c */
 int whc_wusbhc_start(struct wusbhc *wusbhc);
-void whc_wusbhc_stop(struct wusbhc *wusbhc);
+void whc_wusbhc_stop(struct wusbhc *wusbhc, int delay);
 int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt,
                  u8 handle, struct wuie_hdr *wuie);
 int whc_mmcie_rm(struct wusbhc *wusbhc, u8 handle);
@@ -190,8 +194,11 @@ void process_inactive_qtd(struct whc *whc, struct whc_qset *qset,
                                 struct whc_qtd *qtd);
 enum whc_update qset_add_qtds(struct whc *whc, struct whc_qset *qset);
 void qset_remove_complete(struct whc *whc, struct whc_qset *qset);
-void dump_qset(struct whc_qset *qset, struct device *dev);
 void pzl_update(struct whc *whc, uint32_t wusbcmd);
 void asl_update(struct whc *whc, uint32_t wusbcmd);
 
+/* debug.c */
+void whc_dbg_init(struct whc *whc);
+void whc_dbg_clean_up(struct whc *whc);
+
 #endif /* #ifndef __WHCD_H */
index bff1eb7..51df7e3 100644 (file)
@@ -410,6 +410,8 @@ struct dn_buf_entry {
 #  define WUSBDNTSCTRL_SLOTS(s)    ((s) << 0)
 
 #define WUSBTIME             0x68
+#  define WUSBTIME_CHANNEL_TIME_MASK 0x00ffffff
+
 #define WUSBBPST             0x6c
 #define WUSBDIBUPDATED       0x70
 
index 66e4ddc..f24efde 100644 (file)
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/uwb/umc.h>
-#define D_LOCAL 1
-#include <linux/uwb/debug.h>
 
 #include "../../wusbcore/wusbhc.h"
 
 #include "whcd.h"
 
-#if D_LOCAL >= 1
-static void dump_di(struct whc *whc, int idx)
-{
-       struct di_buf_entry *di = &whc->di_buf[idx];
-       struct device *dev = &whc->umc->dev;
-       char buf[128];
-
-       bitmap_scnprintf(buf, sizeof(buf), (unsigned long *)di->availability_info, UWB_NUM_MAS);
-
-       d_printf(1, dev, "DI[%d]\n", idx);
-       d_printf(1, dev, "  availability: %s\n", buf);
-       d_printf(1, dev, "  %c%c key idx: %d dev addr: %d\n",
-                (di->addr_sec_info & WHC_DI_SECURE) ? 'S' : ' ',
-                (di->addr_sec_info & WHC_DI_DISABLE) ? 'D' : ' ',
-                (di->addr_sec_info & WHC_DI_KEY_IDX_MASK) >> 8,
-                (di->addr_sec_info & WHC_DI_DEV_ADDR_MASK));
-}
-#else
-static inline void dump_di(struct whc *whc, int idx)
-{
-}
-#endif
-
 static int whc_update_di(struct whc *whc, int idx)
 {
        int offset = idx / 32;
        u32 bit = 1 << (idx % 32);
 
-       dump_di(whc, idx);
-
        le_writel(bit, whc->base + WUSBDIBUPDATED + offset);
 
        return whci_wait_for(&whc->umc->dev,
@@ -64,8 +36,9 @@ static int whc_update_di(struct whc *whc, int idx)
 }
 
 /*
- * WHCI starts and stops MMCs based on there being a valid GTK so
- * these need only start/stop the asynchronous and periodic schedules.
+ * WHCI starts MMCs based on there being a valid GTK so these need
+ * only start/stop the asynchronous and periodic schedules and send a
+ * channel stop command.
  */
 
 int whc_wusbhc_start(struct wusbhc *wusbhc)
@@ -78,12 +51,20 @@ int whc_wusbhc_start(struct wusbhc *wusbhc)
        return 0;
 }
 
-void whc_wusbhc_stop(struct wusbhc *wusbhc)
+void whc_wusbhc_stop(struct wusbhc *wusbhc, int delay)
 {
        struct whc *whc = wusbhc_to_whc(wusbhc);
+       u32 stop_time, now_time;
+       int ret;
 
        pzl_stop(whc);
        asl_stop(whc);
+
+       now_time = le_readl(whc->base + WUSBTIME) & WUSBTIME_CHANNEL_TIME_MASK;
+       stop_time = (now_time + ((delay * 8) << 7)) & 0x00ffffff;
+       ret = whc_do_gencmd(whc, WUSBGENCMDSTS_CHAN_STOP, stop_time, NULL, 0);
+       if (ret == 0)
+               msleep(delay);
 }
 
 int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt,
index ab4788d..1335cbe 100644 (file)
@@ -88,7 +88,6 @@
  */
 #include <linux/module.h>
 #include <linux/ctype.h>
-#include <linux/version.h>
 #include <linux/usb.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
index c36c438..9ec7fd5 100644 (file)
 #include <linux/uwb.h>
 #include <linux/usb/wusb.h>
 #include <linux/scatterlist.h>
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
 
+static int debug_crypto_verify = 0;
+
+module_param(debug_crypto_verify, int, 0);
+MODULE_PARM_DESC(debug_crypto_verify, "verify the key generation algorithms");
+
+static void wusb_key_dump(const void *buf, size_t len)
+{
+       print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_OFFSET, 16, 1,
+                      buf, len, 0);
+}
 
 /*
  * Block of data, as understood by AES-CCM
@@ -203,9 +211,6 @@ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc,
        const u8 bzero[16] = { 0 };
        size_t zero_padding;
 
-       d_fnstart(3, NULL, "(tfm_cbc %p, tfm_aes %p, mic %p, "
-                 "n %p, a %p, b %p, blen %zu)\n",
-                 tfm_cbc, tfm_aes, mic, n, a, b, blen);
        /*
         * These checks should be compile time optimized out
         * ensure @a fills b1's mac_header and following fields
@@ -247,16 +252,6 @@ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc,
        b1.la = cpu_to_be16(blen + 14);
        memcpy(&b1.mac_header, a, sizeof(*a));
 
-       d_printf(4, NULL, "I: B0 (%zu bytes)\n", sizeof(b0));
-       d_dump(4, NULL, &b0, sizeof(b0));
-       d_printf(4, NULL, "I: B1 (%zu bytes)\n", sizeof(b1));
-       d_dump(4, NULL, &b1, sizeof(b1));
-       d_printf(4, NULL, "I: B (%zu bytes)\n", blen);
-       d_dump(4, NULL, b, blen);
-       d_printf(4, NULL, "I: B 0-padding (%zu bytes)\n", zero_padding);
-       d_printf(4, NULL, "D: IV before crypto (%zu)\n", ivsize);
-       d_dump(4, NULL, iv, ivsize);
-
        sg_init_table(sg, ARRAY_SIZE(sg));
        sg_set_buf(&sg[0], &b0, sizeof(b0));
        sg_set_buf(&sg[1], &b1, sizeof(b1));
@@ -273,8 +268,6 @@ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc,
                       result);
                goto error_cbc_crypt;
        }
-       d_printf(4, NULL, "D: MIC tag\n");
-       d_dump(4, NULL, iv, ivsize);
 
        /* Now we crypt the MIC Tag (*iv) with Ax -- values per WUSB1.0[6.5]
         * The procedure is to AES crypt the A0 block and XOR the MIC
@@ -289,17 +282,10 @@ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc,
        ax.counter = 0;
        crypto_cipher_encrypt_one(tfm_aes, (void *)&ax, (void *)&ax);
        bytewise_xor(mic, &ax, iv, 8);
-       d_printf(4, NULL, "D: CTR[MIC]\n");
-       d_dump(4, NULL, &ax, 8);
-       d_printf(4, NULL, "D: CCM-MIC tag\n");
-       d_dump(4, NULL, mic, 8);
        result = 8;
 error_cbc_crypt:
        kfree(dst_buf);
 error_dst_buf:
-       d_fnend(3, NULL, "(tfm_cbc %p, tfm_aes %p, mic %p, "
-               "n %p, a %p, b %p, blen %zu)\n",
-               tfm_cbc, tfm_aes, mic, n, a, b, blen);
        return result;
 }
 
@@ -321,10 +307,6 @@ ssize_t wusb_prf(void *out, size_t out_size,
        u64 sfn = 0;
        __le64 sfn_le;
 
-       d_fnstart(3, NULL, "(out %p, out_size %zu, key %p, _n %p, "
-                 "a %p, b %p, blen %zu, len %zu)\n", out, out_size,
-                 key, _n, a, b, blen, len);
-
        tfm_cbc = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(tfm_cbc)) {
                result = PTR_ERR(tfm_cbc);
@@ -366,9 +348,6 @@ error_alloc_aes:
 error_setkey_cbc:
        crypto_free_blkcipher(tfm_cbc);
 error_alloc_cbc:
-       d_fnend(3, NULL, "(out %p, out_size %zu, key %p, _n %p, "
-               "a %p, b %p, blen %zu, len %zu) = %d\n", out, out_size,
-               key, _n, a, b, blen, len, (int)bytes);
        return result;
 }
 
@@ -422,14 +401,14 @@ static int wusb_oob_mic_verify(void)
                       "mismatch between MIC result and WUSB1.0[A2]\n");
                hs_size = sizeof(stv_hsmic_hs) - sizeof(stv_hsmic_hs.MIC);
                printk(KERN_ERR "E: Handshake2 in: (%zu bytes)\n", hs_size);
-               dump_bytes(NULL, &stv_hsmic_hs, hs_size);
+               wusb_key_dump(&stv_hsmic_hs, hs_size);
                printk(KERN_ERR "E: CCM Nonce in: (%zu bytes)\n",
                       sizeof(stv_hsmic_n));
-               dump_bytes(NULL, &stv_hsmic_n, sizeof(stv_hsmic_n));
+               wusb_key_dump(&stv_hsmic_n, sizeof(stv_hsmic_n));
                printk(KERN_ERR "E: MIC out:\n");
-               dump_bytes(NULL, mic, sizeof(mic));
+               wusb_key_dump(mic, sizeof(mic));
                printk(KERN_ERR "E: MIC out (from WUSB1.0[A.2]):\n");
-               dump_bytes(NULL, stv_hsmic_hs.MIC, sizeof(stv_hsmic_hs.MIC));
+               wusb_key_dump(stv_hsmic_hs.MIC, sizeof(stv_hsmic_hs.MIC));
                result = -EINVAL;
        } else
                result = 0;
@@ -497,19 +476,16 @@ static int wusb_key_derive_verify(void)
                printk(KERN_ERR "E: WUSB key derivation test: "
                       "mismatch between key derivation result "
                       "and WUSB1.0[A1] Errata 2006/12\n");
-               printk(KERN_ERR "E: keydvt in: key (%zu bytes)\n",
-                      sizeof(stv_key_a1));
-               dump_bytes(NULL, stv_key_a1, sizeof(stv_key_a1));
-               printk(KERN_ERR "E: keydvt in: nonce (%zu bytes)\n",
-                      sizeof(stv_keydvt_n_a1));
-               dump_bytes(NULL, &stv_keydvt_n_a1, sizeof(stv_keydvt_n_a1));
-               printk(KERN_ERR "E: keydvt in: hnonce & dnonce (%zu bytes)\n",
-                      sizeof(stv_keydvt_in_a1));
-               dump_bytes(NULL, &stv_keydvt_in_a1, sizeof(stv_keydvt_in_a1));
+               printk(KERN_ERR "E: keydvt in: key\n");
+               wusb_key_dump(stv_key_a1, sizeof(stv_key_a1));
+               printk(KERN_ERR "E: keydvt in: nonce\n");
+               wusb_key_dump( &stv_keydvt_n_a1, sizeof(stv_keydvt_n_a1));
+               printk(KERN_ERR "E: keydvt in: hnonce & dnonce\n");
+               wusb_key_dump(&stv_keydvt_in_a1, sizeof(stv_keydvt_in_a1));
                printk(KERN_ERR "E: keydvt out: KCK\n");
-               dump_bytes(NULL, &keydvt_out.kck, sizeof(keydvt_out.kck));
+               wusb_key_dump(&keydvt_out.kck, sizeof(keydvt_out.kck));
                printk(KERN_ERR "E: keydvt out: PTK\n");
-               dump_bytes(NULL, &keydvt_out.ptk, sizeof(keydvt_out.ptk));
+               wusb_key_dump(&keydvt_out.ptk, sizeof(keydvt_out.ptk));
                result = -EINVAL;
        } else
                result = 0;
@@ -526,10 +502,13 @@ int wusb_crypto_init(void)
 {
        int result;
 
-       result = wusb_key_derive_verify();
-       if (result < 0)
-               return result;
-       return wusb_oob_mic_verify();
+       if (debug_crypto_verify) {
+               result = wusb_key_derive_verify();
+               if (result < 0)
+                       return result;
+               return wusb_oob_mic_verify();
+       }
+       return 0;
 }
 
 void wusb_crypto_exit(void)
index 7897a19..1018345 100644 (file)
 #include <linux/workqueue.h>
 #include "wusbhc.h"
 
-#undef D_LOCAL
-#define D_LOCAL 4
-#include <linux/uwb/debug.h>
-
 static ssize_t wusb_disconnect_store(struct device *dev,
                                     struct device_attribute *attr,
                                     const char *buf, size_t size)
index f45d777..e2e7e4b 100644 (file)
@@ -57,9 +57,6 @@
  *                              Called by notif.c:wusb_handle_dn_connect()
  *                              when a DN_Connect is received.
  *
- *   wusbhc_devconnect_auth()   Called by rh.c:wusbhc_rh_port_reset() when
- *                              doing the device connect sequence.
- *
  *     wusb_devconnect_acked()  Ack done, release resources.
  *
  *   wusb_handle_dn_alive()     Called by notif.c:wusb_handle_dn()
@@ -69,9 +66,6 @@
  *                              process a disconenct request from a
  *                              device.
  *
- *   wusb_dev_reset()           Called by rh.c:wusbhc_rh_port_reset() when
- *                              resetting a device.
- *
  *   __wusb_dev_disable()       Called by rh.c:wusbhc_rh_clear_port_feat() when
  *                              disabling a port.
  *
 #include <linux/workqueue.h>
 #include "wusbhc.h"
 
-#undef D_LOCAL
-#define D_LOCAL 1
-#include <linux/uwb/debug.h>
-
 static void wusbhc_devconnect_acked_work(struct work_struct *work);
 
 static void wusb_dev_free(struct wusb_dev *wusb_dev)
@@ -240,6 +230,7 @@ static struct wusb_dev *wusbhc_cack_add(struct wusbhc *wusbhc,
        list_add_tail(&wusb_dev->cack_node, &wusbhc->cack_list);
        wusbhc->cack_count++;
        wusbhc_fill_cack_ie(wusbhc);
+
        return wusb_dev;
 }
 
@@ -250,12 +241,9 @@ static struct wusb_dev *wusbhc_cack_add(struct wusbhc *wusbhc,
  */
 static void wusbhc_cack_rm(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
 {
-       struct device *dev = wusbhc->dev;
-       d_fnstart(3, dev, "(wusbhc %p wusb_dev %p)\n", wusbhc, wusb_dev);
        list_del_init(&wusb_dev->cack_node);
        wusbhc->cack_count--;
        wusbhc_fill_cack_ie(wusbhc);
-       d_fnend(3, dev, "(wusbhc %p wusb_dev %p) = void\n", wusbhc, wusb_dev);
 }
 
 /*
@@ -263,14 +251,11 @@ static void wusbhc_cack_rm(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
 static
 void wusbhc_devconnect_acked(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
 {
-       struct device *dev = wusbhc->dev;
-       d_fnstart(3, dev, "(wusbhc %p wusb_dev %p)\n", wusbhc, wusb_dev);
        wusbhc_cack_rm(wusbhc, wusb_dev);
        if (wusbhc->cack_count)
                wusbhc_mmcie_set(wusbhc, 0, 0, &wusbhc->cack_ie.hdr);
        else
                wusbhc_mmcie_rm(wusbhc, &wusbhc->cack_ie.hdr);
-       d_fnend(3, dev, "(wusbhc %p wusb_dev %p) = void\n", wusbhc, wusb_dev);
 }
 
 static void wusbhc_devconnect_acked_work(struct work_struct *work)
@@ -320,7 +305,6 @@ void wusbhc_devconnect_ack(struct wusbhc *wusbhc, struct wusb_dn_connect *dnc,
        struct wusb_port *port;
        unsigned idx, devnum;
 
-       d_fnstart(3, dev, "(%p, %p, %s)\n", wusbhc, dnc, pr_cdid);
        mutex_lock(&wusbhc->mutex);
 
        /* Check we are not handling it already */
@@ -366,16 +350,13 @@ void wusbhc_devconnect_ack(struct wusbhc *wusbhc, struct wusb_dn_connect *dnc,
        port->wusb_dev = wusb_dev;
        port->status |= USB_PORT_STAT_CONNECTION;
        port->change |= USB_PORT_STAT_C_CONNECTION;
-       port->reset_count = 0;
        /* Now the port status changed to connected; khubd will
         * pick the change up and try to reset the port to bring it to
         * the enabled state--so this process returns up to the stack
-        * and it calls back into wusbhc_rh_port_reset() who will call
-        * devconnect_auth().
+        * and it calls back into wusbhc_rh_port_reset().
         */
 error_unlock:
        mutex_unlock(&wusbhc->mutex);
-       d_fnend(3, dev, "(%p, %p, %s) = void\n", wusbhc, dnc, pr_cdid);
        return;
 
 }
@@ -398,10 +379,8 @@ error_unlock:
 static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc,
                                    struct wusb_port *port)
 {
-       struct device *dev = wusbhc->dev;
        struct wusb_dev *wusb_dev = port->wusb_dev;
 
-       d_fnstart(3, dev, "(wusbhc %p, port %p)\n", wusbhc, port);
        port->status &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE
                          | USB_PORT_STAT_SUSPEND | USB_PORT_STAT_RESET
                          | USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED);
@@ -413,15 +392,11 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc,
                wusb_dev_put(wusb_dev);
        }
        port->wusb_dev = NULL;
-       /* don't reset the reset_count to zero or wusbhc_rh_port_reset will get
-        * confused! We only reset to zero when we connect a new device.
-        */
 
        /* After a device disconnects, change the GTK (see [WUSB]
         * section 6.2.11.2). */
        wusbhc_gtk_rekey(wusbhc);
 
-       d_fnend(3, dev, "(wusbhc %p, port %p) = void\n", wusbhc, port);
        /* The Wireless USB part has forgotten about the device already; now
         * khubd's timer will pick up the disconnection and remove the USB
         * device from the system
@@ -429,39 +404,6 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc,
 }
 
 /*
- * Authenticate a device into the WUSB Cluster
- *
- * Called from the Root Hub code (rh.c:wusbhc_rh_port_reset()) when
- * asking for a reset on a port that is not enabled (ie: first connect
- * on the port).
- *
- * Performs the 4way handshake to allow the device to comunicate w/ the
- * WUSB Cluster securely; once done, issue a request to the device for
- * it to change to address 0.
- *
- * This mimics the reset step of Wired USB that once resetting a
- * device, leaves the port in enabled state and the dev with the
- * default address (0).
- *
- * WUSB1.0[7.1.2]
- *
- * @port_idx: port where the change happened--This is the index into
- *            the wusbhc port array, not the USB port number.
- */
-int wusbhc_devconnect_auth(struct wusbhc *wusbhc, u8 port_idx)
-{
-       struct device *dev = wusbhc->dev;
-       struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx);
-
-       d_fnstart(3, dev, "(%p, %u)\n", wusbhc, port_idx);
-       port->status &= ~USB_PORT_STAT_RESET;
-       port->status |= USB_PORT_STAT_ENABLE;
-       port->change |= USB_PORT_STAT_C_RESET | USB_PORT_STAT_C_ENABLE;
-       d_fnend(3, dev, "(%p, %u) = 0\n", wusbhc, port_idx);
-       return 0;
-}
-
-/*
  * Refresh the list of keep alives to emit in the MMC
  *
  * Some devices don't respond to keep alives unless they've been
@@ -528,21 +470,15 @@ static void __wusbhc_keep_alive(struct wusbhc *wusbhc)
  */
 static void wusbhc_keep_alive_run(struct work_struct *ws)
 {
-       struct delayed_work *dw =
-               container_of(ws, struct delayed_work, work);
-       struct wusbhc *wusbhc =
-               container_of(dw, struct wusbhc, keep_alive_timer);
-
-       d_fnstart(5, wusbhc->dev, "(wusbhc %p)\n", wusbhc);
-       if (wusbhc->active) {
-               mutex_lock(&wusbhc->mutex);
-               __wusbhc_keep_alive(wusbhc);
-               mutex_unlock(&wusbhc->mutex);
-               queue_delayed_work(wusbd, &wusbhc->keep_alive_timer,
-                                  (wusbhc->trust_timeout * CONFIG_HZ)/1000/2);
-       }
-       d_fnend(5, wusbhc->dev, "(wusbhc %p) = void\n", wusbhc);
-       return;
+       struct delayed_work *dw = container_of(ws, struct delayed_work, work);
+       struct wusbhc *wusbhc = container_of(dw, struct wusbhc, keep_alive_timer);
+
+       mutex_lock(&wusbhc->mutex);
+       __wusbhc_keep_alive(wusbhc);
+       mutex_unlock(&wusbhc->mutex);
+
+       queue_delayed_work(wusbd, &wusbhc->keep_alive_timer,
+                          msecs_to_jiffies(wusbhc->trust_timeout / 2));
 }
 
 /*
@@ -585,10 +521,6 @@ static struct wusb_dev *wusbhc_find_dev_by_addr(struct wusbhc *wusbhc, u8 addr)
  */
 static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
 {
-       struct device *dev = wusbhc->dev;
-
-       d_printf(2, dev, "DN ALIVE: device 0x%02x pong\n", wusb_dev->addr);
-
        mutex_lock(&wusbhc->mutex);
        wusb_dev->entry_ts = jiffies;
        __wusbhc_keep_alive(wusbhc);
@@ -621,11 +553,10 @@ static void wusbhc_handle_dn_connect(struct wusbhc *wusbhc,
                "no-beacon"
        };
 
-       d_fnstart(3, dev, "(%p, %p, %zu)\n", wusbhc, dn_hdr, size);
        if (size < sizeof(*dnc)) {
                dev_err(dev, "DN CONNECT: short notification (%zu < %zu)\n",
                        size, sizeof(*dnc));
-               goto out;
+               return;
        }
 
        dnc = container_of(dn_hdr, struct wusb_dn_connect, hdr);
@@ -637,10 +568,6 @@ static void wusbhc_handle_dn_connect(struct wusbhc *wusbhc,
                 wusb_dn_connect_new_connection(dnc) ? "connect" : "reconnect");
        /* ACK the connect */
        wusbhc_devconnect_ack(wusbhc, dnc, pr_cdid);
-out:
-       d_fnend(3, dev, "(%p, %p, %zu) = void\n",
-               wusbhc, dn_hdr, size);
-       return;
 }
 
 /*
@@ -662,60 +589,6 @@ static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, struct wusb_dev *
 }
 
 /*
- * Reset a WUSB device on a HWA
- *
- * @wusbhc
- * @port_idx   Index of the port where the device is
- *
- * In Wireless USB, a reset is more or less equivalent to a full
- * disconnect; so we just do a full disconnect and send the device a
- * Device Reset IE (WUSB1.0[7.5.11]) giving it a few millisecs (6 MMCs).
- *
- * @wusbhc should be refcounted and unlocked
- */
-int wusbhc_dev_reset(struct wusbhc *wusbhc, u8 port_idx)
-{
-       int result;
-       struct device *dev = wusbhc->dev;
-       struct wusb_dev *wusb_dev;
-       struct wuie_reset *ie;
-
-       d_fnstart(3, dev, "(%p, %u)\n", wusbhc, port_idx);
-       mutex_lock(&wusbhc->mutex);
-       result = 0;
-       wusb_dev = wusb_port_by_idx(wusbhc, port_idx)->wusb_dev;
-       if (wusb_dev == NULL) {
-               /* reset no device? ignore */
-               dev_dbg(dev, "RESET: no device at port %u, ignoring\n",
-                       port_idx);
-               goto error_unlock;
-       }
-       result = -ENOMEM;
-       ie = kzalloc(sizeof(*ie), GFP_KERNEL);
-       if (ie == NULL)
-               goto error_unlock;
-       ie->hdr.bLength = sizeof(ie->hdr) + sizeof(ie->CDID);
-       ie->hdr.bIEIdentifier = WUIE_ID_RESET_DEVICE;
-       ie->CDID = wusb_dev->cdid;
-       result = wusbhc_mmcie_set(wusbhc, 0xff, 6, &ie->hdr);
-       if (result < 0) {
-               dev_err(dev, "RESET: cant's set MMC: %d\n", result);
-               goto error_kfree;
-       }
-       __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, port_idx));
-
-       /* 120ms, hopefully 6 MMCs (FIXME) */
-       msleep(120);
-       wusbhc_mmcie_rm(wusbhc, &ie->hdr);
-error_kfree:
-       kfree(ie);
-error_unlock:
-       mutex_unlock(&wusbhc->mutex);
-       d_fnend(3, dev, "(%p, %u) = %d\n", wusbhc, port_idx, result);
-       return result;
-}
-
-/*
  * Handle a Device Notification coming a host
  *
  * The Device Notification comes from a host (HWA, DWA or WHCI)
@@ -735,19 +608,17 @@ void wusbhc_handle_dn(struct wusbhc *wusbhc, u8 srcaddr,
        struct device *dev = wusbhc->dev;
        struct wusb_dev *wusb_dev;
 
-       d_fnstart(3, dev, "(%p, %p)\n", wusbhc, dn_hdr);
-
        if (size < sizeof(struct wusb_dn_hdr)) {
                dev_err(dev, "DN data shorter than DN header (%d < %d)\n",
                        (int)size, (int)sizeof(struct wusb_dn_hdr));
-               goto out;
+               return;
        }
 
        wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
        if (wusb_dev == NULL && dn_hdr->bType != WUSB_DN_CONNECT) {
                dev_dbg(dev, "ignoring DN %d from unconnected device %02x\n",
                        dn_hdr->bType, srcaddr);
-               goto out;
+               return;
        }
 
        switch (dn_hdr->bType) {
@@ -772,9 +643,6 @@ void wusbhc_handle_dn(struct wusbhc *wusbhc, u8 srcaddr,
                dev_warn(dev, "unknown DN %u (%d octets) from %u\n",
                         dn_hdr->bType, (int)size, srcaddr);
        }
-out:
-       d_fnend(3, dev, "(%p, %p) = void\n", wusbhc, dn_hdr);
-       return;
 }
 EXPORT_SYMBOL_GPL(wusbhc_handle_dn);
 
@@ -804,59 +672,30 @@ void __wusbhc_dev_disable(struct wusbhc *wusbhc, u8 port_idx)
        struct wusb_dev *wusb_dev;
        struct wuie_disconnect *ie;
 
-       d_fnstart(3, dev, "(%p, %u)\n", wusbhc, port_idx);
-       result = 0;
        wusb_dev = wusb_port_by_idx(wusbhc, port_idx)->wusb_dev;
        if (wusb_dev == NULL) {
                /* reset no device? ignore */
                dev_dbg(dev, "DISCONNECT: no device at port %u, ignoring\n",
                        port_idx);
-               goto error;
+               return;
        }
        __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, port_idx));
 
-       result = -ENOMEM;
        ie = kzalloc(sizeof(*ie), GFP_KERNEL);
        if (ie == NULL)
-               goto error;
+               return;
        ie->hdr.bLength = sizeof(*ie);
        ie->hdr.bIEIdentifier = WUIE_ID_DEVICE_DISCONNECT;
        ie->bDeviceAddress = wusb_dev->addr;
        result = wusbhc_mmcie_set(wusbhc, 0, 0, &ie->hdr);
-       if (result < 0) {
+       if (result < 0)
                dev_err(dev, "DISCONNECT: can't set MMC: %d\n", result);
-               goto error_kfree;
+       else {
+               /* At least 6 MMCs, assuming at least 1 MMC per zone. */
+               msleep(7*4);
+               wusbhc_mmcie_rm(wusbhc, &ie->hdr);
        }
-
-       /* 120ms, hopefully 6 MMCs */
-       msleep(100);
-       wusbhc_mmcie_rm(wusbhc, &ie->hdr);
-error_kfree:
        kfree(ie);
-error:
-       d_fnend(3, dev, "(%p, %u) = %d\n", wusbhc, port_idx, result);
-       return;
-}
-
-static void wusb_cap_descr_printf(const unsigned level, struct device *dev,
-                                 const struct usb_wireless_cap_descriptor *wcd)
-{
-       d_printf(level, dev,
-                "WUSB Capability Descriptor\n"
-                "  bDevCapabilityType          0x%02x\n"
-                "  bmAttributes                0x%02x\n"
-                "  wPhyRates                   0x%04x\n"
-                "  bmTFITXPowerInfo            0x%02x\n"
-                "  bmFFITXPowerInfo            0x%02x\n"
-                "  bmBandGroup                 0x%04x\n"
-                "  bReserved                   0x%02x\n",
-                wcd->bDevCapabilityType,
-                wcd->bmAttributes,
-                le16_to_cpu(wcd->wPHYRates),
-                wcd->bmTFITXPowerInfo,
-                wcd->bmFFITXPowerInfo,
-                wcd->bmBandGroup,
-                wcd->bReserved);
 }
 
 /*
@@ -899,8 +738,6 @@ static int wusb_dev_bos_grok(struct usb_device *usb_dev,
                }
                cap_size = cap_hdr->bLength;
                cap_type = cap_hdr->bDevCapabilityType;
-               d_printf(4, dev, "BOS Capability: 0x%02x (%zu bytes)\n",
-                        cap_type, cap_size);
                if (cap_size == 0)
                        break;
                if (cap_size > top - itr) {
@@ -912,7 +749,6 @@ static int wusb_dev_bos_grok(struct usb_device *usb_dev,
                        result = -EBADF;
                        goto error_bad_cap;
                }
-               d_dump(3, dev, itr, cap_size);
                switch (cap_type) {
                case USB_CAP_TYPE_WIRELESS_USB:
                        if (cap_size != sizeof(*wusb_dev->wusb_cap_descr))
@@ -920,10 +756,8 @@ static int wusb_dev_bos_grok(struct usb_device *usb_dev,
                                        "descriptor is %zu bytes vs %zu "
                                        "needed\n", cap_size,
                                        sizeof(*wusb_dev->wusb_cap_descr));
-                       else {
+                       else
                                wusb_dev->wusb_cap_descr = itr;
-                               wusb_cap_descr_printf(3, dev, itr);
-                       }
                        break;
                default:
                        dev_err(dev, "BUG? Unknown BOS capability 0x%02x "
@@ -988,9 +822,7 @@ static int wusb_dev_bos_add(struct usb_device *usb_dev,
                        "%zu bytes): %zd\n", desc_size, result);
                goto error_get_descriptor;
        }
-       d_printf(2, dev, "Got BOS descriptor %zd bytes, %u capabilities\n",
-                result, bos->bNumDeviceCaps);
-       d_dump(2, dev, bos, result);
+
        result = wusb_dev_bos_grok(usb_dev, wusb_dev, bos, result);
        if (result < 0)
                goto error_bad_bos;
@@ -1056,8 +888,6 @@ static void wusb_dev_add_ncb(struct usb_device *usb_dev)
        if (usb_dev->wusb == 0 || usb_dev->devnum == 1)
                return;         /* skip non wusb and wusb RHs */
 
-       d_fnstart(3, dev, "(usb_dev %p)\n", usb_dev);
-
        wusbhc = wusbhc_get_by_usb_dev(usb_dev);
        if (wusbhc == NULL)
                goto error_nodev;
@@ -1087,7 +917,6 @@ out:
        wusb_dev_put(wusb_dev);
        wusbhc_put(wusbhc);
 error_nodev:
-       d_fnend(3, dev, "(usb_dev %p) = void\n", usb_dev);
        return;
 
        wusb_dev_sysfs_rm(wusb_dev);
@@ -1174,11 +1003,10 @@ EXPORT_SYMBOL_GPL(__wusb_dev_get_by_usb_dev);
 
 void wusb_dev_destroy(struct kref *_wusb_dev)
 {
-       struct wusb_dev *wusb_dev
-               = container_of(_wusb_dev, struct wusb_dev, refcnt);
+       struct wusb_dev *wusb_dev = container_of(_wusb_dev, struct wusb_dev, refcnt);
+
        list_del_init(&wusb_dev->cack_node);
        wusb_dev_free(wusb_dev);
-       d_fnend(1, NULL, "%s (wusb_dev %p) = void\n", __func__, wusb_dev);
 }
 EXPORT_SYMBOL_GPL(wusb_dev_destroy);
 
@@ -1190,8 +1018,6 @@ EXPORT_SYMBOL_GPL(wusb_dev_destroy);
  */
 int wusbhc_devconnect_create(struct wusbhc *wusbhc)
 {
-       d_fnstart(3, wusbhc->dev, "(wusbhc %p)\n", wusbhc);
-
        wusbhc->keep_alive_ie.hdr.bIEIdentifier = WUIE_ID_KEEP_ALIVE;
        wusbhc->keep_alive_ie.hdr.bLength = sizeof(wusbhc->keep_alive_ie.hdr);
        INIT_DELAYED_WORK(&wusbhc->keep_alive_timer, wusbhc_keep_alive_run);
@@ -1200,7 +1026,6 @@ int wusbhc_devconnect_create(struct wusbhc *wusbhc)
        wusbhc->cack_ie.hdr.bLength = sizeof(wusbhc->cack_ie.hdr);
        INIT_LIST_HEAD(&wusbhc->cack_list);
 
-       d_fnend(3, wusbhc->dev, "(wusbhc %p) = void\n", wusbhc);
        return 0;
 }
 
@@ -1209,8 +1034,7 @@ int wusbhc_devconnect_create(struct wusbhc *wusbhc)
  */
 void wusbhc_devconnect_destroy(struct wusbhc *wusbhc)
 {
-       d_fnstart(3, wusbhc->dev, "(wusbhc %p)\n", wusbhc);
-       d_fnend(3, wusbhc->dev, "(wusbhc %p) = void\n", wusbhc);
+       /* no op */
 }
 
 /*
@@ -1222,8 +1046,7 @@ void wusbhc_devconnect_destroy(struct wusbhc *wusbhc)
  * FIXME: This also enables the keep alives but this is not necessary
  * until there are connected and authenticated devices.
  */
-int wusbhc_devconnect_start(struct wusbhc *wusbhc,
-                           const struct wusb_ckhdid *chid)
+int wusbhc_devconnect_start(struct wusbhc *wusbhc)
 {
        struct device *dev = wusbhc->dev;
        struct wuie_host_info *hi;
@@ -1236,7 +1059,7 @@ int wusbhc_devconnect_start(struct wusbhc *wusbhc,
        hi->hdr.bLength       = sizeof(*hi);
        hi->hdr.bIEIdentifier = WUIE_ID_HOST_INFO;
        hi->attributes        = cpu_to_le16((wusbhc->rsv->stream << 3) | WUIE_HI_CAP_ALL);
-       hi->CHID              = *chid;
+       hi->CHID              = wusbhc->chid;
        result = wusbhc_mmcie_set(wusbhc, 0, 0, &hi->hdr);
        if (result < 0) {
                dev_err(dev, "Cannot add Host Info MMCIE: %d\n", result);
index cfa77a0..3b52161 100644 (file)
@@ -159,15 +159,35 @@ found:
 }
 EXPORT_SYMBOL_GPL(wusbhc_mmcie_rm);
 
+static int wusbhc_mmc_start(struct wusbhc *wusbhc)
+{
+       int ret;
+
+       mutex_lock(&wusbhc->mutex);
+       ret = wusbhc->start(wusbhc);
+       if (ret >= 0)
+               wusbhc->active = 1;
+       mutex_unlock(&wusbhc->mutex);
+
+       return ret;
+}
+
+static void wusbhc_mmc_stop(struct wusbhc *wusbhc)
+{
+       mutex_lock(&wusbhc->mutex);
+       wusbhc->active = 0;
+       wusbhc->stop(wusbhc, WUSB_CHANNEL_STOP_DELAY_MS);
+       mutex_unlock(&wusbhc->mutex);
+}
+
 /*
  * wusbhc_start - start transmitting MMCs and accepting connections
  * @wusbhc: the HC to start
- * @chid: the CHID to use for this host
  *
  * Establishes a cluster reservation, enables device connections, and
  * starts MMCs with appropriate DNTS parameters.
  */
-int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid)
+int wusbhc_start(struct wusbhc *wusbhc)
 {
        int result;
        struct device *dev = wusbhc->dev;
@@ -181,7 +201,7 @@ int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid)
                goto error_rsv_establish;
        }
 
-       result = wusbhc_devconnect_start(wusbhc, chid);
+       result = wusbhc_devconnect_start(wusbhc);
        if (result < 0) {
                dev_err(dev, "error enabling device connections: %d\n", result);
                goto error_devconnect_start;
@@ -199,12 +219,12 @@ int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid)
                dev_err(dev, "Cannot set DNTS parameters: %d\n", result);
                goto error_set_num_dnts;
        }
-       result = wusbhc->start(wusbhc);
+       result = wusbhc_mmc_start(wusbhc);
        if (result < 0) {
                dev_err(dev, "error starting wusbch: %d\n", result);
                goto error_wusbhc_start;
        }
-       wusbhc->active = 1;
+
        return 0;
 
 error_wusbhc_start:
@@ -219,76 +239,17 @@ error_rsv_establish:
 }
 
 /*
- * Disconnect all from the WUSB Channel
- *
- * Send a Host Disconnect IE in the MMC, wait, don't send it any more
- */
-static int __wusbhc_host_disconnect_ie(struct wusbhc *wusbhc)
-{
-       int result = -ENOMEM;
-       struct wuie_host_disconnect *host_disconnect_ie;
-       might_sleep();
-       host_disconnect_ie = kmalloc(sizeof(*host_disconnect_ie), GFP_KERNEL);
-       if (host_disconnect_ie == NULL)
-               goto error_alloc;
-       host_disconnect_ie->hdr.bLength       = sizeof(*host_disconnect_ie);
-       host_disconnect_ie->hdr.bIEIdentifier = WUIE_ID_HOST_DISCONNECT;
-       result = wusbhc_mmcie_set(wusbhc, 0, 0, &host_disconnect_ie->hdr);
-       if (result < 0)
-               goto error_mmcie_set;
-
-       /* WUSB1.0[8.5.3.1 & 7.5.2] */
-       msleep(100);
-       wusbhc_mmcie_rm(wusbhc, &host_disconnect_ie->hdr);
-error_mmcie_set:
-       kfree(host_disconnect_ie);
-error_alloc:
-       return result;
-}
-
-/*
  * wusbhc_stop - stop transmitting MMCs
  * @wusbhc: the HC to stop
  *
- * Send a Host Disconnect IE, wait, remove all the MMCs (stop sending MMCs).
- *
- * If we can't allocate a Host Stop IE, screw it, we don't notify the
- * devices we are disconnecting...
+ * Stops the WUSB channel and removes the cluster reservation.
  */
 void wusbhc_stop(struct wusbhc *wusbhc)
 {
-       if (wusbhc->active) {
-               wusbhc->active = 0;
-               wusbhc->stop(wusbhc);
-               wusbhc_sec_stop(wusbhc);
-               __wusbhc_host_disconnect_ie(wusbhc);
-               wusbhc_devconnect_stop(wusbhc);
-               wusbhc_rsv_terminate(wusbhc);
-       }
-}
-EXPORT_SYMBOL_GPL(wusbhc_stop);
-
-/*
- * Change the CHID in a WUSB Channel
- *
- * If it is just a new CHID, send a Host Disconnect IE and then change
- * the CHID IE.
- */
-static int __wusbhc_chid_change(struct wusbhc *wusbhc,
-                               const struct wusb_ckhdid *chid)
-{
-       int result = -ENOSYS;
-       struct device *dev = wusbhc->dev;
-       dev_err(dev, "%s() not implemented yet\n", __func__);
-       return result;
-
-       BUG_ON(wusbhc->wuie_host_info == NULL);
-       __wusbhc_host_disconnect_ie(wusbhc);
-       wusbhc->wuie_host_info->CHID = *chid;
-       result = wusbhc_mmcie_set(wusbhc, 0, 0, &wusbhc->wuie_host_info->hdr);
-       if (result < 0)
-               dev_err(dev, "Can't update Host Info WUSB IE: %d\n", result);
-       return result;
+       wusbhc_mmc_stop(wusbhc);
+       wusbhc_sec_stop(wusbhc);
+       wusbhc_devconnect_stop(wusbhc);
+       wusbhc_rsv_terminate(wusbhc);
 }
 
 /*
@@ -306,16 +267,19 @@ int wusbhc_chid_set(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid)
                chid = NULL;
 
        mutex_lock(&wusbhc->mutex);
-       if (wusbhc->active) {
-               if (chid)
-                       result = __wusbhc_chid_change(wusbhc, chid);
-               else
-                       wusbhc_stop(wusbhc);
-       } else {
-               if (chid)
-                       wusbhc_start(wusbhc, chid);
+       if (chid) {
+               if (wusbhc->active) {
+                       mutex_unlock(&wusbhc->mutex);
+                       return -EBUSY;
+               }
+               wusbhc->chid = *chid;
        }
        mutex_unlock(&wusbhc->mutex);
+
+       if (chid)
+               result = uwb_radio_start(&wusbhc->pal);
+       else
+               uwb_radio_stop(&wusbhc->pal);
        return result;
 }
 EXPORT_SYMBOL_GPL(wusbhc_chid_set);
index 7cc51e9..d0b172c 100644 (file)
  */
 #include "wusbhc.h"
 
+static void wusbhc_channel_changed(struct uwb_pal *pal, int channel)
+{
+       struct wusbhc *wusbhc = container_of(pal, struct wusbhc, pal);
+
+       if (channel < 0)
+               wusbhc_stop(wusbhc);
+       else
+               wusbhc_start(wusbhc);
+}
+
 /**
  * wusbhc_pal_register - register the WUSB HC as a UWB PAL
  * @wusbhc: the WUSB HC
@@ -28,8 +38,10 @@ int wusbhc_pal_register(struct wusbhc *wusbhc)
 
        wusbhc->pal.name   = "wusbhc";
        wusbhc->pal.device = wusbhc->usb_hcd.self.controller;
+       wusbhc->pal.rc     = wusbhc->uwb_rc;
+       wusbhc->pal.channel_changed = wusbhc_channel_changed;
 
-       return uwb_pal_register(wusbhc->uwb_rc, &wusbhc->pal);
+       return uwb_pal_register(&wusbhc->pal);
 }
 
 /**
@@ -38,5 +50,5 @@ int wusbhc_pal_register(struct wusbhc *wusbhc)
  */
 void wusbhc_pal_unregister(struct wusbhc *wusbhc)
 {
-       uwb_pal_unregister(wusbhc->uwb_rc, &wusbhc->pal);
+       uwb_pal_unregister(&wusbhc->pal);
 }
index fc63e77..4ed9736 100644 (file)
@@ -48,18 +48,19 @@ static void wusbhc_rsv_complete_cb(struct uwb_rsv *rsv)
 {
        struct wusbhc *wusbhc = rsv->pal_priv;
        struct device *dev = wusbhc->dev;
+       struct uwb_mas_bm mas;
        char buf[72];
 
        switch (rsv->state) {
        case UWB_RSV_STATE_O_ESTABLISHED:
-               bitmap_scnprintf(buf, sizeof(buf), rsv->mas.bm, UWB_NUM_MAS);
+               uwb_rsv_get_usable_mas(rsv, &mas);
+               bitmap_scnprintf(buf, sizeof(buf), mas.bm, UWB_NUM_MAS);
                dev_dbg(dev, "established reservation: %s\n", buf);
-               wusbhc_bwa_set(wusbhc, rsv->stream, &rsv->mas);
+               wusbhc_bwa_set(wusbhc, rsv->stream, &mas);
                break;
        case UWB_RSV_STATE_NONE:
                dev_dbg(dev, "removed reservation\n");
                wusbhc_bwa_set(wusbhc, 0, NULL);
-               wusbhc->rsv = NULL;
                break;
        default:
                dev_dbg(dev, "unexpected reservation state: %d\n", rsv->state);
@@ -86,13 +87,12 @@ int wusbhc_rsv_establish(struct wusbhc *wusbhc)
        bcid.data[0] = wusbhc->cluster_id;
        bcid.data[1] = 0;
 
-       rsv->owner = &rc->uwb_dev;
        rsv->target.type = UWB_RSV_TARGET_DEVADDR;
        rsv->target.devaddr = bcid;
        rsv->type = UWB_DRP_TYPE_PRIVATE;
-       rsv->max_mas = 256;
-       rsv->min_mas = 16;  /* one MAS per zone? */
-       rsv->sparsity = 16; /* at least one MAS in each zone? */
+       rsv->max_mas = 256; /* try to get as much as possible */
+       rsv->min_mas = 15;  /* one MAS per zone */
+       rsv->max_interval = 1; /* max latency is one zone */
        rsv->is_multicast = true;
 
        ret = uwb_rsv_establish(rsv);
@@ -105,11 +105,14 @@ int wusbhc_rsv_establish(struct wusbhc *wusbhc)
 
 
 /**
- * wusbhc_rsv_terminate - terminate any cluster reservation
+ * wusbhc_rsv_terminate - terminate the cluster reservation
  * @wusbhc: the WUSB host whose reservation is to be terminated
  */
 void wusbhc_rsv_terminate(struct wusbhc *wusbhc)
 {
-       if (wusbhc->rsv)
+       if (wusbhc->rsv) {
                uwb_rsv_terminate(wusbhc->rsv);
+               uwb_rsv_destroy(wusbhc->rsv);
+               wusbhc->rsv = NULL;
+       }
 }
index 267a643..95c6fa3 100644 (file)
  */
 #include "wusbhc.h"
 
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
-
 /*
  * Reset a fake port
  *
- * This can be called to reset a port from any other state or to reset
- * it when connecting. In Wireless USB they are different; when doing
- * a new connect that involves going over the authentication. When
- * just reseting, its a different story.
+ * Using a Reset Device IE is too heavyweight as it causes the device
+ * to enter the UnConnected state and leave the cluster, this can mean
+ * that when the device reconnects it is connected to a different fake
+ * port.
+ *
+ * Instead, reset authenticated devices with a SetAddress(0), followed
+ * by a SetAddresss(AuthAddr).
  *
- * The Linux USB stack resets a port twice before it considers it
- * enabled, so we have to detect and ignore that.
+ * For unauthenticated devices just pretend to reset but do nothing.
+ * If the device initialization continues to fail it will eventually
+ * time out after TrustTimeout and enter the UnConnected state.
  *
  * @wusbhc is assumed referenced and @wusbhc->mutex unlocked.
  *
@@ -97,20 +98,20 @@ static int wusbhc_rh_port_reset(struct wusbhc *wusbhc, u8 port_idx)
 {
        int result = 0;
        struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx);
+       struct wusb_dev *wusb_dev = port->wusb_dev;
 
-       d_fnstart(3, wusbhc->dev, "(wusbhc %p port_idx %u)\n",
-                 wusbhc, port_idx);
-       if (port->reset_count == 0) {
-               wusbhc_devconnect_auth(wusbhc, port_idx);
-               port->reset_count++;
-       } else if (port->reset_count == 1)
-               /* see header */
-               d_printf(2, wusbhc->dev, "Ignoring second reset on port_idx "
-                       "%u\n", port_idx);
+       port->status |= USB_PORT_STAT_RESET;
+       port->change |= USB_PORT_STAT_C_RESET;
+
+       if (wusb_dev->addr & WUSB_DEV_ADDR_UNAUTH)
+               result = 0;
        else
-               result = wusbhc_dev_reset(wusbhc, port_idx);
-       d_fnend(3, wusbhc->dev, "(wusbhc %p port_idx %u) = %d\n",
-               wusbhc, port_idx, result);
+               result = wusb_dev_update_address(wusbhc, wusb_dev);
+
+       port->status &= ~USB_PORT_STAT_RESET;
+       port->status |= USB_PORT_STAT_ENABLE;
+       port->change |= USB_PORT_STAT_C_RESET | USB_PORT_STAT_C_ENABLE; 
+
        return result;
 }
 
@@ -138,7 +139,6 @@ int wusbhc_rh_status_data(struct usb_hcd *usb_hcd, char *_buf)
        size_t cnt, size;
        unsigned long *buf = (unsigned long *) _buf;
 
-       d_fnstart(1, wusbhc->dev, "(wusbhc %p)\n", wusbhc);
        /* WE DON'T LOCK, see comment */
        size = wusbhc->ports_max + 1 /* hub bit */;
        size = (size + 8 - 1) / 8;      /* round to bytes */
@@ -147,8 +147,6 @@ int wusbhc_rh_status_data(struct usb_hcd *usb_hcd, char *_buf)
                        set_bit(cnt + 1, buf);
                else
                        clear_bit(cnt + 1, buf);
-       d_fnend(1, wusbhc->dev, "(wusbhc %p) %u, buffer:\n", wusbhc, (int)size);
-       d_dump(1, wusbhc->dev, _buf, size);
        return size;
 }
 EXPORT_SYMBOL_GPL(wusbhc_rh_status_data);
@@ -197,9 +195,7 @@ static int wusbhc_rh_get_hub_descr(struct wusbhc *wusbhc, u16 wValue,
 static int wusbhc_rh_clear_hub_feat(struct wusbhc *wusbhc, u16 feature)
 {
        int result;
-       struct device *dev = wusbhc->dev;
 
-       d_fnstart(4, dev, "(%p, feature 0x%04u)\n", wusbhc, feature);
        switch (feature) {
        case C_HUB_LOCAL_POWER:
                /* FIXME: maybe plug bit 0 to the power input status,
@@ -211,7 +207,6 @@ static int wusbhc_rh_clear_hub_feat(struct wusbhc *wusbhc, u16 feature)
        default:
                result = -EPIPE;
        }
-       d_fnend(4, dev, "(%p, feature 0x%04u), %d\n", wusbhc, feature, result);
        return result;
 }
 
@@ -238,14 +233,10 @@ static int wusbhc_rh_get_hub_status(struct wusbhc *wusbhc, u32 *buf,
 static int wusbhc_rh_set_port_feat(struct wusbhc *wusbhc, u16 feature,
                                   u8 selector, u8 port_idx)
 {
-       int result = -EINVAL;
        struct device *dev = wusbhc->dev;
 
-       d_fnstart(4, dev, "(feat 0x%04u, selector 0x%u, port_idx %d)\n",
-                 feature, selector, port_idx);
-
        if (port_idx > wusbhc->ports_max)
-               goto error;
+               return -EINVAL;
 
        switch (feature) {
                /* According to USB2.0[11.24.2.13]p2, these features
@@ -255,35 +246,27 @@ static int wusbhc_rh_set_port_feat(struct wusbhc *wusbhc, u16 feature,
        case USB_PORT_FEAT_C_SUSPEND:
        case USB_PORT_FEAT_C_CONNECTION:
        case USB_PORT_FEAT_C_RESET:
-               result = 0;
-               break;
-
+               return 0;
        case USB_PORT_FEAT_POWER:
                /* No such thing, but we fake it works */
                mutex_lock(&wusbhc->mutex);
                wusb_port_by_idx(wusbhc, port_idx)->status |= USB_PORT_STAT_POWER;
                mutex_unlock(&wusbhc->mutex);
-               result = 0;
-               break;
+               return 0;
        case USB_PORT_FEAT_RESET:
-               result = wusbhc_rh_port_reset(wusbhc, port_idx);
-               break;
+               return wusbhc_rh_port_reset(wusbhc, port_idx);
        case USB_PORT_FEAT_ENABLE:
        case USB_PORT_FEAT_SUSPEND:
                dev_err(dev, "(port_idx %d) set feat %d/%d UNIMPLEMENTED\n",
                        port_idx, feature, selector);
-               result = -ENOSYS;
-               break;
+               return -ENOSYS;
        default:
                dev_err(dev, "(port_idx %d) set feat %d/%d UNKNOWN\n",
                        port_idx, feature, selector);
-               result = -EPIPE;
-               break;
+               return -EPIPE;
        }
-error:
-       d_fnend(4, dev, "(feat 0x%04u, selector 0x%u, port_idx %d) = %d\n",
-               feature, selector, port_idx, result);
-       return result;
+
+       return 0;
 }
 
 /*
@@ -294,17 +277,13 @@ error:
 static int wusbhc_rh_clear_port_feat(struct wusbhc *wusbhc, u16 feature,
                                     u8 selector, u8 port_idx)
 {
-       int result = -EINVAL;
+       int result = 0;
        struct device *dev = wusbhc->dev;
 
-       d_fnstart(4, dev, "(wusbhc %p feat 0x%04x selector %d port_idx %d)\n",
-                 wusbhc, feature, selector, port_idx);
-
        if (port_idx > wusbhc->ports_max)
-               goto error;
+               return -EINVAL;
 
        mutex_lock(&wusbhc->mutex);
-       result = 0;
        switch (feature) {
        case USB_PORT_FEAT_POWER:       /* fake port always on */
                /* According to USB2.0[11.24.2.7.1.4], no need to implement? */
@@ -324,10 +303,8 @@ static int wusbhc_rh_clear_port_feat(struct wusbhc *wusbhc, u16 feature,
                break;
        case USB_PORT_FEAT_SUSPEND:
        case USB_PORT_FEAT_C_SUSPEND:
-       case 0xffff:            /* ??? FIXME */
                dev_err(dev, "(port_idx %d) Clear feat %d/%d UNIMPLEMENTED\n",
                        port_idx, feature, selector);
-               /* dump_stack(); */
                result = -ENOSYS;
                break;
        default:
@@ -337,9 +314,7 @@ static int wusbhc_rh_clear_port_feat(struct wusbhc *wusbhc, u16 feature,
                break;
        }
        mutex_unlock(&wusbhc->mutex);
-error:
-       d_fnend(4, dev, "(wusbhc %p feat 0x%04x selector %d port_idx %d) = "
-               "%d\n", wusbhc, feature, selector, port_idx, result);
+
        return result;
 }
 
@@ -351,22 +326,17 @@ error:
 static int wusbhc_rh_get_port_status(struct wusbhc *wusbhc, u16 port_idx,
                                     u32 *_buf, u16 wLength)
 {
-       int result = -EINVAL;
        u16 *buf = (u16 *) _buf;
 
-       d_fnstart(1, wusbhc->dev, "(wusbhc %p port_idx %u wLength %u)\n",
-                 wusbhc, port_idx, wLength);
        if (port_idx > wusbhc->ports_max)
-               goto error;
+               return -EINVAL;
+
        mutex_lock(&wusbhc->mutex);
        buf[0] = cpu_to_le16(wusb_port_by_idx(wusbhc, port_idx)->status);
        buf[1] = cpu_to_le16(wusb_port_by_idx(wusbhc, port_idx)->change);
-       result = 0;
        mutex_unlock(&wusbhc->mutex);
-error:
-       d_fnend(1, wusbhc->dev, "(wusbhc %p) = %d, buffer:\n", wusbhc, result);
-       d_dump(1, wusbhc->dev, _buf, wLength);
-       return result;
+
+       return 0;
 }
 
 /*
index a101cad..f4aa28e 100644 (file)
 #include <linux/random.h>
 #include "wusbhc.h"
 
-/*
- * DEBUG & SECURITY WARNING!!!!
- *
- * If you enable this past 1, the debug code will weaken the
- * cryptographic safety of the system (on purpose, for debugging).
- *
- * Weaken means:
- *   we print secret keys and intermediate values all the way,
- */
-#undef D_LOCAL
-#define D_LOCAL 2
-#include <linux/uwb/debug.h>
-
 static void wusbhc_set_gtk_callback(struct urb *urb);
 static void wusbhc_gtk_rekey_done_work(struct work_struct *work);
 
@@ -219,7 +206,6 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc,
        const void *itr, *top;
        char buf[64];
 
-       d_fnstart(3, dev, "(usb_dev %p, wusb_dev %p)\n", usb_dev, wusb_dev);
        result = usb_get_descriptor(usb_dev, USB_DT_SECURITY,
                                    0, &secd, sizeof(secd));
        if (result < sizeof(secd)) {
@@ -228,8 +214,6 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc,
                goto error_secd;
        }
        secd_size = le16_to_cpu(secd.wTotalLength);
-       d_printf(5, dev, "got %d bytes of sec descriptor, total is %d\n",
-                result, secd_size);
        secd_buf = kmalloc(secd_size, GFP_KERNEL);
        if (secd_buf == NULL) {
                dev_err(dev, "Can't allocate space for security descriptors\n");
@@ -242,7 +226,6 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc,
                        "not enough data: %d\n", result);
                goto error_secd_all;
        }
-       d_printf(5, dev, "got %d bytes of sec descriptors\n", result);
        bytes = 0;
        itr = secd_buf + sizeof(secd);
        top = secd_buf + result;
@@ -279,14 +262,12 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc,
                goto error_no_ccm1;
        }
        wusb_dev->ccm1_etd = *ccm1_etd;
-       dev_info(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n",
-                buf, wusb_et_name(ccm1_etd->bEncryptionType),
-                ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex);
+       dev_dbg(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n",
+               buf, wusb_et_name(ccm1_etd->bEncryptionType),
+               ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex);
        result = 0;
        kfree(secd_buf);
 out:
-       d_fnend(3, dev, "(usb_dev %p, wusb_dev %p) = %d\n",
-               usb_dev, wusb_dev, result);
        return result;
 
 
@@ -303,32 +284,6 @@ void wusb_dev_sec_rm(struct wusb_dev *wusb_dev)
        /* Nothing so far */
 }
 
-static void hs_printk(unsigned level, struct device *dev,
-                     struct usb_handshake *hs)
-{
-       d_printf(level, dev,
-                "  bMessageNumber: %u\n"
-                "  bStatus:        %u\n"
-                "  tTKID:          %02x %02x %02x\n"
-                "  CDID:           %02x %02x %02x %02x %02x %02x %02x %02x\n"
-                "                  %02x %02x %02x %02x %02x %02x %02x %02x\n"
-                "  nonce:          %02x %02x %02x %02x %02x %02x %02x %02x\n"
-                "                  %02x %02x %02x %02x %02x %02x %02x %02x\n"
-                "  MIC:            %02x %02x %02x %02x %02x %02x %02x %02x\n",
-                hs->bMessageNumber, hs->bStatus,
-                hs->tTKID[2], hs->tTKID[1], hs->tTKID[0],
-                hs->CDID[0], hs->CDID[1], hs->CDID[2], hs->CDID[3],
-                hs->CDID[4], hs->CDID[5], hs->CDID[6], hs->CDID[7],
-                hs->CDID[8], hs->CDID[9], hs->CDID[10], hs->CDID[11],
-                hs->CDID[12], hs->CDID[13], hs->CDID[14], hs->CDID[15],
-                hs->nonce[0], hs->nonce[1], hs->nonce[2], hs->nonce[3],
-                hs->nonce[4], hs->nonce[5], hs->nonce[6], hs->nonce[7],
-                hs->nonce[8], hs->nonce[9], hs->nonce[10], hs->nonce[11],
-                hs->nonce[12], hs->nonce[13], hs->nonce[14], hs->nonce[15],
-                hs->MIC[0], hs->MIC[1], hs->MIC[2], hs->MIC[3],
-                hs->MIC[4], hs->MIC[5], hs->MIC[6], hs->MIC[7]);
-}
-
 /**
  * Update the address of an unauthenticated WUSB device
  *
@@ -338,8 +293,7 @@ static void hs_printk(unsigned level, struct device *dev,
  * Before the device's address (as known by it) was usb_dev->devnum |
  * 0x80 (unauthenticated address). With this we update it to usb_dev->devnum.
  */
-static int wusb_dev_update_address(struct wusbhc *wusbhc,
-                                  struct wusb_dev *wusb_dev)
+int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
 {
        int result = -ENOMEM;
        struct usb_device *usb_dev = wusb_dev->usb_dev;
@@ -422,9 +376,6 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev,
        get_random_bytes(&hs[0].nonce, sizeof(hs[0].nonce));
        memset(hs[0].MIC, 0, sizeof(hs[0].MIC));        /* Per WUSB1.0[T7-22] */
 
-       d_printf(1, dev, "I: sending hs1:\n");
-       hs_printk(2, dev, &hs[0]);
-
        result = usb_control_msg(
                usb_dev, usb_sndctrlpipe(usb_dev, 0),
                USB_REQ_SET_HANDSHAKE,
@@ -445,8 +396,6 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev,
                dev_err(dev, "Handshake2: request failed: %d\n", result);
                goto error_hs2;
        }
-       d_printf(1, dev, "got HS2:\n");
-       hs_printk(2, dev, &hs[1]);
 
        result = -EINVAL;
        if (hs[1].bMessageNumber != 2) {
@@ -487,10 +436,6 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev,
                        result);
                goto error_hs2;
        }
-       d_printf(2, dev, "KCK:\n");
-       d_dump(2, dev, keydvt_out.kck, sizeof(keydvt_out.kck));
-       d_printf(2, dev, "PTK:\n");
-       d_dump(2, dev, keydvt_out.ptk, sizeof(keydvt_out.ptk));
 
        /* Compute MIC and verify it */
        result = wusb_oob_mic(mic, keydvt_out.kck, &ccm_n, &hs[1]);
@@ -500,8 +445,6 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev,
                goto error_hs2;
        }
 
-       d_printf(2, dev, "MIC:\n");
-       d_dump(2, dev, mic, sizeof(mic));
        if (memcmp(hs[1].MIC, mic, sizeof(hs[1].MIC))) {
                dev_err(dev, "Handshake2 failed: MIC mismatch\n");
                goto error_hs2;
@@ -521,9 +464,6 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev,
                goto error_hs2;
        }
 
-       d_printf(1, dev, "I: sending hs3:\n");
-       hs_printk(2, dev, &hs[2]);
-
        result = usb_control_msg(
                usb_dev, usb_sndctrlpipe(usb_dev, 0),
                USB_REQ_SET_HANDSHAKE,
@@ -534,14 +474,11 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev,
                goto error_hs3;
        }
 
-       d_printf(1, dev, "I: turning on encryption on host for device\n");
-       d_dump(2, dev, keydvt_out.ptk, sizeof(keydvt_out.ptk));
        result = wusbhc->set_ptk(wusbhc, wusb_dev->port_idx, tkid,
                                 keydvt_out.ptk, sizeof(keydvt_out.ptk));
        if (result < 0)
                goto error_wusbhc_set_ptk;
 
-       d_printf(1, dev, "I: setting a GTK\n");
        result = wusb_dev_set_gtk(wusbhc, wusb_dev);
        if (result < 0) {
                dev_err(dev, "Set GTK for device: request failed: %d\n",
@@ -551,13 +488,12 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev,
 
        /* Update the device's address from unauth to auth */
        if (usb_dev->authenticated == 0) {
-               d_printf(1, dev, "I: updating addres to auth from non-auth\n");
                result = wusb_dev_update_address(wusbhc, wusb_dev);
                if (result < 0)
                        goto error_dev_update_address;
        }
        result = 0;
-       d_printf(1, dev, "I: 4way handshke done, device authenticated\n");
+       dev_info(dev, "device authenticated\n");
 
 error_dev_update_address:
 error_wusbhc_set_gtk:
@@ -570,10 +506,8 @@ error_hs1:
        memset(&keydvt_in, 0, sizeof(keydvt_in));
        memset(&ccm_n, 0, sizeof(ccm_n));
        memset(mic, 0, sizeof(mic));
-       if (result < 0) {
-               /* error path */
+       if (result < 0)
                wusb_dev_set_encryption(usb_dev, 0);
-       }
 error_dev_set_encryption:
        kfree(hs);
 error_kzalloc:
index 3f54299..17d2626 100644 (file)
@@ -51,7 +51,7 @@
  */
 #include <linux/workqueue.h>
 #include <linux/ctype.h>
-#include <linux/uwb/debug.h>
+
 #include "wa-hc.h"
 #include "wusbhc.h"
 
@@ -139,13 +139,10 @@ static void wa_notif_dispatch(struct work_struct *ws)
                        /* FIXME: unimplemented WA NOTIFs */
                        /* fallthru */
                default:
-                       if (printk_ratelimit()) {
-                               dev_err(dev, "HWA: unknown notification 0x%x, "
-                                       "%zu bytes; discarding\n",
-                                       notif_hdr->bNotifyType,
-                                       (size_t)notif_hdr->bLength);
-                               dump_bytes(dev, notif_hdr, 16);
-                       }
+                       dev_err(dev, "HWA: unknown notification 0x%x, "
+                               "%zu bytes; discarding\n",
+                               notif_hdr->bNotifyType,
+                               (size_t)notif_hdr->bLength);
                        break;
                }
        }
@@ -160,12 +157,9 @@ out:
         * discard the data, as this should not happen.
         */
 exhausted_buffer:
-       if (!printk_ratelimit())
-               goto out;
        dev_warn(dev, "HWA: device sent short notification, "
                 "%d bytes missing; discarding %d bytes.\n",
                 missing, (int)size);
-       dump_bytes(dev, itr, size);
        goto out;
 }
 
index f18e4aa..7369655 100644 (file)
 #include <linux/init.h>
 #include <asm/atomic.h>
 #include <linux/bitmap.h>
+
 #include "wusbhc.h"
 #include "wa-hc.h"
 
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
-
-
 static int __rpipe_get_descr(struct wahc *wa,
                             struct usb_rpipe_descriptor *descr, u16 index)
 {
@@ -76,7 +73,6 @@ static int __rpipe_get_descr(struct wahc *wa,
        /* Get the RPIPE descriptor -- we cannot use the usb_get_descriptor()
         * function because the arguments are different.
         */
-       d_printf(1, dev, "rpipe %u: get descr\n", index);
        result = usb_control_msg(
                wa->usb_dev, usb_rcvctrlpipe(wa->usb_dev, 0),
                USB_REQ_GET_DESCRIPTOR,
@@ -115,7 +111,6 @@ static int __rpipe_set_descr(struct wahc *wa,
        /* we cannot use the usb_get_descriptor() function because the
         * arguments are different.
         */
-       d_printf(1, dev, "rpipe %u: set descr\n", index);
        result = usb_control_msg(
                wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0),
                USB_REQ_SET_DESCRIPTOR,
@@ -174,13 +169,12 @@ void rpipe_destroy(struct kref *_rpipe)
 {
        struct wa_rpipe *rpipe = container_of(_rpipe, struct wa_rpipe, refcnt);
        u8 index = le16_to_cpu(rpipe->descr.wRPipeIndex);
-       d_fnstart(1, NULL, "(rpipe %p %u)\n", rpipe, index);
+
        if (rpipe->ep)
                rpipe->ep->hcpriv = NULL;
        rpipe_put_idx(rpipe->wa, index);
        wa_put(rpipe->wa);
        kfree(rpipe);
-       d_fnend(1, NULL, "(rpipe %p %u)\n", rpipe, index);
 }
 EXPORT_SYMBOL_GPL(rpipe_destroy);
 
@@ -202,7 +196,6 @@ static int rpipe_get_idle(struct wa_rpipe **prpipe, struct wahc *wa, u8 crs,
        struct wa_rpipe *rpipe;
        struct device *dev = &wa->usb_iface->dev;
 
-       d_fnstart(3, dev, "(wa %p crs 0x%02x)\n", wa, crs);
        rpipe = kzalloc(sizeof(*rpipe), gfp);
        if (rpipe == NULL)
                return -ENOMEM;
@@ -223,14 +216,12 @@ static int rpipe_get_idle(struct wa_rpipe **prpipe, struct wahc *wa, u8 crs,
        }
        *prpipe = NULL;
        kfree(rpipe);
-       d_fnend(3, dev, "(wa %p crs 0x%02x) = -ENXIO\n", wa, crs);
        return -ENXIO;
 
 found:
        set_bit(rpipe_idx, wa->rpipe_bm);
        rpipe->wa = wa_get(wa);
        *prpipe = rpipe;
-       d_fnstart(3, dev, "(wa %p crs 0x%02x) = 0\n", wa, crs);
        return 0;
 }
 
@@ -239,7 +230,6 @@ static int __rpipe_reset(struct wahc *wa, unsigned index)
        int result;
        struct device *dev = &wa->usb_iface->dev;
 
-       d_printf(1, dev, "rpipe %u: reset\n", index);
        result = usb_control_msg(
                wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0),
                USB_REQ_RPIPE_RESET,
@@ -276,7 +266,6 @@ static struct usb_wireless_ep_comp_descriptor *rpipe_epc_find(
        struct usb_descriptor_header *hdr;
        struct usb_wireless_ep_comp_descriptor *epcd;
 
-       d_fnstart(3, dev, "(ep %p)\n", ep);
        if (ep->desc.bEndpointAddress == 0) {
                epcd = &epc0;
                goto out;
@@ -310,7 +299,6 @@ static struct usb_wireless_ep_comp_descriptor *rpipe_epc_find(
                itr_size -= hdr->bDescriptorType;
        }
 out:
-       d_fnend(3, dev, "(ep %p) = %p\n", ep, epcd);
        return epcd;
 }
 
@@ -329,8 +317,6 @@ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa,
        struct usb_wireless_ep_comp_descriptor *epcd;
        u8 unauth;
 
-       d_fnstart(3, dev, "(rpipe %p wa %p ep %p, urb %p)\n",
-                   rpipe, wa, ep, urb);
        epcd = rpipe_epc_find(dev, ep);
        if (epcd == NULL) {
                dev_err(dev, "ep 0x%02x: can't find companion descriptor\n",
@@ -350,10 +336,12 @@ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa,
        /* FIXME: use maximum speed as supported or recommended by device */
        rpipe->descr.bSpeed = usb_pipeendpoint(urb->pipe) == 0 ?
                UWB_PHY_RATE_53 : UWB_PHY_RATE_200;
-       d_printf(2, dev, "addr %u (0x%02x) rpipe #%u ep# %u speed %d\n",
-                urb->dev->devnum, urb->dev->devnum | unauth,
-                le16_to_cpu(rpipe->descr.wRPipeIndex),
-                usb_pipeendpoint(urb->pipe), rpipe->descr.bSpeed);
+
+       dev_dbg(dev, "addr %u (0x%02x) rpipe #%u ep# %u speed %d\n",
+               urb->dev->devnum, urb->dev->devnum | unauth,
+               le16_to_cpu(rpipe->descr.wRPipeIndex),
+               usb_pipeendpoint(urb->pipe), rpipe->descr.bSpeed);
+
        /* see security.c:wusb_update_address() */
        if (unlikely(urb->dev->devnum == 0x80))
                rpipe->descr.bDeviceAddress = 0;
@@ -384,8 +372,6 @@ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa,
        }
        result = 0;
 error:
-       d_fnend(3, dev, "(rpipe %p wa %p ep %p urb %p) = %d\n",
-                 rpipe, wa, ep, urb, result);
        return result;
 }
 
@@ -405,8 +391,6 @@ static int rpipe_check_aim(const struct wa_rpipe *rpipe, const struct wahc *wa,
        u8 unauth = (usb_dev->wusb && !usb_dev->authenticated) ? 0x80 : 0;
        u8 portnum = wusb_port_no_to_idx(urb->dev->portnum);
 
-       d_fnstart(3, dev, "(rpipe %p wa %p ep %p, urb %p)\n",
-                   rpipe, wa, ep, urb);
 #define AIM_CHECK(rdf, val, text)                                      \
        do {                                                            \
                if (rpipe->descr.rdf != (val)) {                        \
@@ -451,8 +435,6 @@ int rpipe_get_by_ep(struct wahc *wa, struct usb_host_endpoint *ep,
        struct wa_rpipe *rpipe;
        u8 eptype;
 
-       d_fnstart(3, dev, "(wa %p ep %p urb %p gfp 0x%08x)\n", wa, ep, urb,
-                 gfp);
        mutex_lock(&wa->rpipe_mutex);
        rpipe = ep->hcpriv;
        if (rpipe != NULL) {
@@ -462,9 +444,9 @@ int rpipe_get_by_ep(struct wahc *wa, struct usb_host_endpoint *ep,
                                goto error;
                }
                __rpipe_get(rpipe);
-               d_printf(2, dev, "ep 0x%02x: reusing rpipe %u\n",
-                        ep->desc.bEndpointAddress,
-                        le16_to_cpu(rpipe->descr.wRPipeIndex));
+               dev_dbg(dev, "ep 0x%02x: reusing rpipe %u\n",
+                       ep->desc.bEndpointAddress,
+                       le16_to_cpu(rpipe->descr.wRPipeIndex));
        } else {
                /* hmm, assign idle rpipe, aim it */
                result = -ENOBUFS;
@@ -480,14 +462,12 @@ int rpipe_get_by_ep(struct wahc *wa, struct usb_host_endpoint *ep,
                ep->hcpriv = rpipe;
                rpipe->ep = ep;
                __rpipe_get(rpipe);     /* for caching into ep->hcpriv */
-               d_printf(2, dev, "ep 0x%02x: using rpipe %u\n",
-                        ep->desc.bEndpointAddress,
-                        le16_to_cpu(rpipe->descr.wRPipeIndex));
+               dev_dbg(dev, "ep 0x%02x: using rpipe %u\n",
+                       ep->desc.bEndpointAddress,
+                       le16_to_cpu(rpipe->descr.wRPipeIndex));
        }
-       d_dump(4, dev, &rpipe->descr, sizeof(rpipe->descr));
 error:
        mutex_unlock(&wa->rpipe_mutex);
-       d_fnend(3, dev, "(wa %p ep %p urb %p gfp 0x%08x)\n", wa, ep, urb, gfp);
        return result;
 }
 
@@ -507,7 +487,7 @@ int wa_rpipes_create(struct wahc *wa)
 void wa_rpipes_destroy(struct wahc *wa)
 {
        struct device *dev = &wa->usb_iface->dev;
-       d_fnstart(3, dev, "(wa %p)\n", wa);
+
        if (!bitmap_empty(wa->rpipe_bm, wa->rpipes)) {
                char buf[256];
                WARN_ON(1);
@@ -515,7 +495,6 @@ void wa_rpipes_destroy(struct wahc *wa)
                dev_err(dev, "BUG: pipes not released on exit: %s\n", buf);
        }
        kfree(wa->rpipe_bm);
-       d_fnend(3, dev, "(wa %p)\n", wa);
 }
 
 /*
@@ -530,33 +509,20 @@ void wa_rpipes_destroy(struct wahc *wa)
  */
 void rpipe_ep_disable(struct wahc *wa, struct usb_host_endpoint *ep)
 {
-       struct device *dev = &wa->usb_iface->dev;
        struct wa_rpipe *rpipe;
-       d_fnstart(2, dev, "(wa %p ep %p)\n", wa, ep);
+
        mutex_lock(&wa->rpipe_mutex);
        rpipe = ep->hcpriv;
        if (rpipe != NULL) {
-               unsigned rc = atomic_read(&rpipe->refcnt.refcount);
-               int result;
                u16 index = le16_to_cpu(rpipe->descr.wRPipeIndex);
 
-               if (rc != 1)
-                       d_printf(1, dev, "(wa %p ep %p) rpipe %p refcnt %u\n",
-                                wa, ep, rpipe, rc);
-
-               d_printf(1, dev, "rpipe %u: abort\n", index);
-               result = usb_control_msg(
+               usb_control_msg(
                        wa->usb_dev, usb_rcvctrlpipe(wa->usb_dev, 0),
                        USB_REQ_RPIPE_ABORT,
                        USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE,
                        0, index, NULL, 0, 1000 /* FIXME: arbitrary */);
-               if (result < 0 && result != -ENODEV /* dev is gone */)
-                       d_printf(1, dev, "(wa %p rpipe %u): abort failed: %d\n",
-                                wa, index, result);
                rpipe_put(rpipe);
        }
        mutex_unlock(&wa->rpipe_mutex);
-       d_fnend(2, dev, "(wa %p ep %p)\n", wa, ep);
-       return;
 }
 EXPORT_SYMBOL_GPL(rpipe_ep_disable);
index c038635..238a96a 100644 (file)
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/hash.h>
+
 #include "wa-hc.h"
 #include "wusbhc.h"
 
-#undef D_LOCAL
-#define D_LOCAL 0 /* 0 disabled, > 0 different levels... */
-#include <linux/uwb/debug.h>
-
 enum {
        WA_SEGS_MAX = 255,
 };
@@ -180,7 +177,6 @@ static void wa_xfer_destroy(struct kref *_xfer)
                }
        }
        kfree(xfer);
-       d_printf(2, NULL, "xfer %p destroyed\n", xfer);
 }
 
 static void wa_xfer_get(struct wa_xfer *xfer)
@@ -190,10 +186,7 @@ static void wa_xfer_get(struct wa_xfer *xfer)
 
 static void wa_xfer_put(struct wa_xfer *xfer)
 {
-       d_fnstart(3, NULL, "(xfer %p) -- ref count bef put %d\n",
-                   xfer, atomic_read(&xfer->refcnt.refcount));
        kref_put(&xfer->refcnt, wa_xfer_destroy);
-       d_fnend(3, NULL, "(xfer %p) = void\n", xfer);
 }
 
 /*
@@ -209,7 +202,7 @@ static void wa_xfer_put(struct wa_xfer *xfer)
 static void wa_xfer_giveback(struct wa_xfer *xfer)
 {
        unsigned long flags;
-       d_fnstart(3, NULL, "(xfer %p)\n", xfer);
+
        spin_lock_irqsave(&xfer->wa->xfer_list_lock, flags);
        list_del_init(&xfer->list_node);
        spin_unlock_irqrestore(&xfer->wa->xfer_list_lock, flags);
@@ -217,7 +210,6 @@ static void wa_xfer_giveback(struct wa_xfer *xfer)
        wusbhc_giveback_urb(xfer->wa->wusb, xfer->urb, xfer->result);
        wa_put(xfer->wa);
        wa_xfer_put(xfer);
-       d_fnend(3, NULL, "(xfer %p) = void\n", xfer);
 }
 
 /*
@@ -227,13 +219,10 @@ static void wa_xfer_giveback(struct wa_xfer *xfer)
  */
 static void wa_xfer_completion(struct wa_xfer *xfer)
 {
-       d_fnstart(3, NULL, "(xfer %p)\n", xfer);
        if (xfer->wusb_dev)
                wusb_dev_put(xfer->wusb_dev);
        rpipe_put(xfer->ep->hcpriv);
        wa_xfer_giveback(xfer);
-       d_fnend(3, NULL, "(xfer %p) = void\n", xfer);
-       return;
 }
 
 /*
@@ -243,12 +232,12 @@ static void wa_xfer_completion(struct wa_xfer *xfer)
  */
 static unsigned __wa_xfer_is_done(struct wa_xfer *xfer)
 {
+       struct device *dev = &xfer->wa->usb_iface->dev;
        unsigned result, cnt;
        struct wa_seg *seg;
        struct urb *urb = xfer->urb;
        unsigned found_short = 0;
 
-       d_fnstart(3, NULL, "(xfer %p)\n", xfer);
        result = xfer->segs_done == xfer->segs_submitted;
        if (result == 0)
                goto out;
@@ -258,10 +247,8 @@ static unsigned __wa_xfer_is_done(struct wa_xfer *xfer)
                switch (seg->status) {
                case WA_SEG_DONE:
                        if (found_short && seg->result > 0) {
-                               if (printk_ratelimit())
-                                       printk(KERN_ERR "xfer %p#%u: bad short "
-                                              "segments (%zu)\n", xfer, cnt,
-                                              seg->result);
+                               dev_dbg(dev, "xfer %p#%u: bad short segments (%zu)\n",
+                                       xfer, cnt, seg->result);
                                urb->status = -EINVAL;
                                goto out;
                        }
@@ -269,36 +256,30 @@ static unsigned __wa_xfer_is_done(struct wa_xfer *xfer)
                        if (seg->result < xfer->seg_size
                            && cnt != xfer->segs-1)
                                found_short = 1;
-                       d_printf(2, NULL, "xfer %p#%u: DONE short %d "
-                                "result %zu urb->actual_length %d\n",
-                                xfer, seg->index, found_short, seg->result,
-                                urb->actual_length);
+                       dev_dbg(dev, "xfer %p#%u: DONE short %d "
+                               "result %zu urb->actual_length %d\n",
+                               xfer, seg->index, found_short, seg->result,
+                               urb->actual_length);
                        break;
                case WA_SEG_ERROR:
                        xfer->result = seg->result;
-                       d_printf(2, NULL, "xfer %p#%u: ERROR result %zu\n",
-                                xfer, seg->index, seg->result);
+                       dev_dbg(dev, "xfer %p#%u: ERROR result %zu\n",
+                               xfer, seg->index, seg->result);
                        goto out;
                case WA_SEG_ABORTED:
-                       WARN_ON(urb->status != -ECONNRESET
-                               && urb->status != -ENOENT);
-                       d_printf(2, NULL, "xfer %p#%u ABORTED: result %d\n",
-                                xfer, seg->index, urb->status);
+                       dev_dbg(dev, "xfer %p#%u ABORTED: result %d\n",
+                               xfer, seg->index, urb->status);
                        xfer->result = urb->status;
                        goto out;
                default:
-                       /* if (printk_ratelimit()) */
-                               printk(KERN_ERR "xfer %p#%u: "
-                                      "is_done bad state %d\n",
-                                      xfer, cnt, seg->status);
+                       dev_warn(dev, "xfer %p#%u: is_done bad state %d\n",
+                                xfer, cnt, seg->status);
                        xfer->result = -EINVAL;
-                       WARN_ON(1);
                        goto out;
                }
        }
        xfer->result = 0;
 out:
-       d_fnend(3, NULL, "(xfer %p) = void\n", xfer);
        return result;
 }
 
@@ -424,8 +405,6 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer,
        struct urb *urb = xfer->urb;
        struct wa_rpipe *rpipe = xfer->ep->hcpriv;
 
-       d_fnstart(3, dev, "(xfer %p [rpipe %p] urb %p)\n",
-                 xfer, rpipe, urb);
        switch (rpipe->descr.bmAttribute & 0x3) {
        case USB_ENDPOINT_XFER_CONTROL:
                *pxfer_type = WA_XFER_TYPE_CTL;
@@ -472,12 +451,10 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer,
        if (xfer->segs == 0 && *pxfer_type == WA_XFER_TYPE_CTL)
                xfer->segs = 1;
 error:
-       d_fnend(3, dev, "(xfer %p [rpipe %p] urb %p) = %d\n",
-               xfer, rpipe, urb, (int)result);
        return result;
 }
 
-/** Fill in the common request header and xfer-type specific data. */
+/* Fill in the common request header and xfer-type specific data. */
 static void __wa_xfer_setup_hdr0(struct wa_xfer *xfer,
                                 struct wa_xfer_hdr *xfer_hdr0,
                                 enum wa_xfer_type xfer_type,
@@ -534,14 +511,13 @@ static void wa_seg_dto_cb(struct urb *urb)
        unsigned rpipe_ready = 0;
        u8 done = 0;
 
-       d_fnstart(3, NULL, "(urb %p [%d])\n", urb, urb->status);
        switch (urb->status) {
        case 0:
                spin_lock_irqsave(&xfer->lock, flags);
                wa = xfer->wa;
                dev = &wa->usb_iface->dev;
-               d_printf(2, dev, "xfer %p#%u: data out done (%d bytes)\n",
-                          xfer, seg->index, urb->actual_length);
+               dev_dbg(dev, "xfer %p#%u: data out done (%d bytes)\n",
+                       xfer, seg->index, urb->actual_length);
                if (seg->status < WA_SEG_PENDING)
                        seg->status = WA_SEG_PENDING;
                seg->result = urb->actual_length;
@@ -555,9 +531,8 @@ static void wa_seg_dto_cb(struct urb *urb)
                wa = xfer->wa;
                dev = &wa->usb_iface->dev;
                rpipe = xfer->ep->hcpriv;
-               if (printk_ratelimit())
-                       dev_err(dev, "xfer %p#%u: data out error %d\n",
-                               xfer, seg->index, urb->status);
+               dev_dbg(dev, "xfer %p#%u: data out error %d\n",
+                       xfer, seg->index, urb->status);
                if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS,
                            EDC_ERROR_TIMEFRAME)){
                        dev_err(dev, "DTO: URB max acceptable errors "
@@ -578,7 +553,6 @@ static void wa_seg_dto_cb(struct urb *urb)
                if (rpipe_ready)
                        wa_xfer_delayed_run(rpipe);
        }
-       d_fnend(3, NULL, "(urb %p [%d]) = void\n", urb, urb->status);
 }
 
 /*
@@ -610,14 +584,12 @@ static void wa_seg_cb(struct urb *urb)
        unsigned rpipe_ready;
        u8 done = 0;
 
-       d_fnstart(3, NULL, "(urb %p [%d])\n", urb, urb->status);
        switch (urb->status) {
        case 0:
                spin_lock_irqsave(&xfer->lock, flags);
                wa = xfer->wa;
                dev = &wa->usb_iface->dev;
-               d_printf(2, dev, "xfer %p#%u: request done\n",
-                          xfer, seg->index);
+               dev_dbg(dev, "xfer %p#%u: request done\n", xfer, seg->index);
                if (xfer->is_inbound && seg->status < WA_SEG_PENDING)
                        seg->status = WA_SEG_PENDING;
                spin_unlock_irqrestore(&xfer->lock, flags);
@@ -652,7 +624,6 @@ static void wa_seg_cb(struct urb *urb)
                if (rpipe_ready)
                        wa_xfer_delayed_run(rpipe);
        }
-       d_fnend(3, NULL, "(urb %p [%d]) = void\n", urb, urb->status);
 }
 
 /*
@@ -750,9 +721,6 @@ static int __wa_xfer_setup(struct wa_xfer *xfer, struct urb *urb)
        size_t xfer_hdr_size, cnt, transfer_size;
        struct wa_xfer_hdr *xfer_hdr0, *xfer_hdr;
 
-       d_fnstart(3, dev, "(xfer %p [rpipe %p] urb %p)\n",
-                 xfer, xfer->ep->hcpriv, urb);
-
        result = __wa_xfer_setup_sizes(xfer, &xfer_type);
        if (result < 0)
                goto error_setup_sizes;
@@ -788,8 +756,6 @@ static int __wa_xfer_setup(struct wa_xfer *xfer, struct urb *urb)
        result = 0;
 error_setup_segs:
 error_setup_sizes:
-       d_fnend(3, dev, "(xfer %p [rpipe %p] urb %p) = %d\n",
-               xfer, xfer->ep->hcpriv, urb, result);
        return result;
 }
 
@@ -843,9 +809,6 @@ static void wa_xfer_delayed_run(struct wa_rpipe *rpipe)
        struct wa_xfer *xfer;
        unsigned long flags;
 
-       d_fnstart(1, dev, "(rpipe #%d) %d segments available\n",
-                 le16_to_cpu(rpipe->descr.wRPipeIndex),
-                 atomic_read(&rpipe->segs_available));
        spin_lock_irqsave(&rpipe->seg_lock, flags);
        while (atomic_read(&rpipe->segs_available) > 0
              && !list_empty(&rpipe->seg_list)) {
@@ -854,10 +817,8 @@ static void wa_xfer_delayed_run(struct wa_rpipe *rpipe)
                list_del(&seg->list_node);
                xfer = seg->xfer;
                result = __wa_seg_submit(rpipe, xfer, seg);
-               d_printf(1, dev, "xfer %p#%u submitted from delayed "
-                        "[%d segments available] %d\n",
-                        xfer, seg->index,
-                        atomic_read(&rpipe->segs_available), result);
+               dev_dbg(dev, "xfer %p#%u submitted from delayed [%d segments available] %d\n",
+                       xfer, seg->index, atomic_read(&rpipe->segs_available), result);
                if (unlikely(result < 0)) {
                        spin_unlock_irqrestore(&rpipe->seg_lock, flags);
                        spin_lock_irqsave(&xfer->lock, flags);
@@ -868,10 +829,6 @@ static void wa_xfer_delayed_run(struct wa_rpipe *rpipe)
                }
        }
        spin_unlock_irqrestore(&rpipe->seg_lock, flags);
-       d_fnend(1, dev, "(rpipe #%d) = void, %d segments available\n",
-               le16_to_cpu(rpipe->descr.wRPipeIndex),
-               atomic_read(&rpipe->segs_available));
-
 }
 
 /*
@@ -894,9 +851,6 @@ static int __wa_xfer_submit(struct wa_xfer *xfer)
        u8 available;
        u8 empty;
 
-       d_fnstart(3, dev, "(xfer %p [rpipe %p])\n",
-                 xfer, xfer->ep->hcpriv);
-
        spin_lock_irqsave(&wa->xfer_list_lock, flags);
        list_add_tail(&xfer->list_node, &wa->xfer_list);
        spin_unlock_irqrestore(&wa->xfer_list_lock, flags);
@@ -908,30 +862,24 @@ static int __wa_xfer_submit(struct wa_xfer *xfer)
                available = atomic_read(&rpipe->segs_available);
                empty = list_empty(&rpipe->seg_list);
                seg = xfer->seg[cnt];
-               d_printf(2, dev, "xfer %p#%u: available %u empty %u (%s)\n",
-                        xfer, cnt, available, empty,
-                        available == 0 || !empty ? "delayed" : "submitted");
+               dev_dbg(dev, "xfer %p#%u: available %u empty %u (%s)\n",
+                       xfer, cnt, available, empty,
+                       available == 0 || !empty ? "delayed" : "submitted");
                if (available == 0 || !empty) {
-                       d_printf(1, dev, "xfer %p#%u: delayed\n", xfer, cnt);
+                       dev_dbg(dev, "xfer %p#%u: delayed\n", xfer, cnt);
                        seg->status = WA_SEG_DELAYED;
                        list_add_tail(&seg->list_node, &rpipe->seg_list);
                } else {
                        result = __wa_seg_submit(rpipe, xfer, seg);
-                       if (result < 0)
+                       if (result < 0) {
+                               __wa_xfer_abort(xfer);
                                goto error_seg_submit;
+                       }
                }
                xfer->segs_submitted++;
        }
-       spin_unlock_irqrestore(&rpipe->seg_lock, flags);
-       d_fnend(3, dev, "(xfer %p [rpipe %p]) = void\n", xfer,
-               xfer->ep->hcpriv);
-       return result;
-
 error_seg_submit:
-       __wa_xfer_abort(xfer);
        spin_unlock_irqrestore(&rpipe->seg_lock, flags);
-       d_fnend(3, dev, "(xfer %p [rpipe %p]) = void\n", xfer,
-               xfer->ep->hcpriv);
        return result;
 }
 
@@ -964,11 +912,9 @@ static void wa_urb_enqueue_b(struct wa_xfer *xfer)
        struct urb *urb = xfer->urb;
        struct wahc *wa = xfer->wa;
        struct wusbhc *wusbhc = wa->wusb;
-       struct device *dev = &wa->usb_iface->dev;
        struct wusb_dev *wusb_dev;
        unsigned done;
 
-       d_fnstart(3, dev, "(wa %p urb %p)\n", wa, urb);
        result = rpipe_get_by_ep(wa, xfer->ep, urb, xfer->gfp);
        if (result < 0)
                goto error_rpipe_get;
@@ -997,7 +943,6 @@ static void wa_urb_enqueue_b(struct wa_xfer *xfer)
        if (result < 0)
                goto error_xfer_submit;
        spin_unlock_irqrestore(&xfer->lock, flags);
-       d_fnend(3, dev, "(wa %p urb %p) = void\n", wa, urb);
        return;
 
        /* this is basically wa_xfer_completion() broken up wa_xfer_giveback()
@@ -1015,7 +960,6 @@ error_dev_gone:
 error_rpipe_get:
        xfer->result = result;
        wa_xfer_giveback(xfer);
-       d_fnend(3, dev, "(wa %p urb %p) = (void) %d\n", wa, urb, result);
        return;
 
 error_xfer_submit:
@@ -1024,8 +968,6 @@ error_xfer_submit:
        spin_unlock_irqrestore(&xfer->lock, flags);
        if (done)
                wa_xfer_completion(xfer);
-       d_fnend(3, dev, "(wa %p urb %p) = (void) %d\n", wa, urb, result);
-       return;
 }
 
 /*
@@ -1041,11 +983,9 @@ error_xfer_submit:
 void wa_urb_enqueue_run(struct work_struct *ws)
 {
        struct wahc *wa = container_of(ws, struct wahc, xfer_work);
-       struct device *dev = &wa->usb_iface->dev;
        struct wa_xfer *xfer, *next;
        struct urb *urb;
 
-       d_fnstart(3, dev, "(wa %p)\n", wa);
        spin_lock_irq(&wa->xfer_list_lock);
        list_for_each_entry_safe(xfer, next, &wa->xfer_delayed_list,
                                 list_node) {
@@ -1059,7 +999,6 @@ void wa_urb_enqueue_run(struct work_struct *ws)
                spin_lock_irq(&wa->xfer_list_lock);
        }
        spin_unlock_irq(&wa->xfer_list_lock);
-       d_fnend(3, dev, "(wa %p) = void\n", wa);
 }
 EXPORT_SYMBOL_GPL(wa_urb_enqueue_run);
 
@@ -1084,9 +1023,6 @@ int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep,
        unsigned long my_flags;
        unsigned cant_sleep = irqs_disabled() | in_atomic();
 
-       d_fnstart(3, dev, "(wa %p ep %p urb %p [%d] gfp 0x%x)\n",
-                 wa, ep, urb, urb->transfer_buffer_length, gfp);
-
        if (urb->transfer_buffer == NULL
            && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
            && urb->transfer_buffer_length != 0) {
@@ -1108,11 +1044,13 @@ int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep,
        xfer->gfp = gfp;
        xfer->ep = ep;
        urb->hcpriv = xfer;
-       d_printf(2, dev, "xfer %p urb %p pipe 0x%02x [%d bytes] %s %s %s\n",
-                xfer, urb, urb->pipe, urb->transfer_buffer_length,
-                urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP ? "dma" : "nodma",
-                urb->pipe & USB_DIR_IN ? "inbound" : "outbound",
-                cant_sleep ? "deferred" : "inline");
+
+       dev_dbg(dev, "xfer %p urb %p pipe 0x%02x [%d bytes] %s %s %s\n",
+               xfer, urb, urb->pipe, urb->transfer_buffer_length,
+               urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP ? "dma" : "nodma",
+               urb->pipe & USB_DIR_IN ? "inbound" : "outbound",
+               cant_sleep ? "deferred" : "inline");
+
        if (cant_sleep) {
                usb_get_urb(urb);
                spin_lock_irqsave(&wa->xfer_list_lock, my_flags);
@@ -1122,15 +1060,11 @@ int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep,
        } else {
                wa_urb_enqueue_b(xfer);
        }
-       d_fnend(3, dev, "(wa %p ep %p urb %p [%d] gfp 0x%x) = 0\n",
-               wa, ep, urb, urb->transfer_buffer_length, gfp);
        return 0;
 
 error_dequeued:
        kfree(xfer);
 error_kmalloc:
-       d_fnend(3, dev, "(wa %p ep %p urb %p [%d] gfp 0x%x) = %d\n",
-               wa, ep, urb, urb->transfer_buffer_length, gfp, result);
        return result;
 }
 EXPORT_SYMBOL_GPL(wa_urb_enqueue);
@@ -1155,7 +1089,6 @@ EXPORT_SYMBOL_GPL(wa_urb_enqueue);
  */
 int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
 {
-       struct device *dev = &wa->usb_iface->dev;
        unsigned long flags, flags2;
        struct wa_xfer *xfer;
        struct wa_seg *seg;
@@ -1163,9 +1096,6 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
        unsigned cnt;
        unsigned rpipe_ready = 0;
 
-       d_fnstart(3, dev, "(wa %p, urb %p)\n", wa, urb);
-
-       d_printf(1, dev, "xfer %p urb %p: aborting\n", urb->hcpriv, urb);
        xfer = urb->hcpriv;
        if (xfer == NULL) {
                /* NOthing setup yet enqueue will see urb->status !=
@@ -1234,13 +1164,11 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
        wa_xfer_completion(xfer);
        if (rpipe_ready)
                wa_xfer_delayed_run(rpipe);
-       d_fnend(3, dev, "(wa %p, urb %p) = 0\n", wa, urb);
        return 0;
 
 out_unlock:
        spin_unlock_irqrestore(&xfer->lock, flags);
 out:
-       d_fnend(3, dev, "(wa %p, urb %p) = 0\n", wa, urb);
        return 0;
 
 dequeue_delayed:
@@ -1250,7 +1178,6 @@ dequeue_delayed:
        spin_unlock_irqrestore(&xfer->lock, flags);
        wa_xfer_giveback(xfer);
        usb_put_urb(urb);               /* we got a ref in enqueue() */
-       d_fnend(3, dev, "(wa %p, urb %p) = 0\n", wa, urb);
        return 0;
 }
 EXPORT_SYMBOL_GPL(wa_urb_dequeue);
@@ -1326,7 +1253,6 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer)
        u8 usb_status;
        unsigned rpipe_ready = 0;
 
-       d_fnstart(3, dev, "(wa %p xfer %p)\n", wa, xfer);
        spin_lock_irqsave(&xfer->lock, flags);
        seg_idx = xfer_result->bTransferSegment & 0x7f;
        if (unlikely(seg_idx >= xfer->segs))
@@ -1334,8 +1260,8 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer)
        seg = xfer->seg[seg_idx];
        rpipe = xfer->ep->hcpriv;
        usb_status = xfer_result->bTransferStatus;
-       d_printf(2, dev, "xfer %p#%u: bTransferStatus 0x%02x (seg %u)\n",
-                xfer, seg_idx, usb_status, seg->status);
+       dev_dbg(dev, "xfer %p#%u: bTransferStatus 0x%02x (seg %u)\n",
+               xfer, seg_idx, usb_status, seg->status);
        if (seg->status == WA_SEG_ABORTED
            || seg->status == WA_SEG_ERROR)     /* already handled */
                goto segment_aborted;
@@ -1391,10 +1317,8 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer)
                wa_xfer_completion(xfer);
        if (rpipe_ready)
                wa_xfer_delayed_run(rpipe);
-       d_fnend(3, dev, "(wa %p xfer %p) = void\n", wa, xfer);
        return;
 
-
 error_submit_buf_in:
        if (edc_inc(&wa->dti_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {
                dev_err(dev, "DTI: URB max acceptable errors "
@@ -1416,11 +1340,8 @@ error_complete:
                wa_xfer_completion(xfer);
        if (rpipe_ready)
                wa_xfer_delayed_run(rpipe);
-       d_fnend(3, dev, "(wa %p xfer %p) = void [segment/DTI-submit error]\n",
-               wa, xfer);
        return;
 
-
 error_bad_seg:
        spin_unlock_irqrestore(&xfer->lock, flags);
        wa_urb_dequeue(wa, xfer->urb);
@@ -1431,17 +1352,11 @@ error_bad_seg:
                        "exceeded, resetting device\n");
                wa_reset_all(wa);
        }
-       d_fnend(3, dev, "(wa %p xfer %p) = void [bad seg]\n", wa, xfer);
        return;
 
-
 segment_aborted:
        /* nothing to do, as the aborter did the completion */
        spin_unlock_irqrestore(&xfer->lock, flags);
-       d_fnend(3, dev, "(wa %p xfer %p) = void [segment aborted]\n",
-               wa, xfer);
-       return;
-
 }
 
 /*
@@ -1465,15 +1380,14 @@ static void wa_buf_in_cb(struct urb *urb)
        unsigned long flags;
        u8 done = 0;
 
-       d_fnstart(3, NULL, "(urb %p [%d])\n", urb, urb->status);
        switch (urb->status) {
        case 0:
                spin_lock_irqsave(&xfer->lock, flags);
                wa = xfer->wa;
                dev = &wa->usb_iface->dev;
                rpipe = xfer->ep->hcpriv;
-               d_printf(2, dev, "xfer %p#%u: data in done (%zu bytes)\n",
-                          xfer, seg->index, (size_t)urb->actual_length);
+               dev_dbg(dev, "xfer %p#%u: data in done (%zu bytes)\n",
+                       xfer, seg->index, (size_t)urb->actual_length);
                seg->status = WA_SEG_DONE;
                seg->result = urb->actual_length;
                xfer->segs_done++;
@@ -1514,7 +1428,6 @@ static void wa_buf_in_cb(struct urb *urb)
                if (rpipe_ready)
                        wa_xfer_delayed_run(rpipe);
        }
-       d_fnend(3, NULL, "(urb %p [%d]) = void\n", urb, urb->status);
 }
 
 /*
@@ -1553,14 +1466,12 @@ static void wa_xfer_result_cb(struct urb *urb)
        struct wa_xfer *xfer;
        u8 usb_status;
 
-       d_fnstart(3, dev, "(%p)\n", wa);
        BUG_ON(wa->dti_urb != urb);
        switch (wa->dti_urb->status) {
        case 0:
                /* We have a xfer result buffer; check it */
-               d_printf(2, dev, "DTI: xfer result %d bytes at %p\n",
-                          urb->actual_length, urb->transfer_buffer);
-               d_dump(3, dev, urb->transfer_buffer, urb->actual_length);
+               dev_dbg(dev, "DTI: xfer result %d bytes at %p\n",
+                       urb->actual_length, urb->transfer_buffer);
                if (wa->dti_urb->actual_length != sizeof(*xfer_result)) {
                        dev_err(dev, "DTI Error: xfer result--bad size "
                                "xfer result (%d bytes vs %zu needed)\n",
@@ -1622,7 +1533,6 @@ static void wa_xfer_result_cb(struct urb *urb)
                wa_reset_all(wa);
        }
 out:
-       d_fnend(3, dev, "(%p) = void\n", wa);
        return;
 }
 
@@ -1653,7 +1563,6 @@ void wa_handle_notif_xfer(struct wahc *wa, struct wa_notif_hdr *notif_hdr)
        struct wa_notif_xfer *notif_xfer;
        const struct usb_endpoint_descriptor *dti_epd = wa->dti_epd;
 
-       d_fnstart(4, dev, "(%p, %p)\n", wa, notif_hdr);
        notif_xfer = container_of(notif_hdr, struct wa_notif_xfer, hdr);
        BUG_ON(notif_hdr->bNotifyType != WA_NOTIF_TRANSFER);
 
@@ -1693,7 +1602,6 @@ void wa_handle_notif_xfer(struct wahc *wa, struct wa_notif_hdr *notif_hdr)
                goto error_dti_urb_submit;
        }
 out:
-       d_fnend(4, dev, "(%p, %p) = void\n", wa, notif_hdr);
        return;
 
 error_dti_urb_submit:
@@ -1704,6 +1612,4 @@ error_buf_in_urb_alloc:
 error_dti_urb_alloc:
 error:
        wa_reset_all(wa);
-       d_fnend(4, dev, "(%p, %p) = void\n", wa, notif_hdr);
-       return;
 }
index d0c1324..797c245 100644 (file)
 #include <linux/uwb.h>
 #include <linux/usb/wusb.h>
 
+/*
+ * Time from a WUSB channel stop request to the last transmitted MMC.
+ *
+ * This needs to be > 4.096 ms in case no MMCs can be transmitted in
+ * zone 0.
+ */
+#define WUSB_CHANNEL_STOP_DELAY_MS 8
 
 /**
  * Wireless USB device
@@ -147,7 +154,6 @@ struct wusb_port {
        u16 status;
        u16 change;
        struct wusb_dev *wusb_dev;      /* connected device's info */
-       unsigned reset_count;
        u32 ptk_tkid;
 };
 
@@ -198,21 +204,18 @@ struct wusb_port {
  * @mmcies_max    Max number of Information Elements this HC can send
  *                 in its MMC. Read-only.
  *
+ * @start          Start the WUSB channel.
+ *
+ * @stop           Stop the WUSB channel after the specified number of
+ *                 milliseconds.  Channel Stop IEs should be transmitted
+ *                 as required by [WUSB] 4.16.2.1.
+ *
  * @mmcie_add     HC specific operation (WHCI or HWA) for adding an
  *                 MMCIE.
  *
  * @mmcie_rm      HC specific operation (WHCI or HWA) for removing an
  *                 MMCIE.
  *
- * @enc_types     Array which describes the encryptions methods
- *                 supported by the host as described in WUSB1.0 --
- *                 one entry per supported method. As of WUSB1.0 there
- *                 is only four methods, we make space for eight just in
- *                 case they decide to add some more (and pray they do
- *                 it in sequential order). if 'enc_types[enc_method]
- *                 != 0', then it is supported by the host. enc_method
- *                 is USB_ENC_TYPE*.
- *
  * @set_ptk:       Set the PTK and enable encryption for a device. Or, if
  *                 the supplied key is NULL, disable encryption for that
  *                 device.
@@ -249,7 +252,8 @@ struct wusbhc {
        struct uwb_pal pal;
 
        unsigned trust_timeout;                 /* in jiffies */
-       struct wuie_host_info *wuie_host_info;  /* Includes CHID */
+       struct wusb_ckhdid chid;
+       struct wuie_host_info *wuie_host_info;
 
        struct mutex mutex;                     /* locks everything else */
        u16 cluster_id;                         /* Wireless USB Cluster ID */
@@ -269,7 +273,7 @@ struct wusbhc {
        u8 mmcies_max;
        /* FIXME: make wusbhc_ops? */
        int (*start)(struct wusbhc *wusbhc);
-       void (*stop)(struct wusbhc *wusbhc);
+       void (*stop)(struct wusbhc *wusbhc, int delay);
        int (*mmcie_add)(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt,
                         u8 handle, struct wuie_hdr *wuie);
        int (*mmcie_rm)(struct wusbhc *wusbhc, u8 handle);
@@ -373,20 +377,17 @@ static inline void wusbhc_put(struct wusbhc *wusbhc)
        usb_put_hcd(&wusbhc->usb_hcd);
 }
 
-int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid);
+int wusbhc_start(struct wusbhc *wusbhc);
 void wusbhc_stop(struct wusbhc *wusbhc);
 extern int wusbhc_chid_set(struct wusbhc *, const struct wusb_ckhdid *);
 
 /* Device connect handling */
 extern int wusbhc_devconnect_create(struct wusbhc *);
 extern void wusbhc_devconnect_destroy(struct wusbhc *);
-extern int wusbhc_devconnect_start(struct wusbhc *wusbhc,
-                                  const struct wusb_ckhdid *chid);
+extern int wusbhc_devconnect_start(struct wusbhc *wusbhc);
 extern void wusbhc_devconnect_stop(struct wusbhc *wusbhc);
-extern int wusbhc_devconnect_auth(struct wusbhc *, u8);
 extern void wusbhc_handle_dn(struct wusbhc *, u8 srcaddr,
                             struct wusb_dn_hdr *dn_hdr, size_t size);
-extern int wusbhc_dev_reset(struct wusbhc *wusbhc, u8 port);
 extern void __wusbhc_dev_disable(struct wusbhc *wusbhc, u8 port);
 extern int wusb_usb_ncb(struct notifier_block *nb, unsigned long val,
                        void *priv);
@@ -432,6 +433,7 @@ extern void wusb_dev_sec_rm(struct wusb_dev *) ;
 extern int wusb_dev_4way_handshake(struct wusbhc *, struct wusb_dev *,
                                   struct wusb_ckhdid *ck);
 void wusbhc_gtk_rekey(struct wusbhc *wusbhc);
+int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev);
 
 
 /* WUSB Cluster ID handling */
index 257e690..2f98d08 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_UWB_I1480U)        += i1480/
 
 uwb-objs :=            \
        address.o       \
+       allocator.o     \
        beacon.o        \
        driver.o        \
        drp.o           \
@@ -13,10 +14,12 @@ uwb-objs :=         \
        drp-ie.o        \
        est.o           \
        ie.o            \
+       ie-rcv.o        \
        lc-dev.o        \
        lc-rc.o         \
        neh.o           \
        pal.o           \
+       radio.o         \
        reset.o         \
        rsv.o           \
        scan.o          \
index 1664ae5..ad21b1d 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/device.h>
 #include <linux/random.h>
 #include <linux/etherdevice.h>
-#include <linux/uwb/debug.h>
+
 #include "uwb-internal.h"
 
 
diff --git a/drivers/uwb/allocator.c b/drivers/uwb/allocator.c
new file mode 100644 (file)
index 0000000..c8185e6
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * UWB reservation management.
+ *
+ * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/uwb.h>
+
+#include "uwb-internal.h"
+
+static void uwb_rsv_fill_column_alloc(struct uwb_rsv_alloc_info *ai)
+{
+       int col, mas, safe_mas, unsafe_mas;
+       unsigned char *bm = ai->bm;
+       struct uwb_rsv_col_info *ci = ai->ci;
+       unsigned char c;
+
+       for (col = ci->csi.start_col; col < UWB_NUM_ZONES; col += ci->csi.interval) {
+    
+               safe_mas   = ci->csi.safe_mas_per_col;
+               unsafe_mas = ci->csi.unsafe_mas_per_col;
+    
+               for (mas = 0; mas < UWB_MAS_PER_ZONE; mas++ ) {
+                       if (bm[col * UWB_MAS_PER_ZONE + mas] == 0) {
+       
+                               if (safe_mas > 0) {
+                                       safe_mas--;
+                                       c = UWB_RSV_MAS_SAFE;
+                               } else if (unsafe_mas > 0) {
+                                       unsafe_mas--;
+                                       c = UWB_RSV_MAS_UNSAFE;
+                               } else {
+                                       break;
+                               }
+                               bm[col * UWB_MAS_PER_ZONE + mas] = c;
+                       }
+               }
+       }
+}
+
+static void uwb_rsv_fill_row_alloc(struct uwb_rsv_alloc_info *ai)
+{
+       int mas, col, rows;
+       unsigned char *bm = ai->bm;
+       struct uwb_rsv_row_info *ri = &ai->ri;
+       unsigned char c;
+
+       rows = 1;
+       c = UWB_RSV_MAS_SAFE;
+       for (mas = UWB_MAS_PER_ZONE - 1; mas >= 0; mas--) {
+               if (ri->avail[mas] == 1) {
+      
+                       if (rows > ri->used_rows) {
+                               break;
+                       } else if (rows > 7) {
+                               c = UWB_RSV_MAS_UNSAFE;
+                       }
+
+                       for (col = 0; col < UWB_NUM_ZONES; col++) {
+                               if (bm[col * UWB_NUM_ZONES + mas] != UWB_RSV_MAS_NOT_AVAIL) {
+                                       bm[col * UWB_NUM_ZONES + mas] = c;
+                                       if(c == UWB_RSV_MAS_SAFE)
+                                               ai->safe_allocated_mases++;
+                                       else
+                                               ai->unsafe_allocated_mases++;
+                               }
+                       }
+                       rows++;
+               }
+       }
+       ai->total_allocated_mases = ai->safe_allocated_mases + ai->unsafe_allocated_mases;
+}
+
+/*
+ * Find the best column set for a given availability, interval, num safe mas and
+ * num unsafe mas.
+ *
+ * The different sets are tried in order as shown below, depending on the interval.
+ *
+ * interval = 16
+ *     deep = 0
+ *             set 1 ->  {  8 }
+ *     deep = 1
+ *             set 1 ->  {  4 }
+ *             set 2 ->  { 12 }
+ *     deep = 2
+ *             set 1 ->  {  2 }
+ *             set 2 ->  {  6 }
+ *             set 3 ->  { 10 }
+ *             set 4 ->  { 14 }
+ *     deep = 3
+ *             set 1 ->  {  1 }
+ *             set 2 ->  {  3 }
+ *             set 3 ->  {  5 }
+ *             set 4 ->  {  7 }
+ *             set 5 ->  {  9 }
+ *             set 6 ->  { 11 }
+ *             set 7 ->  { 13 }
+ *             set 8 ->  { 15 }
+ *
+ * interval = 8
+ *     deep = 0
+ *             set 1 ->  {  4  12 }
+ *     deep = 1
+ *             set 1 ->  {  2  10 }
+ *             set 2 ->  {  6  14 }
+ *     deep = 2
+ *             set 1 ->  {  1   9 }
+ *             set 2 ->  {  3  11 }
+ *             set 3 ->  {  5  13 }
+ *             set 4 ->  {  7  15 }
+ *
+ * interval = 4
+ *     deep = 0
+ *             set 1 ->  {  2   6  10  14 }
+ *     deep = 1
+ *             set 1 ->  {  1   5   9  13 }
+ *             set 2 ->  {  3   7  11  15 }
+ *
+ * interval = 2
+ *     deep = 0
+ *             set 1 ->  {  1   3   5   7   9  11  13  15 }
+ */
+static int uwb_rsv_find_best_column_set(struct uwb_rsv_alloc_info *ai, int interval, 
+                                       int num_safe_mas, int num_unsafe_mas)
+{
+       struct uwb_rsv_col_info *ci = ai->ci;
+       struct uwb_rsv_col_set_info *csi = &ci->csi;
+       struct uwb_rsv_col_set_info tmp_csi;
+       int deep, set, col, start_col_deep, col_start_set;
+       int start_col, max_mas_in_set, lowest_max_mas_in_deep;
+       int n_mas;
+       int found = UWB_RSV_ALLOC_NOT_FOUND; 
+
+       tmp_csi.start_col = 0;
+       start_col_deep = interval;
+       n_mas = num_unsafe_mas + num_safe_mas;
+
+       for (deep = 0; ((interval >> deep) & 0x1) == 0; deep++) {
+               start_col_deep /= 2;
+               col_start_set = 0;
+               lowest_max_mas_in_deep = UWB_MAS_PER_ZONE;
+
+               for (set = 1; set <= (1 << deep); set++) {
+                       max_mas_in_set = 0;
+                       start_col = start_col_deep + col_start_set;
+                       for (col = start_col; col < UWB_NUM_ZONES; col += interval) {
+                
+                               if (ci[col].max_avail_safe >= num_safe_mas &&
+                                   ci[col].max_avail_unsafe >= n_mas) {
+                                       if (ci[col].highest_mas[n_mas] > max_mas_in_set)
+                                               max_mas_in_set = ci[col].highest_mas[n_mas];
+                               } else {
+                                       max_mas_in_set = 0;
+                                       break;
+                               }
+                       }
+                       if ((lowest_max_mas_in_deep > max_mas_in_set) && max_mas_in_set) {
+                               lowest_max_mas_in_deep = max_mas_in_set;
+
+                               tmp_csi.start_col = start_col;
+                       }
+                       col_start_set += (interval >> deep);
+               }
+
+               if (lowest_max_mas_in_deep < 8) {
+                       csi->start_col = tmp_csi.start_col;
+                       found = UWB_RSV_ALLOC_FOUND;
+                       break;
+               } else if ((lowest_max_mas_in_deep > 8) && 
+                          (lowest_max_mas_in_deep != UWB_MAS_PER_ZONE) &&
+                          (found == UWB_RSV_ALLOC_NOT_FOUND)) {
+                       csi->start_col = tmp_csi.start_col;
+                       found = UWB_RSV_ALLOC_FOUND;
+               }
+       }
+
+       if (found == UWB_RSV_ALLOC_FOUND) {
+               csi->interval = interval;
+               csi->safe_mas_per_col = num_safe_mas;
+               csi->unsafe_mas_per_col = num_unsafe_mas;
+
+               ai->safe_allocated_mases = (UWB_NUM_ZONES / interval) * num_safe_mas;
+               ai->unsafe_allocated_mases = (UWB_NUM_ZONES / interval) * num_unsafe_mas;
+               ai->total_allocated_mases = ai->safe_allocated_mases + ai->unsafe_allocated_mases;
+               ai->interval = interval;                
+       }
+       return found;
+}
+
+static void get_row_descriptors(struct uwb_rsv_alloc_info *ai)
+{
+       unsigned char *bm = ai->bm;
+       struct uwb_rsv_row_info *ri = &ai->ri;
+       int col, mas;
+  
+       ri->free_rows = 16;
+       for (mas = 0; mas < UWB_MAS_PER_ZONE; mas ++) {
+               ri->avail[mas] = 1;
+               for (col = 1; col < UWB_NUM_ZONES; col++) {
+                       if (bm[col * UWB_NUM_ZONES + mas] == UWB_RSV_MAS_NOT_AVAIL) {
+                               ri->free_rows--;
+                               ri->avail[mas]=0;
+                               break;
+                       }
+               }
+       }
+}
+
+static void uwb_rsv_fill_column_info(unsigned char *bm, int column, struct uwb_rsv_col_info *rci)
+{
+       int mas;
+       int block_count = 0, start_block = 0; 
+       int previous_avail = 0;
+       int available = 0;
+       int safe_mas_in_row[UWB_MAS_PER_ZONE] = {
+               8, 7, 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1,
+       };
+
+       rci->max_avail_safe = 0;
+
+       for (mas = 0; mas < UWB_MAS_PER_ZONE; mas ++) {
+               if (!bm[column * UWB_NUM_ZONES + mas]) {
+                       available++;
+                       rci->max_avail_unsafe = available;
+
+                       rci->highest_mas[available] = mas;
+
+                       if (previous_avail) {
+                               block_count++;
+                               if ((block_count > safe_mas_in_row[start_block]) &&
+                                   (!rci->max_avail_safe))
+                                       rci->max_avail_safe = available - 1;
+                       } else {
+                               previous_avail = 1;
+                               start_block = mas;
+                               block_count = 1;
+                       }
+               } else {
+                       previous_avail = 0;
+               }
+       }
+       if (!rci->max_avail_safe)
+               rci->max_avail_safe = rci->max_avail_unsafe;
+}
+
+static void get_column_descriptors(struct uwb_rsv_alloc_info *ai)
+{
+       unsigned char *bm = ai->bm;
+       struct uwb_rsv_col_info *ci = ai->ci;
+       int col;
+
+       for (col = 1; col < UWB_NUM_ZONES; col++) {
+               uwb_rsv_fill_column_info(bm, col, &ci[col]);
+       }
+}
+
+static int uwb_rsv_find_best_row_alloc(struct uwb_rsv_alloc_info *ai)
+{
+       int n_rows;
+       int max_rows = ai->max_mas / UWB_USABLE_MAS_PER_ROW;
+       int min_rows = ai->min_mas / UWB_USABLE_MAS_PER_ROW;
+       if (ai->min_mas % UWB_USABLE_MAS_PER_ROW)
+               min_rows++;
+       for (n_rows = max_rows; n_rows >= min_rows; n_rows--) {
+               if (n_rows <= ai->ri.free_rows) {
+                       ai->ri.used_rows = n_rows;
+                       ai->interval = 1; /* row reservation */
+                       uwb_rsv_fill_row_alloc(ai);
+                       return UWB_RSV_ALLOC_FOUND;
+               }
+       }  
+       return UWB_RSV_ALLOC_NOT_FOUND;
+}
+
+static int uwb_rsv_find_best_col_alloc(struct uwb_rsv_alloc_info *ai, int interval)
+{
+       int n_safe, n_unsafe, n_mas;  
+       int n_column = UWB_NUM_ZONES / interval;
+       int max_per_zone = ai->max_mas / n_column;
+       int min_per_zone = ai->min_mas / n_column;
+
+       if (ai->min_mas % n_column)
+               min_per_zone++;
+
+       if (min_per_zone > UWB_MAS_PER_ZONE) {
+               return UWB_RSV_ALLOC_NOT_FOUND;
+       }
+    
+       if (max_per_zone > UWB_MAS_PER_ZONE) {
+               max_per_zone = UWB_MAS_PER_ZONE;
+       }
+    
+       for (n_mas = max_per_zone; n_mas >= min_per_zone; n_mas--) {
+               if (uwb_rsv_find_best_column_set(ai, interval, 0, n_mas) == UWB_RSV_ALLOC_NOT_FOUND)
+                       continue;
+               for (n_safe = n_mas; n_safe >= 0; n_safe--) {
+                       n_unsafe = n_mas - n_safe;
+                       if (uwb_rsv_find_best_column_set(ai, interval, n_safe, n_unsafe) == UWB_RSV_ALLOC_FOUND) {
+                               uwb_rsv_fill_column_alloc(ai);
+                               return UWB_RSV_ALLOC_FOUND;
+                       }
+               }
+       }
+       return UWB_RSV_ALLOC_NOT_FOUND;
+}
+
+int uwb_rsv_find_best_allocation(struct uwb_rsv *rsv, struct uwb_mas_bm *available, 
+                                struct uwb_mas_bm *result)
+{
+       struct uwb_rsv_alloc_info *ai;
+       int interval;
+       int bit_index;
+
+       ai = kzalloc(sizeof(struct uwb_rsv_alloc_info), GFP_KERNEL);
+       
+       ai->min_mas = rsv->min_mas;
+       ai->max_mas = rsv->max_mas;
+       ai->max_interval = rsv->max_interval;
+
+
+       /* fill the not available vector from the available bm */
+       for (bit_index = 0; bit_index < UWB_NUM_MAS; bit_index++) {
+               if (!test_bit(bit_index, available->bm))
+                       ai->bm[bit_index] = UWB_RSV_MAS_NOT_AVAIL;
+       }
+
+       if (ai->max_interval == 1) {
+               get_row_descriptors(ai);
+               if (uwb_rsv_find_best_row_alloc(ai) == UWB_RSV_ALLOC_FOUND)
+                       goto alloc_found;
+               else
+                       goto alloc_not_found;
+       }
+
+       get_column_descriptors(ai);
+        
+       for (interval = 16; interval >= 2; interval>>=1) {
+               if (interval > ai->max_interval)
+                       continue;
+               if (uwb_rsv_find_best_col_alloc(ai, interval) == UWB_RSV_ALLOC_FOUND)
+                       goto alloc_found;
+       }
+
+       /* try row reservation if no column is found */
+       get_row_descriptors(ai);
+       if (uwb_rsv_find_best_row_alloc(ai) == UWB_RSV_ALLOC_FOUND)
+               goto alloc_found;
+       else
+               goto alloc_not_found;
+
+  alloc_found:
+       bitmap_zero(result->bm, UWB_NUM_MAS);
+       bitmap_zero(result->unsafe_bm, UWB_NUM_MAS);
+       /* fill the safe and unsafe bitmaps */
+       for (bit_index = 0; bit_index < UWB_NUM_MAS; bit_index++) {
+               if (ai->bm[bit_index] == UWB_RSV_MAS_SAFE)
+                       set_bit(bit_index, result->bm);
+               else if (ai->bm[bit_index] == UWB_RSV_MAS_UNSAFE)
+                       set_bit(bit_index, result->unsafe_bm);
+       }
+       bitmap_or(result->bm, result->bm, result->unsafe_bm, UWB_NUM_MAS);
+
+       result->safe   = ai->safe_allocated_mases;
+       result->unsafe = ai->unsafe_allocated_mases;
+       
+       kfree(ai);              
+       return UWB_RSV_ALLOC_FOUND;
+  
+  alloc_not_found:
+       kfree(ai);
+       return UWB_RSV_ALLOC_NOT_FOUND;
+}
index 46b18ee..36bc315 100644 (file)
  *
  * FIXME: docs
  */
-
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/kdev_t.h>
-#include "uwb-internal.h"
 
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
+#include "uwb-internal.h"
 
-/** Start Beaconing command structure */
+/* Start Beaconing command structure */
 struct uwb_rc_cmd_start_beacon {
        struct uwb_rccb rccb;
        __le16 wBPSTOffset;
@@ -119,7 +116,6 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset)
        int result;
        struct device *dev = &rc->uwb_dev.dev;
 
-       mutex_lock(&rc->uwb_dev.mutex);
        if (channel < 0)
                channel = -1;
        if (channel == -1)
@@ -128,7 +124,7 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset)
                /* channel >= 0...dah */
                result = uwb_rc_start_beacon(rc, bpst_offset, channel);
                if (result < 0)
-                       goto out_up;
+                       return result;
                if (le16_to_cpu(rc->ies->wIELength) > 0) {
                        result = uwb_rc_set_ie(rc, rc->ies);
                        if (result < 0) {
@@ -137,19 +133,12 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset)
                                result = uwb_rc_stop_beacon(rc);
                                channel = -1;
                                bpst_offset = 0;
-                       } else
-                               result = 0;
+                       }
                }
        }
 
-       if (result < 0)
-               goto out_up;
-       rc->beaconing = channel;
-
-       uwb_notify(rc, NULL, uwb_bg_joined(rc) ? UWB_NOTIF_BG_JOIN : UWB_NOTIF_BG_LEAVE);
-
-out_up:
-       mutex_unlock(&rc->uwb_dev.mutex);
+       if (result >= 0)
+               rc->beaconing = channel;
        return result;
 }
 
@@ -168,12 +157,6 @@ out_up:
  * FIXME: use something faster for search than a list
  */
 
-struct uwb_beca uwb_beca = {
-       .list = LIST_HEAD_INIT(uwb_beca.list),
-       .mutex = __MUTEX_INITIALIZER(uwb_beca.mutex)
-};
-
-
 void uwb_bce_kfree(struct kref *_bce)
 {
        struct uwb_beca_e *bce = container_of(_bce, struct uwb_beca_e, refcnt);
@@ -185,13 +168,11 @@ void uwb_bce_kfree(struct kref *_bce)
 
 /* Find a beacon by dev addr in the cache */
 static
-struct uwb_beca_e *__uwb_beca_find_bydev(const struct uwb_dev_addr *dev_addr)
+struct uwb_beca_e *__uwb_beca_find_bydev(struct uwb_rc *rc,
+                                        const struct uwb_dev_addr *dev_addr)
 {
        struct uwb_beca_e *bce, *next;
-       list_for_each_entry_safe(bce, next, &uwb_beca.list, node) {
-               d_printf(6, NULL, "looking for addr %02x:%02x in %02x:%02x\n",
-                        dev_addr->data[0], dev_addr->data[1],
-                        bce->dev_addr.data[0], bce->dev_addr.data[1]);
+       list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) {
                if (!memcmp(&bce->dev_addr, dev_addr, sizeof(bce->dev_addr)))
                        goto out;
        }
@@ -202,10 +183,11 @@ out:
 
 /* Find a beacon by dev addr in the cache */
 static
-struct uwb_beca_e *__uwb_beca_find_bymac(const struct uwb_mac_addr *mac_addr)
+struct uwb_beca_e *__uwb_beca_find_bymac(struct uwb_rc *rc, 
+                                        const struct uwb_mac_addr *mac_addr)
 {
        struct uwb_beca_e *bce, *next;
-       list_for_each_entry_safe(bce, next, &uwb_beca.list, node) {
+       list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) {
                if (!memcmp(bce->mac_addr, mac_addr->data,
                            sizeof(struct uwb_mac_addr)))
                        goto out;
@@ -229,11 +211,11 @@ struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc,
        struct uwb_dev *found = NULL;
        struct uwb_beca_e *bce;
 
-       mutex_lock(&uwb_beca.mutex);
-       bce = __uwb_beca_find_bydev(devaddr);
+       mutex_lock(&rc->uwb_beca.mutex);
+       bce = __uwb_beca_find_bydev(rc, devaddr);
        if (bce)
                found = uwb_dev_try_get(rc, bce->uwb_dev);
-       mutex_unlock(&uwb_beca.mutex);
+       mutex_unlock(&rc->uwb_beca.mutex);
 
        return found;
 }
@@ -249,11 +231,11 @@ struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc,
        struct uwb_dev *found = NULL;
        struct uwb_beca_e *bce;
 
-       mutex_lock(&uwb_beca.mutex);
-       bce = __uwb_beca_find_bymac(macaddr);
+       mutex_lock(&rc->uwb_beca.mutex);
+       bce = __uwb_beca_find_bymac(rc, macaddr);
        if (bce)
                found = uwb_dev_try_get(rc, bce->uwb_dev);
-       mutex_unlock(&uwb_beca.mutex);
+       mutex_unlock(&rc->uwb_beca.mutex);
 
        return found;
 }
@@ -274,7 +256,9 @@ static void uwb_beca_e_init(struct uwb_beca_e *bce)
  * @bf:         Beacon frame (part of b, really)
  * @ts_jiffies: Timestamp (in jiffies) when the beacon was received
  */
-struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be,
+static
+struct uwb_beca_e *__uwb_beca_add(struct uwb_rc *rc,
+                                 struct uwb_rc_evt_beacon *be,
                                  struct uwb_beacon_frame *bf,
                                  unsigned long ts_jiffies)
 {
@@ -286,7 +270,7 @@ struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be,
        uwb_beca_e_init(bce);
        bce->ts_jiffies = ts_jiffies;
        bce->uwb_dev = NULL;
-       list_add(&bce->node, &uwb_beca.list);
+       list_add(&bce->node, &rc->uwb_beca.list);
        return bce;
 }
 
@@ -295,33 +279,32 @@ struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be,
  *
  * Remove associated devicest too.
  */
-void uwb_beca_purge(void)
+void uwb_beca_purge(struct uwb_rc *rc)
 {
        struct uwb_beca_e *bce, *next;
        unsigned long expires;
 
-       mutex_lock(&uwb_beca.mutex);
-       list_for_each_entry_safe(bce, next, &uwb_beca.list, node) {
+       mutex_lock(&rc->uwb_beca.mutex);
+       list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) {
                expires = bce->ts_jiffies + msecs_to_jiffies(beacon_timeout_ms);
                if (time_after(jiffies, expires)) {
                        uwbd_dev_offair(bce);
-                       list_del(&bce->node);
-                       uwb_bce_put(bce);
                }
        }
-       mutex_unlock(&uwb_beca.mutex);
+       mutex_unlock(&rc->uwb_beca.mutex);
 }
 
 /* Clean up the whole beacon cache. Called on shutdown */
-void uwb_beca_release(void)
+void uwb_beca_release(struct uwb_rc *rc)
 {
        struct uwb_beca_e *bce, *next;
-       mutex_lock(&uwb_beca.mutex);
-       list_for_each_entry_safe(bce, next, &uwb_beca.list, node) {
+
+       mutex_lock(&rc->uwb_beca.mutex);
+       list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) {
                list_del(&bce->node);
                uwb_bce_put(bce);
        }
-       mutex_unlock(&uwb_beca.mutex);
+       mutex_unlock(&rc->uwb_beca.mutex);
 }
 
 static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be,
@@ -349,22 +332,22 @@ ssize_t uwb_bce_print_IEs(struct uwb_dev *uwb_dev, struct uwb_beca_e *bce,
        ssize_t result = 0;
        struct uwb_rc_evt_beacon *be;
        struct uwb_beacon_frame *bf;
-       struct uwb_buf_ctx ctx = {
-               .buf = buf,
-               .bytes = 0,
-               .size = size
-       };
+       int ies_len;
+       struct uwb_ie_hdr *ies;
 
        mutex_lock(&bce->mutex);
+
        be = bce->be;
-       if (be == NULL)
-               goto out;
-       bf = (void *) be->BeaconInfo;
-       uwb_ie_for_each(uwb_dev, uwb_ie_dump_hex, &ctx,
-                       bf->IEData, be->wBeaconInfoLength - sizeof(*bf));
-       result = ctx.bytes;
-out:
+       if (be) {
+               bf = (struct uwb_beacon_frame *)bce->be->BeaconInfo;
+               ies_len = be->wBeaconInfoLength - sizeof(struct uwb_beacon_frame);
+               ies = (struct uwb_ie_hdr *)bf->IEData;
+
+               result = uwb_ie_dump_hex(ies, ies_len, buf, size);
+       }
+
        mutex_unlock(&bce->mutex);
+
        return result;
 }
 
@@ -437,18 +420,18 @@ int uwbd_evt_handle_rc_beacon(struct uwb_event *evt)
        if (uwb_mac_addr_bcast(&bf->Device_Identifier))
                return 0;
 
-       mutex_lock(&uwb_beca.mutex);
-       bce = __uwb_beca_find_bymac(&bf->Device_Identifier);
+       mutex_lock(&rc->uwb_beca.mutex);
+       bce = __uwb_beca_find_bymac(rc, &bf->Device_Identifier);
        if (bce == NULL) {
                /* Not in there, a new device is pinging */
                uwb_beacon_print(evt->rc, be, bf);
-               bce = __uwb_beca_add(be, bf, evt->ts_jiffies);
+               bce = __uwb_beca_add(rc, be, bf, evt->ts_jiffies);
                if (bce == NULL) {
-                       mutex_unlock(&uwb_beca.mutex);
+                       mutex_unlock(&rc->uwb_beca.mutex);
                        return -ENOMEM;
                }
        }
-       mutex_unlock(&uwb_beca.mutex);
+       mutex_unlock(&rc->uwb_beca.mutex);
 
        mutex_lock(&bce->mutex);
        /* purge old beacon data */
@@ -588,19 +571,6 @@ error:
        return result;
 }
 
-/**
- * uwb_bg_joined - is the RC in a beacon group?
- * @rc: the radio controller
- *
- * Returns true if the radio controller is in a beacon group (even if
- * it's the sole member).
- */
-int uwb_bg_joined(struct uwb_rc *rc)
-{
-       return rc->beaconing != -1;
-}
-EXPORT_SYMBOL_GPL(uwb_bg_joined);
-
 /*
  * Print beaconing state.
  */
@@ -619,9 +589,6 @@ static ssize_t uwb_rc_beacon_show(struct device *dev,
 
 /*
  * Start beaconing on the specified channel, or stop beaconing.
- *
- * The BPST offset of when to start searching for a beacon group to
- * join may be specified.
  */
 static ssize_t uwb_rc_beacon_store(struct device *dev,
                                   struct device_attribute *attr,
@@ -630,12 +597,11 @@ static ssize_t uwb_rc_beacon_store(struct device *dev,
        struct uwb_dev *uwb_dev = to_uwb_dev(dev);
        struct uwb_rc *rc = uwb_dev->rc;
        int channel;
-       unsigned bpst_offset = 0;
        ssize_t result = -EINVAL;
 
-       result = sscanf(buf, "%d %u\n", &channel, &bpst_offset);
+       result = sscanf(buf, "%d", &channel);
        if (result >= 1)
-               result = uwb_rc_beacon(rc, channel, bpst_offset);
+               result = uwb_radio_force_channel(rc, channel);
 
        return result < 0 ? result : size;
 }
index 521cdeb..da77e41 100644 (file)
@@ -53,7 +53,7 @@
 #include <linux/err.h>
 #include <linux/kdev_t.h>
 #include <linux/random.h>
-#include <linux/uwb/debug.h>
+
 #include "uwb-internal.h"
 
 
@@ -118,7 +118,6 @@ static int __init uwb_subsys_init(void)
        result = class_register(&uwb_rc_class);
        if (result < 0)
                goto error_uwb_rc_class_register;
-       uwbd_start();
        uwb_dbg_init();
        return 0;
 
@@ -132,7 +131,6 @@ module_init(uwb_subsys_init);
 static void __exit uwb_subsys_exit(void)
 {
        uwb_dbg_exit();
-       uwbd_stop();
        class_unregister(&uwb_rc_class);
        uwb_est_destroy();
        return;
index 3febd85..40a540a 100644 (file)
@@ -58,7 +58,7 @@ void uwb_drp_avail_init(struct uwb_rc *rc)
  *
  * avail = global & local & pending
  */
-static void uwb_drp_available(struct uwb_rc *rc, struct uwb_mas_bm *avail)
+void uwb_drp_available(struct uwb_rc *rc, struct uwb_mas_bm *avail)
 {
        bitmap_and(avail->bm, rc->drp_avail.global, rc->drp_avail.local, UWB_NUM_MAS);
        bitmap_and(avail->bm, avail->bm, rc->drp_avail.pending, UWB_NUM_MAS);
@@ -105,6 +105,7 @@ void uwb_drp_avail_release(struct uwb_rc *rc, struct uwb_mas_bm *mas)
        bitmap_or(rc->drp_avail.local, rc->drp_avail.local, mas->bm, UWB_NUM_MAS);
        bitmap_or(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS);
        rc->drp_avail.ie_valid = false;
+       uwb_rsv_handle_drp_avail_change(rc);
 }
 
 /**
@@ -280,6 +281,7 @@ int uwbd_evt_handle_rc_drp_avail(struct uwb_event *evt)
        mutex_lock(&rc->rsvs_mutex);
        bitmap_copy(rc->drp_avail.global, bmp, UWB_NUM_MAS);
        rc->drp_avail.ie_valid = false;
+       uwb_rsv_handle_drp_avail_change(rc);
        mutex_unlock(&rc->rsvs_mutex);
 
        uwb_rsv_sched_update(rc);
index 882724c..2840d7b 100644 (file)
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/random.h>
 #include <linux/uwb.h>
 
 #include "uwb-internal.h"
 
+
+/*
+ * Return the reason code for a reservations's DRP IE.
+ */
+int uwb_rsv_reason_code(struct uwb_rsv *rsv)
+{
+       static const int reason_codes[] = {
+               [UWB_RSV_STATE_O_INITIATED]          = UWB_DRP_REASON_ACCEPTED,
+               [UWB_RSV_STATE_O_PENDING]            = UWB_DRP_REASON_ACCEPTED,
+               [UWB_RSV_STATE_O_MODIFIED]           = UWB_DRP_REASON_MODIFIED,
+               [UWB_RSV_STATE_O_ESTABLISHED]        = UWB_DRP_REASON_ACCEPTED,
+               [UWB_RSV_STATE_O_TO_BE_MOVED]        = UWB_DRP_REASON_ACCEPTED,
+               [UWB_RSV_STATE_O_MOVE_COMBINING]     = UWB_DRP_REASON_MODIFIED,
+               [UWB_RSV_STATE_O_MOVE_REDUCING]      = UWB_DRP_REASON_MODIFIED,
+               [UWB_RSV_STATE_O_MOVE_EXPANDING]     = UWB_DRP_REASON_ACCEPTED,
+               [UWB_RSV_STATE_T_ACCEPTED]           = UWB_DRP_REASON_ACCEPTED,
+               [UWB_RSV_STATE_T_CONFLICT]           = UWB_DRP_REASON_CONFLICT,
+               [UWB_RSV_STATE_T_PENDING]            = UWB_DRP_REASON_PENDING,
+               [UWB_RSV_STATE_T_DENIED]             = UWB_DRP_REASON_DENIED,
+               [UWB_RSV_STATE_T_RESIZED]            = UWB_DRP_REASON_ACCEPTED,
+               [UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = UWB_DRP_REASON_ACCEPTED,
+               [UWB_RSV_STATE_T_EXPANDING_CONFLICT] = UWB_DRP_REASON_CONFLICT,
+               [UWB_RSV_STATE_T_EXPANDING_PENDING]  = UWB_DRP_REASON_PENDING,
+               [UWB_RSV_STATE_T_EXPANDING_DENIED]   = UWB_DRP_REASON_DENIED,
+       };
+
+       return reason_codes[rsv->state];
+}
+
+/*
+ * Return the reason code for a reservations's companion DRP IE .
+ */
+int uwb_rsv_companion_reason_code(struct uwb_rsv *rsv)
+{
+       static const int companion_reason_codes[] = {
+               [UWB_RSV_STATE_O_MOVE_EXPANDING]     = UWB_DRP_REASON_ACCEPTED,
+               [UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = UWB_DRP_REASON_ACCEPTED,
+               [UWB_RSV_STATE_T_EXPANDING_CONFLICT] = UWB_DRP_REASON_CONFLICT,
+               [UWB_RSV_STATE_T_EXPANDING_PENDING]  = UWB_DRP_REASON_PENDING,
+               [UWB_RSV_STATE_T_EXPANDING_DENIED]   = UWB_DRP_REASON_DENIED,
+       };
+
+       return companion_reason_codes[rsv->state];
+}
+
+/*
+ * Return the status bit for a reservations's DRP IE.
+ */
+int uwb_rsv_status(struct uwb_rsv *rsv)
+{
+       static const int statuses[] = {
+               [UWB_RSV_STATE_O_INITIATED]          = 0,
+               [UWB_RSV_STATE_O_PENDING]            = 0,
+               [UWB_RSV_STATE_O_MODIFIED]           = 1,
+               [UWB_RSV_STATE_O_ESTABLISHED]        = 1,
+               [UWB_RSV_STATE_O_TO_BE_MOVED]        = 0,
+               [UWB_RSV_STATE_O_MOVE_COMBINING]     = 1,
+               [UWB_RSV_STATE_O_MOVE_REDUCING]      = 1,
+               [UWB_RSV_STATE_O_MOVE_EXPANDING]     = 1,
+               [UWB_RSV_STATE_T_ACCEPTED]           = 1,
+               [UWB_RSV_STATE_T_CONFLICT]           = 0,
+               [UWB_RSV_STATE_T_PENDING]            = 0,
+               [UWB_RSV_STATE_T_DENIED]             = 0,
+               [UWB_RSV_STATE_T_RESIZED]            = 1,
+               [UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = 1,
+               [UWB_RSV_STATE_T_EXPANDING_CONFLICT] = 1,
+               [UWB_RSV_STATE_T_EXPANDING_PENDING]  = 1,
+               [UWB_RSV_STATE_T_EXPANDING_DENIED]   = 1,
+
+       };
+
+       return statuses[rsv->state];
+}
+
+/*
+ * Return the status bit for a reservations's companion DRP IE .
+ */
+int uwb_rsv_companion_status(struct uwb_rsv *rsv)
+{
+       static const int companion_statuses[] = {
+               [UWB_RSV_STATE_O_MOVE_EXPANDING]     = 0,
+               [UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = 1,
+               [UWB_RSV_STATE_T_EXPANDING_CONFLICT] = 0,
+               [UWB_RSV_STATE_T_EXPANDING_PENDING]  = 0,
+               [UWB_RSV_STATE_T_EXPANDING_DENIED]   = 0,
+       };
+
+       return companion_statuses[rsv->state];
+}
+
 /*
  * Allocate a DRP IE.
  *
 static struct uwb_ie_drp *uwb_drp_ie_alloc(void)
 {
        struct uwb_ie_drp *drp_ie;
-       unsigned tiebreaker;
 
        drp_ie = kzalloc(sizeof(struct uwb_ie_drp) +
                        UWB_NUM_ZONES * sizeof(struct uwb_drp_alloc),
                        GFP_KERNEL);
        if (drp_ie) {
                drp_ie->hdr.element_id = UWB_IE_DRP;
-
-               get_random_bytes(&tiebreaker, sizeof(unsigned));
-               uwb_ie_drp_set_tiebreaker(drp_ie, tiebreaker & 1);
        }
        return drp_ie;
 }
@@ -104,43 +189,17 @@ static void uwb_drp_ie_from_bm(struct uwb_ie_drp *drp_ie,
  */
 int uwb_drp_ie_update(struct uwb_rsv *rsv)
 {
-       struct device *dev = &rsv->rc->uwb_dev.dev;
        struct uwb_ie_drp *drp_ie;
-       int reason_code, status;
+       struct uwb_rsv_move *mv;
+       int unsafe;
 
-       switch (rsv->state) {
-       case UWB_RSV_STATE_NONE:
+       if (rsv->state == UWB_RSV_STATE_NONE) {
                kfree(rsv->drp_ie);
                rsv->drp_ie = NULL;
                return 0;
-       case UWB_RSV_STATE_O_INITIATED:
-               reason_code = UWB_DRP_REASON_ACCEPTED;
-               status = 0;
-               break;
-       case UWB_RSV_STATE_O_PENDING:
-               reason_code = UWB_DRP_REASON_ACCEPTED;
-               status = 0;
-               break;
-       case UWB_RSV_STATE_O_MODIFIED:
-               reason_code = UWB_DRP_REASON_MODIFIED;
-               status = 1;
-               break;
-       case UWB_RSV_STATE_O_ESTABLISHED:
-               reason_code = UWB_DRP_REASON_ACCEPTED;
-               status = 1;
-               break;
-       case UWB_RSV_STATE_T_ACCEPTED:
-               reason_code = UWB_DRP_REASON_ACCEPTED;
-               status = 1;
-               break;
-       case UWB_RSV_STATE_T_DENIED:
-               reason_code = UWB_DRP_REASON_DENIED;
-               status = 0;
-               break;
-       default:
-               dev_dbg(dev, "rsv with unhandled state (%d)\n", rsv->state);
-               return -EINVAL;
        }
+       
+       unsafe = rsv->mas.unsafe ? 1 : 0;
 
        if (rsv->drp_ie == NULL) {
                rsv->drp_ie = uwb_drp_ie_alloc();
@@ -149,9 +208,11 @@ int uwb_drp_ie_update(struct uwb_rsv *rsv)
        }
        drp_ie = rsv->drp_ie;
 
+       uwb_ie_drp_set_unsafe(drp_ie,       unsafe);
+       uwb_ie_drp_set_tiebreaker(drp_ie,   rsv->tiebreaker);
        uwb_ie_drp_set_owner(drp_ie,        uwb_rsv_is_owner(rsv));
-       uwb_ie_drp_set_status(drp_ie,       status);
-       uwb_ie_drp_set_reason_code(drp_ie,  reason_code);
+       uwb_ie_drp_set_status(drp_ie,       uwb_rsv_status(rsv));
+       uwb_ie_drp_set_reason_code(drp_ie,  uwb_rsv_reason_code(rsv));
        uwb_ie_drp_set_stream_index(drp_ie, rsv->stream);
        uwb_ie_drp_set_type(drp_ie,         rsv->type);
 
@@ -169,6 +230,27 @@ int uwb_drp_ie_update(struct uwb_rsv *rsv)
 
        uwb_drp_ie_from_bm(drp_ie, &rsv->mas);
 
+       if (uwb_rsv_has_two_drp_ies(rsv)) {
+               mv = &rsv->mv; 
+               if (mv->companion_drp_ie == NULL) {
+                       mv->companion_drp_ie = uwb_drp_ie_alloc();
+                       if (mv->companion_drp_ie == NULL)
+                               return -ENOMEM;
+               }
+               drp_ie = mv->companion_drp_ie;
+               
+               /* keep all the same configuration of the main drp_ie */
+               memcpy(drp_ie, rsv->drp_ie, sizeof(struct uwb_ie_drp));
+               
+
+               /* FIXME: handle properly the unsafe bit */
+               uwb_ie_drp_set_unsafe(drp_ie,       1);
+               uwb_ie_drp_set_status(drp_ie,       uwb_rsv_companion_status(rsv));
+               uwb_ie_drp_set_reason_code(drp_ie,  uwb_rsv_companion_reason_code(rsv));
+       
+               uwb_drp_ie_from_bm(drp_ie, &mv->companion_mas);
+       }
+
        rsv->ie_valid = true;
        return 0;
 }
@@ -219,6 +301,8 @@ void uwb_drp_ie_to_bm(struct uwb_mas_bm *bm, const struct uwb_ie_drp *drp_ie)
        u8 zone;
        u16 zone_mask;
 
+       bitmap_zero(bm->bm, UWB_NUM_MAS);
+
        for (cnt = 0; cnt < numallocs; cnt++) {
                alloc = &drp_ie->allocs[cnt];
                zone_bm = le16_to_cpu(alloc->zone_bm);
@@ -230,3 +314,4 @@ void uwb_drp_ie_to_bm(struct uwb_mas_bm *bm, const struct uwb_ie_drp *drp_ie)
                }
        }
 }
+
index c0b1e5e..2b4f940 100644 (file)
 #include <linux/delay.h>
 #include "uwb-internal.h"
 
+
+/* DRP Conflict Actions ([ECMA-368 2nd Edition] 17.4.6) */
+enum uwb_drp_conflict_action {
+       /* Reservation is mantained, no action needed */
+       UWB_DRP_CONFLICT_MANTAIN = 0,
+       
+       /* the device shall not transmit frames in conflicting MASs in
+        * the following superframe. If the device is the reservation
+        * target, it shall also set the Reason Code in its DRP IE to
+        * Conflict in its beacon in the following superframe.
+        */
+       UWB_DRP_CONFLICT_ACT1,
+       
+       /* the device shall not set the Reservation Status bit to ONE
+        * and shall not transmit frames in conflicting MASs. If the
+        * device is the reservation target, it shall also set the
+        * Reason Code in its DRP IE to Conflict.
+        */     
+       UWB_DRP_CONFLICT_ACT2,
+
+       /* the device shall not transmit frames in conflicting MASs in
+        * the following superframe. It shall remove the conflicting
+        * MASs from the reservation or set the Reservation Status to
+        * ZERO in its beacon in the following superframe. If the
+        * device is the reservation target, it shall also set the
+        * Reason Code in its DRP IE to Conflict.
+        */
+       UWB_DRP_CONFLICT_ACT3,
+};
+
+
+static void uwb_rc_set_drp_cmd_done(struct uwb_rc *rc, void *arg,
+                                   struct uwb_rceb *reply, ssize_t reply_size)
+{
+       struct uwb_rc_evt_set_drp_ie *r = (struct uwb_rc_evt_set_drp_ie *)reply;
+
+       if (r != NULL) {
+               if (r->bResultCode != UWB_RC_RES_SUCCESS)
+                       dev_err(&rc->uwb_dev.dev, "SET-DRP-IE failed: %s (%d)\n",
+                               uwb_rc_strerror(r->bResultCode), r->bResultCode);
+       } else
+               dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: timeout\n");
+
+       spin_lock(&rc->rsvs_lock);
+       if (rc->set_drp_ie_pending > 1) {
+               rc->set_drp_ie_pending = 0;
+               uwb_rsv_queue_update(rc);       
+       } else {
+               rc->set_drp_ie_pending = 0;     
+       }
+       spin_unlock(&rc->rsvs_lock);
+}
+
 /**
  * Construct and send the SET DRP IE
  *
  *
  * A DRP Availability IE is appended.
  *
- * rc->uwb_dev.mutex is held
+ * rc->rsvs_mutex is held
  *
  * FIXME We currently ignore the returned value indicating the remaining space
  * in beacon. This could be used to deny reservation requests earlier if
  * determined that they would cause the beacon space to be exceeded.
  */
-static
-int uwb_rc_gen_send_drp_ie(struct uwb_rc *rc)
+int uwb_rc_send_all_drp_ie(struct uwb_rc *rc)
 {
        int result;
-       struct device *dev = &rc->uwb_dev.dev;
        struct uwb_rc_cmd_set_drp_ie *cmd;
-       struct uwb_rc_evt_set_drp_ie reply;
        struct uwb_rsv *rsv;
+       struct uwb_rsv_move *mv;
        int num_bytes = 0;
        u8 *IEDataptr;
 
        result = -ENOMEM;
        /* First traverse all reservations to determine memory needed. */
        list_for_each_entry(rsv, &rc->reservations, rc_node) {
-               if (rsv->drp_ie != NULL)
+               if (rsv->drp_ie != NULL) {
                        num_bytes += rsv->drp_ie->hdr.length + 2;
+                       if (uwb_rsv_has_two_drp_ies(rsv) &&
+                               (rsv->mv.companion_drp_ie != NULL)) {
+                               mv = &rsv->mv;
+                               num_bytes += mv->companion_drp_ie->hdr.length + 2;      
+                       }
+               }
        }
        num_bytes += sizeof(rc->drp_avail.ie);
        cmd = kzalloc(sizeof(*cmd) + num_bytes, GFP_KERNEL);
@@ -69,128 +126,322 @@ int uwb_rc_gen_send_drp_ie(struct uwb_rc *rc)
        cmd->wIELength = num_bytes;
        IEDataptr = (u8 *)&cmd->IEData[0];
 
+       /* FIXME: DRV avail IE is not always needed */
+       /* put DRP avail IE first */
+       memcpy(IEDataptr, &rc->drp_avail.ie, sizeof(rc->drp_avail.ie));
+       IEDataptr += sizeof(struct uwb_ie_drp_avail);
+
        /* Next traverse all reservations to place IEs in allocated memory. */
        list_for_each_entry(rsv, &rc->reservations, rc_node) {
                if (rsv->drp_ie != NULL) {
                        memcpy(IEDataptr, rsv->drp_ie,
                               rsv->drp_ie->hdr.length + 2);
                        IEDataptr += rsv->drp_ie->hdr.length + 2;
+                       
+                       if (uwb_rsv_has_two_drp_ies(rsv) &&
+                               (rsv->mv.companion_drp_ie != NULL)) {
+                               mv = &rsv->mv;
+                               memcpy(IEDataptr, mv->companion_drp_ie,
+                                      mv->companion_drp_ie->hdr.length + 2);
+                               IEDataptr += mv->companion_drp_ie->hdr.length + 2;      
+                       }
                }
        }
-       memcpy(IEDataptr, &rc->drp_avail.ie, sizeof(rc->drp_avail.ie));
 
-       reply.rceb.bEventType = UWB_RC_CET_GENERAL;
-       reply.rceb.wEvent = UWB_RC_CMD_SET_DRP_IE;
-       result = uwb_rc_cmd(rc, "SET-DRP-IE", &cmd->rccb,
-                       sizeof(*cmd) + num_bytes, &reply.rceb,
-                       sizeof(reply));
-       if (result < 0)
-               goto error_cmd;
-       result = le16_to_cpu(reply.wRemainingSpace);
-       if (reply.bResultCode != UWB_RC_RES_SUCCESS) {
-               dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: command execution "
-                               "failed: %s (%d). RemainingSpace in beacon "
-                               "= %d\n", uwb_rc_strerror(reply.bResultCode),
-                               reply.bResultCode, result);
-               result = -EIO;
-       } else {
-               dev_dbg(dev, "SET-DRP-IE sent. RemainingSpace in beacon "
-                            "= %d.\n", result);
-               result = 0;
-       }
-error_cmd:
+       result = uwb_rc_cmd_async(rc, "SET-DRP-IE", &cmd->rccb, sizeof(*cmd) + num_bytes,
+                                 UWB_RC_CET_GENERAL, UWB_RC_CMD_SET_DRP_IE,
+                                 uwb_rc_set_drp_cmd_done, NULL);
+       
+       rc->set_drp_ie_pending = 1;
+
        kfree(cmd);
 error:
        return result;
-
 }
-/**
- * Send all DRP IEs associated with this host
- *
- * @returns:    >= 0 number of bytes still available in the beacon
- *              < 0 errno code on error.
+
+/*
+ * Evaluate the action to perform using conflict resolution rules
  *
- * As per the protocol we obtain the host controller device lock to access
- * bandwidth structures.
+ * Return a uwb_drp_conflict_action.
  */
-int uwb_rc_send_all_drp_ie(struct uwb_rc *rc)
+static int evaluate_conflict_action(struct uwb_ie_drp *ext_drp_ie, int ext_beacon_slot,
+                                   struct uwb_rsv *rsv, int our_status)
 {
-       int result;
+       int our_tie_breaker = rsv->tiebreaker;
+       int our_type        = rsv->type;
+       int our_beacon_slot = rsv->rc->uwb_dev.beacon_slot;
+
+       int ext_tie_breaker = uwb_ie_drp_tiebreaker(ext_drp_ie);
+       int ext_status      = uwb_ie_drp_status(ext_drp_ie);
+       int ext_type        = uwb_ie_drp_type(ext_drp_ie);
+       
+       
+       /* [ECMA-368 2nd Edition] 17.4.6 */
+       if (ext_type == UWB_DRP_TYPE_PCA && our_type == UWB_DRP_TYPE_PCA) {
+               return UWB_DRP_CONFLICT_MANTAIN;
+       }
 
-       mutex_lock(&rc->uwb_dev.mutex);
-       result = uwb_rc_gen_send_drp_ie(rc);
-       mutex_unlock(&rc->uwb_dev.mutex);
-       return result;
+       /* [ECMA-368 2nd Edition] 17.4.6-1 */
+       if (our_type == UWB_DRP_TYPE_ALIEN_BP) {
+               return UWB_DRP_CONFLICT_MANTAIN;
+       }
+       
+       /* [ECMA-368 2nd Edition] 17.4.6-2 */
+       if (ext_type == UWB_DRP_TYPE_ALIEN_BP) {
+               /* here we know our_type != UWB_DRP_TYPE_ALIEN_BP */
+               return UWB_DRP_CONFLICT_ACT1;
+       }
+
+       /* [ECMA-368 2nd Edition] 17.4.6-3 */
+       if (our_status == 0 && ext_status == 1) {
+               return UWB_DRP_CONFLICT_ACT2;
+       }
+
+       /* [ECMA-368 2nd Edition] 17.4.6-4 */
+       if (our_status == 1 && ext_status == 0) {
+               return UWB_DRP_CONFLICT_MANTAIN;
+       }
+
+       /* [ECMA-368 2nd Edition] 17.4.6-5a */
+       if (our_tie_breaker == ext_tie_breaker &&
+           our_beacon_slot <  ext_beacon_slot) {
+               return UWB_DRP_CONFLICT_MANTAIN;
+       }
+
+       /* [ECMA-368 2nd Edition] 17.4.6-5b */
+       if (our_tie_breaker != ext_tie_breaker &&
+           our_beacon_slot >  ext_beacon_slot) {
+               return UWB_DRP_CONFLICT_MANTAIN;
+       }
+       
+       if (our_status == 0) {
+               if (our_tie_breaker == ext_tie_breaker) {
+                       /* [ECMA-368 2nd Edition] 17.4.6-6a */
+                       if (our_beacon_slot > ext_beacon_slot) {
+                               return UWB_DRP_CONFLICT_ACT2;
+                       }
+               } else  {
+                       /* [ECMA-368 2nd Edition] 17.4.6-6b */
+                       if (our_beacon_slot < ext_beacon_slot) {
+                               return UWB_DRP_CONFLICT_ACT2;
+                       }
+               }
+       } else {
+               if (our_tie_breaker == ext_tie_breaker) {
+                       /* [ECMA-368 2nd Edition] 17.4.6-7a */
+                       if (our_beacon_slot > ext_beacon_slot) {
+                               return UWB_DRP_CONFLICT_ACT3;
+                       }
+               } else {
+                       /* [ECMA-368 2nd Edition] 17.4.6-7b */
+                       if (our_beacon_slot < ext_beacon_slot) {
+                               return UWB_DRP_CONFLICT_ACT3;
+                       }
+               }
+       }
+       return UWB_DRP_CONFLICT_MANTAIN;
 }
 
-void uwb_drp_handle_timeout(struct uwb_rsv *rsv)
+static void handle_conflict_normal(struct uwb_ie_drp *drp_ie, 
+                                  int ext_beacon_slot, 
+                                  struct uwb_rsv *rsv, 
+                                  struct uwb_mas_bm *conflicting_mas)
 {
-       struct device *dev = &rsv->rc->uwb_dev.dev;
+       struct uwb_rc *rc = rsv->rc;
+       struct uwb_rsv_move *mv = &rsv->mv;
+       struct uwb_drp_backoff_win *bow = &rc->bow;
+       int action;
+
+       action = evaluate_conflict_action(drp_ie, ext_beacon_slot, rsv, uwb_rsv_status(rsv));
+
+       if (uwb_rsv_is_owner(rsv)) {
+               switch(action) {
+               case UWB_DRP_CONFLICT_ACT2:
+                       /* try move */
+                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_TO_BE_MOVED);
+                       if (bow->can_reserve_extra_mases == false)
+                               uwb_rsv_backoff_win_increment(rc);
+                       
+                       break;
+               case UWB_DRP_CONFLICT_ACT3:
+                       uwb_rsv_backoff_win_increment(rc);
+                       /* drop some mases with reason modified */
+                       /* put in the companion the mases to be dropped */
+                       bitmap_and(mv->companion_mas.bm, rsv->mas.bm, conflicting_mas->bm, UWB_NUM_MAS);
+                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MODIFIED);
+               default:
+                       break;
+               }
+       } else {
+               switch(action) {
+               case UWB_DRP_CONFLICT_ACT2:
+               case UWB_DRP_CONFLICT_ACT3:
+                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_CONFLICT);       
+               default:
+                       break;
+               }
 
-       dev_dbg(dev, "reservation timeout in state %s (%d)\n",
-               uwb_rsv_state_str(rsv->state), rsv->state);
+       }
+       
+}
 
-       switch (rsv->state) {
-       case UWB_RSV_STATE_O_INITIATED:
-               if (rsv->is_multicast) {
-                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED);
-                       return;
+static void handle_conflict_expanding(struct uwb_ie_drp *drp_ie, int ext_beacon_slot,
+                                     struct uwb_rsv *rsv, bool companion_only,
+                                     struct uwb_mas_bm *conflicting_mas)
+{
+       struct uwb_rc *rc = rsv->rc;
+       struct uwb_drp_backoff_win *bow = &rc->bow;
+       struct uwb_rsv_move *mv = &rsv->mv;
+       int action;
+       
+       if (companion_only) {
+               /* status of companion is 0 at this point */
+               action = evaluate_conflict_action(drp_ie, ext_beacon_slot, rsv, 0);
+               if (uwb_rsv_is_owner(rsv)) {
+                       switch(action) {
+                       case UWB_DRP_CONFLICT_ACT2:
+                       case UWB_DRP_CONFLICT_ACT3:
+                               uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED);
+                               rsv->needs_release_companion_mas = false;
+                               if (bow->can_reserve_extra_mases == false)
+                                       uwb_rsv_backoff_win_increment(rc);
+                               uwb_drp_avail_release(rsv->rc, &rsv->mv.companion_mas);
+                       }
+               } else { /* rsv is target */                    
+                       switch(action) {
+                       case UWB_DRP_CONFLICT_ACT2:
+                       case UWB_DRP_CONFLICT_ACT3:
+                               uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_EXPANDING_CONFLICT);
+                                /* send_drp_avail_ie = true; */
+                       }
                }
-               break;
-       case UWB_RSV_STATE_O_ESTABLISHED:
-               if (rsv->is_multicast)
-                       return;
-               break;
-       default:
-               break;
+       } else { /* also base part of the reservation is conflicting */         
+               if (uwb_rsv_is_owner(rsv)) {
+                       uwb_rsv_backoff_win_increment(rc);
+                       /* remove companion part */
+                       uwb_drp_avail_release(rsv->rc, &rsv->mv.companion_mas);
+
+                       /* drop some mases with reason modified */
+
+                       /* put in the companion the mases to be dropped */
+                       bitmap_andnot(mv->companion_mas.bm, rsv->mas.bm, conflicting_mas->bm, UWB_NUM_MAS);
+                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MODIFIED);
+               } else { /* it is a target rsv */
+                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_CONFLICT);
+                        /* send_drp_avail_ie = true; */
+               }
+       }
+}
+
+static void uwb_drp_handle_conflict_rsv(struct uwb_rc *rc, struct uwb_rsv *rsv,
+                                       struct uwb_rc_evt_drp *drp_evt, 
+                                       struct uwb_ie_drp *drp_ie,
+                                       struct uwb_mas_bm *conflicting_mas)
+{
+       struct uwb_rsv_move *mv;
+
+       /* check if the conflicting reservation has two drp_ies */
+       if (uwb_rsv_has_two_drp_ies(rsv)) {
+               mv = &rsv->mv;
+               if (bitmap_intersects(rsv->mas.bm, conflicting_mas->bm, UWB_NUM_MAS)) {
+                       handle_conflict_expanding(drp_ie, drp_evt->beacon_slot_number,
+                                                 rsv, false, conflicting_mas);
+               } else {
+                       if (bitmap_intersects(mv->companion_mas.bm, conflicting_mas->bm, UWB_NUM_MAS)) {
+                               handle_conflict_expanding(drp_ie, drp_evt->beacon_slot_number,
+                                                         rsv, true, conflicting_mas);  
+                       }
+               }
+       } else if (bitmap_intersects(rsv->mas.bm, conflicting_mas->bm, UWB_NUM_MAS)) {
+               handle_conflict_normal(drp_ie, drp_evt->beacon_slot_number, rsv, conflicting_mas);
        }
-       uwb_rsv_remove(rsv);
 }
 
+static void uwb_drp_handle_all_conflict_rsv(struct uwb_rc *rc,
+                                           struct uwb_rc_evt_drp *drp_evt, 
+                                           struct uwb_ie_drp *drp_ie,
+                                           struct uwb_mas_bm *conflicting_mas)
+{
+       struct uwb_rsv *rsv;
+       
+       list_for_each_entry(rsv, &rc->reservations, rc_node) {
+               uwb_drp_handle_conflict_rsv(rc, rsv, drp_evt, drp_ie, conflicting_mas); 
+       }
+}
+       
 /*
  * Based on the DRP IE, transition a target reservation to a new
  * state.
  */
 static void uwb_drp_process_target(struct uwb_rc *rc, struct uwb_rsv *rsv,
-                                  struct uwb_ie_drp *drp_ie)
+                                  struct uwb_ie_drp *drp_ie, struct uwb_rc_evt_drp *drp_evt)
 {
        struct device *dev = &rc->uwb_dev.dev;
+       struct uwb_rsv_move *mv = &rsv->mv;
        int status;
        enum uwb_drp_reason reason_code;
-
+       struct uwb_mas_bm mas;
+       
        status = uwb_ie_drp_status(drp_ie);
        reason_code = uwb_ie_drp_reason_code(drp_ie);
+       uwb_drp_ie_to_bm(&mas, drp_ie);
 
-       if (status) {
-               switch (reason_code) {
-               case UWB_DRP_REASON_ACCEPTED:
-                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_ACCEPTED);
-                       break;
-               case UWB_DRP_REASON_MODIFIED:
-                       dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n",
-                               reason_code, status);
+       switch (reason_code) {
+       case UWB_DRP_REASON_ACCEPTED:
+
+               if (rsv->state == UWB_RSV_STATE_T_CONFLICT) {
+                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_CONFLICT);
                        break;
-               default:
-                       dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n",
-                                reason_code, status);
                }
-       } else {
-               switch (reason_code) {
-               case UWB_DRP_REASON_ACCEPTED:
-                       /* New reservations are handled in uwb_rsv_find(). */
-                       break;
-               case UWB_DRP_REASON_DENIED:
-                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE);
-                       break;
-               case UWB_DRP_REASON_CONFLICT:
-               case UWB_DRP_REASON_MODIFIED:
-                       dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n",
-                               reason_code, status);
+
+               if (rsv->state == UWB_RSV_STATE_T_EXPANDING_ACCEPTED) {
+                       /* drp_ie is companion */
+                       if (!bitmap_equal(rsv->mas.bm, mas.bm, UWB_NUM_MAS))
+                               /* stroke companion */
+                               uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_EXPANDING_ACCEPTED);     
+               } else {
+                       if (!bitmap_equal(rsv->mas.bm, mas.bm, UWB_NUM_MAS)) {
+                               if (uwb_drp_avail_reserve_pending(rc, &mas) == -EBUSY) {
+                                       /* FIXME: there is a conflict, find
+                                        * the conflicting reservations and
+                                        * take a sensible action. Consider
+                                        * that in drp_ie there is the
+                                        * "neighbour" */
+                                       uwb_drp_handle_all_conflict_rsv(rc, drp_evt, drp_ie, &mas);
+                               } else {
+                                       /* accept the extra reservation */
+                                       bitmap_copy(mv->companion_mas.bm, mas.bm, UWB_NUM_MAS);
+                                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_EXPANDING_ACCEPTED);
+                               }
+                       } else {
+                               if (status) {
+                                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_ACCEPTED);
+                               }
+                       }
+                       
+               }
+               break;
+
+       case UWB_DRP_REASON_MODIFIED:
+               /* check to see if we have already modified the reservation */
+               if (bitmap_equal(rsv->mas.bm, mas.bm, UWB_NUM_MAS)) {
+                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_ACCEPTED);
                        break;
-               default:
-                       dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n",
-                                reason_code, status);
                }
+
+               /* find if the owner wants to expand or reduce */
+               if (bitmap_subset(mas.bm, rsv->mas.bm, UWB_NUM_MAS)) {
+                       /* owner is reducing */
+                       bitmap_andnot(mv->companion_mas.bm, rsv->mas.bm, mas.bm, UWB_NUM_MAS);
+                       uwb_drp_avail_release(rsv->rc, &mv->companion_mas);
+               }
+
+               bitmap_copy(rsv->mas.bm, mas.bm, UWB_NUM_MAS);
+               uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_RESIZED);
+               break;
+       default:
+               dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n",
+                        reason_code, status);
        }
 }
 
@@ -199,23 +450,60 @@ static void uwb_drp_process_target(struct uwb_rc *rc, struct uwb_rsv *rsv,
  * state.
  */
 static void uwb_drp_process_owner(struct uwb_rc *rc, struct uwb_rsv *rsv,
-                                 struct uwb_ie_drp *drp_ie)
+                                 struct uwb_dev *src, struct uwb_ie_drp *drp_ie,
+                                 struct uwb_rc_evt_drp *drp_evt)
 {
        struct device *dev = &rc->uwb_dev.dev;
+       struct uwb_rsv_move *mv = &rsv->mv;
        int status;
        enum uwb_drp_reason reason_code;
+       struct uwb_mas_bm mas;
 
        status = uwb_ie_drp_status(drp_ie);
        reason_code = uwb_ie_drp_reason_code(drp_ie);
+       uwb_drp_ie_to_bm(&mas, drp_ie);
 
        if (status) {
                switch (reason_code) {
                case UWB_DRP_REASON_ACCEPTED:
-                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED);
-                       break;
-               case UWB_DRP_REASON_MODIFIED:
-                       dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n",
-                               reason_code, status);
+                       switch (rsv->state) {
+                       case UWB_RSV_STATE_O_PENDING:
+                       case UWB_RSV_STATE_O_INITIATED:
+                       case UWB_RSV_STATE_O_ESTABLISHED:
+                               uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED);
+                               break;
+                       case UWB_RSV_STATE_O_MODIFIED:
+                               if (bitmap_equal(mas.bm, rsv->mas.bm, UWB_NUM_MAS)) {
+                                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED);
+                               } else {
+                                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MODIFIED);       
+                               }
+                               break;
+                               
+                       case UWB_RSV_STATE_O_MOVE_REDUCING: /* shouldn' t be a problem */
+                               if (bitmap_equal(mas.bm, rsv->mas.bm, UWB_NUM_MAS)) {
+                                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED);
+                               } else {
+                                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_REDUCING);  
+                               }
+                               break;
+                       case UWB_RSV_STATE_O_MOVE_EXPANDING:
+                               if (bitmap_equal(mas.bm, mv->companion_mas.bm, UWB_NUM_MAS)) {
+                                       /* Companion reservation accepted */
+                                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_COMBINING);
+                               } else {
+                                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_EXPANDING);
+                               }
+                               break;
+                       case UWB_RSV_STATE_O_MOVE_COMBINING:
+                               if (bitmap_equal(mas.bm, rsv->mas.bm, UWB_NUM_MAS))
+                                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_REDUCING);
+                               else
+                                       uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_COMBINING);
+                               break;
+                       default:
+                               break;  
+                       }
                        break;
                default:
                        dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n",
@@ -230,9 +518,10 @@ static void uwb_drp_process_owner(struct uwb_rc *rc, struct uwb_rsv *rsv,
                        uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE);
                        break;
                case UWB_DRP_REASON_CONFLICT:
-               case UWB_DRP_REASON_MODIFIED:
-                       dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n",
-                               reason_code, status);
+                       /* resolve the conflict */
+                       bitmap_complement(mas.bm, src->last_availability_bm,
+                                         UWB_NUM_MAS);
+                       uwb_drp_handle_conflict_rsv(rc, rsv, drp_evt, drp_ie, &mas);
                        break;
                default:
                        dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n",
@@ -241,12 +530,110 @@ static void uwb_drp_process_owner(struct uwb_rc *rc, struct uwb_rsv *rsv,
        }
 }
 
+static void uwb_cnflt_alien_stroke_timer(struct uwb_cnflt_alien *cnflt)
+{
+       unsigned timeout_us = UWB_MAX_LOST_BEACONS * UWB_SUPERFRAME_LENGTH_US;
+       mod_timer(&cnflt->timer, jiffies + usecs_to_jiffies(timeout_us));
+}
+
+static void uwb_cnflt_update_work(struct work_struct *work)
+{
+       struct uwb_cnflt_alien *cnflt = container_of(work,
+                                                    struct uwb_cnflt_alien,
+                                                    cnflt_update_work);
+       struct uwb_cnflt_alien *c;
+       struct uwb_rc *rc = cnflt->rc;
+       
+       unsigned long delay_us = UWB_MAS_LENGTH_US * UWB_MAS_PER_ZONE;
+       
+       mutex_lock(&rc->rsvs_mutex);
+
+       list_del(&cnflt->rc_node);
+
+       /* update rc global conflicting alien bitmap */
+       bitmap_zero(rc->cnflt_alien_bitmap.bm, UWB_NUM_MAS);
+
+       list_for_each_entry(c, &rc->cnflt_alien_list, rc_node) {
+               bitmap_or(rc->cnflt_alien_bitmap.bm, rc->cnflt_alien_bitmap.bm, c->mas.bm, UWB_NUM_MAS);                        
+       }
+       
+       queue_delayed_work(rc->rsv_workq, &rc->rsv_alien_bp_work, usecs_to_jiffies(delay_us));
+
+       kfree(cnflt);
+       mutex_unlock(&rc->rsvs_mutex);
+}
+
+static void uwb_cnflt_timer(unsigned long arg)
+{
+       struct uwb_cnflt_alien *cnflt = (struct uwb_cnflt_alien *)arg;
+
+       queue_work(cnflt->rc->rsv_workq, &cnflt->cnflt_update_work);
+}
+
 /*
- * Process a received DRP IE, it's either for a reservation owned by
- * the RC or targeted at it (or it's for a WUSB cluster reservation).
+ * We have received an DRP_IE of type Alien BP and we need to make
+ * sure we do not transmit in conflicting MASs.
  */
-static void uwb_drp_process(struct uwb_rc *rc, struct uwb_dev *src,
-                    struct uwb_ie_drp *drp_ie)
+static void uwb_drp_handle_alien_drp(struct uwb_rc *rc, struct uwb_ie_drp *drp_ie)
+{
+       struct device *dev = &rc->uwb_dev.dev;
+       struct uwb_mas_bm mas;
+       struct uwb_cnflt_alien *cnflt;
+       char buf[72];
+       unsigned long delay_us = UWB_MAS_LENGTH_US * UWB_MAS_PER_ZONE;
+       
+       uwb_drp_ie_to_bm(&mas, drp_ie);
+       bitmap_scnprintf(buf, sizeof(buf), mas.bm, UWB_NUM_MAS);
+       
+       list_for_each_entry(cnflt, &rc->cnflt_alien_list, rc_node) {
+               if (bitmap_equal(cnflt->mas.bm, mas.bm, UWB_NUM_MAS)) {
+                       /* Existing alien BP reservation conflicting
+                        * bitmap, just reset the timer */
+                       uwb_cnflt_alien_stroke_timer(cnflt);
+                       return;
+               }
+       }
+
+       /* New alien BP reservation conflicting bitmap */
+
+       /* alloc and initialize new uwb_cnflt_alien */
+       cnflt = kzalloc(sizeof(struct uwb_cnflt_alien), GFP_KERNEL);
+       if (!cnflt)
+               dev_err(dev, "failed to alloc uwb_cnflt_alien struct\n");
+       INIT_LIST_HEAD(&cnflt->rc_node);
+       init_timer(&cnflt->timer);
+       cnflt->timer.function = uwb_cnflt_timer;
+       cnflt->timer.data     = (unsigned long)cnflt;
+
+       cnflt->rc = rc;
+       INIT_WORK(&cnflt->cnflt_update_work, uwb_cnflt_update_work);
+       
+       bitmap_copy(cnflt->mas.bm, mas.bm, UWB_NUM_MAS);
+
+       list_add_tail(&cnflt->rc_node, &rc->cnflt_alien_list);
+
+       /* update rc global conflicting alien bitmap */
+       bitmap_or(rc->cnflt_alien_bitmap.bm, rc->cnflt_alien_bitmap.bm, mas.bm, UWB_NUM_MAS);
+
+       queue_delayed_work(rc->rsv_workq, &rc->rsv_alien_bp_work, usecs_to_jiffies(delay_us));
+       
+       /* start the timer */
+       uwb_cnflt_alien_stroke_timer(cnflt);
+}
+
+static void uwb_drp_process_not_involved(struct uwb_rc *rc,
+                                        struct uwb_rc_evt_drp *drp_evt, 
+                                        struct uwb_ie_drp *drp_ie)
+{
+       struct uwb_mas_bm mas;
+       
+       uwb_drp_ie_to_bm(&mas, drp_ie);
+       uwb_drp_handle_all_conflict_rsv(rc, drp_evt, drp_ie, &mas);
+}
+
+static void uwb_drp_process_involved(struct uwb_rc *rc, struct uwb_dev *src,
+                                    struct uwb_rc_evt_drp *drp_evt,
+                                    struct uwb_ie_drp *drp_ie)
 {
        struct uwb_rsv *rsv;
 
@@ -259,7 +646,7 @@ static void uwb_drp_process(struct uwb_rc *rc, struct uwb_dev *src,
                 */
                return;
        }
-
+       
        /*
         * Do nothing with DRP IEs for reservations that have been
         * terminated.
@@ -268,13 +655,43 @@ static void uwb_drp_process(struct uwb_rc *rc, struct uwb_dev *src,
                uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE);
                return;
        }
-
+                       
        if (uwb_ie_drp_owner(drp_ie))
-               uwb_drp_process_target(rc, rsv, drp_ie);
+               uwb_drp_process_target(rc, rsv, drp_ie, drp_evt);
+       else
+               uwb_drp_process_owner(rc, rsv, src, drp_ie, drp_evt);
+       
+}
+
+
+static bool uwb_drp_involves_us(struct uwb_rc *rc, struct uwb_ie_drp *drp_ie)
+{
+       return uwb_dev_addr_cmp(&rc->uwb_dev.dev_addr, &drp_ie->dev_addr) == 0;
+}
+
+/*
+ * Process a received DRP IE.
+ */
+static void uwb_drp_process(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt,
+                           struct uwb_dev *src, struct uwb_ie_drp *drp_ie)
+{
+       if (uwb_ie_drp_type(drp_ie) == UWB_DRP_TYPE_ALIEN_BP)
+               uwb_drp_handle_alien_drp(rc, drp_ie);
+       else if (uwb_drp_involves_us(rc, drp_ie))
+               uwb_drp_process_involved(rc, src, drp_evt, drp_ie);
        else
-               uwb_drp_process_owner(rc, rsv, drp_ie);
+               uwb_drp_process_not_involved(rc, drp_evt, drp_ie);
 }
 
+/*
+ * Process a received DRP Availability IE
+ */
+static void uwb_drp_availability_process(struct uwb_rc *rc, struct uwb_dev *src,
+                                        struct uwb_ie_drp_avail *drp_availability_ie)
+{
+       bitmap_copy(src->last_availability_bm,
+                   drp_availability_ie->bmp, UWB_NUM_MAS);
+}
 
 /*
  * Process all the DRP IEs (both DRP IEs and the DRP Availability IE)
@@ -296,10 +713,10 @@ void uwb_drp_process_all(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt,
 
                switch (ie_hdr->element_id) {
                case UWB_IE_DRP_AVAILABILITY:
-                       /* FIXME: does something need to be done with this? */
+                       uwb_drp_availability_process(rc, src_dev, (struct uwb_ie_drp_avail *)ie_hdr);
                        break;
                case UWB_IE_DRP:
-                       uwb_drp_process(rc, src_dev, (struct uwb_ie_drp *)ie_hdr);
+                       uwb_drp_process(rc, drp_evt, src_dev, (struct uwb_ie_drp *)ie_hdr);
                        break;
                default:
                        dev_warn(dev, "unexpected IE in DRP notification\n");
@@ -312,55 +729,6 @@ void uwb_drp_process_all(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt,
                         (int)ielen);
 }
 
-
-/*
- * Go through all the DRP IEs and find the ones that conflict with our
- * reservations.
- *
- * FIXME: must resolve the conflict according the the rules in
- * [ECMA-368].
- */
-static
-void uwb_drp_process_conflict_all(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt,
-                                 size_t ielen, struct uwb_dev *src_dev)
-{
-       struct device *dev = &rc->uwb_dev.dev;
-       struct uwb_ie_hdr *ie_hdr;
-       struct uwb_ie_drp *drp_ie;
-       void *ptr;
-
-       ptr = drp_evt->ie_data;
-       for (;;) {
-               ie_hdr = uwb_ie_next(&ptr, &ielen);
-               if (!ie_hdr)
-                       break;
-
-               drp_ie = container_of(ie_hdr, struct uwb_ie_drp, hdr);
-
-               /* FIXME: check if this DRP IE conflicts. */
-       }
-
-       if (ielen > 0)
-               dev_warn(dev, "%d octets remaining in DRP notification\n",
-                        (int)ielen);
-}
-
-
-/*
- * Terminate all reservations owned by, or targeted at, 'uwb_dev'.
- */
-static void uwb_drp_terminate_all(struct uwb_rc *rc, struct uwb_dev *uwb_dev)
-{
-       struct uwb_rsv *rsv;
-
-       list_for_each_entry(rsv, &rc->reservations, rc_node) {
-               if (rsv->owner == uwb_dev
-                   || (rsv->target.type == UWB_RSV_TARGET_DEV && rsv->target.dev == uwb_dev))
-                       uwb_rsv_remove(rsv);
-       }
-}
-
-
 /**
  * uwbd_evt_handle_rc_drp - handle a DRP_IE event
  * @evt: the DRP_IE event from the radio controller
@@ -401,7 +769,6 @@ int uwbd_evt_handle_rc_drp(struct uwb_event *evt)
        size_t ielength, bytes_left;
        struct uwb_dev_addr src_addr;
        struct uwb_dev *src_dev;
-       int reason;
 
        /* Is there enough data to decode the event (and any IEs in
           its payload)? */
@@ -437,22 +804,8 @@ int uwbd_evt_handle_rc_drp(struct uwb_event *evt)
 
        mutex_lock(&rc->rsvs_mutex);
 
-       reason = uwb_rc_evt_drp_reason(drp_evt);
-
-       switch (reason) {
-       case UWB_DRP_NOTIF_DRP_IE_RCVD:
-               uwb_drp_process_all(rc, drp_evt, ielength, src_dev);
-               break;
-       case UWB_DRP_NOTIF_CONFLICT:
-               uwb_drp_process_conflict_all(rc, drp_evt, ielength, src_dev);
-               break;
-       case UWB_DRP_NOTIF_TERMINATE:
-               uwb_drp_terminate_all(rc, src_dev);
-               break;
-       default:
-               dev_warn(dev, "ignored DRP event with reason code: %d\n", reason);
-               break;
-       }
+       /* We do not distinguish from the reason */
+       uwb_drp_process_all(rc, drp_evt, ielength, src_dev);
 
        mutex_unlock(&rc->rsvs_mutex);
 
index 5fe566b..328fcc2 100644 (file)
  *   uwb_est_get_size()
  */
 #include <linux/spinlock.h>
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
-#include "uwb-internal.h"
 
+#include "uwb-internal.h"
 
 struct uwb_est {
        u16 type_event_high;
@@ -52,7 +50,6 @@ struct uwb_est {
        const struct uwb_est_entry *entry;
 };
 
-
 static struct uwb_est *uwb_est;
 static u8 uwb_est_size;
 static u8 uwb_est_used;
@@ -440,21 +437,12 @@ ssize_t uwb_est_find_size(struct uwb_rc *rc, const struct uwb_rceb *rceb,
        u8 *ptr = (u8 *) rceb;
 
        read_lock_irqsave(&uwb_est_lock, flags);
-       d_printf(2, dev, "Size query for event 0x%02x/%04x/%02x,"
-                " buffer size %ld\n",
-                (unsigned) rceb->bEventType,
-                (unsigned) le16_to_cpu(rceb->wEvent),
-                (unsigned) rceb->bEventContext,
-                (long) rceb_size);
        size = -ENOSPC;
        if (rceb_size < sizeof(*rceb))
                goto out;
        event = le16_to_cpu(rceb->wEvent);
        type_event_high = rceb->bEventType << 8 | (event & 0xff00) >> 8;
        for (itr = 0; itr < uwb_est_used; itr++) {
-               d_printf(3, dev, "Checking EST 0x%04x/%04x/%04x\n",
-                       uwb_est[itr].type_event_high, uwb_est[itr].vendor,
-                       uwb_est[itr].product);
                if (uwb_est[itr].type_event_high != type_event_high)
                        continue;
                size = uwb_est_get_size(rc, &uwb_est[itr],
index 3d26fa0..559f878 100644 (file)
  *
  *
  */
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/usb/wusb.h>
 #include <linux/usb/wusb-wa.h>
 #include <linux/uwb.h>
+
 #include "uwb-internal.h"
-#define D_LOCAL 1
-#include <linux/uwb/debug.h>
 
 /* The device uses commands and events from the WHCI specification, although
  * reporting itself as WUSB compliant. */
@@ -631,17 +629,13 @@ void hwarc_neep_cb(struct urb *urb)
 
        switch (result = urb->status) {
        case 0:
-               d_printf(3, dev, "NEEP: receive stat %d, %zu bytes\n",
-                        urb->status, (size_t)urb->actual_length);
                uwb_rc_neh_grok(hwarc->uwb_rc, urb->transfer_buffer,
                                urb->actual_length);
                break;
        case -ECONNRESET:       /* Not an error, but a controlled situation; */
        case -ENOENT:           /* (we killed the URB)...so, no broadcast */
-               d_printf(2, dev, "NEEP: URB reset/noent %d\n", urb->status);
                goto out;
        case -ESHUTDOWN:        /* going away! */
-               d_printf(2, dev, "NEEP: URB down %d\n", urb->status);
                goto out;
        default:                /* On general errors, retry unless it gets ugly */
                if (edc_inc(&hwarc->neep_edc, EDC_MAX_ERRORS,
@@ -650,7 +644,6 @@ void hwarc_neep_cb(struct urb *urb)
                dev_err(dev, "NEEP: URB error %d\n", urb->status);
        }
        result = usb_submit_urb(urb, GFP_ATOMIC);
-       d_printf(3, dev, "NEEP: submit %d\n", result);
        if (result < 0) {
                dev_err(dev, "NEEP: Can't resubmit URB (%d) resetting device\n",
                        result);
@@ -759,11 +752,11 @@ static int hwarc_get_version(struct uwb_rc *rc)
        itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength);
        while (itr_size >= sizeof(*hdr)) {
                hdr = (struct usb_descriptor_header *) itr;
-               d_printf(3, dev, "Extra device descriptor: "
-                        "type %02x/%u bytes @ %zu (%zu left)\n",
-                        hdr->bDescriptorType, hdr->bLength,
-                        (itr - usb_dev->rawdescriptors[actconfig_idx]),
-                        itr_size);
+               dev_dbg(dev, "Extra device descriptor: "
+                       "type %02x/%u bytes @ %zu (%zu left)\n",
+                       hdr->bDescriptorType, hdr->bLength,
+                       (itr - usb_dev->rawdescriptors[actconfig_idx]),
+                       itr_size);
                if (hdr->bDescriptorType == USB_DT_CS_RADIO_CONTROL)
                        goto found;
                itr += hdr->bLength;
@@ -795,8 +788,7 @@ found:
                goto error;
        }
        rc->version = version;
-       d_printf(3, dev, "Device supports WUSB protocol version 0x%04x \n",
-                rc->version);
+       dev_dbg(dev, "Device supports WUSB protocol version 0x%04x \n", rc->version);
        result = 0;
 error:
        return result;
@@ -877,11 +869,28 @@ static void hwarc_disconnect(struct usb_interface *iface)
        uwb_rc_rm(uwb_rc);
        usb_put_intf(hwarc->usb_iface);
        usb_put_dev(hwarc->usb_dev);
-       d_printf(1, &hwarc->usb_iface->dev, "freed hwarc %p\n", hwarc);
        kfree(hwarc);
        uwb_rc_put(uwb_rc);     /* when creating the device, refcount = 1 */
 }
 
+static int hwarc_pre_reset(struct usb_interface *iface)
+{
+       struct hwarc *hwarc = usb_get_intfdata(iface);
+       struct uwb_rc *uwb_rc = hwarc->uwb_rc;
+
+       uwb_rc_pre_reset(uwb_rc);
+       return 0;
+}
+
+static int hwarc_post_reset(struct usb_interface *iface)
+{
+       struct hwarc *hwarc = usb_get_intfdata(iface);
+       struct uwb_rc *uwb_rc = hwarc->uwb_rc;
+
+       uwb_rc_post_reset(uwb_rc);
+       return 0;
+}
+
 /** USB device ID's that we handle */
 static struct usb_device_id hwarc_id_table[] = {
        /* D-Link DUB-1210 */
@@ -898,20 +907,16 @@ MODULE_DEVICE_TABLE(usb, hwarc_id_table);
 
 static struct usb_driver hwarc_driver = {
        .name =         "hwa-rc",
+       .id_table =     hwarc_id_table,
        .probe =        hwarc_probe,
        .disconnect =   hwarc_disconnect,
-       .id_table =     hwarc_id_table,
+       .pre_reset =    hwarc_pre_reset,
+       .post_reset =   hwarc_post_reset,
 };
 
 static int __init hwarc_driver_init(void)
 {
-       int result;
-       result = usb_register(&hwarc_driver);
-       if (result < 0)
-               printk(KERN_ERR "HWA-RC: Cannot register USB driver: %d\n",
-                      result);
-       return result;
-
+       return usb_register(&hwarc_driver);
 }
 module_init(hwarc_driver_init);
 
index 9097b3b..da7b1d0 100644 (file)
 #include <linux/uwb.h>
 #include <linux/random.h>
 
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
-
-/**
+/*
  * i1480_rceb_check - Check RCEB for expected field values
  * @i1480: pointer to device for which RCEB is being checked
  * @rceb: RCEB being checked
@@ -83,7 +80,7 @@ int i1480_rceb_check(const struct i1480 *i1480, const struct uwb_rceb *rceb,
 EXPORT_SYMBOL_GPL(i1480_rceb_check);
 
 
-/**
+/*
  * Execute a Radio Control Command
  *
  * Command data has to be in i1480->cmd_buf.
@@ -101,7 +98,6 @@ ssize_t i1480_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size,
        u8 expected_type = reply->bEventType;
        u8 context;
 
-       d_fnstart(3, i1480->dev, "(%p, %s, %zu)\n", i1480, cmd_name, cmd_size);
        init_completion(&i1480->evt_complete);
        i1480->evt_result = -EINPROGRESS;
        do {
@@ -150,8 +146,6 @@ ssize_t i1480_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size,
        result = i1480_rceb_check(i1480, i1480->evt_buf, cmd_name, context,
                                  expected_type, expected_event);
 error:
-       d_fnend(3, i1480->dev, "(%p, %s, %zu) = %zd\n",
-               i1480, cmd_name, cmd_size, result);
        return result;
 }
 EXPORT_SYMBOL_GPL(i1480_cmd);
index 2e4d8f0..694d0da 100644 (file)
@@ -31,9 +31,6 @@
 #include <linux/uwb.h>
 #include "i1480-dfu.h"
 
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
-
 /*
  * Descriptor for a continuous segment of MAC fw data
  */
@@ -184,10 +181,6 @@ ssize_t i1480_fw_cmp(struct i1480 *i1480, struct fw_hdr *hdr)
                }
                if (memcmp(i1480->cmd_buf, bin + src_itr, result)) {
                        u8 *buf = i1480->cmd_buf;
-                       d_printf(2, i1480->dev,
-                                "original data @ %p + %u, %zu bytes\n",
-                                bin, src_itr, result);
-                       d_dump(4, i1480->dev, bin + src_itr, result);
                        for (cnt = 0; cnt < result; cnt++)
                                if (bin[src_itr + cnt] != buf[cnt]) {
                                        dev_err(i1480->dev, "byte failed at "
@@ -224,7 +217,6 @@ int mac_fw_hdrs_push(struct i1480 *i1480, struct fw_hdr *hdr,
        struct fw_hdr *hdr_itr;
        int verif_retry_count;
 
-       d_fnstart(3, dev, "(%p, %p)\n", i1480, hdr);
        /* Now, header by header, push them to the hw */
        for (hdr_itr = hdr; hdr_itr != NULL; hdr_itr = hdr_itr->next) {
                verif_retry_count = 0;
@@ -264,7 +256,6 @@ retry:
                        break;
                }
        }
-       d_fnend(3, dev, "(%zd)\n", result);
        return result;
 }
 
@@ -337,11 +328,9 @@ int __mac_fw_upload(struct i1480 *i1480, const char *fw_name,
        const struct firmware *fw;
        struct fw_hdr *fw_hdrs;
 
-       d_fnstart(3, i1480->dev, "(%p, %s, %s)\n", i1480, fw_name, fw_tag);
        result = request_firmware(&fw, fw_name, i1480->dev);
        if (result < 0) /* Up to caller to complain on -ENOENT */
                goto out;
-       d_printf(3, i1480->dev, "%s fw '%s': uploading\n", fw_tag, fw_name);
        result = fw_hdrs_load(i1480, &fw_hdrs, fw->data, fw->size);
        if (result < 0) {
                dev_err(i1480->dev, "%s fw '%s': failed to parse firmware "
@@ -363,8 +352,6 @@ out_hdrs_release:
 out_release:
        release_firmware(fw);
 out:
-       d_fnend(3, i1480->dev, "(%p, %s, %s) = %d\n", i1480, fw_name, fw_tag,
-               result);
        return result;
 }
 
@@ -433,7 +420,6 @@ int i1480_fw_is_running_q(struct i1480 *i1480)
        int result;
        u32 *val = (u32 *) i1480->cmd_buf;
 
-       d_fnstart(3, i1480->dev, "(i1480 %p)\n", i1480);
        for (cnt = 0; cnt < 10; cnt++) {
                msleep(100);
                result = i1480->read(i1480, 0x80080000, 4);
@@ -447,7 +433,6 @@ int i1480_fw_is_running_q(struct i1480 *i1480)
        dev_err(i1480->dev, "Timed out waiting for fw to start\n");
        result = -ETIMEDOUT;
 out:
-       d_fnend(3, i1480->dev, "(i1480 %p) = %d\n", i1480, result);
        return result;
 
 }
@@ -467,7 +452,6 @@ int i1480_mac_fw_upload(struct i1480 *i1480)
        int result = 0, deprecated_name = 0;
        struct i1480_rceb *rcebe = (void *) i1480->evt_buf;
 
-       d_fnstart(3, i1480->dev, "(%p)\n", i1480);
        result = __mac_fw_upload(i1480, i1480->mac_fw_name, "MAC");
        if (result == -ENOENT) {
                result = __mac_fw_upload(i1480, i1480->mac_fw_name_deprecate,
@@ -501,7 +485,6 @@ int i1480_mac_fw_upload(struct i1480 *i1480)
                dev_err(i1480->dev, "MAC fw '%s': initialization event returns "
                        "wrong size (%zu bytes vs %zu needed)\n",
                        i1480->mac_fw_name, i1480->evt_result, sizeof(*rcebe));
-               dump_bytes(i1480->dev, rcebe, min(i1480->evt_result, (ssize_t)32));
                goto error_size;
        }
        result = -EIO;
@@ -522,6 +505,5 @@ error_fw_not_running:
 error_init_timeout:
 error_size:
 error_setup:
-       d_fnend(3, i1480->dev, "(i1480 %p) = %d\n", i1480, result);
        return result;
 }
index 98eeeff..686795e 100644 (file)
@@ -35,7 +35,6 @@
  * the functions are i1480_usb_NAME().
  */
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/usb.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/usb/wusb-wa.h>
 #include "i1480-dfu.h"
 
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
-
-
 struct i1480_usb {
        struct i1480 i1480;
        struct usb_device *usb_dev;
@@ -118,8 +113,6 @@ int i1480_usb_write(struct i1480 *i1480, u32 memory_address,
        struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480);
        size_t buffer_size, itr = 0;
 
-       d_fnstart(3, i1480->dev, "(%p, 0x%08x, %p, %zu)\n",
-                 i1480, memory_address, buffer, size);
        BUG_ON(size & 0x3); /* Needs to be a multiple of 4 */
        while (size > 0) {
                buffer_size = size < i1480->buf_size ? size : i1480->buf_size;
@@ -132,16 +125,10 @@ int i1480_usb_write(struct i1480 *i1480, u32 memory_address,
                        i1480->cmd_buf, buffer_size, 100 /* FIXME: arbitrary */);
                if (result < 0)
                        break;
-               d_printf(3, i1480->dev,
-                        "wrote @ 0x%08x %u bytes (of %zu bytes requested)\n",
-                        memory_address, result, buffer_size);
-               d_dump(4, i1480->dev, i1480->cmd_buf, result);
                itr += result;
                memory_address += result;
                size -= result;
        }
-       d_fnend(3, i1480->dev, "(%p, 0x%08x, %p, %zu) = %d\n",
-               i1480, memory_address, buffer, size, result);
        return result;
 }
 
@@ -166,8 +153,6 @@ int i1480_usb_read(struct i1480 *i1480, u32 addr, size_t size)
        size_t itr, read_size = i1480->buf_size;
        struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480);
 
-       d_fnstart(3, i1480->dev, "(%p, 0x%08x, %zu)\n",
-                 i1480, addr, size);
        BUG_ON(size > i1480->buf_size);
        BUG_ON(size & 0x3); /* Needs to be a multiple of 4 */
        BUG_ON(read_size > 512);
@@ -201,10 +186,6 @@ int i1480_usb_read(struct i1480 *i1480, u32 addr, size_t size)
        }
        result = bytes;
 out:
-       d_fnend(3, i1480->dev, "(%p, 0x%08x, %zu) = %zd\n",
-               i1480, addr, size, result);
-       if (result > 0)
-               d_dump(4, i1480->dev, i1480->cmd_buf, result);
        return result;
 }
 
@@ -260,7 +241,6 @@ int i1480_usb_wait_init_done(struct i1480 *i1480)
        struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480);
        struct usb_endpoint_descriptor *epd;
 
-       d_fnstart(3, dev, "(%p)\n", i1480);
        init_completion(&i1480->evt_complete);
        i1480->evt_result = -EINPROGRESS;
        epd = &i1480_usb->usb_iface->cur_altsetting->endpoint[0].desc;
@@ -282,14 +262,12 @@ int i1480_usb_wait_init_done(struct i1480 *i1480)
                goto error_wait;
        }
        usb_kill_urb(i1480_usb->neep_urb);
-       d_fnend(3, dev, "(%p) = 0\n", i1480);
        return 0;
 
 error_wait:
        usb_kill_urb(i1480_usb->neep_urb);
 error_submit:
        i1480->evt_result = result;
-       d_fnend(3, dev, "(%p) = %d\n", i1480, result);
        return result;
 }
 
@@ -320,7 +298,6 @@ int i1480_usb_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size)
        struct uwb_rccb *cmd = i1480->cmd_buf;
        u8 iface_no;
 
-       d_fnstart(3, dev, "(%p, %s, %zu)\n", i1480, cmd_name, cmd_size);
        /* Post a read on the notification & event endpoint */
        iface_no = i1480_usb->usb_iface->cur_altsetting->desc.bInterfaceNumber;
        epd = &i1480_usb->usb_iface->cur_altsetting->endpoint[0].desc;
@@ -348,15 +325,11 @@ int i1480_usb_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size)
                        cmd_name, result);
                goto error_submit_ep0;
        }
-       d_fnend(3, dev, "(%p, %s, %zu) = %d\n",
-               i1480, cmd_name, cmd_size, result);
        return result;
 
 error_submit_ep0:
        usb_kill_urb(i1480_usb->neep_urb);
 error_submit_ep1:
-       d_fnend(3, dev, "(%p, %s, %zu) = %d\n",
-               i1480, cmd_name, cmd_size, result);
        return result;
 }
 
index 737d60c..049c05d 100644 (file)
  *                          is being removed.
  *         i1480u_rm()
  */
-#include <linux/version.h>
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
-#include <linux/uwb/debug.h>
+
 #include "i1480u-wlp.h"
 
 
@@ -207,7 +206,7 @@ int i1480u_add(struct i1480u *i1480u, struct usb_interface *iface)
        wlp->fill_device_info = i1480u_fill_device_info;
        wlp->stop_queue = i1480u_stop_queue;
        wlp->start_queue = i1480u_start_queue;
-       result = wlp_setup(wlp, rc);
+       result = wlp_setup(wlp, rc, net_dev);
        if (result < 0) {
                dev_err(&iface->dev, "Cannot setup WLP\n");
                goto error_wlp_setup;
index 8802ac4..e3873ff 100644 (file)
@@ -41,7 +41,7 @@
 
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
-#include <linux/uwb/debug.h>
+
 #include "i1480u-wlp.h"
 
 struct i1480u_cmd_set_ip_mas {
@@ -207,6 +207,11 @@ int i1480u_open(struct net_device *net_dev)
        result = i1480u_rx_setup(i1480u);               /* Alloc RX stuff */
        if (result < 0)
                goto error_rx_setup;
+
+       result = uwb_radio_start(&wlp->pal);
+       if (result < 0)
+               goto error_radio_start;
+
        netif_wake_queue(net_dev);
 #ifdef i1480u_FLOW_CONTROL
        result = usb_submit_urb(i1480u->notif_urb, GFP_KERNEL);;
@@ -215,25 +220,20 @@ int i1480u_open(struct net_device *net_dev)
                goto error_notif_urb_submit;
        }
 #endif
-       i1480u->uwb_notifs_handler.cb = i1480u_uwb_notifs_cb;
-       i1480u->uwb_notifs_handler.data = i1480u;
-       if (uwb_bg_joined(rc))
-               netif_carrier_on(net_dev);
-       else
-               netif_carrier_off(net_dev);
-       uwb_notifs_register(rc, &i1480u->uwb_notifs_handler);
        /* Interface is up with an address, now we can create WSS */
        result = wlp_wss_setup(net_dev, &wlp->wss);
        if (result < 0) {
                dev_err(dev, "Can't create WSS: %d. \n", result);
-               goto error_notif_deregister;
+               goto error_wss_setup;
        }
        return 0;
-error_notif_deregister:
-       uwb_notifs_deregister(rc, &i1480u->uwb_notifs_handler);
+error_wss_setup:
 #ifdef i1480u_FLOW_CONTROL
+       usb_kill_urb(i1480u->notif_urb);
 error_notif_urb_submit:
 #endif
+       uwb_radio_stop(&wlp->pal);
+error_radio_start:
        netif_stop_queue(net_dev);
        i1480u_rx_release(i1480u);
 error_rx_setup:
@@ -248,16 +248,15 @@ int i1480u_stop(struct net_device *net_dev)
 {
        struct i1480u *i1480u = netdev_priv(net_dev);
        struct wlp *wlp = &i1480u->wlp;
-       struct uwb_rc *rc = wlp->rc;
 
        BUG_ON(wlp->rc == NULL);
        wlp_wss_remove(&wlp->wss);
-       uwb_notifs_deregister(rc, &i1480u->uwb_notifs_handler);
        netif_carrier_off(net_dev);
 #ifdef i1480u_FLOW_CONTROL
        usb_kill_urb(i1480u->notif_urb);
 #endif
        netif_stop_queue(net_dev);
+       uwb_radio_stop(&wlp->pal);
        i1480u_rx_release(i1480u);
        i1480u_tx_release(i1480u);
        return 0;
@@ -303,34 +302,6 @@ int i1480u_change_mtu(struct net_device *net_dev, int mtu)
        return 0;
 }
 
-
-/**
- * Callback function to handle events from UWB
- * When we see other devices we know the carrier is ok,
- * if we are the only device in the beacon group we set the carrier
- * state to off.
- * */
-void i1480u_uwb_notifs_cb(void *data, struct uwb_dev *uwb_dev,
-                         enum uwb_notifs event)
-{
-       struct i1480u *i1480u = data;
-       struct net_device *net_dev = i1480u->net_dev;
-       struct device *dev = &i1480u->usb_iface->dev;
-       switch (event) {
-       case UWB_NOTIF_BG_JOIN:
-               netif_carrier_on(net_dev);
-               dev_info(dev, "Link is up\n");
-               break;
-       case UWB_NOTIF_BG_LEAVE:
-               netif_carrier_off(net_dev);
-               dev_info(dev, "Link is down\n");
-               break;
-       default:
-               dev_err(dev, "don't know how to handle event %d from uwb\n",
-                               event);
-       }
-}
-
 /**
  * Stop the network queue
  *
index 9fc0353..34f4cf9 100644 (file)
 #include <linux/etherdevice.h>
 #include "i1480u-wlp.h"
 
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
-
-
-/**
+/*
  * Setup the RX context
  *
  * Each URB is provided with a transfer_buffer that is the data field
@@ -129,7 +125,7 @@ error:
 }
 
 
-/** Release resources associated to the rx context */
+/* Release resources associated to the rx context */
 void i1480u_rx_release(struct i1480u *i1480u)
 {
        int cnt;
@@ -155,7 +151,7 @@ void i1480u_rx_unlink_urbs(struct i1480u *i1480u)
        }
 }
 
-/** Fix an out-of-sequence packet */
+/* Fix an out-of-sequence packet */
 #define i1480u_fix(i1480u, msg...)                     \
 do {                                                   \
        if (printk_ratelimit())                         \
@@ -166,7 +162,7 @@ do {                                                        \
 } while (0)
 
 
-/** Drop an out-of-sequence packet */
+/* Drop an out-of-sequence packet */
 #define i1480u_drop(i1480u, msg...)                    \
 do {                                                   \
        if (printk_ratelimit())                         \
@@ -177,7 +173,7 @@ do {                                                        \
 
 
 
-/** Finalizes setting up the SKB and delivers it
+/* Finalizes setting up the SKB and delivers it
  *
  * We first pass the incoming frame to WLP substack for verification. It
  * may also be a WLP association frame in which case WLP will take over the
@@ -192,18 +188,11 @@ void i1480u_skb_deliver(struct i1480u *i1480u)
        struct net_device *net_dev = i1480u->net_dev;
        struct device *dev = &i1480u->usb_iface->dev;
 
-       d_printf(6, dev, "RX delivered pre skb(%p), %u bytes\n",
-                i1480u->rx_skb, i1480u->rx_skb->len);
-       d_dump(7, dev, i1480u->rx_skb->data, i1480u->rx_skb->len);
        should_parse = wlp_receive_frame(dev, &i1480u->wlp, i1480u->rx_skb,
                                         &i1480u->rx_srcaddr);
        if (!should_parse)
                goto out;
        i1480u->rx_skb->protocol = eth_type_trans(i1480u->rx_skb, net_dev);
-       d_printf(5, dev, "RX delivered skb(%p), %u bytes\n",
-                i1480u->rx_skb, i1480u->rx_skb->len);
-       d_dump(7, dev, i1480u->rx_skb->data,
-              i1480u->rx_skb->len > 72 ? 72 : i1480u->rx_skb->len);
        i1480u->stats.rx_packets++;
        i1480u->stats.rx_bytes += i1480u->rx_untd_pkt_size;
        net_dev->last_rx = jiffies;
@@ -216,7 +205,7 @@ out:
 }
 
 
-/**
+/*
  * Process a buffer of data received from the USB RX endpoint
  *
  * First fragment arrives with next or last fragment. All other fragments
@@ -404,7 +393,7 @@ out:
 }
 
 
-/**
+/*
  * Called when an RX URB has finished receiving or has found some kind
  * of error condition.
  *
index a1d8ca6..4ffaf54 100644 (file)
@@ -25,8 +25,8 @@
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <linux/uwb/debug.h>
 #include <linux/device.h>
+
 #include "i1480u-wlp.h"
 
 
@@ -226,7 +226,6 @@ ssize_t wlp_tx_inflight_store(struct i1480u_tx_inflight *inflight,
  * (CLASS_DEVICE_ATTR or DEVICE_ATTR) and i1480u_ATTR_NAME produces a
  * class_device_attr_NAME or device_attr_NAME (for group registration).
  */
-#include <linux/version.h>
 
 #define i1480u_SHOW(name, fn, param)                           \
 static ssize_t i1480u_show_##name(struct device *dev,          \
index 3426bfb..39032cc 100644 (file)
@@ -55,8 +55,6 @@
  */
 
 #include "i1480u-wlp.h"
-#define D_LOCAL 5
-#include <linux/uwb/debug.h>
 
 enum {
        /* This is only for Next and Last TX packets */
@@ -64,7 +62,7 @@ enum {
                - sizeof(struct untd_hdr_rst),
 };
 
-/** Free resources allocated to a i1480u tx context. */
+/* Free resources allocated to a i1480u tx context. */
 static
 void i1480u_tx_free(struct i1480u_tx *wtx)
 {
@@ -99,7 +97,7 @@ void i1480u_tx_unlink_urbs(struct i1480u *i1480u)
 }
 
 
-/**
+/*
  * Callback for a completed tx USB URB.
  *
  * TODO:
@@ -149,8 +147,6 @@ void i1480u_tx_cb(struct urb *urb)
            <= i1480u->tx_inflight.threshold
            && netif_queue_stopped(net_dev)
            && i1480u->tx_inflight.threshold != 0) {
-               if (d_test(2) && printk_ratelimit())
-                       d_printf(2, dev, "Restart queue. \n");
                netif_start_queue(net_dev);
                atomic_inc(&i1480u->tx_inflight.restart_count);
        }
@@ -158,7 +154,7 @@ void i1480u_tx_cb(struct urb *urb)
 }
 
 
-/**
+/*
  * Given a buffer that doesn't fit in a single fragment, create an
  * scatter/gather structure for delivery to the USB pipe.
  *
@@ -253,15 +249,11 @@ int i1480u_tx_create_n(struct i1480u_tx *wtx, struct sk_buff *skb,
        /* Now do each remaining fragment */
        result = -EINVAL;
        while (pl_size_left > 0) {
-               d_printf(5, NULL, "ITR HDR: pl_size_left %zu buf_itr %zu\n",
-                        pl_size_left, buf_itr - wtx->buf);
                if (buf_itr + sizeof(*untd_hdr_rst) - wtx->buf
                    > wtx->buf_size) {
                        printk(KERN_ERR "BUG: no space for header\n");
                        goto error_bug;
                }
-               d_printf(5, NULL, "ITR HDR 2: pl_size_left %zu buf_itr %zu\n",
-                        pl_size_left, buf_itr - wtx->buf);
                untd_hdr_rst = buf_itr;
                buf_itr += sizeof(*untd_hdr_rst);
                if (pl_size_left > i1480u_MAX_PL_SIZE) {
@@ -271,9 +263,6 @@ int i1480u_tx_create_n(struct i1480u_tx *wtx, struct sk_buff *skb,
                        frg_pl_size = pl_size_left;
                        untd_hdr_set_type(&untd_hdr_rst->hdr, i1480u_PKT_FRAG_LST);
                }
-               d_printf(5, NULL,
-                        "ITR PL: pl_size_left %zu buf_itr %zu frg_pl_size %zu\n",
-                        pl_size_left, buf_itr - wtx->buf, frg_pl_size);
                untd_hdr_set_rx_tx(&untd_hdr_rst->hdr, 0);
                untd_hdr_rst->hdr.len = cpu_to_le16(frg_pl_size);
                untd_hdr_rst->padding = 0;
@@ -286,9 +275,6 @@ int i1480u_tx_create_n(struct i1480u_tx *wtx, struct sk_buff *skb,
                buf_itr += frg_pl_size;
                pl_itr += frg_pl_size;
                pl_size_left -= frg_pl_size;
-               d_printf(5, NULL,
-                        "ITR PL 2: pl_size_left %zu buf_itr %zu frg_pl_size %zu\n",
-                        pl_size_left, buf_itr - wtx->buf, frg_pl_size);
        }
        dev_kfree_skb_irq(skb);
        return 0;
@@ -308,7 +294,7 @@ error_buf_alloc:
 }
 
 
-/**
+/*
  * Given a buffer that fits in a single fragment, fill out a @wtx
  * struct for transmitting it down the USB pipe.
  *
@@ -346,7 +332,7 @@ int i1480u_tx_create_1(struct i1480u_tx *wtx, struct sk_buff *skb,
 }
 
 
-/**
+/*
  * Given a skb to transmit, massage it to become palatable for the TX pipe
  *
  * This will break the buffer in chunks smaller than
@@ -425,7 +411,7 @@ error_wtx_alloc:
        return NULL;
 }
 
-/**
+/*
  * Actual fragmentation and transmission of frame
  *
  * @wlp:  WLP substack data structure
@@ -447,20 +433,12 @@ int i1480u_xmit_frame(struct wlp *wlp, struct sk_buff *skb,
        struct i1480u_tx *wtx;
        struct wlp_tx_hdr *wlp_tx_hdr;
        static unsigned char dev_bcast[2] = { 0xff, 0xff };
-#if 0
-       int lockup = 50;
-#endif
 
-       d_fnstart(6, dev, "(skb %p (%u), net_dev %p)\n", skb, skb->len,
-                 net_dev);
        BUG_ON(i1480u->wlp.rc == NULL);
        if ((net_dev->flags & IFF_UP) == 0)
                goto out;
        result = -EBUSY;
        if (atomic_read(&i1480u->tx_inflight.count) >= i1480u->tx_inflight.max) {
-               if (d_test(2) && printk_ratelimit())
-                       d_printf(2, dev, "Max frames in flight "
-                                "stopping queue.\n");
                netif_stop_queue(net_dev);
                goto error_max_inflight;
        }
@@ -489,21 +467,6 @@ int i1480u_xmit_frame(struct wlp *wlp, struct sk_buff *skb,
                wlp_tx_hdr_set_delivery_id_type(wlp_tx_hdr, i1480u->options.pca_base_priority);
        }
 
-#if 0
-       dev_info(dev, "TX delivering skb -> USB, %zu bytes\n", skb->len);
-       dump_bytes(dev, skb->data, skb->len > 72 ? 72 : skb->len);
-#endif
-#if 0
-       /* simulates a device lockup after every lockup# packets */
-       if (lockup && ((i1480u->stats.tx_packets + 1) % lockup) == 0) {
-               /* Simulate a dropped transmit interrupt */
-               net_dev->trans_start = jiffies;
-               netif_stop_queue(net_dev);
-               dev_err(dev, "Simulate lockup at %ld\n", jiffies);
-               return result;
-       }
-#endif
-
        result = usb_submit_urb(wtx->urb, GFP_ATOMIC);          /* Go baby */
        if (result < 0) {
                dev_err(dev, "TX: cannot submit URB: %d\n", result);
@@ -513,8 +476,6 @@ int i1480u_xmit_frame(struct wlp *wlp, struct sk_buff *skb,
        }
        atomic_inc(&i1480u->tx_inflight.count);
        net_dev->trans_start = jiffies;
-       d_fnend(6, dev, "(skb %p (%u), net_dev %p) = %d\n", skb, skb->len,
-               net_dev, result);
        return result;
 
 error_tx_urb_submit:
@@ -522,13 +483,11 @@ error_tx_urb_submit:
 error_wtx_alloc:
 error_max_inflight:
 out:
-       d_fnend(6, dev, "(skb %p (%u), net_dev %p) = %d\n", skb, skb->len,
-               net_dev, result);
        return result;
 }
 
 
-/**
+/*
  * Transmit an skb  Called when an skbuf has to be transmitted
  *
  * The skb is first passed to WLP substack to ensure this is a valid
@@ -551,9 +510,6 @@ int i1480u_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
        struct device *dev = &i1480u->usb_iface->dev;
        struct uwb_dev_addr dst;
 
-       d_fnstart(6, dev, "(skb %p (%u), net_dev %p)\n", skb, skb->len,
-                 net_dev);
-       BUG_ON(i1480u->wlp.rc == NULL);
        if ((net_dev->flags & IFF_UP) == 0)
                goto error;
        result = wlp_prepare_tx_frame(dev, &i1480u->wlp, skb, &dst);
@@ -562,31 +518,25 @@ int i1480u_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
                        "Dropping packet.\n", result);
                goto error;
        } else if (result == 1) {
-               d_printf(6, dev, "WLP will transmit frame. \n");
                /* trans_start time will be set when WLP actually transmits
                 * the frame */
                goto out;
        }
-       d_printf(6, dev, "Transmitting frame. \n");
        result = i1480u_xmit_frame(&i1480u->wlp, skb, &dst);
        if (result < 0) {
                dev_err(dev, "Frame TX failed (%d).\n", result);
                goto error;
        }
-       d_fnend(6, dev, "(skb %p (%u), net_dev %p) = %d\n", skb, skb->len,
-               net_dev, result);
        return NETDEV_TX_OK;
 error:
        dev_kfree_skb_any(skb);
        i1480u->stats.tx_dropped++;
 out:
-       d_fnend(6, dev, "(skb %p (%u), net_dev %p) = %d\n", skb, skb->len,
-               net_dev, result);
        return NETDEV_TX_OK;
 }
 
 
-/**
+/*
  * Called when a pkt transmission doesn't complete in a reasonable period
  * Device reset may sleep - do it outside of interrupt context (delayed)
  */
diff --git a/drivers/uwb/ie-rcv.c b/drivers/uwb/ie-rcv.c
new file mode 100644 (file)
index 0000000..917e6d7
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Ultra Wide Band
+ * IE Received notification handling.
+ *
+ * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/bitmap.h>
+#include "uwb-internal.h"
+
+/*
+ * Process an incoming IE Received notification.
+ */
+int uwbd_evt_handle_rc_ie_rcv(struct uwb_event *evt)
+{
+       int result = -EINVAL;
+       struct device *dev = &evt->rc->uwb_dev.dev;
+       struct uwb_rc_evt_ie_rcv *iercv;
+       size_t iesize;
+
+       /* Is there enough data to decode it? */
+       if (evt->notif.size < sizeof(*iercv)) {
+               dev_err(dev, "IE Received notification: Not enough data to "
+                       "decode (%zu vs %zu bytes needed)\n",
+                       evt->notif.size, sizeof(*iercv));
+               goto error;
+       }
+       iercv = container_of(evt->notif.rceb, struct uwb_rc_evt_ie_rcv, rceb);
+       iesize = le16_to_cpu(iercv->wIELength);
+
+       dev_dbg(dev, "IE received, element ID=%d\n", iercv->IEData[0]);
+
+       if (iercv->IEData[0] == UWB_RELINQUISH_REQUEST_IE) {
+               dev_warn(dev, "unhandled Relinquish Request IE\n");
+       }
+
+       return 0;
+error:
+       return result;
+}
index cf6f3d1..ab97668 100644 (file)
@@ -25,8 +25,6 @@
  */
 
 #include "uwb-internal.h"
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
 
 /**
  * uwb_ie_next - get the next IE in a buffer
@@ -61,6 +59,42 @@ struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len)
 EXPORT_SYMBOL_GPL(uwb_ie_next);
 
 /**
+ * uwb_ie_dump_hex - print IEs to a character buffer
+ * @ies: the IEs to print.
+ * @len: length of all the IEs.
+ * @buf: the destination buffer.
+ * @size: size of @buf.
+ *
+ * Returns the number of characters written.
+ */
+int uwb_ie_dump_hex(const struct uwb_ie_hdr *ies, size_t len,
+                   char *buf, size_t size)
+{
+       void *ptr;
+       const struct uwb_ie_hdr *ie;
+       int r = 0;
+       u8 *d;
+
+       ptr = (void *)ies;
+       for (;;) {
+               ie = uwb_ie_next(&ptr, &len);
+               if (!ie)
+                       break;
+
+               r += scnprintf(buf + r, size - r, "%02x %02x",
+                              (unsigned)ie->element_id,
+                              (unsigned)ie->length);
+               d = (uint8_t *)ie + sizeof(struct uwb_ie_hdr);
+               while (d != ptr && r < size)
+                       r += scnprintf(buf + r, size - r, " %02x", (unsigned)*d++);
+               if (r < size)
+                       buf[r++] = '\n';
+       };
+
+       return r;
+}
+
+/**
  * Get the IEs that a radio controller is sending in its beacon
  *
  * @uwb_rc:  UWB Radio Controller
@@ -70,6 +104,7 @@ EXPORT_SYMBOL_GPL(uwb_ie_next);
  * anything. Once done with the iedata buffer, call
  * uwb_rc_ie_release(iedata). Don't call kfree on it.
  */
+static
 ssize_t uwb_rc_get_ie(struct uwb_rc *uwb_rc, struct uwb_rc_evt_get_ie **pget_ie)
 {
        ssize_t result;
@@ -78,148 +113,35 @@ ssize_t uwb_rc_get_ie(struct uwb_rc *uwb_rc, struct uwb_rc_evt_get_ie **pget_ie)
        struct uwb_rceb *reply = NULL;
        struct uwb_rc_evt_get_ie *get_ie;
 
-       d_fnstart(3, dev, "(%p, %p)\n", uwb_rc, pget_ie);
-       result = -ENOMEM;
        cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
        if (cmd == NULL)
-               goto error_kzalloc;
+               return -ENOMEM;
+
        cmd->bCommandType = UWB_RC_CET_GENERAL;
        cmd->wCommand = cpu_to_le16(UWB_RC_CMD_GET_IE);
        result = uwb_rc_vcmd(uwb_rc, "GET_IE", cmd, sizeof(*cmd),
                             UWB_RC_CET_GENERAL, UWB_RC_CMD_GET_IE,
                             &reply);
+       kfree(cmd);
        if (result < 0)
-               goto error_cmd;
+               return result;
+
        get_ie = container_of(reply, struct uwb_rc_evt_get_ie, rceb);
        if (result < sizeof(*get_ie)) {
                dev_err(dev, "not enough data returned for decoding GET IE "
                        "(%zu bytes received vs %zu needed)\n",
                        result, sizeof(*get_ie));
-               result = -EINVAL;
+               return -EINVAL;
        } else if (result < sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength)) {
                dev_err(dev, "not enough data returned for decoding GET IE "
                        "payload (%zu bytes received vs %zu needed)\n", result,
                        sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength));
-               result = -EINVAL;
-       } else
-               *pget_ie = get_ie;
-error_cmd:
-       kfree(cmd);
-error_kzalloc:
-       d_fnend(3, dev, "(%p, %p) = %d\n", uwb_rc, pget_ie, (int)result);
-       return result;
-}
-EXPORT_SYMBOL_GPL(uwb_rc_get_ie);
-
-
-/*
- * Given a pointer to an IE, print it in ASCII/hex followed by a new line
- *
- * @ie_hdr: pointer to the IE header. Length is in there, and it is
- *          guaranteed that the ie_hdr->length bytes following it are
- *          safely accesible.
- *
- * @_data: context data passed from uwb_ie_for_each(), an struct output_ctx
- */
-int uwb_ie_dump_hex(struct uwb_dev *uwb_dev, const struct uwb_ie_hdr *ie_hdr,
-                   size_t offset, void *_ctx)
-{
-       struct uwb_buf_ctx *ctx = _ctx;
-       const u8 *pl = (void *)(ie_hdr + 1);
-       u8 pl_itr;
-
-       ctx->bytes += scnprintf(ctx->buf + ctx->bytes, ctx->size - ctx->bytes,
-                               "%02x %02x ", (unsigned) ie_hdr->element_id,
-                               (unsigned) ie_hdr->length);
-       pl_itr = 0;
-       while (pl_itr < ie_hdr->length && ctx->bytes < ctx->size)
-               ctx->bytes += scnprintf(ctx->buf + ctx->bytes,
-                                       ctx->size - ctx->bytes,
-                                       "%02x ", (unsigned) pl[pl_itr++]);
-       if (ctx->bytes < ctx->size)
-               ctx->buf[ctx->bytes++] = '\n';
-       return 0;
-}
-EXPORT_SYMBOL_GPL(uwb_ie_dump_hex);
-
-
-/**
- * Verify that a pointer in a buffer points to valid IE
- *
- * @start: pointer to start of buffer in which IE appears
- * @itr:   pointer to IE inside buffer that will be verified
- * @top:   pointer to end of buffer
- *
- * @returns: 0 if IE is valid, <0 otherwise
- *
- * Verification involves checking that the buffer can contain a
- * header and the amount of data reported in the IE header can be found in
- * the buffer.
- */
-static
-int uwb_rc_ie_verify(struct uwb_dev *uwb_dev, const void *start,
-                    const void *itr, const void *top)
-{
-       struct device *dev = &uwb_dev->dev;
-       const struct uwb_ie_hdr *ie_hdr;
-
-       if (top - itr < sizeof(*ie_hdr)) {
-               dev_err(dev, "Bad IE: no data to decode header "
-                       "(%zu bytes left vs %zu needed) at offset %zu\n",
-                       top - itr, sizeof(*ie_hdr), itr - start);
-               return -EINVAL;
-       }
-       ie_hdr = itr;
-       itr += sizeof(*ie_hdr);
-       if (top - itr < ie_hdr->length) {
-               dev_err(dev, "Bad IE: not enough data for payload "
-                       "(%zu bytes left vs %zu needed) at offset %zu\n",
-                       top - itr, (size_t)ie_hdr->length,
-                       (void *)ie_hdr - start);
                return -EINVAL;
        }
-       return 0;
-}
 
-
-/**
- * Walk a buffer filled with consecutive IE's a buffer
- *
- * @uwb_dev: UWB device this IEs belong to (for err messages mainly)
- *
- * @fn: function to call with each IE; if it returns 0, we keep
- *      traversing the buffer. If it returns !0, we'll stop and return
- *      that value.
- *
- * @data: pointer passed to @fn
- *
- * @buf: buffer where the consecutive IEs are located
- *
- * @size: size of @buf
- *
- * Each IE is checked for basic correctness (there is space left for
- * the header and the payload). If that test is failed, we stop
- * processing. For every good IE, @fn is called.
- */
-ssize_t uwb_ie_for_each(struct uwb_dev *uwb_dev, uwb_ie_f fn, void *data,
-                       const void *buf, size_t size)
-{
-       ssize_t result = 0;
-       const struct uwb_ie_hdr *ie_hdr;
-       const void *itr = buf, *top = itr + size;
-
-       while (itr < top) {
-               if (uwb_rc_ie_verify(uwb_dev, buf, itr, top) != 0)
-                       break;
-               ie_hdr = itr;
-               itr += sizeof(*ie_hdr) + ie_hdr->length;
-               result = fn(uwb_dev, ie_hdr, itr - buf, data);
-               if (result != 0)
-                       break;
-       }
+       *pget_ie = get_ie;
        return result;
 }
-EXPORT_SYMBOL_GPL(uwb_ie_for_each);
 
 
 /**
@@ -256,70 +178,6 @@ error_cmd:
        return result;
 }
 
-/**
- * Determine by IE id if IE is host settable
- * WUSB 1.0 [8.6.2.8 Table 8.85]
- *
- * EXCEPTION:
- * All but UWB_IE_WLP appears in Table 8.85 from WUSB 1.0. Setting this IE
- * is required for the WLP substack to perform association with its WSS so
- * we hope that the WUSB spec will be changed to reflect this.
- */
-static
-int uwb_rc_ie_is_host_settable(enum uwb_ie element_id)
-{
-       if (element_id == UWB_PCA_AVAILABILITY ||
-           element_id == UWB_BP_SWITCH_IE ||
-           element_id == UWB_MAC_CAPABILITIES_IE ||
-           element_id == UWB_PHY_CAPABILITIES_IE ||
-           element_id == UWB_APP_SPEC_PROBE_IE ||
-           element_id == UWB_IDENTIFICATION_IE ||
-           element_id == UWB_MASTER_KEY_ID_IE ||
-           element_id == UWB_IE_WLP ||
-           element_id == UWB_APP_SPEC_IE)
-               return 1;
-       return 0;
-}
-
-
-/**
- * Extract Host Settable IEs from IE
- *
- * @ie_data: pointer to buffer containing all IEs
- * @size:    size of buffer
- *
- * @returns: length of buffer that only includes host settable IEs
- *
- * Given a buffer of IEs we move all Host Settable IEs to front of buffer
- * by overwriting the IEs that are not Host Settable.
- * Buffer length is adjusted accordingly.
- */
-static
-ssize_t uwb_rc_parse_host_settable_ie(struct uwb_dev *uwb_dev,
-                                     void *ie_data, size_t size)
-{
-       size_t new_len = size;
-       struct uwb_ie_hdr *ie_hdr;
-       size_t ie_length;
-       void *itr = ie_data, *top = itr + size;
-
-       while (itr < top) {
-               if (uwb_rc_ie_verify(uwb_dev, ie_data, itr, top) != 0)
-                       break;
-               ie_hdr = itr;
-               ie_length = sizeof(*ie_hdr) + ie_hdr->length;
-               if (uwb_rc_ie_is_host_settable(ie_hdr->element_id)) {
-                       itr += ie_length;
-               } else {
-                       memmove(itr, itr + ie_length, top - (itr + ie_length));
-                       new_len -= ie_length;
-                       top -= ie_length;
-               }
-       }
-       return new_len;
-}
-
-
 /* Cleanup the whole IE management subsystem */
 void uwb_rc_ie_init(struct uwb_rc *uwb_rc)
 {
@@ -328,49 +186,34 @@ void uwb_rc_ie_init(struct uwb_rc *uwb_rc)
 
 
 /**
- * Set up cache for host settable IEs currently being transmitted
+ * uwb_rc_ie_setup - setup a radio controller's IE manager
+ * @uwb_rc: the radio controller.
  *
- * First we just call GET-IE to get the current IEs being transmitted
- * (or we workaround and pretend we did) and (because the format is
- * the same) reuse that as the IE cache (with the command prefix, as
- * explained in 'struct uwb_rc').
+ * The current set of IEs are obtained from the hardware with a GET-IE
+ * command (since the radio controller is not yet beaconing this will
+ * be just the hardware's MAC and PHY Capability IEs).
  *
- * @returns: size of cache created
+ * Returns 0 on success; -ve on an error.
  */
-ssize_t uwb_rc_ie_setup(struct uwb_rc *uwb_rc)
+int uwb_rc_ie_setup(struct uwb_rc *uwb_rc)
 {
-       struct device *dev = &uwb_rc->uwb_dev.dev;
-       ssize_t result;
-       size_t capacity;
-       struct uwb_rc_evt_get_ie *ie_info;
+       struct uwb_rc_evt_get_ie *ie_info = NULL;
+       int capacity;
+
+       capacity = uwb_rc_get_ie(uwb_rc, &ie_info);
+       if (capacity < 0)
+               return capacity;
 
-       d_fnstart(3, dev, "(%p)\n", uwb_rc);
        mutex_lock(&uwb_rc->ies_mutex);
-       result = uwb_rc_get_ie(uwb_rc, &ie_info);
-       if (result < 0)
-               goto error_get_ie;
-       capacity = result;
-       d_printf(5, dev, "Got IEs %zu bytes (%zu long at %p)\n", result,
-                (size_t)le16_to_cpu(ie_info->wIELength), ie_info);
-
-       /* Remove IEs that host should not set. */
-       result = uwb_rc_parse_host_settable_ie(&uwb_rc->uwb_dev,
-                       ie_info->IEData, le16_to_cpu(ie_info->wIELength));
-       if (result < 0)
-               goto error_parse;
-       d_printf(5, dev, "purged non-settable IEs to %zu bytes\n", result);
-       uwb_rc->ies = (void *) ie_info;
+
+       uwb_rc->ies = (struct uwb_rc_cmd_set_ie *)ie_info;
        uwb_rc->ies->rccb.bCommandType = UWB_RC_CET_GENERAL;
        uwb_rc->ies->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_SET_IE);
        uwb_rc->ies_capacity = capacity;
-       d_printf(5, dev, "IE cache at %p %zu bytes, %zu capacity\n",
-                ie_info, result, capacity);
-       result = 0;
-error_parse:
-error_get_ie:
+
        mutex_unlock(&uwb_rc->ies_mutex);
-       d_fnend(3, dev, "(%p) = %zu\n", uwb_rc, result);
-       return result;
+
+       return 0;
 }
 
 
@@ -383,26 +226,47 @@ void uwb_rc_ie_release(struct uwb_rc *uwb_rc)
 }
 
 
-static
-int __acc_size(struct uwb_dev *uwb_dev, const struct uwb_ie_hdr *ie_hdr,
-              size_t offset, void *_ctx)
+static int uwb_rc_ie_add_one(struct uwb_rc *rc, const struct uwb_ie_hdr *new_ie)
 {
-       size_t *acc_size = _ctx;
-       *acc_size += sizeof(*ie_hdr) + ie_hdr->length;
-       d_printf(6, &uwb_dev->dev, "new acc size %zu\n", *acc_size);
+       struct uwb_rc_cmd_set_ie *new_ies;
+       void *ptr, *prev_ie;
+       struct uwb_ie_hdr *ie;
+       size_t length, new_ie_len, new_capacity, size, prev_size;
+
+       length = le16_to_cpu(rc->ies->wIELength);
+       new_ie_len = sizeof(struct uwb_ie_hdr) + new_ie->length;
+       new_capacity = sizeof(struct uwb_rc_cmd_set_ie) + length + new_ie_len;
+
+       if (new_capacity > rc->ies_capacity) {
+               new_ies = krealloc(rc->ies, new_capacity, GFP_KERNEL);
+               if (!new_ies)
+                       return -ENOMEM;
+               rc->ies = new_ies;
+       }
+
+       ptr = rc->ies->IEData;
+       size = length;
+       for (;;) {
+               prev_ie = ptr;
+               prev_size = size;
+               ie = uwb_ie_next(&ptr, &size);
+               if (!ie || ie->element_id > new_ie->element_id)
+                       break;
+       }
+
+       memmove(prev_ie + new_ie_len, prev_ie, prev_size);
+       memcpy(prev_ie, new_ie, new_ie_len);
+       rc->ies->wIELength = cpu_to_le16(length + new_ie_len);
+
        return 0;
 }
 
-
 /**
- * Add a new IE to IEs currently being transmitted by device
- *
+ * uwb_rc_ie_add - add new IEs to the radio controller's beacon
+ * @uwb_rc: the radio controller.
  * @ies: the buffer containing the new IE or IEs to be added to
- *       the device's beacon. The buffer will be verified for
- *       consistence (meaning the headers should be right) and
- *       consistent with the buffer size.
- * @size: size of @ies (in bytes, total buffer size)
- * @returns: 0 if ok, <0 errno code on error
+ *       the device's beacon.
+ * @size: length of all the IEs.
  *
  * According to WHCI 0.95 [4.13.6] the driver will only receive the RCEB
  * after the device sent the first beacon that includes the IEs specified
@@ -411,66 +275,40 @@ int __acc_size(struct uwb_dev *uwb_dev, const struct uwb_ie_hdr *ie_hdr,
  * we start beaconing.
  *
  * Setting an IE on the device will overwrite all current IEs in device. So
- * we take the current IEs being transmitted by the device, append the
+ * we take the current IEs being transmitted by the device, insert the
  * new one, and call SET IE with all the IEs needed.
  *
- * The local IE cache will only be updated with the new IE if SET IE
- * completed successfully.
+ * Returns 0 on success; or -ENOMEM.
  */
 int uwb_rc_ie_add(struct uwb_rc *uwb_rc,
                  const struct uwb_ie_hdr *ies, size_t size)
 {
        int result = 0;
-       struct device *dev = &uwb_rc->uwb_dev.dev;
-       struct uwb_rc_cmd_set_ie *new_ies;
-       size_t ies_size, total_size, acc_size = 0;
-
-       if (uwb_rc->ies == NULL)
-               return -ESHUTDOWN;
-       uwb_ie_for_each(&uwb_rc->uwb_dev, __acc_size, &acc_size, ies, size);
-       if (acc_size != size) {
-               dev_err(dev, "BUG: bad IEs, misconstructed headers "
-                       "[%zu bytes reported vs %zu calculated]\n",
-                       size, acc_size);
-               WARN_ON(1);
-               return -EINVAL;
-       }
+       void *ptr;
+       const&