aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/wusbcore
diff options
context:
space:
mode:
authorThomas Pugliese <thomas.pugliese@gmail.com>2013-06-24 15:26:35 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-06-24 19:20:43 -0400
commita899575191ba85a71401f2c8f36bec7b14487043 (patch)
tree74070049b20ec44cf625db68ac62751e4b33cab0 /drivers/usb/wusbcore
parent6e6581e0a94758a4e69fab82407d39312eeff5c4 (diff)
USB: HWA: fix device probe failure
This patch fixes a race condition that caused the HWA_HC interface probe function to occasionally fail. The HWA_HC would attempt to register itself with the HWA_RC by searching for a uwb_rc class device with the same parent device ptr. If the probe function for the HWA_RC interface had yet to run, the uwb_rc class device would not have been created causing the look up to fail and the HWA_HC probe function to return an error causing the device to be unusable. The fix is for the HWA to delay registering with the HWA_RC until receiving the command from userspace to start the wireless channel. It is the responsibility of userspace to ensure that the uwb_rc class device has been created before starting the HWA channel. Signed-off-by: Thomas Pugliese <thomas.pugliese@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/wusbcore')
-rw-r--r--drivers/usb/wusbcore/mmc.c27
-rw-r--r--drivers/usb/wusbcore/pal.c5
-rw-r--r--drivers/usb/wusbcore/reservation.c3
-rw-r--r--drivers/usb/wusbcore/wusbhc.c9
4 files changed, 35 insertions, 9 deletions
diff --git a/drivers/usb/wusbcore/mmc.c b/drivers/usb/wusbcore/mmc.c
index 021467f86d9e..b71760c8d3ad 100644
--- a/drivers/usb/wusbcore/mmc.c
+++ b/drivers/usb/wusbcore/mmc.c
@@ -195,6 +195,7 @@ int wusbhc_start(struct wusbhc *wusbhc)
195 struct device *dev = wusbhc->dev; 195 struct device *dev = wusbhc->dev;
196 196
197 WARN_ON(wusbhc->wuie_host_info != NULL); 197 WARN_ON(wusbhc->wuie_host_info != NULL);
198 BUG_ON(wusbhc->uwb_rc == NULL);
198 199
199 result = wusbhc_rsv_establish(wusbhc); 200 result = wusbhc_rsv_establish(wusbhc);
200 if (result < 0) { 201 if (result < 0) {
@@ -276,12 +277,38 @@ int wusbhc_chid_set(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid)
276 } 277 }
277 wusbhc->chid = *chid; 278 wusbhc->chid = *chid;
278 } 279 }
280
281 /* register with UWB if we haven't already since we are about to start
282 the radio. */
283 if ((chid) && (wusbhc->uwb_rc == NULL)) {
284 wusbhc->uwb_rc = uwb_rc_get_by_grandpa(wusbhc->dev->parent);
285 if (wusbhc->uwb_rc == NULL) {
286 result = -ENODEV;
287 dev_err(wusbhc->dev, "Cannot get associated UWB Host Controller\n");
288 goto error_rc_get;
289 }
290
291 result = wusbhc_pal_register(wusbhc);
292 if (result < 0) {
293 dev_err(wusbhc->dev, "Cannot register as a UWB PAL\n");
294 goto error_pal_register;
295 }
296 }
279 mutex_unlock(&wusbhc->mutex); 297 mutex_unlock(&wusbhc->mutex);
280 298
281 if (chid) 299 if (chid)
282 result = uwb_radio_start(&wusbhc->pal); 300 result = uwb_radio_start(&wusbhc->pal);
283 else 301 else
284 uwb_radio_stop(&wusbhc->pal); 302 uwb_radio_stop(&wusbhc->pal);
303
304 return result;
305
306error_pal_register:
307 uwb_rc_put(wusbhc->uwb_rc);
308 wusbhc->uwb_rc = NULL;
309error_rc_get:
310 mutex_unlock(&wusbhc->mutex);
311
285 return result; 312 return result;
286} 313}
287EXPORT_SYMBOL_GPL(wusbhc_chid_set); 314EXPORT_SYMBOL_GPL(wusbhc_chid_set);
diff --git a/drivers/usb/wusbcore/pal.c b/drivers/usb/wusbcore/pal.c
index d0b172c5ecc7..59e100c2eb50 100644
--- a/drivers/usb/wusbcore/pal.c
+++ b/drivers/usb/wusbcore/pal.c
@@ -45,10 +45,11 @@ int wusbhc_pal_register(struct wusbhc *wusbhc)
45} 45}
46 46
47/** 47/**
48 * wusbhc_pal_register - unregister the WUSB HC as a UWB PAL 48 * wusbhc_pal_unregister - unregister the WUSB HC as a UWB PAL
49 * @wusbhc: the WUSB HC 49 * @wusbhc: the WUSB HC
50 */ 50 */
51void wusbhc_pal_unregister(struct wusbhc *wusbhc) 51void wusbhc_pal_unregister(struct wusbhc *wusbhc)
52{ 52{
53 uwb_pal_unregister(&wusbhc->pal); 53 if (wusbhc->uwb_rc)
54 uwb_pal_unregister(&wusbhc->pal);
54} 55}
diff --git a/drivers/usb/wusbcore/reservation.c b/drivers/usb/wusbcore/reservation.c
index 6f4fafdc2401..ead79f793927 100644
--- a/drivers/usb/wusbcore/reservation.c
+++ b/drivers/usb/wusbcore/reservation.c
@@ -80,6 +80,9 @@ int wusbhc_rsv_establish(struct wusbhc *wusbhc)
80 struct uwb_dev_addr bcid; 80 struct uwb_dev_addr bcid;
81 int ret; 81 int ret;
82 82
83 if (rc == NULL)
84 return -ENODEV;
85
83 rsv = uwb_rsv_create(rc, wusbhc_rsv_complete_cb, wusbhc); 86 rsv = uwb_rsv_create(rc, wusbhc_rsv_complete_cb, wusbhc);
84 if (rsv == NULL) 87 if (rsv == NULL)
85 return -ENOMEM; 88 return -ENOMEM;
diff --git a/drivers/usb/wusbcore/wusbhc.c b/drivers/usb/wusbcore/wusbhc.c
index e712af3e46c2..742c607d1fa3 100644
--- a/drivers/usb/wusbcore/wusbhc.c
+++ b/drivers/usb/wusbcore/wusbhc.c
@@ -325,13 +325,7 @@ int wusbhc_b_create(struct wusbhc *wusbhc)
325 goto error_create_attr_group; 325 goto error_create_attr_group;
326 } 326 }
327 327
328 result = wusbhc_pal_register(wusbhc);
329 if (result < 0)
330 goto error_pal_register;
331 return 0; 328 return 0;
332
333error_pal_register:
334 sysfs_remove_group(wusbhc_kobj(wusbhc), &wusbhc_attr_group);
335error_create_attr_group: 329error_create_attr_group:
336 return result; 330 return result;
337} 331}
@@ -457,7 +451,8 @@ EXPORT_SYMBOL_GPL(wusbhc_giveback_urb);
457 */ 451 */
458void wusbhc_reset_all(struct wusbhc *wusbhc) 452void wusbhc_reset_all(struct wusbhc *wusbhc)
459{ 453{
460 uwb_rc_reset_all(wusbhc->uwb_rc); 454 if (wusbhc->uwb_rc)
455 uwb_rc_reset_all(wusbhc->uwb_rc);
461} 456}
462EXPORT_SYMBOL_GPL(wusbhc_reset_all); 457EXPORT_SYMBOL_GPL(wusbhc_reset_all);
463 458