mac80211: update to 2014-10-08
Signed-off-by: Felix Fietkau <nbd@openwrt.org> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@42952 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
3cb3abd960
commit
2a685ec414
|
@ -10,11 +10,11 @@ include $(INCLUDE_DIR)/kernel.mk
|
|||
|
||||
PKG_NAME:=mac80211
|
||||
|
||||
PKG_VERSION:=2014-09-26
|
||||
PKG_VERSION:=2014-10-08
|
||||
PKG_RELEASE:=1
|
||||
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
|
||||
PKG_BACKPORT_VERSION:=
|
||||
PKG_MD5SUM:=b66f5fbd10e335fc660182ce6114d41f
|
||||
PKG_MD5SUM:=20e9de70e63fd9649d61d4670a9cc1bd
|
||||
|
||||
PKG_SOURCE:=compat-wireless-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.bz2
|
||||
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/.local-symbols
|
||||
+++ b/.local-symbols
|
||||
@@ -414,42 +414,6 @@ USB_CDC_PHONET=
|
||||
@@ -416,42 +416,6 @@ USB_CDC_PHONET=
|
||||
USB_IPHETH=
|
||||
USB_SIERRA_NET=
|
||||
USB_VL600=
|
||||
|
|
|
@ -0,0 +1,395 @@
|
|||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 27 Sep 2014 15:57:09 +0200
|
||||
Subject: [PATCH] Revert "ath5k: Remove AHB bus support"
|
||||
|
||||
This reverts commit 093ec3c5337434f40d77c1af06c139da3e5ba6dc.
|
||||
---
|
||||
create mode 100644 drivers/net/wireless/ath/ath5k/ahb.c
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath5k/Kconfig
|
||||
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
|
||||
@@ -1,13 +1,14 @@
|
||||
config ATH5K
|
||||
tristate "Atheros 5xxx wireless cards support"
|
||||
depends on m
|
||||
- depends on PCI && MAC80211
|
||||
+ depends on (PCI || ATHEROS_AR231X) && MAC80211
|
||||
select ATH_COMMON
|
||||
select MAC80211_LEDS
|
||||
select BACKPORT_LEDS_CLASS
|
||||
select BACKPORT_NEW_LEDS
|
||||
select BACKPORT_AVERAGE
|
||||
- select ATH5K_PCI
|
||||
+ select ATH5K_AHB if (ATHEROS_AR231X && !PCI)
|
||||
+ select ATH5K_PCI if (!ATHEROS_AR231X && PCI)
|
||||
---help---
|
||||
This module adds support for wireless adapters based on
|
||||
Atheros 5xxx chipset.
|
||||
@@ -52,9 +53,16 @@ config ATH5K_TRACER
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
+config ATH5K_AHB
|
||||
+ bool "Atheros 5xxx AHB bus support"
|
||||
+ depends on (ATHEROS_AR231X && !PCI)
|
||||
+ ---help---
|
||||
+ This adds support for WiSoC type chipsets of the 5xxx Atheros
|
||||
+ family.
|
||||
+
|
||||
config ATH5K_PCI
|
||||
bool "Atheros 5xxx PCI bus support"
|
||||
- depends on PCI
|
||||
+ depends on (!ATHEROS_AR231X && PCI)
|
||||
---help---
|
||||
This adds support for PCI type chipsets of the 5xxx Atheros
|
||||
family.
|
||||
--- a/drivers/net/wireless/ath/ath5k/Makefile
|
||||
+++ b/drivers/net/wireless/ath/ath5k/Makefile
|
||||
@@ -17,5 +17,6 @@ ath5k-y += ani.o
|
||||
ath5k-y += sysfs.o
|
||||
ath5k-y += mac80211-ops.o
|
||||
ath5k-$(CPTCFG_ATH5K_DEBUG) += debug.o
|
||||
+ath5k-$(CPTCFG_ATH5K_AHB) += ahb.o
|
||||
ath5k-$(CPTCFG_ATH5K_PCI) += pci.o
|
||||
obj-$(CPTCFG_ATH5K) += ath5k.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
|
||||
@@ -0,0 +1,234 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
+ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and/or distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/nl80211.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+#include <linux/export.h>
|
||||
+#include <ar231x_platform.h>
|
||||
+#include "ath5k.h"
|
||||
+#include "debug.h"
|
||||
+#include "base.h"
|
||||
+#include "reg.h"
|
||||
+
|
||||
+/* return bus cachesize in 4B word units */
|
||||
+static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
|
||||
+{
|
||||
+ *csz = L1_CACHE_BYTES >> 2;
|
||||
+}
|
||||
+
|
||||
+static bool
|
||||
+ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
|
||||
+{
|
||||
+ struct ath5k_hw *ah = common->priv;
|
||||
+ struct platform_device *pdev = to_platform_device(ah->dev);
|
||||
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
|
||||
+ u16 *eeprom, *eeprom_end;
|
||||
+
|
||||
+ eeprom = (u16 *) bcfg->radio;
|
||||
+ eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ;
|
||||
+
|
||||
+ eeprom += off;
|
||||
+ if (eeprom > eeprom_end)
|
||||
+ return false;
|
||||
+
|
||||
+ *data = *eeprom;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+int ath5k_hw_read_srev(struct ath5k_hw *ah)
|
||||
+{
|
||||
+ struct platform_device *pdev = to_platform_device(ah->dev);
|
||||
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
|
||||
+ ah->ah_mac_srev = bcfg->devid;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
|
||||
+{
|
||||
+ struct platform_device *pdev = to_platform_device(ah->dev);
|
||||
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
|
||||
+ u8 *cfg_mac;
|
||||
+
|
||||
+ if (to_platform_device(ah->dev)->id == 0)
|
||||
+ cfg_mac = bcfg->config->wlan0_mac;
|
||||
+ else
|
||||
+ cfg_mac = bcfg->config->wlan1_mac;
|
||||
+
|
||||
+ memcpy(mac, cfg_mac, ETH_ALEN);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct ath_bus_ops ath_ahb_bus_ops = {
|
||||
+ .ath_bus_type = ATH_AHB,
|
||||
+ .read_cachesize = ath5k_ahb_read_cachesize,
|
||||
+ .eeprom_read = ath5k_ahb_eeprom_read,
|
||||
+ .eeprom_read_mac = ath5k_ahb_eeprom_read_mac,
|
||||
+};
|
||||
+
|
||||
+/*Initialization*/
|
||||
+static int ath_ahb_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
|
||||
+ struct ath5k_hw *ah;
|
||||
+ struct ieee80211_hw *hw;
|
||||
+ struct resource *res;
|
||||
+ void __iomem *mem;
|
||||
+ int irq;
|
||||
+ int ret = 0;
|
||||
+ u32 reg;
|
||||
+
|
||||
+ if (!dev_get_platdata(&pdev->dev)) {
|
||||
+ dev_err(&pdev->dev, "no platform data specified\n");
|
||||
+ ret = -EINVAL;
|
||||
+ goto err_out;
|
||||
+ }
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ if (res == NULL) {
|
||||
+ dev_err(&pdev->dev, "no memory resource found\n");
|
||||
+ ret = -ENXIO;
|
||||
+ goto err_out;
|
||||
+ }
|
||||
+
|
||||
+ mem = ioremap_nocache(res->start, resource_size(res));
|
||||
+ if (mem == NULL) {
|
||||
+ dev_err(&pdev->dev, "ioremap failed\n");
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_out;
|
||||
+ }
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
+ if (res == NULL) {
|
||||
+ dev_err(&pdev->dev, "no IRQ resource found\n");
|
||||
+ ret = -ENXIO;
|
||||
+ goto err_iounmap;
|
||||
+ }
|
||||
+
|
||||
+ irq = res->start;
|
||||
+
|
||||
+ hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops);
|
||||
+ if (hw == NULL) {
|
||||
+ dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_iounmap;
|
||||
+ }
|
||||
+
|
||||
+ ah = hw->priv;
|
||||
+ ah->hw = hw;
|
||||
+ ah->dev = &pdev->dev;
|
||||
+ ah->iobase = mem;
|
||||
+ ah->irq = irq;
|
||||
+ ah->devid = bcfg->devid;
|
||||
+
|
||||
+ if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
|
||||
+ /* Enable WMAC AHB arbitration */
|
||||
+ reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
|
||||
+ reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN;
|
||||
+ iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
|
||||
+
|
||||
+ /* Enable global WMAC swapping */
|
||||
+ reg = ioread32((void __iomem *) AR5K_AR2315_BYTESWAP);
|
||||
+ reg |= AR5K_AR2315_BYTESWAP_WMAC;
|
||||
+ iowrite32(reg, (void __iomem *) AR5K_AR2315_BYTESWAP);
|
||||
+ } else {
|
||||
+ /* Enable WMAC DMA access (assuming 5312 or 231x*/
|
||||
+ /* TODO: check other platforms */
|
||||
+ reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
|
||||
+ if (to_platform_device(ah->dev)->id == 0)
|
||||
+ reg |= AR5K_AR5312_ENABLE_WLAN0;
|
||||
+ else
|
||||
+ reg |= AR5K_AR5312_ENABLE_WLAN1;
|
||||
+ iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
|
||||
+
|
||||
+ /*
|
||||
+ * On a dual-band AR5312, the multiband radio is only
|
||||
+ * used as pass-through. Disable 2 GHz support in the
|
||||
+ * driver for it
|
||||
+ */
|
||||
+ if (to_platform_device(ah->dev)->id == 0 &&
|
||||
+ (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) ==
|
||||
+ (BD_WLAN1 | BD_WLAN0))
|
||||
+ ah->ah_capabilities.cap_needs_2GHz_ovr = true;
|
||||
+ else
|
||||
+ ah->ah_capabilities.cap_needs_2GHz_ovr = false;
|
||||
+ }
|
||||
+
|
||||
+ ret = ath5k_init_ah(ah, &ath_ahb_bus_ops);
|
||||
+ if (ret != 0) {
|
||||
+ dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
|
||||
+ ret = -ENODEV;
|
||||
+ goto err_free_hw;
|
||||
+ }
|
||||
+
|
||||
+ platform_set_drvdata(pdev, hw);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+ err_free_hw:
|
||||
+ ieee80211_free_hw(hw);
|
||||
+ err_iounmap:
|
||||
+ iounmap(mem);
|
||||
+ err_out:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int ath_ahb_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
|
||||
+ struct ieee80211_hw *hw = platform_get_drvdata(pdev);
|
||||
+ struct ath5k_hw *ah;
|
||||
+ u32 reg;
|
||||
+
|
||||
+ if (!hw)
|
||||
+ return 0;
|
||||
+
|
||||
+ ah = hw->priv;
|
||||
+
|
||||
+ if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
|
||||
+ /* Disable WMAC AHB arbitration */
|
||||
+ reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
|
||||
+ reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN;
|
||||
+ iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
|
||||
+ } else {
|
||||
+ /*Stop DMA access */
|
||||
+ reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
|
||||
+ if (to_platform_device(ah->dev)->id == 0)
|
||||
+ reg &= ~AR5K_AR5312_ENABLE_WLAN0;
|
||||
+ else
|
||||
+ reg &= ~AR5K_AR5312_ENABLE_WLAN1;
|
||||
+ iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
|
||||
+ }
|
||||
+
|
||||
+ ath5k_deinit_ah(ah);
|
||||
+ iounmap(ah->iobase);
|
||||
+ ieee80211_free_hw(hw);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver ath_ahb_driver = {
|
||||
+ .probe = ath_ahb_probe,
|
||||
+ .remove = ath_ahb_remove,
|
||||
+ .driver = {
|
||||
+ .name = "ar231x-wmac",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(ath_ahb_driver);
|
||||
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
|
||||
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
|
||||
@@ -1647,6 +1647,32 @@ static inline struct ath_regulatory *ath
|
||||
return &(ath5k_hw_common(ah)->regulatory);
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_ATHEROS_AR231X
|
||||
+#define AR5K_AR2315_PCI_BASE ((void __iomem *)0xb0100000)
|
||||
+
|
||||
+static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg)
|
||||
+{
|
||||
+ /* On AR2315 and AR2317 the PCI clock domain registers
|
||||
+ * are outside of the WMAC register space */
|
||||
+ if (unlikely((reg >= 0x4000) && (reg < 0x5000) &&
|
||||
+ (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
|
||||
+ return AR5K_AR2315_PCI_BASE + reg;
|
||||
+
|
||||
+ return ah->iobase + reg;
|
||||
+}
|
||||
+
|
||||
+static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
|
||||
+{
|
||||
+ return ioread32(ath5k_ahb_reg(ah, reg));
|
||||
+}
|
||||
+
|
||||
+static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
|
||||
+{
|
||||
+ iowrite32(val, ath5k_ahb_reg(ah, reg));
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+
|
||||
static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
|
||||
{
|
||||
return ioread32(ah->iobase + reg);
|
||||
@@ -1657,6 +1683,8 @@ static inline void ath5k_hw_reg_write(st
|
||||
iowrite32(val, ah->iobase + reg);
|
||||
}
|
||||
|
||||
+#endif
|
||||
+
|
||||
static inline enum ath_bus_type ath5k_get_bus_type(struct ath5k_hw *ah)
|
||||
{
|
||||
return ath5k_hw_common(ah)->bus_ops->ath_bus_type;
|
||||
--- a/drivers/net/wireless/ath/ath5k/base.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/base.c
|
||||
@@ -99,6 +99,15 @@ static int ath5k_reset(struct ath5k_hw *
|
||||
|
||||
/* Known SREVs */
|
||||
static const struct ath5k_srev_name srev_names[] = {
|
||||
+#ifdef CONFIG_ATHEROS_AR231X
|
||||
+ { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R2 },
|
||||
+ { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R7 },
|
||||
+ { "2313", AR5K_VERSION_MAC, AR5K_SREV_AR2313_R8 },
|
||||
+ { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R6 },
|
||||
+ { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R7 },
|
||||
+ { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R1 },
|
||||
+ { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R2 },
|
||||
+#else
|
||||
{ "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 },
|
||||
{ "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 },
|
||||
{ "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A },
|
||||
@@ -117,6 +126,7 @@ static const struct ath5k_srev_name srev
|
||||
{ "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 },
|
||||
{ "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 },
|
||||
{ "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 },
|
||||
+#endif
|
||||
{ "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN },
|
||||
{ "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
|
||||
{ "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
|
||||
@@ -132,6 +142,10 @@ static const struct ath5k_srev_name srev
|
||||
{ "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 },
|
||||
{ "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 },
|
||||
{ "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
|
||||
+#ifdef CONFIG_ATHEROS_AR231X
|
||||
+ { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 },
|
||||
+ { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 },
|
||||
+#endif
|
||||
{ "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN },
|
||||
};
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath5k/led.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/led.c
|
||||
@@ -163,14 +163,20 @@ int ath5k_init_leds(struct ath5k_hw *ah)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ieee80211_hw *hw = ah->hw;
|
||||
+#ifndef CONFIG_ATHEROS_AR231X
|
||||
struct pci_dev *pdev = ah->pdev;
|
||||
+#endif
|
||||
char name[ATH5K_LED_MAX_NAME_LEN + 1];
|
||||
const struct pci_device_id *match;
|
||||
|
||||
if (!ah->pdev)
|
||||
return 0;
|
||||
|
||||
+#ifdef CONFIG_ATHEROS_AR231X
|
||||
+ match = NULL;
|
||||
+#else
|
||||
match = pci_match_id(&ath5k_led_devices[0], pdev);
|
||||
+#endif
|
||||
if (match) {
|
||||
__set_bit(ATH_STAT_LEDSOFT, ah->status);
|
||||
ah->led_pin = ATH_PIN(match->driver_data);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,37 @@
|
|||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 27 Sep 2014 15:58:51 +0200
|
||||
Subject: [PATCH] ath5k: fix AHB kconfig dependency
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath5k/Kconfig
|
||||
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
|
||||
@@ -7,8 +7,8 @@ config ATH5K
|
||||
select BACKPORT_LEDS_CLASS
|
||||
select BACKPORT_NEW_LEDS
|
||||
select BACKPORT_AVERAGE
|
||||
- select ATH5K_AHB if (ATHEROS_AR231X && !PCI)
|
||||
- select ATH5K_PCI if (!ATHEROS_AR231X && PCI)
|
||||
+ select ATH5K_AHB if ATHEROS_AR231X
|
||||
+ select ATH5K_PCI if !ATHEROS_AR231X
|
||||
---help---
|
||||
This module adds support for wireless adapters based on
|
||||
Atheros 5xxx chipset.
|
||||
@@ -55,14 +55,14 @@ config ATH5K_TRACER
|
||||
|
||||
config ATH5K_AHB
|
||||
bool "Atheros 5xxx AHB bus support"
|
||||
- depends on (ATHEROS_AR231X && !PCI)
|
||||
+ depends on ATHEROS_AR231X
|
||||
---help---
|
||||
This adds support for WiSoC type chipsets of the 5xxx Atheros
|
||||
family.
|
||||
|
||||
config ATH5K_PCI
|
||||
bool "Atheros 5xxx PCI bus support"
|
||||
- depends on (!ATHEROS_AR231X && PCI)
|
||||
+ depends on !ATHEROS_AR231X
|
||||
---help---
|
||||
This adds support for PCI type chipsets of the 5xxx Atheros
|
||||
family.
|
|
@ -0,0 +1,20 @@
|
|||
From: Karl Beldan <karl.beldan@rivierawaves.com>
|
||||
Date: Tue, 7 Oct 2014 15:53:38 +0200
|
||||
Subject: [PATCH] mac80211/trivial: fix typo in starting baserate for
|
||||
rts_cts_rate_idx
|
||||
|
||||
Fixes: 5253ffb8 ("mac80211: always pick a basic rate to tx RTS/CTS for pre-HT rates")
|
||||
Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rate.c
|
||||
+++ b/net/mac80211/rate.c
|
||||
@@ -448,7 +448,7 @@ static void rate_fixup_ratelist(struct i
|
||||
*/
|
||||
if (!(rates[0].flags & IEEE80211_TX_RC_MCS)) {
|
||||
u32 basic_rates = vif->bss_conf.basic_rates;
|
||||
- s8 baserate = basic_rates ? ffs(basic_rates - 1) : 0;
|
||||
+ s8 baserate = basic_rates ? ffs(basic_rates) - 1 : 0;
|
||||
|
||||
rate = &sband->bitrates[rates[0].idx];
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:08 +0530
|
||||
Subject: [PATCH] ath9k: Use sta_state() callback
|
||||
|
||||
Instead of using the sta_add()/sta_remove() callbacks,
|
||||
use the sta_state() callback since this gives
|
||||
more fine-grained control.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -1547,6 +1547,31 @@ static int ath9k_sta_remove(struct ieee8
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int ath9k_sta_state(struct ieee80211_hw *hw,
|
||||
+ struct ieee80211_vif *vif,
|
||||
+ struct ieee80211_sta *sta,
|
||||
+ enum ieee80211_sta_state old_state,
|
||||
+ enum ieee80211_sta_state new_state)
|
||||
+{
|
||||
+ struct ath_softc *sc = hw->priv;
|
||||
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (old_state == IEEE80211_STA_AUTH &&
|
||||
+ new_state == IEEE80211_STA_ASSOC) {
|
||||
+ ret = ath9k_sta_add(hw, vif, sta);
|
||||
+ ath_dbg(common, CONFIG,
|
||||
+ "Add station: %pM\n", sta->addr);
|
||||
+ } else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
+ new_state == IEEE80211_STA_AUTH) {
|
||||
+ ret = ath9k_sta_remove(hw, vif, sta);
|
||||
+ ath_dbg(common, CONFIG,
|
||||
+ "Remove station: %pM\n", sta->addr);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static void ath9k_sta_set_tx_filter(struct ath_hw *ah,
|
||||
struct ath_node *an,
|
||||
bool set)
|
||||
@@ -2471,8 +2496,7 @@ struct ieee80211_ops ath9k_ops = {
|
||||
.remove_interface = ath9k_remove_interface,
|
||||
.config = ath9k_config,
|
||||
.configure_filter = ath9k_configure_filter,
|
||||
- .sta_add = ath9k_sta_add,
|
||||
- .sta_remove = ath9k_sta_remove,
|
||||
+ .sta_state = ath9k_sta_state,
|
||||
.sta_notify = ath9k_sta_notify,
|
||||
.conf_tx = ath9k_conf_tx,
|
||||
.bss_info_changed = ath9k_bss_info_changed,
|
|
@ -0,0 +1,82 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:09 +0530
|
||||
Subject: [PATCH] ath9k: Enable multi-channel properly
|
||||
|
||||
In MCC mode, currently the decision to enable
|
||||
the multi-channel state machine is done
|
||||
based on the association status if one of
|
||||
the interfaces assigned to a context is in
|
||||
station mode.
|
||||
|
||||
This allows the driver to switch to the other
|
||||
context before the current station is able to
|
||||
complete the 4-way handshake in case it is
|
||||
required and this causes problems.
|
||||
|
||||
Instead, enable multi-channel mode when the
|
||||
station moves to the authorized state. This
|
||||
disallows an early switch to the other channel.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -362,7 +362,7 @@ enum ath_chanctx_event {
|
||||
ATH_CHANCTX_EVENT_BEACON_SENT,
|
||||
ATH_CHANCTX_EVENT_TSF_TIMER,
|
||||
ATH_CHANCTX_EVENT_BEACON_RECEIVED,
|
||||
- ATH_CHANCTX_EVENT_ASSOC,
|
||||
+ ATH_CHANCTX_EVENT_AUTHORIZED,
|
||||
ATH_CHANCTX_EVENT_SWITCH,
|
||||
ATH_CHANCTX_EVENT_ASSIGN,
|
||||
ATH_CHANCTX_EVENT_UNASSIGN,
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -171,7 +171,7 @@ static const char *chanctx_event_string(
|
||||
case_rtn_string(ATH_CHANCTX_EVENT_BEACON_SENT);
|
||||
case_rtn_string(ATH_CHANCTX_EVENT_TSF_TIMER);
|
||||
case_rtn_string(ATH_CHANCTX_EVENT_BEACON_RECEIVED);
|
||||
- case_rtn_string(ATH_CHANCTX_EVENT_ASSOC);
|
||||
+ case_rtn_string(ATH_CHANCTX_EVENT_AUTHORIZED);
|
||||
case_rtn_string(ATH_CHANCTX_EVENT_SWITCH);
|
||||
case_rtn_string(ATH_CHANCTX_EVENT_ASSIGN);
|
||||
case_rtn_string(ATH_CHANCTX_EVENT_UNASSIGN);
|
||||
@@ -510,7 +510,7 @@ void ath_chanctx_event(struct ath_softc
|
||||
|
||||
ath_chanctx_setup_timer(sc, tsf_time);
|
||||
break;
|
||||
- case ATH_CHANCTX_EVENT_ASSOC:
|
||||
+ case ATH_CHANCTX_EVENT_AUTHORIZED:
|
||||
if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE ||
|
||||
avp->chanctx != sc->cur_chan)
|
||||
break;
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -1569,6 +1569,13 @@ static int ath9k_sta_state(struct ieee80
|
||||
"Remove station: %pM\n", sta->addr);
|
||||
}
|
||||
|
||||
+ if (ath9k_is_chanctx_enabled()) {
|
||||
+ if (old_state == IEEE80211_STA_ASSOC &&
|
||||
+ new_state == IEEE80211_STA_AUTHORIZED)
|
||||
+ ath_chanctx_event(sc, vif,
|
||||
+ ATH_CHANCTX_EVENT_AUTHORIZED);
|
||||
+ }
|
||||
+
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1761,12 +1768,6 @@ static void ath9k_bss_info_changed(struc
|
||||
avp->assoc = bss_conf->assoc;
|
||||
|
||||
ath9k_calculate_summary_state(sc, avp->chanctx);
|
||||
-
|
||||
- if (ath9k_is_chanctx_enabled()) {
|
||||
- if (bss_conf->assoc)
|
||||
- ath_chanctx_event(sc, vif,
|
||||
- ATH_CHANCTX_EVENT_ASSOC);
|
||||
- }
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_IBSS) {
|
|
@ -0,0 +1,37 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:10 +0530
|
||||
Subject: [PATCH] ath9k: Process beacons properly
|
||||
|
||||
When the current operating channel context has
|
||||
been marked as ATH_CHANCTX_STATE_FORCE_ACTIVE,
|
||||
do not process beacons that might be received,
|
||||
since we have to wait for the station to become
|
||||
authorized.
|
||||
|
||||
Also, since the cached TSF value will be zero
|
||||
initially do not rearm the timer in this
|
||||
case when a beacon is received, since it results
|
||||
in spurious values.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -495,10 +495,15 @@ void ath_chanctx_event(struct ath_softc
|
||||
sc->cur_chan == &sc->offchannel.chan)
|
||||
break;
|
||||
|
||||
- ath_chanctx_adjust_tbtt_delta(sc);
|
||||
sc->sched.beacon_pending = false;
|
||||
sc->sched.beacon_miss = 0;
|
||||
|
||||
+ if (sc->sched.state == ATH_CHANCTX_STATE_FORCE_ACTIVE ||
|
||||
+ !sc->cur_chan->tsf_val)
|
||||
+ break;
|
||||
+
|
||||
+ ath_chanctx_adjust_tbtt_delta(sc);
|
||||
+
|
||||
/* TSF time might have been updated by the incoming beacon,
|
||||
* need update the channel switch timer to reflect the change.
|
||||
*/
|
|
@ -0,0 +1,108 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:11 +0530
|
||||
Subject: [PATCH] ath9k: Unify reset API
|
||||
|
||||
Instead of having ath_reset_internal() and ath_reset()
|
||||
as two separate calls to perform a HW reset, have
|
||||
one function. This makes sure that the behavior will
|
||||
be the same at all callsites.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -540,7 +540,6 @@ static inline void ath_chanctx_check_act
|
||||
|
||||
#endif /* CPTCFG_ATH9K_CHANNEL_CONTEXT */
|
||||
|
||||
-int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan);
|
||||
void ath_startrecv(struct ath_softc *sc);
|
||||
bool ath_stoprecv(struct ath_softc *sc);
|
||||
u32 ath_calcrxfilter(struct ath_softc *sc);
|
||||
@@ -1069,7 +1068,7 @@ void ath9k_tasklet(unsigned long data);
|
||||
int ath_cabq_update(struct ath_softc *);
|
||||
u8 ath9k_parse_mpdudensity(u8 mpdudensity);
|
||||
irqreturn_t ath_isr(int irq, void *dev);
|
||||
-int ath_reset(struct ath_softc *sc);
|
||||
+int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan);
|
||||
void ath_cancel_work(struct ath_softc *sc);
|
||||
void ath_restart_work(struct ath_softc *sc);
|
||||
int ath9k_init_device(u16 devid, struct ath_softc *sc,
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -66,7 +66,7 @@ static int ath_set_channel(struct ath_so
|
||||
}
|
||||
|
||||
hchan = &sc->sc_ah->channels[pos];
|
||||
- r = ath_reset_internal(sc, hchan);
|
||||
+ r = ath_reset(sc, hchan);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -270,7 +270,7 @@ static bool ath_complete_reset(struct at
|
||||
return true;
|
||||
}
|
||||
|
||||
-int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
|
||||
+static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
@@ -598,12 +598,12 @@ chip_reset:
|
||||
#undef SCHED_INTR
|
||||
}
|
||||
|
||||
-int ath_reset(struct ath_softc *sc)
|
||||
+int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan)
|
||||
{
|
||||
int r;
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
- r = ath_reset_internal(sc, NULL);
|
||||
+ r = ath_reset_internal(sc, hchan);
|
||||
ath9k_ps_restore(sc);
|
||||
|
||||
return r;
|
||||
@@ -623,7 +623,9 @@ void ath_reset_work(struct work_struct *
|
||||
{
|
||||
struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
|
||||
|
||||
- ath_reset(sc);
|
||||
+ ath9k_ps_wakeup(sc);
|
||||
+ ath_reset_internal(sc, NULL);
|
||||
+ ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
/**********************/
|
||||
@@ -2044,7 +2046,7 @@ void __ath9k_flush(struct ieee80211_hw *
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
if (!drain_txq)
|
||||
- ath_reset(sc);
|
||||
+ ath_reset(sc, NULL);
|
||||
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath9k/tx99.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/tx99.c
|
||||
@@ -99,7 +99,7 @@ static struct sk_buff *ath9k_build_tx99_
|
||||
|
||||
static void ath9k_tx99_deinit(struct ath_softc *sc)
|
||||
{
|
||||
- ath_reset(sc);
|
||||
+ ath_reset(sc, NULL);
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath9k_tx99_stop(sc);
|
||||
@@ -127,7 +127,7 @@ static int ath9k_tx99_init(struct ath_so
|
||||
memset(&txctl, 0, sizeof(txctl));
|
||||
txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
|
||||
|
||||
- ath_reset(sc);
|
||||
+ ath_reset(sc, NULL);
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:12 +0530
|
||||
Subject: [PATCH] ath9k: Set ATH_OP_HW_RESET before HW reset
|
||||
|
||||
When a HW reset is done, the interrupt tasklet is
|
||||
disabled before ISRs are disabled in the HW. This
|
||||
allows a small window where the HW can still generate
|
||||
interrupts. Since the tasklet is disabled and not killed,
|
||||
it is not scheduled but deferred for execution at a later
|
||||
time.
|
||||
|
||||
This happens because ATH_OP_HW_RESET is not set when ath_reset()
|
||||
is called. When the hw_reset_work workqueue is used, this
|
||||
problem doesn't arise because ATH_OP_HW_RESET is set
|
||||
and the ISR bails out.
|
||||
|
||||
Set ATH_OP_HW_RESET properly in ath_reset() to avoid
|
||||
this race - all the ath_reset_internal() callers have
|
||||
been converted to use ath_reset() in the previous patch.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -598,10 +598,17 @@ chip_reset:
|
||||
#undef SCHED_INTR
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * This function is called when a HW reset cannot be deferred
|
||||
+ * and has to be immediate.
|
||||
+ */
|
||||
int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan)
|
||||
{
|
||||
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
int r;
|
||||
|
||||
+ set_bit(ATH_OP_HW_RESET, &common->op_flags);
|
||||
+
|
||||
ath9k_ps_wakeup(sc);
|
||||
r = ath_reset_internal(sc, hchan);
|
||||
ath9k_ps_restore(sc);
|
||||
@@ -609,6 +616,11 @@ int ath_reset(struct ath_softc *sc, stru
|
||||
return r;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * When a HW reset can be deferred, it is added to the
|
||||
+ * hw_reset_work workqueue, but we set ATH_OP_HW_RESET before
|
||||
+ * queueing.
|
||||
+ */
|
||||
void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
|
@ -0,0 +1,29 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:13 +0530
|
||||
Subject: [PATCH] ath9k: Disable beacon tasklet during reset
|
||||
|
||||
When a chip reset is done, all running timers,
|
||||
tasklets etc. are stopped but the beacon tasklet
|
||||
is left running. Fix this.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -281,6 +281,7 @@ static int ath_reset_internal(struct ath
|
||||
__ath_cancel_work(sc);
|
||||
|
||||
tasklet_disable(&sc->intr_tq);
|
||||
+ tasklet_disable(&sc->bcon_tasklet);
|
||||
spin_lock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
if (!sc->cur_chan->offchannel) {
|
||||
@@ -326,6 +327,7 @@ static int ath_reset_internal(struct ath
|
||||
|
||||
out:
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
+ tasklet_enable(&sc->bcon_tasklet);
|
||||
tasklet_enable(&sc->intr_tq);
|
||||
|
||||
return r;
|
|
@ -0,0 +1,36 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:14 +0530
|
||||
Subject: [PATCH] ath9k: Clear NoA schedule properly
|
||||
|
||||
When an active context transitions to inactive
|
||||
state, the NoA schedule needs to be removed
|
||||
for the context that has beaconing enabled.
|
||||
Not doing this will affect p2p clients.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -356,6 +356,21 @@ void ath_chanctx_event(struct ath_softc
|
||||
"Move chanctx state from WAIT_FOR_TIMER to WAIT_FOR_BEACON\n");
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * When a context becomes inactive, for example,
|
||||
+ * disassociation of a station context, the NoA
|
||||
+ * attribute needs to be removed from subsequent
|
||||
+ * beacons.
|
||||
+ */
|
||||
+ if (!ctx->active && avp->noa_duration &&
|
||||
+ sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON) {
|
||||
+ avp->noa_duration = 0;
|
||||
+ avp->periodic_noa = false;
|
||||
+
|
||||
+ ath_dbg(common, CHAN_CTX,
|
||||
+ "Clearing NoA schedule\n");
|
||||
+ }
|
||||
+
|
||||
if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
|
||||
break;
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:15 +0530
|
||||
Subject: [PATCH] ath9k: Use configurable timeout for flush
|
||||
|
||||
The timeout value for flushing the TX queues
|
||||
is hardcoded at 200ms right now. Use a channel
|
||||
context-specific value instead to allow adjustments
|
||||
to the timeout in case MCC is enabled.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -345,6 +345,7 @@ struct ath_chanctx {
|
||||
u64 tsf_val;
|
||||
u32 last_beacon;
|
||||
|
||||
+ int flush_timeout;
|
||||
u16 txpower;
|
||||
bool offchannel;
|
||||
bool stopped;
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -117,6 +117,7 @@ void ath_chanctx_init(struct ath_softc *
|
||||
cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
|
||||
INIT_LIST_HEAD(&ctx->vifs);
|
||||
ctx->txpower = ATH_TXPOWER_MAX;
|
||||
+ ctx->flush_timeout = HZ / 5; /* 200ms */
|
||||
for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
|
||||
INIT_LIST_HEAD(&ctx->acq[j]);
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -2034,7 +2034,7 @@ void __ath9k_flush(struct ieee80211_hw *
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
- int timeout = HZ / 5; /* 200 ms */
|
||||
+ int timeout;
|
||||
bool drain_txq;
|
||||
|
||||
cancel_delayed_work_sync(&sc->tx_complete_work);
|
||||
@@ -2049,6 +2049,13 @@ void __ath9k_flush(struct ieee80211_hw *
|
||||
return;
|
||||
}
|
||||
|
||||
+ spin_lock_bh(&sc->chan_lock);
|
||||
+ timeout = sc->cur_chan->flush_timeout;
|
||||
+ spin_unlock_bh(&sc->chan_lock);
|
||||
+
|
||||
+ ath_dbg(common, CHAN_CTX,
|
||||
+ "Flush timeout: %d\n", jiffies_to_msecs(timeout));
|
||||
+
|
||||
if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc),
|
||||
timeout) > 0)
|
||||
drop = false;
|
|
@ -0,0 +1,68 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:16 +0530
|
||||
Subject: [PATCH] ath9k: Fix MCC flush timeout
|
||||
|
||||
In MCC mode, the duration for a channel context
|
||||
is half the beacon interval and having a large
|
||||
flush timeout will adversely affect GO operation,
|
||||
since the default value of 200ms will overshoot
|
||||
the advertised NoA absence duration.
|
||||
|
||||
The scheduler initiates a channel context switch
|
||||
only when the slot duration for the current
|
||||
context expires, so there is no possibility of
|
||||
having a fixed timeout for flush.
|
||||
|
||||
Since the channel_switch_time is added to the
|
||||
absence duration when the GO sets up the NoA
|
||||
attribute, this is the maximum time that we
|
||||
have to flush the TX queues. The duration is very
|
||||
small, but we don't have a choice in MCC mode.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -199,6 +199,7 @@ static const char *chanctx_state_string(
|
||||
void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
+ struct ath_chanctx *ictx;
|
||||
struct ath_vif *avp;
|
||||
bool active = false;
|
||||
u8 n_active = 0;
|
||||
@@ -206,6 +207,8 @@ void ath_chanctx_check_active(struct ath
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
+ ictx = ctx;
|
||||
+
|
||||
list_for_each_entry(avp, &ctx->vifs, list) {
|
||||
struct ieee80211_vif *vif = avp->vif;
|
||||
|
||||
@@ -228,12 +231,23 @@ void ath_chanctx_check_active(struct ath
|
||||
n_active++;
|
||||
}
|
||||
|
||||
+ spin_lock_bh(&sc->chan_lock);
|
||||
+
|
||||
if (n_active <= 1) {
|
||||
+ ictx->flush_timeout = HZ / 5;
|
||||
clear_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags);
|
||||
+ spin_unlock_bh(&sc->chan_lock);
|
||||
return;
|
||||
}
|
||||
- if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
|
||||
+
|
||||
+ ictx->flush_timeout = usecs_to_jiffies(sc->sched.channel_switch_time);
|
||||
+
|
||||
+ if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) {
|
||||
+ spin_unlock_bh(&sc->chan_lock);
|
||||
return;
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock_bh(&sc->chan_lock);
|
||||
|
||||
if (ath9k_is_chanctx_enabled()) {
|
||||
ath_chanctx_event(sc, NULL,
|
|
@ -0,0 +1,43 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:17 +0530
|
||||
Subject: [PATCH] ath9k: Fix offchannel flush timeout
|
||||
|
||||
An offchannel operation also needs to have
|
||||
a flush timeout that doesn't exceed the NoA
|
||||
absence duration of a GO context, so use
|
||||
channel_switch_time. The first offchannel
|
||||
operation is set a flush timeout of 10ms since
|
||||
channel_switch_time will be zero.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -207,6 +207,26 @@ void ath_chanctx_check_active(struct ath
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
+ if (ctx == &sc->offchannel.chan) {
|
||||
+ spin_lock_bh(&sc->chan_lock);
|
||||
+
|
||||
+ if (likely(sc->sched.channel_switch_time))
|
||||
+ ctx->flush_timeout =
|
||||
+ usecs_to_jiffies(sc->sched.channel_switch_time);
|
||||
+ else
|
||||
+ ctx->flush_timeout =
|
||||
+ msecs_to_jiffies(10);
|
||||
+
|
||||
+ spin_unlock_bh(&sc->chan_lock);
|
||||
+
|
||||
+ /*
|
||||
+ * There is no need to iterate over the
|
||||
+ * active/assigned channel contexts if
|
||||
+ * the current context is offchannel.
|
||||
+ */
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
ictx = ctx;
|
||||
|
||||
list_for_each_entry(avp, &ctx->vifs, list) {
|
|
@ -0,0 +1,125 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:18 +0530
|
||||
Subject: [PATCH] ath9k: Check for pending frames properly
|
||||
|
||||
Pending frames in the driver can be present
|
||||
either in the HW queues or SW. ath9k_has_pending_frames()
|
||||
currently checks for the HW queues first and then
|
||||
checks if any ACs are queued in the driver.
|
||||
|
||||
In MCC mode, we need to check the HW queues alone, since
|
||||
the SW queues are just marked as 'stopped' - they will
|
||||
be processed in the next context switch. But since we
|
||||
don't differentiate this now, mention whether we want
|
||||
to check if there are frames in the SW queues.
|
||||
|
||||
* The flush() callback checks both HW and SW queues.
|
||||
* The tx_frames_pending() callback does the same.
|
||||
* The call to __ath9k_flush() in MCC mode checks HW queues alone.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -715,7 +715,8 @@ int ath_update_survey_stats(struct ath_s
|
||||
void ath_update_survey_nf(struct ath_softc *sc, int channel);
|
||||
void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
|
||||
void ath_ps_full_sleep(unsigned long data);
|
||||
-void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
|
||||
+void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
|
||||
+ bool sw_pending);
|
||||
|
||||
/**********/
|
||||
/* BTCOEX */
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -1137,10 +1137,11 @@ void ath_chanctx_set_next(struct ath_sof
|
||||
ath9k_chanctx_stop_queues(sc, sc->cur_chan);
|
||||
queues_stopped = true;
|
||||
|
||||
- __ath9k_flush(sc->hw, ~0, true);
|
||||
+ __ath9k_flush(sc->hw, ~0, true, false);
|
||||
|
||||
if (ath_chanctx_send_ps_frame(sc, true))
|
||||
- __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), false);
|
||||
+ __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO),
|
||||
+ false, false);
|
||||
|
||||
send_ps = true;
|
||||
spin_lock_bh(&sc->chan_lock);
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -54,7 +54,8 @@ u8 ath9k_parse_mpdudensity(u8 mpdudensit
|
||||
}
|
||||
}
|
||||
|
||||
-static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
|
||||
+static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq,
|
||||
+ bool sw_pending)
|
||||
{
|
||||
bool pending = false;
|
||||
|
||||
@@ -65,6 +66,9 @@ static bool ath9k_has_pending_frames(str
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ if (!sw_pending)
|
||||
+ goto out;
|
||||
+
|
||||
if (txq->mac80211_qnum >= 0) {
|
||||
struct list_head *list;
|
||||
|
||||
@@ -2003,7 +2007,8 @@ static void ath9k_set_coverage_class(str
|
||||
mutex_unlock(&sc->mutex);
|
||||
}
|
||||
|
||||
-static bool ath9k_has_tx_pending(struct ath_softc *sc)
|
||||
+static bool ath9k_has_tx_pending(struct ath_softc *sc,
|
||||
+ bool sw_pending)
|
||||
{
|
||||
int i, npend = 0;
|
||||
|
||||
@@ -2011,7 +2016,8 @@ static bool ath9k_has_tx_pending(struct
|
||||
if (!ATH_TXQ_SETUP(sc, i))
|
||||
continue;
|
||||
|
||||
- npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
|
||||
+ npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i],
|
||||
+ sw_pending);
|
||||
if (npend)
|
||||
break;
|
||||
}
|
||||
@@ -2025,11 +2031,12 @@ static void ath9k_flush(struct ieee80211
|
||||
struct ath_softc *sc = hw->priv;
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
- __ath9k_flush(hw, queues, drop);
|
||||
+ __ath9k_flush(hw, queues, drop, true);
|
||||
mutex_unlock(&sc->mutex);
|
||||
}
|
||||
|
||||
-void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
||||
+void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
|
||||
+ bool sw_pending)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
@@ -2056,7 +2063,7 @@ void __ath9k_flush(struct ieee80211_hw *
|
||||
ath_dbg(common, CHAN_CTX,
|
||||
"Flush timeout: %d\n", jiffies_to_msecs(timeout));
|
||||
|
||||
- if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc),
|
||||
+ if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc, sw_pending),
|
||||
timeout) > 0)
|
||||
drop = false;
|
||||
|
||||
@@ -2079,7 +2086,7 @@ static bool ath9k_tx_frames_pending(stru
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
|
||||
- return ath9k_has_tx_pending(sc);
|
||||
+ return ath9k_has_tx_pending(sc, true);
|
||||
}
|
||||
|
||||
static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
|
|
@ -0,0 +1,33 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:19 +0530
|
||||
Subject: [PATCH] ath9k: Send AUTHORIZED event only for station mode
|
||||
|
||||
ATH_CHANCTX_EVENT_AUTHORIZED is required to trigger
|
||||
the MCC scheduler when a station interface becomes
|
||||
authorized. But, since the driver gets station state
|
||||
notifications when the current operating mode is AP
|
||||
too, make sure that we send ATH_CHANCTX_EVENT_AUTHORIZED
|
||||
only when the interface is in station mode.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -1590,10 +1590,12 @@ static int ath9k_sta_state(struct ieee80
|
||||
}
|
||||
|
||||
if (ath9k_is_chanctx_enabled()) {
|
||||
- if (old_state == IEEE80211_STA_ASSOC &&
|
||||
- new_state == IEEE80211_STA_AUTHORIZED)
|
||||
- ath_chanctx_event(sc, vif,
|
||||
- ATH_CHANCTX_EVENT_AUTHORIZED);
|
||||
+ if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
+ if (old_state == IEEE80211_STA_ASSOC &&
|
||||
+ new_state == IEEE80211_STA_AUTHORIZED)
|
||||
+ ath_chanctx_event(sc, vif,
|
||||
+ ATH_CHANCTX_EVENT_AUTHORIZED);
|
||||
+ }
|
||||
}
|
||||
|
||||
return ret;
|
|
@ -0,0 +1,65 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:20 +0530
|
||||
Subject: [PATCH] ath9k: Fix address management
|
||||
|
||||
Since both the arguments need to satisfy
|
||||
the alignment requirements of ether_addr_copy(),
|
||||
use memcpy() in cases where there will be no
|
||||
big performance benefit and make sure that
|
||||
ether_addr_copy() calls use properly aligned
|
||||
arguments.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath.h
|
||||
+++ b/drivers/net/wireless/ath/ath.h
|
||||
@@ -147,7 +147,7 @@ struct ath_common {
|
||||
u16 cachelsz;
|
||||
u16 curaid;
|
||||
u8 macaddr[ETH_ALEN];
|
||||
- u8 curbssid[ETH_ALEN];
|
||||
+ u8 curbssid[ETH_ALEN] __aligned(2);
|
||||
u8 bssidmask[ETH_ALEN];
|
||||
|
||||
u32 rx_bufsize;
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -595,7 +595,7 @@ struct ath_vif {
|
||||
u16 seq_no;
|
||||
|
||||
/* BSS info */
|
||||
- u8 bssid[ETH_ALEN];
|
||||
+ u8 bssid[ETH_ALEN] __aligned(2);
|
||||
u16 aid;
|
||||
bool assoc;
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -1057,7 +1057,7 @@ static void ath9k_set_offchannel_state(s
|
||||
|
||||
eth_zero_addr(common->curbssid);
|
||||
eth_broadcast_addr(common->bssidmask);
|
||||
- ether_addr_copy(common->macaddr, vif->addr);
|
||||
+ memcpy(common->macaddr, vif->addr, ETH_ALEN);
|
||||
common->curaid = 0;
|
||||
ah->opmode = vif->type;
|
||||
ah->imask &= ~ATH9K_INT_SWBA;
|
||||
@@ -1098,7 +1098,7 @@ void ath9k_calculate_summary_state(struc
|
||||
ath9k_calculate_iter_data(sc, ctx, &iter_data);
|
||||
|
||||
if (iter_data.has_hw_macaddr)
|
||||
- ether_addr_copy(common->macaddr, iter_data.hw_macaddr);
|
||||
+ memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN);
|
||||
|
||||
memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
|
||||
ath_hw_setbssidmask(common);
|
||||
@@ -1785,7 +1785,7 @@ static void ath9k_bss_info_changed(struc
|
||||
ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
|
||||
bss_conf->bssid, bss_conf->assoc);
|
||||
|
||||
- ether_addr_copy(avp->bssid, bss_conf->bssid);
|
||||
+ memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN);
|
||||
avp->aid = bss_conf->aid;
|
||||
avp->assoc = bss_conf->assoc;
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:21 +0530
|
||||
Subject: [PATCH] ath9k: Add a function to check for an active GO
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -469,6 +469,7 @@ void ath_chanctx_set_next(struct ath_sof
|
||||
void ath_offchannel_next(struct ath_softc *sc);
|
||||
void ath_scan_complete(struct ath_softc *sc, bool abort);
|
||||
void ath_roc_complete(struct ath_softc *sc, bool abort);
|
||||
+struct ath_chanctx* ath_is_go_chanctx_present(struct ath_softc *sc);
|
||||
|
||||
#else
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -146,6 +146,36 @@ void ath_chanctx_set_channel(struct ath_
|
||||
|
||||
#ifdef CPTCFG_ATH9K_CHANNEL_CONTEXT
|
||||
|
||||
+/*************/
|
||||
+/* Utilities */
|
||||
+/*************/
|
||||
+
|
||||
+struct ath_chanctx* ath_is_go_chanctx_present(struct ath_softc *sc)
|
||||
+{
|
||||
+ struct ath_chanctx *ctx;
|
||||
+ struct ath_vif *avp;
|
||||
+ struct ieee80211_vif *vif;
|
||||
+
|
||||
+ spin_lock_bh(&sc->chan_lock);
|
||||
+
|
||||
+ ath_for_each_chanctx(sc, ctx) {
|
||||
+ if (!ctx->active)
|
||||
+ continue;
|
||||
+
|
||||
+ list_for_each_entry(avp, &ctx->vifs, list) {
|
||||
+ vif = avp->vif;
|
||||
+
|
||||
+ if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_P2P_GO) {
|
||||
+ spin_unlock_bh(&sc->chan_lock);
|
||||
+ return ctx;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock_bh(&sc->chan_lock);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
/**********************************************************/
|
||||
/* Functions to handle the channel context state machine. */
|
||||
/**********************************************************/
|
|
@ -0,0 +1,134 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:22 +0530
|
||||
Subject: [PATCH] ath9k: Check for active GO in mgd_prepare_tx()
|
||||
|
||||
If a GO interface is active when we receive a
|
||||
mgd_prepare_tx() call, then we need to send
|
||||
out a new NoA before switching to a new context.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -385,6 +385,7 @@ struct ath_chanctx_sched {
|
||||
bool wait_switch;
|
||||
bool force_noa_update;
|
||||
bool extend_absence;
|
||||
+ bool mgd_prepare_tx;
|
||||
enum ath_chanctx_state state;
|
||||
u8 beacon_miss;
|
||||
|
||||
@@ -977,6 +978,7 @@ struct ath_softc {
|
||||
struct ath_chanctx_sched sched;
|
||||
struct ath_offchannel offchannel;
|
||||
struct ath_chanctx *next_chan;
|
||||
+ struct completion go_beacon;
|
||||
#endif
|
||||
|
||||
unsigned long driver_data;
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -421,6 +421,9 @@ void ath_chanctx_event(struct ath_softc
|
||||
"Move chanctx state from WAIT_FOR_TIMER to WAIT_FOR_BEACON\n");
|
||||
}
|
||||
|
||||
+ if (sc->sched.mgd_prepare_tx)
|
||||
+ sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
|
||||
+
|
||||
/*
|
||||
* When a context becomes inactive, for example,
|
||||
* disassociation of a station context, the NoA
|
||||
@@ -547,6 +550,15 @@ void ath_chanctx_event(struct ath_softc
|
||||
}
|
||||
|
||||
sc->sched.beacon_pending = false;
|
||||
+
|
||||
+ if (sc->sched.mgd_prepare_tx) {
|
||||
+ sc->sched.mgd_prepare_tx = false;
|
||||
+ complete(&sc->go_beacon);
|
||||
+ ath_dbg(common, CHAN_CTX,
|
||||
+ "Beacon sent, complete go_beacon\n");
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
|
||||
break;
|
||||
|
||||
@@ -1263,6 +1275,8 @@ void ath9k_init_channel_context(struct a
|
||||
(unsigned long)sc);
|
||||
setup_timer(&sc->sched.timer, ath_chanctx_timer,
|
||||
(unsigned long)sc);
|
||||
+
|
||||
+ init_completion(&sc->go_beacon);
|
||||
}
|
||||
|
||||
void ath9k_deinit_channel_context(struct ath_softc *sc)
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -2474,7 +2474,11 @@ static void ath9k_mgd_prepare_tx(struct
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_vif *avp = (struct ath_vif *) vif->drv_priv;
|
||||
+ struct ath_beacon_config *cur_conf;
|
||||
+ struct ath_chanctx *go_ctx;
|
||||
+ unsigned long timeout;
|
||||
bool changed = false;
|
||||
+ u32 beacon_int;
|
||||
|
||||
if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
|
||||
return;
|
||||
@@ -2485,19 +2489,46 @@ static void ath9k_mgd_prepare_tx(struct
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
spin_lock_bh(&sc->chan_lock);
|
||||
- if (sc->next_chan || (sc->cur_chan != avp->chanctx)) {
|
||||
- sc->next_chan = avp->chanctx;
|
||||
+ if (sc->next_chan || (sc->cur_chan != avp->chanctx))
|
||||
changed = true;
|
||||
+ spin_unlock_bh(&sc->chan_lock);
|
||||
+
|
||||
+ if (!changed)
|
||||
+ goto out;
|
||||
+
|
||||
+ go_ctx = ath_is_go_chanctx_present(sc);
|
||||
+
|
||||
+ if (go_ctx) {
|
||||
+ /*
|
||||
+ * Wait till the GO interface gets a chance
|
||||
+ * to send out an NoA.
|
||||
+ */
|
||||
+ spin_lock_bh(&sc->chan_lock);
|
||||
+ sc->sched.mgd_prepare_tx = true;
|
||||
+ cur_conf = &go_ctx->beacon;
|
||||
+ beacon_int = TU_TO_USEC(cur_conf->beacon_interval);
|
||||
+ spin_unlock_bh(&sc->chan_lock);
|
||||
+
|
||||
+ timeout = usecs_to_jiffies(beacon_int);
|
||||
+ init_completion(&sc->go_beacon);
|
||||
+
|
||||
+ if (wait_for_completion_timeout(&sc->go_beacon,
|
||||
+ timeout) == 0)
|
||||
+ ath_dbg(common, CHAN_CTX,
|
||||
+ "Failed to send new NoA\n");
|
||||
}
|
||||
+
|
||||
ath_dbg(common, CHAN_CTX,
|
||||
- "%s: Set chanctx state to FORCE_ACTIVE, changed: %d\n",
|
||||
- __func__, changed);
|
||||
+ "%s: Set chanctx state to FORCE_ACTIVE for vif: %pM\n",
|
||||
+ __func__, vif->addr);
|
||||
+
|
||||
+ spin_lock_bh(&sc->chan_lock);
|
||||
+ sc->next_chan = avp->chanctx;
|
||||
sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE;
|
||||
spin_unlock_bh(&sc->chan_lock);
|
||||
|
||||
- if (changed)
|
||||
- ath_chanctx_set_next(sc, true);
|
||||
-
|
||||
+ ath_chanctx_set_next(sc, true);
|
||||
+out:
|
||||
mutex_unlock(&sc->mutex);
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:23 +0530
|
||||
Subject: [PATCH] ath9k: Use a helper function for offchannel NoA
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -366,6 +366,32 @@ static void ath_chanctx_setup_timer(stru
|
||||
"Setup chanctx timer with timeout: %d ms\n", jiffies_to_msecs(tsf_time));
|
||||
}
|
||||
|
||||
+static void ath_chanctx_offchannel_noa(struct ath_softc *sc,
|
||||
+ struct ath_chanctx *ctx,
|
||||
+ struct ath_vif *avp,
|
||||
+ u32 tsf_time)
|
||||
+{
|
||||
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
+
|
||||
+ avp->noa_index++;
|
||||
+ avp->offchannel_start = tsf_time;
|
||||
+ avp->offchannel_duration = sc->sched.offchannel_duration;
|
||||
+
|
||||
+ ath_dbg(common, CHAN_CTX,
|
||||
+ "offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n",
|
||||
+ avp->offchannel_duration,
|
||||
+ avp->offchannel_start,
|
||||
+ avp->noa_index);
|
||||
+
|
||||
+ /*
|
||||
+ * When multiple contexts are active, the NoA
|
||||
+ * has to be recalculated and advertised after
|
||||
+ * an offchannel operation.
|
||||
+ */
|
||||
+ if (ctx->active && avp->noa_duration)
|
||||
+ avp->noa_duration = 0;
|
||||
+}
|
||||
+
|
||||
void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
|
||||
enum ath_chanctx_event ev)
|
||||
{
|
||||
@@ -461,24 +487,7 @@ void ath_chanctx_event(struct ath_softc
|
||||
* values and increment the index.
|
||||
*/
|
||||
if (sc->next_chan == &sc->offchannel.chan) {
|
||||
- avp->noa_index++;
|
||||
- avp->offchannel_start = tsf_time;
|
||||
- avp->offchannel_duration = sc->sched.offchannel_duration;
|
||||
-
|
||||
- ath_dbg(common, CHAN_CTX,
|
||||
- "offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n",
|
||||
- avp->offchannel_duration,
|
||||
- avp->offchannel_start,
|
||||
- avp->noa_index);
|
||||
-
|
||||
- /*
|
||||
- * When multiple contexts are active, the NoA
|
||||
- * has to be recalculated and advertised after
|
||||
- * an offchannel operation.
|
||||
- */
|
||||
- if (ctx->active && avp->noa_duration)
|
||||
- avp->noa_duration = 0;
|
||||
-
|
||||
+ ath_chanctx_offchannel_noa(sc, ctx, avp, tsf_time);
|
||||
break;
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:24 +0530
|
||||
Subject: [PATCH] ath9k: Use a helper function to set NoA
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -392,6 +392,39 @@ static void ath_chanctx_offchannel_noa(s
|
||||
avp->noa_duration = 0;
|
||||
}
|
||||
|
||||
+static void ath_chanctx_set_periodic_noa(struct ath_softc *sc,
|
||||
+ struct ath_vif *avp,
|
||||
+ struct ath_beacon_config *cur_conf,
|
||||
+ u32 tsf_time,
|
||||
+ u32 beacon_int)
|
||||
+{
|
||||
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
+
|
||||
+ avp->noa_index++;
|
||||
+ avp->noa_start = tsf_time;
|
||||
+
|
||||
+ if (sc->sched.extend_absence)
|
||||
+ avp->noa_duration = (3 * beacon_int / 2) +
|
||||
+ sc->sched.channel_switch_time;
|
||||
+ else
|
||||
+ avp->noa_duration =
|
||||
+ TU_TO_USEC(cur_conf->beacon_interval) / 2 +
|
||||
+ sc->sched.channel_switch_time;
|
||||
+
|
||||
+ if (test_bit(ATH_OP_SCANNING, &common->op_flags) ||
|
||||
+ sc->sched.extend_absence)
|
||||
+ avp->periodic_noa = false;
|
||||
+ else
|
||||
+ avp->periodic_noa = true;
|
||||
+
|
||||
+ ath_dbg(common, CHAN_CTX,
|
||||
+ "noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
|
||||
+ avp->noa_duration,
|
||||
+ avp->noa_start,
|
||||
+ avp->noa_index,
|
||||
+ avp->periodic_noa);
|
||||
+}
|
||||
+
|
||||
void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
|
||||
enum ath_chanctx_event ev)
|
||||
{
|
||||
@@ -521,31 +554,9 @@ void ath_chanctx_event(struct ath_softc
|
||||
* announcement.
|
||||
*/
|
||||
if (ctx->active &&
|
||||
- (!avp->noa_duration || sc->sched.force_noa_update)) {
|
||||
- avp->noa_index++;
|
||||
- avp->noa_start = tsf_time;
|
||||
-
|
||||
- if (sc->sched.extend_absence)
|
||||
- avp->noa_duration = (3 * beacon_int / 2) +
|
||||
- sc->sched.channel_switch_time;
|
||||
- else
|
||||
- avp->noa_duration =
|
||||
- TU_TO_USEC(cur_conf->beacon_interval) / 2 +
|
||||
- sc->sched.channel_switch_time;
|
||||
-
|
||||
- if (test_bit(ATH_OP_SCANNING, &common->op_flags) ||
|
||||
- sc->sched.extend_absence)
|
||||
- avp->periodic_noa = false;
|
||||
- else
|
||||
- avp->periodic_noa = true;
|
||||
-
|
||||
- ath_dbg(common, CHAN_CTX,
|
||||
- "noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
|
||||
- avp->noa_duration,
|
||||
- avp->noa_start,
|
||||
- avp->noa_index,
|
||||
- avp->periodic_noa);
|
||||
- }
|
||||
+ (!avp->noa_duration || sc->sched.force_noa_update))
|
||||
+ ath_chanctx_set_periodic_noa(sc, avp, cur_conf,
|
||||
+ tsf_time, beacon_int);
|
||||
|
||||
if (ctx->active && sc->sched.force_noa_update)
|
||||
sc->sched.force_noa_update = false;
|
|
@ -0,0 +1,68 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:25 +0530
|
||||
Subject: [PATCH] ath9k: Use a helper function for bmiss
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -366,6 +366,31 @@ static void ath_chanctx_setup_timer(stru
|
||||
"Setup chanctx timer with timeout: %d ms\n", jiffies_to_msecs(tsf_time));
|
||||
}
|
||||
|
||||
+static void ath_chanctx_handle_bmiss(struct ath_softc *sc,
|
||||
+ struct ath_chanctx *ctx,
|
||||
+ struct ath_vif *avp)
|
||||
+{
|
||||
+ /*
|
||||
+ * Clear the extend_absence flag if it had been
|
||||
+ * set during the previous beacon transmission,
|
||||
+ * since we need to revert to the normal NoA
|
||||
+ * schedule.
|
||||
+ */
|
||||
+ if (ctx->active && sc->sched.extend_absence) {
|
||||
+ avp->noa_duration = 0;
|
||||
+ sc->sched.extend_absence = false;
|
||||
+ }
|
||||
+
|
||||
+ /* If at least two consecutive beacons were missed on the STA
|
||||
+ * chanctx, stay on the STA channel for one extra beacon period,
|
||||
+ * to resync the timer properly.
|
||||
+ */
|
||||
+ if (ctx->active && sc->sched.beacon_miss >= 2) {
|
||||
+ avp->noa_duration = 0;
|
||||
+ sc->sched.extend_absence = true;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void ath_chanctx_offchannel_noa(struct ath_softc *sc,
|
||||
struct ath_chanctx *ctx,
|
||||
struct ath_vif *avp,
|
||||
@@ -524,25 +549,7 @@ void ath_chanctx_event(struct ath_softc
|
||||
break;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Clear the extend_absence flag if it had been
|
||||
- * set during the previous beacon transmission,
|
||||
- * since we need to revert to the normal NoA
|
||||
- * schedule.
|
||||
- */
|
||||
- if (ctx->active && sc->sched.extend_absence) {
|
||||
- avp->noa_duration = 0;
|
||||
- sc->sched.extend_absence = false;
|
||||
- }
|
||||
-
|
||||
- /* If at least two consecutive beacons were missed on the STA
|
||||
- * chanctx, stay on the STA channel for one extra beacon period,
|
||||
- * to resync the timer properly.
|
||||
- */
|
||||
- if (ctx->active && sc->sched.beacon_miss >= 2) {
|
||||
- avp->noa_duration = 0;
|
||||
- sc->sched.extend_absence = true;
|
||||
- }
|
||||
+ ath_chanctx_handle_bmiss(sc, ctx, avp);
|
||||
|
||||
/* Prevent wrap-around issues */
|
||||
if (avp->noa_duration && tsf_time - avp->noa_start > BIT(30))
|
|
@ -0,0 +1,38 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:26 +0530
|
||||
Subject: [PATCH] ath9k: Fix RoC expiration
|
||||
|
||||
mac80211 has to be notified when a RoC period
|
||||
expires in the driver. In MCC mode, since the
|
||||
offchannel/RoC timer is set with the requested
|
||||
duration, ieee80211_remain_on_channel_expired() needs
|
||||
to be called when the timer expires.
|
||||
|
||||
But, currently it is done after we move back to
|
||||
the operating channel. This is incorrect - fix this
|
||||
by calling ieee80211_remain_on_channel_expired() when
|
||||
the RoC timer expires and in ath_roc_complete() when
|
||||
the RoC request is aborted.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -894,7 +894,7 @@ void ath_roc_complete(struct ath_softc *
|
||||
|
||||
sc->offchannel.roc_vif = NULL;
|
||||
sc->offchannel.roc_chan = NULL;
|
||||
- if (!abort)
|
||||
+ if (abort)
|
||||
ieee80211_remain_on_channel_expired(sc->hw);
|
||||
ath_offchannel_next(sc);
|
||||
ath9k_ps_restore(sc);
|
||||
@@ -1028,6 +1028,7 @@ static void ath_offchannel_timer(unsigne
|
||||
case ATH_OFFCHANNEL_ROC_WAIT:
|
||||
ctx = ath_chanctx_get_oper_chan(sc, false);
|
||||
sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE;
|
||||
+ ieee80211_remain_on_channel_expired(sc->hw);
|
||||
ath_chanctx_switch(sc, ctx, NULL);
|
||||
break;
|
||||
default:
|
|
@ -0,0 +1,85 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:27 +0530
|
||||
Subject: [PATCH] ath9k: Send oneshot NoA
|
||||
|
||||
This patch makes sure that a GO interface
|
||||
sends out a new NoA schedule with 200ms duration
|
||||
when mgd_prepare_tx() is called.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -620,6 +620,7 @@ struct ath_vif {
|
||||
u32 noa_start;
|
||||
u32 noa_duration;
|
||||
bool periodic_noa;
|
||||
+ bool oneshot_noa;
|
||||
};
|
||||
|
||||
struct ath9k_vif_iter_data {
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -450,6 +450,27 @@ static void ath_chanctx_set_periodic_noa
|
||||
avp->periodic_noa);
|
||||
}
|
||||
|
||||
+static void ath_chanctx_set_oneshot_noa(struct ath_softc *sc,
|
||||
+ struct ath_vif *avp,
|
||||
+ u32 tsf_time,
|
||||
+ u32 duration)
|
||||
+{
|
||||
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
+
|
||||
+ avp->noa_index++;
|
||||
+ avp->noa_start = tsf_time;
|
||||
+ avp->periodic_noa = false;
|
||||
+ avp->oneshot_noa = true;
|
||||
+ avp->noa_duration = duration + sc->sched.channel_switch_time;
|
||||
+
|
||||
+ ath_dbg(common, CHAN_CTX,
|
||||
+ "oneshot noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
|
||||
+ avp->noa_duration,
|
||||
+ avp->noa_start,
|
||||
+ avp->noa_index,
|
||||
+ avp->periodic_noa);
|
||||
+}
|
||||
+
|
||||
void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
|
||||
enum ath_chanctx_event ev)
|
||||
{
|
||||
@@ -476,6 +497,14 @@ void ath_chanctx_event(struct ath_softc
|
||||
if (avp->offchannel_duration)
|
||||
avp->offchannel_duration = 0;
|
||||
|
||||
+ if (avp->oneshot_noa) {
|
||||
+ avp->noa_duration = 0;
|
||||
+ avp->oneshot_noa = false;
|
||||
+
|
||||
+ ath_dbg(common, CHAN_CTX,
|
||||
+ "Clearing oneshot NoA\n");
|
||||
+ }
|
||||
+
|
||||
if (avp->chanctx != sc->cur_chan) {
|
||||
ath_dbg(common, CHAN_CTX,
|
||||
"Contexts differ, not preparing beacon\n");
|
||||
@@ -551,6 +580,18 @@ void ath_chanctx_event(struct ath_softc
|
||||
|
||||
ath_chanctx_handle_bmiss(sc, ctx, avp);
|
||||
|
||||
+ /*
|
||||
+ * If a mgd_prepare_tx() has been called by mac80211,
|
||||
+ * a one-shot NoA needs to be sent. This can happen
|
||||
+ * with one or more active channel contexts - in both
|
||||
+ * cases, a new NoA schedule has to be advertised.
|
||||
+ */
|
||||
+ if (sc->sched.mgd_prepare_tx) {
|
||||
+ ath_chanctx_set_oneshot_noa(sc, avp, tsf_time,
|
||||
+ jiffies_to_usecs(HZ / 5));
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
/* Prevent wrap-around issues */
|
||||
if (avp->noa_duration && tsf_time - avp->noa_start > BIT(30))
|
||||
avp->noa_duration = 0;
|
|
@ -0,0 +1,68 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:28 +0530
|
||||
Subject: [PATCH] ath9k: Fix HW scan abort
|
||||
|
||||
Instead of using ATH_CHANCTX_EVENT_ASSIGN to abort
|
||||
a HW scan when a new interface becomes active, use the
|
||||
mgd_prepare_tx() callback. This allows us to make
|
||||
sure that the GO's channel becomes operational by
|
||||
using flush_work().
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -743,22 +743,6 @@ void ath_chanctx_event(struct ath_softc
|
||||
ieee80211_queue_work(sc->hw, &sc->chanctx_work);
|
||||
break;
|
||||
case ATH_CHANCTX_EVENT_ASSIGN:
|
||||
- /*
|
||||
- * When adding a new channel context, check if a scan
|
||||
- * is in progress and abort it since the addition of
|
||||
- * a new channel context is usually followed by VIF
|
||||
- * assignment, in which case we have to start multi-channel
|
||||
- * operation.
|
||||
- */
|
||||
- if (test_bit(ATH_OP_SCANNING, &common->op_flags)) {
|
||||
- ath_dbg(common, CHAN_CTX,
|
||||
- "Aborting HW scan to add new context\n");
|
||||
-
|
||||
- spin_unlock_bh(&sc->chan_lock);
|
||||
- del_timer_sync(&sc->offchannel.timer);
|
||||
- ath_scan_complete(sc, true);
|
||||
- spin_lock_bh(&sc->chan_lock);
|
||||
- }
|
||||
break;
|
||||
case ATH_CHANCTX_EVENT_CHANGE:
|
||||
break;
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -2365,7 +2365,6 @@ static int ath9k_add_chanctx(struct ieee
|
||||
conf->def.chan->center_freq);
|
||||
|
||||
ath_chanctx_set_channel(sc, ctx, &conf->def);
|
||||
- ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_ASSIGN);
|
||||
|
||||
mutex_unlock(&sc->mutex);
|
||||
return 0;
|
||||
@@ -2496,6 +2495,19 @@ static void ath9k_mgd_prepare_tx(struct
|
||||
if (!changed)
|
||||
goto out;
|
||||
|
||||
+ if (test_bit(ATH_OP_SCANNING, &common->op_flags)) {
|
||||
+ ath_dbg(common, CHAN_CTX,
|
||||
+ "%s: Aborting HW scan\n", __func__);
|
||||
+
|
||||
+ mutex_unlock(&sc->mutex);
|
||||
+
|
||||
+ del_timer_sync(&sc->offchannel.timer);
|
||||
+ ath_scan_complete(sc, true);
|
||||
+ flush_work(&sc->chanctx_work);
|
||||
+
|
||||
+ mutex_lock(&sc->mutex);
|
||||
+ }
|
||||
+
|
||||
go_ctx = ath_is_go_chanctx_present(sc);
|
||||
|
||||
if (go_ctx) {
|
|
@ -0,0 +1,95 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:29 +0530
|
||||
Subject: [PATCH] ath9k: Improve flush() in mcc mode
|
||||
|
||||
The flush timeout in MCC mode is very small, since
|
||||
we are constrained by the time slice for each
|
||||
channel context, but since only the HW queues are
|
||||
flushed when switching contexts, it is acceptable.
|
||||
|
||||
Since the SW queues are also emptied in the mac80211 flush()
|
||||
callback, a larger duration is needed. Add an override
|
||||
argument to __ath9k_flush() and set it when flush()
|
||||
is called in MCC mode. This allows the driver to
|
||||
drain both the SW and HW queues.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -719,7 +719,7 @@ void ath_update_survey_nf(struct ath_sof
|
||||
void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
|
||||
void ath_ps_full_sleep(unsigned long data);
|
||||
void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
|
||||
- bool sw_pending);
|
||||
+ bool sw_pending, bool timeout_override);
|
||||
|
||||
/**********/
|
||||
/* BTCOEX */
|
||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
||||
@@ -1232,11 +1232,11 @@ void ath_chanctx_set_next(struct ath_sof
|
||||
ath9k_chanctx_stop_queues(sc, sc->cur_chan);
|
||||
queues_stopped = true;
|
||||
|
||||
- __ath9k_flush(sc->hw, ~0, true, false);
|
||||
+ __ath9k_flush(sc->hw, ~0, true, false, false);
|
||||
|
||||
if (ath_chanctx_send_ps_frame(sc, true))
|
||||
__ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO),
|
||||
- false, false);
|
||||
+ false, false, false);
|
||||
|
||||
send_ps = true;
|
||||
spin_lock_bh(&sc->chan_lock);
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -2031,14 +2031,33 @@ static void ath9k_flush(struct ieee80211
|
||||
u32 queues, bool drop)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
+
|
||||
+ if (ath9k_is_chanctx_enabled()) {
|
||||
+ if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
|
||||
+ goto flush;
|
||||
|
||||
+ /*
|
||||
+ * If MCC is active, extend the flush timeout
|
||||
+ * and wait for the HW/SW queues to become
|
||||
+ * empty. This needs to be done outside the
|
||||
+ * sc->mutex lock to allow the channel scheduler
|
||||
+ * to switch channel contexts.
|
||||
+ *
|
||||
+ * The vif queues have been stopped in mac80211,
|
||||
+ * so there won't be any incoming frames.
|
||||
+ */
|
||||
+ __ath9k_flush(hw, queues, drop, true, true);
|
||||
+ return;
|
||||
+ }
|
||||
+flush:
|
||||
mutex_lock(&sc->mutex);
|
||||
- __ath9k_flush(hw, queues, drop, true);
|
||||
+ __ath9k_flush(hw, queues, drop, true, false);
|
||||
mutex_unlock(&sc->mutex);
|
||||
}
|
||||
|
||||
void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
|
||||
- bool sw_pending)
|
||||
+ bool sw_pending, bool timeout_override)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
@@ -2059,7 +2078,10 @@ void __ath9k_flush(struct ieee80211_hw *
|
||||
}
|
||||
|
||||
spin_lock_bh(&sc->chan_lock);
|
||||
- timeout = sc->cur_chan->flush_timeout;
|
||||
+ if (timeout_override)
|
||||
+ timeout = HZ / 5;
|
||||
+ else
|
||||
+ timeout = sc->cur_chan->flush_timeout;
|
||||
spin_unlock_bh(&sc->chan_lock);
|
||||
|
||||
ath_dbg(common, CHAN_CTX,
|
|
@ -0,0 +1,60 @@
|
|||
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
Date: Fri, 17 Oct 2014 07:40:30 +0530
|
||||
Subject: [PATCH] ath9k: Do not start BA when scanning
|
||||
|
||||
mac80211 currently has a race which can be hit
|
||||
with this sequence:
|
||||
|
||||
* Start a scan operation.
|
||||
* TX BA is initiated by ieee80211_start_tx_ba_session().
|
||||
* Driver sets up internal state and calls
|
||||
ieee80211_start_tx_ba_cb_irqsafe().
|
||||
* mac80211 adds a packet to sdata->skb_queue with
|
||||
type IEEE80211_SDATA_QUEUE_AGG_START.
|
||||
* ieee80211_iface_work() doesn't process the
|
||||
packet because scan is in progress.
|
||||
* ADDBA response timer expires and the sta/tid is
|
||||
torn down.
|
||||
* Driver receives BA stop notification and calls
|
||||
ieee80211_stop_tx_ba_cb_irqsafe().
|
||||
* This is also added to the queue by mac80211.
|
||||
* Now, scan finishes.
|
||||
|
||||
At this point, the queued up packets might be processed
|
||||
if some other operation schedules the sdata work. Since
|
||||
the tids have been cleaned up already, warnings are hit.
|
||||
|
||||
If this doesn't happen, the packets are left in the queue
|
||||
until the interface is torn down.
|
||||
|
||||
Since initiating a BA session when scan is in progress
|
||||
leads to flaky connections, especially in MCC mode, we
|
||||
can drop the TX BA request. This improves connectivity
|
||||
with legacy clients in MCC mode.
|
||||
|
||||
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -1885,6 +1885,7 @@ static int ath9k_ampdu_action(struct iee
|
||||
u16 tid, u16 *ssn, u8 buf_size)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
bool flush = false;
|
||||
int ret = 0;
|
||||
|
||||
@@ -1896,6 +1897,12 @@ static int ath9k_ampdu_action(struct iee
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
+ if (ath9k_is_chanctx_enabled()) {
|
||||
+ if (test_bit(ATH_OP_SCANNING, &common->op_flags)) {
|
||||
+ ret = -EBUSY;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
ath9k_ps_wakeup(sc);
|
||||
ret = ath_tx_aggr_start(sc, sta, tid, ssn);
|
||||
if (!ret)
|
|
@ -1,3 +1,13 @@
|
|||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 18 Oct 2014 13:23:34 +0200
|
||||
Subject: [PATCH] ath9k_hw: make support for PC-OEM cards optional
|
||||
|
||||
The initvals use up quite a bit of space, and PC-OEM support is
|
||||
typically not needed on embedded systems
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/Kconfig
|
||||
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
|
||||
@@ -151,6 +151,11 @@ config ATH9K_CHANNEL_CONTEXT
|
||||
|
@ -84,7 +94,7 @@
|
|||
#endif
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -245,13 +245,20 @@ enum ath9k_hw_caps {
|
||||
@@ -244,13 +244,20 @@ enum ath9k_hw_caps {
|
||||
ATH9K_HW_CAP_2GHZ = BIT(11),
|
||||
ATH9K_HW_CAP_5GHZ = BIT(12),
|
||||
ATH9K_HW_CAP_APM = BIT(13),
|
||||
|
@ -167,8 +177,8 @@
|
|||
.driver_data = ATH9K_PCI_BT_ANT_DIV },
|
||||
+#endif
|
||||
|
||||
{ PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E internal chip default ID */
|
||||
{ 0 }
|
||||
};
|
||||
--- a/drivers/net/wireless/ath/ath9k/reg.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/reg.h
|
||||
@@ -892,10 +892,21 @@
|
|
@ -1,3 +1,13 @@
|
|||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 18 Oct 2014 13:25:26 +0200
|
||||
Subject: [PATCH] ath9k_hw: remove support for UB124 tx gain table
|
||||
|
||||
UB124 is a USB based reference design not supported by ath9k or
|
||||
ath9k_htc.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
|
||||
@@ -670,9 +670,6 @@ static void ar9003_tx_gain_table_mode5(s
|
|
@ -0,0 +1,33 @@
|
|||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 18 Oct 2014 13:31:52 +0200
|
||||
Subject: [PATCH] ath9k: fix processing RXORN interrupts
|
||||
|
||||
The "goto chip_reset" is a bit misleading, because it does not actually
|
||||
issue a chip reset. Instead it is bypassing processing of other
|
||||
interrupts and assumes that the tasklet will issue a chip reset.
|
||||
|
||||
In the case of RXORN this does not happen, so bypassing processing of
|
||||
other interrupts will simply allow them to fire again. Even if RXORN
|
||||
was triggering a reset, it is not critical enough to need the bypass
|
||||
here.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -545,11 +545,10 @@ irqreturn_t ath_isr(int irq, void *dev)
|
||||
sched = true;
|
||||
|
||||
/*
|
||||
- * If a FATAL or RXORN interrupt is received, we have to reset the
|
||||
- * chip immediately.
|
||||
+ * If a FATAL interrupt is received, we have to reset the chip
|
||||
+ * immediately.
|
||||
*/
|
||||
- if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) &&
|
||||
- !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)))
|
||||
+ if (status & ATH9K_INT_FATAL)
|
||||
goto chip_reset;
|
||||
|
||||
if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) &&
|
|
@ -1,3 +1,12 @@
|
|||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 18 Oct 2014 13:36:41 +0200
|
||||
Subject: [PATCH] ath9k: clean up debugfs print of reset causes
|
||||
|
||||
Reduce code duplication
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -852,36 +852,30 @@ static ssize_t read_file_reset(struct fi
|
|
@ -1,3 +1,76 @@
|
|||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 18 Oct 2014 13:37:32 +0200
|
||||
Subject: [PATCH] ath9k: restart hardware after noise floor calibration
|
||||
failure
|
||||
|
||||
When NF calibration fails, the radio often becomes deaf. The usual
|
||||
hardware hang checks do not detect this, so it's better to issue a reset
|
||||
when that happens.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
|
||||
@@ -657,14 +657,13 @@ static void ar9002_hw_olc_temp_compensat
|
||||
ar9280_hw_olc_temp_compensation(ah);
|
||||
}
|
||||
|
||||
-static bool ar9002_hw_calibrate(struct ath_hw *ah,
|
||||
- struct ath9k_channel *chan,
|
||||
- u8 rxchainmask,
|
||||
- bool longcal)
|
||||
+static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
+ u8 rxchainmask, bool longcal)
|
||||
{
|
||||
bool iscaldone = true;
|
||||
struct ath9k_cal_list *currCal = ah->cal_list_curr;
|
||||
bool nfcal, nfcal_pending = false;
|
||||
+ int ret;
|
||||
|
||||
nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
|
||||
if (ah->caldata)
|
||||
@@ -698,7 +697,9 @@ static bool ar9002_hw_calibrate(struct a
|
||||
* NF is slow time-variant, so it is OK to use a
|
||||
* historical value.
|
||||
*/
|
||||
- ath9k_hw_loadnf(ah, ah->curchan);
|
||||
+ ret = ath9k_hw_loadnf(ah, ah->curchan);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
if (longcal) {
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
|
||||
@@ -121,13 +121,12 @@ static bool ar9003_hw_per_calibration(st
|
||||
return iscaldone;
|
||||
}
|
||||
|
||||
-static bool ar9003_hw_calibrate(struct ath_hw *ah,
|
||||
- struct ath9k_channel *chan,
|
||||
- u8 rxchainmask,
|
||||
- bool longcal)
|
||||
+static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
+ u8 rxchainmask, bool longcal)
|
||||
{
|
||||
bool iscaldone = true;
|
||||
struct ath9k_cal_list *currCal = ah->cal_list_curr;
|
||||
+ int ret;
|
||||
|
||||
/*
|
||||
* For given calibration:
|
||||
@@ -163,7 +162,9 @@ static bool ar9003_hw_calibrate(struct a
|
||||
* NF is slow time-variant, so it is OK to use a historical
|
||||
* value.
|
||||
*/
|
||||
- ath9k_hw_loadnf(ah, ah->curchan);
|
||||
+ ret = ath9k_hw_loadnf(ah, ah->curchan);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
|
||||
/* start NF calibration, without updating BB NF register */
|
||||
ath9k_hw_start_nfcal(ah, false);
|
||||
--- a/drivers/net/wireless/ath/ath9k/calib.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/calib.c
|
||||
@@ -234,7 +234,7 @@ void ath9k_hw_start_nfcal(struct ath_hw
|
||||
|
@ -38,37 +111,26 @@
|
|||
bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan);
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
|
||||
@@ -657,14 +657,13 @@ static void ar9002_hw_olc_temp_compensat
|
||||
ar9280_hw_olc_temp_compensation(ah);
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -863,6 +863,7 @@ static ssize_t read_file_reset(struct fi
|
||||
[RESET_TYPE_MAC_HANG] = "MAC Hang",
|
||||
[RESET_TYPE_BEACON_STUCK] = "Stuck Beacon",
|
||||
[RESET_TYPE_MCI] = "MCI Reset",
|
||||
+ [RESET_TYPE_CALIBRATION] = "Calibration error",
|
||||
};
|
||||
char buf[512];
|
||||
unsigned int len = 0;
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.h
|
||||
@@ -49,6 +49,7 @@ enum ath_reset_type {
|
||||
RESET_TYPE_MAC_HANG,
|
||||
RESET_TYPE_BEACON_STUCK,
|
||||
RESET_TYPE_MCI,
|
||||
+ RESET_TYPE_CALIBRATION,
|
||||
__RESET_TYPE_MAX
|
||||
};
|
||||
|
||||
-static bool ar9002_hw_calibrate(struct ath_hw *ah,
|
||||
- struct ath9k_channel *chan,
|
||||
- u8 rxchainmask,
|
||||
- bool longcal)
|
||||
+static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
+ u8 rxchainmask, bool longcal)
|
||||
{
|
||||
bool iscaldone = true;
|
||||
struct ath9k_cal_list *currCal = ah->cal_list_curr;
|
||||
bool nfcal, nfcal_pending = false;
|
||||
+ int ret;
|
||||
|
||||
nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
|
||||
if (ah->caldata)
|
||||
@@ -698,7 +697,9 @@ static bool ar9002_hw_calibrate(struct a
|
||||
* NF is slow time-variant, so it is OK to use a
|
||||
* historical value.
|
||||
*/
|
||||
- ath9k_hw_loadnf(ah, ah->curchan);
|
||||
+ ret = ath9k_hw_loadnf(ah, ah->curchan);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
if (longcal) {
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
|
||||
@@ -41,10 +41,9 @@ static inline void ath9k_hw_set_desc_lin
|
||||
|
@ -85,39 +147,9 @@
|
|||
{
|
||||
return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal);
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
|
||||
@@ -121,13 +121,12 @@ static bool ar9003_hw_per_calibration(st
|
||||
return iscaldone;
|
||||
}
|
||||
|
||||
-static bool ar9003_hw_calibrate(struct ath_hw *ah,
|
||||
- struct ath9k_channel *chan,
|
||||
- u8 rxchainmask,
|
||||
- bool longcal)
|
||||
+static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
+ u8 rxchainmask, bool longcal)
|
||||
{
|
||||
bool iscaldone = true;
|
||||
struct ath9k_cal_list *currCal = ah->cal_list_curr;
|
||||
+ int ret;
|
||||
|
||||
/*
|
||||
* For given calibration:
|
||||
@@ -163,7 +162,9 @@ static bool ar9003_hw_calibrate(struct a
|
||||
* NF is slow time-variant, so it is OK to use a historical
|
||||
* value.
|
||||
*/
|
||||
- ath9k_hw_loadnf(ah, ah->curchan);
|
||||
+ ret = ath9k_hw_loadnf(ah, ah->curchan);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
|
||||
/* start NF calibration, without updating BB NF register */
|
||||
ath9k_hw_start_nfcal(ah, false);
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -696,10 +696,8 @@ struct ath_hw_ops {
|
||||
@@ -688,10 +688,8 @@ struct ath_hw_ops {
|
||||
bool power_off);
|
||||
void (*rx_enable)(struct ath_hw *ah);
|
||||
void (*set_desc_link)(void *ds, u32 link);
|
||||
|
@ -130,26 +162,6 @@
|
|||
bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked,
|
||||
u32 *sync_cause_p);
|
||||
void (*set_txdesc)(struct ath_hw *ah, void *ds,
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.h
|
||||
@@ -49,6 +49,7 @@ enum ath_reset_type {
|
||||
RESET_TYPE_MAC_HANG,
|
||||
RESET_TYPE_BEACON_STUCK,
|
||||
RESET_TYPE_MCI,
|
||||
+ RESET_TYPE_CALIBRATION,
|
||||
__RESET_TYPE_MAX
|
||||
};
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -863,6 +863,7 @@ static ssize_t read_file_reset(struct fi
|
||||
[RESET_TYPE_MAC_HANG] = "MAC Hang",
|
||||
[RESET_TYPE_BEACON_STUCK] = "Stuck Beacon",
|
||||
[RESET_TYPE_MCI] = "MCI Reset",
|
||||
+ [RESET_TYPE_CALIBRATION] = "Calibration error",
|
||||
};
|
||||
char buf[512];
|
||||
unsigned int len = 0;
|
||||
--- a/drivers/net/wireless/ath/ath9k/link.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/link.c
|
||||
@@ -371,9 +371,14 @@ void ath_ani_calibrate(unsigned long dat
|
|
@ -1,3 +1,14 @@
|
|||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 18 Oct 2014 13:39:11 +0200
|
||||
Subject: [PATCH] ath9k_hw: do not run NF and periodic calibration at the
|
||||
same time
|
||||
|
||||
It can cause inconsistent calibration results or in some cases turn the
|
||||
radio deaf.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
|
||||
@@ -660,7 +660,6 @@ static void ar9002_hw_olc_temp_compensat
|
|
@ -1,3 +1,13 @@
|
|||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 18 Oct 2014 13:42:03 +0200
|
||||
Subject: [PATCH] ath9k_hw: start initial NF calibration after PA
|
||||
calibration on <AR9003
|
||||
|
||||
This makes the initial NF calibration less likely to fail.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
|
||||
@@ -854,6 +854,7 @@ static bool ar9002_hw_init_cal(struct at
|
||||
|
@ -10,7 +20,7 @@
|
|||
set_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
||||
@@ -1997,8 +1997,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
|
||||
@@ -1953,8 +1953,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
|
||||
if (ath9k_hw_mci_is_enabled(ah))
|
||||
ar9003_mci_check_bt(ah);
|
||||
|
|
@ -1,3 +1,15 @@
|
|||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 18 Oct 2014 18:24:15 +0200
|
||||
Subject: [PATCH] ath9k: add support for endian swap of eeprom from
|
||||
platform data
|
||||
|
||||
On some devices (especially little-endian ones), the flash EEPROM data
|
||||
has a different endian, which needs to be detected.
|
||||
Add a flag to the platform data to allow overriding that behavior
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
|
||||
@@ -262,7 +262,7 @@ static int ath9k_hw_def_check_eeprom(str
|
||||
|
@ -47,31 +59,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
|
||||
@@ -57,7 +57,7 @@ static bool ath9k_hw_4k_fill_eeprom(stru
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
- if (!ath9k_hw_use_flash(ah)) {
|
||||
+ if (!(ah->ah_flags & AH_NO_EEP_SWAP)) {
|
||||
ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
|
||||
@@ -60,7 +60,7 @@ static bool ath9k_hw_ar9287_fill_eeprom(
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
- if (!ath9k_hw_use_flash(ah)) {
|
||||
+ if (!(ah->ah_flags & AH_NO_EEP_SWAP)) {
|
||||
ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -726,6 +726,7 @@ enum ath_cal_list {
|
||||
@@ -731,6 +731,7 @@ enum ath_cal_list {
|
||||
#define AH_USE_EEPROM 0x1
|
||||
#define AH_UNPLUGGED 0x2 /* The card has been physically removed. */
|
||||
#define AH_FASTCC 0x4
|
||||
|
@ -81,7 +71,7 @@
|
|||
struct ath_ops reg_ops;
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -528,6 +528,8 @@ static int ath9k_init_softc(u16 devid, s
|
||||
@@ -531,6 +531,8 @@ static int ath9k_init_softc(u16 devid, s
|
||||
ah->is_clk_25mhz = pdata->is_clk_25mhz;
|
||||
ah->get_mac_revision = pdata->get_mac_revision;
|
||||
ah->external_reset = pdata->external_reset;
|
|
@ -1,17 +1,18 @@
|
|||
--- a/include/linux/ath9k_platform.h
|
||||
+++ b/include/linux/ath9k_platform.h
|
||||
@@ -34,6 +34,8 @@ struct ath9k_platform_data {
|
||||
bool endian_check;
|
||||
bool is_clk_25mhz;
|
||||
bool tx_gain_buffalo;
|
||||
+ bool disable_2ghz;
|
||||
+ bool disable_5ghz;
|
||||
|
||||
int (*get_mac_revision)(void);
|
||||
int (*external_reset)(void);
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 18 Oct 2014 18:27:23 +0200
|
||||
Subject: [PATCH] ath9k: allow disabling bands via platform data
|
||||
|
||||
Some devices have multiple bands enables in the EEPROM data, even though
|
||||
they are only calibrated for one. Allow platform data to disable
|
||||
unsupported bands.
|
||||
|
||||
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
||||
@@ -2362,17 +2362,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw
|
||||
@@ -2344,17 +2344,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw
|
||||
}
|
||||
|
||||
eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
|
||||
|
@ -47,7 +48,7 @@
|
|||
AR_SREV_9285(ah) ||
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -934,6 +934,8 @@ struct ath_hw {
|
||||
@@ -930,6 +930,8 @@ struct ath_hw {
|
||||
bool is_clk_25mhz;
|
||||
int (*get_mac_revision)(void);
|
||||
int (*external_reset)(void);
|
||||
|
@ -58,7 +59,7 @@
|
|||
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -528,6 +528,8 @@ static int ath9k_init_softc(u16 devid, s
|
||||
@@ -531,6 +531,8 @@ static int ath9k_init_softc(u16 devid, s
|
||||
ah->is_clk_25mhz = pdata->is_clk_25mhz;
|
||||
ah->get_mac_revision = pdata->get_mac_revision;
|
||||
ah->external_reset = pdata->external_reset;
|
||||
|
@ -67,3 +68,14 @@
|
|||
if (!pdata->endian_check)
|
||||
ah->ah_flags |= AH_NO_EEP_SWAP;
|
||||
}
|
||||
--- a/include/linux/ath9k_platform.h
|
||||
+++ b/include/linux/ath9k_platform.h
|
||||
@@ -34,6 +34,8 @@ struct ath9k_platform_data {
|
||||
bool endian_check;
|
||||
bool is_clk_25mhz;
|
||||
bool tx_gain_buffalo;
|
||||
+ bool disable_2ghz;
|
||||
+ bool disable_5ghz;
|
||||
|
||||
int (*get_mac_revision)(void);
|
||||
int (*external_reset)(void);
|
|
@ -1,3 +1,13 @@
|
|||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 18 Oct 2014 18:31:49 +0200
|
||||
Subject: [PATCH] ath9k: use a random MAC address if the EEPROM address
|
||||
is invalid
|
||||
|
||||
Based on OpenWrt patch by Gabor Juhos
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
||||
@@ -19,6 +19,7 @@
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/Makefile
|
||||
+++ b/drivers/net/wireless/ath/Makefile
|
||||
@@ -13,8 +13,8 @@ ath-objs := main.o \
|
||||
@@ -13,10 +13,10 @@ ath-objs := main.o \
|
||||
regd.o \
|
||||
hw.o \
|
||||
key.o \
|
||||
|
@ -9,10 +9,12 @@
|
|||
dfs_pri_detector.o
|
||||
|
||||
-ath-$(CPTCFG_ATH_DEBUG) += debug.o
|
||||
ath-$(CPTCFG_ATH_TRACEPOINTS) += trace.o
|
||||
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
||||
--- a/drivers/net/wireless/ath/ath.h
|
||||
+++ b/drivers/net/wireless/ath/ath.h
|
||||
@@ -299,13 +299,6 @@ void _ath_dbg(struct ath_common *common,
|
||||
@@ -300,13 +300,6 @@ void _ath_dbg(struct ath_common *common,
|
||||
#endif /* CPTCFG_ATH_DEBUG */
|
||||
|
||||
/** Returns string describing opmode, or NULL if unknown mode. */
|
||||
|
|
|
@ -63,6 +63,6 @@
|
|||
ATH_CARDS=
|
||||
ATH_DEBUG=
|
||||
+ATH_USER_REGD=
|
||||
ATH_TRACEPOINTS=
|
||||
ATH_REG_DYNAMIC_USER_REG_HINTS=
|
||||
ATH_REG_DYNAMIC_USER_CERT_TESTING=
|
||||
ATH5K=
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -670,6 +670,7 @@ static const struct ieee80211_iface_limi
|
||||
@@ -677,6 +677,7 @@ static const struct ieee80211_iface_limi
|
||||
BIT(NL80211_IFTYPE_AP) },
|
||||
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) },
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -1318,6 +1318,53 @@ void ath9k_deinit_debug(struct ath_softc
|
||||
@@ -1313,6 +1313,53 @@ void ath9k_deinit_debug(struct ath_softc
|
||||
ath9k_spectral_deinit_debug(sc);
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@
|
|||
int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
@@ -1337,6 +1384,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
@@ -1332,6 +1379,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
ath9k_tx99_init_debug(sc);
|
||||
ath9k_spectral_init_debug(sc);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -976,23 +976,23 @@ static int __init ath9k_init(void)
|
||||
@@ -981,23 +981,23 @@ static int __init ath9k_init(void)
|
||||
{
|
||||
int error;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -1365,6 +1365,52 @@ static const struct file_operations fops
|
||||
@@ -1360,6 +1360,52 @@ static const struct file_operations fops
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
|
@ -53,7 +53,7 @@
|
|||
int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
@@ -1386,6 +1432,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
@@ -1381,6 +1427,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
|
||||
debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
&fops_eeprom);
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
#define AR9160_DEVID_PCI 0x0027
|
||||
--- a/drivers/net/wireless/ath/ath9k/pci.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/pci.c
|
||||
@@ -658,6 +658,7 @@ static const struct pci_device_id ath_pc
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0036),
|
||||
@@ -664,6 +664,7 @@ static const struct pci_device_id ath_pc
|
||||
.driver_data = ATH9K_PCI_BT_ANT_DIV },
|
||||
#endif
|
||||
|
||||
+ { PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E internal chip default ID */
|
||||
{ 0 }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -323,8 +323,12 @@ int ath_reset_internal(struct ath_softc
|
||||
@@ -326,8 +326,12 @@ static int ath_reset_internal(struct ath
|
||||
sc->cur_chan->offchannel)
|
||||
ath9k_mci_set_txpower(sc, true, false);
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
|||
|
||||
out:
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
@@ -1453,6 +1457,7 @@ static int ath9k_config(struct ieee80211
|
||||
@@ -1470,6 +1474,7 @@ static int ath9k_config(struct ieee80211
|
||||
sc->cur_chan->txpower = 2 * conf->power_level;
|
||||
ath9k_cmn_update_txpow(ah, sc->curtxpow,
|
||||
sc->cur_chan->txpower, &sc->curtxpow);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -799,6 +799,9 @@ static inline int ath9k_dump_btcoex(stru
|
||||
@@ -811,6 +811,9 @@ static inline int ath9k_dump_btcoex(stru
|
||||
void ath_init_leds(struct ath_softc *sc);
|
||||
void ath_deinit_leds(struct ath_softc *sc);
|
||||
void ath_fill_led_pin(struct ath_softc *sc);
|
||||
|
@ -10,7 +10,7 @@
|
|||
#else
|
||||
static inline void ath_init_leds(struct ath_softc *sc)
|
||||
{
|
||||
@@ -939,6 +942,13 @@ void ath_ant_comb_scan(struct ath_softc
|
||||
@@ -951,6 +954,13 @@ void ath_ant_comb_scan(struct ath_softc
|
||||
|
||||
#define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
|||
struct ath_softc {
|
||||
struct ieee80211_hw *hw;
|
||||
struct device *dev;
|
||||
@@ -990,9 +1000,8 @@ struct ath_softc {
|
||||
@@ -1003,9 +1013,8 @@ struct ath_softc {
|
||||
spinlock_t chan_lock;
|
||||
|
||||
#ifdef CPTCFG_MAC80211_LEDS
|
||||
|
@ -162,7 +162,7 @@
|
|||
void ath_fill_led_pin(struct ath_softc *sc)
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -889,7 +889,7 @@ int ath9k_init_device(u16 devid, struct
|
||||
@@ -894,7 +894,7 @@ int ath9k_init_device(u16 devid, struct
|
||||
|
||||
#ifdef CPTCFG_MAC80211_LEDS
|
||||
/* must be initialized before ieee80211_register_hw */
|
||||
|
@ -173,7 +173,7 @@
|
|||
#endif
|
||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -1410,6 +1410,61 @@ static const struct file_operations fops
|
||||
@@ -1405,6 +1405,61 @@ static const struct file_operations fops
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
|
@ -235,7 +235,7 @@
|
|||
|
||||
int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
@@ -1434,6 +1489,10 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
@@ -1429,6 +1484,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);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/include/linux/ath9k_platform.h
|
||||
+++ b/include/linux/ath9k_platform.h
|
||||
@@ -39,6 +39,9 @@ struct ath9k_platform_data {
|
||||
@@ -41,6 +41,9 @@ struct ath9k_platform_data {
|
||||
int (*external_reset)(void);
|
||||
|
||||
bool use_eeprom;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -1466,6 +1466,50 @@ static const struct file_operations fops
|
||||
@@ -1461,6 +1461,50 @@ static const struct file_operations fops
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -51,7 +51,7 @@
|
|||
int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
@@ -1493,6 +1537,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
@@ -1488,6 +1532,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
debugfs_create_file("gpio_led", S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_gpio_led);
|
||||
#endif
|
||||
|
@ -62,7 +62,7 @@
|
|||
debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -483,6 +483,12 @@ enum {
|
||||
@@ -490,6 +490,12 @@ enum {
|
||||
ATH9K_RESET_COLD,
|
||||
};
|
||||
|
||||
|
@ -75,7 +75,7 @@
|
|||
struct ath9k_hw_version {
|
||||
u32 magic;
|
||||
u16 devid;
|
||||
@@ -764,6 +770,8 @@ struct ath_hw {
|
||||
@@ -769,6 +775,8 @@ struct ath_hw {
|
||||
u32 rfkill_polarity;
|
||||
u32 ah_flags;
|
||||
|
||||
|
@ -84,7 +84,7 @@
|
|||
bool reset_power_on;
|
||||
bool htc_reset_init;
|
||||
|
||||
@@ -1018,6 +1026,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
|
||||
@@ -1025,6 +1033,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
|
||||
bool ath9k_hw_check_alive(struct ath_hw *ah);
|
||||
|
||||
bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
|
||||
|
@ -115,7 +115,7 @@
|
|||
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
struct ath9k_hw_cal_data *caldata, bool fastcc)
|
||||
{
|
||||
@@ -1968,6 +1982,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
|
||||
@@ -1970,6 +1984,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
|
||||
ar9003_hw_disable_phy_restart(ah);
|
||||
|
||||
ath9k_hw_apply_gpio_override(ah);
|
||||
|
@ -125,7 +125,7 @@
|
|||
REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -531,6 +531,11 @@ irqreturn_t ath_isr(int irq, void *dev)
|
||||
@@ -535,6 +535,11 @@ irqreturn_t ath_isr(int irq, void *dev)
|
||||
ath9k_debug_sync_cause(sc, sync_cause);
|
||||
status &= ah->imask; /* discard unasked-for bits */
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -679,6 +679,7 @@ struct ath_spec_scan {
|
||||
@@ -686,6 +686,7 @@ struct ath_spec_scan {
|
||||
* @config_pci_powersave:
|
||||
* @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
|
||||
*
|
||||
|
@ -8,7 +8,7 @@
|
|||
* @spectral_scan_config: set parameters for spectral scan and enable/disable it
|
||||
* @spectral_scan_trigger: trigger a spectral scan run
|
||||
* @spectral_scan_wait: wait for a spectral scan run to finish
|
||||
@@ -703,6 +704,7 @@ struct ath_hw_ops {
|
||||
@@ -708,6 +709,7 @@ struct ath_hw_ops {
|
||||
struct ath_hw_antcomb_conf *antconf);
|
||||
void (*antdiv_comb_conf_set)(struct ath_hw *ah,
|
||||
struct ath_hw_antcomb_conf *antconf);
|
||||
|
@ -55,7 +55,7 @@
|
|||
ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -662,7 +662,8 @@ static void ath9k_init_txpower_limits(st
|
||||
@@ -665,7 +665,8 @@ static void ath9k_init_txpower_limits(st
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
|
||||
ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
|
||||
|
||||
|
@ -65,7 +65,7 @@
|
|||
}
|
||||
|
||||
static const struct ieee80211_iface_limit if_limits[] = {
|
||||
@@ -848,6 +849,18 @@ static void ath9k_set_hw_capab(struct at
|
||||
@@ -851,6 +852,18 @@ static void ath9k_set_hw_capab(struct at
|
||||
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@
|
|||
int ath9k_init_device(u16 devid, struct ath_softc *sc,
|
||||
const struct ath_bus_ops *bus_ops)
|
||||
{
|
||||
@@ -896,6 +909,8 @@ int ath9k_init_device(u16 devid, struct
|
||||
@@ -899,6 +912,8 @@ int ath9k_init_device(u16 devid, struct
|
||||
ARRAY_SIZE(ath9k_tpt_blink));
|
||||
#endif
|
||||
|
||||
|
@ -95,7 +95,7 @@
|
|||
if (error)
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
|
||||
@@ -101,6 +101,12 @@ static inline void ath9k_hw_tx99_set_txp
|
||||
@@ -100,6 +100,12 @@ static inline void ath9k_hw_tx99_set_txp
|
||||
ath9k_hw_ops(ah)->tx99_set_txpower(ah, power);
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1993,6 +2018,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
|
||||
@@ -1995,6 +2020,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
|
||||
ath9k_hw_set_radar_params(ah);
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -553,8 +553,7 @@ irqreturn_t ath_isr(int irq, void *dev)
|
||||
* If a FATAL or RXORN interrupt is received, we have to reset the
|
||||
* chip immediately.
|
||||
*/
|
||||
- if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) &&
|
||||
- !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)))
|
||||
+ if (status & ATH9K_INT_FATAL)
|
||||
goto chip_reset;
|
||||
|
||||
if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) &&
|
|
@ -1,6 +1,6 @@
|
|||
--- a/.local-symbols
|
||||
+++ b/.local-symbols
|
||||
@@ -284,6 +284,7 @@ RT2X00_LIB_FIRMWARE=
|
||||
@@ -285,6 +285,7 @@ RT2X00_LIB_FIRMWARE=
|
||||
RT2X00_LIB_CRYPTO=
|
||||
RT2X00_LIB_LEDS=
|
||||
RT2X00_LIB_DEBUGFS=
|
||||
|
|
Loading…
Reference in New Issue