because it tries to load firmware before userspace is up :/
johannes
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)
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
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)
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