diff options
75 files changed, 3252 insertions, 2837 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-uwb_rc b/Documentation/ABI/testing/sysfs-class-uwb_rc index a0d18db..6a5fd07 100644 --- a/Documentation/ABI/testing/sysfs-class-uwb_rc +++ b/Documentation/ABI/testing/sysfs-class-uwb_rc @@ -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 diff --git a/Documentation/usb/wusb-cbaf b/Documentation/usb/wusb-cbaf index 2e78b70..426ddaa 100644 --- a/Documentation/usb/wusb-cbaf +++ b/Documentation/usb/wusb-cbaf @@ -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) diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 64be4d8..8582236 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c @@ -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> @@ -63,16 +62,12 @@ #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); diff --git a/drivers/usb/host/whci/Kbuild b/drivers/usb/host/whci/Kbuild index 26a3871..11e5040 100644 --- a/drivers/usb/host/whci/Kbuild +++ b/drivers/usb/host/whci/Kbuild @@ -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 \ diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index 4d7078e5..577c0d2 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/usb/host/whci/asl.c @@ -19,32 +19,11 @@ #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 index 0000000..cf2d459 --- /dev/null +++ b/drivers/usb/host/whci/debug.c @@ -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); + } +} diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c index ef3ad4d..1569afd 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/usb/host/whci/hcd.c @@ -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); diff --git a/drivers/usb/host/whci/hw.c b/drivers/usb/host/whci/hw.c index ac86e59..d498e72 100644 --- a/drivers/usb/host/whci/hw.c +++ b/drivers/usb/host/whci/hw.c @@ -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; } diff --git a/drivers/usb/host/whci/int.c b/drivers/usb/host/whci/int.c index fce0117..6aae700 100644 --- a/drivers/usb/host/whci/int.c +++ b/drivers/usb/host/whci/int.c @@ -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> diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c index 8d62df0..2ae5abf 100644 --- a/drivers/usb/host/whci/pzl.c +++ b/drivers/usb/host/whci/pzl.c @@ -19,35 +19,11 @@ #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) { diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index 0420037..7be7431 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c @@ -24,46 +24,6 @@ #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; diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h index 1d2a53b..0f3540f 100644 --- a/drivers/usb/host/whci/whcd.h +++ b/drivers/usb/host/whci/whcd.h @@ -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 */ diff --git a/drivers/usb/host/whci/whci-hc.h b/drivers/usb/host/whci/whci-hc.h index bff1eb7..51df7e3 100644 --- a/drivers/usb/host/whci/whci-hc.h +++ b/drivers/usb/host/whci/whci-hc.h @@ -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 diff --git a/drivers/usb/host/whci/wusb.c b/drivers/usb/host/whci/wusb.c index 66e4ddc..f24efde 100644 --- a/drivers/usb/host/whci/wusb.c +++ b/drivers/usb/host/whci/wusb.c @@ -15,47 +15,19 @@ * 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, diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c index ab4788d..1335cbe 100644 --- a/drivers/usb/wusbcore/cbaf.c +++ b/drivers/usb/wusbcore/cbaf.c @@ -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> diff --git a/drivers/usb/wusbcore/crypto.c b/drivers/usb/wusbcore/crypto.c index c36c438..9ec7fd5 100644 --- a/drivers/usb/wusbcore/crypto.c +++ b/drivers/usb/wusbcore/crypto.c @@ -51,9 +51,17 @@ #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) diff --git a/drivers/usb/wusbcore/dev-sysfs.c b/drivers/usb/wusbcore/dev-sysfs.c index 7897a19..1018345 100644 --- a/drivers/usb/wusbcore/dev-sysfs.c +++ b/drivers/usb/wusbcore/dev-sysfs.c @@ -28,10 +28,6 @@ #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) diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index f45d777..e2e7e4b 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c @@ -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. * @@ -97,10 +91,6 @@ #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); diff --git a/drivers/usb/wusbcore/mmc.c b/drivers/usb/wusbcore/mmc.c index cfa77a0..3b52161 100644 --- a/drivers/usb/wusbcore/mmc.c +++ b/drivers/usb/wusbcore/mmc.c @@ -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); diff --git a/drivers/usb/wusbcore/pal.c b/drivers/usb/wusbcore/pal.c index 7cc51e9..d0b172c 100644 --- a/drivers/usb/wusbcore/pal.c +++ b/drivers/usb/wusbcore/pal.c @@ -18,6 +18,16 @@ */ #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); } diff --git a/drivers/usb/wusbcore/reservation.c b/drivers/usb/wusbcore/reservation.c index fc63e77..4ed9736 100644 --- a/drivers/usb/wusbcore/reservation.c +++ b/drivers/usb/wusbcore/reservation.c @@ -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; + } } diff --git a/drivers/usb/wusbcore/rh.c b/drivers/usb/wusbcore/rh.c index 267a643..95c6fa3 100644 --- a/drivers/usb/wusbcore/rh.c +++ b/drivers/usb/wusbcore/rh.c @@ -71,19 +71,20 @@ */ #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; } /* diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index a101cad..f4aa28e 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c @@ -27,19 +27,6 @@ #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: diff --git a/drivers/usb/wusbcore/wa-nep.c b/drivers/usb/wusbcore/wa-nep.c index 3f54299..17d2626 100644 --- a/drivers/usb/wusbcore/wa-nep.c +++ b/drivers/usb/wusbcore/wa-nep.c @@ -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; } diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c index f18e4aa..7369655 100644 --- a/drivers/usb/wusbcore/wa-rpipe.c +++ b/drivers/usb/wusbcore/wa-rpipe.c @@ -60,13 +60,10 @@ #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); diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index c038635..238a96a 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -82,13 +82,10 @@ #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; } diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h index d0c1324..797c245 100644 --- a/drivers/usb/wusbcore/wusbhc.h +++ b/drivers/usb/wusbcore/wusbhc.h @@ -64,6 +64,13 @@ #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 */ diff --git a/drivers/uwb/Makefile b/drivers/uwb/Makefile index 257e690..2f98d08 100644 --- a/drivers/uwb/Makefile +++ b/drivers/uwb/Makefile @@ -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 \ diff --git a/drivers/uwb/address.c b/drivers/uwb/address.c index 1664ae5..ad21b1d7 100644 --- a/drivers/uwb/address.c +++ b/drivers/uwb/address.c @@ -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 index 0000000..c8185e6 --- /dev/null +++ b/drivers/uwb/allocator.c @@ -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; +} diff --git a/drivers/uwb/beacon.c b/drivers/uwb/beacon.c index 46b18ee..36bc315 100644 --- a/drivers/uwb/beacon.c +++ b/drivers/uwb/beacon.c @@ -22,19 +22,16 @@ * * 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; } diff --git a/drivers/uwb/driver.c b/drivers/uwb/driver.c index 521cdeb..da77e41 100644 --- a/drivers/uwb/driver.c +++ b/drivers/uwb/driver.c @@ -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; diff --git a/drivers/uwb/drp-avail.c b/drivers/uwb/drp-avail.c index 3febd855..40a540a 100644 --- a/drivers/uwb/drp-avail.c +++ b/drivers/uwb/drp-avail.c @@ -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); diff --git a/drivers/uwb/drp-ie.c b/drivers/uwb/drp-ie.c index 882724c..2840d7b 100644 --- a/drivers/uwb/drp-ie.c +++ b/drivers/uwb/drp-ie.c @@ -16,13 +16,102 @@ * 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. * @@ -34,16 +123,12 @@ 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) } } } + diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c index c0b1e5e..2b4f940 100644 --- a/drivers/uwb/drp.c +++ b/drivers/uwb/drp.c @@ -23,6 +23,59 @@ #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 * @@ -37,28 +90,32 @@ * * 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); diff --git a/drivers/uwb/est.c b/drivers/uwb/est.c index 5fe566b..328fcc2 100644 --- a/drivers/uwb/est.c +++ b/drivers/uwb/est.c @@ -40,10 +40,8 @@ * 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], diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c index 3d26fa0..559f878 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/uwb/hwa-rc.c @@ -51,16 +51,14 @@ * * */ -#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); diff --git a/drivers/uwb/i1480/dfu/dfu.c b/drivers/uwb/i1480/dfu/dfu.c index 9097b3b..da7b1d0 100644 --- a/drivers/uwb/i1480/dfu/dfu.c +++ b/drivers/uwb/i1480/dfu/dfu.c @@ -34,10 +34,7 @@ #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); diff --git a/drivers/uwb/i1480/dfu/mac.c b/drivers/uwb/i1480/dfu/mac.c index 2e4d8f0..694d0da 100644 --- a/drivers/uwb/i1480/dfu/mac.c +++ b/drivers/uwb/i1480/dfu/mac.c @@ -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; } diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/uwb/i1480/dfu/usb.c index 98eeeff..686795e 100644 --- a/drivers/uwb/i1480/dfu/usb.c +++ b/drivers/uwb/i1480/dfu/usb.c @@ -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> @@ -44,10 +43,6 @@ #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; } diff --git a/drivers/uwb/i1480/i1480u-wlp/lc.c b/drivers/uwb/i1480/i1480u-wlp/lc.c index 737d60c..049c05d 100644 --- a/drivers/uwb/i1480/i1480u-wlp/lc.c +++ b/drivers/uwb/i1480/i1480u-wlp/lc.c @@ -55,10 +55,9 @@ * 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; diff --git a/drivers/uwb/i1480/i1480u-wlp/netdev.c b/drivers/uwb/i1480/i1480u-wlp/netdev.c index 8802ac4..e3873ff 100644 --- a/drivers/uwb/i1480/i1480u-wlp/netdev.c +++ b/drivers/uwb/i1480/i1480u-wlp/netdev.c @@ -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 * diff --git a/drivers/uwb/i1480/i1480u-wlp/rx.c b/drivers/uwb/i1480/i1480u-wlp/rx.c index 9fc0353..34f4cf9 100644 --- a/drivers/uwb/i1480/i1480u-wlp/rx.c +++ b/drivers/uwb/i1480/i1480u-wlp/rx.c @@ -68,11 +68,7 @@ #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. * diff --git a/drivers/uwb/i1480/i1480u-wlp/sysfs.c b/drivers/uwb/i1480/i1480u-wlp/sysfs.c index a1d8ca6..4ffaf54 100644 --- a/drivers/uwb/i1480/i1480u-wlp/sysfs.c +++ b/drivers/uwb/i1480/i1480u-wlp/sysfs.c @@ -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, \ diff --git a/drivers/uwb/i1480/i1480u-wlp/tx.c b/drivers/uwb/i1480/i1480u-wlp/tx.c index 3426bfb..39032cc 100644 --- a/drivers/uwb/i1480/i1480u-wlp/tx.c +++ b/drivers/uwb/i1480/i1480u-wlp/tx.c @@ -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 index 0000000..917e6d7 --- /dev/null +++ b/drivers/uwb/ie-rcv.c @@ -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; +} diff --git a/drivers/uwb/ie.c b/drivers/uwb/ie.c index cf6f3d1..ab97668 100644 --- a/drivers/uwb/ie.c +++ b/drivers/uwb/ie.c @@ -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 struct uwb_ie_hdr *ie; + mutex_lock(&uwb_rc->ies_mutex); - ies_size = le16_to_cpu(uwb_rc->ies->wIELength); - total_size = sizeof(*uwb_rc->ies) + ies_size; - if (total_size + size > uwb_rc->ies_capacity) { - d_printf(4, dev, "Reallocating IE cache from %p capacity %zu " - "to capacity %zu\n", uwb_rc->ies, uwb_rc->ies_capacity, - total_size + size); - new_ies = kzalloc(total_size + size, GFP_KERNEL); - if (new_ies == NULL) { - dev_err(dev, "No memory for adding new IE\n"); - result = -ENOMEM; - goto error_alloc; - } - memcpy(new_ies, uwb_rc->ies, total_size); - uwb_rc->ies_capacity = total_size + size; - kfree(uwb_rc->ies); - uwb_rc->ies = new_ies; - d_printf(4, dev, "New IE cache at %p capacity %zu\n", - uwb_rc->ies, uwb_rc->ies_capacity); + + ptr = (void *)ies; + for (;;) { + ie = uwb_ie_next(&ptr, &size); + if (!ie) + break; + + result = uwb_rc_ie_add_one(uwb_rc, ie); + if (result < 0) + break; } - memcpy((void *)uwb_rc->ies + total_size, ies, size); - uwb_rc->ies->wIELength = cpu_to_le16(ies_size + size); - if (uwb_rc->beaconing != -1) { - result = uwb_rc_set_ie(uwb_rc, uwb_rc->ies); - if (result < 0) { - dev_err(dev, "Cannot set new IE on device: %d\n", - result); - uwb_rc->ies->wIELength = cpu_to_le16(ies_size); + if (result >= 0) { + if (size == 0) { + if (uwb_rc->beaconing != -1) + result = uwb_rc_set_ie(uwb_rc, uwb_rc->ies); } else - result = 0; + result = -EINVAL; } - d_printf(4, dev, "IEs now occupy %hu bytes of %zu capacity at %p\n", - le16_to_cpu(uwb_rc->ies->wIELength), uwb_rc->ies_capacity, - uwb_rc->ies); -error_alloc: + mutex_unlock(&uwb_rc->ies_mutex); + return result; } EXPORT_SYMBOL_GPL(uwb_rc_ie_add); @@ -489,53 +327,52 @@ EXPORT_SYMBOL_GPL(uwb_rc_ie_add); * beacon. We don't reallocate, we just mark the size smaller. */ static -int uwb_rc_ie_cache_rm(struct uwb_rc *uwb_rc, enum uwb_ie to_remove) +void uwb_rc_ie_cache_rm(struct uwb_rc *uwb_rc, enum uwb_ie to_remove) { - struct uwb_ie_hdr *ie_hdr; - size_t new_len = le16_to_cpu(uwb_rc->ies->wIELength); - void *itr = uwb_rc->ies->IEData; - void *top = itr + new_len; - - while (itr < top) { - ie_hdr = itr; - if (ie_hdr->element_id != to_remove) { - itr += sizeof(*ie_hdr) + ie_hdr->length; - } else { - int ie_length; - ie_length = sizeof(*ie_hdr) + ie_hdr->length; - if (top - itr != ie_length) - memmove(itr, itr + ie_length, top - itr + ie_length); - top -= ie_length; - new_len -= ie_length; + struct uwb_ie_hdr *ie; + size_t len = le16_to_cpu(uwb_rc->ies->wIELength); + void *ptr; + size_t size; + + ptr = uwb_rc->ies->IEData; + size = len; + for (;;) { + ie = uwb_ie_next(&ptr, &size); + if (!ie) + break; + if (ie->element_id == to_remove) { + len -= sizeof(struct uwb_ie_hdr) + ie->length; + memmove(ie, ptr, size); + ptr = ie; } } - uwb_rc->ies->wIELength = cpu_to_le16(new_len); - return 0; + uwb_rc->ies->wIELength = cpu_to_le16(len); } /** - * Remove an IE currently being transmitted by device + * uwb_rc_ie_rm - remove an IE from the radio controller's beacon + * @uwb_rc: the radio controller. + * @element_id: the element ID of the IE to remove. * - * @element_id: id of IE to be removed from device's beacon + * Only IEs previously added with uwb_rc_ie_add() may be removed. + * + * Returns 0 on success; or -ve the SET-IE command to the radio + * controller failed. */ int uwb_rc_ie_rm(struct uwb_rc *uwb_rc, enum uwb_ie element_id) { - struct device *dev = &uwb_rc->uwb_dev.dev; - int result; + int result = 0; - if (uwb_rc->ies == NULL) - return -ESHUTDOWN; mutex_lock(&uwb_rc->ies_mutex); - result = uwb_rc_ie_cache_rm(uwb_rc, element_id); - if (result < 0) - dev_err(dev, "Cannot remove IE from cache.\n"); - if (uwb_rc->beaconing != -1) { + + uwb_rc_ie_cache_rm(uwb_rc, element_id); + + if (uwb_rc->beaconing != -1) result = uwb_rc_set_ie(uwb_rc, uwb_rc->ies); - if (result < 0) - dev_err(dev, "Cannot set new IE on device.\n"); - } + mutex_unlock(&uwb_rc->ies_mutex); + return result; } EXPORT_SYMBOL_GPL(uwb_rc_ie_rm); diff --git a/drivers/uwb/lc-dev.c b/drivers/uwb/lc-dev.c index 15f856c..e9fe1bb 100644 --- a/drivers/uwb/lc-dev.c +++ b/drivers/uwb/lc-dev.c @@ -22,7 +22,6 @@ * * FIXME: docs */ - #include <linux/kernel.h> #include <linux/device.h> #include <linux/err.h> @@ -30,10 +29,6 @@ #include <linux/random.h> #include "uwb-internal.h" -#define D_LOCAL 1 -#include <linux/uwb/debug.h> - - /* We initialize addresses to 0xff (invalid, as it is bcast) */ static inline void uwb_dev_addr_init(struct uwb_dev_addr *addr) { @@ -104,12 +99,9 @@ static void uwb_dev_sys_release(struct device *dev) { struct uwb_dev *uwb_dev = to_uwb_dev(dev); - d_fnstart(4, NULL, "(dev %p uwb_dev %p)\n", dev, uwb_dev); uwb_bce_put(uwb_dev->bce); - d_printf(0, &uwb_dev->dev, "uwb_dev %p freed\n", uwb_dev); memset(uwb_dev, 0x69, sizeof(*uwb_dev)); kfree(uwb_dev); - d_fnend(4, NULL, "(dev %p uwb_dev %p) = void\n", dev, uwb_dev); } /* @@ -275,12 +267,8 @@ static struct attribute_group *groups[] = { */ static int __uwb_dev_sys_add(struct uwb_dev *uwb_dev, struct device *parent_dev) { - int result; struct device *dev; - d_fnstart(4, NULL, "(uwb_dev %p parent_dev %p)\n", uwb_dev, parent_dev); - BUG_ON(parent_dev == NULL); - dev = &uwb_dev->dev; /* Device sysfs files are only useful for neighbor devices not local radio controllers. */ @@ -289,18 +277,14 @@ static int __uwb_dev_sys_add(struct uwb_dev *uwb_dev, struct device *parent_dev) dev->parent = parent_dev; dev_set_drvdata(dev, uwb_dev); - result = device_add(dev); - d_fnend(4, NULL, "(uwb_dev %p parent_dev %p) = %d\n", uwb_dev, parent_dev, result); - return result; + return device_add(dev); } static void __uwb_dev_sys_rm(struct uwb_dev *uwb_dev) { - d_fnstart(4, NULL, "(uwb_dev %p)\n", uwb_dev); dev_set_drvdata(&uwb_dev->dev, NULL); device_del(&uwb_dev->dev); - d_fnend(4, NULL, "(uwb_dev %p) = void\n", uwb_dev); } @@ -384,7 +368,6 @@ int __uwb_dev_offair(struct uwb_dev *uwb_dev, struct uwb_rc *rc) struct device *dev = &uwb_dev->dev; char macbuf[UWB_ADDR_STRSIZE], devbuf[UWB_ADDR_STRSIZE]; - d_fnstart(3, NULL, "(dev %p [uwb_dev %p], uwb_rc %p)\n", dev, uwb_dev, rc); uwb_mac_addr_print(macbuf, sizeof(macbuf), &uwb_dev->mac_addr); uwb_dev_addr_print(devbuf, sizeof(devbuf), &uwb_dev->dev_addr); dev_info(dev, "uwb device (mac %s dev %s) disconnected from %s %s\n", @@ -392,8 +375,10 @@ int __uwb_dev_offair(struct uwb_dev *uwb_dev, struct uwb_rc *rc) rc ? rc->uwb_dev.dev.parent->bus->name : "n/a", rc ? dev_name(rc->uwb_dev.dev.parent) : ""); uwb_dev_rm(uwb_dev); + list_del(&uwb_dev->bce->node); + uwb_bce_put(uwb_dev->bce); uwb_dev_put(uwb_dev); /* for the creation in _onair() */ - d_fnend(3, NULL, "(dev %p [uwb_dev %p], uwb_rc %p) = 0\n", dev, uwb_dev, rc); + return 0; } diff --git a/drivers/uwb/lc-rc.c b/drivers/uwb/lc-rc.c index ee5772f..9cf21e6 100644 --- a/drivers/uwb/lc-rc.c +++ b/drivers/uwb/lc-rc.c @@ -36,8 +36,6 @@ #include <linux/etherdevice.h> #include <linux/usb.h> -#define D_LOCAL 1 -#include <linux/uwb/debug.h> #include "uwb-internal.h" static int uwb_rc_index_match(struct device *dev, void *data) @@ -81,9 +79,7 @@ static void uwb_rc_sys_release(struct device *dev) struct uwb_dev *uwb_dev = container_of(dev, struct uwb_dev, dev); struct uwb_rc *rc = container_of(uwb_dev, struct uwb_rc, uwb_dev); - uwb_rc_neh_destroy(rc); uwb_rc_ie_release(rc); - d_printf(1, dev, "freed uwb_rc %p\n", rc); kfree(rc); } @@ -100,6 +96,8 @@ void uwb_rc_init(struct uwb_rc *rc) rc->scan_type = UWB_SCAN_DISABLED; INIT_LIST_HEAD(&rc->notifs_chain.list); mutex_init(&rc->notifs_chain.mutex); + INIT_LIST_HEAD(&rc->uwb_beca.list); + mutex_init(&rc->uwb_beca.mutex); uwb_drp_avail_init(rc); uwb_rc_ie_init(rc); uwb_rsv_init(rc); @@ -191,9 +189,9 @@ static int uwb_rc_setup(struct uwb_rc *rc) int result; struct device *dev = &rc->uwb_dev.dev; - result = uwb_rc_reset(rc); + result = uwb_radio_setup(rc); if (result < 0) { - dev_err(dev, "cannot reset UWB radio: %d\n", result); + dev_err(dev, "cannot setup UWB radio: %d\n", result); goto error; } result = uwb_rc_mac_addr_setup(rc); @@ -250,6 +248,12 @@ int uwb_rc_add(struct uwb_rc *rc, struct device *parent_dev, void *priv) rc->priv = priv; + init_waitqueue_head(&rc->uwbd.wq); + INIT_LIST_HEAD(&rc->uwbd.event_list); + spin_lock_init(&rc->uwbd.event_list_lock); + + uwbd_start(rc); + result = rc->start(rc); if (result < 0) goto error_rc_start; @@ -284,7 +288,7 @@ error_sys_add: error_dev_add: error_rc_setup: rc->stop(rc); - uwbd_flush(rc); + uwbd_stop(rc); error_rc_start: return result; } @@ -306,25 +310,24 @@ void uwb_rc_rm(struct uwb_rc *rc) rc->ready = 0; uwb_dbg_del_rc(rc); - uwb_rsv_cleanup(rc); - uwb_rc_ie_rm(rc, UWB_IDENTIFICATION_IE); - if (rc->beaconing >= 0) - uwb_rc_beacon(rc, -1, 0); - if (rc->scan_type != UWB_SCAN_DISABLED) - uwb_rc_scan(rc, rc->scanning, UWB_SCAN_DISABLED, 0); - uwb_rc_reset(rc); + uwb_rsv_remove_all(rc); + uwb_radio_shutdown(rc); rc->stop(rc); - uwbd_flush(rc); + + uwbd_stop(rc); + uwb_rc_neh_destroy(rc); uwb_dev_lock(&rc->uwb_dev); rc->priv = NULL; rc->cmd = NULL; uwb_dev_unlock(&rc->uwb_dev); - mutex_lock(&uwb_beca.mutex); + mutex_lock(&rc->uwb_beca.mutex); uwb_dev_for_each(rc, uwb_dev_offair_helper, NULL); __uwb_rc_sys_rm(rc); - mutex_unlock(&uwb_beca.mutex); + mutex_unlock(&rc->uwb_beca.mutex); + uwb_rsv_cleanup(rc); + uwb_beca_release(rc); uwb_dev_rm(&rc->uwb_dev); } EXPORT_SYMBOL_GPL(uwb_rc_rm); @@ -468,28 +471,3 @@ void uwb_rc_put(struct uwb_rc *rc) __uwb_rc_put(rc); } EXPORT_SYMBOL_GPL(uwb_rc_put); - -/* - * - * - */ -ssize_t uwb_rc_print_IEs(struct uwb_rc *uwb_rc, char *buf, size_t size) -{ - ssize_t result; - struct uwb_rc_evt_get_ie *ie_info; - struct uwb_buf_ctx ctx; - - result = uwb_rc_get_ie(uwb_rc, &ie_info); - if (result < 0) - goto error_get_ie; - ctx.buf = buf; - ctx.size = size; - ctx.bytes = 0; - uwb_ie_for_each(&uwb_rc->uwb_dev, uwb_ie_dump_hex, &ctx, - ie_info->IEData, result - sizeof(*ie_info)); - result = ctx.bytes; - kfree(ie_info); -error_get_ie: - return result; -} - diff --git a/drivers/uwb/neh.c b/drivers/uwb/neh.c index 9b4eb64..0af8916 100644 --- a/drivers/uwb/neh.c +++ b/drivers/uwb/neh.c @@ -86,8 +86,6 @@ #include <linux/err.h> #include "uwb-internal.h" -#define D_LOCAL 0 -#include <linux/uwb/debug.h> /* * UWB Radio Controller Notification/Event Handle @@ -254,7 +252,6 @@ error_kzalloc: static void __uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) { - del_timer(&neh->timer); __uwb_rc_ctx_put(rc, neh); list_del(&neh->list_node); } @@ -275,6 +272,7 @@ void uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) __uwb_rc_neh_rm(rc, neh); spin_unlock_irqrestore(&rc->neh_lock, flags); + del_timer_sync(&neh->timer); uwb_rc_neh_put(neh); } @@ -349,7 +347,7 @@ struct uwb_rc_neh *uwb_rc_neh_lookup(struct uwb_rc *rc, } -/** +/* * Process notifications coming from the radio control interface * * @rc: UWB Radio Control Interface descriptor @@ -401,23 +399,6 @@ void uwb_rc_notif(struct uwb_rc *rc, struct uwb_rceb *rceb, ssize_t size) uwb_evt->notif.size = size; uwb_evt->notif.rceb = rceb; - switch (le16_to_cpu(rceb->wEvent)) { - /* Trap some vendor specific events - * - * FIXME: move this to handling in ptc-est, where we - * register a NULL event handler for these two guys - * using the Intel IDs. - */ - case 0x0103: - dev_info(dev, "FIXME: DEVICE ADD\n"); - return; - case 0x0104: - dev_info(dev, "FIXME: DEVICE RM\n"); - return; - default: - break; - } - uwbd_event_queue(uwb_evt); } @@ -438,9 +419,10 @@ static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size rceb->bEventContext, size); } else { neh = uwb_rc_neh_lookup(rc, rceb); - if (neh) + if (neh) { + del_timer_sync(&neh->timer); uwb_rc_neh_cb(neh, rceb, size); - else + } else dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n", rceb->bEventType, le16_to_cpu(rceb->wEvent), rceb->bEventContext, size); @@ -495,8 +477,6 @@ void uwb_rc_neh_grok(struct uwb_rc *rc, void *buf, size_t buf_size) size_t size, real_size, event_size; int needtofree; - d_fnstart(3, dev, "(rc %p buf %p %zu buf_size)\n", rc, buf, buf_size); - d_printf(2, dev, "groking event block: %zu bytes\n", buf_size); itr = buf; size = buf_size; while (size > 0) { @@ -544,10 +524,7 @@ void uwb_rc_neh_grok(struct uwb_rc *rc, void *buf, size_t buf_size) itr += real_size; size -= real_size; - d_printf(2, dev, "consumed %zd bytes, %zu left\n", - event_size, size); } - d_fnend(3, dev, "(rc %p buf %p %zu buf_size) = void\n", rc, buf, buf_size); } EXPORT_SYMBOL_GPL(uwb_rc_neh_grok); @@ -562,16 +539,22 @@ EXPORT_SYMBOL_GPL(uwb_rc_neh_grok); */ void uwb_rc_neh_error(struct uwb_rc *rc, int error) { - struct uwb_rc_neh *neh, *next; + struct uwb_rc_neh *neh; unsigned long flags; - BUG_ON(error >= 0); - spin_lock_irqsave(&rc->neh_lock, flags); - list_for_each_entry_safe(neh, next, &rc->neh_list, list_node) { + for (;;) { + spin_lock_irqsave(&rc->neh_lock, flags); + if (list_empty(&rc->neh_list)) { + spin_unlock_irqrestore(&rc->neh_lock, flags); + break; + } + neh = list_first_entry(&rc->neh_list, struct uwb_rc_neh, list_node); __uwb_rc_neh_rm(rc, neh); + spin_unlock_irqrestore(&rc->neh_lock, flags); + + del_timer_sync(&neh->timer); uwb_rc_neh_cb(neh, NULL, error); } - spin_unlock_irqrestore(&rc->neh_lock, flags); } EXPORT_SYMBOL_GPL(uwb_rc_neh_error); @@ -583,10 +566,14 @@ static void uwb_rc_neh_timer(unsigned long arg) unsigned long flags; spin_lock_irqsave(&rc->neh_lock, flags); - __uwb_rc_neh_rm(rc, neh); + if (neh->context) + __uwb_rc_neh_rm(rc, neh); + else + neh = NULL; spin_unlock_irqrestore(&rc->neh_lock, flags); - uwb_rc_neh_cb(neh, NULL, -ETIMEDOUT); + if (neh) + uwb_rc_neh_cb(neh, NULL, -ETIMEDOUT); } /** Initializes the @rc's neh subsystem @@ -605,12 +592,19 @@ void uwb_rc_neh_create(struct uwb_rc *rc) void uwb_rc_neh_destroy(struct uwb_rc *rc) { unsigned long flags; - struct uwb_rc_neh *neh, *next; + struct uwb_rc_neh *neh; - spin_lock_irqsave(&rc->neh_lock, flags); - list_for_each_entry_safe(neh, next, &rc->neh_list, list_node) { + for (;;) { + spin_lock_irqsave(&rc->neh_lock, flags); + if (list_empty(&rc->neh_list)) { + spin_unlock_irqrestore(&rc->neh_lock, flags); + break; + } + neh = list_first_entry(&rc->neh_list, struct uwb_rc_neh, list_node); __uwb_rc_neh_rm(rc, neh); + spin_unlock_irqrestore(&rc->neh_lock, flags); + + del_timer_sync(&neh->timer); uwb_rc_neh_put(neh); } - spin_unlock_irqrestore(&rc->neh_lock, flags); } diff --git a/drivers/uwb/pal.c b/drivers/uwb/pal.c index 1afb38e..99a19c1 100644 --- a/drivers/uwb/pal.c +++ b/drivers/uwb/pal.c @@ -16,6 +16,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/kernel.h> +#include <linux/debugfs.h> #include <linux/uwb.h> #include "uwb-internal.h" @@ -32,13 +33,13 @@ EXPORT_SYMBOL_GPL(uwb_pal_init); /** * uwb_pal_register - register a UWB PAL - * @rc: the radio controller the PAL will be using * @pal: the PAL * * The PAL must be initialized with uwb_pal_init(). */ -int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal) +int uwb_pal_register(struct uwb_pal *pal) { + struct uwb_rc *rc = pal->rc; int ret; if (pal->device) { @@ -54,9 +55,11 @@ int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal) } } - spin_lock(&rc->pal_lock); + pal->debugfs_dir = uwb_dbg_create_pal_dir(pal); + + mutex_lock(&rc->uwb_dev.mutex); list_add(&pal->node, &rc->pals); - spin_unlock(&rc->pal_lock); + mutex_unlock(&rc->uwb_dev.mutex); return 0; } @@ -64,14 +67,19 @@ EXPORT_SYMBOL_GPL(uwb_pal_register); /** * uwb_pal_register - unregister a UWB PAL - * @rc: the radio controller the PAL was using * @pal: the PAL */ -void uwb_pal_unregister(struct uwb_rc *rc, struct uwb_pal *pal) +void uwb_pal_unregister(struct uwb_pal *pal) { - spin_lock(&rc->pal_lock); + struct uwb_rc *rc = pal->rc; + + uwb_radio_stop(pal); + + mutex_lock(&rc->uwb_dev.mutex); list_del(&pal->node); - spin_unlock(&rc->pal_lock); + mutex_unlock(&rc->uwb_dev.mutex); + + debugfs_remove(pal->debugfs_dir); if (pal->device) { sysfs_remove_link(&rc->uwb_dev.dev.kobj, pal->name); @@ -86,6 +94,5 @@ EXPORT_SYMBOL_GPL(uwb_pal_unregister); */ void uwb_rc_pal_init(struct uwb_rc *rc) { - spin_lock_init(&rc->pal_lock); INIT_LIST_HEAD(&rc->pals); } diff --git a/drivers/uwb/radio.c b/drivers/uwb/radio.c new file mode 100644 index 0000000..f0d5549 --- /dev/null +++ b/drivers/uwb/radio.c @@ -0,0 +1,202 @@ +/* + * UWB radio (channel) 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/kernel.h> +#include <linux/uwb.h> + +#include "uwb-internal.h" + + +static int uwb_radio_select_channel(struct uwb_rc *rc) +{ + /* + * Default to channel 9 (BG1, TFC1) unless the user has + * selected a specific channel or there are no active PALs. + */ + if (rc->active_pals == 0) + return -1; + if (rc->beaconing_forced) + return rc->beaconing_forced; + return 9; +} + + +/* + * Notify all active PALs that the channel has changed. + */ +static void uwb_radio_channel_changed(struct uwb_rc *rc, int channel) +{ + struct uwb_pal *pal; + + list_for_each_entry(pal, &rc->pals, node) { + if (pal->channel && channel != pal->channel) { + pal->channel = channel; + if (pal->channel_changed) + pal->channel_changed(pal, pal->channel); + } + } +} + +/* + * Change to a new channel and notify any active PALs of the new + * channel. + * + * When stopping the radio, PALs need to be notified first so they can + * terminate any active reservations. + */ +static int uwb_radio_change_channel(struct uwb_rc *rc, int channel) +{ + int ret = 0; + + if (channel == -1) + uwb_radio_channel_changed(rc, channel); + + if (channel != rc->beaconing) { + if (rc->beaconing != -1 && channel != -1) { + /* + * FIXME: should signal the channel change + * with a Channel Change IE. + */ + ret = uwb_radio_change_channel(rc, -1); + if (ret < 0) + return ret; + } + ret = uwb_rc_beacon(rc, channel, 0); + } + + if (channel != -1) + uwb_radio_channel_changed(rc, rc->beaconing); + + return ret; +} + +/** + * uwb_radio_start - request that the radio be started + * @pal: the PAL making the request. + * + * If the radio is not already active, aa suitable channel is selected + * and beacons are started. + */ +int uwb_radio_start(struct uwb_pal *pal) +{ + struct uwb_rc *rc = pal->rc; + int ret = 0; + + mutex_lock(&rc->uwb_dev.mutex); + + if (!pal->channel) { + pal->channel = -1; + rc->active_pals++; + ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc)); + } + + mutex_unlock(&rc->uwb_dev.mutex); + return ret; +} +EXPORT_SYMBOL_GPL(uwb_radio_start); + +/** + * uwb_radio_stop - request tha the radio be stopped. + * @pal: the PAL making the request. + * + * Stops the radio if no other PAL is making use of it. + */ +void uwb_radio_stop(struct uwb_pal *pal) +{ + struct uwb_rc *rc = pal->rc; + + mutex_lock(&rc->uwb_dev.mutex); + + if (pal->channel) { + rc->active_pals--; + uwb_radio_change_channel(rc, uwb_radio_select_channel(rc)); + pal->channel = 0; + } + + mutex_unlock(&rc->uwb_dev.mutex); +} +EXPORT_SYMBOL_GPL(uwb_radio_stop); + +/* + * uwb_radio_force_channel - force a specific channel to be used + * @rc: the radio controller. + * @channel: the channel to use; -1 to force the radio to stop; 0 to + * use the default channel selection algorithm. + */ +int uwb_radio_force_channel(struct uwb_rc *rc, int channel) +{ + int ret = 0; + + mutex_lock(&rc->uwb_dev.mutex); + + rc->beaconing_forced = channel; + ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc)); + + mutex_unlock(&rc->uwb_dev.mutex); + return ret; +} + +/* + * uwb_radio_setup - setup the radio manager + * @rc: the radio controller. + * + * The radio controller is reset to ensure it's in a known state + * before it's used. + */ +int uwb_radio_setup(struct uwb_rc *rc) +{ + return uwb_rc_reset(rc); +} + +/* + * uwb_radio_reset_state - reset any radio manager state + * @rc: the radio controller. + * + * All internal radio manager state is reset to values corresponding + * to a reset radio controller. + */ +void uwb_radio_reset_state(struct uwb_rc *rc) +{ + struct uwb_pal *pal; + + mutex_lock(&rc->uwb_dev.mutex); + + list_for_each_entry(pal, &rc->pals, node) { + if (pal->channel) { + pal->channel = -1; + if (pal->channel_changed) + pal->channel_changed(pal, -1); + } + } + + rc->beaconing = -1; + rc->scanning = -1; + + mutex_unlock(&rc->uwb_dev.mutex); +} + +/* + * uwb_radio_shutdown - shutdown the radio manager + * @rc: the radio controller. + * + * The radio controller is reset. + */ +void uwb_radio_shutdown(struct uwb_rc *rc) +{ + uwb_radio_reset_state(rc); + uwb_rc_reset(rc); +} diff --git a/drivers/uwb/reset.c b/drivers/uwb/reset.c index 8de856f..70f8050 100644 --- a/drivers/uwb/reset.c +++ b/drivers/uwb/reset.c @@ -32,8 +32,6 @@ #include <linux/err.h> #include "uwb-internal.h" -#define D_LOCAL 0 -#include <linux/uwb/debug.h> /** * Command result codes (WUSB1.0[T8-69]) @@ -323,17 +321,16 @@ int uwbd_msg_handle_reset(struct uwb_event *evt) struct uwb_rc *rc = evt->rc; int ret; - /* Need to prevent the RC hardware module going away while in - the rc->reset() call. */ - if (!try_module_get(rc->owner)) - return 0; - dev_info(&rc->uwb_dev.dev, "resetting radio controller\n"); ret = rc->reset(rc); - if (ret) + if (ret) { dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret); - - module_put(rc->owner); + goto error; + } + return 0; +error: + /* Nothing can be done except try the reset again. */ + uwb_rc_reset_all(rc); return ret; } @@ -360,3 +357,33 @@ void uwb_rc_reset_all(struct uwb_rc *rc) uwbd_event_queue(evt); } EXPORT_SYMBOL_GPL(uwb_rc_reset_all); + +void uwb_rc_pre_reset(struct uwb_rc *rc) +{ + rc->stop(rc); + uwbd_flush(rc); + + uwb_radio_reset_state(rc); + uwb_rsv_remove_all(rc); +} +EXPORT_SYMBOL_GPL(uwb_rc_pre_reset); + +void uwb_rc_post_reset(struct uwb_rc *rc) +{ + int ret; + + ret = rc->start(rc); + if (ret) + goto error; + ret = uwb_rc_mac_addr_set(rc, &rc->uwb_dev.mac_addr); + if (ret) + goto error; + ret = uwb_rc_dev_addr_set(rc, &rc->uwb_dev.dev_addr); + if (ret) + goto error; + return; +error: + /* Nothing can be done except try the reset again. */ + uwb_rc_reset_all(rc); +} +EXPORT_SYMBOL_GPL(uwb_rc_post_reset); diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c index bae16204..ec6eecb 100644 --- a/drivers/uwb/rsv.c +++ b/drivers/uwb/rsv.c @@ -15,23 +15,33 @@ * 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 <linux/random.h> #include "uwb-internal.h" static void uwb_rsv_timer(unsigned long arg); static const char *rsv_states[] = { - [UWB_RSV_STATE_NONE] = "none", - [UWB_RSV_STATE_O_INITIATED] = "initiated", - [UWB_RSV_STATE_O_PENDING] = "pending", - [UWB_RSV_STATE_O_MODIFIED] = "modified", - [UWB_RSV_STATE_O_ESTABLISHED] = "established", - [UWB_RSV_STATE_T_ACCEPTED] = "accepted", - [UWB_RSV_STATE_T_DENIED] = "denied", - [UWB_RSV_STATE_T_PENDING] = "pending", + [UWB_RSV_STATE_NONE] = "none ", + [UWB_RSV_STATE_O_INITIATED] = "o initiated ", + [UWB_RSV_STATE_O_PENDING] = "o pending ", + [UWB_RSV_STATE_O_MODIFIED] = "o modified ", + [UWB_RSV_STATE_O_ESTABLISHED] = "o established ", + [UWB_RSV_STATE_O_TO_BE_MOVED] = "o to be moved ", + [UWB_RSV_STATE_O_MOVE_EXPANDING] = "o move expanding", + [UWB_RSV_STATE_O_MOVE_COMBINING] = "o move combining", + [UWB_RSV_STATE_O_MOVE_REDUCING] = "o move reducing ", + [UWB_RSV_STATE_T_ACCEPTED] = "t accepted ", + [UWB_RSV_STATE_T_CONFLICT] = "t conflict ", + [UWB_RSV_STATE_T_PENDING] = "t pending ", + [UWB_RSV_STATE_T_DENIED] = "t denied ", + [UWB_RSV_STATE_T_RESIZED] = "t resized ", + [UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = "t expanding acc ", + [UWB_RSV_STATE_T_EXPANDING_CONFLICT] = "t expanding conf", + [UWB_RSV_STATE_T_EXPANDING_PENDING] = "t expanding pend", + [UWB_RSV_STATE_T_EXPANDING_DENIED] = "t expanding den ", }; static const char *rsv_types[] = { @@ -42,6 +52,31 @@ static const char *rsv_types[] = { [UWB_DRP_TYPE_PCA] = "pca", }; +bool uwb_rsv_has_two_drp_ies(struct uwb_rsv *rsv) +{ + static const bool has_two_drp_ies[] = { + [UWB_RSV_STATE_O_INITIATED] = false, + [UWB_RSV_STATE_O_PENDING] = false, + [UWB_RSV_STATE_O_MODIFIED] = false, + [UWB_RSV_STATE_O_ESTABLISHED] = false, + [UWB_RSV_STATE_O_TO_BE_MOVED] = false, + [UWB_RSV_STATE_O_MOVE_COMBINING] = false, + [UWB_RSV_STATE_O_MOVE_REDUCING] = false, + [UWB_RSV_STATE_O_MOVE_EXPANDING] = true, + [UWB_RSV_STATE_T_ACCEPTED] = false, + [UWB_RSV_STATE_T_CONFLICT] = false, + [UWB_RSV_STATE_T_PENDING] = false, + [UWB_RSV_STATE_T_DENIED] = false, + [UWB_RSV_STATE_T_RESIZED] = false, + [UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = true, + [UWB_RSV_STATE_T_EXPANDING_CONFLICT] = true, + [UWB_RSV_STATE_T_EXPANDING_PENDING] = true, + [UWB_RSV_STATE_T_EXPANDING_DENIED] = true, + }; + + return has_two_drp_ies[rsv->state]; +} + /** * uwb_rsv_state_str - return a string for a reservation state * @state: the reservation state. @@ -66,7 +101,7 @@ const char *uwb_rsv_type_str(enum uwb_drp_type type) } EXPORT_SYMBOL_GPL(uwb_rsv_type_str); -static void uwb_rsv_dump(struct uwb_rsv *rsv) +void uwb_rsv_dump(char *text, struct uwb_rsv *rsv) { struct device *dev = &rsv->rc->uwb_dev.dev; struct uwb_dev_addr devaddr; @@ -82,6 +117,23 @@ static void uwb_rsv_dump(struct uwb_rsv *rsv) dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state)); } +static void uwb_rsv_release(struct kref *kref) +{ + struct uwb_rsv *rsv = container_of(kref, struct uwb_rsv, kref); + + kfree(rsv); +} + +void uwb_rsv_get(struct uwb_rsv *rsv) +{ + kref_get(&rsv->kref); +} + +void uwb_rsv_put(struct uwb_rsv *rsv) +{ + kref_put(&rsv->kref, uwb_rsv_release); +} + /* * Get a free stream index for a reservation. * @@ -92,6 +144,7 @@ static void uwb_rsv_dump(struct uwb_rsv *rsv) static int uwb_rsv_get_stream(struct uwb_rsv *rsv) { struct uwb_rc *rc = rsv->rc; + struct device *dev = &rc->uwb_dev.dev; unsigned long *streams_bm; int stream; @@ -113,12 +166,15 @@ static int uwb_rsv_get_stream(struct uwb_rsv *rsv) rsv->stream = stream; set_bit(stream, streams_bm); + dev_dbg(dev, "get stream %d\n", rsv->stream); + return 0; } static void uwb_rsv_put_stream(struct uwb_rsv *rsv) { struct uwb_rc *rc = rsv->rc; + struct device *dev = &rc->uwb_dev.dev; unsigned long *streams_bm; switch (rsv->target.type) { @@ -133,86 +189,52 @@ static void uwb_rsv_put_stream(struct uwb_rsv *rsv) } clear_bit(rsv->stream, streams_bm); + + dev_dbg(dev, "put stream %d\n", rsv->stream); } -/* - * Generate a MAS allocation with a single row component. - */ -static void uwb_rsv_gen_alloc_row(struct uwb_mas_bm *mas, - int first_mas, int mas_per_zone, - int zs, int ze) +void uwb_rsv_backoff_win_timer(unsigned long arg) { - struct uwb_mas_bm col; - int z; - - bitmap_zero(mas->bm, UWB_NUM_MAS); - bitmap_zero(col.bm, UWB_NUM_MAS); - bitmap_fill(col.bm, mas_per_zone); - bitmap_shift_left(col.bm, col.bm, first_mas + zs * UWB_MAS_PER_ZONE, UWB_NUM_MAS); - - for (z = zs; z <= ze; z++) { - bitmap_or(mas->bm, mas->bm, col.bm, UWB_NUM_MAS); - bitmap_shift_left(col.bm, col.bm, UWB_MAS_PER_ZONE, UWB_NUM_MAS); + struct uwb_drp_backoff_win *bow = (struct uwb_drp_backoff_win *)arg; + struct uwb_rc *rc = container_of(bow, struct uwb_rc, bow); + struct device *dev = &rc->uwb_dev.dev; + + bow->can_reserve_extra_mases = true; + if (bow->total_expired <= 4) { + bow->total_expired++; + } else { + /* after 4 backoff window has expired we can exit from + * the backoff procedure */ + bow->total_expired = 0; + bow->window = UWB_DRP_BACKOFF_WIN_MIN >> 1; } + dev_dbg(dev, "backoff_win_timer total_expired=%d, n=%d\n: ", bow->total_expired, bow->n); + + /* try to relocate all the "to be moved" relocations */ + uwb_rsv_handle_drp_avail_change(rc); } -/* - * Allocate some MAS for this reservation based on current local - * availability, the reservation parameters (max_mas, min_mas, - * sparsity), and the WiMedia rules for MAS allocations. - * - * Returns -EBUSY is insufficient free MAS are available. - * - * FIXME: to simplify this, only safe reservations with a single row - * component in zones 1 to 15 are tried (zone 0 is skipped to avoid - * problems with the MAS reserved for the BP). - * - * [ECMA-368] section B.2. - */ -static int uwb_rsv_alloc_mas(struct uwb_rsv *rsv) +void uwb_rsv_backoff_win_increment(struct uwb_rc *rc) { - static const int safe_mas_in_row[UWB_NUM_ZONES] = { - 8, 7, 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, - }; - int n, r; - struct uwb_mas_bm mas; - bool found = false; + struct uwb_drp_backoff_win *bow = &rc->bow; + struct device *dev = &rc->uwb_dev.dev; + unsigned timeout_us; - /* - * Search all valid safe allocations until either: too few MAS - * are available; or the smallest allocation with sufficient - * MAS is found. - * - * The top of the zones are preferred, so space for larger - * allocations is available in the bottom of the zone (e.g., a - * 15 MAS allocation should start in row 14 leaving space for - * a 120 MAS allocation at row 0). - */ - for (n = safe_mas_in_row[0]; n >= 1; n--) { - int num_mas; + dev_dbg(dev, "backoff_win_increment: window=%d\n", bow->window); - num_mas = n * (UWB_NUM_ZONES - 1); - if (num_mas < rsv->min_mas) - break; - if (found && num_mas < rsv->max_mas) - break; + bow->can_reserve_extra_mases = false; - for (r = UWB_MAS_PER_ZONE-1; r >= 0; r--) { - if (safe_mas_in_row[r] < n) - continue; - uwb_rsv_gen_alloc_row(&mas, r, n, 1, UWB_NUM_ZONES); - if (uwb_drp_avail_reserve_pending(rsv->rc, &mas) == 0) { - found = true; - break; - } - } - } + if((bow->window << 1) == UWB_DRP_BACKOFF_WIN_MAX) + return; - if (!found) - return -EBUSY; + bow->window <<= 1; + bow->n = random32() & (bow->window - 1); + dev_dbg(dev, "new_window=%d, n=%d\n: ", bow->window, bow->n); - bitmap_copy(rsv->mas.bm, mas.bm, UWB_NUM_MAS); - return 0; + /* reset the timer associated variables */ + timeout_us = bow->n * UWB_SUPERFRAME_LENGTH_US; + bow->total_expired = 0; + mod_timer(&bow->timer, jiffies + usecs_to_jiffies(timeout_us)); } static void uwb_rsv_stroke_timer(struct uwb_rsv *rsv) @@ -225,13 +247,16 @@ static void uwb_rsv_stroke_timer(struct uwb_rsv *rsv) * received. */ if (rsv->is_multicast) { - if (rsv->state == UWB_RSV_STATE_O_INITIATED) + if (rsv->state == UWB_RSV_STATE_O_INITIATED + || rsv->state == UWB_RSV_STATE_O_MOVE_EXPANDING + || rsv->state == UWB_RSV_STATE_O_MOVE_COMBINING + || rsv->state == UWB_RSV_STATE_O_MOVE_REDUCING) sframes = 1; if (rsv->state == UWB_RSV_STATE_O_ESTABLISHED) sframes = 0; + } - rsv->expired = false; if (sframes > 0) { /* * Add an additional 2 superframes to account for the @@ -253,7 +278,7 @@ static void uwb_rsv_state_update(struct uwb_rsv *rsv, rsv->state = new_state; rsv->ie_valid = false; - uwb_rsv_dump(rsv); + uwb_rsv_dump("SU", rsv); uwb_rsv_stroke_timer(rsv); uwb_rsv_sched_update(rsv->rc); @@ -267,10 +292,17 @@ static void uwb_rsv_callback(struct uwb_rsv *rsv) void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state) { + struct uwb_rsv_move *mv = &rsv->mv; + if (rsv->state == new_state) { switch (rsv->state) { case UWB_RSV_STATE_O_ESTABLISHED: + case UWB_RSV_STATE_O_MOVE_EXPANDING: + case UWB_RSV_STATE_O_MOVE_COMBINING: + case UWB_RSV_STATE_O_MOVE_REDUCING: case UWB_RSV_STATE_T_ACCEPTED: + case UWB_RSV_STATE_T_EXPANDING_ACCEPTED: + case UWB_RSV_STATE_T_RESIZED: case UWB_RSV_STATE_NONE: uwb_rsv_stroke_timer(rsv); break; @@ -282,10 +314,10 @@ void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state) return; } + uwb_rsv_dump("SC", rsv); + switch (new_state) { case UWB_RSV_STATE_NONE: - uwb_drp_avail_release(rsv->rc, &rsv->mas); - uwb_rsv_put_stream(rsv); uwb_rsv_state_update(rsv, UWB_RSV_STATE_NONE); uwb_rsv_callback(rsv); break; @@ -295,12 +327,45 @@ void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state) case UWB_RSV_STATE_O_PENDING: uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_PENDING); break; + case UWB_RSV_STATE_O_MODIFIED: + /* in the companion there are the MASes to drop */ + bitmap_andnot(rsv->mas.bm, rsv->mas.bm, mv->companion_mas.bm, UWB_NUM_MAS); + uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_MODIFIED); + break; case UWB_RSV_STATE_O_ESTABLISHED: + if (rsv->state == UWB_RSV_STATE_O_MODIFIED + || rsv->state == UWB_RSV_STATE_O_MOVE_REDUCING) { + uwb_drp_avail_release(rsv->rc, &mv->companion_mas); + rsv->needs_release_companion_mas = false; + } uwb_drp_avail_reserve(rsv->rc, &rsv->mas); uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_ESTABLISHED); uwb_rsv_callback(rsv); break; + case UWB_RSV_STATE_O_MOVE_EXPANDING: + rsv->needs_release_companion_mas = true; + uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_MOVE_EXPANDING); + break; + case UWB_RSV_STATE_O_MOVE_COMBINING: + rsv->needs_release_companion_mas = false; + uwb_drp_avail_reserve(rsv->rc, &mv->companion_mas); + bitmap_or(rsv->mas.bm, rsv->mas.bm, mv->companion_mas.bm, UWB_NUM_MAS); + rsv->mas.safe += mv->companion_mas.safe; + rsv->mas.unsafe += mv->companion_mas.unsafe; + uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_MOVE_COMBINING); + break; + case UWB_RSV_STATE_O_MOVE_REDUCING: + bitmap_andnot(mv->companion_mas.bm, rsv->mas.bm, mv->final_mas.bm, UWB_NUM_MAS); + rsv->needs_release_companion_mas = true; + rsv->mas.safe = mv->final_mas.safe; + rsv->mas.unsafe = mv->final_mas.unsafe; + bitmap_copy(rsv->mas.bm, mv->final_mas.bm, UWB_NUM_MAS); + bitmap_copy(rsv->mas.unsafe_bm, mv->final_mas.unsafe_bm, UWB_NUM_MAS); + uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_MOVE_REDUCING); + break; case UWB_RSV_STATE_T_ACCEPTED: + case UWB_RSV_STATE_T_RESIZED: + rsv->needs_release_companion_mas = false; uwb_drp_avail_reserve(rsv->rc, &rsv->mas); uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_ACCEPTED); uwb_rsv_callback(rsv); @@ -308,12 +373,82 @@ void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state) case UWB_RSV_STATE_T_DENIED: uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_DENIED); break; + case UWB_RSV_STATE_T_CONFLICT: + uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_CONFLICT); + break; + case UWB_RSV_STATE_T_PENDING: + uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_PENDING); + break; + case UWB_RSV_STATE_T_EXPANDING_ACCEPTED: + rsv->needs_release_companion_mas = true; + uwb_drp_avail_reserve(rsv->rc, &mv->companion_mas); + uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_EXPANDING_ACCEPTED); + break; default: dev_err(&rsv->rc->uwb_dev.dev, "unhandled state: %s (%d)\n", uwb_rsv_state_str(new_state), new_state); } } +static void uwb_rsv_handle_timeout_work(struct work_struct *work) +{ + struct uwb_rsv *rsv = container_of(work, struct uwb_rsv, + handle_timeout_work); + struct uwb_rc *rc = rsv->rc; + + mutex_lock(&rc->rsvs_mutex); + + uwb_rsv_dump("TO", rsv); + + switch (rsv->state) { + case UWB_RSV_STATE_O_INITIATED: + if (rsv->is_multicast) { + uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); + goto unlock; + } + break; + case UWB_RSV_STATE_O_MOVE_EXPANDING: + if (rsv->is_multicast) { + uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_COMBINING); + goto unlock; + } + break; + case UWB_RSV_STATE_O_MOVE_COMBINING: + if (rsv->is_multicast) { + uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_REDUCING); + goto unlock; + } + break; + case UWB_RSV_STATE_O_MOVE_REDUCING: + if (rsv->is_multicast) { + uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); + goto unlock; + } + break; + case UWB_RSV_STATE_O_ESTABLISHED: + if (rsv->is_multicast) + goto unlock; + break; + case UWB_RSV_STATE_T_EXPANDING_ACCEPTED: + /* + * The time out could be for the main or of the + * companion DRP, assume it's for the companion and + * drop that first. A further time out is required to + * drop the main. + */ + uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_ACCEPTED); + uwb_drp_avail_release(rsv->rc, &rsv->mv.companion_mas); + goto unlock; + default: + break; + } + + uwb_rsv_remove(rsv); + +unlock: + mutex_unlock(&rc->rsvs_mutex); +} + static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc) { struct uwb_rsv *rsv; @@ -324,23 +459,17 @@ static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc) INIT_LIST_HEAD(&rsv->rc_node); INIT_LIST_HEAD(&rsv->pal_node); + kref_init(&rsv->kref); init_timer(&rsv->timer); rsv->timer.function = uwb_rsv_timer; rsv->timer.data = (unsigned long)rsv; rsv->rc = rc; + INIT_WORK(&rsv->handle_timeout_work, uwb_rsv_handle_timeout_work); return rsv; } -static void uwb_rsv_free(struct uwb_rsv *rsv) -{ - uwb_dev_put(rsv->owner); - if (rsv->target.type == UWB_RSV_TARGET_DEV) - uwb_dev_put(rsv->target.dev); - kfree(rsv); -} - /** * uwb_rsv_create - allocate and initialize a UWB reservation structure * @rc: the radio controller @@ -371,26 +500,36 @@ EXPORT_SYMBOL_GPL(uwb_rsv_create); void uwb_rsv_remove(struct uwb_rsv *rsv) { + uwb_rsv_dump("RM", rsv); + if (rsv->state != UWB_RSV_STATE_NONE) uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); + + if (rsv->needs_release_companion_mas) + uwb_drp_avail_release(rsv->rc, &rsv->mv.companion_mas); + uwb_drp_avail_release(rsv->rc, &rsv->mas); + + if (uwb_rsv_is_owner(rsv)) + uwb_rsv_put_stream(rsv); + del_timer_sync(&rsv->timer); - list_del(&rsv->rc_node); - uwb_rsv_free(rsv); + uwb_dev_put(rsv->owner); + if (rsv->target.type == UWB_RSV_TARGET_DEV) + uwb_dev_put(rsv->target.dev); + + list_del_init(&rsv->rc_node); + uwb_rsv_put(rsv); } /** * uwb_rsv_destroy - free a UWB reservation structure * @rsv: the reservation to free * - * The reservation will be terminated if it is pending or established. + * The reservation must already be terminated. */ void uwb_rsv_destroy(struct uwb_rsv *rsv) { - struct uwb_rc *rc = rsv->rc; - - mutex_lock(&rc->rsvs_mutex); - uwb_rsv_remove(rsv); - mutex_unlock(&rc->rsvs_mutex); + uwb_rsv_put(rsv); } EXPORT_SYMBOL_GPL(uwb_rsv_destroy); @@ -399,7 +538,7 @@ EXPORT_SYMBOL_GPL(uwb_rsv_destroy); * @rsv: the reservation * * The PAL should fill in @rsv's owner, target, type, max_mas, - * min_mas, sparsity and is_multicast fields. If the target is a + * min_mas, max_interval and is_multicast fields. If the target is a * uwb_dev it must be referenced. * * The reservation's callback will be called when the reservation is @@ -408,20 +547,32 @@ EXPORT_SYMBOL_GPL(uwb_rsv_destroy); int uwb_rsv_establish(struct uwb_rsv *rsv) { struct uwb_rc *rc = rsv->rc; + struct uwb_mas_bm available; int ret; mutex_lock(&rc->rsvs_mutex); - ret = uwb_rsv_get_stream(rsv); if (ret) goto out; - ret = uwb_rsv_alloc_mas(rsv); - if (ret) { + rsv->tiebreaker = random32() & 1; + /* get available mas bitmap */ + uwb_drp_available(rc, &available); + + ret = uwb_rsv_find_best_allocation(rsv, &available, &rsv->mas); + if (ret == UWB_RSV_ALLOC_NOT_FOUND) { + ret = -EBUSY; + uwb_rsv_put_stream(rsv); + goto out; + } + + ret = uwb_drp_avail_reserve_pending(rc, &rsv->mas); + if (ret != 0) { uwb_rsv_put_stream(rsv); goto out; } + uwb_rsv_get(rsv); list_add_tail(&rsv->rc_node, &rc->reservations); rsv->owner = &rc->uwb_dev; uwb_dev_get(rsv->owner); @@ -437,16 +588,71 @@ EXPORT_SYMBOL_GPL(uwb_rsv_establish); * @rsv: the reservation to modify * @max_mas: new maximum MAS to reserve * @min_mas: new minimum MAS to reserve - * @sparsity: new sparsity to use + * @max_interval: new max_interval to use * * FIXME: implement this once there are PALs that use it. */ -int uwb_rsv_modify(struct uwb_rsv *rsv, int max_mas, int min_mas, int sparsity) +int uwb_rsv_modify(struct uwb_rsv *rsv, int max_mas, int min_mas, int max_interval) { return -ENOSYS; } EXPORT_SYMBOL_GPL(uwb_rsv_modify); +/* + * move an already established reservation (rc->rsvs_mutex must to be + * taken when tis function is called) + */ +int uwb_rsv_try_move(struct uwb_rsv *rsv, struct uwb_mas_bm *available) +{ + struct uwb_rc *rc = rsv->rc; + struct uwb_drp_backoff_win *bow = &rc->bow; + struct device *dev = &rc->uwb_dev.dev; + struct uwb_rsv_move *mv; + int ret = 0; + + if (bow->can_reserve_extra_mases == false) + return -EBUSY; + + mv = &rsv->mv; + + if (uwb_rsv_find_best_allocation(rsv, available, &mv->final_mas) == UWB_RSV_ALLOC_FOUND) { + + if (!bitmap_equal(rsv->mas.bm, mv->final_mas.bm, UWB_NUM_MAS)) { + /* We want to move the reservation */ + bitmap_andnot(mv->companion_mas.bm, mv->final_mas.bm, rsv->mas.bm, UWB_NUM_MAS); + uwb_drp_avail_reserve_pending(rc, &mv->companion_mas); + uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_EXPANDING); + } + } else { + dev_dbg(dev, "new allocation not found\n"); + } + + return ret; +} + +/* It will try to move every reservation in state O_ESTABLISHED giving + * to the MAS allocator algorithm an availability that is the real one + * plus the allocation already established from the reservation. */ +void uwb_rsv_handle_drp_avail_change(struct uwb_rc *rc) +{ + struct uwb_drp_backoff_win *bow = &rc->bow; + struct uwb_rsv *rsv; + struct uwb_mas_bm mas; + + if (bow->can_reserve_extra_mases == false) + return; + + list_for_each_entry(rsv, &rc->reservations, rc_node) { + if (rsv->state == UWB_RSV_STATE_O_ESTABLISHED || + rsv->state == UWB_RSV_STATE_O_TO_BE_MOVED) { + uwb_drp_available(rc, &mas); + bitmap_or(mas.bm, mas.bm, rsv->mas.bm, UWB_NUM_MAS); + uwb_rsv_try_move(rsv, &mas); + } + } + +} + /** * uwb_rsv_terminate - terminate an established reservation * @rsv: the reservation to terminate @@ -463,7 +669,8 @@ void uwb_rsv_terminate(struct uwb_rsv *rsv) mutex_lock(&rc->rsvs_mutex); - uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); + if (rsv->state != UWB_RSV_STATE_NONE) + uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); mutex_unlock(&rc->rsvs_mutex); } @@ -477,9 +684,14 @@ EXPORT_SYMBOL_GPL(uwb_rsv_terminate); * * Reservation requests from peers are denied unless a PAL accepts it * by calling this function. + * + * The PAL call uwb_rsv_destroy() for all accepted reservations before + * calling uwb_pal_unregister(). */ void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv) { + uwb_rsv_get(rsv); + rsv->callback = cb; rsv->pal_priv = pal_priv; rsv->state = UWB_RSV_STATE_T_ACCEPTED; @@ -530,9 +742,9 @@ static struct uwb_rsv *uwb_rsv_new_target(struct uwb_rc *rc, uwb_dev_get(rsv->owner); rsv->target.type = UWB_RSV_TARGET_DEV; rsv->target.dev = &rc->uwb_dev; + uwb_dev_get(&rc->uwb_dev); rsv->type = uwb_ie_drp_type(drp_ie); rsv->stream = uwb_ie_drp_stream_index(drp_ie); - set_bit(rsv->stream, rsv->owner->streams); uwb_drp_ie_to_bm(&rsv->mas, drp_ie); /* @@ -540,24 +752,46 @@ static struct uwb_rsv *uwb_rsv_new_target(struct uwb_rc *rc, * deny the request. */ rsv->state = UWB_RSV_STATE_T_DENIED; - spin_lock(&rc->pal_lock); + mutex_lock(&rc->uwb_dev.mutex); list_for_each_entry(pal, &rc->pals, node) { if (pal->new_rsv) - pal->new_rsv(rsv); + pal->new_rsv(pal, rsv); if (rsv->state == UWB_RSV_STATE_T_ACCEPTED) break; } - spin_unlock(&rc->pal_lock); + mutex_unlock(&rc->uwb_dev.mutex); list_add_tail(&rsv->rc_node, &rc->reservations); state = rsv->state; rsv->state = UWB_RSV_STATE_NONE; - uwb_rsv_set_state(rsv, state); + + /* FIXME: do something sensible here */ + if (state == UWB_RSV_STATE_T_ACCEPTED + && uwb_drp_avail_reserve_pending(rc, &rsv->mas) == -EBUSY) { + /* FIXME: do something sensible here */ + } else { + uwb_rsv_set_state(rsv, state); + } return rsv; } /** + * uwb_rsv_get_usable_mas - get the bitmap of the usable MAS of a reservations + * @rsv: the reservation. + * @mas: returns the available MAS. + * + * The usable MAS of a reservation may be less than the negotiated MAS + * if alien BPs are present. + */ +void uwb_rsv_get_usable_mas(struct uwb_rsv *rsv, struct uwb_mas_bm *mas) +{ + bitmap_zero(mas->bm, UWB_NUM_MAS); + bitmap_andnot(mas->bm, rsv->mas.bm, rsv->rc->cnflt_alien_bitmap.bm, UWB_NUM_MAS); +} +EXPORT_SYMBOL_GPL(uwb_rsv_get_usable_mas); + +/** * uwb_rsv_find - find a reservation for a received DRP IE. * @rc: the radio controller * @src: source of the DRP IE @@ -596,8 +830,6 @@ static bool uwb_rsv_update_all(struct uwb_rc *rc) bool ie_updated = false; list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { - if (rsv->expired) - uwb_drp_handle_timeout(rsv); if (!rsv->ie_valid) { uwb_drp_ie_update(rsv); ie_updated = true; @@ -607,9 +839,47 @@ static bool uwb_rsv_update_all(struct uwb_rc *rc) return ie_updated; } +void uwb_rsv_queue_update(struct uwb_rc *rc) +{ + unsigned long delay_us = UWB_MAS_LENGTH_US * UWB_MAS_PER_ZONE; + + queue_delayed_work(rc->rsv_workq, &rc->rsv_update_work, usecs_to_jiffies(delay_us)); +} + +/** + * uwb_rsv_sched_update - schedule an update of the DRP IEs + * @rc: the radio controller. + * + * To improve performance and ensure correctness with [ECMA-368] the + * number of SET-DRP-IE commands that are done are limited. + * + * DRP IEs update come from two sources: DRP events from the hardware + * which all occur at the beginning of the superframe ('syncronous' + * events) and reservation establishment/termination requests from + * PALs or timers ('asynchronous' events). + * + * A delayed work ensures that all the synchronous events result in + * one SET-DRP-IE command. + * + * Additional logic (the set_drp_ie_pending and rsv_updated_postponed + * flags) will prevent an asynchrous event starting a SET-DRP-IE + * command if one is currently awaiting a response. + * + * FIXME: this does leave a window where an asynchrous event can delay + * the SET-DRP-IE for a synchronous event by one superframe. + */ void uwb_rsv_sched_update(struct uwb_rc *rc) { - queue_work(rc->rsv_workq, &rc->rsv_update_work); + spin_lock(&rc->rsvs_lock); + if (!delayed_work_pending(&rc->rsv_update_work)) { + if (rc->set_drp_ie_pending > 0) { + rc->set_drp_ie_pending++; + goto unlock; + } + uwb_rsv_queue_update(rc); + } +unlock: + spin_unlock(&rc->rsvs_lock); } /* @@ -618,7 +888,8 @@ void uwb_rsv_sched_update(struct uwb_rc *rc) */ static void uwb_rsv_update_work(struct work_struct *work) { - struct uwb_rc *rc = container_of(work, struct uwb_rc, rsv_update_work); + struct uwb_rc *rc = container_of(work, struct uwb_rc, + rsv_update_work.work); bool ie_updated; mutex_lock(&rc->rsvs_mutex); @@ -630,25 +901,71 @@ static void uwb_rsv_update_work(struct work_struct *work) ie_updated = true; } - if (ie_updated) + if (ie_updated && (rc->set_drp_ie_pending == 0)) uwb_rc_send_all_drp_ie(rc); mutex_unlock(&rc->rsvs_mutex); } +static void uwb_rsv_alien_bp_work(struct work_struct *work) +{ + struct uwb_rc *rc = container_of(work, struct uwb_rc, + rsv_alien_bp_work.work); + struct uwb_rsv *rsv; + + mutex_lock(&rc->rsvs_mutex); + + list_for_each_entry(rsv, &rc->reservations, rc_node) { + if (rsv->type != UWB_DRP_TYPE_ALIEN_BP) { + rsv->callback(rsv); + } + } + + mutex_unlock(&rc->rsvs_mutex); +} + static void uwb_rsv_timer(unsigned long arg) { struct uwb_rsv *rsv = (struct uwb_rsv *)arg; - rsv->expired = true; - uwb_rsv_sched_update(rsv->rc); + queue_work(rsv->rc->rsv_workq, &rsv->handle_timeout_work); +} + +/** + * uwb_rsv_remove_all - remove all reservations + * @rc: the radio controller + * + * A DRP IE update is not done. + */ +void uwb_rsv_remove_all(struct uwb_rc *rc) +{ + struct uwb_rsv *rsv, *t; + + mutex_lock(&rc->rsvs_mutex); + list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { + uwb_rsv_remove(rsv); + } + /* Cancel any postponed update. */ + rc->set_drp_ie_pending = 0; + mutex_unlock(&rc->rsvs_mutex); + + cancel_delayed_work_sync(&rc->rsv_update_work); } void uwb_rsv_init(struct uwb_rc *rc) { INIT_LIST_HEAD(&rc->reservations); + INIT_LIST_HEAD(&rc->cnflt_alien_list); mutex_init(&rc->rsvs_mutex); - INIT_WORK(&rc->rsv_update_work, uwb_rsv_update_work); + spin_lock_init(&rc->rsvs_lock); + INIT_DELAYED_WORK(&rc->rsv_update_work, uwb_rsv_update_work); + INIT_DELAYED_WORK(&rc->rsv_alien_bp_work, uwb_rsv_alien_bp_work); + rc->bow.can_reserve_extra_mases = true; + rc->bow.total_expired = 0; + rc->bow.window = UWB_DRP_BACKOFF_WIN_MIN >> 1; + init_timer(&rc->bow.timer); + rc->bow.timer.function = uwb_rsv_backoff_win_timer; + rc->bow.timer.data = (unsigned long)&rc->bow; bitmap_complement(rc->uwb_dev.streams, rc->uwb_dev.streams, UWB_NUM_STREAMS); } @@ -667,14 +984,6 @@ int uwb_rsv_setup(struct uwb_rc *rc) void uwb_rsv_cleanup(struct uwb_rc *rc) { - struct uwb_rsv *rsv, *t; - - mutex_lock(&rc->rsvs_mutex); - list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { - uwb_rsv_remove(rsv); - } - mutex_unlock(&rc->rsvs_mutex); - - cancel_work_sync(&rc->rsv_update_work); + uwb_rsv_remove_all(rc); destroy_workqueue(rc->rsv_workq); } diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c index 2d8d62d..5ad3616 100644 --- a/drivers/uwb/umc-bus.c +++ b/drivers/uwb/umc-bus.c @@ -11,23 +11,48 @@ #include <linux/uwb/umc.h> #include <linux/pci.h> -static int umc_bus_unbind_helper(struct device *dev, void *data) +static int umc_bus_pre_reset_helper(struct device *dev, void *data) { - struct device *parent = data; + int ret = 0; - if (dev->parent == parent && dev->driver) - device_release_driver(dev); - return 0; + if (dev->driver) { + struct umc_dev *umc = to_umc_dev(dev); + struct umc_driver *umc_drv = to_umc_driver(dev->driver); + + if (umc_drv->pre_reset) + ret = umc_drv->pre_reset(umc); + else + device_release_driver(dev); + } + return ret; +} + +static int umc_bus_post_reset_helper(struct device *dev, void *data) +{ + int ret = 0; + + if (dev->driver) { + struct umc_dev *umc = to_umc_dev(dev); + struct umc_driver *umc_drv = to_umc_driver(dev->driver); + + if (umc_drv->post_reset) + ret = umc_drv->post_reset(umc); + } else + ret = device_attach(dev); + + return ret; } /** * umc_controller_reset - reset the whole UMC controller * @umc: the UMC device for the radio controller. * - * Drivers will be unbound from all UMC devices belonging to the - * controller and then the radio controller will be rebound. The - * radio controller is expected to do a full hardware reset when it is - * probed. + * Drivers or all capabilities of the controller will have their + * pre_reset methods called or be unbound from their device. Then all + * post_reset methods will be called or the drivers will be rebound. + * + * Radio controllers must provide pre_reset and post_reset methods and + * reset the hardware in their start method. * * If this is called while a probe() or remove() is in progress it * will return -EAGAIN and not perform the reset. @@ -35,14 +60,13 @@ static int umc_bus_unbind_helper(struct device *dev, void *data) int umc_controller_reset(struct umc_dev *umc) { struct device *parent = umc->dev.parent; - int ret; + int ret = 0; - if (down_trylock(&parent->sem)) + if(down_trylock(&parent->sem)) return -EAGAIN; - bus_for_each_dev(&umc_bus_type, NULL, parent, umc_bus_unbind_helper); - ret = device_attach(&umc->dev); - if (ret == 1) - ret = 0; + ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper); + if (ret >= 0) + device_for_each_child(parent, parent, umc_bus_post_reset_helper); up(&parent->sem); return ret; @@ -75,10 +99,10 @@ static int umc_bus_rescan_helper(struct device *dev, void *data) if (!dev->driver) ret = device_attach(dev); - return ret < 0 ? ret : 0; + return ret; } -static void umc_bus_rescan(void) +static void umc_bus_rescan(struct device *parent) { int err; @@ -86,7 +110,7 @@ static void umc_bus_rescan(void) * We can't use bus_rescan_devices() here as it deadlocks when * it tries to retake the dev->parent semaphore. */ - err = bus_for_each_dev(&umc_bus_type, NULL, NULL, umc_bus_rescan_helper); + err = device_for_each_child(parent, NULL, umc_bus_rescan_helper); if (err < 0) printk(KERN_WARNING "%s: rescan of bus failed: %d\n", KBUILD_MODNAME, err); @@ -120,7 +144,7 @@ static int umc_device_probe(struct device *dev) if (err) put_device(dev); else - umc_bus_rescan(); + umc_bus_rescan(dev->parent); return err; } diff --git a/drivers/uwb/umc-dev.c b/drivers/uwb/umc-dev.c index aa44e1c..1fc7d82 100644 --- a/drivers/uwb/umc-dev.c +++ b/drivers/uwb/umc-dev.c @@ -7,8 +7,6 @@ */ #include <linux/kernel.h> #include <linux/uwb/umc.h> -#define D_LOCAL 0 -#include <linux/uwb/debug.h> static void umc_device_release(struct device *dev) { @@ -31,8 +29,7 @@ struct umc_dev *umc_device_create(struct device *parent, int n) umc = kzalloc(sizeof(struct umc_dev), GFP_KERNEL); if (umc) { - snprintf(umc->dev.bus_id, sizeof(umc->dev.bus_id), "%s-%d", - parent->bus_id, n); + dev_set_name(&umc->dev, "%s-%d", dev_name(parent), n); umc->dev.parent = parent; umc->dev.bus = &umc_bus_type; umc->dev.release = umc_device_release; @@ -54,8 +51,6 @@ int umc_device_register(struct umc_dev *umc) { int err; - d_fnstart(3, &umc->dev, "(umc_dev %p)\n", umc); - err = request_resource(umc->resource.parent, &umc->resource); if (err < 0) { dev_err(&umc->dev, "can't allocate resource range " @@ -69,13 +64,11 @@ int umc_device_register(struct umc_dev *umc) err = device_register(&umc->dev); if (err < 0) goto error_device_register; - d_fnend(3, &umc->dev, "(umc_dev %p) = 0\n", umc); return 0; error_device_register: release_resource(&umc->resource); error_request_resource: - d_fnend(3, &umc->dev, "(umc_dev %p) = %d\n", umc, err); return err; } EXPORT_SYMBOL_GPL(umc_device_register); @@ -95,10 +88,8 @@ void umc_device_unregister(struct umc_dev *umc) if (!umc) return; dev = get_device(&umc->dev); - d_fnstart(3, dev, "(umc_dev %p)\n", umc); device_unregister(&umc->dev); release_resource(&umc->resource); - d_fnend(3, dev, "(umc_dev %p) = void\n", umc); put_device(dev); } EXPORT_SYMBOL_GPL(umc_device_unregister); diff --git a/drivers/uwb/uwb-debug.c b/drivers/uwb/uwb-debug.c index 6d232c3..4a42993 100644 --- a/drivers/uwb/uwb-debug.c +++ b/drivers/uwb/uwb-debug.c @@ -4,6 +4,7 @@ * * Copyright (C) 2005-2006 Intel Corporation * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> + * 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 @@ -33,31 +34,9 @@ #include <linux/seq_file.h> #include <linux/uwb/debug-cmd.h> -#define D_LOCAL 0 -#include <linux/uwb/debug.h> #include "uwb-internal.h" -void dump_bytes(struct device *dev, const void *_buf, size_t rsize) -{ - const char *buf = _buf; - char line[32]; - size_t offset = 0; - int cnt, cnt2; - for (cnt = 0; cnt < rsize; cnt += 8) { - size_t rtop = rsize - cnt < 8 ? rsize - cnt : 8; - for (offset = cnt2 = 0; cnt2 < rtop; cnt2++) { - offset += scnprintf(line + offset, sizeof(line) - offset, - "%02x ", buf[cnt + cnt2] & 0xff); - } - if (dev) - dev_info(dev, "%s\n", line); - else - printk(KERN_INFO "%s\n", line); - } -} -EXPORT_SYMBOL_GPL(dump_bytes); - /* * Debug interface * @@ -84,26 +63,23 @@ struct uwb_dbg { struct dentry *reservations_f; struct dentry *accept_f; struct dentry *drp_avail_f; + spinlock_t list_lock; }; static struct dentry *root_dir; static void uwb_dbg_rsv_cb(struct uwb_rsv *rsv) { - struct uwb_rc *rc = rsv->rc; - struct device *dev = &rc->uwb_dev.dev; - struct uwb_dev_addr devaddr; - char owner[UWB_ADDR_STRSIZE], target[UWB_ADDR_STRSIZE]; - - uwb_dev_addr_print(owner, sizeof(owner), &rsv->owner->dev_addr); - if (rsv->target.type == UWB_RSV_TARGET_DEV) - devaddr = rsv->target.dev->dev_addr; - else - devaddr = rsv->target.devaddr; - uwb_dev_addr_print(target, sizeof(target), &devaddr); + struct uwb_dbg *dbg = rsv->pal_priv; - dev_dbg(dev, "debug: rsv %s -> %s: %s\n", - owner, target, uwb_rsv_state_str(rsv->state)); + uwb_rsv_dump("debug", rsv); + + if (rsv->state == UWB_RSV_STATE_NONE) { + spin_lock(&dbg->list_lock); + list_del(&rsv->pal_node); + spin_unlock(&dbg->list_lock); + uwb_rsv_destroy(rsv); + } } static int cmd_rsv_establish(struct uwb_rc *rc, @@ -119,26 +95,27 @@ static int cmd_rsv_establish(struct uwb_rc *rc, if (target == NULL) return -ENODEV; - rsv = uwb_rsv_create(rc, uwb_dbg_rsv_cb, NULL); + rsv = uwb_rsv_create(rc, uwb_dbg_rsv_cb, rc->dbg); if (rsv == NULL) { uwb_dev_put(target); return -ENOMEM; } - rsv->owner = &rc->uwb_dev; - rsv->target.type = UWB_RSV_TARGET_DEV; - rsv->target.dev = target; - rsv->type = cmd->type; - rsv->max_mas = cmd->max_mas; - rsv->min_mas = cmd->min_mas; - rsv->sparsity = cmd->sparsity; + rsv->target.type = UWB_RSV_TARGET_DEV; + rsv->target.dev = target; + rsv->type = cmd->type; + rsv->max_mas = cmd->max_mas; + rsv->min_mas = cmd->min_mas; + rsv->max_interval = cmd->max_interval; ret = uwb_rsv_establish(rsv); if (ret) uwb_rsv_destroy(rsv); - else + else { + spin_lock(&(rc->dbg)->list_lock); list_add_tail(&rsv->pal_node, &rc->dbg->rsvs); - + spin_unlock(&(rc->dbg)->list_lock); + } return ret; } @@ -148,21 +125,40 @@ static int cmd_rsv_terminate(struct uwb_rc *rc, struct uwb_rsv *rsv, *found = NULL; int i = 0; + spin_lock(&(rc->dbg)->list_lock); + list_for_each_entry(rsv, &rc->dbg->rsvs, pal_node) { if (i == cmd->index) { found = rsv; + uwb_rsv_get(found); break; } + i++; } + + spin_unlock(&(rc->dbg)->list_lock); + if (!found) return -EINVAL; - list_del(&found->pal_node); uwb_rsv_terminate(found); + uwb_rsv_put(found); return 0; } +static int cmd_ie_add(struct uwb_rc *rc, struct uwb_dbg_cmd_ie *ie_to_add) +{ + return uwb_rc_ie_add(rc, + (const struct uwb_ie_hdr *) ie_to_add->data, + ie_to_add->len); +} + +static int cmd_ie_rm(struct uwb_rc *rc, struct uwb_dbg_cmd_ie *ie_to_rm) +{ + return uwb_rc_ie_rm(rc, ie_to_rm->data[0]); +} + static int command_open(struct inode *inode, struct file *file) { file->private_data = inode->i_private; @@ -175,8 +171,8 @@ static ssize_t command_write(struct file *file, const char __user *buf, { struct uwb_rc *rc = file->private_data; struct uwb_dbg_cmd cmd; - int ret; - + int ret = 0; + if (len != sizeof(struct uwb_dbg_cmd)) return -EINVAL; @@ -190,6 +186,18 @@ static ssize_t command_write(struct file *file, const char __user *buf, case UWB_DBG_CMD_RSV_TERMINATE: ret = cmd_rsv_terminate(rc, &cmd.rsv_terminate); break; + case UWB_DBG_CMD_IE_ADD: + ret = cmd_ie_add(rc, &cmd.ie_add); + break; + case UWB_DBG_CMD_IE_RM: + ret = cmd_ie_rm(rc, &cmd.ie_rm); + break; + case UWB_DBG_CMD_RADIO_START: + ret = uwb_radio_start(&rc->dbg->pal); + break; + case UWB_DBG_CMD_RADIO_STOP: + uwb_radio_stop(&rc->dbg->pal); + break; default: return -EINVAL; } @@ -283,12 +291,26 @@ static struct file_operations drp_avail_fops = { .owner = THIS_MODULE, }; -static void uwb_dbg_new_rsv(struct uwb_rsv *rsv) +static void uwb_dbg_channel_changed(struct uwb_pal *pal, int channel) +{ + struct device *dev = &pal->rc->uwb_dev.dev; + + if (channel > 0) + dev_info(dev, "debug: channel %d started\n", channel); + else + dev_info(dev, "debug: channel stopped\n"); +} + +static void uwb_dbg_new_rsv(struct uwb_pal *pal, struct uwb_rsv *rsv) { - struct uwb_rc *rc = rsv->rc; + struct uwb_dbg *dbg = container_of(pal, struct uwb_dbg, pal); - if (rc->dbg->accept) - uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, NULL); + if (dbg->accept) { + spin_lock(&dbg->list_lock); + list_add_tail(&rsv->pal_node, &dbg->rsvs); + spin_unlock(&dbg->list_lock); + uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, dbg); + } } /** @@ -302,10 +324,14 @@ void uwb_dbg_add_rc(struct uwb_rc *rc) return; INIT_LIST_HEAD(&rc->dbg->rsvs); + spin_lock_init(&(rc->dbg)->list_lock); uwb_pal_init(&rc->dbg->pal); + rc->dbg->pal.rc = rc; + rc->dbg->pal.channel_changed = uwb_dbg_channel_changed; rc->dbg->pal.new_rsv = uwb_dbg_new_rsv; - uwb_pal_register(rc, &rc->dbg->pal); + uwb_pal_register(&rc->dbg->pal); + if (root_dir) { rc->dbg->root_d = debugfs_create_dir(dev_name(&rc->uwb_dev.dev), root_dir); @@ -325,7 +351,7 @@ void uwb_dbg_add_rc(struct uwb_rc *rc) } /** - * uwb_dbg_add_rc - remove a radio controller's debug interface + * uwb_dbg_del_rc - remove a radio controller's debug interface * @rc: the radio controller */ void uwb_dbg_del_rc(struct uwb_rc *rc) @@ -336,10 +362,10 @@ void uwb_dbg_del_rc(struct uwb_rc *rc) return; list_for_each_entry_safe(rsv, t, &rc->dbg->rsvs, pal_node) { - uwb_rsv_destroy(rsv); + uwb_rsv_terminate(rsv); } - uwb_pal_unregister(rc, &rc->dbg->pal); + uwb_pal_unregister(&rc->dbg->pal); if (root_dir) { debugfs_remove(rc->dbg->drp_avail_f); @@ -365,3 +391,16 @@ void uwb_dbg_exit(void) { debugfs_remove(root_dir); } + +/** + * uwb_dbg_create_pal_dir - create a debugfs directory for a PAL + * @pal: The PAL. + */ +struct dentry *uwb_dbg_create_pal_dir(struct uwb_pal *pal) +{ + struct uwb_rc *rc = pal->rc; + + if (root_dir && rc->dbg && rc->dbg->root_d && pal->name) + return debugfs_create_dir(pal->name, rc->dbg->root_d); + return NULL; +} diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h index 2ad307d..d5bcfc1 100644 --- a/drivers/uwb/uwb-internal.h +++ b/drivers/uwb/uwb-internal.h @@ -66,14 +66,14 @@ extern int uwb_rc_scan(struct uwb_rc *rc, unsigned channel, enum uwb_scan_type type, unsigned bpst_offset); extern int uwb_rc_send_all_drp_ie(struct uwb_rc *rc); -extern ssize_t uwb_rc_print_IEs(struct uwb_rc *rc, char *, size_t); -extern void uwb_rc_ie_init(struct uwb_rc *); -extern void uwb_rc_ie_init(struct uwb_rc *); -extern ssize_t uwb_rc_ie_setup(struct uwb_rc *); -extern void uwb_rc_ie_release(struct uwb_rc *); -extern int uwb_rc_ie_add(struct uwb_rc *, - const struct uwb_ie_hdr *, size_t); -extern int uwb_rc_ie_rm(struct uwb_rc *, enum uwb_ie); + +void uwb_rc_ie_init(struct uwb_rc *); +int uwb_rc_ie_setup(struct uwb_rc *); +void uwb_rc_ie_release(struct uwb_rc *); +int uwb_ie_dump_hex(const struct uwb_ie_hdr *ies, size_t len, + char *buf, size_t size); +int uwb_rc_set_ie(struct uwb_rc *, struct uwb_rc_cmd_set_ie *); + extern const char *uwb_rc_strerror(unsigned code); @@ -92,6 +92,12 @@ extern const char *uwb_rc_strerror(unsigned code); struct uwb_rc_neh; +extern int uwb_rc_cmd_async(struct uwb_rc *rc, const char *cmd_name, + struct uwb_rccb *cmd, size_t cmd_size, + u8 expected_type, u16 expected_event, + uwb_rc_cmd_cb_f cb, void *arg); + + void uwb_rc_neh_create(struct uwb_rc *rc); void uwb_rc_neh_destroy(struct uwb_rc *rc); @@ -106,7 +112,69 @@ void uwb_rc_neh_put(struct uwb_rc_neh *neh); extern int uwb_est_create(void); extern void uwb_est_destroy(void); +/* + * UWB conflicting alien reservations + */ +struct uwb_cnflt_alien { + struct uwb_rc *rc; + struct list_head rc_node; + struct uwb_mas_bm mas; + struct timer_list timer; + struct work_struct cnflt_update_work; +}; + +enum uwb_uwb_rsv_alloc_result { + UWB_RSV_ALLOC_FOUND = 0, + UWB_RSV_ALLOC_NOT_FOUND, +}; + +enum uwb_rsv_mas_status { + UWB_RSV_MAS_NOT_AVAIL = 1, + UWB_RSV_MAS_SAFE, + UWB_RSV_MAS_UNSAFE, +}; + +struct uwb_rsv_col_set_info { + unsigned char start_col; + unsigned char interval; + unsigned char safe_mas_per_col; + unsigned char unsafe_mas_per_col; +}; + +struct uwb_rsv_col_info { + unsigned char max_avail_safe; + unsigned char max_avail_unsafe; + unsigned char highest_mas[UWB_MAS_PER_ZONE]; + struct uwb_rsv_col_set_info csi; +}; + +struct uwb_rsv_row_info { + unsigned char avail[UWB_MAS_PER_ZONE]; + unsigned char free_rows; + unsigned char used_rows; +}; + +/* + * UWB find allocation + */ +struct uwb_rsv_alloc_info { + unsigned char bm[UWB_MAS_PER_ZONE * UWB_NUM_ZONES]; + struct uwb_rsv_col_info ci[UWB_NUM_ZONES]; + struct uwb_rsv_row_info ri; + struct uwb_mas_bm *not_available; + struct uwb_mas_bm *result; + int min_mas; + int max_mas; + int max_interval; + int total_allocated_mases; + int safe_allocated_mases; + int unsafe_allocated_mases; + int interval; +}; +int uwb_rsv_find_best_allocation(struct uwb_rsv *rsv, struct uwb_mas_bm *available, + struct uwb_mas_bm *result); +void uwb_rsv_handle_drp_avail_change(struct uwb_rc *rc); /* * UWB Events & management daemon */ @@ -160,13 +228,14 @@ struct uwb_event { }; }; -extern void uwbd_start(void); -extern void uwbd_stop(void); +extern void uwbd_start(struct uwb_rc *rc); +extern void uwbd_stop(struct uwb_rc *rc); extern struct uwb_event *uwb_event_alloc(size_t, gfp_t gfp_mask); extern void uwbd_event_queue(struct uwb_event *); void uwbd_flush(struct uwb_rc *rc); /* UWB event handlers */ +extern int uwbd_evt_handle_rc_ie_rcv(struct uwb_event *); extern int uwbd_evt_handle_rc_beacon(struct uwb_event *); extern int uwbd_evt_handle_rc_beacon_size(struct uwb_event *); extern int uwbd_evt_handle_rc_bpoie_change(struct uwb_event *); @@ -193,15 +262,6 @@ int uwbd_evt_handle_rc_dev_addr_conflict(struct uwb_event *evt); extern unsigned long beacon_timeout_ms; -/** Beacon cache list */ -struct uwb_beca { - struct list_head list; - size_t entries; - struct mutex mutex; -}; - -extern struct uwb_beca uwb_beca; - /** * Beacon cache entry * @@ -228,9 +288,6 @@ struct uwb_beca_e { struct uwb_beacon_frame; extern ssize_t uwb_bce_print_IEs(struct uwb_dev *, struct uwb_beca_e *, char *, size_t); -extern struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *, - struct uwb_beacon_frame *, - unsigned long); extern void uwb_bce_kfree(struct kref *_bce); static inline void uwb_bce_get(struct uwb_beca_e *bce) @@ -241,14 +298,19 @@ static inline void uwb_bce_put(struct uwb_beca_e *bce) { kref_put(&bce->refcnt, uwb_bce_kfree); } -extern void uwb_beca_purge(void); -extern void uwb_beca_release(void); +extern void uwb_beca_purge(struct uwb_rc *rc); +extern void uwb_beca_release(struct uwb_rc *rc); struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, const struct uwb_dev_addr *devaddr); struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc, const struct uwb_mac_addr *macaddr); +int uwb_radio_setup(struct uwb_rc *rc); +void uwb_radio_reset_state(struct uwb_rc *rc); +void uwb_radio_shutdown(struct uwb_rc *rc); +int uwb_radio_force_channel(struct uwb_rc *rc, int channel); + /* -- UWB Sysfs representation */ extern struct class uwb_rc_class; extern struct device_attribute dev_attr_mac_address; @@ -259,18 +321,29 @@ extern struct device_attribute dev_attr_scan; void uwb_rsv_init(struct uwb_rc *rc); int uwb_rsv_setup(struct uwb_rc *rc); void uwb_rsv_cleanup(struct uwb_rc *rc); +void uwb_rsv_remove_all(struct uwb_rc *rc); +void uwb_rsv_get(struct uwb_rsv *rsv); +void uwb_rsv_put(struct uwb_rsv *rsv); +bool uwb_rsv_has_two_drp_ies(struct uwb_rsv *rsv); +void uwb_rsv_dump(char *text, struct uwb_rsv *rsv); +int uwb_rsv_try_move(struct uwb_rsv *rsv, struct uwb_mas_bm *available); +void uwb_rsv_backoff_win_timer(unsigned long arg); +void uwb_rsv_backoff_win_increment(struct uwb_rc *rc); +int uwb_rsv_status(struct uwb_rsv *rsv); +int uwb_rsv_companion_status(struct uwb_rsv *rsv); void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state); void uwb_rsv_remove(struct uwb_rsv *rsv); struct uwb_rsv *uwb_rsv_find(struct uwb_rc *rc, struct uwb_dev *src, struct uwb_ie_drp *drp_ie); void uwb_rsv_sched_update(struct uwb_rc *rc); +void uwb_rsv_queue_update(struct uwb_rc *rc); -void uwb_drp_handle_timeout(struct uwb_rsv *rsv); int uwb_drp_ie_update(struct uwb_rsv *rsv); void uwb_drp_ie_to_bm(struct uwb_mas_bm *bm, const struct uwb_ie_drp *drp_ie); void uwb_drp_avail_init(struct uwb_rc *rc); +void uwb_drp_available(struct uwb_rc *rc, struct uwb_mas_bm *avail); int uwb_drp_avail_reserve_pending(struct uwb_rc *rc, struct uwb_mas_bm *mas); void uwb_drp_avail_reserve(struct uwb_rc *rc, struct uwb_mas_bm *mas); void uwb_drp_avail_release(struct uwb_rc *rc, struct uwb_mas_bm *mas); @@ -289,8 +362,7 @@ void uwb_dbg_init(void); void uwb_dbg_exit(void); void uwb_dbg_add_rc(struct uwb_rc *rc); void uwb_dbg_del_rc(struct uwb_rc *rc); - -/* Workarounds for version specific stuff */ +struct dentry *uwb_dbg_create_pal_dir(struct uwb_pal *pal); static inline void uwb_dev_lock(struct uwb_dev *uwb_dev) { diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c index 7890841..57bd6bf 100644 --- a/drivers/uwb/uwbd.c +++ b/drivers/uwb/uwbd.c @@ -68,17 +68,13 @@ * * Handler functions are called normally uwbd_evt_handle_*(). */ - #include <linux/kthread.h> #include <linux/module.h> #include <linux/freezer.h> -#include "uwb-internal.h" - -#define D_LOCAL 1 -#include <linux/uwb/debug.h> +#include "uwb-internal.h" -/** +/* * UWBD Event handler function signature * * Return !0 if the event needs not to be freed (ie the handler @@ -101,9 +97,12 @@ struct uwbd_event { const char *name; }; -/** Table of handlers for and properties of the UWBD Radio Control Events */ -static -struct uwbd_event uwbd_events[] = { +/* Table of handlers for and properties of the UWBD Radio Control Events */ +static struct uwbd_event uwbd_urc_events[] = { + [UWB_RC_EVT_IE_RCV] = { + .handler = uwbd_evt_handle_rc_ie_rcv, + .name = "IE_RECEIVED" + }, [UWB_RC_EVT_BEACON] = { .handler = uwbd_evt_handle_rc_beacon, .name = "BEACON_RECEIVED" @@ -142,23 +141,15 @@ struct uwbd_evt_type_handler { size_t size; }; -#define UWBD_EVT_TYPE_HANDLER(n,a) { \ - .name = (n), \ - .uwbd_events = (a), \ - .size = sizeof(a)/sizeof((a)[0]) \ -} - - -/** Table of handlers for each UWBD Event type. */ -static -struct uwbd_evt_type_handler uwbd_evt_type_handlers[] = { - [UWB_RC_CET_GENERAL] = UWBD_EVT_TYPE_HANDLER("RC", uwbd_events) +/* Table of handlers for each UWBD Event type. */ +static struct uwbd_evt_type_handler uwbd_urc_evt_type_handlers[] = { + [UWB_RC_CET_GENERAL] = { + .name = "URC", + .uwbd_events = uwbd_urc_events, + .size = ARRAY_SIZE(uwbd_urc_events), + }, }; -static const -size_t uwbd_evt_type_handlers_len = - sizeof(uwbd_evt_type_handlers) / sizeof(uwbd_evt_type_handlers[0]); - static const struct uwbd_event uwbd_message_handlers[] = { [UWB_EVT_MSG_RESET] = { .handler = uwbd_msg_handle_reset, @@ -166,9 +157,7 @@ static const struct uwbd_event uwbd_message_handlers[] = { }, }; -static DEFINE_MUTEX(uwbd_event_mutex); - -/** +/* * Handle an URC event passed to the UWB Daemon * * @evt: the event to handle @@ -188,6 +177,7 @@ static DEFINE_MUTEX(uwbd_event_mutex); static int uwbd_event_handle_urc(struct uwb_event *evt) { + int result = -EINVAL; struct uwbd_evt_type_handler *type_table; uwbd_evt_handler_f handler; u8 type, context; @@ -197,26 +187,24 @@ int uwbd_event_handle_urc(struct uwb_event *evt) event = le16_to_cpu(evt->notif.rceb->wEvent); context = evt->notif.rceb->bEventContext; - if (type > uwbd_evt_type_handlers_len) { - printk(KERN_ERR "UWBD: event type %u: unknown (too high)\n", type); - return -EINVAL; - } - type_table = &uwbd_evt_type_handlers[type]; - if (type_table->uwbd_events == NULL) { - printk(KERN_ERR "UWBD: event type %u: unknown\n", type); - return -EINVAL; - } - if (event > type_table->size) { - printk(KERN_ERR "UWBD: event %s[%u]: unknown (too high)\n", - type_table->name, event); - return -EINVAL; - } + if (type > ARRAY_SIZE(uwbd_urc_evt_type_handlers)) + goto out; + type_table = &uwbd_urc_evt_type_handlers[type]; + if (type_table->uwbd_events == NULL) + goto out; + if (event > type_table->size) + goto out; handler = type_table->uwbd_events[event].handler; - if (handler == NULL) { - printk(KERN_ERR "UWBD: event %s[%u]: unknown\n", type_table->name, event); - return -EINVAL; - } - return (*handler)(evt); + if (handler == NULL) + goto out; + + result = (*handler)(evt); +out: + if (result < 0) + dev_err(&evt->rc->uwb_dev.dev, + "UWBD: event 0x%02x/%04x/%02x, handling failed: %d\n", + type, event, context, result); + return result; } static void uwbd_event_handle_message(struct uwb_event *evt) @@ -231,19 +219,10 @@ static void uwbd_event_handle_message(struct uwb_event *evt) return; } - /* If this is a reset event we need to drop the - * uwbd_event_mutex or it deadlocks when the reset handler - * attempts to flush the uwbd events. */ - if (evt->message == UWB_EVT_MSG_RESET) - mutex_unlock(&uwbd_event_mutex); - result = uwbd_message_handlers[evt->message].handler(evt); if (result < 0) dev_err(&rc->uwb_dev.dev, "UWBD: '%s' message failed: %d\n", uwbd_message_handlers[evt->message].name, result); - - if (evt->message == UWB_EVT_MSG_RESET) - mutex_lock(&uwbd_event_mutex); } static void uwbd_event_handle(struct uwb_event *evt) @@ -271,20 +250,6 @@ static void uwbd_event_handle(struct uwb_event *evt) __uwb_rc_put(rc); /* for the __uwb_rc_get() in uwb_rc_notif_cb() */ } -/* The UWB Daemon */ - - -/** Daemon's PID: used to decide if we can queue or not */ -static int uwbd_pid; -/** Daemon's task struct for managing the kthread */ -static struct task_struct *uwbd_task; -/** Daemon's waitqueue for waiting for new events */ -static DECLARE_WAIT_QUEUE_HEAD(uwbd_wq); -/** Daemon's list of events; we queue/dequeue here */ -static struct list_head uwbd_event_list = LIST_HEAD_INIT(uwbd_event_list); -/** Daemon's list lock to protect concurent access */ -static DEFINE_SPINLOCK(uwbd_event_list_lock); - /** * UWB Daemon @@ -298,65 +263,58 @@ static DEFINE_SPINLOCK(uwbd_event_list_lock); * FIXME: should change so we don't have a 1HZ timer all the time, but * only if there are devices. */ -static int uwbd(void *unused) +static int uwbd(void *param) { + struct uwb_rc *rc = param; unsigned long flags; - struct list_head list = LIST_HEAD_INIT(list); - struct uwb_event *evt, *nxt; + struct uwb_event *evt; int should_stop = 0; + while (1) { wait_event_interruptible_timeout( - uwbd_wq, - !list_empty(&uwbd_event_list) + rc->uwbd.wq, + !list_empty(&rc->uwbd.event_list) || (should_stop = kthread_should_stop()), HZ); if (should_stop) break; try_to_freeze(); - mutex_lock(&uwbd_event_mutex); - spin_lock_irqsave(&uwbd_event_list_lock, flags); - list_splice_init(&uwbd_event_list, &list); - spin_unlock_irqrestore(&uwbd_event_list_lock, flags); - list_for_each_entry_safe(evt, nxt, &list, list_node) { + spin_lock_irqsave(&rc->uwbd.event_list_lock, flags); + if (!list_empty(&rc->uwbd.event_list)) { + evt = list_first_entry(&rc->uwbd.event_list, struct uwb_event, list_node); list_del(&evt->list_node); + } else + evt = NULL; + spin_unlock_irqrestore(&rc->uwbd.event_list_lock, flags); + + if (evt) { uwbd_event_handle(evt); kfree(evt); } - mutex_unlock(&uwbd_event_mutex); - uwb_beca_purge(); /* Purge devices that left */ + uwb_beca_purge(rc); /* Purge devices that left */ } return 0; } /** Start the UWB daemon */ -void uwbd_start(void) +void uwbd_start(struct uwb_rc *rc) { - uwbd_task = kthread_run(uwbd, NULL, "uwbd"); - if (uwbd_task == NULL) + rc->uwbd.task = kthread_run(uwbd, rc, "uwbd"); + if (rc->uwbd.task == NULL) printk(KERN_ERR "UWB: Cannot start management daemon; " "UWB won't work\n"); else - uwbd_pid = uwbd_task->pid; + rc->uwbd.pid = rc->uwbd.task->pid; } /* Stop the UWB daemon and free any unprocessed events */ -void uwbd_stop(void) +void uwbd_stop(struct uwb_rc *rc) { - unsigned long flags; - struct uwb_event *evt, *nxt; - kthread_stop(uwbd_task); - spin_lock_irqsave(&uwbd_event_list_lock, flags); - uwbd_pid = 0; - list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) { - if (evt->type == UWB_EVT_TYPE_NOTIF) - kfree(evt->notif.rceb); - kfree(evt); - } - spin_unlock_irqrestore(&uwbd_event_list_lock, flags); - uwb_beca_release(); + kthread_stop(rc->uwbd.task); + uwbd_flush(rc); } /* @@ -373,18 +331,20 @@ void uwbd_stop(void) */ void uwbd_event_queue(struct uwb_event *evt) { + struct uwb_rc *rc = evt->rc; unsigned long flags; - spin_lock_irqsave(&uwbd_event_list_lock, flags); - if (uwbd_pid != 0) { - list_add(&evt->list_node, &uwbd_event_list); - wake_up_all(&uwbd_wq); + + spin_lock_irqsave(&rc->uwbd.event_list_lock, flags); + if (rc->uwbd.pid != 0) { + list_add(&evt->list_node, &rc->uwbd.event_list); + wake_up_all(&rc->uwbd.wq); } else { __uwb_rc_put(evt->rc); if (evt->type == UWB_EVT_TYPE_NOTIF) kfree(evt->notif.rceb); kfree(evt); } - spin_unlock_irqrestore(&uwbd_event_list_lock, flags); + spin_unlock_irqrestore(&rc->uwbd.event_list_lock, flags); return; } @@ -392,10 +352,8 @@ void uwbd_flush(struct uwb_rc *rc) { struct uwb_event *evt, *nxt; - mutex_lock(&uwbd_event_mutex); - - spin_lock_irq(&uwbd_event_list_lock); - list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) { + spin_lock_irq(&rc->uwbd.event_list_lock); + list_for_each_entry_safe(evt, nxt, &rc->uwbd.event_list, list_node) { if (evt->rc == rc) { __uwb_rc_put(rc); list_del(&evt->list_node); @@ -404,7 +362,5 @@ void uwbd_flush(struct uwb_rc *rc) kfree(evt); } } - spin_unlock_irq(&uwbd_event_list_lock); - - mutex_unlock(&uwbd_event_mutex); + spin_unlock_irq(&rc->uwbd.event_list_lock); } diff --git a/drivers/uwb/whc-rc.c b/drivers/uwb/whc-rc.c index 1711dea..19a1dd1 100644 --- a/drivers/uwb/whc-rc.c +++ b/drivers/uwb/whc-rc.c @@ -39,7 +39,6 @@ * them to the hw and transfer the replies/notifications back to the * UWB stack through the UWB daemon (UWBD). */ -#include <linux/version.h> #include <linux/init.h> #include <linux/module.h> #include <linux/pci.h> @@ -49,10 +48,8 @@ #include <linux/uwb.h> #include <linux/uwb/whci.h> #include <linux/uwb/umc.h> -#include "uwb-internal.h" -#define D_LOCAL 0 -#include <linux/uwb/debug.h> +#include "uwb-internal.h" /** * Descriptor for an instance of the UWB Radio Control Driver that @@ -98,13 +95,8 @@ static int whcrc_cmd(struct uwb_rc *uwb_rc, struct device *dev = &whcrc->umc_dev->dev; u32 urccmd; - d_fnstart(3, dev, "(%p, %p, %zu)\n", uwb_rc, cmd, cmd_size); - might_sleep(); - - if (cmd_size >= 4096) { - result = -E2BIG; - goto error; - } + if (cmd_size >= 4096) + return -EINVAL; /* * If the URC is halted, then the hardware has reset itself. @@ -115,16 +107,14 @@ static int whcrc_cmd(struct uwb_rc *uwb_rc, if (le_readl(whcrc->rc_base + URCSTS) & URCSTS_HALTED) { dev_err(dev, "requesting reset of halted radio controller\n"); uwb_rc_reset_all(uwb_rc); - result = -EIO; - goto error; + return -EIO; } result = wait_event_timeout(whcrc->cmd_wq, !(le_readl(whcrc->rc_base + URCCMD) & URCCMD_ACTIVE), HZ/2); if (result == 0) { dev_err(dev, "device is not ready to execute commands\n"); - result = -ETIMEDOUT; - goto error; + return -ETIMEDOUT; } memmove(whcrc->cmd_buf, cmd, cmd_size); @@ -137,10 +127,7 @@ static int whcrc_cmd(struct uwb_rc *uwb_rc, whcrc->rc_base + URCCMD); spin_unlock(&whcrc->irq_lock); -error: - d_fnend(3, dev, "(%p, %p, %zu) = %d\n", - uwb_rc, cmd, cmd_size, result); - return result; + return 0; } static int whcrc_reset(struct uwb_rc *rc) @@ -167,34 +154,25 @@ static int whcrc_reset(struct uwb_rc *rc) static void whcrc_enable_events(struct whcrc *whcrc) { - struct device *dev = &whcrc->umc_dev->dev; u32 urccmd; - d_fnstart(4, dev, "(whcrc %p)\n", whcrc); - le_writeq(whcrc->evt_dma_buf, whcrc->rc_base + URCEVTADDR); spin_lock(&whcrc->irq_lock); urccmd = le_readl(whcrc->rc_base + URCCMD) & ~URCCMD_ACTIVE; le_writel(urccmd | URCCMD_EARV, whcrc->rc_base + URCCMD); spin_unlock(&whcrc->irq_lock); - - d_fnend(4, dev, "(whcrc %p) = void\n", whcrc); } static void whcrc_event_work(struct work_struct *work) { struct whcrc *whcrc = container_of(work, struct whcrc, event_work); - struct device *dev = &whcrc->umc_dev->dev; size_t size; u64 urcevtaddr; urcevtaddr = le_readq(whcrc->rc_base + URCEVTADDR); size = urcevtaddr & URCEVTADDR_OFFSET_MASK; - d_printf(3, dev, "received %zu octet event\n", size); - d_dump(4, dev, whcrc->evt_buf, size > 32 ? 32 : size); - uwb_rc_neh_grok(whcrc->uwb_rc, whcrc->evt_buf, size); whcrc_enable_events(whcrc); } @@ -217,22 +195,15 @@ irqreturn_t whcrc_irq_cb(int irq, void *_whcrc) return IRQ_NONE; le_writel(urcsts & URCSTS_INT_MASK, whcrc->rc_base + URCSTS); - d_printf(4, dev, "acked 0x%08x, urcsts 0x%08x\n", - le_readl(whcrc->rc_base + URCSTS), urcsts); - if (urcsts & URCSTS_HSE) { dev_err(dev, "host system error -- hardware halted\n"); /* FIXME: do something sensible here */ goto out; } - if (urcsts & URCSTS_ER) { - d_printf(3, dev, "ER: event ready\n"); + if (urcsts & URCSTS_ER) schedule_work(&whcrc->event_work); - } - if (urcsts & URCSTS_RCI) { - d_printf(3, dev, "RCI: ready to execute another command\n"); + if (urcsts & URCSTS_RCI) wake_up_all(&whcrc->cmd_wq); - } out: return IRQ_HANDLED; } @@ -251,8 +222,7 @@ int whcrc_setup_rc_umc(struct whcrc *whcrc) whcrc->area = umc_dev->resource.start; whcrc->rc_len = umc_dev->resource.end - umc_dev->resource.start + 1; result = -EBUSY; - if (request_mem_region(whcrc->area, whcrc->rc_len, KBUILD_MODNAME) - == NULL) { + if (request_mem_region(whcrc->area, whcrc->rc_len, KBUILD_MODNAME) == NULL) { dev_err(dev, "can't request URC region (%zu bytes @ 0x%lx): %d\n", whcrc->rc_len, whcrc->area, result); goto error_request_region; @@ -287,8 +257,6 @@ int whcrc_setup_rc_umc(struct whcrc *whcrc) dev_err(dev, "Can't allocate evt transfer buffer\n"); goto error_evt_buffer; } - d_printf(3, dev, "UWB RC Interface: %zu bytes at 0x%p, irq %u\n", - whcrc->rc_len, whcrc->rc_base, umc_dev->irq); return 0; error_evt_buffer: @@ -333,47 +301,23 @@ void whcrc_release_rc_umc(struct whcrc *whcrc) static int whcrc_start_rc(struct uwb_rc *rc) { struct whcrc *whcrc = rc->priv; - int result = 0; struct device *dev = &whcrc->umc_dev->dev; - unsigned long start, duration; /* Reset the thing */ le_writel(URCCMD_RESET, whcrc->rc_base + URCCMD); - if (d_test(3)) - start = jiffies; if (whci_wait_for(dev, whcrc->rc_base + URCCMD, URCCMD_RESET, 0, - 5000, "device to reset at init") < 0) { - result = -EBUSY; - goto error; - } else if (d_test(3)) { - duration = jiffies - start; - if (duration > msecs_to_jiffies(40)) - dev_err(dev, "Device took %ums to " - "reset. MAX expected: 40ms\n", - jiffies_to_msecs(duration)); - } + 5000, "hardware reset") < 0) + return -EBUSY; /* Set the event buffer, start the controller (enable IRQs later) */ le_writel(0, whcrc->rc_base + URCINTR); le_writel(URCCMD_RS, whcrc->rc_base + URCCMD); - result = -ETIMEDOUT; - if (d_test(3)) - start = jiffies; if (whci_wait_for(dev, whcrc->rc_base + URCSTS, URCSTS_HALTED, 0, - 5000, "device to start") < 0) - goto error; - if (d_test(3)) { - duration = jiffies - start; - if (duration > msecs_to_jiffies(40)) - dev_err(dev, "Device took %ums to start. " - "MAX expected: 40ms\n", - jiffies_to_msecs(duration)); - } + 5000, "radio controller start") < 0) + return -ETIMEDOUT; whcrc_enable_events(whcrc); - result = 0; le_writel(URCINTR_EN_ALL, whcrc->rc_base + URCINTR); -error: - return result; + return 0; } @@ -395,7 +339,7 @@ void whcrc_stop_rc(struct uwb_rc *rc) le_writel(0, whcrc->rc_base + URCCMD); whci_wait_for(&umc_dev->dev, whcrc->rc_base + URCSTS, - URCSTS_HALTED, 0, 40, "URCSTS.HALTED"); + URCSTS_HALTED, URCSTS_HALTED, 100, "radio controller stop"); } static void whcrc_init(struct whcrc *whcrc) @@ -421,7 +365,6 @@ int whcrc_probe(struct umc_dev *umc_dev) struct whcrc *whcrc; struct device *dev = &umc_dev->dev; - d_fnstart(3, dev, "(umc_dev %p)\n", umc_dev); result = -ENOMEM; uwb_rc = uwb_rc_alloc(); if (uwb_rc == NULL) { @@ -453,7 +396,6 @@ int whcrc_probe(struct umc_dev *umc_dev) if (result < 0) goto error_rc_add; umc_set_drvdata(umc_dev, whcrc); - d_fnend(3, dev, "(umc_dev %p) = 0\n", umc_dev); return 0; error_rc_add: @@ -463,7 +405,6 @@ error_setup_rc_umc: error_alloc: uwb_rc_put(uwb_rc); error_rc_alloc: - d_fnend(3, dev, "(umc_dev %p) = %d\n", umc_dev, result); return result; } @@ -486,7 +427,24 @@ static void whcrc_remove(struct umc_dev *umc_dev) whcrc_release_rc_umc(whcrc); kfree(whcrc); uwb_rc_put(uwb_rc); - d_printf(1, &umc_dev->dev, "freed whcrc %p\n", whcrc); +} + +static int whcrc_pre_reset(struct umc_dev *umc) +{ + struct whcrc *whcrc = umc_get_drvdata(umc); + struct uwb_rc *uwb_rc = whcrc->uwb_rc; + + uwb_rc_pre_reset(uwb_rc); + return 0; +} + +static int whcrc_post_reset(struct umc_dev *umc) +{ + struct whcrc *whcrc = umc_get_drvdata(umc); + struct uwb_rc *uwb_rc = whcrc->uwb_rc; + + uwb_rc_post_reset(uwb_rc); + return 0; } /* PCI device ID's that we handle [so it gets loaded] */ @@ -497,10 +455,12 @@ static struct pci_device_id whcrc_id_table[] = { MODULE_DEVICE_TABLE(pci, whcrc_id_table); static struct umc_driver whcrc_driver = { - .name = "whc-rc", - .cap_id = UMC_CAP_ID_WHCI_RC, - .probe = whcrc_probe, - .remove = whcrc_remove, + .name = "whc-rc", + .cap_id = UMC_CAP_ID_WHCI_RC, + .probe = whcrc_probe, + .remove = whcrc_remove, + .pre_reset = whcrc_pre_reset, + .post_reset = whcrc_post_reset, }; static int __init whcrc_driver_init(void) diff --git a/drivers/uwb/whci.c b/drivers/uwb/whci.c index 3df2388..1f8964e 100644 --- a/drivers/uwb/whci.c +++ b/drivers/uwb/whci.c @@ -67,11 +67,11 @@ int whci_wait_for(struct device *dev, u32 __iomem *reg, u32 mask, u32 result, val = le_readl(reg); if ((val & mask) == result) break; - msleep(10); if (t >= max_ms) { - dev_err(dev, "timed out waiting for %s ", tag); + dev_err(dev, "%s timed out\n", tag); return -ETIMEDOUT; } + msleep(10); t += 10; } return 0; @@ -111,7 +111,7 @@ static int whci_add_cap(struct whci_card *card, int n) + UWBCAPDATA_TO_OFFSET(capdata); umc->resource.end = umc->resource.start + (n == 0 ? 0x20 : UWBCAPDATA_TO_SIZE(capdata)) - 1; - umc->resource.name = umc->dev.bus_id; + umc->resource.name = dev_name(&umc->dev); umc->resource.flags = card->pci->resource[bar].flags; umc->resource.parent = &card->pci->resource[bar]; umc->irq = card->pci->irq; diff --git a/drivers/uwb/wlp/eda.c b/drivers/uwb/wlp/eda.c index 10985fa..69e0200 100644 --- a/drivers/uwb/wlp/eda.c +++ b/drivers/uwb/wlp/eda.c @@ -51,9 +51,7 @@ * the tag and address of the transmitting neighbor. */ -#define D_LOCAL 5 #include <linux/netdevice.h> -#include <linux/uwb/debug.h> #include <linux/etherdevice.h> #include <linux/wlp.h> #include "wlp-internal.h" @@ -304,7 +302,6 @@ int wlp_eda_for_virtual(struct wlp_eda *eda, { int result = 0; struct wlp *wlp = container_of(eda, struct wlp, eda); - struct device *dev = &wlp->rc->uwb_dev.dev; struct wlp_eda_node *itr; unsigned long flags; int found = 0; @@ -313,26 +310,14 @@ int wlp_eda_for_virtual(struct wlp_eda *eda, list_for_each_entry(itr, &eda->cache, list_node) { if (!memcmp(itr->virt_addr, virt_addr, sizeof(itr->virt_addr))) { - d_printf(6, dev, "EDA: looking for %pM hit %02x:%02x " - "wss %p tag 0x%02x state %u\n", - virt_addr, - itr->dev_addr.data[1], - itr->dev_addr.data[0], itr->wss, - itr->tag, itr->state); result = (*function)(wlp, itr, priv); *dev_addr = itr->dev_addr; found = 1; break; - } else - d_printf(6, dev, "EDA: looking for %pM against %pM miss\n", - virt_addr, itr->virt_addr); + } } - if (!found) { - if (printk_ratelimit()) - dev_err(dev, "EDA: Eth addr %pM not found.\n", - virt_addr); + if (!found) result = -ENODEV; - } spin_unlock_irqrestore(&eda->lock, flags); return result; } diff --git a/drivers/uwb/wlp/messages.c b/drivers/uwb/wlp/messages.c index a64cb824..aa42fce 100644 --- a/drivers/uwb/wlp/messages.c +++ b/drivers/uwb/wlp/messages.c @@ -24,8 +24,7 @@ */ #include <linux/wlp.h> -#define D_LOCAL 6 -#include <linux/uwb/debug.h> + #include "wlp-internal.h" static @@ -105,24 +104,18 @@ static inline void wlp_set_attr_hdr(struct wlp_attr_hdr *hdr, unsigned type, #define wlp_set(type, type_code, name) \ static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \ { \ - d_fnstart(6, NULL, "(attribute %p)\n", attr); \ wlp_set_attr_hdr(&attr->hdr, type_code, \ sizeof(*attr) - sizeof(struct wlp_attr_hdr)); \ attr->name = value; \ - d_dump(6, NULL, attr, sizeof(*attr)); \ - d_fnend(6, NULL, "(attribute %p)\n", attr); \ return sizeof(*attr); \ } #define wlp_pset(type, type_code, name) \ static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \ { \ - d_fnstart(6, NULL, "(attribute %p)\n", attr); \ wlp_set_attr_hdr(&attr->hdr, type_code, \ sizeof(*attr) - sizeof(struct wlp_attr_hdr)); \ attr->name = *value; \ - d_dump(6, NULL, attr, sizeof(*attr)); \ - d_fnend(6, NULL, "(attribute %p)\n", attr); \ return sizeof(*attr); \ } @@ -139,11 +132,8 @@ static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \ static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value, \ size_t len) \ { \ - d_fnstart(6, NULL, "(attribute %p)\n", attr); \ wlp_set_attr_hdr(&attr->hdr, type_code, len); \ memcpy(attr->name, value, len); \ - d_dump(6, NULL, attr, sizeof(*attr) + len); \ - d_fnend(6, NULL, "(attribute %p)\n", attr); \ return sizeof(*attr) + len; \ } @@ -182,7 +172,7 @@ static size_t wlp_set_wss_info(struct wlp_attr_wss_info *attr, size_t datalen; void *ptr = attr->wss_info; size_t used = sizeof(*attr); - d_fnstart(6, NULL, "(attribute %p)\n", attr); + datalen = sizeof(struct wlp_wss_info) + strlen(wss->name); wlp_set_attr_hdr(&attr->hdr, WLP_ATTR_WSS_INFO, datalen); used = wlp_set_wssid(ptr, &wss->wssid); @@ -190,9 +180,6 @@ static size_t wlp_set_wss_info(struct wlp_attr_wss_info *attr, used += wlp_set_accept_enrl(ptr + used, wss->accept_enroll); used += wlp_set_wss_sec_status(ptr + used, wss->secure_status); used += wlp_set_wss_bcast(ptr + used, &wss->bcast); - d_dump(6, NULL, attr, sizeof(*attr) + datalen); - d_fnend(6, NULL, "(attribute %p, used %d)\n", - attr, (int)(sizeof(*attr) + used)); return sizeof(*attr) + used; } @@ -414,7 +401,6 @@ static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp, size_t used = 0; ssize_t result = -EINVAL; - d_printf(6, dev, "WLP: WSS info: Retrieving WSS name\n"); result = wlp_get_wss_name(wlp, ptr, info->name, buflen); if (result < 0) { dev_err(dev, "WLP: unable to obtain WSS name from " @@ -422,7 +408,7 @@ static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp, goto error_parse; } used += result; - d_printf(6, dev, "WLP: WSS info: Retrieving accept enroll\n"); + result = wlp_get_accept_enrl(wlp, ptr + used, &info->accept_enroll, buflen - used); if (result < 0) { @@ -437,7 +423,7 @@ static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp, goto error_parse; } used += result; - d_printf(6, dev, "WLP: WSS info: Retrieving secure status\n"); + result = wlp_get_wss_sec_status(wlp, ptr + used, &info->sec_status, buflen - used); if (result < 0) { @@ -452,7 +438,7 @@ static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp, goto error_parse; } used += result; - d_printf(6, dev, "WLP: WSS info: Retrieving broadcast\n"); + result = wlp_get_wss_bcast(wlp, ptr + used, &info->bcast, buflen - used); if (result < 0) { @@ -530,7 +516,7 @@ static ssize_t wlp_get_wss_info(struct wlp *wlp, struct wlp_attr_wss_info *attr, len = result; used = sizeof(*attr); ptr = attr; - d_printf(6, dev, "WLP: WSS info: Retrieving WSSID\n"); + result = wlp_get_wssid(wlp, ptr + used, wssid, buflen - used); if (result < 0) { dev_err(dev, "WLP: unable to obtain WSSID from WSS info.\n"); @@ -553,8 +539,6 @@ static ssize_t wlp_get_wss_info(struct wlp *wlp, struct wlp_attr_wss_info *attr, goto out; } result = used; - d_printf(6, dev, "WLP: Successfully parsed WLP information " - "attribute. used %zu bytes\n", used); out: return result; } @@ -598,8 +582,6 @@ static ssize_t wlp_get_all_wss_info(struct wlp *wlp, struct wlp_wssid_e *wssid_e; char buf[WLP_WSS_UUID_STRSIZE]; - d_fnstart(6, dev, "wlp %p, attr %p, neighbor %p, wss %p, buflen %d \n", - wlp, attr, neighbor, wss, (int)buflen); if (buflen < 0) goto out; @@ -638,8 +620,7 @@ static ssize_t wlp_get_all_wss_info(struct wlp *wlp, wss->accept_enroll = wss_info.accept_enroll; wss->state = WLP_WSS_STATE_PART_ENROLLED; wlp_wss_uuid_print(buf, sizeof(buf), &wssid); - d_printf(2, dev, "WLP: Found WSS %s. Enrolling.\n", - buf); + dev_dbg(dev, "WLP: Found WSS %s. Enrolling.\n", buf); } else { wssid_e = wlp_create_wssid_e(wlp, neighbor); if (wssid_e == NULL) { @@ -660,9 +641,6 @@ error_parse: if (result < 0 && !enroll) /* this was a discovery */ wlp_remove_neighbor_tmp_info(neighbor); out: - d_fnend(6, dev, "wlp %p, attr %p, neighbor %p, wss %p, buflen %d, " - "result %d \n", wlp, attr, neighbor, wss, (int)buflen, - (int)result); return result; } @@ -718,7 +696,6 @@ static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss, struct sk_buff *_skb; void *d1_itr; - d_fnstart(6, dev, "wlp %p\n", wlp); if (wlp->dev_info == NULL) { result = __wlp_setup_device_info(wlp); if (result < 0) { @@ -728,24 +705,6 @@ static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss, } } info = wlp->dev_info; - d_printf(6, dev, "Local properties:\n" - "Device name (%d bytes): %s\n" - "Model name (%d bytes): %s\n" - "Manufacturer (%d bytes): %s\n" - "Model number (%d bytes): %s\n" - "Serial number (%d bytes): %s\n" - "Primary device type: \n" - " Category: %d \n" - " OUI: %02x:%02x:%02x \n" - " OUI Subdivision: %u \n", - (int)strlen(info->name), info->name, - (int)strlen(info->model_name), info->model_name, - (int)strlen(info->manufacturer), info->manufacturer, - (int)strlen(info->model_nr), info->model_nr, - (int)strlen(info->serial), info->serial, - info->prim_dev_type.category, - info->prim_dev_type.OUI[0], info->prim_dev_type.OUI[1], - info->prim_dev_type.OUI[2], info->prim_dev_type.OUIsubdiv); _skb = dev_alloc_skb(sizeof(*_d1) + sizeof(struct wlp_attr_uuid_e) + sizeof(struct wlp_attr_wss_sel_mthd) @@ -768,7 +727,6 @@ static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss, goto error; } _d1 = (void *) _skb->data; - d_printf(6, dev, "D1 starts at %p \n", _d1); _d1->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); _d1->hdr.type = WLP_FRAME_ASSOCIATION; _d1->type = WLP_ASSOC_D1; @@ -791,25 +749,8 @@ static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss, used += wlp_set_prim_dev_type(d1_itr + used, &info->prim_dev_type); used += wlp_set_wlp_assc_err(d1_itr + used, WLP_ASSOC_ERROR_NONE); skb_put(_skb, sizeof(*_d1) + used); - d_printf(6, dev, "D1 message:\n"); - d_dump(6, dev, _d1, sizeof(*_d1) - + sizeof(struct wlp_attr_uuid_e) - + sizeof(struct wlp_attr_wss_sel_mthd) - + sizeof(struct wlp_attr_dev_name) - + strlen(info->name) - + sizeof(struct wlp_attr_manufacturer) - + strlen(info->manufacturer) - + sizeof(struct wlp_attr_model_name) - + strlen(info->model_name) - + sizeof(struct wlp_attr_model_nr) - + strlen(info->model_nr) - + sizeof(struct wlp_attr_serial) - + strlen(info->serial) - + sizeof(struct wlp_attr_prim_dev_type) - + sizeof(struct wlp_attr_wlp_assc_err)); *skb = _skb; error: - d_fnend(6, dev, "wlp %p, result = %d\n", wlp, result); return result; } @@ -837,7 +778,6 @@ int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss, void *d2_itr; size_t mem_needed; - d_fnstart(6, dev, "wlp %p\n", wlp); if (wlp->dev_info == NULL) { result = __wlp_setup_device_info(wlp); if (result < 0) { @@ -847,24 +787,6 @@ int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss, } } info = wlp->dev_info; - d_printf(6, dev, "Local properties:\n" - "Device name (%d bytes): %s\n" - "Model name (%d bytes): %s\n" - "Manufacturer (%d bytes): %s\n" - "Model number (%d bytes): %s\n" - "Serial number (%d bytes): %s\n" - "Primary device type: \n" - " Category: %d \n" - " OUI: %02x:%02x:%02x \n" - " OUI Subdivision: %u \n", - (int)strlen(info->name), info->name, - (int)strlen(info->model_name), info->model_name, - (int)strlen(info->manufacturer), info->manufacturer, - (int)strlen(info->model_nr), info->model_nr, - (int)strlen(info->serial), info->serial, - info->prim_dev_type.category, - info->prim_dev_type.OUI[0], info->prim_dev_type.OUI[1], - info->prim_dev_type.OUI[2], info->prim_dev_type.OUIsubdiv); mem_needed = sizeof(*_d2) + sizeof(struct wlp_attr_uuid_e) + sizeof(struct wlp_attr_uuid_r) @@ -892,7 +814,6 @@ int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss, goto error; } _d2 = (void *) _skb->data; - d_printf(6, dev, "D2 starts at %p \n", _d2); _d2->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); _d2->hdr.type = WLP_FRAME_ASSOCIATION; _d2->type = WLP_ASSOC_D2; @@ -917,11 +838,8 @@ int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss, used += wlp_set_prim_dev_type(d2_itr + used, &info->prim_dev_type); used += wlp_set_wlp_assc_err(d2_itr + used, WLP_ASSOC_ERROR_NONE); skb_put(_skb, sizeof(*_d2) + used); - d_printf(6, dev, "D2 message:\n"); - d_dump(6, dev, _d2, mem_needed); *skb = _skb; error: - d_fnend(6, dev, "wlp %p, result = %d\n", wlp, result); return result; } @@ -947,7 +865,6 @@ int wlp_build_assoc_f0(struct wlp *wlp, struct sk_buff **skb, struct sk_buff *_skb; struct wlp_nonce tmp; - d_fnstart(6, dev, "wlp %p\n", wlp); _skb = dev_alloc_skb(sizeof(*f0)); if (_skb == NULL) { dev_err(dev, "WLP: Unable to allocate memory for F0 " @@ -955,7 +872,6 @@ int wlp_build_assoc_f0(struct wlp *wlp, struct sk_buff **skb, goto error_alloc; } f0 = (void *) _skb->data; - d_printf(6, dev, "F0 starts at %p \n", f0); f0->f0_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); f0->f0_hdr.hdr.type = WLP_FRAME_ASSOCIATION; f0->f0_hdr.type = WLP_ASSOC_F0; @@ -969,7 +885,6 @@ int wlp_build_assoc_f0(struct wlp *wlp, struct sk_buff **skb, *skb = _skb; result = 0; error_alloc: - d_fnend(6, dev, "wlp %p, result %d \n", wlp, result); return result; } @@ -1242,12 +1157,9 @@ void wlp_handle_d1_frame(struct work_struct *ws) enum wlp_wss_sel_mthd sel_mthd = 0; struct wlp_device_info dev_info; enum wlp_assc_error assc_err; - char uuid[WLP_WSS_UUID_STRSIZE]; struct sk_buff *resp = NULL; /* Parse D1 frame */ - d_fnstart(6, dev, "WLP: handle D1 frame. wlp = %p, skb = %p\n", - wlp, skb); mutex_lock(&wss->mutex); mutex_lock(&wlp->mutex); /* to access wlp->uuid */ memset(&dev_info, 0, sizeof(dev_info)); @@ -1258,30 +1170,6 @@ void wlp_handle_d1_frame(struct work_struct *ws) kfree_skb(skb); goto out; } - wlp_wss_uuid_print(uuid, sizeof(uuid), &uuid_e); - d_printf(6, dev, "From D1 frame:\n" - "UUID-E: %s\n" - "Selection method: %d\n" - "Device name (%d bytes): %s\n" - "Model name (%d bytes): %s\n" - "Manufacturer (%d bytes): %s\n" - "Model number (%d bytes): %s\n" - "Serial number (%d bytes): %s\n" - "Primary device type: \n" - " Category: %d \n" - " OUI: %02x:%02x:%02x \n" - " OUI Subdivision: %u \n", - uuid, sel_mthd, - (int)strlen(dev_info.name), dev_info.name, - (int)strlen(dev_info.model_name), dev_info.model_name, - (int)strlen(dev_info.manufacturer), dev_info.manufacturer, - (int)strlen(dev_info.model_nr), dev_info.model_nr, - (int)strlen(dev_info.serial), dev_info.serial, - dev_info.prim_dev_type.category, - dev_info.prim_dev_type.OUI[0], - dev_info.prim_dev_type.OUI[1], - dev_info.prim_dev_type.OUI[2], - dev_info.prim_dev_type.OUIsubdiv); kfree_skb(skb); if (!wlp_uuid_is_set(&wlp->uuid)) { @@ -1316,7 +1204,6 @@ out: kfree(frame_ctx); mutex_unlock(&wlp->mutex); mutex_unlock(&wss->mutex); - d_fnend(6, dev, "WLP: handle D1 frame. wlp = %p\n", wlp); } /** @@ -1546,10 +1433,8 @@ int wlp_parse_c3c4_frame(struct wlp *wlp, struct sk_buff *skb, void *ptr = skb->data; size_t len = skb->len; size_t used; - char buf[WLP_WSS_UUID_STRSIZE]; struct wlp_frame_assoc *assoc = ptr; - d_fnstart(6, dev, "wlp %p, skb %p \n", wlp, skb); used = sizeof(*assoc); result = wlp_get_wssid(wlp, ptr + used, wssid, len - used); if (result < 0) { @@ -1572,14 +1457,7 @@ int wlp_parse_c3c4_frame(struct wlp *wlp, struct sk_buff *skb, wlp_assoc_frame_str(assoc->type)); goto error_parse; } - wlp_wss_uuid_print(buf, sizeof(buf), wssid); - d_printf(6, dev, "WLP: parsed: WSSID %s, tag 0x%02x, virt " - "%02x:%02x:%02x:%02x:%02x:%02x \n", buf, *tag, - virt_addr->data[0], virt_addr->data[1], virt_addr->data[2], - virt_addr->data[3], virt_addr->data[4], virt_addr->data[5]); - error_parse: - d_fnend(6, dev, "wlp %p, skb %p, result = %d \n", wlp, skb, result); return result; } @@ -1600,7 +1478,6 @@ int wlp_build_assoc_c1c2(struct wlp *wlp, struct wlp_wss *wss, } *c; struct sk_buff *_skb; - d_fnstart(6, dev, "wlp %p, wss %p \n", wlp, wss); _skb = dev_alloc_skb(sizeof(*c)); if (_skb == NULL) { dev_err(dev, "WLP: Unable to allocate memory for C1/C2 " @@ -1608,7 +1485,6 @@ int wlp_build_assoc_c1c2(struct wlp *wlp, struct wlp_wss *wss, goto error_alloc; } c = (void *) _skb->data; - d_printf(6, dev, "C1/C2 starts at %p \n", c); c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION; c->c_hdr.type = type; @@ -1616,12 +1492,9 @@ int wlp_build_assoc_c1c2(struct wlp *wlp, struct wlp_wss *wss, wlp_set_msg_type(&c->c_hdr.msg_type, type); wlp_set_wssid(&c->wssid, &wss->wssid); skb_put(_skb, sizeof(*c)); - d_printf(6, dev, "C1/C2 message:\n"); - d_dump(6, dev, c, sizeof(*c)); *skb = _skb; result = 0; error_alloc: - d_fnend(6, dev, "wlp %p, wss %p, result %d \n", wlp, wss, result); return result; } @@ -1660,7 +1533,6 @@ int wlp_build_assoc_c3c4(struct wlp *wlp, struct wlp_wss *wss, } *c; struct sk_buff *_skb; - d_fnstart(6, dev, "wlp %p, wss %p \n", wlp, wss); _skb = dev_alloc_skb(sizeof(*c)); if (_skb == NULL) { dev_err(dev, "WLP: Unable to allocate memory for C3/C4 " @@ -1668,7 +1540,6 @@ int wlp_build_assoc_c3c4(struct wlp *wlp, struct wlp_wss *wss, goto error_alloc; } c = (void *) _skb->data; - d_printf(6, dev, "C3/C4 starts at %p \n", c); c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION; c->c_hdr.type = type; @@ -1678,12 +1549,9 @@ int wlp_build_assoc_c3c4(struct wlp *wlp, struct wlp_wss *wss, wlp_set_wss_tag(&c->wss_tag, wss->tag); wlp_set_wss_virt(&c->wss_virt, &wss->virtual_addr); skb_put(_skb, sizeof(*c)); - d_printf(6, dev, "C3/C4 message:\n"); - d_dump(6, dev, c, sizeof(*c)); *skb = _skb; result = 0; error_alloc: - d_fnend(6, dev, "wlp %p, wss %p, result %d \n", wlp, wss, result); return result; } @@ -1709,10 +1577,7 @@ static int wlp_send_assoc_##type(struct wlp *wlp, struct wlp_wss *wss, \ struct device *dev = &wlp->rc->uwb_dev.dev; \ int result; \ struct sk_buff *skb = NULL; \ - d_fnstart(6, dev, "wlp %p, wss %p, neighbor: %02x:%02x\n", \ - wlp, wss, dev_addr->data[1], dev_addr->data[0]); \ - d_printf(6, dev, "WLP: Constructing %s frame. \n", \ - wlp_assoc_frame_str(id)); \ + \ /* Build the frame */ \ result = wlp_build_assoc_##type(wlp, wss, &skb); \ if (result < 0) { \ @@ -1721,9 +1586,6 @@ static int wlp_send_assoc_##type(struct wlp *wlp, struct wlp_wss *wss, \ goto error_build_assoc; \ } \ /* Send the frame */ \ - d_printf(6, dev, "Transmitting %s frame to %02x:%02x \n", \ - wlp_assoc_frame_str(id), \ - dev_addr->data[1], dev_addr->data[0]); \ BUG_ON(wlp->xmit_frame == NULL); \ result = wlp->xmit_frame(wlp, skb, dev_addr); \ if (result < 0) { \ @@ -1740,8 +1602,6 @@ error_xmit: \ /* We could try again ... */ \ dev_kfree_skb_any(skb);/*we need to free if tx fails*/ \ error_build_assoc: \ - d_fnend(6, dev, "wlp %p, wss %p, neighbor: %02x:%02x\n", \ - wlp, wss, dev_addr->data[1], dev_addr->data[0]); \ return result; \ } @@ -1794,12 +1654,9 @@ void wlp_handle_c1_frame(struct work_struct *ws) struct uwb_dev_addr *src = &frame_ctx->src; int result; struct wlp_uuid wssid; - char buf[WLP_WSS_UUID_STRSIZE]; struct sk_buff *resp = NULL; /* Parse C1 frame */ - d_fnstart(6, dev, "WLP: handle C1 frame. wlp = %p, c1 = %p\n", - wlp, c1); mutex_lock(&wss->mutex); result = wlp_get_wssid(wlp, (void *)c1 + sizeof(*c1), &wssid, len - sizeof(*c1)); @@ -1807,12 +1664,8 @@ void wlp_handle_c1_frame(struct work_struct *ws) dev_err(dev, "WLP: unable to obtain WSSID from C1 frame.\n"); goto out; } - wlp_wss_uuid_print(buf, sizeof(buf), &wssid); - d_printf(6, dev, "Received C1 frame with WSSID %s \n", buf); if (!memcmp(&wssid, &wss->wssid, sizeof(wssid)) && wss->state == WLP_WSS_STATE_ACTIVE) { - d_printf(6, dev, "WSSID from C1 frame is known locally " - "and is active\n"); /* Construct C2 frame */ result = wlp_build_assoc_c2(wlp, wss, &resp); if (result < 0) { @@ -1820,8 +1673,6 @@ void wlp_handle_c1_frame(struct work_struct *ws) goto out; } } else { - d_printf(6, dev, "WSSID from C1 frame is not known locally " - "or is not active\n"); /* Construct F0 frame */ result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV); if (result < 0) { @@ -1830,8 +1681,6 @@ void wlp_handle_c1_frame(struct work_struct *ws) } } /* Send C2 frame */ - d_printf(6, dev, "Transmitting response (C2/F0) frame to %02x:%02x \n", - src->data[1], src->data[0]); BUG_ON(wlp->xmit_frame == NULL); result = wlp->xmit_frame(wlp, resp, src); if (result < 0) { @@ -1846,7 +1695,6 @@ out: kfree_skb(frame_ctx->skb); kfree(frame_ctx); mutex_unlock(&wss->mutex); - d_fnend(6, dev, "WLP: handle C1 frame. wlp = %p\n", wlp); } /** @@ -1868,27 +1716,20 @@ void wlp_handle_c3_frame(struct work_struct *ws) struct sk_buff *skb = frame_ctx->skb; struct uwb_dev_addr *src = &frame_ctx->src; int result; - char buf[WLP_WSS_UUID_STRSIZE]; struct sk_buff *resp = NULL; struct wlp_uuid wssid; u8 tag; struct uwb_mac_addr virt_addr; /* Parse C3 frame */ - d_fnstart(6, dev, "WLP: handle C3 frame. wlp = %p, skb = %p\n", - wlp, skb); mutex_lock(&wss->mutex); result = wlp_parse_c3c4_frame(wlp, skb, &wssid, &tag, &virt_addr); if (result < 0) { dev_err(dev, "WLP: unable to obtain values from C3 frame.\n"); goto out; } - wlp_wss_uuid_print(buf, sizeof(buf), &wssid); - d_printf(6, dev, "Received C3 frame with WSSID %s \n", buf); if (!memcmp(&wssid, &wss->wssid, sizeof(wssid)) && wss->state >= WLP_WSS_STATE_ACTIVE) { - d_printf(6, dev, "WSSID from C3 frame is known locally " - "and is active\n"); result = wlp_eda_update_node(&wlp->eda, src, wss, (void *) virt_addr.data, tag, WLP_WSS_CONNECTED); @@ -1913,8 +1754,6 @@ void wlp_handle_c3_frame(struct work_struct *ws) } } } else { - d_printf(6, dev, "WSSID from C3 frame is not known locally " - "or is not active\n"); /* Construct F0 frame */ result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV); if (result < 0) { @@ -1923,8 +1762,6 @@ void wlp_handle_c3_frame(struct work_struct *ws) } } /* Send C4 frame */ - d_printf(6, dev, "Transmitting response (C4/F0) frame to %02x:%02x \n", - src->data[1], src->data[0]); BUG_ON(wlp->xmit_frame == NULL); result = wlp->xmit_frame(wlp, resp, src); if (result < 0) { @@ -1939,8 +1776,6 @@ out: kfree_skb(frame_ctx->skb); kfree(frame_ctx); mutex_unlock(&wss->mutex); - d_fnend(6, dev, "WLP: handle C3 frame. wlp = %p, skb = %p\n", - wlp, skb); } diff --git a/drivers/uwb/wlp/sysfs.c b/drivers/uwb/wlp/sysfs.c index 1bb9b1f..0370399 100644 --- a/drivers/uwb/wlp/sysfs.c +++ b/drivers/uwb/wlp/sysfs.c @@ -23,8 +23,8 @@ * FIXME: Docs * */ - #include <linux/wlp.h> + #include "wlp-internal.h" static diff --git a/drivers/uwb/wlp/txrx.c b/drivers/uwb/wlp/txrx.c index c701bd1..cd20357 100644 --- a/drivers/uwb/wlp/txrx.c +++ b/drivers/uwb/wlp/txrx.c @@ -26,12 +26,10 @@ #include <linux/etherdevice.h> #include <linux/wlp.h> -#define D_LOCAL 5 -#include <linux/uwb/debug.h> -#include "wlp-internal.h" +#include "wlp-internal.h" -/** +/* * Direct incoming association msg to correct parsing routine * * We only expect D1, E1, C1, C3 messages as new. All other incoming @@ -48,35 +46,31 @@ void wlp_direct_assoc_frame(struct wlp *wlp, struct sk_buff *skb, struct device *dev = &wlp->rc->uwb_dev.dev; struct wlp_frame_assoc *assoc = (void *) skb->data; struct wlp_assoc_frame_ctx *frame_ctx; - d_fnstart(5, dev, "wlp %p, skb %p\n", wlp, skb); + frame_ctx = kmalloc(sizeof(*frame_ctx), GFP_ATOMIC); if (frame_ctx == NULL) { dev_err(dev, "WLP: Unable to allocate memory for association " "frame handling.\n"); kfree_skb(skb); - goto out; + return; } frame_ctx->wlp = wlp; frame_ctx->skb = skb; frame_ctx->src = *src; switch (assoc->type) { case WLP_ASSOC_D1: - d_printf(5, dev, "Received a D1 frame.\n"); INIT_WORK(&frame_ctx->ws, wlp_handle_d1_frame); schedule_work(&frame_ctx->ws); break; case WLP_ASSOC_E1: - d_printf(5, dev, "Received a E1 frame. FIXME?\n"); kfree_skb(skb); /* Temporary until we handle it */ kfree(frame_ctx); /* Temporary until we handle it */ break; case WLP_ASSOC_C1: - d_printf(5, dev, "Received a C1 frame.\n"); INIT_WORK(&frame_ctx->ws, wlp_handle_c1_frame); schedule_work(&frame_ctx->ws); break; case WLP_ASSOC_C3: - d_printf(5, dev, "Received a C3 frame.\n"); INIT_WORK(&frame_ctx->ws, wlp_handle_c3_frame); schedule_work(&frame_ctx->ws); break; @@ -87,11 +81,9 @@ void wlp_direct_assoc_frame(struct wlp *wlp, struct sk_buff *skb, kfree(frame_ctx); break; } -out: - d_fnend(5, dev, "wlp %p\n", wlp); } -/** +/* * Process incoming association frame * * Although it could be possible to deal with some incoming association @@ -112,7 +104,6 @@ void wlp_receive_assoc_frame(struct wlp *wlp, struct sk_buff *skb, struct wlp_frame_assoc *assoc = (void *) skb->data; struct wlp_session *session = wlp->session; u8 version; - d_fnstart(5, dev, "wlp %p, skb %p\n", wlp, skb); if (wlp_get_version(wlp, &assoc->version, &version, sizeof(assoc->version)) < 0) @@ -150,14 +141,12 @@ void wlp_receive_assoc_frame(struct wlp *wlp, struct sk_buff *skb, } else { wlp_direct_assoc_frame(wlp, skb, src); } - d_fnend(5, dev, "wlp %p\n", wlp); return; error: kfree_skb(skb); - d_fnend(5, dev, "wlp %p\n", wlp); } -/** +/* * Verify incoming frame is from connected neighbor, prep to pass to WLP client * * Verification proceeds according to WLP 0.99 [7.3.1]. The source address @@ -176,7 +165,6 @@ int wlp_verify_prep_rx_frame(struct wlp *wlp, struct sk_buff *skb, struct wlp_eda_node eda_entry; struct wlp_frame_std_abbrv_hdr *hdr = (void *) skb->data; - d_fnstart(6, dev, "wlp %p, skb %p \n", wlp, skb); /*verify*/ result = wlp_copy_eda_node(&wlp->eda, src, &eda_entry); if (result < 0) { @@ -207,11 +195,10 @@ int wlp_verify_prep_rx_frame(struct wlp *wlp, struct sk_buff *skb, /*prep*/ skb_pull(skb, sizeof(*hdr)); out: - d_fnend(6, dev, "wlp %p, skb %p, result = %d \n", wlp, skb, result); return result; } -/** +/* * Receive a WLP frame from device * * @returns: 1 if calling function should free the skb @@ -226,14 +213,12 @@ int wlp_receive_frame(struct device *dev, struct wlp *wlp, struct sk_buff *skb, struct wlp_frame_hdr *hdr; int result = 0; - d_fnstart(6, dev, "skb (%p), len (%u)\n", skb, len); if (len < sizeof(*hdr)) { dev_err(dev, "Not enough data to parse WLP header.\n"); result = -EINVAL; goto out; } hdr = ptr; - d_dump(6, dev, hdr, sizeof(*hdr)); if (le16_to_cpu(hdr->mux_hdr) != WLP_PROTOCOL_ID) { dev_err(dev, "Not a WLP frame type.\n"); result = -EINVAL; @@ -270,7 +255,6 @@ int wlp_receive_frame(struct device *dev, struct wlp *wlp, struct sk_buff *skb, "WLP header.\n"); goto out; } - d_printf(5, dev, "Association frame received.\n"); wlp_receive_assoc_frame(wlp, skb, src); break; default: @@ -283,13 +267,12 @@ out: kfree_skb(skb); result = 0; } - d_fnend(6, dev, "skb (%p)\n", skb); return result; } EXPORT_SYMBOL_GPL(wlp_receive_frame); -/** +/* * Verify frame from network stack, prepare for further transmission * * @skb: the socket buffer that needs to be prepared for transmission (it @@ -343,9 +326,7 @@ int wlp_prepare_tx_frame(struct device *dev, struct wlp *wlp, int result = -EINVAL; struct ethhdr *eth_hdr = (void *) skb->data; - d_fnstart(6, dev, "wlp (%p), skb (%p) \n", wlp, skb); if (is_broadcast_ether_addr(eth_hdr->h_dest)) { - d_printf(6, dev, "WLP: handling broadcast frame. \n"); result = wlp_eda_for_each(&wlp->eda, wlp_wss_send_copy, skb); if (result < 0) { if (printk_ratelimit()) @@ -357,7 +338,6 @@ int wlp_prepare_tx_frame(struct device *dev, struct wlp *wlp, result = 1; /* Frame will be transmitted by WLP. */ } else { - d_printf(6, dev, "WLP: handling unicast frame. \n"); result = wlp_eda_for_virtual(&wlp->eda, eth_hdr->h_dest, dst, wlp_wss_prep_hdr, skb); if (unlikely(result < 0)) { @@ -368,7 +348,6 @@ int wlp_prepare_tx_frame(struct device *dev, struct wlp *wlp, } } out: - d_fnend(6, dev, "wlp (%p), skb (%p). result = %d \n", wlp, skb, result); return result; } EXPORT_SYMBOL_GPL(wlp_prepare_tx_frame); diff --git a/drivers/uwb/wlp/wlp-internal.h b/drivers/uwb/wlp/wlp-internal.h index 1c94fab..3e8d5de 100644 --- a/drivers/uwb/wlp/wlp-internal.h +++ b/drivers/uwb/wlp/wlp-internal.h @@ -42,10 +42,6 @@ enum wlp_wss_connect { extern struct kobj_type wss_ktype; extern struct attribute_group wss_attr_group; -extern int uwb_rc_ie_add(struct uwb_rc *, const struct uwb_ie_hdr *, size_t); -extern int uwb_rc_ie_rm(struct uwb_rc *, enum uwb_ie); - - /* This should be changed to a dynamic array where entries are sorted * by eth_addr and search is done in a binary form * diff --git a/drivers/uwb/wlp/wlp-lc.c b/drivers/uwb/wlp/wlp-lc.c index 0799402e..13db739 100644 --- a/drivers/uwb/wlp/wlp-lc.c +++ b/drivers/uwb/wlp/wlp-lc.c @@ -21,12 +21,9 @@ * * FIXME: docs */ - #include <linux/wlp.h> -#define D_LOCAL 6 -#include <linux/uwb/debug.h> -#include "wlp-internal.h" +#include "wlp-internal.h" static void wlp_neighbor_init(struct wlp_neighbor_e *neighbor) @@ -61,11 +58,6 @@ int __wlp_alloc_device_info(struct wlp *wlp) static void __wlp_fill_device_info(struct wlp *wlp) { - struct device *dev = &wlp->rc->uwb_dev.dev; - - BUG_ON(wlp->fill_device_info == NULL); - d_printf(6, dev, "Retrieving device information " - "from device driver.\n"); wlp->fill_device_info(wlp, wlp->dev_info); } @@ -127,7 +119,7 @@ void wlp_remove_neighbor_tmp_info(struct wlp_neighbor_e *neighbor) } } -/** +/* * Populate WLP neighborhood cache with neighbor information * * A new neighbor is found. If it is discoverable then we add it to the @@ -141,10 +133,7 @@ int wlp_add_neighbor(struct wlp *wlp, struct uwb_dev *dev) int discoverable; struct wlp_neighbor_e *neighbor; - d_fnstart(6, &dev->dev, "uwb %p \n", dev); - d_printf(6, &dev->dev, "Found neighbor device %02x:%02x \n", - dev->dev_addr.data[1], dev->dev_addr.data[0]); - /** + /* * FIXME: * Use contents of WLP IE found in beacon cache to determine if * neighbor is discoverable. @@ -167,7 +156,6 @@ int wlp_add_neighbor(struct wlp *wlp, struct uwb_dev *dev) list_add(&neighbor->node, &wlp->neighbors); } error_no_mem: - d_fnend(6, &dev->dev, "uwb %p, result = %d \n", dev, result); return result; } @@ -255,8 +243,6 @@ int wlp_d1d2_exchange(struct wlp *wlp, struct wlp_neighbor_e *neighbor, dev_err(dev, "Unable to send D1 frame to neighbor " "%02x:%02x (%d)\n", dev_addr->data[1], dev_addr->data[0], result); - d_printf(6, dev, "Add placeholders into buffer next to " - "neighbor information we have (dev address).\n"); goto out; } /* Create session, wait for response */ @@ -284,8 +270,6 @@ int wlp_d1d2_exchange(struct wlp *wlp, struct wlp_neighbor_e *neighbor, /* Parse message in session->data: it will be either D2 or F0 */ skb = session.data; resp = (void *) skb->data; - d_printf(6, dev, "Received response to D1 frame. \n"); - d_dump(6, dev, skb->data, skb->len > 72 ? 72 : skb->len); if (resp->type == WLP_ASSOC_F0) { result = wlp_parse_f0(wlp, skb); @@ -337,10 +321,9 @@ int wlp_enroll_neighbor(struct wlp *wlp, struct wlp_neighbor_e *neighbor, struct device *dev = &wlp->rc->uwb_dev.dev; char buf[WLP_WSS_UUID_STRSIZE]; struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr; + wlp_wss_uuid_print(buf, sizeof(buf), wssid); - d_fnstart(6, dev, "wlp %p, neighbor %p, wss %p, wssid %p (%s)\n", - wlp, neighbor, wss, wssid, buf); - d_printf(6, dev, "Complete me.\n"); + result = wlp_d1d2_exchange(wlp, neighbor, wss, wssid); if (result < 0) { dev_err(dev, "WLP: D1/D2 message exchange for enrollment " @@ -360,13 +343,10 @@ int wlp_enroll_neighbor(struct wlp *wlp, struct wlp_neighbor_e *neighbor, goto error; } else { wss->state = WLP_WSS_STATE_ENROLLED; - d_printf(2, dev, "WLP: Success Enrollment into unsecure WSS " - "%s using neighbor %02x:%02x. \n", buf, - dev_addr->data[1], dev_addr->data[0]); + dev_dbg(dev, "WLP: Success Enrollment into unsecure WSS " + "%s using neighbor %02x:%02x. \n", + buf, dev_addr->data[1], dev_addr->data[0]); } - - d_fnend(6, dev, "wlp %p, neighbor %p, wss %p, wssid %p (%s)\n", - wlp, neighbor, wss, wssid, buf); out: return result; error: @@ -449,7 +429,6 @@ ssize_t wlp_discover(struct wlp *wlp) int result = 0; struct device *dev = &wlp->rc->uwb_dev.dev; - d_fnstart(6, dev, "wlp %p \n", wlp); mutex_lock(&wlp->nbmutex); /* Clear current neighborhood cache. */ __wlp_neighbors_release(wlp); @@ -469,7 +448,6 @@ ssize_t wlp_discover(struct wlp *wlp) } error_dev_for_each: mutex_unlock(&wlp->nbmutex); - d_fnend(6, dev, "wlp %p \n", wlp); return result; } @@ -492,9 +470,6 @@ void wlp_uwb_notifs_cb(void *_wlp, struct uwb_dev *uwb_dev, int result; switch (event) { case UWB_NOTIF_ONAIR: - d_printf(6, dev, "UWB device %02x:%02x is onair\n", - uwb_dev->dev_addr.data[1], - uwb_dev->dev_addr.data[0]); result = wlp_eda_create_node(&wlp->eda, uwb_dev->mac_addr.data, &uwb_dev->dev_addr); @@ -505,18 +480,11 @@ void wlp_uwb_notifs_cb(void *_wlp, struct uwb_dev *uwb_dev, uwb_dev->dev_addr.data[0]); break; case UWB_NOTIF_OFFAIR: - d_printf(6, dev, "UWB device %02x:%02x is offair\n", - uwb_dev->dev_addr.data[1], - uwb_dev->dev_addr.data[0]); wlp_eda_rm_node(&wlp->eda, &uwb_dev->dev_addr); mutex_lock(&wlp->nbmutex); - list_for_each_entry_safe(neighbor, next, &wlp->neighbors, - node) { - if (neighbor->uwb_dev == uwb_dev) { - d_printf(6, dev, "Removing device from " - "neighborhood.\n"); + list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) { + if (neighbor->uwb_dev == uwb_dev) __wlp_neighbor_release(neighbor); - } } mutex_unlock(&wlp->nbmutex); break; @@ -526,38 +494,47 @@ void wlp_uwb_notifs_cb(void *_wlp, struct uwb_dev *uwb_dev, } } -int wlp_setup(struct wlp *wlp, struct uwb_rc *rc) +static void wlp_channel_changed(struct uwb_pal *pal, int channel) +{ + struct wlp *wlp = container_of(pal, struct wlp, pal); + + if (channel < 0) + netif_carrier_off(wlp->ndev); + else + netif_carrier_on(wlp->ndev); +} + +int wlp_setup(struct wlp *wlp, struct uwb_rc *rc, struct net_device *ndev) { - struct device *dev = &rc->uwb_dev.dev; int result; - d_fnstart(6, dev, "wlp %p\n", wlp); BUG_ON(wlp->fill_device_info == NULL); BUG_ON(wlp->xmit_frame == NULL); BUG_ON(wlp->stop_queue == NULL); BUG_ON(wlp->start_queue == NULL); + wlp->rc = rc; + wlp->ndev = ndev; wlp_eda_init(&wlp->eda);/* Set up address cache */ wlp->uwb_notifs_handler.cb = wlp_uwb_notifs_cb; wlp->uwb_notifs_handler.data = wlp; uwb_notifs_register(rc, &wlp->uwb_notifs_handler); uwb_pal_init(&wlp->pal); - result = uwb_pal_register(rc, &wlp->pal); + wlp->pal.rc = rc; + wlp->pal.channel_changed = wlp_channel_changed; + result = uwb_pal_register(&wlp->pal); if (result < 0) uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); - d_fnend(6, dev, "wlp %p, result = %d\n", wlp, result); return result; } EXPORT_SYMBOL_GPL(wlp_setup); void wlp_remove(struct wlp *wlp) { - struct device *dev = &wlp->rc->uwb_dev.dev; - d_fnstart(6, dev, "wlp %p\n", wlp); wlp_neighbors_release(wlp); - uwb_pal_unregister(wlp->rc, &wlp->pal); + uwb_pal_unregister(&wlp->pal); uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); wlp_eda_release(&wlp->eda); mutex_lock(&wlp->mutex); @@ -565,9 +542,6 @@ void wlp_remove(struct wlp *wlp) kfree(wlp->dev_info); mutex_unlock(&wlp->mutex); wlp->rc = NULL; - /* We have to use NULL here because this function can be called - * when the device disappeared. */ - d_fnend(6, NULL, "wlp %p\n", wlp); } EXPORT_SYMBOL_GPL(wlp_remove); diff --git a/drivers/uwb/wlp/wss-lc.c b/drivers/uwb/wlp/wss-lc.c index 96b18c9..5913c7a 100644 --- a/drivers/uwb/wlp/wss-lc.c +++ b/drivers/uwb/wlp/wss-lc.c @@ -43,14 +43,11 @@ * wlp_wss_release() * wlp_wss_reset() */ - #include <linux/etherdevice.h> /* for is_valid_ether_addr */ #include <linux/skbuff.h> #include <linux/wlp.h> -#define D_LOCAL 5 -#include <linux/uwb/debug.h> -#include "wlp-internal.h" +#include "wlp-internal.h" size_t wlp_wss_key_print(char *buf, size_t bufsize, u8 *key) { @@ -116,9 +113,6 @@ struct uwb_mac_addr wlp_wss_sel_bcast_addr(struct wlp_wss *wss) */ void wlp_wss_reset(struct wlp_wss *wss) { - struct wlp *wlp = container_of(wss, struct wlp, wss); - struct device *dev = &wlp->rc->uwb_dev.dev; - d_fnstart(5, dev, "wss (%p) \n", wss); memset(&wss->wssid, 0, sizeof(wss->wssid)); wss->hash = 0; memset(&wss->name[0], 0, sizeof(wss->name)); @@ -127,7 +121,6 @@ void wlp_wss_reset(struct wlp_wss *wss) memset(&wss->master_key[0], 0, sizeof(wss->master_key)); wss->tag = 0; wss->state = WLP_WSS_STATE_NONE; - d_fnend(5, dev, "wss (%p) \n", wss); } /** @@ -145,7 +138,6 @@ int wlp_wss_sysfs_add(struct wlp_wss *wss, char *wssid_str) struct device *dev = &wlp->rc->uwb_dev.dev; int result; - d_fnstart(5, dev, "wss (%p), wssid: %s\n", wss, wssid_str); result = kobject_set_name(&wss->kobj, "wss-%s", wssid_str); if (result < 0) return result; @@ -162,7 +154,6 @@ int wlp_wss_sysfs_add(struct wlp_wss *wss, char *wssid_str) result); goto error_sysfs_create_group; } - d_fnend(5, dev, "Completed. result = %d \n", result); return 0; error_sysfs_create_group: @@ -214,22 +205,14 @@ int wlp_wss_enroll_target(struct wlp_wss *wss, struct wlp_uuid *wssid, struct wlp *wlp = container_of(wss, struct wlp, wss); struct device *dev = &wlp->rc->uwb_dev.dev; struct wlp_neighbor_e *neighbor; - char buf[WLP_WSS_UUID_STRSIZE]; int result = -ENXIO; struct uwb_dev_addr *dev_addr; - wlp_wss_uuid_print(buf, sizeof(buf), wssid); - d_fnstart(5, dev, "wss %p, wssid %s, registrar %02x:%02x \n", - wss, buf, dest->data[1], dest->data[0]); mutex_lock(&wlp->nbmutex); list_for_each_entry(neighbor, &wlp->neighbors, node) { dev_addr = &neighbor->uwb_dev->dev_addr; if (!memcmp(dest, dev_addr, sizeof(*dest))) { - d_printf(5, dev, "Neighbor %02x:%02x is valid, " - "enrolling. \n", - dev_addr->data[1], dev_addr->data[0]); - result = wlp_enroll_neighbor(wlp, neighbor, wss, - wssid); + result = wlp_enroll_neighbor(wlp, neighbor, wss, wssid); break; } } @@ -237,8 +220,6 @@ int wlp_wss_enroll_target(struct wlp_wss *wss, struct wlp_uuid *wssid, dev_err(dev, "WLP: Cannot find neighbor %02x:%02x. \n", dest->data[1], dest->data[0]); mutex_unlock(&wlp->nbmutex); - d_fnend(5, dev, "wss %p, wssid %s, registrar %02x:%02x, result %d \n", - wss, buf, dest->data[1], dest->data[0], result); return result; } @@ -260,16 +241,11 @@ int wlp_wss_enroll_discovered(struct wlp_wss *wss, struct wlp_uuid *wssid) char buf[WLP_WSS_UUID_STRSIZE]; int result = -ENXIO; - wlp_wss_uuid_print(buf, sizeof(buf), wssid); - d_fnstart(5, dev, "wss %p, wssid %s \n", wss, buf); + mutex_lock(&wlp->nbmutex); list_for_each_entry(neighbor, &wlp->neighbors, node) { list_for_each_entry(wssid_e, &neighbor->wssid, node) { if (!memcmp(wssid, &wssid_e->wssid, sizeof(*wssid))) { - d_printf(5, dev, "Found WSSID %s in neighbor " - "%02x:%02x cache. \n", buf, - neighbor->uwb_dev->dev_addr.data[1], - neighbor->uwb_dev->dev_addr.data[0]); result = wlp_enroll_neighbor(wlp, neighbor, wss, wssid); if (result == 0) /* enrollment success */ @@ -279,10 +255,11 @@ int wlp_wss_enroll_discovered(struct wlp_wss *wss, struct wlp_uuid *wssid) } } out: - if (result == -ENXIO) + if (result == -ENXIO) { + wlp_wss_uuid_print(buf, sizeof(buf), wssid); dev_err(dev, "WLP: Cannot find WSSID %s in cache. \n", buf); + } mutex_unlock(&wlp->nbmutex); - d_fnend(5, dev, "wss %p, wssid %s, result %d \n", wss, buf, result); return result; } @@ -307,27 +284,22 @@ int wlp_wss_enroll(struct wlp_wss *wss, struct wlp_uuid *wssid, struct uwb_dev_addr bcast = {.data = {0xff, 0xff} }; wlp_wss_uuid_print(buf, sizeof(buf), wssid); + if (wss->state != WLP_WSS_STATE_NONE) { dev_err(dev, "WLP: Already enrolled in WSS %s.\n", buf); result = -EEXIST; goto error; } - if (!memcmp(&bcast, devaddr, sizeof(bcast))) { - d_printf(5, dev, "Request to enroll in discovered WSS " - "with WSSID %s \n", buf); + if (!memcmp(&bcast, devaddr, sizeof(bcast))) result = wlp_wss_enroll_discovered(wss, wssid); - } else { - d_printf(5, dev, "Request to enroll in WSSID %s with " - "registrar %02x:%02x\n", buf, devaddr->data[1], - devaddr->data[0]); + else result = wlp_wss_enroll_target(wss, wssid, devaddr); - } if (result < 0) { dev_err(dev, "WLP: Unable to enroll into WSS %s, result %d \n", buf, result); goto error; } - d_printf(2, dev, "Successfully enrolled into WSS %s \n", buf); + dev_dbg(dev, "Successfully enrolled into WSS %s \n", buf); result = wlp_wss_sysfs_add(wss, buf); if (result < 0) { dev_err(dev, "WLP: Unable to set up sysfs for WSS kobject.\n"); @@ -363,7 +335,6 @@ int wlp_wss_activate(struct wlp_wss *wss) u8 hash; /* only include one hash */ } ie_data; - d_fnstart(5, dev, "Activating WSS %p. \n", wss); BUG_ON(wss->state != WLP_WSS_STATE_ENROLLED); wss->hash = wlp_wss_comp_wssid_hash(&wss->wssid); wss->tag = wss->hash; @@ -382,7 +353,6 @@ int wlp_wss_activate(struct wlp_wss *wss) wss->state = WLP_WSS_STATE_ACTIVE; result = 0; error_wlp_ie: - d_fnend(5, dev, "Activating WSS %p, result = %d \n", wss, result); return result; } @@ -405,7 +375,6 @@ int wlp_wss_enroll_activate(struct wlp_wss *wss, struct wlp_uuid *wssid, int result = 0; char buf[WLP_WSS_UUID_STRSIZE]; - d_fnstart(5, dev, "Enrollment and activation requested. \n"); mutex_lock(&wss->mutex); result = wlp_wss_enroll(wss, wssid, devaddr); if (result < 0) { @@ -424,7 +393,6 @@ int wlp_wss_enroll_activate(struct wlp_wss *wss, struct wlp_uuid *wssid, error_activate: error_enroll: mutex_unlock(&wss->mutex); - d_fnend(5, dev, "Completed. result = %d \n", result); return result; } @@ -447,11 +415,9 @@ int wlp_wss_create_activate(struct wlp_wss *wss, struct wlp_uuid *wssid, struct device *dev = &wlp->rc->uwb_dev.dev; int result = 0; char buf[WLP_WSS_UUID_STRSIZE]; - d_fnstart(5, dev, "Request to create new WSS.\n"); + result = wlp_wss_uuid_print(buf, sizeof(buf), wssid); - d_printf(5, dev, "Request to create WSS: WSSID=%s, name=%s, " - "sec_status=%u, accepting enrollment=%u \n", - buf, name, sec_status, accept); + if (!mutex_trylock(&wss->mutex)) { dev_err(dev, "WLP: WLP association session in progress.\n"); return -EBUSY; @@ -498,7 +464,6 @@ int wlp_wss_create_activate(struct wlp_wss *wss, struct wlp_uuid *wssid, result = 0; out: mutex_unlock(&wss->mutex); - d_fnend(5, dev, "Completed. result = %d \n", result); return result; } @@ -520,16 +485,12 @@ int wlp_wss_is_active(struct wlp *wlp, struct wlp_wss *wss, { int result = 0; struct device *dev = &wlp->rc->uwb_dev.dev; - char buf[WLP_WSS_UUID_STRSIZE]; DECLARE_COMPLETION_ONSTACK(completion); struct wlp_session session; struct sk_buff *skb; struct wlp_frame_assoc *resp; struct wlp_uuid wssid; - wlp_wss_uuid_print(buf, sizeof(buf), &wss->wssid); - d_fnstart(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", - wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); mutex_lock(&wlp->mutex); /* Send C1 association frame */ result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C1); @@ -565,8 +526,6 @@ int wlp_wss_is_active(struct wlp *wlp, struct wlp_wss *wss, /* Parse message in session->data: it will be either C2 or F0 */ skb = session.data; resp = (void *) skb->data; - d_printf(5, dev, "Received response to C1 frame. \n"); - d_dump(5, dev, skb->data, skb->len > 72 ? 72 : skb->len); if (resp->type == WLP_ASSOC_F0) { result = wlp_parse_f0(wlp, skb); if (result < 0) @@ -584,11 +543,9 @@ int wlp_wss_is_active(struct wlp *wlp, struct wlp_wss *wss, result = 0; goto error_resp_parse; } - if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))) { - d_printf(5, dev, "WSSID in C2 frame matches local " - "active WSS.\n"); + if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))) result = 1; - } else { + else { dev_err(dev, "WLP: Received a C2 frame without matching " "WSSID.\n"); result = 0; @@ -598,8 +555,6 @@ error_resp_parse: out: wlp->session = NULL; mutex_unlock(&wlp->mutex); - d_fnend(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", - wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); return result; } @@ -620,16 +575,8 @@ int wlp_wss_activate_connection(struct wlp *wlp, struct wlp_wss *wss, { struct device *dev = &wlp->rc->uwb_dev.dev; int result = 0; - char buf[WLP_WSS_UUID_STRSIZE]; - wlp_wss_uuid_print(buf, sizeof(buf), wssid); - d_fnstart(5, dev, "wlp %p, wss %p, wssid %s, tag %u, virtual " - "%02x:%02x:%02x:%02x:%02x:%02x \n", wlp, wss, buf, *tag, - virt_addr->data[0], virt_addr->data[1], virt_addr->data[2], - virt_addr->data[3], virt_addr->data[4], virt_addr->data[5]); if (!memcmp(wssid, &wss->wssid, sizeof(*wssid))) { - d_printf(5, dev, "WSSID from neighbor frame matches local " - "active WSS.\n"); /* Update EDA cache */ result = wlp_eda_update_node(&wlp->eda, dev_addr, wss, (void *) virt_addr->data, *tag, @@ -638,18 +585,9 @@ int wlp_wss_activate_connection(struct wlp *wlp, struct wlp_wss *wss, dev_err(dev, "WLP: Unable to update EDA cache " "with new connected neighbor information.\n"); } else { - dev_err(dev, "WLP: Neighbor does not have matching " - "WSSID.\n"); + dev_err(dev, "WLP: Neighbor does not have matching WSSID.\n"); result = -EINVAL; } - - d_fnend(5, dev, "wlp %p, wss %p, wssid %s, tag %u, virtual " - "%02x:%02x:%02x:%02x:%02x:%02x, result = %d \n", - wlp, wss, buf, *tag, - virt_addr->data[0], virt_addr->data[1], virt_addr->data[2], - virt_addr->data[3], virt_addr->data[4], virt_addr->data[5], - result); - return result; } @@ -665,7 +603,6 @@ int wlp_wss_connect_neighbor(struct wlp *wlp, struct wlp_wss *wss, { int result; struct device *dev = &wlp->rc->uwb_dev.dev; - char buf[WLP_WSS_UUID_STRSIZE]; struct wlp_uuid wssid; u8 tag; struct uwb_mac_addr virt_addr; @@ -674,9 +611,6 @@ int wlp_wss_connect_neighbor(struct wlp *wlp, struct wlp_wss *wss, struct wlp_frame_assoc *resp; struct sk_buff *skb; - wlp_wss_uuid_print(buf, sizeof(buf), &wss->wssid); - d_fnstart(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", - wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); mutex_lock(&wlp->mutex); /* Send C3 association frame */ result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C3); @@ -711,8 +645,6 @@ int wlp_wss_connect_neighbor(struct wlp *wlp, struct wlp_wss *wss, /* Parse message in session->data: it will be either C4 or F0 */ skb = session.data; resp = (void *) skb->data; - d_printf(5, dev, "Received response to C3 frame. \n"); - d_dump(5, dev, skb->data, skb->len > 72 ? 72 : skb->len); if (resp->type == WLP_ASSOC_F0) { result = wlp_parse_f0(wlp, skb); if (result < 0) @@ -744,8 +676,6 @@ out: WLP_WSS_CONNECT_FAILED); wlp->session = NULL; mutex_unlock(&wlp->mutex); - d_fnend(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", - wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); return result; } @@ -780,12 +710,8 @@ void wlp_wss_connect_send(struct work_struct *ws) struct wlp_wss *wss = &wlp->wss; int result; struct device *dev = &wlp->rc->uwb_dev.dev; - char buf[WLP_WSS_UUID_STRSIZE]; mutex_lock(&wss->mutex); - wlp_wss_uuid_print(buf, sizeof(buf), &wss->wssid); - d_fnstart(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", - wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); if (wss->state < WLP_WSS_STATE_ACTIVE) { if (printk_ratelimit()) dev_err(dev, "WLP: Attempting to connect with " @@ -836,7 +762,6 @@ out: BUG_ON(wlp->start_queue == NULL); wlp->start_queue(wlp); mutex_unlock(&wss->mutex); - d_fnend(5, dev, "wlp %p, wss %p (wssid %s)\n", wlp, wss, buf); } /** @@ -855,7 +780,6 @@ int wlp_wss_prep_hdr(struct wlp *wlp, struct wlp_eda_node *eda_entry, struct sk_buff *skb = _skb; struct wlp_frame_std_abbrv_hdr *std_hdr; - d_fnstart(6, dev, "wlp %p \n", wlp); if (eda_entry->state == WLP_WSS_CONNECTED) { /* Add WLP header */ BUG_ON(skb_headroom(skb) < sizeof(*std_hdr)); @@ -873,7 +797,6 @@ int wlp_wss_prep_hdr(struct wlp *wlp, struct wlp_eda_node *eda_entry, dev_addr->data[0]); result = -EINVAL; } - d_fnend(6, dev, "wlp %p \n", wlp); return result; } @@ -893,16 +816,9 @@ int wlp_wss_connect_prep(struct wlp *wlp, struct wlp_eda_node *eda_entry, { int result = 0; struct device *dev = &wlp->rc->uwb_dev.dev; - struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr; - unsigned char *eth_addr = eda_entry->eth_addr; struct sk_buff *skb = _skb; struct wlp_assoc_conn_ctx *conn_ctx; - d_fnstart(5, dev, "wlp %p\n", wlp); - d_printf(5, dev, "To neighbor %02x:%02x with eth " - "%02x:%02x:%02x:%02x:%02x:%02x\n", dev_addr->data[1], - dev_addr->data[0], eth_addr[0], eth_addr[1], eth_addr[2], - eth_addr[3], eth_addr[4], eth_addr[5]); if (eda_entry->state == WLP_WSS_UNCONNECTED) { /* We don't want any more packets while we set up connection */ BUG_ON(wlp->stop_queue == NULL); @@ -929,12 +845,9 @@ int wlp_wss_connect_prep(struct wlp *wlp, struct wlp_eda_node *eda_entry, "previously. Not retrying. \n"); result = -ENONET; goto out; - } else { /* eda_entry->state == WLP_WSS_CONNECTED */ - d_printf(5, dev, "Neighbor is connected, preparing frame.\n"); + } else /* eda_entry->state == WLP_WSS_CONNECTED */ result = wlp_wss_prep_hdr(wlp, eda_entry, skb); - } out: - d_fnend(5, dev, "wlp %p, result = %d \n", wlp, result); return result; } @@ -957,8 +870,6 @@ int wlp_wss_send_copy(struct wlp *wlp, struct wlp_eda_node *eda_entry, struct sk_buff *copy; struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr; - d_fnstart(5, dev, "to neighbor %02x:%02x, skb (%p) \n", - dev_addr->data[1], dev_addr->data[0], skb); copy = skb_copy(skb, GFP_ATOMIC); if (copy == NULL) { if (printk_ratelimit()) @@ -988,8 +899,6 @@ int wlp_wss_send_copy(struct wlp *wlp, struct wlp_eda_node *eda_entry, dev_kfree_skb_irq(copy);/*we need to free if tx fails */ } out: - d_fnend(5, dev, "to neighbor %02x:%02x \n", dev_addr->data[1], - dev_addr->data[0]); return result; } @@ -1005,7 +914,7 @@ int wlp_wss_setup(struct net_device *net_dev, struct wlp_wss *wss) struct wlp *wlp = container_of(wss, struct wlp, wss); struct device *dev = &wlp->rc->uwb_dev.dev; int result = 0; - d_fnstart(5, dev, "wss (%p) \n", wss); + mutex_lock(&wss->mutex); wss->kobj.parent = &net_dev->dev.kobj; if (!is_valid_ether_addr(net_dev->dev_addr)) { @@ -1018,7 +927,6 @@ int wlp_wss_setup(struct net_device *net_dev, struct wlp_wss *wss) sizeof(wss->virtual_addr.data)); out: mutex_unlock(&wss->mutex); - d_fnend(5, dev, "wss (%p) \n", wss); return result; } EXPORT_SYMBOL_GPL(wlp_wss_setup); @@ -1035,8 +943,7 @@ EXPORT_SYMBOL_GPL(wlp_wss_setup); void wlp_wss_remove(struct wlp_wss *wss) { struct wlp *wlp = container_of(wss, struct wlp, wss); - struct device *dev = &wlp->rc->uwb_dev.dev; - d_fnstart(5, dev, "wss (%p) \n", wss); + mutex_lock(&wss->mutex); if (wss->state == WLP_WSS_STATE_ACTIVE) uwb_rc_ie_rm(wlp->rc, UWB_IE_WLP); @@ -1050,6 +957,5 @@ void wlp_wss_remove(struct wlp_wss *wss) wlp_eda_release(&wlp->eda); wlp_eda_init(&wlp->eda); mutex_unlock(&wss->mutex); - d_fnend(5, dev, "wss (%p) \n", wss); } EXPORT_SYMBOL_GPL(wlp_wss_remove); diff --git a/include/linux/usb/wusb-wa.h b/include/linux/usb/wusb-wa.h index a102561..fb7c359 100644 --- a/include/linux/usb/wusb-wa.h +++ b/include/linux/usb/wusb-wa.h @@ -51,6 +51,7 @@ enum { WUSB_REQ_GET_TIME = 25, WUSB_REQ_SET_STREAM_IDX = 26, WUSB_REQ_SET_WUSB_MAS = 27, + WUSB_REQ_CHAN_STOP = 28, }; diff --git a/include/linux/uwb.h b/include/linux/uwb.h index f9ccbd9..c021289 100644 --- a/include/linux/uwb.h +++ b/include/linux/uwb.h @@ -30,6 +30,7 @@ #include <linux/device.h> #include <linux/mutex.h> #include <linux/timer.h> +#include <linux/wait.h> #include <linux/workqueue.h> #include <linux/uwb/spec.h> @@ -66,6 +67,7 @@ struct uwb_dev { struct uwb_dev_addr dev_addr; int beacon_slot; DECLARE_BITMAP(streams, UWB_NUM_STREAMS); + DECLARE_BITMAP(last_availability_bm, UWB_NUM_MAS); }; #define to_uwb_dev(d) container_of(d, struct uwb_dev, dev) @@ -86,12 +88,31 @@ struct uwb_notifs_chain { struct mutex mutex; }; +/* Beacon cache list */ +struct uwb_beca { + struct list_head list; + size_t entries; + struct mutex mutex; +}; + +/* Event handling thread. */ +struct uwbd { + int pid; + struct task_struct *task; + wait_queue_head_t wq; + struct list_head event_list; + spinlock_t event_list_lock; +}; + /** * struct uwb_mas_bm - a bitmap of all MAS in a superframe * @bm: a bitmap of length #UWB_NUM_MAS */ struct uwb_mas_bm { DECLARE_BITMAP(bm, UWB_NUM_MAS); + DECLARE_BITMAP(unsafe_bm, UWB_NUM_MAS); + int safe; + int unsafe; }; /** @@ -117,14 +138,24 @@ struct uwb_mas_bm { * FIXME: further target states TBD. */ enum uwb_rsv_state { - UWB_RSV_STATE_NONE, + UWB_RSV_STATE_NONE = 0, UWB_RSV_STATE_O_INITIATED, UWB_RSV_STATE_O_PENDING, UWB_RSV_STATE_O_MODIFIED, UWB_RSV_STATE_O_ESTABLISHED, + UWB_RSV_STATE_O_TO_BE_MOVED, + UWB_RSV_STATE_O_MOVE_EXPANDING, + UWB_RSV_STATE_O_MOVE_COMBINING, + UWB_RSV_STATE_O_MOVE_REDUCING, UWB_RSV_STATE_T_ACCEPTED, UWB_RSV_STATE_T_DENIED, + UWB_RSV_STATE_T_CONFLICT, UWB_RSV_STATE_T_PENDING, + UWB_RSV_STATE_T_EXPANDING_ACCEPTED, + UWB_RSV_STATE_T_EXPANDING_CONFLICT, + UWB_RSV_STATE_T_EXPANDING_PENDING, + UWB_RSV_STATE_T_EXPANDING_DENIED, + UWB_RSV_STATE_T_RESIZED, UWB_RSV_STATE_LAST, }; @@ -149,6 +180,12 @@ struct uwb_rsv_target { }; }; +struct uwb_rsv_move { + struct uwb_mas_bm final_mas; + struct uwb_ie_drp *companion_drp_ie; + struct uwb_mas_bm companion_mas; +}; + /* * Number of streams reserved for reservations targeted at DevAddrs. */ @@ -186,6 +223,7 @@ typedef void (*uwb_rsv_cb_f)(struct uwb_rsv *rsv); * * @status: negotiation status * @stream: stream index allocated for this reservation + * @tiebreaker: conflict tiebreaker for this reservation * @mas: reserved MAS * @drp_ie: the DRP IE * @ie_valid: true iff the DRP IE matches the reservation parameters @@ -201,25 +239,29 @@ struct uwb_rsv { struct uwb_rc *rc; struct list_head rc_node; struct list_head pal_node; + struct kref kref; struct uwb_dev *owner; struct uwb_rsv_target target; enum uwb_drp_type type; int max_mas; int min_mas; - int sparsity; + int max_interval; bool is_multicast; uwb_rsv_cb_f callback; void *pal_priv; enum uwb_rsv_state state; + bool needs_release_companion_mas; u8 stream; + u8 tiebreaker; struct uwb_mas_bm mas; struct uwb_ie_drp *drp_ie; + struct uwb_rsv_move mv; bool ie_valid; struct timer_list timer; - bool expired; + struct work_struct handle_timeout_work; }; static const @@ -261,6 +303,13 @@ struct uwb_drp_avail { bool ie_valid; }; +struct uwb_drp_backoff_win { + u8 window; + u8 n; + int total_expired; + struct timer_list timer; + bool can_reserve_extra_mases; +}; const char *uwb_rsv_state_str(enum uwb_rsv_state state); const char *uwb_rsv_type_str(enum uwb_drp_type type); @@ -276,6 +325,8 @@ void uwb_rsv_terminate(struct uwb_rsv *rsv); void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv); +void uwb_rsv_get_usable_mas(struct uwb_rsv *orig_rsv, struct uwb_mas_bm *mas); + /** * Radio Control Interface instance * @@ -337,23 +388,33 @@ struct uwb_rc { u8 ctx_roll; int beaconing; /* Beaconing state [channel number] */ + int beaconing_forced; int scanning; enum uwb_scan_type scan_type:3; unsigned ready:1; struct uwb_notifs_chain notifs_chain; + struct uwb_beca uwb_beca; + + struct uwbd uwbd; + struct uwb_drp_backoff_win bow; struct uwb_drp_avail drp_avail; struct list_head reservations; + struct list_head cnflt_alien_list; + struct uwb_mas_bm cnflt_alien_bitmap; struct mutex rsvs_mutex; + spinlock_t rsvs_lock; struct workqueue_struct *rsv_workq; - struct work_struct rsv_update_work; + struct delayed_work rsv_update_work; + struct delayed_work rsv_alien_bp_work; + int set_drp_ie_pending; struct mutex ies_mutex; struct uwb_rc_cmd_set_ie *ies; size_t ies_capacity; - spinlock_t pal_lock; struct list_head pals; + int active_pals; struct uwb_dbg *dbg; }; @@ -361,11 +422,19 @@ struct uwb_rc { /** * struct uwb_pal - a UWB PAL - * @name: descriptive name for this PAL (wushc, wlp, etc.). + * @name: descriptive name for this PAL (wusbhc, wlp, etc.). * @device: a device for the PAL. Used to link the PAL and the radio * controller in sysfs. + * @rc: the radio controller the PAL uses. + * @channel_changed: called when the channel used by the radio changes. + * A channel of -1 means the channel has been stopped. * @new_rsv: called when a peer requests a reservation (may be NULL if * the PAL cannot accept reservation requests). + * @channel: channel being used by the PAL; 0 if the PAL isn't using + * the radio; -1 if the PAL wishes to use the radio but + * cannot. + * @debugfs_dir: a debugfs directory which the PAL can use for its own + * debugfs files. * * A Protocol Adaptation Layer (PAL) is a user of the WiMedia UWB * radio platform (e.g., WUSB, WLP or Bluetooth UWB AMP). @@ -384,12 +453,21 @@ struct uwb_pal { struct list_head node; const char *name; struct device *device; - void (*new_rsv)(struct uwb_rsv *rsv); + struct uwb_rc *rc; + + void (*channel_changed)(struct uwb_pal *pal, int channel); + void (*new_rsv)(struct uwb_pal *pal, struct uwb_rsv *rsv); + + int channel; + struct dentry *debugfs_dir; }; void uwb_pal_init(struct uwb_pal *pal); -int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal); -void uwb_pal_unregister(struct uwb_rc *rc, struct uwb_pal *pal); +int uwb_pal_register(struct uwb_pal *pal); +void uwb_pal_unregister(struct uwb_pal *pal); + +int uwb_radio_start(struct uwb_pal *pal); +void uwb_radio_stop(struct uwb_pal *pal); /* * General public API @@ -443,8 +521,6 @@ ssize_t uwb_rc_vcmd(struct uwb_rc *rc, const char *cmd_name, struct uwb_rccb *cmd, size_t cmd_size, u8 expected_type, u16 expected_event, struct uwb_rceb **preply); -ssize_t uwb_rc_get_ie(struct uwb_rc *, struct uwb_rc_evt_get_ie **); -int uwb_bg_joined(struct uwb_rc *rc); size_t __uwb_addr_print(char *, size_t, const unsigned char *, int); @@ -520,6 +596,8 @@ void uwb_rc_rm(struct uwb_rc *); void uwb_rc_neh_grok(struct uwb_rc *, void *, size_t); void uwb_rc_neh_error(struct uwb_rc *, int); void uwb_rc_reset_all(struct uwb_rc *rc); +void uwb_rc_pre_reset(struct uwb_rc *rc); +void uwb_rc_post_reset(struct uwb_rc *rc); /** * uwb_rsv_is_owner - is the owner of this reservation the RC? @@ -531,7 +609,9 @@ static inline bool uwb_rsv_is_owner(struct uwb_rsv *rsv) } /** - * Events generated by UWB that can be passed to any listeners + * enum uwb_notifs - UWB events that can be passed to any listeners + * @UWB_NOTIF_ONAIR: a new neighbour has joined the beacon group. + * @UWB_NOTIF_OFFAIR: a neighbour has left the beacon group. * * Higher layers can register callback functions with the radio * controller using uwb_notifs_register(). The radio controller @@ -539,8 +619,6 @@ static inline bool uwb_rsv_is_owner(struct uwb_rsv *rsv) * nodes when an event occurs. */ enum uwb_notifs { - UWB_NOTIF_BG_JOIN = 0, /* radio controller joined a beacon group */ - UWB_NOTIF_BG_LEAVE = 1, /* radio controller left a beacon group */ UWB_NOTIF_ONAIR, UWB_NOTIF_OFFAIR, }; @@ -652,22 +730,9 @@ static inline int edc_inc(struct edc *err_hist, u16 max_err, u16 timeframe) /* Information Element handling */ -/* For representing the state of writing to a buffer when iterating */ -struct uwb_buf_ctx { - char *buf; - size_t bytes, size; -}; - -typedef int (*uwb_ie_f)(struct uwb_dev *, const struct uwb_ie_hdr *, - size_t, void *); struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len); -ssize_t uwb_ie_for_each(struct uwb_dev *uwb_dev, uwb_ie_f fn, void *data, - const void *buf, size_t size); -int uwb_ie_dump_hex(struct uwb_dev *, const struct uwb_ie_hdr *, - size_t, void *); -int uwb_rc_set_ie(struct uwb_rc *, struct uwb_rc_cmd_set_ie *); -struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len); - +int uwb_rc_ie_add(struct uwb_rc *uwb_rc, const struct uwb_ie_hdr *ies, size_t size); +int uwb_rc_ie_rm(struct uwb_rc *uwb_rc, enum uwb_ie element_id); /* * Transmission statistics diff --git a/include/linux/uwb/debug-cmd.h b/include/linux/uwb/debug-cmd.h index 1141f41..8da004e 100644 --- a/include/linux/uwb/debug-cmd.h +++ b/include/linux/uwb/debug-cmd.h @@ -32,6 +32,10 @@ enum uwb_dbg_cmd_type { UWB_DBG_CMD_RSV_ESTABLISH = 1, UWB_DBG_CMD_RSV_TERMINATE = 2, + UWB_DBG_CMD_IE_ADD = 3, + UWB_DBG_CMD_IE_RM = 4, + UWB_DBG_CMD_RADIO_START = 5, + UWB_DBG_CMD_RADIO_STOP = 6, }; struct uwb_dbg_cmd_rsv_establish { @@ -39,18 +43,25 @@ struct uwb_dbg_cmd_rsv_establish { __u8 type; __u16 max_mas; __u16 min_mas; - __u8 sparsity; + __u8 max_interval; }; struct uwb_dbg_cmd_rsv_terminate { int index; }; +struct uwb_dbg_cmd_ie { + __u8 data[128]; + int len; +}; + struct uwb_dbg_cmd { __u32 type; union { struct uwb_dbg_cmd_rsv_establish rsv_establish; struct uwb_dbg_cmd_rsv_terminate rsv_terminate; + struct uwb_dbg_cmd_ie ie_add; + struct uwb_dbg_cmd_ie ie_rm; }; }; diff --git a/include/linux/uwb/debug.h b/include/linux/uwb/debug.h deleted file mode 100644 index a86a73f..0000000 --- a/include/linux/uwb/debug.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Ultra Wide Band - * Debug Support - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> - * - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: doc - * Invoke like: - * - * #define D_LOCAL 4 - * #include <linux/uwb/debug.h> - * - * At the end of your include files. - */ -#include <linux/types.h> - -struct device; -extern void dump_bytes(struct device *dev, const void *_buf, size_t rsize); - -/* Master debug switch; !0 enables, 0 disables */ -#define D_MASTER (!0) - -/* Local (per-file) debug switch; #define before #including */ -#ifndef D_LOCAL -#define D_LOCAL 0 -#endif - -#undef __d_printf -#undef d_fnstart -#undef d_fnend -#undef d_printf -#undef d_dump - -#define __d_printf(l, _tag, _dev, f, a...) \ -do { \ - struct device *__dev = (_dev); \ - if (D_MASTER && D_LOCAL >= (l)) { \ - char __head[64] = ""; \ - if (_dev != NULL) { \ - if ((unsigned long)__dev < 4096) \ - printk(KERN_ERR "E: Corrupt dev %p\n", \ - __dev); \ - else \ - snprintf(__head, sizeof(__head), \ - "%s %s: ", \ - dev_driver_string(__dev), \ - __dev->bus_id); \ - } \ - printk(KERN_ERR "%s%s" _tag ": " f, __head, \ - __func__, ## a); \ - } \ -} while (0 && _dev) - -#define d_fnstart(l, _dev, f, a...) \ - __d_printf(l, " FNSTART", _dev, f, ## a) -#define d_fnend(l, _dev, f, a...) \ - __d_printf(l, " FNEND", _dev, f, ## a) -#define d_printf(l, _dev, f, a...) \ - __d_printf(l, "", _dev, f, ## a) -#define d_dump(l, _dev, ptr, size) \ -do { \ - struct device *__dev = _dev; \ - if (D_MASTER && D_LOCAL >= (l)) \ - dump_bytes(__dev, ptr, size); \ -} while (0 && _dev) -#define d_test(l) (D_MASTER && D_LOCAL >= (l)) diff --git a/include/linux/uwb/spec.h b/include/linux/uwb/spec.h index 198c15f..b52e44f 100644 --- a/include/linux/uwb/spec.h +++ b/include/linux/uwb/spec.h @@ -59,6 +59,11 @@ enum { UWB_NUM_ZONES = 16 }; #define UWB_MAS_PER_ZONE (UWB_NUM_MAS / UWB_NUM_ZONES) /* + * Number of MAS required before a row can be considered available. + */ +#define UWB_USABLE_MAS_PER_ROW (UWB_NUM_ZONES - 1) + +/* * Number of streams per DRP reservation between a pair of devices. * * [ECMA-368] section 16.8.6. @@ -94,6 +99,26 @@ enum { UWB_BEACON_SLOT_LENGTH_US = 85 }; enum { UWB_MAX_LOST_BEACONS = 3 }; /* + * mDRPBackOffWinMin + * + * The minimum number of superframes to wait before trying to reserve + * extra MAS. + * + * [ECMA-368] section 17.16 + */ +enum { UWB_DRP_BACKOFF_WIN_MIN = 2 }; + +/* + * mDRPBackOffWinMax + * + * The maximum number of superframes to wait before trying to reserve + * extra MAS. + * + * [ECMA-368] section 17.16 + */ +enum { UWB_DRP_BACKOFF_WIN_MAX = 16 }; + +/* * Length of a superframe in microseconds. */ #define UWB_SUPERFRAME_LENGTH_US (UWB_MAS_LENGTH_US * UWB_NUM_MAS) @@ -200,6 +225,12 @@ enum uwb_drp_reason { UWB_DRP_REASON_MODIFIED, }; +/** Relinquish Request Reason Codes ([ECMA-368] table 113) */ +enum uwb_relinquish_req_reason { + UWB_RELINQUISH_REQ_REASON_NON_SPECIFIC = 0, + UWB_RELINQUISH_REQ_REASON_OVER_ALLOCATION, +}; + /** * DRP Notification Reason Codes (WHCI 0.95 [3.1.4.9]) */ @@ -252,6 +283,7 @@ enum uwb_ie { UWB_APP_SPEC_PROBE_IE = 15, UWB_IDENTIFICATION_IE = 19, UWB_MASTER_KEY_ID_IE = 20, + UWB_RELINQUISH_REQUEST_IE = 21, UWB_IE_WLP = 250, /* WiMedia Logical Link Control Protocol WLP 0.99 */ UWB_APP_SPEC_IE = 255, }; @@ -365,6 +397,27 @@ struct uwb_ie_drp_avail { DECLARE_BITMAP(bmp, UWB_NUM_MAS); } __attribute__((packed)); +/* Relinqish Request IE ([ECMA-368] section 16.8.19). */ +struct uwb_relinquish_request_ie { + struct uwb_ie_hdr hdr; + __le16 relinquish_req_control; + struct uwb_dev_addr dev_addr; + struct uwb_drp_alloc allocs[]; +} __attribute__((packed)); + +static inline int uwb_ie_relinquish_req_reason_code(struct uwb_relinquish_request_ie *ie) +{ + return (le16_to_cpu(ie->relinquish_req_control) >> 0) & 0xf; +} + +static inline void uwb_ie_relinquish_req_set_reason_code(struct uwb_relinquish_request_ie *ie, + int reason_code) +{ + u16 ctrl = le16_to_cpu(ie->relinquish_req_control); + ctrl = (ctrl & ~(0xf << 0)) | (reason_code << 0); + ie->relinquish_req_control = cpu_to_le16(ctrl); +} + /** * The Vendor ID is set to an OUI that indicates the vendor of the device. * ECMA-368 [16.8.10] diff --git a/include/linux/uwb/umc.h b/include/linux/uwb/umc.h index 36a39e3..4b4fc0f 100644 --- a/include/linux/uwb/umc.h +++ b/include/linux/uwb/umc.h @@ -89,6 +89,8 @@ struct umc_driver { void (*remove)(struct umc_dev *); int (*suspend)(struct umc_dev *, pm_message_t state); int (*resume)(struct umc_dev *); + int (*pre_reset)(struct umc_dev *); + int (*post_reset)(struct umc_dev *); struct device_driver driver; }; diff --git a/include/linux/wlp.h b/include/linux/wlp.h index 033545e..ac95ce6 100644 --- a/include/linux/wlp.h +++ b/include/linux/wlp.h @@ -646,6 +646,7 @@ struct wlp_wss { struct wlp { struct mutex mutex; struct uwb_rc *rc; /* UWB radio controller */ + struct net_device *ndev; struct uwb_pal pal; struct wlp_eda eda; struct wlp_uuid uuid; @@ -675,7 +676,7 @@ struct wlp_wss_attribute { static struct wlp_wss_attribute wss_attr_##_name = __ATTR(_name, _mode, \ _show, _store) -extern int wlp_setup(struct wlp *, struct uwb_rc *); +extern int wlp_setup(struct wlp *, struct uwb_rc *, struct net_device *ndev); extern void wlp_remove(struct wlp *); extern ssize_t wlp_neighborhood_show(struct wlp *, char *); extern int wlp_wss_setup(struct net_device *, struct wlp_wss *); |