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.c    14 Oct 2011 17:08:09 -0000      1.52
> +++ ar5212.c    16 Jan 2013 16:58:33 -0000
> @@ -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.
> + */
> +
> +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>

Reply via email to