Re: system freeze with DWL-G520 and possible fix

2013-03-12 Thread Stefan Sperling
On Wed, Jan 16, 2013 at 09:31:19PM +0300, Dinar Talypov wrote:
 Hi,
 
 My D-link DWL-G520 card attaches on ath(4):
 
 ath0 at pci0 dev 9 function 0 Atheros AR5212 rev 0x01: irq 11
 ath0: AR2414 7.9 phy 4.5 rf2413 5.6, FCC2A*, address 00:17:9a:09:f4:5a
 
 On ifconfig ath0 down  ifconfig ath0 up I've got system freeze.
 
 Googleing showed that system can freeze on register read or write
 while AR5212 chip in full sleep mode. And it is not possible to wake it up.
 This implies only for some AR5212 chips.
 
 In linux this is solved by making warm reset, instead 
 of putting it in full sleep mode.
 The diff below does the same thing.
 What do you think about it? Or warm_reset function 
 must be called only for particular chips?

This doesn't seem to break my AP with an ar5212.

ath0 at pci0 dev 12 function 0 Atheros AR5212 rev 0x01: irq 9
ath0: AR5213A 5.9 phy 4.3 rf5112a 3.6, FCC2A*, address 00:02:6f:21:ea:8b

However, I have a few nits:

 Index: ar5212.c
 ===
 RCS file: /cvs/src/sys/dev/ic/ar5212.c,v
 retrieving revision 1.52
 diff -u -r1.52 ar5212.c
 --- ar5212.c  14 Oct 2011 17:08:09 -  1.52
 +++ ar5212.c  16 Jan 2013 16:58:33 -
 @@ -30,6 +30,7 @@
  u_int16_t ar5k_ar5212_radio_revision(struct ath_hal *, HAL_CHIP);
  void  ar5k_ar5212_fill(struct ath_hal *);
  HAL_BOOL  ar5k_ar5212_txpower(struct ath_hal *, HAL_CHANNEL *, u_int);
 +HAL_BOOL  ar5k_ar5212_warm_reset(struct ath_hal *);
  
  /*
   * Initial register setting for the AR5212
 @@ -2420,6 +2421,44 @@
  }
  
  /*
 + * Put MAC and Baseband on warm reset and keep that state
 + * (don't clean sleep control register). After this MAC
 + * and Baseband are disabled and a full reset is needed
 + * to come back. This way we save as much power as possible
 + * without putting the card on full sleep.
 + */

The above comment is copied verbatim from Linux. It's probably OK
to copy comments from a legal perspective, but I would prefer an
original comment written from scratch.

 +
 +HAL_BOOL
 +ar5k_ar5212_warm_reset(struct ath_hal *hal)
 +{
 + u_int32_t flags;
 +
 + flags = AR5K_AR5212_RC_PCU | AR5K_AR5212_RC_BB;
 + if (hal-ah_pci_express == AH_FALSE)
 + flags |= AR5K_AR5212_RC_PCI;
 +
 + if (ar5k_ar5212_nic_reset(hal, flags) == AH_FALSE) {
 + AR5K_PRINT(failed to reset the AR5212 + PCI chipset\n);

I don't see the point of printing anything here.

 + return (AH_FALSE);
 + }
 +
 + /* ...wakeup */

This comment is also adapted from Linux. And not very useful.

 + if (ar5k_ar5212_set_power(hal,
 + HAL_PM_AWAKE, AH_TRUE, 0) == AH_FALSE) {
 + AR5K_PRINT(failed to resume the AR5212 (again)\n);

Again, it doesn't seem useful to print something here.

 + return (AH_FALSE);
 + }
 +
 + /* Put chipset on warm reset... */
 + if (ar5k_ar5212_nic_reset(hal, 0) == AH_FALSE) {
 + AR5K_PRINT(failed to warm reset the AR5212\n);

Likewise.

 + return (AH_FALSE);
 + }
 +
 + return (AH_TRUE);
 +}
 +
 +/*
   * Power management functions
   */
  
 @@ -2445,10 +2484,8 @@
   break;
  
   case HAL_PM_FULL_SLEEP:
 - if (set_chip == AH_TRUE) {
 - AR5K_REG_WRITE(AR5K_AR5212_SCR,
 - AR5K_AR5212_SCR_SLE_SLP);
 - }
 + if (set_chip == AH_TRUE)
 + ar5k_ar5212_warm_reset(hal);
   staid |= AR5K_AR5212_STA_ID1_PWR_SV;
   break;
  
 
 
 -- 
 Dinar Talypov t.dina...@gmail.com



Re: system freeze with DWL-G520 and possible fix

2013-01-30 Thread Dinar Talypov
Any comments on this?


2013/1/16 Dinar Talypov t.dina...@gmail.com:
 Hi,

 My D-link DWL-G520 card attaches on ath(4):

 ath0 at pci0 dev 9 function 0 Atheros AR5212 rev 0x01: irq 11
 ath0: AR2414 7.9 phy 4.5 rf2413 5.6, FCC2A*, address 00:17:9a:09:f4:5a

 On ifconfig ath0 down  ifconfig ath0 up I've got system freeze.

 Googleing showed that system can freeze on register read or write
 while AR5212 chip in full sleep mode. And it is not possible to wake it up.
 This implies only for some AR5212 chips.

 In linux this is solved by making warm reset, instead
 of putting it in full sleep mode.
 The diff below does the same thing.
 What do you think about it? Or warm_reset function
 must be called only for particular chips?

 Index: ar5212.c
 ===
 RCS file: /cvs/src/sys/dev/ic/ar5212.c,v
 retrieving revision 1.52
 diff -u -r1.52 ar5212.c
 --- ar5212.c14 Oct 2011 17:08:09 -  1.52
 +++ ar5212.c16 Jan 2013 16:58:33 -
 @@ -30,6 +30,7 @@
  u_int16_t   ar5k_ar5212_radio_revision(struct ath_hal *, HAL_CHIP);
  voidar5k_ar5212_fill(struct ath_hal *);
  HAL_BOOLar5k_ar5212_txpower(struct ath_hal *, HAL_CHANNEL *, u_int);
 +HAL_BOOLar5k_ar5212_warm_reset(struct ath_hal *);

  /*
   * Initial register setting for the AR5212
 @@ -2420,6 +2421,44 @@
  }

  /*
 + * Put MAC and Baseband on warm reset and keep that state
 + * (don't clean sleep control register). After this MAC
 + * and Baseband are disabled and a full reset is needed
 + * to come back. This way we save as much power as possible
 + * without putting the card on full sleep.
 + */
 +
 +HAL_BOOL
 +ar5k_ar5212_warm_reset(struct ath_hal *hal)
 +{
 +   u_int32_t flags;
 +
 +   flags = AR5K_AR5212_RC_PCU | AR5K_AR5212_RC_BB;
 +   if (hal-ah_pci_express == AH_FALSE)
 +   flags |= AR5K_AR5212_RC_PCI;
 +
 +   if (ar5k_ar5212_nic_reset(hal, flags) == AH_FALSE) {
 +   AR5K_PRINT(failed to reset the AR5212 + PCI chipset\n);
 +   return (AH_FALSE);
 +   }
 +
 +   /* ...wakeup */
 +   if (ar5k_ar5212_set_power(hal,
 +   HAL_PM_AWAKE, AH_TRUE, 0) == AH_FALSE) {
 +   AR5K_PRINT(failed to resume the AR5212 (again)\n);
 +   return (AH_FALSE);
 +   }
 +
 +   /* Put chipset on warm reset... */
 +   if (ar5k_ar5212_nic_reset(hal, 0) == AH_FALSE) {
 +   AR5K_PRINT(failed to warm reset the AR5212\n);
 +   return (AH_FALSE);
 +   }
 +
 +   return (AH_TRUE);
 +}
 +
 +/*
   * Power management functions
   */

 @@ -2445,10 +2484,8 @@
 break;

 case HAL_PM_FULL_SLEEP:
 -   if (set_chip == AH_TRUE) {
 -   AR5K_REG_WRITE(AR5K_AR5212_SCR,
 -   AR5K_AR5212_SCR_SLE_SLP);
 -   }
 +   if (set_chip == AH_TRUE)
 +   ar5k_ar5212_warm_reset(hal);
 staid |= AR5K_AR5212_STA_ID1_PWR_SV;
 break;



 --
 Dinar Talypov t.dina...@gmail.com



system freeze with DWL-G520 and possible fix

2013-01-16 Thread Dinar Talypov
Hi,

My D-link DWL-G520 card attaches on ath(4):

ath0 at pci0 dev 9 function 0 Atheros AR5212 rev 0x01: irq 11
ath0: AR2414 7.9 phy 4.5 rf2413 5.6, FCC2A*, address 00:17:9a:09:f4:5a

On ifconfig ath0 down  ifconfig ath0 up I've got system freeze.

Googleing showed that system can freeze on register read or write
while AR5212 chip in full sleep mode. And it is not possible to wake it up.
This implies only for some AR5212 chips.

In linux this is solved by making warm reset, instead 
of putting it in full sleep mode.
The diff below does the same thing.
What do you think about it? Or warm_reset function 
must be called only for particular chips?

Index: ar5212.c
===
RCS file: /cvs/src/sys/dev/ic/ar5212.c,v
retrieving revision 1.52
diff -u -r1.52 ar5212.c
--- ar5212.c14 Oct 2011 17:08:09 -  1.52
+++ ar5212.c16 Jan 2013 16:58:33 -
@@ -30,6 +30,7 @@
 u_int16_t   ar5k_ar5212_radio_revision(struct ath_hal *, HAL_CHIP);
 voidar5k_ar5212_fill(struct ath_hal *);
 HAL_BOOLar5k_ar5212_txpower(struct ath_hal *, HAL_CHANNEL *, u_int);
+HAL_BOOLar5k_ar5212_warm_reset(struct ath_hal *);
 
 /*
  * Initial register setting for the AR5212
@@ -2420,6 +2421,44 @@
 }
 
 /*
+ * Put MAC and Baseband on warm reset and keep that state
+ * (don't clean sleep control register). After this MAC
+ * and Baseband are disabled and a full reset is needed
+ * to come back. This way we save as much power as possible
+ * without putting the card on full sleep.
+ */
+
+HAL_BOOL
+ar5k_ar5212_warm_reset(struct ath_hal *hal)
+{
+   u_int32_t flags;
+
+   flags = AR5K_AR5212_RC_PCU | AR5K_AR5212_RC_BB;
+   if (hal-ah_pci_express == AH_FALSE)
+   flags |= AR5K_AR5212_RC_PCI;
+
+   if (ar5k_ar5212_nic_reset(hal, flags) == AH_FALSE) {
+   AR5K_PRINT(failed to reset the AR5212 + PCI chipset\n);
+   return (AH_FALSE);
+   }
+
+   /* ...wakeup */
+   if (ar5k_ar5212_set_power(hal,
+   HAL_PM_AWAKE, AH_TRUE, 0) == AH_FALSE) {
+   AR5K_PRINT(failed to resume the AR5212 (again)\n);
+   return (AH_FALSE);
+   }
+
+   /* Put chipset on warm reset... */
+   if (ar5k_ar5212_nic_reset(hal, 0) == AH_FALSE) {
+   AR5K_PRINT(failed to warm reset the AR5212\n);
+   return (AH_FALSE);
+   }
+
+   return (AH_TRUE);
+}
+
+/*
  * Power management functions
  */
 
@@ -2445,10 +2484,8 @@
break;
 
case HAL_PM_FULL_SLEEP:
-   if (set_chip == AH_TRUE) {
-   AR5K_REG_WRITE(AR5K_AR5212_SCR,
-   AR5K_AR5212_SCR_SLE_SLP);
-   }
+   if (set_chip == AH_TRUE)
+   ar5k_ar5212_warm_reset(hal);
staid |= AR5K_AR5212_STA_ID1_PWR_SV;
break;
 


-- 
Dinar Talypov t.dina...@gmail.com