mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
b7f1d43a2b
100 changed files with 4341 additions and 2701 deletions
14
MAINTAINERS
14
MAINTAINERS
|
@ -2653,25 +2653,21 @@ F: drivers/net/ixgbe/
|
|||
|
||||
INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: James Ketrenos <jketreno@linux.intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
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
|
||||
S: Supported
|
||||
S: Odd Fixes
|
||||
F: Documentation/networking/README.ipw2100
|
||||
F: drivers/net/wireless/ipw2x00/ipw2100.*
|
||||
|
||||
INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: James Ketrenos <jketreno@linux.intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
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
|
||||
S: Supported
|
||||
S: Odd Fixes
|
||||
F: Documentation/networking/README.ipw2200
|
||||
F: drivers/net/wireless/ipw2x00/ipw2200.*
|
||||
|
||||
|
@ -2688,8 +2684,8 @@ F: include/linux/wimax/i2400m.h
|
|||
INTEL WIRELESS WIFI LINK (iwlwifi)
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: ipw3945-devel@lists.sourceforge.net
|
||||
W: http://intellinuxwireless.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git
|
||||
S: Supported
|
||||
|
|
|
@ -178,6 +178,7 @@ struct ar9170 {
|
|||
/* beaconing */
|
||||
struct sk_buff *beacon;
|
||||
struct work_struct beacon_work;
|
||||
bool enable_beacon;
|
||||
|
||||
/* cryptographic engine */
|
||||
u64 usedkeys;
|
||||
|
|
|
@ -383,24 +383,26 @@ int ar9170_set_beacon_timers(struct ar9170 *ar)
|
|||
if (ar->vif) {
|
||||
v |= ar->vif->bss_conf.beacon_int;
|
||||
|
||||
switch (ar->vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
v |= BIT(25);
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
v |= BIT(24);
|
||||
pretbtt = (ar->vif->bss_conf.beacon_int - 6) << 16;
|
||||
break;
|
||||
default:
|
||||
if (ar->enable_beacon) {
|
||||
switch (ar->vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
v |= BIT(25);
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
v |= BIT(24);
|
||||
pretbtt = (ar->vif->bss_conf.beacon_int - 6) <<
|
||||
16;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
v |= ar->vif->bss_conf.dtim_period << 16;
|
||||
}
|
||||
|
||||
ar9170_regwrite_begin(ar);
|
||||
|
||||
ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt);
|
||||
ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v);
|
||||
ar9170_regwrite_finish();
|
||||
|
|
|
@ -2031,12 +2031,6 @@ static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_INT) {
|
||||
err = ar9170_set_beacon_timers(ar);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
|
||||
/* adjust slot time for 5 GHz */
|
||||
|
@ -2148,11 +2142,17 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
|
|||
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);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON |
|
||||
BSS_CHANGED_BEACON_INT)) {
|
||||
err = ar9170_set_beacon_timers(ar);
|
||||
if (err)
|
||||
goto out;
|
||||
|
@ -2165,12 +2165,6 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
|
|||
#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) {
|
||||
/* TODO */
|
||||
err = 0;
|
||||
|
|
|
@ -306,6 +306,7 @@ struct ath5k_srev_name {
|
|||
#define AR5K_SREV_AR5311B 0x30 /* Spirit */
|
||||
#define AR5K_SREV_AR5211 0x40 /* Oahu */
|
||||
#define AR5K_SREV_AR5212 0x50 /* Venice */
|
||||
#define AR5K_SREV_AR5212_V4 0x54 /* ??? */
|
||||
#define AR5K_SREV_AR5213 0x55 /* ??? */
|
||||
#define AR5K_SREV_AR5213A 0x59 /* Hainan */
|
||||
#define AR5K_SREV_AR2413 0x78 /* Griffin lite */
|
||||
|
@ -1037,6 +1038,7 @@ struct ath5k_hw {
|
|||
bool ah_turbo;
|
||||
bool ah_calibration;
|
||||
bool ah_single_chip;
|
||||
bool ah_aes_support;
|
||||
bool ah_combined_mic;
|
||||
|
||||
enum ath5k_version ah_version;
|
||||
|
@ -1158,7 +1160,7 @@ struct ath5k_hw {
|
|||
*/
|
||||
|
||||
/* 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);
|
||||
|
||||
/* LED functions */
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* @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
|
||||
* 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
|
||||
* 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 pci_dev *pdev = sc->pdev;
|
||||
struct ath5k_eeprom_info *ee;
|
||||
int ret;
|
||||
u32 srev;
|
||||
|
||||
|
@ -135,9 +135,15 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
|
|||
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*/
|
||||
ret = ath5k_hw_init_desc_functions(ah);
|
||||
|
@ -150,7 +156,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
|
|||
goto err_free;
|
||||
|
||||
/* Get MAC, PHY and RADIO revisions */
|
||||
srev = ath5k_hw_reg_read(ah, AR5K_SREV);
|
||||
ah->ah_mac_srev = srev;
|
||||
ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
|
||||
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)
|
|||
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) {
|
||||
ah->ah_combined_mic = true;
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE,
|
||||
|
|
|
@ -84,24 +84,24 @@ MODULE_VERSION("0.6.0 (EXPERIMENTAL)");
|
|||
|
||||
/* Known PCI ids */
|
||||
static const struct pci_device_id ath5k_pci_id_table[] = {
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0012), .driver_data = AR5K_AR5211 }, /* 5211 */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0013), .driver_data = AR5K_AR5212 }, /* 5212 */
|
||||
{ PCI_VDEVICE(3COM_2, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 5212 */
|
||||
{ PCI_VDEVICE(3COM, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 3CRDAG675 5212 */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x1014), .driver_data = AR5K_AR5212 }, /* IBM minipci 5212 */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0014), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0015), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0016), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0017), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0018), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0019), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* PCI-E cards */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x001d), .driver_data = AR5K_AR5212 }, /* 2417 Nala */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */
|
||||
{ PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */
|
||||
{ PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
|
||||
{ PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
|
||||
|
@ -566,7 +566,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
|
|||
}
|
||||
|
||||
/* Initialize device */
|
||||
sc->ah = ath5k_hw_attach(sc, id->driver_data);
|
||||
sc->ah = ath5k_hw_attach(sc);
|
||||
if (IS_ERR(sc->ah)) {
|
||||
ret = PTR_ERR(sc->ah);
|
||||
goto err_irq;
|
||||
|
@ -1741,7 +1741,7 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
|
|||
static void
|
||||
ath5k_tasklet_rx(unsigned long data)
|
||||
{
|
||||
struct ieee80211_rx_status rxs = {};
|
||||
struct ieee80211_rx_status *rxs;
|
||||
struct ath5k_rx_status rs = {};
|
||||
struct sk_buff *skb, *next_skb;
|
||||
dma_addr_t next_skb_addr;
|
||||
|
@ -1751,6 +1751,7 @@ ath5k_tasklet_rx(unsigned long data)
|
|||
int ret;
|
||||
int hdrlen;
|
||||
int padsize;
|
||||
int rx_flag;
|
||||
|
||||
spin_lock(&sc->rxbuflock);
|
||||
if (list_empty(&sc->rxbuf)) {
|
||||
|
@ -1758,7 +1759,7 @@ ath5k_tasklet_rx(unsigned long data)
|
|||
goto unlock;
|
||||
}
|
||||
do {
|
||||
rxs.flag = 0;
|
||||
rx_flag = 0;
|
||||
|
||||
bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
|
||||
BUG_ON(bf->skb == NULL);
|
||||
|
@ -1802,7 +1803,7 @@ ath5k_tasklet_rx(unsigned long data)
|
|||
goto accept;
|
||||
}
|
||||
if (rs.rs_status & AR5K_RXERR_MIC) {
|
||||
rxs.flag |= RX_FLAG_MMIC_ERROR;
|
||||
rx_flag |= RX_FLAG_MMIC_ERROR;
|
||||
goto accept;
|
||||
}
|
||||
|
||||
|
@ -1840,6 +1841,7 @@ accept:
|
|||
memmove(skb->data + padsize, skb->data, hdrlen);
|
||||
skb_pull(skb, padsize);
|
||||
}
|
||||
rxs = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
/*
|
||||
* always extend the mac timestamp, since this information is
|
||||
|
@ -1861,41 +1863,40 @@ accept:
|
|||
* impossible to comply to that. This affects IBSS merge only
|
||||
* right now, so it's not too bad...
|
||||
*/
|
||||
rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp);
|
||||
rxs.flag |= RX_FLAG_TSFT;
|
||||
rxs->mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp);
|
||||
rxs->flag = rx_flag | RX_FLAG_TSFT;
|
||||
|
||||
rxs.freq = sc->curchan->center_freq;
|
||||
rxs.band = sc->curband->band;
|
||||
rxs->freq = sc->curchan->center_freq;
|
||||
rxs->band = sc->curband->band;
|
||||
|
||||
rxs.noise = sc->ah->ah_noise_floor;
|
||||
rxs.signal = rxs.noise + rs.rs_rssi;
|
||||
rxs->noise = sc->ah->ah_noise_floor;
|
||||
rxs->signal = rxs->noise + rs.rs_rssi;
|
||||
|
||||
/* An rssi of 35 indicates you should be able use
|
||||
* 54 Mbps reliably. A more elaborate scheme can be used
|
||||
* here but it requires a map of SNR/throughput for each
|
||||
* 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
|
||||
* should be considered at 100% */
|
||||
if (rxs.qual > 100)
|
||||
rxs.qual = 100;
|
||||
if (rxs->qual > 100)
|
||||
rxs->qual = 100;
|
||||
|
||||
rxs.antenna = rs.rs_antenna;
|
||||
rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
|
||||
rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
|
||||
rxs->antenna = rs.rs_antenna;
|
||||
rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
|
||||
rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
|
||||
|
||||
if (rxs.rate_idx >= 0 && rs.rs_rate ==
|
||||
sc->curband->bitrates[rxs.rate_idx].hw_value_short)
|
||||
rxs.flag |= RX_FLAG_SHORTPRE;
|
||||
if (rxs->rate_idx >= 0 && rs.rs_rate ==
|
||||
sc->curband->bitrates[rxs->rate_idx].hw_value_short)
|
||||
rxs->flag |= RX_FLAG_SHORTPRE;
|
||||
|
||||
ath5k_debug_dump_skb(sc, skb, "RX ", 0);
|
||||
|
||||
/* check beacons in IBSS mode */
|
||||
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);
|
||||
|
||||
bf->skb = next_skb;
|
||||
|
@ -2918,6 +2919,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
|
|||
struct ath5k_hw *ah = sc->ah;
|
||||
u32 mfilt[2], rfilt;
|
||||
|
||||
mutex_lock(&sc->lock);
|
||||
|
||||
mfilt[0] = multicast;
|
||||
mfilt[1] = multicast >> 32;
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
if (sc->opmode == NL80211_IFTYPE_MONITOR)
|
||||
rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
|
||||
AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
|
||||
if (sc->opmode != NL80211_IFTYPE_STATION)
|
||||
rfilt |= AR5K_RX_FILTER_PROBEREQ;
|
||||
if (sc->opmode != NL80211_IFTYPE_AP &&
|
||||
sc->opmode != NL80211_IFTYPE_MESH_POINT &&
|
||||
test_bit(ATH_STAT_PROMISC, sc->status))
|
||||
rfilt |= AR5K_RX_FILTER_PROM;
|
||||
if ((sc->opmode == NL80211_IFTYPE_STATION && sc->assoc) ||
|
||||
sc->opmode == NL80211_IFTYPE_ADHOC ||
|
||||
sc->opmode == NL80211_IFTYPE_AP)
|
||||
rfilt |= AR5K_RX_FILTER_BEACON;
|
||||
if (sc->opmode == NL80211_IFTYPE_MESH_POINT)
|
||||
rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
|
||||
AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
|
||||
switch (sc->opmode) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
rfilt |= AR5K_RX_FILTER_CONTROL |
|
||||
AR5K_RX_FILTER_BEACON |
|
||||
AR5K_RX_FILTER_PROBEREQ |
|
||||
AR5K_RX_FILTER_PROM;
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
rfilt |= AR5K_RX_FILTER_PROBEREQ |
|
||||
AR5K_RX_FILTER_BEACON;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (sc->assoc)
|
||||
rfilt |= AR5K_RX_FILTER_BEACON;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set filters */
|
||||
ath5k_hw_set_rx_filter(ah, rfilt);
|
||||
|
@ -2993,6 +2999,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
|
|||
/* Set the cached hw filter flags, this will alter actually
|
||||
* be set in HW */
|
||||
sc->filter_flags = rfilt;
|
||||
|
||||
mutex_unlock(&sc->lock);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -3014,6 +3022,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
case ALG_TKIP:
|
||||
break;
|
||||
case ALG_CCMP:
|
||||
if (sc->ah->ah_aes_support)
|
||||
break;
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
|
|
|
@ -414,27 +414,11 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
|
|||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
/* return new offset */
|
||||
*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;
|
||||
|
||||
/*
|
||||
* Read turbo mode information on newer EEPROM versions
|
||||
*/
|
||||
if (ee->ee_version < AR5K_EEPROM_VERSION_5_0)
|
||||
return 0;
|
||||
goto done;
|
||||
|
||||
switch (mode){
|
||||
case AR5K_EEPROM_MODE_11A:
|
||||
|
@ -468,6 +452,7 @@ ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah,
|
|||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
/* return new offset */
|
||||
*offset = o;
|
||||
|
||||
|
@ -504,10 +489,6 @@ ath5k_eeprom_init_modes(struct ath5k_hw *ah)
|
|||
ret = ath5k_eeprom_read_modes(ah, &offset, mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* override for older eeprom versions for better performance */
|
||||
|
|
|
@ -69,6 +69,8 @@ static const struct pci_device_id ath5k_led_devices[] = {
|
|||
{ ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) },
|
||||
/* IBM ThinkPad AR5BXB6 (legovini@spiro.fisica.unipd.it) */
|
||||
{ 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) */
|
||||
{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) },
|
||||
{ }
|
||||
|
|
|
@ -12,7 +12,8 @@ ath9k-y += hw.o \
|
|||
recv.o \
|
||||
xmit.o \
|
||||
virtual.o \
|
||||
rc.o
|
||||
rc.o \
|
||||
btcoex.o
|
||||
|
||||
ath9k-$(CONFIG_PCI) += pci.o
|
||||
ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "rc.h"
|
||||
#include "debug.h"
|
||||
#include "../ath.h"
|
||||
#include "btcoex.h"
|
||||
|
||||
struct ath_node;
|
||||
|
||||
|
@ -521,6 +522,8 @@ struct ath_led {
|
|||
#define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17)
|
||||
#define SC_OP_WAIT_FOR_TX_ACK BIT(18)
|
||||
#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 {
|
||||
void (*read_cachesize)(struct ath_softc *sc, int *csz);
|
||||
|
@ -609,6 +612,7 @@ struct ath_softc {
|
|||
struct ath_bus_ops *bus_ops;
|
||||
struct ath_beacon_config cur_beacon_conf;
|
||||
struct delayed_work tx_complete_work;
|
||||
struct ath_btcoex_info btcoex_info;
|
||||
};
|
||||
|
||||
struct ath_wiphy {
|
||||
|
@ -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);
|
||||
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 */
|
||||
|
|
319
drivers/net/wireless/ath/ath9k/btcoex.c
Normal file
319
drivers/net/wireless/ath/ath9k/btcoex.c
Normal file
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
98
drivers/net/wireless/ath/ath9k/btcoex.h
Normal file
98
drivers/net/wireless/ath/ath9k/btcoex.h
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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)
|
|||
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;
|
||||
|
@ -877,6 +877,13 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
|
|||
{ 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)) {
|
||||
REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
|
||||
udelay(10);
|
||||
|
@ -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_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_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_PDPAOUT, 0);
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
|
||||
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);
|
||||
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);
|
||||
udelay(30);
|
||||
|
@ -917,7 +924,6 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
|
|||
regVal |= (1 << (19 + i));
|
||||
REG_WRITE(ah, 0x7834, regVal);
|
||||
udelay(1);
|
||||
regVal = REG_READ(ah, 0x7834);
|
||||
regVal &= (~(0x1 << (19 + i)));
|
||||
reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
|
||||
regVal |= (reg_field << (19 + i));
|
||||
|
@ -936,6 +942,17 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
|
|||
offs_6_1 = 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_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
|
||||
|
||||
|
@ -982,8 +999,12 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
/* Do periodic PAOffset Cal */
|
||||
if (AR_SREV_9271(ah))
|
||||
ath9k_hw_9271_pa_cal(ah);
|
||||
else if (AR_SREV_9285_11_OR_LATER(ah))
|
||||
ath9k_hw_9285_pa_cal(ah);
|
||||
else if (AR_SREV_9285_11_OR_LATER(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)
|
||||
ath9k_olc_temp_compensation(ah);
|
||||
|
@ -1081,7 +1102,7 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
|
|||
|
||||
/* Do PA Calibration */
|
||||
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 */
|
||||
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
|
||||
|
|
|
@ -110,6 +110,13 @@ struct ath9k_nfcal_hist {
|
|||
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);
|
||||
void ath9k_hw_start_nfcal(struct ath_hw *ah);
|
||||
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,
|
|||
int i, qcuOffset = 0, dcuOffset = 0;
|
||||
u32 *qcuBase = &val[0], *dcuBase = &val[4];
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
|
||||
REG_WRITE(ah, AR_MACMISC,
|
||||
((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
|
||||
(AR_MACMISC_MISC_OBS_BUS_1 <<
|
||||
|
@ -159,6 +161,8 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
|
|||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"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);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ enum ATH_DEBUG {
|
|||
ATH_DBG_CONFIG = 0x00000200,
|
||||
ATH_DBG_FATAL = 0x00000400,
|
||||
ATH_DBG_PS = 0x00000800,
|
||||
ATH_DBG_HWTIMER = 0x00001000,
|
||||
ATH_DBG_BTCOEX = 0x00002000,
|
||||
ATH_DBG_ANY = 0xffffffff
|
||||
};
|
||||
|
||||
|
|
|
@ -143,10 +143,10 @@ void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
|
|||
IS_CHAN_2GHZ(chan))) {
|
||||
matchIndex = i;
|
||||
break;
|
||||
} else if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
|
||||
IS_CHAN_2GHZ(chan))) &&
|
||||
(freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
|
||||
IS_CHAN_2GHZ(chan)))) {
|
||||
} else if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
|
||||
IS_CHAN_2GHZ(chan)) && i > 0 &&
|
||||
freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
|
||||
IS_CHAN_2GHZ(chan))) {
|
||||
lowIndex = i - 1;
|
||||
break;
|
||||
}
|
||||
|
@ -198,10 +198,10 @@ void ath9k_hw_get_target_powers(struct ath_hw *ah,
|
|||
matchIndex = i;
|
||||
break;
|
||||
} else
|
||||
if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
|
||||
IS_CHAN_2GHZ(chan))) &&
|
||||
(freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
|
||||
IS_CHAN_2GHZ(chan)))) {
|
||||
if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
|
||||
IS_CHAN_2GHZ(chan)) && i > 0 &&
|
||||
freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
|
||||
IS_CHAN_2GHZ(chan))) {
|
||||
lowIndex = i - 1;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2555,6 +2555,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
#endif
|
||||
}
|
||||
|
||||
if (ah->ah_sc->sc_flags & SC_OP_BTCOEX_ENABLED)
|
||||
ath9k_hw_btcoex_enable(ah);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3212,6 +3215,23 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
|
|||
if (AR_SREV_9100(ah))
|
||||
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) {
|
||||
fatal_int =
|
||||
(sync_cause &
|
||||
|
@ -3486,6 +3506,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
|||
{
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info;
|
||||
|
||||
u16 capField = 0, eeval;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah) && btcoex_enable) {
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_BT_COEX;
|
||||
ah->btactive_gpio = 6;
|
||||
ah->wlanactive_gpio = 5;
|
||||
btcoex_info->btactive_gpio = ATH_BTACTIVE_GPIO;
|
||||
btcoex_info->wlanactive_gpio = ATH_WLANACTIVE_GPIO;
|
||||
|
||||
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)
|
|||
REG_WRITE(ah, AR_2040_MODE, macmode);
|
||||
}
|
||||
|
||||
/***************************/
|
||||
/* Bluetooth Coexistence */
|
||||
/***************************/
|
||||
/* HW Generic timers configuration */
|
||||
|
||||
void ath9k_hw_btcoex_enable(struct ath_hw *ah)
|
||||
static const struct ath_gen_timer_configuration gen_tmr_configuration[] =
|
||||
{
|
||||
/* 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));
|
||||
{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}
|
||||
};
|
||||
|
||||
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
|
||||
AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
|
||||
/* HW generic timer primitives */
|
||||
|
||||
/* Set input mux for bt_active to gpio pin */
|
||||
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
|
||||
AR_GPIO_INPUT_MUX1_BT_ACTIVE,
|
||||
ah->btactive_gpio);
|
||||
/* compute and clear index of rightmost 1 */
|
||||
static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask)
|
||||
{
|
||||
u32 b;
|
||||
|
||||
/* Configure the desired gpio port for input */
|
||||
ath9k_hw_cfg_gpio_input(ah, ah->btactive_gpio);
|
||||
b = *mask;
|
||||
b &= (0-b);
|
||||
*mask &= ~b;
|
||||
b *= debruijn32;
|
||||
b >>= 27;
|
||||
|
||||
/* Configure the desired GPIO port for TX_FRAME output */
|
||||
ath9k_hw_cfg_output(ah, ah->wlanactive_gpio,
|
||||
AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
|
||||
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);
|
||||
|
||||
tsf = ath9k_hw_gettsf32(ah);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_HWTIMER, "curent tsf %x period %x"
|
||||
"timer_next %x\n", tsf, timer_period, timer_next);
|
||||
|
||||
/*
|
||||
* Pull timer_next forward if the current TSF already passed it
|
||||
* 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 @@
|
|||
#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_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_POWER_LED 6
|
||||
|
||||
|
@ -151,7 +152,6 @@ enum ath9k_hw_caps {
|
|||
ATH9K_HW_CAP_ENHANCEDPM = BIT(14),
|
||||
ATH9K_HW_CAP_AUTOSLEEP = BIT(15),
|
||||
ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16),
|
||||
ATH9K_HW_CAP_BT_COEX = BIT(17)
|
||||
};
|
||||
|
||||
enum ath9k_capability_type {
|
||||
|
@ -238,6 +238,7 @@ enum ath9k_int {
|
|||
ATH9K_INT_GPIO = 0x01000000,
|
||||
ATH9K_INT_CABEND = 0x02000000,
|
||||
ATH9K_INT_TSFOOR = 0x04000000,
|
||||
ATH9K_INT_GENTIMER = 0x08000000,
|
||||
ATH9K_INT_CST = 0x10000000,
|
||||
ATH9K_INT_GTT = 0x20000000,
|
||||
ATH9K_INT_FATAL = 0x40000000,
|
||||
|
@ -391,6 +392,41 @@ struct ath9k_hw_version {
|
|||
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_softc *ah_sc;
|
||||
struct ath9k_hw_version hw_version;
|
||||
|
@ -414,8 +450,6 @@ struct ath_hw {
|
|||
u16 rfsilent;
|
||||
u32 rfkill_gpio;
|
||||
u32 rfkill_polarity;
|
||||
u32 btactive_gpio;
|
||||
u32 wlanactive_gpio;
|
||||
u32 ah_flags;
|
||||
|
||||
bool htc_reset_init;
|
||||
|
@ -424,6 +458,7 @@ struct ath_hw {
|
|||
enum ath9k_power_mode power_mode;
|
||||
|
||||
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
|
||||
struct ath9k_pacal_info pacal_info;
|
||||
struct ar5416Stats stats;
|
||||
struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
|
||||
|
||||
|
@ -538,6 +573,10 @@ struct ath_hw {
|
|||
struct ar5416IniArray iniModesAdditional;
|
||||
struct ar5416IniArray iniModesRxGain;
|
||||
struct ar5416IniArray iniModesTxGain;
|
||||
|
||||
u32 intr_gen_timer_trigger;
|
||||
u32 intr_gen_timer_thresh;
|
||||
struct ath_gen_timer_table hw_gen_timers;
|
||||
};
|
||||
|
||||
/* Initialization, Detach, Reset */
|
||||
|
@ -613,6 +652,17 @@ bool ath9k_hw_intrpend(struct ath_hw *ah);
|
|||
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);
|
||||
|
||||
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
|
||||
|
|
|
@ -4133,7 +4133,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = {
|
|||
{ 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
|
||||
{ 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
|
||||
{ 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
|
||||
{ 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
|
||||
{ 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e },
|
||||
{ 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
|
||||
{ 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
|
||||
{ 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
|
||||
|
@ -4158,7 +4158,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = {
|
|||
{ 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
|
||||
{ 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
|
||||
{ 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
|
||||
{ 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 },
|
||||
{ 0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f },
|
||||
{ 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
|
||||
{ 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
|
||||
{ 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
|
@ -4601,7 +4601,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = {
|
|||
{ 0x00008258, 0x00000000 },
|
||||
{ 0x0000825c, 0x400000ff },
|
||||
{ 0x00008260, 0x00080922 },
|
||||
{ 0x00008264, 0xa8a00010 },
|
||||
{ 0x00008264, 0x88a00010 },
|
||||
{ 0x00008270, 0x00000000 },
|
||||
{ 0x00008274, 0x40000000 },
|
||||
{ 0x00008278, 0x003e4180 },
|
||||
|
@ -4650,7 +4650,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = {
|
|||
{ 0x00009954, 0x5f3ca3de },
|
||||
{ 0x00009958, 0x2108ecff },
|
||||
{ 0x00009968, 0x000003ce },
|
||||
{ 0x00009970, 0x192bb515 },
|
||||
{ 0x00009970, 0x192bb514 },
|
||||
{ 0x00009974, 0x00000000 },
|
||||
{ 0x00009978, 0x00000001 },
|
||||
{ 0x0000997c, 0x00000000 },
|
||||
|
@ -4728,7 +4728,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = {
|
|||
{ 0x00007800, 0x00140000 },
|
||||
{ 0x00007804, 0x0e4548d8 },
|
||||
{ 0x00007808, 0x54214514 },
|
||||
{ 0x0000780c, 0x02025820 },
|
||||
{ 0x0000780c, 0x02025830 },
|
||||
{ 0x00007810, 0x71c0d388 },
|
||||
{ 0x00007814, 0x924934a8 },
|
||||
{ 0x0000781c, 0x00000000 },
|
||||
|
|
|
@ -439,8 +439,8 @@ static void ath_start_ani(struct ath_softc *sc)
|
|||
*/
|
||||
void ath_update_chainmask(struct ath_softc *sc, int is_ht)
|
||||
{
|
||||
if (is_ht ||
|
||||
(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) {
|
||||
if ((sc->sc_flags & SC_OP_SCANNING) || is_ht ||
|
||||
(sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE)) {
|
||||
sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
|
||||
sc->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
|
||||
} else {
|
||||
|
@ -602,6 +602,10 @@ irqreturn_t ath_isr(int irq, void *dev)
|
|||
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:
|
||||
|
||||
ath_debug_stat_interrupt(sc, status);
|
||||
|
@ -1279,6 +1283,10 @@ void ath_detach(struct ath_softc *sc)
|
|||
if (ATH_TXQ_SETUP(sc, 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);
|
||||
sc->sc_ah = NULL;
|
||||
ath9k_exit_debug(sc);
|
||||
|
@ -1509,8 +1517,11 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc)
|
|||
ARRAY_SIZE(ath9k_5ghz_chantable);
|
||||
}
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)
|
||||
ath9k_hw_btcoex_enable(sc->sc_ah);
|
||||
if (sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE) {
|
||||
r = ath9k_hw_btcoex_init(ah);
|
||||
if (r)
|
||||
goto bad2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
bad2:
|
||||
|
@ -1992,6 +2003,16 @@ static int ath9k_start(struct ieee80211_hw *hw)
|
|||
|
||||
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(&sc->mutex);
|
||||
|
||||
|
@ -2125,6 +2146,12 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
|||
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
|
||||
* before setting the invalid flag. */
|
||||
ath9k_hw_set_interrupts(sc->sc_ah, 0);
|
||||
|
@ -2713,6 +2740,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
|
|||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
if (ath9k_wiphy_scanning(sc)) {
|
||||
printk(KERN_DEBUG "ath9k: Two wiphys trying to scan at the "
|
||||
"same time\n");
|
||||
|
@ -2720,6 +2748,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
|
|||
* Do not allow the concurrent scanning state for now. This
|
||||
* could be improved with scanning control moved into ath9k.
|
||||
*/
|
||||
mutex_unlock(&sc->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2729,6 +2758,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
|
|||
spin_lock_bh(&sc->ani_lock);
|
||||
sc->sc_flags |= SC_OP_SCANNING;
|
||||
spin_unlock_bh(&sc->ani_lock);
|
||||
mutex_unlock(&sc->mutex);
|
||||
}
|
||||
|
||||
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_softc *sc = aphy->sc;
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
spin_lock_bh(&sc->ani_lock);
|
||||
aphy->state = ATH_WIPHY_ACTIVE;
|
||||
sc->sc_flags &= ~SC_OP_SCANNING;
|
||||
sc->sc_flags |= SC_OP_FULL_RESET;
|
||||
spin_unlock_bh(&sc->ani_lock);
|
||||
mutex_unlock(&sc->mutex);
|
||||
}
|
||||
|
||||
struct ieee80211_ops ath9k_ops = {
|
||||
|
|
|
@ -423,11 +423,12 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
|
|||
if (sc->rx.rxfilter & FIF_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
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -234,7 +234,15 @@
|
|||
#define AR_IMR_S5 0x00b8
|
||||
#define AR_IMR_S5_TIM_TIMER 0x00000010
|
||||
#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_RXOK 0x00000001
|
||||
|
@ -962,6 +970,8 @@ enum {
|
|||
#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_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_S 15
|
||||
#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000
|
||||
|
@ -970,6 +980,8 @@ enum {
|
|||
#define AR_GPIO_INPUT_MUX1 0x4058
|
||||
#define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000
|
||||
#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_CLK25 0x0000000f
|
||||
|
@ -995,6 +1007,8 @@ enum {
|
|||
|
||||
#define AR_OBS 0x4080
|
||||
|
||||
#define AR_GPIO_PDPU 0x4088
|
||||
|
||||
#define AR_PCIE_MSI 0x4094
|
||||
#define AR_PCIE_MSI_ENABLE 0x00000001
|
||||
|
||||
|
@ -1428,6 +1442,7 @@ enum {
|
|||
#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff
|
||||
#define AR_QUIET1_QUIET_ENABLE 0x00010000
|
||||
#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000
|
||||
#define AR_QUIET1_QUIET_ACK_CTS_ENABLE_S 17
|
||||
#define AR_QUIET2 0x8100
|
||||
#define AR_QUIET2_QUIET_PERIOD_S 0
|
||||
#define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff
|
||||
|
@ -1473,6 +1488,8 @@ enum {
|
|||
#define AR_PCU_CLEAR_VMF 0x01000000
|
||||
#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_COUNT 0x00FFFFFF
|
||||
|
@ -1500,6 +1517,46 @@ enum {
|
|||
#define AR_PHY_ERR_3_COUNT 0x00FFFFFF
|
||||
#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_TIME 0x000000FF
|
||||
#define AR_TXSIFS_TX_LATENCY 0x00000F00
|
||||
|
@ -1516,7 +1573,10 @@ enum {
|
|||
#define AR_TXOP_8_11 0x81f8
|
||||
#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_DMA_BEACON_ALERT 0x8204
|
||||
#define AR_NEXT_SWBA 0x8208
|
||||
|
|
|
@ -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)
|
||||
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).
|
||||
|
@ -872,7 +877,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
|
|||
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;
|
||||
|
||||
|
|
|
@ -82,15 +82,13 @@ config B43_NPHY
|
|||
config B43_PHY_LP
|
||||
bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)"
|
||||
depends on B43 && EXPERIMENTAL
|
||||
default y
|
||||
---help---
|
||||
Support for the LP-PHY.
|
||||
The LP-PHY is a low-power PHY built into some notebooks
|
||||
and embedded devices. It supports 802.11a/g
|
||||
(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,
|
||||
# if it's possible.
|
||||
config B43_LEDS
|
||||
|
|
|
@ -1456,7 +1456,8 @@ static u16 b43_antenna_to_phyctl(int antenna)
|
|||
return B43_TXH_PHY_ANT2;
|
||||
case B43_ANTENNA3:
|
||||
return B43_TXH_PHY_ANT3;
|
||||
case B43_ANTENNA_AUTO:
|
||||
case B43_ANTENNA_AUTO0:
|
||||
case B43_ANTENNA_AUTO1:
|
||||
return B43_TXH_PHY_ANT01AUTO;
|
||||
}
|
||||
B43_WARN_ON(1);
|
||||
|
|
|
@ -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_BBANDCFG_RXANT;
|
||||
tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna)
|
||||
tmp |= (autodiv ? B43_ANTENNA_AUTO1 : antenna)
|
||||
<< B43_PHY_BBANDCFG_RXANT_SHIFT;
|
||||
b43_phy_write(dev, B43_PHY_BBANDCFG, tmp);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
b43_phy_write(dev, offset,
|
||||
b43_phy_read(dev, offset) & mask);
|
||||
if (dev->phy.ops->phy_maskset) {
|
||||
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)
|
||||
{
|
||||
b43_phy_write(dev, offset,
|
||||
b43_phy_read(dev, offset) | set);
|
||||
if (dev->phy.ops->phy_maskset) {
|
||||
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)
|
||||
{
|
||||
b43_phy_write(dev, offset,
|
||||
(b43_phy_read(dev, offset) & mask) | set);
|
||||
if (dev->phy.ops->phy_maskset) {
|
||||
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)
|
||||
|
|
|
@ -49,11 +49,11 @@ enum b43_interference_mitigation {
|
|||
|
||||
/* Antenna identifiers */
|
||||
enum {
|
||||
B43_ANTENNA0, /* Antenna 0 */
|
||||
B43_ANTENNA1, /* Antenna 0 */
|
||||
B43_ANTENNA_AUTO1, /* Automatic, starting with antenna 1 */
|
||||
B43_ANTENNA_AUTO0, /* Automatic, starting with antenna 0 */
|
||||
B43_ANTENNA2,
|
||||
B43_ANTENNA0 = 0, /* Antenna 0 */
|
||||
B43_ANTENNA1 = 1, /* Antenna 1 */
|
||||
B43_ANTENNA_AUTO0 = 2, /* Automatic, starting with antenna 0 */
|
||||
B43_ANTENNA_AUTO1 = 3, /* Automatic, starting with antenna 1 */
|
||||
B43_ANTENNA2 = 4,
|
||||
B43_ANTENNA3 = 8,
|
||||
|
||||
B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0,
|
||||
|
@ -95,6 +95,8 @@ enum b43_txpwr_result {
|
|||
* Must not be NULL.
|
||||
* @phy_write: Write to a PHY register.
|
||||
* 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.
|
||||
* Must not be NULL.
|
||||
* @radio_write: Write to a Radio register.
|
||||
|
@ -154,6 +156,7 @@ struct b43_phy_operations {
|
|||
/* Register access */
|
||||
u16 (*phy_read)(struct b43_wldev *dev, u16 reg);
|
||||
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);
|
||||
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)
|
|||
|
||||
tmp = b43_phy_read(dev, B43_PHY_BBANDCFG);
|
||||
tmp &= ~B43_PHY_BBANDCFG_RXANT;
|
||||
tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna)
|
||||
tmp |= (autodiv ? B43_ANTENNA_AUTO1 : antenna)
|
||||
<< B43_PHY_BBANDCFG_RXANT_SHIFT;
|
||||
b43_phy_write(dev, B43_PHY_BBANDCFG, tmp);
|
||||
|
||||
|
|
|
@ -182,8 +182,8 @@ static void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq)
|
|||
temp[1] = temp[0] + 0x1000;
|
||||
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(12, 0), 3, temp);
|
||||
}
|
||||
|
||||
static void lpphy_table_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_mask(dev, B43_LPPHY_RX_RADIO_CTL, 0xFFFE);
|
||||
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, 0x83FF, 0x3800);
|
||||
b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0x0180);
|
||||
b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3C00);
|
||||
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_CRS_ED_THRESH, 0xFF00, 0x00B3);
|
||||
|
@ -234,19 +234,15 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
|
|||
if ((bus->sprom.boardflags_lo & B43_BFL_FEM) &&
|
||||
((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
|
||||
(bus->sprom.boardflags_hi & B43_BFH_PAREF))) {
|
||||
/* TODO:
|
||||
* Set the LDO voltage to 0x0028 - FIXME: What is this?
|
||||
* Call sb_pmu_set_ldo_voltage with 4 and the LDO voltage
|
||||
* as arguments
|
||||
* Call sb_pmu_paref_ldo_enable with argument TRUE
|
||||
*/
|
||||
ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28);
|
||||
ssb_pmu_set_ldo_paref(&bus->chipco, true);
|
||||
if (dev->phy.rev == 0) {
|
||||
b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT,
|
||||
0xFFCF, 0x0010);
|
||||
}
|
||||
b43_lptab_write(dev, B43_LPTAB16(11, 7), 60);
|
||||
} 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,
|
||||
0xFFCF, 0x0020);
|
||||
b43_lptab_write(dev, B43_LPTAB16(11, 7), 100);
|
||||
|
@ -340,11 +336,11 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
|
|||
if (dev->phy.rev == 1) {
|
||||
tmp = b43_phy_read(dev, B43_LPPHY_CLIPCTRTHRESH);
|
||||
tmp2 = (tmp & 0x03E0) >> 5;
|
||||
tmp2 |= tmp << 5;
|
||||
tmp2 |= tmp2 << 5;
|
||||
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 << 5;
|
||||
tmp2 |= tmp2 << 5;
|
||||
b43_phy_write(dev, B43_LPPHY_4C4, tmp2);
|
||||
tmp = b43_phy_read(dev, B43_LPPHY_VERYLOWGAINDB);
|
||||
tmp2 = tmp & 0x00FF;
|
||||
|
@ -705,7 +701,7 @@ static void lpphy_set_rc_cap(struct b43_wldev *dev)
|
|||
u8 rc_cap = (lpphy->rc_cap & 0x1F) >> 1;
|
||||
|
||||
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,
|
||||
max_t(u8, lpphy->rc_cap - 4, 0x80));
|
||||
|
@ -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_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
|
||||
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_VAL_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,
|
|||
b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFF9F, scale_idx << 5);
|
||||
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, 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,
|
||||
|
@ -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_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_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++) {
|
||||
if (!(b43_phy_read(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_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_set(dev, B43_LPPHY_RF_OVERRIDE_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)
|
|||
return index;
|
||||
}
|
||||
|
||||
/* Fixed-point division algorithm using only integer math. */
|
||||
static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
|
||||
{
|
||||
u32 quotient, remainder, rbit, roundup, tmp;
|
||||
u32 quotient, remainder;
|
||||
|
||||
if (divisor == 0)
|
||||
return 0;
|
||||
|
@ -1041,20 +1039,16 @@ static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
|
|||
quotient = dividend / divisor;
|
||||
remainder = dividend % divisor;
|
||||
|
||||
rbit = divisor & 0x1;
|
||||
roundup = (divisor >> 1) + rbit;
|
||||
|
||||
while (precision != 0) {
|
||||
tmp = remainder - roundup;
|
||||
while (precision > 0) {
|
||||
quotient <<= 1;
|
||||
if (remainder >= roundup)
|
||||
remainder = (tmp << 1) + rbit;
|
||||
else
|
||||
remainder <<= 1;
|
||||
if (remainder << 1 >= divisor) {
|
||||
quotient++;
|
||||
remainder = (remainder << 1) - divisor;
|
||||
}
|
||||
precision--;
|
||||
}
|
||||
|
||||
if (remainder >= roundup)
|
||||
if (remainder << 1 >= divisor)
|
||||
quotient++;
|
||||
|
||||
return quotient;
|
||||
|
@ -1137,9 +1131,9 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev,
|
|||
}
|
||||
if (dev->phy.rev >= 2) {
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
@ -1171,7 +1165,7 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
|
|||
err = b43_lpphy_op_switch_channel(dev, 7);
|
||||
if (err) {
|
||||
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);
|
||||
}
|
||||
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)
|
|||
mean_sq_pwr = ideal_pwr - normal_pwr;
|
||||
mean_sq_pwr *= 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;
|
||||
mean_sq_pwr_min = inner_sum;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* Register 1 is a 32-bit register. */
|
||||
|
@ -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)
|
||||
{
|
||||
b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x42);
|
||||
b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x62);
|
||||
b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x42);
|
||||
b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x62);
|
||||
udelay(200);
|
||||
}
|
||||
|
||||
|
@ -1982,7 +1984,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,
|
|||
tmp6 = tmp5 / tmp4;
|
||||
tmp7 = tmp5 % 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);
|
||||
b43_radio_write(dev, B2062_S_RFPLL_CTL23, (tmp9 >> 8) + 16);
|
||||
b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF);
|
||||
|
@ -2021,17 +2023,17 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
|
|||
{
|
||||
u16 tmp;
|
||||
|
||||
b43_phy_mask(dev, B2063_PLL_SP1, ~0x40);
|
||||
tmp = b43_phy_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8;
|
||||
b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp);
|
||||
b43_radio_mask(dev, B2063_PLL_SP1, ~0x40);
|
||||
tmp = b43_radio_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8;
|
||||
b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp);
|
||||
udelay(1);
|
||||
b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4);
|
||||
b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4);
|
||||
udelay(1);
|
||||
b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6);
|
||||
b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6);
|
||||
udelay(1);
|
||||
b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7);
|
||||
b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7);
|
||||
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,
|
||||
|
@ -2126,31 +2128,31 @@ static int lpphy_b2063_tune(struct b43_wldev *dev,
|
|||
scale = 0;
|
||||
tmp5 = ((tmp4 + (tmp3 >> 1)) / tmp3) - 8;
|
||||
}
|
||||
b43_phy_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, 0xFFC0, tmp5);
|
||||
b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6);
|
||||
|
||||
tmp6 = lpphy_qdiv_roundup(100 * val1, val3, 16);
|
||||
tmp6 *= (tmp5 * 8) * (scale + 1);
|
||||
if (tmp6 > 150)
|
||||
tmp6 = 0;
|
||||
|
||||
b43_phy_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, 0xFFE0, tmp6);
|
||||
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)
|
||||
b43_phy_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2);
|
||||
b43_radio_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2);
|
||||
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)
|
||||
b43_phy_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2);
|
||||
b43_radio_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2);
|
||||
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);
|
||||
b43_phy_mask(dev, B2063_PLL_SP2, 0xFFFC);
|
||||
b43_radio_mask(dev, B2063_PLL_SP2, 0xFFFC);
|
||||
lpphy_b2063_vco_calib(dev);
|
||||
b43_radio_write(dev, B2063_COMM15, old_comm15);
|
||||
|
||||
|
@ -2160,10 +2162,9 @@ static int lpphy_b2063_tune(struct b43_wldev *dev,
|
|||
static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
|
||||
unsigned int new_channel)
|
||||
{
|
||||
struct b43_phy_lp *lpphy = dev->phy.lp;
|
||||
int err;
|
||||
|
||||
b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
|
||||
|
||||
if (dev->phy.radio_ver == 0x2063) {
|
||||
err = lpphy_b2063_tune(dev, new_channel);
|
||||
if (err)
|
||||
|
@ -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->channel = new_channel;
|
||||
b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2187,10 +2191,9 @@ static int b43_lpphy_op_init(struct b43_wldev *dev)
|
|||
lpphy_baseband_init(dev);
|
||||
lpphy_radio_init(dev);
|
||||
lpphy_calibrate_rc(dev);
|
||||
err = b43_lpphy_op_switch_channel(dev,
|
||||
b43_lpphy_op_get_default_chan(dev));
|
||||
err = b43_lpphy_op_switch_channel(dev, 7);
|
||||
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);
|
||||
}
|
||||
lpphy_tx_pctl_init(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)
|
||||
{
|
||||
//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)
|
||||
|
@ -2224,6 +2234,7 @@ const struct b43_phy_operations b43_phyops_lp = {
|
|||
.init = b43_lpphy_op_init,
|
||||
.phy_read = b43_lpphy_op_read,
|
||||
.phy_write = b43_lpphy_op_write,
|
||||
.phy_maskset = b43_lpphy_op_maskset,
|
||||
.radio_read = b43_lpphy_op_radio_read,
|
||||
.radio_write = b43_lpphy_op_radio_write,
|
||||
.software_rfkill = b43_lpphy_op_software_rfkill,
|
||||
|
|
|
@ -888,6 +888,9 @@ struct b43_phy_lp {
|
|||
bool crs_usr_disable, crs_sys_disable;
|
||||
|
||||
unsigned int pdiv;
|
||||
|
||||
/* The channel we are tuned to */
|
||||
u8 channel;
|
||||
};
|
||||
|
||||
enum tssi_mux_mode {
|
||||
|
|
|
@ -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,
|
||||
unsigned int nr_elements, void *_data)
|
||||
{
|
||||
u32 type, value;
|
||||
u32 type;
|
||||
u8 *data = _data;
|
||||
unsigned int i;
|
||||
|
||||
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++) {
|
||||
value = b43_lptab_read(dev, offset);
|
||||
switch (type) {
|
||||
case B43_LPTAB_8BIT:
|
||||
*data = value;
|
||||
*data = b43_phy_read(dev, B43_LPPHY_TABLEDATALO) & 0xFF;
|
||||
data++;
|
||||
break;
|
||||
case B43_LPTAB_16BIT:
|
||||
*((u16 *)data) = value;
|
||||
*((u16 *)data) = b43_phy_read(dev, B43_LPPHY_TABLEDATALO);
|
||||
data += 2;
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
default:
|
||||
B43_WARN_ON(1);
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -688,26 +693,34 @@ void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset,
|
|||
unsigned int i;
|
||||
|
||||
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++) {
|
||||
switch (type) {
|
||||
case B43_LPTAB_8BIT:
|
||||
value = *data;
|
||||
data++;
|
||||
B43_WARN_ON(value & ~0xFF);
|
||||
b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
|
||||
break;
|
||||
case B43_LPTAB_16BIT:
|
||||
value = *((u16 *)data);
|
||||
data += 2;
|
||||
B43_WARN_ON(value & ~0xFFFF);
|
||||
b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
|
||||
break;
|
||||
case B43_LPTAB_32BIT:
|
||||
value = *((u32 *)data);
|
||||
data += 4;
|
||||
b43_phy_write(dev, B43_LPPHY_TABLEDATAHI, value >> 16);
|
||||
b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
|
||||
break;
|
||||
default:
|
||||
B43_WARN_ON(1);
|
||||
value = 0;
|
||||
}
|
||||
b43_lptab_write(dev, offset, value);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -777,7 +790,7 @@ static const u8 lpphy_pll_fraction_table[] = {
|
|||
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,
|
||||
0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
|
@ -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, 0x4000, 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,
|
||||
0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075,
|
||||
0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d,
|
||||
|
@ -2263,11 +2283,18 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev)
|
|||
b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
|
||||
ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
|
||||
b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
|
||||
ARRAY_SIZE(lpphy_iq_local_table), lpphy_iq_local_table);
|
||||
b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
|
||||
ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table);
|
||||
b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
|
||||
ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table);
|
||||
ARRAY_SIZE(lpphy_iqlo_cal_table), lpphy_iqlo_cal_table);
|
||||
if (dev->phy.rev == 0) {
|
||||
b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
|
||||
ARRAY_SIZE(lpphy_rev0_ofdm_cck_gain_table), lpphy_rev0_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),
|
||||
ARRAY_SIZE(lpphy_gain_delta_table), lpphy_gain_delta_table);
|
||||
b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
|
||||
|
@ -2281,22 +2308,6 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
|
|||
|
||||
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++)
|
||||
b43_lptab_write(dev, B43_LPTAB32(7, i), 0);
|
||||
|
||||
|
@ -2323,7 +2334,7 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
|
|||
b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
|
||||
ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
|
||||
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),
|
||||
ARRAY_SIZE(lpphy_papd_eps_table), lpphy_papd_eps_table);
|
||||
b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
file called LICENSE.
|
||||
|
||||
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
|
||||
|
||||
Portions of this file are based on the sample_* files provided by Wireless
|
||||
|
@ -1673,7 +1673,7 @@ static int ipw2100_start_scan(struct ipw2100_priv *priv)
|
|||
return err;
|
||||
}
|
||||
|
||||
static const struct ieee80211_geo ipw_geos[] = {
|
||||
static const struct libipw_geo ipw_geos[] = {
|
||||
{ /* Restricted */
|
||||
"---",
|
||||
.bg_channels = 14,
|
||||
|
@ -1694,7 +1694,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
|
|||
|
||||
/* Age scan list entries found before suspend */
|
||||
if (priv->suspend_time) {
|
||||
ieee80211_networks_age(priv->ieee, priv->suspend_time);
|
||||
libipw_networks_age(priv->ieee, priv->suspend_time);
|
||||
priv->suspend_time = 0;
|
||||
}
|
||||
|
||||
|
@ -1752,11 +1752,11 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
|
|||
}
|
||||
|
||||
/* Initialize the geo */
|
||||
if (ieee80211_set_geo(priv->ieee, &ipw_geos[0])) {
|
||||
if (libipw_set_geo(priv->ieee, &ipw_geos[0])) {
|
||||
printk(KERN_WARNING DRV_NAME "Could not set geo\n");
|
||||
return 0;
|
||||
}
|
||||
priv->ieee->freq_band = IEEE80211_24GHZ_BAND;
|
||||
priv->ieee->freq_band = LIBIPW_24GHZ_BAND;
|
||||
|
||||
lock = LOCK_NONE;
|
||||
if (ipw2100_set_ordinal(priv, IPW_ORD_PERS_DB_LOCK, &lock, &ord_len)) {
|
||||
|
@ -1817,7 +1817,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
|
|||
/* Called by register_netdev() */
|
||||
static int ipw2100_net_init(struct net_device *dev)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
return ipw2100_up(priv, 1);
|
||||
}
|
||||
|
||||
|
@ -2340,8 +2340,8 @@ static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
|
|||
*
|
||||
* When packet is provided by the firmware, it contains the following:
|
||||
*
|
||||
* . ieee80211_hdr
|
||||
* . ieee80211_snap_hdr
|
||||
* . libipw_hdr
|
||||
* . libipw_snap_hdr
|
||||
*
|
||||
* The size of the constructed ethernet
|
||||
*
|
||||
|
@ -2396,7 +2396,7 @@ static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
|
|||
}
|
||||
|
||||
static void isr_rx(struct ipw2100_priv *priv, int i,
|
||||
struct ieee80211_rx_stats *stats)
|
||||
struct libipw_rx_stats *stats)
|
||||
{
|
||||
struct net_device *dev = priv->net_dev;
|
||||
struct ipw2100_status *status = &priv->status_queue.drv[i];
|
||||
|
@ -2435,13 +2435,13 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
|
|||
|
||||
#ifdef IPW2100_RX_DEBUG
|
||||
/* Make a copy of the frame so we can dump it to the logs if
|
||||
* ieee80211_rx fails */
|
||||
* libipw_rx fails */
|
||||
skb_copy_from_linear_data(packet->skb, packet_data,
|
||||
min_t(u32, status->frame_size,
|
||||
IPW_RX_NIC_BUFFER_LENGTH));
|
||||
#endif
|
||||
|
||||
if (!ieee80211_rx(priv->ieee, packet->skb, stats)) {
|
||||
if (!libipw_rx(priv->ieee, packet->skb, stats)) {
|
||||
#ifdef IPW2100_RX_DEBUG
|
||||
IPW_DEBUG_DROP("%s: Non consumed packet:\n",
|
||||
dev->name);
|
||||
|
@ -2449,7 +2449,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
|
|||
#endif
|
||||
dev->stats.rx_errors++;
|
||||
|
||||
/* ieee80211_rx failed, so it didn't free the SKB */
|
||||
/* libipw_rx failed, so it didn't free the SKB */
|
||||
dev_kfree_skb_any(packet->skb);
|
||||
packet->skb = NULL;
|
||||
}
|
||||
|
@ -2470,7 +2470,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
|
|||
#ifdef CONFIG_IPW2100_MONITOR
|
||||
|
||||
static void isr_rx_monitor(struct ipw2100_priv *priv, int i,
|
||||
struct ieee80211_rx_stats *stats)
|
||||
struct libipw_rx_stats *stats)
|
||||
{
|
||||
struct net_device *dev = priv->net_dev;
|
||||
struct ipw2100_status *status = &priv->status_queue.drv[i];
|
||||
|
@ -2528,10 +2528,10 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i,
|
|||
|
||||
skb_put(packet->skb, status->frame_size + sizeof(struct ipw_rt_hdr));
|
||||
|
||||
if (!ieee80211_rx(priv->ieee, packet->skb, stats)) {
|
||||
if (!libipw_rx(priv->ieee, packet->skb, stats)) {
|
||||
dev->stats.rx_errors++;
|
||||
|
||||
/* ieee80211_rx failed, so it didn't free the SKB */
|
||||
/* libipw_rx failed, so it didn't free the SKB */
|
||||
dev_kfree_skb_any(packet->skb);
|
||||
packet->skb = NULL;
|
||||
}
|
||||
|
@ -2615,7 +2615,7 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv)
|
|||
u16 frame_type;
|
||||
u32 r, w, i, s;
|
||||
struct ipw2100_rx *u;
|
||||
struct ieee80211_rx_stats stats = {
|
||||
struct libipw_rx_stats stats = {
|
||||
.mac_time = jiffies,
|
||||
};
|
||||
|
||||
|
@ -2661,8 +2661,8 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv)
|
|||
|
||||
stats.mask = 0;
|
||||
if (stats.rssi != 0)
|
||||
stats.mask |= IEEE80211_STATMASK_RSSI;
|
||||
stats.freq = IEEE80211_24GHZ_BAND;
|
||||
stats.mask |= LIBIPW_STATMASK_RSSI;
|
||||
stats.freq = LIBIPW_24GHZ_BAND;
|
||||
|
||||
IPW_DEBUG_RX("%s: '%s' frame type received (%d).\n",
|
||||
priv->net_dev->name, frame_types[frame_type],
|
||||
|
@ -2686,11 +2686,11 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv)
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
if (stats.len < sizeof(struct ieee80211_hdr_3addr))
|
||||
if (stats.len < sizeof(struct libipw_hdr_3addr))
|
||||
break;
|
||||
switch (WLAN_FC_GET_TYPE(le16_to_cpu(u->rx_data.header.frame_ctl))) {
|
||||
case IEEE80211_FTYPE_MGMT:
|
||||
ieee80211_rx_mgt(priv->ieee,
|
||||
libipw_rx_mgt(priv->ieee,
|
||||
&u->rx_data.header, &stats);
|
||||
break;
|
||||
|
||||
|
@ -2884,7 +2884,7 @@ static int __ipw2100_tx_process(struct ipw2100_priv *priv)
|
|||
tbd->buf_length, PCI_DMA_TODEVICE);
|
||||
}
|
||||
|
||||
ieee80211_txb_free(packet->info.d_struct.txb);
|
||||
libipw_txb_free(packet->info.d_struct.txb);
|
||||
packet->info.d_struct.txb = NULL;
|
||||
|
||||
list_add_tail(element, &priv->tx_free_list);
|
||||
|
@ -3028,7 +3028,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
|
|||
int next = txq->next;
|
||||
int i = 0;
|
||||
struct ipw2100_data_header *ipw_hdr;
|
||||
struct ieee80211_hdr_3addr *hdr;
|
||||
struct libipw_hdr_3addr *hdr;
|
||||
|
||||
while (!list_empty(&priv->tx_pend_list)) {
|
||||
/* if there isn't enough space in TBD queue, then
|
||||
|
@ -3062,7 +3062,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
|
|||
packet->index = txq->next;
|
||||
|
||||
ipw_hdr = packet->info.d_struct.data;
|
||||
hdr = (struct ieee80211_hdr_3addr *)packet->info.d_struct.txb->
|
||||
hdr = (struct libipw_hdr_3addr *)packet->info.d_struct.txb->
|
||||
fragments[0]->data;
|
||||
|
||||
if (priv->ieee->iw_mode == IW_MODE_INFRA) {
|
||||
|
@ -3086,7 +3086,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
|
|||
if (packet->info.d_struct.txb->nr_frags > 1)
|
||||
ipw_hdr->fragment_size =
|
||||
packet->info.d_struct.txb->frag_size -
|
||||
IEEE80211_3ADDR_LEN;
|
||||
LIBIPW_3ADDR_LEN;
|
||||
else
|
||||
ipw_hdr->fragment_size = 0;
|
||||
|
||||
|
@ -3119,13 +3119,13 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
|
|||
IPW_BD_STATUS_TX_FRAME_NOT_LAST_FRAGMENT;
|
||||
|
||||
tbd->buf_length = packet->info.d_struct.txb->
|
||||
fragments[i]->len - IEEE80211_3ADDR_LEN;
|
||||
fragments[i]->len - LIBIPW_3ADDR_LEN;
|
||||
|
||||
tbd->host_addr = pci_map_single(priv->pci_dev,
|
||||
packet->info.d_struct.
|
||||
txb->fragments[i]->
|
||||
data +
|
||||
IEEE80211_3ADDR_LEN,
|
||||
LIBIPW_3ADDR_LEN,
|
||||
tbd->buf_length,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
|
@ -3330,10 +3330,10 @@ static irqreturn_t ipw2100_interrupt(int irq, void *data)
|
|||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev,
|
||||
static int ipw2100_tx(struct libipw_txb *txb, struct net_device *dev,
|
||||
int pri)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
struct list_head *element;
|
||||
struct ipw2100_tx_packet *packet;
|
||||
unsigned long flags;
|
||||
|
@ -4488,7 +4488,7 @@ static void ipw2100_tx_initialize(struct ipw2100_priv *priv)
|
|||
/* We simply drop any SKBs that have been queued for
|
||||
* transmit */
|
||||
if (priv->tx_buffers[i].info.d_struct.txb) {
|
||||
ieee80211_txb_free(priv->tx_buffers[i].info.d_struct.
|
||||
libipw_txb_free(priv->tx_buffers[i].info.d_struct.
|
||||
txb);
|
||||
priv->tx_buffers[i].info.d_struct.txb = NULL;
|
||||
}
|
||||
|
@ -4527,7 +4527,7 @@ static void ipw2100_tx_free(struct ipw2100_priv *priv)
|
|||
|
||||
for (i = 0; i < TX_PENDED_QUEUE_LENGTH; i++) {
|
||||
if (priv->tx_buffers[i].info.d_struct.txb) {
|
||||
ieee80211_txb_free(priv->tx_buffers[i].info.d_struct.
|
||||
libipw_txb_free(priv->tx_buffers[i].info.d_struct.
|
||||
txb);
|
||||
priv->tx_buffers[i].info.d_struct.txb = NULL;
|
||||
}
|
||||
|
@ -5558,9 +5558,9 @@ static void ipw2100_security_work(struct work_struct *work)
|
|||
}
|
||||
|
||||
static void shim__set_security(struct net_device *dev,
|
||||
struct ieee80211_security *sec)
|
||||
struct libipw_security *sec)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int i, force_update = 0;
|
||||
|
||||
mutex_lock(&priv->action_mutex);
|
||||
|
@ -5753,7 +5753,7 @@ static int ipw2100_adapter_setup(struct ipw2100_priv *priv)
|
|||
* method as well) to talk to the firmware */
|
||||
static int ipw2100_set_address(struct net_device *dev, void *p)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
struct sockaddr *addr = p;
|
||||
int err = 0;
|
||||
|
||||
|
@ -5781,7 +5781,7 @@ static int ipw2100_set_address(struct net_device *dev, void *p)
|
|||
|
||||
static int ipw2100_open(struct net_device *dev)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
unsigned long flags;
|
||||
IPW_DEBUG_INFO("dev->open\n");
|
||||
|
||||
|
@ -5797,7 +5797,7 @@ static int ipw2100_open(struct net_device *dev)
|
|||
|
||||
static int ipw2100_close(struct net_device *dev)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
unsigned long flags;
|
||||
struct list_head *element;
|
||||
struct ipw2100_tx_packet *packet;
|
||||
|
@ -5818,7 +5818,7 @@ static int ipw2100_close(struct net_device *dev)
|
|||
list_del(element);
|
||||
DEC_STAT(&priv->tx_pend_stat);
|
||||
|
||||
ieee80211_txb_free(packet->info.d_struct.txb);
|
||||
libipw_txb_free(packet->info.d_struct.txb);
|
||||
packet->info.d_struct.txb = NULL;
|
||||
|
||||
list_add_tail(element, &priv->tx_free_list);
|
||||
|
@ -5836,7 +5836,7 @@ static int ipw2100_close(struct net_device *dev)
|
|||
*/
|
||||
static void ipw2100_tx_timeout(struct net_device *dev)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
dev->stats.tx_errors++;
|
||||
|
||||
|
@ -5861,8 +5861,8 @@ static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value)
|
|||
static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value)
|
||||
{
|
||||
|
||||
struct ieee80211_device *ieee = priv->ieee;
|
||||
struct ieee80211_security sec = {
|
||||
struct libipw_device *ieee = priv->ieee;
|
||||
struct libipw_security sec = {
|
||||
.flags = SEC_AUTH_MODE,
|
||||
};
|
||||
int ret = 0;
|
||||
|
@ -5907,7 +5907,7 @@ static void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv,
|
|||
static void ipw_ethtool_get_drvinfo(struct net_device *dev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
char fw_ver[64], ucode_ver[64];
|
||||
|
||||
strcpy(info->driver, DRV_NAME);
|
||||
|
@ -5924,7 +5924,7 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
|
|||
|
||||
static u32 ipw2100_ethtool_get_link(struct net_device *dev)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
return (priv->status & STATUS_ASSOCIATED) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
@ -6011,8 +6011,8 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv);
|
|||
static const struct net_device_ops ipw2100_netdev_ops = {
|
||||
.ndo_open = ipw2100_open,
|
||||
.ndo_stop = ipw2100_close,
|
||||
.ndo_start_xmit = ieee80211_xmit,
|
||||
.ndo_change_mtu = ieee80211_change_mtu,
|
||||
.ndo_start_xmit = libipw_xmit,
|
||||
.ndo_change_mtu = libipw_change_mtu,
|
||||
.ndo_init = ipw2100_net_init,
|
||||
.ndo_tx_timeout = ipw2100_tx_timeout,
|
||||
.ndo_set_mac_address = ipw2100_set_address,
|
||||
|
@ -6029,10 +6029,10 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
|
|||
struct ipw2100_priv *priv;
|
||||
struct net_device *dev;
|
||||
|
||||
dev = alloc_ieee80211(sizeof(struct ipw2100_priv));
|
||||
dev = alloc_ieee80211(sizeof(struct ipw2100_priv), 0);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
priv = ieee80211_priv(dev);
|
||||
priv = libipw_priv(dev);
|
||||
priv->ieee = netdev_priv(dev);
|
||||
priv->pci_dev = pci_dev;
|
||||
priv->net_dev = dev;
|
||||
|
@ -6046,7 +6046,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
|
|||
dev->netdev_ops = &ipw2100_netdev_ops;
|
||||
dev->ethtool_ops = &ipw2100_ethtool_ops;
|
||||
dev->wireless_handlers = &ipw2100_wx_handler_def;
|
||||
priv->wireless_data.ieee80211 = priv->ieee;
|
||||
priv->wireless_data.libipw = priv->ieee;
|
||||
dev->wireless_data = &priv->wireless_data;
|
||||
dev->watchdog_timeo = 3 * HZ;
|
||||
dev->irq = 0;
|
||||
|
@ -6202,7 +6202,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
|
|||
return err;
|
||||
}
|
||||
|
||||
priv = ieee80211_priv(dev);
|
||||
priv = libipw_priv(dev);
|
||||
|
||||
pci_set_master(pci_dev);
|
||||
pci_set_drvdata(pci_dev, priv);
|
||||
|
@ -6342,7 +6342,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
|
|||
sysfs_remove_group(&pci_dev->dev.kobj,
|
||||
&ipw2100_attribute_group);
|
||||
|
||||
free_ieee80211(dev);
|
||||
free_ieee80211(dev, 0);
|
||||
pci_set_drvdata(pci_dev, NULL);
|
||||
}
|
||||
|
||||
|
@ -6400,7 +6400,7 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
|
|||
if (dev->base_addr)
|
||||
iounmap((void __iomem *)dev->base_addr);
|
||||
|
||||
free_ieee80211(dev);
|
||||
free_ieee80211(dev, 0);
|
||||
}
|
||||
|
||||
pci_release_regions(pci_dev);
|
||||
|
@ -6629,7 +6629,7 @@ static int ipw2100_wx_get_name(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
if (!(priv->status & STATUS_ASSOCIATED))
|
||||
strcpy(wrqu->name, "unassociated");
|
||||
else
|
||||
|
@ -6643,7 +6643,7 @@ static int ipw2100_wx_set_freq(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
struct iw_freq *fwrq = &wrqu->freq;
|
||||
int err = 0;
|
||||
|
||||
|
@ -6693,7 +6693,7 @@ static int ipw2100_wx_get_freq(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
wrqu->freq.e = 0;
|
||||
|
||||
|
@ -6714,7 +6714,7 @@ static int ipw2100_wx_set_mode(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int err = 0;
|
||||
|
||||
IPW_DEBUG_WX("SET Mode -> %d \n", wrqu->mode);
|
||||
|
@ -6757,7 +6757,7 @@ static int ipw2100_wx_get_mode(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
wrqu->mode = priv->ieee->iw_mode;
|
||||
IPW_DEBUG_WX("GET Mode -> %d\n", wrqu->mode);
|
||||
|
@ -6792,7 +6792,7 @@ static int ipw2100_wx_get_range(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
struct iw_range *range = (struct iw_range *)extra;
|
||||
u16 val;
|
||||
int i, level;
|
||||
|
@ -6913,7 +6913,7 @@ static int ipw2100_wx_set_wap(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int err = 0;
|
||||
|
||||
static const unsigned char any[] = {
|
||||
|
@ -6962,7 +6962,7 @@ static int ipw2100_wx_get_wap(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
/* If we are associated, trying to associate, or have a statically
|
||||
* configured BSSID then return that; otherwise return ANY */
|
||||
|
@ -6980,7 +6980,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
char *essid = ""; /* ANY */
|
||||
int length = 0;
|
||||
int err = 0;
|
||||
|
@ -7035,7 +7035,7 @@ static int ipw2100_wx_get_essid(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
/* If we are associated, trying to associate, or have a statically
|
||||
|
@ -7063,7 +7063,7 @@ static int ipw2100_wx_set_nick(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
if (wrqu->data.length > IW_ESSID_MAX_SIZE)
|
||||
return -E2BIG;
|
||||
|
@ -7085,7 +7085,7 @@ static int ipw2100_wx_get_nick(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
wrqu->data.length = strlen(priv->nick);
|
||||
memcpy(extra, priv->nick, wrqu->data.length);
|
||||
|
@ -7100,7 +7100,7 @@ static int ipw2100_wx_set_rate(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
u32 target_rate = wrqu->bitrate.value;
|
||||
u32 rate;
|
||||
int err = 0;
|
||||
|
@ -7140,7 +7140,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int val;
|
||||
unsigned int len = sizeof(val);
|
||||
int err = 0;
|
||||
|
@ -7192,7 +7192,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int value, err;
|
||||
|
||||
/* Auto RTS not yet supported */
|
||||
|
@ -7231,7 +7231,7 @@ static int ipw2100_wx_get_rts(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
wrqu->rts.value = priv->rts_threshold & ~RTS_DISABLED;
|
||||
wrqu->rts.fixed = 1; /* no auto select */
|
||||
|
@ -7248,7 +7248,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int err = 0, value;
|
||||
|
||||
if (ipw_radio_kill_sw(priv, wrqu->txpower.disabled))
|
||||
|
@ -7293,7 +7293,7 @@ static int ipw2100_wx_get_txpow(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
wrqu->txpower.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0;
|
||||
|
||||
|
@ -7320,7 +7320,7 @@ static int ipw2100_wx_set_frag(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
if (!wrqu->frag.fixed)
|
||||
return -EINVAL;
|
||||
|
@ -7350,7 +7350,7 @@ static int ipw2100_wx_get_frag(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
wrqu->frag.value = priv->frag_threshold & ~FRAG_DISABLED;
|
||||
wrqu->frag.fixed = 0; /* no auto select */
|
||||
wrqu->frag.disabled = (priv->frag_threshold & FRAG_DISABLED) ? 1 : 0;
|
||||
|
@ -7364,7 +7364,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int err = 0;
|
||||
|
||||
if (wrqu->retry.flags & IW_RETRY_LIFETIME || wrqu->retry.disabled)
|
||||
|
@ -7412,7 +7412,7 @@ static int ipw2100_wx_get_retry(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
wrqu->retry.disabled = 0; /* can't be disabled */
|
||||
|
||||
|
@ -7440,7 +7440,7 @@ static int ipw2100_wx_set_scan(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&priv->action_mutex);
|
||||
|
@ -7472,8 +7472,8 @@ static int ipw2100_wx_get_scan(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
return ieee80211_wx_get_scan(priv->ieee, info, wrqu, extra);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
return libipw_wx_get_scan(priv->ieee, info, wrqu, extra);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -7487,8 +7487,8 @@ static int ipw2100_wx_set_encode(struct net_device *dev,
|
|||
* No check of STATUS_INITIALIZED required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
return ieee80211_wx_set_encode(priv->ieee, info, wrqu, key);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
return libipw_wx_set_encode(priv->ieee, info, wrqu, key);
|
||||
}
|
||||
|
||||
static int ipw2100_wx_get_encode(struct net_device *dev,
|
||||
|
@ -7499,15 +7499,15 @@ static int ipw2100_wx_get_encode(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
return ieee80211_wx_get_encode(priv->ieee, info, wrqu, key);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
return libipw_wx_get_encode(priv->ieee, info, wrqu, key);
|
||||
}
|
||||
|
||||
static int ipw2100_wx_set_power(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&priv->action_mutex);
|
||||
|
@ -7556,7 +7556,7 @@ static int ipw2100_wx_get_power(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
if (!(priv->power_mode & IPW_POWER_ENABLED))
|
||||
wrqu->power.disabled = 1;
|
||||
|
@ -7580,8 +7580,8 @@ static int ipw2100_wx_set_genie(struct net_device *dev,
|
|||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ieee80211_device *ieee = priv->ieee;
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
struct libipw_device *ieee = priv->ieee;
|
||||
u8 *buf;
|
||||
|
||||
if (!ieee->wpa_enabled)
|
||||
|
@ -7615,8 +7615,8 @@ static int ipw2100_wx_get_genie(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ieee80211_device *ieee = priv->ieee;
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
struct libipw_device *ieee = priv->ieee;
|
||||
|
||||
if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) {
|
||||
wrqu->data.length = 0;
|
||||
|
@ -7637,8 +7637,8 @@ static int ipw2100_wx_set_auth(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ieee80211_device *ieee = priv->ieee;
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
struct libipw_device *ieee = priv->ieee;
|
||||
struct iw_param *param = &wrqu->param;
|
||||
struct lib80211_crypt_data *crypt;
|
||||
unsigned long flags;
|
||||
|
@ -7682,7 +7682,7 @@ static int ipw2100_wx_set_auth(struct net_device *dev,
|
|||
* can use this to determine if the CAP_PRIVACY_ON bit should
|
||||
* be set.
|
||||
*/
|
||||
struct ieee80211_security sec = {
|
||||
struct libipw_security sec = {
|
||||
.flags = SEC_ENABLED,
|
||||
.enabled = param->value,
|
||||
};
|
||||
|
@ -7730,8 +7730,8 @@ static int ipw2100_wx_get_auth(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ieee80211_device *ieee = priv->ieee;
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
struct libipw_device *ieee = priv->ieee;
|
||||
struct lib80211_crypt_data *crypt;
|
||||
struct iw_param *param = &wrqu->param;
|
||||
int ret = 0;
|
||||
|
@ -7792,8 +7792,8 @@ static int ipw2100_wx_set_encodeext(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
return ieee80211_wx_set_encodeext(priv->ieee, info, wrqu, extra);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
return libipw_wx_set_encodeext(priv->ieee, info, wrqu, extra);
|
||||
}
|
||||
|
||||
/* SIOCGIWENCODEEXT */
|
||||
|
@ -7801,8 +7801,8 @@ static int ipw2100_wx_get_encodeext(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
return ieee80211_wx_get_encodeext(priv->ieee, info, wrqu, extra);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
return libipw_wx_get_encodeext(priv->ieee, info, wrqu, extra);
|
||||
}
|
||||
|
||||
/* SIOCSIWMLME */
|
||||
|
@ -7810,7 +7810,7 @@ static int ipw2100_wx_set_mlme(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
struct iw_mlme *mlme = (struct iw_mlme *)extra;
|
||||
__le16 reason;
|
||||
|
||||
|
@ -7841,7 +7841,7 @@ static int ipw2100_wx_set_promisc(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int *parms = (int *)extra;
|
||||
int enable = (parms[0] > 0);
|
||||
int err = 0;
|
||||
|
@ -7872,7 +7872,7 @@ static int ipw2100_wx_reset(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
if (priv->status & STATUS_INITIALIZED)
|
||||
schedule_reset(priv);
|
||||
return 0;
|
||||
|
@ -7884,7 +7884,7 @@ static int ipw2100_wx_set_powermode(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int err = 0, mode = *(int *)extra;
|
||||
|
||||
mutex_lock(&priv->action_mutex);
|
||||
|
@ -7912,7 +7912,7 @@ static int ipw2100_wx_get_powermode(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int level = IPW_POWER_LEVEL(priv->power_mode);
|
||||
s32 timeout, period;
|
||||
|
||||
|
@ -7948,7 +7948,7 @@ static int ipw2100_wx_set_preamble(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int err, mode = *(int *)extra;
|
||||
|
||||
mutex_lock(&priv->action_mutex);
|
||||
|
@ -7981,7 +7981,7 @@ static int ipw2100_wx_get_preamble(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
if (priv->config & CFG_LONG_PREAMBLE)
|
||||
snprintf(wrqu->name, IFNAMSIZ, "long (1)");
|
||||
|
@ -7996,7 +7996,7 @@ static int ipw2100_wx_set_crc_check(struct net_device *dev,
|
|||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
int err, mode = *(int *)extra;
|
||||
|
||||
mutex_lock(&priv->action_mutex);
|
||||
|
@ -8028,7 +8028,7 @@ static int ipw2100_wx_get_crc_check(struct net_device *dev,
|
|||
* This can be called at any time. No action lock required
|
||||
*/
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
if (priv->config & CFG_CRC_CHECK)
|
||||
snprintf(wrqu->name, IFNAMSIZ, "CRC checked (1)");
|
||||
|
@ -8181,7 +8181,7 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev)
|
|||
int beacon_qual;
|
||||
int quality;
|
||||
|
||||
struct ipw2100_priv *priv = ieee80211_priv(dev);
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
struct iw_statistics *wstats;
|
||||
u32 rssi, tx_retries, missed_beacons, tx_failures;
|
||||
u32 ord_len = sizeof(u32);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
file called LICENSE.
|
||||
|
||||
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
|
||||
|
||||
******************************************************************************/
|
||||
|
@ -46,7 +46,7 @@
|
|||
#include <linux/workqueue.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include "ieee80211.h"
|
||||
#include "libipw.h"
|
||||
|
||||
struct ipw2100_priv;
|
||||
struct ipw2100_tx_packet;
|
||||
|
@ -343,7 +343,7 @@ struct ipw2100_tx_packet {
|
|||
struct { /* DATA */
|
||||
struct ipw2100_data_header *data;
|
||||
dma_addr_t data_phys;
|
||||
struct ieee80211_txb *txb;
|
||||
struct libipw_txb *txb;
|
||||
} d_struct;
|
||||
} info;
|
||||
int jiffy_start;
|
||||
|
@ -492,7 +492,7 @@ struct ipw2100_priv {
|
|||
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 */
|
||||
|
||||
struct ieee80211_device *ieee;
|
||||
struct libipw_device *ieee;
|
||||
unsigned long status;
|
||||
unsigned long config;
|
||||
unsigned long capability;
|
||||
|
@ -788,7 +788,7 @@ struct ipw2100_priv {
|
|||
#define IPW_CARD_DISABLE_PHY_OFF_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_802_11_PAYLOAD_LENGTH 2312
|
||||
#define IPW_MAX_ACCEPTABLE_TX_FRAME_LENGTH 1536
|
||||
|
@ -803,13 +803,13 @@ struct ipw2100_priv {
|
|||
IPW_802_11_FCS_LENGTH)
|
||||
|
||||
#define IPW_802_11_PAYLOAD_OFFSET \
|
||||
(sizeof(struct ieee80211_hdr_3addr) + \
|
||||
sizeof(struct ieee80211_snap_hdr))
|
||||
(sizeof(struct libipw_hdr_3addr) + \
|
||||
sizeof(struct libipw_snap_hdr))
|
||||
|
||||
struct ipw2100_rx {
|
||||
union {
|
||||
unsigned char payload[IPW_RX_NIC_BUFFER_LENGTH];
|
||||
struct ieee80211_hdr_4addr header;
|
||||
struct libipw_hdr_4addr header;
|
||||
u32 status;
|
||||
struct ipw2100_notification notification;
|
||||
struct ipw2100_cmd_header command;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -19,7 +19,7 @@
|
|||
file called LICENSE.
|
||||
|
||||
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
|
||||
|
||||
******************************************************************************/
|
||||
|
@ -55,7 +55,7 @@
|
|||
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "ieee80211.h"
|
||||
#include "libipw.h"
|
||||
|
||||
/* Authentication and Association States */
|
||||
enum connection_manager_assoc_states {
|
||||
|
@ -365,8 +365,8 @@ enum connection_manager_assoc_states {
|
|||
/* QoS sturctures */
|
||||
struct ipw_qos_info {
|
||||
int qos_enable;
|
||||
struct ieee80211_qos_parameters *def_qos_parm_OFDM;
|
||||
struct ieee80211_qos_parameters *def_qos_parm_CCK;
|
||||
struct libipw_qos_parameters *def_qos_parm_OFDM;
|
||||
struct libipw_qos_parameters *def_qos_parm_CCK;
|
||||
u32 burst_duration_CCK;
|
||||
u32 burst_duration_OFDM;
|
||||
u16 qos_no_ack_mask;
|
||||
|
@ -534,7 +534,7 @@ typedef void destructor_func(const void *);
|
|||
struct clx2_tx_queue {
|
||||
struct clx2_queue q;
|
||||
struct tfd_frame *bd;
|
||||
struct ieee80211_txb **txb;
|
||||
struct libipw_txb **txb;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1144,7 +1144,7 @@ enum ipw_prom_filter {
|
|||
struct ipw_priv;
|
||||
struct ipw_prom_priv {
|
||||
struct ipw_priv *priv;
|
||||
struct ieee80211_device *ieee;
|
||||
struct libipw_device *ieee;
|
||||
enum ipw_prom_filter filter;
|
||||
int tx_packets;
|
||||
int rx_packets;
|
||||
|
@ -1175,7 +1175,7 @@ struct ipw_rt_hdr {
|
|||
|
||||
struct ipw_priv {
|
||||
/* ieee device used by generic ieee processing code */
|
||||
struct ieee80211_device *ieee;
|
||||
struct libipw_device *ieee;
|
||||
|
||||
spinlock_t lock;
|
||||
spinlock_t irq_lock;
|
||||
|
@ -1222,7 +1222,7 @@ struct ipw_priv {
|
|||
u32 roaming_threshold;
|
||||
|
||||
struct ipw_associate assoc_request;
|
||||
struct ieee80211_network *assoc_network;
|
||||
struct libipw_network *assoc_network;
|
||||
|
||||
unsigned long ts_scan_abort;
|
||||
struct ipw_supported_rates rates;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -19,7 +19,7 @@
|
|||
file called LICENSE.
|
||||
|
||||
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
|
||||
|
||||
******************************************************************************/
|
||||
|
@ -41,9 +41,9 @@
|
|||
#include <linux/etherdevice.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;
|
||||
|
||||
|
@ -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)
|
||||
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++)
|
||||
/* NOTE: If G mode is currently supported but
|
||||
* this is a B only channel, we don't see it
|
||||
* as valid. */
|
||||
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->geo.bg[i].flags & IEEE80211_CH_B_ONLY)))
|
||||
return IEEE80211_24GHZ_BAND;
|
||||
!(ieee->geo.bg[i].flags & LIBIPW_CH_B_ONLY)))
|
||||
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++)
|
||||
if ((ieee->geo.a[i].channel == channel) &&
|
||||
!(ieee->geo.a[i].flags & IEEE80211_CH_INVALID))
|
||||
return IEEE80211_52GHZ_BAND;
|
||||
!(ieee->geo.a[i].flags & LIBIPW_CH_INVALID))
|
||||
return LIBIPW_52GHZ_BAND;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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)
|
||||
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++)
|
||||
if (ieee->geo.bg[i].channel == channel)
|
||||
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++)
|
||||
if (ieee->geo.a[i].channel == channel)
|
||||
return i;
|
||||
|
@ -94,22 +94,22 @@ int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
|
|||
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
|
||||
* these helper functions */
|
||||
if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
|
||||
return 0;
|
||||
|
||||
ch = ieee80211_get_channel(ieee, channel);
|
||||
ch = libipw_get_channel(ieee, channel);
|
||||
if (!ch->channel)
|
||||
return 0;
|
||||
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;
|
||||
|
||||
|
@ -120,12 +120,12 @@ u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
|
|||
|
||||
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++)
|
||||
if (ieee->geo.bg[i].freq == freq)
|
||||
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++)
|
||||
if (ieee->geo.a[i].freq == freq)
|
||||
return ieee->geo.a[i].channel;
|
||||
|
@ -133,63 +133,63 @@ u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ieee80211_set_geo(struct ieee80211_device *ieee,
|
||||
const struct ieee80211_geo *geo)
|
||||
int libipw_set_geo(struct libipw_device *ieee,
|
||||
const struct libipw_geo *geo)
|
||||
{
|
||||
memcpy(ieee->geo.name, geo->name, 3);
|
||||
ieee->geo.name[3] = '\0';
|
||||
ieee->geo.bg_channels = geo->bg_channels;
|
||||
ieee->geo.a_channels = geo->a_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 *
|
||||
sizeof(struct ieee80211_channel));
|
||||
sizeof(struct libipw_channel));
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
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.a[index].flags;
|
||||
}
|
||||
|
||||
static const struct ieee80211_channel bad_channel = {
|
||||
static const struct libipw_channel bad_channel = {
|
||||
.channel = 0,
|
||||
.flags = IEEE80211_CH_INVALID,
|
||||
.flags = LIBIPW_CH_INVALID,
|
||||
.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)
|
||||
{
|
||||
int index = ieee80211_channel_to_index(ieee, channel);
|
||||
int index = libipw_channel_to_index(ieee, channel);
|
||||
|
||||
if (index == -1)
|
||||
return &bad_channel;
|
||||
|
||||
if (channel <= IEEE80211_24GHZ_CHANNELS)
|
||||
if (channel <= LIBIPW_24GHZ_CHANNELS)
|
||||
return &ieee->geo.bg[index];
|
||||
|
||||
return &ieee->geo.a[index];
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ieee80211_get_channel);
|
||||
EXPORT_SYMBOL(ieee80211_get_channel_flags);
|
||||
EXPORT_SYMBOL(ieee80211_is_valid_channel);
|
||||
EXPORT_SYMBOL(ieee80211_freq_to_channel);
|
||||
EXPORT_SYMBOL(ieee80211_channel_to_freq);
|
||||
EXPORT_SYMBOL(ieee80211_channel_to_index);
|
||||
EXPORT_SYMBOL(ieee80211_set_geo);
|
||||
EXPORT_SYMBOL(ieee80211_get_geo);
|
||||
EXPORT_SYMBOL(libipw_get_channel);
|
||||
EXPORT_SYMBOL(libipw_get_channel_flags);
|
||||
EXPORT_SYMBOL(libipw_is_valid_channel);
|
||||
EXPORT_SYMBOL(libipw_freq_to_channel);
|
||||
EXPORT_SYMBOL(libipw_channel_to_freq);
|
||||
EXPORT_SYMBOL(libipw_channel_to_index);
|
||||
EXPORT_SYMBOL(libipw_set_geo);
|
||||
EXPORT_SYMBOL(libipw_get_geo);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
file called LICENSE.
|
||||
|
||||
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
|
||||
|
||||
*******************************************************************************/
|
||||
|
@ -50,11 +50,11 @@
|
|||
#include <net/net_namespace.h>
|
||||
#include <net/arp.h>
|
||||
|
||||
#include "ieee80211.h"
|
||||
#include "libipw.h"
|
||||
|
||||
#define DRV_DESCRIPTION "802.11 data/management/control stack"
|
||||
#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>"
|
||||
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
@ -62,13 +62,16 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
|||
MODULE_AUTHOR(DRV_COPYRIGHT);
|
||||
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)
|
||||
return 0;
|
||||
|
||||
ieee->networks =
|
||||
kzalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
|
||||
kzalloc(MAX_NETWORK_COUNT * sizeof(struct libipw_network),
|
||||
GFP_KERNEL);
|
||||
if (!ieee->networks) {
|
||||
printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
|
||||
|
@ -79,7 +82,7 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ieee80211_network_reset(struct ieee80211_network *network)
|
||||
void libipw_network_reset(struct libipw_network *network)
|
||||
{
|
||||
if (!network)
|
||||
return;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -105,10 +108,10 @@ static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
|
|||
ieee->networks = NULL;
|
||||
}
|
||||
|
||||
void ieee80211_networks_age(struct ieee80211_device *ieee,
|
||||
void libipw_networks_age(struct libipw_device *ieee,
|
||||
unsigned long age_secs)
|
||||
{
|
||||
struct ieee80211_network *network = NULL;
|
||||
struct libipw_network *network = NULL;
|
||||
unsigned long flags;
|
||||
unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
|
||||
|
||||
|
@ -118,9 +121,9 @@ void ieee80211_networks_age(struct ieee80211_device *ieee,
|
|||
}
|
||||
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;
|
||||
|
||||
|
@ -131,38 +134,59 @@ static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
|
|||
&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;
|
||||
dev->mtu = new_mtu;
|
||||
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;
|
||||
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) {
|
||||
IEEE80211_ERROR("Unable to allocate network device.\n");
|
||||
LIBIPW_ERROR("Unable to allocate network device.\n");
|
||||
goto failed;
|
||||
}
|
||||
ieee = netdev_priv(dev);
|
||||
|
||||
ieee->dev = dev;
|
||||
|
||||
err = ieee80211_networks_allocate(ieee);
|
||||
if (err) {
|
||||
IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
|
||||
goto failed_free_netdev;
|
||||
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);
|
||||
}
|
||||
ieee80211_networks_initialize(ieee);
|
||||
|
||||
err = libipw_networks_allocate(ieee);
|
||||
if (err) {
|
||||
LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
|
||||
goto failed_free_wiphy;
|
||||
}
|
||||
libipw_networks_initialize(ieee);
|
||||
|
||||
/* Default fragmentation threshold is maximum payload size */
|
||||
ieee->fts = DEFAULT_FTS;
|
||||
|
@ -193,33 +217,45 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
|
|||
|
||||
return dev;
|
||||
|
||||
failed_free_wiphy:
|
||||
if (!monitor)
|
||||
wiphy_free(ieee->wdev.wiphy);
|
||||
failed_free_netdev:
|
||||
free_netdev(dev);
|
||||
failed:
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LIBIPW_DEBUG
|
||||
|
||||
static int debug = 0;
|
||||
u32 ieee80211_debug_level = 0;
|
||||
EXPORT_SYMBOL_GPL(ieee80211_debug_level);
|
||||
static struct proc_dir_entry *ieee80211_proc = NULL;
|
||||
u32 libipw_debug_level = 0;
|
||||
EXPORT_SYMBOL_GPL(libipw_debug_level);
|
||||
static struct proc_dir_entry *libipw_proc = NULL;
|
||||
|
||||
static int show_debug_level(char *page, char **start, off_t offset,
|
||||
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,
|
||||
|
@ -236,29 +272,29 @@ static int store_debug_level(struct file *file, const char __user * buffer,
|
|||
printk(KERN_INFO DRV_NAME
|
||||
": %s is not in hex or decimal form.\n", buf);
|
||||
else
|
||||
ieee80211_debug_level = val;
|
||||
libipw_debug_level = val;
|
||||
|
||||
return strnlen(buf, len);
|
||||
}
|
||||
#endif /* CONFIG_LIBIPW_DEBUG */
|
||||
|
||||
static int __init ieee80211_init(void)
|
||||
static int __init libipw_init(void)
|
||||
{
|
||||
#ifdef CONFIG_LIBIPW_DEBUG
|
||||
struct proc_dir_entry *e;
|
||||
|
||||
ieee80211_debug_level = debug;
|
||||
ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
|
||||
if (ieee80211_proc == NULL) {
|
||||
IEEE80211_ERROR("Unable to create " DRV_NAME
|
||||
libipw_debug_level = debug;
|
||||
libipw_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
|
||||
if (libipw_proc == NULL) {
|
||||
LIBIPW_ERROR("Unable to create " DRV_NAME
|
||||
" proc directory\n");
|
||||
return -EIO;
|
||||
}
|
||||
e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
|
||||
ieee80211_proc);
|
||||
libipw_proc);
|
||||
if (!e) {
|
||||
remove_proc_entry(DRV_NAME, init_net.proc_net);
|
||||
ieee80211_proc = NULL;
|
||||
libipw_proc = NULL;
|
||||
return -EIO;
|
||||
}
|
||||
e->read_proc = show_debug_level;
|
||||
|
@ -272,13 +308,13 @@ static int __init ieee80211_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ieee80211_exit(void)
|
||||
static void __exit libipw_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_LIBIPW_DEBUG
|
||||
if (ieee80211_proc) {
|
||||
remove_proc_entry("debug_level", ieee80211_proc);
|
||||
if (libipw_proc) {
|
||||
remove_proc_entry("debug_level", libipw_proc);
|
||||
remove_proc_entry(DRV_NAME, init_net.proc_net);
|
||||
ieee80211_proc = NULL;
|
||||
libipw_proc = NULL;
|
||||
}
|
||||
#endif /* CONFIG_LIBIPW_DEBUG */
|
||||
}
|
||||
|
@ -289,8 +325,8 @@ module_param(debug, int, 0444);
|
|||
MODULE_PARM_DESC(debug, "debug output mask");
|
||||
#endif /* CONFIG_LIBIPW_DEBUG */
|
||||
|
||||
module_exit(ieee80211_exit);
|
||||
module_init(ieee80211_init);
|
||||
module_exit(libipw_exit);
|
||||
module_init(libipw_init);
|
||||
|
||||
EXPORT_SYMBOL(alloc_ieee80211);
|
||||
EXPORT_SYMBOL(free_ieee80211);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -19,7 +19,7 @@
|
|||
file called LICENSE.
|
||||
|
||||
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
|
||||
|
||||
******************************************************************************/
|
||||
|
@ -41,7 +41,7 @@
|
|||
#include <linux/etherdevice.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "ieee80211.h"
|
||||
#include "libipw.h"
|
||||
|
||||
/*
|
||||
|
||||
|
@ -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 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;
|
||||
|
||||
snap = (struct ieee80211_snap_hdr *)data;
|
||||
snap = (struct libipw_snap_hdr *)data;
|
||||
snap->dsap = 0xaa;
|
||||
snap->ssap = 0xaa;
|
||||
snap->ctrl = 0x03;
|
||||
|
@ -149,7 +149,7 @@ static int ieee80211_copy_snap(u8 * data, __be16 h_proto)
|
|||
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 lib80211_crypt_data *crypt =
|
||||
|
@ -177,7 +177,7 @@ static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ieee80211_txb_free(struct ieee80211_txb *txb)
|
||||
void libipw_txb_free(struct libipw_txb *txb)
|
||||
{
|
||||
int i;
|
||||
if (unlikely(!txb))
|
||||
|
@ -188,17 +188,17 @@ void ieee80211_txb_free(struct ieee80211_txb *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)
|
||||
{
|
||||
struct ieee80211_txb *txb;
|
||||
struct libipw_txb *txb;
|
||||
int i;
|
||||
txb = kmalloc(sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags),
|
||||
txb = kmalloc(sizeof(struct libipw_txb) + (sizeof(u8 *) * nr_frags),
|
||||
gfp_mask);
|
||||
if (!txb)
|
||||
return NULL;
|
||||
|
||||
memset(txb, 0, sizeof(struct ieee80211_txb));
|
||||
memset(txb, 0, sizeof(struct libipw_txb));
|
||||
txb->nr_frags = nr_frags;
|
||||
txb->frag_size = txb_size;
|
||||
|
||||
|
@ -220,7 +220,7 @@ static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
|
|||
return txb;
|
||||
}
|
||||
|
||||
static int ieee80211_classify(struct sk_buff *skb)
|
||||
static int libipw_classify(struct sk_buff *skb)
|
||||
{
|
||||
struct ethhdr *eth;
|
||||
struct iphdr *ip;
|
||||
|
@ -252,11 +252,11 @@ static int ieee80211_classify(struct sk_buff *skb)
|
|||
|
||||
/* Incoming skb is converted to a txb which consists of
|
||||
* 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 ieee80211_txb *txb = NULL;
|
||||
struct ieee80211_hdr_3addrqos *frag_hdr;
|
||||
struct libipw_device *ieee = netdev_priv(dev);
|
||||
struct libipw_txb *txb = NULL;
|
||||
struct libipw_hdr_3addrqos *frag_hdr;
|
||||
int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
|
||||
rts_required;
|
||||
unsigned long flags;
|
||||
|
@ -264,7 +264,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
__be16 ether_type;
|
||||
int bytes, fc, hdr_len;
|
||||
struct sk_buff *skb_frag;
|
||||
struct ieee80211_hdr_3addrqos header = {/* Ensure zero initialized */
|
||||
struct libipw_hdr_3addrqos header = {/* Ensure zero initialized */
|
||||
.duration_id = 0,
|
||||
.seq_ctl = 0,
|
||||
.qos_ctl = 0
|
||||
|
@ -331,14 +331,14 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
memcpy(header.addr2, src, 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)) {
|
||||
fc |= IEEE80211_STYPE_QOS_DATA;
|
||||
hdr_len += 2;
|
||||
|
||||
skb->priority = ieee80211_classify(skb);
|
||||
header.qos_ctl |= cpu_to_le16(skb->priority & IEEE80211_QCTL_TID);
|
||||
skb->priority = libipw_classify(skb);
|
||||
header.qos_ctl |= cpu_to_le16(skb->priority & LIBIPW_QCTL_TID);
|
||||
}
|
||||
header.frame_ctl = cpu_to_le16(fc);
|
||||
|
||||
|
@ -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);
|
||||
memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
|
||||
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);
|
||||
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);
|
||||
if (res < 0) {
|
||||
IEEE80211_ERROR("msdu encryption failed\n");
|
||||
LIBIPW_ERROR("msdu encryption failed\n");
|
||||
dev_kfree_skb_any(skb_new);
|
||||
goto failed;
|
||||
}
|
||||
|
@ -393,8 +393,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
* for it when determining the amount of payload space. */
|
||||
bytes_per_frag = frag_size - hdr_len;
|
||||
if (ieee->config &
|
||||
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
|
||||
bytes_per_frag -= IEEE80211_FCS_LEN;
|
||||
(CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
|
||||
bytes_per_frag -= LIBIPW_FCS_LEN;
|
||||
|
||||
/* Each fragment may need to have room for encryptiong
|
||||
* pre/postfix */
|
||||
|
@ -417,14 +417,14 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
}
|
||||
|
||||
rts_required = (frag_size > ieee->rts
|
||||
&& ieee->config & CFG_IEEE80211_RTS);
|
||||
&& ieee->config & CFG_LIBIPW_RTS);
|
||||
if (rts_required)
|
||||
nr_frags++;
|
||||
|
||||
/* When we allocate the TXB we allocate enough space for the reserve
|
||||
* and full fragment bytes (bytes_per_frag doesn't include prefix,
|
||||
* 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);
|
||||
if (unlikely(!txb)) {
|
||||
printk(KERN_WARNING "%s: Could not allocate TXB\n",
|
||||
|
@ -441,7 +441,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
if (rts_required) {
|
||||
skb_frag = txb->fragments[0];
|
||||
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.
|
||||
|
@ -456,7 +456,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
header.frame_ctl = cpu_to_le16(fc);
|
||||
|
||||
if (ieee->config &
|
||||
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
|
||||
(CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
|
||||
skb_put(skb_frag, 4);
|
||||
|
||||
txb->rts_included = 1;
|
||||
|
@ -472,7 +472,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
crypt->ops->extra_mpdu_prefix_len);
|
||||
|
||||
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);
|
||||
|
||||
/* 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)
|
|||
}
|
||||
|
||||
if (i == 0 && !snapped) {
|
||||
ieee80211_copy_snap(skb_put
|
||||
libipw_copy_snap(skb_put
|
||||
(skb_frag, SNAP_SIZE + sizeof(u16)),
|
||||
ether_type);
|
||||
bytes -= SNAP_SIZE + sizeof(u16);
|
||||
|
@ -501,7 +501,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
/* Encryption routine will move the header forward in order
|
||||
* to insert the IV between the header and the payload */
|
||||
if (host_encrypt)
|
||||
ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
|
||||
libipw_encrypt_fragment(ieee, skb_frag, hdr_len);
|
||||
else if (host_build_iv) {
|
||||
atomic_inc(&crypt->refcnt);
|
||||
if (crypt->ops->build_iv)
|
||||
|
@ -513,7 +513,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
}
|
||||
|
||||
if (ieee->config &
|
||||
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
|
||||
(CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS))
|
||||
skb_put(skb_frag, 4);
|
||||
}
|
||||
|
||||
|
@ -530,7 +530,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
ieee80211_txb_free(txb);
|
||||
libipw_txb_free(txb);
|
||||
}
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
|
@ -541,6 +541,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
dev->stats.tx_errors++;
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_xmit);
|
||||
EXPORT_SYMBOL(libipw_xmit);
|
||||
|
||||
EXPORT_SYMBOL(ieee80211_txb_free);
|
||||
EXPORT_SYMBOL(libipw_txb_free);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
file called LICENSE.
|
||||
|
||||
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
|
||||
|
||||
******************************************************************************/
|
||||
|
@ -37,9 +37,9 @@
|
|||
#include <net/lib80211.h>
|
||||
#include <linux/wireless.h>
|
||||
|
||||
#include "ieee80211.h"
|
||||
#include "libipw.h"
|
||||
|
||||
static const char *ieee80211_modes[] = {
|
||||
static const char *libipw_modes[] = {
|
||||
"?", "a", "b", "ab", "g", "ag", "bg", "abg"
|
||||
};
|
||||
|
||||
|
@ -54,9 +54,9 @@ static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
|
|||
}
|
||||
|
||||
#define MAX_CUSTOM_LEN 64
|
||||
static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
|
||||
static char *libipw_translate_scan(struct libipw_device *ieee,
|
||||
char *start, char *stop,
|
||||
struct ieee80211_network *network,
|
||||
struct libipw_network *network,
|
||||
struct iw_request_info *info)
|
||||
{
|
||||
char custom[MAX_CUSTOM_LEN];
|
||||
|
@ -84,7 +84,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
|
|||
/* Add the protocol name */
|
||||
iwe.cmd = SIOCGIWNAME;
|
||||
snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s",
|
||||
ieee80211_modes[network->mode]);
|
||||
libipw_modes[network->mode]);
|
||||
start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
|
||||
|
||||
/* Add mode */
|
||||
|
@ -102,7 +102,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
|
|||
/* Add channel and frequency */
|
||||
/* Note : userspace automatically computes channel using iwrange */
|
||||
iwe.cmd = SIOCGIWFREQ;
|
||||
iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel);
|
||||
iwe.u.freq.m = libipw_channel_to_freq(ieee, network->channel);
|
||||
iwe.u.freq.e = 6;
|
||||
iwe.u.freq.i = 0;
|
||||
start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
|
||||
|
@ -155,7 +155,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
|
|||
iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
|
||||
IW_QUAL_NOISE_UPDATED;
|
||||
|
||||
if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) {
|
||||
if (!(network->stats.mask & LIBIPW_STATMASK_RSSI)) {
|
||||
iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
|
||||
IW_QUAL_LEVEL_INVALID;
|
||||
iwe.u.qual.qual = 0;
|
||||
|
@ -180,14 +180,14 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
|
|||
iwe.u.qual.qual = 0;
|
||||
}
|
||||
|
||||
if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
|
||||
if (!(network->stats.mask & LIBIPW_STATMASK_NOISE)) {
|
||||
iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
|
||||
iwe.u.qual.noise = 0;
|
||||
} else {
|
||||
iwe.u.qual.noise = network->stats.noise;
|
||||
}
|
||||
|
||||
if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) {
|
||||
if (!(network->stats.mask & LIBIPW_STATMASK_SIGNAL)) {
|
||||
iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
|
||||
iwe.u.qual.level = 0;
|
||||
} else {
|
||||
|
@ -237,14 +237,14 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
|
|||
p = custom;
|
||||
p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");
|
||||
|
||||
if (ieee80211_get_channel_flags(ieee, network->channel) &
|
||||
IEEE80211_CH_INVALID) {
|
||||
if (libipw_get_channel_flags(ieee, network->channel) &
|
||||
LIBIPW_CH_INVALID) {
|
||||
iwe.cmd = IWEVCUSTOM;
|
||||
p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");
|
||||
}
|
||||
|
||||
if (ieee80211_get_channel_flags(ieee, network->channel) &
|
||||
IEEE80211_CH_RADAR_DETECT) {
|
||||
if (libipw_get_channel_flags(ieee, network->channel) &
|
||||
LIBIPW_CH_RADAR_DETECT) {
|
||||
iwe.cmd = IWEVCUSTOM;
|
||||
p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");
|
||||
}
|
||||
|
@ -259,11 +259,11 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
|
|||
|
||||
#define SCAN_ITEM_SIZE 128
|
||||
|
||||
int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
|
||||
int libipw_wx_get_scan(struct libipw_device *ieee,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ieee80211_network *network;
|
||||
struct libipw_network *network;
|
||||
unsigned long flags;
|
||||
int err = 0;
|
||||
|
||||
|
@ -272,7 +272,7 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
|
|||
int i = 0;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
IEEE80211_DEBUG_WX("Getting scan\n");
|
||||
LIBIPW_DEBUG_WX("Getting scan\n");
|
||||
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
|
||||
|
@ -285,10 +285,10 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
|
|||
|
||||
if (ieee->scan_age == 0 ||
|
||||
time_after(network->last_scanned + ieee->scan_age, jiffies))
|
||||
ev = ieee80211_translate_scan(ieee, ev, stop, network,
|
||||
ev = libipw_translate_scan(ieee, ev, stop, network,
|
||||
info);
|
||||
else {
|
||||
IEEE80211_DEBUG_SCAN("Not showing network '%s ("
|
||||
LIBIPW_DEBUG_SCAN("Not showing network '%s ("
|
||||
"%pM)' due to age (%ums).\n",
|
||||
print_ssid(ssid, network->ssid,
|
||||
network->ssid_len),
|
||||
|
@ -303,18 +303,18 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
|
|||
wrqu->data.length = ev - extra;
|
||||
wrqu->data.flags = 0;
|
||||
|
||||
IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
|
||||
LIBIPW_DEBUG_WX("exit: %d networks returned.\n", i);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
||||
int libipw_wx_set_encode(struct libipw_device *ieee,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *keybuf)
|
||||
{
|
||||
struct iw_point *erq = &(wrqu->encoding);
|
||||
struct net_device *dev = ieee->dev;
|
||||
struct ieee80211_security sec = {
|
||||
struct libipw_security sec = {
|
||||
.flags = 0
|
||||
};
|
||||
int i, key, key_provided, len;
|
||||
|
@ -322,7 +322,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
|||
int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
|
||||
IEEE80211_DEBUG_WX("SET_ENCODE\n");
|
||||
LIBIPW_DEBUG_WX("SET_ENCODE\n");
|
||||
|
||||
key = erq->flags & IW_ENCODE_INDEX;
|
||||
if (key) {
|
||||
|
@ -335,18 +335,18 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
|||
key = ieee->crypt_info.tx_keyidx;
|
||||
}
|
||||
|
||||
IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
|
||||
LIBIPW_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
|
||||
"provided" : "default");
|
||||
|
||||
crypt = &ieee->crypt_info.crypt[key];
|
||||
|
||||
if (erq->flags & IW_ENCODE_DISABLED) {
|
||||
if (key_provided && *crypt) {
|
||||
IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
|
||||
LIBIPW_DEBUG_WX("Disabling encryption on key %d.\n",
|
||||
key);
|
||||
lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
|
||||
} else
|
||||
IEEE80211_DEBUG_WX("Disabling encryption.\n");
|
||||
LIBIPW_DEBUG_WX("Disabling encryption.\n");
|
||||
|
||||
/* Check all the keys to see if any are still configured,
|
||||
* and if no key index was provided, de-init them all */
|
||||
|
@ -410,7 +410,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
|||
|
||||
/* If a new key was provided, set it up */
|
||||
if (erq->length > 0) {
|
||||
#ifdef CONFIG_IEEE80211_DEBUG
|
||||
#ifdef CONFIG_LIBIPW_DEBUG
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
#endif
|
||||
|
||||
|
@ -419,7 +419,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
|||
if (len > erq->length)
|
||||
memset(sec.keys[key] + erq->length, 0,
|
||||
len - erq->length);
|
||||
IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
|
||||
LIBIPW_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
|
||||
key, print_ssid(ssid, sec.keys[key], len),
|
||||
erq->length, len);
|
||||
sec.key_sizes[key] = len;
|
||||
|
@ -438,7 +438,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
|||
NULL, (*crypt)->priv);
|
||||
if (len == 0) {
|
||||
/* Set a default key of all 0 */
|
||||
IEEE80211_DEBUG_WX("Setting key %d to all "
|
||||
LIBIPW_DEBUG_WX("Setting key %d to all "
|
||||
"zero.\n", key);
|
||||
memset(sec.keys[key], 0, 13);
|
||||
(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
|
||||
|
@ -449,7 +449,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
|||
}
|
||||
/* No key data - just set the default TX key index */
|
||||
if (key_provided) {
|
||||
IEEE80211_DEBUG_WX("Setting key %d to default Tx "
|
||||
LIBIPW_DEBUG_WX("Setting key %d to default Tx "
|
||||
"key.\n", key);
|
||||
ieee->crypt_info.tx_keyidx = key;
|
||||
sec.active_key = key;
|
||||
|
@ -461,7 +461,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
|||
sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
|
||||
WLAN_AUTH_SHARED_KEY;
|
||||
sec.flags |= SEC_AUTH_MODE;
|
||||
IEEE80211_DEBUG_WX("Auth: %s\n",
|
||||
LIBIPW_DEBUG_WX("Auth: %s\n",
|
||||
sec.auth_mode == WLAN_AUTH_OPEN ?
|
||||
"OPEN" : "SHARED KEY");
|
||||
}
|
||||
|
@ -490,16 +490,16 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
|
||||
int libipw_wx_get_encode(struct libipw_device *ieee,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *keybuf)
|
||||
{
|
||||
struct iw_point *erq = &(wrqu->encoding);
|
||||
int len, key;
|
||||
struct lib80211_crypt_data *crypt;
|
||||
struct ieee80211_security *sec = &ieee->sec;
|
||||
struct libipw_security *sec = &ieee->sec;
|
||||
|
||||
IEEE80211_DEBUG_WX("GET_ENCODE\n");
|
||||
LIBIPW_DEBUG_WX("GET_ENCODE\n");
|
||||
|
||||
key = erq->flags & IW_ENCODE_INDEX;
|
||||
if (key) {
|
||||
|
@ -532,7 +532,7 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
||||
int libipw_wx_set_encodeext(struct libipw_device *ieee,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
|
@ -545,7 +545,7 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
|||
struct lib80211_crypto_ops *ops;
|
||||
struct lib80211_crypt_data **crypt;
|
||||
|
||||
struct ieee80211_security sec = {
|
||||
struct libipw_security sec = {
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
|
@ -611,7 +611,7 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
|||
module = "lib80211_crypt_ccmp";
|
||||
break;
|
||||
default:
|
||||
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
|
||||
LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n",
|
||||
dev->name, ext->alg);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
|
@ -623,7 +623,7 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
|||
ops = lib80211_get_crypto_ops(alg);
|
||||
}
|
||||
if (ops == NULL) {
|
||||
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
|
||||
LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n",
|
||||
dev->name, ext->alg);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
|
@ -653,7 +653,7 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
|||
if (ext->key_len > 0 && (*crypt)->ops->set_key &&
|
||||
(*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
|
||||
(*crypt)->priv) < 0) {
|
||||
IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
|
||||
LIBIPW_DEBUG_WX("%s: key setting failed\n", dev->name);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
@ -700,20 +700,20 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
|
|||
if (ieee->reset_on_keychange &&
|
||||
ieee->iw_mode != IW_MODE_INFRA &&
|
||||
ieee->reset_port && ieee->reset_port(dev)) {
|
||||
IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
|
||||
LIBIPW_DEBUG_WX("%s: reset_port failed\n", dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
|
||||
int libipw_wx_get_encodeext(struct libipw_device *ieee,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct iw_point *encoding = &wrqu->encoding;
|
||||
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
|
||||
struct ieee80211_security *sec = &ieee->sec;
|
||||
struct libipw_security *sec = &ieee->sec;
|
||||
int idx, max_key_len;
|
||||
|
||||
max_key_len = encoding->length - sizeof(*ext);
|
||||
|
@ -763,9 +763,9 @@ int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
|
|||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
|
||||
EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
|
||||
EXPORT_SYMBOL(libipw_wx_set_encodeext);
|
||||
EXPORT_SYMBOL(libipw_wx_get_encodeext);
|
||||
|
||||
EXPORT_SYMBOL(ieee80211_wx_get_scan);
|
||||
EXPORT_SYMBOL(ieee80211_wx_set_encode);
|
||||
EXPORT_SYMBOL(ieee80211_wx_get_encode);
|
||||
EXPORT_SYMBOL(libipw_wx_get_scan);
|
||||
EXPORT_SYMBOL(libipw_wx_set_encode);
|
||||
EXPORT_SYMBOL(libipw_wx_get_encode);
|
||||
|
|
|
@ -46,8 +46,8 @@
|
|||
#include "iwl-5000-hw.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL6000_UCODE_API_MAX 3
|
||||
#define IWL6050_UCODE_API_MAX 3
|
||||
#define IWL6000_UCODE_API_MAX 4
|
||||
#define IWL6050_UCODE_API_MAX 4
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL6000_UCODE_API_MIN 1
|
||||
|
@ -126,6 +126,7 @@ static struct iwl_lib_ops iwl6000_lib = {
|
|||
.release_semaphore = iwlcore_eeprom_release_semaphore,
|
||||
.calib_version = iwl5000_eeprom_calib_version,
|
||||
.query_addr = iwl5000_eeprom_query_addr,
|
||||
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
|
||||
},
|
||||
.post_associate = iwl_post_associate,
|
||||
.isr = iwl_isr_ict,
|
||||
|
|
|
@ -2546,6 +2546,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
|
|||
rate_idx = rate_lowest_index(sband, sta);
|
||||
else if (sband->band == IEEE80211_BAND_5GHZ)
|
||||
rate_idx -= IWL_FIRST_OFDM_RATE;
|
||||
info->control.rates[0].flags = 0;
|
||||
}
|
||||
info->control.rates[0].idx = rate_idx;
|
||||
|
||||
|
|
|
@ -2155,7 +2155,7 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
|
|||
|
||||
priv->is_open = 0;
|
||||
|
||||
if (iwl_is_ready_rf(priv)) {
|
||||
if (iwl_is_ready_rf(priv) || test_bit(STATUS_SCAN_HW, &priv->status)) {
|
||||
/* stop mac, cancel any scan request and clear
|
||||
* RXON_FILTER_ASSOC_MSK BIT
|
||||
*/
|
||||
|
@ -2477,10 +2477,15 @@ static ssize_t store_tx_power(struct device *d,
|
|||
ret = strict_strtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
IWL_INFO(priv, "%s is not in decimal form.\n", buf);
|
||||
else
|
||||
iwl_set_tx_power(priv, val, false);
|
||||
|
||||
return count;
|
||||
else {
|
||||
ret = iwl_set_tx_power(priv, val, false);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "failed setting tx power (0x%d).\n",
|
||||
ret);
|
||||
else
|
||||
ret = count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
|
||||
|
|
|
@ -886,7 +886,6 @@ struct iwl_qosparam_cmd {
|
|||
|
||||
#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2);
|
||||
#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8);
|
||||
#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8);
|
||||
#define STA_FLG_RTS_MIMO_PROT_MSK cpu_to_le32(1 << 17)
|
||||
#define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18)
|
||||
#define STA_FLG_MAX_AGG_SIZE_POS (19)
|
||||
|
@ -2930,6 +2929,20 @@ struct statistics_rx {
|
|||
struct statistics_rx_ht_phy ofdm_ht;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/**
|
||||
* struct statistics_tx_power - current tx power
|
||||
*
|
||||
* @ant_a: current tx power on chain a in 1/2 dB step
|
||||
* @ant_b: current tx power on chain b in 1/2 dB step
|
||||
* @ant_c: current tx power on chain c in 1/2 dB step
|
||||
*/
|
||||
struct statistics_tx_power {
|
||||
u8 ant_a;
|
||||
u8 ant_b;
|
||||
u8 ant_c;
|
||||
u8 reserved;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct statistics_tx_non_phy_agg {
|
||||
__le32 ba_timeout;
|
||||
__le32 ba_reschedule_frames;
|
||||
|
@ -2941,8 +2954,6 @@ struct statistics_tx_non_phy_agg {
|
|||
__le32 underrun;
|
||||
__le32 bt_prio_kill;
|
||||
__le32 rx_ba_rsp_cnt;
|
||||
__le32 reserved2;
|
||||
__le32 reserved3;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct statistics_tx {
|
||||
|
@ -2961,6 +2972,8 @@ struct statistics_tx {
|
|||
__le32 cts_timeout_collision;
|
||||
__le32 ack_or_ba_timeout_collision;
|
||||
struct statistics_tx_non_phy_agg agg;
|
||||
struct statistics_tx_power tx_power;
|
||||
__le32 reserved1;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
|
|
|
@ -543,8 +543,8 @@ int iwlcore_init_geos(struct iwl_priv *priv)
|
|||
|
||||
geo_ch->flags |= ch->ht40_extension_channel;
|
||||
|
||||
if (ch->max_power_avg > priv->tx_power_channel_lmt)
|
||||
priv->tx_power_channel_lmt = ch->max_power_avg;
|
||||
if (ch->max_power_avg > priv->tx_power_device_lmt)
|
||||
priv->tx_power_device_lmt = ch->max_power_avg;
|
||||
} else {
|
||||
geo_ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
|
@ -1671,7 +1671,10 @@ int iwl_init_drv(struct iwl_priv *priv)
|
|||
priv->qos_data.qos_cap.val = 0;
|
||||
|
||||
priv->rates_mask = IWL_RATES_MASK;
|
||||
priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MAX;
|
||||
/* Set the tx_power_user_lmt to the lowest power level
|
||||
* this value will get overwritten by channel max power avg
|
||||
* from eeprom */
|
||||
priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN;
|
||||
|
||||
ret = iwl_init_channel_map(priv);
|
||||
if (ret) {
|
||||
|
@ -1698,6 +1701,8 @@ EXPORT_SYMBOL(iwl_init_drv);
|
|||
int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
|
||||
{
|
||||
int ret = 0;
|
||||
s8 prev_tx_power = priv->tx_power_user_lmt;
|
||||
|
||||
if (tx_power < IWL_TX_POWER_TARGET_POWER_MIN) {
|
||||
IWL_WARN(priv, "Requested user TXPOWER %d below lower limit %d.\n",
|
||||
tx_power,
|
||||
|
@ -1705,25 +1710,37 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (tx_power > IWL_TX_POWER_TARGET_POWER_MAX) {
|
||||
IWL_WARN(priv, "Requested user TXPOWER %d above upper limit %d.\n",
|
||||
tx_power,
|
||||
IWL_TX_POWER_TARGET_POWER_MAX);
|
||||
if (tx_power > priv->tx_power_device_lmt) {
|
||||
IWL_WARN(priv,
|
||||
"Requested user TXPOWER %d above upper limit %d.\n",
|
||||
tx_power, priv->tx_power_device_lmt);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (priv->tx_power_user_lmt != tx_power)
|
||||
force = true;
|
||||
|
||||
priv->tx_power_user_lmt = tx_power;
|
||||
|
||||
/* if nic is not up don't send command */
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return ret;
|
||||
|
||||
if (force && priv->cfg->ops->lib->send_tx_power)
|
||||
ret = priv->cfg->ops->lib->send_tx_power(priv);
|
||||
if (iwl_is_ready_rf(priv)) {
|
||||
priv->tx_power_user_lmt = tx_power;
|
||||
if (force && priv->cfg->ops->lib->send_tx_power)
|
||||
ret = priv->cfg->ops->lib->send_tx_power(priv);
|
||||
else if (!priv->cfg->ops->lib->send_tx_power)
|
||||
ret = -EOPNOTSUPP;
|
||||
/*
|
||||
* if fail to set tx_power, restore the orig. tx power
|
||||
*/
|
||||
if (ret)
|
||||
priv->tx_power_user_lmt = prev_tx_power;
|
||||
}
|
||||
|
||||
/*
|
||||
* Even this is an async host command, the command
|
||||
* will always report success from uCode
|
||||
* So once driver can placing the command into the queue
|
||||
* successfully, driver can use priv->tx_power_user_lmt
|
||||
* to reflect the current tx power
|
||||
*/
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_set_tx_power);
|
||||
|
@ -1806,7 +1823,7 @@ int iwl_reset_ict(struct iwl_priv *priv)
|
|||
spin_lock_irqsave(&priv->lock, flags);
|
||||
iwl_disable_interrupts(priv);
|
||||
|
||||
memset(&priv->ict_tbl[0],0, sizeof(u32) * ICT_COUNT);
|
||||
memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
|
||||
|
||||
val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT;
|
||||
|
||||
|
@ -1884,13 +1901,13 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
|
|||
/* read all entries that not 0 start with ict_index */
|
||||
while (priv->ict_tbl[priv->ict_index]) {
|
||||
|
||||
val |= priv->ict_tbl[priv->ict_index];
|
||||
val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]);
|
||||
IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n",
|
||||
priv->ict_index,
|
||||
priv->ict_tbl[priv->ict_index]);
|
||||
priv->ict_index,
|
||||
le32_to_cpu(priv->ict_tbl[priv->ict_index]));
|
||||
priv->ict_tbl[priv->ict_index] = 0;
|
||||
priv->ict_index = iwl_queue_inc_wrap(priv->ict_index,
|
||||
ICT_COUNT);
|
||||
ICT_COUNT);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,7 @@ struct iwl_debugfs {
|
|||
struct dentry *file_ucode_general_stats;
|
||||
struct dentry *file_sensitivity;
|
||||
struct dentry *file_chain_noise;
|
||||
struct dentry *file_tx_power;
|
||||
} dbgfs_debug_files;
|
||||
u32 sram_offset;
|
||||
u32 sram_len;
|
||||
|
|
|
@ -1563,6 +1563,57 @@ static ssize_t iwl_dbgfs_chain_noise_read(struct file *file,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_tx_power_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
||||
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
|
||||
char buf[128];
|
||||
int pos = 0;
|
||||
ssize_t ret;
|
||||
const size_t bufsz = sizeof(buf);
|
||||
struct statistics_tx *tx;
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
|
||||
else {
|
||||
/* make request to uCode to retrieve statistics information */
|
||||
mutex_lock(&priv->mutex);
|
||||
ret = iwl_send_statistics_request(priv, 0);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error sending statistics request: %zd\n",
|
||||
ret);
|
||||
return -EAGAIN;
|
||||
}
|
||||
tx = &priv->statistics.tx;
|
||||
if (tx->tx_power.ant_a ||
|
||||
tx->tx_power.ant_b ||
|
||||
tx->tx_power.ant_c) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"tx power: (1/2 dB step)\n");
|
||||
if ((priv->cfg->valid_tx_ant & ANT_A) &&
|
||||
tx->tx_power.ant_a)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tantenna A: 0x%X\n",
|
||||
tx->tx_power.ant_a);
|
||||
if ((priv->cfg->valid_tx_ant & ANT_B) &&
|
||||
tx->tx_power.ant_b)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tantenna B: 0x%X\n",
|
||||
tx->tx_power.ant_b);
|
||||
if ((priv->cfg->valid_tx_ant & ANT_C) &&
|
||||
tx->tx_power.ant_c)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tantenna C: 0x%X\n",
|
||||
tx->tx_power.ant_c);
|
||||
} else
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
|
||||
}
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
|
||||
|
@ -1573,6 +1624,7 @@ DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
|
|||
DEBUGFS_READ_FILE_OPS(ucode_general_stats);
|
||||
DEBUGFS_READ_FILE_OPS(sensitivity);
|
||||
DEBUGFS_READ_FILE_OPS(chain_noise);
|
||||
DEBUGFS_READ_FILE_OPS(tx_power);
|
||||
|
||||
/*
|
||||
* Create the debugfs files and directories
|
||||
|
@ -1621,6 +1673,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
|||
DEBUGFS_ADD_FILE(traffic_log, debug);
|
||||
DEBUGFS_ADD_FILE(rx_queue, debug);
|
||||
DEBUGFS_ADD_FILE(tx_queue, debug);
|
||||
DEBUGFS_ADD_FILE(tx_power, debug);
|
||||
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
|
||||
DEBUGFS_ADD_FILE(ucode_rx_stats, debug);
|
||||
DEBUGFS_ADD_FILE(ucode_tx_stats, debug);
|
||||
|
@ -1674,6 +1727,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
|
|||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power);
|
||||
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
|
||||
file_ucode_rx_stats);
|
||||
|
|
|
@ -1170,7 +1170,7 @@ struct iwl_priv {
|
|||
struct iwl_hw_params hw_params;
|
||||
|
||||
/* INT ICT Table */
|
||||
u32 *ict_tbl;
|
||||
__le32 *ict_tbl;
|
||||
dma_addr_t ict_tbl_dma;
|
||||
dma_addr_t aligned_ict_tbl_dma;
|
||||
int ict_index;
|
||||
|
@ -1215,7 +1215,7 @@ struct iwl_priv {
|
|||
|
||||
/* TX Power */
|
||||
s8 tx_power_user_lmt;
|
||||
s8 tx_power_channel_lmt;
|
||||
s8 tx_power_device_lmt;
|
||||
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
|
|
|
@ -135,6 +135,78 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */
|
|||
36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_txpwr_section: eeprom section information
|
||||
* @offset: indirect address into eeprom image
|
||||
* @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section
|
||||
* @band: band type for the section
|
||||
* @is_common - true: common section, false: channel section
|
||||
* @is_cck - true: cck section, false: not cck section
|
||||
* @is_ht_40 - true: all channel in the section are HT40 channel,
|
||||
* false: legacy or HT 20 MHz
|
||||
* ignore if it is common section
|
||||
* @iwl_eeprom_section_channel: channel array in the section,
|
||||
* ignore if common section
|
||||
*/
|
||||
struct iwl_txpwr_section {
|
||||
u32 offset;
|
||||
u8 count;
|
||||
enum ieee80211_band band;
|
||||
bool is_common;
|
||||
bool is_cck;
|
||||
bool is_ht40;
|
||||
u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS];
|
||||
};
|
||||
|
||||
/**
|
||||
* section 1 - 3 are regulatory tx power apply to all channels based on
|
||||
* modulation: CCK, OFDM
|
||||
* Band: 2.4GHz, 5.2GHz
|
||||
* section 4 - 10 are regulatory tx power apply to specified channels
|
||||
* For example:
|
||||
* 1L - Channel 1 Legacy
|
||||
* 1HT - Channel 1 HT
|
||||
* (1,+1) - Channel 1 HT40 "_above_"
|
||||
*
|
||||
* Section 1: all CCK channels
|
||||
* Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels
|
||||
* Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
|
||||
* Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT
|
||||
* Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1)
|
||||
* Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT
|
||||
* Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1)
|
||||
* Section 8: 2.4 GHz channel: 13L, 13HT
|
||||
* Section 9: 2.4 GHz channel: 140L, 140HT
|
||||
* Section 10: 2.4 GHz 40MHz channels: (132,+1) (44,+1)
|
||||
*
|
||||
*/
|
||||
static const struct iwl_txpwr_section enhinfo[] = {
|
||||
{ EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false },
|
||||
{ EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false },
|
||||
{ EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false },
|
||||
{ EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ,
|
||||
false, false, false,
|
||||
{1, 1, 2, 2, 10, 10, 11, 11 } },
|
||||
{ EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ,
|
||||
false, false, true,
|
||||
{ 1, 2, 6, 7, 9 } },
|
||||
{ EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ,
|
||||
false, false, false,
|
||||
{ 36, 64, 100, 36, 64, 100 } },
|
||||
{ EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ,
|
||||
false, false, true,
|
||||
{ 36, 60, 100 } },
|
||||
{ EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ,
|
||||
false, false, false,
|
||||
{ 13, 13 } },
|
||||
{ EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ,
|
||||
false, false, false,
|
||||
{ 140, 140 } },
|
||||
{ EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ,
|
||||
false, false, true,
|
||||
{ 132, 44 } },
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* EEPROM related functions
|
||||
|
@ -643,6 +715,178 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_get_max_txpower_avg - get the highest tx power from all chains.
|
||||
* find the highest tx power from all chains for the channel
|
||||
*/
|
||||
static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, int element)
|
||||
{
|
||||
s8 max_txpower_avg = 0; /* (dBm) */
|
||||
|
||||
IWL_DEBUG_INFO(priv, "%d - "
|
||||
"chain_a: %d dB chain_b: %d dB "
|
||||
"chain_c: %d dB mimo2: %d dB mimo3: %d dB\n",
|
||||
element,
|
||||
enhanced_txpower[element].chain_a_max >> 1,
|
||||
enhanced_txpower[element].chain_b_max >> 1,
|
||||
enhanced_txpower[element].chain_c_max >> 1,
|
||||
enhanced_txpower[element].mimo2_max >> 1,
|
||||
enhanced_txpower[element].mimo3_max >> 1);
|
||||
/* Take the highest tx power from any valid chains */
|
||||
if ((priv->cfg->valid_tx_ant & ANT_A) &&
|
||||
(enhanced_txpower[element].chain_a_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_a_max;
|
||||
if ((priv->cfg->valid_tx_ant & ANT_B) &&
|
||||
(enhanced_txpower[element].chain_b_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_b_max;
|
||||
if ((priv->cfg->valid_tx_ant & ANT_C) &&
|
||||
(enhanced_txpower[element].chain_c_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_c_max;
|
||||
if (((priv->cfg->valid_tx_ant == ANT_AB) |
|
||||
(priv->cfg->valid_tx_ant == ANT_BC) |
|
||||
(priv->cfg->valid_tx_ant == ANT_AC)) &&
|
||||
(enhanced_txpower[element].mimo2_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].mimo2_max;
|
||||
if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
|
||||
(enhanced_txpower[element].mimo3_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].mimo3_max;
|
||||
|
||||
/* max. tx power in EEPROM is in 1/2 dBm format
|
||||
* convert from 1/2 dBm to dBm
|
||||
*/
|
||||
return max_txpower_avg >> 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_update_common_txpower: update channel tx power
|
||||
* update tx power per band based on EEPROM enhanced tx power info.
|
||||
*/
|
||||
static s8 iwl_update_common_txpower(struct iwl_priv *priv,
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
|
||||
int section, int element)
|
||||
{
|
||||
struct iwl_channel_info *ch_info;
|
||||
int ch;
|
||||
bool is_ht40 = false;
|
||||
s8 max_txpower_avg; /* (dBm) */
|
||||
|
||||
/* it is common section, contain all type (Legacy, HT and HT40)
|
||||
* based on the element in the section to determine
|
||||
* is it HT 40 or not
|
||||
*/
|
||||
if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
|
||||
is_ht40 = true;
|
||||
max_txpower_avg =
|
||||
iwl_get_max_txpower_avg(priv, enhanced_txpower, element);
|
||||
ch_info = priv->channel_info;
|
||||
|
||||
for (ch = 0; ch < priv->channel_count; ch++) {
|
||||
/* find matching band and update tx power if needed */
|
||||
if ((ch_info->band == enhinfo[section].band) &&
|
||||
(ch_info->max_power_avg < max_txpower_avg) && (!is_ht40)) {
|
||||
/* Update regulatory-based run-time data */
|
||||
ch_info->max_power_avg = ch_info->curr_txpow =
|
||||
max_txpower_avg;
|
||||
ch_info->scan_power = max_txpower_avg;
|
||||
}
|
||||
if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
|
||||
ch_info->ht40_max_power_avg &&
|
||||
(ch_info->ht40_max_power_avg < max_txpower_avg)) {
|
||||
/* Update regulatory-based run-time data */
|
||||
ch_info->ht40_max_power_avg = max_txpower_avg;
|
||||
ch_info->ht40_curr_txpow = max_txpower_avg;
|
||||
ch_info->ht40_scan_power = max_txpower_avg;
|
||||
}
|
||||
ch_info++;
|
||||
}
|
||||
return max_txpower_avg;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_update_channel_txpower: update channel tx power
|
||||
* update channel tx power based on EEPROM enhanced tx power info.
|
||||
*/
|
||||
static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
|
||||
int section, int element)
|
||||
{
|
||||
struct iwl_channel_info *ch_info;
|
||||
int ch;
|
||||
u8 channel;
|
||||
s8 max_txpower_avg; /* (dBm) */
|
||||
|
||||
channel = enhinfo[section].iwl_eeprom_section_channel[element];
|
||||
max_txpower_avg =
|
||||
iwl_get_max_txpower_avg(priv, enhanced_txpower, element);
|
||||
|
||||
ch_info = priv->channel_info;
|
||||
for (ch = 0; ch < priv->channel_count; ch++) {
|
||||
/* find matching channel and update tx power if needed */
|
||||
if (ch_info->channel == channel) {
|
||||
if ((ch_info->max_power_avg < max_txpower_avg) &&
|
||||
(!enhinfo[section].is_ht40)) {
|
||||
/* Update regulatory-based run-time data */
|
||||
ch_info->max_power_avg = max_txpower_avg;
|
||||
ch_info->curr_txpow = max_txpower_avg;
|
||||
ch_info->scan_power = max_txpower_avg;
|
||||
}
|
||||
if ((enhinfo[section].is_ht40) &&
|
||||
(ch_info->ht40_max_power_avg) &&
|
||||
(ch_info->ht40_max_power_avg < max_txpower_avg)) {
|
||||
/* Update regulatory-based run-time data */
|
||||
ch_info->ht40_max_power_avg = max_txpower_avg;
|
||||
ch_info->ht40_curr_txpow = max_txpower_avg;
|
||||
ch_info->ht40_scan_power = max_txpower_avg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ch_info++;
|
||||
}
|
||||
return max_txpower_avg;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
|
||||
*/
|
||||
void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
|
||||
{
|
||||
int eeprom_section_count = 0;
|
||||
int section, element;
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
|
||||
u32 offset;
|
||||
s8 max_txpower_avg; /* (dBm) */
|
||||
|
||||
/* Loop through all the sections
|
||||
* adjust bands and channel's max tx power
|
||||
* Set the tx_power_user_lmt to the highest power
|
||||
* supported by any channels and chains
|
||||
*/
|
||||
for (section = 0; section < ARRAY_SIZE(enhinfo); section++) {
|
||||
eeprom_section_count = enhinfo[section].count;
|
||||
offset = enhinfo[section].offset;
|
||||
enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
|
||||
iwl_eeprom_query_addr(priv, offset);
|
||||
|
||||
for (element = 0; element < eeprom_section_count; element++) {
|
||||
if (enhinfo[section].is_common)
|
||||
max_txpower_avg =
|
||||
iwl_update_common_txpower(priv,
|
||||
enhanced_txpower, section, element);
|
||||
else
|
||||
max_txpower_avg =
|
||||
iwl_update_channel_txpower(priv,
|
||||
enhanced_txpower, section, element);
|
||||
|
||||
/* Update the tx_power_user_lmt to the highest power
|
||||
* supported by any channel */
|
||||
if (max_txpower_avg > priv->tx_power_user_lmt)
|
||||
priv->tx_power_user_lmt = max_txpower_avg;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwlcore_eeprom_enhanced_txpower);
|
||||
|
||||
#define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
|
||||
? # x " " : "")
|
||||
|
||||
|
@ -790,6 +1034,14 @@ int iwl_init_channel_map(struct iwl_priv *priv)
|
|||
}
|
||||
}
|
||||
|
||||
/* for newer device (6000 series and up)
|
||||
* EEPROM contain enhanced tx power information
|
||||
* driver need to process addition information
|
||||
* to determine the max channel tx power limits
|
||||
*/
|
||||
if (priv->cfg->ops->lib->eeprom_ops.update_enhanced_txpower)
|
||||
priv->cfg->ops->lib->eeprom_ops.update_enhanced_txpower(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_init_channel_map);
|
||||
|
|
|
@ -118,6 +118,30 @@ struct iwl_eeprom_channel {
|
|||
s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/**
|
||||
* iwl_eeprom_enhanced_txpwr structure
|
||||
* This structure presents the enhanced regulatory tx power limit layout
|
||||
* in eeprom image
|
||||
* Enhanced regulatory tx power portion of eeprom image can be broken down
|
||||
* into individual structures; each one is 8 bytes in size and contain the
|
||||
* following information
|
||||
* @chain_a_max_pwr: chain a max power in 1/2 dBm
|
||||
* @chain_b_max_pwr: chain b max power in 1/2 dBm
|
||||
* @chain_c_max_pwr: chain c max power in 1/2 dBm
|
||||
* @mimo2_max_pwr: mimo2 max power in 1/2 dBm
|
||||
* @mimo3_max_pwr: mimo3 max power in 1/2 dBm
|
||||
*
|
||||
*/
|
||||
struct iwl_eeprom_enhanced_txpwr {
|
||||
u16 reserved;
|
||||
s8 chain_a_max;
|
||||
s8 chain_b_max;
|
||||
s8 chain_c_max;
|
||||
s8 reserved1;
|
||||
s8 mimo2_max;
|
||||
s8 mimo3_max;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* 3945 Specific */
|
||||
#define EEPROM_3945_EEPROM_VERSION (0x2f)
|
||||
|
||||
|
@ -175,6 +199,59 @@ struct iwl_eeprom_channel {
|
|||
#define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\
|
||||
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */
|
||||
|
||||
/* 6000 and up regulatory tx power - indirect access */
|
||||
/* max. elements per section */
|
||||
#define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS (8)
|
||||
#define EEPROM_TXPOWER_COMMON_HT40_INDEX (2)
|
||||
|
||||
/**
|
||||
* Partition the enhanced tx power portion of eeprom image into
|
||||
* 10 sections based on band, modulation, frequency and channel
|
||||
*
|
||||
* Section 1: all CCK channels
|
||||
* Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40 ) channels
|
||||
* Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
|
||||
* Section 4: 2.4 GHz 20MHz channels: 1, 2, 10, 11. Both Legacy and HT
|
||||
* Section 5: 2.4 GHz 40MHz channels: 1, 2, 6, 7, 9, (_above_)
|
||||
* Section 6: 5.2 GHz 20MHz channels: 36, 64, 100, both Legacy and HT
|
||||
* Section 7: 5.2 GHz 40MHz channels: 36, 60, 100 (_above_)
|
||||
* Section 8: 2.4 GHz channel 13, Both Legacy and HT
|
||||
* Section 9: 2.4 GHz channel 140, Both Legacy and HT
|
||||
* Section 10: 2.4 GHz 40MHz channels: 132, 44 (_above_)
|
||||
*/
|
||||
/* 2.4 GHz band: CCK */
|
||||
#define EEPROM_LB_CCK_20_COMMON ((0xAA)\
|
||||
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 8 bytes */
|
||||
/* 2.4 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */
|
||||
#define EEPROM_LB_OFDM_COMMON ((0xB2)\
|
||||
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */
|
||||
/* 5.2 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */
|
||||
#define EEPROM_HB_OFDM_COMMON ((0xCA)\
|
||||
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */
|
||||
/* 2.4GHz band channels:
|
||||
* 1Legacy, 1HT, 2Legacy, 2HT, 10Legacy, 10HT, 11Legacy, 11HT */
|
||||
#define EEPROM_LB_OFDM_20_BAND ((0xE2)\
|
||||
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 64 bytes */
|
||||
/* 2.4 GHz band HT40 channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) */
|
||||
#define EEPROM_LB_OFDM_HT40_BAND ((0x122)\
|
||||
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 40 bytes */
|
||||
/* 5.2GHz band channels: 36Legacy, 36HT, 64Legacy, 64HT, 100Legacy, 100HT */
|
||||
#define EEPROM_HB_OFDM_20_BAND ((0x14A)\
|
||||
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 48 bytes */
|
||||
/* 5.2 GHz band HT40 channels: (36,+1) (60,+1) (100,+1) */
|
||||
#define EEPROM_HB_OFDM_HT40_BAND ((0x17A)\
|
||||
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */
|
||||
/* 2.4 GHz band, channnel 13: Legacy, HT */
|
||||
#define EEPROM_LB_OFDM_20_CHANNEL_13 ((0x192)\
|
||||
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */
|
||||
/* 5.2 GHz band, channnel 140: Legacy, HT */
|
||||
#define EEPROM_HB_OFDM_20_CHANNEL_140 ((0x1A2)\
|
||||
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */
|
||||
/* 5.2 GHz band, HT40 channnels (132,+1) (44,+1) */
|
||||
#define EEPROM_HB_OFDM_HT40_BAND_1 ((0x1B2)\
|
||||
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */
|
||||
|
||||
|
||||
/* 5050 Specific */
|
||||
#define EEPROM_5050_TX_POWER_VERSION (4)
|
||||
#define EEPROM_5050_EEPROM_VERSION (0x21E)
|
||||
|
@ -389,6 +466,7 @@ struct iwl_eeprom_ops {
|
|||
void (*release_semaphore) (struct iwl_priv *priv);
|
||||
u16 (*calib_version) (struct iwl_priv *priv);
|
||||
const u8* (*query_addr) (const struct iwl_priv *priv, size_t offset);
|
||||
void (*update_enhanced_txpower) (struct iwl_priv *priv);
|
||||
};
|
||||
|
||||
|
||||
|
@ -403,7 +481,7 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
|
|||
int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
|
||||
void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
|
||||
const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
|
||||
|
||||
void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv);
|
||||
int iwl_init_channel_map(struct iwl_priv *priv);
|
||||
void iwl_free_channel_map(struct iwl_priv *priv);
|
||||
const struct iwl_channel_info *iwl_get_channel_info(
|
||||
|
|
|
@ -915,6 +915,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
|
|||
u32 len;
|
||||
u32 ampdu_status;
|
||||
u16 fc;
|
||||
u32 rate_n_flags;
|
||||
|
||||
/**
|
||||
* REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
|
||||
|
@ -1032,6 +1033,15 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
|
|||
if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
|
||||
rx_status.flag |= RX_FLAG_SHORTPRE;
|
||||
|
||||
/* Set up the HT phy flags */
|
||||
rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
|
||||
if (rate_n_flags & RATE_MCS_HT_MSK)
|
||||
rx_status.flag |= RX_FLAG_HT;
|
||||
if (rate_n_flags & RATE_MCS_HT40_MSK)
|
||||
rx_status.flag |= RX_FLAG_40MHZ;
|
||||
if (rate_n_flags & RATE_MCS_SGI_MSK)
|
||||
rx_status.flag |= RX_FLAG_SHORT_GI;
|
||||
|
||||
if (iwl_is_network_packet(priv, header)) {
|
||||
priv->last_rx_rssi = rx_status.signal;
|
||||
priv->last_beacon_time = priv->ucode_beacon_time;
|
||||
|
|
|
@ -796,7 +796,8 @@ void iwl_bg_abort_scan(struct work_struct *work)
|
|||
{
|
||||
struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
|
||||
|
||||
if (!iwl_is_ready(priv))
|
||||
if (!test_bit(STATUS_READY, &priv->status) ||
|
||||
!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
|
||||
return;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
|
|
@ -520,7 +520,7 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
|
|||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_WEPKEY,
|
||||
.data = wep_cmd,
|
||||
.flags = CMD_ASYNC,
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
|
||||
memset(wep_cmd, 0, cmd_size +
|
||||
|
|
|
@ -718,10 +718,9 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
|
||||
#endif
|
||||
|
||||
/* drop all data frame if we are not associated */
|
||||
/* drop all non-injected data frame if we are not associated */
|
||||
if (ieee80211_is_data(fc) &&
|
||||
(!iwl_is_monitor_mode(priv) ||
|
||||
!(info->flags & IEEE80211_TX_CTL_INJECTED)) && /* packet injection */
|
||||
!(info->flags & IEEE80211_TX_CTL_INJECTED) &&
|
||||
(!iwl_is_associated(priv) ||
|
||||
((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) ||
|
||||
!priv->assoc_station_added)) {
|
||||
|
@ -732,7 +731,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
hdr_len = ieee80211_hdrlen(fc);
|
||||
|
||||
/* Find (or create) index into station table for destination station */
|
||||
sta_id = iwl_get_sta_id(priv, hdr);
|
||||
if (info->flags & IEEE80211_TX_CTL_INJECTED)
|
||||
sta_id = priv->hw_params.bcast_sta_id;
|
||||
else
|
||||
sta_id = iwl_get_sta_id(priv, hdr);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
|
||||
hdr->addr1);
|
||||
|
|
|
@ -518,9 +518,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
|
||||
#endif
|
||||
|
||||
/* drop all data frame if we are not associated */
|
||||
/* drop all non-injected data frame if we are not associated */
|
||||
if (ieee80211_is_data(fc) &&
|
||||
(!iwl_is_monitor_mode(priv)) && /* packet injection */
|
||||
!(info->flags & IEEE80211_TX_CTL_INJECTED) &&
|
||||
(!iwl_is_associated(priv) ||
|
||||
((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n");
|
||||
|
@ -532,7 +532,10 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
hdr_len = ieee80211_hdrlen(fc);
|
||||
|
||||
/* Find (or create) index into station table for destination station */
|
||||
sta_id = iwl_get_sta_id(priv, hdr);
|
||||
if (info->flags & IEEE80211_TX_CTL_INJECTED)
|
||||
sta_id = priv->hw_params.bcast_sta_id;
|
||||
else
|
||||
sta_id = iwl_get_sta_id(priv, hdr);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
|
||||
hdr->addr1);
|
||||
|
|
|
@ -34,7 +34,8 @@ static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
|
|||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param rates the buffer which keeps input and output
|
||||
* @param rates_size the size of rate1 buffer; new size of buffer on return
|
||||
* @param rates_size the size of rates buffer; new size of buffer on return,
|
||||
* which will be less than or equal to original rates_size
|
||||
*
|
||||
* @return 0 on success, or -1 on error
|
||||
*/
|
||||
|
@ -42,48 +43,42 @@ static int get_common_rates(struct lbs_private *priv,
|
|||
u8 *rates,
|
||||
u16 *rates_size)
|
||||
{
|
||||
u8 *card_rates = lbs_bg_rates;
|
||||
size_t num_card_rates = sizeof(lbs_bg_rates);
|
||||
int ret = 0, i, j;
|
||||
u8 *tmp;
|
||||
size_t tmp_size = 0;
|
||||
int i, j;
|
||||
u8 intersection[MAX_RATES];
|
||||
u16 intersection_size;
|
||||
u16 num_rates = 0;
|
||||
|
||||
tmp = kzalloc((ARRAY_SIZE(lbs_bg_rates) - 1) * (*rates_size - 1),
|
||||
GFP_KERNEL);
|
||||
if (!tmp)
|
||||
return -1;
|
||||
intersection_size = min_t(u16, *rates_size, ARRAY_SIZE(intersection));
|
||||
|
||||
/* For each rate in card_rates that exists in rate1, copy to tmp */
|
||||
for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
|
||||
for (j = 0; rates[j] && (j < *rates_size); j++) {
|
||||
if (rates[j] == card_rates[i])
|
||||
tmp[tmp_size++] = card_rates[i];
|
||||
/* Allow each rate from 'rates' that is supported by the hardware */
|
||||
for (i = 0; i < ARRAY_SIZE(lbs_bg_rates) && lbs_bg_rates[i]; i++) {
|
||||
for (j = 0; j < intersection_size && rates[j]; j++) {
|
||||
if (rates[j] == lbs_bg_rates[i])
|
||||
intersection[num_rates++] = rates[j];
|
||||
}
|
||||
}
|
||||
|
||||
lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
|
||||
lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
|
||||
lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
|
||||
lbs_deb_hex(LBS_DEB_JOIN, "card rates ", lbs_bg_rates,
|
||||
ARRAY_SIZE(lbs_bg_rates));
|
||||
lbs_deb_hex(LBS_DEB_JOIN, "common rates", intersection, num_rates);
|
||||
lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
|
||||
|
||||
if (!priv->enablehwauto) {
|
||||
for (i = 0; i < tmp_size; i++) {
|
||||
if (tmp[i] == priv->cur_rate)
|
||||
for (i = 0; i < num_rates; i++) {
|
||||
if (intersection[i] == priv->cur_rate)
|
||||
goto done;
|
||||
}
|
||||
lbs_pr_alert("Previously set fixed data rate %#x isn't "
|
||||
"compatible with the network.\n", priv->cur_rate);
|
||||
ret = -1;
|
||||
goto done;
|
||||
return -1;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
memset(rates, 0, *rates_size);
|
||||
*rates_size = min_t(int, tmp_size, *rates_size);
|
||||
memcpy(rates, tmp, *rates_size);
|
||||
kfree(tmp);
|
||||
return ret;
|
||||
*rates_size = num_rates;
|
||||
memcpy(rates, intersection, num_rates);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -325,8 +320,8 @@ static int lbs_associate(struct lbs_private *priv,
|
|||
|
||||
rates = (struct mrvl_ie_rates_param_set *) pos;
|
||||
rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
|
||||
memcpy(&rates->rates, &bss->rates, MAX_RATES);
|
||||
tmplen = MAX_RATES;
|
||||
tmplen = min_t(u16, ARRAY_SIZE(bss->rates), MAX_RATES);
|
||||
memcpy(&rates->rates, &bss->rates, tmplen);
|
||||
if (get_common_rates(priv, rates->rates, &tmplen)) {
|
||||
ret = -1;
|
||||
goto done;
|
||||
|
@ -600,7 +595,7 @@ static int lbs_adhoc_join(struct lbs_private *priv,
|
|||
|
||||
/* Copy Data rates from the rates recorded in scan response */
|
||||
memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates));
|
||||
ratesize = min_t(u16, sizeof(cmd.bss.rates), MAX_RATES);
|
||||
ratesize = min_t(u16, ARRAY_SIZE(cmd.bss.rates), ARRAY_SIZE (bss->rates));
|
||||
memcpy(cmd.bss.rates, bss->rates, ratesize);
|
||||
if (get_common_rates(priv, cmd.bss.rates, &ratesize)) {
|
||||
lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n");
|
||||
|
|
|
@ -45,6 +45,8 @@ static ssize_t lbs_dev_info(struct file *file, char __user *userbuf,
|
|||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
ssize_t res;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pos += snprintf(buf+pos, len-pos, "state = %s\n",
|
||||
szStates[priv->connect_status]);
|
||||
|
@ -68,6 +70,8 @@ static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
|
|||
char *buf = (char *)addr;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
struct bss_descriptor * iter_bss;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pos += snprintf(buf+pos, len-pos,
|
||||
"# | ch | rssi | bssid | cap | Qual | SSID \n");
|
||||
|
@ -110,6 +114,8 @@ static ssize_t lbs_sleepparams_write(struct file *file,
|
|||
int p1, p2, p3, p4, p5, p6;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, user_buf, buf_size)) {
|
||||
|
@ -148,6 +154,8 @@ static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
|
|||
struct sleep_params sp;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp);
|
||||
if (ret)
|
||||
|
@ -433,6 +441,8 @@ static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
|
|||
int ret;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
offval.offset = priv->mac_offset;
|
||||
offval.value = 0;
|
||||
|
@ -457,6 +467,8 @@ static ssize_t lbs_rdmac_write(struct file *file,
|
|||
ssize_t res, buf_size;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
|
@ -481,6 +493,8 @@ static ssize_t lbs_wrmac_write(struct file *file,
|
|||
struct lbs_offset_value offval;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
|
@ -515,6 +529,8 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
|
|||
int ret;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
offval.offset = priv->bbp_offset;
|
||||
offval.value = 0;
|
||||
|
@ -540,6 +556,8 @@ static ssize_t lbs_rdbbp_write(struct file *file,
|
|||
ssize_t res, buf_size;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
|
@ -564,6 +582,8 @@ static ssize_t lbs_wrbbp_write(struct file *file,
|
|||
struct lbs_offset_value offval;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
|
@ -598,6 +618,8 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
|
|||
int ret;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
offval.offset = priv->rf_offset;
|
||||
offval.value = 0;
|
||||
|
@ -623,6 +645,8 @@ static ssize_t lbs_rdrf_write(struct file *file,
|
|||
ssize_t res, buf_size;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
|
@ -647,6 +671,8 @@ static ssize_t lbs_wrrf_write(struct file *file,
|
|||
struct lbs_offset_value offval;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
|
@ -853,6 +879,8 @@ static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf,
|
|||
struct debug_data *d;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
p = buf;
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ struct if_cs_card {
|
|||
struct pcmcia_device *p_dev;
|
||||
struct lbs_private *priv;
|
||||
void __iomem *iobase;
|
||||
bool align_regs;
|
||||
};
|
||||
|
||||
|
||||
|
@ -274,16 +275,25 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
|
|||
#define IF_CS_PRODUCT_ID 0x0000001C
|
||||
#define IF_CS_CF8385_B1_REV 0x12
|
||||
#define IF_CS_CF8381_B3_REV 0x04
|
||||
#define IF_CS_CF8305_B1_REV 0x03
|
||||
|
||||
/*
|
||||
* Used to detect other cards than CF8385 since their revisions of silicon
|
||||
* doesn't match those from CF8385, eg. CF8381 B3 works with this driver.
|
||||
*/
|
||||
#define CF8305_MANFID 0x02db
|
||||
#define CF8305_CARDID 0x8103
|
||||
#define CF8381_MANFID 0x02db
|
||||
#define CF8381_CARDID 0x6064
|
||||
#define CF8385_MANFID 0x02df
|
||||
#define CF8385_CARDID 0x8103
|
||||
|
||||
static inline int if_cs_hw_is_cf8305(struct pcmcia_device *p_dev)
|
||||
{
|
||||
return (p_dev->manf_id == CF8305_MANFID &&
|
||||
p_dev->card_id == CF8305_CARDID);
|
||||
}
|
||||
|
||||
static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev)
|
||||
{
|
||||
return (p_dev->manf_id == CF8381_MANFID &&
|
||||
|
@ -556,7 +566,15 @@ static int if_cs_prog_helper(struct if_cs_card *card)
|
|||
|
||||
lbs_deb_enter(LBS_DEB_CS);
|
||||
|
||||
scratch = if_cs_read8(card, IF_CS_SCRATCH);
|
||||
/*
|
||||
* This is the only place where an unaligned register access happens on
|
||||
* the CF8305 card, therefore for the sake of speed of the driver, we do
|
||||
* the alignment correction here.
|
||||
*/
|
||||
if (card->align_regs)
|
||||
scratch = if_cs_read16(card, IF_CS_SCRATCH) >> 8;
|
||||
else
|
||||
scratch = if_cs_read8(card, IF_CS_SCRATCH);
|
||||
|
||||
/* "If the value is 0x5a, the firmware is already
|
||||
* downloaded successfully"
|
||||
|
@ -880,8 +898,24 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
|
|||
p_dev->irq.AssignedIRQ, p_dev->io.BasePort1,
|
||||
p_dev->io.BasePort1 + p_dev->io.NumPorts1 - 1);
|
||||
|
||||
/*
|
||||
* Most of the libertas cards can do unaligned register access, but some
|
||||
* weird ones can not. That's especially true for the CF8305 card.
|
||||
*/
|
||||
card->align_regs = 0;
|
||||
|
||||
/* Check if we have a current silicon */
|
||||
prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID);
|
||||
if (if_cs_hw_is_cf8305(p_dev)) {
|
||||
card->align_regs = 1;
|
||||
if (prod_id < IF_CS_CF8305_B1_REV) {
|
||||
lbs_pr_err("old chips like 8305 rev B3 "
|
||||
"aren't supported\n");
|
||||
ret = -ENODEV;
|
||||
goto out2;
|
||||
}
|
||||
}
|
||||
|
||||
if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) {
|
||||
lbs_pr_err("old chips like 8381 rev B3 aren't supported\n");
|
||||
ret = -ENODEV;
|
||||
|
@ -896,7 +930,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
|
|||
|
||||
/* Load the firmware early, before calling into libertas.ko */
|
||||
ret = if_cs_prog_helper(card);
|
||||
if (ret == 0)
|
||||
if (ret == 0 && !if_cs_hw_is_cf8305(p_dev))
|
||||
ret = if_cs_prog_real(card);
|
||||
if (ret)
|
||||
goto out2;
|
||||
|
@ -976,6 +1010,7 @@ static void if_cs_detach(struct pcmcia_device *p_dev)
|
|||
/********************************************************************/
|
||||
|
||||
static struct pcmcia_device_id if_cs_ids[] = {
|
||||
PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID),
|
||||
PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID),
|
||||
PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID),
|
||||
PCMCIA_DEVICE_NULL,
|
||||
|
|
|
@ -164,7 +164,7 @@ struct mwl8k_priv {
|
|||
|
||||
u16 num_mcaddrs;
|
||||
u8 hw_rev;
|
||||
__le32 fw_rev;
|
||||
u32 fw_rev;
|
||||
|
||||
/*
|
||||
* Running count of TX packets in flight, to avoid
|
||||
|
@ -1439,8 +1439,11 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
|
|||
return -ENOMEM;
|
||||
|
||||
rc = mwl8k_fw_lock(hw);
|
||||
if (rc)
|
||||
if (rc) {
|
||||
pci_unmap_single(priv->pdev, dma_addr, dma_size,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
priv->hostcmd_wait = &cmd_wait;
|
||||
iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR);
|
||||
|
@ -1471,7 +1474,7 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
|
|||
printk(KERN_ERR "%s: Command %s error 0x%x\n",
|
||||
priv->name,
|
||||
mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
|
||||
cmd->result);
|
||||
le16_to_cpu(cmd->result));
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
@ -2617,7 +2620,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
|
|||
priv->capture_beacon = false;
|
||||
|
||||
rc = mwl8k_fw_lock(hw);
|
||||
if (!rc)
|
||||
if (rc)
|
||||
return;
|
||||
|
||||
if (info->assoc) {
|
||||
|
@ -2822,11 +2825,16 @@ static void mwl8k_finalize_join_worker(struct work_struct *work)
|
|||
static int __devinit mwl8k_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
static int printed_version = 0;
|
||||
struct ieee80211_hw *hw;
|
||||
struct mwl8k_priv *priv;
|
||||
int rc;
|
||||
int i;
|
||||
u8 *fw;
|
||||
|
||||
if (!printed_version) {
|
||||
printk(KERN_INFO "%s version %s\n", MWL8K_DESC, MWL8K_VERSION);
|
||||
printed_version = 1;
|
||||
}
|
||||
|
||||
rc = pci_enable_device(pdev);
|
||||
if (rc) {
|
||||
|
@ -3001,13 +3009,11 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
|
|||
goto err_stop_firmware;
|
||||
}
|
||||
|
||||
fw = (u8 *)&priv->fw_rev;
|
||||
printk(KERN_INFO "%s: 88W%u %s\n", priv->name, priv->part_num,
|
||||
MWL8K_DESC);
|
||||
printk(KERN_INFO "%s: Driver Ver:%s Firmware Ver:%u.%u.%u.%u\n",
|
||||
priv->name, MWL8K_VERSION, fw[3], fw[2], fw[1], fw[0]);
|
||||
printk(KERN_INFO "%s: MAC Address: %pM\n", priv->name,
|
||||
hw->wiphy->perm_addr);
|
||||
printk(KERN_INFO "%s: 88w%u v%d, %pM, firmware version %u.%u.%u.%u\n",
|
||||
wiphy_name(hw->wiphy), priv->part_num, priv->hw_rev,
|
||||
hw->wiphy->perm_addr,
|
||||
(priv->fw_rev >> 24) & 0xff, (priv->fw_rev >> 16) & 0xff,
|
||||
(priv->fw_rev >> 8) & 0xff, priv->fw_rev & 0xff);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -623,6 +623,9 @@ static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb,
|
|||
if (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)
|
||||
*flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL;
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
|
||||
*flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL;
|
||||
|
||||
*queue = skb_get_queue_mapping(skb) + P54_QUEUE_DATA;
|
||||
|
||||
switch (priv->mode) {
|
||||
|
|
|
@ -50,7 +50,7 @@ islpci_eth_cleanup_transmit(islpci_private *priv,
|
|||
|
||||
/* check for holes in the arrays caused by multi fragment frames
|
||||
* searching for the last fragment of a frame */
|
||||
if (priv->pci_map_tx_address[index] != (dma_addr_t) NULL) {
|
||||
if (priv->pci_map_tx_address[index]) {
|
||||
/* entry is the last fragment of a frame
|
||||
* free the skb structure and unmap pci memory */
|
||||
skb = priv->data_low_tx[index];
|
||||
|
@ -450,7 +450,7 @@ islpci_eth_receive(islpci_private *priv)
|
|||
pci_map_single(priv->pdev, (void *) skb->data,
|
||||
MAX_FRAGMENT_SIZE_RX + 2,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
if (unlikely(priv->pci_map_rx_address[index] == (dma_addr_t) NULL)) {
|
||||
if (unlikely(!priv->pci_map_rx_address[index])) {
|
||||
/* error mapping the buffer to device accessable memory address */
|
||||
DEBUG(SHOW_ERROR_MESSAGES,
|
||||
"Error mapping DMA address\n");
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -582,7 +582,6 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct rt2x00_intf *intf = vif_to_intf(vif);
|
||||
unsigned int delayed = 0;
|
||||
int update_bssid = 0;
|
||||
|
||||
/*
|
||||
|
@ -645,13 +644,6 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
|
|||
*/
|
||||
if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT))
|
||||
rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
|
||||
|
||||
spin_lock(&intf->lock);
|
||||
if (delayed) {
|
||||
intf->delayed_flags |= delayed;
|
||||
schedule_work(&rt2x00dev->intf_work);
|
||||
}
|
||||
spin_unlock(&intf->lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o
|
||||
rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o rtl8187_leds.o
|
||||
rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o rtl8187_leds.o rtl8187_rfkill.o
|
||||
|
||||
obj-$(CONFIG_RTL8180) += rtl8180.o
|
||||
obj-$(CONFIG_RTL8187) += rtl8187.o
|
||||
|
|
|
@ -133,6 +133,7 @@ struct rtl8187_priv {
|
|||
__le16 bits16;
|
||||
__le32 bits32;
|
||||
} *io_dmabuf;
|
||||
bool rfkill_off;
|
||||
};
|
||||
|
||||
void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#ifdef CONFIG_RTL8187_LEDS
|
||||
#include "rtl8187_leds.h"
|
||||
#endif
|
||||
#include "rtl8187_rfkill.h"
|
||||
|
||||
MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
|
||||
MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
|
||||
|
@ -648,10 +649,10 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev)
|
|||
|
||||
/* setup card */
|
||||
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
|
||||
rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
|
||||
rtl818x_iowrite8(priv, &priv->map->GPIO0, 0);
|
||||
|
||||
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
|
||||
rtl818x_iowrite8(priv, &priv->map->GPIO, 1);
|
||||
rtl818x_iowrite8(priv, &priv->map->GPIO0, 1);
|
||||
rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
|
||||
|
||||
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
|
||||
|
@ -674,11 +675,11 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev)
|
|||
|
||||
/* host_usb_init */
|
||||
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
|
||||
rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
|
||||
rtl818x_iowrite8(priv, &priv->map->GPIO0, 0);
|
||||
reg = rtl818x_ioread8(priv, (u8 *)0xFE53);
|
||||
rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7));
|
||||
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
|
||||
rtl818x_iowrite8(priv, &priv->map->GPIO, 0x20);
|
||||
rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x20);
|
||||
rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
|
||||
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80);
|
||||
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80);
|
||||
|
@ -907,12 +908,12 @@ static int rtl8187_start(struct ieee80211_hw *dev)
|
|||
u32 reg;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
|
||||
ret = (!priv->is_rtl8187b) ? rtl8187_init_hw(dev) :
|
||||
rtl8187b_init_hw(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
goto rtl8187_start_exit;
|
||||
|
||||
init_usb_anchor(&priv->anchored);
|
||||
priv->dev = dev;
|
||||
|
@ -939,8 +940,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
|
|||
(7 << 21 /* MAX TX DMA */));
|
||||
rtl8187_init_urbs(dev);
|
||||
rtl8187b_init_status_urb(dev);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
return 0;
|
||||
goto rtl8187_start_exit;
|
||||
}
|
||||
|
||||
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
|
||||
|
@ -984,9 +984,10 @@ static int rtl8187_start(struct ieee80211_hw *dev)
|
|||
reg |= RTL818X_CMD_RX_ENABLE;
|
||||
rtl818x_iowrite8(priv, &priv->map->CMD, reg);
|
||||
INIT_DELAYED_WORK(&priv->work, rtl8187_work);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
|
||||
return 0;
|
||||
rtl8187_start_exit:
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rtl8187_stop(struct ieee80211_hw *dev)
|
||||
|
@ -1014,9 +1015,10 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
|
|||
dev_kfree_skb_any(skb);
|
||||
|
||||
usb_kill_anchored_urbs(&priv->anchored);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
|
||||
if (!priv->is_rtl8187b)
|
||||
cancel_delayed_work_sync(&priv->work);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
}
|
||||
|
||||
static int rtl8187_add_interface(struct ieee80211_hw *dev,
|
||||
|
@ -1276,7 +1278,8 @@ static const struct ieee80211_ops rtl8187_ops = {
|
|||
.bss_info_changed = rtl8187_bss_info_changed,
|
||||
.prepare_multicast = rtl8187_prepare_multicast,
|
||||
.configure_filter = rtl8187_configure_filter,
|
||||
.conf_tx = rtl8187_conf_tx
|
||||
.conf_tx = rtl8187_conf_tx,
|
||||
.rfkill_poll = rtl8187_rfkill_poll
|
||||
};
|
||||
|
||||
static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
|
||||
|
@ -1516,6 +1519,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
|
|||
reg &= 0xFF;
|
||||
rtl8187_leds_init(dev, reg);
|
||||
#endif
|
||||
rtl8187_rfkill_init(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -1539,6 +1543,7 @@ static void __devexit rtl8187_disconnect(struct usb_interface *intf)
|
|||
#ifdef CONFIG_RTL8187_LEDS
|
||||
rtl8187_leds_exit(dev);
|
||||
#endif
|
||||
rtl8187_rfkill_exit(dev);
|
||||
ieee80211_unregister_hw(dev);
|
||||
|
||||
priv = dev->priv;
|
||||
|
|
|
@ -42,7 +42,7 @@ static void led_turn_on(struct work_struct *work)
|
|||
mutex_lock(&priv->conf_mutex);
|
||||
switch (led->ledpin) {
|
||||
case LED_PIN_GPIO0:
|
||||
rtl818x_iowrite8(priv, &priv->map->GPIO, 0x01);
|
||||
rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01);
|
||||
rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x00);
|
||||
break;
|
||||
case LED_PIN_LED0:
|
||||
|
@ -80,7 +80,7 @@ static void led_turn_off(struct work_struct *work)
|
|||
mutex_lock(&priv->conf_mutex);
|
||||
switch (led->ledpin) {
|
||||
case LED_PIN_GPIO0:
|
||||
rtl818x_iowrite8(priv, &priv->map->GPIO, 0x01);
|
||||
rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01);
|
||||
rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x01);
|
||||
break;
|
||||
case LED_PIN_LED0:
|
||||
|
|
63
drivers/net/wireless/rtl818x/rtl8187_rfkill.c
Normal file
63
drivers/net/wireless/rtl818x/rtl8187_rfkill.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Linux RFKILL support for RTL8187
|
||||
*
|
||||
* Copyright (c) 2009 Herton Ronaldo Krzesinski <herton@mandriva.com.br>
|
||||
*
|
||||
* Based on the RFKILL handling in the r8187 driver, which is:
|
||||
* Copyright (c) Realtek Semiconductor Corp. All rights reserved.
|
||||
*
|
||||
* Thanks to Realtek for their support!
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/usb.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "rtl8187.h"
|
||||
|
||||
static bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv)
|
||||
{
|
||||
u8 gpio;
|
||||
|
||||
gpio = rtl818x_ioread8(priv, &priv->map->GPIO0);
|
||||
rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~0x02);
|
||||
gpio = rtl818x_ioread8(priv, &priv->map->GPIO1);
|
||||
|
||||
return gpio & 0x02;
|
||||
}
|
||||
|
||||
void rtl8187_rfkill_init(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl8187_priv *priv = hw->priv;
|
||||
|
||||
priv->rfkill_off = rtl8187_is_radio_enabled(priv);
|
||||
printk(KERN_INFO "rtl8187: wireless switch is %s\n",
|
||||
priv->rfkill_off ? "on" : "off");
|
||||
wiphy_rfkill_set_hw_state(hw->wiphy, !priv->rfkill_off);
|
||||
wiphy_rfkill_start_polling(hw->wiphy);
|
||||
}
|
||||
|
||||
void rtl8187_rfkill_poll(struct ieee80211_hw *hw)
|
||||
{
|
||||
bool enabled;
|
||||
struct rtl8187_priv *priv = hw->priv;
|
||||
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
enabled = rtl8187_is_radio_enabled(priv);
|
||||
if (unlikely(enabled != priv->rfkill_off)) {
|
||||
priv->rfkill_off = enabled;
|
||||
printk(KERN_INFO "rtl8187: wireless radio switch turned %s\n",
|
||||
enabled ? "on" : "off");
|
||||
wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
|
||||
}
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
}
|
||||
|
||||
void rtl8187_rfkill_exit(struct ieee80211_hw *hw)
|
||||
{
|
||||
wiphy_rfkill_stop_polling(hw->wiphy);
|
||||
}
|
8
drivers/net/wireless/rtl818x/rtl8187_rfkill.h
Normal file
8
drivers/net/wireless/rtl818x/rtl8187_rfkill.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef RTL8187_RFKILL_H
|
||||
#define RTL8187_RFKILL_H
|
||||
|
||||
void rtl8187_rfkill_init(struct ieee80211_hw *hw);
|
||||
void rtl8187_rfkill_poll(struct ieee80211_hw *hw);
|
||||
void rtl8187_rfkill_exit(struct ieee80211_hw *hw);
|
||||
|
||||
#endif /* RTL8187_RFKILL_H */
|
|
@ -138,8 +138,9 @@ struct rtl818x_csr {
|
|||
__le32 RF_PARA;
|
||||
__le32 RF_TIMING;
|
||||
u8 GP_ENABLE;
|
||||
u8 GPIO;
|
||||
u8 reserved_12[2];
|
||||
u8 GPIO0;
|
||||
u8 GPIO1;
|
||||
u8 reserved_12;
|
||||
__le32 HSSI_PARA;
|
||||
u8 reserved_13[4];
|
||||
u8 TX_AGC_CTL;
|
||||
|
|
|
@ -28,6 +28,21 @@ static void ssb_chipco_pll_write(struct ssb_chipcommon *cc,
|
|||
chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value);
|
||||
}
|
||||
|
||||
static void ssb_chipco_regctl_maskset(struct ssb_chipcommon *cc,
|
||||
u32 offset, u32 mask, u32 set)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR);
|
||||
chipco_write32(cc, SSB_CHIPCO_REGCTL_ADDR, offset);
|
||||
chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR);
|
||||
value = chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA);
|
||||
value &= mask;
|
||||
value |= set;
|
||||
chipco_write32(cc, SSB_CHIPCO_REGCTL_DATA, value);
|
||||
chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA);
|
||||
}
|
||||
|
||||
struct pmu0_plltab_entry {
|
||||
u16 freq; /* Crystal frequency in kHz.*/
|
||||
u8 xf; /* Crystal frequency value for PMU control */
|
||||
|
@ -506,3 +521,82 @@ void ssb_pmu_init(struct ssb_chipcommon *cc)
|
|||
ssb_pmu_pll_init(cc);
|
||||
ssb_pmu_resources_init(cc);
|
||||
}
|
||||
|
||||
void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
|
||||
enum ssb_pmu_ldo_volt_id id, u32 voltage)
|
||||
{
|
||||
struct ssb_bus *bus = cc->dev->bus;
|
||||
u32 addr, shift, mask;
|
||||
|
||||
switch (bus->chip_id) {
|
||||
case 0x4328:
|
||||
case 0x5354:
|
||||
switch (id) {
|
||||
case LDO_VOLT1:
|
||||
addr = 2;
|
||||
shift = 25;
|
||||
mask = 0xF;
|
||||
break;
|
||||
case LDO_VOLT2:
|
||||
addr = 3;
|
||||
shift = 1;
|
||||
mask = 0xF;
|
||||
break;
|
||||
case LDO_VOLT3:
|
||||
addr = 3;
|
||||
shift = 9;
|
||||
mask = 0xF;
|
||||
break;
|
||||
case LDO_PAREF:
|
||||
addr = 3;
|
||||
shift = 17;
|
||||
mask = 0x3F;
|
||||
break;
|
||||
default:
|
||||
SSB_WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x4312:
|
||||
if (SSB_WARN_ON(id != LDO_PAREF))
|
||||
return;
|
||||
addr = 0;
|
||||
shift = 21;
|
||||
mask = 0x3F;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
ssb_chipco_regctl_maskset(cc, addr, ~(mask << shift),
|
||||
(voltage & mask) << shift);
|
||||
}
|
||||
|
||||
void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on)
|
||||
{
|
||||
struct ssb_bus *bus = cc->dev->bus;
|
||||
int ldo;
|
||||
|
||||
switch (bus->chip_id) {
|
||||
case 0x4312:
|
||||
ldo = SSB_PMURES_4312_PA_REF_LDO;
|
||||
break;
|
||||
case 0x4328:
|
||||
ldo = SSB_PMURES_4328_PA_REF_LDO;
|
||||
break;
|
||||
case 0x5354:
|
||||
ldo = SSB_PMURES_5354_PA_REF_LDO;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (on)
|
||||
chipco_set32(cc, SSB_CHIPCO_PMU_MINRES_MSK, 1 << ldo);
|
||||
else
|
||||
chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, ~(1 << ldo));
|
||||
chipco_read32(cc, SSB_CHIPCO_PMU_MINRES_MSK); //SPEC FIXME found via mmiotrace - dummy read?
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage);
|
||||
EXPORT_SYMBOL(ssb_pmu_set_ldo_paref);
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
#define IEEE80211_MAX_SSID_LEN 32
|
||||
|
||||
#define IEEE80211_MAX_MESH_ID_LEN 32
|
||||
#define IEEE80211_MESH_CONFIG_LEN 19
|
||||
#define IEEE80211_MESH_CONFIG_LEN 24
|
||||
|
||||
#define IEEE80211_QOS_CTL_LEN 2
|
||||
#define IEEE80211_QOS_CTL_TID_MASK 0x000F
|
||||
|
|
|
@ -629,5 +629,15 @@ extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
|
|||
/* PMU support */
|
||||
extern void ssb_pmu_init(struct ssb_chipcommon *cc);
|
||||
|
||||
enum ssb_pmu_ldo_volt_id {
|
||||
LDO_PAREF = 0,
|
||||
LDO_VOLT1,
|
||||
LDO_VOLT2,
|
||||
LDO_VOLT3,
|
||||
};
|
||||
|
||||
void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
|
||||
enum ssb_pmu_ldo_volt_id id, u32 voltage);
|
||||
void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on);
|
||||
|
||||
#endif /* LINUX_SSB_CHIPCO_H_ */
|
||||
|
|
|
@ -416,13 +416,13 @@ struct iw_spy_data
|
|||
* data (i.e. valid as long as struct net_device exist, same locking rules).
|
||||
*/
|
||||
/* Forward declaration */
|
||||
struct ieee80211_device;
|
||||
struct libipw_device;
|
||||
/* The struct */
|
||||
struct iw_public_data {
|
||||
/* Driver enhanced spy support */
|
||||
struct iw_spy_data * spy_data;
|
||||
/* Structure managed by the in-kernel IEEE 802.11 layer */
|
||||
struct ieee80211_device * ieee80211;
|
||||
/* Legacy structure managed by the ipw2x00-specific IEEE 802.11 layer */
|
||||
struct libipw_device * libipw;
|
||||
};
|
||||
|
||||
/**************************** PROTOTYPES ****************************/
|
||||
|
|
|
@ -1657,12 +1657,6 @@ void ieee80211_free_hw(struct ieee80211_hw *hw);
|
|||
*/
|
||||
void ieee80211_restart_hw(struct ieee80211_hw *hw);
|
||||
|
||||
/*
|
||||
* trick to avoid symbol clashes with the ieee80211 subsystem,
|
||||
* use the inline below instead
|
||||
*/
|
||||
void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
|
||||
/**
|
||||
* ieee80211_rx - receive frame
|
||||
*
|
||||
|
@ -1678,10 +1672,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb);
|
|||
* @hw: the hardware this frame came in on
|
||||
* @skb: the buffer to receive, owned by mac80211 after this call
|
||||
*/
|
||||
static inline void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
__ieee80211_rx(hw, skb);
|
||||
}
|
||||
void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
|
||||
/**
|
||||
* ieee80211_rx_irqsafe - receive frame
|
||||
|
|
|
@ -12,7 +12,11 @@ static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
|
|||
|
||||
static inline int drv_start(struct ieee80211_local *local)
|
||||
{
|
||||
int ret = local->ops->start(&local->hw);
|
||||
int ret;
|
||||
|
||||
local->started = true;
|
||||
smp_mb();
|
||||
ret = local->ops->start(&local->hw);
|
||||
trace_drv_start(local, ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -21,6 +25,14 @@ static inline void drv_stop(struct ieee80211_local *local)
|
|||
{
|
||||
local->ops->stop(&local->hw);
|
||||
trace_drv_stop(local);
|
||||
|
||||
/* sync away all work on the tasklet before clearing started */
|
||||
tasklet_disable(&local->tasklet);
|
||||
tasklet_enable(&local->tasklet);
|
||||
|
||||
barrier();
|
||||
|
||||
local->started = false;
|
||||
}
|
||||
|
||||
static inline int drv_add_interface(struct ieee80211_local *local,
|
||||
|
|
|
@ -367,6 +367,10 @@ struct ieee80211_if_mesh {
|
|||
u8 mesh_pm_id[4];
|
||||
/* Congestion Control Mode Identifier */
|
||||
u8 mesh_cc_id[4];
|
||||
/* Synchronization Protocol Identifier */
|
||||
u8 mesh_sp_id[4];
|
||||
/* Authentication Protocol Identifier */
|
||||
u8 mesh_auth_id[4];
|
||||
/* Local mesh Destination Sequence Number */
|
||||
u32 dsn;
|
||||
/* Last used PREQ ID */
|
||||
|
@ -663,6 +667,9 @@ struct ieee80211_local {
|
|||
*/
|
||||
bool quiescing;
|
||||
|
||||
/* device is started */
|
||||
bool started;
|
||||
|
||||
int tx_headroom; /* required headroom for hardware/radiotap */
|
||||
|
||||
/* Tasklet and skb queue to process calls from IRQ mode. All frames
|
||||
|
@ -1082,6 +1089,7 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
/* Suspend/resume and hw reconfiguration */
|
||||
int ieee80211_reconfig(struct ieee80211_local *local);
|
||||
void ieee80211_stop_device(struct ieee80211_local *local);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int __ieee80211_suspend(struct ieee80211_hw *hw);
|
||||
|
|
|
@ -277,11 +277,6 @@ static int ieee80211_open(struct net_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (local->open_count == 0) {
|
||||
tasklet_enable(&local->tx_pending_tasklet);
|
||||
tasklet_enable(&local->tasklet);
|
||||
}
|
||||
|
||||
/*
|
||||
* set_multicast_list will be invoked by the networking core
|
||||
* which will check whether any increments here were done in
|
||||
|
@ -502,30 +497,8 @@ static int ieee80211_stop(struct net_device *dev)
|
|||
}
|
||||
/* fall through */
|
||||
default:
|
||||
if (local->scan_sdata == sdata) {
|
||||
if (!local->ops->hw_scan)
|
||||
cancel_delayed_work_sync(&local->scan_work);
|
||||
/*
|
||||
* The software scan can no longer run now, so we can
|
||||
* clear out the scan_sdata reference. However, the
|
||||
* hardware scan may still be running. The complete
|
||||
* function must be prepared to handle a NULL value.
|
||||
*/
|
||||
local->scan_sdata = NULL;
|
||||
/*
|
||||
* The memory barrier guarantees that another CPU
|
||||
* that is hardware-scanning will now see the fact
|
||||
* that this interface is gone.
|
||||
*/
|
||||
smp_mb();
|
||||
/*
|
||||
* If software scanning, complete the scan but since
|
||||
* the scan_sdata is NULL already don't send out a
|
||||
* scan event to userspace -- the scan is incomplete.
|
||||
*/
|
||||
if (test_bit(SCAN_SW_SCANNING, &local->scanning))
|
||||
ieee80211_scan_completed(&local->hw, true);
|
||||
}
|
||||
if (local->scan_sdata == sdata)
|
||||
ieee80211_scan_cancel(local);
|
||||
|
||||
/*
|
||||
* Disable beaconing for AP and mesh, IBSS can't
|
||||
|
@ -552,14 +525,8 @@ static int ieee80211_stop(struct net_device *dev)
|
|||
ieee80211_recalc_ps(local, -1);
|
||||
|
||||
if (local->open_count == 0) {
|
||||
drv_stop(local);
|
||||
|
||||
ieee80211_led_radio(local, false);
|
||||
|
||||
flush_workqueue(local->workqueue);
|
||||
|
||||
tasklet_disable(&local->tx_pending_tasklet);
|
||||
tasklet_disable(&local->tasklet);
|
||||
ieee80211_clear_tx_pending(local);
|
||||
ieee80211_stop_device(local);
|
||||
|
||||
/* no reconfiguring after stop! */
|
||||
hw_reconf_flags = 0;
|
||||
|
|
|
@ -715,12 +715,10 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
|
|||
skb_queue_head_init(&local->pending[i]);
|
||||
tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
|
||||
(unsigned long)local);
|
||||
tasklet_disable(&local->tx_pending_tasklet);
|
||||
|
||||
tasklet_init(&local->tasklet,
|
||||
ieee80211_tasklet_handler,
|
||||
(unsigned long) local);
|
||||
tasklet_disable(&local->tasklet);
|
||||
|
||||
skb_queue_head_init(&local->skb_queue);
|
||||
skb_queue_head_init(&local->skb_queue_unreliable);
|
||||
|
|
|
@ -18,8 +18,11 @@
|
|||
#define PP_OFFSET 1 /* Path Selection Protocol */
|
||||
#define PM_OFFSET 5 /* Path Selection Metric */
|
||||
#define CC_OFFSET 9 /* Congestion Control Mode */
|
||||
#define CAPAB_OFFSET 17
|
||||
#define ACCEPT_PLINKS 0x80
|
||||
#define SP_OFFSET 13 /* Synchronization Protocol */
|
||||
#define AUTH_OFFSET 17 /* Authentication Protocol */
|
||||
#define CAPAB_OFFSET 22
|
||||
#define CAPAB_ACCEPT_PLINKS 0x80
|
||||
#define CAPAB_FORWARDING 0x10
|
||||
|
||||
#define TMR_RUNNING_HK 0
|
||||
#define TMR_RUNNING_MP 1
|
||||
|
@ -84,7 +87,9 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat
|
|||
memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
|
||||
memcmp(ifmsh->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 &&
|
||||
memcmp(ifmsh->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 &&
|
||||
memcmp(ifmsh->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0)
|
||||
memcmp(ifmsh->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0 &&
|
||||
memcmp(ifmsh->mesh_sp_id, ie->mesh_config + SP_OFFSET, 4) == 0 &&
|
||||
memcmp(ifmsh->mesh_auth_id, ie->mesh_config + AUTH_OFFSET, 4) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -97,7 +102,7 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat
|
|||
*/
|
||||
bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie)
|
||||
{
|
||||
return (*(ie->mesh_config + CAPAB_OFFSET) & ACCEPT_PLINKS) != 0;
|
||||
return (*(ie->mesh_config + CAPAB_OFFSET) & CAPAB_ACCEPT_PLINKS) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,11 +128,18 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
|
|||
|
||||
void mesh_ids_set_default(struct ieee80211_if_mesh *sta)
|
||||
{
|
||||
u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff};
|
||||
u8 oui[3] = {0x00, 0x0F, 0xAC};
|
||||
|
||||
memcpy(sta->mesh_pp_id, def_id, 4);
|
||||
memcpy(sta->mesh_pm_id, def_id, 4);
|
||||
memcpy(sta->mesh_cc_id, def_id, 4);
|
||||
memcpy(sta->mesh_pp_id, oui, sizeof(oui));
|
||||
memcpy(sta->mesh_pm_id, oui, sizeof(oui));
|
||||
memcpy(sta->mesh_cc_id, oui, sizeof(oui));
|
||||
memcpy(sta->mesh_sp_id, oui, sizeof(oui));
|
||||
memcpy(sta->mesh_auth_id, oui, sizeof(oui));
|
||||
sta->mesh_pp_id[sizeof(oui)] = 0;
|
||||
sta->mesh_pm_id[sizeof(oui)] = 0;
|
||||
sta->mesh_cc_id[sizeof(oui)] = 0xff;
|
||||
sta->mesh_sp_id[sizeof(oui)] = 0xff;
|
||||
sta->mesh_auth_id[sizeof(oui)] = 0x0;
|
||||
}
|
||||
|
||||
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
|
||||
|
@ -245,7 +257,7 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
|
|||
if (sdata->u.mesh.mesh_id_len)
|
||||
memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len);
|
||||
|
||||
pos = skb_put(skb, 21);
|
||||
pos = skb_put(skb, 2 + IEEE80211_MESH_CONFIG_LEN);
|
||||
*pos++ = WLAN_EID_MESH_CONFIG;
|
||||
*pos++ = IEEE80211_MESH_CONFIG_LEN;
|
||||
/* Version */
|
||||
|
@ -263,15 +275,22 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
|
|||
memcpy(pos, sdata->u.mesh.mesh_cc_id, 4);
|
||||
pos += 4;
|
||||
|
||||
/* Channel precedence:
|
||||
* Not running simple channel unification protocol
|
||||
*/
|
||||
memset(pos, 0x00, 4);
|
||||
/* Synchronization protocol identifier */
|
||||
memcpy(pos, sdata->u.mesh.mesh_sp_id, 4);
|
||||
pos += 4;
|
||||
|
||||
/* Authentication Protocol identifier */
|
||||
memcpy(pos, sdata->u.mesh.mesh_auth_id, 4);
|
||||
pos += 4;
|
||||
|
||||
/* Mesh Formation Info */
|
||||
memset(pos, 0x00, 1);
|
||||
pos += 1;
|
||||
|
||||
/* Mesh capability */
|
||||
sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata);
|
||||
*pos++ = sdata->u.mesh.accepting_plinks ? ACCEPT_PLINKS : 0x00;
|
||||
*pos = CAPAB_FORWARDING;
|
||||
*pos++ |= sdata->u.mesh.accepting_plinks ? CAPAB_ACCEPT_PLINKS : 0x00;
|
||||
*pos++ = 0x00;
|
||||
|
||||
return;
|
||||
|
|
|
@ -2123,25 +2123,9 @@ static void ieee80211_sta_work(struct work_struct *work)
|
|||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(wk, &ifmgd->work_list, list) {
|
||||
if (wk->state != IEEE80211_MGD_STATE_IDLE) {
|
||||
anybusy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ieee80211_recalc_idle(local);
|
||||
|
||||
if (!anybusy) {
|
||||
mutex_unlock(&ifmgd->mtx);
|
||||
|
||||
if (test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request))
|
||||
ieee80211_queue_delayed_work(&local->hw,
|
||||
&local->scan_work,
|
||||
round_jiffies_relative(0));
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) {
|
||||
if (time_is_after_jiffies(wk->timeout)) {
|
||||
/*
|
||||
|
@ -2187,6 +2171,18 @@ static void ieee80211_sta_work(struct work_struct *work)
|
|||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(wk, &ifmgd->work_list, list) {
|
||||
if (wk->state != IEEE80211_MGD_STATE_IDLE) {
|
||||
anybusy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!anybusy &&
|
||||
test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request))
|
||||
ieee80211_queue_delayed_work(&local->hw,
|
||||
&local->scan_work,
|
||||
round_jiffies_relative(0));
|
||||
|
||||
mutex_unlock(&ifmgd->mtx);
|
||||
|
||||
list_for_each_entry_safe(wk, tmp, &free_work, list) {
|
||||
|
|
|
@ -107,17 +107,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
/* stop hardware - this must stop RX */
|
||||
if (local->open_count) {
|
||||
ieee80211_led_radio(local, false);
|
||||
drv_stop(local);
|
||||
}
|
||||
|
||||
/*
|
||||
* flush again, in case driver queued work -- it
|
||||
* shouldn't be doing (or cancel everything in the
|
||||
* stop callback) that but better safe than sorry.
|
||||
*/
|
||||
flush_workqueue(local->workqueue);
|
||||
if (local->open_count)
|
||||
ieee80211_stop_device(local);
|
||||
|
||||
local->suspended = true;
|
||||
/* need suspended to be visible before quiescing is false */
|
||||
|
|
|
@ -33,7 +33,6 @@ struct minstrel_rate {
|
|||
|
||||
/* per-rate throughput */
|
||||
u32 cur_tp;
|
||||
u32 throughput;
|
||||
|
||||
u64 succ_hist;
|
||||
u64 att_hist;
|
||||
|
|
|
@ -83,7 +83,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
|
|||
p += sprintf(p, "%3u%s", mr->bitrate / 2,
|
||||
(mr->bitrate & 1 ? ".5" : " "));
|
||||
|
||||
tp = ((mr->cur_tp * 96) / 18000) >> 10;
|
||||
tp = mr->cur_tp / ((18000 << 10) / 96);
|
||||
prob = mr->cur_prob / 18;
|
||||
eprob = mr->probability / 18;
|
||||
|
||||
|
|
|
@ -2440,24 +2440,20 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
|
|||
* This is the receive path handler. It is called by a low level driver when an
|
||||
* 802.11 MPDU is received from the hardware.
|
||||
*/
|
||||
void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct ieee80211_rate *rate = NULL;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
if (status->band < 0 ||
|
||||
status->band >= IEEE80211_NUM_BANDS) {
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
if (WARN_ON(status->band < 0 ||
|
||||
status->band >= IEEE80211_NUM_BANDS))
|
||||
goto drop;
|
||||
|
||||
sband = local->hw.wiphy->bands[status->band];
|
||||
if (!sband) {
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
if (WARN_ON(!sband))
|
||||
goto drop;
|
||||
|
||||
/*
|
||||
* If we're suspending, it is possible although not too likely
|
||||
|
@ -2466,16 +2462,21 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
* that might, for example, cause stations to be added or other
|
||||
* driver callbacks be invoked.
|
||||
*/
|
||||
if (unlikely(local->quiescing || local->suspended)) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
if (unlikely(local->quiescing || local->suspended))
|
||||
goto drop;
|
||||
|
||||
/*
|
||||
* The same happens when we're not even started,
|
||||
* but that's worth a warning.
|
||||
*/
|
||||
if (WARN_ON(!local->started))
|
||||
goto drop;
|
||||
|
||||
if (status->flag & RX_FLAG_HT) {
|
||||
/* rate_idx is MCS index */
|
||||
if (WARN_ON(status->rate_idx < 0 ||
|
||||
status->rate_idx >= 76))
|
||||
return;
|
||||
goto drop;
|
||||
/* HT rates are not in the table - use the highest legacy rate
|
||||
* for now since other parts of mac80211 may not yet be fully
|
||||
* MCS aware. */
|
||||
|
@ -2483,7 +2484,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
} else {
|
||||
if (WARN_ON(status->rate_idx < 0 ||
|
||||
status->rate_idx >= sband->n_bitrates))
|
||||
return;
|
||||
goto drop;
|
||||
rate = &sband->bitrates[status->rate_idx];
|
||||
}
|
||||
|
||||
|
@ -2522,8 +2523,12 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
__ieee80211_rx_handle_packet(hw, skb, rate);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return;
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
}
|
||||
EXPORT_SYMBOL(__ieee80211_rx);
|
||||
EXPORT_SYMBOL(ieee80211_rx);
|
||||
|
||||
/* This is a version of the rx handler that can be called from hard irq
|
||||
* context. Post the skb on the queue and schedule the tasklet */
|
||||
|
|
|
@ -280,6 +280,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
|||
if (local->scan_req != local->int_scan_req)
|
||||
cfg80211_scan_done(local->scan_req, aborted);
|
||||
local->scan_req = NULL;
|
||||
local->scan_sdata = NULL;
|
||||
|
||||
was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
|
||||
local->scanning = 0;
|
||||
|
@ -660,6 +661,7 @@ void ieee80211_scan_work(struct work_struct *work)
|
|||
int rc;
|
||||
|
||||
local->scan_req = NULL;
|
||||
local->scan_sdata = NULL;
|
||||
|
||||
rc = __ieee80211_start_scan(sdata, req);
|
||||
mutex_unlock(&local->scan_mtx);
|
||||
|
@ -742,7 +744,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
void ieee80211_scan_cancel(struct ieee80211_local *local)
|
||||
{
|
||||
bool swscan;
|
||||
bool abortscan;
|
||||
|
||||
cancel_delayed_work_sync(&local->scan_work);
|
||||
|
||||
|
@ -751,9 +753,10 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
|
|||
* queued -- mostly at suspend under RTNL.
|
||||
*/
|
||||
mutex_lock(&local->scan_mtx);
|
||||
swscan = test_bit(SCAN_SW_SCANNING, &local->scanning);
|
||||
abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) ||
|
||||
(!local->scanning && local->scan_req);
|
||||
mutex_unlock(&local->scan_mtx);
|
||||
|
||||
if (swscan)
|
||||
if (abortscan)
|
||||
ieee80211_scan_completed(&local->hw, true);
|
||||
}
|
||||
|
|
|
@ -1007,6 +1007,16 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
|
|||
return supp_rates;
|
||||
}
|
||||
|
||||
void ieee80211_stop_device(struct ieee80211_local *local)
|
||||
{
|
||||
ieee80211_led_radio(local, false);
|
||||
|
||||
cancel_work_sync(&local->reconfig_filter);
|
||||
drv_stop(local);
|
||||
|
||||
flush_workqueue(local->workqueue);
|
||||
}
|
||||
|
||||
int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_hw *hw = &local->hw;
|
||||
|
|
|
@ -17,6 +17,23 @@ config NL80211_TESTMODE
|
|||
|
||||
Say N.
|
||||
|
||||
config CFG80211_DEVELOPER_WARNINGS
|
||||
bool "enable developer warnings"
|
||||
depends on CFG80211
|
||||
default n
|
||||
help
|
||||
This option enables some additional warnings that help
|
||||
cfg80211 developers and driver developers, but that can
|
||||
trigger due to races with userspace.
|
||||
|
||||
For example, when a driver reports that it was disconnected
|
||||
from the AP, but the user disconnects manually at the same
|
||||
time, the warning might trigger spuriously due to races.
|
||||
|
||||
Say Y only if you are developing cfg80211 or a driver based
|
||||
on it (or mac80211).
|
||||
|
||||
|
||||
config CFG80211_REG_DEBUG
|
||||
bool "cfg80211 regulatory debugging"
|
||||
depends on CFG80211
|
||||
|
|
|
@ -294,69 +294,17 @@ static void cfg80211_rfkill_sync_work(struct work_struct *work)
|
|||
cfg80211_rfkill_set_block(rdev, rfkill_blocked(rdev->rfkill));
|
||||
}
|
||||
|
||||
static void cfg80211_process_events(struct wireless_dev *wdev)
|
||||
{
|
||||
struct cfg80211_event *ev;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&wdev->event_lock, flags);
|
||||
while (!list_empty(&wdev->event_list)) {
|
||||
ev = list_first_entry(&wdev->event_list,
|
||||
struct cfg80211_event, list);
|
||||
list_del(&ev->list);
|
||||
spin_unlock_irqrestore(&wdev->event_lock, flags);
|
||||
|
||||
wdev_lock(wdev);
|
||||
switch (ev->type) {
|
||||
case EVENT_CONNECT_RESULT:
|
||||
__cfg80211_connect_result(
|
||||
wdev->netdev, is_zero_ether_addr(ev->cr.bssid) ?
|
||||
NULL : ev->cr.bssid,
|
||||
ev->cr.req_ie, ev->cr.req_ie_len,
|
||||
ev->cr.resp_ie, ev->cr.resp_ie_len,
|
||||
ev->cr.status,
|
||||
ev->cr.status == WLAN_STATUS_SUCCESS,
|
||||
NULL);
|
||||
break;
|
||||
case EVENT_ROAMED:
|
||||
__cfg80211_roamed(wdev, ev->rm.bssid,
|
||||
ev->rm.req_ie, ev->rm.req_ie_len,
|
||||
ev->rm.resp_ie, ev->rm.resp_ie_len);
|
||||
break;
|
||||
case EVENT_DISCONNECTED:
|
||||
__cfg80211_disconnected(wdev->netdev,
|
||||
ev->dc.ie, ev->dc.ie_len,
|
||||
ev->dc.reason, true);
|
||||
break;
|
||||
case EVENT_IBSS_JOINED:
|
||||
__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
|
||||
break;
|
||||
}
|
||||
wdev_unlock(wdev);
|
||||
|
||||
kfree(ev);
|
||||
|
||||
spin_lock_irqsave(&wdev->event_lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&wdev->event_lock, flags);
|
||||
}
|
||||
|
||||
static void cfg80211_event_work(struct work_struct *work)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wireless_dev *wdev;
|
||||
|
||||
rdev = container_of(work, struct cfg80211_registered_device,
|
||||
event_work);
|
||||
|
||||
rtnl_lock();
|
||||
cfg80211_lock_rdev(rdev);
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
|
||||
list_for_each_entry(wdev, &rdev->netdev_list, list)
|
||||
cfg80211_process_events(wdev);
|
||||
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
cfg80211_process_rdev_events(rdev);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
@ -664,7 +612,7 @@ static void wdev_cleanup_work(struct work_struct *work)
|
|||
|
||||
if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == wdev->netdev)) {
|
||||
rdev->scan_req->aborted = true;
|
||||
___cfg80211_scan_done(rdev);
|
||||
___cfg80211_scan_done(rdev, true);
|
||||
}
|
||||
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
|
@ -755,6 +703,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NETDEV_DOWN:
|
||||
dev_hold(dev);
|
||||
schedule_work(&wdev->cleanup_work);
|
||||
break;
|
||||
|
|
|
@ -370,8 +370,12 @@ void cfg80211_sme_scan_done(struct net_device *dev);
|
|||
void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
|
||||
void cfg80211_sme_disassoc(struct net_device *dev, int idx);
|
||||
void __cfg80211_scan_done(struct work_struct *wk);
|
||||
void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev);
|
||||
void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak);
|
||||
void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
|
||||
int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, enum nl80211_iftype ntype,
|
||||
u32 *flags, struct vif_params *params);
|
||||
void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
|
||||
|
||||
struct ieee80211_channel *
|
||||
rdev_fixed_channel(struct cfg80211_registered_device *rdev,
|
||||
|
@ -380,4 +384,15 @@ int rdev_set_freq(struct cfg80211_registered_device *rdev,
|
|||
struct wireless_dev *for_wdev,
|
||||
int freq, enum nl80211_channel_type channel_type);
|
||||
|
||||
#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
|
||||
#define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond)
|
||||
#else
|
||||
/*
|
||||
* Trick to enable using it as a condition,
|
||||
* and also not give a warning when it's
|
||||
* not used that way.
|
||||
*/
|
||||
#define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; })
|
||||
#endif
|
||||
|
||||
#endif /* __NET_WIRELESS_CORE_H */
|
||||
|
|
|
@ -22,7 +22,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
|||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
|
||||
return;
|
||||
|
||||
if (WARN_ON(!wdev->ssid_len))
|
||||
if (!wdev->ssid_len)
|
||||
return;
|
||||
|
||||
bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
|
||||
|
@ -58,6 +58,8 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
|
|||
struct cfg80211_event *ev;
|
||||
unsigned long flags;
|
||||
|
||||
CFG80211_DEV_WARN_ON(!wdev->ssid_len);
|
||||
|
||||
ev = kzalloc(sizeof(*ev), gfp);
|
||||
if (!ev)
|
||||
return;
|
||||
|
|
|
@ -977,12 +977,6 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
}
|
||||
|
||||
if (!rdev->ops->change_virtual_intf ||
|
||||
!(rdev->wiphy.interface_modes & (1 << ntype))) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_MESH_ID]) {
|
||||
if (ntype != NL80211_IFTYPE_MESH_POINT) {
|
||||
err = -EINVAL;
|
||||
|
@ -1008,18 +1002,10 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
|
||||
if (change)
|
||||
err = rdev->ops->change_virtual_intf(&rdev->wiphy, dev,
|
||||
ntype, flags, ¶ms);
|
||||
err = cfg80211_change_iface(rdev, dev, ntype, flags, ¶ms);
|
||||
else
|
||||
err = 0;
|
||||
|
||||
WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype);
|
||||
|
||||
if (!err && (ntype != otype)) {
|
||||
if (otype == NL80211_IFTYPE_ADHOC)
|
||||
cfg80211_clear_ibss(dev, false);
|
||||
}
|
||||
|
||||
unlock:
|
||||
dev_put(dev);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
|
@ -2195,7 +2181,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
|
|||
|
||||
if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ)
|
||||
|
||||
void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
|
||||
void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
|
||||
{
|
||||
struct cfg80211_scan_request *request;
|
||||
struct net_device *dev;
|
||||
|
@ -26,8 +26,13 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
|
|||
union iwreq_data wrqu;
|
||||
#endif
|
||||
|
||||
ASSERT_RDEV_LOCK(rdev);
|
||||
|
||||
request = rdev->scan_req;
|
||||
|
||||
if (!request)
|
||||
return;
|
||||
|
||||
dev = request->dev;
|
||||
|
||||
/*
|
||||
|
@ -53,7 +58,17 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
|
|||
dev_put(dev);
|
||||
|
||||
rdev->scan_req = NULL;
|
||||
kfree(request);
|
||||
|
||||
/*
|
||||
* OK. If this is invoked with "leak" then we can't
|
||||
* free this ... but we've cleaned it up anyway. The
|
||||
* driver failed to call the scan_done callback, so
|
||||
* all bets are off, it might still be trying to use
|
||||
* the scan request or not ... if it accesses the dev
|
||||
* in there (it shouldn't anyway) then it may crash.
|
||||
*/
|
||||
if (!leak)
|
||||
kfree(request);
|
||||
}
|
||||
|
||||
void __cfg80211_scan_done(struct work_struct *wk)
|
||||
|
@ -64,7 +79,7 @@ void __cfg80211_scan_done(struct work_struct *wk)
|
|||
scan_done_wk);
|
||||
|
||||
cfg80211_lock_rdev(rdev);
|
||||
___cfg80211_scan_done(rdev);
|
||||
___cfg80211_scan_done(rdev, false);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
}
|
||||
|
||||
|
|
|
@ -351,7 +351,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
|||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
|
||||
return;
|
||||
|
||||
if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING))
|
||||
if (wdev->sme_state != CFG80211_SME_CONNECTING)
|
||||
return;
|
||||
|
||||
nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev,
|
||||
|
@ -445,6 +445,8 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
|||
struct cfg80211_event *ev;
|
||||
unsigned long flags;
|
||||
|
||||
CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING);
|
||||
|
||||
ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
|
||||
if (!ev)
|
||||
return;
|
||||
|
@ -481,7 +483,7 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
|
|||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
|
||||
return;
|
||||
|
||||
if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED))
|
||||
if (wdev->sme_state != CFG80211_SME_CONNECTED)
|
||||
return;
|
||||
|
||||
/* internal error -- how did we get to CONNECTED w/o BSS? */
|
||||
|
@ -540,6 +542,8 @@ void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
|
|||
struct cfg80211_event *ev;
|
||||
unsigned long flags;
|
||||
|
||||
CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED);
|
||||
|
||||
ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
|
||||
if (!ev)
|
||||
return;
|
||||
|
@ -575,7 +579,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
|
|||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
|
||||
return;
|
||||
|
||||
if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED))
|
||||
if (wdev->sme_state != CFG80211_SME_CONNECTED)
|
||||
return;
|
||||
|
||||
if (wdev->current_bss) {
|
||||
|
@ -639,6 +643,8 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason,
|
|||
struct cfg80211_event *ev;
|
||||
unsigned long flags;
|
||||
|
||||
CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED);
|
||||
|
||||
ev = kzalloc(sizeof(*ev) + ie_len, gfp);
|
||||
if (!ev)
|
||||
return;
|
||||
|
|
|
@ -574,3 +574,111 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
|
|||
kfree(wdev->connect_keys);
|
||||
wdev->connect_keys = NULL;
|
||||
}
|
||||
|
||||
static void cfg80211_process_wdev_events(struct wireless_dev *wdev)
|
||||
{
|
||||
struct cfg80211_event *ev;
|
||||
unsigned long flags;
|
||||
const u8 *bssid = NULL;
|
||||
|
||||
spin_lock_irqsave(&wdev->event_lock, flags);
|
||||
while (!list_empty(&wdev->event_list)) {
|
||||
ev = list_first_entry(&wdev->event_list,
|
||||
struct cfg80211_event, list);
|
||||
list_del(&ev->list);
|
||||
spin_unlock_irqrestore(&wdev->event_lock, flags);
|
||||
|
||||
wdev_lock(wdev);
|
||||
switch (ev->type) {
|
||||
case EVENT_CONNECT_RESULT:
|
||||
if (!is_zero_ether_addr(ev->cr.bssid))
|
||||
bssid = ev->cr.bssid;
|
||||
__cfg80211_connect_result(
|
||||
wdev->netdev, bssid,
|
||||
ev->cr.req_ie, ev->cr.req_ie_len,
|
||||
ev->cr.resp_ie, ev->cr.resp_ie_len,
|
||||
ev->cr.status,
|
||||
ev->cr.status == WLAN_STATUS_SUCCESS,
|
||||
NULL);
|
||||
break;
|
||||
case EVENT_ROAMED:
|
||||
__cfg80211_roamed(wdev, ev->rm.bssid,
|
||||
ev->rm.req_ie, ev->rm.req_ie_len,
|
||||
ev->rm.resp_ie, ev->rm.resp_ie_len);
|
||||
break;
|
||||
case EVENT_DISCONNECTED:
|
||||
__cfg80211_disconnected(wdev->netdev,
|
||||
ev->dc.ie, ev->dc.ie_len,
|
||||
ev->dc.reason, true);
|
||||
break;
|
||||
case EVENT_IBSS_JOINED:
|
||||
__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
|
||||
break;
|
||||
}
|
||||
wdev_unlock(wdev);
|
||||
|
||||
kfree(ev);
|
||||
|
||||
spin_lock_irqsave(&wdev->event_lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&wdev->event_lock, flags);
|
||||
}
|
||||
|
||||
void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
|
||||
{
|
||||
struct wireless_dev *wdev;
|
||||
|
||||
ASSERT_RTNL();
|
||||
ASSERT_RDEV_LOCK(rdev);
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
|
||||
list_for_each_entry(wdev, &rdev->netdev_list, list)
|
||||
cfg80211_process_wdev_events(wdev);
|
||||
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
}
|
||||
|
||||
int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, enum nl80211_iftype ntype,
|
||||
u32 *flags, struct vif_params *params)
|
||||
{
|
||||
int err;
|
||||
enum nl80211_iftype otype = dev->ieee80211_ptr->iftype;
|
||||
|
||||
ASSERT_RDEV_LOCK(rdev);
|
||||
|
||||
/* don't support changing VLANs, you just re-create them */
|
||||
if (otype == NL80211_IFTYPE_AP_VLAN)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!rdev->ops->change_virtual_intf ||
|
||||
!(rdev->wiphy.interface_modes & (1 << ntype)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (ntype != otype) {
|
||||
switch (otype) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
cfg80211_leave_ibss(rdev, dev, false);
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, true);
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
/* mesh should be handled? */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cfg80211_process_rdev_events(rdev);
|
||||
}
|
||||
|
||||
err = rdev->ops->change_virtual_intf(&rdev->wiphy, dev,
|
||||
ntype, flags, params);
|
||||
|
||||
WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -70,18 +70,8 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
|
|||
enum nl80211_iftype type;
|
||||
int ret;
|
||||
|
||||
if (!wdev)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rdev = wiphy_to_dev(wdev->wiphy);
|
||||
|
||||
if (!rdev->ops->change_virtual_intf)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* don't support changing VLANs, you just re-create them */
|
||||
if (wdev->iftype == NL80211_IFTYPE_AP_VLAN)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (*mode) {
|
||||
case IW_MODE_INFRA:
|
||||
type = NL80211_IFTYPE_STATION;
|
||||
|
@ -104,9 +94,9 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
|
|||
|
||||
memset(&vifparams, 0, sizeof(vifparams));
|
||||
|
||||
ret = rdev->ops->change_virtual_intf(wdev->wiphy, dev, type,
|
||||
NULL, &vifparams);
|
||||
WARN_ON(!ret && wdev->iftype != type);
|
||||
cfg80211_lock_rdev(rdev);
|
||||
ret = cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue