aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/uwb
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@csr.com>2008-11-17 10:53:42 -0500
committerDavid Vrabel <david.vrabel@csr.com>2008-11-19 09:46:33 -0500
commit6fae35f9cea92793a98b2d9ab21235e5ae035581 (patch)
tree82142169ff2ccada8c6c98beb6da59cafe8d913d /drivers/uwb
parente17be2b2a95b43fe0d5878adf330701bb7a77115 (diff)
uwb: add basic radio manager
The UWB radio manager coordinates the use of the radio between the PALs that may be using it. PALs request use of the radio with uwb_radio_start() and the radio manager will start beaconing if its not already doing so. When the last PAL has called uwb_radio_stop() beaconing will be stopped. In the future, the radio manager will have a more sophisticated channel selection algorithm, probably following the Channel Selection Policy from the WiMedia Alliance when it is finalized. For now, channel 9 (BG1, TFC1) is selected. The user may override the channel selected by the radio manager and may force the radio to stop beaconing. The WUSB Host Controller PAL makes use of this and there are two new debug PAL commands that can be used for testing. Signed-off-by: David Vrabel <david.vrabel@csr.com>
Diffstat (limited to 'drivers/uwb')
-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
11 files changed, 261 insertions, 69 deletions
diff --git a/drivers/uwb/Makefile b/drivers/uwb/Makefile
index 2b99c3e61671..ce21a95da04a 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 d9f2a8acc593..247956098afa 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 c0b1e5e2bd08..fe328146adb7 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 f00633d334dd..9cf21e6bb624 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 1afb38eacb9a..605765124f5b 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 000000000000..f0d55495f5e9
--- /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 e39b32099af3..ce8283cc8098 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 935d5b536db7..1cd84f927540 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 217ebaac128d..0e58071a232d 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 af95541dabcd..9c0cdb4ded0c 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 0799402e73fb..7e5eb49b03b8 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);