summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoshua Oreman2009-09-12 18:01:47 +0200
committerMarty Connor2009-10-17 02:22:41 +0200
commit489bd2f396e62e2ec1139da93e242017a7f6e9f5 (patch)
treed605bb0088dff3e1340fd6e129e3b410fe77c5db
parent[infiniband] Send CM requests to target node's GSI rather than SM's GSI (diff)
downloadipxe-489bd2f396e62e2ec1139da93e242017a7f6e9f5.tar.gz
ipxe-489bd2f396e62e2ec1139da93e242017a7f6e9f5.tar.xz
ipxe-489bd2f396e62e2ec1139da93e242017a7f6e9f5.zip
[ath5k] Update for changes in kernel 2.6.31
This adds basic rfkill support for enabling the wireless card on certain laptops, and changes miscellaneous other details that may help in obscure cases. Also change the error handling to not report CRC errors, which due to the basic facts of wireless may happen even more frequently than valid packets. Signed-off-by: Marty Connor <mdc@etherboot.org>
-rw-r--r--src/drivers/net/ath5k/ath5k.c9
-rw-r--r--src/drivers/net/ath5k/ath5k.h4
-rw-r--r--src/drivers/net/ath5k/ath5k_eeprom.c11
-rw-r--r--src/drivers/net/ath5k/ath5k_initvals.c4
-rw-r--r--src/drivers/net/ath5k/ath5k_pcu.c2
-rw-r--r--src/drivers/net/ath5k/ath5k_rfkill.c107
-rw-r--r--src/drivers/net/ath5k/base.h5
-rw-r--r--src/drivers/net/ath5k/eeprom.h10
8 files changed, 147 insertions, 5 deletions
diff --git a/src/drivers/net/ath5k/ath5k.c b/src/drivers/net/ath5k/ath5k.c
index 5101a54f..86ec7354 100644
--- a/src/drivers/net/ath5k/ath5k.c
+++ b/src/drivers/net/ath5k/ath5k.c
@@ -1195,11 +1195,12 @@ ath5k_handle_rx(struct ath5k_softc *sc)
if (rs.rs_status) {
if (rs.rs_status & AR5K_RXERR_PHY) {
- DBG("ath5k: rx PHY error\n");
+ /* These are uncommon, and may indicate a real problem. */
+ net80211_rx_err(sc->dev, NULL, EIO);
goto next;
}
if (rs.rs_status & AR5K_RXERR_CRC) {
- net80211_rx_err(sc->dev, NULL, EIO);
+ /* These occur *all the time*. */
goto next;
}
if (rs.rs_status & AR5K_RXERR_DECRYPT) {
@@ -1358,6 +1359,8 @@ ath5k_init(struct ath5k_softc *sc)
if (ret)
goto done;
+ ath5k_rfkill_hw_start(ah);
+
/*
* Reset the key cache since some parts do not reset the
* contents on initial power up or resume from suspend.
@@ -1405,6 +1408,8 @@ ath5k_stop_hw(struct ath5k_softc *sc)
} else
sc->rxlink = NULL;
+ ath5k_rfkill_hw_stop(sc->ah);
+
return 0;
}
diff --git a/src/drivers/net/ath5k/ath5k.h b/src/drivers/net/ath5k/ath5k.h
index c79fbec0..e54433d7 100644
--- a/src/drivers/net/ath5k/ath5k.h
+++ b/src/drivers/net/ath5k/ath5k.h
@@ -1153,6 +1153,10 @@ extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
+/* rfkill Functions */
+extern void ath5k_rfkill_hw_start(struct ath5k_hw *ah);
+extern void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
+
/* Misc functions */
int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
diff --git a/src/drivers/net/ath5k/ath5k_eeprom.c b/src/drivers/net/ath5k/ath5k_eeprom.c
index 592714dd..0f62c4c7 100644
--- a/src/drivers/net/ath5k/ath5k_eeprom.c
+++ b/src/drivers/net/ath5k/ath5k_eeprom.c
@@ -146,6 +146,17 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
}
+ AR5K_EEPROM_READ(AR5K_EEPROM_IS_HB63, val);
+
+ if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && val)
+ ee->ee_is_hb63 = 1;
+ else
+ ee->ee_is_hb63 = 0;
+
+ AR5K_EEPROM_READ(AR5K_EEPROM_RFKILL, val);
+ ee->ee_rfkill_pin = (u8) AR5K_REG_MS(val, AR5K_EEPROM_RFKILL_GPIO_SEL);
+ ee->ee_rfkill_pol = val & AR5K_EEPROM_RFKILL_POLARITY ? 1 : 0;
+
return 0;
}
diff --git a/src/drivers/net/ath5k/ath5k_initvals.c b/src/drivers/net/ath5k/ath5k_initvals.c
index 5911be89..92011c83 100644
--- a/src/drivers/net/ath5k/ath5k_initvals.c
+++ b/src/drivers/net/ath5k/ath5k_initvals.c
@@ -723,7 +723,7 @@ static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
{ AR5K_PHY_SETTLING,
{ 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } },
{ AR5K_PHY_AGCCTL,
- { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } },
+ { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } },
{ AR5K_PHY_NF,
{ 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
{ AR5K_PHY_WEAK_OFDM_HIGH_THR,
@@ -804,7 +804,7 @@ static const struct ath5k_ini_mode rf5112_ini_mode_end[] = {
{ AR5K_PHY_DESIRED_SIZE,
{ 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
{ AR5K_PHY_SIG,
- { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } },
+ { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } },
{ AR5K_PHY_AGCCOARSE,
{ 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } },
{ AR5K_PHY_WEAK_OFDM_LOW_THR,
diff --git a/src/drivers/net/ath5k/ath5k_pcu.c b/src/drivers/net/ath5k/ath5k_pcu.c
index 1e90a94e..d3e144c4 100644
--- a/src/drivers/net/ath5k/ath5k_pcu.c
+++ b/src/drivers/net/ath5k/ath5k_pcu.c
@@ -520,7 +520,7 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
* Note2: Windows driver (ndiswrapper) sets this to
* 0x00000714 instead of 0x00000007
*/
- if (ah->ah_version > AR5K_AR5211) {
+ if (ah->ah_version >= AR5K_AR5211) {
ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
AR5K_KEYTABLE_TYPE(entry));
diff --git a/src/drivers/net/ath5k/ath5k_rfkill.c b/src/drivers/net/ath5k/ath5k_rfkill.c
new file mode 100644
index 00000000..9d0a2ff1
--- /dev/null
+++ b/src/drivers/net/ath5k/ath5k_rfkill.c
@@ -0,0 +1,107 @@
+/*
+ * RFKILL support for ath5k
+ *
+ * Copyright (c) 2009 Tobias Doerffel <tobias.doerffel@gmail.com>
+ * Lightly modified for gPXE, Sep 2008 by Joshua Oreman <oremanj@rwcr.net>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+FILE_LICENCE ( MIT );
+
+#include "base.h"
+
+
+static inline void ath5k_rfkill_disable(struct ath5k_softc *sc)
+{
+ DBG("ath5k: rfkill disable (gpio:%d polarity:%d)\n",
+ sc->rf_kill.gpio, sc->rf_kill.polarity);
+ ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
+ ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, !sc->rf_kill.polarity);
+}
+
+
+static inline void ath5k_rfkill_enable(struct ath5k_softc *sc)
+{
+ DBG("ath5k: rfkill enable (gpio:%d polarity:%d)\n",
+ sc->rf_kill.gpio, sc->rf_kill.polarity);
+ ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio);
+ ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, sc->rf_kill.polarity);
+}
+
+static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, int enable)
+{
+ struct ath5k_hw *ah = sc->ah;
+ u32 curval;
+
+ ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio);
+ curval = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio);
+ ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ?
+ !!curval : !curval);
+}
+
+static int __unused
+ath5k_is_rfkill_set(struct ath5k_softc *sc)
+{
+ /* configuring GPIO for input for some reason disables rfkill */
+ /*ath5k_hw_set_gpio_input(sc->ah, sc->rf_kill.gpio);*/
+ return (ath5k_hw_get_gpio(sc->ah, sc->rf_kill.gpio) ==
+ sc->rf_kill.polarity);
+}
+
+void
+ath5k_rfkill_hw_start(struct ath5k_hw *ah)
+{
+ struct ath5k_softc *sc = ah->ah_sc;
+
+ /* read rfkill GPIO configuration from EEPROM header */
+ sc->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;
+ sc->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;
+
+ ath5k_rfkill_disable(sc);
+
+ /* enable interrupt for rfkill switch */
+ if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
+ ath5k_rfkill_set_intr(sc, 1);
+}
+
+
+void
+ath5k_rfkill_hw_stop(struct ath5k_hw *ah)
+{
+ struct ath5k_softc *sc = ah->ah_sc;
+
+ /* disable interrupt for rfkill switch */
+ if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header))
+ ath5k_rfkill_set_intr(sc, 0);
+
+ /* enable RFKILL when stopping HW so Wifi LED is turned off */
+ ath5k_rfkill_enable(sc);
+}
diff --git a/src/drivers/net/ath5k/base.h b/src/drivers/net/ath5k/base.h
index 45dad073..870b0ed4 100644
--- a/src/drivers/net/ath5k/base.h
+++ b/src/drivers/net/ath5k/base.h
@@ -123,6 +123,11 @@ struct ath5k_softc {
unsigned int txbuf_len; /* buf count in txbuf list */
struct ath5k_txq txq; /* tx queue */
+ struct {
+ u16 gpio;
+ unsigned polarity;
+ } rf_kill;
+
int last_calib_ticks;
int power_level; /* Requested tx power in dbm */
diff --git a/src/drivers/net/ath5k/eeprom.h b/src/drivers/net/ath5k/eeprom.h
index 4d6250af..da454339 100644
--- a/src/drivers/net/ath5k/eeprom.h
+++ b/src/drivers/net/ath5k/eeprom.h
@@ -26,6 +26,13 @@
#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */
#define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */
+
+#define AR5K_EEPROM_RFKILL 0x0f
+#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
+#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
+#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
+#define AR5K_EEPROM_RFKILL_POLARITY_S 1
+
#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
@@ -369,6 +376,9 @@ struct ath5k_eeprom_info {
u16 ee_version;
u16 ee_header;
u16 ee_ant_gain;
+ u8 ee_rfkill_pin;
+ int ee_rfkill_pol;
+ int ee_is_hb63;
u16 ee_misc0;
u16 ee_misc1;
u16 ee_misc2;