2009-04-18 07:59:46

by Johannes Berg

[permalink] [raw]
Subject: ar9710 resume hangs

because it tries to load firmware before userspace is up :/

johannes


Attachments:
signature.asc (836.00 B)
This is a digitally signed message part

2009-04-18 14:46:30

by Christian Lamparter

[permalink] [raw]
Subject: Re: ar9710 resume hangs

On Saturday 18 April 2009 16:21:27 Christian Lamparter wrote:
> On Saturday 18 April 2009 15:19:43 Johannes Berg wrote:
> > On Sat, 2009-04-18 at 15:04 +0200, Christian Lamparter wrote:
> > > On Saturday 18 April 2009 09:59:42 Johannes Berg wrote:
> > > > because it tries to load firmware before userspace is up :/
> > >
> > > heh, I have 4 different machines and not a single one does
> > > atleast one suspend & resume cycle properly.
> >
> >
> > Heh.
> >
> > > here's a patch that compiles, but may not work at all.
> >
> > Huh, wouldn't it be simpler to just cache the firmware? Everything else
> > seems ok as-is.
> >
>
> > it's better, in that it doesn't hang at resume
> > [ 6694.110048] usb 1-1: unable to lock device for reset (-16).
> > [ 6694.119657] ar9170usb 1-1:1.0: resume error -16
> > [ 6695.140043] usb 1-1: unable to lock device for reset (-16).
> > [ 6695.149649] ar9170usb 1-1:1.0: resume error -16
>
> please retry with the attached version...
> [ 8153.991223] ar9170usb 1-1:1.0: resume error -1
> [ 8154.001191] ar9170usb 1-1:1.0: resume error -1

should be fixed... let's see if the third attempt is the lucky one.
---
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
index c9e422e..8b23386 100644
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -623,6 +623,39 @@ static int ar9170_usb_open(struct ar9170 *ar)
return 0;
}

+static int ar9170_usb_init_device(struct ar9170_usb *aru)
+{
+ int err;
+
+ err = ar9170_usb_alloc_rx_irq_urb(aru);
+ if (err)
+ goto err_out;
+
+ err = ar9170_usb_alloc_rx_bulk_urbs(aru);
+ if (err)
+ goto err_unrx;
+
+ err = ar9170_usb_upload_firmware(aru);
+ if (err) {
+ err = ar9170_echo_test(&aru->common, 0x60d43110);
+ if (err) {
+ /* force user invention, by disabling the device */
+ err = usb_driver_set_configuration(aru->udev, -1);
+ dev_err(&aru->udev->dev, "device is in a bad state. "
+ "please reconnect it!\n");
+ goto err_unrx;
+ }
+ }
+
+ return 0;
+
+err_unrx:
+ ar9170_usb_cancel_urbs(aru);
+
+err_out:
+ return err;
+}
+
static int ar9170_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -658,32 +691,16 @@ static int ar9170_usb_probe(struct usb_interface *intf,

err = ar9170_usb_reset(aru);
if (err)
- goto err_unlock;
+ goto err_freehw;

err = ar9170_usb_request_firmware(aru);
if (err)
- goto err_unlock;
+ goto err_freehw;

- err = ar9170_usb_alloc_rx_irq_urb(aru);
+ err = ar9170_usb_init_device(aru);
if (err)
goto err_freefw;

- err = ar9170_usb_alloc_rx_bulk_urbs(aru);
- if (err)
- goto err_unrx;
-
- err = ar9170_usb_upload_firmware(aru);
- if (err) {
- err = ar9170_echo_test(&aru->common, 0x60d43110);
- if (err) {
- /* force user invention, by disabling the device */
- err = usb_driver_set_configuration(aru->udev, -1);
- dev_err(&aru->udev->dev, "device is in a bad state. "
- "please reconnect it!\n");
- goto err_unrx;
- }
- }
-
err = ar9170_usb_open(ar);
if (err)
goto err_unrx;
@@ -703,7 +720,7 @@ err_freefw:
release_firmware(aru->init_values);
release_firmware(aru->firmware);

-err_unlock:
+err_freehw:
usb_set_intfdata(intf, NULL);
usb_put_dev(udev);
ieee80211_free_hw(ar->hw);
@@ -730,12 +747,60 @@ static void ar9170_usb_disconnect(struct usb_interface *intf)
ieee80211_free_hw(aru->common.hw);
}

+#ifdef CONFIG_PM
+static int ar9170_suspend(struct usb_interface *intf,
+ pm_message_t message)
+{
+ struct ar9170_usb *aru = usb_get_intfdata(intf);
+
+ if (!aru)
+ return -ENODEV;
+
+ aru->common.state = AR9170_IDLE;
+ ar9170_usb_cancel_urbs(aru);
+
+ return 0;
+}
+
+static int ar9170_resume(struct usb_interface *intf)
+{
+ struct ar9170_usb *aru = usb_get_intfdata(intf);
+ int err;
+
+ if (!aru)
+ return -ENODEV;
+
+ usb_unpoison_anchored_urbs(&aru->rx_submitted);
+ usb_unpoison_anchored_urbs(&aru->tx_submitted);
+
+ err = ar9170_usb_init_device(aru);
+ if (err)
+ goto err_unrx;
+
+ err = ar9170_usb_open(&aru->common);
+ if (err)
+ goto err_unrx;
+
+ return 0;
+
+err_unrx:
+ aru->common.state = AR9170_IDLE;
+ ar9170_usb_cancel_urbs(aru);
+
+ return err;
+}
+#endif /* CONFIG_PM */
+
static struct usb_driver ar9170_driver = {
.name = "ar9170usb",
.probe = ar9170_usb_probe,
.disconnect = ar9170_usb_disconnect,
.id_table = ar9170_usb_ids,
.soft_unbind = 1,
+#ifdef CONFIG_PM
+ .suspend = ar9170_suspend,
+ .resume = ar9170_resume,
+#endif /* CONFIG_PM */
};

static int __init ar9170_init(void)

2009-04-18 13:04:17

by Christian Lamparter

[permalink] [raw]
Subject: Re: ar9710 resume hangs

On Saturday 18 April 2009 09:59:42 Johannes Berg wrote:
> because it tries to load firmware before userspace is up :/

heh, I have 4 different machines and not a single one does
atleast one suspend & resume cycle properly.

here's a patch that compiles, but may not work at all.

regards,
chr


Attachments:
(No filename) (295.00 B)
ar9170usb-resume.diff (3.34 kB)
Download all attachments

2009-04-18 14:21:30

by Christian Lamparter

[permalink] [raw]
Subject: Re: ar9710 resume hangs

On Saturday 18 April 2009 15:19:43 Johannes Berg wrote:
> On Sat, 2009-04-18 at 15:04 +0200, Christian Lamparter wrote:
> > On Saturday 18 April 2009 09:59:42 Johannes Berg wrote:
> > > because it tries to load firmware before userspace is up :/
> >
> > heh, I have 4 different machines and not a single one does
> > atleast one suspend & resume cycle properly.
>
>
> Heh.
>
> > here's a patch that compiles, but may not work at all.
>
> Huh, wouldn't it be simpler to just cache the firmware? Everything else
> seems ok as-is.
>

> it's better, in that it doesn't hang at resume
> [ 6694.110048] usb 1-1: unable to lock device for reset (-16).
> [ 6694.119657] ar9170usb 1-1:1.0: resume error -16
> [ 6695.140043] usb 1-1: unable to lock device for reset (-16).
> [ 6695.149649] ar9170usb 1-1:1.0: resume error -16

please retry with the attached version...
---
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
index c9e422e..d9090d9 100644
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -623,6 +623,39 @@ static int ar9170_usb_open(struct ar9170 *ar)
return 0;
}

+static int ar9170_usb_init_device(struct ar9170_usb *aru)
+{
+ int err;
+
+ err = ar9170_usb_alloc_rx_irq_urb(aru);
+ if (err)
+ goto err_out;
+
+ err = ar9170_usb_alloc_rx_bulk_urbs(aru);
+ if (err)
+ goto err_unrx;
+
+ err = ar9170_usb_upload_firmware(aru);
+ if (err) {
+ err = ar9170_echo_test(&aru->common, 0x60d43110);
+ if (err) {
+ /* force user invention, by disabling the device */
+ err = usb_driver_set_configuration(aru->udev, -1);
+ dev_err(&aru->udev->dev, "device is in a bad state. "
+ "please reconnect it!\n");
+ goto err_unrx;
+ }
+ }
+
+ return 0;
+
+err_unrx:
+ ar9170_usb_cancel_urbs(aru);
+
+err_out:
+ return err;
+}
+
static int ar9170_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -658,32 +691,16 @@ static int ar9170_usb_probe(struct usb_interface *intf,

err = ar9170_usb_reset(aru);
if (err)
- goto err_unlock;
+ goto err_freehw;

err = ar9170_usb_request_firmware(aru);
if (err)
- goto err_unlock;
+ goto err_freehw;

- err = ar9170_usb_alloc_rx_irq_urb(aru);
+ err = ar9170_usb_init_device(aru);
if (err)
goto err_freefw;

- err = ar9170_usb_alloc_rx_bulk_urbs(aru);
- if (err)
- goto err_unrx;
-
- err = ar9170_usb_upload_firmware(aru);
- if (err) {
- err = ar9170_echo_test(&aru->common, 0x60d43110);
- if (err) {
- /* force user invention, by disabling the device */
- err = usb_driver_set_configuration(aru->udev, -1);
- dev_err(&aru->udev->dev, "device is in a bad state. "
- "please reconnect it!\n");
- goto err_unrx;
- }
- }
-
err = ar9170_usb_open(ar);
if (err)
goto err_unrx;
@@ -703,7 +720,7 @@ err_freefw:
release_firmware(aru->init_values);
release_firmware(aru->firmware);

-err_unlock:
+err_freehw:
usb_set_intfdata(intf, NULL);
usb_put_dev(udev);
ieee80211_free_hw(ar->hw);
@@ -730,12 +747,57 @@ static void ar9170_usb_disconnect(struct usb_interface *intf)
ieee80211_free_hw(aru->common.hw);
}

+#ifdef CONFIG_PM
+static int ar9170_suspend(struct usb_interface *intf,
+ pm_message_t message)
+{
+ struct ar9170_usb *aru = usb_get_intfdata(intf);
+
+ if (!aru)
+ return -ENODEV;
+
+ aru->common.state = AR9170_IDLE;
+ ar9170_usb_cancel_urbs(aru);
+
+ return 0;
+}
+
+static int ar9170_resume(struct usb_interface *intf)
+{
+ struct ar9170_usb *aru = usb_get_intfdata(intf);
+ int err;
+
+ if (!aru)
+ return -ENODEV;
+
+ err = ar9170_usb_init_device(aru);
+ if (err)
+ goto err_unrx;
+
+ err = ar9170_usb_open(&aru->common);
+ if (err)
+ goto err_unrx;
+
+ return 0;
+
+err_unrx:
+ aru->common.state = AR9170_IDLE;
+ ar9170_usb_cancel_urbs(aru);
+
+ return err;
+}
+#endif /* CONFIG_PM */
+
static struct usb_driver ar9170_driver = {
.name = "ar9170usb",
.probe = ar9170_usb_probe,
.disconnect = ar9170_usb_disconnect,
.id_table = ar9170_usb_ids,
.soft_unbind = 1,
+#ifdef CONFIG_PM
+ .suspend = ar9170_suspend,
+ .resume = ar9170_resume,
+#endif /* CONFIG_PM */
};

static int __init ar9170_init(void)

2009-04-18 13:19:50

by Johannes Berg

[permalink] [raw]
Subject: Re: ar9710 resume hangs

On Sat, 2009-04-18 at 15:04 +0200, Christian Lamparter wrote:
> On Saturday 18 April 2009 09:59:42 Johannes Berg wrote:
> > because it tries to load firmware before userspace is up :/
>
> heh, I have 4 different machines and not a single one does
> atleast one suspend & resume cycle properly.


Heh.

> here's a patch that compiles, but may not work at all.

Huh, wouldn't it be simpler to just cache the firmware? Everything else
seems ok as-is.

johannes


Attachments:
signature.asc (836.00 B)
This is a digitally signed message part