All of lore.kernel.org
 help / color / mirror / Atom feed
* ar9710 resume hangs
@ 2009-04-18  7:59 Johannes Berg
  2009-04-18 13:04 ` Christian Lamparter
  0 siblings, 1 reply; 5+ messages in thread
From: Johannes Berg @ 2009-04-18  7:59 UTC (permalink / raw)
  To: Christian Lamparter; +Cc: linux-wireless

[-- Attachment #1: Type: text/plain, Size: 73 bytes --]

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

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: ar9710 resume hangs
  2009-04-18  7:59 ar9710 resume hangs Johannes Berg
@ 2009-04-18 13:04 ` Christian Lamparter
  2009-04-18 13:19   ` Johannes Berg
  0 siblings, 1 reply; 5+ messages in thread
From: Christian Lamparter @ 2009-04-18 13:04 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

[-- Attachment #1: Type: text/plain, Size: 295 bytes --]

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

[-- Attachment #2: ar9170usb-resume.diff --]
[-- Type: text/x-patch, Size: 3424 bytes --]

diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
index c9e422e..361cb89 100644
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -623,6 +623,43 @@ 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_reset(aru);
+	if (err)
+		goto err_out;
+
+	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)
 {
@@ -656,34 +693,14 @@ static int ar9170_usb_probe(struct usb_interface *intf,
 	aru->common.exec_cmd = ar9170_usb_exec_cmd;
 	aru->common.callback_cmd = ar9170_usb_callback_cmd;
 
-	err = ar9170_usb_reset(aru);
-	if (err)
-		goto err_unlock;
-
 	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)

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: ar9710 resume hangs
  2009-04-18 13:04 ` Christian Lamparter
@ 2009-04-18 13:19   ` Johannes Berg
  2009-04-18 14:21     ` Christian Lamparter
  0 siblings, 1 reply; 5+ messages in thread
From: Johannes Berg @ 2009-04-18 13:19 UTC (permalink / raw)
  To: Christian Lamparter; +Cc: linux-wireless

[-- Attachment #1: Type: text/plain, Size: 476 bytes --]

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

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: ar9710 resume hangs
  2009-04-18 13:19   ` Johannes Berg
@ 2009-04-18 14:21     ` Christian Lamparter
  2009-04-18 14:46       ` Christian Lamparter
  0 siblings, 1 reply; 5+ messages in thread
From: Christian Lamparter @ 2009-04-18 14:21 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

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)

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: ar9710 resume hangs
  2009-04-18 14:21     ` Christian Lamparter
@ 2009-04-18 14:46       ` Christian Lamparter
  0 siblings, 0 replies; 5+ messages in thread
From: Christian Lamparter @ 2009-04-18 14:46 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

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)

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2009-04-18 14:46 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-18  7:59 ar9710 resume hangs Johannes Berg
2009-04-18 13:04 ` Christian Lamparter
2009-04-18 13:19   ` Johannes Berg
2009-04-18 14:21     ` Christian Lamparter
2009-04-18 14:46       ` Christian Lamparter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.