aboutsummaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap/linus/0013-ueagle-atm-fix-PHY-signal-initialization-race.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/linus/0013-ueagle-atm-fix-PHY-signal-initialization-race.patch')
-rw-r--r--extras/recipes-kernel/linux/linux-omap/linus/0013-ueagle-atm-fix-PHY-signal-initialization-race.patch100
1 files changed, 100 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/linus/0013-ueagle-atm-fix-PHY-signal-initialization-race.patch b/extras/recipes-kernel/linux/linux-omap/linus/0013-ueagle-atm-fix-PHY-signal-initialization-race.patch
new file mode 100644
index 00000000..e62a9d8c
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap/linus/0013-ueagle-atm-fix-PHY-signal-initialization-race.patch
@@ -0,0 +1,100 @@
+From c23a13703fb00384d49a00875fc12a5e00f1946a Mon Sep 17 00:00:00 2001
+From: Dan Williams <dcbw@redhat.com>
+Date: Sun, 19 Dec 2010 08:17:50 +0000
+Subject: [PATCH 13/65] ueagle-atm: fix PHY signal initialization race
+
+A race exists when initializing ueagle-atm devices where the generic atm
+device may not yet be created before the driver attempts to initialize
+it's PHY signal state, which checks whether the atm device has been
+created or not. This often causes the sysfs 'carrier' attribute to be
+'1' even though no signal has actually been found.
+
+uea_probe
+ usbatm_usb_probe
+ driver->bind (uea_bind)
+ uea_boot
+ kthread_run(uea_kthread) uea_kthread
+ usbatm_atm_init uea_start_reset
+ atm_dev_register UPDATE_ATM_SIGNAL
+
+UPDATE_ATM_SIGNAL checks whether the ATM device has been created and if
+not, will not update the PHY signal state. Because of the race that
+does not always happen in time, and the PHY signal state remains
+ATM_PHY_SIG_FOUND even though no signal exists.
+
+To fix the race, just create the kthread during initialization, and only
+after initialization is complete, start the thread that reboots the
+device and initializes PHY state.
+
+[ 3030.490931] uea_probe: calling usbatm_usb_probe
+[ 3030.490946] ueagle-atm 8-2:1.0: usbatm_usb_probe: trying driver ueagle-atm with vendor=1110, product=9031, ifnum 0
+[ 3030.493691] uea_bind: setting usbatm
+[ 3030.496932] usb 8-2: [ueagle-atm] using iso mode
+[ 3030.497283] ueagle-atm 8-2:1.0: usbatm_usb_probe: using 3021 byte buffer for rx channel 0xffff880125953508
+ <kthread already started before usbatm_usb_probe() has returned>
+[ 3030.497292] usb 8-2: [ueagle-atm] (re)booting started
+ <UPDATE_ATM_SIGNAL checks whether ATM device has been created yet before setting PHY state>
+[ 3030.497298] uea_start_reset: atm dev (null)
+ <and since it hasn't been created yet PHY state is not set>
+[ 3030.497306] ueagle-atm 8-2:1.0: usbatm_usb_probe: using 3392 byte buffer for tx channel 0xffff8801259535b8
+[ 3030.497374] usbatm_usb_probe: about to init
+[ 3030.497379] usbatm_usb_probe: calling usbatm_atm_init
+ <atm device finally gets created>
+[ 3030.497384] usbatm_atm_init: creating atm device!
+
+Signed-off-by: Dan Williams <dcbw@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/usb/atm/ueagle-atm.c | 22 +++++++++++++++++++---
+ 1 files changed, 19 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
+index 44447f5..99ac70e 100644
+--- a/drivers/usb/atm/ueagle-atm.c
++++ b/drivers/usb/atm/ueagle-atm.c
+@@ -2206,8 +2206,11 @@ static int uea_boot(struct uea_softc *sc)
+ goto err1;
+ }
+
+- sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm");
+- if (sc->kthread == ERR_PTR(-ENOMEM)) {
++ /* Create worker thread, but don't start it here. Start it after
++ * all usbatm generic initialization is done.
++ */
++ sc->kthread = kthread_create(uea_kthread, sc, "ueagle-atm");
++ if (IS_ERR(sc->kthread)) {
+ uea_err(INS_TO_USBDEV(sc), "failed to create thread\n");
+ goto err2;
+ }
+@@ -2624,6 +2627,7 @@ static struct usbatm_driver uea_usbatm_driver = {
+ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ {
+ struct usb_device *usb = interface_to_usbdev(intf);
++ int ret;
+
+ uea_enters(usb);
+ uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) Rev (%#X): %s\n",
+@@ -2637,7 +2641,19 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ if (UEA_IS_PREFIRM(id))
+ return uea_load_firmware(usb, UEA_CHIP_VERSION(id));
+
+- return usbatm_usb_probe(intf, id, &uea_usbatm_driver);
++ ret = usbatm_usb_probe(intf, id, &uea_usbatm_driver);
++ if (ret == 0) {
++ struct usbatm_data *usbatm = usb_get_intfdata(intf);
++ struct uea_softc *sc = usbatm->driver_data;
++
++ /* Ensure carrier is initialized to off as early as possible */
++ UPDATE_ATM_SIGNAL(ATM_PHY_SIG_LOST);
++
++ /* Only start the worker thread when all init is done */
++ wake_up_process(sc->kthread);
++ }
++
++ return ret;
+ }
+
+ static void uea_disconnect(struct usb_interface *intf)
+--
+1.6.6.1
+