aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-class-uwb_rc14
-rw-r--r--Documentation/usb/wusb-cbaf9
-rw-r--r--drivers/usb/host/hwa-hc.c1
-rw-r--r--drivers/usb/host/whci/hcd.c2
-rw-r--r--drivers/usb/wusbcore/devconnect.c5
-rw-r--r--drivers/usb/wusbcore/mmc.c75
-rw-r--r--drivers/usb/wusbcore/pal.c16
-rw-r--r--drivers/usb/wusbcore/wusbhc.h8
-rw-r--r--drivers/uwb/Makefile1
-rw-r--r--drivers/uwb/beacon.c26
-rw-r--r--drivers/uwb/drp.c24
-rw-r--r--drivers/uwb/lc-rc.c11
-rw-r--r--drivers/uwb/pal.c20
-rw-r--r--drivers/uwb/radio.c202
-rw-r--r--drivers/uwb/reset.c6
-rw-r--r--drivers/uwb/rsv.c4
-rw-r--r--drivers/uwb/uwb-debug.c26
-rw-r--r--drivers/uwb/uwb-internal.h5
-rw-r--r--drivers/uwb/wlp/wlp-lc.c5
-rw-r--r--include/linux/uwb.h23
-rw-r--r--include/linux/uwb/debug-cmd.h2
21 files changed, 323 insertions, 162 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-uwb_rc b/Documentation/ABI/testing/sysfs-class-uwb_rc
index a0d18dbeb7a..6a5fd072849 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
32Description: 32Description:
33 Write: 33 Write:
34 34
35 <channel> [<bpst offset>] 35 <channel>
36 36
37 to start beaconing on a specific channel, or stop 37 to force a specific channel to be used when beaconing,
38 beaconing if <channel> is -1. Valid channels depends 38 or, if <channel> is -1, to prohibit beaconing. If
39 on the radio controller's supported band groups. 39 <channel> is 0, then the default channel selection
40 algorithm will be used. Valid channels depends on the
41 radio controller's supported band groups.
40 42
41 <bpst offset> may be used to try and join a specific 43 Reading returns the currently active channel, or -1 if
42 beacon group if more than one was found during a scan. 44 the radio controller is not beaconing.
43 45
44What: /sys/class/uwb_rc/uwbN/scan 46What: /sys/class/uwb_rc/uwbN/scan
45Date: July 2008 47Date: July 2008
diff --git a/Documentation/usb/wusb-cbaf b/Documentation/usb/wusb-cbaf
index 2e78b70f3ad..426ddaaef96 100644
--- a/Documentation/usb/wusb-cbaf
+++ b/Documentation/usb/wusb-cbaf
@@ -80,12 +80,6 @@ case $1 in
80 start) 80 start)
81 for dev in ${2:-$hdevs} 81 for dev in ${2:-$hdevs}
82 do 82 do
83 uwb_rc=$(readlink -f $dev/uwb_rc)
84 if cat $uwb_rc/beacon | grep -q -- "-1"
85 then
86 echo 13 0 > $uwb_rc/beacon
87 echo I: started beaconing on ch 13 on $(basename $uwb_rc) >&2
88 fi
89 echo $host_CHID > $dev/wusb_chid 83 echo $host_CHID > $dev/wusb_chid
90 echo I: started host $(basename $dev) >&2 84 echo I: started host $(basename $dev) >&2
91 done 85 done
@@ -95,9 +89,6 @@ case $1 in
95 do 89 do
96 echo 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > $dev/wusb_chid 90 echo 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > $dev/wusb_chid
97 echo I: stopped host $(basename $dev) >&2 91 echo I: stopped host $(basename $dev) >&2
98 uwb_rc=$(readlink -f $dev/uwb_rc)
99 echo -1 | cat > $uwb_rc/beacon
100 echo I: stopped beaconing on $(basename $uwb_rc) >&2
101 done 92 done
102 ;; 93 ;;
103 set-chid) 94 set-chid)
diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
index 2827353e97e..2a4d36fa70b 100644
--- a/drivers/usb/host/hwa-hc.c
+++ b/drivers/usb/host/hwa-hc.c
@@ -221,7 +221,6 @@ static void hwahc_op_stop(struct usb_hcd *usb_hcd)
221 221
222 d_fnstart(4, dev, "(hwahc %p)\n", hwahc); 222 d_fnstart(4, dev, "(hwahc %p)\n", hwahc);
223 mutex_lock(&wusbhc->mutex); 223 mutex_lock(&wusbhc->mutex);
224 wusbhc_stop(wusbhc);
225 wusb_cluster_id_put(wusbhc->cluster_id); 224 wusb_cluster_id_put(wusbhc->cluster_id);
226 mutex_unlock(&wusbhc->mutex); 225 mutex_unlock(&wusbhc->mutex);
227 d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); 226 d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result);
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c
index de1e07271b8..f599f89d3be 100644
--- a/drivers/usb/host/whci/hcd.c
+++ b/drivers/usb/host/whci/hcd.c
@@ -91,8 +91,6 @@ static void whc_stop(struct usb_hcd *usb_hcd)
91 91
92 mutex_lock(&wusbhc->mutex); 92 mutex_lock(&wusbhc->mutex);
93 93
94 wusbhc_stop(wusbhc);
95
96 /* stop HC */ 94 /* stop HC */
97 le_writel(0, whc->base + WUSBINTR); 95 le_writel(0, whc->base + WUSBINTR);
98 whc_write_wusbcmd(whc, WUSBCMD_RUN, 0); 96 whc_write_wusbcmd(whc, WUSBCMD_RUN, 0);
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c
index c01c7a80744..08a1ec90386 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -1124,8 +1124,7 @@ void wusbhc_devconnect_destroy(struct wusbhc *wusbhc)
1124 * FIXME: This also enables the keep alives but this is not necessary 1124 * FIXME: This also enables the keep alives but this is not necessary
1125 * until there are connected and authenticated devices. 1125 * until there are connected and authenticated devices.
1126 */ 1126 */
1127int wusbhc_devconnect_start(struct wusbhc *wusbhc, 1127int wusbhc_devconnect_start(struct wusbhc *wusbhc)
1128 const struct wusb_ckhdid *chid)
1129{ 1128{
1130 struct device *dev = wusbhc->dev; 1129 struct device *dev = wusbhc->dev;
1131 struct wuie_host_info *hi; 1130 struct wuie_host_info *hi;
@@ -1138,7 +1137,7 @@ int wusbhc_devconnect_start(struct wusbhc *wusbhc,
1138 hi->hdr.bLength = sizeof(*hi); 1137 hi->hdr.bLength = sizeof(*hi);
1139 hi->hdr.bIEIdentifier = WUIE_ID_HOST_INFO; 1138 hi->hdr.bIEIdentifier = WUIE_ID_HOST_INFO;
1140 hi->attributes = cpu_to_le16((wusbhc->rsv->stream << 3) | WUIE_HI_CAP_ALL); 1139 hi->attributes = cpu_to_le16((wusbhc->rsv->stream << 3) | WUIE_HI_CAP_ALL);
1141 hi->CHID = *chid; 1140 hi->CHID = wusbhc->chid;
1142 result = wusbhc_mmcie_set(wusbhc, 0, 0, &hi->hdr); 1141 result = wusbhc_mmcie_set(wusbhc, 0, 0, &hi->hdr);
1143 if (result < 0) { 1142 if (result < 0) {
1144 dev_err(dev, "Cannot add Host Info MMCIE: %d\n", result); 1143 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 af2aee0fdff..5463ecebafd 100644
--- a/drivers/usb/wusbcore/mmc.c
+++ b/drivers/usb/wusbcore/mmc.c
@@ -162,12 +162,11 @@ EXPORT_SYMBOL_GPL(wusbhc_mmcie_rm);
162/* 162/*
163 * wusbhc_start - start transmitting MMCs and accepting connections 163 * wusbhc_start - start transmitting MMCs and accepting connections
164 * @wusbhc: the HC to start 164 * @wusbhc: the HC to start
165 * @chid: the CHID to use for this host
166 * 165 *
167 * Establishes a cluster reservation, enables device connections, and 166 * Establishes a cluster reservation, enables device connections, and
168 * starts MMCs with appropriate DNTS parameters. 167 * starts MMCs with appropriate DNTS parameters.
169 */ 168 */
170int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid) 169int wusbhc_start(struct wusbhc *wusbhc)
171{ 170{
172 int result; 171 int result;
173 struct device *dev = wusbhc->dev; 172 struct device *dev = wusbhc->dev;
@@ -181,7 +180,7 @@ int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid)
181 goto error_rsv_establish; 180 goto error_rsv_establish;
182 } 181 }
183 182
184 result = wusbhc_devconnect_start(wusbhc, chid); 183 result = wusbhc_devconnect_start(wusbhc);
185 if (result < 0) { 184 if (result < 0) {
186 dev_err(dev, "error enabling device connections: %d\n", result); 185 dev_err(dev, "error enabling device connections: %d\n", result);
187 goto error_devconnect_start; 186 goto error_devconnect_start;
@@ -219,34 +218,6 @@ error_rsv_establish:
219} 218}
220 219
221/* 220/*
222 * Disconnect all from the WUSB Channel
223 *
224 * Send a Host Disconnect IE in the MMC, wait, don't send it any more
225 */
226static int __wusbhc_host_disconnect_ie(struct wusbhc *wusbhc)
227{
228 int result = -ENOMEM;
229 struct wuie_host_disconnect *host_disconnect_ie;
230 might_sleep();
231 host_disconnect_ie = kmalloc(sizeof(*host_disconnect_ie), GFP_KERNEL);
232 if (host_disconnect_ie == NULL)
233 goto error_alloc;
234 host_disconnect_ie->hdr.bLength = sizeof(*host_disconnect_ie);
235 host_disconnect_ie->hdr.bIEIdentifier = WUIE_ID_HOST_DISCONNECT;
236 result = wusbhc_mmcie_set(wusbhc, 0, 0, &host_disconnect_ie->hdr);
237 if (result < 0)
238 goto error_mmcie_set;
239
240 /* WUSB1.0[8.5.3.1 & 7.5.2] */
241 msleep(100);
242 wusbhc_mmcie_rm(wusbhc, &host_disconnect_ie->hdr);
243error_mmcie_set:
244 kfree(host_disconnect_ie);
245error_alloc:
246 return result;
247}
248
249/*
250 * wusbhc_stop - stop transmitting MMCs 221 * wusbhc_stop - stop transmitting MMCs
251 * @wusbhc: the HC to stop 222 * @wusbhc: the HC to stop
252 * 223 *
@@ -265,29 +236,6 @@ void wusbhc_stop(struct wusbhc *wusbhc)
265EXPORT_SYMBOL_GPL(wusbhc_stop); 236EXPORT_SYMBOL_GPL(wusbhc_stop);
266 237
267/* 238/*
268 * Change the CHID in a WUSB Channel
269 *
270 * If it is just a new CHID, send a Host Disconnect IE and then change
271 * the CHID IE.
272 */
273static int __wusbhc_chid_change(struct wusbhc *wusbhc,
274 const struct wusb_ckhdid *chid)
275{
276 int result = -ENOSYS;
277 struct device *dev = wusbhc->dev;
278 dev_err(dev, "%s() not implemented yet\n", __func__);
279 return result;
280
281 BUG_ON(wusbhc->wuie_host_info == NULL);
282 __wusbhc_host_disconnect_ie(wusbhc);
283 wusbhc->wuie_host_info->CHID = *chid;
284 result = wusbhc_mmcie_set(wusbhc, 0, 0, &wusbhc->wuie_host_info->hdr);
285 if (result < 0)
286 dev_err(dev, "Can't update Host Info WUSB IE: %d\n", result);
287 return result;
288}
289
290/*
291 * Set/reset/update a new CHID 239 * Set/reset/update a new CHID
292 * 240 *
293 * Depending on the previous state of the MMCs, start, stop or change 241 * Depending on the previous state of the MMCs, start, stop or change
@@ -302,16 +250,19 @@ int wusbhc_chid_set(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid)
302 chid = NULL; 250 chid = NULL;
303 251
304 mutex_lock(&wusbhc->mutex); 252 mutex_lock(&wusbhc->mutex);
305 if (wusbhc->active) { 253 if (chid) {
306 if (chid) 254 if (wusbhc->active) {
307 result = __wusbhc_chid_change(wusbhc, chid); 255 mutex_unlock(&wusbhc->mutex);
308 else 256 return -EBUSY;
309 wusbhc_stop(wusbhc); 257 }
310 } else { 258 wusbhc->chid = *chid;
311 if (chid)
312 wusbhc_start(wusbhc, chid);
313 } 259 }
314 mutex_unlock(&wusbhc->mutex); 260 mutex_unlock(&wusbhc->mutex);
261
262 if (chid)
263 result = uwb_radio_start(&wusbhc->pal);
264 else
265 uwb_radio_stop(&wusbhc->pal);
315 return result; 266 return result;
316} 267}
317EXPORT_SYMBOL_GPL(wusbhc_chid_set); 268EXPORT_SYMBOL_GPL(wusbhc_chid_set);
diff --git a/drivers/usb/wusbcore/pal.c b/drivers/usb/wusbcore/pal.c
index 7cc51e9905c..d0b172c5ecc 100644
--- a/drivers/usb/wusbcore/pal.c
+++ b/drivers/usb/wusbcore/pal.c
@@ -18,6 +18,16 @@
18 */ 18 */
19#include "wusbhc.h" 19#include "wusbhc.h"
20 20
21static void wusbhc_channel_changed(struct uwb_pal *pal, int channel)
22{
23 struct wusbhc *wusbhc = container_of(pal, struct wusbhc, pal);
24
25 if (channel < 0)
26 wusbhc_stop(wusbhc);
27 else
28 wusbhc_start(wusbhc);
29}
30
21/** 31/**
22 * wusbhc_pal_register - register the WUSB HC as a UWB PAL 32 * wusbhc_pal_register - register the WUSB HC as a UWB PAL
23 * @wusbhc: the WUSB HC 33 * @wusbhc: the WUSB HC
@@ -28,8 +38,10 @@ int wusbhc_pal_register(struct wusbhc *wusbhc)
28 38
29 wusbhc->pal.name = "wusbhc"; 39 wusbhc->pal.name = "wusbhc";
30 wusbhc->pal.device = wusbhc->usb_hcd.self.controller; 40 wusbhc->pal.device = wusbhc->usb_hcd.self.controller;
41 wusbhc->pal.rc = wusbhc->uwb_rc;
42 wusbhc->pal.channel_changed = wusbhc_channel_changed;
31 43
32 return uwb_pal_register(wusbhc->uwb_rc, &wusbhc->pal); 44 return uwb_pal_register(&wusbhc->pal);
33} 45}
34 46
35/** 47/**
@@ -38,5 +50,5 @@ int wusbhc_pal_register(struct wusbhc *wusbhc)
38 */ 50 */
39void wusbhc_pal_unregister(struct wusbhc *wusbhc) 51void wusbhc_pal_unregister(struct wusbhc *wusbhc)
40{ 52{
41 uwb_pal_unregister(wusbhc->uwb_rc, &wusbhc->pal); 53 uwb_pal_unregister(&wusbhc->pal);
42} 54}
diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h
index 8fef934ad2f..797c2453a35 100644
--- a/drivers/usb/wusbcore/wusbhc.h
+++ b/drivers/usb/wusbcore/wusbhc.h
@@ -252,7 +252,8 @@ struct wusbhc {
252 struct uwb_pal pal; 252 struct uwb_pal pal;
253 253
254 unsigned trust_timeout; /* in jiffies */ 254 unsigned trust_timeout; /* in jiffies */
255 struct wuie_host_info *wuie_host_info; /* Includes CHID */ 255 struct wusb_ckhdid chid;
256 struct wuie_host_info *wuie_host_info;
256 257
257 struct mutex mutex; /* locks everything else */ 258 struct mutex mutex; /* locks everything else */
258 u16 cluster_id; /* Wireless USB Cluster ID */ 259 u16 cluster_id; /* Wireless USB Cluster ID */
@@ -376,15 +377,14 @@ static inline void wusbhc_put(struct wusbhc *wusbhc)
376 usb_put_hcd(&wusbhc->usb_hcd); 377 usb_put_hcd(&wusbhc->usb_hcd);
377} 378}
378 379
379int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid); 380int wusbhc_start(struct wusbhc *wusbhc);
380void wusbhc_stop(struct wusbhc *wusbhc); 381void wusbhc_stop(struct wusbhc *wusbhc);
381extern int wusbhc_chid_set(struct wusbhc *, const struct wusb_ckhdid *); 382extern int wusbhc_chid_set(struct wusbhc *, const struct wusb_ckhdid *);
382 383
383/* Device connect handling */ 384/* Device connect handling */
384extern int wusbhc_devconnect_create(struct wusbhc *); 385extern int wusbhc_devconnect_create(struct wusbhc *);
385extern void wusbhc_devconnect_destroy(struct wusbhc *); 386extern void wusbhc_devconnect_destroy(struct wusbhc *);
386extern int wusbhc_devconnect_start(struct wusbhc *wusbhc, 387extern int wusbhc_devconnect_start(struct wusbhc *wusbhc);
387 const struct wusb_ckhdid *chid);
388extern void wusbhc_devconnect_stop(struct wusbhc *wusbhc); 388extern void wusbhc_devconnect_stop(struct wusbhc *wusbhc);
389extern void wusbhc_handle_dn(struct wusbhc *, u8 srcaddr, 389extern void wusbhc_handle_dn(struct wusbhc *, u8 srcaddr,
390 struct wusb_dn_hdr *dn_hdr, size_t size); 390 struct wusb_dn_hdr *dn_hdr, size_t size);
diff --git a/drivers/uwb/Makefile b/drivers/uwb/Makefile
index 2b99c3e6167..ce21a95da04 100644
--- a/drivers/uwb/Makefile
+++ b/drivers/uwb/Makefile
@@ -18,6 +18,7 @@ uwb-objs := \
18 lc-rc.o \ 18 lc-rc.o \
19 neh.o \ 19 neh.o \
20 pal.o \ 20 pal.o \
21 radio.o \
21 reset.o \ 22 reset.o \
22 rsv.o \ 23 rsv.o \
23 scan.o \ 24 scan.o \
diff --git a/drivers/uwb/beacon.c b/drivers/uwb/beacon.c
index d9f2a8acc59..247956098af 100644
--- a/drivers/uwb/beacon.c
+++ b/drivers/uwb/beacon.c
@@ -119,7 +119,6 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset)
119 int result; 119 int result;
120 struct device *dev = &rc->uwb_dev.dev; 120 struct device *dev = &rc->uwb_dev.dev;
121 121
122 mutex_lock(&rc->uwb_dev.mutex);
123 if (channel < 0) 122 if (channel < 0)
124 channel = -1; 123 channel = -1;
125 if (channel == -1) 124 if (channel == -1)
@@ -128,7 +127,7 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset)
128 /* channel >= 0...dah */ 127 /* channel >= 0...dah */
129 result = uwb_rc_start_beacon(rc, bpst_offset, channel); 128 result = uwb_rc_start_beacon(rc, bpst_offset, channel);
130 if (result < 0) 129 if (result < 0)
131 goto out_up; 130 return result;
132 if (le16_to_cpu(rc->ies->wIELength) > 0) { 131 if (le16_to_cpu(rc->ies->wIELength) > 0) {
133 result = uwb_rc_set_ie(rc, rc->ies); 132 result = uwb_rc_set_ie(rc, rc->ies);
134 if (result < 0) { 133 if (result < 0) {
@@ -137,19 +136,14 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset)
137 result = uwb_rc_stop_beacon(rc); 136 result = uwb_rc_stop_beacon(rc);
138 channel = -1; 137 channel = -1;
139 bpst_offset = 0; 138 bpst_offset = 0;
140 } else 139 }
141 result = 0;
142 } 140 }
143 } 141 }
144 142
145 if (result < 0) 143 if (result >= 0) {
146 goto out_up; 144 rc->beaconing = channel;
147 rc->beaconing = channel; 145 uwb_notify(rc, NULL, uwb_bg_joined(rc) ? UWB_NOTIF_BG_JOIN : UWB_NOTIF_BG_LEAVE);
148 146 }
149 uwb_notify(rc, NULL, uwb_bg_joined(rc) ? UWB_NOTIF_BG_JOIN : UWB_NOTIF_BG_LEAVE);
150
151out_up:
152 mutex_unlock(&rc->uwb_dev.mutex);
153 return result; 147 return result;
154} 148}
155 149
@@ -618,9 +612,6 @@ static ssize_t uwb_rc_beacon_show(struct device *dev,
618 612
619/* 613/*
620 * Start beaconing on the specified channel, or stop beaconing. 614 * Start beaconing on the specified channel, or stop beaconing.
621 *
622 * The BPST offset of when to start searching for a beacon group to
623 * join may be specified.
624 */ 615 */
625static ssize_t uwb_rc_beacon_store(struct device *dev, 616static ssize_t uwb_rc_beacon_store(struct device *dev,
626 struct device_attribute *attr, 617 struct device_attribute *attr,
@@ -629,12 +620,11 @@ static ssize_t uwb_rc_beacon_store(struct device *dev,
629 struct uwb_dev *uwb_dev = to_uwb_dev(dev); 620 struct uwb_dev *uwb_dev = to_uwb_dev(dev);
630 struct uwb_rc *rc = uwb_dev->rc; 621 struct uwb_rc *rc = uwb_dev->rc;
631 int channel; 622 int channel;
632 unsigned bpst_offset = 0;
633 ssize_t result = -EINVAL; 623 ssize_t result = -EINVAL;
634 624
635 result = sscanf(buf, "%d %u\n", &channel, &bpst_offset); 625 result = sscanf(buf, "%d", &channel);
636 if (result >= 1) 626 if (result >= 1)
637 result = uwb_rc_beacon(rc, channel, bpst_offset); 627 result = uwb_radio_force_channel(rc, channel);
638 628
639 return result < 0 ? result : size; 629 return result < 0 ? result : size;
640} 630}
diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c
index c0b1e5e2bd0..fe328146adb 100644
--- a/drivers/uwb/drp.c
+++ b/drivers/uwb/drp.c
@@ -37,14 +37,13 @@
37 * 37 *
38 * A DRP Availability IE is appended. 38 * A DRP Availability IE is appended.
39 * 39 *
40 * rc->uwb_dev.mutex is held 40 * rc->rsvs_mutex is held
41 * 41 *
42 * FIXME We currently ignore the returned value indicating the remaining space 42 * FIXME We currently ignore the returned value indicating the remaining space
43 * in beacon. This could be used to deny reservation requests earlier if 43 * in beacon. This could be used to deny reservation requests earlier if
44 * determined that they would cause the beacon space to be exceeded. 44 * determined that they would cause the beacon space to be exceeded.
45 */ 45 */
46static 46int uwb_rc_send_all_drp_ie(struct uwb_rc *rc)
47int uwb_rc_gen_send_drp_ie(struct uwb_rc *rc)
48{ 47{
49 int result; 48 int result;
50 struct device *dev = &rc->uwb_dev.dev; 49 struct device *dev = &rc->uwb_dev.dev;
@@ -102,25 +101,6 @@ error_cmd:
102 kfree(cmd); 101 kfree(cmd);
103error: 102error:
104 return result; 103 return result;
105
106}
107/**
108 * Send all DRP IEs associated with this host
109 *
110 * @returns: >= 0 number of bytes still available in the beacon
111 * < 0 errno code on error.
112 *
113 * As per the protocol we obtain the host controller device lock to access
114 * bandwidth structures.
115 */
116int uwb_rc_send_all_drp_ie(struct uwb_rc *rc)
117{
118 int result;
119
120 mutex_lock(&rc->uwb_dev.mutex);
121 result = uwb_rc_gen_send_drp_ie(rc);
122 mutex_unlock(&rc->uwb_dev.mutex);
123 return result;
124} 104}
125 105
126void uwb_drp_handle_timeout(struct uwb_rsv *rsv) 106void uwb_drp_handle_timeout(struct uwb_rsv *rsv)
diff --git a/drivers/uwb/lc-rc.c b/drivers/uwb/lc-rc.c
index f00633d334d..9cf21e6bb62 100644
--- a/drivers/uwb/lc-rc.c
+++ b/drivers/uwb/lc-rc.c
@@ -189,9 +189,9 @@ static int uwb_rc_setup(struct uwb_rc *rc)
189 int result; 189 int result;
190 struct device *dev = &rc->uwb_dev.dev; 190 struct device *dev = &rc->uwb_dev.dev;
191 191
192 result = uwb_rc_reset(rc); 192 result = uwb_radio_setup(rc);
193 if (result < 0) { 193 if (result < 0) {
194 dev_err(dev, "cannot reset UWB radio: %d\n", result); 194 dev_err(dev, "cannot setup UWB radio: %d\n", result);
195 goto error; 195 goto error;
196 } 196 }
197 result = uwb_rc_mac_addr_setup(rc); 197 result = uwb_rc_mac_addr_setup(rc);
@@ -311,12 +311,7 @@ void uwb_rc_rm(struct uwb_rc *rc)
311 311
312 uwb_dbg_del_rc(rc); 312 uwb_dbg_del_rc(rc);
313 uwb_rsv_remove_all(rc); 313 uwb_rsv_remove_all(rc);
314 uwb_rc_ie_rm(rc, UWB_IDENTIFICATION_IE); 314 uwb_radio_shutdown(rc);
315 if (rc->beaconing >= 0)
316 uwb_rc_beacon(rc, -1, 0);
317 if (rc->scan_type != UWB_SCAN_DISABLED)
318 uwb_rc_scan(rc, rc->scanning, UWB_SCAN_DISABLED, 0);
319 uwb_rc_reset(rc);
320 315
321 rc->stop(rc); 316 rc->stop(rc);
322 317
diff --git a/drivers/uwb/pal.c b/drivers/uwb/pal.c
index 1afb38eacb9..605765124f5 100644
--- a/drivers/uwb/pal.c
+++ b/drivers/uwb/pal.c
@@ -32,13 +32,13 @@ EXPORT_SYMBOL_GPL(uwb_pal_init);
32 32
33/** 33/**
34 * uwb_pal_register - register a UWB PAL 34 * uwb_pal_register - register a UWB PAL
35 * @rc: the radio controller the PAL will be using
36 * @pal: the PAL 35 * @pal: the PAL
37 * 36 *
38 * The PAL must be initialized with uwb_pal_init(). 37 * The PAL must be initialized with uwb_pal_init().
39 */ 38 */
40int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal) 39int uwb_pal_register(struct uwb_pal *pal)
41{ 40{
41 struct uwb_rc *rc = pal->rc;
42 int ret; 42 int ret;
43 43
44 if (pal->device) { 44 if (pal->device) {
@@ -54,9 +54,9 @@ int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal)
54 } 54 }
55 } 55 }
56 56
57 spin_lock(&rc->pal_lock); 57 mutex_lock(&rc->uwb_dev.mutex);
58 list_add(&pal->node, &rc->pals); 58 list_add(&pal->node, &rc->pals);
59 spin_unlock(&rc->pal_lock); 59 mutex_unlock(&rc->uwb_dev.mutex);
60 60
61 return 0; 61 return 0;
62} 62}
@@ -64,14 +64,17 @@ EXPORT_SYMBOL_GPL(uwb_pal_register);
64 64
65/** 65/**
66 * uwb_pal_register - unregister a UWB PAL 66 * uwb_pal_register - unregister a UWB PAL
67 * @rc: the radio controller the PAL was using
68 * @pal: the PAL 67 * @pal: the PAL
69 */ 68 */
70void uwb_pal_unregister(struct uwb_rc *rc, struct uwb_pal *pal) 69void uwb_pal_unregister(struct uwb_pal *pal)
71{ 70{
72 spin_lock(&rc->pal_lock); 71 struct uwb_rc *rc = pal->rc;
72
73 uwb_radio_stop(pal);
74
75 mutex_lock(&rc->uwb_dev.mutex);
73 list_del(&pal->node); 76 list_del(&pal->node);
74 spin_unlock(&rc->pal_lock); 77 mutex_unlock(&rc->uwb_dev.mutex);
75 78
76 if (pal->device) { 79 if (pal->device) {
77 sysfs_remove_link(&rc->uwb_dev.dev.kobj, pal->name); 80 sysfs_remove_link(&rc->uwb_dev.dev.kobj, pal->name);
@@ -86,6 +89,5 @@ EXPORT_SYMBOL_GPL(uwb_pal_unregister);
86 */ 89 */
87void uwb_rc_pal_init(struct uwb_rc *rc) 90void uwb_rc_pal_init(struct uwb_rc *rc)
88{ 91{
89 spin_lock_init(&rc->pal_lock);
90 INIT_LIST_HEAD(&rc->pals); 92 INIT_LIST_HEAD(&rc->pals);
91} 93}
diff --git a/drivers/uwb/radio.c b/drivers/uwb/radio.c
new file mode 100644
index 00000000000..f0d55495f5e
--- /dev/null
+++ b/drivers/uwb/radio.c
@@ -0,0 +1,202 @@
1/*
2 * UWB radio (channel) management.
3 *
4 * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18#include <linux/kernel.h>
19#include <linux/uwb.h>
20
21#include "uwb-internal.h"
22
23
24static int uwb_radio_select_channel(struct uwb_rc *rc)
25{
26 /*
27 * Default to channel 9 (BG1, TFC1) unless the user has
28 * selected a specific channel or there are no active PALs.
29 */
30 if (rc->active_pals == 0)
31 return -1;
32 if (rc->beaconing_forced)
33 return rc->beaconing_forced;
34 return 9;
35}
36
37
38/*
39 * Notify all active PALs that the channel has changed.
40 */
41static void uwb_radio_channel_changed(struct uwb_rc *rc, int channel)
42{
43 struct uwb_pal *pal;
44
45 list_for_each_entry(pal, &rc->pals, node) {
46 if (pal->channel && channel != pal->channel) {
47 pal->channel = channel;
48 if (pal->channel_changed)
49 pal->channel_changed(pal, pal->channel);
50 }
51 }
52}
53
54/*
55 * Change to a new channel and notify any active PALs of the new
56 * channel.
57 *
58 * When stopping the radio, PALs need to be notified first so they can
59 * terminate any active reservations.
60 */
61static int uwb_radio_change_channel(struct uwb_rc *rc, int channel)
62{
63 int ret = 0;
64
65 if (channel == -1)
66 uwb_radio_channel_changed(rc, channel);
67
68 if (channel != rc->beaconing) {
69 if (rc->beaconing != -1 && channel != -1) {
70 /*
71 * FIXME: should signal the channel change
72 * with a Channel Change IE.
73 */
74 ret = uwb_radio_change_channel(rc, -1);
75 if (ret < 0)
76 return ret;
77 }
78 ret = uwb_rc_beacon(rc, channel, 0);
79 }
80
81 if (channel != -1)
82 uwb_radio_channel_changed(rc, rc->beaconing);
83
84 return ret;
85}
86
87/**
88 * uwb_radio_start - request that the radio be started
89 * @pal: the PAL making the request.
90 *
91 * If the radio is not already active, aa suitable channel is selected
92 * and beacons are started.
93 */
94int uwb_radio_start(struct uwb_pal *pal)
95{
96 struct uwb_rc *rc = pal->rc;
97 int ret = 0;
98
99 mutex_lock(&rc->uwb_dev.mutex);
100
101 if (!pal->channel) {
102 pal->channel = -1;
103 rc->active_pals++;
104 ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc));
105 }
106
107 mutex_unlock(&rc->uwb_dev.mutex);
108 return ret;
109}
110EXPORT_SYMBOL_GPL(uwb_radio_start);
111
112/**
113 * uwb_radio_stop - request tha the radio be stopped.
114 * @pal: the PAL making the request.
115 *
116 * Stops the radio if no other PAL is making use of it.
117 */
118void uwb_radio_stop(struct uwb_pal *pal)
119{
120 struct uwb_rc *rc = pal->rc;
121
122 mutex_lock(&rc->uwb_dev.mutex);
123
124 if (pal->channel) {
125 rc->active_pals--;
126 uwb_radio_change_channel(rc, uwb_radio_select_channel(rc));
127 pal->channel = 0;
128 }
129
130 mutex_unlock(&rc->uwb_dev.mutex);
131}
132EXPORT_SYMBOL_GPL(uwb_radio_stop);
133
134/*
135 * uwb_radio_force_channel - force a specific channel to be used
136 * @rc: the radio controller.
137 * @channel: the channel to use; -1 to force the radio to stop; 0 to
138 * use the default channel selection algorithm.
139 */
140int uwb_radio_force_channel(struct uwb_rc *rc, int channel)
141{
142 int ret = 0;
143
144 mutex_lock(&rc->uwb_dev.mutex);
145
146 rc->beaconing_forced = channel;
147 ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc));
148
149 mutex_unlock(&rc->uwb_dev.mutex);
150 return ret;
151}
152
153/*
154 * uwb_radio_setup - setup the radio manager
155 * @rc: the radio controller.
156 *
157 * The radio controller is reset to ensure it's in a known state
158 * before it's used.
159 */
160int uwb_radio_setup(struct uwb_rc *rc)
161{
162 return uwb_rc_reset(rc);
163}
164
165/*
166 * uwb_radio_reset_state - reset any radio manager state
167 * @rc: the radio controller.
168 *
169 * All internal radio manager state is reset to values corresponding
170 * to a reset radio controller.
171 */
172void uwb_radio_reset_state(struct uwb_rc *rc)
173{
174 struct uwb_pal *pal;
175
176 mutex_lock(&rc->uwb_dev.mutex);
177
178 list_for_each_entry(pal, &rc->pals, node) {
179 if (pal->channel) {
180 pal->channel = -1;
181 if (pal->channel_changed)
182 pal->channel_changed(pal, -1);
183 }
184 }
185
186 rc->beaconing = -1;
187 rc->scanning = -1;
188
189 mutex_unlock(&rc->uwb_dev.mutex);
190}
191
192/*
193 * uwb_radio_shutdown - shutdown the radio manager
194 * @rc: the radio controller.
195 *
196 * The radio controller is reset.
197 */
198void uwb_radio_shutdown(struct uwb_rc *rc)
199{
200 uwb_radio_reset_state(rc);
201 uwb_rc_reset(rc);
202}
diff --git a/drivers/uwb/reset.c b/drivers/uwb/reset.c
index e39b32099af..ce8283cc809 100644
--- a/drivers/uwb/reset.c
+++ b/drivers/uwb/reset.c
@@ -365,11 +365,7 @@ void uwb_rc_pre_reset(struct uwb_rc *rc)
365 rc->stop(rc); 365 rc->stop(rc);
366 uwbd_flush(rc); 366 uwbd_flush(rc);
367 367
368 mutex_lock(&rc->uwb_dev.mutex); 368 uwb_radio_reset_state(rc);
369 rc->beaconing = -1;
370 rc->scanning = -1;
371 mutex_unlock(&rc->uwb_dev.mutex);
372
373 uwb_rsv_remove_all(rc); 369 uwb_rsv_remove_all(rc);
374} 370}
375EXPORT_SYMBOL_GPL(uwb_rc_pre_reset); 371EXPORT_SYMBOL_GPL(uwb_rc_pre_reset);
diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c
index 935d5b536db..1cd84f92754 100644
--- a/drivers/uwb/rsv.c
+++ b/drivers/uwb/rsv.c
@@ -555,14 +555,14 @@ static struct uwb_rsv *uwb_rsv_new_target(struct uwb_rc *rc,
555 * deny the request. 555 * deny the request.
556 */ 556 */
557 rsv->state = UWB_RSV_STATE_T_DENIED; 557 rsv->state = UWB_RSV_STATE_T_DENIED;
558 spin_lock(&rc->pal_lock); 558 mutex_lock(&rc->uwb_dev.mutex);
559 list_for_each_entry(pal, &rc->pals, node) { 559 list_for_each_entry(pal, &rc->pals, node) {
560 if (pal->new_rsv) 560 if (pal->new_rsv)
561 pal->new_rsv(pal, rsv); 561 pal->new_rsv(pal, rsv);
562 if (rsv->state == UWB_RSV_STATE_T_ACCEPTED) 562 if (rsv->state == UWB_RSV_STATE_T_ACCEPTED)
563 break; 563 break;
564 } 564 }
565 spin_unlock(&rc->pal_lock); 565 mutex_unlock(&rc->uwb_dev.mutex);
566 566
567 list_add_tail(&rsv->rc_node, &rc->reservations); 567 list_add_tail(&rsv->rc_node, &rc->reservations);
568 state = rsv->state; 568 state = rsv->state;
diff --git a/drivers/uwb/uwb-debug.c b/drivers/uwb/uwb-debug.c
index 217ebaac128..0e58071a232 100644
--- a/drivers/uwb/uwb-debug.c
+++ b/drivers/uwb/uwb-debug.c
@@ -192,7 +192,7 @@ static ssize_t command_write(struct file *file, const char __user *buf,
192{ 192{
193 struct uwb_rc *rc = file->private_data; 193 struct uwb_rc *rc = file->private_data;
194 struct uwb_dbg_cmd cmd; 194 struct uwb_dbg_cmd cmd;
195 int ret; 195 int ret = 0;
196 196
197 if (len != sizeof(struct uwb_dbg_cmd)) 197 if (len != sizeof(struct uwb_dbg_cmd))
198 return -EINVAL; 198 return -EINVAL;
@@ -213,6 +213,12 @@ static ssize_t command_write(struct file *file, const char __user *buf,
213 case UWB_DBG_CMD_IE_RM: 213 case UWB_DBG_CMD_IE_RM:
214 ret = cmd_ie_rm(rc, &cmd.ie_rm); 214 ret = cmd_ie_rm(rc, &cmd.ie_rm);
215 break; 215 break;
216 case UWB_DBG_CMD_RADIO_START:
217 ret = uwb_radio_start(&rc->dbg->pal);
218 break;
219 case UWB_DBG_CMD_RADIO_STOP:
220 uwb_radio_stop(&rc->dbg->pal);
221 break;
216 default: 222 default:
217 return -EINVAL; 223 return -EINVAL;
218 } 224 }
@@ -306,6 +312,17 @@ static struct file_operations drp_avail_fops = {
306 .owner = THIS_MODULE, 312 .owner = THIS_MODULE,
307}; 313};
308 314
315static void uwb_dbg_channel_changed(struct uwb_pal *pal, int channel)
316{
317 struct uwb_dbg *dbg = container_of(pal, struct uwb_dbg, pal);
318 struct device *dev = &pal->rc->uwb_dev.dev;
319
320 if (channel > 0)
321 dev_info(dev, "debug: channel %d started\n", channel);
322 else
323 dev_info(dev, "debug: channel stopped\n");
324}
325
309static void uwb_dbg_new_rsv(struct uwb_pal *pal, struct uwb_rsv *rsv) 326static void uwb_dbg_new_rsv(struct uwb_pal *pal, struct uwb_rsv *rsv)
310{ 327{
311 struct uwb_dbg *dbg = container_of(pal, struct uwb_dbg, pal); 328 struct uwb_dbg *dbg = container_of(pal, struct uwb_dbg, pal);
@@ -329,8 +346,11 @@ void uwb_dbg_add_rc(struct uwb_rc *rc)
329 INIT_LIST_HEAD(&rc->dbg->rsvs); 346 INIT_LIST_HEAD(&rc->dbg->rsvs);
330 347
331 uwb_pal_init(&rc->dbg->pal); 348 uwb_pal_init(&rc->dbg->pal);
349 rc->dbg->pal.rc = rc;
350 rc->dbg->pal.channel_changed = uwb_dbg_channel_changed;
332 rc->dbg->pal.new_rsv = uwb_dbg_new_rsv; 351 rc->dbg->pal.new_rsv = uwb_dbg_new_rsv;
333 uwb_pal_register(rc, &rc->dbg->pal); 352 uwb_pal_register(&rc->dbg->pal);
353
334 if (root_dir) { 354 if (root_dir) {
335 rc->dbg->root_d = debugfs_create_dir(dev_name(&rc->uwb_dev.dev), 355 rc->dbg->root_d = debugfs_create_dir(dev_name(&rc->uwb_dev.dev),
336 root_dir); 356 root_dir);
@@ -364,7 +384,7 @@ void uwb_dbg_del_rc(struct uwb_rc *rc)
364 uwb_rsv_terminate(rsv); 384 uwb_rsv_terminate(rsv);
365 } 385 }
366 386
367 uwb_pal_unregister(rc, &rc->dbg->pal); 387 uwb_pal_unregister(&rc->dbg->pal);
368 388
369 if (root_dir) { 389 if (root_dir) {
370 debugfs_remove(rc->dbg->drp_avail_f); 390 debugfs_remove(rc->dbg->drp_avail_f);
diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h
index af95541dabc..9c0cdb4ded0 100644
--- a/drivers/uwb/uwb-internal.h
+++ b/drivers/uwb/uwb-internal.h
@@ -238,6 +238,11 @@ struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc,
238struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc, 238struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc,
239 const struct uwb_mac_addr *macaddr); 239 const struct uwb_mac_addr *macaddr);
240 240
241int uwb_radio_setup(struct uwb_rc *rc);
242void uwb_radio_reset_state(struct uwb_rc *rc);
243void uwb_radio_shutdown(struct uwb_rc *rc);
244int uwb_radio_force_channel(struct uwb_rc *rc, int channel);
245
241/* -- UWB Sysfs representation */ 246/* -- UWB Sysfs representation */
242extern struct class uwb_rc_class; 247extern struct class uwb_rc_class;
243extern struct device_attribute dev_attr_mac_address; 248extern struct device_attribute dev_attr_mac_address;
diff --git a/drivers/uwb/wlp/wlp-lc.c b/drivers/uwb/wlp/wlp-lc.c
index 0799402e73f..7e5eb49b03b 100644
--- a/drivers/uwb/wlp/wlp-lc.c
+++ b/drivers/uwb/wlp/wlp-lc.c
@@ -543,7 +543,8 @@ int wlp_setup(struct wlp *wlp, struct uwb_rc *rc)
543 uwb_notifs_register(rc, &wlp->uwb_notifs_handler); 543 uwb_notifs_register(rc, &wlp->uwb_notifs_handler);
544 544
545 uwb_pal_init(&wlp->pal); 545 uwb_pal_init(&wlp->pal);
546 result = uwb_pal_register(rc, &wlp->pal); 546 wlp->pal.rc = rc;
547 result = uwb_pal_register(&wlp->pal);
547 if (result < 0) 548 if (result < 0)
548 uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); 549 uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler);
549 550
@@ -557,7 +558,7 @@ void wlp_remove(struct wlp *wlp)
557 struct device *dev = &wlp->rc->uwb_dev.dev; 558 struct device *dev = &wlp->rc->uwb_dev.dev;
558 d_fnstart(6, dev, "wlp %p\n", wlp); 559 d_fnstart(6, dev, "wlp %p\n", wlp);
559 wlp_neighbors_release(wlp); 560 wlp_neighbors_release(wlp);
560 uwb_pal_unregister(wlp->rc, &wlp->pal); 561 uwb_pal_unregister(&wlp->pal);
561 uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); 562 uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler);
562 wlp_eda_release(&wlp->eda); 563 wlp_eda_release(&wlp->eda);
563 mutex_lock(&wlp->mutex); 564 mutex_lock(&wlp->mutex);
diff --git a/include/linux/uwb.h b/include/linux/uwb.h
index effd97998fd..7d3ebf046f9 100644
--- a/include/linux/uwb.h
+++ b/include/linux/uwb.h
@@ -355,6 +355,7 @@ struct uwb_rc {
355 u8 ctx_roll; 355 u8 ctx_roll;
356 356
357 int beaconing; /* Beaconing state [channel number] */ 357 int beaconing; /* Beaconing state [channel number] */
358 int beaconing_forced;
358 int scanning; 359 int scanning;
359 enum uwb_scan_type scan_type:3; 360 enum uwb_scan_type scan_type:3;
360 unsigned ready:1; 361 unsigned ready:1;
@@ -373,8 +374,8 @@ struct uwb_rc {
373 struct uwb_rc_cmd_set_ie *ies; 374 struct uwb_rc_cmd_set_ie *ies;
374 size_t ies_capacity; 375 size_t ies_capacity;
375 376
376 spinlock_t pal_lock;
377 struct list_head pals; 377 struct list_head pals;
378 int active_pals;
378 379
379 struct uwb_dbg *dbg; 380 struct uwb_dbg *dbg;
380}; 381};
@@ -382,11 +383,17 @@ struct uwb_rc {
382 383
383/** 384/**
384 * struct uwb_pal - a UWB PAL 385 * struct uwb_pal - a UWB PAL
385 * @name: descriptive name for this PAL (wushc, wlp, etc.). 386 * @name: descriptive name for this PAL (wusbhc, wlp, etc.).
386 * @device: a device for the PAL. Used to link the PAL and the radio 387 * @device: a device for the PAL. Used to link the PAL and the radio
387 * controller in sysfs. 388 * controller in sysfs.
389 * @rc: the radio controller the PAL uses.
390 * @channel_changed: called when the channel used by the radio changes.
391 * A channel of -1 means the channel has been stopped.
388 * @new_rsv: called when a peer requests a reservation (may be NULL if 392 * @new_rsv: called when a peer requests a reservation (may be NULL if
389 * the PAL cannot accept reservation requests). 393 * the PAL cannot accept reservation requests).
394 * @channel: channel being used by the PAL; 0 if the PAL isn't using
395 * the radio; -1 if the PAL wishes to use the radio but
396 * cannot.
390 * 397 *
391 * A Protocol Adaptation Layer (PAL) is a user of the WiMedia UWB 398 * A Protocol Adaptation Layer (PAL) is a user of the WiMedia UWB
392 * radio platform (e.g., WUSB, WLP or Bluetooth UWB AMP). 399 * radio platform (e.g., WUSB, WLP or Bluetooth UWB AMP).
@@ -405,12 +412,20 @@ struct uwb_pal {
405 struct list_head node; 412 struct list_head node;
406 const char *name; 413 const char *name;
407 struct device *device; 414 struct device *device;
415 struct uwb_rc *rc;
416
417 void (*channel_changed)(struct uwb_pal *pal, int channel);
408 void (*new_rsv)(struct uwb_pal *pal, struct uwb_rsv *rsv); 418 void (*new_rsv)(struct uwb_pal *pal, struct uwb_rsv *rsv);
419
420 int channel;
409}; 421};
410 422
411void uwb_pal_init(struct uwb_pal *pal); 423void uwb_pal_init(struct uwb_pal *pal);
412int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal); 424int uwb_pal_register(struct uwb_pal *pal);
413void uwb_pal_unregister(struct uwb_rc *rc, struct uwb_pal *pal); 425void uwb_pal_unregister(struct uwb_pal *pal);
426
427int uwb_radio_start(struct uwb_pal *pal);
428void uwb_radio_stop(struct uwb_pal *pal);
414 429
415/* 430/*
416 * General public API 431 * General public API
diff --git a/include/linux/uwb/debug-cmd.h b/include/linux/uwb/debug-cmd.h
index 6a16566f022..07efbe17db5 100644
--- a/include/linux/uwb/debug-cmd.h
+++ b/include/linux/uwb/debug-cmd.h
@@ -34,6 +34,8 @@ enum uwb_dbg_cmd_type {
34 UWB_DBG_CMD_RSV_TERMINATE = 2, 34 UWB_DBG_CMD_RSV_TERMINATE = 2,
35 UWB_DBG_CMD_IE_ADD = 3, 35 UWB_DBG_CMD_IE_ADD = 3,
36 UWB_DBG_CMD_IE_RM = 4, 36 UWB_DBG_CMD_IE_RM = 4,
37 UWB_DBG_CMD_RADIO_START = 5,
38 UWB_DBG_CMD_RADIO_STOP = 6,
37}; 39};
38 40
39struct uwb_dbg_cmd_rsv_establish { 41struct uwb_dbg_cmd_rsv_establish {