1
0
Fork 0

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6

hifive-unleashed-5.1
David S. Miller 2008-09-25 13:16:16 -07:00
commit db4148da2c
60 changed files with 1077 additions and 1080 deletions

View File

@ -7107,7 +7107,7 @@ static int airo_get_aplist(struct net_device *dev,
*/
static int airo_set_scan(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *vwrq,
struct iw_point *dwrq,
char *extra)
{
struct airo_info *ai = dev->priv;

View File

@ -147,7 +147,7 @@ static int airo_probe(struct pcmcia_device *p_dev)
DEBUG(0, "airo_attach()\n");
/* Interrupt setup */
p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = NULL;

View File

@ -2124,7 +2124,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
udelay(2300);
mdelay(2);
/*
* Set the channel (with AGC turned off)

View File

@ -820,8 +820,6 @@
#define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */
#define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */
#define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */
#define AR5K_RESET_CTL_CHIP (AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA | \
AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY)
/*
* Sleep control register

View File

@ -173,8 +173,10 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
udelay(15);
if (ah->ah_version == AR5K_AR5210) {
val &= AR5K_RESET_CTL_CHIP;
mask &= AR5K_RESET_CTL_CHIP;
val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
| AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
| AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
} else {
val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
@ -361,16 +363,20 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
/* Reset chipset */
ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
AR5K_RESET_CTL_BASEBAND | bus_flags);
if (ah->ah_version == AR5K_AR5210) {
ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
mdelay(2);
} else {
ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
AR5K_RESET_CTL_BASEBAND | bus_flags);
}
if (ret) {
ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
return -EIO;
}
if (ah->ah_version == AR5K_AR5210)
udelay(2300);
/* ...wakeup again!*/
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
if (ret) {

View File

@ -16,7 +16,6 @@
/* Implementation of beacon processing. */
#include <asm/unaligned.h>
#include "core.h"
/*
@ -26,7 +25,6 @@
* the operating mode of the station (AP or AdHoc). Parameters are AIFS
* settings and channel width min/max
*/
static int ath_beaconq_config(struct ath_softc *sc)
{
struct ath_hal *ah = sc->sc_ah;
@ -63,19 +61,18 @@ static int ath_beaconq_config(struct ath_softc *sc)
* up all required antenna switch parameters, rate codes, and channel flags.
* Beacons are always sent out at the lowest rate, and are not retried.
*/
static void ath_beacon_setup(struct ath_softc *sc,
struct ath_vap *avp, struct ath_buf *bf)
struct ath_vap *avp, struct ath_buf *bf)
{
struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
struct ath_hal *ah = sc->sc_ah;
struct ath_desc *ds;
int flags, antenna;
struct ath9k_11n_rate_series series[4];
const struct ath9k_rate_table *rt;
int flags, antenna;
u8 rix, rate;
int ctsrate = 0;
int ctsduration = 0;
struct ath9k_11n_rate_series series[4];
DPRINTF(sc, ATH_DBG_BEACON, "%s: m %p len %u\n",
__func__, skb, skb->len);
@ -115,20 +112,21 @@ static void ath_beacon_setup(struct ath_softc *sc,
rate |= rt->info[rix].shortPreamble;
ath9k_hw_set11n_txdesc(ah, ds,
skb->len + FCS_LEN, /* frame length */
ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */
skb->len + FCS_LEN, /* frame length */
ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */
avp->av_btxctl.txpower, /* txpower XXX */
ATH9K_TXKEYIX_INVALID, /* no encryption */
ATH9K_KEY_TYPE_CLEAR, /* no encryption */
flags /* no ack, veol for beacons */
ATH9K_TXKEYIX_INVALID, /* no encryption */
ATH9K_KEY_TYPE_CLEAR, /* no encryption */
flags /* no ack,
veol for beacons */
);
/* NB: beacon's BufLen must be a multiple of 4 bytes */
ath9k_hw_filltxdesc(ah, ds,
roundup(skb->len, 4), /* buffer length */
true, /* first segment */
true, /* last segment */
ds /* first descriptor */
true, /* first segment */
true, /* last segment */
ds /* first descriptor */
);
memzero(series, sizeof(struct ath9k_11n_rate_series) * 4);
@ -153,22 +151,23 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
struct ath_buf *bf;
struct ath_vap *avp;
struct sk_buff *skb;
int cabq_depth;
struct ath_txq *cabq;
struct ieee80211_tx_info *info;
int cabq_depth;
avp = sc->sc_vaps[if_id];
ASSERT(avp);
cabq = sc->sc_cabq;
ASSERT(avp);
if (avp->av_bcbuf == NULL) {
DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n",
__func__, avp, avp->av_bcbuf);
return NULL;
}
bf = avp->av_bcbuf;
skb = (struct sk_buff *) bf->bf_mpdu;
skb = (struct sk_buff *)bf->bf_mpdu;
if (skb) {
pci_unmap_single(sc->pdev, bf->bf_dmacontext,
skb_end_pointer(skb) - skb->head,
@ -179,17 +178,19 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
bf->bf_mpdu = skb;
if (skb == NULL)
return NULL;
info = IEEE80211_SKB_CB(skb);
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
/*
* TODO: make sure the seq# gets assigned properly (vs. other
* TX frames)
*/
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
sc->seq_no += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
}
bf->bf_buf_addr = bf->bf_dmacontext =
pci_map_single(sc->pdev, skb->data,
skb_end_pointer(skb) - skb->head,
@ -241,7 +242,6 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
* Startup beacon transmission for adhoc mode when they are sent entirely
* by the hardware using the self-linked descriptor + veol trick.
*/
static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
{
struct ath_hal *ah = sc->sc_ah;
@ -278,7 +278,6 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
* min/max, and enable aifs). The info structure does not need to be
* persistant.
*/
int ath_beaconq_setup(struct ath_hal *ah)
{
struct ath9k_tx_queue_info qi;
@ -299,26 +298,24 @@ int ath_beaconq_setup(struct ath_hal *ah)
* the ATH interface. This routine also calculates the beacon "slot" for
* staggared beacons in the mBSSID case.
*/
int ath_beacon_alloc(struct ath_softc *sc, int if_id)
{
struct ath_vap *avp;
struct ieee80211_hdr *wh;
struct ieee80211_hdr *hdr;
struct ath_buf *bf;
struct sk_buff *skb;
__le64 tstamp;
avp = sc->sc_vaps[if_id];
ASSERT(avp);
/* Allocate a beacon descriptor if we haven't done so. */
if (!avp->av_bcbuf) {
/*
* Allocate beacon state for hostap/ibss. We know
* a buffer is available.
*/
/* Allocate beacon state for hostap/ibss. We know
* a buffer is available. */
avp->av_bcbuf = list_first_entry(&sc->sc_bbuf,
struct ath_buf, list);
struct ath_buf, list);
list_del(&avp->av_bcbuf->list);
if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
@ -362,9 +359,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
}
/*
* NB: the beacon data buffer must be 32-bit aligned;
* we assume the wbuf routines will return us something
* with this alignment (perhaps should assert).
* NB: the beacon data buffer must be 32-bit aligned.
* FIXME: Fill avp->av_btxctl.txpower and
* avp->av_btxctl.shortPreamble
*/
@ -375,6 +370,9 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
return -ENOMEM;
}
tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
sc->bc_tstamp = le64_to_cpu(tstamp);
/*
* Calculate a TSF adjustment factor required for
* staggered beacons. Note that we assume the format
@ -408,8 +406,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
__func__, "stagger",
avp->av_bslot, intval, (unsigned long long)tsfadjust);
wh = (struct ieee80211_hdr *)skb->data;
memcpy(&wh[1], &val, sizeof(val));
hdr = (struct ieee80211_hdr *)skb->data;
memcpy(&hdr[1], &val, sizeof(val));
}
bf->bf_buf_addr = bf->bf_dmacontext =
@ -425,9 +423,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
* Reclaim beacon resources and return buffer to the pool.
*
* Checks the VAP to put the beacon frame buffer back to the ATH object
* queue, and de-allocates any wbuf frames that were sent as CAB traffic.
* queue, and de-allocates any skbs that were sent as CAB traffic.
*/
void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
{
if (avp->av_bcbuf != NULL) {
@ -459,10 +456,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
* Transmit one or more beacon frames at SWBA. Dynamic updates to the frame
* contents are done as needed and the slot time is also adjusted based on
* current state.
*
* This tasklet is not scheduled, it's called in ISR context.
*/
void ath9k_beacon_tasklet(unsigned long data)
{
struct ath_softc *sc = (struct ath_softc *)data;
@ -490,6 +484,8 @@ void ath9k_beacon_tasklet(unsigned long data)
* and wait for the next. Missed beacons indicate
* a problem and should not occur. If we miss too
* many consecutive beacons reset the device.
*
* FIXME: Clean up this mess !!
*/
if (ath9k_hw_numtxpending(ah, sc->sc_bhalq) != 0) {
sc->sc_bmisscount++;
@ -505,19 +501,16 @@ void ath9k_beacon_tasklet(unsigned long data)
__func__, sc->sc_bmisscount);
if (show_cycles) {
/*
* Display cycle counter stats
* from HW to aide in debug of
* stickiness.
* Display cycle counter stats from HW
* to aide in debug of stickiness.
*/
DPRINTF(sc,
ATH_DBG_BEACON,
DPRINTF(sc, ATH_DBG_BEACON,
"%s: busy times: rx_clear=%d, "
"rx_frame=%d, tx_frame=%d\n",
__func__, rx_clear, rx_frame,
tx_frame);
} else {
DPRINTF(sc,
ATH_DBG_BEACON,
DPRINTF(sc, ATH_DBG_BEACON,
"%s: unable to obtain "
"busy times\n", __func__);
}
@ -529,8 +522,7 @@ void ath9k_beacon_tasklet(unsigned long data)
} else if (sc->sc_bmisscount >= BSTUCK_THRESH) {
if (sc->sc_flags & SC_OP_NO_RESET) {
if (sc->sc_bmisscount == BSTUCK_THRESH) {
DPRINTF(sc,
ATH_DBG_BEACON,
DPRINTF(sc, ATH_DBG_BEACON,
"%s: beacon is officially "
"stuck\n", __func__);
ath9k_hw_dmaRegDump(ah);
@ -542,13 +534,12 @@ void ath9k_beacon_tasklet(unsigned long data)
ath_bstuck_process(sc);
}
}
return;
}
if (sc->sc_bmisscount != 0) {
if (sc->sc_flags & SC_OP_NO_RESET) {
DPRINTF(sc,
ATH_DBG_BEACON,
DPRINTF(sc, ATH_DBG_BEACON,
"%s: resume beacon xmit after %u misses\n",
__func__, sc->sc_bmisscount);
} else {
@ -572,10 +563,12 @@ void ath9k_beacon_tasklet(unsigned long data)
tsftu = TSF_TO_TU(tsf>>32, tsf);
slot = ((tsftu % intval) * ATH_BCBUF) / intval;
if_id = sc->sc_bslot[(slot + 1) % ATH_BCBUF];
DPRINTF(sc, ATH_DBG_BEACON,
"%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n",
__func__, slot, (unsigned long long) tsf, tsftu,
intval, if_id);
"%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n",
__func__, slot, (unsigned long long)tsf, tsftu,
intval, if_id);
bfaddr = 0;
if (if_id != ATH_IF_ID_ANY) {
bf = ath_beacon_generate(sc, if_id);
@ -632,9 +625,8 @@ void ath9k_beacon_tasklet(unsigned long data)
* Tasklet for Beacon Stuck processing
*
* Processing for Beacon Stuck.
* Basically calls the ath_internal_reset function to reset the chip.
* Basically resets the chip.
*/
void ath_bstuck_process(struct ath_softc *sc)
{
DPRINTF(sc, ATH_DBG_BEACON,
@ -658,13 +650,12 @@ void ath_bstuck_process(struct ath_softc *sc)
* interrupt when we stop seeing beacons from the AP
* we've associated with.
*/
void ath_beacon_config(struct ath_softc *sc, int if_id)
{
struct ath_hal *ah = sc->sc_ah;
u32 nexttbtt, intval;
struct ath_beacon_config conf;
enum ath9k_opmode av_opmode;
u32 nexttbtt, intval;
if (if_id != ATH_IF_ID_ANY)
av_opmode = sc->sc_vaps[if_id]->av_opmode;
@ -673,12 +664,6 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
memzero(&conf, sizeof(struct ath_beacon_config));
/* FIXME: Use default values for now - Sujith */
/* Query beacon configuration first */
/*
* Protocol stack doesn't support dynamic beacon configuration,
* use default configurations.
*/
conf.beacon_interval = sc->hw->conf.beacon_int ?
sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
conf.listen_interval = 1;
@ -687,8 +672,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval;
/* extract tstamp from last beacon and convert to TU */
nexttbtt = TSF_TO_TU(get_unaligned_le32(conf.u.last_tstamp + 4),
get_unaligned_le32(conf.u.last_tstamp));
nexttbtt = TSF_TO_TU(sc->bc_tstamp >> 32, sc->bc_tstamp);
/* XXX conditionalize multi-bss support? */
if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
/*
@ -704,12 +689,14 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
intval = conf.beacon_interval & ATH9K_BEACON_PERIOD;
}
if (nexttbtt == 0) /* e.g. for ap mode */
if (nexttbtt == 0) /* e.g. for ap mode */
nexttbtt = intval;
else if (intval) /* NB: can be 0 for monitor mode */
else if (intval) /* NB: can be 0 for monitor mode */
nexttbtt = roundup(nexttbtt, intval);
DPRINTF(sc, ATH_DBG_BEACON, "%s: nexttbtt %u intval %u (%u)\n",
__func__, nexttbtt, intval, conf.beacon_interval);
/* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */
if (sc->sc_ah->ah_opmode == ATH9K_M_STA) {
struct ath9k_beacon_state bs;
@ -723,19 +710,19 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
* last beacon we received (which may be none).
*/
dtimperiod = conf.dtim_period;
if (dtimperiod <= 0) /* NB: 0 if not known */
if (dtimperiod <= 0) /* NB: 0 if not known */
dtimperiod = 1;
dtimcount = conf.dtim_count;
if (dtimcount >= dtimperiod) /* NB: sanity check */
dtimcount = 0; /* XXX? */
cfpperiod = 1; /* NB: no PCF support yet */
if (dtimcount >= dtimperiod) /* NB: sanity check */
dtimcount = 0;
cfpperiod = 1; /* NB: no PCF support yet */
cfpcount = 0;
sleepduration = conf.listen_interval * intval;
if (sleepduration <= 0)
sleepduration = intval;
#define FUDGE 2
#define FUDGE 2
/*
* Pull nexttbtt forward to reflect the current
* TSF and calculate dtim+cfp state for the result.
@ -759,6 +746,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
bs.bs_cfpmaxduration = 0;
/*
* Calculate the number of consecutive beacons to miss
* before taking a BMISS interrupt. The configuration
@ -767,9 +755,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
* result to at most 15 beacons.
*/
if (sleepduration > intval) {
bs.bs_bmissthreshold =
conf.listen_interval *
ATH_DEFAULT_BMISS_LIMIT / 2;
bs.bs_bmissthreshold = conf.listen_interval *
ATH_DEFAULT_BMISS_LIMIT / 2;
} else {
bs.bs_bmissthreshold =
DIV_ROUND_UP(conf.bmiss_timeout, intval);
@ -789,8 +776,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
* XXX fixed at 100ms
*/
bs.bs_sleepduration =
roundup(IEEE80211_MS_TO_TU(100), sleepduration);
bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100),
sleepduration);
if (bs.bs_sleepduration > bs.bs_dtimperiod)
bs.bs_sleepduration = bs.bs_dtimperiod;
@ -834,9 +821,9 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
/*
* Pull nexttbtt forward to reflect the current
* TSF .
* TSF
*/
#define FUDGE 2
#define FUDGE 2
if (!(intval & ATH9K_BEACON_RESET_TSF)) {
tsf = ath9k_hw_gettsf64(ah);
tsftu = TSF_TO_TU((u32)(tsf>>32),

View File

@ -534,7 +534,8 @@ int ath_vap_attach(struct ath_softc *sc,
avp->av_opmode = opmode;
avp->av_bslot = -1;
ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
if (opmode == ATH9K_M_HOSTAP)
ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
sc->sc_vaps[if_id] = avp;
sc->sc_nvaps++;

View File

@ -1001,6 +1001,7 @@ struct ath_softc {
u32 sc_bhalq;
u32 sc_bmisscount;
u32 ast_be_xmit; /* beacons transmitted */
u64 bc_tstamp;
/* Rate */
struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];

View File

@ -2526,6 +2526,11 @@ static void ath9k_ani_reset(struct ath_hal *ah)
}
}
/*
* Process a MIB interrupt. We may potentially be invoked because
* any of the MIB counters overflow/trigger so don't assume we're
* here because a PHY error counter triggered.
*/
void ath9k_hw_procmibevent(struct ath_hal *ah,
const struct ath9k_node_stats *stats)
{
@ -2533,18 +2538,20 @@ void ath9k_hw_procmibevent(struct ath_hal *ah,
u32 phyCnt1, phyCnt2;
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Processing Mib Intr\n");
/* Reset these counters regardless */
REG_WRITE(ah, AR_FILT_OFDM, 0);
REG_WRITE(ah, AR_FILT_CCK, 0);
if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
/* Clear the mib counters and save them in the stats */
ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
ahp->ah_stats.ast_nodestats = *stats;
if (!DO_ANI(ah))
return;
/* NB: these are not reset-on-read */
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
@ -2552,6 +2559,7 @@ void ath9k_hw_procmibevent(struct ath_hal *ah,
struct ar5416AniState *aniState = ahp->ah_curani;
u32 ofdmPhyErrCnt, cckPhyErrCnt;
/* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
ahp->ah_stats.ast_ani_ofdmerrs +=
ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
@ -2562,11 +2570,17 @@ void ath9k_hw_procmibevent(struct ath_hal *ah,
cckPhyErrCnt - aniState->cckPhyErrCount;
aniState->cckPhyErrCount = cckPhyErrCnt;
/*
* NB: figure out which counter triggered. If both
* trigger we'll only deal with one as the processing
* clobbers the error counter so the trigger threshold
* check will never be true.
*/
if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
ath9k_hw_ani_ofdm_err_trigger(ah);
if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
ath9k_hw_ani_cck_err_trigger(ah);
/* NB: always restart to insure the h/w counters are reset */
ath9k_ani_restart(ah);
}
}

View File

@ -20,6 +20,7 @@
*/
#include "core.h"
/* FIXME: remove this include! */
#include "../net/mac80211/rate.h"
static u32 tx_triglevel_max;
@ -1812,20 +1813,18 @@ static void ath_rc_sib_init(struct ath_rate_node *ath_rc_priv)
}
static void ath_setup_rates(struct ieee80211_local *local, struct sta_info *sta)
static void ath_setup_rates(struct ath_softc *sc,
struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta,
struct ath_rate_node *rc_priv)
{
struct ieee80211_supported_band *sband;
struct ieee80211_hw *hw = local_to_hw(local);
struct ath_softc *sc = hw->priv;
struct ath_rate_node *rc_priv = sta->rate_ctrl_priv;
int i, j = 0;
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
for (i = 0; i < sband->n_bitrates; i++) {
if (sta->sta.supp_rates[local->hw.conf.channel->band] & BIT(i)) {
if (sta->supp_rates[sband->band] & BIT(i)) {
rc_priv->neg_rates.rs_rates[j]
= (sband->bitrates[i].bitrate * 2) / 10;
j++;
@ -1852,19 +1851,17 @@ void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv)
}
/* Rate Control callbacks */
static void ath_tx_status(void *priv, struct net_device *dev,
static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
{
struct ath_softc *sc = priv;
struct ath_tx_info_priv *tx_info_priv;
struct ath_node *an;
struct sta_info *sta;
struct ieee80211_local *local;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr;
__le16 fc;
local = hw_to_local(sc->hw);
hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
@ -1873,8 +1870,7 @@ static void ath_tx_status(void *priv, struct net_device *dev,
an = ath_node_find(sc, hdr->addr1);
spin_unlock_bh(&sc->node_lock);
sta = sta_info_get(local, hdr->addr1);
if (!an || !sta || !ieee80211_is_data(fc)) {
if (!an || !priv_sta || !ieee80211_is_data(fc)) {
if (tx_info->driver_data[0] != NULL) {
kfree(tx_info->driver_data[0]);
tx_info->driver_data[0] = NULL;
@ -1882,24 +1878,22 @@ static void ath_tx_status(void *priv, struct net_device *dev,
return;
}
if (tx_info->driver_data[0] != NULL) {
ath_rate_tx_complete(sc, an, sta->rate_ctrl_priv, tx_info_priv);
ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv);
kfree(tx_info->driver_data[0]);
tx_info->driver_data[0] = NULL;
}
}
static void ath_tx_aggr_resp(struct ath_softc *sc,
struct sta_info *sta,
struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta,
struct ath_node *an,
u8 tidno)
{
struct ieee80211_hw *hw = sc->hw;
struct ieee80211_local *local;
struct ath_atx_tid *txtid;
struct ieee80211_supported_band *sband;
u16 buffersize = 0;
int state;
DECLARE_MAC_BUF(mac);
struct sta_info *si;
if (!(sc->sc_flags & SC_OP_TXAGGR))
return;
@ -1908,11 +1902,16 @@ static void ath_tx_aggr_resp(struct ath_softc *sc,
if (!txtid->paused)
return;
local = hw_to_local(sc->hw);
sband = hw->wiphy->bands[hw->conf.channel->band];
/*
* XXX: This is entirely busted, we aren't supposed to
* access the sta from here because it's internal
* to mac80211, and looking at the state without
* locking is wrong too.
*/
si = container_of(sta, struct sta_info, sta);
buffersize = IEEE80211_MIN_AMPDU_BUF <<
sband->ht_info.ampdu_factor; /* FIXME */
state = sta->ampdu_mlme.tid_state_tx[tidno];
state = si->ampdu_mlme.tid_state_tx[tidno];
if (state & HT_ADDBA_RECEIVED_MSK) {
txtid->addba_exchangecomplete = 1;
@ -1928,18 +1927,15 @@ static void ath_tx_aggr_resp(struct ath_softc *sc,
}
}
static void ath_get_rate(void *priv, struct net_device *dev,
struct ieee80211_supported_band *sband,
struct sk_buff *skb,
struct rate_selection *sel)
static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb, struct rate_selection *sel)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct sta_info *sta;
struct ath_softc *sc = (struct ath_softc *)priv;
struct ath_softc *sc = priv;
struct ieee80211_hw *hw = sc->hw;
struct ath_tx_info_priv *tx_info_priv;
struct ath_rate_node *ath_rc_priv;
struct ath_rate_node *ath_rc_priv = priv_sta;
struct ath_node *an;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
int is_probe = FALSE, chk, ret;
@ -1955,8 +1951,7 @@ static void ath_get_rate(void *priv, struct net_device *dev,
ASSERT(tx_info->driver_data[0] != NULL);
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
sta = sta_info_get(local, hdr->addr1);
lowest_idx = rate_lowest_index(local, sband, sta);
lowest_idx = rate_lowest_index(sband, sta);
tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10;
/* lowest rate for management and multicast/broadcast frames */
if (!ieee80211_is_data(fc) ||
@ -1965,8 +1960,6 @@ static void ath_get_rate(void *priv, struct net_device *dev,
return;
}
ath_rc_priv = sta->rate_ctrl_priv;
/* Find tx rate for unicast frames */
ath_rate_findrate(sc, ath_rc_priv,
ATH_11N_TXMAXTRY, 4,
@ -1975,8 +1968,7 @@ static void ath_get_rate(void *priv, struct net_device *dev,
&is_probe,
false);
if (is_probe)
sel->probe_idx = ((struct ath_tx_ratectrl *)
sta->rate_ctrl_priv)->probe_rate;
sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate;
/* Ratecontrol sometimes returns invalid rate index */
if (tx_info_priv->rcs[0].rix != 0xff)
@ -2020,37 +2012,31 @@ static void ath_get_rate(void *priv, struct net_device *dev,
__func__,
print_mac(mac, hdr->addr1));
} else if (chk == AGGR_EXCHANGE_PROGRESS)
ath_tx_aggr_resp(sc, sta, an, tid);
ath_tx_aggr_resp(sc, sband, sta, an, tid);
}
}
}
static void ath_rate_init(void *priv, void *priv_sta,
struct ieee80211_local *local,
struct sta_info *sta)
static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta)
{
struct ieee80211_supported_band *sband;
struct ieee80211_hw *hw = local_to_hw(local);
struct ieee80211_conf *conf = &local->hw.conf;
struct ath_softc *sc = hw->priv;
struct ath_softc *sc = priv;
struct ath_rate_node *ath_rc_priv = priv_sta;
int i, j = 0;
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
ath_setup_rates(local, sta);
if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
ath_setup_rates(sc, sband, sta, ath_rc_priv);
if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
for (i = 0; i < MCS_SET_SIZE; i++) {
if (conf->ht_conf.supp_mcs_set[i/8] & (1<<(i%8)))
if (sc->hw->conf.ht_conf.supp_mcs_set[i/8] & (1<<(i%8)))
ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
if (j == ATH_RATE_MAX)
break;
}
ath_rc_priv->neg_ht_rates.rs_nrates = j;
}
ath_rc_node_update(hw, priv_sta);
ath_rc_node_update(sc->hw, priv_sta);
}
static void ath_rate_clear(void *priv)
@ -2058,13 +2044,12 @@ static void ath_rate_clear(void *priv)
return;
}
static void *ath_rate_alloc(struct ieee80211_local *local)
static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
{
struct ieee80211_hw *hw = local_to_hw(local);
struct ath_softc *sc = hw->priv;
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
return local->hw.priv;
return hw->priv;
}
static void ath_rate_free(void *priv)
@ -2072,7 +2057,7 @@ static void ath_rate_free(void *priv)
return;
}
static void *ath_rate_alloc_sta(void *priv, gfp_t gfp)
static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
{
struct ath_softc *sc = priv;
struct ath_vap *avp = sc->sc_vaps[0];
@ -2092,7 +2077,8 @@ static void *ath_rate_alloc_sta(void *priv, gfp_t gfp)
return rate_priv;
}
static void ath_rate_free_sta(void *priv, void *priv_sta)
static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
void *priv_sta)
{
struct ath_rate_node *rate_priv = priv_sta;
struct ath_softc *sc = priv;
@ -2111,7 +2097,7 @@ static struct rate_control_ops ath_rate_ops = {
.alloc = ath_rate_alloc,
.free = ath_rate_free,
.alloc_sta = ath_rate_alloc_sta,
.free_sta = ath_rate_free_sta
.free_sta = ath_rate_free_sta,
};
int ath_rate_control_register(void)

View File

@ -2258,7 +2258,7 @@ static int atmel_get_freq(struct net_device *dev,
static int atmel_set_scan(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *vwrq,
struct iw_point *dwrq,
char *extra)
{
struct atmel_private *priv = netdev_priv(dev);

View File

@ -158,7 +158,7 @@ static int atmel_probe(struct pcmcia_device *p_dev)
DEBUG(0, "atmel_attach()\n");
/* Interrupt setup */
p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = NULL;

View File

@ -188,6 +188,11 @@ void b43_rfkill_init(struct b43_wldev *dev)
"The built-in radio LED will not work.\n");
#endif /* CONFIG_RFKILL_INPUT */
#if !defined(CONFIG_RFKILL_INPUT) && !defined(CONFIG_RFKILL_INPUT_MODULE)
b43warn(wl, "The rfkill-input subsystem is not available. "
"The built-in radio LED will not work.\n");
#endif
err = input_register_polled_device(rfk->poll_dev);
if (err)
goto err_unreg_rfk;

View File

@ -36,8 +36,6 @@
#include <linux/workqueue.h>
#include "../net/mac80211/rate.h"
#include "iwl-3945.h"
#define RS_NAME "iwl-3945-rs"
@ -319,10 +317,10 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
}
}
static void rs_rate_init(void *priv_rate, void *priv_sta,
struct ieee80211_local *local, struct sta_info *sta)
static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta)
{
struct iwl3945_rs_sta *rs_sta = (void *)sta->rate_ctrl_priv;
struct iwl3945_rs_sta *rs_sta = priv_sta;
int i;
IWL_DEBUG_RATE("enter\n");
@ -333,22 +331,22 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
* after assoc.. */
for (i = IWL_RATE_COUNT - 1; i >= 0; i--) {
if (sta->sta.supp_rates[local->hw.conf.channel->band] & (1 << i)) {
if (sta->supp_rates[sband->band] & (1 << i)) {
rs_sta->last_txrate_idx = i;
break;
}
}
/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
if (sband->band == IEEE80211_BAND_5GHZ)
rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
IWL_DEBUG_RATE("leave\n");
}
static void *rs_alloc(struct ieee80211_local *local)
static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
{
return local->hw.priv;
return hw->priv;
}
/* rate scale requires free function to be implemented */
@ -356,17 +354,24 @@ static void rs_free(void *priv)
{
return;
}
static void rs_clear(void *priv)
{
return;
}
static void *rs_alloc_sta(void *priv, gfp_t gfp)
static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
{
struct iwl3945_rs_sta *rs_sta;
struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
int i;
/*
* XXX: If it's using sta->drv_priv anyway, it might
* as well just put all the information there.
*/
IWL_DEBUG_RATE("enter\n");
rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp);
@ -375,6 +380,8 @@ static void *rs_alloc_sta(void *priv, gfp_t gfp)
return NULL;
}
psta->rs_sta = rs_sta;
spin_lock_init(&rs_sta->lock);
rs_sta->start_rate = IWL_RATE_INVALID;
@ -400,10 +407,14 @@ static void *rs_alloc_sta(void *priv, gfp_t gfp)
return rs_sta;
}
static void rs_free_sta(void *priv, void *priv_sta)
static void rs_free_sta(void *priv, struct ieee80211_sta *sta,
void *priv_sta)
{
struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
struct iwl3945_rs_sta *rs_sta = priv_sta;
psta->rs_sta = NULL;
IWL_DEBUG_RATE("enter\n");
del_timer_sync(&rs_sta->rate_scale_flush);
kfree(rs_sta);
@ -445,26 +456,19 @@ static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate)
* NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by
* the hardware for each rate.
*/
static void rs_tx_status(void *priv_rate,
struct net_device *dev,
static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
{
u8 retries, current_count;
int scale_rate_index, first_index, last_index;
unsigned long flags;
struct sta_info *sta;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct iwl3945_rs_sta *rs_sta;
struct ieee80211_supported_band *sband;
struct iwl3945_rs_sta *rs_sta = priv_sta;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
IWL_DEBUG_RATE("enter\n");
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
retries = info->status.retry_count;
first_index = sband->bitrates[info->tx_rate_idx].hw_value;
if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) {
@ -472,17 +476,11 @@ static void rs_tx_status(void *priv_rate,
return;
}
rcu_read_lock();
sta = sta_info_get(local, hdr->addr1);
if (!sta || !sta->rate_ctrl_priv) {
rcu_read_unlock();
if (!priv_sta) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
return;
}
rs_sta = (void *)sta->rate_ctrl_priv;
rs_sta->tx_packets++;
scale_rate_index = first_index;
@ -549,8 +547,6 @@ static void rs_tx_status(void *priv_rate,
spin_unlock_irqrestore(&rs_sta->lock, flags);
rcu_read_unlock();
IWL_DEBUG_RATE("leave\n");
return;
@ -634,16 +630,15 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
* rate table and must reference the driver allocated rate table
*
*/
static void rs_get_rate(void *priv_rate, struct net_device *dev,
struct ieee80211_supported_band *sband,
struct sk_buff *skb,
struct rate_selection *sel)
static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb, struct rate_selection *sel)
{
u8 low = IWL_RATE_INVALID;
u8 high = IWL_RATE_INVALID;
u16 high_low;
int index;
struct iwl3945_rs_sta *rs_sta;
struct iwl3945_rs_sta *rs_sta = priv_sta;
struct iwl3945_rate_scale_data *window = NULL;
int current_tpt = IWL_INV_TPT;
int low_tpt = IWL_INV_TPT;
@ -651,34 +646,25 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
u32 fail_count;
s8 scale_action = 0;
unsigned long flags;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct sta_info *sta;
u16 fc, rate_mask;
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
DECLARE_MAC_BUF(mac);
IWL_DEBUG_RATE("enter\n");
rcu_read_lock();
sta = sta_info_get(local, hdr->addr1);
/* Send management frames and broadcast/multicast data using lowest
* rate. */
fc = le16_to_cpu(hdr->frame_control);
if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
is_multicast_ether_addr(hdr->addr1) ||
!sta || !sta->rate_ctrl_priv) {
!sta || !priv_sta) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
sel->rate_idx = rate_lowest_index(local, sband, sta);
rcu_read_unlock();
sel->rate_idx = rate_lowest_index(sband, sta);
return;
}
rs_sta = (void *)sta->rate_ctrl_priv;
rate_mask = sta->sta.supp_rates[sband->band];
rate_mask = sta->supp_rates[sband->band];
index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
if (sband->band == IEEE80211_BAND_5GHZ)
@ -811,8 +797,6 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
else
sel->rate_idx = rs_sta->last_txrate_idx;
rcu_read_unlock();
IWL_DEBUG_RATE("leave: %d\n", index);
}
@ -829,114 +813,28 @@ static struct rate_control_ops rs_ops = {
.free_sta = rs_free_sta,
};
int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
{
struct ieee80211_local *local = hw_to_local(hw);
struct iwl3945_priv *priv = hw->priv;
struct iwl3945_rs_sta *rs_sta;
struct sta_info *sta;
unsigned long flags;
int count = 0, i;
u32 samples = 0, success = 0, good = 0;
unsigned long now = jiffies;
u32 max_time = 0;
rcu_read_lock();
sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
if (!sta || !sta->rate_ctrl_priv) {
if (sta)
IWL_DEBUG_RATE("leave - no private rate data!\n");
else
IWL_DEBUG_RATE("leave - no station!\n");
rcu_read_unlock();
return sprintf(buf, "station %d not found\n", sta_id);
}
rs_sta = (void *)sta->rate_ctrl_priv;
spin_lock_irqsave(&rs_sta->lock, flags);
i = IWL_RATE_54M_INDEX;
while (1) {
u64 mask;
int j;
count +=
sprintf(&buf[count], " %2dMbs: ", iwl3945_rates[i].ieee / 2);
mask = (1ULL << (IWL_RATE_MAX_WINDOW - 1));
for (j = 0; j < IWL_RATE_MAX_WINDOW; j++, mask >>= 1)
buf[count++] =
(rs_sta->win[i].data & mask) ? '1' : '0';
samples += rs_sta->win[i].counter;
good += rs_sta->win[i].success_counter;
success += rs_sta->win[i].success_counter *
iwl3945_rates[i].ieee;
if (rs_sta->win[i].stamp) {
int delta =
jiffies_to_msecs(now - rs_sta->win[i].stamp);
if (delta > max_time)
max_time = delta;
count += sprintf(&buf[count], "%5dms\n", delta);
} else
buf[count++] = '\n';
j = iwl3945_get_prev_ieee_rate(i);
if (j == i)
break;
i = j;
}
spin_unlock_irqrestore(&rs_sta->lock, flags);
rcu_read_unlock();
/* Display the average rate of all samples taken.
*
* NOTE: We multiple # of samples by 2 since the IEEE measurement
* added from iwl3945_rates is actually 2X the rate */
if (samples)
count += sprintf(
&buf[count],
"\nAverage rate is %3d.%02dMbs over last %4dms\n"
"%3d%% success (%d good packets over %d tries)\n",
success / (2 * samples), (success * 5 / samples) % 10,
max_time, good * 100 / samples, good, samples);
else
count += sprintf(&buf[count], "\nAverage rate: 0Mbs\n");
return count;
}
void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
{
struct iwl3945_priv *priv = hw->priv;
s32 rssi = 0;
unsigned long flags;
struct ieee80211_local *local = hw_to_local(hw);
struct iwl3945_rs_sta *rs_sta;
struct sta_info *sta;
struct ieee80211_sta *sta;
struct iwl3945_sta_priv *psta;
IWL_DEBUG_RATE("enter\n");
if (!local->rate_ctrl->ops->name ||
strcmp(local->rate_ctrl->ops->name, RS_NAME)) {
IWL_WARNING("iwl-3945-rs not selected as rate control algo!\n");
IWL_DEBUG_RATE("leave - mac80211 picked the wrong RC algo.\n");
return;
}
rcu_read_lock();
sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
if (!sta || !sta->rate_ctrl_priv) {
sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr);
psta = (void *) sta->drv_priv;
if (!sta || !psta) {
IWL_DEBUG_RATE("leave - no private rate data!\n");
rcu_read_unlock();
return;
}
rs_sta = (void *)sta->rate_ctrl_priv;
rs_sta = psta->rs_sta;
spin_lock_irqsave(&rs_sta->lock, flags);

View File

@ -175,15 +175,6 @@ static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
return rate;
}
/**
* iwl3945_fill_rs_info - Fill an output text buffer with the rate representation
*
* NOTE: This is provided as a quick mechanism for a user to visualize
* the performance of the rate control algorithm and is not meant to be
* parsed software.
*/
extern int iwl3945_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id);
/**
* iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info
*

View File

@ -73,6 +73,10 @@ extern struct pci_device_id iwl3945_hw_card_ids[];
extern int iwl3945_param_hwcrypto;
extern int iwl3945_param_queues_num;
struct iwl3945_sta_priv {
struct iwl3945_rs_sta *rs_sta;
};
enum iwl3945_antenna {
IWL_ANTENNA_DIVERSITY,
IWL_ANTENNA_MAIN,

View File

@ -35,8 +35,6 @@
#include <linux/workqueue.h>
#include "../net/mac80211/rate.h"
#include "iwl-dev.h"
#include "iwl-sta.h"
#include "iwl-core.h"
@ -169,9 +167,9 @@ struct iwl_lq_sta {
};
static void rs_rate_scale_perform(struct iwl_priv *priv,
struct net_device *dev,
struct ieee80211_hdr *hdr,
struct sta_info *sta);
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta);
static void rs_fill_link_cmd(const struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta, u32 rate_n_flags);
@ -357,20 +355,20 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
struct iwl_lq_sta *lq_data, u8 tid,
struct sta_info *sta)
struct ieee80211_sta *sta)
{
DECLARE_MAC_BUF(mac);
if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n",
print_mac(mac, sta->sta.addr), tid);
ieee80211_start_tx_ba_session(priv->hw, sta->sta.addr, tid);
print_mac(mac, sta->addr), tid);
ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid);
}
}
static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
struct iwl_lq_sta *lq_data,
struct sta_info *sta)
struct ieee80211_sta *sta)
{
if ((tid < TID_MAX_LOAD_COUNT))
rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
@ -770,7 +768,8 @@ out:
/*
* mac80211 sends us Tx status
*/
static void rs_tx_status(void *priv_rate, struct net_device *dev,
static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
{
int status;
@ -778,11 +777,9 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
int rs_index, index = 0;
struct iwl_lq_sta *lq_sta;
struct iwl_link_quality_cmd *table;
struct sta_info *sta;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_hw *hw = local_to_hw(local);
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
struct ieee80211_hw *hw = priv->hw;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_rate_scale_data *window = NULL;
struct iwl_rate_scale_data *search_win = NULL;
@ -808,15 +805,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
if (retries > 15)
retries = 15;
rcu_read_lock();
sta = sta_info_get(local, hdr->addr1);
if (!sta || !sta->rate_ctrl_priv)
goto out;
lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv;
lq_sta = (struct iwl_lq_sta *)priv_sta;
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!lq_sta->ibss_sta_added)
@ -962,9 +951,8 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
}
/* See if there's a better rate or modulation mode to try. */
rs_rate_scale_perform(priv, dev, hdr, sta);
rs_rate_scale_perform(priv, hdr, sta, lq_sta);
out:
rcu_read_unlock();
return;
}
@ -1140,7 +1128,7 @@ static s32 rs_get_best_rate(struct iwl_priv *priv,
static int rs_switch_to_mimo2(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct ieee80211_conf *conf,
struct sta_info *sta,
struct ieee80211_sta *sta,
struct iwl_scale_tbl_info *tbl, int index)
{
u16 rate_mask;
@ -1148,10 +1136,10 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
s8 is_green = lq_sta->is_green;
if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
!sta->sta.ht_info.ht_supported)
!sta->ht_info.ht_supported)
return -1;
if (((sta->sta.ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
if (((sta->ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
== WLAN_HT_CAP_SM_PS_STATIC)
return -1;
@ -1208,7 +1196,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
static int rs_switch_to_siso(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct ieee80211_conf *conf,
struct sta_info *sta,
struct ieee80211_sta *sta,
struct iwl_scale_tbl_info *tbl, int index)
{
u16 rate_mask;
@ -1216,7 +1204,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
s32 rate;
if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
!sta->sta.ht_info.ht_supported)
!sta->ht_info.ht_supported)
return -1;
IWL_DEBUG_RATE("LQ: try to switch to SISO\n");
@ -1268,7 +1256,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
static int rs_move_legacy_other(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct ieee80211_conf *conf,
struct sta_info *sta,
struct ieee80211_sta *sta,
int index)
{
struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
@ -1376,7 +1364,7 @@ out:
static int rs_move_siso_to_other(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct ieee80211_conf *conf,
struct sta_info *sta, int index)
struct ieee80211_sta *sta, int index)
{
u8 is_green = lq_sta->is_green;
struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
@ -1487,7 +1475,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
static int rs_move_mimo_to_other(struct iwl_priv *priv,
struct iwl_lq_sta *lq_sta,
struct ieee80211_conf *conf,
struct sta_info *sta, int index)
struct ieee80211_sta *sta, int index)
{
s8 is_green = lq_sta->is_green;
struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
@ -1680,12 +1668,11 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta)
* Do rate scaling and search for new modulation mode.
*/
static void rs_rate_scale_perform(struct iwl_priv *priv,
struct net_device *dev,
struct ieee80211_hdr *hdr,
struct sta_info *sta)
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_hw *hw = local_to_hw(local);
struct ieee80211_hw *hw = priv->hw;
struct ieee80211_conf *conf = &hw->conf;
int low = IWL_RATE_INVALID;
int high = IWL_RATE_INVALID;
@ -1700,7 +1687,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
__le16 fc;
u16 rate_mask;
u8 update_lq = 0;
struct iwl_lq_sta *lq_sta;
struct iwl_scale_tbl_info *tbl, *tbl1;
u16 rate_scale_index_msk = 0;
u32 rate;
@ -1721,11 +1707,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
return;
}
if (!sta || !sta->rate_ctrl_priv)
if (!sta || !lq_sta)
return;
lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv;
lq_sta->supp_rates = sta->sta.supp_rates[lq_sta->band];
lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
tid = rs_tl_add_packet(lq_sta, hdr);
@ -2064,9 +2049,9 @@ out:
static void rs_initialize_lq(struct iwl_priv *priv,
struct ieee80211_conf *conf,
struct sta_info *sta)
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta)
{
struct iwl_lq_sta *lq_sta;
struct iwl_scale_tbl_info *tbl;
int rate_idx;
int i;
@ -2075,10 +2060,9 @@ static void rs_initialize_lq(struct iwl_priv *priv,
u8 active_tbl = 0;
u8 valid_tx_ant;
if (!sta || !sta->rate_ctrl_priv)
if (!sta || !lq_sta)
goto out;
lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv;
i = lq_sta->last_txrate_idx;
if ((lq_sta->lq.sta_id == 0xff) &&
@ -2119,37 +2103,30 @@ static void rs_initialize_lq(struct iwl_priv *priv,
return;
}
static void rs_get_rate(void *priv_rate, struct net_device *dev,
struct ieee80211_supported_band *sband,
struct sk_buff *skb,
struct rate_selection *sel)
static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb, struct rate_selection *sel)
{
int i;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_conf *conf = &local->hw.conf;
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
struct ieee80211_conf *conf = &priv->hw->conf;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct sta_info *sta;
__le16 fc;
struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
struct iwl_lq_sta *lq_sta;
IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
rcu_read_lock();
sta = sta_info_get(local, hdr->addr1);
/* Send management frames and broadcast/multicast data using lowest
* rate. */
fc = hdr->frame_control;
if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
!sta || !sta->rate_ctrl_priv) {
sel->rate_idx = rate_lowest_index(local, sband, sta);
goto out;
!sta || !priv_sta) {
sel->rate_idx = rate_lowest_index(sband, sta);
return;
}
lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv;
lq_sta = (struct iwl_lq_sta *)priv_sta;
i = lq_sta->last_txrate_idx;
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
@ -2167,23 +2144,22 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
lq_sta->lq.sta_id = sta_id;
lq_sta->lq.rs_table[0].rate_n_flags = 0;
lq_sta->ibss_sta_added = 1;
rs_initialize_lq(priv, conf, sta);
rs_initialize_lq(priv, conf, sta, lq_sta);
}
}
if ((i < 0) || (i > IWL_RATE_COUNT)) {
sel->rate_idx = rate_lowest_index(local, sband, sta);
goto out;
sel->rate_idx = rate_lowest_index(sband, sta);
return;
}
if (sband->band == IEEE80211_BAND_5GHZ)
i -= IWL_FIRST_OFDM_RATE;
sel->rate_idx = i;
out:
rcu_read_unlock();
}
static void *rs_alloc_sta(void *priv_rate, gfp_t gfp)
static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
gfp_t gfp)
{
struct iwl_lq_sta *lq_sta;
struct iwl_priv *priv;
@ -2206,20 +2182,16 @@ static void *rs_alloc_sta(void *priv_rate, gfp_t gfp)
return lq_sta;
}
static void rs_rate_init(void *priv_rate, void *priv_sta,
struct ieee80211_local *local,
struct sta_info *sta)
static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta)
{
int i, j;
struct ieee80211_conf *conf = &local->hw.conf;
struct ieee80211_supported_band *sband;
struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
struct ieee80211_conf *conf = &priv->hw->conf;
struct iwl_lq_sta *lq_sta = priv_sta;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
lq_sta->flush_timer = 0;
lq_sta->supp_rates = sta->sta.supp_rates[sband->band];
lq_sta->supp_rates = sta->supp_rates[sband->band];
for (j = 0; j < LQ_SIZE; j++)
for (i = 0; i < IWL_RATE_COUNT; i++)
rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
@ -2232,17 +2204,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
lq_sta->ibss_sta_added = 0;
if (priv->iw_mode == NL80211_IFTYPE_AP) {
u8 sta_id = iwl_find_station(priv, sta->sta.addr);
u8 sta_id = iwl_find_station(priv, sta->addr);
DECLARE_MAC_BUF(mac);
/* for IBSS the call are from tasklet */
IWL_DEBUG_RATE("LQ: ADD station %s\n",
print_mac(mac, sta->sta.addr));
print_mac(mac, sta->addr));
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_RATE("LQ: ADD station %s\n",
print_mac(mac, sta->sta.addr));
sta_id = iwl_add_station_flags(priv, sta->sta.addr,
print_mac(mac, sta->addr));
sta_id = iwl_add_station_flags(priv, sta->addr,
0, CMD_ASYNC, NULL);
}
if ((sta_id != IWL_INVALID_STATION)) {
@ -2256,11 +2228,11 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
/* Find highest tx rate supported by hardware and destination station */
lq_sta->last_txrate_idx = 3;
for (i = 0; i < sband->n_bitrates; i++)
if (sta->sta.supp_rates[sband->band] & BIT(i))
if (sta->supp_rates[sband->band] & BIT(i))
lq_sta->last_txrate_idx = i;
/* For MODE_IEEE80211A, skip over cck rates in global rate table */
if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
if (sband->band == IEEE80211_BAND_5GHZ)
lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
lq_sta->is_dup = 0;
@ -2301,7 +2273,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
lq_sta->drv = priv;
rs_initialize_lq(priv, conf, sta);
rs_initialize_lq(priv, conf, sta, lq_sta);
}
static void rs_fill_link_cmd(const struct iwl_priv *priv,
@ -2423,9 +2395,9 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv,
lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000);
}
static void *rs_alloc(struct ieee80211_local *local)
static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
{
return local->hw.priv;
return hw->priv;
}
/* rate scale requires free function to be implemented */
static void rs_free(void *priv_rate)
@ -2446,12 +2418,12 @@ static void rs_clear(void *priv_rate)
#endif /* CONFIG_IWLWIFI_DEBUG */
}
static void rs_free_sta(void *priv_rate, void *priv_sta)
static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
void *priv_sta)
{
struct iwl_lq_sta *lq_sta = priv_sta;
struct iwl_priv *priv;
struct iwl_priv *priv = priv_r;
priv = (struct iwl_priv *)priv_rate;
IWL_DEBUG_RATE("enter\n");
kfree(lq_sta);
IWL_DEBUG_RATE("leave\n");

View File

@ -2504,8 +2504,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
if (priv->current_ht_config.is_ht)
iwl_set_rxon_ht(priv, &priv->current_ht_config);
iwl_set_rxon_ht(priv, &priv->current_ht_config);
iwl_set_rxon_chain(priv);
priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
@ -2568,8 +2567,6 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
iwl_chain_noise_reset(priv);
priv->start_calib = 1;
/* we have just associated, don't start scan too early */
priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
}
static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
@ -3171,6 +3168,10 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
priv->power_data.dtim_period = bss_conf->dtim_period;
priv->timestamp = bss_conf->timestamp;
priv->assoc_capability = bss_conf->assoc_capability;
/* we have just associated, don't start scan too early
* leave time for EAPOL exchange to complete
*/
priv->next_scan_jiffies = jiffies +
IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
mutex_lock(&priv->mutex);
@ -3189,9 +3190,9 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len)
{
int ret;
unsigned long flags;
struct iwl_priv *priv = hw->priv;
int ret;
IWL_DEBUG_MAC80211("enter\n");
@ -3210,20 +3211,27 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len)
goto out_unlock;
}
/* we don't schedule scan within next_scan_jiffies period */
/* We don't schedule scan within next_scan_jiffies period.
* Avoid scanning during possible EAPOL exchange, return
* success immediately.
*/
if (priv->next_scan_jiffies &&
time_after(priv->next_scan_jiffies, jiffies)) {
IWL_DEBUG_SCAN("scan rejected: within next scan period\n");
ret = -EAGAIN;
queue_work(priv->workqueue, &priv->scan_completed);
ret = 0;
goto out_unlock;
}
/* if we just finished scan ask for delay */
if (iwl_is_associated(priv) && priv->last_scan_jiffies &&
time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) {
IWL_DEBUG_SCAN("scan rejected: within previous scan period\n");
ret = -EAGAIN;
queue_work(priv->workqueue, &priv->scan_completed);
ret = 0;
goto out_unlock;
}
if (ssid_len) {
priv->one_direct_scan = 1;
priv->direct_ssid_len = min_t(u8, ssid_len, IW_ESSID_MAX_SIZE);

View File

@ -646,8 +646,14 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
u32 val;
if (!ht_info->is_ht)
if (!ht_info->is_ht) {
rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
RXON_FLG_CHANNEL_MODE_PURE_40_MSK |
RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
RXON_FLG_FAT_PROT_MSK |
RXON_FLG_HT_PROT_MSK);
return;
}
/* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */
if (iwl_is_fat_tx_allowed(priv, NULL))
@ -697,8 +703,12 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
}
EXPORT_SYMBOL(iwl_set_rxon_ht);
/*
* Determine how many receiver/antenna chains to use.
#define IWL_NUM_RX_CHAINS_MULTIPLE 3
#define IWL_NUM_RX_CHAINS_SINGLE 2
#define IWL_NUM_IDLE_CHAINS_DUAL 2
#define IWL_NUM_IDLE_CHAINS_SINGLE 1
/* Determine how many receiver/antenna chains to use.
* More provides better reception via diversity. Fewer saves power.
* MIMO (dual stream) requires at least 2, but works better with 3.
* This does not determine *which* chains to use, just how many.
@ -711,9 +721,9 @@ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
/* # of Rx chains to use when expecting MIMO. */
if (is_single || (!is_cam && (priv->current_ht_config.sm_ps ==
WLAN_HT_CAP_SM_PS_STATIC)))
return 2;
return IWL_NUM_RX_CHAINS_SINGLE;
else
return 3;
return IWL_NUM_RX_CHAINS_MULTIPLE;
}
static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
@ -724,10 +734,11 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
switch (priv->current_ht_config.sm_ps) {
case WLAN_HT_CAP_SM_PS_STATIC:
case WLAN_HT_CAP_SM_PS_DYNAMIC:
idle_cnt = (is_cam) ? 2 : 1;
idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL :
IWL_NUM_IDLE_CHAINS_SINGLE;
break;
case WLAN_HT_CAP_SM_PS_DISABLED:
idle_cnt = (is_cam) ? active_cnt : 1;
idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE;
break;
case WLAN_HT_CAP_SM_PS_INVALID:
default:
@ -796,7 +807,7 @@ void iwl_set_rxon_chain(struct iwl_priv *priv)
priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain);
if (!is_single && (active_rx_cnt >= 2) && is_cam)
if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
else
priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;

View File

@ -463,11 +463,6 @@ void iwl_init_scan_params(struct iwl_priv *priv)
int iwl_scan_initiate(struct iwl_priv *priv)
{
if (priv->iw_mode == NL80211_IFTYPE_AP) {
IWL_ERROR("APs don't scan.\n");
return 0;
}
if (!iwl_is_ready_rf(priv)) {
IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
return -EIO;
@ -479,8 +474,7 @@ int iwl_scan_initiate(struct iwl_priv *priv)
}
if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
IWL_DEBUG_SCAN("Scan request while abort pending. "
"Queuing.\n");
IWL_DEBUG_SCAN("Scan request while abort pending\n");
return -EAGAIN;
}

View File

@ -1200,10 +1200,9 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
/* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced
* in the queue management code. */
if (txq_id != IWL_CMD_QUEUE_NUM)
IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
txq_id, pkt->hdr.cmd);
BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
if (WARN(txq_id != IWL_CMD_QUEUE_NUM,
"wrong command queue %d, command id 0x%X\n", txq_id, pkt->hdr.cmd))
return;
cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];

View File

@ -7370,15 +7370,6 @@ static ssize_t show_temperature(struct device *d,
static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
static ssize_t show_rs_window(struct device *d,
struct device_attribute *attr,
char *buf)
{
struct iwl3945_priv *priv = d->driver_data;
return iwl3945_fill_rs_info(priv->hw, buf, IWL_AP_ID);
}
static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);
static ssize_t show_tx_power(struct device *d,
struct device_attribute *attr, char *buf)
{
@ -7840,7 +7831,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
#endif
&dev_attr_power_level.attr,
&dev_attr_retry_rate.attr,
&dev_attr_rs_window.attr,
&dev_attr_statistics.attr,
&dev_attr_status.attr,
&dev_attr_temperature.attr,
@ -7908,6 +7898,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
SET_IEEE80211_DEV(hw, &pdev->dev);
hw->rate_control_algorithm = "iwl-3945-rs";
hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
priv = hw->priv;

View File

@ -58,6 +58,7 @@ struct lbs_802_11_security {
u8 WPA2enabled;
u8 wep_enabled;
u8 auth_mode;
u32 key_mgmt;
};
/** Current Basic Service Set State Structure */

View File

@ -1598,8 +1598,20 @@ static int lbs_set_encodeext(struct net_device *dev,
}
out:
if (ret == 0) { /* key installation is time critical: postpone not! */
lbs_do_association_work(priv);
if (ret == 0) {
/* 802.1x and WPA rekeying must happen as quickly as possible,
* especially during the 4-way handshake; thus if in
* infrastructure mode, and either (a) 802.1x is enabled or
* (b) WPA is being used, set the key right away.
*/
if (assoc_req->mode == IW_MODE_INFRA &&
((assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_802_1X) ||
(assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_PSK) ||
assoc_req->secinfo.WPAenabled ||
assoc_req->secinfo.WPA2enabled)) {
lbs_do_association_work(priv);
} else
lbs_postpone_association_work(priv);
} else {
lbs_cancel_association_work(priv);
}
@ -1707,13 +1719,17 @@ static int lbs_set_auth(struct net_device *dev,
case IW_AUTH_TKIP_COUNTERMEASURES:
case IW_AUTH_CIPHER_PAIRWISE:
case IW_AUTH_CIPHER_GROUP:
case IW_AUTH_KEY_MGMT:
case IW_AUTH_DROP_UNENCRYPTED:
/*
* libertas does not use these parameters
*/
break;
case IW_AUTH_KEY_MGMT:
assoc_req->secinfo.key_mgmt = dwrq->value;
updated = 1;
break;
case IW_AUTH_WPA_VERSION:
if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
assoc_req->secinfo.WPAenabled = 0;
@ -1793,6 +1809,10 @@ static int lbs_get_auth(struct net_device *dev,
lbs_deb_enter(LBS_DEB_WEXT);
switch (dwrq->flags & IW_AUTH_INDEX) {
case IW_AUTH_KEY_MGMT:
dwrq->value = priv->secinfo.key_mgmt;
break;
case IW_AUTH_WPA_VERSION:
dwrq->value = 0;
if (priv->secinfo.WPAenabled)

View File

@ -398,7 +398,7 @@ static int netwave_probe(struct pcmcia_device *link)
link->io.IOAddrLines = 5;
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = &netwave_interrupt;

View File

@ -5291,7 +5291,7 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
/* Trigger a scan (look for other cells in the vicinity) */
static int orinoco_ioctl_setscan(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *srq,
struct iw_point *srq,
char *extra)
{
struct orinoco_private *priv = netdev_priv(dev);

View File

@ -121,7 +121,7 @@ orinoco_cs_probe(struct pcmcia_device *link)
link->priv = dev;
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = orinoco_interrupt;
link->irq.Instance = dev;

View File

@ -325,7 +325,7 @@ static int ray_probe(struct pcmcia_device *p_dev)
p_dev->io.IOAddrLines = 5;
/* Interrupt setup. For PCMCIA, driver takes what's given */
p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = &ray_interrupt;

View File

@ -1627,7 +1627,6 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
static int rndis_iw_set_scan(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
struct iw_param *param = &wrqu->param;
struct usbnet *usbdev = dev->priv;
union iwreq_data evt;
int ret = -EINVAL;
@ -1635,7 +1634,7 @@ static int rndis_iw_set_scan(struct net_device *dev,
devdbg(usbdev, "SIOCSIWSCAN");
if (param->flags == 0) {
if (wrqu->data.flags == 0) {
tmp = ccpu2(1);
ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
sizeof(tmp));

View File

@ -543,7 +543,8 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
* provided but key 0 is not, then the key is not found
* by the hardware during RX).
*/
key->hw_key_idx = 0;
if (cmd == SET_KEY)
key->hw_key_idx = 0;
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
set_key = rt2x00dev->ops->lib->config_pairwise_key;

View File

@ -381,7 +381,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
if (reg && reg == mask)
return -ENOSPC;
key->hw_key_idx += reg ? (ffz(reg) - 1) : 0;
key->hw_key_idx += reg ? ffz(reg) : 0;
/*
* Upload key to hardware
@ -477,7 +477,7 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
return -ENOSPC;
}
key->hw_key_idx += reg ? (ffz(reg) - 1) : 0;
key->hw_key_idx += reg ? ffz(reg) : 0;
/*
* Upload key to hardware

View File

@ -393,7 +393,7 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
if (reg && reg == mask)
return -ENOSPC;
key->hw_key_idx += reg ? (ffz(reg) - 1) : 0;
key->hw_key_idx += reg ? ffz(reg) : 0;
/*
* Upload key to hardware
@ -494,7 +494,7 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
return -ENOSPC;
}
key->hw_key_idx += reg ? (ffz(reg) - 1) : 0;
key->hw_key_idx += reg ? ffz(reg) : 0;
/*
* Upload key to hardware

View File

@ -195,7 +195,7 @@ spectrum_cs_probe(struct pcmcia_device *link)
link->priv = dev;
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = orinoco_interrupt;
link->irq.Instance = dev;

View File

@ -4496,7 +4496,7 @@ wavelan_probe(struct pcmcia_device *p_dev)
p_dev->io.IOAddrLines = 3;
/* Interrupt setup */
p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = wavelan_interrupt;

View File

@ -1917,7 +1917,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
p_dev->io.IOAddrLines = 5;
/* Interrupt setup */
p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = wl3501_interrupt;

View File

@ -471,6 +471,11 @@ struct ieee80211s_hdr {
u8 eaddr3[6];
} __attribute__ ((packed));
/* Mesh flags */
#define MESH_FLAGS_AE_A4 0x1
#define MESH_FLAGS_AE_A5_A6 0x2
#define MESH_FLAGS_PS_DEEP 0x4
/**
* struct ieee80211_quiet_ie
*

View File

@ -363,11 +363,13 @@ struct wiphy;
* wireless extensions but this is subject to reevaluation as soon as this
* code is used more widely and we have a first user without wext.
*
* @add_virtual_intf: create a new virtual interface with the given name
* @add_virtual_intf: create a new virtual interface with the given name,
* must set the struct wireless_dev's iftype.
*
* @del_virtual_intf: remove the virtual interface determined by ifindex.
*
* @change_virtual_intf: change type of virtual interface
* @change_virtual_intf: change type/configuration of virtual interface,
* keep the struct wireless_dev's iftype updated.
*
* @add_key: add a key with the given parameters. @mac_addr will be %NULL
* when adding a group key.

View File

@ -1800,4 +1800,72 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw,
struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
const u8 *addr);
/* Rate control API */
/**
* struct rate_selection - rate information for/from rate control algorithms
*
* @rate_idx: selected transmission rate index
* @nonerp_idx: Non-ERP rate to use instead if ERP cannot be used
* @probe_idx: rate for probing (or -1)
* @max_rate_idx: maximum rate index that can be used, this is
* input to the algorithm and will be enforced
*/
struct rate_selection {
s8 rate_idx, nonerp_idx, probe_idx, max_rate_idx;
};
struct rate_control_ops {
struct module *module;
const char *name;
void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir);
void (*clear)(void *priv);
void (*free)(void *priv);
void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp);
void (*rate_init)(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta);
void (*free_sta)(void *priv, struct ieee80211_sta *sta,
void *priv_sta);
void (*tx_status)(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb);
void (*get_rate)(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb,
struct rate_selection *sel);
void (*add_sta_debugfs)(void *priv, void *priv_sta,
struct dentry *dir);
void (*remove_sta_debugfs)(void *priv, void *priv_sta);
};
static inline int rate_supported(struct ieee80211_sta *sta,
enum ieee80211_band band,
int index)
{
return (sta == NULL || sta->supp_rates[band] & BIT(index));
}
static inline s8
rate_lowest_index(struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta)
{
int i;
for (i = 0; i < sband->n_bitrates; i++)
if (rate_supported(sta, sband->band, i))
return i;
/* warn when we cannot find a rate. */
WARN_ON(1);
return 0;
}
int ieee80211_rate_control_register(struct rate_control_ops *ops);
void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
#endif /* MAC80211_H */

View File

@ -223,9 +223,11 @@ struct wiphy {
* the netdev.)
*
* @wiphy: pointer to hardware description
* @iftype: interface type
*/
struct wireless_dev {
struct wiphy *wiphy;
enum nl80211_iftype iftype;
/* private to the generic wireless code */
struct list_head list;
@ -328,6 +330,15 @@ extern int ieee80211_frequency_to_channel(int freq);
*/
extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
int freq);
/**
* ieee80211_get_channel - get channel struct from wiphy for specified frequency
*/
static inline struct ieee80211_channel *
ieee80211_get_channel(struct wiphy *wiphy, int freq)
{
return __ieee80211_get_channel(wiphy, freq);
}
/**
* __regulatory_hint - hint to the wireless core a regulatory domain
* @wiphy: if a driver is providing the hint this is the driver's very
@ -380,13 +391,4 @@ extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
*/
extern int regulatory_hint(struct wiphy *wiphy,
const char *alpha2, struct ieee80211_regdomain *rd);
/**
* ieee80211_get_channel - get channel struct from wiphy for specified frequency
*/
static inline struct ieee80211_channel *
ieee80211_get_channel(struct wiphy *wiphy, int freq)
{
return __ieee80211_get_channel(wiphy, freq);
}
#endif /* __NET_WIRELESS_H */

View File

@ -82,7 +82,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct net_device *dev;
struct ieee80211_sub_if_data *sdata;
int ret;
@ -95,15 +94,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
if (!nl80211_type_check(type))
return -EINVAL;
if (dev == local->mdev)
return -EOPNOTSUPP;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
ret = ieee80211_if_change_type(sdata, type);
if (ret)
return ret;
if (netif_running(sdata->dev))
return -EBUSY;
if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
ieee80211_sdata_set_mesh_id(sdata,
params->mesh_id_len,
@ -120,16 +119,12 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
u8 key_idx, u8 *mac_addr,
struct key_params *params)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta = NULL;
enum ieee80211_key_alg alg;
struct ieee80211_key *key;
int err;
if (dev == local->mdev)
return -EOPNOTSUPP;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
switch (params->cipher) {
@ -174,14 +169,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
u8 key_idx, u8 *mac_addr)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
int ret;
if (dev == local->mdev)
return -EOPNOTSUPP;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
rcu_read_lock();
@ -222,7 +213,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
void (*callback)(void *cookie,
struct key_params *params))
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta = NULL;
u8 seq[6] = {0};
@ -232,9 +222,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
u16 iv16;
int err = -ENOENT;
if (dev == local->mdev)
return -EOPNOTSUPP;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
rcu_read_lock();
@ -310,12 +297,8 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
struct net_device *dev,
u8 key_idx)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
if (dev == local->mdev)
return -EOPNOTSUPP;
rcu_read_lock();
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@ -496,13 +479,9 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
struct beacon_parameters *params)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
struct beacon_data *old;
if (dev == local->mdev)
return -EOPNOTSUPP;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != NL80211_IFTYPE_AP)
@ -519,13 +498,9 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
struct beacon_parameters *params)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
struct beacon_data *old;
if (dev == local->mdev)
return -EOPNOTSUPP;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != NL80211_IFTYPE_AP)
@ -541,13 +516,9 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
struct beacon_data *old;
if (dev == local->mdev)
return -EOPNOTSUPP;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != NL80211_IFTYPE_AP)
@ -695,9 +666,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_sub_if_data *sdata;
int err;
if (dev == local->mdev || params->vlan == local->mdev)
return -EOPNOTSUPP;
/* Prevent a race with changing the rate control algorithm */
if (!netif_running(dev))
return -ENETDOWN;
@ -725,7 +693,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
sta_apply_parameters(local, sta, params);
rate_control_rate_init(sta, local);
rate_control_rate_init(sta);
rcu_read_lock();
@ -752,9 +720,6 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
if (dev == local->mdev)
return -EOPNOTSUPP;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (mac) {
@ -786,9 +751,6 @@ static int ieee80211_change_station(struct wiphy *wiphy,
struct sta_info *sta;
struct ieee80211_sub_if_data *vlansdata;
if (dev == local->mdev || params->vlan == local->mdev)
return -EOPNOTSUPP;
rcu_read_lock();
/* XXX: get sta belonging to dev */
@ -828,9 +790,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
struct sta_info *sta;
int err;
if (dev == local->mdev)
return -EOPNOTSUPP;
if (!netif_running(dev))
return -ENETDOWN;
@ -884,9 +843,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy,
struct mesh_path *mpath;
struct sta_info *sta;
if (dev == local->mdev)
return -EOPNOTSUPP;
if (!netif_running(dev))
return -ENETDOWN;
@ -958,13 +914,9 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
struct mesh_path *mpath;
if (dev == local->mdev)
return -EOPNOTSUPP;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
@ -986,13 +938,9 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
int idx, u8 *dst, u8 *next_hop,
struct mpath_info *pinfo)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
struct mesh_path *mpath;
if (dev == local->mdev)
return -EOPNOTSUPP;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
@ -1015,13 +963,9 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
struct net_device *dev,
struct bss_parameters *params)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata;
u32 changed = 0;
if (dev == local->mdev)
return -EOPNOTSUPP;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->vif.type != NL80211_IFTYPE_AP)

View File

@ -173,8 +173,7 @@ static ssize_t sta_agg_status_write(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos)
{
struct sta_info *sta = file->private_data;
struct net_device *dev = sta->sdata->dev;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_local *local = sta->sdata->local;
struct ieee80211_hw *hw = &local->hw;
u8 *da = sta->sta.addr;
static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0,

View File

@ -573,6 +573,10 @@ enum {
/* maximum number of hardware queues we support. */
#define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES)
struct ieee80211_master_priv {
struct ieee80211_local *local;
};
struct ieee80211_local {
/* embed the driver visible part.
* don't cast (use the static inlines below), but we keep
@ -720,6 +724,8 @@ struct ieee80211_local {
#ifdef CONFIG_MAC80211_DEBUGFS
struct local_debugfsdentries {
struct dentry *rcdir;
struct dentry *rcname;
struct dentry *frequency;
struct dentry *antenna_sel_tx;
struct dentry *antenna_sel_rx;

View File

@ -625,6 +625,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
/* and set some type-dependent values */
sdata->vif.type = type;
sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit;
sdata->wdev.iftype = type;
/* only monitor differs */
sdata->dev->type = ARPHRD_ETHER;

View File

@ -106,7 +106,8 @@ static const struct header_ops ieee80211_header_ops = {
static int ieee80211_master_open(struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_master_priv *mpriv = netdev_priv(dev);
struct ieee80211_local *local = mpriv->local;
struct ieee80211_sub_if_data *sdata;
int res = -EOPNOTSUPP;
@ -128,7 +129,8 @@ static int ieee80211_master_open(struct net_device *dev)
static int ieee80211_master_stop(struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_master_priv *mpriv = netdev_priv(dev);
struct ieee80211_local *local = mpriv->local;
struct ieee80211_sub_if_data *sdata;
/* we hold the RTNL here so can safely walk the list */
@ -141,7 +143,8 @@ static int ieee80211_master_stop(struct net_device *dev)
static void ieee80211_master_set_multicast_list(struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_master_priv *mpriv = netdev_priv(dev);
struct ieee80211_local *local = mpriv->local;
ieee80211_configure_filter(local);
}
@ -539,6 +542,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u16 frag, type;
__le16 fc;
struct ieee80211_supported_band *sband;
struct ieee80211_tx_status_rtap_hdr *rthdr;
struct ieee80211_sub_if_data *sdata;
struct net_device *prev_dev = NULL;
@ -585,7 +589,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
sta->tx_retry_count += info->status.retry_count;
}
rate_control_tx_status(local->mdev, skb);
sband = local->hw.wiphy->bands[info->band];
rate_control_tx_status(local, sband, sta, skb);
}
rcu_read_unlock();
@ -787,7 +792,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
int result;
enum ieee80211_band band;
struct net_device *mdev;
struct wireless_dev *mwdev;
struct ieee80211_master_priv *mpriv;
/*
* generic code guarantees at least one band,
@ -829,16 +834,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (hw->queues < 4)
hw->ampdu_queues = 0;
mdev = alloc_netdev_mq(sizeof(struct wireless_dev),
mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv),
"wmaster%d", ether_setup,
ieee80211_num_queues(hw));
if (!mdev)
goto fail_mdev_alloc;
mwdev = netdev_priv(mdev);
mdev->ieee80211_ptr = mwdev;
mwdev->wiphy = local->hw.wiphy;
mpriv = netdev_priv(mdev);
mpriv->local = local;
local->mdev = mdev;
ieee80211_rx_bss_list_init(local);

View File

@ -351,7 +351,7 @@ static void ieee80211_mesh_path_timer(unsigned long data)
struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = wdev_priv(&sdata->wdev);
struct ieee80211_local *local = sdata->local;
queue_work(local->hw.workqueue, &ifmsh->work);
}

View File

@ -71,6 +71,7 @@ enum mesh_path_flags {
*/
struct mesh_path {
u8 dst[ETH_ALEN];
u8 mpp[ETH_ALEN]; /* used for MPP or MAP */
struct ieee80211_sub_if_data *sdata;
struct sta_info *next_hop;
struct timer_list timer;
@ -226,6 +227,9 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata);
struct mesh_path *mesh_path_lookup(u8 *dst,
struct ieee80211_sub_if_data *sdata);
struct mesh_path *mpp_path_lookup(u8 *dst,
struct ieee80211_sub_if_data *sdata);
int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata);
struct mesh_path *mesh_path_lookup_by_idx(int idx,
struct ieee80211_sub_if_data *sdata);
void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);

View File

@ -36,6 +36,7 @@ struct mpath_node {
};
static struct mesh_table *mesh_paths;
static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */
/* This lock will have the grow table function as writer and add / delete nodes
* as readers. When reading the table (i.e. doing lookups) we are well protected
@ -94,6 +95,34 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
return NULL;
}
struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
{
struct mesh_path *mpath;
struct hlist_node *n;
struct hlist_head *bucket;
struct mesh_table *tbl;
struct mpath_node *node;
tbl = rcu_dereference(mpp_paths);
bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)];
hlist_for_each_entry_rcu(node, n, bucket, list) {
mpath = node->mpath;
if (mpath->sdata == sdata &&
memcmp(dst, mpath->dst, ETH_ALEN) == 0) {
if (MPATH_EXPIRED(mpath)) {
spin_lock_bh(&mpath->state_lock);
if (MPATH_EXPIRED(mpath))
mpath->flags &= ~MESH_PATH_ACTIVE;
spin_unlock_bh(&mpath->state_lock);
}
return mpath;
}
}
return NULL;
}
/**
* mesh_path_lookup_by_idx - look up a path in the mesh path table by its index
* @idx: index
@ -226,6 +255,91 @@ err_path_alloc:
}
int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
{
struct mesh_path *mpath, *new_mpath;
struct mpath_node *node, *new_node;
struct hlist_head *bucket;
struct hlist_node *n;
int grow = 0;
int err = 0;
u32 hash_idx;
if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
/* never add ourselves as neighbours */
return -ENOTSUPP;
if (is_multicast_ether_addr(dst))
return -ENOTSUPP;
err = -ENOMEM;
new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL);
if (!new_mpath)
goto err_path_alloc;
new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
if (!new_node)
goto err_node_alloc;
read_lock(&pathtbl_resize_lock);
memcpy(new_mpath->dst, dst, ETH_ALEN);
memcpy(new_mpath->mpp, mpp, ETH_ALEN);
new_mpath->sdata = sdata;
new_mpath->flags = 0;
skb_queue_head_init(&new_mpath->frame_queue);
new_node->mpath = new_mpath;
new_mpath->exp_time = jiffies;
spin_lock_init(&new_mpath->state_lock);
hash_idx = mesh_table_hash(dst, sdata, mpp_paths);
bucket = &mpp_paths->hash_buckets[hash_idx];
spin_lock(&mpp_paths->hashwlock[hash_idx]);
err = -EEXIST;
hlist_for_each_entry(node, n, bucket, list) {
mpath = node->mpath;
if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0)
goto err_exists;
}
hlist_add_head_rcu(&new_node->list, bucket);
if (atomic_inc_return(&mpp_paths->entries) >=
mpp_paths->mean_chain_len * (mpp_paths->hash_mask + 1))
grow = 1;
spin_unlock(&mpp_paths->hashwlock[hash_idx]);
read_unlock(&pathtbl_resize_lock);
if (grow) {
struct mesh_table *oldtbl, *newtbl;
write_lock(&pathtbl_resize_lock);
oldtbl = mpp_paths;
newtbl = mesh_table_grow(mpp_paths);
if (!newtbl) {
write_unlock(&pathtbl_resize_lock);
return 0;
}
rcu_assign_pointer(mpp_paths, newtbl);
write_unlock(&pathtbl_resize_lock);
synchronize_rcu();
mesh_table_free(oldtbl, false);
}
return 0;
err_exists:
spin_unlock(&mpp_paths->hashwlock[hash_idx]);
read_unlock(&pathtbl_resize_lock);
kfree(new_node);
err_node_alloc:
kfree(new_mpath);
err_path_alloc:
return err;
}
/**
* mesh_plink_broken - deactivates paths and sends perr when a link breaks
*
@ -475,11 +589,21 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl)
int mesh_pathtbl_init(void)
{
mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
if (!mesh_paths)
return -ENOMEM;
mesh_paths->free_node = &mesh_path_node_free;
mesh_paths->copy_node = &mesh_path_node_copy;
mesh_paths->mean_chain_len = MEAN_CHAIN_LEN;
if (!mesh_paths)
mpp_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
if (!mpp_paths) {
mesh_table_free(mesh_paths, true);
return -ENOMEM;
}
mpp_paths->free_node = &mesh_path_node_free;
mpp_paths->copy_node = &mesh_path_node_copy;
mpp_paths->mean_chain_len = MEAN_CHAIN_LEN;
return 0;
}
@ -511,4 +635,5 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
void mesh_pathtbl_unregister(void)
{
mesh_table_free(mesh_paths, true);
mesh_table_free(mpp_paths, true);
}

View File

@ -942,8 +942,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata,
disassoc = 1;
} else
ieee80211_send_probe_req(sdata, ifsta->bssid,
local->scan_ssid,
local->scan_ssid_len);
ifsta->ssid,
ifsta->ssid_len);
ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL;
} else {
ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
@ -1323,7 +1323,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info);
}
rate_control_rate_init(sta, local);
rate_control_rate_init(sta);
if (elems.wmm_param) {
set_sta_flags(sta, WLAN_STA_WME);
@ -1452,6 +1452,8 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED;
mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
ieee80211_led_assoc(local, true);
memset(&wrqu, 0, sizeof(wrqu));
memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN);
wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL);
@ -2342,7 +2344,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
sta->sta.supp_rates[band] = supp_rates |
ieee80211_mandatory_rates(local, band);
rate_control_rate_init(sta, local);
rate_control_rate_init(sta);
if (sta_info_insert(sta))
return NULL;

View File

@ -12,6 +12,7 @@
#include <linux/rtnetlink.h>
#include "rate.h"
#include "ieee80211_i.h"
#include "debugfs.h"
struct rate_control_alg {
struct list_head list;
@ -127,19 +128,46 @@ static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops)
module_put(ops->module);
}
#ifdef CONFIG_MAC80211_DEBUGFS
static ssize_t rcname_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct rate_control_ref *ref = file->private_data;
int len = strlen(ref->ops->name);
return simple_read_from_buffer(userbuf, count, ppos,
ref->ops->name, len);
}
static const struct file_operations rcname_ops = {
.read = rcname_read,
.open = mac80211_open_file_generic,
};
#endif
struct rate_control_ref *rate_control_alloc(const char *name,
struct ieee80211_local *local)
{
struct dentry *debugfsdir = NULL;
struct rate_control_ref *ref;
ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
if (!ref)
goto fail_ref;
kref_init(&ref->kref);
ref->local = local;
ref->ops = ieee80211_rate_control_ops_get(name);
if (!ref->ops)
goto fail_ops;
ref->priv = ref->ops->alloc(local);
#ifdef CONFIG_MAC80211_DEBUGFS
debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir);
local->debugfs.rcdir = debugfsdir;
local->debugfs.rcname = debugfs_create_file("name", 0400, debugfsdir,
ref, &rcname_ops);
#endif
ref->priv = ref->ops->alloc(&local->hw, debugfsdir);
if (!ref->priv)
goto fail_priv;
return ref;
@ -158,29 +186,46 @@ static void rate_control_release(struct kref *kref)
ctrl_ref = container_of(kref, struct rate_control_ref, kref);
ctrl_ref->ops->free(ctrl_ref->priv);
#ifdef CONFIG_MAC80211_DEBUGFS
debugfs_remove(ctrl_ref->local->debugfs.rcname);
ctrl_ref->local->debugfs.rcname = NULL;
debugfs_remove(ctrl_ref->local->debugfs.rcdir);
ctrl_ref->local->debugfs.rcdir = NULL;
#endif
ieee80211_rate_control_ops_put(ctrl_ref->ops);
kfree(ctrl_ref);
}
void rate_control_get_rate(struct net_device *dev,
void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
struct ieee80211_supported_band *sband,
struct sk_buff *skb,
struct sta_info *sta, struct sk_buff *skb,
struct rate_selection *sel)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct rate_control_ref *ref = local->rate_ctrl;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct sta_info *sta;
struct rate_control_ref *ref = sdata->local->rate_ctrl;
void *priv_sta = NULL;
struct ieee80211_sta *ista = NULL;
int i;
rcu_read_lock();
sta = sta_info_get(local, hdr->addr1);
sel->rate_idx = -1;
sel->nonerp_idx = -1;
sel->probe_idx = -1;
sel->max_rate_idx = sdata->max_ratectrl_rateidx;
ref->ops->get_rate(ref->priv, dev, sband, skb, sel);
if (sta) {
ista = &sta->sta;
priv_sta = sta->rate_ctrl_priv;
}
if (sta && sdata->force_unicast_rateidx > -1)
sel->rate_idx = sdata->force_unicast_rateidx;
else
ref->ops->get_rate(ref->priv, sband, ista, priv_sta, skb, sel);
if (sdata->max_ratectrl_rateidx > -1 &&
sel->rate_idx > sdata->max_ratectrl_rateidx)
sel->rate_idx = sdata->max_ratectrl_rateidx;
BUG_ON(sel->rate_idx < 0);
@ -191,13 +236,11 @@ void rate_control_get_rate(struct net_device *dev,
if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate)
break;
if (rate_supported(sta, sband->band, i) &&
if (rate_supported(ista, sband->band, i) &&
!(rate->flags & IEEE80211_RATE_ERP_G))
sel->nonerp_idx = i;
}
}
rcu_read_unlock();
}
struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)

View File

@ -19,77 +19,48 @@
#include "ieee80211_i.h"
#include "sta_info.h"
/**
* struct rate_selection - rate selection for rate control algos
* @rate: selected transmission rate index
* @nonerp: Non-ERP rate to use instead if ERP cannot be used
* @probe: rate for probing (or -1)
*
*/
struct rate_selection {
s8 rate_idx, nonerp_idx, probe_idx;
};
struct rate_control_ops {
struct module *module;
const char *name;
void (*tx_status)(void *priv, struct net_device *dev,
struct sk_buff *skb);
void (*get_rate)(void *priv, struct net_device *dev,
struct ieee80211_supported_band *band,
struct sk_buff *skb,
struct rate_selection *sel);
void (*rate_init)(void *priv, void *priv_sta,
struct ieee80211_local *local, struct sta_info *sta);
void (*clear)(void *priv);
void *(*alloc)(struct ieee80211_local *local);
void (*free)(void *priv);
void *(*alloc_sta)(void *priv, gfp_t gfp);
void (*free_sta)(void *priv, void *priv_sta);
int (*add_attrs)(void *priv, struct kobject *kobj);
void (*remove_attrs)(void *priv, struct kobject *kobj);
void (*add_sta_debugfs)(void *priv, void *priv_sta,
struct dentry *dir);
void (*remove_sta_debugfs)(void *priv, void *priv_sta);
};
struct rate_control_ref {
struct ieee80211_local *local;
struct rate_control_ops *ops;
void *priv;
struct kref kref;
};
int ieee80211_rate_control_register(struct rate_control_ops *ops);
void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
/* Get a reference to the rate control algorithm. If `name' is NULL, get the
* first available algorithm. */
struct rate_control_ref *rate_control_alloc(const char *name,
struct ieee80211_local *local);
void rate_control_get_rate(struct net_device *dev,
void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
struct ieee80211_supported_band *sband,
struct sk_buff *skb,
struct sta_info *sta, struct sk_buff *skb,
struct rate_selection *sel);
struct rate_control_ref *rate_control_get(struct rate_control_ref *ref);
void rate_control_put(struct rate_control_ref *ref);
static inline void rate_control_tx_status(struct net_device *dev,
static inline void rate_control_tx_status(struct ieee80211_local *local,
struct ieee80211_supported_band *sband,
struct sta_info *sta,
struct sk_buff *skb)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct rate_control_ref *ref = local->rate_ctrl;
struct ieee80211_sta *ista = &sta->sta;
void *priv_sta = sta->rate_ctrl_priv;
ref->ops->tx_status(ref->priv, dev, skb);
ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb);
}
static inline void rate_control_rate_init(struct sta_info *sta,
struct ieee80211_local *local)
static inline void rate_control_rate_init(struct sta_info *sta)
{
struct ieee80211_local *local = sta->sdata->local;
struct rate_control_ref *ref = sta->rate_ctrl;
ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta);
struct ieee80211_sta *ista = &sta->sta;
void *priv_sta = sta->rate_ctrl_priv;
struct ieee80211_supported_band *sband;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
ref->ops->rate_init(ref->priv, sband, ista, priv_sta);
}
@ -100,15 +71,19 @@ static inline void rate_control_clear(struct ieee80211_local *local)
}
static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
struct ieee80211_sta *sta,
gfp_t gfp)
{
return ref->ops->alloc_sta(ref->priv, gfp);
return ref->ops->alloc_sta(ref->priv, sta, gfp);
}
static inline void rate_control_free_sta(struct rate_control_ref *ref,
void *priv)
static inline void rate_control_free_sta(struct sta_info *sta)
{
ref->ops->free_sta(ref->priv, priv);
struct rate_control_ref *ref = sta->rate_ctrl;
struct ieee80211_sta *ista = &sta->sta;
void *priv_sta = sta->rate_ctrl_priv;
ref->ops->free_sta(ref->priv, ista, priv_sta);
}
static inline void rate_control_add_sta_debugfs(struct sta_info *sta)
@ -130,31 +105,6 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta)
#endif
}
static inline int rate_supported(struct sta_info *sta,
enum ieee80211_band band,
int index)
{
return (sta == NULL || sta->sta.supp_rates[band] & BIT(index));
}
static inline s8
rate_lowest_index(struct ieee80211_local *local,
struct ieee80211_supported_band *sband,
struct sta_info *sta)
{
int i;
for (i = 0; i < sband->n_bitrates; i++)
if (rate_supported(sta, sband->band, i))
return i;
/* warn when we cannot find a rate. */
WARN_ON(1);
return 0;
}
/* functions for rate control related to a device */
int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
const char *name);

View File

@ -124,7 +124,6 @@ struct rc_pid_events_file_info {
* struct rc_pid_debugfs_entries - tunable parameters
*
* Algorithm parameters, tunable via debugfs.
* @dir: the debugfs directory for a specific phy
* @target: target percentage for failed frames
* @sampling_period: error sampling interval in milliseconds
* @coeff_p: absolute value of the proportional coefficient
@ -143,7 +142,6 @@ struct rc_pid_events_file_info {
* ordering of rates)
*/
struct rc_pid_debugfs_entries {
struct dentry *dir;
struct dentry *target;
struct dentry *sampling_period;
struct dentry *coeff_p;

View File

@ -68,18 +68,14 @@
* exhibited a worse failed frames behaviour and we'll choose the highest rate
* whose failed frames behaviour is not worse than the one of the original rate
* target. While at it, check that the new rate is valid. */
static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
struct sta_info *sta, int adj,
static void rate_control_pid_adjust_rate(struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta,
struct rc_pid_sta_info *spinfo, int adj,
struct rc_pid_rateinfo *rinfo)
{
struct ieee80211_sub_if_data *sdata;
struct ieee80211_supported_band *sband;
int cur_sorted, new_sorted, probe, tmp, n_bitrates, band;
struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv;
int cur = spinfo->txrate_idx;
sdata = sta->sdata;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
band = sband->band;
n_bitrates = sband->n_bitrates;
@ -146,13 +142,11 @@ static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l)
}
static void rate_control_pid_sample(struct rc_pid_info *pinfo,
struct ieee80211_local *local,
struct sta_info *sta)
struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta,
struct rc_pid_sta_info *spinfo)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv;
struct rc_pid_rateinfo *rinfo = pinfo->rinfo;
struct ieee80211_supported_band *sband;
u32 pf;
s32 err_avg;
u32 err_prop;
@ -161,9 +155,6 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
int adj, i, j, tmp;
unsigned long period;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
spinfo = sta->rate_ctrl_priv;
/* In case nothing happened during the previous control interval, turn
* the sharpening factor on. */
period = (HZ * pinfo->sampling_period + 500) / 1000;
@ -179,11 +170,15 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
if (unlikely(spinfo->tx_num_xmit == 0))
pf = spinfo->last_pf;
else {
/* XXX: BAD HACK!!! */
struct sta_info *si = container_of(sta, struct sta_info, sta);
pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit;
if (ieee80211_vif_is_mesh(&sdata->vif) && pf == 100)
mesh_plink_broken(sta);
if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100)
mesh_plink_broken(si);
pf <<= RC_PID_ARITH_SHIFT;
sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9)
si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9)
>> RC_PID_ARITH_SHIFT;
}
@ -229,43 +224,25 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
/* Change rate. */
if (adj)
rate_control_pid_adjust_rate(local, sta, adj, rinfo);
rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo);
}
static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_sub_if_data *sdata;
struct rc_pid_info *pinfo = priv;
struct sta_info *sta;
struct rc_pid_sta_info *spinfo;
struct rc_pid_sta_info *spinfo = priv_sta;
unsigned long period;
struct ieee80211_supported_band *sband;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
rcu_read_lock();
sta = sta_info_get(local, hdr->addr1);
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
if (!sta)
goto unlock;
spinfo = sta->rate_ctrl_priv;
/* Don't update the state if we're not controlling the rate. */
sdata = sta->sdata;
if (sdata->force_unicast_rateidx > -1) {
spinfo->txrate_idx = sdata->max_ratectrl_rateidx;
goto unlock;
}
if (!spinfo)
return;
/* Ignore all frames that were sent with a different rate than the rate
* we currently advise mac80211 to use. */
if (info->tx_rate_idx != spinfo->txrate_idx)
goto unlock;
return;
spinfo->tx_num_xmit++;
@ -289,78 +266,63 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
if (!period)
period = 1;
if (time_after(jiffies, spinfo->last_sample + period))
rate_control_pid_sample(pinfo, local, sta);
unlock:
rcu_read_unlock();
rate_control_pid_sample(pinfo, sband, sta, spinfo);
}
static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
struct ieee80211_supported_band *sband,
struct sk_buff *skb,
struct rate_selection *sel)
static void
rate_control_pid_get_rate(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb,
struct rate_selection *sel)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_sub_if_data *sdata;
struct rc_pid_sta_info *spinfo;
struct sta_info *sta;
struct rc_pid_sta_info *spinfo = priv_sta;
int rateidx;
u16 fc;
rcu_read_lock();
sta = sta_info_get(local, hdr->addr1);
/* Send management frames and broadcast/multicast data using lowest
* rate. */
fc = le16_to_cpu(hdr->frame_control);
if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
is_multicast_ether_addr(hdr->addr1) || !sta) {
sel->rate_idx = rate_lowest_index(local, sband, sta);
rcu_read_unlock();
if (!sta || !spinfo ||
(fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
is_multicast_ether_addr(hdr->addr1)) {
sel->rate_idx = rate_lowest_index(sband, sta);
return;
}
/* If a forced rate is in effect, select it. */
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
spinfo = (struct rc_pid_sta_info *)sta->rate_ctrl_priv;
if (sdata->force_unicast_rateidx > -1)
spinfo->txrate_idx = sdata->force_unicast_rateidx;
rateidx = spinfo->txrate_idx;
if (rateidx >= sband->n_bitrates)
rateidx = sband->n_bitrates - 1;
rcu_read_unlock();
sel->rate_idx = rateidx;
#ifdef CONFIG_MAC80211_DEBUGFS
rate_control_pid_event_tx_rate(
&((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events,
rate_control_pid_event_tx_rate(&spinfo->events,
rateidx, sband->bitrates[rateidx].bitrate);
#endif
}
static void rate_control_pid_rate_init(void *priv, void *priv_sta,
struct ieee80211_local *local,
struct sta_info *sta)
static void
rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta)
{
struct rc_pid_sta_info *spinfo = priv_sta;
struct sta_info *si;
/* TODO: This routine should consider using RSSI from previous packets
* as we need to have IEEE 802.1X auth succeed immediately after assoc..
* Until that method is implemented, we will use the lowest supported
* rate as a workaround. */
struct ieee80211_supported_band *sband;
struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
spinfo->txrate_idx = rate_lowest_index(local, sband, sta);
sta->fail_avg = 0;
spinfo->txrate_idx = rate_lowest_index(sband, sta);
/* HACK */
si = container_of(sta, struct sta_info, sta);
si->fail_avg = 0;
}
static void *rate_control_pid_alloc(struct ieee80211_local *local)
static void *rate_control_pid_alloc(struct ieee80211_hw *hw,
struct dentry *debugfsdir)
{
struct rc_pid_info *pinfo;
struct rc_pid_rateinfo *rinfo;
@ -371,7 +333,7 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local)
struct rc_pid_debugfs_entries *de;
#endif
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
sband = hw->wiphy->bands[hw->conf.channel->band];
pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC);
if (!pinfo)
@ -426,30 +388,28 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local)
#ifdef CONFIG_MAC80211_DEBUGFS
de = &pinfo->dentries;
de->dir = debugfs_create_dir("rc80211_pid",
local->hw.wiphy->debugfsdir);
de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR,
de->dir, &pinfo->target);
debugfsdir, &pinfo->target);
de->sampling_period = debugfs_create_u32("sampling_period",
S_IRUSR | S_IWUSR, de->dir,
S_IRUSR | S_IWUSR, debugfsdir,
&pinfo->sampling_period);
de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR,
de->dir, &pinfo->coeff_p);
debugfsdir, &pinfo->coeff_p);
de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR,
de->dir, &pinfo->coeff_i);
debugfsdir, &pinfo->coeff_i);
de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR,
de->dir, &pinfo->coeff_d);
debugfsdir, &pinfo->coeff_d);
de->smoothing_shift = debugfs_create_u32("smoothing_shift",
S_IRUSR | S_IWUSR, de->dir,
S_IRUSR | S_IWUSR, debugfsdir,
&pinfo->smoothing_shift);
de->sharpen_factor = debugfs_create_u32("sharpen_factor",
S_IRUSR | S_IWUSR, de->dir,
S_IRUSR | S_IWUSR, debugfsdir,
&pinfo->sharpen_factor);
de->sharpen_duration = debugfs_create_u32("sharpen_duration",
S_IRUSR | S_IWUSR, de->dir,
S_IRUSR | S_IWUSR, debugfsdir,
&pinfo->sharpen_duration);
de->norm_offset = debugfs_create_u32("norm_offset",
S_IRUSR | S_IWUSR, de->dir,
S_IRUSR | S_IWUSR, debugfsdir,
&pinfo->norm_offset);
#endif
@ -471,7 +431,6 @@ static void rate_control_pid_free(void *priv)
debugfs_remove(de->coeff_p);
debugfs_remove(de->sampling_period);
debugfs_remove(de->target);
debugfs_remove(de->dir);
#endif
kfree(pinfo->rinfo);
@ -482,7 +441,8 @@ static void rate_control_pid_clear(void *priv)
{
}
static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp)
static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta,
gfp_t gfp)
{
struct rc_pid_sta_info *spinfo;
@ -500,10 +460,10 @@ static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp)
return spinfo;
}
static void rate_control_pid_free_sta(void *priv, void *priv_sta)
static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta,
void *priv_sta)
{
struct rc_pid_sta_info *spinfo = priv_sta;
kfree(spinfo);
kfree(priv_sta);
}
static struct rate_control_ops mac80211_rcpid = {

View File

@ -650,32 +650,28 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
return result;
}
static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
static void ap_sta_ps_start(struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata;
struct ieee80211_sub_if_data *sdata = sta->sdata;
DECLARE_MAC_BUF(mac);
sdata = sta->sdata;
atomic_inc(&sdata->bss->num_sta_ps);
set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL);
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n",
dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid);
sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
}
static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
static int ap_sta_ps_end(struct sta_info *sta)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
int sent = 0;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_tx_info *info;
DECLARE_MAC_BUF(mac);
sdata = sta->sdata;
atomic_dec(&sdata->bss->num_sta_ps);
clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL);
@ -685,7 +681,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n",
dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid);
sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
/* Send all buffered frames to the station */
@ -701,7 +697,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
sent++;
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %s aid %d send PS frame "
"since STA not sleeping anymore\n", dev->name,
"since STA not sleeping anymore\n", sdata->dev->name,
print_mac(mac, sta->sta.addr), sta->sta.aid);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
info->flags |= IEEE80211_TX_CTL_REQUEUE;
@ -715,7 +711,6 @@ static ieee80211_rx_result debug_noinline
ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
{
struct sta_info *sta = rx->sta;
struct net_device *dev = rx->dev;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
if (!sta)
@ -757,10 +752,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
* exchange sequence */
if (test_sta_flags(sta, WLAN_STA_PS) &&
!ieee80211_has_pm(hdr->frame_control))
rx->sent_ps_buffered += ap_sta_ps_end(dev, sta);
rx->sent_ps_buffered += ap_sta_ps_end(sta);
else if (!test_sta_flags(sta, WLAN_STA_PS) &&
ieee80211_has_pm(hdr->frame_control))
ap_sta_ps_start(dev, sta);
ap_sta_ps_start(sta);
}
/* Drop data::nullfunc frames silently, since they are used only to
@ -1112,10 +1107,6 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
hdrlen = ieee80211_hdrlen(hdr->frame_control);
if (ieee80211_vif_is_mesh(&sdata->vif))
hdrlen += ieee80211_get_mesh_hdrlen(
(struct ieee80211s_hdr *) (skb->data + hdrlen));
/* convert IEEE 802.11 header + possible LLC headers into Ethernet
* header
* IEEE 802.11 address fields:
@ -1139,6 +1130,15 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT))
return -1;
if (ieee80211_vif_is_mesh(&sdata->vif)) {
struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *)
(skb->data + hdrlen);
hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
memcpy(dst, meshdr->eaddr1, ETH_ALEN);
memcpy(src, meshdr->eaddr2, ETH_ALEN);
}
}
break;
case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS):
if (sdata->vif.type != NL80211_IFTYPE_STATION ||
@ -1398,6 +1398,25 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
/* illegal frame */
return RX_DROP_MONITOR;
if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){
struct ieee80211_sub_if_data *sdata;
struct mesh_path *mppath;
sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
rcu_read_lock();
mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata);
if (!mppath) {
mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata);
} else {
spin_lock_bh(&mppath->state_lock);
mppath->exp_time = jiffies;
if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0)
memcpy(mppath->mpp, hdr->addr4, ETH_ALEN);
spin_unlock_bh(&mppath->state_lock);
}
rcu_read_unlock();
}
if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0)
return RX_CONTINUE;
@ -1538,7 +1557,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
*/
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_ADHOC)
return RX_DROP_MONITOR;
return RX_CONTINUE;
switch (mgmt->u.action.category) {
case WLAN_CATEGORY_BACK:

View File

@ -93,8 +93,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
}
/* protected by RCU */
static struct sta_info *__sta_info_find(struct ieee80211_local *local,
const u8 *addr)
struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr)
{
struct sta_info *sta;
@ -107,12 +106,6 @@ static struct sta_info *__sta_info_find(struct ieee80211_local *local,
return sta;
}
struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
{
return __sta_info_find(local, addr);
}
EXPORT_SYMBOL(sta_info_get);
struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx,
struct net_device *dev)
{
@ -146,7 +139,7 @@ static void __sta_info_free(struct ieee80211_local *local,
{
DECLARE_MAC_BUF(mbuf);
rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
rate_control_free_sta(sta);
rate_control_put(sta->rate_ctrl);
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
@ -244,7 +237,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
sta->rate_ctrl = rate_control_get(local->rate_ctrl);
sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
gfp);
&sta->sta, gfp);
if (!sta->rate_ctrl_priv) {
rate_control_put(sta->rate_ctrl);
kfree(sta);
@ -308,7 +301,7 @@ int sta_info_insert(struct sta_info *sta)
spin_lock_irqsave(&local->sta_lock, flags);
/* check if STA exists already */
if (__sta_info_find(local, sta->sta.addr)) {
if (sta_info_get(local, sta->sta.addr)) {
spin_unlock_irqrestore(&local->sta_lock, flags);
err = -EEXIST;
goto out_free;
@ -834,7 +827,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
const u8 *addr)
{
struct sta_info *sta = __sta_info_find(hw_to_local(hw), addr);
struct sta_info *sta = sta_info_get(hw_to_local(hw), addr);
if (!sta)
return NULL;

View File

@ -416,7 +416,7 @@ static inline u32 get_sta_flags(struct sta_info *sta)
/*
* Get a STA info, must have be under RCU read lock.
*/
struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr);
struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr);
/*
* Get STA info by index, BROKEN!
*/

View File

@ -165,11 +165,10 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
return cpu_to_le16(dur);
}
static int inline is_ieee80211_device(struct net_device *dev,
struct net_device *master)
static int inline is_ieee80211_device(struct ieee80211_local *local,
struct net_device *dev)
{
return (wdev_priv(dev->ieee80211_ptr) ==
wdev_priv(master->ieee80211_ptr));
return local == wdev_priv(dev->ieee80211_ptr);
}
/* tx handlers */
@ -447,7 +446,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
sband = tx->local->hw.wiphy->bands[tx->channel->band];
if (likely(tx->rate_idx < 0)) {
rate_control_get_rate(tx->dev, sband, tx->skb, &rsel);
rate_control_get_rate(tx->sdata, sband, tx->sta,
tx->skb, &rsel);
if (tx->sta)
tx->sta->last_txrate_idx = rsel.rate_idx;
tx->rate_idx = rsel.rate_idx;
@ -1001,14 +1001,14 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
/*
* NB: @tx is uninitialised when passed in here
*/
static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
struct sk_buff *skb,
struct net_device *mdev)
static int ieee80211_tx_prepare(struct ieee80211_local *local,
struct ieee80211_tx_data *tx,
struct sk_buff *skb)
{
struct net_device *dev;
dev = dev_get_by_index(&init_net, skb->iif);
if (unlikely(dev && !is_ieee80211_device(dev, mdev))) {
if (unlikely(dev && !is_ieee80211_device(local, dev))) {
dev_put(dev);
dev = NULL;
}
@ -1258,6 +1258,8 @@ static int ieee80211_skb_resize(struct ieee80211_local *local,
int ieee80211_master_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct ieee80211_master_priv *mpriv = netdev_priv(dev);
struct ieee80211_local *local = mpriv->local;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct net_device *odev = NULL;
@ -1273,7 +1275,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
if (skb->iif)
odev = dev_get_by_index(&init_net, skb->iif);
if (unlikely(odev && !is_ieee80211_device(odev, dev))) {
if (unlikely(odev && !is_ieee80211_device(local, odev))) {
dev_put(odev);
odev = NULL;
}
@ -1449,8 +1451,8 @@ fail:
int ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata;
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
int ret = 1, head_need;
u16 ethertype, hdrlen, meshhdrlen = 0;
__le16 fc;
@ -1462,7 +1464,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
struct sta_info *sta;
u32 sta_flags = 0;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (unlikely(skb->len < ETH_HLEN)) {
ret = 0;
goto fail;
@ -1498,18 +1499,50 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
#ifdef CONFIG_MAC80211_MESH
case NL80211_IFTYPE_MESH_POINT:
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
/* RA TA DA SA */
memset(hdr.addr1, 0, ETH_ALEN);
memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
memcpy(hdr.addr3, skb->data, ETH_ALEN);
memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
if (!sdata->u.mesh.mshcfg.dot11MeshTTL) {
/* Do not send frames with mesh_ttl == 0 */
sdata->u.mesh.mshstats.dropped_frames_ttl++;
ret = 0;
goto fail;
}
meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata);
memset(&mesh_hdr, 0, sizeof(mesh_hdr));
if (compare_ether_addr(dev->dev_addr,
skb->data + ETH_ALEN) == 0) {
/* RA TA DA SA */
memset(hdr.addr1, 0, ETH_ALEN);
memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
memcpy(hdr.addr3, skb->data, ETH_ALEN);
memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata);
} else {
/* packet from other interface */
struct mesh_path *mppath;
memset(hdr.addr1, 0, ETH_ALEN);
memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN);
if (is_multicast_ether_addr(skb->data))
memcpy(hdr.addr3, skb->data, ETH_ALEN);
else {
rcu_read_lock();
mppath = mpp_path_lookup(skb->data, sdata);
if (mppath)
memcpy(hdr.addr3, mppath->mpp, ETH_ALEN);
else
memset(hdr.addr3, 0xff, ETH_ALEN);
rcu_read_unlock();
}
mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6;
mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum);
memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN);
memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN);
sdata->u.mesh.mesh_seqnum++;
meshhdrlen = 18;
}
hdrlen = 30;
break;
#endif
@ -1923,7 +1956,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
skb->do_not_encrypt = 1;
info->band = band;
rate_control_get_rate(local->mdev, sband, skb, &rsel);
rate_control_get_rate(sdata, sband, NULL, skb, &rsel);
if (unlikely(rsel.rate_idx < 0)) {
if (net_ratelimit()) {
@ -2032,7 +2065,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
cpu_to_le16(IEEE80211_FCTL_MOREDATA);
}
if (!ieee80211_tx_prepare(&tx, skb, local->mdev))
if (!ieee80211_tx_prepare(local, &tx, skb))
break;
dev_kfree_skb_any(skb);
}

View File

@ -29,113 +29,11 @@ MODULE_AUTHOR("Johannes Berg");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("wireless configuration support");
struct list_head regulatory_requests;
/* Central wireless core regulatory domains, we only need two,
* the current one and a world regulatory domain in case we have no
* information to give us an alpha2 */
struct ieee80211_regdomain *cfg80211_regdomain;
/* We keep a static world regulatory domain in case of the absence of CRDA */
const struct ieee80211_regdomain world_regdom = {
.n_reg_rules = 1,
.alpha2 = "00",
.reg_rules = {
REG_RULE(2402, 2472, 40, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),
}
};
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
/* All this fucking static junk will be removed soon, so
* don't fucking count on it !@#$ */
static char *ieee80211_regdom = "US";
module_param(ieee80211_regdom, charp, 0444);
MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
/* We assume 40 MHz bandwidth for the old regulatory work.
* We make emphasis we are using the exact same frequencies
* as before */
const struct ieee80211_regdomain us_regdom = {
.n_reg_rules = 6,
.alpha2 = "US",
.reg_rules = {
/* IEEE 802.11b/g, channels 1..11 */
REG_RULE(2412-20, 2462+20, 40, 6, 27, 0),
/* IEEE 802.11a, channel 36 */
REG_RULE(5180-20, 5180+20, 40, 6, 23, 0),
/* IEEE 802.11a, channel 40 */
REG_RULE(5200-20, 5200+20, 40, 6, 23, 0),
/* IEEE 802.11a, channel 44 */
REG_RULE(5220-20, 5220+20, 40, 6, 23, 0),
/* IEEE 802.11a, channels 48..64 */
REG_RULE(5240-20, 5320+20, 40, 6, 23, 0),
/* IEEE 802.11a, channels 149..165, outdoor */
REG_RULE(5745-20, 5825+20, 40, 6, 30, 0),
}
};
const struct ieee80211_regdomain jp_regdom = {
.n_reg_rules = 3,
.alpha2 = "JP",
.reg_rules = {
/* IEEE 802.11b/g, channels 1..14 */
REG_RULE(2412-20, 2484+20, 40, 6, 20, 0),
/* IEEE 802.11a, channels 34..48 */
REG_RULE(5170-20, 5240+20, 40, 6, 20,
NL80211_RRF_PASSIVE_SCAN),
/* IEEE 802.11a, channels 52..64 */
REG_RULE(5260-20, 5320+20, 40, 6, 20,
NL80211_RRF_NO_IBSS |
NL80211_RRF_DFS),
}
};
const struct ieee80211_regdomain eu_regdom = {
.n_reg_rules = 6,
/* This alpha2 is bogus, we leave it here just for stupid
* backward compatibility */
.alpha2 = "EU",
.reg_rules = {
/* IEEE 802.11b/g, channels 1..13 */
REG_RULE(2412-20, 2472+20, 40, 6, 20, 0),
/* IEEE 802.11a, channel 36 */
REG_RULE(5180-20, 5180+20, 40, 6, 23,
NL80211_RRF_PASSIVE_SCAN),
/* IEEE 802.11a, channel 40 */
REG_RULE(5200-20, 5200+20, 40, 6, 23,
NL80211_RRF_PASSIVE_SCAN),
/* IEEE 802.11a, channel 44 */
REG_RULE(5220-20, 5220+20, 40, 6, 23,
NL80211_RRF_PASSIVE_SCAN),
/* IEEE 802.11a, channels 48..64 */
REG_RULE(5240-20, 5320+20, 40, 6, 20,
NL80211_RRF_NO_IBSS |
NL80211_RRF_DFS),
/* IEEE 802.11a, channels 100..140 */
REG_RULE(5500-20, 5700+20, 40, 6, 30,
NL80211_RRF_NO_IBSS |
NL80211_RRF_DFS),
}
};
#endif
struct ieee80211_regdomain *cfg80211_world_regdom =
(struct ieee80211_regdomain *) &world_regdom;
LIST_HEAD(regulatory_requests);
DEFINE_MUTEX(cfg80211_reg_mutex);
/* RCU might be appropriate here since we usually
* only read the list, and that can happen quite
* often because we need to do it for each command */
LIST_HEAD(cfg80211_drv_list);
DEFINE_MUTEX(cfg80211_drv_mutex);
static int wiphy_counter;
/* for debugfs */
static struct dentry *ieee80211_debugfs_dir;
@ -307,6 +205,8 @@ out_unlock:
struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
{
static int wiphy_counter;
struct cfg80211_registered_device *drv;
int alloc_size;
@ -323,21 +223,18 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
mutex_lock(&cfg80211_drv_mutex);
drv->idx = wiphy_counter;
/* now increase counter for the next device unless
* it has wrapped previously */
if (wiphy_counter >= 0)
wiphy_counter++;
mutex_unlock(&cfg80211_drv_mutex);
drv->idx = wiphy_counter++;
if (unlikely(drv->idx < 0)) {
wiphy_counter--;
mutex_unlock(&cfg80211_drv_mutex);
/* ugh, wrapped! */
kfree(drv);
return NULL;
}
mutex_unlock(&cfg80211_drv_mutex);
/* give it a proper name */
snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE,
PHY_NAME "%d", drv->idx);
@ -485,6 +382,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
WARN_ON(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_UNSPECIFIED);
switch (state) {
case NETDEV_REGISTER:
mutex_lock(&rdev->devlist_mtx);
@ -514,34 +413,10 @@ static struct notifier_block cfg80211_netdev_notifier = {
.notifier_call = cfg80211_netdev_notifier_call,
};
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
const struct ieee80211_regdomain *static_regdom(char *alpha2)
{
if (alpha2[0] == 'U' && alpha2[1] == 'S')
return &us_regdom;
if (alpha2[0] == 'J' && alpha2[1] == 'P')
return &jp_regdom;
if (alpha2[0] == 'E' && alpha2[1] == 'U')
return &eu_regdom;
/* Default, as per the old rules */
return &us_regdom;
}
#endif
static int cfg80211_init(void)
{
int err;
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
cfg80211_regdomain =
(struct ieee80211_regdomain *) static_regdom(ieee80211_regdom);
/* Used during reset_regdomains_static() */
cfg80211_world_regdom = cfg80211_regdomain;
#else
cfg80211_regdomain =
(struct ieee80211_regdomain *) cfg80211_world_regdom;
#endif
err = wiphy_sysfs_init();
if (err)
goto out_fail_sysfs;
@ -560,25 +435,6 @@ static int cfg80211_init(void)
if (err)
goto out_fail_reg;
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
printk(KERN_INFO "cfg80211: Using old static regulatory domain:\n");
print_regdomain_info(cfg80211_regdomain);
/* The old code still requests for a new regdomain and if
* you have CRDA you get it updated, otherwise you get
* stuck with the static values. We ignore "EU" code as
* that is not a valid ISO / IEC 3166 alpha2 */
if (ieee80211_regdom[0] != 'E' &&
ieee80211_regdom[1] != 'U')
err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE,
ieee80211_regdom, NULL);
#else
err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL);
if (err)
printk(KERN_ERR "cfg80211: calling CRDA failed - "
"unable to update world regulatory domain, "
"using static definition\n");
#endif
return 0;
out_fail_reg:

View File

@ -299,7 +299,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
/* TODO: interface type */
NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype);
return genlmsg_end(msg, hdr);
nla_put_failure:
@ -418,41 +418,56 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
int err, ifindex;
enum nl80211_iftype type;
struct net_device *dev;
u32 flags;
u32 _flags, *flags = NULL;
memset(&params, 0, sizeof(params));
if (info->attrs[NL80211_ATTR_IFTYPE]) {
type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
if (type > NL80211_IFTYPE_MAX)
return -EINVAL;
} else
return -EINVAL;
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
if (err)
return err;
ifindex = dev->ifindex;
type = dev->ieee80211_ptr->iftype;
dev_put(dev);
err = -EINVAL;
if (info->attrs[NL80211_ATTR_IFTYPE]) {
type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
if (type > NL80211_IFTYPE_MAX)
goto unlock;
}
if (!drv->ops->change_virtual_intf ||
!(drv->wiphy.interface_modes & (1 << type))) {
err = -EOPNOTSUPP;
goto unlock;
}
if (type == NL80211_IFTYPE_MESH_POINT &&
info->attrs[NL80211_ATTR_MESH_ID]) {
if (info->attrs[NL80211_ATTR_MESH_ID]) {
if (type != NL80211_IFTYPE_MESH_POINT) {
err = -EINVAL;
goto unlock;
}
params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
}
if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
if (type != NL80211_IFTYPE_MONITOR) {
err = -EINVAL;
goto unlock;
}
err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS],
&_flags);
if (!err)
flags = &_flags;
}
rtnl_lock();
err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
&flags);
err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
type, err ? NULL : &flags, &params);
type, flags, &params);
dev = __dev_get_by_index(&init_net, ifindex);
WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type));
rtnl_unlock();
unlock:

View File

@ -42,6 +42,18 @@
#include "core.h"
#include "reg.h"
/* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */
struct regulatory_request {
struct list_head list;
struct wiphy *wiphy;
int granted;
enum reg_set_by initiator;
char alpha2[2];
};
static LIST_HEAD(regulatory_requests);
DEFINE_MUTEX(cfg80211_reg_mutex);
/* To trigger userspace events */
static struct platform_device *reg_pdev;
@ -51,7 +63,156 @@ static u32 supported_bandwidths[] = {
MHZ_TO_KHZ(20),
};
bool is_world_regdom(char *alpha2)
static struct list_head regulatory_requests;
/* Central wireless core regulatory domains, we only need two,
* the current one and a world regulatory domain in case we have no
* information to give us an alpha2 */
static const struct ieee80211_regdomain *cfg80211_regdomain;
/* We keep a static world regulatory domain in case of the absence of CRDA */
static const struct ieee80211_regdomain world_regdom = {
.n_reg_rules = 1,
.alpha2 = "00",
.reg_rules = {
REG_RULE(2412-10, 2462+10, 40, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),
}
};
static const struct ieee80211_regdomain *cfg80211_world_regdom =
&world_regdom;
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
static char *ieee80211_regdom = "US";
module_param(ieee80211_regdom, charp, 0444);
MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
/* We assume 40 MHz bandwidth for the old regulatory work.
* We make emphasis we are using the exact same frequencies
* as before */
static const struct ieee80211_regdomain us_regdom = {
.n_reg_rules = 6,
.alpha2 = "US",
.reg_rules = {
/* IEEE 802.11b/g, channels 1..11 */
REG_RULE(2412-10, 2462+10, 40, 6, 27, 0),
/* IEEE 802.11a, channel 36 */
REG_RULE(5180-10, 5180+10, 40, 6, 23, 0),
/* IEEE 802.11a, channel 40 */
REG_RULE(5200-10, 5200+10, 40, 6, 23, 0),
/* IEEE 802.11a, channel 44 */
REG_RULE(5220-10, 5220+10, 40, 6, 23, 0),
/* IEEE 802.11a, channels 48..64 */
REG_RULE(5240-10, 5320+10, 40, 6, 23, 0),
/* IEEE 802.11a, channels 149..165, outdoor */
REG_RULE(5745-10, 5825+10, 40, 6, 30, 0),
}
};
static const struct ieee80211_regdomain jp_regdom = {
.n_reg_rules = 3,
.alpha2 = "JP",
.reg_rules = {
/* IEEE 802.11b/g, channels 1..14 */
REG_RULE(2412-10, 2484+10, 40, 6, 20, 0),
/* IEEE 802.11a, channels 34..48 */
REG_RULE(5170-10, 5240+10, 40, 6, 20,
NL80211_RRF_PASSIVE_SCAN),
/* IEEE 802.11a, channels 52..64 */
REG_RULE(5260-10, 5320+10, 40, 6, 20,
NL80211_RRF_NO_IBSS |
NL80211_RRF_DFS),
}
};
static const struct ieee80211_regdomain eu_regdom = {
.n_reg_rules = 6,
/* This alpha2 is bogus, we leave it here just for stupid
* backward compatibility */
.alpha2 = "EU",
.reg_rules = {
/* IEEE 802.11b/g, channels 1..13 */
REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
/* IEEE 802.11a, channel 36 */
REG_RULE(5180-10, 5180+10, 40, 6, 23,
NL80211_RRF_PASSIVE_SCAN),
/* IEEE 802.11a, channel 40 */
REG_RULE(5200-10, 5200+10, 40, 6, 23,
NL80211_RRF_PASSIVE_SCAN),
/* IEEE 802.11a, channel 44 */
REG_RULE(5220-10, 5220+10, 40, 6, 23,
NL80211_RRF_PASSIVE_SCAN),
/* IEEE 802.11a, channels 48..64 */
REG_RULE(5240-10, 5320+10, 40, 6, 20,
NL80211_RRF_NO_IBSS |
NL80211_RRF_DFS),
/* IEEE 802.11a, channels 100..140 */
REG_RULE(5500-10, 5700+10, 40, 6, 30,
NL80211_RRF_NO_IBSS |
NL80211_RRF_DFS),
}
};
static const struct ieee80211_regdomain *static_regdom(char *alpha2)
{
if (alpha2[0] == 'U' && alpha2[1] == 'S')
return &us_regdom;
if (alpha2[0] == 'J' && alpha2[1] == 'P')
return &jp_regdom;
if (alpha2[0] == 'E' && alpha2[1] == 'U')
return &eu_regdom;
/* Default, as per the old rules */
return &us_regdom;
}
static bool is_old_static_regdom(const struct ieee80211_regdomain *rd)
{
if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom)
return true;
return false;
}
#else
static inline bool is_old_static_regdom(const struct ieee80211_regdomain *rd)
{
return false;
}
#endif
static void reset_regdomains(void)
{
/* avoid freeing static information or freeing something twice */
if (cfg80211_regdomain == cfg80211_world_regdom)
cfg80211_regdomain = NULL;
if (cfg80211_world_regdom == &world_regdom)
cfg80211_world_regdom = NULL;
if (cfg80211_regdomain == &world_regdom)
cfg80211_regdomain = NULL;
if (is_old_static_regdom(cfg80211_regdomain))
cfg80211_regdomain = NULL;
kfree(cfg80211_regdomain);
kfree(cfg80211_world_regdom);
cfg80211_world_regdom = &world_regdom;
cfg80211_regdomain = NULL;
}
/* Dynamic world regulatory domain requested by the wireless
* core upon initialization */
static void update_world_regdomain(const struct ieee80211_regdomain *rd)
{
BUG_ON(list_empty(&regulatory_requests));
reset_regdomains();
cfg80211_world_regdom = rd;
cfg80211_regdomain = rd;
}
bool is_world_regdom(const char *alpha2)
{
if (!alpha2)
return false;
@ -60,7 +221,7 @@ bool is_world_regdom(char *alpha2)
return false;
}
static bool is_alpha2_set(char *alpha2)
static bool is_alpha2_set(const char *alpha2)
{
if (!alpha2)
return false;
@ -77,7 +238,7 @@ static bool is_alpha_upper(char letter)
return false;
}
static bool is_unknown_alpha2(char *alpha2)
static bool is_unknown_alpha2(const char *alpha2)
{
if (!alpha2)
return false;
@ -88,7 +249,7 @@ static bool is_unknown_alpha2(char *alpha2)
return false;
}
static bool is_an_alpha2(char *alpha2)
static bool is_an_alpha2(const char *alpha2)
{
if (!alpha2)
return false;
@ -97,7 +258,7 @@ static bool is_an_alpha2(char *alpha2)
return false;
}
static bool alpha2_equal(char *alpha2_x, char *alpha2_y)
static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y)
{
if (!alpha2_x || !alpha2_y)
return false;
@ -107,7 +268,7 @@ static bool alpha2_equal(char *alpha2_x, char *alpha2_y)
return false;
}
static bool regdom_changed(char *alpha2)
static bool regdom_changed(const char *alpha2)
{
if (!cfg80211_regdomain)
return true;
@ -130,12 +291,8 @@ static int call_crda(const char *alpha2)
printk(KERN_INFO "cfg80211: Calling CRDA for country: %c%c\n",
alpha2[0], alpha2[1]);
else
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
return -EINVAL;
#else
printk(KERN_INFO "cfg80211: Calling CRDA to update world "
"regulatory domain\n");
#endif
country_env[8] = alpha2[0];
country_env[9] = alpha2[1];
@ -238,7 +395,7 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
}
}
static bool __reg_is_valid_request(char *alpha2,
static bool __reg_is_valid_request(const char *alpha2,
struct regulatory_request **request)
{
struct regulatory_request *req;
@ -254,16 +411,16 @@ static bool __reg_is_valid_request(char *alpha2,
}
/* Used by nl80211 before kmalloc'ing our regulatory domain */
bool reg_is_valid_request(char *alpha2)
bool reg_is_valid_request(const char *alpha2)
{
struct regulatory_request *request = NULL;
return __reg_is_valid_request(alpha2, &request);
}
/* Sanity check on a regulatory rule */
static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule)
static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
{
struct ieee80211_freq_range *freq_range = &rule->freq_range;
const struct ieee80211_freq_range *freq_range = &rule->freq_range;
u32 freq_diff;
if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0)
@ -280,9 +437,9 @@ static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule)
return true;
}
static bool is_valid_rd(struct ieee80211_regdomain *rd)
static bool is_valid_rd(const struct ieee80211_regdomain *rd)
{
struct ieee80211_reg_rule *reg_rule = NULL;
const struct ieee80211_reg_rule *reg_rule = NULL;
unsigned int i;
if (!rd->n_reg_rules)
@ -494,12 +651,12 @@ unlock_and_exit:
EXPORT_SYMBOL(regulatory_hint);
static void print_rd_rules(struct ieee80211_regdomain *rd)
static void print_rd_rules(const struct ieee80211_regdomain *rd)
{
unsigned int i;
struct ieee80211_reg_rule *reg_rule = NULL;
struct ieee80211_freq_range *freq_range = NULL;
struct ieee80211_power_rule *power_rule = NULL;
const struct ieee80211_reg_rule *reg_rule = NULL;
const struct ieee80211_freq_range *freq_range = NULL;
const struct ieee80211_power_rule *power_rule = NULL;
printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), "
"(max_antenna_gain, max_eirp)\n");
@ -529,7 +686,7 @@ static void print_rd_rules(struct ieee80211_regdomain *rd)
}
}
static void print_regdomain(struct ieee80211_regdomain *rd)
static void print_regdomain(const struct ieee80211_regdomain *rd)
{
if (is_world_regdom(rd->alpha2))
@ -548,85 +705,25 @@ static void print_regdomain(struct ieee80211_regdomain *rd)
print_rd_rules(rd);
}
void print_regdomain_info(struct ieee80211_regdomain *rd)
void print_regdomain_info(const struct ieee80211_regdomain *rd)
{
printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n",
rd->alpha2[0], rd->alpha2[1]);
print_rd_rules(rd);
}
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
static bool is_old_static_regdom(struct ieee80211_regdomain *rd)
{
if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom)
return true;
return false;
}
/* The old crap never deals with a world regulatory domain, it only
* deals with the static regulatory domain passed and if possible
* an updated "US" or "JP" regulatory domain. We do however store the
* old static regulatory domain in cfg80211_world_regdom for convenience
* of use here */
static void reset_regdomains_static(void)
{
if (!is_old_static_regdom(cfg80211_regdomain))
kfree(cfg80211_regdomain);
/* This is setting the regdom to the old static regdom */
cfg80211_regdomain =
(struct ieee80211_regdomain *) cfg80211_world_regdom;
}
#else
static void reset_regdomains(void)
{
if (cfg80211_world_regdom && cfg80211_world_regdom != &world_regdom) {
if (cfg80211_world_regdom == cfg80211_regdomain) {
kfree(cfg80211_regdomain);
} else {
kfree(cfg80211_world_regdom);
kfree(cfg80211_regdomain);
}
} else if (cfg80211_regdomain && cfg80211_regdomain != &world_regdom)
kfree(cfg80211_regdomain);
cfg80211_world_regdom = (struct ieee80211_regdomain *) &world_regdom;
cfg80211_regdomain = NULL;
}
/* Dynamic world regulatory domain requested by the wireless
* core upon initialization */
static void update_world_regdomain(struct ieee80211_regdomain *rd)
{
BUG_ON(list_empty(&regulatory_requests));
reset_regdomains();
cfg80211_world_regdom = rd;
cfg80211_regdomain = rd;
}
#endif
static int __set_regdom(struct ieee80211_regdomain *rd)
static int __set_regdom(const struct ieee80211_regdomain *rd)
{
struct regulatory_request *request = NULL;
/* Some basic sanity checks first */
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
/* We ignore the world regdom with the old static regdomains setup
* as there is no point to it with satic regulatory definitions :(
* Don't worry this shit will be removed soon... */
if (is_world_regdom(rd->alpha2))
return -EINVAL;
#else
if (is_world_regdom(rd->alpha2)) {
if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request)))
return -EINVAL;
update_world_regdomain(rd);
return 0;
}
#endif
if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) &&
!is_unknown_alpha2(rd->alpha2))
@ -635,15 +732,10 @@ static int __set_regdom(struct ieee80211_regdomain *rd)
if (list_empty(&regulatory_requests))
return -EINVAL;
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
/* Static "US" and "JP" will be overridden, but just once */
/* allow overriding the static definitions if CRDA is present */
if (!is_old_static_regdom(cfg80211_regdomain) &&
!regdom_changed(rd->alpha2))
!regdom_changed(rd->alpha2))
return -EINVAL;
#else
if (!regdom_changed(rd->alpha2))
return -EINVAL;
#endif
/* Now lets set the regulatory domain, update all driver channels
* and finally inform them of what we have done, in case they want
@ -653,11 +745,7 @@ static int __set_regdom(struct ieee80211_regdomain *rd)
if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request)))
return -EINVAL;
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
reset_regdomains_static();
#else
reset_regdomains();
#endif
/* Country IE parsing coming soon */
switch (request->initiator) {
@ -689,7 +777,7 @@ static int __set_regdom(struct ieee80211_regdomain *rd)
* multiple drivers can be ironed out later. Caller must've already
* kmalloc'd the rd structure. If this calls fails you should kfree()
* the passed rd. Caller must hold cfg80211_drv_mutex */
int set_regdom(struct ieee80211_regdomain *rd)
int set_regdom(const struct ieee80211_regdomain *rd)
{
struct regulatory_request *this_request = NULL, *prev_request = NULL;
int r;
@ -735,25 +823,50 @@ int set_regdom(struct ieee80211_regdomain *rd)
int regulatory_init(void)
{
int err;
reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0);
if (IS_ERR(reg_pdev))
return PTR_ERR(reg_pdev);
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
cfg80211_regdomain = static_regdom(ieee80211_regdom);
printk(KERN_INFO "cfg80211: Using static regulatory domain info\n");
print_regdomain_info(cfg80211_regdomain);
/* The old code still requests for a new regdomain and if
* you have CRDA you get it updated, otherwise you get
* stuck with the static values. We ignore "EU" code as
* that is not a valid ISO / IEC 3166 alpha2 */
if (ieee80211_regdom[0] != 'E' && ieee80211_regdom[1] != 'U')
err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE,
ieee80211_regdom, NULL);
#else
cfg80211_regdomain = cfg80211_world_regdom;
err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL);
if (err)
printk(KERN_ERR "cfg80211: calling CRDA failed - "
"unable to update world regulatory domain, "
"using static definition\n");
#endif
return 0;
}
void regulatory_exit(void)
{
struct regulatory_request *req, *req_tmp;
mutex_lock(&cfg80211_drv_mutex);
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
reset_regdomains_static();
#else
reset_regdomains();
#endif
list_for_each_entry_safe(req, req_tmp, &regulatory_requests, list) {
list_del(&req->list);
kfree(req);
}
platform_device_unregister(reg_pdev);
mutex_unlock(&cfg80211_drv_mutex);
}

View File

@ -1,44 +1,13 @@
#ifndef __NET_WIRELESS_REG_H
#define __NET_WIRELESS_REG_H
extern const struct ieee80211_regdomain world_regdom;
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
extern const struct ieee80211_regdomain us_regdom;
extern const struct ieee80211_regdomain jp_regdom;
extern const struct ieee80211_regdomain eu_regdom;
#endif
extern struct ieee80211_regdomain *cfg80211_regdomain;
extern struct ieee80211_regdomain *cfg80211_world_regdom;
extern struct list_head regulatory_requests;
struct regdom_last_setby {
struct wiphy *wiphy;
u8 initiator;
};
/* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */
struct regulatory_request {
struct list_head list;
struct wiphy *wiphy;
int granted;
enum reg_set_by initiator;
char alpha2[2];
};
bool is_world_regdom(char *alpha2);
bool reg_is_valid_request(char *alpha2);
int set_regdom(struct ieee80211_regdomain *rd);
int __regulatory_hint_alpha2(struct wiphy *wiphy, enum reg_set_by set_by,
const char *alpha2);
extern struct mutex cfg80211_reg_mutex;
bool is_world_regdom(const char *alpha2);
bool reg_is_valid_request(const char *alpha2);
int regulatory_init(void);
void regulatory_exit(void);
void print_regdomain_info(struct ieee80211_regdomain *);
/* If a char is A-Z */
#define IS_ALPHA(letter) (letter >= 65 && letter <= 90)
int set_regdom(const struct ieee80211_regdomain *rd);
#endif /* __NET_WIRELESS_REG_H */