2011-04-13 19:56:55

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 1/5] ath5k: disable 5 GHz support if a 2.4 GHz radio is detected

On a dual-radio dual-band AR5312 device, the calibration data is shared
between the 5 GHz and the 2.4 GHz radio/MAC.

Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath5k/caps.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c
index f77e8a7..7dd88e1 100644
--- a/drivers/net/wireless/ath/ath5k/caps.c
+++ b/drivers/net/wireless/ath/ath5k/caps.c
@@ -94,6 +94,9 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
}
}

+ if ((ah->ah_radio_5ghz_revision & 0xf0) == AR5K_SREV_RAD_2112)
+ __clear_bit(AR5K_MODE_11A, caps->cap_mode);
+
/* Set number of supported TX queues */
if (ah->ah_version == AR5K_AR5210)
caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU;
--
1.7.3.2



2011-04-14 11:19:40

by Sedat Dilek

[permalink] [raw]
Subject: Re: [PATCH 1/5] ath5k: disable 5 GHz support if a 2.4 GHz radio is detected

On Wed, Apr 13, 2011 at 9:56 PM, Felix Fietkau <[email protected]> wrote:
> On a dual-radio dual-band AR5312 device, the calibration data is shared
> between the 5 GHz and the 2.4 GHz radio/MAC.
>
> Signed-off-by: Felix Fietkau <[email protected]>
> ---

Tested all 5 patches against "freaky" linux-next (next-20110414).

Feel free to add:

Tested-by: Sedat Dilek <sedat.dilekłgmail.com>

- Sedat -

P.S.: Attach dmesg and lspci outputs

# dmesg | egrep -i 'ath|80211|wlan|crda'
[ 4.784132] cfg80211: Calling CRDA to update world regulatory domain
[ 5.004594] ath5k 0000:02:02.0: PCI INT A -> Link[LNKC] -> GSI 11
(level, low) -> IRQ 11
[ 5.004709] ath5k 0000:02:02.0: registered as 'phy0'
[ 5.294992] ath: EEPROM regdomain: 0x61
[ 5.294996] ath: EEPROM indicates we should expect a direct regpair map
[ 5.295002] ath: Country alpha2 being used: 00
[ 5.295004] ath: Regpair used: 0x61
[ 5.506881] ieee80211 phy0: Selected rate control algorithm 'minstrel_ht'
[ 5.507770] Registered led device: ath5k-phy0::rx
[ 5.507800] Registered led device: ath5k-phy0::tx
[ 5.507813] ath5k phy0: Atheros AR5212 chip found (MAC: 0x56, PHY: 0x41)
[ 5.507857] ath5k phy0: RF5111 5GHz radio found (0x17)
[ 5.507893] ath5k phy0: RF2111 2GHz radio found (0x23)
[ 8.297097] cfg80211: World regulatory domain updated:
[ 8.297149] cfg80211: (start_freq - end_freq @ bandwidth),
(max_antenna_gain, max_eirp)
[ 8.299903] cfg80211: (2402000 KHz - 2472000 KHz @ 40000 KHz),
(300 mBi, 2000 mBm)
[ 8.299950] cfg80211: (2457000 KHz - 2482000 KHz @ 20000 KHz),
(300 mBi, 2000 mBm)
[ 8.299997] cfg80211: (2474000 KHz - 2494000 KHz @ 20000 KHz),
(300 mBi, 2000 mBm)
[ 8.300057] cfg80211: (5170000 KHz - 5250000 KHz @ 40000 KHz),
(300 mBi, 2000 mBm)
[ 8.300104] cfg80211: (5735000 KHz - 5835000 KHz @ 40000 KHz),
(300 mBi, 2000 mBm)
[ 12.303413] ADDRCONF(NETDEV_UP): wlan0: link is not ready
[ 17.690110] wlan0: authenticate with 00:04:0e:e4:00:3d (try 1)
[ 17.691907] wlan0: authenticated
[ 17.691974] wlan0: associate with 00:04:0e:e4:00:3d (try 1)
[ 17.698281] wlan0: RX AssocResp from 00:04:0e:e4:00:3d (capab=0x411
status=0 aid=1)
[ 17.698293] wlan0: associated
[ 17.700380] ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
[ 28.424062] wlan0: no IPv6 routers present

# lspci -nnvv -s 02:02.0
02:02.0 Ethernet controller [0200]: Atheros Communications Inc. AR5212
802.11abg NIC [168c:1014] (rev 01)
Subsystem: Phillips Components Device [17ab:8331]
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV+ VGASnoop-
ParErr- Stepping- SERR+ FastB2B- DisINTx-
Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium
>TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 168 (2500ns min, 7000ns max), Cache Line Size: 32 bytes
Interrupt: pin A routed to IRQ 11
Region 0: Memory at c0210000 (32-bit, non-prefetchable) [size=64K]
Capabilities: [44] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA
PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=2 PME-
Kernel driver in use: ath5k

- EOT -

2011-04-13 19:56:55

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 2/5] ath: unshare struct ath_bus_ops between ath5k and ath9k

This struct is not used in any common code, and moving it out of
the ath header makes it easier to add more driver specific ops.

Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath.h | 9 +--------
drivers/net/wireless/ath/ath5k/ath5k.h | 6 ++++++
drivers/net/wireless/ath/ath9k/hw.h | 8 ++++++++
3 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index 6d7105b..7cf4317 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -123,14 +123,7 @@ struct ath_ops {
};

struct ath_common;
-
-struct ath_bus_ops {
- enum ath_bus_type ath_bus_type;
- void (*read_cachesize)(struct ath_common *common, int *csz);
- bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
- void (*bt_coex_prep)(struct ath_common *common);
- void (*extn_synch_en)(struct ath_common *common);
-};
+struct ath_bus_ops;

struct ath_common {
void *ah;
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index e303db7..266e548 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1155,6 +1155,12 @@ struct ath5k_hw {
struct ath5k_rx_status *);
};

+struct ath_bus_ops {
+ enum ath_bus_type ath_bus_type;
+ void (*read_cachesize)(struct ath_common *common, int *csz);
+ bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
+};
+
/*
* Prototypes
*/
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index a778b66..073bc9e 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -846,6 +846,14 @@ struct ath_hw {
u32 ent_mode;
};

+struct ath_bus_ops {
+ enum ath_bus_type ath_bus_type;
+ void (*read_cachesize)(struct ath_common *common, int *csz);
+ bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
+ void (*bt_coex_prep)(struct ath_common *common);
+ void (*extn_synch_en)(struct ath_common *common);
+};
+
static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
{
return &ah->common;
--
1.7.3.2


2011-04-13 19:56:55

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 3/5] ath5k: add a new bus op for reading the mac address

On AHB, the calibration data usually does not contain a valid MAC address,
the correct MAC address is stored in the board config.

Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath5k/ahb.c | 18 +++++++++++++++++
drivers/net/wireless/ath/ath5k/ath5k.h | 2 +-
drivers/net/wireless/ath/ath5k/base.c | 2 +-
drivers/net/wireless/ath/ath5k/eeprom.c | 29 ----------------------------
drivers/net/wireless/ath/ath5k/pci.c | 32 +++++++++++++++++++++++++++++++
5 files changed, 52 insertions(+), 31 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index 82324e9..1374e64 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -18,6 +18,7 @@

#include <linux/nl80211.h>
#include <linux/platform_device.h>
+#include <linux/etherdevice.h>
#include <ar231x_platform.h>
#include "ath5k.h"
#include "debug.h"
@@ -62,10 +63,27 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)
return 0;
}

+static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+{
+ struct ath5k_softc *sc = ah->ah_sc;
+ struct platform_device *pdev = to_platform_device(sc->dev);
+ struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+ u8 *cfg_mac;
+
+ if (to_platform_device(sc->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*/
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 266e548..bb50700 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1159,6 +1159,7 @@ struct ath_bus_ops {
enum ath_bus_type ath_bus_type;
void (*read_cachesize)(struct ath_common *common, int *csz);
bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
+ int (*eeprom_read_mac)(struct ath5k_hw *ah, u8 *mac);
};

/*
@@ -1244,7 +1245,6 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah);
/* EEPROM access functions */
int ath5k_eeprom_init(struct ath5k_hw *ah);
void ath5k_eeprom_detach(struct ath5k_hw *ah);
-int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);


/* Protocol Control Unit Functions */
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 16349d6..203243b 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2880,7 +2880,7 @@ ath5k_init(struct ieee80211_hw *hw)
INIT_WORK(&sc->reset_work, ath5k_reset_work);
INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work);

- ret = ath5k_eeprom_read_mac(ah, mac);
+ ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac);
if (ret) {
ATH5K_ERR(sc, "unable to read address from EEPROM\n");
goto err_queues;
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index 0aaaab2..1fef84f 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -1732,35 +1732,6 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah)
return ret;
}

-/*
- * Read the MAC address from eeprom
- */
-int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
-{
- u8 mac_d[ETH_ALEN] = {};
- u32 total, offset;
- u16 data;
- int octet;
-
- AR5K_EEPROM_READ(0x20, data);
-
- for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
- AR5K_EEPROM_READ(offset, data);
-
- total += data;
- mac_d[octet + 1] = data & 0xff;
- mac_d[octet] = data >> 8;
- octet += 2;
- }
-
- if (!total || total == 3 * 0xffff)
- return -EINVAL;
-
- memcpy(mac, mac_d, ETH_ALEN);
-
- return 0;
-}
-

/***********************\
* Init/Detach functions *
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
index 3c44689..296c316 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -17,6 +17,7 @@
#include <linux/nl80211.h>
#include <linux/pci.h>
#include <linux/pci-aspm.h>
+#include <linux/etherdevice.h>
#include "../ath.h"
#include "ath5k.h"
#include "debug.h"
@@ -108,11 +109,42 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)
return 0;
}

+/*
+ * Read the MAC address from eeprom or platform_data
+ */
+static int ath5k_pci_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+{
+ u8 mac_d[ETH_ALEN] = {};
+ u32 total, offset;
+ u16 data;
+ int octet;
+
+ AR5K_EEPROM_READ(0x20, data);
+
+ for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
+ AR5K_EEPROM_READ(offset, data);
+
+ total += data;
+ mac_d[octet + 1] = data & 0xff;
+ mac_d[octet] = data >> 8;
+ octet += 2;
+ }
+
+ if (!total || total == 3 * 0xffff)
+ return -EINVAL;
+
+ memcpy(mac, mac_d, ETH_ALEN);
+
+ return 0;
+}
+
+
/* Common ath_bus_opts structure */
static const struct ath_bus_ops ath_pci_bus_ops = {
.ath_bus_type = ATH_PCI,
.read_cachesize = ath5k_pci_read_cachesize,
.eeprom_read = ath5k_pci_eeprom_read,
+ .eeprom_read_mac = ath5k_pci_eeprom_read_mac,
};

/********************\
--
1.7.3.2


2011-04-13 19:56:55

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 4/5] ath5k: fix the EEPROM check for hw AES crypto support

EEPROM version 5.0 adds a new field for disabling AES support, having
an older version means that AES is present. This patch fixes hw AES
crypto support on AR5312 boards, which have an older EEPROM version.

Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath5k/attach.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index bc82405..326d7c8 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -318,7 +318,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)
AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);

if (srev >= AR5K_SREV_AR5212_V4 &&
- (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 &&
+ (ee->ee_version < AR5K_EEPROM_VERSION_5_0 ||
!AR5K_EEPROM_AES_DIS(ee->ee_misc5)))
common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;

--
1.7.3.2


2011-04-13 19:56:55

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH 5/5] ath5k: disable 5 GHz support for the dualband PHY chip on dual-radio AR5312

There are two variants of AR5312 dual-band devices, one single-radio
and the other one dual-radio. On the dual-radio board, the first MAC
only supports 5 GHz, even though it has a dual-band PHY. The 2.4 GHz
part of this phy is used in pass-through mode, connecting the second
MAC with the second PHY.
Disable 2.4 GHz for the first MAC on an AR5312, but only if the board
configuration indicates a dual-radio device.

Signed-off-by: Felix Fietkau <[email protected]>
---
drivers/net/wireless/ath/ath5k/ahb.c | 10 ++++++++++
drivers/net/wireless/ath/ath5k/attach.c | 5 +++++
drivers/net/wireless/ath/ath5k/base.h | 3 ++-
3 files changed, 17 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index 1374e64..ea99827 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -160,6 +160,16 @@ static int ath_ahb_probe(struct platform_device *pdev)
else
reg |= AR5K_AR5312_ENABLE_WLAN1;
__raw_writel(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(sc->dev)->id == 0 &&
+ (bcfg->config->flags & (BD_WLAN0|BD_WLAN1)) ==
+ (BD_WLAN1|BD_WLAN0))
+ __set_bit(ATH_STAT_2G_DISABLED, sc->status);
}

ret = ath5k_init_softc(sc, &ath_ahb_bus_ops);
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index 326d7c8..1588401 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -313,6 +313,11 @@ int ath5k_hw_init(struct ath5k_softc *sc)
goto err;
}

+ if (test_bit(ATH_STAT_2G_DISABLED, sc->status)) {
+ __clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode);
+ __clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode);
+ }
+
/* Crypto settings */
common->keymax = (sc->ah->ah_version == AR5K_AR5210 ?
AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index 4c4e360..b294f33 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -193,12 +193,13 @@ struct ath5k_softc {
dma_addr_t desc_daddr; /* DMA (physical) address */
size_t desc_len; /* size of TX/RX descriptors */

- DECLARE_BITMAP(status, 5);
+ DECLARE_BITMAP(status, 6);
#define ATH_STAT_INVALID 0 /* disable hardware accesses */
#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */
#define ATH_STAT_PROMISC 2
#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */
#define ATH_STAT_STARTED 4 /* opened & irqs enabled */
+#define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */

unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
struct ieee80211_channel *curchan; /* current h/w channel */
--
1.7.3.2