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 



Re: system freeze with DWL-G520 and possible fix

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


2013/1/16 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