Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80618fa8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/dvrabel/uwb: (31 commits)
  uwb: remove beacon cache entry after calling uwb_notify()
  uwb: remove unused include/linux/uwb/debug.h
  uwb: use print_hex_dump()
  uwb: use dev_dbg() for debug messages
  uwb: fix memory leak in uwb_rc_notif()
  wusb: fix oops when terminating a non-existant reservation
  uwb: fix oops when terminating an already terminated reservation
  uwb: improved MAS allocator and reservation conflict handling
  wusb: add debug files for ASL, PZL and DI to the whci-hcd driver
  uwb: fix oops in debug PAL's reservation callback
  uwb: clean up whci_wait_for() timeout error message
  wusb: whci-hcd shouldn't do ASL/PZL updates while channel is inactive
  uwb: remove unused beacon group join/leave events
  wlp: start/stop radio on network interface up/down
  uwb: add basic radio manager
  uwb: add pal parameter to new reservation callback
  uwb: fix races between events and neh timers
  uwb: don't unbind the radio controller driver when resetting
  uwb: per-radio controller event thread and beacon cache
  uwb: add commands to add/remove IEs to the debug interface
  ...
parents 92cde4d5 b21a2071
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -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
+0 −9
Original line number Diff line number Diff line
@@ -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)
+55 −104
Original line number Diff line number Diff line
@@ -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 @@ static int hwahc_op_start(struct usb_hcd *usb_hcd)

}

/*
 * 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,7 +552,7 @@ 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: "
		dev_dbg(dev, "Extra device descriptor: "
			"type %02x/%u bytes @ %zu (%zu left)\n",
			hdr->bDescriptorType, hdr->bLength,
			(itr - usb_dev->rawdescriptors[actconfig_idx]),
@@ -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 @@ static int hwahc_probe(struct usb_interface *usb_iface,
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);

+1 −0
Original line number Diff line number Diff line
@@ -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	\
+18 −28
Original line number Diff line number Diff line
@@ -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,12 +158,27 @@ 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)
{
	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);
}

/**
 * scan_async_work - scan the ASL for qsets to process.
@@ -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) {
Loading