diff options
author | David Vrabel <david.vrabel@csr.com> | 2008-11-17 10:53:42 -0500 |
---|---|---|
committer | David Vrabel <david.vrabel@csr.com> | 2008-11-19 09:46:33 -0500 |
commit | 6fae35f9cea92793a98b2d9ab21235e5ae035581 (patch) | |
tree | 82142169ff2ccada8c6c98beb6da59cafe8d913d /drivers/usb/wusbcore | |
parent | e17be2b2a95b43fe0d5878adf330701bb7a77115 (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/usb/wusbcore')
-rw-r--r-- | drivers/usb/wusbcore/devconnect.c | 5 | ||||
-rw-r--r-- | drivers/usb/wusbcore/mmc.c | 75 | ||||
-rw-r--r-- | drivers/usb/wusbcore/pal.c | 16 | ||||
-rw-r--r-- | drivers/usb/wusbcore/wusbhc.h | 8 |
4 files changed, 33 insertions, 71 deletions
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 | */ |
1127 | int wusbhc_devconnect_start(struct wusbhc *wusbhc, | 1127 | int 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 | */ |
170 | int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid) | 169 | int 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 | */ | ||
226 | static 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); | ||
243 | error_mmcie_set: | ||
244 | kfree(host_disconnect_ie); | ||
245 | error_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) | |||
265 | EXPORT_SYMBOL_GPL(wusbhc_stop); | 236 | EXPORT_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 | */ | ||
273 | static 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 | } |
317 | EXPORT_SYMBOL_GPL(wusbhc_chid_set); | 268 | EXPORT_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 | ||
21 | static 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 | */ |
39 | void wusbhc_pal_unregister(struct wusbhc *wusbhc) | 51 | void 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 | ||
379 | int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid); | 380 | int wusbhc_start(struct wusbhc *wusbhc); |
380 | void wusbhc_stop(struct wusbhc *wusbhc); | 381 | void wusbhc_stop(struct wusbhc *wusbhc); |
381 | extern int wusbhc_chid_set(struct wusbhc *, const struct wusb_ckhdid *); | 382 | extern int wusbhc_chid_set(struct wusbhc *, const struct wusb_ckhdid *); |
382 | 383 | ||
383 | /* Device connect handling */ | 384 | /* Device connect handling */ |
384 | extern int wusbhc_devconnect_create(struct wusbhc *); | 385 | extern int wusbhc_devconnect_create(struct wusbhc *); |
385 | extern void wusbhc_devconnect_destroy(struct wusbhc *); | 386 | extern void wusbhc_devconnect_destroy(struct wusbhc *); |
386 | extern int wusbhc_devconnect_start(struct wusbhc *wusbhc, | 387 | extern int wusbhc_devconnect_start(struct wusbhc *wusbhc); |
387 | const struct wusb_ckhdid *chid); | ||
388 | extern void wusbhc_devconnect_stop(struct wusbhc *wusbhc); | 388 | extern void wusbhc_devconnect_stop(struct wusbhc *wusbhc); |
389 | extern void wusbhc_handle_dn(struct wusbhc *, u8 srcaddr, | 389 | extern 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); |