mirror of
https://github.com/torvalds/linux.git
synced 2024-10-31 09:11:49 +00:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts: drivers/net/wireless/iwlwifi/iwl-commands.h
This commit is contained in:
commit
2a88e7e559
@ -2931,8 +2931,8 @@ err_out_res:
|
||||
release_region( dev->base_addr, 64 );
|
||||
err_out_nets:
|
||||
airo_networks_free(ai);
|
||||
del_airo_dev(ai);
|
||||
err_out_free:
|
||||
del_airo_dev(ai);
|
||||
free_netdev(dev);
|
||||
return NULL;
|
||||
}
|
||||
@ -4657,7 +4657,7 @@ static ssize_t proc_write( struct file *file,
|
||||
loff_t *offset )
|
||||
{
|
||||
loff_t pos = *offset;
|
||||
struct proc_data *priv = (struct proc_data*)file->private_data;
|
||||
struct proc_data *priv = file->private_data;
|
||||
|
||||
if (!priv->wbuffer)
|
||||
return -EINVAL;
|
||||
@ -4689,7 +4689,7 @@ static int proc_status_open(struct inode *inode, struct file *file)
|
||||
|
||||
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
|
||||
return -ENOMEM;
|
||||
data = (struct proc_data *)file->private_data;
|
||||
data = file->private_data;
|
||||
if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
|
||||
kfree (file->private_data);
|
||||
return -ENOMEM;
|
||||
@ -4772,7 +4772,7 @@ static int proc_stats_rid_open( struct inode *inode,
|
||||
|
||||
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
|
||||
return -ENOMEM;
|
||||
data = (struct proc_data *)file->private_data;
|
||||
data = file->private_data;
|
||||
if ((data->rbuffer = kmalloc( 4096, GFP_KERNEL )) == NULL) {
|
||||
kfree (file->private_data);
|
||||
return -ENOMEM;
|
||||
@ -5045,7 +5045,7 @@ static int proc_config_open(struct inode *inode, struct file *file)
|
||||
|
||||
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
|
||||
return -ENOMEM;
|
||||
data = (struct proc_data *)file->private_data;
|
||||
data = file->private_data;
|
||||
if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
|
||||
kfree (file->private_data);
|
||||
return -ENOMEM;
|
||||
@ -5127,7 +5127,7 @@ static int proc_config_open(struct inode *inode, struct file *file)
|
||||
|
||||
static void proc_SSID_on_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct proc_data *data = (struct proc_data *)file->private_data;
|
||||
struct proc_data *data = file->private_data;
|
||||
struct proc_dir_entry *dp = PDE(inode);
|
||||
struct net_device *dev = dp->data;
|
||||
struct airo_info *ai = dev->ml_priv;
|
||||
@ -5163,7 +5163,7 @@ static void proc_SSID_on_close(struct inode *inode, struct file *file)
|
||||
}
|
||||
|
||||
static void proc_APList_on_close( struct inode *inode, struct file *file ) {
|
||||
struct proc_data *data = (struct proc_data *)file->private_data;
|
||||
struct proc_data *data = file->private_data;
|
||||
struct proc_dir_entry *dp = PDE(inode);
|
||||
struct net_device *dev = dp->data;
|
||||
struct airo_info *ai = dev->ml_priv;
|
||||
@ -5309,7 +5309,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
|
||||
|
||||
memset(key, 0, sizeof(key));
|
||||
|
||||
data = (struct proc_data *)file->private_data;
|
||||
data = file->private_data;
|
||||
if ( !data->writelen ) return;
|
||||
|
||||
if (data->wbuffer[0] >= '0' && data->wbuffer[0] <= '3' &&
|
||||
@ -5363,7 +5363,7 @@ static int proc_wepkey_open( struct inode *inode, struct file *file )
|
||||
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
|
||||
return -ENOMEM;
|
||||
memset(&wkr, 0, sizeof(wkr));
|
||||
data = (struct proc_data *)file->private_data;
|
||||
data = file->private_data;
|
||||
if ((data->rbuffer = kzalloc( 180, GFP_KERNEL )) == NULL) {
|
||||
kfree (file->private_data);
|
||||
return -ENOMEM;
|
||||
@ -5409,7 +5409,7 @@ static int proc_SSID_open(struct inode *inode, struct file *file)
|
||||
|
||||
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
|
||||
return -ENOMEM;
|
||||
data = (struct proc_data *)file->private_data;
|
||||
data = file->private_data;
|
||||
if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
|
||||
kfree (file->private_data);
|
||||
return -ENOMEM;
|
||||
@ -5453,7 +5453,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
|
||||
|
||||
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
|
||||
return -ENOMEM;
|
||||
data = (struct proc_data *)file->private_data;
|
||||
data = file->private_data;
|
||||
if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
|
||||
kfree (file->private_data);
|
||||
return -ENOMEM;
|
||||
@ -5495,7 +5495,7 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
|
||||
|
||||
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
|
||||
return -ENOMEM;
|
||||
data = (struct proc_data *)file->private_data;
|
||||
data = file->private_data;
|
||||
if ((data->rbuffer = kmalloc( 1024, GFP_KERNEL )) == NULL) {
|
||||
kfree (file->private_data);
|
||||
return -ENOMEM;
|
||||
|
@ -388,7 +388,7 @@ static int ath5k_init(struct ath5k_softc *sc);
|
||||
static int ath5k_stop_locked(struct ath5k_softc *sc);
|
||||
static int ath5k_stop_hw(struct ath5k_softc *sc);
|
||||
static irqreturn_t ath5k_intr(int irq, void *dev_id);
|
||||
static void ath5k_tasklet_reset(unsigned long data);
|
||||
static void ath5k_reset_work(struct work_struct *work);
|
||||
|
||||
static void ath5k_tasklet_calibrate(unsigned long data);
|
||||
|
||||
@ -831,11 +831,12 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
|
||||
|
||||
tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
|
||||
tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
|
||||
tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
|
||||
tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
|
||||
tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
|
||||
tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
|
||||
|
||||
INIT_WORK(&sc->reset_work, ath5k_reset_work);
|
||||
|
||||
ret = ath5k_eeprom_read_mac(ah, mac);
|
||||
if (ret) {
|
||||
ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
|
||||
@ -1727,8 +1728,6 @@ ath5k_rx_stop(struct ath5k_softc *sc)
|
||||
ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */
|
||||
|
||||
ath5k_debug_printrxbuffs(sc, ah);
|
||||
|
||||
sc->rxlink = NULL; /* just in case */
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
@ -2294,8 +2293,8 @@ err_unmap:
|
||||
* frame contents are done as needed and the slot time is
|
||||
* also adjusted based on current state.
|
||||
*
|
||||
* This is called from software irq context (beacontq or restq
|
||||
* tasklets) or user context from ath5k_beacon_config.
|
||||
* This is called from software irq context (beacontq tasklets)
|
||||
* or user context from ath5k_beacon_config.
|
||||
*/
|
||||
static void
|
||||
ath5k_beacon_send(struct ath5k_softc *sc)
|
||||
@ -2328,7 +2327,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
|
||||
sc->bmisscount);
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
|
||||
"stuck beacon, resetting\n");
|
||||
tasklet_schedule(&sc->restq);
|
||||
ieee80211_queue_work(sc->hw, &sc->reset_work);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -2632,12 +2631,20 @@ ath5k_stop_locked(struct ath5k_softc *sc)
|
||||
if (!test_bit(ATH_STAT_INVALID, sc->status)) {
|
||||
ath5k_rx_stop(sc);
|
||||
ath5k_hw_phy_disable(ah);
|
||||
} else
|
||||
sc->rxlink = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stop_tasklets(struct ath5k_softc *sc)
|
||||
{
|
||||
tasklet_kill(&sc->rxtq);
|
||||
tasklet_kill(&sc->txtq);
|
||||
tasklet_kill(&sc->calib);
|
||||
tasklet_kill(&sc->beacontq);
|
||||
tasklet_kill(&sc->ani_tasklet);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop the device, grabbing the top-level lock to protect
|
||||
* against concurrent entry through ath5k_init (which can happen
|
||||
@ -2682,12 +2689,7 @@ ath5k_stop_hw(struct ath5k_softc *sc)
|
||||
mmiowb();
|
||||
mutex_unlock(&sc->lock);
|
||||
|
||||
tasklet_kill(&sc->rxtq);
|
||||
tasklet_kill(&sc->txtq);
|
||||
tasklet_kill(&sc->restq);
|
||||
tasklet_kill(&sc->calib);
|
||||
tasklet_kill(&sc->beacontq);
|
||||
tasklet_kill(&sc->ani_tasklet);
|
||||
stop_tasklets(sc);
|
||||
|
||||
ath5k_rfkill_hw_stop(sc->ah);
|
||||
|
||||
@ -2737,7 +2739,7 @@ ath5k_intr(int irq, void *dev_id)
|
||||
*/
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
|
||||
"fatal int, resetting\n");
|
||||
tasklet_schedule(&sc->restq);
|
||||
ieee80211_queue_work(sc->hw, &sc->reset_work);
|
||||
} else if (unlikely(status & AR5K_INT_RXORN)) {
|
||||
/*
|
||||
* Receive buffers are full. Either the bus is busy or
|
||||
@ -2752,7 +2754,7 @@ ath5k_intr(int irq, void *dev_id)
|
||||
if (ah->ah_mac_srev < AR5K_SREV_AR5212) {
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
|
||||
"rx overrun, resetting\n");
|
||||
tasklet_schedule(&sc->restq);
|
||||
ieee80211_queue_work(sc->hw, &sc->reset_work);
|
||||
}
|
||||
else
|
||||
tasklet_schedule(&sc->rxtq);
|
||||
@ -2766,7 +2768,7 @@ ath5k_intr(int irq, void *dev_id)
|
||||
* RXE bit is written, but it doesn't work at
|
||||
* least on older hardware revs.
|
||||
*/
|
||||
sc->rxlink = NULL;
|
||||
sc->stats.rxeol_intr++;
|
||||
}
|
||||
if (status & AR5K_INT_TXURN) {
|
||||
/* bump tx trigger level */
|
||||
@ -2799,14 +2801,6 @@ ath5k_intr(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_tasklet_reset(unsigned long data)
|
||||
{
|
||||
struct ath5k_softc *sc = (void *)data;
|
||||
|
||||
ath5k_reset(sc, sc->curchan);
|
||||
}
|
||||
|
||||
/*
|
||||
* Periodically recalibrate the PHY to account
|
||||
* for temperature/environment changes.
|
||||
@ -2830,7 +2824,7 @@ ath5k_tasklet_calibrate(unsigned long data)
|
||||
* to load new gain values.
|
||||
*/
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n");
|
||||
ath5k_reset(sc, sc->curchan);
|
||||
ieee80211_queue_work(sc->hw, &sc->reset_work);
|
||||
}
|
||||
if (ath5k_hw_phy_calibrate(ah, sc->curchan))
|
||||
ATH5K_ERR(sc, "calibration of channel %u failed\n",
|
||||
@ -2934,6 +2928,8 @@ drop_packet:
|
||||
/*
|
||||
* Reset the hardware. If chan is not NULL, then also pause rx/tx
|
||||
* and change to the given channel.
|
||||
*
|
||||
* This should be called with sc->lock.
|
||||
*/
|
||||
static int
|
||||
ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
|
||||
@ -2943,8 +2939,11 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
|
||||
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
|
||||
|
||||
ath5k_hw_set_imr(ah, 0);
|
||||
synchronize_irq(sc->pdev->irq);
|
||||
stop_tasklets(sc);
|
||||
|
||||
if (chan) {
|
||||
ath5k_hw_set_imr(ah, 0);
|
||||
ath5k_txq_cleanup(sc);
|
||||
ath5k_rx_stop(sc);
|
||||
|
||||
@ -2990,6 +2989,16 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath5k_reset_work(struct work_struct *work)
|
||||
{
|
||||
struct ath5k_softc *sc = container_of(work, struct ath5k_softc,
|
||||
reset_work);
|
||||
|
||||
mutex_lock(&sc->lock);
|
||||
ath5k_reset(sc, sc->curchan);
|
||||
mutex_unlock(&sc->lock);
|
||||
}
|
||||
|
||||
static int ath5k_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
return ath5k_init(hw->priv);
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/rfkill.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "ath5k.h"
|
||||
#include "debug.h"
|
||||
@ -136,6 +137,7 @@ struct ath5k_statistics {
|
||||
|
||||
unsigned int mib_intr;
|
||||
unsigned int rxorn_intr;
|
||||
unsigned int rxeol_intr;
|
||||
};
|
||||
|
||||
#if CHAN_DEBUG
|
||||
@ -189,7 +191,7 @@ struct ath5k_softc {
|
||||
unsigned int led_pin, /* GPIO pin for driving LED */
|
||||
led_on; /* pin setting for LED on */
|
||||
|
||||
struct tasklet_struct restq; /* reset tasklet */
|
||||
struct work_struct reset_work; /* deferred chip reset */
|
||||
|
||||
unsigned int rxbufsize; /* rx size based on mtu */
|
||||
struct list_head rxbuf; /* receive buffer */
|
||||
|
@ -279,7 +279,7 @@ static ssize_t write_file_reset(struct file *file,
|
||||
{
|
||||
struct ath5k_softc *sc = file->private_data;
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
|
||||
tasklet_schedule(&sc->restq);
|
||||
ieee80211_queue_work(sc->hw, &sc->reset_work);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -85,21 +85,6 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
|
||||
ar9287PciePhy_clkreq_always_on_L1_9287_1_1,
|
||||
ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1),
|
||||
2);
|
||||
} else if (AR_SREV_9287_10_OR_LATER(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_0,
|
||||
ARRAY_SIZE(ar9287Modes_9287_1_0), 6);
|
||||
INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_0,
|
||||
ARRAY_SIZE(ar9287Common_9287_1_0), 2);
|
||||
|
||||
if (ah->config.pcie_clock_req)
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9287PciePhy_clkreq_off_L1_9287_1_0,
|
||||
ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_0), 2);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9287PciePhy_clkreq_always_on_L1_9287_1_0,
|
||||
ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_0),
|
||||
2);
|
||||
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
|
||||
|
||||
|
||||
@ -118,21 +103,6 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
|
||||
ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2),
|
||||
2);
|
||||
}
|
||||
} else if (AR_SREV_9285_10_OR_LATER(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285,
|
||||
ARRAY_SIZE(ar9285Modes_9285), 6);
|
||||
INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285,
|
||||
ARRAY_SIZE(ar9285Common_9285), 2);
|
||||
|
||||
if (ah->config.pcie_clock_req) {
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9285PciePhy_clkreq_off_L1_9285,
|
||||
ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2);
|
||||
} else {
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9285PciePhy_clkreq_always_on_L1_9285,
|
||||
ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2);
|
||||
}
|
||||
} else if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_9280_2), 6);
|
||||
@ -151,11 +121,6 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
|
||||
INIT_INI_ARRAY(&ah->iniModesAdditional,
|
||||
ar9280Modes_fast_clock_9280_2,
|
||||
ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
|
||||
} else if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280,
|
||||
ARRAY_SIZE(ar9280Modes_9280), 6);
|
||||
INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280,
|
||||
ARRAY_SIZE(ar9280Common_9280), 2);
|
||||
} else if (AR_SREV_9160_10_OR_LATER(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
|
||||
ARRAY_SIZE(ar5416Modes_9160), 6);
|
||||
@ -305,10 +270,6 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9287Modes_rx_gain_9287_1_1,
|
||||
ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
|
||||
else if (AR_SREV_9287_10(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9287Modes_rx_gain_9287_1_0,
|
||||
ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_0), 6);
|
||||
else if (AR_SREV_9280_20(ah))
|
||||
ar9280_20_hw_init_rxgain_ini(ah);
|
||||
|
||||
@ -316,10 +277,6 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9287Modes_tx_gain_9287_1_1,
|
||||
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
|
||||
} else if (AR_SREV_9287_10(ah)) {
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9287Modes_tx_gain_9287_1_0,
|
||||
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_0), 6);
|
||||
} else if (AR_SREV_9280_20(ah)) {
|
||||
ar9280_20_hw_init_txgain_ini(ah);
|
||||
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
|
||||
@ -389,29 +346,6 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
|
||||
REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
|
||||
INI_RA(&ah->iniPcieSerdes, i, 1));
|
||||
}
|
||||
} else if (AR_SREV_9280(ah) &&
|
||||
(ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) {
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
|
||||
|
||||
/* RX shut off when elecidle is asserted */
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
|
||||
|
||||
/* Shut off CLKREQ active in L1 */
|
||||
if (ah->config.pcie_clock_req)
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
|
||||
else
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
|
||||
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
|
||||
|
||||
/* Load the new settings */
|
||||
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
|
||||
|
||||
} else {
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -579,12 +579,39 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
|
||||
rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
|
||||
|
||||
if ((rxsp->status11 & AR_RxFrameOK) == 0) {
|
||||
/*
|
||||
* AR_CRCErr will bet set to true if we're on the last
|
||||
* subframe and the AR_PostDelimCRCErr is caught.
|
||||
* In a way this also gives us a guarantee that when
|
||||
* (!(AR_CRCErr) && (AR_PostDelimCRCErr)) we cannot
|
||||
* possibly be reviewing the last subframe. AR_CRCErr
|
||||
* is the CRC of the actual data.
|
||||
*/
|
||||
if (rxsp->status11 & AR_CRCErr) {
|
||||
rxs->rs_status |= ATH9K_RXERR_CRC;
|
||||
} else if (rxsp->status11 & AR_PHYErr) {
|
||||
rxs->rs_status |= ATH9K_RXERR_PHY;
|
||||
phyerr = MS(rxsp->status11, AR_PHYErrCode);
|
||||
rxs->rs_phyerr = phyerr;
|
||||
/*
|
||||
* If we reach a point here where AR_PostDelimCRCErr is
|
||||
* true it implies we're *not* on the last subframe. In
|
||||
* in that case that we know already that the CRC of
|
||||
* the frame was OK, and MAC would send an ACK for that
|
||||
* subframe, even if we did get a phy error of type
|
||||
* ATH9K_PHYERR_OFDM_RESTART. This is only applicable
|
||||
* to frame that are prior to the last subframe.
|
||||
* The AR_PostDelimCRCErr is the CRC for the MPDU
|
||||
* delimiter, which contains the 4 reserved bits,
|
||||
* the MPDU length (12 bits), and follows the MPDU
|
||||
* delimiter for an A-MPDU subframe (0x4E = 'N' ASCII).
|
||||
*/
|
||||
if ((phyerr == ATH9K_PHYERR_OFDM_RESTART) &&
|
||||
(rxsp->status11 & AR_PostDelimCRCErr)) {
|
||||
rxs->rs_phyerr = 0;
|
||||
} else {
|
||||
rxs->rs_status |= ATH9K_RXERR_PHY;
|
||||
rxs->rs_phyerr = phyerr;
|
||||
}
|
||||
|
||||
} else if (rxsp->status11 & AR_DecryptCRCErr) {
|
||||
rxs->rs_status |= ATH9K_RXERR_DECRYPT;
|
||||
} else if (rxsp->status11 & AR_MichaelErr) {
|
||||
|
@ -222,7 +222,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct cal_data_per_freq_4k *pRawDataSet,
|
||||
u8 *bChans, u16 availPiers,
|
||||
u16 tPdGainOverlap, int16_t *pMinCalPower,
|
||||
u16 tPdGainOverlap,
|
||||
u16 *pPdGainBoundaries, u8 *pPDADCValues,
|
||||
u16 numXpdGains)
|
||||
{
|
||||
@ -308,8 +308,6 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
|
||||
}
|
||||
}
|
||||
|
||||
*pMinCalPower = (int16_t)(minPwrT4[0] / 2);
|
||||
|
||||
k = 0;
|
||||
|
||||
for (i = 0; i < numXpdGains; i++) {
|
||||
@ -399,7 +397,6 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
|
||||
static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
|
||||
u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK];
|
||||
u16 numPiers, i, j;
|
||||
int16_t tMinCalPower;
|
||||
u16 numXpdGain, xpdMask;
|
||||
u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
|
||||
u32 reg32, regOffset, regChainOffset;
|
||||
@ -452,7 +449,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
|
||||
ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
|
||||
pRawDataset, pCalBChans,
|
||||
numPiers, pdGainOverlap_t2,
|
||||
&tMinCalPower, gainBoundaries,
|
||||
gainBoundaries,
|
||||
pdadcValues, numXpdGain);
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
@ -223,7 +223,6 @@ static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah,
|
||||
struct cal_data_per_freq_ar9287 *pRawDataSet,
|
||||
u8 *bChans, u16 availPiers,
|
||||
u16 tPdGainOverlap,
|
||||
int16_t *pMinCalPower,
|
||||
u16 *pPdGainBoundaries,
|
||||
u8 *pPDADCValues,
|
||||
u16 numXpdGains)
|
||||
@ -303,7 +302,6 @@ static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah,
|
||||
}
|
||||
}
|
||||
|
||||
*pMinCalPower = (int16_t)(minPwrT4[0] / 2);
|
||||
k = 0;
|
||||
|
||||
for (i = 0; i < numXpdGains; i++) {
|
||||
@ -458,7 +456,6 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
|
||||
u8 pdadcValues[AR9287_NUM_PDADC_VALUES];
|
||||
u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK];
|
||||
u16 numPiers = 0, i, j;
|
||||
int16_t tMinCalPower;
|
||||
u16 numXpdGain, xpdMask;
|
||||
u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0};
|
||||
u32 reg32, regOffset, regChainOffset, regval;
|
||||
@ -530,7 +527,6 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
|
||||
pRawDataset,
|
||||
pCalBChans, numPiers,
|
||||
pdGainOverlap_t2,
|
||||
&tMinCalPower,
|
||||
gainBoundaries,
|
||||
pdadcValues,
|
||||
numXpdGain);
|
||||
|
@ -593,7 +593,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct cal_data_per_freq *pRawDataSet,
|
||||
u8 *bChans, u16 availPiers,
|
||||
u16 tPdGainOverlap, int16_t *pMinCalPower,
|
||||
u16 tPdGainOverlap,
|
||||
u16 *pPdGainBoundaries, u8 *pPDADCValues,
|
||||
u16 numXpdGains)
|
||||
{
|
||||
@ -675,8 +675,6 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
|
||||
}
|
||||
}
|
||||
|
||||
*pMinCalPower = (int16_t)(minPwrT4[0] / 2);
|
||||
|
||||
k = 0;
|
||||
|
||||
for (i = 0; i < numXpdGains; i++) {
|
||||
@ -838,7 +836,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
||||
static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
|
||||
u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
|
||||
u16 numPiers, i, j;
|
||||
int16_t tMinCalPower, diff = 0;
|
||||
int16_t diff = 0;
|
||||
u16 numXpdGain, xpdMask;
|
||||
u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
|
||||
u32 reg32, regOffset, regChainOffset;
|
||||
@ -923,7 +921,6 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
||||
chan, pRawDataset,
|
||||
pCalBChans, numPiers,
|
||||
pdGainOverlap_t2,
|
||||
&tMinCalPower,
|
||||
gainBoundaries,
|
||||
pdadcValues,
|
||||
numXpdGain);
|
||||
|
@ -438,10 +438,11 @@ static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv,
|
||||
bss_conf->bssid, be32_to_cpu(trate.capflags));
|
||||
}
|
||||
|
||||
int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
enum ieee80211_ampdu_mlme_action action, u16 tid)
|
||||
static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
enum ieee80211_ampdu_mlme_action action,
|
||||
u16 tid)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath9k_htc_target_aggr aggr;
|
||||
@ -492,8 +493,7 @@ static int ath9k_debugfs_open(struct inode *inode, struct file *file)
|
||||
static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath9k_htc_priv *priv =
|
||||
(struct ath9k_htc_priv *) file->private_data;
|
||||
struct ath9k_htc_priv *priv = file->private_data;
|
||||
struct ath9k_htc_target_stats cmd_rsp;
|
||||
char buf[512];
|
||||
unsigned int len = 0;
|
||||
@ -536,8 +536,7 @@ static const struct file_operations fops_tgt_stats = {
|
||||
static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath9k_htc_priv *priv =
|
||||
(struct ath9k_htc_priv *) file->private_data;
|
||||
struct ath9k_htc_priv *priv = file->private_data;
|
||||
char buf[512];
|
||||
unsigned int len = 0;
|
||||
|
||||
@ -582,8 +581,7 @@ static const struct file_operations fops_xmit = {
|
||||
static ssize_t read_file_recv(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath9k_htc_priv *priv =
|
||||
(struct ath9k_htc_priv *) file->private_data;
|
||||
struct ath9k_htc_priv *priv = file->private_data;
|
||||
char buf[512];
|
||||
unsigned int len = 0;
|
||||
|
||||
|
@ -787,12 +787,12 @@ void ath9k_deinit_device(struct ath_softc *sc)
|
||||
ieee80211_unregister_hw(aphy->hw);
|
||||
ieee80211_free_hw(aphy->hw);
|
||||
}
|
||||
kfree(sc->sec_wiphy);
|
||||
|
||||
ieee80211_unregister_hw(hw);
|
||||
ath_rx_cleanup(sc);
|
||||
ath_tx_cleanup(sc);
|
||||
ath9k_deinit_softc(sc);
|
||||
kfree(sc->sec_wiphy);
|
||||
}
|
||||
|
||||
void ath_descdma_cleanup(struct ath_softc *sc,
|
||||
|
@ -279,7 +279,7 @@ void ath_paprd_calibrate(struct work_struct *work)
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
ftype = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC;
|
||||
hdr->frame_control = cpu_to_le16(ftype);
|
||||
hdr->duration_id = 10;
|
||||
hdr->duration_id = cpu_to_le16(10);
|
||||
memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN);
|
||||
memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
|
||||
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
|
||||
@ -857,9 +857,14 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
ath9k_ps_wakeup(sc);
|
||||
ieee80211_stop_queues(hw);
|
||||
|
||||
/* Disable LED */
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 1);
|
||||
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
|
||||
/*
|
||||
* Keep the LED on when the radio is disabled
|
||||
* during idle unassociated state.
|
||||
*/
|
||||
if (!sc->ps_idle) {
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 1);
|
||||
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
|
||||
}
|
||||
|
||||
/* Disable interrupts */
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
@ -1264,6 +1269,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int i;
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
@ -1276,7 +1282,12 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
||||
cancel_work_sync(&sc->paprd_work);
|
||||
cancel_work_sync(&sc->hw_check_work);
|
||||
|
||||
if (!sc->num_sec_wiphy) {
|
||||
for (i = 0; i < sc->num_sec_wiphy; i++) {
|
||||
if (sc->sec_wiphy[i])
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == sc->num_sec_wiphy) {
|
||||
cancel_delayed_work_sync(&sc->wiphy_work);
|
||||
cancel_work_sync(&sc->chan_work);
|
||||
}
|
||||
|
@ -329,7 +329,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
|
||||
bool rc_update = true;
|
||||
struct ieee80211_tx_rate rates[4];
|
||||
unsigned long flags;
|
||||
|
||||
skb = bf->bf_mpdu;
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
@ -346,9 +345,21 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
if (!sta) {
|
||||
rcu_read_unlock();
|
||||
|
||||
spin_lock_irqsave(&sc->tx.txbuflock, flags);
|
||||
list_splice_tail_init(bf_q, &sc->tx.txbuf);
|
||||
spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
while (bf) {
|
||||
bf_next = bf->bf_next;
|
||||
|
||||
bf->bf_state.bf_type |= BUF_XRETRY;
|
||||
if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
|
||||
!bf->bf_stale || bf_next != NULL)
|
||||
list_move_tail(&bf->list, &bf_head);
|
||||
|
||||
ath_tx_rc_status(bf, ts, 0, 0, false);
|
||||
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
|
||||
0, 0);
|
||||
|
||||
bf = bf_next;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT;
|
||||
module_param_named(verbose, b43_modparam_verbose, int, 0644);
|
||||
MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug");
|
||||
|
||||
int b43_modparam_pio = B43_PIO_DEFAULT;
|
||||
static int b43_modparam_pio = B43_PIO_DEFAULT;
|
||||
module_param_named(pio, b43_modparam_pio, int, 0644);
|
||||
MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
|
||||
|
||||
|
@ -972,7 +972,7 @@ b43_radio_interference_mitigation_enable(struct b43_wldev *dev, int mode)
|
||||
b43_phy_maskset(dev, 0x04A2, 0xFFF0, 0x000B);
|
||||
|
||||
if (phy->rev >= 3) {
|
||||
b43_phy_mask(dev, 0x048A, (u16)~0x8000);
|
||||
b43_phy_mask(dev, 0x048A, 0x7FFF);
|
||||
b43_phy_maskset(dev, 0x0415, 0x8000, 0x36D8);
|
||||
b43_phy_maskset(dev, 0x0416, 0x8000, 0x36D8);
|
||||
b43_phy_maskset(dev, 0x0417, 0xFE00, 0x016D);
|
||||
|
@ -1145,7 +1145,7 @@ static void lpphy_write_tx_pctl_mode_to_hardware(struct b43_wldev *dev)
|
||||
B43_WARN_ON(1);
|
||||
}
|
||||
b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
|
||||
(u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE, ctl);
|
||||
~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF, ctl);
|
||||
}
|
||||
|
||||
static void lpphy_set_tx_power_control(struct b43_wldev *dev,
|
||||
@ -1522,11 +1522,11 @@ static void lpphy_tx_pctl_init_hw(struct b43_wldev *dev)
|
||||
b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xFF);
|
||||
b43_phy_write(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xA);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
|
||||
(u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE,
|
||||
~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF,
|
||||
B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF);
|
||||
b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xF8FF);
|
||||
b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
|
||||
(u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE,
|
||||
~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF,
|
||||
B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW);
|
||||
|
||||
if (dev->phy.rev < 2) {
|
||||
@ -2698,7 +2698,7 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
|
||||
return B43_TXPWR_RES_DONE;
|
||||
}
|
||||
|
||||
void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on)
|
||||
static void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on)
|
||||
{
|
||||
if (on) {
|
||||
b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xfff8);
|
||||
|
@ -509,7 +509,8 @@ static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
|
||||
b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
|
||||
b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
|
||||
|
||||
b43_phy_maskset(dev, B43_NPHY_RFSEQCA, (u16)~B43_NPHY_RFSEQCA_RXDIS,
|
||||
b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
|
||||
~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
|
||||
((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
|
||||
b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
|
||||
((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT));
|
||||
@ -762,7 +763,7 @@ static void b43_nphy_stop_playback(struct b43_wldev *dev)
|
||||
if (tmp & 0x1)
|
||||
b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP);
|
||||
else if (tmp & 0x2)
|
||||
b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, (u16)~0x8000);
|
||||
b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
|
||||
|
||||
b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004);
|
||||
|
||||
@ -1009,7 +1010,7 @@ static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev)
|
||||
b43_nphy_set_rf_sequence(dev, 5,
|
||||
rfseq_events, rfseq_delays, 3);
|
||||
b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
|
||||
(u16)~B43_NPHY_OVER_DGAIN_CCKDGECV,
|
||||
~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
|
||||
0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
|
||||
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
|
||||
@ -1116,7 +1117,7 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
|
||||
b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
|
||||
|
||||
b43_phy_mask(dev, B43_NPHY_PIL_DW1,
|
||||
(u16)~B43_NPHY_PIL_DW_64QAM);
|
||||
~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
|
||||
b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
|
||||
@ -2455,7 +2456,8 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
|
||||
b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600);
|
||||
|
||||
regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG);
|
||||
b43_phy_mask(dev, B43_NPHY_BBCFG, (u16)~B43_NPHY_BBCFG_RSTRX);
|
||||
b43_phy_mask(dev, B43_NPHY_BBCFG,
|
||||
~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
|
||||
|
||||
tmp = b43_ntab_read(dev, B43_NTAB16(8, 3));
|
||||
regs[5] = tmp;
|
||||
@ -2930,7 +2932,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
|
||||
tmp[5] = b43_phy_read(dev, rfctl[1]);
|
||||
|
||||
b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
|
||||
(u16)~B43_NPHY_RFSEQCA_RXDIS,
|
||||
~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
|
||||
((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
|
||||
b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
|
||||
(1 - i));
|
||||
@ -3291,7 +3293,7 @@ static void b43_nphy_chanspec_setup(struct b43_wldev *dev,
|
||||
b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
|
||||
tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
|
||||
b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
|
||||
b43_phy_mask(dev, B43_PHY_B_BBCFG, (u16)~0xC000);
|
||||
b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF);
|
||||
b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
|
||||
}
|
||||
|
||||
|
@ -382,7 +382,7 @@ static void b43_wa_altagc(struct b43_wldev *dev)
|
||||
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 3, 25);
|
||||
}
|
||||
|
||||
b43_phy_maskset(dev, B43_PHY_CCKSHIFTBITS_WA, (u16)~0xFF00, 0x5700);
|
||||
b43_phy_maskset(dev, B43_PHY_CCKSHIFTBITS_WA, 0x00FF, 0x5700);
|
||||
b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x007F, 0x000F);
|
||||
b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x3F80, 0x2B80);
|
||||
b43_phy_maskset(dev, B43_PHY_ANTWRSETT, 0xF0FF, 0x0300);
|
||||
@ -400,9 +400,9 @@ static void b43_wa_altagc(struct b43_wldev *dev)
|
||||
b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x00FF, 0x0020);
|
||||
b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x3F00, 0x0200);
|
||||
b43_phy_maskset(dev, B43_PHY_OFDM(0x82), ~0x00FF, 0x002E);
|
||||
b43_phy_maskset(dev, B43_PHY_OFDM(0x96), (u16)~0xFF00, 0x1A00);
|
||||
b43_phy_maskset(dev, B43_PHY_OFDM(0x96), 0x00FF, 0x1A00);
|
||||
b43_phy_maskset(dev, B43_PHY_OFDM(0x81), ~0x00FF, 0x0028);
|
||||
b43_phy_maskset(dev, B43_PHY_OFDM(0x81), (u16)~0xFF00, 0x2C00);
|
||||
b43_phy_maskset(dev, B43_PHY_OFDM(0x81), 0x00FF, 0x2C00);
|
||||
if (phy->rev == 1) {
|
||||
b43_phy_write(dev, B43_PHY_PEAK_COUNT, 0x092B);
|
||||
b43_phy_maskset(dev, B43_PHY_OFDM(0x1B), ~0x001E, 0x0002);
|
||||
@ -412,7 +412,7 @@ static void b43_wa_altagc(struct b43_wldev *dev)
|
||||
b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, ~0x000F, 0x0004);
|
||||
if (phy->rev >= 6) {
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0x22), 0x287A);
|
||||
b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, (u16)~0xF000, 0x3000);
|
||||
b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, 0x0FFF, 0x3000);
|
||||
}
|
||||
}
|
||||
b43_phy_maskset(dev, B43_PHY_DIVSRCHIDX, 0x8080, 0x7874);
|
||||
|
@ -174,7 +174,7 @@ that only one external action is invoked at a time.
|
||||
#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver"
|
||||
#define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation"
|
||||
|
||||
struct pm_qos_request_list *ipw2100_pm_qos_req;
|
||||
static struct pm_qos_request_list *ipw2100_pm_qos_req;
|
||||
|
||||
/* Debugging stuff */
|
||||
#ifdef CONFIG_IPW2100_DEBUG
|
||||
|
@ -62,8 +62,8 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
MODULE_AUTHOR(DRV_COPYRIGHT);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
struct cfg80211_ops libipw_config_ops = { };
|
||||
void *libipw_wiphy_privid = &libipw_wiphy_privid;
|
||||
static struct cfg80211_ops libipw_config_ops = { };
|
||||
static void *libipw_wiphy_privid = &libipw_wiphy_privid;
|
||||
|
||||
static int libipw_networks_allocate(struct libipw_device *ieee)
|
||||
{
|
||||
|
@ -411,10 +411,6 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
|
||||
|
||||
/* If a new key was provided, set it up */
|
||||
if (erq->length > 0) {
|
||||
#ifdef CONFIG_LIBIPW_DEBUG
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
#endif
|
||||
|
||||
len = erq->length <= 5 ? 5 : 13;
|
||||
memcpy(sec.keys[key], keybuf, erq->length);
|
||||
if (len > erq->length)
|
||||
|
@ -2286,6 +2286,7 @@ static struct iwl_lib_ops iwl4965_lib = {
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
.general_stats_read = iwl_ucode_general_stats_read,
|
||||
},
|
||||
.recover_from_tx_stall = iwl_bg_monitor_recover,
|
||||
.check_plcp_health = iwl_good_plcp_health,
|
||||
};
|
||||
|
||||
|
@ -811,6 +811,13 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
|
||||
le32_to_cpu(dbg->burst_count),
|
||||
accum_dbg->burst_count,
|
||||
delta_dbg->burst_count, max_dbg->burst_count);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"wait_for_silence_timeout_count:",
|
||||
le32_to_cpu(dbg->wait_for_silence_timeout_cnt),
|
||||
accum_dbg->wait_for_silence_timeout_cnt,
|
||||
delta_dbg->wait_for_silence_timeout_cnt,
|
||||
max_dbg->wait_for_silence_timeout_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"sleep_time:",
|
||||
|
@ -1245,7 +1245,7 @@ struct iwl_txfifo_flush_cmd {
|
||||
__le32 fifo_control;
|
||||
__le16 flush_control;
|
||||
__le16 reserved;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* REPLY_WEP_KEY = 0x20
|
||||
@ -3035,7 +3035,8 @@ struct iwl39_statistics_tx {
|
||||
struct statistics_dbg {
|
||||
__le32 burst_check;
|
||||
__le32 burst_count;
|
||||
__le32 reserved[4];
|
||||
__le32 wait_for_silence_timeout_cnt;
|
||||
__le32 reserved[3];
|
||||
} __packed;
|
||||
|
||||
struct iwl39_statistics_div {
|
||||
@ -3547,7 +3548,7 @@ struct iwl_sensitivity_cmd {
|
||||
struct iwl_enhance_sensitivity_cmd {
|
||||
__le16 control; /* always use "1" */
|
||||
__le16 enhance_table[ENHANCE_HD_TABLE_SIZE]; /* use HD_* as index */
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -1763,6 +1763,15 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (changes & BSS_CHANGED_QOS) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->qos_data.qos_active = bss_conf->qos;
|
||||
iwl_update_qos(priv);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
|
||||
dev_kfree_skb(priv->ibss_beacon);
|
||||
priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
|
||||
@ -2134,15 +2143,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
iwl_set_tx_power(priv, conf->power_level, false);
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_QOS) {
|
||||
bool qos_active = !!(conf->flags & IEEE80211_CONF_QOS);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->qos_data.qos_active = qos_active;
|
||||
iwl_update_qos(priv);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
if (!iwl_is_ready(priv)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
|
||||
goto out;
|
||||
|
@ -1267,7 +1267,7 @@ static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
||||
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
int pos = 0;
|
||||
char buf[128];
|
||||
const size_t bufsz = sizeof(buf);
|
||||
@ -1317,7 +1317,7 @@ static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
||||
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
int len = 0;
|
||||
char buf[20];
|
||||
|
||||
@ -1329,7 +1329,7 @@ static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
||||
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
int len = 0;
|
||||
char buf[20];
|
||||
|
||||
@ -1342,7 +1342,7 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
char *buf;
|
||||
int pos = 0;
|
||||
ssize_t ret = -EFAULT;
|
||||
@ -1404,7 +1404,7 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
||||
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
int pos = 0;
|
||||
char buf[12];
|
||||
const size_t bufsz = sizeof(buf);
|
||||
|
@ -891,7 +891,7 @@ struct cmd_key_material {
|
||||
|
||||
__le16 action;
|
||||
struct MrvlIEtype_keyParamSet param;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
static int lbs_set_key_material(struct lbs_private *priv,
|
||||
int key_type,
|
||||
@ -1395,7 +1395,7 @@ struct cmd_monitor_mode {
|
||||
|
||||
__le16 action;
|
||||
__le16 mode;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
static int lbs_enable_monitor_mode(struct lbs_private *priv, int mode)
|
||||
{
|
||||
@ -1450,7 +1450,7 @@ struct cmd_rssi {
|
||||
__le16 nf;
|
||||
__le16 avg_snr;
|
||||
__le16 avg_nf;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
static int lbs_get_signal(struct lbs_private *priv, s8 *signal, s8 *noise)
|
||||
{
|
||||
|
@ -905,7 +905,7 @@ static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf,
|
||||
|
||||
p = buf;
|
||||
|
||||
d = (struct debug_data *)file->private_data;
|
||||
d = file->private_data;
|
||||
|
||||
for (i = 0; i < num_of_items; i++) {
|
||||
if (d[i].size == 1)
|
||||
@ -944,7 +944,7 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
|
||||
char *p0;
|
||||
char *p1;
|
||||
char *p2;
|
||||
struct debug_data *d = (struct debug_data *)f->private_data;
|
||||
struct debug_data *d = f->private_data;
|
||||
|
||||
pdata = kmalloc(cnt, GFP_KERNEL);
|
||||
if (pdata == NULL)
|
||||
|
@ -398,12 +398,12 @@ struct mrvl_ie_domain_param_set {
|
||||
|
||||
u8 countrycode[COUNTRY_CODE_LEN];
|
||||
struct ieee80211_country_ie_triplet triplet[1];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11d_domain_info {
|
||||
__le16 action;
|
||||
struct mrvl_ie_domain_param_set domain;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
struct lbs_802_11d_domain_reg {
|
||||
/** Country code*/
|
||||
@ -411,7 +411,7 @@ struct lbs_802_11d_domain_reg {
|
||||
/** No. of triplet*/
|
||||
u8 no_triplet;
|
||||
struct ieee80211_country_ie_triplet triplet[MRVDRV_MAX_TRIPLET_802_11D];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Define data structure for CMD_GET_HW_SPEC
|
||||
|
@ -314,13 +314,15 @@ static const struct ieee80211_rate mwl8k_rates_50[] = {
|
||||
#define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */
|
||||
#define MWL8K_CMD_UPDATE_STADB 0x1123
|
||||
|
||||
static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize)
|
||||
static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
|
||||
{
|
||||
u16 command = le16_to_cpu(cmd);
|
||||
|
||||
#define MWL8K_CMDNAME(x) case MWL8K_CMD_##x: do {\
|
||||
snprintf(buf, bufsize, "%s", #x);\
|
||||
return buf;\
|
||||
} while (0)
|
||||
switch (cmd & ~0x8000) {
|
||||
switch (command & ~0x8000) {
|
||||
MWL8K_CMDNAME(CODE_DNLD);
|
||||
MWL8K_CMDNAME(GET_HW_SPEC);
|
||||
MWL8K_CMDNAME(SET_HW_SPEC);
|
||||
@ -1538,7 +1540,7 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
|
||||
unsigned long timeout = 0;
|
||||
u8 buf[32];
|
||||
|
||||
cmd->result = 0xffff;
|
||||
cmd->result = (__force __le16) 0xffff;
|
||||
dma_size = le16_to_cpu(cmd->length);
|
||||
dma_addr = pci_map_single(priv->pdev, cmd, dma_size,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
@ -1842,22 +1844,22 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw)
|
||||
priv->sta_macids_supported = 0x00000000;
|
||||
|
||||
off = le32_to_cpu(cmd->wcbbase0) & 0xffff;
|
||||
iowrite32(cpu_to_le32(priv->txq[0].txd_dma), priv->sram + off);
|
||||
iowrite32(priv->txq[0].txd_dma, priv->sram + off);
|
||||
|
||||
off = le32_to_cpu(cmd->rxwrptr) & 0xffff;
|
||||
iowrite32(cpu_to_le32(priv->rxq[0].rxd_dma), priv->sram + off);
|
||||
iowrite32(priv->rxq[0].rxd_dma, priv->sram + off);
|
||||
|
||||
off = le32_to_cpu(cmd->rxrdptr) & 0xffff;
|
||||
iowrite32(cpu_to_le32(priv->rxq[0].rxd_dma), priv->sram + off);
|
||||
iowrite32(priv->rxq[0].rxd_dma, priv->sram + off);
|
||||
|
||||
off = le32_to_cpu(cmd->wcbbase1) & 0xffff;
|
||||
iowrite32(cpu_to_le32(priv->txq[1].txd_dma), priv->sram + off);
|
||||
iowrite32(priv->txq[1].txd_dma, priv->sram + off);
|
||||
|
||||
off = le32_to_cpu(cmd->wcbbase2) & 0xffff;
|
||||
iowrite32(cpu_to_le32(priv->txq[2].txd_dma), priv->sram + off);
|
||||
iowrite32(priv->txq[2].txd_dma, priv->sram + off);
|
||||
|
||||
off = le32_to_cpu(cmd->wcbbase3) & 0xffff;
|
||||
iowrite32(cpu_to_le32(priv->txq[3].txd_dma), priv->sram + off);
|
||||
iowrite32(priv->txq[3].txd_dma, priv->sram + off);
|
||||
}
|
||||
|
||||
kfree(cmd);
|
||||
@ -3052,7 +3054,7 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw,
|
||||
p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT;
|
||||
p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability);
|
||||
p->ht_support = sta->ht_cap.ht_supported;
|
||||
p->ht_caps = sta->ht_cap.cap;
|
||||
p->ht_caps = cpu_to_le16(sta->ht_cap.cap);
|
||||
p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) |
|
||||
((sta->ht_cap.ampdu_density & 7) << 2);
|
||||
if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
|
||||
|
@ -1502,16 +1502,16 @@ static inline void ezusb_delete(struct ezusb_priv *upriv)
|
||||
ezusb_ctx_complete(list_entry(item,
|
||||
struct request_context, list));
|
||||
|
||||
if (upriv->read_urb->status == -EINPROGRESS)
|
||||
if (upriv->read_urb && upriv->read_urb->status == -EINPROGRESS)
|
||||
printk(KERN_ERR PFX "Some URB in progress\n");
|
||||
|
||||
mutex_unlock(&upriv->mtx);
|
||||
|
||||
kfree(upriv->read_urb->transfer_buffer);
|
||||
if (upriv->bap_buf != NULL)
|
||||
kfree(upriv->bap_buf);
|
||||
if (upriv->read_urb != NULL)
|
||||
if (upriv->read_urb) {
|
||||
kfree(upriv->read_urb->transfer_buffer);
|
||||
usb_free_urb(upriv->read_urb);
|
||||
}
|
||||
kfree(upriv->bap_buf);
|
||||
if (upriv->dev) {
|
||||
struct orinoco_private *priv = ndev_priv(upriv->dev);
|
||||
orinoco_if_del(priv);
|
||||
|
@ -116,7 +116,7 @@ struct rt2x00dump_hdr {
|
||||
|
||||
__le16 chip_rt;
|
||||
__le16 chip_rf;
|
||||
__le32 chip_rev;
|
||||
__le16 chip_rev;
|
||||
|
||||
__le16 type;
|
||||
__u8 queue_index;
|
||||
|
@ -103,6 +103,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
|
||||
{
|
||||
struct rtl8180_priv *priv = dev->priv;
|
||||
unsigned int count = 32;
|
||||
u8 signal;
|
||||
|
||||
while (count--) {
|
||||
struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx];
|
||||
@ -130,10 +131,14 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
|
||||
skb_put(skb, flags & 0xFFF);
|
||||
|
||||
rx_status.antenna = (flags2 >> 15) & 1;
|
||||
/* TODO: improve signal/rssi reporting */
|
||||
rx_status.signal = (flags2 >> 8) & 0x7F;
|
||||
/* XXX: is this correct? */
|
||||
rx_status.rate_idx = (flags >> 20) & 0xF;
|
||||
/* TODO: improve signal/rssi reporting for !rtl8185 */
|
||||
signal = (flags2 >> 17) & 0x7F;
|
||||
if (rx_status.rate_idx > 3)
|
||||
signal = 90 - clamp_t(u8, signal, 25, 90);
|
||||
else
|
||||
signal = 95 - clamp_t(u8, signal, 30, 95);
|
||||
rx_status.signal = signal;
|
||||
rx_status.freq = dev->conf.channel->center_freq;
|
||||
rx_status.band = dev->conf.channel->band;
|
||||
rx_status.mactime = le64_to_cpu(entry->tsft);
|
||||
|
@ -1952,6 +1952,10 @@ int cfg80211_wext_giwap(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct sockaddr *ap_addr, char *extra);
|
||||
|
||||
int cfg80211_wext_siwpmksa(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_point *data, char *extra);
|
||||
|
||||
/*
|
||||
* callbacks for asynchronous cfg80211 methods, notification
|
||||
* functions and BSS handling helpers
|
||||
|
@ -147,6 +147,8 @@ struct ieee80211_low_level_stats {
|
||||
* @BSS_CHANGED_CQM: Connection quality monitor config changed
|
||||
* @BSS_CHANGED_IBSS: IBSS join status changed
|
||||
* @BSS_CHANGED_ARP_FILTER: Hardware ARP filter address list or state changed.
|
||||
* @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note
|
||||
* that it is only ever disabled for station mode.
|
||||
*/
|
||||
enum ieee80211_bss_change {
|
||||
BSS_CHANGED_ASSOC = 1<<0,
|
||||
@ -162,6 +164,7 @@ enum ieee80211_bss_change {
|
||||
BSS_CHANGED_CQM = 1<<10,
|
||||
BSS_CHANGED_IBSS = 1<<11,
|
||||
BSS_CHANGED_ARP_FILTER = 1<<12,
|
||||
BSS_CHANGED_QOS = 1<<13,
|
||||
|
||||
/* when adding here, make sure to change ieee80211_reconfig */
|
||||
};
|
||||
@ -217,6 +220,7 @@ enum ieee80211_bss_change {
|
||||
* filter ARP queries based on the @arp_addr_list, if disabled, the
|
||||
* hardware must not perform any ARP filtering. Note, that the filter will
|
||||
* be enabled also in promiscuous mode.
|
||||
* @qos: This is a QoS-enabled BSS.
|
||||
*/
|
||||
struct ieee80211_bss_conf {
|
||||
const u8 *bssid;
|
||||
@ -240,6 +244,7 @@ struct ieee80211_bss_conf {
|
||||
__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
|
||||
u8 arp_addr_cnt;
|
||||
bool arp_filter_enabled;
|
||||
bool qos;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -620,15 +625,11 @@ struct ieee80211_rx_status {
|
||||
* may turn the device off as much as possible. Typically, this flag will
|
||||
* be set when an interface is set UP but not associated or scanning, but
|
||||
* it can also be unset in that case when monitor interfaces are active.
|
||||
* @IEEE80211_CONF_QOS: Enable 802.11e QoS also know as WMM (Wireless
|
||||
* Multimedia). On some drivers (iwlwifi is one of know) we have
|
||||
* to enable/disable QoS explicitly.
|
||||
*/
|
||||
enum ieee80211_conf_flags {
|
||||
IEEE80211_CONF_MONITOR = (1<<0),
|
||||
IEEE80211_CONF_PS = (1<<1),
|
||||
IEEE80211_CONF_IDLE = (1<<2),
|
||||
IEEE80211_CONF_QOS = (1<<3),
|
||||
};
|
||||
|
||||
|
||||
@ -643,7 +644,6 @@ enum ieee80211_conf_flags {
|
||||
* @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed
|
||||
* @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
|
||||
* @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed
|
||||
* @IEEE80211_CONF_CHANGE_QOS: Quality of service was enabled or disabled
|
||||
*/
|
||||
enum ieee80211_conf_changed {
|
||||
IEEE80211_CONF_CHANGE_SMPS = BIT(1),
|
||||
@ -654,7 +654,6 @@ enum ieee80211_conf_changed {
|
||||
IEEE80211_CONF_CHANGE_CHANNEL = BIT(6),
|
||||
IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7),
|
||||
IEEE80211_CONF_CHANGE_IDLE = BIT(8),
|
||||
IEEE80211_CONF_CHANGE_QOS = BIT(9),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -54,7 +54,6 @@ struct regulatory_request {
|
||||
enum nl80211_reg_initiator initiator;
|
||||
char alpha2[2];
|
||||
bool intersect;
|
||||
u32 country_ie_checksum;
|
||||
enum environment_cap country_ie_env;
|
||||
struct list_head list;
|
||||
};
|
||||
|
@ -1154,10 +1154,6 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* enable WMM or activate new settings */
|
||||
local->hw.conf.flags |= IEEE80211_CONF_QOS;
|
||||
drv_config(local, IEEE80211_CONF_CHANGE_QOS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
|
||||
|
||||
memset(ht_cap, 0, sizeof(*ht_cap));
|
||||
|
||||
if (!ht_cap_ie)
|
||||
if (!ht_cap_ie || !sband->ht_cap.ht_supported)
|
||||
return;
|
||||
|
||||
ht_cap->ht_supported = true;
|
||||
|
@ -43,6 +43,8 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
|
||||
{
|
||||
u16 auth_alg, auth_transaction, status_code;
|
||||
|
||||
lockdep_assert_held(&sdata->u.ibss.mtx);
|
||||
|
||||
if (len < 24 + 6)
|
||||
return;
|
||||
|
||||
@ -78,6 +80,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
||||
u32 bss_change;
|
||||
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
|
||||
|
||||
lockdep_assert_held(&ifibss->mtx);
|
||||
|
||||
/* Reset own TSF to allow time synchronization work. */
|
||||
drv_reset_tsf(local);
|
||||
|
||||
@ -205,6 +209,8 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
||||
int i, j;
|
||||
u16 beacon_int = cbss->beacon_interval;
|
||||
|
||||
lockdep_assert_held(&sdata->u.ibss.mtx);
|
||||
|
||||
if (beacon_int < 10)
|
||||
beacon_int = 10;
|
||||
|
||||
@ -449,6 +455,8 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
|
||||
int active = 0;
|
||||
struct sta_info *sta;
|
||||
|
||||
lockdep_assert_held(&sdata->u.ibss.mtx);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
list_for_each_entry_rcu(sta, &local->sta_list, list) {
|
||||
@ -473,6 +481,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
||||
|
||||
lockdep_assert_held(&ifibss->mtx);
|
||||
|
||||
mod_timer(&ifibss->timer,
|
||||
round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
|
||||
|
||||
@ -505,6 +515,8 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
|
||||
u16 capability;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&ifibss->mtx);
|
||||
|
||||
if (ifibss->fixed_bssid) {
|
||||
memcpy(bssid, ifibss->bssid, ETH_ALEN);
|
||||
} else {
|
||||
@ -549,6 +561,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
|
||||
int active_ibss;
|
||||
u16 capability;
|
||||
|
||||
lockdep_assert_held(&ifibss->mtx);
|
||||
|
||||
active_ibss = ieee80211_sta_active_ibss(sdata);
|
||||
#ifdef CONFIG_MAC80211_IBSS_DEBUG
|
||||
printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
|
||||
@ -637,6 +651,8 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_mgmt *resp;
|
||||
u8 *pos, *end;
|
||||
|
||||
lockdep_assert_held(&ifibss->mtx);
|
||||
|
||||
if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
|
||||
len < 24 + 2 || !ifibss->presp)
|
||||
return;
|
||||
@ -740,6 +756,8 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
||||
mgmt = (struct ieee80211_mgmt *) skb->data;
|
||||
fc = le16_to_cpu(mgmt->frame_control);
|
||||
|
||||
mutex_lock(&sdata->u.ibss.mtx);
|
||||
|
||||
switch (fc & IEEE80211_FCTL_STYPE) {
|
||||
case IEEE80211_STYPE_PROBE_REQ:
|
||||
ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len);
|
||||
@ -756,14 +774,23 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&sdata->u.ibss.mtx);
|
||||
}
|
||||
|
||||
void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
||||
|
||||
if (!test_and_clear_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request))
|
||||
return;
|
||||
mutex_lock(&ifibss->mtx);
|
||||
|
||||
/*
|
||||
* Work could be scheduled after scan or similar
|
||||
* when we aren't even joined (or trying) with a
|
||||
* network.
|
||||
*/
|
||||
if (!ifibss->ssid_len)
|
||||
goto out;
|
||||
|
||||
switch (ifibss->state) {
|
||||
case IEEE80211_IBSS_MLME_SEARCH:
|
||||
@ -776,15 +803,9 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
|
||||
WARN_ON(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ieee80211_queue_ibss_work(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
|
||||
ieee80211_queue_work(&local->hw, &sdata->work);
|
||||
out:
|
||||
mutex_unlock(&ifibss->mtx);
|
||||
}
|
||||
|
||||
static void ieee80211_ibss_timer(unsigned long data)
|
||||
@ -799,7 +820,7 @@ static void ieee80211_ibss_timer(unsigned long data)
|
||||
return;
|
||||
}
|
||||
|
||||
ieee80211_queue_ibss_work(sdata);
|
||||
ieee80211_queue_work(&local->hw, &sdata->work);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@ -828,6 +849,7 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
|
||||
|
||||
setup_timer(&ifibss->timer, ieee80211_ibss_timer,
|
||||
(unsigned long) sdata);
|
||||
mutex_init(&ifibss->mtx);
|
||||
}
|
||||
|
||||
/* scan finished notification */
|
||||
@ -841,10 +863,8 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
|
||||
continue;
|
||||
if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
|
||||
continue;
|
||||
if (!sdata->u.ibss.ssid_len)
|
||||
continue;
|
||||
sdata->u.ibss.last_scan_completed = jiffies;
|
||||
ieee80211_queue_ibss_work(sdata);
|
||||
ieee80211_queue_work(&local->hw, &sdata->work);
|
||||
}
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
}
|
||||
@ -854,6 +874,17 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
|
||||
36 /* bitrates */ +
|
||||
34 /* SSID */ +
|
||||
3 /* DS params */ +
|
||||
4 /* IBSS params */ +
|
||||
params->ie_len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&sdata->u.ibss.mtx);
|
||||
|
||||
if (params->bssid) {
|
||||
memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
|
||||
sdata->u.ibss.fixed_bssid = true;
|
||||
@ -882,35 +913,19 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
|
||||
sdata->u.ibss.ie_len = params->ie_len;
|
||||
}
|
||||
|
||||
skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
|
||||
36 /* bitrates */ +
|
||||
34 /* SSID */ +
|
||||
3 /* DS params */ +
|
||||
4 /* IBSS params */ +
|
||||
params->ie_len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
sdata->u.ibss.skb = skb;
|
||||
sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
|
||||
sdata->u.ibss.ibss_join_req = jiffies;
|
||||
|
||||
memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
|
||||
|
||||
/*
|
||||
* The ssid_len setting below is used to see whether
|
||||
* we are active, and we need all other settings
|
||||
* before that may get visible.
|
||||
*/
|
||||
mb();
|
||||
|
||||
sdata->u.ibss.ssid_len = params->ssid_len;
|
||||
|
||||
ieee80211_recalc_idle(sdata->local);
|
||||
|
||||
set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
|
||||
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
|
||||
|
||||
mutex_unlock(&sdata->u.ibss.mtx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -921,7 +936,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct cfg80211_bss *cbss;
|
||||
u16 capability;
|
||||
int active_ibss = 0;
|
||||
int active_ibss;
|
||||
|
||||
mutex_lock(&sdata->u.ibss.mtx);
|
||||
|
||||
active_ibss = ieee80211_sta_active_ibss(sdata);
|
||||
|
||||
@ -943,11 +960,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
|
||||
}
|
||||
}
|
||||
|
||||
del_timer_sync(&sdata->u.ibss.timer);
|
||||
clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
|
||||
cancel_work_sync(&sdata->work);
|
||||
clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
|
||||
|
||||
sta_info_flush(sdata->local, sdata);
|
||||
|
||||
/* remove beacon */
|
||||
@ -964,6 +976,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
|
||||
memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
|
||||
sdata->u.ibss.ssid_len = 0;
|
||||
|
||||
del_timer_sync(&sdata->u.ibss.timer);
|
||||
|
||||
mutex_unlock(&sdata->u.ibss.mtx);
|
||||
|
||||
ieee80211_recalc_idle(sdata->local);
|
||||
|
||||
return 0;
|
||||
|
@ -377,14 +377,11 @@ struct ieee80211_if_managed {
|
||||
int last_cqm_event_signal;
|
||||
};
|
||||
|
||||
enum ieee80211_ibss_request {
|
||||
IEEE80211_IBSS_REQ_RUN = 0,
|
||||
};
|
||||
|
||||
struct ieee80211_if_ibss {
|
||||
struct timer_list timer;
|
||||
|
||||
unsigned long request;
|
||||
struct mutex mtx;
|
||||
|
||||
unsigned long last_scan_completed;
|
||||
|
||||
u32 basic_rates;
|
||||
|
@ -249,6 +249,8 @@ static int ieee80211_open(struct net_device *dev)
|
||||
local->fif_other_bss++;
|
||||
|
||||
ieee80211_configure_filter(local);
|
||||
|
||||
netif_carrier_on(dev);
|
||||
break;
|
||||
default:
|
||||
res = drv_add_interface(local, &sdata->vif);
|
||||
@ -741,7 +743,7 @@ static void ieee80211_iface_work(struct work_struct *work)
|
||||
int len = skb->len;
|
||||
|
||||
mutex_lock(&local->sta_mtx);
|
||||
sta = sta_info_get(sdata, mgmt->sa);
|
||||
sta = sta_info_get_bss(sdata, mgmt->sa);
|
||||
if (sta) {
|
||||
switch (mgmt->u.action.u.addba_req.action_code) {
|
||||
case WLAN_ACTION_ADDBA_REQ:
|
||||
@ -782,7 +784,7 @@ static void ieee80211_iface_work(struct work_struct *work)
|
||||
* right, so terminate the session.
|
||||
*/
|
||||
mutex_lock(&local->sta_mtx);
|
||||
sta = sta_info_get(sdata, mgmt->sa);
|
||||
sta = sta_info_get_bss(sdata, mgmt->sa);
|
||||
if (sta) {
|
||||
u16 tid = *ieee80211_get_qos_ctl(hdr) &
|
||||
IEEE80211_QOS_CTL_TID_MASK;
|
||||
|
@ -698,10 +698,11 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
|
||||
|
||||
/* MLME */
|
||||
static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
|
||||
struct ieee80211_if_managed *ifmgd,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
u8 *wmm_param, size_t wmm_param_len)
|
||||
{
|
||||
struct ieee80211_tx_queue_params params;
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
size_t left;
|
||||
int count;
|
||||
u8 *pos, uapsd_queues = 0;
|
||||
@ -790,8 +791,8 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
|
||||
}
|
||||
|
||||
/* enable WMM or activate new settings */
|
||||
local->hw.conf.flags |= IEEE80211_CONF_QOS;
|
||||
drv_config(local, IEEE80211_CONF_CHANGE_QOS);
|
||||
sdata->vif.bss_conf.qos = true;
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
|
||||
}
|
||||
|
||||
static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
|
||||
@ -1325,7 +1326,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
|
||||
}
|
||||
|
||||
if (elems.wmm_param)
|
||||
ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
|
||||
ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
|
||||
elems.wmm_param_len);
|
||||
else
|
||||
ieee80211_set_wmm_default(sdata);
|
||||
@ -1597,7 +1598,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems,
|
||||
true);
|
||||
|
||||
ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
|
||||
ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
|
||||
elems.wmm_param_len);
|
||||
}
|
||||
|
||||
@ -2030,6 +2031,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
|
||||
auth_alg = WLAN_AUTH_OPEN;
|
||||
break;
|
||||
case NL80211_AUTHTYPE_SHARED_KEY:
|
||||
if (IS_ERR(sdata->local->wep_tx_tfm))
|
||||
return -EOPNOTSUPP;
|
||||
auth_alg = WLAN_AUTH_SHARED_KEY;
|
||||
break;
|
||||
case NL80211_AUTHTYPE_FT:
|
||||
|
@ -803,8 +803,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
|
||||
|
||||
/* after reinitialize QoS TX queues setting to default,
|
||||
* disable QoS at all */
|
||||
local->hw.conf.flags &= ~IEEE80211_CONF_QOS;
|
||||
drv_config(local, IEEE80211_CONF_CHANGE_QOS);
|
||||
sdata->vif.bss_conf.qos = sdata->vif.type != NL80211_IFTYPE_STATION;
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
|
||||
}
|
||||
|
||||
void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
|
||||
@ -1161,7 +1161,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
BSS_CHANGED_BASIC_RATES |
|
||||
BSS_CHANGED_BEACON_INT |
|
||||
BSS_CHANGED_BSSID |
|
||||
BSS_CHANGED_CQM;
|
||||
BSS_CHANGED_CQM |
|
||||
BSS_CHANGED_QOS;
|
||||
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
|
@ -32,13 +32,16 @@ int ieee80211_wep_init(struct ieee80211_local *local)
|
||||
|
||||
local->wep_tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0,
|
||||
CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(local->wep_tx_tfm))
|
||||
if (IS_ERR(local->wep_tx_tfm)) {
|
||||
local->wep_rx_tfm = ERR_PTR(-EINVAL);
|
||||
return PTR_ERR(local->wep_tx_tfm);
|
||||
}
|
||||
|
||||
local->wep_rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0,
|
||||
CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(local->wep_rx_tfm)) {
|
||||
crypto_free_blkcipher(local->wep_tx_tfm);
|
||||
local->wep_tx_tfm = ERR_PTR(-EINVAL);
|
||||
return PTR_ERR(local->wep_rx_tfm);
|
||||
}
|
||||
|
||||
|
@ -472,24 +472,22 @@ int wiphy_register(struct wiphy *wiphy)
|
||||
/* check and set up bitrates */
|
||||
ieee80211_set_bitrate_flags(wiphy);
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
res = device_add(&rdev->wiphy.dev);
|
||||
if (res)
|
||||
return res;
|
||||
goto out_unlock;
|
||||
|
||||
res = rfkill_register(rdev->rfkill);
|
||||
if (res)
|
||||
goto out_rm_dev;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
/* set up regulatory info */
|
||||
wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
|
||||
|
||||
list_add_rcu(&rdev->list, &cfg80211_rdev_list);
|
||||
cfg80211_rdev_list_generation++;
|
||||
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
/* add to debugfs */
|
||||
rdev->wiphy.debugfsdir =
|
||||
debugfs_create_dir(wiphy_name(&rdev->wiphy),
|
||||
@ -509,11 +507,15 @@ int wiphy_register(struct wiphy *wiphy)
|
||||
}
|
||||
|
||||
cfg80211_debugfs_rdev_add(rdev);
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
out_rm_dev:
|
||||
out_rm_dev:
|
||||
device_del(&rdev->wiphy.dev);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_register);
|
||||
|
@ -21,6 +21,7 @@ BEGIN {
|
||||
print ""
|
||||
print "#include <linux/nl80211.h>"
|
||||
print "#include <net/cfg80211.h>"
|
||||
print "#include \"regdb.h\""
|
||||
print ""
|
||||
regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n"
|
||||
}
|
||||
|
@ -578,7 +578,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
|
||||
}
|
||||
|
||||
if (ieee80211_is_data_qos(hdr11->frame_control)) {
|
||||
hdr[12] = le16_to_cpu(*ieee80211_get_qos_ctl(hdr11))
|
||||
hdr[12] = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(hdr11)))
|
||||
& IEEE80211_QOS_CTL_TID_MASK;
|
||||
} else
|
||||
hdr[12] = 0; /* priority */
|
||||
|
@ -66,18 +66,10 @@ static struct platform_device *reg_pdev;
|
||||
*/
|
||||
const struct ieee80211_regdomain *cfg80211_regdomain;
|
||||
|
||||
/*
|
||||
* We use this as a place for the rd structure built from the
|
||||
* last parsed country IE to rest until CRDA gets back to us with
|
||||
* what it thinks should apply for the same country
|
||||
*/
|
||||
static const struct ieee80211_regdomain *country_ie_regdomain;
|
||||
|
||||
/*
|
||||
* Protects static reg.c components:
|
||||
* - cfg80211_world_regdom
|
||||
* - cfg80211_regdom
|
||||
* - country_ie_regdomain
|
||||
* - last_request
|
||||
*/
|
||||
static DEFINE_MUTEX(reg_mutex);
|
||||
@ -275,25 +267,6 @@ static bool is_user_regdom_saved(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* country_ie_integrity_changes - tells us if the country IE has changed
|
||||
* @checksum: checksum of country IE of fields we are interested in
|
||||
*
|
||||
* If the country IE has not changed you can ignore it safely. This is
|
||||
* useful to determine if two devices are seeing two different country IEs
|
||||
* even on the same alpha2. Note that this will return false if no IE has
|
||||
* been set on the wireless core yet.
|
||||
*/
|
||||
static bool country_ie_integrity_changes(u32 checksum)
|
||||
{
|
||||
/* If no IE has been set then the checksum doesn't change */
|
||||
if (unlikely(!last_request->country_ie_checksum))
|
||||
return false;
|
||||
if (unlikely(last_request->country_ie_checksum != checksum))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd,
|
||||
const struct ieee80211_regdomain *src_regd)
|
||||
{
|
||||
@ -505,471 +478,6 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
|
||||
#undef ONE_GHZ_IN_KHZ
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a work around for sanity checking ieee80211_channel_to_frequency()'s
|
||||
* work. ieee80211_channel_to_frequency() can for example currently provide a
|
||||
* 2 GHz channel when in fact a 5 GHz channel was desired. An example would be
|
||||
* an AP providing channel 8 on a country IE triplet when it sent this on the
|
||||
* 5 GHz band, that channel is designed to be channel 8 on 5 GHz, not a 2 GHz
|
||||
* channel.
|
||||
*
|
||||
* This can be removed once ieee80211_channel_to_frequency() takes in a band.
|
||||
*/
|
||||
static bool chan_in_band(int chan, enum ieee80211_band band)
|
||||
{
|
||||
int center_freq = ieee80211_channel_to_frequency(chan);
|
||||
|
||||
switch (band) {
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
if (center_freq <= 2484)
|
||||
return true;
|
||||
return false;
|
||||
case IEEE80211_BAND_5GHZ:
|
||||
if (center_freq >= 5005)
|
||||
return true;
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some APs may send a country IE triplet for each channel they
|
||||
* support and while this is completely overkill and silly we still
|
||||
* need to support it. We avoid making a single rule for each channel
|
||||
* though and to help us with this we use this helper to find the
|
||||
* actual subband end channel. These type of country IE triplet
|
||||
* scenerios are handled then, all yielding two regulaotry rules from
|
||||
* parsing a country IE:
|
||||
*
|
||||
* [1]
|
||||
* [2]
|
||||
* [36]
|
||||
* [40]
|
||||
*
|
||||
* [1]
|
||||
* [2-4]
|
||||
* [5-12]
|
||||
* [36]
|
||||
* [40-44]
|
||||
*
|
||||
* [1-4]
|
||||
* [5-7]
|
||||
* [36-44]
|
||||
* [48-64]
|
||||
*
|
||||
* [36-36]
|
||||
* [40-40]
|
||||
* [44-44]
|
||||
* [48-48]
|
||||
* [52-52]
|
||||
* [56-56]
|
||||
* [60-60]
|
||||
* [64-64]
|
||||
* [100-100]
|
||||
* [104-104]
|
||||
* [108-108]
|
||||
* [112-112]
|
||||
* [116-116]
|
||||
* [120-120]
|
||||
* [124-124]
|
||||
* [128-128]
|
||||
* [132-132]
|
||||
* [136-136]
|
||||
* [140-140]
|
||||
*
|
||||
* Returns 0 if the IE has been found to be invalid in the middle
|
||||
* somewhere.
|
||||
*/
|
||||
static int max_subband_chan(enum ieee80211_band band,
|
||||
int orig_cur_chan,
|
||||
int orig_end_channel,
|
||||
s8 orig_max_power,
|
||||
u8 **country_ie,
|
||||
u8 *country_ie_len)
|
||||
{
|
||||
u8 *triplets_start = *country_ie;
|
||||
u8 len_at_triplet = *country_ie_len;
|
||||
int end_subband_chan = orig_end_channel;
|
||||
|
||||
/*
|
||||
* We'll deal with padding for the caller unless
|
||||
* its not immediate and we don't process any channels
|
||||
*/
|
||||
if (*country_ie_len == 1) {
|
||||
*country_ie += 1;
|
||||
*country_ie_len -= 1;
|
||||
return orig_end_channel;
|
||||
}
|
||||
|
||||
/* Move to the next triplet and then start search */
|
||||
*country_ie += 3;
|
||||
*country_ie_len -= 3;
|
||||
|
||||
if (!chan_in_band(orig_cur_chan, band))
|
||||
return 0;
|
||||
|
||||
while (*country_ie_len >= 3) {
|
||||
int end_channel = 0;
|
||||
struct ieee80211_country_ie_triplet *triplet =
|
||||
(struct ieee80211_country_ie_triplet *) *country_ie;
|
||||
int cur_channel = 0, next_expected_chan;
|
||||
|
||||
/* means last triplet is completely unrelated to this one */
|
||||
if (triplet->ext.reg_extension_id >=
|
||||
IEEE80211_COUNTRY_EXTENSION_ID) {
|
||||
*country_ie -= 3;
|
||||
*country_ie_len += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
if (triplet->chans.first_channel == 0) {
|
||||
*country_ie += 1;
|
||||
*country_ie_len -= 1;
|
||||
if (*country_ie_len != 0)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (triplet->chans.num_channels == 0)
|
||||
return 0;
|
||||
|
||||
/* Monitonically increasing channel order */
|
||||
if (triplet->chans.first_channel <= end_subband_chan)
|
||||
return 0;
|
||||
|
||||
if (!chan_in_band(triplet->chans.first_channel, band))
|
||||
return 0;
|
||||
|
||||
/* 2 GHz */
|
||||
if (triplet->chans.first_channel <= 14) {
|
||||
end_channel = triplet->chans.first_channel +
|
||||
triplet->chans.num_channels - 1;
|
||||
}
|
||||
else {
|
||||
end_channel = triplet->chans.first_channel +
|
||||
(4 * (triplet->chans.num_channels - 1));
|
||||
}
|
||||
|
||||
if (!chan_in_band(end_channel, band))
|
||||
return 0;
|
||||
|
||||
if (orig_max_power != triplet->chans.max_power) {
|
||||
*country_ie -= 3;
|
||||
*country_ie_len += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
cur_channel = triplet->chans.first_channel;
|
||||
|
||||
/* The key is finding the right next expected channel */
|
||||
if (band == IEEE80211_BAND_2GHZ)
|
||||
next_expected_chan = end_subband_chan + 1;
|
||||
else
|
||||
next_expected_chan = end_subband_chan + 4;
|
||||
|
||||
if (cur_channel != next_expected_chan) {
|
||||
*country_ie -= 3;
|
||||
*country_ie_len += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
end_subband_chan = end_channel;
|
||||
|
||||
/* Move to the next one */
|
||||
*country_ie += 3;
|
||||
*country_ie_len -= 3;
|
||||
|
||||
/*
|
||||
* Padding needs to be dealt with if we processed
|
||||
* some channels.
|
||||
*/
|
||||
if (*country_ie_len == 1) {
|
||||
*country_ie += 1;
|
||||
*country_ie_len -= 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If seen, the IE is invalid */
|
||||
if (*country_ie_len == 2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (end_subband_chan == orig_end_channel) {
|
||||
*country_ie = triplets_start;
|
||||
*country_ie_len = len_at_triplet;
|
||||
return orig_end_channel;
|
||||
}
|
||||
|
||||
return end_subband_chan;
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts a country IE to a regulatory domain. A regulatory domain
|
||||
* structure has a lot of information which the IE doesn't yet have,
|
||||
* so for the other values we use upper max values as we will intersect
|
||||
* with our userspace regulatory agent to get lower bounds.
|
||||
*/
|
||||
static struct ieee80211_regdomain *country_ie_2_rd(
|
||||
enum ieee80211_band band,
|
||||
u8 *country_ie,
|
||||
u8 country_ie_len,
|
||||
u32 *checksum)
|
||||
{
|
||||
struct ieee80211_regdomain *rd = NULL;
|
||||
unsigned int i = 0;
|
||||
char alpha2[2];
|
||||
u32 flags = 0;
|
||||
u32 num_rules = 0, size_of_regd = 0;
|
||||
u8 *triplets_start = NULL;
|
||||
u8 len_at_triplet = 0;
|
||||
/* the last channel we have registered in a subband (triplet) */
|
||||
int last_sub_max_channel = 0;
|
||||
|
||||
*checksum = 0xDEADBEEF;
|
||||
|
||||
/* Country IE requirements */
|
||||
BUG_ON(country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN ||
|
||||
country_ie_len & 0x01);
|
||||
|
||||
alpha2[0] = country_ie[0];
|
||||
alpha2[1] = country_ie[1];
|
||||
|
||||
/*
|
||||
* Third octet can be:
|
||||
* 'I' - Indoor
|
||||
* 'O' - Outdoor
|
||||
*
|
||||
* anything else we assume is no restrictions
|
||||
*/
|
||||
if (country_ie[2] == 'I')
|
||||
flags = NL80211_RRF_NO_OUTDOOR;
|
||||
else if (country_ie[2] == 'O')
|
||||
flags = NL80211_RRF_NO_INDOOR;
|
||||
|
||||
country_ie += 3;
|
||||
country_ie_len -= 3;
|
||||
|
||||
triplets_start = country_ie;
|
||||
len_at_triplet = country_ie_len;
|
||||
|
||||
*checksum ^= ((flags ^ alpha2[0] ^ alpha2[1]) << 8);
|
||||
|
||||
/*
|
||||
* We need to build a reg rule for each triplet, but first we must
|
||||
* calculate the number of reg rules we will need. We will need one
|
||||
* for each channel subband
|
||||
*/
|
||||
while (country_ie_len >= 3) {
|
||||
int end_channel = 0;
|
||||
struct ieee80211_country_ie_triplet *triplet =
|
||||
(struct ieee80211_country_ie_triplet *) country_ie;
|
||||
int cur_sub_max_channel = 0, cur_channel = 0;
|
||||
|
||||
if (triplet->ext.reg_extension_id >=
|
||||
IEEE80211_COUNTRY_EXTENSION_ID) {
|
||||
country_ie += 3;
|
||||
country_ie_len -= 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* APs can add padding to make length divisible
|
||||
* by two, required by the spec.
|
||||
*/
|
||||
if (triplet->chans.first_channel == 0) {
|
||||
country_ie++;
|
||||
country_ie_len--;
|
||||
/* This is expected to be at the very end only */
|
||||
if (country_ie_len != 0)
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (triplet->chans.num_channels == 0)
|
||||
return NULL;
|
||||
|
||||
if (!chan_in_band(triplet->chans.first_channel, band))
|
||||
return NULL;
|
||||
|
||||
/* 2 GHz */
|
||||
if (band == IEEE80211_BAND_2GHZ)
|
||||
end_channel = triplet->chans.first_channel +
|
||||
triplet->chans.num_channels - 1;
|
||||
else
|
||||
/*
|
||||
* 5 GHz -- For example in country IEs if the first
|
||||
* channel given is 36 and the number of channels is 4
|
||||
* then the individual channel numbers defined for the
|
||||
* 5 GHz PHY by these parameters are: 36, 40, 44, and 48
|
||||
* and not 36, 37, 38, 39.
|
||||
*
|
||||
* See: http://tinyurl.com/11d-clarification
|
||||
*/
|
||||
end_channel = triplet->chans.first_channel +
|
||||
(4 * (triplet->chans.num_channels - 1));
|
||||
|
||||
cur_channel = triplet->chans.first_channel;
|
||||
|
||||
/*
|
||||
* Enhancement for APs that send a triplet for every channel
|
||||
* or for whatever reason sends triplets with multiple channels
|
||||
* separated when in fact they should be together.
|
||||
*/
|
||||
end_channel = max_subband_chan(band,
|
||||
cur_channel,
|
||||
end_channel,
|
||||
triplet->chans.max_power,
|
||||
&country_ie,
|
||||
&country_ie_len);
|
||||
if (!end_channel)
|
||||
return NULL;
|
||||
|
||||
if (!chan_in_band(end_channel, band))
|
||||
return NULL;
|
||||
|
||||
cur_sub_max_channel = end_channel;
|
||||
|
||||
/* Basic sanity check */
|
||||
if (cur_sub_max_channel < cur_channel)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Do not allow overlapping channels. Also channels
|
||||
* passed in each subband must be monotonically
|
||||
* increasing
|
||||
*/
|
||||
if (last_sub_max_channel) {
|
||||
if (cur_channel <= last_sub_max_channel)
|
||||
return NULL;
|
||||
if (cur_sub_max_channel <= last_sub_max_channel)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* When dot11RegulatoryClassesRequired is supported
|
||||
* we can throw ext triplets as part of this soup,
|
||||
* for now we don't care when those change as we
|
||||
* don't support them
|
||||
*/
|
||||
*checksum ^= ((cur_channel ^ cur_sub_max_channel) << 8) |
|
||||
((cur_sub_max_channel ^ cur_sub_max_channel) << 16) |
|
||||
((triplet->chans.max_power ^ cur_sub_max_channel) << 24);
|
||||
|
||||
last_sub_max_channel = cur_sub_max_channel;
|
||||
|
||||
num_rules++;
|
||||
|
||||
if (country_ie_len >= 3) {
|
||||
country_ie += 3;
|
||||
country_ie_len -= 3;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: this is not a IEEE requirement but
|
||||
* simply a memory requirement
|
||||
*/
|
||||
if (num_rules > NL80211_MAX_SUPP_REG_RULES)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
country_ie = triplets_start;
|
||||
country_ie_len = len_at_triplet;
|
||||
|
||||
size_of_regd = sizeof(struct ieee80211_regdomain) +
|
||||
(num_rules * sizeof(struct ieee80211_reg_rule));
|
||||
|
||||
rd = kzalloc(size_of_regd, GFP_KERNEL);
|
||||
if (!rd)
|
||||
return NULL;
|
||||
|
||||
rd->n_reg_rules = num_rules;
|
||||
rd->alpha2[0] = alpha2[0];
|
||||
rd->alpha2[1] = alpha2[1];
|
||||
|
||||
/* This time around we fill in the rd */
|
||||
while (country_ie_len >= 3) {
|
||||
int end_channel = 0;
|
||||
struct ieee80211_country_ie_triplet *triplet =
|
||||
(struct ieee80211_country_ie_triplet *) country_ie;
|
||||
struct ieee80211_reg_rule *reg_rule = NULL;
|
||||
struct ieee80211_freq_range *freq_range = NULL;
|
||||
struct ieee80211_power_rule *power_rule = NULL;
|
||||
|
||||
/*
|
||||
* Must parse if dot11RegulatoryClassesRequired is true,
|
||||
* we don't support this yet
|
||||
*/
|
||||
if (triplet->ext.reg_extension_id >=
|
||||
IEEE80211_COUNTRY_EXTENSION_ID) {
|
||||
country_ie += 3;
|
||||
country_ie_len -= 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (triplet->chans.first_channel == 0) {
|
||||
country_ie++;
|
||||
country_ie_len--;
|
||||
break;
|
||||
}
|
||||
|
||||
reg_rule = &rd->reg_rules[i];
|
||||
freq_range = ®_rule->freq_range;
|
||||
power_rule = ®_rule->power_rule;
|
||||
|
||||
reg_rule->flags = flags;
|
||||
|
||||
/* 2 GHz */
|
||||
if (band == IEEE80211_BAND_2GHZ)
|
||||
end_channel = triplet->chans.first_channel +
|
||||
triplet->chans.num_channels -1;
|
||||
else
|
||||
end_channel = triplet->chans.first_channel +
|
||||
(4 * (triplet->chans.num_channels - 1));
|
||||
|
||||
end_channel = max_subband_chan(band,
|
||||
triplet->chans.first_channel,
|
||||
end_channel,
|
||||
triplet->chans.max_power,
|
||||
&country_ie,
|
||||
&country_ie_len);
|
||||
|
||||
/*
|
||||
* The +10 is since the regulatory domain expects
|
||||
* the actual band edge, not the center of freq for
|
||||
* its start and end freqs, assuming 20 MHz bandwidth on
|
||||
* the channels passed
|
||||
*/
|
||||
freq_range->start_freq_khz =
|
||||
MHZ_TO_KHZ(ieee80211_channel_to_frequency(
|
||||
triplet->chans.first_channel) - 10);
|
||||
freq_range->end_freq_khz =
|
||||
MHZ_TO_KHZ(ieee80211_channel_to_frequency(
|
||||
end_channel) + 10);
|
||||
|
||||
/*
|
||||
* These are large arbitrary values we use to intersect later.
|
||||
* Increment this if we ever support >= 40 MHz channels
|
||||
* in IEEE 802.11
|
||||
*/
|
||||
freq_range->max_bandwidth_khz = MHZ_TO_KHZ(40);
|
||||
power_rule->max_antenna_gain = DBI_TO_MBI(100);
|
||||
power_rule->max_eirp = DBM_TO_MBM(triplet->chans.max_power);
|
||||
|
||||
i++;
|
||||
|
||||
if (country_ie_len >= 3) {
|
||||
country_ie += 3;
|
||||
country_ie_len -= 3;
|
||||
}
|
||||
|
||||
BUG_ON(i > NL80211_MAX_SUPP_REG_RULES);
|
||||
}
|
||||
|
||||
return rd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Helper for regdom_intersect(), this does the real
|
||||
* mathematical intersection fun
|
||||
@ -1191,7 +699,6 @@ static int freq_reg_info_regd(struct wiphy *wiphy,
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(freq_reg_info);
|
||||
|
||||
int freq_reg_info(struct wiphy *wiphy,
|
||||
u32 center_freq,
|
||||
@ -1205,6 +712,7 @@ int freq_reg_info(struct wiphy *wiphy,
|
||||
reg_rule,
|
||||
NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(freq_reg_info);
|
||||
|
||||
/*
|
||||
* Note that right now we assume the desired channel bandwidth
|
||||
@ -1243,41 +751,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
|
||||
desired_bw_khz,
|
||||
®_rule);
|
||||
|
||||
if (r) {
|
||||
/*
|
||||
* This means no regulatory rule was found in the country IE
|
||||
* with a frequency range on the center_freq's band, since
|
||||
* IEEE-802.11 allows for a country IE to have a subset of the
|
||||
* regulatory information provided in a country we ignore
|
||||
* disabling the channel unless at least one reg rule was
|
||||
* found on the center_freq's band. For details see this
|
||||
* clarification:
|
||||
*
|
||||
* http://tinyurl.com/11d-clarification
|
||||
*/
|
||||
if (r == -ERANGE &&
|
||||
last_request->initiator ==
|
||||
NL80211_REGDOM_SET_BY_COUNTRY_IE) {
|
||||
REG_DBG_PRINT("cfg80211: Leaving channel %d MHz "
|
||||
"intact on %s - no rule found in band on "
|
||||
"Country IE\n",
|
||||
chan->center_freq, wiphy_name(wiphy));
|
||||
} else {
|
||||
/*
|
||||
* In this case we know the country IE has at least one reg rule
|
||||
* for the band so we respect its band definitions
|
||||
*/
|
||||
if (last_request->initiator ==
|
||||
NL80211_REGDOM_SET_BY_COUNTRY_IE)
|
||||
REG_DBG_PRINT("cfg80211: Disabling "
|
||||
"channel %d MHz on %s due to "
|
||||
"Country IE\n",
|
||||
chan->center_freq, wiphy_name(wiphy));
|
||||
flags |= IEEE80211_CHAN_DISABLED;
|
||||
chan->flags = flags;
|
||||
}
|
||||
if (r)
|
||||
return;
|
||||
}
|
||||
|
||||
power_rule = ®_rule->power_rule;
|
||||
freq_range = ®_rule->freq_range;
|
||||
@ -2008,35 +1483,6 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
|
||||
}
|
||||
EXPORT_SYMBOL(regulatory_hint);
|
||||
|
||||
/* Caller must hold reg_mutex */
|
||||
static bool reg_same_country_ie_hint(struct wiphy *wiphy,
|
||||
u32 country_ie_checksum)
|
||||
{
|
||||
struct wiphy *request_wiphy;
|
||||
|
||||
assert_reg_lock();
|
||||
|
||||
if (unlikely(last_request->initiator !=
|
||||
NL80211_REGDOM_SET_BY_COUNTRY_IE))
|
||||
return false;
|
||||
|
||||
request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
|
||||
|
||||
if (!request_wiphy)
|
||||
return false;
|
||||
|
||||
if (likely(request_wiphy != wiphy))
|
||||
return !country_ie_integrity_changes(country_ie_checksum);
|
||||
/*
|
||||
* We should not have let these through at this point, they
|
||||
* should have been picked up earlier by the first alpha2 check
|
||||
* on the device
|
||||
*/
|
||||
if (WARN_ON(!country_ie_integrity_changes(country_ie_checksum)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* We hold wdev_lock() here so we cannot hold cfg80211_mutex() and
|
||||
* therefore cannot iterate over the rdev list here.
|
||||
@ -2048,7 +1494,6 @@ void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
{
|
||||
struct ieee80211_regdomain *rd = NULL;
|
||||
char alpha2[2];
|
||||
u32 checksum = 0;
|
||||
enum environment_cap env = ENVIRON_ANY;
|
||||
struct regulatory_request *request;
|
||||
|
||||
@ -2064,14 +1509,6 @@ void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Pending country IE processing, this can happen after we
|
||||
* call CRDA and wait for a response if a beacon was received before
|
||||
* we were able to process the last regulatory_hint_11d() call
|
||||
*/
|
||||
if (country_ie_regdomain)
|
||||
goto out;
|
||||
|
||||
alpha2[0] = country_ie[0];
|
||||
alpha2[1] = country_ie[1];
|
||||
|
||||
@ -2090,39 +1527,14 @@ void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
wiphy_idx_valid(last_request->wiphy_idx)))
|
||||
goto out;
|
||||
|
||||
rd = country_ie_2_rd(band, country_ie, country_ie_len, &checksum);
|
||||
if (!rd) {
|
||||
REG_DBG_PRINT("cfg80211: Ignoring bogus country IE\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* This will not happen right now but we leave it here for the
|
||||
* the future when we want to add suspend/resume support and having
|
||||
* the user move to another country after doing so, or having the user
|
||||
* move to another AP. Right now we just trust the first AP.
|
||||
*
|
||||
* If we hit this before we add this support we want to be informed of
|
||||
* it as it would indicate a mistake in the current design
|
||||
*/
|
||||
if (WARN_ON(reg_same_country_ie_hint(wiphy, checksum)))
|
||||
goto free_rd_out;
|
||||
|
||||
request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
|
||||
if (!request)
|
||||
goto free_rd_out;
|
||||
|
||||
/*
|
||||
* We keep this around for when CRDA comes back with a response so
|
||||
* we can intersect with that
|
||||
*/
|
||||
country_ie_regdomain = rd;
|
||||
|
||||
request->wiphy_idx = get_wiphy_idx(wiphy);
|
||||
request->alpha2[0] = rd->alpha2[0];
|
||||
request->alpha2[1] = rd->alpha2[1];
|
||||
request->alpha2[0] = alpha2[0];
|
||||
request->alpha2[1] = alpha2[1];
|
||||
request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE;
|
||||
request->country_ie_checksum = checksum;
|
||||
request->country_ie_env = env;
|
||||
|
||||
mutex_unlock(®_mutex);
|
||||
@ -2383,33 +1795,6 @@ static void print_regdomain_info(const struct ieee80211_regdomain *rd)
|
||||
print_rd_rules(rd);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CFG80211_REG_DEBUG
|
||||
static void reg_country_ie_process_debug(
|
||||
const struct ieee80211_regdomain *rd,
|
||||
const struct ieee80211_regdomain *country_ie_regdomain,
|
||||
const struct ieee80211_regdomain *intersected_rd)
|
||||
{
|
||||
printk(KERN_DEBUG "cfg80211: Received country IE:\n");
|
||||
print_regdomain_info(country_ie_regdomain);
|
||||
printk(KERN_DEBUG "cfg80211: CRDA thinks this should applied:\n");
|
||||
print_regdomain_info(rd);
|
||||
if (intersected_rd) {
|
||||
printk(KERN_DEBUG "cfg80211: We intersect both of these "
|
||||
"and get:\n");
|
||||
print_regdomain_info(intersected_rd);
|
||||
return;
|
||||
}
|
||||
printk(KERN_DEBUG "cfg80211: Intersection between both failed\n");
|
||||
}
|
||||
#else
|
||||
static inline void reg_country_ie_process_debug(
|
||||
const struct ieee80211_regdomain *rd,
|
||||
const struct ieee80211_regdomain *country_ie_regdomain,
|
||||
const struct ieee80211_regdomain *intersected_rd)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Takes ownership of rd only if it doesn't fail */
|
||||
static int __set_regdom(const struct ieee80211_regdomain *rd)
|
||||
{
|
||||
@ -2521,34 +1906,6 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Country IE requests are handled a bit differently, we intersect
|
||||
* the country IE rd with what CRDA believes that country should have
|
||||
*/
|
||||
|
||||
/*
|
||||
* Userspace could have sent two replies with only
|
||||
* one kernel request. By the second reply we would have
|
||||
* already processed and consumed the country_ie_regdomain.
|
||||
*/
|
||||
if (!country_ie_regdomain)
|
||||
return -EALREADY;
|
||||
BUG_ON(rd == country_ie_regdomain);
|
||||
|
||||
/*
|
||||
* Intersect what CRDA returned and our what we
|
||||
* had built from the Country IE received
|
||||
*/
|
||||
|
||||
intersected_rd = regdom_intersect(rd, country_ie_regdomain);
|
||||
|
||||
reg_country_ie_process_debug(rd,
|
||||
country_ie_regdomain,
|
||||
intersected_rd);
|
||||
|
||||
kfree(country_ie_regdomain);
|
||||
country_ie_regdomain = NULL;
|
||||
|
||||
if (!intersected_rd)
|
||||
return -EINVAL;
|
||||
|
||||
@ -2688,9 +2045,6 @@ void /* __init_or_exit */ regulatory_exit(void)
|
||||
|
||||
reset_regdomains();
|
||||
|
||||
kfree(country_ie_regdomain);
|
||||
country_ie_regdomain = NULL;
|
||||
|
||||
kfree(last_request);
|
||||
|
||||
platform_device_unregister(reg_pdev);
|
||||
|
@ -275,6 +275,7 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
|
||||
{
|
||||
struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
|
||||
struct cfg80211_internal_bss *bss, *res = NULL;
|
||||
unsigned long now = jiffies;
|
||||
|
||||
spin_lock_bh(&dev->bss_lock);
|
||||
|
||||
@ -283,6 +284,10 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
|
||||
continue;
|
||||
if (channel && bss->pub.channel != channel)
|
||||
continue;
|
||||
/* Don't get expired BSS structs */
|
||||
if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
|
||||
!atomic_read(&bss->hold))
|
||||
continue;
|
||||
if (is_bss(&bss->pub, bssid, ssid, ssid_len)) {
|
||||
res = bss;
|
||||
kref_get(&res->ref);
|
||||
|
@ -35,7 +35,7 @@ struct cfg80211_conn {
|
||||
bool auto_auth, prev_bssid_valid;
|
||||
};
|
||||
|
||||
bool cfg80211_is_all_idle(void)
|
||||
static bool cfg80211_is_all_idle(void)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wireless_dev *wdev;
|
||||
|
@ -1471,6 +1471,7 @@ int cfg80211_wext_siwpmksa(struct net_device *dev,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cfg80211_wext_siwpmksa);
|
||||
|
||||
static const iw_handler cfg80211_handlers[] = {
|
||||
[IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname,
|
||||
|
Loading…
Reference in New Issue
Block a user