linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ian Schram <ischram@telenet.be>
To: Vasanthakumar Thiagarajan <vasanth@atheros.com>
Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org,
	jouni.malinen@atheros.com, luis.rodriguez@atheros.com
Subject: Re: [PATCH] ath9k: Add LED support
Date: Mon, 25 Aug 2008 16:00:24 +0200	[thread overview]
Message-ID: <48B2BAF8.4090300@telenet.be> (raw)
In-Reply-To: <20080825132845.GA7746@vasanth-lnx.users.atheros.com>


Vasanthakumar Thiagarajan wrote:
> Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com>
> ---
>  drivers/net/wireless/ath9k/ath9k.h |   16 ++--
>  drivers/net/wireless/ath9k/core.h  |   28 +++++++
>  drivers/net/wireless/ath9k/hw.c    |   33 +--------
>  drivers/net/wireless/ath9k/main.c  |  138 +++++++++++++++++++++++++++++++++++-
>  drivers/net/wireless/ath9k/reg.h   |    6 --
>  5 files changed, 175 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h
> index 841893b..020b97f 100644
> --- a/drivers/net/wireless/ath9k/ath9k.h
> +++ b/drivers/net/wireless/ath9k/ath9k.h
> @@ -757,14 +757,11 @@ struct ath9k_node_stats {
>  
>  #define ATH9K_RSSI_EP_MULTIPLIER  (1<<7)
>  
> -enum ath9k_gpio_output_mux_type {
> -	ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT,
> -	ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
> -	ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
> -	ATH9K_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
> -	ATH9K_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
> -	ATH9K_GPIO_OUTPUT_MUX_NUM_ENTRIES
> -};
> +#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT             0
> +#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
> +#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED     2
> +#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED    5
> +#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED      6
>  
>  enum {
>  	ATH9K_RESET_POWER_ON,
> @@ -1008,4 +1005,7 @@ void ath9k_hw_get_channel_centers(struct ath_hal *ah,
>  bool ath9k_get_channel_edges(struct ath_hal *ah,
>  			     u16 flags, u16 *low,
>  			     u16 *high);
> +void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
> +			u32 ah_signal_type);
> +void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 value);
>  #endif
> diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h
> index de1d12f..a4dc58d 100644
> --- a/drivers/net/wireless/ath9k/core.h
> +++ b/drivers/net/wireless/ath9k/core.h
> @@ -39,6 +39,7 @@
>  #include <linux/scatterlist.h>
>  #include <asm/page.h>
>  #include <net/mac80211.h>
> +#include <linux/leds.h>
>  
>  #include "ath9k.h"
>  #include "rc.h"
> @@ -803,6 +804,26 @@ void ath_slow_ant_div(struct ath_antdiv *antdiv,
>  void ath_setdefantenna(void *sc, u32 antenna);
>  
>  /********************/
> +/*   LED Control    */
> +/********************/
> +
> +#define ATH_LED_PIN	1
> +
> +enum ath_led_type {
> +	ATH_LED_RADIO,
> +	ATH_LED_ASSOC,
> +	ATH_LED_TX,
> +	ATH_LED_RX
> +};
> +
> +struct ath_led {
> +	struct ath_softc *sc;
> +	struct led_classdev led_cdev;
> +	enum ath_led_type led_type;
> +	bool registered;
> +};
> +
> +/********************/
>  /* Main driver core */
>  /********************/
>  
> @@ -884,6 +905,7 @@ struct ath_ht_info {
>  #define SC_OP_PREAMBLE_SHORT	BIT(7)
>  #define SC_OP_PROTECT_ENABLE	BIT(8)
>  #define SC_OP_RXFLUSH		BIT(9)
> +#define SC_OP_LED_ASSOCIATED	BIT(10)
>  
>  struct ath_softc {
>  	struct ieee80211_hw *hw;
> @@ -988,6 +1010,12 @@ struct ath_softc {
>  	spinlock_t sc_txbuflock;
>  	spinlock_t sc_resetlock;
>  	spinlock_t node_lock;
> +
> +	/* LEDs */
> +	struct ath_led radio_led;
> +	struct ath_led assoc_led;
> +	struct ath_led tx_led;
> +	struct ath_led rx_led;
>  };
>  
>  int ath_init(u16 devid, struct ath_softc *sc);
> diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c
> index 41d613b..ff5eedc 100644
> --- a/drivers/net/wireless/ath9k/hw.c
> +++ b/drivers/net/wireless/ath9k/hw.c
> @@ -2800,32 +2800,11 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hal *ah,
>  	}
>  }
>  
> -static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
> -				enum ath9k_gpio_output_mux_type
> -				halSignalType)
> +void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
> +			 u32 ah_signal_type)
>  {
> -	u32 ah_signal_type;
>  	u32 gpio_shift;
>  
> -	static u32 MuxSignalConversionTable[] = {
> -
> -		AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
> -
> -		AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
> -
> -		AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
> -
> -		AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
> -
> -		AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
> -	};
> -
> -	if ((halSignalType >= 0)
> -	    && (halSignalType < ARRAY_SIZE(MuxSignalConversionTable)))
> -		ah_signal_type = MuxSignalConversionTable[halSignalType];
> -	else
> -		return false;
> -
>  	ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
>  
>  	gpio_shift = 2 * gpio;
> @@ -2834,16 +2813,12 @@ static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
>  		AR_GPIO_OE_OUT,
>  		(AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
>  		(AR_GPIO_OE_OUT_DRV << gpio_shift));
> -
> -	return true;
>  }
>  
> -static bool ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio,
> -			      u32 val)
> +void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val)
>  {
>  	REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
>  		AR_GPIO_BIT(gpio));
> -	return true;
>  }
>  
>  static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
> @@ -5919,7 +5894,7 @@ bool ath9k_hw_reset(struct ath_hal *ah,
>  			else
>  				ath9k_hw_set_gpio(ah, 9, 1);
>  		}
> -		ath9k_hw_cfg_output(ah, 9, ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT);
> +		ath9k_hw_cfg_output(ah, 9, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
>  	}
>  
>  	ecode = ath9k_hw_process_ini(ah, chan, macmode);
> diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
> index dca00c3..4424af2 100644
> --- a/drivers/net/wireless/ath9k/main.c
> +++ b/drivers/net/wireless/ath9k/main.c
> @@ -1172,12 +1172,130 @@ enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc)
>  	return sc->sc_ht_info.tx_chan_width;
>  }
>  
> +/********************************/
> +/*	 LED functions		*/
> +/********************************/
> +
> +static void ath_led_brightness(struct led_classdev *led_cdev,
> +			       enum led_brightness brightness)
> +{
> +	struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
> +	struct ath_softc *sc = led->sc;
> +
> +	switch (brightness) {
> +	case LED_OFF:
> +		if (led->led_type == ATH_LED_ASSOC ||
> +		    led->led_type == ATH_LED_RADIO)
> +			sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
> +		ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
> +				(led->led_type == ATH_LED_RADIO) ? 1 :
> +				!!(sc->sc_flags & SC_OP_LED_ASSOCIATED));
> +		break;
> +	case LED_FULL:
> +		if (led->led_type == ATH_LED_ASSOC)
> +			sc->sc_flags |= SC_OP_LED_ASSOCIATED;
> +		ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +
> +static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
> +			    char *trigger, const char *name)
> +{
> +	int ret;
> +
> +	led->sc = sc;
> +	led->led_cdev.name = name;

If i'm not mistaken, this has a similar problem as was recently fixed in
iwlwifi.

See the thread
"[PATCH] iwlwifi: Don't use buffer allocated on the stack for led names"
by Sven Wegener from 1/8/8

name is a stack pointer allocated in the calling function.



> +	led->led_cdev.default_trigger = trigger;
> +	led->led_cdev.brightness_set = ath_led_brightness;
> +
> +	ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
> +	if (ret)
> +		DPRINTF(sc, ATH_DBG_FATAL, "Failed to register led:%s", name);
> +	else
> +		led->registered = 1;
> +	return ret;
> +}
> +
> +static void ath_unregister_led(struct ath_led *led)
> +{
> +	if (led->registered) {
> +		led_classdev_unregister(&led->led_cdev);
> +		led->registered = 0;
> +	}
> +}
> +
> +static void ath_deinit_leds(struct ath_softc *sc)
> +{
> +	ath_unregister_led(&sc->assoc_led);
> +	sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
> +	ath_unregister_led(&sc->tx_led);
> +	ath_unregister_led(&sc->rx_led);
> +	ath_unregister_led(&sc->radio_led);
> +	ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
> +}
> +
> +static void ath_init_leds(struct ath_softc *sc)
> +{
> +	char *trigger;
> +	char name[32];
> +	int ret;
> +
> +	/* Configure gpio 1 for output */
> +	ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
> +			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
> +	/* LED off, active low */
> +	ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
> +
> +	trigger = ieee80211_get_radio_led_name(sc->hw);
> +	snprintf(name, sizeof(name), "ath9k-%s:radio",
> +		 wiphy_name(sc->hw->wiphy));
> +	ret = ath_register_led(sc, &sc->radio_led, trigger, name);
> +	sc->radio_led.led_type = ATH_LED_RADIO;
> +	if (ret)
> +		goto fail;
> +
> +	trigger = ieee80211_get_assoc_led_name(sc->hw);
> +	snprintf(name, sizeof(name), "ath9k-%s:assoc",
> +		 wiphy_name(sc->hw->wiphy));
> +	ret = ath_register_led(sc, &sc->assoc_led, trigger, name);
> +	sc->assoc_led.led_type = ATH_LED_ASSOC;
> +	if (ret)
> +		goto fail;
> +
> +	trigger = ieee80211_get_tx_led_name(sc->hw);
> +	snprintf(name, sizeof(name), "ath9k-%s:tx",
> +		 wiphy_name(sc->hw->wiphy));
> +	ret = ath_register_led(sc, &sc->tx_led, trigger, name);
> +	sc->tx_led.led_type = ATH_LED_TX;
> +	if (ret)
> +		goto fail;
> +
> +	trigger = ieee80211_get_rx_led_name(sc->hw);
> +	snprintf(name, sizeof(name), "ath9k-%s:rx",
> +		 wiphy_name(sc->hw->wiphy));
> +	ret = ath_register_led(sc, &sc->rx_led, trigger, name);
> +	sc->rx_led.led_type = ATH_LED_RX;
> +	if (ret)
> +		goto fail;
> +
> +	return;
> +
> +fail:
> +	ath_deinit_leds(sc);
> +}
> +
>  static int ath_detach(struct ath_softc *sc)
>  {
>  	struct ieee80211_hw *hw = sc->hw;
>  
>  	DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__);
>  
> +	/* Deinit LED control */
> +	ath_deinit_leds(sc);
> +
>  	/* Unregister hw */
>  
>  	ieee80211_unregister_hw(hw);
> @@ -1271,18 +1389,21 @@ static int ath_attach(u16 devid,
>  		goto bad;
>  	}
>  
> +	/* Initialize LED control */
> +	ath_init_leds(sc);
> +
>  	/* initialize tx/rx engine */
>  
>  	error = ath_tx_init(sc, ATH_TXBUF);
>  	if (error != 0)
> -		goto bad1;
> +		goto detach;
>  
>  	error = ath_rx_init(sc, ATH_RXBUF);
>  	if (error != 0)
> -		goto bad1;
> +		goto detach;
>  
>  	return 0;
> -bad1:
> +detach:
>  	ath_detach(sc);
>  bad:
>  	return error;
> @@ -1427,6 +1548,10 @@ static void ath_pci_remove(struct pci_dev *pdev)
>  
>  static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
>  {
> +	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
> +	struct ath_softc *sc = hw->priv;
> +
> +	ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
>  	pci_save_state(pdev);
>  	pci_disable_device(pdev);
>  	pci_set_power_state(pdev, 3);
> @@ -1436,6 +1561,8 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
>  
>  static int ath_pci_resume(struct pci_dev *pdev)
>  {
> +	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
> +	struct ath_softc *sc = hw->priv;
>  	u32 val;
>  	int err;
>  
> @@ -1452,6 +1579,11 @@ static int ath_pci_resume(struct pci_dev *pdev)
>  	if ((val & 0x0000ff00) != 0)
>  		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
>  
> +	/* Enable LED */
> +	ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
> +			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
> +	ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
> +
>  	return 0;
>  }
>  
> diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h
> index 42b0890..60617ae 100644
> --- a/drivers/net/wireless/ath9k/reg.h
> +++ b/drivers/net/wireless/ath9k/reg.h
> @@ -899,12 +899,6 @@ enum {
>  #define AR_GPIO_OUTPUT_MUX2                      0x4064
>  #define AR_GPIO_OUTPUT_MUX3                      0x4068
>  
> -#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT             0
> -#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
> -#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED     2
> -#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED    5
> -#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED      6
> -
>  #define AR_INPUT_STATE                           0x406c
>  
>  #define AR_EEPROM_STATUS_DATA                    0x407c

  reply	other threads:[~2008-08-25 14:01 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-25 13:28 [PATCH] ath9k: Add LED support Vasanthakumar Thiagarajan
2008-08-25 14:00 ` Ian Schram [this message]
  -- strict thread matches above, loose matches on Subject: below --
2008-08-25 15:17 Vasanthakumar Thiagarajan
2008-08-25 13:19 Vasanthakumar Thiagarajan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=48B2BAF8.4090300@telenet.be \
    --to=ischram@telenet.be \
    --cc=jouni.malinen@atheros.com \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linville@tuxdriver.com \
    --cc=luis.rodriguez@atheros.com \
    --cc=vasanth@atheros.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).