提交 b7f1d43a 编写于 作者: D David S. Miller
...@@ -2653,25 +2653,21 @@ F: drivers/net/ixgbe/ ...@@ -2653,25 +2653,21 @@ F: drivers/net/ixgbe/
INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
M: Zhu Yi <yi.zhu@intel.com> M: Zhu Yi <yi.zhu@intel.com>
M: James Ketrenos <jketreno@linux.intel.com>
M: Reinette Chatre <reinette.chatre@intel.com> M: Reinette Chatre <reinette.chatre@intel.com>
M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org
L: ipw2100-devel@lists.sourceforge.net
W: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
W: http://ipw2100.sourceforge.net W: http://ipw2100.sourceforge.net
S: Supported S: Odd Fixes
F: Documentation/networking/README.ipw2100 F: Documentation/networking/README.ipw2100
F: drivers/net/wireless/ipw2x00/ipw2100.* F: drivers/net/wireless/ipw2x00/ipw2100.*
INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
M: Zhu Yi <yi.zhu@intel.com> M: Zhu Yi <yi.zhu@intel.com>
M: James Ketrenos <jketreno@linux.intel.com>
M: Reinette Chatre <reinette.chatre@intel.com> M: Reinette Chatre <reinette.chatre@intel.com>
M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org
L: ipw2100-devel@lists.sourceforge.net
W: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
W: http://ipw2200.sourceforge.net W: http://ipw2200.sourceforge.net
S: Supported S: Odd Fixes
F: Documentation/networking/README.ipw2200 F: Documentation/networking/README.ipw2200
F: drivers/net/wireless/ipw2x00/ipw2200.* F: drivers/net/wireless/ipw2x00/ipw2200.*
...@@ -2688,8 +2684,8 @@ F: include/linux/wimax/i2400m.h ...@@ -2688,8 +2684,8 @@ F: include/linux/wimax/i2400m.h
INTEL WIRELESS WIFI LINK (iwlwifi) INTEL WIRELESS WIFI LINK (iwlwifi)
M: Zhu Yi <yi.zhu@intel.com> M: Zhu Yi <yi.zhu@intel.com>
M: Reinette Chatre <reinette.chatre@intel.com> M: Reinette Chatre <reinette.chatre@intel.com>
M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org
L: ipw3945-devel@lists.sourceforge.net
W: http://intellinuxwireless.org W: http://intellinuxwireless.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git
S: Supported S: Supported
......
...@@ -178,6 +178,7 @@ struct ar9170 { ...@@ -178,6 +178,7 @@ struct ar9170 {
/* beaconing */ /* beaconing */
struct sk_buff *beacon; struct sk_buff *beacon;
struct work_struct beacon_work; struct work_struct beacon_work;
bool enable_beacon;
/* cryptographic engine */ /* cryptographic engine */
u64 usedkeys; u64 usedkeys;
......
...@@ -383,24 +383,26 @@ int ar9170_set_beacon_timers(struct ar9170 *ar) ...@@ -383,24 +383,26 @@ int ar9170_set_beacon_timers(struct ar9170 *ar)
if (ar->vif) { if (ar->vif) {
v |= ar->vif->bss_conf.beacon_int; v |= ar->vif->bss_conf.beacon_int;
switch (ar->vif->type) { if (ar->enable_beacon) {
case NL80211_IFTYPE_MESH_POINT: switch (ar->vif->type) {
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT:
v |= BIT(25); case NL80211_IFTYPE_ADHOC:
break; v |= BIT(25);
case NL80211_IFTYPE_AP: break;
v |= BIT(24); case NL80211_IFTYPE_AP:
pretbtt = (ar->vif->bss_conf.beacon_int - 6) << 16; v |= BIT(24);
break; pretbtt = (ar->vif->bss_conf.beacon_int - 6) <<
default: 16;
break;
default:
break; break;
}
} }
v |= ar->vif->bss_conf.dtim_period << 16; v |= ar->vif->bss_conf.dtim_period << 16;
} }
ar9170_regwrite_begin(ar); ar9170_regwrite_begin(ar);
ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt); ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt);
ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v); ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v);
ar9170_regwrite_finish(); ar9170_regwrite_finish();
......
...@@ -2031,12 +2031,6 @@ static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) ...@@ -2031,12 +2031,6 @@ static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed)
goto out; goto out;
} }
if (changed & BSS_CHANGED_BEACON_INT) {
err = ar9170_set_beacon_timers(ar);
if (err)
goto out;
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
/* adjust slot time for 5 GHz */ /* adjust slot time for 5 GHz */
...@@ -2148,11 +2142,17 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, ...@@ -2148,11 +2142,17 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
goto out; goto out;
} }
if (changed & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) { if (changed & BSS_CHANGED_BEACON_ENABLED)
ar->enable_beacon = bss_conf->enable_beacon;
if (changed & BSS_CHANGED_BEACON) {
err = ar9170_update_beacon(ar); err = ar9170_update_beacon(ar);
if (err) if (err)
goto out; goto out;
}
if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_INT)) {
err = ar9170_set_beacon_timers(ar); err = ar9170_set_beacon_timers(ar);
if (err) if (err)
goto out; goto out;
...@@ -2165,12 +2165,6 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, ...@@ -2165,12 +2165,6 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
#endif /* CONFIG_AR9170_LEDS */ #endif /* CONFIG_AR9170_LEDS */
} }
if (changed & BSS_CHANGED_BEACON_INT) {
err = ar9170_set_beacon_timers(ar);
if (err)
goto out;
}
if (changed & BSS_CHANGED_HT) { if (changed & BSS_CHANGED_HT) {
/* TODO */ /* TODO */
err = 0; err = 0;
......
...@@ -306,6 +306,7 @@ struct ath5k_srev_name { ...@@ -306,6 +306,7 @@ struct ath5k_srev_name {
#define AR5K_SREV_AR5311B 0x30 /* Spirit */ #define AR5K_SREV_AR5311B 0x30 /* Spirit */
#define AR5K_SREV_AR5211 0x40 /* Oahu */ #define AR5K_SREV_AR5211 0x40 /* Oahu */
#define AR5K_SREV_AR5212 0x50 /* Venice */ #define AR5K_SREV_AR5212 0x50 /* Venice */
#define AR5K_SREV_AR5212_V4 0x54 /* ??? */
#define AR5K_SREV_AR5213 0x55 /* ??? */ #define AR5K_SREV_AR5213 0x55 /* ??? */
#define AR5K_SREV_AR5213A 0x59 /* Hainan */ #define AR5K_SREV_AR5213A 0x59 /* Hainan */
#define AR5K_SREV_AR2413 0x78 /* Griffin lite */ #define AR5K_SREV_AR2413 0x78 /* Griffin lite */
...@@ -1037,6 +1038,7 @@ struct ath5k_hw { ...@@ -1037,6 +1038,7 @@ struct ath5k_hw {
bool ah_turbo; bool ah_turbo;
bool ah_calibration; bool ah_calibration;
bool ah_single_chip; bool ah_single_chip;
bool ah_aes_support;
bool ah_combined_mic; bool ah_combined_mic;
enum ath5k_version ah_version; enum ath5k_version ah_version;
...@@ -1158,7 +1160,7 @@ struct ath5k_hw { ...@@ -1158,7 +1160,7 @@ struct ath5k_hw {
*/ */
/* Attach/Detach Functions */ /* Attach/Detach Functions */
extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version); extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc);
extern void ath5k_hw_detach(struct ath5k_hw *ah); extern void ath5k_hw_detach(struct ath5k_hw *ah);
/* LED functions */ /* LED functions */
......
...@@ -95,17 +95,17 @@ static int ath5k_hw_post(struct ath5k_hw *ah) ...@@ -95,17 +95,17 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
* ath5k_hw_attach - Check if hw is supported and init the needed structs * ath5k_hw_attach - Check if hw is supported and init the needed structs
* *
* @sc: The &struct ath5k_softc we got from the driver's attach function * @sc: The &struct ath5k_softc we got from the driver's attach function
* @mac_version: The mac version id (check out ath5k.h) based on pci id
* *
* Check if the device is supported, perform a POST and initialize the needed * Check if the device is supported, perform a POST and initialize the needed
* structs. Returns -ENOMEM if we don't have memory for the needed structs, * structs. Returns -ENOMEM if we don't have memory for the needed structs,
* -ENODEV if the device is not supported or prints an error msg if something * -ENODEV if the device is not supported or prints an error msg if something
* else went wrong. * else went wrong.
*/ */
struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc)
{ {
struct ath5k_hw *ah; struct ath5k_hw *ah;
struct pci_dev *pdev = sc->pdev; struct pci_dev *pdev = sc->pdev;
struct ath5k_eeprom_info *ee;
int ret; int ret;
u32 srev; u32 srev;
...@@ -135,9 +135,15 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ...@@ -135,9 +135,15 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
ah->ah_software_retry = false; ah->ah_software_retry = false;
/* /*
* Set the mac version based on the pci id * Find the mac version
*/ */
ah->ah_version = mac_version; srev = ath5k_hw_reg_read(ah, AR5K_SREV);
if (srev < AR5K_SREV_AR5311)
ah->ah_version = AR5K_AR5210;
else if (srev < AR5K_SREV_AR5212)
ah->ah_version = AR5K_AR5211;
else
ah->ah_version = AR5K_AR5212;
/*Fill the ath5k_hw struct with the needed functions*/ /*Fill the ath5k_hw struct with the needed functions*/
ret = ath5k_hw_init_desc_functions(ah); ret = ath5k_hw_init_desc_functions(ah);
...@@ -150,7 +156,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ...@@ -150,7 +156,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
goto err_free; goto err_free;
/* Get MAC, PHY and RADIO revisions */ /* Get MAC, PHY and RADIO revisions */
srev = ath5k_hw_reg_read(ah, AR5K_SREV);
ah->ah_mac_srev = srev; ah->ah_mac_srev = srev;
ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV); ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
...@@ -315,6 +320,12 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ...@@ -315,6 +320,12 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
goto err_free; goto err_free;
} }
/* Crypto settings */
ee = &ah->ah_capabilities.cap_eeprom;
ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 &&
(ee->ee_version >= AR5K_EEPROM_VERSION_5_0 &&
!AR5K_EEPROM_AES_DIS(ee->ee_misc5));
if (srev >= AR5K_SREV_AR2414) { if (srev >= AR5K_SREV_AR2414) {
ah->ah_combined_mic = true; ah->ah_combined_mic = true;
AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE, AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE,
......
...@@ -84,24 +84,24 @@ MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); ...@@ -84,24 +84,24 @@ MODULE_VERSION("0.6.0 (EXPERIMENTAL)");
/* Known PCI ids */ /* Known PCI ids */
static const struct pci_device_id ath5k_pci_id_table[] = { static const struct pci_device_id ath5k_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */ { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */
{ PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */ { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */
{ PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/ { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/
{ PCI_VDEVICE(ATHEROS, 0x0012), .driver_data = AR5K_AR5211 }, /* 5211 */ { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */
{ PCI_VDEVICE(ATHEROS, 0x0013), .driver_data = AR5K_AR5212 }, /* 5212 */ { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */
{ PCI_VDEVICE(3COM_2, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 5212 */ { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */
{ PCI_VDEVICE(3COM, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 3CRDAG675 5212 */ { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */
{ PCI_VDEVICE(ATHEROS, 0x1014), .driver_data = AR5K_AR5212 }, /* IBM minipci 5212 */ { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */
{ PCI_VDEVICE(ATHEROS, 0x0014), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */
{ PCI_VDEVICE(ATHEROS, 0x0015), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */
{ PCI_VDEVICE(ATHEROS, 0x0016), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */
{ PCI_VDEVICE(ATHEROS, 0x0017), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */
{ PCI_VDEVICE(ATHEROS, 0x0018), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */
{ PCI_VDEVICE(ATHEROS, 0x0019), .driver_data = AR5K_AR5212 }, /* 5212 combatible */ { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */
{ PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */ { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */
{ PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */ { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
{ PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* PCI-E cards */ { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
{ PCI_VDEVICE(ATHEROS, 0x001d), .driver_data = AR5K_AR5212 }, /* 2417 Nala */ { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
{ 0 } { 0 }
}; };
MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
...@@ -566,7 +566,7 @@ ath5k_pci_probe(struct pci_dev *pdev, ...@@ -566,7 +566,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
} }
/* Initialize device */ /* Initialize device */
sc->ah = ath5k_hw_attach(sc, id->driver_data); sc->ah = ath5k_hw_attach(sc);
if (IS_ERR(sc->ah)) { if (IS_ERR(sc->ah)) {
ret = PTR_ERR(sc->ah); ret = PTR_ERR(sc->ah);
goto err_irq; goto err_irq;
...@@ -1741,7 +1741,7 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, ...@@ -1741,7 +1741,7 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
static void static void
ath5k_tasklet_rx(unsigned long data) ath5k_tasklet_rx(unsigned long data)
{ {
struct ieee80211_rx_status rxs = {}; struct ieee80211_rx_status *rxs;
struct ath5k_rx_status rs = {}; struct ath5k_rx_status rs = {};
struct sk_buff *skb, *next_skb; struct sk_buff *skb, *next_skb;
dma_addr_t next_skb_addr; dma_addr_t next_skb_addr;
...@@ -1751,6 +1751,7 @@ ath5k_tasklet_rx(unsigned long data) ...@@ -1751,6 +1751,7 @@ ath5k_tasklet_rx(unsigned long data)
int ret; int ret;
int hdrlen; int hdrlen;
int padsize; int padsize;
int rx_flag;
spin_lock(&sc->rxbuflock); spin_lock(&sc->rxbuflock);
if (list_empty(&sc->rxbuf)) { if (list_empty(&sc->rxbuf)) {
...@@ -1758,7 +1759,7 @@ ath5k_tasklet_rx(unsigned long data) ...@@ -1758,7 +1759,7 @@ ath5k_tasklet_rx(unsigned long data)
goto unlock; goto unlock;
} }
do { do {
rxs.flag = 0; rx_flag = 0;
bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
BUG_ON(bf->skb == NULL); BUG_ON(bf->skb == NULL);
...@@ -1802,7 +1803,7 @@ ath5k_tasklet_rx(unsigned long data) ...@@ -1802,7 +1803,7 @@ ath5k_tasklet_rx(unsigned long data)
goto accept; goto accept;
} }
if (rs.rs_status & AR5K_RXERR_MIC) { if (rs.rs_status & AR5K_RXERR_MIC) {
rxs.flag |= RX_FLAG_MMIC_ERROR; rx_flag |= RX_FLAG_MMIC_ERROR;
goto accept; goto accept;
} }
...@@ -1840,6 +1841,7 @@ ath5k_tasklet_rx(unsigned long data) ...@@ -1840,6 +1841,7 @@ ath5k_tasklet_rx(unsigned long data)
memmove(skb->data + padsize, skb->data, hdrlen); memmove(skb->data + padsize, skb->data, hdrlen);
skb_pull(skb, padsize); skb_pull(skb, padsize);
} }
rxs = IEEE80211_SKB_RXCB(skb);
/* /*
* always extend the mac timestamp, since this information is * always extend the mac timestamp, since this information is
...@@ -1861,41 +1863,40 @@ ath5k_tasklet_rx(unsigned long data) ...@@ -1861,41 +1863,40 @@ ath5k_tasklet_rx(unsigned long data)
* impossible to comply to that. This affects IBSS merge only * impossible to comply to that. This affects IBSS merge only
* right now, so it's not too bad... * right now, so it's not too bad...
*/ */
rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp); rxs->mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp);
rxs.flag |= RX_FLAG_TSFT; rxs->flag = rx_flag | RX_FLAG_TSFT;
rxs.freq = sc->curchan->center_freq; rxs->freq = sc->curchan->center_freq;
rxs.band = sc->curband->band; rxs->band = sc->curband->band;
rxs.noise = sc->ah->ah_noise_floor; rxs->noise = sc->ah->ah_noise_floor;
rxs.signal = rxs.noise + rs.rs_rssi; rxs->signal = rxs->noise + rs.rs_rssi;
/* An rssi of 35 indicates you should be able use /* An rssi of 35 indicates you should be able use
* 54 Mbps reliably. A more elaborate scheme can be used * 54 Mbps reliably. A more elaborate scheme can be used
* here but it requires a map of SNR/throughput for each * here but it requires a map of SNR/throughput for each
* possible mode used */ * possible mode used */
rxs.qual = rs.rs_rssi * 100 / 35; rxs->qual = rs.rs_rssi * 100 / 35;
/* rssi can be more than 35 though, anything above that /* rssi can be more than 35 though, anything above that
* should be considered at 100% */ * should be considered at 100% */
if (rxs.qual > 100) if (rxs->qual > 100)
rxs.qual = 100; rxs->qual = 100;
rxs.antenna = rs.rs_antenna; rxs->antenna = rs.rs_antenna;
rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
if (rxs.rate_idx >= 0 && rs.rs_rate == if (rxs->rate_idx >= 0 && rs.rs_rate ==
sc->curband->bitrates[rxs.rate_idx].hw_value_short) sc->curband->bitrates[rxs->rate_idx].hw_value_short)
rxs.flag |= RX_FLAG_SHORTPRE; rxs->flag |= RX_FLAG_SHORTPRE;
ath5k_debug_dump_skb(sc, skb, "RX ", 0); ath5k_debug_dump_skb(sc, skb, "RX ", 0);
/* check beacons in IBSS mode */ /* check beacons in IBSS mode */
if (sc->opmode == NL80211_IFTYPE_ADHOC) if (sc->opmode == NL80211_IFTYPE_ADHOC)
ath5k_check_ibss_tsf(sc, skb, &rxs); ath5k_check_ibss_tsf(sc, skb, rxs);
memcpy(IEEE80211_SKB_RXCB(skb), &rxs, sizeof(rxs));
ieee80211_rx(sc->hw, skb); ieee80211_rx(sc->hw, skb);
bf->skb = next_skb; bf->skb = next_skb;
...@@ -2918,6 +2919,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, ...@@ -2918,6 +2919,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
struct ath5k_hw *ah = sc->ah; struct ath5k_hw *ah = sc->ah;
u32 mfilt[2], rfilt; u32 mfilt[2], rfilt;
mutex_lock(&sc->lock);
mfilt[0] = multicast; mfilt[0] = multicast;
mfilt[1] = multicast >> 32; mfilt[1] = multicast >> 32;
...@@ -2968,22 +2971,25 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, ...@@ -2968,22 +2971,25 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
/* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */ /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
if (sc->opmode == NL80211_IFTYPE_MONITOR) switch (sc->opmode) {
rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | case NL80211_IFTYPE_MESH_POINT:
AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM; case NL80211_IFTYPE_MONITOR:
if (sc->opmode != NL80211_IFTYPE_STATION) rfilt |= AR5K_RX_FILTER_CONTROL |
rfilt |= AR5K_RX_FILTER_PROBEREQ; AR5K_RX_FILTER_BEACON |
if (sc->opmode != NL80211_IFTYPE_AP && AR5K_RX_FILTER_PROBEREQ |
sc->opmode != NL80211_IFTYPE_MESH_POINT && AR5K_RX_FILTER_PROM;
test_bit(ATH_STAT_PROMISC, sc->status)) break;
rfilt |= AR5K_RX_FILTER_PROM; case NL80211_IFTYPE_AP:
if ((sc->opmode == NL80211_IFTYPE_STATION && sc->assoc) || case NL80211_IFTYPE_ADHOC:
sc->opmode == NL80211_IFTYPE_ADHOC || rfilt |= AR5K_RX_FILTER_PROBEREQ |
sc->opmode == NL80211_IFTYPE_AP) AR5K_RX_FILTER_BEACON;
rfilt |= AR5K_RX_FILTER_BEACON; break;
if (sc->opmode == NL80211_IFTYPE_MESH_POINT) case NL80211_IFTYPE_STATION:
rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | if (sc->assoc)
AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM; rfilt |= AR5K_RX_FILTER_BEACON;
default:
break;
}
/* Set filters */ /* Set filters */
ath5k_hw_set_rx_filter(ah, rfilt); ath5k_hw_set_rx_filter(ah, rfilt);
...@@ -2993,6 +2999,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, ...@@ -2993,6 +2999,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
/* Set the cached hw filter flags, this will alter actually /* Set the cached hw filter flags, this will alter actually
* be set in HW */ * be set in HW */
sc->filter_flags = rfilt; sc->filter_flags = rfilt;
mutex_unlock(&sc->lock);
} }
static int static int
...@@ -3014,6 +3022,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ...@@ -3014,6 +3022,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
case ALG_TKIP: case ALG_TKIP:
break; break;
case ALG_CCMP: case ALG_CCMP:
if (sc->ah->ah_aes_support)
break;
return -EOPNOTSUPP; return -EOPNOTSUPP;
default: default:
WARN_ON(1); WARN_ON(1);
......
...@@ -414,27 +414,11 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, ...@@ -414,27 +414,11 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
break; break;
} }
done: /*
/* return new offset */ * Read turbo mode information on newer EEPROM versions
*offset = o; */
return 0;
}
/*
* Read turbo mode information on newer EEPROM versions
*/
static int
ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah,
u32 *offset, unsigned int mode)
{
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
u32 o = *offset;
u16 val;
int ret;
if (ee->ee_version < AR5K_EEPROM_VERSION_5_0) if (ee->ee_version < AR5K_EEPROM_VERSION_5_0)
return 0; goto done;
switch (mode){ switch (mode){
case AR5K_EEPROM_MODE_11A: case AR5K_EEPROM_MODE_11A:
...@@ -468,6 +452,7 @@ ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah, ...@@ -468,6 +452,7 @@ ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah,
break; break;
} }
done:
/* return new offset */ /* return new offset */
*offset = o; *offset = o;
...@@ -504,10 +489,6 @@ ath5k_eeprom_init_modes(struct ath5k_hw *ah) ...@@ -504,10 +489,6 @@ ath5k_eeprom_init_modes(struct ath5k_hw *ah)
ret = ath5k_eeprom_read_modes(ah, &offset, mode); ret = ath5k_eeprom_read_modes(ah, &offset, mode);
if (ret) if (ret)
return ret; return ret;
ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode);
if (ret)
return ret;
} }
/* override for older eeprom versions for better performance */ /* override for older eeprom versions for better performance */
......
...@@ -69,6 +69,8 @@ static const struct pci_device_id ath5k_led_devices[] = { ...@@ -69,6 +69,8 @@ static const struct pci_device_id ath5k_led_devices[] = {
{ ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) }, { ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) },
/* IBM ThinkPad AR5BXB6 (legovini@spiro.fisica.unipd.it) */ /* IBM ThinkPad AR5BXB6 (legovini@spiro.fisica.unipd.it) */
{ ATH_SDEVICE(PCI_VENDOR_ID_IBM, 0x058a), ATH_LED(1, 0) }, { ATH_SDEVICE(PCI_VENDOR_ID_IBM, 0x058a), ATH_LED(1, 0) },
/* HP Compaq C700 (nitrousnrg@gmail.com) */
{ ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) },
/* IBM-specific AR5212 (all others) */ /* IBM-specific AR5212 (all others) */
{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) },
{ } { }
......
...@@ -12,7 +12,8 @@ ath9k-y += hw.o \ ...@@ -12,7 +12,8 @@ ath9k-y += hw.o \
recv.o \ recv.o \
xmit.o \ xmit.o \
virtual.o \ virtual.o \
rc.o rc.o \
btcoex.o
ath9k-$(CONFIG_PCI) += pci.o ath9k-$(CONFIG_PCI) += pci.o
ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "rc.h" #include "rc.h"
#include "debug.h" #include "debug.h"
#include "../ath.h" #include "../ath.h"
#include "btcoex.h"
struct ath_node; struct ath_node;
...@@ -521,6 +522,8 @@ struct ath_led { ...@@ -521,6 +522,8 @@ struct ath_led {
#define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17) #define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17)
#define SC_OP_WAIT_FOR_TX_ACK BIT(18) #define SC_OP_WAIT_FOR_TX_ACK BIT(18)
#define SC_OP_BEACON_SYNC BIT(19) #define SC_OP_BEACON_SYNC BIT(19)
#define SC_OP_BTCOEX_ENABLED BIT(20)
#define SC_OP_BT_PRIORITY_DETECTED BIT(21)
struct ath_bus_ops { struct ath_bus_ops {
void (*read_cachesize)(struct ath_softc *sc, int *csz); void (*read_cachesize)(struct ath_softc *sc, int *csz);
...@@ -609,6 +612,7 @@ struct ath_softc { ...@@ -609,6 +612,7 @@ struct ath_softc {
struct ath_bus_ops *bus_ops; struct ath_bus_ops *bus_ops;
struct ath_beacon_config cur_beacon_conf; struct ath_beacon_config cur_beacon_conf;
struct delayed_work tx_complete_work; struct delayed_work tx_complete_work;
struct ath_btcoex_info btcoex_info;
}; };
struct ath_wiphy { struct ath_wiphy {
...@@ -705,4 +709,5 @@ bool ath9k_all_wiphys_idle(struct ath_softc *sc); ...@@ -705,4 +709,5 @@ bool ath9k_all_wiphys_idle(struct ath_softc *sc);
void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val); void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val);
unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset); unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset);
int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype);
#endif /* ATH9K_H */ #endif /* ATH9K_H */
/*
* Copyright (c) 2009 Atheros Communications Inc.
*
* 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 "ath9k.h"
static const struct ath_btcoex_config ath_bt_config = { 0, true, true,
ATH_BT_COEX_MODE_SLOTTED, true, true, 2, 5, true };
/*
* Detects if there is any priority bt traffic
*/
static void ath_detect_bt_priority(struct ath_softc *sc)
{
struct ath_btcoex_info *btinfo = &sc->btcoex_info;
if (ath9k_hw_gpio_get(sc->sc_ah, btinfo->btpriority_gpio))
btinfo->bt_priority_cnt++;
if (time_after(jiffies, btinfo->bt_priority_time +
msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
if (btinfo->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
DPRINTF(sc, ATH_DBG_BTCOEX,
"BT priority traffic detected");
sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
} else {
sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
}
btinfo->bt_priority_cnt = 0;
btinfo->bt_priority_time = jiffies;
}
}
/*
* Configures appropriate weight based on stomp type.
*/
static void ath_btcoex_bt_stomp(struct ath_softc *sc,
struct ath_btcoex_info *btinfo,
int stomp_type)
{
switch (stomp_type) {
case ATH_BTCOEX_STOMP_ALL:
ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
AR_STOMP_ALL_WLAN_WGHT);
break;
case ATH_BTCOEX_STOMP_LOW:
ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
AR_STOMP_LOW_WLAN_WGHT);
break;
case ATH_BTCOEX_STOMP_NONE:
ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
AR_STOMP_NONE_WLAN_WGHT);
break;
default:
DPRINTF(sc, ATH_DBG_BTCOEX, "Invalid Stomptype\n");
break;
}
ath9k_hw_btcoex_enable(sc->sc_ah);
}
/*
* This is the master bt coex timer which runs for every
* 45ms, bt traffic will be given priority during 55% of this
* period while wlan gets remaining 45%
*/
static void ath_btcoex_period_timer(unsigned long data)
{
struct ath_softc *sc = (struct ath_softc *) data;
struct ath_btcoex_info *btinfo = &sc->btcoex_info;
unsigned long flags;
ath_detect_bt_priority(sc);
spin_lock_irqsave(&btinfo->btcoex_lock, flags);
ath_btcoex_bt_stomp(sc, btinfo, btinfo->bt_stomp_type);
spin_unlock_irqrestore(&btinfo->btcoex_lock, flags);
if (btinfo->btcoex_period != btinfo->btcoex_no_stomp) {
if (btinfo->hw_timer_enabled)
ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer);
ath_gen_timer_start(sc->sc_ah,
btinfo->no_stomp_timer,
(ath9k_hw_gettsf32(sc->sc_ah) +
btinfo->btcoex_no_stomp),
btinfo->btcoex_no_stomp * 10);
btinfo->hw_timer_enabled = true;
}
mod_timer(&btinfo->period_timer, jiffies +
msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD));
}
/*
* Generic tsf based hw timer which configures weight
* registers to time slice between wlan and bt traffic
*/
static void ath_btcoex_no_stomp_timer(void *arg)
{
struct ath_softc *sc = (struct ath_softc *)arg;
struct ath_btcoex_info *btinfo = &sc->btcoex_info;
unsigned long flags;
DPRINTF(sc, ATH_DBG_BTCOEX, "no stomp timer running \n");
spin_lock_irqsave(&btinfo->btcoex_lock, flags);
if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_LOW)
ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_NONE);
else if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_LOW);
spin_unlock_irqrestore(&btinfo->btcoex_lock, flags);
}
static int ath_init_btcoex_info(struct ath_hw *hw,
struct ath_btcoex_info *btcoex_info)
{
u32 i;
int qnum;
qnum = ath_tx_get_qnum(hw->ah_sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
btcoex_info->bt_coex_mode =
(btcoex_info->bt_coex_mode & AR_BT_QCU_THRESH) |
SM(ath_bt_config.bt_time_extend, AR_BT_TIME_EXTEND) |
SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) |
SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) |
SM(ath_bt_config.bt_mode, AR_BT_MODE) |
SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) |
SM(ath_bt_config.bt_rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) |
SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) |
SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) |
SM(qnum, AR_BT_QCU_THRESH);
btcoex_info->bt_coex_mode2 =
SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) |
SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
AR_BT_DISABLE_BT_ANT;
btcoex_info->bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
btcoex_info->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
btcoex_info->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
btcoex_info->btcoex_period / 100;
for (i = 0; i < 32; i++)
hw->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i;
setup_timer(&btcoex_info->period_timer, ath_btcoex_period_timer,
(unsigned long) hw->ah_sc);
btcoex_info->no_stomp_timer = ath_gen_timer_alloc(hw,
ath_btcoex_no_stomp_timer,
ath_btcoex_no_stomp_timer,
(void *)hw->ah_sc, AR_FIRST_NDP_TIMER);
if (btcoex_info->no_stomp_timer == NULL)
return -ENOMEM;
spin_lock_init(&btcoex_info->btcoex_lock);
return 0;
}
int ath9k_hw_btcoex_init(struct ath_hw *ah)
{
struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info;
int ret = 0;
if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) {
/* connect bt_active to baseband */
REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
(AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
/* Set input mux for bt_active to gpio pin */
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
AR_GPIO_INPUT_MUX1_BT_ACTIVE,
btcoex_info->btactive_gpio);
/* Configure the desired gpio port for input */
ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio);
} else {
/* btcoex 3-wire */
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
(AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB |
AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB));
/* Set input mux for bt_prority_async and
* bt_active_async to GPIO pins */
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
AR_GPIO_INPUT_MUX1_BT_ACTIVE,
btcoex_info->btactive_gpio);
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
AR_GPIO_INPUT_MUX1_BT_PRIORITY,
btcoex_info->btpriority_gpio);
/* Configure the desired GPIO ports for input */
ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio);
ath9k_hw_cfg_gpio_input(ah, btcoex_info->btpriority_gpio);
ret = ath_init_btcoex_info(ah, btcoex_info);
}
return ret;
}
void ath9k_hw_btcoex_enable(struct ath_hw *ah)
{
struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info;
if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) {
/* Configure the desired GPIO port for TX_FRAME output */
ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio,
AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
} else {
/*
* Program coex mode and weight registers to
* enable coex 3-wire
*/
REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_info->bt_coex_mode);
REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_info->bt_coex_weights);
REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_info->bt_coex_mode2);
REG_RMW_FIELD(ah, AR_QUIET1,
AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
REG_RMW_FIELD(ah, AR_PCU_MISC,
AR_PCU_BT_ANT_PREVENT_RX, 0);
ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio,
AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL);
}
REG_RMW(ah, AR_GPIO_PDPU,
(0x2 << (btcoex_info->btactive_gpio * 2)),
(0x3 << (btcoex_info->btactive_gpio * 2)));
ah->ah_sc->sc_flags |= SC_OP_BTCOEX_ENABLED;
}
void ath9k_hw_btcoex_disable(struct ath_hw *ah)
{
struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info;
ath9k_hw_set_gpio(ah, btcoex_info->wlanactive_gpio, 0);
ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) {
REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE);
REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0);
REG_WRITE(ah, AR_BT_COEX_MODE2, 0);
}
ah->ah_sc->sc_flags &= ~SC_OP_BTCOEX_ENABLED;
}
/*
* Pause btcoex timer and bt duty cycle timer
*/
void ath_btcoex_timer_pause(struct ath_softc *sc,
struct ath_btcoex_info *btinfo)
{
del_timer_sync(&btinfo->period_timer);
if (btinfo->hw_timer_enabled)
ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer);
btinfo->hw_timer_enabled = false;
}
/*
* (Re)start btcoex timers
*/
void ath_btcoex_timer_resume(struct ath_softc *sc,
struct ath_btcoex_info *btinfo)
{
DPRINTF(sc, ATH_DBG_BTCOEX, "Starting btcoex timers");
/* make sure duty cycle timer is also stopped when resuming */
if (btinfo->hw_timer_enabled)
ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer);
btinfo->bt_priority_cnt = 0;
btinfo->bt_priority_time = jiffies;
sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
mod_timer(&btinfo->period_timer, jiffies);
}
/*
* Copyright (c) 2009 Atheros Communications Inc.
*
* 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.
*/
#ifndef BTCOEX_H
#define BTCOEX_H
#define ATH_WLANACTIVE_GPIO 5
#define ATH_BTACTIVE_GPIO 6
#define ATH_BTCOEX_DEF_BT_PERIOD 45
#define ATH_BTCOEX_DEF_DUTY_CYCLE 55
#define ATH_BTCOEX_BMISS_THRESH 50
#define ATH_BT_PRIORITY_TIME_THRESHOLD 1000 /* ms */
#define ATH_BT_CNT_THRESHOLD 3
enum ath_btcoex_scheme {
ATH_BTCOEX_CFG_NONE,
ATH_BTCOEX_CFG_2WIRE,
ATH_BTCOEX_CFG_3WIRE,
};
enum ath_stomp_type {
ATH_BTCOEX_NO_STOMP,
ATH_BTCOEX_STOMP_ALL,
ATH_BTCOEX_STOMP_LOW,
ATH_BTCOEX_STOMP_NONE
};
enum ath_bt_mode {
ATH_BT_COEX_MODE_LEGACY, /* legacy rx_clear mode */
ATH_BT_COEX_MODE_UNSLOTTED, /* untimed/unslotted mode */
ATH_BT_COEX_MODE_SLOTTED, /* slotted mode */
ATH_BT_COEX_MODE_DISALBED, /* coexistence disabled */
};
struct ath_btcoex_config {
u8 bt_time_extend;
bool bt_txstate_extend;
bool bt_txframe_extend;
enum ath_bt_mode bt_mode; /* coexistence mode */
bool bt_quiet_collision;
bool bt_rxclear_polarity; /* invert rx_clear as WLAN_ACTIVE*/
u8 bt_priority_time;
u8 bt_first_slot_time;
bool bt_hold_rx_clear;
};
struct ath_btcoex_info {
enum ath_btcoex_scheme btcoex_scheme;
u8 wlanactive_gpio;
u8 btactive_gpio;
u8 btpriority_gpio;
u8 bt_duty_cycle; /* BT duty cycle in percentage */
int bt_stomp_type; /* Types of BT stomping */
u32 bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */
u32 bt_coex_weights; /* Register setting for AR_BT_COEX_WEIGHT */
u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */
u32 btcoex_no_stomp; /* in usec */
u32 btcoex_period; /* in usec */
u32 bt_priority_cnt;
unsigned long bt_priority_time;
bool hw_timer_enabled;
spinlock_t btcoex_lock;
struct timer_list period_timer; /* Timer for BT period */
struct ath_gen_timer *no_stomp_timer; /*Timer for no BT stomping*/
};
int ath9k_hw_btcoex_init(struct ath_hw *ah);
void ath9k_hw_btcoex_enable(struct ath_hw *ah);
void ath9k_hw_btcoex_disable(struct ath_hw *ah);
void ath_btcoex_timer_resume(struct ath_softc *sc,
struct ath_btcoex_info *btinfo);
void ath_btcoex_timer_pause(struct ath_softc *sc,
struct ath_btcoex_info *btinfo);
static inline void ath_btcoex_set_weight(struct ath_btcoex_info *btcoex_info,
u32 bt_weight,
u32 wlan_weight)
{
btcoex_info->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) |
SM(wlan_weight, AR_BTCOEX_WL_WGHT);
}
#endif
...@@ -861,7 +861,7 @@ static void ath9k_hw_9271_pa_cal(struct ath_hw *ah) ...@@ -861,7 +861,7 @@ static void ath9k_hw_9271_pa_cal(struct ath_hw *ah)
REG_WRITE(ah, regList[i][0], regList[i][1]); REG_WRITE(ah, regList[i][0], regList[i][1]);
} }
static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset)
{ {
u32 regVal; u32 regVal;
...@@ -877,6 +877,13 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) ...@@ -877,6 +877,13 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
{ 0x7838, 0 }, { 0x7838, 0 },
}; };
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "Running PA Calibration\n");
/* PA CAL is not needed for high power solution */
if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
AR5416_EEP_TXGAIN_HIGH_POWER)
return;
if (AR_SREV_9285_11(ah)) { if (AR_SREV_9285_11(ah)) {
REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
udelay(10); udelay(10);
...@@ -899,13 +906,13 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) ...@@ -899,13 +906,13 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 1); REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 7); REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
udelay(30); udelay(30);
...@@ -917,7 +924,6 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) ...@@ -917,7 +924,6 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
regVal |= (1 << (19 + i)); regVal |= (1 << (19 + i));
REG_WRITE(ah, 0x7834, regVal); REG_WRITE(ah, 0x7834, regVal);
udelay(1); udelay(1);
regVal = REG_READ(ah, 0x7834);
regVal &= (~(0x1 << (19 + i))); regVal &= (~(0x1 << (19 + i)));
reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
regVal |= (reg_field << (19 + i)); regVal |= (reg_field << (19 + i));
...@@ -936,6 +942,17 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah) ...@@ -936,6 +942,17 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
offs_6_1 = offset>>1; offs_6_1 = offset>>1;
offs_0 = offset & 1; offs_0 = offset & 1;
if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
ah->pacal_info.max_skipcount =
2 * ah->pacal_info.max_skipcount;
ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
} else {
ah->pacal_info.max_skipcount = 1;
ah->pacal_info.skipcount = 0;
ah->pacal_info.prev_offset = offset;
}
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
...@@ -982,8 +999,12 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, ...@@ -982,8 +999,12 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
/* Do periodic PAOffset Cal */ /* Do periodic PAOffset Cal */
if (AR_SREV_9271(ah)) if (AR_SREV_9271(ah))
ath9k_hw_9271_pa_cal(ah); ath9k_hw_9271_pa_cal(ah);
else if (AR_SREV_9285_11_OR_LATER(ah)) else if (AR_SREV_9285_11_OR_LATER(ah)) {
ath9k_hw_9285_pa_cal(ah); if (!ah->pacal_info.skipcount)
ath9k_hw_9285_pa_cal(ah, false);
else
ah->pacal_info.skipcount--;
}
if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER) if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER)
ath9k_olc_temp_compensation(ah); ath9k_olc_temp_compensation(ah);
...@@ -1081,7 +1102,7 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) ...@@ -1081,7 +1102,7 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
/* Do PA Calibration */ /* Do PA Calibration */
if (AR_SREV_9285_11_OR_LATER(ah)) if (AR_SREV_9285_11_OR_LATER(ah))
ath9k_hw_9285_pa_cal(ah); ath9k_hw_9285_pa_cal(ah, true);
/* Do NF Calibration after DC offset and other calibrations */ /* Do NF Calibration after DC offset and other calibrations */
REG_WRITE(ah, AR_PHY_AGC_CONTROL, REG_WRITE(ah, AR_PHY_AGC_CONTROL,
......
...@@ -110,6 +110,13 @@ struct ath9k_nfcal_hist { ...@@ -110,6 +110,13 @@ struct ath9k_nfcal_hist {
u8 invalidNFcount; u8 invalidNFcount;
}; };
#define MAX_PACAL_SKIPCOUNT 8
struct ath9k_pacal_info{
int32_t prev_offset; /* Previous value of PA offset value */
int8_t max_skipcount; /* Max No. of times PACAL can be skipped */
int8_t skipcount; /* No. of times the PACAL to be skipped */
};
bool ath9k_hw_reset_calvalid(struct ath_hw *ah); bool ath9k_hw_reset_calvalid(struct ath_hw *ah);
void ath9k_hw_start_nfcal(struct ath_hw *ah); void ath9k_hw_start_nfcal(struct ath_hw *ah);
void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
......
...@@ -93,6 +93,8 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, ...@@ -93,6 +93,8 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
int i, qcuOffset = 0, dcuOffset = 0; int i, qcuOffset = 0, dcuOffset = 0;
u32 *qcuBase = &val[0], *dcuBase = &val[4]; u32 *qcuBase = &val[0], *dcuBase = &val[4];
ath9k_ps_wakeup(sc);
REG_WRITE(ah, AR_MACMISC, REG_WRITE(ah, AR_MACMISC,
((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
(AR_MACMISC_MISC_OBS_BUS_1 << (AR_MACMISC_MISC_OBS_BUS_1 <<
...@@ -159,6 +161,8 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, ...@@ -159,6 +161,8 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
len += snprintf(buf + len, sizeof(buf) - len, len += snprintf(buf + len, sizeof(buf) - len,
"AR_CR: 0x%x \n", REG_READ(ah, AR_CR)); "AR_CR: 0x%x \n", REG_READ(ah, AR_CR));
ath9k_ps_restore(sc);
return simple_read_from_buffer(user_buf, count, ppos, buf, len); return simple_read_from_buffer(user_buf, count, ppos, buf, len);
} }
......
...@@ -30,6 +30,8 @@ enum ATH_DEBUG { ...@@ -30,6 +30,8 @@ enum ATH_DEBUG {
ATH_DBG_CONFIG = 0x00000200, ATH_DBG_CONFIG = 0x00000200,
ATH_DBG_FATAL = 0x00000400, ATH_DBG_FATAL = 0x00000400,
ATH_DBG_PS = 0x00000800, ATH_DBG_PS = 0x00000800,
ATH_DBG_HWTIMER = 0x00001000,
ATH_DBG_BTCOEX = 0x00002000,
ATH_DBG_ANY = 0xffffffff ATH_DBG_ANY = 0xffffffff
}; };
......
...@@ -143,10 +143,10 @@ void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah, ...@@ -143,10 +143,10 @@ void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
IS_CHAN_2GHZ(chan))) { IS_CHAN_2GHZ(chan))) {
matchIndex = i; matchIndex = i;
break; break;
} else if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel, } else if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
IS_CHAN_2GHZ(chan))) && IS_CHAN_2GHZ(chan)) && i > 0 &&
(freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel, freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
IS_CHAN_2GHZ(chan)))) { IS_CHAN_2GHZ(chan))) {
lowIndex = i - 1; lowIndex = i - 1;
break; break;
} }
...@@ -198,10 +198,10 @@ void ath9k_hw_get_target_powers(struct ath_hw *ah, ...@@ -198,10 +198,10 @@ void ath9k_hw_get_target_powers(struct ath_hw *ah,
matchIndex = i; matchIndex = i;
break; break;
} else } else
if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel, if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
IS_CHAN_2GHZ(chan))) && IS_CHAN_2GHZ(chan)) && i > 0 &&
(freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel, freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
IS_CHAN_2GHZ(chan)))) { IS_CHAN_2GHZ(chan))) {
lowIndex = i - 1; lowIndex = i - 1;
break; break;
} }
......
...@@ -2555,6 +2555,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ...@@ -2555,6 +2555,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
#endif #endif
} }
if (ah->ah_sc->sc_flags & SC_OP_BTCOEX_ENABLED)
ath9k_hw_btcoex_enable(ah);
return 0; return 0;
} }
...@@ -3212,6 +3215,23 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) ...@@ -3212,6 +3215,23 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
if (AR_SREV_9100(ah)) if (AR_SREV_9100(ah))
return true; return true;
if (isr & AR_ISR_GENTMR) {
u32 s5_s;
s5_s = REG_READ(ah, AR_ISR_S5_S);
if (isr & AR_ISR_GENTMR) {
ah->intr_gen_timer_trigger =
MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
ah->intr_gen_timer_thresh =
MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
if (ah->intr_gen_timer_trigger)
*masked |= ATH9K_INT_GENTIMER;
}
}
if (sync_cause) { if (sync_cause) {
fatal_int = fatal_int =
(sync_cause & (sync_cause &
...@@ -3486,6 +3506,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) ...@@ -3486,6 +3506,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
{ {
struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info;
u16 capField = 0, eeval; u16 capField = 0, eeval;
...@@ -3662,9 +3683,15 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) ...@@ -3662,9 +3683,15 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
if (AR_SREV_9280_10_OR_LATER(ah) && btcoex_enable) { if (AR_SREV_9280_10_OR_LATER(ah) && btcoex_enable) {
pCap->hw_caps |= ATH9K_HW_CAP_BT_COEX; btcoex_info->btactive_gpio = ATH_BTACTIVE_GPIO;
ah->btactive_gpio = 6; btcoex_info->wlanactive_gpio = ATH_WLANACTIVE_GPIO;
ah->wlanactive_gpio = 5;
if (AR_SREV_9285(ah))
btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_3WIRE;
else
btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_2WIRE;
} else {
btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_NONE;
} }
} }
...@@ -4069,29 +4096,197 @@ void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode) ...@@ -4069,29 +4096,197 @@ void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode)
REG_WRITE(ah, AR_2040_MODE, macmode); REG_WRITE(ah, AR_2040_MODE, macmode);
} }
/***************************/ /* HW Generic timers configuration */
/* Bluetooth Coexistence */
/***************************/
void ath9k_hw_btcoex_enable(struct ath_hw *ah) static const struct ath_gen_timer_configuration gen_tmr_configuration[] =
{
{AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
{AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
{AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
{AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
{AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
{AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
{AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
{AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},
{AR_NEXT_NDP2_TIMER, AR_NDP2_PERIOD, AR_NDP2_TIMER_MODE, 0x0001},
{AR_NEXT_NDP2_TIMER + 1*4, AR_NDP2_PERIOD + 1*4,
AR_NDP2_TIMER_MODE, 0x0002},
{AR_NEXT_NDP2_TIMER + 2*4, AR_NDP2_PERIOD + 2*4,
AR_NDP2_TIMER_MODE, 0x0004},
{AR_NEXT_NDP2_TIMER + 3*4, AR_NDP2_PERIOD + 3*4,
AR_NDP2_TIMER_MODE, 0x0008},
{AR_NEXT_NDP2_TIMER + 4*4, AR_NDP2_PERIOD + 4*4,
AR_NDP2_TIMER_MODE, 0x0010},
{AR_NEXT_NDP2_TIMER + 5*4, AR_NDP2_PERIOD + 5*4,
AR_NDP2_TIMER_MODE, 0x0020},
{AR_NEXT_NDP2_TIMER + 6*4, AR_NDP2_PERIOD + 6*4,
AR_NDP2_TIMER_MODE, 0x0040},
{AR_NEXT_NDP2_TIMER + 7*4, AR_NDP2_PERIOD + 7*4,
AR_NDP2_TIMER_MODE, 0x0080}
};
/* HW generic timer primitives */
/* compute and clear index of rightmost 1 */
static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask)
{ {
/* connect bt_active to baseband */ u32 b;
REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
(AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, b = *mask;
AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); b &= (0-b);
*mask &= ~b;
b *= debruijn32;
b >>= 27;
return timer_table->gen_timer_index[b];
}
u32 ath9k_hw_gettsf32(struct ath_hw *ah)
{
return REG_READ(ah, AR_TSF_L32);
}
struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
void (*trigger)(void *),
void (*overflow)(void *),
void *arg,
u8 timer_index)
{
struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
struct ath_gen_timer *timer;
timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL);
if (timer == NULL) {
printk(KERN_DEBUG "Failed to allocate memory"
"for hw timer[%d]\n", timer_index);
return NULL;
}
/* allocate a hardware generic timer slot */
timer_table->timers[timer_index] = timer;
timer->index = timer_index;
timer->trigger = trigger;
timer->overflow = overflow;
timer->arg = arg;
return timer;
}
void ath_gen_timer_start(struct ath_hw *ah,
struct ath_gen_timer *timer,
u32 timer_next, u32 timer_period)
{
struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
u32 tsf;
BUG_ON(!timer_period);
set_bit(timer->index, &timer_table->timer_mask.timer_bits);
/* Set input mux for bt_active to gpio pin */ tsf = ath9k_hw_gettsf32(ah);
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
AR_GPIO_INPUT_MUX1_BT_ACTIVE,
ah->btactive_gpio);
/* Configure the desired gpio port for input */ DPRINTF(ah->ah_sc, ATH_DBG_HWTIMER, "curent tsf %x period %x"
ath9k_hw_cfg_gpio_input(ah, ah->btactive_gpio); "timer_next %x\n", tsf, timer_period, timer_next);
/* Configure the desired GPIO port for TX_FRAME output */ /*
ath9k_hw_cfg_output(ah, ah->wlanactive_gpio, * Pull timer_next forward if the current TSF already passed it
AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); * because of software latency
*/
if (timer_next < tsf)
timer_next = tsf + timer_period;
/*
* Program generic timer registers
*/
REG_WRITE(ah, gen_tmr_configuration[timer->index].next_addr,
timer_next);
REG_WRITE(ah, gen_tmr_configuration[timer->index].period_addr,
timer_period);
REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
gen_tmr_configuration[timer->index].mode_mask);
/* Enable both trigger and thresh interrupt masks */
REG_SET_BIT(ah, AR_IMR_S5,
(SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG)));
if ((ah->ah_sc->imask & ATH9K_INT_GENTIMER) == 0) {
ath9k_hw_set_interrupts(ah, 0);
ah->ah_sc->imask |= ATH9K_INT_GENTIMER;
ath9k_hw_set_interrupts(ah, ah->ah_sc->imask);
}
}
void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
{
struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
if ((timer->index < AR_FIRST_NDP_TIMER) ||
(timer->index >= ATH_MAX_GEN_TIMER)) {
return;
}
/* Clear generic timer enable bits. */
REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
gen_tmr_configuration[timer->index].mode_mask);
/* Disable both trigger and thresh interrupt masks */
REG_CLR_BIT(ah, AR_IMR_S5,
(SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG)));
clear_bit(timer->index, &timer_table->timer_mask.timer_bits);
/* if no timer is enabled, turn off interrupt mask */
if (timer_table->timer_mask.val == 0) {
ath9k_hw_set_interrupts(ah, 0);
ah->ah_sc->imask &= ~ATH9K_INT_GENTIMER;
ath9k_hw_set_interrupts(ah, ah->ah_sc->imask);
}
}
void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer)
{
struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
/* free the hardware generic timer slot */
timer_table->timers[timer->index] = NULL;
kfree(timer);
}
/*
* Generic Timer Interrupts handling
*/
void ath_gen_timer_isr(struct ath_hw *ah)
{
struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
struct ath_gen_timer *timer;
u32 trigger_mask, thresh_mask, index;
/* get hardware generic timer interrupt status */
trigger_mask = ah->intr_gen_timer_trigger;
thresh_mask = ah->intr_gen_timer_thresh;
trigger_mask &= timer_table->timer_mask.val;
thresh_mask &= timer_table->timer_mask.val;
trigger_mask &= ~thresh_mask;
while (thresh_mask) {
index = rightmost_index(timer_table, &thresh_mask);
timer = timer_table->timers[index];
BUG_ON(!timer);
DPRINTF(ah->ah_sc, ATH_DBG_HWTIMER,
"TSF overflow for Gen timer %d\n", index);
timer->overflow(timer->arg);
}
while (trigger_mask) {
index = rightmost_index(timer_table, &trigger_mask);
timer = timer_table->timers[index];
BUG_ON(!timer);
DPRINTF(ah->ah_sc, ATH_DBG_HWTIMER,
"Gen timer[%d] trigger\n", index);
timer->trigger(timer->arg);
}
} }
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 #define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2
#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3 #define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3
#define AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL 4
#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 #define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5
#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 #define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6
...@@ -151,7 +152,6 @@ enum ath9k_hw_caps { ...@@ -151,7 +152,6 @@ enum ath9k_hw_caps {
ATH9K_HW_CAP_ENHANCEDPM = BIT(14), ATH9K_HW_CAP_ENHANCEDPM = BIT(14),
ATH9K_HW_CAP_AUTOSLEEP = BIT(15), ATH9K_HW_CAP_AUTOSLEEP = BIT(15),
ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16), ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16),
ATH9K_HW_CAP_BT_COEX = BIT(17)
}; };
enum ath9k_capability_type { enum ath9k_capability_type {
...@@ -238,6 +238,7 @@ enum ath9k_int { ...@@ -238,6 +238,7 @@ enum ath9k_int {
ATH9K_INT_GPIO = 0x01000000, ATH9K_INT_GPIO = 0x01000000,
ATH9K_INT_CABEND = 0x02000000, ATH9K_INT_CABEND = 0x02000000,
ATH9K_INT_TSFOOR = 0x04000000, ATH9K_INT_TSFOOR = 0x04000000,
ATH9K_INT_GENTIMER = 0x08000000,
ATH9K_INT_CST = 0x10000000, ATH9K_INT_CST = 0x10000000,
ATH9K_INT_GTT = 0x20000000, ATH9K_INT_GTT = 0x20000000,
ATH9K_INT_FATAL = 0x40000000, ATH9K_INT_FATAL = 0x40000000,
...@@ -391,6 +392,41 @@ struct ath9k_hw_version { ...@@ -391,6 +392,41 @@ struct ath9k_hw_version {
u16 analog2GhzRev; u16 analog2GhzRev;
}; };
/* Generic TSF timer definitions */
#define ATH_MAX_GEN_TIMER 16
#define AR_GENTMR_BIT(_index) (1 << (_index))
/*
* Using de Bruijin sequence to to look up 1's index in a 32 bit number
* debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001
*/
#define debruijn32 0x077CB531UL
struct ath_gen_timer_configuration {
u32 next_addr;
u32 period_addr;
u32 mode_addr;
u32 mode_mask;
};
struct ath_gen_timer {
void (*trigger)(void *arg);
void (*overflow)(void *arg);
void *arg;
u8 index;
};
struct ath_gen_timer_table {
u32 gen_timer_index[32];
struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER];
union {
unsigned long timer_bits;
u16 val;
} timer_mask;
};
struct ath_hw { struct ath_hw {
struct ath_softc *ah_sc; struct ath_softc *ah_sc;
struct ath9k_hw_version hw_version; struct ath9k_hw_version hw_version;
...@@ -414,8 +450,6 @@ struct ath_hw { ...@@ -414,8 +450,6 @@ struct ath_hw {
u16 rfsilent; u16 rfsilent;
u32 rfkill_gpio; u32 rfkill_gpio;
u32 rfkill_polarity; u32 rfkill_polarity;
u32 btactive_gpio;
u32 wlanactive_gpio;
u32 ah_flags; u32 ah_flags;
bool htc_reset_init; bool htc_reset_init;
...@@ -424,6 +458,7 @@ struct ath_hw { ...@@ -424,6 +458,7 @@ struct ath_hw {
enum ath9k_power_mode power_mode; enum ath9k_power_mode power_mode;
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
struct ath9k_pacal_info pacal_info;
struct ar5416Stats stats; struct ar5416Stats stats;
struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
...@@ -538,6 +573,10 @@ struct ath_hw { ...@@ -538,6 +573,10 @@ struct ath_hw {
struct ar5416IniArray iniModesAdditional; struct ar5416IniArray iniModesAdditional;
struct ar5416IniArray iniModesRxGain; struct ar5416IniArray iniModesRxGain;
struct ar5416IniArray iniModesTxGain; struct ar5416IniArray iniModesTxGain;
u32 intr_gen_timer_trigger;
u32 intr_gen_timer_thresh;
struct ath_gen_timer_table hw_gen_timers;
}; };
/* Initialization, Detach, Reset */ /* Initialization, Detach, Reset */
...@@ -613,6 +652,17 @@ bool ath9k_hw_intrpend(struct ath_hw *ah); ...@@ -613,6 +652,17 @@ bool ath9k_hw_intrpend(struct ath_hw *ah);
bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked); bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked);
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints); enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
void ath9k_hw_btcoex_enable(struct ath_hw *ah); /* Generic hw timer primitives */
struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
void (*trigger)(void *),
void (*overflow)(void *),
void *arg,
u8 timer_index);
void ath_gen_timer_start(struct ath_hw *ah, struct ath_gen_timer *timer,
u32 timer_next, u32 timer_period);
void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer);
void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
void ath_gen_timer_isr(struct ath_hw *hw);
u32 ath9k_hw_gettsf32(struct ath_hw *ah);
#endif #endif
...@@ -4133,7 +4133,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { ...@@ -4133,7 +4133,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = {
{ 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
{ 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
{ 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
{ 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e },
{ 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
{ 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
{ 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
...@@ -4158,7 +4158,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { ...@@ -4158,7 +4158,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = {
{ 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
{ 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
{ 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
{ 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 }, { 0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f },
{ 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
{ 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
{ 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
...@@ -4601,7 +4601,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { ...@@ -4601,7 +4601,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = {
{ 0x00008258, 0x00000000 }, { 0x00008258, 0x00000000 },
{ 0x0000825c, 0x400000ff }, { 0x0000825c, 0x400000ff },
{ 0x00008260, 0x00080922 }, { 0x00008260, 0x00080922 },
{ 0x00008264, 0xa8a00010 }, { 0x00008264, 0x88a00010 },
{ 0x00008270, 0x00000000 }, { 0x00008270, 0x00000000 },
{ 0x00008274, 0x40000000 }, { 0x00008274, 0x40000000 },
{ 0x00008278, 0x003e4180 }, { 0x00008278, 0x003e4180 },
...@@ -4650,7 +4650,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { ...@@ -4650,7 +4650,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = {
{ 0x00009954, 0x5f3ca3de }, { 0x00009954, 0x5f3ca3de },
{ 0x00009958, 0x2108ecff }, { 0x00009958, 0x2108ecff },
{ 0x00009968, 0x000003ce }, { 0x00009968, 0x000003ce },
{ 0x00009970, 0x192bb515 }, { 0x00009970, 0x192bb514 },
{ 0x00009974, 0x00000000 }, { 0x00009974, 0x00000000 },
{ 0x00009978, 0x00000001 }, { 0x00009978, 0x00000001 },
{ 0x0000997c, 0x00000000 }, { 0x0000997c, 0x00000000 },
...@@ -4728,7 +4728,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { ...@@ -4728,7 +4728,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = {
{ 0x00007800, 0x00140000 }, { 0x00007800, 0x00140000 },
{ 0x00007804, 0x0e4548d8 }, { 0x00007804, 0x0e4548d8 },
{ 0x00007808, 0x54214514 }, { 0x00007808, 0x54214514 },
{ 0x0000780c, 0x02025820 }, { 0x0000780c, 0x02025830 },
{ 0x00007810, 0x71c0d388 }, { 0x00007810, 0x71c0d388 },
{ 0x00007814, 0x924934a8 }, { 0x00007814, 0x924934a8 },
{ 0x0000781c, 0x00000000 }, { 0x0000781c, 0x00000000 },
......
...@@ -439,8 +439,8 @@ static void ath_start_ani(struct ath_softc *sc) ...@@ -439,8 +439,8 @@ static void ath_start_ani(struct ath_softc *sc)
*/ */
void ath_update_chainmask(struct ath_softc *sc, int is_ht) void ath_update_chainmask(struct ath_softc *sc, int is_ht)
{ {
if (is_ht || if ((sc->sc_flags & SC_OP_SCANNING) || is_ht ||
(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) { (sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE)) {
sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask; sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
sc->rx_chainmask = sc->sc_ah->caps.rx_chainmask; sc->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
} else { } else {
...@@ -602,6 +602,10 @@ irqreturn_t ath_isr(int irq, void *dev) ...@@ -602,6 +602,10 @@ irqreturn_t ath_isr(int irq, void *dev)
sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
} }
if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
if (status & ATH9K_INT_GENTIMER)
ath_gen_timer_isr(ah);
chip_reset: chip_reset:
ath_debug_stat_interrupt(sc, status); ath_debug_stat_interrupt(sc, status);
...@@ -1279,6 +1283,10 @@ void ath_detach(struct ath_softc *sc) ...@@ -1279,6 +1283,10 @@ void ath_detach(struct ath_softc *sc)
if (ATH_TXQ_SETUP(sc, i)) if (ATH_TXQ_SETUP(sc, i))
ath_tx_cleanupq(sc, &sc->tx.txq[i]); ath_tx_cleanupq(sc, &sc->tx.txq[i]);
if ((sc->btcoex_info.no_stomp_timer) &&
sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
ath_gen_timer_free(sc->sc_ah, sc->btcoex_info.no_stomp_timer);
ath9k_hw_detach(sc->sc_ah); ath9k_hw_detach(sc->sc_ah);
sc->sc_ah = NULL; sc->sc_ah = NULL;
ath9k_exit_debug(sc); ath9k_exit_debug(sc);
...@@ -1509,8 +1517,11 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc) ...@@ -1509,8 +1517,11 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc)
ARRAY_SIZE(ath9k_5ghz_chantable); ARRAY_SIZE(ath9k_5ghz_chantable);
} }
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX) if (sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE) {
ath9k_hw_btcoex_enable(sc->sc_ah); r = ath9k_hw_btcoex_init(ah);
if (r)
goto bad2;
}
return 0; return 0;
bad2: bad2:
...@@ -1992,6 +2003,16 @@ static int ath9k_start(struct ieee80211_hw *hw) ...@@ -1992,6 +2003,16 @@ static int ath9k_start(struct ieee80211_hw *hw)
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
if ((sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE) &&
!(sc->sc_flags & SC_OP_BTCOEX_ENABLED)) {
ath_btcoex_set_weight(&sc->btcoex_info, AR_BT_COEX_WGHT,
AR_STOMP_LOW_WLAN_WGHT);
ath9k_hw_btcoex_enable(sc->sc_ah);
if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
ath_btcoex_timer_resume(sc, &sc->btcoex_info);
}
mutex_unlock: mutex_unlock:
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
...@@ -2125,6 +2146,12 @@ static void ath9k_stop(struct ieee80211_hw *hw) ...@@ -2125,6 +2146,12 @@ static void ath9k_stop(struct ieee80211_hw *hw)
return; /* another wiphy still in use */ return; /* another wiphy still in use */
} }
if (sc->sc_flags & SC_OP_BTCOEX_ENABLED) {
ath9k_hw_btcoex_disable(sc->sc_ah);
if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
ath_btcoex_timer_pause(sc, &sc->btcoex_info);
}
/* make sure h/w will not generate any interrupt /* make sure h/w will not generate any interrupt
* before setting the invalid flag. */ * before setting the invalid flag. */
ath9k_hw_set_interrupts(sc->sc_ah, 0); ath9k_hw_set_interrupts(sc->sc_ah, 0);
...@@ -2713,6 +2740,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) ...@@ -2713,6 +2740,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
struct ath_wiphy *aphy = hw->priv; struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc; struct ath_softc *sc = aphy->sc;
mutex_lock(&sc->mutex);
if (ath9k_wiphy_scanning(sc)) { if (ath9k_wiphy_scanning(sc)) {
printk(KERN_DEBUG "ath9k: Two wiphys trying to scan at the " printk(KERN_DEBUG "ath9k: Two wiphys trying to scan at the "
"same time\n"); "same time\n");
...@@ -2720,6 +2748,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) ...@@ -2720,6 +2748,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
* Do not allow the concurrent scanning state for now. This * Do not allow the concurrent scanning state for now. This
* could be improved with scanning control moved into ath9k. * could be improved with scanning control moved into ath9k.
*/ */
mutex_unlock(&sc->mutex);
return; return;
} }
...@@ -2729,6 +2758,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) ...@@ -2729,6 +2758,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
spin_lock_bh(&sc->ani_lock); spin_lock_bh(&sc->ani_lock);
sc->sc_flags |= SC_OP_SCANNING; sc->sc_flags |= SC_OP_SCANNING;
spin_unlock_bh(&sc->ani_lock); spin_unlock_bh(&sc->ani_lock);
mutex_unlock(&sc->mutex);
} }
static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
...@@ -2736,11 +2766,13 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) ...@@ -2736,11 +2766,13 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
struct ath_wiphy *aphy = hw->priv; struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc; struct ath_softc *sc = aphy->sc;
mutex_lock(&sc->mutex);
spin_lock_bh(&sc->ani_lock); spin_lock_bh(&sc->ani_lock);
aphy->state = ATH_WIPHY_ACTIVE; aphy->state = ATH_WIPHY_ACTIVE;
sc->sc_flags &= ~SC_OP_SCANNING; sc->sc_flags &= ~SC_OP_SCANNING;
sc->sc_flags |= SC_OP_FULL_RESET; sc->sc_flags |= SC_OP_FULL_RESET;
spin_unlock_bh(&sc->ani_lock); spin_unlock_bh(&sc->ani_lock);
mutex_unlock(&sc->mutex);
} }
struct ieee80211_ops ath9k_ops = { struct ieee80211_ops ath9k_ops = {
......
...@@ -423,11 +423,12 @@ u32 ath_calcrxfilter(struct ath_softc *sc) ...@@ -423,11 +423,12 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
if (sc->rx.rxfilter & FIF_PSPOLL) if (sc->rx.rxfilter & FIF_PSPOLL)
rfilt |= ATH9K_RX_FILTER_PSPOLL; rfilt |= ATH9K_RX_FILTER_PSPOLL;
if (sc->sec_wiphy) { if (sc->sec_wiphy || (sc->rx.rxfilter & FIF_OTHER_BSS)) {
/* TODO: only needed if more than one BSSID is in use in /* TODO: only needed if more than one BSSID is in use in
* station/adhoc mode */ * station/adhoc mode */
/* TODO: for older chips, may need to add ATH9K_RX_FILTER_PROM /* The following may also be needed for other older chips */
*/ if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160)
rfilt |= ATH9K_RX_FILTER_PROM;
rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
} }
......
...@@ -234,7 +234,15 @@ ...@@ -234,7 +234,15 @@
#define AR_IMR_S5 0x00b8 #define AR_IMR_S5 0x00b8
#define AR_IMR_S5_TIM_TIMER 0x00000010 #define AR_IMR_S5_TIM_TIMER 0x00000010
#define AR_IMR_S5_DTIM_TIMER 0x00000020 #define AR_IMR_S5_DTIM_TIMER 0x00000020
#define AR_ISR_S5_GENTIMER_TRIG 0x0000FF80
#define AR_ISR_S5_GENTIMER_TRIG_S 0
#define AR_ISR_S5_GENTIMER_THRESH 0xFF800000
#define AR_ISR_S5_GENTIMER_THRESH_S 16
#define AR_ISR_S5_S 0x00d8
#define AR_IMR_S5_GENTIMER_TRIG 0x0000FF80
#define AR_IMR_S5_GENTIMER_TRIG_S 0
#define AR_IMR_S5_GENTIMER_THRESH 0xFF800000
#define AR_IMR_S5_GENTIMER_THRESH_S 16
#define AR_IMR 0x00a0 #define AR_IMR 0x00a0
#define AR_IMR_RXOK 0x00000001 #define AR_IMR_RXOK 0x00000001
...@@ -962,6 +970,8 @@ enum { ...@@ -962,6 +970,8 @@ enum {
#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7
#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000
#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12
#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB 0x00001000
#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S 1
#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000
#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15
#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000
...@@ -970,6 +980,8 @@ enum { ...@@ -970,6 +980,8 @@ enum {
#define AR_GPIO_INPUT_MUX1 0x4058 #define AR_GPIO_INPUT_MUX1 0x4058
#define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 #define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000
#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 #define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16
#define AR_GPIO_INPUT_MUX1_BT_PRIORITY 0x00000f00
#define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8
#define AR_GPIO_INPUT_MUX2 0x405c #define AR_GPIO_INPUT_MUX2 0x405c
#define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f #define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f
...@@ -995,6 +1007,8 @@ enum { ...@@ -995,6 +1007,8 @@ enum {
#define AR_OBS 0x4080 #define AR_OBS 0x4080
#define AR_GPIO_PDPU 0x4088
#define AR_PCIE_MSI 0x4094 #define AR_PCIE_MSI 0x4094
#define AR_PCIE_MSI_ENABLE 0x00000001 #define AR_PCIE_MSI_ENABLE 0x00000001
...@@ -1428,6 +1442,7 @@ enum { ...@@ -1428,6 +1442,7 @@ enum {
#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff #define AR_QUIET1_NEXT_QUIET_M 0x0000ffff
#define AR_QUIET1_QUIET_ENABLE 0x00010000 #define AR_QUIET1_QUIET_ENABLE 0x00010000
#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000 #define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000
#define AR_QUIET1_QUIET_ACK_CTS_ENABLE_S 17
#define AR_QUIET2 0x8100 #define AR_QUIET2 0x8100
#define AR_QUIET2_QUIET_PERIOD_S 0 #define AR_QUIET2_QUIET_PERIOD_S 0
#define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff #define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff
...@@ -1473,6 +1488,8 @@ enum { ...@@ -1473,6 +1488,8 @@ enum {
#define AR_PCU_CLEAR_VMF 0x01000000 #define AR_PCU_CLEAR_VMF 0x01000000
#define AR_PCU_CLEAR_BA_VALID 0x04000000 #define AR_PCU_CLEAR_BA_VALID 0x04000000
#define AR_PCU_BT_ANT_PREVENT_RX 0x00100000
#define AR_PCU_BT_ANT_PREVENT_RX_S 20
#define AR_FILT_OFDM 0x8124 #define AR_FILT_OFDM 0x8124
#define AR_FILT_OFDM_COUNT 0x00FFFFFF #define AR_FILT_OFDM_COUNT 0x00FFFFFF
...@@ -1500,6 +1517,46 @@ enum { ...@@ -1500,6 +1517,46 @@ enum {
#define AR_PHY_ERR_3_COUNT 0x00FFFFFF #define AR_PHY_ERR_3_COUNT 0x00FFFFFF
#define AR_PHY_ERR_MASK_3 0x816c #define AR_PHY_ERR_MASK_3 0x816c
#define AR_BT_COEX_MODE 0x8170
#define AR_BT_TIME_EXTEND 0x000000ff
#define AR_BT_TIME_EXTEND_S 0
#define AR_BT_TXSTATE_EXTEND 0x00000100
#define AR_BT_TXSTATE_EXTEND_S 8
#define AR_BT_TX_FRAME_EXTEND 0x00000200
#define AR_BT_TX_FRAME_EXTEND_S 9
#define AR_BT_MODE 0x00000c00
#define AR_BT_MODE_S 10
#define AR_BT_QUIET 0x00001000
#define AR_BT_QUIET_S 12
#define AR_BT_QCU_THRESH 0x0001e000
#define AR_BT_QCU_THRESH_S 13
#define AR_BT_RX_CLEAR_POLARITY 0x00020000
#define AR_BT_RX_CLEAR_POLARITY_S 17
#define AR_BT_PRIORITY_TIME 0x00fc0000
#define AR_BT_PRIORITY_TIME_S 18
#define AR_BT_FIRST_SLOT_TIME 0xff000000
#define AR_BT_FIRST_SLOT_TIME_S 24
#define AR_BT_COEX_WEIGHT 0x8174
#define AR_BT_COEX_WGHT 0xff55
#define AR_STOMP_ALL_WLAN_WGHT 0xffcc
#define AR_STOMP_LOW_WLAN_WGHT 0xaaa8
#define AR_STOMP_NONE_WLAN_WGHT 0xaa00
#define AR_BTCOEX_BT_WGHT 0x0000ffff
#define AR_BTCOEX_BT_WGHT_S 0
#define AR_BTCOEX_WL_WGHT 0xffff0000
#define AR_BTCOEX_WL_WGHT_S 16
#define AR_BT_COEX_MODE2 0x817c
#define AR_BT_BCN_MISS_THRESH 0x000000ff
#define AR_BT_BCN_MISS_THRESH_S 0
#define AR_BT_BCN_MISS_CNT 0x0000ff00
#define AR_BT_BCN_MISS_CNT_S 8
#define AR_BT_HOLD_RX_CLEAR 0x00010000
#define AR_BT_HOLD_RX_CLEAR_S 16
#define AR_BT_DISABLE_BT_ANT 0x00100000
#define AR_BT_DISABLE_BT_ANT_S 20
#define AR_TXSIFS 0x81d0 #define AR_TXSIFS 0x81d0
#define AR_TXSIFS_TIME 0x000000FF #define AR_TXSIFS_TIME 0x000000FF
#define AR_TXSIFS_TX_LATENCY 0x00000F00 #define AR_TXSIFS_TX_LATENCY 0x00000F00
...@@ -1516,7 +1573,10 @@ enum { ...@@ -1516,7 +1573,10 @@ enum {
#define AR_TXOP_8_11 0x81f8 #define AR_TXOP_8_11 0x81f8
#define AR_TXOP_12_15 0x81fc #define AR_TXOP_12_15 0x81fc
#define AR_NEXT_NDP2_TIMER 0x8180
#define AR_FIRST_NDP_TIMER 7
#define AR_NDP2_PERIOD 0x81a0
#define AR_NDP2_TIMER_MODE 0x81c0
#define AR_NEXT_TBTT_TIMER 0x8200 #define AR_NEXT_TBTT_TIMER 0x8200
#define AR_NEXT_DMA_BEACON_ALERT 0x8204 #define AR_NEXT_DMA_BEACON_ALERT 0x8204
#define AR_NEXT_SWBA 0x8208 #define AR_NEXT_SWBA 0x8208
......
...@@ -493,7 +493,12 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, ...@@ -493,7 +493,12 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy) if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
return 0; return 0;
aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_MAX); if (sc->sc_flags & SC_OP_BT_PRIORITY_DETECTED)
aggr_limit = min((max_4ms_framelen * 3) / 8,
(u32)ATH_AMPDU_LIMIT_MAX);
else
aggr_limit = min(max_4ms_framelen,
(u32)ATH_AMPDU_LIMIT_MAX);
/* /*
* h/w can accept aggregates upto 16 bit lengths (65535). * h/w can accept aggregates upto 16 bit lengths (65535).
...@@ -872,7 +877,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) ...@@ -872,7 +877,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
return &sc->tx.txq[qnum]; return &sc->tx.txq[qnum];
} }
static int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
{ {
int qnum; int qnum;
......
...@@ -82,15 +82,13 @@ config B43_NPHY ...@@ -82,15 +82,13 @@ config B43_NPHY
config B43_PHY_LP config B43_PHY_LP
bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)" bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)"
depends on B43 && EXPERIMENTAL depends on B43 && EXPERIMENTAL
default y
---help--- ---help---
Support for the LP-PHY. Support for the LP-PHY.
The LP-PHY is a low-power PHY built into some notebooks The LP-PHY is a low-power PHY built into some notebooks
and embedded devices. It supports 802.11a/g and embedded devices. It supports 802.11a/g
(802.11a support is optional, and currently disabled). (802.11a support is optional, and currently disabled).
This is heavily experimental, and probably will not work for you.
Say N unless you want to help debug the driver.
# This config option automatically enables b43 LEDS support, # This config option automatically enables b43 LEDS support,
# if it's possible. # if it's possible.
config B43_LEDS config B43_LEDS
......
...@@ -1456,7 +1456,8 @@ static u16 b43_antenna_to_phyctl(int antenna) ...@@ -1456,7 +1456,8 @@ static u16 b43_antenna_to_phyctl(int antenna)
return B43_TXH_PHY_ANT2; return B43_TXH_PHY_ANT2;
case B43_ANTENNA3: case B43_ANTENNA3:
return B43_TXH_PHY_ANT3; return B43_TXH_PHY_ANT3;
case B43_ANTENNA_AUTO: case B43_ANTENNA_AUTO0:
case B43_ANTENNA_AUTO1:
return B43_TXH_PHY_ANT01AUTO; return B43_TXH_PHY_ANT01AUTO;
} }
B43_WARN_ON(1); B43_WARN_ON(1);
......
...@@ -531,7 +531,7 @@ static void b43_aphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) ...@@ -531,7 +531,7 @@ static void b43_aphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
tmp = b43_phy_read(dev, B43_PHY_BBANDCFG); tmp = b43_phy_read(dev, B43_PHY_BBANDCFG);
tmp &= ~B43_PHY_BBANDCFG_RXANT; tmp &= ~B43_PHY_BBANDCFG_RXANT;
tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna) tmp |= (autodiv ? B43_ANTENNA_AUTO1 : antenna)
<< B43_PHY_BBANDCFG_RXANT_SHIFT; << B43_PHY_BBANDCFG_RXANT_SHIFT;
b43_phy_write(dev, B43_PHY_BBANDCFG, tmp); b43_phy_write(dev, B43_PHY_BBANDCFG, tmp);
......
...@@ -249,20 +249,35 @@ void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg) ...@@ -249,20 +249,35 @@ void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg)
void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask) void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
{ {
b43_phy_write(dev, offset, if (dev->phy.ops->phy_maskset) {
b43_phy_read(dev, offset) & mask); assert_mac_suspended(dev);
dev->phy.ops->phy_maskset(dev, offset, mask, 0);
} else {
b43_phy_write(dev, offset,
b43_phy_read(dev, offset) & mask);
}
} }
void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set) void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set)
{ {
b43_phy_write(dev, offset, if (dev->phy.ops->phy_maskset) {
b43_phy_read(dev, offset) | set); assert_mac_suspended(dev);
dev->phy.ops->phy_maskset(dev, offset, 0xFFFF, set);
} else {
b43_phy_write(dev, offset,
b43_phy_read(dev, offset) | set);
}
} }
void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
{ {
b43_phy_write(dev, offset, if (dev->phy.ops->phy_maskset) {
(b43_phy_read(dev, offset) & mask) | set); assert_mac_suspended(dev);
dev->phy.ops->phy_maskset(dev, offset, mask, set);
} else {
b43_phy_write(dev, offset,
(b43_phy_read(dev, offset) & mask) | set);
}
} }
int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel) int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
......
...@@ -49,11 +49,11 @@ enum b43_interference_mitigation { ...@@ -49,11 +49,11 @@ enum b43_interference_mitigation {
/* Antenna identifiers */ /* Antenna identifiers */
enum { enum {
B43_ANTENNA0, /* Antenna 0 */ B43_ANTENNA0 = 0, /* Antenna 0 */
B43_ANTENNA1, /* Antenna 0 */ B43_ANTENNA1 = 1, /* Antenna 1 */
B43_ANTENNA_AUTO1, /* Automatic, starting with antenna 1 */ B43_ANTENNA_AUTO0 = 2, /* Automatic, starting with antenna 0 */
B43_ANTENNA_AUTO0, /* Automatic, starting with antenna 0 */ B43_ANTENNA_AUTO1 = 3, /* Automatic, starting with antenna 1 */
B43_ANTENNA2, B43_ANTENNA2 = 4,
B43_ANTENNA3 = 8, B43_ANTENNA3 = 8,
B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0, B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0,
...@@ -95,6 +95,8 @@ enum b43_txpwr_result { ...@@ -95,6 +95,8 @@ enum b43_txpwr_result {
* Must not be NULL. * Must not be NULL.
* @phy_write: Write to a PHY register. * @phy_write: Write to a PHY register.
* Must not be NULL. * Must not be NULL.
* @phy_maskset: Maskset a PHY register, taking shortcuts.
* If it is NULL, a generic algorithm is used.
* @radio_read: Read from a Radio register. * @radio_read: Read from a Radio register.
* Must not be NULL. * Must not be NULL.
* @radio_write: Write to a Radio register. * @radio_write: Write to a Radio register.
...@@ -154,6 +156,7 @@ struct b43_phy_operations { ...@@ -154,6 +156,7 @@ struct b43_phy_operations {
/* Register access */ /* Register access */
u16 (*phy_read)(struct b43_wldev *dev, u16 reg); u16 (*phy_read)(struct b43_wldev *dev, u16 reg);
void (*phy_write)(struct b43_wldev *dev, u16 reg, u16 value); void (*phy_write)(struct b43_wldev *dev, u16 reg, u16 value);
void (*phy_maskset)(struct b43_wldev *dev, u16 reg, u16 mask, u16 set);
u16 (*radio_read)(struct b43_wldev *dev, u16 reg); u16 (*radio_read)(struct b43_wldev *dev, u16 reg);
void (*radio_write)(struct b43_wldev *dev, u16 reg, u16 value); void (*radio_write)(struct b43_wldev *dev, u16 reg, u16 value);
......
...@@ -2664,7 +2664,7 @@ static void b43_gphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) ...@@ -2664,7 +2664,7 @@ static void b43_gphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
tmp = b43_phy_read(dev, B43_PHY_BBANDCFG); tmp = b43_phy_read(dev, B43_PHY_BBANDCFG);
tmp &= ~B43_PHY_BBANDCFG_RXANT; tmp &= ~B43_PHY_BBANDCFG_RXANT;
tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna) tmp |= (autodiv ? B43_ANTENNA_AUTO1 : antenna)
<< B43_PHY_BBANDCFG_RXANT_SHIFT; << B43_PHY_BBANDCFG_RXANT_SHIFT;
b43_phy_write(dev, B43_PHY_BBANDCFG, tmp); b43_phy_write(dev, B43_PHY_BBANDCFG, tmp);
......
...@@ -182,8 +182,8 @@ static void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq) ...@@ -182,8 +182,8 @@ static void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq)
temp[1] = temp[0] + 0x1000; temp[1] = temp[0] + 0x1000;
temp[2] = temp[0] + 0x2000; temp[2] = temp[0] + 0x2000;
b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp);
b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), 3, temp); b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), 3, temp);
b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp);
} }
static void lpphy_table_init(struct b43_wldev *dev) static void lpphy_table_init(struct b43_wldev *dev)
...@@ -223,8 +223,8 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) ...@@ -223,8 +223,8 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0x0006); b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0x0006);
b43_phy_mask(dev, B43_LPPHY_RX_RADIO_CTL, 0xFFFE); b43_phy_mask(dev, B43_LPPHY_RX_RADIO_CTL, 0xFFFE);
b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x0005); b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x0005);
b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC10, 0x0180); b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0x0180);
b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3800); b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3C00);
b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFFF0, 0x0005); b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFFF0, 0x0005);
b43_phy_maskset(dev, B43_LPPHY_GAIN_MISMATCH_LIMIT, 0xFFC0, 0x001A); b43_phy_maskset(dev, B43_LPPHY_GAIN_MISMATCH_LIMIT, 0xFFC0, 0x001A);
b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0x00B3); b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0x00B3);
...@@ -234,19 +234,15 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) ...@@ -234,19 +234,15 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
if ((bus->sprom.boardflags_lo & B43_BFL_FEM) && if ((bus->sprom.boardflags_lo & B43_BFL_FEM) &&
((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) || ((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
(bus->sprom.boardflags_hi & B43_BFH_PAREF))) { (bus->sprom.boardflags_hi & B43_BFH_PAREF))) {
/* TODO: ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28);
* Set the LDO voltage to 0x0028 - FIXME: What is this? ssb_pmu_set_ldo_paref(&bus->chipco, true);
* Call sb_pmu_set_ldo_voltage with 4 and the LDO voltage
* as arguments
* Call sb_pmu_paref_ldo_enable with argument TRUE
*/
if (dev->phy.rev == 0) { if (dev->phy.rev == 0) {
b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT, b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT,
0xFFCF, 0x0010); 0xFFCF, 0x0010);
} }
b43_lptab_write(dev, B43_LPTAB16(11, 7), 60); b43_lptab_write(dev, B43_LPTAB16(11, 7), 60);
} else { } else {
//TODO: Call ssb_pmu_paref_ldo_enable with argument FALSE ssb_pmu_set_ldo_paref(&bus->chipco, false);
b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT, b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT,
0xFFCF, 0x0020); 0xFFCF, 0x0020);
b43_lptab_write(dev, B43_LPTAB16(11, 7), 100); b43_lptab_write(dev, B43_LPTAB16(11, 7), 100);
...@@ -340,11 +336,11 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) ...@@ -340,11 +336,11 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
if (dev->phy.rev == 1) { if (dev->phy.rev == 1) {
tmp = b43_phy_read(dev, B43_LPPHY_CLIPCTRTHRESH); tmp = b43_phy_read(dev, B43_LPPHY_CLIPCTRTHRESH);
tmp2 = (tmp & 0x03E0) >> 5; tmp2 = (tmp & 0x03E0) >> 5;
tmp2 |= tmp << 5; tmp2 |= tmp2 << 5;
b43_phy_write(dev, B43_LPPHY_4C3, tmp2); b43_phy_write(dev, B43_LPPHY_4C3, tmp2);
tmp = b43_phy_read(dev, B43_LPPHY_OFDMSYNCTHRESH0); tmp = b43_phy_read(dev, B43_LPPHY_GAINDIRECTMISMATCH);
tmp2 = (tmp & 0x1F00) >> 8; tmp2 = (tmp & 0x1F00) >> 8;
tmp2 |= tmp << 5; tmp2 |= tmp2 << 5;
b43_phy_write(dev, B43_LPPHY_4C4, tmp2); b43_phy_write(dev, B43_LPPHY_4C4, tmp2);
tmp = b43_phy_read(dev, B43_LPPHY_VERYLOWGAINDB); tmp = b43_phy_read(dev, B43_LPPHY_VERYLOWGAINDB);
tmp2 = tmp & 0x00FF; tmp2 = tmp & 0x00FF;
...@@ -705,7 +701,7 @@ static void lpphy_set_rc_cap(struct b43_wldev *dev) ...@@ -705,7 +701,7 @@ static void lpphy_set_rc_cap(struct b43_wldev *dev)
u8 rc_cap = (lpphy->rc_cap & 0x1F) >> 1; u8 rc_cap = (lpphy->rc_cap & 0x1F) >> 1;
if (dev->phy.rev == 1) //FIXME check channel 14! if (dev->phy.rev == 1) //FIXME check channel 14!
rc_cap = max_t(u8, rc_cap + 5, 15); rc_cap = min_t(u8, rc_cap + 5, 15);
b43_radio_write(dev, B2062_N_RXBB_CALIB2, b43_radio_write(dev, B2062_N_RXBB_CALIB2,
max_t(u8, lpphy->rc_cap - 4, 0x80)); max_t(u8, lpphy->rc_cap - 4, 0x80));
...@@ -761,7 +757,7 @@ static void lpphy_disable_crs(struct b43_wldev *dev, bool user) ...@@ -761,7 +757,7 @@ static void lpphy_disable_crs(struct b43_wldev *dev, bool user)
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3); b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB); b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4); b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7); b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFF7);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8); b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10); b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10); b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
...@@ -956,7 +952,7 @@ static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on, ...@@ -956,7 +952,7 @@ static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on,
b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFF9F, scale_idx << 5); b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFF9F, scale_idx << 5);
b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFB); b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFB);
b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x2); b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x2);
b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x20); b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x20);
} }
static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time, static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
...@@ -968,7 +964,7 @@ static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time, ...@@ -968,7 +964,7 @@ static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
b43_phy_write(dev, B43_LPPHY_IQ_NUM_SMPLS_ADDR, samples); b43_phy_write(dev, B43_LPPHY_IQ_NUM_SMPLS_ADDR, samples);
b43_phy_maskset(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFF00, time); b43_phy_maskset(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFF00, time);
b43_phy_mask(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFEFF); b43_phy_mask(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFEFF);
b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFDFF); b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
for (i = 0; i < 500; i++) { for (i = 0; i < 500; i++) {
if (!(b43_phy_read(dev, if (!(b43_phy_read(dev,
...@@ -1008,6 +1004,7 @@ static int lpphy_loopback(struct b43_wldev *dev) ...@@ -1008,6 +1004,7 @@ static int lpphy_loopback(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x3); b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x3);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3); b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 1);
b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE); b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800); b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800); b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
...@@ -1031,9 +1028,10 @@ static int lpphy_loopback(struct b43_wldev *dev) ...@@ -1031,9 +1028,10 @@ static int lpphy_loopback(struct b43_wldev *dev)
return index; return index;
} }
/* Fixed-point division algorithm using only integer math. */
static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision) static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
{ {
u32 quotient, remainder, rbit, roundup, tmp; u32 quotient, remainder;
if (divisor == 0) if (divisor == 0)
return 0; return 0;
...@@ -1041,20 +1039,16 @@ static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision) ...@@ -1041,20 +1039,16 @@ static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
quotient = dividend / divisor; quotient = dividend / divisor;
remainder = dividend % divisor; remainder = dividend % divisor;
rbit = divisor & 0x1; while (precision > 0) {
roundup = (divisor >> 1) + rbit;
while (precision != 0) {
tmp = remainder - roundup;
quotient <<= 1; quotient <<= 1;
if (remainder >= roundup) if (remainder << 1 >= divisor) {
remainder = (tmp << 1) + rbit; quotient++;
else remainder = (remainder << 1) - divisor;
remainder <<= 1; }
precision--; precision--;
} }
if (remainder >= roundup) if (remainder << 1 >= divisor)
quotient++; quotient++;
return quotient; return quotient;
...@@ -1137,9 +1131,9 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev, ...@@ -1137,9 +1131,9 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev,
} }
if (dev->phy.rev >= 2) { if (dev->phy.rev >= 2) {
if (mode == B43_LPPHY_TXPCTL_HW) if (mode == B43_LPPHY_TXPCTL_HW)
b43_phy_maskset(dev, B43_PHY_OFDM(0xD0), 0xFD, 0x2); b43_phy_set(dev, B43_PHY_OFDM(0xD0), 0x2);
else else
b43_phy_maskset(dev, B43_PHY_OFDM(0xD0), 0xFD, 0); b43_phy_mask(dev, B43_PHY_OFDM(0xD0), 0xFFFD);
} }
lpphy_write_tx_pctl_mode_to_hardware(dev); lpphy_write_tx_pctl_mode_to_hardware(dev);
} }
...@@ -1171,7 +1165,7 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) ...@@ -1171,7 +1165,7 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
err = b43_lpphy_op_switch_channel(dev, 7); err = b43_lpphy_op_switch_channel(dev, 7);
if (err) { if (err) {
b43dbg(dev->wl, b43dbg(dev->wl,
"RC calib: Failed to switch to channel 7, error = %d", "RC calib: Failed to switch to channel 7, error = %d\n",
err); err);
} }
old_txg_ovr = !!(b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40); old_txg_ovr = !!(b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40);
...@@ -1213,7 +1207,7 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) ...@@ -1213,7 +1207,7 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
mean_sq_pwr = ideal_pwr - normal_pwr; mean_sq_pwr = ideal_pwr - normal_pwr;
mean_sq_pwr *= mean_sq_pwr; mean_sq_pwr *= mean_sq_pwr;
inner_sum += mean_sq_pwr; inner_sum += mean_sq_pwr;
if ((i = 128) || (inner_sum < mean_sq_pwr_min)) { if ((i == 128) || (inner_sum < mean_sq_pwr_min)) {
lpphy->rc_cap = i; lpphy->rc_cap = i;
mean_sq_pwr_min = inner_sum; mean_sq_pwr_min = inner_sum;
} }
...@@ -1506,6 +1500,14 @@ static void b43_lpphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) ...@@ -1506,6 +1500,14 @@ static void b43_lpphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
b43_write16(dev, B43_MMIO_PHY_DATA, value); b43_write16(dev, B43_MMIO_PHY_DATA, value);
} }
static void b43_lpphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
u16 set)
{
b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
b43_write16(dev, B43_MMIO_PHY_DATA,
(b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
}
static u16 b43_lpphy_op_radio_read(struct b43_wldev *dev, u16 reg) static u16 b43_lpphy_op_radio_read(struct b43_wldev *dev, u16 reg)
{ {
/* Register 1 is a 32-bit register. */ /* Register 1 is a 32-bit register. */
...@@ -1922,8 +1924,8 @@ static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev) ...@@ -1922,8 +1924,8 @@ static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)
static void lpphy_b2062_vco_calib(struct b43_wldev *dev) static void lpphy_b2062_vco_calib(struct b43_wldev *dev)
{ {
b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x42); b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x42);
b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x62); b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x62);
udelay(200); udelay(200);
} }
...@@ -1982,7 +1984,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev, ...@@ -1982,7 +1984,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,
tmp6 = tmp5 / tmp4; tmp6 = tmp5 / tmp4;
tmp7 = tmp5 % tmp4; tmp7 = tmp5 % tmp4;
b43_radio_write(dev, B2062_S_RFPLL_CTL29, tmp6 + ((2 * tmp7) / tmp4)); b43_radio_write(dev, B2062_S_RFPLL_CTL29, tmp6 + ((2 * tmp7) / tmp4));
tmp8 = b43_phy_read(dev, B2062_S_RFPLL_CTL19); tmp8 = b43_radio_read(dev, B2062_S_RFPLL_CTL19);
tmp9 = ((2 * tmp3 * (tmp8 + 1)) + (3 * tmp1)) / (6 * tmp1); tmp9 = ((2 * tmp3 * (tmp8 + 1)) + (3 * tmp1)) / (6 * tmp1);
b43_radio_write(dev, B2062_S_RFPLL_CTL23, (tmp9 >> 8) + 16); b43_radio_write(dev, B2062_S_RFPLL_CTL23, (tmp9 >> 8) + 16);
b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF); b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF);
...@@ -2021,17 +2023,17 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev) ...@@ -2021,17 +2023,17 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
{ {
u16 tmp; u16 tmp;
b43_phy_mask(dev, B2063_PLL_SP1, ~0x40); b43_radio_mask(dev, B2063_PLL_SP1, ~0x40);
tmp = b43_phy_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8; tmp = b43_radio_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8;
b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp); b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp);
udelay(1); udelay(1);
b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4); b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4);
udelay(1); udelay(1);
b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6); b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6);
udelay(1); udelay(1);
b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7); b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7);
udelay(300); udelay(300);
b43_phy_set(dev, B2063_PLL_SP1, 0x40); b43_radio_set(dev, B2063_PLL_SP1, 0x40);
} }
static int lpphy_b2063_tune(struct b43_wldev *dev, static int lpphy_b2063_tune(struct b43_wldev *dev,
...@@ -2126,31 +2128,31 @@ static int lpphy_b2063_tune(struct b43_wldev *dev, ...@@ -2126,31 +2128,31 @@ static int lpphy_b2063_tune(struct b43_wldev *dev,
scale = 0; scale = 0;
tmp5 = ((tmp4 + (tmp3 >> 1)) / tmp3) - 8; tmp5 = ((tmp4 + (tmp3 >> 1)) / tmp3) - 8;
} }
b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5); b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5);
b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6); b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6);
tmp6 = lpphy_qdiv_roundup(100 * val1, val3, 16); tmp6 = lpphy_qdiv_roundup(100 * val1, val3, 16);
tmp6 *= (tmp5 * 8) * (scale + 1); tmp6 *= (tmp5 * 8) * (scale + 1);
if (tmp6 > 150) if (tmp6 > 150)
tmp6 = 0; tmp6 = 0;
b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6); b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6);
b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5); b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5);
b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4); b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4);
if (crystal_freq > 26000000) if (crystal_freq > 26000000)
b43_phy_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2); b43_radio_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2);
else else
b43_phy_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD); b43_radio_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD);
if (val1 == 45) if (val1 == 45)
b43_phy_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2); b43_radio_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2);
else else
b43_phy_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD); b43_radio_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD);
b43_phy_set(dev, B2063_PLL_SP2, 0x3); b43_radio_set(dev, B2063_PLL_SP2, 0x3);
udelay(1); udelay(1);
b43_phy_mask(dev, B2063_PLL_SP2, 0xFFFC); b43_radio_mask(dev, B2063_PLL_SP2, 0xFFFC);
lpphy_b2063_vco_calib(dev); lpphy_b2063_vco_calib(dev);
b43_radio_write(dev, B2063_COMM15, old_comm15); b43_radio_write(dev, B2063_COMM15, old_comm15);
...@@ -2160,10 +2162,9 @@ static int lpphy_b2063_tune(struct b43_wldev *dev, ...@@ -2160,10 +2162,9 @@ static int lpphy_b2063_tune(struct b43_wldev *dev,
static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
unsigned int new_channel) unsigned int new_channel)
{ {
struct b43_phy_lp *lpphy = dev->phy.lp;
int err; int err;
b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
if (dev->phy.radio_ver == 0x2063) { if (dev->phy.radio_ver == 0x2063) {
err = lpphy_b2063_tune(dev, new_channel); err = lpphy_b2063_tune(dev, new_channel);
if (err) if (err)
...@@ -2176,6 +2177,9 @@ static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, ...@@ -2176,6 +2177,9 @@ static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel)); lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel));
} }
lpphy->channel = new_channel;
b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
return 0; return 0;
} }
...@@ -2187,10 +2191,9 @@ static int b43_lpphy_op_init(struct b43_wldev *dev) ...@@ -2187,10 +2191,9 @@ static int b43_lpphy_op_init(struct b43_wldev *dev)
lpphy_baseband_init(dev); lpphy_baseband_init(dev);
lpphy_radio_init(dev); lpphy_radio_init(dev);
lpphy_calibrate_rc(dev); lpphy_calibrate_rc(dev);
err = b43_lpphy_op_switch_channel(dev, err = b43_lpphy_op_switch_channel(dev, 7);
b43_lpphy_op_get_default_chan(dev));
if (err) { if (err) {
b43dbg(dev->wl, "Switch to init channel failed, error = %d.\n", b43dbg(dev->wl, "Switch to channel 7 failed, error = %d.\n",
err); err);
} }
lpphy_tx_pctl_init(dev); lpphy_tx_pctl_init(dev);
...@@ -2202,7 +2205,14 @@ static int b43_lpphy_op_init(struct b43_wldev *dev) ...@@ -2202,7 +2205,14 @@ static int b43_lpphy_op_init(struct b43_wldev *dev)
static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
{ {
//TODO if (dev->phy.rev >= 2)
return; // rev2+ doesn't support antenna diversity
if (B43_WARN_ON(antenna > B43_ANTENNA_AUTO1))
return;
b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFD, antenna & 0x2);
b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFE, antenna & 0x1);
} }
static void b43_lpphy_op_adjust_txpower(struct b43_wldev *dev) static void b43_lpphy_op_adjust_txpower(struct b43_wldev *dev)
...@@ -2224,6 +2234,7 @@ const struct b43_phy_operations b43_phyops_lp = { ...@@ -2224,6 +2234,7 @@ const struct b43_phy_operations b43_phyops_lp = {
.init = b43_lpphy_op_init, .init = b43_lpphy_op_init,
.phy_read = b43_lpphy_op_read, .phy_read = b43_lpphy_op_read,
.phy_write = b43_lpphy_op_write, .phy_write = b43_lpphy_op_write,
.phy_maskset = b43_lpphy_op_maskset,
.radio_read = b43_lpphy_op_radio_read, .radio_read = b43_lpphy_op_radio_read,
.radio_write = b43_lpphy_op_radio_write, .radio_write = b43_lpphy_op_radio_write,
.software_rfkill = b43_lpphy_op_software_rfkill, .software_rfkill = b43_lpphy_op_software_rfkill,
......
...@@ -888,6 +888,9 @@ struct b43_phy_lp { ...@@ -888,6 +888,9 @@ struct b43_phy_lp {
bool crs_usr_disable, crs_sys_disable; bool crs_usr_disable, crs_sys_disable;
unsigned int pdiv; unsigned int pdiv;
/* The channel we are tuned to */
u8 channel;
}; };
enum tssi_mux_mode { enum tssi_mux_mode {
......
...@@ -624,30 +624,35 @@ u32 b43_lptab_read(struct b43_wldev *dev, u32 offset) ...@@ -624,30 +624,35 @@ u32 b43_lptab_read(struct b43_wldev *dev, u32 offset)
void b43_lptab_read_bulk(struct b43_wldev *dev, u32 offset, void b43_lptab_read_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, void *_data) unsigned int nr_elements, void *_data)
{ {
u32 type, value; u32 type;
u8 *data = _data; u8 *data = _data;
unsigned int i; unsigned int i;
type = offset & B43_LPTAB_TYPEMASK; type = offset & B43_LPTAB_TYPEMASK;
offset &= ~B43_LPTAB_TYPEMASK;
B43_WARN_ON(offset > 0xFFFF);
b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
for (i = 0; i < nr_elements; i++) { for (i = 0; i < nr_elements; i++) {
value = b43_lptab_read(dev, offset);
switch (type) { switch (type) {
case B43_LPTAB_8BIT: case B43_LPTAB_8BIT:
*data = value; *data = b43_phy_read(dev, B43_LPPHY_TABLEDATALO) & 0xFF;
data++; data++;
break; break;
case B43_LPTAB_16BIT: case B43_LPTAB_16BIT:
*((u16 *)data) = value; *((u16 *)data) = b43_phy_read(dev, B43_LPPHY_TABLEDATALO);
data += 2; data += 2;
break; break;
case B43_LPTAB_32BIT: case B43_LPTAB_32BIT:
*((u32 *)data) = value; *((u32 *)data) = b43_phy_read(dev, B43_LPPHY_TABLEDATAHI);
*((u32 *)data) <<= 16;
*((u32 *)data) |= b43_phy_read(dev, B43_LPPHY_TABLEDATALO);
data += 4; data += 4;
break; break;
default: default:
B43_WARN_ON(1); B43_WARN_ON(1);
} }
offset++;
} }
} }
...@@ -688,26 +693,34 @@ void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset, ...@@ -688,26 +693,34 @@ void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int i; unsigned int i;
type = offset & B43_LPTAB_TYPEMASK; type = offset & B43_LPTAB_TYPEMASK;
offset &= ~B43_LPTAB_TYPEMASK;
B43_WARN_ON(offset > 0xFFFF);
b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
for (i = 0; i < nr_elements; i++) { for (i = 0; i < nr_elements; i++) {
switch (type) { switch (type) {
case B43_LPTAB_8BIT: case B43_LPTAB_8BIT:
value = *data; value = *data;
data++; data++;
B43_WARN_ON(value & ~0xFF);
b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
break; break;
case B43_LPTAB_16BIT: case B43_LPTAB_16BIT:
value = *((u16 *)data); value = *((u16 *)data);
data += 2; data += 2;
B43_WARN_ON(value & ~0xFFFF);
b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
break; break;
case B43_LPTAB_32BIT: case B43_LPTAB_32BIT:
value = *((u32 *)data); value = *((u32 *)data);
data += 4; data += 4;
b43_phy_write(dev, B43_LPPHY_TABLEDATAHI, value >> 16);
b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
break; break;
default: default:
B43_WARN_ON(1); B43_WARN_ON(1);
value = 0;
} }
b43_lptab_write(dev, offset, value);
offset++;
} }
} }
...@@ -777,7 +790,7 @@ static const u8 lpphy_pll_fraction_table[] = { ...@@ -777,7 +790,7 @@ static const u8 lpphy_pll_fraction_table[] = {
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
}; };
static const u16 lpphy_iq_local_table[] = { static const u16 lpphy_iqlo_cal_table[] = {
0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
...@@ -789,10 +802,17 @@ static const u16 lpphy_iq_local_table[] = { ...@@ -789,10 +802,17 @@ static const u16 lpphy_iq_local_table[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
}; };
static const u16 lpphy_ofdm_cck_gain_table[] = { static const u16 lpphy_rev0_ofdm_cck_gain_table[] = {
0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001,
0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075,
0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d,
0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d, 0x755d,
};
static const u16 lpphy_rev1_ofdm_cck_gain_table[] = {
0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001, 0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001,
0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075,
0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d,
...@@ -2263,11 +2283,18 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev) ...@@ -2263,11 +2283,18 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev)
b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0), b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table); ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0), b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
ARRAY_SIZE(lpphy_iq_local_table), lpphy_iq_local_table); ARRAY_SIZE(lpphy_iqlo_cal_table), lpphy_iqlo_cal_table);
b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), if (dev->phy.rev == 0) {
ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table); b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), ARRAY_SIZE(lpphy_rev0_ofdm_cck_gain_table), lpphy_rev0_ofdm_cck_gain_table);
ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table); b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
ARRAY_SIZE(lpphy_rev0_ofdm_cck_gain_table), lpphy_rev0_ofdm_cck_gain_table);
} else {
b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
ARRAY_SIZE(lpphy_rev1_ofdm_cck_gain_table), lpphy_rev1_ofdm_cck_gain_table);
b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
ARRAY_SIZE(lpphy_rev1_ofdm_cck_gain_table), lpphy_rev1_ofdm_cck_gain_table);
}
b43_lptab_write_bulk(dev, B43_LPTAB16(15, 0), b43_lptab_write_bulk(dev, B43_LPTAB16(15, 0),
ARRAY_SIZE(lpphy_gain_delta_table), lpphy_gain_delta_table); ARRAY_SIZE(lpphy_gain_delta_table), lpphy_gain_delta_table);
b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0), b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
...@@ -2281,22 +2308,6 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev) ...@@ -2281,22 +2308,6 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
B43_WARN_ON(dev->phy.rev < 2); B43_WARN_ON(dev->phy.rev < 2);
/*
* FIXME This code follows the specs, but it looks wrong:
* In each pass, it writes 4 bytes to an offset in table ID 7,
* then increments the offset by 1 for the next pass. This results
* in the first 3 bytes of each pass except the first one getting
* written to a location that has already been zeroed in the previous
* pass.
* This is what the vendor driver does, but it still looks suspicious.
*
* This should probably suffice:
*
* for (i = 0; i < 704; i+=4)
* b43_lptab_write(dev, B43_LPTAB32(7, i), 0)
*
* This should be tested once the code is functional.
*/
for (i = 0; i < 704; i++) for (i = 0; i < 704; i++)
b43_lptab_write(dev, B43_LPTAB32(7, i), 0); b43_lptab_write(dev, B43_LPTAB32(7, i), 0);
...@@ -2323,7 +2334,7 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev) ...@@ -2323,7 +2334,7 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0), b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table); ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0), b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
ARRAY_SIZE(lpphy_iq_local_table), lpphy_iq_local_table); ARRAY_SIZE(lpphy_iqlo_cal_table), lpphy_iqlo_cal_table);
b43_lptab_write_bulk(dev, B43_LPTAB32(9, 0), b43_lptab_write_bulk(dev, B43_LPTAB32(9, 0),
ARRAY_SIZE(lpphy_papd_eps_table), lpphy_papd_eps_table); ARRAY_SIZE(lpphy_papd_eps_table), lpphy_papd_eps_table);
b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0), b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
file called LICENSE. file called LICENSE.
Contact Information: Contact Information:
James P. Ketrenos <ipw2100-admin@linux.intel.com> Intel Linux Wireless <ilw@linux.intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
******************************************************************************/ ******************************************************************************/
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include "ieee80211.h" #include "libipw.h"
struct ipw2100_priv; struct ipw2100_priv;
struct ipw2100_tx_packet; struct ipw2100_tx_packet;
...@@ -343,7 +343,7 @@ struct ipw2100_tx_packet { ...@@ -343,7 +343,7 @@ struct ipw2100_tx_packet {
struct { /* DATA */ struct { /* DATA */
struct ipw2100_data_header *data; struct ipw2100_data_header *data;
dma_addr_t data_phys; dma_addr_t data_phys;
struct ieee80211_txb *txb; struct libipw_txb *txb;
} d_struct; } d_struct;
} info; } info;
int jiffy_start; int jiffy_start;
...@@ -492,7 +492,7 @@ struct ipw2100_priv { ...@@ -492,7 +492,7 @@ struct ipw2100_priv {
int stop_hang_check; /* Set 1 when shutting down to kill hang_check */ int stop_hang_check; /* Set 1 when shutting down to kill hang_check */
int stop_rf_kill; /* Set 1 when shutting down to kill rf_kill */ int stop_rf_kill; /* Set 1 when shutting down to kill rf_kill */
struct ieee80211_device *ieee; struct libipw_device *ieee;
unsigned long status; unsigned long status;
unsigned long config; unsigned long config;
unsigned long capability; unsigned long capability;
...@@ -788,7 +788,7 @@ struct ipw2100_priv { ...@@ -788,7 +788,7 @@ struct ipw2100_priv {
#define IPW_CARD_DISABLE_PHY_OFF_COMPLETE_WAIT 100 // 100 milli #define IPW_CARD_DISABLE_PHY_OFF_COMPLETE_WAIT 100 // 100 milli
#define IPW_PREPARE_POWER_DOWN_COMPLETE_WAIT 100 // 100 milli #define IPW_PREPARE_POWER_DOWN_COMPLETE_WAIT 100 // 100 milli
#define IPW_HEADER_802_11_SIZE sizeof(struct ieee80211_hdr_3addr) #define IPW_HEADER_802_11_SIZE sizeof(struct libipw_hdr_3addr)
#define IPW_MAX_80211_PAYLOAD_SIZE 2304U #define IPW_MAX_80211_PAYLOAD_SIZE 2304U
#define IPW_MAX_802_11_PAYLOAD_LENGTH 2312 #define IPW_MAX_802_11_PAYLOAD_LENGTH 2312
#define IPW_MAX_ACCEPTABLE_TX_FRAME_LENGTH 1536 #define IPW_MAX_ACCEPTABLE_TX_FRAME_LENGTH 1536
...@@ -803,13 +803,13 @@ struct ipw2100_priv { ...@@ -803,13 +803,13 @@ struct ipw2100_priv {
IPW_802_11_FCS_LENGTH) IPW_802_11_FCS_LENGTH)
#define IPW_802_11_PAYLOAD_OFFSET \ #define IPW_802_11_PAYLOAD_OFFSET \
(sizeof(struct ieee80211_hdr_3addr) + \ (sizeof(struct libipw_hdr_3addr) + \
sizeof(struct ieee80211_snap_hdr)) sizeof(struct libipw_snap_hdr))
struct ipw2100_rx { struct ipw2100_rx {
union { union {
unsigned char payload[IPW_RX_NIC_BUFFER_LENGTH]; unsigned char payload[IPW_RX_NIC_BUFFER_LENGTH];
struct ieee80211_hdr_4addr header; struct libipw_hdr_4addr header;
u32 status; u32 status;
struct ipw2100_notification notification; struct ipw2100_notification notification;
struct ipw2100_cmd_header command; struct ipw2100_cmd_header command;
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
file called LICENSE. file called LICENSE.
Contact Information: Contact Information:
James P. Ketrenos <ipw2100-admin@linux.intel.com> Intel Linux Wireless <ilw@linux.intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
******************************************************************************/ ******************************************************************************/
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include "ieee80211.h" #include "libipw.h"
/* Authentication and Association States */ /* Authentication and Association States */
enum connection_manager_assoc_states { enum connection_manager_assoc_states {
...@@ -365,8 +365,8 @@ enum connection_manager_assoc_states { ...@@ -365,8 +365,8 @@ enum connection_manager_assoc_states {
/* QoS sturctures */ /* QoS sturctures */
struct ipw_qos_info { struct ipw_qos_info {
int qos_enable; int qos_enable;
struct ieee80211_qos_parameters *def_qos_parm_OFDM; struct libipw_qos_parameters *def_qos_parm_OFDM;
struct ieee80211_qos_parameters *def_qos_parm_CCK; struct libipw_qos_parameters *def_qos_parm_CCK;
u32 burst_duration_CCK; u32 burst_duration_CCK;
u32 burst_duration_OFDM; u32 burst_duration_OFDM;
u16 qos_no_ack_mask; u16 qos_no_ack_mask;
...@@ -534,7 +534,7 @@ typedef void destructor_func(const void *); ...@@ -534,7 +534,7 @@ typedef void destructor_func(const void *);
struct clx2_tx_queue { struct clx2_tx_queue {
struct clx2_queue q; struct clx2_queue q;
struct tfd_frame *bd; struct tfd_frame *bd;
struct ieee80211_txb **txb; struct libipw_txb **txb;
}; };
/* /*
...@@ -1144,7 +1144,7 @@ enum ipw_prom_filter { ...@@ -1144,7 +1144,7 @@ enum ipw_prom_filter {
struct ipw_priv; struct ipw_priv;
struct ipw_prom_priv { struct ipw_prom_priv {
struct ipw_priv *priv; struct ipw_priv *priv;
struct ieee80211_device *ieee; struct libipw_device *ieee;
enum ipw_prom_filter filter; enum ipw_prom_filter filter;
int tx_packets; int tx_packets;
int rx_packets; int rx_packets;
...@@ -1175,7 +1175,7 @@ struct ipw_rt_hdr { ...@@ -1175,7 +1175,7 @@ struct ipw_rt_hdr {
struct ipw_priv { struct ipw_priv {
/* ieee device used by generic ieee processing code */ /* ieee device used by generic ieee processing code */
struct ieee80211_device *ieee; struct libipw_device *ieee;
spinlock_t lock; spinlock_t lock;
spinlock_t irq_lock; spinlock_t irq_lock;
...@@ -1222,7 +1222,7 @@ struct ipw_priv { ...@@ -1222,7 +1222,7 @@ struct ipw_priv {
u32 roaming_threshold; u32 roaming_threshold;
struct ipw_associate assoc_request; struct ipw_associate assoc_request;
struct ieee80211_network *assoc_network; struct libipw_network *assoc_network;
unsigned long ts_scan_abort; unsigned long ts_scan_abort;
struct ipw_supported_rates rates; struct ipw_supported_rates rates;
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
file called LICENSE. file called LICENSE.
Contact Information: Contact Information:
James P. Ketrenos <ipw2100-admin@linux.intel.com> Intel Linux Wireless <ilw@linux.intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
******************************************************************************/ ******************************************************************************/
...@@ -41,9 +41,9 @@ ...@@ -41,9 +41,9 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "ieee80211.h" #include "libipw.h"
int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel) int libipw_is_valid_channel(struct libipw_device *ieee, u8 channel)
{ {
int i; int i;
...@@ -52,27 +52,27 @@ int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel) ...@@ -52,27 +52,27 @@ int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0) if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
return 0; return 0;
if (ieee->freq_band & IEEE80211_24GHZ_BAND) if (ieee->freq_band & LIBIPW_24GHZ_BAND)
for (i = 0; i < ieee->geo.bg_channels; i++) for (i = 0; i < ieee->geo.bg_channels; i++)
/* NOTE: If G mode is currently supported but /* NOTE: If G mode is currently supported but
* this is a B only channel, we don't see it * this is a B only channel, we don't see it
* as valid. */ * as valid. */
if ((ieee->geo.bg[i].channel == channel) && if ((ieee->geo.bg[i].channel == channel) &&
!(ieee->geo.bg[i].flags & IEEE80211_CH_INVALID) && !(ieee->geo.bg[i].flags & LIBIPW_CH_INVALID) &&
(!(ieee->mode & IEEE_G) || (!(ieee->mode & IEEE_G) ||
!(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY))) !(ieee->geo.bg[i].flags & LIBIPW_CH_B_ONLY)))
return IEEE80211_24GHZ_BAND; return LIBIPW_24GHZ_BAND;
if (ieee->freq_band & IEEE80211_52GHZ_BAND) if (ieee->freq_band & LIBIPW_52GHZ_BAND)
for (i = 0; i < ieee->geo.a_channels; i++) for (i = 0; i < ieee->geo.a_channels; i++)
if ((ieee->geo.a[i].channel == channel) && if ((ieee->geo.a[i].channel == channel) &&
!(ieee->geo.a[i].flags & IEEE80211_CH_INVALID)) !(ieee->geo.a[i].flags & LIBIPW_CH_INVALID))
return IEEE80211_52GHZ_BAND; return LIBIPW_52GHZ_BAND;
return 0; return 0;
} }
int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel) int libipw_channel_to_index(struct libipw_device *ieee, u8 channel)
{ {
int i; int i;
...@@ -81,12 +81,12 @@ int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel) ...@@ -81,12 +81,12 @@ int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0) if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
return -1; return -1;
if (ieee->freq_band & IEEE80211_24GHZ_BAND) if (ieee->freq_band & LIBIPW_24GHZ_BAND)
for (i = 0; i < ieee->geo.bg_channels; i++) for (i = 0; i < ieee->geo.bg_channels; i++)
if (ieee->geo.bg[i].channel == channel) if (ieee->geo.bg[i].channel == channel)
return i; return i;
if (ieee->freq_band & IEEE80211_52GHZ_BAND) if (ieee->freq_band & LIBIPW_52GHZ_BAND)
for (i = 0; i < ieee->geo.a_channels; i++) for (i = 0; i < ieee->geo.a_channels; i++)
if (ieee->geo.a[i].channel == channel) if (ieee->geo.a[i].channel == channel)
return i; return i;
...@@ -94,22 +94,22 @@ int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel) ...@@ -94,22 +94,22 @@ int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
return -1; return -1;
} }
u32 ieee80211_channel_to_freq(struct ieee80211_device * ieee, u8 channel) u32 libipw_channel_to_freq(struct libipw_device * ieee, u8 channel)
{ {
const struct ieee80211_channel * ch; const struct libipw_channel * ch;
/* Driver needs to initialize the geography map before using /* Driver needs to initialize the geography map before using
* these helper functions */ * these helper functions */
if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0) if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
return 0; return 0;
ch = ieee80211_get_channel(ieee, channel); ch = libipw_get_channel(ieee, channel);
if (!ch->channel) if (!ch->channel)
return 0; return 0;
return ch->freq; return ch->freq;
} }
u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq) u8 libipw_freq_to_channel(struct libipw_device * ieee, u32 freq)
{ {
int i; int i;
...@@ -120,12 +120,12 @@ u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq) ...@@ -120,12 +120,12 @@ u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
freq /= 100000; freq /= 100000;
if (ieee->freq_band & IEEE80211_24GHZ_BAND) if (ieee->freq_band & LIBIPW_24GHZ_BAND)
for (i = 0; i < ieee->geo.bg_channels; i++) for (i = 0; i < ieee->geo.bg_channels; i++)
if (ieee->geo.bg[i].freq == freq) if (ieee->geo.bg[i].freq == freq)
return ieee->geo.bg[i].channel; return ieee->geo.bg[i].channel;
if (ieee->freq_band & IEEE80211_52GHZ_BAND) if (ieee->freq_band & LIBIPW_52GHZ_BAND)
for (i = 0; i < ieee->geo.a_channels; i++) for (i = 0; i < ieee->geo.a_channels; i++)
if (ieee->geo.a[i].freq == freq) if (ieee->geo.a[i].freq == freq)
return ieee->geo.a[i].channel; return ieee->geo.a[i].channel;
...@@ -133,63 +133,63 @@ u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq) ...@@ -133,63 +133,63 @@ u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
return 0; return 0;
} }
int ieee80211_set_geo(struct ieee80211_device *ieee, int libipw_set_geo(struct libipw_device *ieee,
const struct ieee80211_geo *geo) const struct libipw_geo *geo)
{ {
memcpy(ieee->geo.name, geo->name, 3); memcpy(ieee->geo.name, geo->name, 3);
ieee->geo.name[3] = '\0'; ieee->geo.name[3] = '\0';
ieee->geo.bg_channels = geo->bg_channels; ieee->geo.bg_channels = geo->bg_channels;
ieee->geo.a_channels = geo->a_channels; ieee->geo.a_channels = geo->a_channels;
memcpy(ieee->geo.bg, geo->bg, geo->bg_channels * memcpy(ieee->geo.bg, geo->bg, geo->bg_channels *
sizeof(struct ieee80211_channel)); sizeof(struct libipw_channel));
memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels * memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
sizeof(struct ieee80211_channel)); sizeof(struct libipw_channel));
return 0; return 0;
} }
const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device *ieee) const struct libipw_geo *libipw_get_geo(struct libipw_device *ieee)
{ {
return &ieee->geo; return &ieee->geo;
} }
u8 ieee80211_get_channel_flags(struct ieee80211_device * ieee, u8 channel) u8 libipw_get_channel_flags(struct libipw_device * ieee, u8 channel)
{ {
int index = ieee80211_channel_to_index(ieee, channel); int index = libipw_channel_to_index(ieee, channel);
if (index == -1) if (index == -1)
return IEEE80211_CH_INVALID; return LIBIPW_CH_INVALID;
if (channel <= IEEE80211_24GHZ_CHANNELS) if (channel <= LIBIPW_24GHZ_CHANNELS)
return ieee->geo.bg[index].flags; return ieee->geo.bg[index].flags;
return ieee->geo.a[index].flags; return ieee->geo.a[index].flags;
} }
static const struct ieee80211_channel bad_channel = { static const struct libipw_channel bad_channel = {
.channel = 0, .channel = 0,
.flags = IEEE80211_CH_INVALID, .flags = LIBIPW_CH_INVALID,
.max_power = 0, .max_power = 0,
}; };
const struct ieee80211_channel *ieee80211_get_channel(struct ieee80211_device const struct libipw_channel *libipw_get_channel(struct libipw_device
*ieee, u8 channel) *ieee, u8 channel)
{ {
int index = ieee80211_channel_to_index(ieee, channel); int index = libipw_channel_to_index(ieee, channel);
if (index == -1) if (index == -1)
return &bad_channel; return &bad_channel;
if (channel <= IEEE80211_24GHZ_CHANNELS) if (channel <= LIBIPW_24GHZ_CHANNELS)
return &ieee->geo.bg[index]; return &ieee->geo.bg[index];
return &ieee->geo.a[index]; return &ieee->geo.a[index];
} }
EXPORT_SYMBOL(ieee80211_get_channel); EXPORT_SYMBOL(libipw_get_channel);
EXPORT_SYMBOL(ieee80211_get_channel_flags); EXPORT_SYMBOL(libipw_get_channel_flags);
EXPORT_SYMBOL(ieee80211_is_valid_channel); EXPORT_SYMBOL(libipw_is_valid_channel);
EXPORT_SYMBOL(ieee80211_freq_to_channel); EXPORT_SYMBOL(libipw_freq_to_channel);
EXPORT_SYMBOL(ieee80211_channel_to_freq); EXPORT_SYMBOL(libipw_channel_to_freq);
EXPORT_SYMBOL(ieee80211_channel_to_index); EXPORT_SYMBOL(libipw_channel_to_index);
EXPORT_SYMBOL(ieee80211_set_geo); EXPORT_SYMBOL(libipw_set_geo);
EXPORT_SYMBOL(ieee80211_get_geo); EXPORT_SYMBOL(libipw_get_geo);
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
file called LICENSE. file called LICENSE.
Contact Information: Contact Information:
James P. Ketrenos <ipw2100-admin@linux.intel.com> Intel Linux Wireless <ilw@linux.intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/ *******************************************************************************/
...@@ -50,11 +50,11 @@ ...@@ -50,11 +50,11 @@
#include <net/net_namespace.h> #include <net/net_namespace.h>
#include <net/arp.h> #include <net/arp.h>
#include "ieee80211.h" #include "libipw.h"
#define DRV_DESCRIPTION "802.11 data/management/control stack" #define DRV_DESCRIPTION "802.11 data/management/control stack"
#define DRV_NAME "ieee80211" #define DRV_NAME "ieee80211"
#define DRV_VERSION IEEE80211_VERSION #define DRV_VERSION LIBIPW_VERSION
#define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>" #define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
MODULE_VERSION(DRV_VERSION); MODULE_VERSION(DRV_VERSION);
...@@ -62,13 +62,16 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); ...@@ -62,13 +62,16 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_AUTHOR(DRV_COPYRIGHT); MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int ieee80211_networks_allocate(struct ieee80211_device *ieee) struct cfg80211_ops libipw_config_ops = { };
void *libipw_wiphy_privid = &libipw_wiphy_privid;
static int libipw_networks_allocate(struct libipw_device *ieee)
{ {
if (ieee->networks) if (ieee->networks)
return 0; return 0;
ieee->networks = ieee->networks =
kzalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network), kzalloc(MAX_NETWORK_COUNT * sizeof(struct libipw_network),
GFP_KERNEL); GFP_KERNEL);
if (!ieee->networks) { if (!ieee->networks) {
printk(KERN_WARNING "%s: Out of memory allocating beacons\n", printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
...@@ -79,7 +82,7 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee) ...@@ -79,7 +82,7 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
return 0; return 0;
} }
void ieee80211_network_reset(struct ieee80211_network *network) void libipw_network_reset(struct libipw_network *network)
{ {
if (!network) if (!network)
return; return;
...@@ -90,7 +93,7 @@ void ieee80211_network_reset(struct ieee80211_network *network) ...@@ -90,7 +93,7 @@ void ieee80211_network_reset(struct ieee80211_network *network)
} }
} }
static inline void ieee80211_networks_free(struct ieee80211_device *ieee) static inline void libipw_networks_free(struct libipw_device *ieee)
{ {
int i; int i;
...@@ -105,10 +108,10 @@ static inline void ieee80211_networks_free(struct ieee80211_device *ieee) ...@@ -105,10 +108,10 @@ static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
ieee->networks = NULL; ieee->networks = NULL;
} }
void ieee80211_networks_age(struct ieee80211_device *ieee, void libipw_networks_age(struct libipw_device *ieee,
unsigned long age_secs) unsigned long age_secs)
{ {
struct ieee80211_network *network = NULL; struct libipw_network *network = NULL;
unsigned long flags; unsigned long flags;
unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC); unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
...@@ -118,9 +121,9 @@ void ieee80211_networks_age(struct ieee80211_device *ieee, ...@@ -118,9 +121,9 @@ void ieee80211_networks_age(struct ieee80211_device *ieee,
} }
spin_unlock_irqrestore(&ieee->lock, flags); spin_unlock_irqrestore(&ieee->lock, flags);
} }
EXPORT_SYMBOL(ieee80211_networks_age); EXPORT_SYMBOL(libipw_networks_age);
static void ieee80211_networks_initialize(struct ieee80211_device *ieee) static void libipw_networks_initialize(struct libipw_device *ieee)
{ {
int i; int i;
...@@ -131,38 +134,59 @@ static void ieee80211_networks_initialize(struct ieee80211_device *ieee) ...@@ -131,38 +134,59 @@ static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
&ieee->network_free_list); &ieee->network_free_list);
} }
int ieee80211_change_mtu(struct net_device *dev, int new_mtu) int libipw_change_mtu(struct net_device *dev, int new_mtu)
{ {
if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN)) if ((new_mtu < 68) || (new_mtu > LIBIPW_DATA_LEN))
return -EINVAL; return -EINVAL;
dev->mtu = new_mtu; dev->mtu = new_mtu;
return 0; return 0;
} }
EXPORT_SYMBOL(ieee80211_change_mtu); EXPORT_SYMBOL(libipw_change_mtu);
struct net_device *alloc_ieee80211(int sizeof_priv) struct net_device *alloc_ieee80211(int sizeof_priv, int monitor)
{ {
struct ieee80211_device *ieee; struct libipw_device *ieee;
struct net_device *dev; struct net_device *dev;
int err; int err;
IEEE80211_DEBUG_INFO("Initializing...\n"); LIBIPW_DEBUG_INFO("Initializing...\n");
dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv); dev = alloc_etherdev(sizeof(struct libipw_device) + sizeof_priv);
if (!dev) { if (!dev) {
IEEE80211_ERROR("Unable to allocate network device.\n"); LIBIPW_ERROR("Unable to allocate network device.\n");
goto failed; goto failed;
} }
ieee = netdev_priv(dev); ieee = netdev_priv(dev);
ieee->dev = dev; ieee->dev = dev;
err = ieee80211_networks_allocate(ieee); if (!monitor) {
ieee->wdev.wiphy = wiphy_new(&libipw_config_ops, 0);
if (!ieee->wdev.wiphy) {
LIBIPW_ERROR("Unable to allocate wiphy.\n");
goto failed_free_netdev;
}
ieee->dev->ieee80211_ptr = &ieee->wdev;
ieee->wdev.iftype = NL80211_IFTYPE_STATION;
/* Fill-out wiphy structure bits we know... Not enough info
here to call set_wiphy_dev or set MAC address or channel info
-- have to do that in ->ndo_init... */
ieee->wdev.wiphy->privid = libipw_wiphy_privid;
ieee->wdev.wiphy->max_scan_ssids = 1;
ieee->wdev.wiphy->max_scan_ie_len = 0;
ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
| BIT(NL80211_IFTYPE_ADHOC);
}
err = libipw_networks_allocate(ieee);
if (err) { if (err) {
IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err); LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
goto failed_free_netdev; goto failed_free_wiphy;
} }
ieee80211_networks_initialize(ieee); libipw_networks_initialize(ieee);
/* Default fragmentation threshold is maximum payload size */ /* Default fragmentation threshold is maximum payload size */
ieee->fts = DEFAULT_FTS; ieee->fts = DEFAULT_FTS;
...@@ -193,33 +217,45 @@ struct net_device *alloc_ieee80211(int sizeof_priv) ...@@ -193,33 +217,45 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
return dev; return dev;
failed_free_wiphy:
if (!monitor)
wiphy_free(ieee->wdev.wiphy);
failed_free_netdev: failed_free_netdev:
free_netdev(dev); free_netdev(dev);
failed: failed:
return NULL; return NULL;
} }
void free_ieee80211(struct net_device *dev) void free_ieee80211(struct net_device *dev, int monitor)
{ {
struct ieee80211_device *ieee = netdev_priv(dev); struct libipw_device *ieee = netdev_priv(dev);
lib80211_crypt_info_free(&ieee->crypt_info); lib80211_crypt_info_free(&ieee->crypt_info);
ieee80211_networks_free(ieee); libipw_networks_free(ieee);
/* free cfg80211 resources */
if (!monitor) {
wiphy_unregister(ieee->wdev.wiphy);
kfree(ieee->a_band.channels);
kfree(ieee->bg_band.channels);
wiphy_free(ieee->wdev.wiphy);
}
free_netdev(dev); free_netdev(dev);
} }
#ifdef CONFIG_LIBIPW_DEBUG #ifdef CONFIG_LIBIPW_DEBUG
static int debug = 0; static int debug = 0;
u32 ieee80211_debug_level = 0; u32 libipw_debug_level = 0;
EXPORT_SYMBOL_GPL(ieee80211_debug_level); EXPORT_SYMBOL_GPL(libipw_debug_level);
static struct proc_dir_entry *ieee80211_proc = NULL; static struct proc_dir_entry *libipw_proc = NULL;
static int show_debug_level(char *page, char **start, off_t offset, static int show_debug_level(char *page, char **start, off_t offset,
int count, int *eof, void *data) int count, int *eof, void *data)
{ {
return snprintf(page, count, "0x%08X\n", ieee80211_debug_level); return snprintf(page, count, "0x%08X\n", libipw_debug_level);
} }
static int store_debug_level(struct file *file, const char __user * buffer, static int store_debug_level(struct file *file, const char __user * buffer,
...@@ -236,29 +272,29 @@ static int store_debug_level(struct file *file, const char __user * buffer, ...@@ -236,29 +272,29 @@ static int store_debug_level(struct file *file, const char __user * buffer,
printk(KERN_INFO DRV_NAME printk(KERN_INFO DRV_NAME
": %s is not in hex or decimal form.\n", buf); ": %s is not in hex or decimal form.\n", buf);
else else
ieee80211_debug_level = val; libipw_debug_level = val;
return strnlen(buf, len); return strnlen(buf, len);
} }
#endif /* CONFIG_LIBIPW_DEBUG */ #endif /* CONFIG_LIBIPW_DEBUG */
static int __init ieee80211_init(void) static int __init libipw_init(void)
{ {
#ifdef CONFIG_LIBIPW_DEBUG #ifdef CONFIG_LIBIPW_DEBUG
struct proc_dir_entry *e; struct proc_dir_entry *e;
ieee80211_debug_level = debug; libipw_debug_level = debug;
ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net); libipw_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
if (ieee80211_proc == NULL) { if (libipw_proc == NULL) {
IEEE80211_ERROR("Unable to create " DRV_NAME LIBIPW_ERROR("Unable to create " DRV_NAME
" proc directory\n"); " proc directory\n");
return -EIO; return -EIO;
} }
e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR, e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
ieee80211_proc); libipw_proc);
if (!e) { if (!e) {
remove_proc_entry(DRV_NAME, init_net.proc_net); remove_proc_entry(DRV_NAME, init_net.proc_net);
ieee80211_proc = NULL; libipw_proc = NULL;
return -EIO; return -EIO;
} }
e->read_proc = show_debug_level; e->read_proc = show_debug_level;
...@@ -272,13 +308,13 @@ static int __init ieee80211_init(void) ...@@ -272,13 +308,13 @@ static int __init ieee80211_init(void)
return 0; return 0;
} }
static void __exit ieee80211_exit(void) static void __exit libipw_exit(void)
{ {
#ifdef CONFIG_LIBIPW_DEBUG #ifdef CONFIG_LIBIPW_DEBUG
if (ieee80211_proc) { if (libipw_proc) {
remove_proc_entry("debug_level", ieee80211_proc); remove_proc_entry("debug_level", libipw_proc);
remove_proc_entry(DRV_NAME, init_net.proc_net); remove_proc_entry(DRV_NAME, init_net.proc_net);
ieee80211_proc = NULL; libipw_proc = NULL;
} }
#endif /* CONFIG_LIBIPW_DEBUG */ #endif /* CONFIG_LIBIPW_DEBUG */
} }
...@@ -289,8 +325,8 @@ module_param(debug, int, 0444); ...@@ -289,8 +325,8 @@ module_param(debug, int, 0444);
MODULE_PARM_DESC(debug, "debug output mask"); MODULE_PARM_DESC(debug, "debug output mask");
#endif /* CONFIG_LIBIPW_DEBUG */ #endif /* CONFIG_LIBIPW_DEBUG */
module_exit(ieee80211_exit); module_exit(libipw_exit);
module_init(ieee80211_init); module_init(libipw_init);
EXPORT_SYMBOL(alloc_ieee80211); EXPORT_SYMBOL(alloc_ieee80211);
EXPORT_SYMBOL(free_ieee80211); EXPORT_SYMBOL(free_ieee80211);
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
file called LICENSE. file called LICENSE.
Contact Information: Contact Information:
James P. Ketrenos <ipw2100-admin@linux.intel.com> Intel Linux Wireless <ilw@linux.intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
******************************************************************************/ ******************************************************************************/
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "ieee80211.h" #include "libipw.h"
/* /*
...@@ -126,12 +126,12 @@ payload of each frame is reduced to 492 bytes. ...@@ -126,12 +126,12 @@ payload of each frame is reduced to 492 bytes.
static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
static int ieee80211_copy_snap(u8 * data, __be16 h_proto) static int libipw_copy_snap(u8 * data, __be16 h_proto)
{ {
struct ieee80211_snap_hdr *snap; struct libipw_snap_hdr *snap;
u8 *oui; u8 *oui;
snap = (struct ieee80211_snap_hdr *)data; snap = (struct libipw_snap_hdr *)data;
snap->dsap = 0xaa; snap->dsap = 0xaa;
snap->ssap = 0xaa; snap->ssap = 0xaa;
snap->ctrl = 0x03; snap->ctrl = 0x03;
...@@ -149,7 +149,7 @@ static int ieee80211_copy_snap(u8 * data, __be16 h_proto) ...@@ -149,7 +149,7 @@ static int ieee80211_copy_snap(u8 * data, __be16 h_proto)
return SNAP_SIZE + sizeof(u16); return SNAP_SIZE + sizeof(u16);
} }
static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, static int libipw_encrypt_fragment(struct libipw_device *ieee,
struct sk_buff *frag, int hdr_len) struct sk_buff *frag, int hdr_len)
{ {
struct lib80211_crypt_data *crypt = struct lib80211_crypt_data *crypt =
...@@ -177,7 +177,7 @@ static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, ...@@ -177,7 +177,7 @@ static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
return 0; return 0;
} }
void ieee80211_txb_free(struct ieee80211_txb *txb) void libipw_txb_free(struct libipw_txb *txb)
{ {
int i; int i;
if (unlikely(!txb)) if (unlikely(!txb))
...@@ -188,17 +188,17 @@ void ieee80211_txb_free(struct ieee80211_txb *txb) ...@@ -188,17 +188,17 @@ void ieee80211_txb_free(struct ieee80211_txb *txb)
kfree(txb); kfree(txb);
} }
static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, static struct libipw_txb *libipw_alloc_txb(int nr_frags, int txb_size,
int headroom, gfp_t gfp_mask) int headroom, gfp_t gfp_mask)
{ {
struct ieee80211_txb *txb; struct libipw_txb *txb;
int i; int i;
txb = kmalloc(sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags), txb = kmalloc(sizeof(struct libipw_txb) + (sizeof(u8 *) * nr_frags),
gfp_mask); gfp_mask);
if (!txb) if (!txb)
return NULL; return NULL;
memset(txb, 0, sizeof(struct ieee80211_txb)); memset(txb, 0, sizeof(struct libipw_txb));
txb->nr_frags = nr_frags; txb->nr_frags = nr_frags;
txb->frag_size = txb_size; txb->frag_size = txb_size;
...@@ -220,7 +220,7 @@ static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, ...@@ -220,7 +220,7 @@ static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
return txb; return txb;
} }
static int ieee80211_classify(struct sk_buff *skb) static int libipw_classify(struct sk_buff *skb)
{ {
struct ethhdr *eth; struct ethhdr *eth;
struct iphdr *ip; struct iphdr *ip;
...@@ -252,11 +252,11 @@ static int ieee80211_classify(struct sk_buff *skb) ...@@ -252,11 +252,11 @@ static int ieee80211_classify(struct sk_buff *skb)
/* Incoming skb is converted to a txb which consists of /* Incoming skb is converted to a txb which consists of
* a block of 802.11 fragment packets (stored as skbs) */ * a block of 802.11 fragment packets (stored as skbs) */
int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) int libipw_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct ieee80211_device *ieee = netdev_priv(dev); struct libipw_device *ieee = netdev_priv(dev);
struct ieee80211_txb *txb = NULL; struct libipw_txb *txb = NULL;
struct ieee80211_hdr_3addrqos *frag_hdr; struct libipw_hdr_3addrqos *frag_hdr;
int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size, int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
rts_required; rts_required;
unsigned long flags; unsigned long flags;
...@@ -264,7 +264,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -264,7 +264,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
__be16 ether_type; __be16 ether_type;
int bytes, fc, hdr_len; int bytes, fc, hdr_len;
struct sk_buff *skb_frag; struct sk_buff *skb_frag;
struct ieee80211_hdr_3addrqos header = {/* Ensure zero initialized */ struct libipw_hdr_3addrqos header = {/* Ensure zero initialized */
.duration_id = 0, .duration_id = 0,
.seq_ctl = 0, .seq_ctl = 0,
.qos_ctl = 0 .qos_ctl = 0
...@@ -331,14 +331,14 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -331,14 +331,14 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
memcpy(header.addr2, src, ETH_ALEN); memcpy(header.addr2, src, ETH_ALEN);
memcpy(header.addr3, ieee->bssid, ETH_ALEN); memcpy(header.addr3, ieee->bssid, ETH_ALEN);
} }
hdr_len = IEEE80211_3ADDR_LEN; hdr_len = LIBIPW_3ADDR_LEN;
if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) { if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) {
fc |= IEEE80211_STYPE_QOS_DATA; fc |= IEEE80211_STYPE_QOS_DATA;
hdr_len += 2; hdr_len += 2;
skb->priority = ieee80211_classify(skb); skb->priority = libipw_classify(skb);
header.qos_ctl |= cpu_to_le16(skb->priority & IEEE80211_QCTL_TID); header.qos_ctl |= cpu_to_le16(skb->priority & LIBIPW_QCTL_TID);
} }
header.frame_ctl = cpu_to_le16(fc); header.frame_ctl = cpu_to_le16(fc);
...@@ -362,12 +362,12 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -362,12 +362,12 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len); skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
memcpy(skb_put(skb_new, hdr_len), &header, hdr_len); memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
snapped = 1; snapped = 1;
ieee80211_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)), libipw_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),
ether_type); ether_type);
skb_copy_from_linear_data(skb, skb_put(skb_new, skb->len), skb->len); skb_copy_from_linear_data(skb, skb_put(skb_new, skb->len), skb->len);
res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv); res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);
if (res < 0) { if (res < 0) {
IEEE80211_ERROR("msdu encryption failed\n"); LIBIPW_ERROR("msdu encryption failed\n");
dev_kfree_skb_any(skb_new); dev_kfree_skb_any(skb_new);
goto failed; goto failed;
} }
...@@ -393,8 +393,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -393,8 +393,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
* for it when determining the amount of payload space. */ * for it when determining the amount of payload space. */
bytes_per_frag = frag_size - hdr_len; bytes_per_frag = frag_size - hdr_len;
if (ieee->config & if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
bytes_per_frag -= IEEE80211_FCS_LEN; bytes_per_frag -= LIBIPW_FCS_LEN;
/* Each fragment may need to have room for encryptiong /* Each fragment may need to have room for encryptiong
* pre/postfix */ * pre/postfix */
...@@ -417,14 +417,14 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -417,14 +417,14 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
} }
rts_required = (frag_size > ieee->rts rts_required = (frag_size > ieee->rts
&& ieee->config & CFG_IEEE80211_RTS); && ieee->config & CFG_LIBIPW_RTS);
if (rts_required) if (rts_required)
nr_frags++; nr_frags++;
/* When we allocate the TXB we allocate enough space for the reserve /* When we allocate the TXB we allocate enough space for the reserve
* and full fragment bytes (bytes_per_frag doesn't include prefix, * and full fragment bytes (bytes_per_frag doesn't include prefix,
* postfix, header, FCS, etc.) */ * postfix, header, FCS, etc.) */
txb = ieee80211_alloc_txb(nr_frags, frag_size, txb = libipw_alloc_txb(nr_frags, frag_size,
ieee->tx_headroom, GFP_ATOMIC); ieee->tx_headroom, GFP_ATOMIC);
if (unlikely(!txb)) { if (unlikely(!txb)) {
printk(KERN_WARNING "%s: Could not allocate TXB\n", printk(KERN_WARNING "%s: Could not allocate TXB\n",
...@@ -441,7 +441,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -441,7 +441,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
if (rts_required) { if (rts_required) {
skb_frag = txb->fragments[0]; skb_frag = txb->fragments[0];
frag_hdr = frag_hdr =
(struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len); (struct libipw_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
/* /*
* Set header frame_ctl to the RTS. * Set header frame_ctl to the RTS.
...@@ -456,7 +456,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -456,7 +456,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
header.frame_ctl = cpu_to_le16(fc); header.frame_ctl = cpu_to_le16(fc);
if (ieee->config & if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
skb_put(skb_frag, 4); skb_put(skb_frag, 4);
txb->rts_included = 1; txb->rts_included = 1;
...@@ -472,7 +472,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -472,7 +472,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
crypt->ops->extra_mpdu_prefix_len); crypt->ops->extra_mpdu_prefix_len);
frag_hdr = frag_hdr =
(struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len); (struct libipw_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
memcpy(frag_hdr, &header, hdr_len); memcpy(frag_hdr, &header, hdr_len);
/* If this is not the last fragment, then add the MOREFRAGS /* If this is not the last fragment, then add the MOREFRAGS
...@@ -487,7 +487,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -487,7 +487,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
} }
if (i == 0 && !snapped) { if (i == 0 && !snapped) {
ieee80211_copy_snap(skb_put libipw_copy_snap(skb_put
(skb_frag, SNAP_SIZE + sizeof(u16)), (skb_frag, SNAP_SIZE + sizeof(u16)),
ether_type); ether_type);
bytes -= SNAP_SIZE + sizeof(u16); bytes -= SNAP_SIZE + sizeof(u16);
...@@ -501,7 +501,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -501,7 +501,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
/* Encryption routine will move the header forward in order /* Encryption routine will move the header forward in order
* to insert the IV between the header and the payload */ * to insert the IV between the header and the payload */
if (host_encrypt) if (host_encrypt)
ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); libipw_encrypt_fragment(ieee, skb_frag, hdr_len);
else if (host_build_iv) { else if (host_build_iv) {
atomic_inc(&crypt->refcnt); atomic_inc(&crypt->refcnt);
if (crypt->ops->build_iv) if (crypt->ops->build_iv)
...@@ -513,7 +513,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -513,7 +513,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
} }
if (ieee->config & if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
skb_put(skb_frag, 4); skb_put(skb_frag, 4);
} }
...@@ -530,7 +530,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -530,7 +530,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
ieee80211_txb_free(txb); libipw_txb_free(txb);
} }
return NETDEV_TX_OK; return NETDEV_TX_OK;
...@@ -541,6 +541,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -541,6 +541,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_errors++; dev->stats.tx_errors++;
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
EXPORT_SYMBOL(ieee80211_xmit); EXPORT_SYMBOL(libipw_xmit);
EXPORT_SYMBOL(ieee80211_txb_free); EXPORT_SYMBOL(libipw_txb_free);
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册