mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-26 00:41:17 +00:00
3394af677c
The ath patch number is already large and adding other patch for ath11k will add more confusion with the patch numbering. Since the support of ath11k based device is imminent, prepare the mac80211 ath patch dir and split it in the dedicated ath5k, ath9k, ath10k and ath11k (empty for now). Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
268 lines
7.0 KiB
Diff
268 lines
7.0 KiB
Diff
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
|
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
|
@@ -844,6 +844,9 @@ static inline int ath9k_dump_btcoex(stru
|
|
#ifdef CPTCFG_MAC80211_LEDS
|
|
void ath_init_leds(struct ath_softc *sc);
|
|
void ath_deinit_leds(struct ath_softc *sc);
|
|
+int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name,
|
|
+ const char *trigger, bool active_low);
|
|
+
|
|
#else
|
|
static inline void ath_init_leds(struct ath_softc *sc)
|
|
{
|
|
@@ -980,6 +983,13 @@ void ath_ant_comb_scan(struct ath_softc
|
|
|
|
#define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */
|
|
|
|
+struct ath_led {
|
|
+ struct list_head list;
|
|
+ struct ath_softc *sc;
|
|
+ const struct gpio_led *gpio;
|
|
+ struct led_classdev cdev;
|
|
+};
|
|
+
|
|
struct ath_softc {
|
|
struct ieee80211_hw *hw;
|
|
struct device *dev;
|
|
@@ -1033,9 +1043,8 @@ struct ath_softc {
|
|
spinlock_t chan_lock;
|
|
|
|
#ifdef CPTCFG_MAC80211_LEDS
|
|
- bool led_registered;
|
|
- char led_name[32];
|
|
- struct led_classdev led_cdev;
|
|
+ const char *led_default_trigger;
|
|
+ struct list_head leds;
|
|
#endif
|
|
|
|
#ifdef CPTCFG_ATH9K_DEBUGFS
|
|
--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
|
@@ -39,61 +39,111 @@ static void ath_fill_led_pin(struct ath_
|
|
else
|
|
ah->led_pin = ATH_LED_PIN_DEF;
|
|
}
|
|
+}
|
|
+
|
|
+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, cdev);
|
|
+ struct ath_softc *sc = led->sc;
|
|
+
|
|
+ ath9k_ps_wakeup(sc);
|
|
+ ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio,
|
|
+ (brightness != LED_OFF) ^ led->gpio->active_low);
|
|
+ ath9k_ps_restore(sc);
|
|
+}
|
|
+
|
|
+static int ath_add_led(struct ath_softc *sc, struct ath_led *led)
|
|
+{
|
|
+ const struct gpio_led *gpio = led->gpio;
|
|
+ int ret;
|
|
+
|
|
+ led->cdev.name = gpio->name;
|
|
+ led->cdev.default_trigger = gpio->default_trigger;
|
|
+ led->cdev.brightness_set = ath_led_brightness;
|
|
+
|
|
+ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ led->sc = sc;
|
|
+ list_add(&led->list, &sc->leds);
|
|
|
|
/* Configure gpio for output */
|
|
- ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led",
|
|
+ ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name,
|
|
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
|
|
|
- /* LED off, active low */
|
|
- ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1);
|
|
+ /* LED off */
|
|
+ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
-static void ath_led_brightness(struct led_classdev *led_cdev,
|
|
- enum led_brightness brightness)
|
|
+int ath_create_gpio_led(struct ath_softc *sc, int gpio_num, const char *name,
|
|
+ const char *trigger, bool active_low)
|
|
{
|
|
- struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
|
|
- u32 val = (brightness == LED_OFF);
|
|
+ struct ath_led *led;
|
|
+ struct gpio_led *gpio;
|
|
+ char *_name;
|
|
+ int ret;
|
|
|
|
- if (sc->sc_ah->config.led_active_high)
|
|
- val = !val;
|
|
+ led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1,
|
|
+ GFP_KERNEL);
|
|
+ if (!led)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ led->gpio = gpio = (struct gpio_led *) (led + 1);
|
|
+ _name = (char *) (led->gpio + 1);
|
|
+
|
|
+ strcpy(_name, name);
|
|
+ gpio->name = _name;
|
|
+ gpio->gpio = gpio_num;
|
|
+ gpio->active_low = active_low;
|
|
+ gpio->default_trigger = trigger;
|
|
+
|
|
+ ret = ath_add_led(sc, led);
|
|
+ if (unlikely(ret < 0))
|
|
+ kfree(led);
|
|
|
|
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val);
|
|
+ return ret;
|
|
}
|
|
|
|
void ath_deinit_leds(struct ath_softc *sc)
|
|
{
|
|
- if (!sc->led_registered)
|
|
- return;
|
|
+ struct ath_led *led;
|
|
|
|
- ath_led_brightness(&sc->led_cdev, LED_OFF);
|
|
- led_classdev_unregister(&sc->led_cdev);
|
|
-
|
|
- ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin);
|
|
+ while (!list_empty(&sc->leds)) {
|
|
+ led = list_first_entry(&sc->leds, struct ath_led, list);
|
|
+ list_del(&led->list);
|
|
+ ath_led_brightness(&led->cdev, LED_OFF);
|
|
+ led_classdev_unregister(&led->cdev);
|
|
+ ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio);
|
|
+ kfree(led);
|
|
+ }
|
|
}
|
|
|
|
void ath_init_leds(struct ath_softc *sc)
|
|
{
|
|
- int ret;
|
|
+ char led_name[32];
|
|
+ const char *trigger;
|
|
+
|
|
+ INIT_LIST_HEAD(&sc->leds);
|
|
|
|
if (AR_SREV_9100(sc->sc_ah))
|
|
return;
|
|
|
|
ath_fill_led_pin(sc);
|
|
|
|
- if (!ath9k_led_blink)
|
|
- sc->led_cdev.default_trigger =
|
|
- ieee80211_get_radio_led_name(sc->hw);
|
|
-
|
|
- snprintf(sc->led_name, sizeof(sc->led_name),
|
|
- "ath9k-%s", wiphy_name(sc->hw->wiphy));
|
|
- sc->led_cdev.name = sc->led_name;
|
|
- sc->led_cdev.brightness_set = ath_led_brightness;
|
|
+ snprintf(led_name, sizeof(led_name), "ath9k-%s",
|
|
+ wiphy_name(sc->hw->wiphy));
|
|
|
|
- ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev);
|
|
- if (ret < 0)
|
|
- return;
|
|
+ if (ath9k_led_blink)
|
|
+ trigger = sc->led_default_trigger;
|
|
+ else
|
|
+ trigger = ieee80211_get_radio_led_name(sc->hw);
|
|
|
|
- sc->led_registered = true;
|
|
+ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
|
|
+ !sc->sc_ah->config.led_active_high);
|
|
}
|
|
#endif
|
|
|
|
--- a/drivers/net/wireless/ath/ath9k/init.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
|
@@ -1055,7 +1055,7 @@ int ath9k_init_device(u16 devid, struct
|
|
|
|
#ifdef CPTCFG_MAC80211_LEDS
|
|
/* must be initialized before ieee80211_register_hw */
|
|
- sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
|
|
+ sc->led_default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
|
|
IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
|
|
ARRAY_SIZE(ath9k_tpt_blink));
|
|
#endif
|
|
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
|
@@ -1456,6 +1456,61 @@ static const struct file_operations fops
|
|
.llseek = default_llseek,
|
|
};
|
|
|
|
+#ifdef CONFIG_MAC80211_LEDS
|
|
+
|
|
+static ssize_t write_file_gpio_led(struct file *file, const char __user *ubuf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ath_softc *sc = file->private_data;
|
|
+ char buf[32], *str, *name, *c;
|
|
+ ssize_t len;
|
|
+ unsigned int gpio;
|
|
+ bool active_low = false;
|
|
+
|
|
+ len = min(count, sizeof(buf) - 1);
|
|
+ if (copy_from_user(buf, ubuf, len))
|
|
+ return -EFAULT;
|
|
+
|
|
+ buf[len] = '\0';
|
|
+ name = strchr(buf, ',');
|
|
+ if (!name)
|
|
+ return -EINVAL;
|
|
+
|
|
+ *(name++) = 0;
|
|
+ if (!*name)
|
|
+ return -EINVAL;
|
|
+
|
|
+ c = strchr(name, '\n');
|
|
+ if (c)
|
|
+ *c = 0;
|
|
+
|
|
+ str = buf;
|
|
+ if (*str == '!') {
|
|
+ str++;
|
|
+ active_low = true;
|
|
+ }
|
|
+
|
|
+ if (kstrtouint(str, 0, &gpio) < 0)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (gpio >= sc->sc_ah->caps.num_gpio_pins)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (ath_create_gpio_led(sc, gpio, name, NULL, active_low) < 0)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static const struct file_operations fops_gpio_led = {
|
|
+ .write = write_file_gpio_led,
|
|
+ .open = simple_open,
|
|
+ .owner = THIS_MODULE,
|
|
+ .llseek = default_llseek,
|
|
+};
|
|
+
|
|
+#endif
|
|
+
|
|
|
|
int ath9k_init_debug(struct ath_hw *ah)
|
|
{
|
|
@@ -1480,6 +1535,10 @@ int ath9k_init_debug(struct ath_hw *ah)
|
|
&fops_eeprom);
|
|
debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
|
|
sc, &fops_chanbw);
|
|
+#ifdef CONFIG_MAC80211_LEDS
|
|
+ debugfs_create_file("gpio_led", S_IWUSR,
|
|
+ sc->debug.debugfs_phy, sc, &fops_gpio_led);
|
|
+#endif
|
|
debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
|
|
read_file_dma);
|
|
debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
|