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

This commit is contained in:
David S. Miller 2008-12-12 22:20:51 -08:00
commit 56bde88590
98 changed files with 4550 additions and 1537 deletions

View File

@ -1099,9 +1099,9 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
if (ah->ah_combined_mic) {
key_v[0] = rxmic[0];
key_v[1] = (txmic[0] >> 16) & 0xffff;
key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16);
key_v[2] = rxmic[1];
key_v[3] = txmic[0] & 0xffff;
key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff);
key_v[4] = txmic[1];
} else {
key_v[0] = rxmic[0];

View File

@ -26,6 +26,7 @@
#define AR9160_DEVID_PCI 0x0027
#define AR9280_DEVID_PCI 0x0029
#define AR9280_DEVID_PCIE 0x002a
#define AR9285_DEVID_PCIE 0x002b
#define AR5416_AR9100_DEVID 0x000b

View File

@ -26,7 +26,7 @@ static int ath_beaconq_config(struct ath_softc *sc)
struct ath_hal *ah = sc->sc_ah;
struct ath9k_tx_queue_info qi;
ath9k_hw_get_txq_props(ah, sc->sc_bhalq, &qi);
ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP) {
/* Always burst out beacon and CAB traffic. */
qi.tqi_aifs = 1;
@ -34,17 +34,17 @@ static int ath_beaconq_config(struct ath_softc *sc)
qi.tqi_cwmax = 0;
} else {
/* Adhoc mode; important thing is to use 2x cwmin. */
qi.tqi_aifs = sc->sc_beacon_qi.tqi_aifs;
qi.tqi_cwmin = 2*sc->sc_beacon_qi.tqi_cwmin;
qi.tqi_cwmax = sc->sc_beacon_qi.tqi_cwmax;
qi.tqi_aifs = sc->beacon.beacon_qi.tqi_aifs;
qi.tqi_cwmin = 2*sc->beacon.beacon_qi.tqi_cwmin;
qi.tqi_cwmax = sc->beacon.beacon_qi.tqi_cwmax;
}
if (!ath9k_hw_set_txq_props(ah, sc->sc_bhalq, &qi)) {
if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
DPRINTF(sc, ATH_DBG_FATAL,
"unable to update h/w beacon queue parameters\n");
return 0;
} else {
ath9k_hw_resettxqueue(ah, sc->sc_bhalq); /* push to h/w */
ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); /* push to h/w */
return 1;
}
}
@ -53,7 +53,7 @@ static void ath_bstuck_process(struct ath_softc *sc)
{
DPRINTF(sc, ATH_DBG_BEACON,
"stuck beacon; resetting (bmiss count %u)\n",
sc->sc_bmisscount);
sc->beacon.bmisscnt);
ath_reset(sc, false);
}
@ -96,7 +96,7 @@ static void ath_beacon_setup(struct ath_softc *sc,
* SWBA's
* XXX assumes two antenna
*/
antenna = ((sc->ast_be_xmit / sc->sc_nbcnvaps) & 1 ? 2 : 1);
antenna = ((sc->beacon.ast_be_xmit / sc->sc_nbcnvaps) & 1 ? 2 : 1);
}
ds->ds_data = bf->bf_buf_addr;
@ -106,7 +106,7 @@ static void ath_beacon_setup(struct ath_softc *sc,
* XXX everything at min xmit rate
*/
rix = 0;
rt = sc->hw_rate_table[sc->sc_curmode];
rt = sc->cur_rate_table;
rate = rt->info[rix].ratecode;
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
rate |= rt->info[rix].short_preamble;
@ -153,7 +153,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
ASSERT(vif);
avp = (void *)vif->drv_priv;
cabq = sc->sc_cabq;
cabq = sc->beacon.cabq;
if (avp->av_bcbuf == NULL) {
DPRINTF(sc, ATH_DBG_BEACON, "avp=%p av_bcbuf=%p\n",
@ -167,6 +167,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
pci_unmap_single(sc->pdev, bf->bf_dmacontext,
skb->len,
PCI_DMA_TODEVICE);
dev_kfree_skb_any(skb);
}
skb = ieee80211_beacon_get(sc->hw, vif);
@ -181,9 +182,9 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
* TX frames)
*/
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
sc->seq_no += 0x10;
sc->tx.seq_no += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
}
bf->bf_buf_addr = bf->bf_dmacontext =
@ -269,10 +270,10 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
ath_beacon_setup(sc, avp, bf);
/* NB: caller is known to have already stopped tx dma */
ath9k_hw_puttxbuf(ah, sc->sc_bhalq, bf->bf_daddr);
ath9k_hw_txstart(ah, sc->sc_bhalq);
ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
ath9k_hw_txstart(ah, sc->beacon.beaconq);
DPRINTF(sc, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n",
sc->sc_bhalq, ito64(bf->bf_daddr), bf->bf_desc);
sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc);
}
int ath_beaconq_setup(struct ath_hal *ah)
@ -305,7 +306,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
if (!avp->av_bcbuf) {
/* Allocate beacon state for hostap/ibss. We know
* a buffer is available. */
avp->av_bcbuf = list_first_entry(&sc->sc_bbuf,
avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf,
struct ath_buf, list);
list_del(&avp->av_bcbuf->list);
@ -318,13 +319,13 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
*/
avp->av_bslot = 0;
for (slot = 0; slot < ATH_BCBUF; slot++)
if (sc->sc_bslot[slot] == ATH_IF_ID_ANY) {
if (sc->beacon.bslot[slot] == ATH_IF_ID_ANY) {
/*
* XXX hack, space out slots to better
* deal with misses
*/
if (slot+1 < ATH_BCBUF &&
sc->sc_bslot[slot+1] ==
sc->beacon.bslot[slot+1] ==
ATH_IF_ID_ANY) {
avp->av_bslot = slot+1;
break;
@ -332,8 +333,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
avp->av_bslot = slot;
/* NB: keep looking for a double slot */
}
BUG_ON(sc->sc_bslot[avp->av_bslot] != ATH_IF_ID_ANY);
sc->sc_bslot[avp->av_bslot] = if_id;
BUG_ON(sc->beacon.bslot[avp->av_bslot] != ATH_IF_ID_ANY);
sc->beacon.bslot[avp->av_bslot] = if_id;
sc->sc_nbcnvaps++;
}
}
@ -361,7 +362,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
}
tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
sc->bc_tstamp = le64_to_cpu(tstamp);
sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
/*
* Calculate a TSF adjustment factor required for
@ -421,7 +422,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
struct ath_buf *bf;
if (avp->av_bslot != -1) {
sc->sc_bslot[avp->av_bslot] = ATH_IF_ID_ANY;
sc->beacon.bslot[avp->av_bslot] = ATH_IF_ID_ANY;
sc->sc_nbcnvaps--;
}
@ -434,7 +435,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
}
list_add_tail(&bf->list, &sc->sc_bbuf);
list_add_tail(&bf->list, &sc->beacon.bbuf);
avp->av_bcbuf = NULL;
}
@ -468,18 +469,18 @@ void ath9k_beacon_tasklet(unsigned long data)
*
* FIXME: Clean up this mess !!
*/
if (ath9k_hw_numtxpending(ah, sc->sc_bhalq) != 0) {
sc->sc_bmisscount++;
if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
sc->beacon.bmisscnt++;
/* XXX: doth needs the chanchange IE countdown decremented.
* We should consider adding a mac80211 call to indicate
* a beacon miss so appropriate action could be taken
* (in that layer).
*/
if (sc->sc_bmisscount < BSTUCK_THRESH) {
if (sc->beacon.bmisscnt < BSTUCK_THRESH) {
if (sc->sc_flags & SC_OP_NO_RESET) {
DPRINTF(sc, ATH_DBG_BEACON,
"missed %u consecutive beacons\n",
sc->sc_bmisscount);
sc->beacon.bmisscnt);
if (show_cycles) {
/*
* Display cycle counter stats from HW
@ -498,11 +499,11 @@ void ath9k_beacon_tasklet(unsigned long data)
} else {
DPRINTF(sc, ATH_DBG_BEACON,
"missed %u consecutive beacons\n",
sc->sc_bmisscount);
sc->beacon.bmisscnt);
}
} else if (sc->sc_bmisscount >= BSTUCK_THRESH) {
} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
if (sc->sc_flags & SC_OP_NO_RESET) {
if (sc->sc_bmisscount == BSTUCK_THRESH) {
if (sc->beacon.bmisscnt == BSTUCK_THRESH) {
DPRINTF(sc, ATH_DBG_BEACON,
"beacon is officially "
"stuck\n");
@ -516,17 +517,17 @@ void ath9k_beacon_tasklet(unsigned long data)
return;
}
if (sc->sc_bmisscount != 0) {
if (sc->beacon.bmisscnt != 0) {
if (sc->sc_flags & SC_OP_NO_RESET) {
DPRINTF(sc, ATH_DBG_BEACON,
"resume beacon xmit after %u misses\n",
sc->sc_bmisscount);
sc->beacon.bmisscnt);
} else {
DPRINTF(sc, ATH_DBG_BEACON,
"resume beacon xmit after %u misses\n",
sc->sc_bmisscount);
sc->beacon.bmisscnt);
}
sc->sc_bmisscount = 0;
sc->beacon.bmisscnt = 0;
}
/*
@ -541,7 +542,7 @@ void ath9k_beacon_tasklet(unsigned long data)
tsf = ath9k_hw_gettsf64(ah);
tsftu = TSF_TO_TU(tsf>>32, tsf);
slot = ((tsftu % intval) * ATH_BCBUF) / intval;
if_id = sc->sc_bslot[(slot + 1) % ATH_BCBUF];
if_id = sc->beacon.bslot[(slot + 1) % ATH_BCBUF];
DPRINTF(sc, ATH_DBG_BEACON,
"slot %d [tsf %llu tsftu %u intval %u] if_id %d\n",
@ -573,12 +574,12 @@ void ath9k_beacon_tasklet(unsigned long data)
* set to ATH_BCBUF so this check is a noop.
*/
/* XXX locking */
if (sc->sc_updateslot == UPDATE) {
sc->sc_updateslot = COMMIT; /* commit next beacon */
sc->sc_slotupdate = slot;
} else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot) {
ath9k_hw_setslottime(sc->sc_ah, sc->sc_slottime);
sc->sc_updateslot = OK;
if (sc->beacon.updateslot == UPDATE) {
sc->beacon.updateslot = COMMIT; /* commit next beacon */
sc->beacon.slotupdate = slot;
} else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) {
ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime);
sc->beacon.updateslot = OK;
}
if (bfaddr != 0) {
/*
@ -586,17 +587,17 @@ void ath9k_beacon_tasklet(unsigned long data)
* This should never fail since we check above that no frames
* are still pending on the queue.
*/
if (!ath9k_hw_stoptxdma(ah, sc->sc_bhalq)) {
if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
DPRINTF(sc, ATH_DBG_FATAL,
"beacon queue %u did not stop?\n", sc->sc_bhalq);
"beacon queue %u did not stop?\n", sc->beacon.beaconq);
/* NB: the HAL still stops DMA, so proceed */
}
/* NB: cabq traffic should already be queued and primed */
ath9k_hw_puttxbuf(ah, sc->sc_bhalq, bfaddr);
ath9k_hw_txstart(ah, sc->sc_bhalq);
ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
ath9k_hw_txstart(ah, sc->beacon.beaconq);
sc->ast_be_xmit += bc; /* XXX per-vap? */
sc->beacon.ast_be_xmit += bc; /* XXX per-vap? */
}
}
@ -643,7 +644,7 @@ 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(sc->bc_tstamp >> 32, sc->bc_tstamp);
nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp);
/* XXX conditionalize multi-bss support? */
if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP) {
@ -830,7 +831,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
ath_beaconq_config(sc);
}
ath9k_hw_beaconinit(ah, nexttbtt, intval);
sc->sc_bmisscount = 0;
sc->beacon.bmisscnt = 0;
ath9k_hw_set_interrupts(ah, sc->sc_imask);
/*
* When using a self-linked beacon descriptor in

View File

@ -818,6 +818,101 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
return true;
}
static inline void ath9k_hw_9285_pa_cal(struct ath_hal *ah)
{
u32 regVal;
int i, offset, offs_6_1, offs_0;
u32 ccomp_org, reg_field;
u32 regList[][2] = {
{ 0x786c, 0 },
{ 0x7854, 0 },
{ 0x7820, 0 },
{ 0x7824, 0 },
{ 0x7868, 0 },
{ 0x783c, 0 },
{ 0x7838, 0 },
};
if (AR_SREV_9285_11(ah)) {
REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
udelay(10);
}
for (i = 0; i < ARRAY_SIZE(regList); i++)
regList[i][1] = REG_READ(ah, regList[i][0]);
regVal = REG_READ(ah, 0x7834);
regVal &= (~(0x1));
REG_WRITE(ah, 0x7834, regVal);
regVal = REG_READ(ah, 0x9808);
regVal |= (0x1 << 27);
REG_WRITE(ah, 0x9808, regVal);
REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 1);
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 7);
REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
udelay(30);
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
for (i = 6; i > 0; i--) {
regVal = REG_READ(ah, 0x7834);
regVal |= (1 << (19 + i));
REG_WRITE(ah, 0x7834, regVal);
udelay(1);
regVal = REG_READ(ah, 0x7834);
regVal &= (~(0x1 << (19 + i)));
reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
regVal |= (reg_field << (19 + i));
REG_WRITE(ah, 0x7834, regVal);
}
REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
udelay(1);
reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
offset = (offs_6_1<<1) | offs_0;
offset = offset - 0;
offs_6_1 = offset>>1;
offs_0 = offset & 1;
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
regVal = REG_READ(ah, 0x7834);
regVal |= 0x1;
REG_WRITE(ah, 0x7834, regVal);
regVal = REG_READ(ah, 0x9808);
regVal &= (~(0x1 << 27));
REG_WRITE(ah, 0x9808, regVal);
for (i = 0; i < ARRAY_SIZE(regList); i++)
REG_WRITE(ah, regList[i][0], regList[i][1]);
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
if (AR_SREV_9285_11(ah))
REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
}
bool ath9k_hw_init_cal(struct ath_hal *ah,
struct ath9k_channel *chan)
{
@ -835,6 +930,9 @@ bool ath9k_hw_init_cal(struct ath_hal *ah,
return false;
}
if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
ath9k_hw_9285_pa_cal(ah);
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
REG_READ(ah, AR_PHY_AGC_CONTROL) |
AR_PHY_AGC_CONTROL_NF);

View File

@ -61,7 +61,7 @@ struct ath_node;
#define TSF_TO_TU(_h,_l) \
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
#define ATH_TXQ_SETUP(sc, i) ((sc)->sc_txqsetup & (1<<i))
#define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i))
static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
@ -88,16 +88,66 @@ enum ATH_DEBUG {
#ifdef CONFIG_ATH9K_DEBUG
/**
* struct ath_interrupt_stats - Contains statistics about interrupts
* @total: Total no. of interrupts generated so far
* @rxok: RX with no errors
* @rxeol: RX with no more RXDESC available
* @rxorn: RX FIFO overrun
* @txok: TX completed at the requested rate
* @txurn: TX FIFO underrun
* @mib: MIB regs reaching its threshold
* @rxphyerr: RX with phy errors
* @rx_keycache_miss: RX with key cache misses
* @swba: Software Beacon Alert
* @bmiss: Beacon Miss
* @bnr: Beacon Not Ready
* @cst: Carrier Sense TImeout
* @gtt: Global TX Timeout
* @tim: RX beacon TIM occurrence
* @cabend: RX End of CAB traffic
* @dtimsync: DTIM sync lossage
* @dtim: RX Beacon with DTIM
*/
struct ath_interrupt_stats {
u32 total;
u32 rxok;
u32 rxeol;
u32 rxorn;
u32 txok;
u32 txeol;
u32 txurn;
u32 mib;
u32 rxphyerr;
u32 rx_keycache_miss;
u32 swba;
u32 bmiss;
u32 bnr;
u32 cst;
u32 gtt;
u32 tim;
u32 cabend;
u32 dtimsync;
u32 dtim;
};
struct ath_stats {
struct ath_interrupt_stats istats;
};
struct ath9k_debug {
int debug_mask;
struct dentry *debugfs_root;
struct dentry *debugfs_phy;
struct dentry *debugfs_dma;
struct dentry *debugfs_interrupt;
struct ath_stats stats;
};
void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...);
int ath9k_init_debug(struct ath_softc *sc);
void ath9k_exit_debug(struct ath_softc *sc);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
#else
@ -115,6 +165,11 @@ static inline void ath9k_exit_debug(struct ath_softc *sc)
{
}
static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
enum ath9k_int status)
{
}
#endif /* CONFIG_ATH9K_DEBUG */
struct ath_config {
@ -235,18 +290,9 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
/* RX / TX */
/***********/
#define ATH_MAX_ANTENNA 3
#define ATH_RXBUF 512
#define WME_NUM_TID 16
int ath_startrecv(struct ath_softc *sc);
bool ath_stoprecv(struct ath_softc *sc);
void ath_flushrecv(struct ath_softc *sc);
u32 ath_calcrxfilter(struct ath_softc *sc);
int ath_rx_init(struct ath_softc *sc, int nbufs);
void ath_rx_cleanup(struct ath_softc *sc);
int ath_rx_tasklet(struct ath_softc *sc, int flush);
#define ATH_MAX_ANTENNA 3
#define ATH_RXBUF 512
#define WME_NUM_TID 16
#define ATH_TXBUF 512
#define ATH_TXMAXTRY 13
#define ATH_11N_TXMAXTRY 10
@ -254,19 +300,61 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush);
#define WME_BA_BMP_SIZE 64
#define WME_MAX_BA WME_BA_BMP_SIZE
#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
#define TID_TO_WME_AC(_tid) \
((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
(((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
(((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
WME_AC_VO)
#define WME_AC_BE 0
#define WME_AC_BK 1
#define WME_AC_VI 2
#define WME_AC_VO 3
#define WME_NUM_AC 4
#define ADDBA_EXCHANGE_ATTEMPTS 10
#define ATH_AGGR_DELIM_SZ 4
#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
/* number of delimiters for encryption padding */
#define ATH_AGGR_ENCRYPTDELIM 10
/* minimum h/w qdepth to be sustained to maximize aggregation */
#define ATH_AGGR_MIN_QDEPTH 2
#define ATH_AMPDU_SUBFRAME_DEFAULT 32
#define IEEE80211_SEQ_SEQ_SHIFT 4
#define IEEE80211_SEQ_MAX 4096
#define IEEE80211_MIN_AMPDU_BUF 0x8
#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
/* return whether a bit at index _n in bitmap _bm is set
* _sz is the size of the bitmap */
#define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \
((_bm)[(_n) >> 5] & (1 << ((_n) & 31))))
/* return block-ack bitmap index given sequence and starting sequence */
#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
/* returns delimiter padding required given the packet length */
#define ATH_AGGR_GET_NDELIM(_len) \
(((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \
(ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
#define BAW_WITHIN(_start, _bawsz, _seqno) \
((((_seqno) - (_start)) & 4095) < (_bawsz))
#define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum)
#define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low)
#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA)
#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)])
enum ATH_AGGR_STATUS {
ATH_AGGR_DONE,
ATH_AGGR_BAW_CLOSED,
ATH_AGGR_LIMITED,
ATH_AGGR_SHORTPKT,
ATH_AGGR_8K_LIMITED,
};
struct ath_txq {
u32 axq_qnum; /* hardware q number */
u32 *axq_link; /* link ptr in last TX desc */
@ -276,7 +364,6 @@ struct ath_txq {
u32 axq_depth; /* queue depth */
u8 axq_aggr_depth; /* aggregates queued */
u32 axq_totalqueued; /* total ever queued */
bool stopped; /* Is mac80211 queue stopped ? */
struct ath_buf *axq_linkbuf; /* virtual addr of last buffer*/
@ -322,12 +409,6 @@ struct ath_atx_ac {
struct list_head tid_q; /* queue of TIDs with buffers */
};
/* per dest tx state */
struct ath_atx {
struct ath_atx_tid tid[WME_NUM_TID];
struct ath_atx_ac ac[WME_NUM_AC];
};
/* per-frame tx control block */
struct ath_tx_control {
struct ath_txq *txq;
@ -353,13 +434,54 @@ struct ath_tx_stat {
int rateKbps;
int ratecode;
int flags;
/* if any of ctl,extn chain rssis are valid */
#define ATH_TX_CHAIN_RSSI_VALID 0x01
/* if extn chain rssis are valid */
#define ATH_TX_RSSI_EXTN_VALID 0x02
u32 airtime; /* time on air per final tx rate */
};
struct aggr_rifs_param {
int param_max_frames;
int param_max_len;
int param_rl;
int param_al;
struct ath_rc_series *param_rcs;
};
struct ath_node {
struct ath_softc *an_sc;
struct ath_atx_tid tid[WME_NUM_TID];
struct ath_atx_ac ac[WME_NUM_AC];
u16 maxampdu;
u8 mpdudensity;
};
struct ath_tx {
u16 seq_no;
u32 txqsetup;
int hwq_map[ATH9K_WME_AC_VO+1];
spinlock_t txbuflock;
struct list_head txbuf;
struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
struct ath_descdma txdma;
};
struct ath_rx {
u8 defant;
u8 rxotherant;
u32 *rxlink;
int bufsize;
unsigned int rxfilter;
spinlock_t rxflushlock;
spinlock_t rxbuflock;
struct list_head rxbuf;
struct ath_descdma rxdma;
};
int ath_startrecv(struct ath_softc *sc);
bool ath_stoprecv(struct ath_softc *sc);
void ath_flushrecv(struct ath_softc *sc);
u32 ath_calcrxfilter(struct ath_softc *sc);
int ath_rx_init(struct ath_softc *sc, int nbufs);
void ath_rx_cleanup(struct ath_softc *sc);
int ath_rx_tasklet(struct ath_softc *sc, int flush);
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
int ath_tx_setup(struct ath_softc *sc, int haltype);
@ -382,73 +504,6 @@ void ath_tx_tasklet(struct ath_softc *sc);
u32 ath_txq_depth(struct ath_softc *sc, int qnum);
u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum);
void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
/**********************/
/* Node / Aggregation */
/**********************/
#define ADDBA_EXCHANGE_ATTEMPTS 10
#define ATH_AGGR_DELIM_SZ 4
#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
/* number of delimiters for encryption padding */
#define ATH_AGGR_ENCRYPTDELIM 10
/* minimum h/w qdepth to be sustained to maximize aggregation */
#define ATH_AGGR_MIN_QDEPTH 2
#define ATH_AMPDU_SUBFRAME_DEFAULT 32
#define IEEE80211_SEQ_SEQ_SHIFT 4
#define IEEE80211_SEQ_MAX 4096
#define IEEE80211_MIN_AMPDU_BUF 0x8
#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
/* return whether a bit at index _n in bitmap _bm is set
* _sz is the size of the bitmap */
#define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \
((_bm)[(_n) >> 5] & (1 << ((_n) & 31))))
/* return block-ack bitmap index given sequence and starting sequence */
#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
/* returns delimiter padding required given the packet length */
#define ATH_AGGR_GET_NDELIM(_len) \
(((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \
(ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
#define BAW_WITHIN(_start, _bawsz, _seqno) \
((((_seqno) - (_start)) & 4095) < (_bawsz))
#define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum)
#define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low)
#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA)
#define ATH_AN_2_TID(_an, _tidno) (&(_an)->an_aggr.tx.tid[(_tidno)])
enum ATH_AGGR_STATUS {
ATH_AGGR_DONE,
ATH_AGGR_BAW_CLOSED,
ATH_AGGR_LIMITED,
ATH_AGGR_SHORTPKT,
ATH_AGGR_8K_LIMITED,
};
struct aggr_rifs_param {
int param_max_frames;
int param_max_len;
int param_rl;
int param_al;
struct ath_rc_series *param_rcs;
};
/* Per-node aggregation state */
struct ath_node_aggr {
struct ath_atx tx;
};
struct ath_node {
struct ath_softc *an_sc;
struct ath_node_aggr an_aggr;
u16 maxampdu;
u8 mpdudensity;
};
void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
void ath_tx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tidno);
@ -489,7 +544,7 @@ struct ath_vap {
* number of beacon intervals, the game's up.
*/
#define BSTUCK_THRESH (9 * ATH_BCBUF)
#define ATH_BCBUF 4
#define ATH_BCBUF 1
#define ATH_DEFAULT_BINTVAL 100 /* TU */
#define ATH_DEFAULT_BMISS_LIMIT 10
#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024)
@ -507,6 +562,26 @@ struct ath_beacon_config {
} u; /* last received beacon/probe response timestamp of this BSS. */
};
struct ath_beacon {
enum {
OK, /* no change needed */
UPDATE, /* update pending */
COMMIT /* beacon sent, commit change */
} updateslot; /* slot time update fsm */
u32 beaconq;
u32 bmisscnt;
u32 ast_be_xmit;
u64 bc_tstamp;
int bslot[ATH_BCBUF];
int slottime;
int slotupdate;
struct ath9k_tx_queue_info beacon_qi;
struct ath_descdma bdma;
struct ath_txq *cabq;
struct list_head bbuf;
};
void ath9k_beacon_tasklet(unsigned long data);
void ath_beacon_config(struct ath_softc *sc, int if_id);
int ath_beaconq_setup(struct ath_hal *ah);
@ -577,7 +652,7 @@ struct ath_rfkill {
#define DEFAULT_CACHELINE 32
#define ATH_DEFAULT_NOISE_FLOOR -95
#define ATH_REGCLASSIDS_MAX 10
#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
#define ATH_MAX_SW_RETRIES 10
#define ATH_CHAN_MAX 255
#define IEEE80211_WEP_NKID 4 /* number of key ids */
@ -590,7 +665,7 @@ struct ath_rfkill {
* Different parts have different size key caches. We handle
* up to ATH_KEYMAX entries (could dynamically allocate state).
*/
#define ATH_KEYMAX 128 /* max key cache size we handle */
#define ATH_KEYMAX 128 /* max key cache size we handle */
#define ATH_IF_ID_ANY 0xff
#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
@ -623,108 +698,51 @@ struct ath_softc {
struct pci_dev *pdev;
struct tasklet_struct intr_tq;
struct tasklet_struct bcon_tasklet;
struct ath_config sc_config;
struct ath_hal *sc_ah;
void __iomem *mem;
spinlock_t sc_resetlock;
u8 sc_curbssid[ETH_ALEN];
u8 sc_myaddr[ETH_ALEN];
u8 sc_bssidmask[ETH_ALEN];
#ifdef CONFIG_ATH9K_DEBUG
struct ath9k_debug sc_debug;
#endif
u32 sc_intrstatus;
u32 sc_flags; /* SC_OP_* */
unsigned int rx_filter;
u16 sc_curtxpow;
u16 sc_curaid;
u16 sc_cachelsz;
int sc_slotupdate; /* slot to next advance fsm */
int sc_slottime;
int sc_bslot[ATH_BCBUF];
u8 sc_tx_chainmask;
u8 sc_rx_chainmask;
enum ath9k_int sc_imask;
enum wireless_mode sc_curmode;
enum PROT_MODE sc_protmode;
u8 sc_nbcnvaps;
u16 sc_nvaps;
struct ieee80211_vif *sc_vaps[ATH_BCBUF];
u8 sc_mcastantenna;
u8 sc_defant;
u8 sc_rxotherant;
struct ath9k_node_stats sc_halstats;
u8 sc_tx_chainmask;
u8 sc_rx_chainmask;
u32 sc_keymax;
DECLARE_BITMAP(sc_keymap, ATH_KEYMAX);
u8 sc_splitmic;
u8 sc_protrix;
enum ath9k_int sc_imask;
enum PROT_MODE sc_protmode;
enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
enum ath9k_ht_macmode tx_chan_width;
#ifdef CONFIG_SLOW_ANT_DIV
struct ath_antdiv sc_antdiv;
#endif
enum {
OK, /* no change needed */
UPDATE, /* update pending */
COMMIT /* beacon sent, commit change */
} sc_updateslot; /* slot time update fsm */
/* Crypto */
u32 sc_keymax;
DECLARE_BITMAP(sc_keymap, ATH_KEYMAX);
u8 sc_splitmic; /* split TKIP MIC keys */
/* RX */
struct list_head sc_rxbuf;
struct ath_descdma sc_rxdma;
int sc_rxbufsize;
u32 *sc_rxlink;
/* TX */
struct list_head sc_txbuf;
struct ath_txq sc_txq[ATH9K_NUM_TX_QUEUES];
struct ath_descdma sc_txdma;
u32 sc_txqsetup;
int sc_haltype2q[ATH9K_WME_AC_VO+1];
u16 seq_no; /* TX sequence number */
/* Beacon */
struct ath9k_tx_queue_info sc_beacon_qi;
struct ath_descdma sc_bdma;
struct ath_txq *sc_cabq;
struct list_head sc_bbuf;
u32 sc_bhalq;
u32 sc_bmisscount;
u32 ast_be_xmit;
u64 bc_tstamp;
/* Rate */
struct ath_config sc_config;
struct ath_rx rx;
struct ath_tx tx;
struct ath_beacon beacon;
struct ieee80211_vif *sc_vaps[ATH_BCBUF];
struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX];
u8 sc_protrix;
/* Channel, Band */
struct ath_rate_table *cur_rate_table;
struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX];
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
/* Locks */
spinlock_t sc_rxflushlock;
spinlock_t sc_rxbuflock;
spinlock_t sc_txbuflock;
spinlock_t sc_resetlock;
/* LEDs */
struct ath_led radio_led;
struct ath_led assoc_led;
struct ath_led tx_led;
struct ath_led rx_led;
/* Rfkill */
struct ath_rfkill rf_kill;
/* ANI */
struct ath_ani sc_ani;
struct ath9k_node_stats sc_halstats;
#ifdef CONFIG_ATH9K_DEBUG
struct ath9k_debug sc_debug;
#endif
};
int ath_reset(struct ath_softc *sc, bool retry_tx);

View File

@ -128,6 +128,100 @@ static const struct file_operations fops_dma = {
.owner = THIS_MODULE
};
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
{
if (status)
sc->sc_debug.stats.istats.total++;
if (status & ATH9K_INT_RX)
sc->sc_debug.stats.istats.rxok++;
if (status & ATH9K_INT_RXEOL)
sc->sc_debug.stats.istats.rxeol++;
if (status & ATH9K_INT_RXORN)
sc->sc_debug.stats.istats.rxorn++;
if (status & ATH9K_INT_TX)
sc->sc_debug.stats.istats.txok++;
if (status & ATH9K_INT_TXURN)
sc->sc_debug.stats.istats.txurn++;
if (status & ATH9K_INT_MIB)
sc->sc_debug.stats.istats.mib++;
if (status & ATH9K_INT_RXPHY)
sc->sc_debug.stats.istats.rxphyerr++;
if (status & ATH9K_INT_RXKCM)
sc->sc_debug.stats.istats.rx_keycache_miss++;
if (status & ATH9K_INT_SWBA)
sc->sc_debug.stats.istats.swba++;
if (status & ATH9K_INT_BMISS)
sc->sc_debug.stats.istats.bmiss++;
if (status & ATH9K_INT_BNR)
sc->sc_debug.stats.istats.bnr++;
if (status & ATH9K_INT_CST)
sc->sc_debug.stats.istats.cst++;
if (status & ATH9K_INT_GTT)
sc->sc_debug.stats.istats.gtt++;
if (status & ATH9K_INT_TIM)
sc->sc_debug.stats.istats.tim++;
if (status & ATH9K_INT_CABEND)
sc->sc_debug.stats.istats.cabend++;
if (status & ATH9K_INT_DTIMSYNC)
sc->sc_debug.stats.istats.dtimsync++;
if (status & ATH9K_INT_DTIM)
sc->sc_debug.stats.istats.dtim++;
}
static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char buf[512];
unsigned int len = 0;
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "RX", sc->sc_debug.stats.istats.rxok);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "RXEOL", sc->sc_debug.stats.istats.rxeol);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "RXORN", sc->sc_debug.stats.istats.rxorn);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "TX", sc->sc_debug.stats.istats.txok);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "TXURN", sc->sc_debug.stats.istats.txurn);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "MIB", sc->sc_debug.stats.istats.mib);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "RXPHY", sc->sc_debug.stats.istats.rxphyerr);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "RXKCM", sc->sc_debug.stats.istats.rx_keycache_miss);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "SWBA", sc->sc_debug.stats.istats.swba);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "BMISS", sc->sc_debug.stats.istats.bmiss);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "BNR", sc->sc_debug.stats.istats.bnr);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "CST", sc->sc_debug.stats.istats.cst);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "GTT", sc->sc_debug.stats.istats.gtt);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "TIM", sc->sc_debug.stats.istats.tim);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "CABEND", sc->sc_debug.stats.istats.cabend);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "DTIMSYNC", sc->sc_debug.stats.istats.dtimsync);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "DTIM", sc->sc_debug.stats.istats.dtim);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "TOTAL", sc->sc_debug.stats.istats.total);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static const struct file_operations fops_interrupt = {
.read = read_file_interrupt,
.open = ath9k_debugfs_open,
.owner = THIS_MODULE
};
int ath9k_init_debug(struct ath_softc *sc)
{
sc->sc_debug.debug_mask = ath9k_debug;
@ -146,6 +240,13 @@ int ath9k_init_debug(struct ath_softc *sc)
if (!sc->sc_debug.debugfs_dma)
goto err;
sc->sc_debug.debugfs_interrupt = debugfs_create_file("interrupt",
S_IRUGO,
sc->sc_debug.debugfs_phy,
sc, &fops_interrupt);
if (!sc->sc_debug.debugfs_interrupt)
goto err;
return 0;
err:
ath9k_exit_debug(sc);
@ -154,6 +255,7 @@ err:
void ath9k_exit_debug(struct ath_softc *sc)
{
debugfs_remove(sc->sc_debug.debugfs_interrupt);
debugfs_remove(sc->sc_debug.debugfs_dma);
debugfs_remove(sc->sc_debug.debugfs_phy);
debugfs_remove(sc->sc_debug.debugfs_root);

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hal *ah, u32 type);
static void ath9k_hw_set_regs(struct ath_hal *ah, struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode);
static u32 ath9k_hw_ini_fixup(struct ath_hal *ah,
struct ar5416_eeprom *pEepData,
struct ar5416_eeprom_def *pEepData,
u32 reg, u32 value);
static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *chan);
static void ath9k_hw_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *chan);
@ -392,6 +392,8 @@ static const char *ath9k_hw_devname(u16 devid)
case AR9280_DEVID_PCI:
case AR9280_DEVID_PCIE:
return "Atheros 9280";
case AR9285_DEVID_PCIE:
return "Atheros 9285";
}
return NULL;
@ -640,10 +642,7 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
struct ath_hal_5416 *ahp;
struct ath_hal *ah;
int ecode;
#ifndef CONFIG_SLOW_ANT_DIV
u32 i;
u32 j;
#endif
u32 i, j;
ahp = ath9k_hw_newstate(devid, sc, mem, status);
if (ahp == NULL)
@ -685,7 +684,7 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
if ((ah->ah_macVersion != AR_SREV_VERSION_5416_PCI) &&
(ah->ah_macVersion != AR_SREV_VERSION_5416_PCIE) &&
(ah->ah_macVersion != AR_SREV_VERSION_9160) &&
(!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah))) {
(!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) {
DPRINTF(ah->ah_sc, ATH_DBG_RESET,
"Mac Chip Rev 0x%02x.%x is not supported by "
"this driver\n", ah->ah_macVersion, ah->ah_macRev);
@ -736,7 +735,38 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
"This Mac Chip Rev 0x%02x.%x is \n",
ah->ah_macVersion, ah->ah_macRev);
if (AR_SREV_9280_20_OR_LATER(ah)) {
if (AR_SREV_9285_12_OR_LATER(ah)) {
INIT_INI_ARRAY(&ahp->ah_iniModes, ar9285Modes_9285_1_2,
ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9285Common_9285_1_2,
ARRAY_SIZE(ar9285Common_9285_1_2), 2);
if (ah->ah_config.pcie_clock_req) {
INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
ar9285PciePhy_clkreq_off_L1_9285_1_2,
ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2);
} else {
INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
ar9285PciePhy_clkreq_always_on_L1_9285_1_2,
ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2),
2);
}
} else if (AR_SREV_9285_10_OR_LATER(ah)) {
INIT_INI_ARRAY(&ahp->ah_iniModes, ar9285Modes_9285,
ARRAY_SIZE(ar9285Modes_9285), 6);
INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9285Common_9285,
ARRAY_SIZE(ar9285Common_9285), 2);
if (ah->ah_config.pcie_clock_req) {
INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
ar9285PciePhy_clkreq_off_L1_9285,
ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2);
} else {
INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
ar9285PciePhy_clkreq_always_on_L1_9285,
ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2);
}
} else if (AR_SREV_9280_20_OR_LATER(ah)) {
INIT_INI_ARRAY(&ahp->ah_iniModes, ar9280Modes_9280_2,
ARRAY_SIZE(ar9280Modes_9280_2), 6);
INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9280Common_9280_2,
@ -846,14 +876,13 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
goto bad;
/* rxgain table */
if (AR_SREV_9280_20_OR_LATER(ah))
if (AR_SREV_9280_20(ah))
ath9k_hw_init_rxgain_ini(ah);
/* txgain table */
if (AR_SREV_9280_20_OR_LATER(ah))
if (AR_SREV_9280_20(ah))
ath9k_hw_init_txgain_ini(ah);
#ifndef CONFIG_SLOW_ANT_DIV
if (ah->ah_devid == AR9280_DEVID_PCI) {
for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) {
u32 reg = INI_RA(&ahp->ah_iniModes, i, 0);
@ -862,12 +891,13 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
u32 val = INI_RA(&ahp->ah_iniModes, i, j);
INI_RA(&ahp->ah_iniModes, i, j) =
ath9k_hw_ini_fixup(ah, &ahp->ah_eeprom,
ath9k_hw_ini_fixup(ah,
&ahp->ah_eeprom.def,
reg, val);
}
}
}
#endif
if (!ath9k_hw_fill_cap_info(ah)) {
DPRINTF(ah->ah_sc, ATH_DBG_RESET,
"failed ath9k_hw_fill_cap_info\n");
@ -1020,8 +1050,6 @@ static void ath9k_hw_init_chain_masks(struct ath_hal *ah)
}
case 0x1:
case 0x2:
if (!AR_SREV_9280(ah))
break;
case 0x7:
REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
@ -1166,12 +1194,10 @@ struct ath_hal *ath9k_hw_attach(u16 devid, struct ath_softc *sc,
case AR9160_DEVID_PCI:
case AR9280_DEVID_PCI:
case AR9280_DEVID_PCIE:
case AR9285_DEVID_PCIE:
ah = ath9k_hw_do_attach(devid, sc, mem, error);
break;
default:
DPRINTF(ah->ah_sc, ATH_DBG_ANY,
"devid=0x%x not supported.\n", devid);
ah = NULL;
*error = -ENXIO;
break;
}
@ -1186,6 +1212,14 @@ struct ath_hal *ath9k_hw_attach(u16 devid, struct ath_softc *sc,
static void ath9k_hw_override_ini(struct ath_hal *ah,
struct ath9k_channel *chan)
{
/*
* Set the RX_ABORT and RX_DIS and clear if off only after
* RXE is set for MAC. This prevents frames with corrupted
* descriptor status.
*/
REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
if (!AR_SREV_5416_V20_OR_LATER(ah) ||
AR_SREV_9280_10_OR_LATER(ah))
return;
@ -1193,8 +1227,8 @@ static void ath9k_hw_override_ini(struct ath_hal *ah,
REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
}
static u32 ath9k_hw_ini_fixup(struct ath_hal *ah,
struct ar5416_eeprom *pEepData,
static u32 ath9k_hw_def_ini_fixup(struct ath_hal *ah,
struct ar5416_eeprom_def *pEepData,
u32 reg, u32 value)
{
struct base_eep_header *pBase = &(pEepData->baseEepHeader);
@ -1227,6 +1261,18 @@ static u32 ath9k_hw_ini_fixup(struct ath_hal *ah,
return value;
}
static u32 ath9k_hw_ini_fixup(struct ath_hal *ah,
struct ar5416_eeprom_def *pEepData,
u32 reg, u32 value)
{
struct ath_hal_5416 *ahp = AH5416(ah);
if (ahp->ah_eep_map == EEP_MAP_4KBITS)
return value;
else
return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value);
}
static int ath9k_hw_process_ini(struct ath_hal *ah,
struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode)
@ -1294,11 +1340,6 @@ static int ath9k_hw_process_ini(struct ath_hal *ah,
u32 reg = INI_RA(&ahp->ah_iniModes, i, 0);
u32 val = INI_RA(&ahp->ah_iniModes, i, modesIndex);
#ifdef CONFIG_SLOW_ANT_DIV
if (ah->ah_devid == AR9280_DEVID_PCI)
val = ath9k_hw_ini_fixup(ah, &ahp->ah_eeprom, reg, val);
#endif
REG_WRITE(ah, reg, val);
if (reg >= 0x7800 && reg < 0x78a0
@ -1309,10 +1350,10 @@ static int ath9k_hw_process_ini(struct ath_hal *ah,
DO_DELAY(regWrites);
}
if (AR_SREV_9280_20_OR_LATER(ah))
if (AR_SREV_9280(ah))
REG_WRITE_ARRAY(&ahp->ah_iniModesRxGain, modesIndex, regWrites);
if (AR_SREV_9280_20_OR_LATER(ah))
if (AR_SREV_9280(ah))
REG_WRITE_ARRAY(&ahp->ah_iniModesTxGain, modesIndex, regWrites);
for (i = 0; i < ahp->ah_iniCommon.ia_rows; i++) {
@ -1585,10 +1626,15 @@ static void ath9k_hw_set_regs(struct ath_hal *ah, struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode)
{
u32 phymode;
u32 enableDacFifo = 0;
struct ath_hal_5416 *ahp = AH5416(ah);
if (AR_SREV_9285_10_OR_LATER(ah))
enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
AR_PHY_FC_ENABLE_DAC_FIFO);
phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
| AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH;
| AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo;
if (IS_CHAN_HT40(chan)) {
phymode |= AR_PHY_FC_DYN2040_EN;
@ -2771,11 +2817,14 @@ void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore)
if (ah->ah_config.pcie_waen) {
REG_WRITE(ah, AR_WA, ah->ah_config.pcie_waen);
} else {
if (AR_SREV_9280(ah))
REG_WRITE(ah, AR_WA, 0x0040073f);
if (AR_SREV_9285(ah))
REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
else if (AR_SREV_9280(ah))
REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT);
else
REG_WRITE(ah, AR_WA, 0x0000073f);
REG_WRITE(ah, AR_WA, AR_WA_DEFAULT);
}
}
/**********************/
@ -3326,7 +3375,7 @@ bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
else
pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
if (AR_SREV_9280(ah))
if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
else
pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
@ -3346,9 +3395,9 @@ bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
pCap->num_antcfg_5ghz =
ath9k_hw_get_num_ant_config(ah, IEEE80211_BAND_5GHZ);
ath9k_hw_get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ);
pCap->num_antcfg_2ghz =
ath9k_hw_get_num_ant_config(ah, IEEE80211_BAND_2GHZ);
ath9k_hw_get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
return true;
}

View File

@ -448,6 +448,17 @@ struct ar5416Stats {
#define AR5416_EEP_TXGAIN_ORIGINAL 0
#define AR5416_EEP_TXGAIN_HIGH_POWER 1
#define AR5416_EEP4K_START_LOC 64
#define AR5416_EEP4K_NUM_2G_CAL_PIERS 3
#define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3
#define AR5416_EEP4K_NUM_2G_20_TARGET_POWERS 3
#define AR5416_EEP4K_NUM_2G_40_TARGET_POWERS 3
#define AR5416_EEP4K_NUM_CTLS 12
#define AR5416_EEP4K_NUM_BAND_EDGES 4
#define AR5416_EEP4K_NUM_PD_GAINS 2
#define AR5416_EEP4K_PD_GAINS_IN_MASK 4
#define AR5416_EEP4K_PD_GAIN_ICEPTS 5
#define AR5416_EEP4K_MAX_CHAINS 1
enum eeprom_param {
EEP_NFTHRESH_5,
@ -484,6 +495,11 @@ enum ar5416_rates {
Ar5416RateSize
};
enum ath9k_hal_freq_band {
ATH9K_HAL_FREQ_BAND_5GHZ = 0,
ATH9K_HAL_FREQ_BAND_2GHZ = 1
};
struct base_eep_header {
u16 length;
u16 checksum;
@ -507,6 +523,25 @@ struct base_eep_header {
u8 futureBase_3[25];
} __packed;
struct base_eep_header_4k {
u16 length;
u16 checksum;
u16 version;
u8 opCapFlags;
u8 eepMisc;
u16 regDmn[2];
u8 macAddr[6];
u8 rxMask;
u8 txMask;
u16 rfSilent;
u16 blueToothOptions;
u16 deviceCap;
u32 binBuildNumber;
u8 deviceType;
u8 futureBase[1];
} __packed;
struct spur_chan {
u16 spurChan;
u8 spurRangeLow;
@ -559,11 +594,58 @@ struct modal_eep_header {
struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
} __packed;
struct modal_eep_4k_header {
u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
u32 antCtrlCommon;
u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS];
u8 switchSettling;
u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS];
u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS];
u8 adcDesiredSize;
u8 pgaDesiredSize;
u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS];
u8 txEndToXpaOff;
u8 txEndToRxOn;
u8 txFrameToXpaOn;
u8 thresh62;
u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS];
u8 xpdGain;
u8 xpd;
u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS];
u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS];
u8 pdGainOverlap;
u8 ob_01;
u8 db1_01;
u8 xpaBiasLvl;
u8 txFrameToDataStart;
u8 txFrameToPaOn;
u8 ht40PowerIncForPdadc;
u8 bswAtten[AR5416_EEP4K_MAX_CHAINS];
u8 bswMargin[AR5416_EEP4K_MAX_CHAINS];
u8 swSettleHt40;
u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS];
u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS];
u8 db2_01;
u8 version;
u16 ob_234;
u16 db1_234;
u16 db2_234;
u8 futureModal[4];
struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
} __packed;
struct cal_data_per_freq {
u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
} __packed;
struct cal_data_per_freq_4k {
u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
} __packed;
struct cal_target_power_leg {
u8 bChannel;
u8 tPow2x[4];
@ -574,6 +656,7 @@ struct cal_target_power_ht {
u8 tPow2x[8];
} __packed;
#ifdef __BIG_ENDIAN_BITFIELD
struct cal_ctl_edges {
u8 bChannel;
@ -588,10 +671,15 @@ struct cal_ctl_edges {
struct cal_ctl_data {
struct cal_ctl_edges
ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
} __packed;
struct ar5416_eeprom {
struct cal_ctl_data_4k {
struct cal_ctl_edges
ctlEdges[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_BAND_EDGES];
} __packed;
struct ar5416_eeprom_def {
struct base_eep_header baseEepHeader;
u8 custData[64];
struct modal_eep_header modalHeader[2];
@ -620,6 +708,26 @@ struct ar5416_eeprom {
u8 padding;
} __packed;
struct ar5416_eeprom_4k {
struct base_eep_header_4k baseEepHeader;
u8 custData[20];
struct modal_eep_4k_header modalHeader;
u8 calFreqPier2G[AR5416_EEP4K_NUM_2G_CAL_PIERS];
struct cal_data_per_freq_4k
calPierData2G[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_2G_CAL_PIERS];
struct cal_target_power_leg
calTargetPowerCck[AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS];
struct cal_target_power_leg
calTargetPower2G[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
struct cal_target_power_ht
calTargetPower2GHT20[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
struct cal_target_power_ht
calTargetPower2GHT40[AR5416_EEP4K_NUM_2G_40_TARGET_POWERS];
u8 ctlIndex[AR5416_EEP4K_NUM_CTLS];
struct cal_ctl_data_4k ctlData[AR5416_EEP4K_NUM_CTLS];
u8 padding;
} __packed;
struct ar5416IniArray {
u32 *ia_array;
u32 ia_rows;
@ -687,9 +795,22 @@ struct hal_cal_list {
struct hal_cal_list *calNext;
};
/*
* Enum to indentify the eeprom mappings
*/
enum hal_eep_map {
EEP_MAP_DEFAULT = 0x0,
EEP_MAP_4KBITS,
EEP_MAP_MAX
};
struct ath_hal_5416 {
struct ath_hal ah;
struct ar5416_eeprom ah_eeprom;
union {
struct ar5416_eeprom_def def;
struct ar5416_eeprom_4k map4k;
} ah_eeprom;
struct ar5416Stats ah_stats;
struct ath9k_tx_queue_info ah_txq[ATH9K_NUM_TX_QUEUES];
void __iomem *ah_cal_mem;
@ -813,6 +934,8 @@ struct ath_hal_5416 {
struct ar5416IniArray ah_iniModesAdditional;
struct ar5416IniArray ah_iniModesRxGain;
struct ar5416IniArray ah_iniModesTxGain;
/* To indicate EEPROM mapping used */
enum hal_eep_map ah_eep_map;
};
#define AH5416(_ah) ((struct ath_hal_5416 *)(_ah))
@ -854,13 +977,20 @@ struct ath_hal_5416 {
(AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200
#define AR5416_EEPROM_MAX 0xae0
#define ar5416_get_eep_ver(_ahp) \
(((_ahp)->ah_eeprom.baseEepHeader.version >> 12) & 0xF)
(((_ahp)->ah_eeprom.def.baseEepHeader.version >> 12) & 0xF)
#define ar5416_get_eep_rev(_ahp) \
(((_ahp)->ah_eeprom.baseEepHeader.version) & 0xFFF)
(((_ahp)->ah_eeprom.def.baseEepHeader.version) & 0xFFF)
#define ar5416_get_ntxchains(_txchainmask) \
(((_txchainmask >> 2) & 1) + \
((_txchainmask >> 1) & 1) + (_txchainmask & 1))
/* EEPROM 4K bit map definations */
#define ar5416_get_eep4k_ver(_ahp) \
(((_ahp)->ah_eeprom.map4k.baseEepHeader.version >> 12) & 0xF)
#define ar5416_get_eep4k_rev(_ahp) \
(((_ahp)->ah_eeprom.map4k.baseEepHeader.version) & 0xFFF)
#ifdef __BIG_ENDIAN
#define AR5416_EEPROM_MAGIC 0x5aa5
#else

File diff suppressed because it is too large Load Diff

View File

@ -916,12 +916,11 @@ void ath9k_hw_rxena(struct ath_hal *ah)
void ath9k_hw_startpcureceive(struct ath_hal *ah)
{
REG_CLR_BIT(ah, AR_DIAG_SW,
(AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
ath9k_enable_mib_counters(ah);
ath9k_ani_reset(ah);
REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
}
void ath9k_hw_stoppcurecv(struct ath_hal *ah)

View File

@ -34,6 +34,7 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = {
{ PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
{ 0 }
};
@ -60,7 +61,8 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz)
static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode)
{
sc->sc_curmode = mode;
if (!sc->sc_curaid)
sc->cur_rate_table = sc->hw_rate_table[mode];
/*
* All protection frames are transmited at 2Mb/s for
* 11g, otherwise at 1Mb/s.
@ -346,7 +348,7 @@ static void ath_ani_calibrate(unsigned long data)
* don't calibrate when we're scanning.
* we are most likely not on our home channel.
*/
if (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC)
if (sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)
return;
/* Long calibration runs independently of short calibration. */
@ -485,9 +487,9 @@ static void ath9k_tasklet(unsigned long data)
if (status &
(ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
spin_lock_bh(&sc->sc_rxflushlock);
spin_lock_bh(&sc->rx.rxflushlock);
ath_rx_tasklet(sc, 0);
spin_unlock_bh(&sc->sc_rxflushlock);
spin_unlock_bh(&sc->rx.rxflushlock);
}
/* XXX: optimize this */
if (status & ATH9K_INT_TX)
@ -597,6 +599,8 @@ static irqreturn_t ath_isr(int irq, void *dev)
}
} while (0);
ath_debug_stat_interrupt(sc, status);
if (sched) {
/* turn off every interrupt except SWBA */
ath9k_hw_set_interrupts(ah, (sc->sc_imask & ATH9K_INT_SWBA));
@ -1302,7 +1306,7 @@ static void ath_detach(struct ath_softc *sc)
/* cleanup tx queues */
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
if (ATH_TXQ_SETUP(sc, i))
ath_tx_cleanupq(sc, &sc->sc_txq[i]);
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
ath9k_hw_detach(sc->sc_ah);
ath9k_exit_debug(sc);
@ -1393,15 +1397,15 @@ static int ath_init(u16 devid, struct ath_softc *sc)
* priority. Note that the hal handles reseting
* these queues at the needed time.
*/
sc->sc_bhalq = ath_beaconq_setup(ah);
if (sc->sc_bhalq == -1) {
sc->beacon.beaconq = ath_beaconq_setup(ah);
if (sc->beacon.beaconq == -1) {
DPRINTF(sc, ATH_DBG_FATAL,
"Unable to setup a beacon xmit queue\n");
error = -EIO;
goto bad2;
}
sc->sc_cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
if (sc->sc_cabq == NULL) {
sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
if (sc->beacon.cabq == NULL) {
DPRINTF(sc, ATH_DBG_FATAL,
"Unable to setup CAB xmit queue\n");
error = -EIO;
@ -1411,8 +1415,8 @@ static int ath_init(u16 devid, struct ath_softc *sc)
sc->sc_config.cabqReadytime = ATH_CABQ_READY_TIME;
ath_cabq_update(sc);
for (i = 0; i < ARRAY_SIZE(sc->sc_haltype2q); i++)
sc->sc_haltype2q[i] = -1;
for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
sc->tx.hwq_map[i] = -1;
/* Setup data queues */
/* NB: ensure BK queue is the lowest priority h/w queue */
@ -1492,7 +1496,7 @@ static int ath_init(u16 devid, struct ath_softc *sc)
sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask;
ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
sc->sc_defant = ath9k_hw_getdefantenna(ah);
sc->rx.defant = ath9k_hw_getdefantenna(ah);
ath9k_hw_getmac(ah, sc->sc_myaddr);
if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) {
@ -1501,20 +1505,15 @@ static int ath_init(u16 devid, struct ath_softc *sc)
ath9k_hw_setbssidmask(ah, sc->sc_bssidmask);
}
sc->sc_slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */
sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */
/* initialize beacon slots */
for (i = 0; i < ARRAY_SIZE(sc->sc_bslot); i++)
sc->sc_bslot[i] = ATH_IF_ID_ANY;
for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
sc->beacon.bslot[i] = ATH_IF_ID_ANY;
/* save MISC configurations */
sc->sc_config.swBeaconProcess = 1;
#ifdef CONFIG_SLOW_ANT_DIV
/* range is 40 - 255, we use something in the middle */
ath_slow_ant_div_init(&sc->sc_antdiv, sc, 0x127);
#endif
/* setup channels and rates */
sc->sbands[IEEE80211_BAND_2GHZ].channels =
@ -1536,7 +1535,7 @@ bad2:
/* cleanup tx queues */
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
if (ATH_TXQ_SETUP(sc, i))
ath_tx_cleanupq(sc, &sc->sc_txq[i]);
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
bad:
if (ah)
ath9k_hw_detach(ah);
@ -1674,9 +1673,9 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
int i;
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i)) {
spin_lock_bh(&sc->sc_txq[i].axq_lock);
ath_txq_schedule(sc, &sc->sc_txq[i]);
spin_unlock_bh(&sc->sc_txq[i].axq_lock);
spin_lock_bh(&sc->tx.txq[i].axq_lock);
ath_txq_schedule(sc, &sc->tx.txq[i]);
spin_unlock_bh(&sc->tx.txq[i].axq_lock);
}
}
}
@ -1811,19 +1810,19 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
switch (queue) {
case 0:
qnum = sc->sc_haltype2q[ATH9K_WME_AC_VO];
qnum = sc->tx.hwq_map[ATH9K_WME_AC_VO];
break;
case 1:
qnum = sc->sc_haltype2q[ATH9K_WME_AC_VI];
qnum = sc->tx.hwq_map[ATH9K_WME_AC_VI];
break;
case 2:
qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE];
qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE];
break;
case 3:
qnum = sc->sc_haltype2q[ATH9K_WME_AC_BK];
qnum = sc->tx.hwq_map[ATH9K_WME_AC_BK];
break;
default:
qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE];
qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE];
break;
}
@ -1994,9 +1993,9 @@ static int ath9k_tx(struct ieee80211_hw *hw,
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
sc->seq_no += 0x10;
sc->tx.seq_no += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
}
/* Add the padding after the header if this is not already done */
@ -2050,7 +2049,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
ath_stoprecv(sc);
ath9k_hw_phy_disable(sc->sc_ah);
} else
sc->sc_rxlink = NULL;
sc->rx.rxlink = NULL;
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
@ -2126,16 +2125,13 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n");
#ifdef CONFIG_SLOW_ANT_DIV
ath_slow_ant_div_stop(&sc->sc_antdiv);
#endif
/* Stop ANI */
del_timer_sync(&sc->sc_ani.timer);
/* Reclaim beacon resources */
if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP ||
sc->sc_ah->ah_opmode == NL80211_IFTYPE_ADHOC) {
ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
ath_beacon_return(sc, avp);
}
@ -2254,7 +2250,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
* causes reconfiguration; we may be called
* with beacon transmission active.
*/
ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
error = ath_beacon_alloc(sc, 0);
if (error != 0)
@ -2300,7 +2296,7 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
changed_flags &= SUPPORTED_FILTERS;
*total_flags &= SUPPORTED_FILTERS;
sc->rx_filter = *total_flags;
sc->rx.rxfilter = *total_flags;
rfilt = ath_calcrxfilter(sc);
ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
@ -2309,7 +2305,7 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
ath9k_hw_write_associd(sc->sc_ah, ath_bcast_mac, 0);
}
DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", sc->rx_filter);
DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", sc->rx.rxfilter);
}
static void ath9k_sta_notify(struct ieee80211_hw *hw,
@ -2491,11 +2487,6 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
return ret;
}
static int ath9k_no_fragmentation(struct ieee80211_hw *hw, u32 value)
{
return -EOPNOTSUPP;
}
static struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
@ -2512,7 +2503,6 @@ static struct ieee80211_ops ath9k_ops = {
.get_tsf = ath9k_get_tsf,
.reset_tsf = ath9k_reset_tsf,
.ampdu_action = ath9k_ampdu_action,
.set_frag_threshold = ath9k_no_fragmentation,
};
static struct {

View File

@ -50,6 +50,9 @@ bool ath9k_hw_init_rf(struct ath_hal *ah,
#define AR_PHY_FC_SHORT_GI_40 0x00000080
#define AR_PHY_FC_WALSH 0x00000100
#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200
#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800
#define AR_PHY_TEST2 0x9808
#define AR_PHY_TIMING2 0x9810
#define AR_PHY_TIMING3 0x9814
@ -100,6 +103,8 @@ bool ath9k_hw_init_rf(struct ath_hal *ah,
#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF
#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0
#define AR_PHY_TSTDAC_CONST 0x983c
#define AR_PHY_SETTLING 0x9844
#define AR_PHY_SETTLING_SWITCH 0x00003F80
#define AR_PHY_SETTLING_SWITCH_S 7

View File

@ -817,7 +817,7 @@ static void ath_rc_ratefind(struct ath_softc *sc,
struct ath_rate_table *rate_table;
struct ieee80211_tx_rate *rates = tx_info->control.rates;
rate_table = sc->hw_rate_table[sc->sc_curmode];
rate_table = sc->cur_rate_table;
rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, 1,
is_probe, is_retry);
nrix = rix;
@ -874,10 +874,9 @@ static void ath_rc_ratefind(struct ath_softc *sc,
* So, set fourth rate in series to be same as third one for
* above conditions.
*/
if ((sc->sc_curmode == ATH9K_MODE_11NG_HT20) ||
(sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) ||
(sc->sc_curmode == ATH9K_MODE_11NG_HT40MINUS)) {
u8 dot11rate = rate_table->info[rix].dot11rate;
if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
(sc->hw->conf.ht.enabled)) {
u8 dot11rate = rate_table->info[rix].dot11rate;
u8 phy = rate_table->info[rix].phy;
if (i == 4 &&
((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
@ -1094,7 +1093,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
int rate;
u8 last_per;
bool state_change = false;
struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode];
struct ath_rate_table *rate_table = sc->cur_rate_table;
int size = ath_rc_priv->rate_table_size;
if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
@ -1254,7 +1253,7 @@ static void ath_rc_tx_status(struct ath_softc *sc,
u8 flags;
u32 i = 0, rix;
rate_table = sc->hw_rate_table[sc->sc_curmode];
rate_table = sc->cur_rate_table;
/*
* If the first rate is not the final index, there
@ -1354,8 +1353,8 @@ static void ath_rc_init(struct ath_softc *sc,
sta->ht_cap.ht_supported,
is_cw_40);
} else if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP) {
/* sc_curmode would be set on init through config() */
rate_table = sc->hw_rate_table[sc->sc_curmode];
/* cur_rate_table would be set on init through config() */
rate_table = sc->cur_rate_table;
}
if (!rate_table) {
@ -1432,6 +1431,7 @@ static void ath_rc_init(struct ath_softc *sc,
ath_rc_priv->max_valid_rate = k;
ath_rc_sort_validrates(rate_table, ath_rc_priv);
ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
sc->cur_rate_table = rate_table;
}
/* Rate Control callbacks */

View File

@ -41,20 +41,19 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
ASSERT(skb != NULL);
ds->ds_vdata = skb->data;
/* setup rx descriptors. The sc_rxbufsize here tells the harware
/* setup rx descriptors. The rx.bufsize here tells the harware
* how much data it can DMA to us and that we are prepared
* to process */
ath9k_hw_setuprxdesc(ah,
ds,
sc->sc_rxbufsize,
ath9k_hw_setuprxdesc(ah, ds,
sc->rx.bufsize,
0);
if (sc->sc_rxlink == NULL)
if (sc->rx.rxlink == NULL)
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
else
*sc->sc_rxlink = bf->bf_daddr;
*sc->rx.rxlink = bf->bf_daddr;
sc->sc_rxlink = &ds->ds_link;
sc->rx.rxlink = &ds->ds_link;
ath9k_hw_rxena(ah);
}
@ -62,8 +61,8 @@ static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
{
/* XXX block beacon interrupts */
ath9k_hw_setantenna(sc->sc_ah, antenna);
sc->sc_defant = antenna;
sc->sc_rxotherant = 0;
sc->rx.defant = antenna;
sc->rx.rxotherant = 0;
}
/*
@ -148,7 +147,7 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
struct ieee80211_rx_status *rx_status, bool *decrypt_error,
struct ath_softc *sc)
{
struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode];
struct ath_rate_table *rate_table = sc->cur_rate_table;
struct ieee80211_hdr *hdr;
int ratekbps, rix;
u8 ratecode;
@ -272,20 +271,20 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
int error = 0;
do {
spin_lock_init(&sc->sc_rxflushlock);
spin_lock_init(&sc->rx.rxflushlock);
sc->sc_flags &= ~SC_OP_RXFLUSH;
spin_lock_init(&sc->sc_rxbuflock);
spin_lock_init(&sc->rx.rxbuflock);
sc->sc_rxbufsize = roundup(IEEE80211_MAX_MPDU_LEN,
sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
min(sc->sc_cachelsz,
(u16)64));
DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
sc->sc_cachelsz, sc->sc_rxbufsize);
sc->sc_cachelsz, sc->rx.bufsize);
/* Initialize rx descriptors */
error = ath_descdma_setup(sc, &sc->sc_rxdma, &sc->sc_rxbuf,
error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
"rx", nbufs, 1);
if (error != 0) {
DPRINTF(sc, ATH_DBG_FATAL,
@ -293,8 +292,8 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
break;
}
list_for_each_entry(bf, &sc->sc_rxbuf, list) {
skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
skb = ath_rxbuf_alloc(sc, sc->rx.bufsize);
if (skb == NULL) {
error = -ENOMEM;
break;
@ -302,8 +301,8 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
bf->bf_mpdu = skb;
bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data,
sc->sc_rxbufsize,
PCI_DMA_FROMDEVICE);
sc->rx.bufsize,
PCI_DMA_FROMDEVICE);
if (unlikely(pci_dma_mapping_error(sc->pdev,
bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
@ -315,7 +314,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
}
bf->bf_dmacontext = bf->bf_buf_addr;
}
sc->sc_rxlink = NULL;
sc->rx.rxlink = NULL;
} while (0);
@ -330,14 +329,14 @@ void ath_rx_cleanup(struct ath_softc *sc)
struct sk_buff *skb;
struct ath_buf *bf;
list_for_each_entry(bf, &sc->sc_rxbuf, list) {
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
skb = bf->bf_mpdu;
if (skb)
dev_kfree_skb(skb);
}
if (sc->sc_rxdma.dd_desc_len != 0)
ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf);
if (sc->rx.rxdma.dd_desc_len != 0)
ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf);
}
/*
@ -375,7 +374,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
/* Can't set HOSTAP into promiscous mode */
if (((sc->sc_ah->ah_opmode != NL80211_IFTYPE_AP) &&
(sc->rx_filter & FIF_PROMISC_IN_BSS)) ||
(sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) ||
(sc->sc_ah->ah_opmode == NL80211_IFTYPE_MONITOR)) {
rfilt |= ATH9K_RX_FILTER_PROM;
/* ??? To prevent from sending ACK */
@ -401,25 +400,25 @@ int ath_startrecv(struct ath_softc *sc)
struct ath_hal *ah = sc->sc_ah;
struct ath_buf *bf, *tbf;
spin_lock_bh(&sc->sc_rxbuflock);
if (list_empty(&sc->sc_rxbuf))
spin_lock_bh(&sc->rx.rxbuflock);
if (list_empty(&sc->rx.rxbuf))
goto start_recv;
sc->sc_rxlink = NULL;
list_for_each_entry_safe(bf, tbf, &sc->sc_rxbuf, list) {
sc->rx.rxlink = NULL;
list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
ath_rx_buf_link(sc, bf);
}
/* We could have deleted elements so the list may be empty now */
if (list_empty(&sc->sc_rxbuf))
if (list_empty(&sc->rx.rxbuf))
goto start_recv;
bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list);
bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
ath9k_hw_rxena(ah);
start_recv:
spin_unlock_bh(&sc->sc_rxbuflock);
spin_unlock_bh(&sc->rx.rxbuflock);
ath_opmode_init(sc);
ath9k_hw_startpcureceive(ah);
@ -435,25 +434,25 @@ bool ath_stoprecv(struct ath_softc *sc)
ath9k_hw_setrxfilter(ah, 0);
stopped = ath9k_hw_stopdmarecv(ah);
mdelay(3); /* 3ms is long enough for 1 frame */
sc->sc_rxlink = NULL;
sc->rx.rxlink = NULL;
return stopped;
}
void ath_flushrecv(struct ath_softc *sc)
{
spin_lock_bh(&sc->sc_rxflushlock);
spin_lock_bh(&sc->rx.rxflushlock);
sc->sc_flags |= SC_OP_RXFLUSH;
ath_rx_tasklet(sc, 1);
sc->sc_flags &= ~SC_OP_RXFLUSH;
spin_unlock_bh(&sc->sc_rxflushlock);
spin_unlock_bh(&sc->rx.rxflushlock);
}
int ath_rx_tasklet(struct ath_softc *sc, int flush)
{
#define PA2DESC(_sc, _pa) \
((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
((struct ath_desc *)((caddr_t)(_sc)->rx.rxdma.dd_desc + \
((_pa) - (_sc)->rx.rxdma.dd_desc_paddr)))
struct ath_buf *bf;
struct ath_desc *ds;
@ -465,19 +464,19 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
bool decrypt_error = false;
u8 keyix;
spin_lock_bh(&sc->sc_rxbuflock);
spin_lock_bh(&sc->rx.rxbuflock);
do {
/* If handling rx interrupt and flush is in progress => exit */
if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))
break;
if (list_empty(&sc->sc_rxbuf)) {
sc->sc_rxlink = NULL;
if (list_empty(&sc->rx.rxbuf)) {
sc->rx.rxlink = NULL;
break;
}
bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list);
bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
ds = bf->bf_desc;
/*
@ -499,8 +498,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
struct ath_buf *tbf;
struct ath_desc *tds;
if (list_is_last(&bf->list, &sc->sc_rxbuf)) {
sc->sc_rxlink = NULL;
if (list_is_last(&bf->list, &sc->rx.rxbuf)) {
sc->rx.rxlink = NULL;
break;
}
@ -540,7 +539,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
goto requeue;
/* The status portion of the descriptor could get corrupted. */
if (sc->sc_rxbufsize < ds->ds_rxstat.rs_datalen)
if (sc->rx.bufsize < ds->ds_rxstat.rs_datalen)
goto requeue;
if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc))
@ -548,21 +547,21 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
/* Ensure we always have an skb to requeue once we are done
* processing the current buffer's skb */
requeue_skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize);
/* If there is no memory we ignore the current RX'd frame,
* tell hardware it can give us a new frame using the old
* skb and put it at the tail of the sc->sc_rxbuf list for
* skb and put it at the tail of the sc->rx.rxbuf list for
* processing. */
if (!requeue_skb)
goto requeue;
pci_dma_sync_single_for_cpu(sc->pdev,
bf->bf_buf_addr,
sc->sc_rxbufsize,
/* Sync and unmap the frame */
pci_dma_sync_single_for_cpu(sc->pdev, bf->bf_buf_addr,
sc->rx.bufsize,
PCI_DMA_FROMDEVICE);
pci_unmap_single(sc->pdev, bf->bf_buf_addr,
sc->sc_rxbufsize,
sc->rx.bufsize,
PCI_DMA_FROMDEVICE);
skb_put(skb, ds->ds_rxstat.rs_datalen);
@ -572,8 +571,16 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
hdr = (struct ieee80211_hdr *)skb->data;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
if (hdrlen & 3) {
padsize = hdrlen % 4;
/* The MAC header is padded to have 32-bit boundary if the
* packet payload is non-zero. The general calculation for
* padsize would take into account odd header lengths:
* padsize = (4 - hdrlen % 4) % 4; However, since only
* even-length headers are used, padding can only be 0 or 2
* bytes and we can optimize this a bit. In addition, we must
* not try to remove padding from short control frames that do
* not have payload. */
padsize = hdrlen & 3;
if (padsize && hdrlen >= 24) {
memmove(skb->data + padsize, skb->data, hdrlen);
skb_pull(skb, padsize);
}
@ -596,7 +603,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
/* We will now give hardware our shiny new allocated skb */
bf->bf_mpdu = requeue_skb;
bf->bf_buf_addr = pci_map_single(sc->pdev, requeue_skb->data,
sc->sc_rxbufsize,
sc->rx.bufsize,
PCI_DMA_FROMDEVICE);
if (unlikely(pci_dma_mapping_error(sc->pdev,
bf->bf_buf_addr))) {
@ -612,18 +619,18 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
* change the default rx antenna if rx diversity chooses the
* other antenna 3 times in a row.
*/
if (sc->sc_defant != ds->ds_rxstat.rs_antenna) {
if (++sc->sc_rxotherant >= 3)
if (sc->rx.defant != ds->ds_rxstat.rs_antenna) {
if (++sc->rx.rxotherant >= 3)
ath_setdefantenna(sc, ds->ds_rxstat.rs_antenna);
} else {
sc->sc_rxotherant = 0;
sc->rx.rxotherant = 0;
}
requeue:
list_move_tail(&bf->list, &sc->sc_rxbuf);
list_move_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_buf_link(sc, bf);
} while (1);
spin_unlock_bh(&sc->sc_rxbuflock);
spin_unlock_bh(&sc->rx.rxbuflock);
return 0;
#undef PA2DESC

View File

@ -671,7 +671,11 @@
#define AR_RC_APB 0x00000002
#define AR_RC_HOSTIF 0x00000100
#define AR_WA 0x4004
#define AR_WA 0x4004
#define AR9285_WA_DEFAULT 0x004a05cb
#define AR9280_WA_DEFAULT 0x0040073f
#define AR_WA_DEFAULT 0x0000073f
#define AR_PM_STATE 0x4008
#define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000
@ -738,6 +742,8 @@
#define AR_SREV_REVISION_9280_21 2
#define AR_SREV_VERSION_9285 0xC0
#define AR_SREV_REVISION_9285_10 0
#define AR_SREV_REVISION_9285_11 1
#define AR_SREV_REVISION_9285_12 2
#define AR_SREV_9100_OR_LATER(_ah) \
(((_ah)->ah_macVersion >= AR_SREV_VERSION_5416_PCIE))
@ -768,6 +774,16 @@
#define AR_SREV_9285(_ah) (((_ah)->ah_macVersion == AR_SREV_VERSION_9285))
#define AR_SREV_9285_10_OR_LATER(_ah) \
(((_ah)->ah_macVersion >= AR_SREV_VERSION_9285))
#define AR_SREV_9285_11(_ah) \
(AR_SREV_9280(ah) && ((_ah)->ah_macRev == AR_SREV_REVISION_9285_11))
#define AR_SREV_9285_11_OR_LATER(_ah) \
(((_ah)->ah_macVersion > AR_SREV_VERSION_9285) || \
(AR_SREV_9285(ah) && ((_ah)->ah_macRev >= AR_SREV_REVISION_9285_11)))
#define AR_SREV_9285_12(_ah) \
(AR_SREV_9280(ah) && ((_ah)->ah_macRev == AR_SREV_REVISION_9285_12))
#define AR_SREV_9285_12_OR_LATER(_ah) \
(((_ah)->ah_macVersion > AR_SREV_VERSION_9285) || \
(AR_SREV_9285(ah) && ((_ah)->ah_macRev >= AR_SREV_REVISION_9285_12)))
#define AR_RADIO_SREV_MAJOR 0xf0
#define AR_RAD5133_SREV_MAJOR 0xc0
@ -1017,6 +1033,97 @@ enum {
#define AR_AN_SYNTH9_REFDIVA 0xf8000000
#define AR_AN_SYNTH9_REFDIVA_S 27
#define AR9285_AN_RF2G1 0x7820
#define AR9285_AN_RF2G1_ENPACAL 0x00000800
#define AR9285_AN_RF2G1_ENPACAL_S 11
#define AR9285_AN_RF2G1_PDPADRV1 0x02000000
#define AR9285_AN_RF2G1_PDPADRV1_S 25
#define AR9285_AN_RF2G1_PDPADRV2 0x01000000
#define AR9285_AN_RF2G1_PDPADRV2_S 24
#define AR9285_AN_RF2G1_PDPAOUT 0x00800000
#define AR9285_AN_RF2G1_PDPAOUT_S 23
#define AR9285_AN_RF2G2 0x7824
#define AR9285_AN_RF2G2_OFFCAL 0x00001000
#define AR9285_AN_RF2G2_OFFCAL_S 12
#define AR9285_AN_RF2G3 0x7828
#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000
#define AR9285_AN_RF2G3_PDVCCOMP_S 25
#define AR9285_AN_RF2G3_OB_0 0x00E00000
#define AR9285_AN_RF2G3_OB_0_S 21
#define AR9285_AN_RF2G3_OB_1 0x001C0000
#define AR9285_AN_RF2G3_OB_1_S 18
#define AR9285_AN_RF2G3_OB_2 0x00038000
#define AR9285_AN_RF2G3_OB_2_S 15
#define AR9285_AN_RF2G3_OB_3 0x00007000
#define AR9285_AN_RF2G3_OB_3_S 12
#define AR9285_AN_RF2G3_OB_4 0x00000E00
#define AR9285_AN_RF2G3_OB_4_S 9
#define AR9285_AN_RF2G3_DB1_0 0x000001C0
#define AR9285_AN_RF2G3_DB1_0_S 6
#define AR9285_AN_RF2G3_DB1_1 0x00000038
#define AR9285_AN_RF2G3_DB1_1_S 3
#define AR9285_AN_RF2G3_DB1_2 0x00000007
#define AR9285_AN_RF2G3_DB1_2_S 0
#define AR9285_AN_RF2G4 0x782C
#define AR9285_AN_RF2G4_DB1_3 0xE0000000
#define AR9285_AN_RF2G4_DB1_3_S 29
#define AR9285_AN_RF2G4_DB1_4 0x1C000000
#define AR9285_AN_RF2G4_DB1_4_S 26
#define AR9285_AN_RF2G4_DB2_0 0x03800000
#define AR9285_AN_RF2G4_DB2_0_S 23
#define AR9285_AN_RF2G4_DB2_1 0x00700000
#define AR9285_AN_RF2G4_DB2_1_S 20
#define AR9285_AN_RF2G4_DB2_2 0x000E0000
#define AR9285_AN_RF2G4_DB2_2_S 17
#define AR9285_AN_RF2G4_DB2_3 0x0001C000
#define AR9285_AN_RF2G4_DB2_3_S 14
#define AR9285_AN_RF2G4_DB2_4 0x00003800
#define AR9285_AN_RF2G4_DB2_4_S 11
#define AR9285_AN_RF2G6 0x7834
#define AR9285_AN_RF2G6_CCOMP 0x00007800
#define AR9285_AN_RF2G6_CCOMP_S 11
#define AR9285_AN_RF2G6_OFFS 0x03f00000
#define AR9285_AN_RF2G6_OFFS_S 20
#define AR9285_AN_RF2G7 0x7838
#define AR9285_AN_RF2G7_PWDDB 0x00000002
#define AR9285_AN_RF2G7_PWDDB_S 1
#define AR9285_AN_RF2G7_PADRVGN2TAB0 0xE0000000
#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29
#define AR9285_AN_RF2G8 0x783C
#define AR9285_AN_RF2G8_PADRVGN2TAB0 0x0001C000
#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14
#define AR9285_AN_RF2G9 0x7840
#define AR9285_AN_RXTXBB1 0x7854
#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020
#define AR9285_AN_RXTXBB1_PDRXTXBB1_S 5
#define AR9285_AN_RXTXBB1_PDV2I 0x00000080
#define AR9285_AN_RXTXBB1_PDV2I_S 7
#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100
#define AR9285_AN_RXTXBB1_PDDACIF_S 8
#define AR9285_AN_RXTXBB1_SPARE9 0x00000001
#define AR9285_AN_RXTXBB1_SPARE9_S 0
#define AR9285_AN_TOP2 0x7868
#define AR9285_AN_TOP3 0x786c
#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C
#define AR9285_AN_TOP3_XPABIAS_LVL_S 2
#define AR9285_AN_TOP3_PWDDAC 0x00800000
#define AR9285_AN_TOP3_PWDDAC_S 23
#define AR9285_AN_TOP4 0x7870
#define AR9285_AN_TOP4_DEFAULT 0x10142c00
#define AR_STA_ID0 0x8000
#define AR_STA_ID1 0x8004
#define AR_STA_ID1_SADH_MASK 0x0000FFFF

View File

@ -286,17 +286,17 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
{
struct ath_buf *bf = NULL;
spin_lock_bh(&sc->sc_txbuflock);
spin_lock_bh(&sc->tx.txbuflock);
if (unlikely(list_empty(&sc->sc_txbuf))) {
spin_unlock_bh(&sc->sc_txbuflock);
if (unlikely(list_empty(&sc->tx.txbuf))) {
spin_unlock_bh(&sc->tx.txbuflock);
return NULL;
}
bf = list_first_entry(&sc->sc_txbuf, struct ath_buf, list);
bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
list_del(&bf->list);
spin_unlock_bh(&sc->sc_txbuflock);
spin_unlock_bh(&sc->tx.txbuflock);
return bf;
}
@ -310,6 +310,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc,
{
struct sk_buff *skb = bf->bf_mpdu;
struct ath_xmit_status tx_status;
unsigned long flags;
/*
* Set retry information.
@ -340,9 +341,9 @@ static void ath_tx_complete_buf(struct ath_softc *sc,
/*
* Return the list of ath_buf of this mpdu to free queue
*/
spin_lock_bh(&sc->sc_txbuflock);
list_splice_tail_init(bf_q, &sc->sc_txbuf);
spin_unlock_bh(&sc->sc_txbuflock);
spin_lock_irqsave(&sc->tx.txbuflock, flags);
list_splice_tail_init(bf_q, &sc->tx.txbuf);
spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
}
/*
@ -383,7 +384,7 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
struct ath_txq *txq = &sc->sc_txq[tid->ac->qnum];
struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
spin_lock_bh(&txq->axq_lock);
@ -396,7 +397,7 @@ static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
struct ath_txq *txq = &sc->sc_txq[tid->ac->qnum];
struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
ASSERT(tid->paused > 0);
spin_lock_bh(&txq->axq_lock);
@ -493,7 +494,7 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
int width, int half_gi, bool shortPreamble)
{
struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode];
struct ath_rate_table *rate_table = sc->cur_rate_table;
u32 nbits, nsymbits, duration, nsymbols;
u8 rc;
int streams, pktlen;
@ -557,7 +558,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
}
/* get the cix for the lowest valid rix */
rt = sc->hw_rate_table[sc->sc_curmode];
rt = sc->cur_rate_table;
for (i = 3; i >= 0; i--) {
if (rates[i].count && (rates[i].idx >= 0)) {
rix = rates[i].idx;
@ -685,7 +686,7 @@ static int ath_tx_send_normal(struct ath_softc *sc,
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
struct ath_txq *txq = &sc->sc_txq[tid->ac->qnum];
struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
struct ath_buf *bf;
struct list_head bf_head;
INIT_LIST_HEAD(&bf_head);
@ -860,12 +861,12 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
struct ath_buf *tbf;
/* allocate new descriptor */
spin_lock_bh(&sc->sc_txbuflock);
ASSERT(!list_empty((&sc->sc_txbuf)));
tbf = list_first_entry(&sc->sc_txbuf,
spin_lock_bh(&sc->tx.txbuflock);
ASSERT(!list_empty((&sc->tx.txbuf)));
tbf = list_first_entry(&sc->tx.txbuf,
struct ath_buf, list);
list_del(&tbf->list);
spin_unlock_bh(&sc->sc_txbuflock);
spin_unlock_bh(&sc->tx.txbuflock);
ATH_TXBUF_RESET(tbf);
@ -1057,9 +1058,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
if (bf_held) {
list_del(&bf_held->list);
spin_lock_bh(&sc->sc_txbuflock);
list_add_tail(&bf_held->list, &sc->sc_txbuf);
spin_unlock_bh(&sc->sc_txbuflock);
spin_lock_bh(&sc->tx.txbuflock);
list_add_tail(&bf_held->list, &sc->tx.txbuf);
spin_unlock_bh(&sc->tx.txbuflock);
}
if (!bf_isampdu(bf)) {
@ -1128,11 +1129,11 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx)
if (!(sc->sc_flags & SC_OP_INVALID)) {
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i)) {
ath_tx_stopdma(sc, &sc->sc_txq[i]);
ath_tx_stopdma(sc, &sc->tx.txq[i]);
/* The TxDMA may not really be stopped.
* Double check the hal tx pending count */
npend += ath9k_hw_numtxpending(ah,
sc->sc_txq[i].axq_qnum);
sc->tx.txq[i].axq_qnum);
}
}
}
@ -1157,7 +1158,7 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx)
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i))
ath_tx_draintxq(sc, &sc->sc_txq[i], retry_tx);
ath_tx_draintxq(sc, &sc->tx.txq[i], retry_tx);
}
}
@ -1240,7 +1241,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc,
struct ath_buf *bf,
struct ath_atx_tid *tid)
{
struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode];
struct ath_rate_table *rate_table = sc->cur_rate_table;
struct sk_buff *skb;
struct ieee80211_tx_info *tx_info;
struct ieee80211_tx_rate *rates;
@ -1308,7 +1309,7 @@ static int ath_compute_num_delims(struct ath_softc *sc,
struct ath_buf *bf,
u16 frmlen)
{
struct ath_rate_table *rt = sc->hw_rate_table[sc->sc_curmode];
struct ath_rate_table *rt = sc->cur_rate_table;
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
u32 nsymbits, nsymbols, mpdudensity;
@ -1819,9 +1820,9 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
}
spin_unlock_bh(&txq->axq_lock);
spin_lock_bh(&sc->sc_txbuflock);
list_add_tail(&bf->list, &sc->sc_txbuf);
spin_unlock_bh(&sc->sc_txbuflock);
spin_lock_bh(&sc->tx.txbuflock);
list_add_tail(&bf->list, &sc->tx.txbuf);
spin_unlock_bh(&sc->tx.txbuflock);
return r;
}
@ -1838,10 +1839,10 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
int error = 0;
do {
spin_lock_init(&sc->sc_txbuflock);
spin_lock_init(&sc->tx.txbuflock);
/* Setup tx descriptors */
error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf,
error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
"tx", nbufs, 1);
if (error != 0) {
DPRINTF(sc, ATH_DBG_FATAL,
@ -1851,7 +1852,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
}
/* XXX allocate beacon state together with vap */
error = ath_descdma_setup(sc, &sc->sc_bdma, &sc->sc_bbuf,
error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
"beacon", ATH_BCBUF, 1);
if (error != 0) {
DPRINTF(sc, ATH_DBG_FATAL,
@ -1873,12 +1874,12 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
int ath_tx_cleanup(struct ath_softc *sc)
{
/* cleanup beacon descriptors */
if (sc->sc_bdma.dd_desc_len != 0)
ath_descdma_cleanup(sc, &sc->sc_bdma, &sc->sc_bbuf);
if (sc->beacon.bdma.dd_desc_len != 0)
ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf);
/* cleanup tx descriptors */
if (sc->sc_txdma.dd_desc_len != 0)
ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf);
if (sc->tx.txdma.dd_desc_len != 0)
ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
return 0;
}
@ -1926,15 +1927,15 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
*/
return NULL;
}
if (qnum >= ARRAY_SIZE(sc->sc_txq)) {
if (qnum >= ARRAY_SIZE(sc->tx.txq)) {
DPRINTF(sc, ATH_DBG_FATAL,
"qnum %u out of range, max %u!\n",
qnum, (unsigned int)ARRAY_SIZE(sc->sc_txq));
qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq));
ath9k_hw_releasetxqueue(ah, qnum);
return NULL;
}
if (!ATH_TXQ_SETUP(sc, qnum)) {
struct ath_txq *txq = &sc->sc_txq[qnum];
struct ath_txq *txq = &sc->tx.txq[qnum];
txq->axq_qnum = qnum;
txq->axq_link = NULL;
@ -1945,9 +1946,9 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
txq->axq_aggr_depth = 0;
txq->axq_totalqueued = 0;
txq->axq_linkbuf = NULL;
sc->sc_txqsetup |= 1<<qnum;
sc->tx.txqsetup |= 1<<qnum;
}
return &sc->sc_txq[qnum];
return &sc->tx.txq[qnum];
}
/* Reclaim resources for a setup queue */
@ -1955,7 +1956,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
{
ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
sc->sc_txqsetup &= ~(1<<txq->axq_qnum);
sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
}
/*
@ -1972,15 +1973,15 @@ int ath_tx_setup(struct ath_softc *sc, int haltype)
{
struct ath_txq *txq;
if (haltype >= ARRAY_SIZE(sc->sc_haltype2q)) {
if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
DPRINTF(sc, ATH_DBG_FATAL,
"HAL AC %u out of range, max %zu!\n",
haltype, ARRAY_SIZE(sc->sc_haltype2q));
haltype, ARRAY_SIZE(sc->tx.hwq_map));
return 0;
}
txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype);
if (txq != NULL) {
sc->sc_haltype2q[haltype] = txq->axq_qnum;
sc->tx.hwq_map[haltype] = txq->axq_qnum;
return 1;
} else
return 0;
@ -1992,19 +1993,19 @@ int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
switch (qtype) {
case ATH9K_TX_QUEUE_DATA:
if (haltype >= ARRAY_SIZE(sc->sc_haltype2q)) {
if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
DPRINTF(sc, ATH_DBG_FATAL,
"HAL AC %u out of range, max %zu!\n",
haltype, ARRAY_SIZE(sc->sc_haltype2q));
haltype, ARRAY_SIZE(sc->tx.hwq_map));
return -1;
}
qnum = sc->sc_haltype2q[haltype];
qnum = sc->tx.hwq_map[haltype];
break;
case ATH9K_TX_QUEUE_BEACON:
qnum = sc->sc_bhalq;
qnum = sc->beacon.beaconq;
break;
case ATH9K_TX_QUEUE_CAB:
qnum = sc->sc_cabq->axq_qnum;
qnum = sc->beacon.cabq->axq_qnum;
break;
default:
qnum = -1;
@ -2020,7 +2021,7 @@ struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
int qnum;
qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
txq = &sc->sc_txq[qnum];
txq = &sc->tx.txq[qnum];
spin_lock_bh(&txq->axq_lock);
@ -2049,17 +2050,17 @@ int ath_txq_update(struct ath_softc *sc, int qnum,
int error = 0;
struct ath9k_tx_queue_info qi;
if (qnum == sc->sc_bhalq) {
if (qnum == sc->beacon.beaconq) {
/*
* XXX: for beacon queue, we just save the parameter.
* It will be picked up by ath_beaconq_config when
* it's necessary.
*/
sc->sc_beacon_qi = *qinfo;
sc->beacon.beacon_qi = *qinfo;
return 0;
}
ASSERT(sc->sc_txq[qnum].axq_qnum == qnum);
ASSERT(sc->tx.txq[qnum].axq_qnum == qnum);
ath9k_hw_get_txq_props(ah, qnum, &qi);
qi.tqi_aifs = qinfo->tqi_aifs;
@ -2082,7 +2083,7 @@ int ath_txq_update(struct ath_softc *sc, int qnum,
int ath_cabq_update(struct ath_softc *sc)
{
struct ath9k_tx_queue_info qi;
int qnum = sc->sc_cabq->axq_qnum;
int qnum = sc->beacon.cabq->axq_qnum;
struct ath_beacon_config conf;
ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
@ -2116,7 +2117,7 @@ void ath_tx_tasklet(struct ath_softc *sc)
*/
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
ath_tx_processq(sc, &sc->sc_txq[i]);
ath_tx_processq(sc, &sc->tx.txq[i]);
}
}
@ -2148,9 +2149,9 @@ void ath_tx_draintxq(struct ath_softc *sc,
list_del(&bf->list);
spin_unlock_bh(&txq->axq_lock);
spin_lock_bh(&sc->sc_txbuflock);
list_add_tail(&bf->list, &sc->sc_txbuf);
spin_unlock_bh(&sc->sc_txbuflock);
spin_lock_bh(&sc->tx.txbuflock);
list_add_tail(&bf->list, &sc->tx.txbuf);
spin_unlock_bh(&sc->tx.txbuflock);
continue;
}
@ -2188,9 +2189,9 @@ void ath_draintxq(struct ath_softc *sc, bool retry_tx)
/* stop beacon queue. The beacon will be freed when
* we go to INIT state */
if (!(sc->sc_flags & SC_OP_INVALID)) {
(void) ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
(void) ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
DPRINTF(sc, ATH_DBG_XMIT, "beacon queue %x\n",
ath9k_hw_gettxbuf(sc->sc_ah, sc->sc_bhalq));
ath9k_hw_gettxbuf(sc->sc_ah, sc->beacon.beaconq));
}
ath_drain_txdataq(sc, retry_tx);
@ -2198,12 +2199,12 @@ void ath_draintxq(struct ath_softc *sc, bool retry_tx)
u32 ath_txq_depth(struct ath_softc *sc, int qnum)
{
return sc->sc_txq[qnum].axq_depth;
return sc->tx.txq[qnum].axq_depth;
}
u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum)
{
return sc->sc_txq[qnum].axq_aggr_depth;
return sc->tx.txq[qnum].axq_aggr_depth;
}
bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno)
@ -2284,7 +2285,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid
void ath_tx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tid)
{
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
struct ath_txq *txq = &sc->sc_txq[txtid->ac->qnum];
struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
struct ath_buf *bf;
struct list_head bf_head;
INIT_LIST_HEAD(&bf_head);
@ -2405,7 +2406,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
/*
* Init per tid tx state
*/
for (tidno = 0, tid = &an->an_aggr.tx.tid[tidno];
for (tidno = 0, tid = &an->tid[tidno];
tidno < WME_NUM_TID;
tidno++, tid++) {
tid->an = an;
@ -2419,7 +2420,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
INIT_LIST_HEAD(&tid->buf_q);
acno = TID_TO_WME_AC(tidno);
tid->ac = &an->an_aggr.tx.ac[acno];
tid->ac = &an->ac[acno];
/* ADDBA state */
tid->state &= ~AGGR_ADDBA_COMPLETE;
@ -2430,7 +2431,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
/*
* Init per ac tx state
*/
for (acno = 0, ac = &an->an_aggr.tx.ac[acno];
for (acno = 0, ac = &an->ac[acno];
acno < WME_NUM_AC; acno++, ac++) {
ac->sched = false;
INIT_LIST_HEAD(&ac->tid_q);
@ -2466,7 +2467,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
struct ath_txq *txq;
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i)) {
txq = &sc->sc_txq[i];
txq = &sc->tx.txq[i];
spin_lock(&txq->axq_lock);
@ -2511,9 +2512,9 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
sc->seq_no += 0x10;
sc->tx.seq_no += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
}
/* Add the padding after the header if this is not already done */
@ -2529,7 +2530,7 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
memmove(skb->data, skb->data + padsize, hdrlen);
}
txctl.txq = sc->sc_cabq;
txctl.txq = sc->beacon.cabq;
DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb);

View File

@ -211,7 +211,7 @@ static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf,
struct b43legacy_dfs_file *dfile;
ssize_t uninitialized_var(ret);
char *buf;
const size_t bufsize = 1024 * 128;
const size_t bufsize = 1024 * 16; /* 16 KiB buffer */
const size_t buforder = get_order(bufsize);
int err = 0;

View File

@ -1296,12 +1296,10 @@ void b43legacy_lo_write(struct b43legacy_wldev *dev,
/* Sanity check. */
if (pair->low < -8 || pair->low > 8 ||
pair->high < -8 || pair->high > 8) {
struct b43legacy_phy *phy = &dev->phy;
b43legacydbg(dev->wl,
"WARNING: Writing invalid LOpair "
"(low: %d, high: %d, index: %lu)\n",
pair->low, pair->high,
(unsigned long)(pair - phy->_lo_pairs));
"(low: %d, high: %d)\n",
pair->low, pair->high);
dump_stack();
}
#endif

View File

@ -4345,7 +4345,8 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv,
return;
}
if (priv->status & STATUS_SCANNING) {
if (priv->status & STATUS_SCANNING &&
missed_count > IPW_MB_SCAN_CANCEL_THRESHOLD) {
/* Stop scan to keep fw from getting
* stuck (only if we aren't roaming --
* otherwise we'll never scan more than 2 or 3
@ -6271,6 +6272,20 @@ static void ipw_add_scan_channels(struct ipw_priv *priv,
}
}
static int ipw_passive_dwell_time(struct ipw_priv *priv)
{
/* staying on passive channels longer than the DTIM interval during a
* scan, while associated, causes the firmware to cancel the scan
* without notification. Hence, don't stay on passive channels longer
* than the beacon interval.
*/
if (priv->status & STATUS_ASSOCIATED
&& priv->assoc_network->beacon_interval > 10)
return priv->assoc_network->beacon_interval - 10;
else
return 120;
}
static int ipw_request_scan_helper(struct ipw_priv *priv, int type, int direct)
{
struct ipw_scan_request_ext scan;
@ -6314,16 +6329,16 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type, int direct)
scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee));
if (type == IW_SCAN_TYPE_PASSIVE) {
IPW_DEBUG_WX("use passive scanning\n");
scan_type = IPW_SCAN_PASSIVE_FULL_DWELL_SCAN;
IPW_DEBUG_WX("use passive scanning\n");
scan_type = IPW_SCAN_PASSIVE_FULL_DWELL_SCAN;
scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] =
cpu_to_le16(120);
cpu_to_le16(ipw_passive_dwell_time(priv));
ipw_add_scan_channels(priv, &scan, scan_type);
goto send_request;
}
/* Use active scan by default. */
if (priv->config & CFG_SPEED_SCAN)
if (priv->config & CFG_SPEED_SCAN)
scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] =
cpu_to_le16(30);
else
@ -6333,7 +6348,8 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type, int direct)
scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] =
cpu_to_le16(20);
scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120);
scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] =
cpu_to_le16(ipw_passive_dwell_time(priv));
scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20);
#ifdef CONFIG_IPW2200_MONITOR

View File

@ -245,6 +245,7 @@ enum connection_manager_assoc_states {
#define HOST_NOTIFICATION_S36_MEASUREMENT_REFUSED 31
#define HOST_NOTIFICATION_STATUS_BEACON_MISSING 1
#define IPW_MB_SCAN_CANCEL_THRESHOLD 3
#define IPW_MB_ROAMING_THRESHOLD_MIN 1
#define IPW_MB_ROAMING_THRESHOLD_DEFAULT 8
#define IPW_MB_ROAMING_THRESHOLD_MAX 30

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* Tomas Winkler <tomas.winkler@intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -21,7 +21,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -103,7 +103,6 @@
* Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
*/
#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */
#define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */
/*
* Regulatory channel usage flags in EEPROM struct iwl_eeprom_channel.flags.
@ -321,6 +320,7 @@ struct iwl3945_eeprom {
/* RSSR */
#define FH_RSSR_CTRL (FH_RSSR_TABLE+0x000)
#define FH_RSSR_STATUS (FH_RSSR_TABLE+0x004)
#define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000)
/* TCSR */
#define FH_TCSR(_channel) (FH_TCSR_TABLE+(_channel)*0x20)
#define FH_TCSR_CONFIG(_channel) (FH_TCSR(_channel)+0x00)

View File

@ -21,7 +21,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -93,7 +93,7 @@ static inline int _iwl3945_poll_bit(struct iwl3945_priv *priv, u32 addr,
do {
if ((_iwl3945_read32(priv, addr) & mask) == (bits & mask))
return i;
mdelay(10);
udelay(10);
i += 10;
} while (i < timeout);
@ -271,16 +271,7 @@ static inline void iwl3945_write_reg_buf(struct iwl3945_priv *priv,
static inline int _iwl3945_poll_direct_bit(struct iwl3945_priv *priv,
u32 addr, u32 mask, int timeout)
{
int i = 0;
do {
if ((_iwl3945_read_direct32(priv, addr) & mask) == mask)
return i;
mdelay(10);
i += 10;
} while (i < timeout);
return -ETIMEDOUT;
return _iwl3945_poll_bit(priv, addr, mask, mask, timeout);
}
#ifdef CONFIG_IWL3945_DEBUG
@ -307,6 +298,7 @@ static inline int __iwl3945_poll_direct_bit(const char *f, u32 l,
static inline u32 _iwl3945_read_prph(struct iwl3945_priv *priv, u32 reg)
{
_iwl3945_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
rmb();
return _iwl3945_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
}
#ifdef CONFIG_IWL3945_DEBUG
@ -328,6 +320,7 @@ static inline void _iwl3945_write_prph(struct iwl3945_priv *priv,
{
_iwl3945_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
((addr & 0x0000FFFF) | (3 << 24)));
wmb();
_iwl3945_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
}
#ifdef CONFIG_IWL3945_DEBUG
@ -389,12 +382,14 @@ static inline void iwl3945_clear_bits_prph(struct iwl3945_priv
static inline u32 iwl3945_read_targ_mem(struct iwl3945_priv *priv, u32 addr)
{
iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
rmb();
return iwl3945_read_direct32(priv, HBUS_TARG_MEM_RDAT);
}
static inline void iwl3945_write_targ_mem(struct iwl3945_priv *priv, u32 addr, u32 val)
{
iwl3945_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
wmb();
iwl3945_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
}
@ -402,6 +397,7 @@ static inline void iwl3945_write_targ_mem_buf(struct iwl3945_priv *priv, u32 add
u32 len, u32 *values)
{
iwl3945_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
wmb();
for (; 0 < len; len -= sizeof(u32), values++)
iwl3945_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
}

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -335,10 +335,11 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
}
static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband,
static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta)
{
struct iwl3945_rs_sta *rs_sta = priv_sta;
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
int i;
IWL_DEBUG_RATE("enter\n");
@ -348,16 +349,21 @@ static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband,
* previous packets? Need to have IEEE 802.1X auth succeed immediately
* after assoc.. */
for (i = IWL_RATE_COUNT - 1; i >= 0; i--) {
for (i = sband->n_bitrates - 1; i >= 0; i--) {
if (sta->supp_rates[sband->band] & (1 << i)) {
rs_sta->last_txrate_idx = i;
break;
}
}
priv->sta_supp_rates = sta->supp_rates[sband->band];
/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
if (sband->band == IEEE80211_BAND_5GHZ)
if (sband->band == IEEE80211_BAND_5GHZ) {
rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
priv->sta_supp_rates = priv->sta_supp_rates <<
IWL_FIRST_OFDM_RATE;
}
IWL_DEBUG_RATE("leave\n");
}

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -277,12 +277,14 @@ int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate)
else if (rate == IWL_RATE_6M_INDEX)
next_rate = IWL_RATE_6M_INDEX;
break;
/* XXX cannot be invoked in current mac80211 so not a regression
case MODE_IEEE80211B:
if (rate == IWL_RATE_11M_INDEX_TABLE)
next_rate = IWL_RATE_5M_INDEX_TABLE;
case IEEE80211_BAND_2GHZ:
if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) &&
iwl3945_is_associated(priv)) {
if (rate == IWL_RATE_11M_INDEX)
next_rate = IWL_RATE_5M_INDEX;
}
break;
*/
default:
break;
}
@ -1101,9 +1103,8 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv)
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
rc = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
rc = iwl3945_poll_direct_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (rc < 0) {
spin_unlock_irqrestore(&priv->lock, flags);
IWL_DEBUG_INFO("Failed to init the card\n");
@ -1284,8 +1285,7 @@ int iwl3945_hw_nic_stop_master(struct iwl3945_priv *priv)
IWL_DEBUG_INFO("Card in power save, master is already "
"stopped\n");
else {
rc = iwl3945_poll_bit(priv, CSR_RESET,
CSR_RESET_REG_FLAG_MASTER_DISABLED,
rc = iwl3945_poll_direct_bit(priv, CSR_RESET,
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
if (rc < 0) {
spin_unlock_irqrestore(&priv->lock, flags);
@ -1310,9 +1310,8 @@ int iwl3945_hw_nic_reset(struct iwl3945_priv *priv)
iwl3945_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
rc = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
iwl3945_poll_direct_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
rc = iwl3945_grab_nic_access(priv);
if (!rc) {
@ -2309,7 +2308,8 @@ int iwl3945_hw_rxq_stop(struct iwl3945_priv *priv)
}
iwl3945_write_direct32(priv, FH_RCSR_CONFIG(0), 0);
rc = iwl3945_poll_direct_bit(priv, FH_RSSR_STATUS, (1 << 24), 1000);
rc = iwl3945_poll_direct_bit(priv, FH_RSSR_STATUS,
FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
if (rc < 0)
IWL_ERROR("Can't stop Rx DMA.\n");
@ -2378,7 +2378,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
iwl3945_hw_set_rate_n_flags(iwl3945_rates[i].plcp, 0);
table[index].try_cnt = priv->retry_rate;
prev_index = iwl3945_get_prev_ieee_rate(i);
table[index].next_rate_index = iwl3945_rates[prev_index].table_rs_index;
table[index].next_rate_index =
iwl3945_rates[prev_index].table_rs_index;
}
switch (priv->band) {
@ -2386,11 +2387,14 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
IWL_DEBUG_RATE("Select A mode rate scale\n");
/* If one of the following CCK rates is used,
* have it fall back to the 6M OFDM rate */
for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++)
table[i].next_rate_index = iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
for (i = IWL_RATE_1M_INDEX_TABLE;
i <= IWL_RATE_11M_INDEX_TABLE; i++)
table[i].next_rate_index =
iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
/* Don't fall back to CCK rates */
table[IWL_RATE_12M_INDEX_TABLE].next_rate_index = IWL_RATE_9M_INDEX_TABLE;
table[IWL_RATE_12M_INDEX_TABLE].next_rate_index =
IWL_RATE_9M_INDEX_TABLE;
/* Don't drop out of OFDM rates */
table[IWL_RATE_6M_INDEX_TABLE].next_rate_index =
@ -2401,11 +2405,20 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
IWL_DEBUG_RATE("Select B/G mode rate scale\n");
/* If an OFDM rate is used, have it fall back to the
* 1M CCK rates */
for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++)
table[i].next_rate_index = iwl3945_rates[IWL_FIRST_CCK_RATE].table_rs_index;
/* CCK shouldn't fall back to OFDM... */
table[IWL_RATE_11M_INDEX_TABLE].next_rate_index = IWL_RATE_5M_INDEX_TABLE;
if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) &&
iwl3945_is_associated(priv)) {
index = IWL_FIRST_CCK_RATE;
for (i = IWL_RATE_6M_INDEX_TABLE;
i <= IWL_RATE_54M_INDEX_TABLE; i++)
table[i].next_rate_index =
iwl3945_rates[index].table_rs_index;
index = IWL_RATE_11M_INDEX_TABLE;
/* CCK shouldn't fall back to OFDM... */
table[index].next_rate_index = IWL_RATE_5M_INDEX_TABLE;
}
break;
default:

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -476,7 +476,6 @@ union iwl3945_qos_capabity {
/* QoS structures */
struct iwl3945_qos_info {
int qos_enable;
int qos_active;
union iwl3945_qos_capabity qos_cap;
struct iwl3945_qosparam_cmd def_qos_parm;
@ -810,6 +809,8 @@ struct iwl3945_priv {
u16 active_rate;
u16 active_rate_basic;
u32 sta_supp_rates;
u8 call_post_assoc_from_beacon;
/* Rate scaling data */
s8 data_retry_limit;
@ -906,9 +907,6 @@ struct iwl3945_priv {
s8 user_txpower_limit;
s8 max_channel_txpower_limit;
#ifdef CONFIG_PM
u32 pm_state[16];
#endif
#ifdef CONFIG_IWL3945_DEBUG
/* debugging info */

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -84,12 +84,6 @@
#define IWL_CMD_FIFO_NUM 4
#define IWL49_FIRST_AMPDU_QUEUE 7
/* Tx rates */
#define IWL_CCK_RATES 4
#define IWL_OFDM_RATES 8
#define IWL_HT_RATES 16
#define IWL_MAX_RATES (IWL_CCK_RATES+IWL_OFDM_RATES+IWL_HT_RATES)
/* Time constants */
#define SHORT_SLOT_TIME 9
#define LONG_SLOT_TIME 20

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -63,7 +63,6 @@ static int iwl4965_hw_get_temperature(const struct iwl_priv *priv);
static struct iwl_mod_params iwl4965_mod_params = {
.num_of_queues = IWL49_NUM_QUEUES,
.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
.enable_qos = 1,
.amsdu_size_8K = 1,
.restart_fw = 1,
/* the rest are 0 by default */
@ -352,9 +351,8 @@ static int iwl4965_apm_init(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/* wait for clock stabilization */
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (ret < 0) {
IWL_DEBUG_INFO("Failed to init the card\n");
goto out;
@ -436,9 +434,8 @@ static int iwl4965_apm_stop_master(struct iwl_priv *priv)
/* set stop master bit */
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
ret = iwl_poll_bit(priv, CSR_RESET,
CSR_RESET_REG_FLAG_MASTER_DISABLED,
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
ret = iwl_poll_direct_bit(priv, CSR_RESET,
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
if (ret < 0)
goto out;
@ -482,11 +479,9 @@ static int iwl4965_apm_reset(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
ret = iwl_poll_bit(priv, CSR_RESET,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25);
if (ret)
ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (ret < 0)
goto out;
udelay(10);
@ -2367,9 +2362,6 @@ MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444);
MODULE_PARM_DESC(queues_num, "number of hw queues.");
/* QoS */
module_param_named(qos_enable, iwl4965_mod_params.enable_qos, int, 0444);
MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
/* 11n */
module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, 0444);
MODULE_PARM_DESC(11n_disable, "disable 11n functionality");

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -81,8 +81,7 @@ static int iwl5000_apm_stop_master(struct iwl_priv *priv)
/* set stop master bit */
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
ret = iwl_poll_bit(priv, CSR_RESET,
CSR_RESET_REG_FLAG_MASTER_DISABLED,
ret = iwl_poll_direct_bit(priv, CSR_RESET,
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
if (ret < 0)
goto out;
@ -120,9 +119,8 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/* wait for clock stabilization */
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (ret < 0) {
IWL_DEBUG_INFO("Failed to init the card\n");
return ret;
@ -189,9 +187,8 @@ static int iwl5000_apm_reset(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/* wait for clock stabilization */
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (ret < 0) {
IWL_DEBUG_INFO("Failed to init the card\n");
goto out;
@ -1533,7 +1530,6 @@ static struct iwl_ops iwl5000_ops = {
static struct iwl_mod_params iwl50_mod_params = {
.num_of_queues = IWL50_NUM_QUEUES,
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
.enable_qos = 1,
.amsdu_size_8K = 1,
.restart_fw = 1,
/* the rest are 0 by default */
@ -1631,8 +1627,6 @@ module_param_named(debug50, iwl50_mod_params.debug, int, 0444);
MODULE_PARM_DESC(debug50, "50XX debug output mask");
module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444);
MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series");
module_param_named(qos_enable50, iwl50_mod_params.enable_qos, int, 0444);
MODULE_PARM_DESC(qos_enable50, "enable all 50XX QoS functionality");
module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, 0444);
MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality");
module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, int, 0444);

View File

@ -22,7 +22,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* Tomas Winkler <tomas.winkler@intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -38,7 +38,6 @@
#include "iwl-dev.h"
#include "iwl-sta.h"
#include "iwl-core.h"
#include "iwl-helpers.h"
#define RS_NAME "iwl-agn-rs"

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -83,7 +83,7 @@
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
MODULE_ALIAS("iwl4965");
@ -310,7 +310,7 @@ void iwl_update_chain_flags(struct iwl_priv *priv)
static int iwl_send_bt_config(struct iwl_priv *priv)
{
struct iwl4965_bt_cmd bt_cmd = {
struct iwl_bt_cmd bt_cmd = {
.flags = 3,
.lead_time = 0xAA,
.max_kill = 1,
@ -319,7 +319,7 @@ static int iwl_send_bt_config(struct iwl_priv *priv)
};
return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
sizeof(struct iwl4965_bt_cmd), &bt_cmd);
sizeof(struct iwl_bt_cmd), &bt_cmd);
}
static void iwl_clear_free_frames(struct iwl_priv *priv)
@ -546,9 +546,6 @@ static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
if (!priv->qos_data.qos_enable)
return;
priv->qos_data.def_qos_parm.qos_flags = 0;
if (priv->qos_data.qos_cap.q_AP.queue_request &&
@ -860,7 +857,7 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
struct iwl4965_csa_notification *csa = &(pkt->u.csa_notif);
struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
IWL_DEBUG_11H("CSA notif: channel %d, status %d\n",
le16_to_cpu(csa->channel), le32_to_cpu(csa->status));
rxon->channel = csa->channel;
@ -872,7 +869,7 @@ static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_sleep_notification *sleep = &(pkt->u.sleep_notif);
struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
@ -942,7 +939,8 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_beacon_notif *beacon = &(pkt->u.beacon_status);
struct iwl4965_beacon_notif *beacon =
(struct iwl4965_beacon_notif *)pkt->u.raw;
u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
IWL_DEBUG_RX("beacon status %x retries %d iss %d "
@ -1405,8 +1403,11 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
* the driver as well won't allow loading if RFKILL is set
* therefore no need to restart the driver from this handler
*/
if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status))
if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
clear_bit(STATUS_RF_KILL_HW, &priv->status);
if (priv->is_open && !iwl_is_rfkill(priv))
queue_work(priv->workqueue, &priv->up);
}
handled |= CSR_INT_BIT_RF_KILL;
}
@ -2963,12 +2964,6 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len)
goto out_unlock;
}
if (priv->iw_mode == NL80211_IFTYPE_AP) { /* APs don't scan */
ret = -EIO;
IWL_ERROR("ERROR: APs don't scan\n");
goto out_unlock;
}
/* We don't schedule scan within next_scan_jiffies period.
* Avoid scanning during possible EAPOL exchange, return
* success immediately.
@ -3112,11 +3107,6 @@ static int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
return 0;
}
if (!priv->qos_data.qos_enable) {
priv->qos_data.qos_active = 0;
IWL_DEBUG_MAC80211("leave - qos not enabled\n");
return 0;
}
q = AC_NUM - 1 - queue;
spin_lock_irqsave(&priv->lock, flags);

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* Tomas Winkler <tomas.winkler@intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* Tomas Winkler <tomas.winkler@intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -94,6 +94,7 @@ enum {
REPLY_WEPKEY = 0x20,
/* RX, TX, LEDs */
REPLY_3945_RX = 0x1b, /* 3945 only */
REPLY_TX = 0x1c,
REPLY_RATE_SCALE = 0x47, /* 3945 only */
REPLY_LEDS_CMD = 0x48,
@ -701,7 +702,7 @@ struct iwl_rxon_time_cmd {
/*
* REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
*/
struct iwl4965_channel_switch_cmd {
struct iwl_channel_switch_cmd {
u8 band;
u8 expect_beacon;
__le16 channel;
@ -714,7 +715,7 @@ struct iwl4965_channel_switch_cmd {
/*
* CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command)
*/
struct iwl4965_csa_notification {
struct iwl_csa_notification {
__le16 band;
__le16 channel;
__le32 status; /* 0 - OK, 1 - fail */
@ -1023,25 +1024,6 @@ struct iwl_wep_cmd {
*
*****************************************************************************/
struct iwl4965_rx_frame_stats {
u8 phy_count;
u8 id;
u8 rssi;
u8 agc;
__le16 sig_avg;
__le16 noise_diff;
u8 payload[0];
} __attribute__ ((packed));
struct iwl4965_rx_frame_hdr {
__le16 channel;
__le16 phy_flags;
u8 reserved1;
u8 rate;
__le16 len;
u8 payload[0];
} __attribute__ ((packed));
#define RX_RES_STATUS_NO_CRC32_ERROR cpu_to_le32(1 << 0)
#define RX_RES_STATUS_NO_RXE_OVERFLOW cpu_to_le32(1 << 1)
@ -1072,26 +1054,6 @@ struct iwl4965_rx_frame_hdr {
#define RX_MPDU_RES_STATUS_TTAK_OK (1 << 7)
#define RX_MPDU_RES_STATUS_DEC_DONE_MSK (0x800)
struct iwl4965_rx_frame_end {
__le32 status;
__le64 timestamp;
__le32 beacon_timestamp;
} __attribute__ ((packed));
/*
* REPLY_3945_RX = 0x1b (response only, not a command)
*
* NOTE: DO NOT dereference from casts to this structure
* It is provided only for calculating minimum data set size.
* The actual offsets of the hdr and end are dynamic based on
* stats.phy_count
*/
struct iwl4965_rx_frame {
struct iwl4965_rx_frame_stats stats;
struct iwl4965_rx_frame_hdr hdr;
struct iwl4965_rx_frame_end end;
} __attribute__ ((packed));
/* Fixed (non-configurable) rx data from phy */
#define IWL49_RX_RES_PHY_CNT 14
@ -1276,7 +1238,7 @@ struct iwl4965_rx_mpdu_res_start {
* Used for managing Tx retries when expecting block-acks.
* Driver should set these fields to 0.
*/
struct iwl4965_dram_scratch {
struct iwl_dram_scratch {
u8 try_cnt; /* Tx attempts */
u8 bt_kill_cnt; /* Tx attempts blocked by Bluetooth device */
__le16 reserved;
@ -1307,9 +1269,9 @@ struct iwl_tx_cmd {
__le32 tx_flags; /* TX_CMD_FLG_* */
/* 4965's uCode may modify this field of the Tx command (in host DRAM!).
/* uCode may modify this field of the Tx command (in host DRAM!).
* Driver must also set dram_lsb_ptr and dram_msb_ptr in this cmd. */
struct iwl4965_dram_scratch scratch;
struct iwl_dram_scratch scratch;
/* Rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is cleared. */
__le32 rate_n_flags; /* RATE_MCS_* */
@ -1917,7 +1879,7 @@ struct iwl_link_quality_cmd {
* same platform. Bluetooth device alerts wireless device when it will Tx;
* wireless device can delay or kill its own Tx to accommodate.
*/
struct iwl4965_bt_cmd {
struct iwl_bt_cmd {
u8 flags;
u8 lead_time;
u8 max_kill;
@ -1943,18 +1905,18 @@ struct iwl4965_bt_cmd {
RXON_FILTER_ASSOC_MSK | \
RXON_FILTER_BCON_AWARE_MSK)
struct iwl4965_measure_channel {
struct iwl_measure_channel {
__le32 duration; /* measurement duration in extended beacon
* format */
u8 channel; /* channel to measure */
u8 type; /* see enum iwl4965_measure_type */
u8 type; /* see enum iwl_measure_type */
__le16 reserved;
} __attribute__ ((packed));
/*
* REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command)
*/
struct iwl4965_spectrum_cmd {
struct iwl_spectrum_cmd {
__le16 len; /* number of bytes starting from token */
u8 token; /* token id */
u8 id; /* measurement id -- 0 or 1 */
@ -1967,13 +1929,13 @@ struct iwl4965_spectrum_cmd {
__le32 filter_flags; /* rxon filter flags */
__le16 channel_count; /* minimum 1, maximum 10 */
__le16 reserved3;
struct iwl4965_measure_channel channels[10];
struct iwl_measure_channel channels[10];
} __attribute__ ((packed));
/*
* REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response)
*/
struct iwl4965_spectrum_resp {
struct iwl_spectrum_resp {
u8 token;
u8 id; /* id of the prior command replaced, or 0xff */
__le16 status; /* 0 - command will be handled
@ -1981,12 +1943,12 @@ struct iwl4965_spectrum_resp {
* measurement) */
} __attribute__ ((packed));
enum iwl4965_measurement_state {
enum iwl_measurement_state {
IWL_MEASUREMENT_START = 0,
IWL_MEASUREMENT_STOP = 1,
};
enum iwl4965_measurement_status {
enum iwl_measurement_status {
IWL_MEASUREMENT_OK = 0,
IWL_MEASUREMENT_CONCURRENT = 1,
IWL_MEASUREMENT_CSA_CONFLICT = 2,
@ -1999,18 +1961,18 @@ enum iwl4965_measurement_status {
#define NUM_ELEMENTS_IN_HISTOGRAM 8
struct iwl4965_measurement_histogram {
struct iwl_measurement_histogram {
__le32 ofdm[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 0.8usec counts */
__le32 cck[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 1usec counts */
} __attribute__ ((packed));
/* clear channel availability counters */
struct iwl4965_measurement_cca_counters {
struct iwl_measurement_cca_counters {
__le32 ofdm;
__le32 cck;
} __attribute__ ((packed));
enum iwl4965_measure_type {
enum iwl_measure_type {
IWL_MEASURE_BASIC = (1 << 0),
IWL_MEASURE_CHANNEL_LOAD = (1 << 1),
IWL_MEASURE_HISTOGRAM_RPI = (1 << 2),
@ -2023,7 +1985,7 @@ enum iwl4965_measure_type {
/*
* SPECTRUM_MEASURE_NOTIFICATION = 0x75 (notification only, not a command)
*/
struct iwl4965_spectrum_notification {
struct iwl_spectrum_notification {
u8 id; /* measurement id -- 0 or 1 */
u8 token;
u8 channel_index; /* index in measurement channel list */
@ -2031,7 +1993,7 @@ struct iwl4965_spectrum_notification {
__le32 start_time; /* lower 32-bits of TSF */
u8 band; /* 0 - 5.2GHz, 1 - 2.4GHz */
u8 channel;
u8 type; /* see enum iwl4965_measurement_type */
u8 type; /* see enum iwl_measurement_type */
u8 reserved1;
/* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only only
* valid if applicable for measurement type requested. */
@ -2041,9 +2003,9 @@ struct iwl4965_spectrum_notification {
u8 basic_type; /* 0 - bss, 1 - ofdm preamble, 2 -
* unidentified */
u8 reserved2[3];
struct iwl4965_measurement_histogram histogram;
struct iwl_measurement_histogram histogram;
__le32 stop_time; /* lower 32-bits of TSF */
__le32 status; /* see iwl4965_measurement_status */
__le32 status; /* see iwl_measurement_status */
} __attribute__ ((packed));
/******************************************************************************
@ -2101,7 +2063,7 @@ struct iwl_powertable_cmd {
* PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command)
* 3945 and 4965 identical.
*/
struct iwl4965_sleep_notification {
struct iwl_sleep_notification {
u8 pm_sleep_mode;
u8 pm_wakeup_src;
__le16 reserved;
@ -2131,14 +2093,14 @@ enum {
#define CARD_STATE_CMD_DISABLE 0x00 /* Put card to sleep */
#define CARD_STATE_CMD_ENABLE 0x01 /* Wake up card */
#define CARD_STATE_CMD_HALT 0x02 /* Power down permanently */
struct iwl4965_card_state_cmd {
struct iwl_card_state_cmd {
__le32 status; /* CARD_STATE_CMD_* request new power state */
} __attribute__ ((packed));
/*
* CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command)
*/
struct iwl4965_card_state_notif {
struct iwl_card_state_notif {
__le32 flags;
} __attribute__ ((packed));
@ -2201,7 +2163,7 @@ struct iwl_scan_channel {
* struct iwl_ssid_ie - directed scan network information element
*
* Up to 4 of these may appear in REPLY_SCAN_CMD, selected by "type" field
* in struct iwl4965_scan_channel; each channel may select different ssids from
* in struct iwl_scan_channel; each channel may select different ssids from
* among the 4 entries. SSID IEs get transmitted in reverse order of entry.
*/
struct iwl_ssid_ie {
@ -2301,7 +2263,7 @@ struct iwl_scan_cmd {
* Number of channels in list is specified by channel_count.
* Each channel in list is of type:
*
* struct iwl4965_scan_channel channels[0];
* struct iwl_scan_channel channels[0];
*
* NOTE: Only one band of channels can be scanned per pass. You
* must not mix 2.4GHz channels and 5.2GHz channels, and you must wait
@ -2612,7 +2574,7 @@ struct iwl_notif_statistics {
* then this notification will be sent. */
#define CONSECUTIVE_MISSED_BCONS_TH 20
struct iwl4965_missed_beacon_notif {
struct iwl_missed_beacon_notif {
__le32 consequtive_missed_beacons;
__le32 total_missed_becons;
__le32 num_expected_beacons;
@ -3049,27 +3011,22 @@ struct iwl_rx_packet {
struct iwl_cmd_header hdr;
union {
struct iwl_alive_resp alive_frame;
struct iwl4965_rx_frame rx_frame;
struct iwl4965_tx_resp tx_resp;
struct iwl4965_spectrum_notification spectrum_notif;
struct iwl4965_csa_notification csa_notif;
struct iwl_spectrum_notification spectrum_notif;
struct iwl_csa_notification csa_notif;
struct iwl_error_resp err_resp;
struct iwl4965_card_state_notif card_state_notif;
struct iwl4965_beacon_notif beacon_status;
struct iwl_card_state_notif card_state_notif;
struct iwl_add_sta_resp add_sta;
struct iwl_rem_sta_resp rem_sta;
struct iwl4965_sleep_notification sleep_notif;
struct iwl4965_spectrum_resp spectrum;
struct iwl_sleep_notification sleep_notif;
struct iwl_spectrum_resp spectrum;
struct iwl_notif_statistics stats;
struct iwl_compressed_ba_resp compressed_ba;
struct iwl4965_missed_beacon_notif missed_beacon;
struct iwl_missed_beacon_notif missed_beacon;
__le32 status;
u8 raw[0];
} u;
} __attribute__ ((packed));
#define IWL_RX_FRAME_SIZE (4 + sizeof(struct iwl4965_rx_frame))
int iwl_agn_check_rxon_cmd(struct iwl_rxon_cmd *rxon);
#endif /* __iwl_commands_h__ */

View File

@ -22,7 +22,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* Tomas Winkler <tomas.winkler@intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
@ -42,7 +42,7 @@
MODULE_DESCRIPTION("iwl core");
MODULE_VERSION(IWLWIFI_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \
@ -243,24 +243,25 @@ void iwl_reset_qos(struct iwl_priv *priv)
u16 cw_min = 15;
u16 cw_max = 1023;
u8 aifs = 2;
u8 is_legacy = 0;
bool is_legacy = false;
unsigned long flags;
int i;
spin_lock_irqsave(&priv->lock, flags);
priv->qos_data.qos_active = 0;
/* QoS always active in AP and ADHOC mode
* In STA mode wait for association
*/
if (priv->iw_mode == NL80211_IFTYPE_ADHOC ||
priv->iw_mode == NL80211_IFTYPE_AP)
priv->qos_data.qos_active = 1;
else
priv->qos_data.qos_active = 0;
if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
if (!(priv->active_rate & 0xfff0)) {
cw_min = 31;
is_legacy = 1;
}
} else if (priv->iw_mode == NL80211_IFTYPE_AP) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
} else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
/* check for legacy mode */
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC &&
(priv->active_rate & IWL_OFDM_RATES_MASK) == 0) ||
(priv->iw_mode == NL80211_IFTYPE_STATION &&
(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) {
cw_min = 31;
is_legacy = 1;
}
@ -890,9 +891,6 @@ int iwl_init_drv(struct iwl_priv *priv)
iwl_set_rxon_chain(priv);
iwl_init_scan_params(priv);
if (priv->cfg->mod_params->enable_qos)
priv->qos_data.qos_enable = 1;
iwl_reset_qos(priv);
priv->qos_data.qos_active = 0;
@ -1448,6 +1446,16 @@ int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
return 0;
}
/* when driver is up while rfkill is on, it wont receive
* any CARD_STATE_NOTIFICATION notifications so we have to
* restart it in here
*/
if (priv->is_open && !test_bit(STATUS_ALIVE, &priv->status)) {
clear_bit(STATUS_RF_KILL_SW, &priv->status);
if (!iwl_is_rfkill(priv))
queue_work(priv->workqueue, &priv->up);
}
/* If the driver is already loaded, it will receive
* CARD_STATE_NOTIFICATION notifications and the handler will
* call restart to reload the driver.

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* Tomas Winkler <tomas.winkler@intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -72,6 +72,7 @@ struct iwl_cmd;
#define IWLWIFI_VERSION "1.3.27k"
#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation"
#define DRV_AUTHOR "<ilw@linux.intel.com>"
#define IWL_PCI_DEVICE(dev, subdev, cfg) \
.vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
@ -157,7 +158,6 @@ struct iwl_mod_params {
int disable_hw_scan; /* def: 0 = use h/w scan */
int num_of_queues; /* def: HW dependent */
int num_of_ampdu_queues;/* def: HW dependent */
int enable_qos; /* def: 1 = use quality of service */
int disable_11n; /* def: 0 = disable 11n capabilities */
int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */
int antenna; /* def: 0 = both antennas (use diversity) */

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -216,6 +216,8 @@
/* EEPROM REG */
#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
#define CSR_EEPROM_REG_MSK_ADDR (0x0000FFFC)
#define CSR_EEPROM_REG_MSK_DATA (0xFFFF0000)
/* EEPROM GP */
#define CSR_EEPROM_GP_VALID_MSK (0x00000006)

View File

@ -21,7 +21,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -22,7 +22,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* Tomas Winkler <tomas.winkler@intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -186,12 +186,6 @@ struct iwl_channel_info {
u8 fat_extension_channel; /* HT_IE_EXT_CHANNEL_* */
};
struct iwl4965_clip_group {
/* maximum power level to prevent clipping for each rate, derived by
* us from this band's saturation power in EEPROM */
const s8 clip_powers[IWL_MAX_RATES];
};
#define IWL_TX_FIFO_AC0 0
#define IWL_TX_FIFO_AC1 1
@ -436,7 +430,6 @@ union iwl_qos_capabity {
/* QoS structures */
struct iwl_qos_info {
int qos_enable;
int qos_active;
union iwl_qos_capabity qos_cap;
struct iwl_qosparam_cmd def_qos_parm;
@ -505,6 +498,10 @@ struct iwl_sensitivity_ranges {
#define IWL_FAT_CHANNEL_52 BIT(IEEE80211_BAND_5GHZ)
#define KELVIN_TO_CELSIUS(x) ((x)-273)
#define CELSIUS_TO_KELVIN(x) ((x)+273)
/**
* struct iwl_hw_params
* @max_txq_num: Max # Tx queues supported
@ -553,15 +550,6 @@ struct iwl_hw_params {
#define HT_SHORT_GI_40MHZ (1 << 1)
#define IWL_RX_HDR(x) ((struct iwl4965_rx_frame_hdr *)(\
x->u.rx_frame.stats.payload + \
x->u.rx_frame.stats.phy_count))
#define IWL_RX_END(x) ((struct iwl4965_rx_frame_end *)(\
IWL_RX_HDR(x)->payload + \
le16_to_cpu(IWL_RX_HDR(x)->len)))
#define IWL_RX_STATS(x) (&x->u.rx_frame.stats)
#define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload)
/******************************************************************************
*
* Functions implemented in core module which are forward declared here
@ -792,7 +780,7 @@ struct iwl_priv {
#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
/* spectrum measurement report caching */
struct iwl4965_spectrum_notification measure_report;
struct iwl_spectrum_notification measure_report;
u8 measurement_status;
#endif
/* ucode beacon time */
@ -803,10 +791,6 @@ struct iwl_priv {
struct iwl_channel_info *channel_info; /* channel info array */
u8 channel_count; /* # of channels */
/* each calibration channel group in the EEPROM has a derived
* clip setting for each rate. */
const struct iwl4965_clip_group clip_groups[5];
/* thermal calibration */
s32 temperature; /* degrees Kelvin */
s32 last_temperature;
@ -1003,9 +987,6 @@ struct iwl_priv {
s8 tx_power_user_lmt;
s8 tx_power_channel_lmt;
#ifdef CONFIG_PM
u32 pm_state[16];
#endif
#ifdef CONFIG_IWLWIFI_DEBUG
/* debugging info */

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* Tomas Winkler <tomas.winkler@intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -169,10 +169,9 @@ int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
/* See if we got it */
ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
EEPROM_SEM_TIMEOUT);
ret = iwl_poll_direct_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
EEPROM_SEM_TIMEOUT);
if (ret >= 0) {
IWL_DEBUG_IO("Acquired semaphore after %d tries.\n",
count+1);
@ -210,10 +209,8 @@ int iwl_eeprom_init(struct iwl_priv *priv)
{
u16 *e;
u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
u32 r;
int sz = priv->cfg->eeprom_size;
int ret;
int i;
u16 addr;
/* allocate eeprom */
@ -241,22 +238,19 @@ int iwl_eeprom_init(struct iwl_priv *priv)
/* eeprom is an array of 16bit values */
for (addr = 0; addr < sz; addr += sizeof(u16)) {
_iwl_write32(priv, CSR_EEPROM_REG, addr << 1);
_iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
u32 r;
for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
i += IWL_EEPROM_ACCESS_DELAY) {
r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
if (r & CSR_EEPROM_REG_READ_VALID_MSK)
break;
udelay(IWL_EEPROM_ACCESS_DELAY);
}
_iwl_write32(priv, CSR_EEPROM_REG,
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
CSR_EEPROM_REG_READ_VALID_MSK,
IWL_EEPROM_ACCESS_TIMEOUT);
if (ret < 0) {
IWL_ERROR("Time out reading EEPROM[%d]\n", addr);
ret = -ETIMEDOUT;
goto done;
}
r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
}
ret = 0;

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* Tomas Winkler <tomas.winkler@intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -68,17 +68,14 @@ struct iwl_priv;
/*
* EEPROM access time values:
*
* Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG,
* then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit
* CSR_EEPROM_REG_BIT_CMD (0x2).
* Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG.
* Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
* When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
* Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
*/
#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */
#define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */
#define IWL_EEPROM_SEM_TIMEOUT 10 /* milliseconds */
#define IWL_EEPROM_SEM_TIMEOUT 10 /* microseconds */
#define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -266,11 +266,8 @@
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000)
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000)
#define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME (0x00008000)
#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */
/**
* Rx Shared Status Registers (RSSR)
*

View File

@ -22,7 +22,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* Tomas Winkler <tomas.winkler@intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -32,8 +32,6 @@
#include <linux/ctype.h>
#define KELVIN_TO_CELSIUS(x) ((x)-273)
#define CELSIUS_TO_KELVIN(x) ((x)+273)
#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))

View File

@ -21,7 +21,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -95,7 +95,7 @@ static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr,
do {
if ((_iwl_read32(priv, addr) & mask) == (bits & mask))
return i;
mdelay(10);
udelay(10);
i += 10;
} while (i < timeout);
@ -269,19 +269,10 @@ static inline void iwl_write_reg_buf(struct iwl_priv *priv,
}
}
static inline int _iwl_poll_direct_bit(struct iwl_priv *priv,
u32 addr, u32 mask, int timeout)
static inline int _iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr,
u32 mask, int timeout)
{
int i = 0;
do {
if ((_iwl_read_direct32(priv, addr) & mask) == mask)
return i;
mdelay(10);
i += 10;
} while (i < timeout);
return -ETIMEDOUT;
return _iwl_poll_bit(priv, addr, mask, mask, timeout);
}
#ifdef CONFIG_IWLWIFI_DEBUG
@ -308,6 +299,7 @@ static inline int __iwl_poll_direct_bit(const char *f, u32 l,
static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg)
{
_iwl_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
rmb();
return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
}
#ifdef CONFIG_IWLWIFI_DEBUG
@ -330,6 +322,7 @@ static inline void _iwl_write_prph(struct iwl_priv *priv,
{
_iwl_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
((addr & 0x0000FFFF) | (3 << 24)));
wmb();
_iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
}
#ifdef CONFIG_IWLWIFI_DEBUG
@ -392,12 +385,14 @@ static inline void iwl_clear_bits_prph(struct iwl_priv
static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr)
{
iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
rmb();
return iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
}
static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val)
{
iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
wmb();
iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
}
@ -405,6 +400,7 @@ static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr,
u32 len, u32 *values)
{
iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
wmb();
for (; 0 < len; len -= sizeof(u32), values++)
iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
}

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -41,7 +41,6 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-helpers.h"
#ifdef CONFIG_IWLWIFI_DEBUG
static const char *led_type_str[] = {

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
@ -39,7 +39,6 @@
#include "iwl-commands.h"
#include "iwl-debug.h"
#include "iwl-power.h"
#include "iwl-helpers.h"
/*
* Setting power level allow the card to go to sleep when not busy

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
#ifndef __iwl_power_setting_h__

View File

@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
#include <linux/kernel.h>
@ -34,8 +34,6 @@
#include "iwl-eeprom.h"
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-helpers.h"
/* software rf-kill from user */
static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
#ifndef __iwl_rf_kill_h__

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -439,7 +439,7 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME |
FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
rb_size|
(rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
(rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
@ -467,10 +467,8 @@ int iwl_rxq_stop(struct iwl_priv *priv)
/* stop Rx DMA */
iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
ret = iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
(1 << 24), 1000);
if (ret < 0)
IWL_ERROR("Can't stop Rx DMA.\n");
iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
@ -484,7 +482,7 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_missed_beacon_notif *missed_beacon;
struct iwl_missed_beacon_notif *missed_beacon;
missed_beacon = &pkt->u.missed_beacon;
if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) {
@ -622,20 +620,24 @@ static int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm)
return sig_qual;
}
#ifdef CONFIG_IWLWIFI_DEBUG
/* Calc max signal level (dBm) among 3 possible receivers */
static inline int iwl_calc_rssi(struct iwl_priv *priv,
struct iwl_rx_phy_res *rx_resp)
{
return priv->cfg->ops->utils->calc_rssi(priv, rx_resp);
}
#ifdef CONFIG_IWLWIFI_DEBUG
/**
* iwl_dbg_report_frame - dump frame to syslog during debug sessions
*
* You may hack this function to show different aspects of received frames,
* including selective frame dumps.
* group100 parameter selects whether to show 1 out of 100 good frames.
*
* TODO: This was originally written for 3945, need to audit for
* proper operation with 4965.
* group100 parameter selects whether to show 1 out of 100 good data frames.
* All beacon and probe response frames are printed.
*/
static void iwl_dbg_report_frame(struct iwl_priv *priv,
struct iwl_rx_packet *pkt,
struct iwl_rx_phy_res *phy_res, u16 length,
struct ieee80211_hdr *header, int group100)
{
u32 to_us;
@ -647,20 +649,9 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
u16 seq_ctl;
u16 channel;
u16 phy_flags;
int rate_sym;
u16 length;
u16 status;
u16 bcn_tmr;
u32 rate_n_flags;
u32 tsf_low;
u64 tsf;
u8 rssi;
u8 agc;
u16 sig_avg;
u16 noise_diff;
struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
u8 *data = IWL_RX_DATA(pkt);
int rssi;
if (likely(!(priv->debug_level & IWL_DL_RX)))
return;
@ -670,22 +661,13 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
seq_ctl = le16_to_cpu(header->seq_ctrl);
/* metadata */
channel = le16_to_cpu(rx_hdr->channel);
phy_flags = le16_to_cpu(rx_hdr->phy_flags);
rate_sym = rx_hdr->rate;
length = le16_to_cpu(rx_hdr->len);
/* end-of-frame status and timestamp */
status = le32_to_cpu(rx_end->status);
bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
tsf = le64_to_cpu(rx_end->timestamp);
channel = le16_to_cpu(phy_res->channel);
phy_flags = le16_to_cpu(phy_res->phy_flags);
rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
/* signal statistics */
rssi = rx_stats->rssi;
agc = rx_stats->agc;
sig_avg = le16_to_cpu(rx_stats->sig_avg);
noise_diff = le16_to_cpu(rx_stats->noise_diff);
rssi = iwl_calc_rssi(priv, phy_res);
tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff;
to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
@ -739,11 +721,13 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
else
title = "Frame";
rate_idx = iwl_hwrate_to_plcp_idx(rate_sym);
if (unlikely(rate_idx == -1))
rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags);
if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) {
bitrate = 0;
else
WARN_ON_ONCE(1);
} else {
bitrate = iwl_rates[rate_idx].ieee / 2;
}
/* print frame summary.
* MAC addresses show just the last byte (for brevity),
@ -755,24 +739,17 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
length, rssi, channel, bitrate);
else {
/* src/dst addresses assume managed mode */
IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
"src=0x%02x, rssi=%u, tim=%lu usec, "
IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, src=0x%02x, "
"len=%u, rssi=%d, tim=%lu usec, "
"phy=0x%02x, chnl=%d\n",
title, le16_to_cpu(fc), header->addr1[5],
header->addr3[5], rssi,
header->addr3[5], length, rssi,
tsf_low - priv->scan_start_tsf,
phy_flags, channel);
}
}
if (print_dump)
iwl_print_hex_dump(priv, IWL_DL_RX, data, length);
}
#else
static inline void iwl_dbg_report_frame(struct iwl_priv *priv,
struct iwl_rx_packet *pkt,
struct ieee80211_hdr *header,
int group100)
{
iwl_print_hex_dump(priv, IWL_DL_RX, header, length);
}
#endif
@ -966,14 +943,6 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
rxb->skb = NULL;
}
/* Calc max signal level (dBm) among 3 possible receivers */
static inline int iwl_calc_rssi(struct iwl_priv *priv,
struct iwl_rx_phy_res *rx_resp)
{
return priv->cfg->ops->utils->calc_rssi(priv, rx_resp);
}
/* This is necessary only for a number of statistics, see the caller. */
static int iwl_is_network_packet(struct iwl_priv *priv,
struct ieee80211_hdr *header)
@ -1096,9 +1065,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
/* Set "1" to report good data frames in groups of 100 */
/* FIXME: need to optimize the call: */
iwl_dbg_report_frame(priv, pkt, header, 1);
#ifdef CONFIG_IWLWIFI_DEBUG
if (unlikely(priv->debug_level & IWL_DL_RX))
iwl_dbg_report_frame(priv, rx_start, len, header, 1);
#endif
IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n",
rx_status.signal, rx_status.noise, rx_status.signal,
(unsigned long long)rx_status.mactime);

View File

@ -22,7 +22,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
* Tomas Winkler <tomas.winkler@intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
#include <linux/types.h>

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -178,7 +178,7 @@ static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_spectrum_notification *report = &(pkt->u.spectrum_notif);
struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
if (!report->state) {
IWL_DEBUG(IWL_DL_11H,

View File

@ -21,7 +21,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -33,8 +33,6 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-sta.h"
#include "iwl-helpers.h"
#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */
#define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -628,7 +628,7 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv)
iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
200);
1000);
}
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -69,7 +69,6 @@ static int iwl3945_param_debug; /* def: 0 = minimal debug log messages */
static int iwl3945_param_disable; /* def: 0 = enable radio */
static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */
int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */
static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */
int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */
/*
@ -94,12 +93,13 @@ int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */
#define IWLWIFI_VERSION "1.2.26k" VD VS
#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation"
#define DRV_AUTHOR "<ilw@linux.intel.com>"
#define DRV_VERSION IWLWIFI_VERSION
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
static const struct ieee80211_supported_band *iwl3945_get_band(
@ -1505,10 +1505,8 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
{
u16 *e = (u16 *)&priv->eeprom;
u32 gp = iwl3945_read32(priv, CSR_EEPROM_GP);
u32 r;
int sz = sizeof(priv->eeprom);
int rc;
int i;
int ret;
u16 addr;
/* The EEPROM structure has several padding buffers within it
@ -1523,29 +1521,28 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
}
/* Make sure driver (instead of uCode) is allowed to read EEPROM */
rc = iwl3945_eeprom_acquire_semaphore(priv);
if (rc < 0) {
ret = iwl3945_eeprom_acquire_semaphore(priv);
if (ret < 0) {
IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
return -ENOENT;
}
/* eeprom is an array of 16bit values */
for (addr = 0; addr < sz; addr += sizeof(u16)) {
_iwl3945_write32(priv, CSR_EEPROM_REG, addr << 1);
u32 r;
_iwl3945_write32(priv, CSR_EEPROM_REG,
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
_iwl3945_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
i += IWL_EEPROM_ACCESS_DELAY) {
r = _iwl3945_read_direct32(priv, CSR_EEPROM_REG);
if (r & CSR_EEPROM_REG_READ_VALID_MSK)
break;
udelay(IWL_EEPROM_ACCESS_DELAY);
}
if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
ret = iwl3945_poll_direct_bit(priv, CSR_EEPROM_REG,
CSR_EEPROM_REG_READ_VALID_MSK,
IWL_EEPROM_ACCESS_TIMEOUT);
if (ret < 0) {
IWL_ERROR("Time out reading EEPROM[%d]\n", addr);
return -ETIMEDOUT;
return ret;
}
r = _iwl3945_read_direct32(priv, CSR_EEPROM_REG);
e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
}
@ -1693,17 +1690,21 @@ static void iwl3945_reset_qos(struct iwl3945_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
priv->qos_data.qos_active = 0;
if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
if (!(priv->active_rate & 0xfff0)) {
cw_min = 31;
is_legacy = 1;
}
} else if (priv->iw_mode == NL80211_IFTYPE_AP) {
if (priv->qos_data.qos_enable)
priv->qos_data.qos_active = 1;
} else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
/* QoS always active in AP and ADHOC mode
* In STA mode wait for association
*/
if (priv->iw_mode == NL80211_IFTYPE_ADHOC ||
priv->iw_mode == NL80211_IFTYPE_AP)
priv->qos_data.qos_active = 1;
else
priv->qos_data.qos_active = 0;
/* check for legacy mode */
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC &&
(priv->active_rate & IWL_OFDM_RATES_MASK) == 0) ||
(priv->iw_mode == NL80211_IFTYPE_STATION &&
(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) {
cw_min = 31;
is_legacy = 1;
}
@ -1775,9 +1776,6 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
if (!priv->qos_data.qos_enable)
return;
spin_lock_irqsave(&priv->lock, flags);
priv->qos_data.def_qos_parm.qos_flags = 0;
@ -2103,11 +2101,6 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv)
static int iwl3945_scan_initiate(struct iwl3945_priv *priv)
{
if (priv->iw_mode == NL80211_IFTYPE_AP) {
IWL_ERROR("APs don't scan.\n");
return 0;
}
if (!iwl3945_is_ready_rf(priv)) {
IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
return -EIO;
@ -6976,12 +6969,6 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
goto out_unlock;
}
if (priv->iw_mode == NL80211_IFTYPE_AP) { /* APs don't scan */
rc = -EIO;
IWL_ERROR("ERROR: APs don't scan\n");
goto out_unlock;
}
/* we don't schedule scan within next_scan_jiffies period */
if (priv->next_scan_jiffies &&
time_after(priv->next_scan_jiffies, jiffies)) {
@ -7095,11 +7082,6 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
return 0;
}
if (!priv->qos_data.qos_enable) {
priv->qos_data.qos_active = 0;
IWL_DEBUG_MAC80211("leave - qos not enabled\n");
return 0;
}
q = AC_NUM - 1 - queue;
spin_lock_irqsave(&priv->lock, flags);
@ -7925,9 +7907,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
err = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
err = iwl3945_poll_direct_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (err < 0) {
IWL_DEBUG_INFO("Failed to init the card\n");
goto out_remove_sysfs;
@ -7980,9 +7961,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
priv->iw_mode = NL80211_IFTYPE_STATION;
if (iwl3945_param_qos_enable)
priv->qos_data.qos_enable = 1;
iwl3945_reset_qos(priv);
priv->qos_data.qos_active = 0;
@ -8373,9 +8351,5 @@ MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
module_param_named(queues_num, iwl3945_param_queues_num, int, 0444);
MODULE_PARM_DESC(queues_num, "number of hw queues.");
/* QoS */
module_param_named(qos_enable, iwl3945_param_qos_enable, int, 0444);
MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
module_exit(iwl3945_exit);
module_init(iwl3945_init);

View File

@ -245,6 +245,7 @@ enum cmd_mesh_access_opts {
CMD_ACT_MESH_GET_ROUTE_EXP,
CMD_ACT_MESH_SET_AUTOSTART_ENABLED,
CMD_ACT_MESH_GET_AUTOSTART_ENABLED,
CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT = 17,
};
/* Define actions and types for CMD_MESH_CONFIG */

View File

@ -257,6 +257,58 @@ static ssize_t lbs_anycast_set(struct device *dev,
return strlen(buf);
}
/**
* @brief Get function for sysfs attribute prb_rsp_limit
*/
static ssize_t lbs_prb_rsp_limit_get(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct lbs_private *priv = netdev_priv(to_net_dev(dev));
struct cmd_ds_mesh_access mesh_access;
int ret;
u32 retry_limit;
memset(&mesh_access, 0, sizeof(mesh_access));
mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET);
ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
&mesh_access);
if (ret)
return ret;
retry_limit = le32_to_cpu(mesh_access.data[1]);
return snprintf(buf, 10, "%d\n", retry_limit);
}
/**
* @brief Set function for sysfs attribute prb_rsp_limit
*/
static ssize_t lbs_prb_rsp_limit_set(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct lbs_private *priv = netdev_priv(to_net_dev(dev));
struct cmd_ds_mesh_access mesh_access;
int ret;
unsigned long retry_limit;
memset(&mesh_access, 0, sizeof(mesh_access));
mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET);
if (!strict_strtoul(buf, 10, &retry_limit))
return -ENOTSUPP;
if (retry_limit > 15)
return -ENOTSUPP;
mesh_access.data[1] = cpu_to_le32(retry_limit);
ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
&mesh_access);
if (ret)
return ret;
return strlen(buf);
}
static int lbs_add_rtap(struct lbs_private *priv);
static void lbs_remove_rtap(struct lbs_private *priv);
static int lbs_add_mesh(struct lbs_private *priv);
@ -375,8 +427,16 @@ static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set);
*/
static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set);
/**
* prb_rsp_limit attribute to be exported per mshX interface
* through sysfs (/sys/class/net/mshX/prb_rsp_limit)
*/
static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get,
lbs_prb_rsp_limit_set);
static struct attribute *lbs_mesh_sysfs_entries[] = {
&dev_attr_anycast_mask.attr,
&dev_attr_prb_rsp_limit.attr,
NULL,
};

View File

@ -522,6 +522,10 @@ static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw,
case STA_NOTIFY_REMOVE:
hwsim_clear_sta_magic(sta);
break;
case STA_NOTIFY_SLEEP:
case STA_NOTIFY_AWAKE:
/* TODO: make good use of these flags */
break;
}
}

View File

@ -279,7 +279,7 @@ init_airport(void)
static void __exit
exit_airport(void)
{
return macio_unregister_driver(&airport_driver);
macio_unregister_driver(&airport_driver);
}
module_init(init_airport);

View File

@ -1750,7 +1750,7 @@ static void orinoco_send_bssid_wevent(struct orinoco_private *priv)
union iwreq_data wrqu;
int err;
err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
if (err != 0)
return;
@ -1773,7 +1773,7 @@ static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv)
if (!priv->has_wpa)
return;
err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
sizeof(buf), NULL, &buf);
if (err != 0)
return;
@ -1803,7 +1803,7 @@ static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv)
if (!priv->has_wpa)
return;
err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO,
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO,
sizeof(buf), NULL, &buf);
if (err != 0)
return;

View File

@ -178,13 +178,17 @@ static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
__func__, vcc,
cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
if (!ignore_cis_vcc)
goto next_entry;
}
} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
__func__, vcc,
dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
if (!ignore_cis_vcc)
goto next_entry;
}

View File

@ -248,13 +248,17 @@ static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
__func__, vcc,
cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
if (!ignore_cis_vcc)
goto next_entry;
}
} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
__func__, vcc,
dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
if (!ignore_cis_vcc)
goto next_entry;
}

View File

@ -540,6 +540,14 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
size_t header_len = sizeof(*hdr);
u32 tsf32;
/*
* If the device is in a unspecified state we have to
* ignore all data frames. Else we could end up with a
* nasty crash.
*/
if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
return 0;
if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) {
if (priv->filter_flags & FIF_FCSFAIL)
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
@ -608,6 +616,12 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue)))
return;
/*
* don't try to free an already unlinked skb
*/
if (unlikely((!skb->next) || (!skb->prev)))
return;
spin_lock_irqsave(&priv->tx_queue.lock, flags);
info = IEEE80211_SKB_CB(skb);
range = (void *)info->rate_driver_data;
@ -874,7 +888,27 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
return -EINVAL;
spin_lock_irqsave(&priv->tx_queue.lock, flags);
left = skb_queue_len(&priv->tx_queue);
if (unlikely(left >= 28)) {
/*
* The tx_queue is nearly full!
* We have throttle normal data traffic, because we must
* have a few spare slots for control frames left.
*/
ieee80211_stop_queues(dev);
if (unlikely(left == 32)) {
/*
* The tx_queue is now really full.
*
* TODO: check if the device has crashed and reset it.
*/
spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
return -ENOSPC;
}
}
while (left--) {
u32 hole_size;
info = IEEE80211_SKB_CB(entry);
@ -903,7 +937,7 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
if (!target_skb) {
spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
ieee80211_stop_queues(dev);
return -ENOMEM;
return -ENOSPC;
}
info = IEEE80211_SKB_CB(skb);
@ -1051,19 +1085,6 @@ static int p54_sta_unlock(struct ieee80211_hw *dev, u8 *addr)
return 0;
}
static void p54_sta_notify_ps(struct ieee80211_hw *dev,
enum sta_notify_ps_cmd notify_cmd,
struct ieee80211_sta *sta)
{
switch (notify_cmd) {
case STA_NOTIFY_AWAKE:
p54_sta_unlock(dev, sta->addr);
break;
default:
break;
}
}
static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
enum sta_notify_cmd notify_cmd,
struct ieee80211_sta *sta)
@ -1076,6 +1097,10 @@ static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
* need to buffer frames for this station anymore.
*/
p54_sta_unlock(dev, sta->addr);
break;
case STA_NOTIFY_AWAKE:
/* update the firmware's filter table */
p54_sta_unlock(dev, sta->addr);
break;
default:
@ -1684,19 +1709,18 @@ static void p54_stop(struct ieee80211_hw *dev)
struct sk_buff *skb;
mutex_lock(&priv->conf_mutex);
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
del_timer(&priv->stats_timer);
p54_free_skb(dev, priv->cached_stats);
priv->cached_stats = NULL;
if (priv->cached_beacon)
p54_tx_cancel(dev, priv->cached_beacon);
priv->stop(dev);
while ((skb = skb_dequeue(&priv->tx_queue)))
kfree_skb(skb);
priv->cached_beacon = NULL;
priv->stop(dev);
priv->tsf_high32 = priv->tsf_low32 = 0;
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
mutex_unlock(&priv->conf_mutex);
}
@ -2027,7 +2051,6 @@ static const struct ieee80211_ops p54_ops = {
.add_interface = p54_add_interface,
.remove_interface = p54_remove_interface,
.set_tim = p54_set_tim,
.sta_notify_ps = p54_sta_notify_ps,
.sta_notify = p54_sta_notify,
.set_key = p54_set_key,
.config = p54_config,

View File

@ -332,13 +332,6 @@ static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
P54P_READ(dev_int);
/* FIXME: unlikely to happen because the device usually runs out of
memory before we fill the ring up, but we can make it impossible */
if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2) {
p54_free_skb(dev, skb);
printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy));
}
}
static void p54p_stop(struct ieee80211_hw *dev)

View File

@ -86,13 +86,13 @@ static void p54u_rx_cb(struct urb *urb)
struct ieee80211_hw *dev = info->dev;
struct p54u_priv *priv = dev->priv;
skb_unlink(skb, &priv->rx_queue);
if (unlikely(urb->status)) {
info->urb = NULL;
usb_free_urb(urb);
dev_kfree_skb_irq(skb);
return;
}
skb_unlink(skb, &priv->rx_queue);
skb_put(skb, urb->actual_length);
if (priv->hw_type == P54U_NET2280)
@ -105,7 +105,6 @@ static void p54u_rx_cb(struct urb *urb)
if (p54_rx(dev, skb)) {
skb = dev_alloc_skb(priv->common.rx_mtu + 32);
if (unlikely(!skb)) {
usb_free_urb(urb);
/* TODO check rx queue length and refill *somewhere* */
return;
}
@ -115,7 +114,6 @@ static void p54u_rx_cb(struct urb *urb)
info->dev = dev;
urb->transfer_buffer = skb_tail_pointer(skb);
urb->context = skb;
skb_queue_tail(&priv->rx_queue, skb);
} else {
if (priv->hw_type == P54U_NET2280)
skb_push(skb, priv->common.tx_hdr_len);
@ -130,11 +128,14 @@ static void p54u_rx_cb(struct urb *urb)
WARN_ON(1);
urb->transfer_buffer = skb_tail_pointer(skb);
}
skb_queue_tail(&priv->rx_queue, skb);
}
usb_submit_urb(urb, GFP_ATOMIC);
skb_queue_tail(&priv->rx_queue, skb);
usb_anchor_urb(urb, &priv->submitted);
if (usb_submit_urb(urb, GFP_ATOMIC)) {
skb_unlink(skb, &priv->rx_queue);
usb_unanchor_urb(urb);
dev_kfree_skb_irq(skb);
}
}
static void p54u_tx_reuse_skb_cb(struct urb *urb)
@ -144,18 +145,6 @@ static void p54u_tx_reuse_skb_cb(struct urb *urb)
usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)))->priv;
skb_pull(skb, priv->common.tx_hdr_len);
usb_free_urb(urb);
}
static void p54u_tx_cb(struct urb *urb)
{
usb_free_urb(urb);
}
static void p54u_tx_free_cb(struct urb *urb)
{
kfree(urb->transfer_buffer);
usb_free_urb(urb);
}
static void p54u_tx_free_skb_cb(struct urb *urb)
@ -165,25 +154,36 @@ static void p54u_tx_free_skb_cb(struct urb *urb)
usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
p54_free_skb(dev, skb);
usb_free_urb(urb);
}
static void p54u_tx_dummy_cb(struct urb *urb) { }
static void p54u_free_urbs(struct ieee80211_hw *dev)
{
struct p54u_priv *priv = dev->priv;
usb_kill_anchored_urbs(&priv->submitted);
}
static int p54u_init_urbs(struct ieee80211_hw *dev)
{
struct p54u_priv *priv = dev->priv;
struct urb *entry;
struct urb *entry = NULL;
struct sk_buff *skb;
struct p54u_rx_info *info;
int ret = 0;
while (skb_queue_len(&priv->rx_queue) < 32) {
skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL);
if (!skb)
break;
if (!skb) {
ret = -ENOMEM;
goto err;
}
entry = usb_alloc_urb(0, GFP_KERNEL);
if (!entry) {
kfree_skb(skb);
break;
ret = -ENOMEM;
goto err;
}
usb_fill_bulk_urb(entry, priv->udev,
usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
skb_tail_pointer(skb),
@ -192,26 +192,25 @@ static int p54u_init_urbs(struct ieee80211_hw *dev)
info->urb = entry;
info->dev = dev;
skb_queue_tail(&priv->rx_queue, skb);
usb_submit_urb(entry, GFP_KERNEL);
usb_anchor_urb(entry, &priv->submitted);
ret = usb_submit_urb(entry, GFP_KERNEL);
if (ret) {
skb_unlink(skb, &priv->rx_queue);
usb_unanchor_urb(entry);
goto err;
}
usb_free_urb(entry);
entry = NULL;
}
return 0;
}
static void p54u_free_urbs(struct ieee80211_hw *dev)
{
struct p54u_priv *priv = dev->priv;
struct p54u_rx_info *info;
struct sk_buff *skb;
while ((skb = skb_dequeue(&priv->rx_queue))) {
info = (struct p54u_rx_info *) skb->cb;
if (!info->urb)
continue;
usb_kill_urb(info->urb);
kfree_skb(skb);
}
err:
usb_free_urb(entry);
kfree_skb(skb);
p54u_free_urbs(dev);
return ret;
}
static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb,
@ -219,6 +218,7 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb,
{
struct p54u_priv *priv = dev->priv;
struct urb *addr_urb, *data_urb;
int err = 0;
addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!addr_urb)
@ -233,15 +233,31 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb,
usb_fill_bulk_urb(addr_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
&((struct p54_hdr *)skb->data)->req_id, 4,
p54u_tx_cb, dev);
p54u_tx_dummy_cb, dev);
usb_fill_bulk_urb(data_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
skb->data, skb->len,
free_on_tx ? p54u_tx_free_skb_cb :
p54u_tx_reuse_skb_cb, skb);
usb_submit_urb(addr_urb, GFP_ATOMIC);
usb_submit_urb(data_urb, GFP_ATOMIC);
usb_anchor_urb(addr_urb, &priv->submitted);
err = usb_submit_urb(addr_urb, GFP_ATOMIC);
if (err) {
usb_unanchor_urb(addr_urb);
goto out;
}
usb_anchor_urb(addr_urb, &priv->submitted);
err = usb_submit_urb(data_urb, GFP_ATOMIC);
if (err)
usb_unanchor_urb(data_urb);
out:
usb_free_urb(addr_urb);
usb_free_urb(data_urb);
if (err)
p54_free_skb(dev, skb);
}
static __le32 p54u_lm87_chksum(const __le32 *data, size_t length)
@ -281,7 +297,13 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb,
free_on_tx ? p54u_tx_free_skb_cb :
p54u_tx_reuse_skb_cb, skb);
usb_submit_urb(data_urb, GFP_ATOMIC);
usb_anchor_urb(data_urb, &priv->submitted);
if (usb_submit_urb(data_urb, GFP_ATOMIC)) {
usb_unanchor_urb(data_urb);
skb_pull(skb, sizeof(*hdr));
p54_free_skb(dev, skb);
}
usb_free_urb(data_urb);
}
static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb,
@ -291,6 +313,7 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb,
struct urb *int_urb, *data_urb;
struct net2280_tx_hdr *hdr;
struct net2280_reg_write *reg;
int err = 0;
reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
if (!reg)
@ -320,15 +343,42 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb,
usb_fill_bulk_urb(int_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
p54u_tx_free_cb, dev);
usb_submit_urb(int_urb, GFP_ATOMIC);
p54u_tx_dummy_cb, dev);
/*
* This flag triggers a code path in the USB subsystem that will
* free what's inside the transfer_buffer after the callback routine
* has completed.
*/
int_urb->transfer_flags |= URB_FREE_BUFFER;
usb_fill_bulk_urb(data_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
skb->data, skb->len,
free_on_tx ? p54u_tx_free_skb_cb :
p54u_tx_reuse_skb_cb, skb);
usb_submit_urb(data_urb, GFP_ATOMIC);
usb_anchor_urb(int_urb, &priv->submitted);
err = usb_submit_urb(int_urb, GFP_ATOMIC);
if (err) {
usb_unanchor_urb(int_urb);
goto out;
}
usb_anchor_urb(data_urb, &priv->submitted);
err = usb_submit_urb(data_urb, GFP_ATOMIC);
if (err) {
usb_unanchor_urb(data_urb);
goto out;
}
out:
usb_free_urb(int_urb);
usb_free_urb(data_urb);
if (err) {
skb_pull(skb, sizeof(*hdr));
p54_free_skb(dev, skb);
}
}
static int p54u_write(struct p54u_priv *priv,
@ -885,6 +935,7 @@ static int __devinit p54u_probe(struct usb_interface *intf,
goto err_free_dev;
skb_queue_head_init(&priv->rx_queue);
init_usb_anchor(&priv->submitted);
p54u_open(dev);
err = p54_read_eeprom(dev);

View File

@ -133,6 +133,7 @@ struct p54u_priv {
spinlock_t lock;
struct sk_buff_head rx_queue;
struct usb_anchor submitted;
};
#endif /* P54USB_H */

View File

@ -99,6 +99,7 @@ struct rtl8187_priv {
struct ieee80211_supported_band band;
struct usb_device *udev;
u32 rx_conf;
struct usb_anchor anchored;
u16 txpwr_base;
u8 asic_rev;
u8 is_rtl8187b;
@ -115,7 +116,6 @@ struct rtl8187_priv {
u8 aifsn[4];
struct {
__le64 buf;
struct urb *urb;
struct sk_buff_head queue;
} b_tx_status;
};

View File

@ -99,7 +99,6 @@ static const struct ieee80211_channel rtl818x_channels[] = {
static void rtl8187_iowrite_async_cb(struct urb *urb)
{
kfree(urb->context);
usb_free_urb(urb);
}
static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr,
@ -136,11 +135,13 @@ static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr,
usb_fill_control_urb(urb, priv->udev, usb_sndctrlpipe(priv->udev, 0),
(unsigned char *)dr, buf, len,
rtl8187_iowrite_async_cb, buf);
usb_anchor_urb(urb, &priv->anchored);
rc = usb_submit_urb(urb, GFP_ATOMIC);
if (rc < 0) {
kfree(buf);
usb_free_urb(urb);
usb_unanchor_urb(urb);
}
usb_free_urb(urb);
}
static inline void rtl818x_iowrite32_async(struct rtl8187_priv *priv,
@ -172,7 +173,6 @@ static void rtl8187_tx_cb(struct urb *urb)
struct ieee80211_hw *hw = info->rate_driver_data[0];
struct rtl8187_priv *priv = hw->priv;
usb_free_urb(info->rate_driver_data[1]);
skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) :
sizeof(struct rtl8187_tx_hdr));
ieee80211_tx_info_clear_status(info);
@ -273,11 +273,13 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep),
buf, skb->len, rtl8187_tx_cb, skb);
usb_anchor_urb(urb, &priv->anchored);
rc = usb_submit_urb(urb, GFP_ATOMIC);
if (rc < 0) {
usb_free_urb(urb);
usb_unanchor_urb(urb);
kfree_skb(skb);
}
usb_free_urb(urb);
return 0;
}
@ -301,41 +303,25 @@ static void rtl8187_rx_cb(struct urb *urb)
return;
}
spin_unlock(&priv->rx_queue.lock);
skb_put(skb, urb->actual_length);
if (unlikely(urb->status)) {
usb_free_urb(urb);
dev_kfree_skb_irq(skb);
return;
}
skb_put(skb, urb->actual_length);
if (!priv->is_rtl8187b) {
struct rtl8187_rx_hdr *hdr =
(typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
flags = le32_to_cpu(hdr->flags);
signal = hdr->signal & 0x7f;
/* As with the RTL8187B below, the AGC is used to calculate
* signal strength and quality. In this case, the scaling
* constants are derived from the output of p54usb.
*/
quality = 130 - ((41 * hdr->agc) >> 6);
signal = -4 - ((27 * hdr->agc) >> 6);
rx_status.antenna = (hdr->signal >> 7) & 1;
rx_status.noise = hdr->noise;
rx_status.mactime = le64_to_cpu(hdr->mac_time);
priv->quality = signal;
rx_status.qual = priv->quality;
priv->noise = hdr->noise;
rate = (flags >> 20) & 0xF;
if (rate > 3) { /* OFDM rate */
if (signal > 90)
signal = 90;
else if (signal < 25)
signal = 25;
signal = 90 - signal;
} else { /* CCK rate */
if (signal > 95)
signal = 95;
else if (signal < 30)
signal = 30;
signal = 95 - signal;
}
rx_status.signal = signal;
priv->signal = signal;
} else {
struct rtl8187b_rx_hdr *hdr =
(typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
@ -353,18 +339,18 @@ static void rtl8187_rx_cb(struct urb *urb)
*/
flags = le32_to_cpu(hdr->flags);
quality = 170 - hdr->agc;
if (quality > 100)
quality = 100;
signal = 14 - hdr->agc / 2;
rx_status.qual = quality;
priv->quality = quality;
rx_status.signal = signal;
priv->signal = signal;
rx_status.antenna = (hdr->rssi >> 7) & 1;
rx_status.mactime = le64_to_cpu(hdr->mac_time);
rate = (flags >> 20) & 0xF;
}
if (quality > 100)
quality = 100;
rx_status.qual = quality;
priv->quality = quality;
rx_status.signal = signal;
priv->signal = signal;
rate = (flags >> 20) & 0xF;
skb_trim(skb, flags & 0x0FFF);
rx_status.rate_idx = rate;
rx_status.freq = dev->conf.channel->center_freq;
@ -376,7 +362,6 @@ static void rtl8187_rx_cb(struct urb *urb)
skb = dev_alloc_skb(RTL8187_MAX_RX);
if (unlikely(!skb)) {
usb_free_urb(urb);
/* TODO check rx queue length and refill *somewhere* */
return;
}
@ -388,24 +373,32 @@ static void rtl8187_rx_cb(struct urb *urb)
urb->context = skb;
skb_queue_tail(&priv->rx_queue, skb);
usb_submit_urb(urb, GFP_ATOMIC);
usb_anchor_urb(urb, &priv->anchored);
if (usb_submit_urb(urb, GFP_ATOMIC)) {
usb_unanchor_urb(urb);
skb_unlink(skb, &priv->rx_queue);
dev_kfree_skb_irq(skb);
}
}
static int rtl8187_init_urbs(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
struct urb *entry;
struct urb *entry = NULL;
struct sk_buff *skb;
struct rtl8187_rx_info *info;
int ret = 0;
while (skb_queue_len(&priv->rx_queue) < 8) {
skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
if (!skb)
break;
if (!skb) {
ret = -ENOMEM;
goto err;
}
entry = usb_alloc_urb(0, GFP_KERNEL);
if (!entry) {
kfree_skb(skb);
break;
ret = -ENOMEM;
goto err;
}
usb_fill_bulk_urb(entry, priv->udev,
usb_rcvbulkpipe(priv->udev,
@ -416,10 +409,22 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)
info->urb = entry;
info->dev = dev;
skb_queue_tail(&priv->rx_queue, skb);
usb_submit_urb(entry, GFP_KERNEL);
usb_anchor_urb(entry, &priv->anchored);
ret = usb_submit_urb(entry, GFP_KERNEL);
if (ret) {
skb_unlink(skb, &priv->rx_queue);
usb_unanchor_urb(entry);
goto err;
}
usb_free_urb(entry);
}
return ret;
return 0;
err:
usb_free_urb(entry);
kfree_skb(skb);
usb_kill_anchored_urbs(&priv->anchored);
return ret;
}
static void rtl8187b_status_cb(struct urb *urb)
@ -429,10 +434,8 @@ static void rtl8187b_status_cb(struct urb *urb)
u64 val;
unsigned int cmd_type;
if (unlikely(urb->status)) {
usb_free_urb(urb);
if (unlikely(urb->status))
return;
}
/*
* Read from status buffer:
@ -503,26 +506,32 @@ static void rtl8187b_status_cb(struct urb *urb)
spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags);
}
usb_submit_urb(urb, GFP_ATOMIC);
usb_anchor_urb(urb, &priv->anchored);
if (usb_submit_urb(urb, GFP_ATOMIC))
usb_unanchor_urb(urb);
}
static int rtl8187b_init_status_urb(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
struct urb *entry;
int ret = 0;
entry = usb_alloc_urb(0, GFP_KERNEL);
if (!entry)
return -ENOMEM;
priv->b_tx_status.urb = entry;
usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9),
&priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf),
rtl8187b_status_cb, dev);
usb_submit_urb(entry, GFP_KERNEL);
usb_anchor_urb(entry, &priv->anchored);
ret = usb_submit_urb(entry, GFP_KERNEL);
if (ret)
usb_unanchor_urb(entry);
usb_free_urb(entry);
return 0;
return ret;
}
static int rtl8187_cmd_reset(struct ieee80211_hw *dev)
@ -856,6 +865,9 @@ static int rtl8187_start(struct ieee80211_hw *dev)
return ret;
mutex_lock(&priv->conf_mutex);
init_usb_anchor(&priv->anchored);
if (priv->is_rtl8187b) {
reg = RTL818X_RX_CONF_MGMT |
RTL818X_RX_CONF_DATA |
@ -951,12 +963,12 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
while ((skb = skb_dequeue(&priv->rx_queue))) {
info = (struct rtl8187_rx_info *)skb->cb;
usb_kill_urb(info->urb);
kfree_skb(skb);
}
while ((skb = skb_dequeue(&priv->b_tx_status.queue)))
dev_kfree_skb_any(skb);
usb_kill_urb(priv->b_tx_status.urb);
usb_kill_anchored_urbs(&priv->anchored);
mutex_unlock(&priv->conf_mutex);
}
@ -1293,6 +1305,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
priv->mode = NL80211_IFTYPE_MONITOR;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_RX_INCLUDES_FCS;
eeprom.data = dev;
@ -1408,13 +1421,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
(*channel++).hw_value = txpwr >> 8;
}
if (priv->is_rtl8187b) {
if (priv->is_rtl8187b)
printk(KERN_WARNING "rtl8187: 8187B chip detected.\n");
dev->flags |= IEEE80211_HW_SIGNAL_DBM;
} else {
dev->flags |= IEEE80211_HW_SIGNAL_UNSPEC;
dev->max_signal = 65;
}
/*
* XXX: Once this driver supports anything that requires

View File

@ -836,7 +836,7 @@ struct ieee80211_ht_info {
/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
#define WLAN_AUTH_SHARED_KEY 1
#define WLAN_AUTH_LEAP 2
#define WLAN_AUTH_LEAP 128
#define WLAN_AUTH_CHALLENGE_LEN 128

View File

@ -149,11 +149,4 @@ static inline char *rfkill_get_led_name(struct rfkill *rfkill)
#endif
}
/* rfkill notification chain */
#define RFKILL_STATE_CHANGED 0x0001 /* state of a normal rfkill
switch has changed */
int register_rfkill_notifier(struct notifier_block *nb);
int unregister_rfkill_notifier(struct notifier_block *nb);
#endif /* RFKILL_H */

View File

@ -385,9 +385,8 @@ struct ieee80211_device;
#define SCM_TEMPORAL_KEY_LENGTH 16
struct ieee80211_security {
u16 active_key:2,
enabled:1,
auth_mode:2, auth_algo:4, unicast_uses_group:1, encrypt:1;
u16 active_key:2, enabled:1, unicast_uses_group:1, encrypt:1;
u8 auth_mode;
u8 encode_alg[WEP_KEYS];
u8 key_sizes[WEP_KEYS];
u8 keys[WEP_KEYS][SCM_KEY_LEN];

View File

@ -773,25 +773,16 @@ struct ieee80211_sta {
* enum sta_notify_cmd - sta notify command
*
* Used with the sta_notify() callback in &struct ieee80211_ops, this
* indicates addition and removal of a station to station table.
* indicates addition and removal of a station to station table,
* or if a associated station made a power state transition.
*
* @STA_NOTIFY_ADD: a station was added to the station table
* @STA_NOTIFY_REMOVE: a station being removed from the station table
*/
enum sta_notify_cmd {
STA_NOTIFY_ADD, STA_NOTIFY_REMOVE
};
/**
* enum sta_notify_ps_cmd - sta power save notify command
*
* Used with the sta_notify_ps() callback in &struct ieee80211_ops to
* notify the driver if a station made a power state transition.
*
* @STA_NOTIFY_SLEEP: a station is now sleeping
* @STA_NOTIFY_AWAKE: a sleeping station woke up
*/
enum sta_notify_ps_cmd {
enum sta_notify_cmd {
STA_NOTIFY_ADD, STA_NOTIFY_REMOVE,
STA_NOTIFY_SLEEP, STA_NOTIFY_AWAKE,
};
@ -1258,15 +1249,9 @@ enum ieee80211_ampdu_mlme_action {
*
* @set_rts_threshold: Configuration of RTS threshold (if device needs it)
*
* @set_frag_threshold: Configuration of fragmentation threshold. Assign this if
* the device does fragmentation by itself; if this method is assigned then
* the stack will not do fragmentation.
*
* @sta_notify: Notifies low level driver about addition or removal
* of associated station or AP.
*
* @sta_ps_notify: Notifies low level driver about the power state transition
* of a associated station. Must be atomic.
* @sta_notify: Notifies low level driver about addition, removal or power
* state transition of an associated station, AP, IBSS/WDS/mesh peer etc.
* Must be atomic.
*
* @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
* bursting) for a hardware TX queue.
@ -1331,11 +1316,8 @@ struct ieee80211_ops {
void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx,
u32 *iv32, u16 *iv16);
int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value);
int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value);
void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum sta_notify_cmd, struct ieee80211_sta *sta);
void (*sta_notify_ps)(struct ieee80211_hw *hw,
enum sta_notify_ps_cmd, struct ieee80211_sta *sta);
int (*conf_tx)(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params);
int (*get_tx_stats)(struct ieee80211_hw *hw,

View File

@ -46,3 +46,5 @@ rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o
mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y)
mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
ccflags-y += -D__CHECK_ENDIAN__

View File

@ -396,8 +396,10 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
*/
if (params->interval) {
sdata->local->hw.conf.beacon_int = params->interval;
ieee80211_hw_config(sdata->local,
IEEE80211_CONF_CHANGE_BEACON_INTERVAL);
err = ieee80211_hw_config(sdata->local,
IEEE80211_CONF_CHANGE_BEACON_INTERVAL);
if (err < 0)
return err;
/*
* We updated some parameter so if below bails out
* it's not an error.

View File

@ -187,7 +187,6 @@ struct ieee80211_rx_data {
struct ieee80211_rx_status *status;
struct ieee80211_rate *rate;
u16 ethertype;
unsigned int flags;
int sent_ps_buffered;
int queue;
@ -864,8 +863,7 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid);
void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_sta *ifsta);
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, u8 *bssid,
u8 *addr, u64 supp_rates);
u8 *bssid, u8 *addr, u64 supp_rates);
int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason);
int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason);
u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata);

View File

@ -243,10 +243,20 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
if (changed && local->open_count) {
ret = local->ops->config(local_to_hw(local), changed);
/*
* Goal:
* HW reconfiguration should never fail, the driver has told
* us what it can support so it should live up to that promise.
*
* Current status:
* rfkill is not integrated with mac80211 and a
* configuration command can thus fail if hardware rfkill
* is enabled
*
* FIXME: integrate rfkill with mac80211 and then add this
* WARN_ON() back
*
*/
WARN_ON(ret);
/* WARN_ON(ret); */
}
return ret;
@ -876,12 +886,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
local->mdev->select_queue = ieee80211_select_queue;
/* add one default STA interface */
result = ieee80211_if_add(local, "wlan%d", NULL,
NL80211_IFTYPE_STATION, NULL);
if (result)
printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
wiphy_name(local->hw.wiphy));
/* add one default STA interface if supported */
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
result = ieee80211_if_add(local, "wlan%d", NULL,
NL80211_IFTYPE_STATION, NULL);
if (result)
printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
wiphy_name(local->hw.wiphy));
}
rtnl_unlock();

View File

@ -1565,8 +1565,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
(unsigned long long) sta->sta.supp_rates[band]);
#endif
} else {
ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid,
mgmt->sa, supp_rates);
ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates);
}
rcu_read_unlock();
@ -1638,9 +1637,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
sdata->dev->name, mgmt->bssid);
#endif
ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss);
ieee80211_ibss_add_sta(sdata, NULL,
mgmt->bssid, mgmt->sa,
supp_rates);
ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates);
}
}
@ -2373,8 +2370,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
* must be callable in atomic context.
*/
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, u8 *bssid,
u8 *addr, u64 supp_rates)
u8 *bssid,u8 *addr, u64 supp_rates)
{
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;

View File

@ -658,9 +658,9 @@ static void ap_sta_ps_start(struct sta_info *sta)
atomic_inc(&sdata->bss->num_sta_ps);
set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL);
if (local->ops->sta_notify_ps)
local->ops->sta_notify_ps(local_to_hw(local), STA_NOTIFY_SLEEP,
&sta->sta);
if (local->ops->sta_notify)
local->ops->sta_notify(local_to_hw(local), &sdata->vif,
STA_NOTIFY_SLEEP, &sta->sta);
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n",
sdata->dev->name, sta->sta.addr, sta->sta.aid);
@ -677,9 +677,9 @@ static int ap_sta_ps_end(struct sta_info *sta)
atomic_dec(&sdata->bss->num_sta_ps);
clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL);
if (local->ops->sta_notify_ps)
local->ops->sta_notify_ps(local_to_hw(local), STA_NOTIFY_AWAKE,
&sta->sta);
if (local->ops->sta_notify)
local->ops->sta_notify(local_to_hw(local), &sdata->vif,
STA_NOTIFY_AWAKE, &sta->sta);
if (!skb_queue_empty(&sta->ps_tx_buf))
sta_info_clear_tim_bit(sta);
@ -1850,9 +1850,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
return 0;
rx->flags &= ~IEEE80211_RX_RA_MATCH;
} else if (!rx->sta)
rx->sta = ieee80211_ibss_add_sta(sdata, rx->skb,
bssid, hdr->addr2,
BIT(rx->status->rate_idx));
rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2,
BIT(rx->status->rate_idx));
break;
case NL80211_IFTYPE_MESH_POINT:
if (!multicast &&

View File

@ -1001,7 +1001,6 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
if (tx->flags & IEEE80211_TX_FRAGMENTED) {
if ((tx->flags & IEEE80211_TX_UNICAST) &&
skb->len + FCS_LEN > local->fragmentation_threshold &&
!local->ops->set_frag_threshold &&
!(info->flags & IEEE80211_TX_CTL_AMPDU))
tx->flags |= IEEE80211_TX_FRAGMENTED;
else

View File

@ -418,8 +418,7 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev,
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_ADHOC &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
sdata->vif.type != NL80211_IFTYPE_AP)
sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
return -EOPNOTSUPP;
/* if SSID was specified explicitly then use that */
@ -639,14 +638,6 @@ static int ieee80211_ioctl_siwfrag(struct net_device *dev,
local->fragmentation_threshold = frag->value & ~0x1;
}
/* If the wlan card performs fragmentation in hardware/firmware,
* configure it here */
if (local->ops->set_frag_threshold)
return local->ops->set_frag_threshold(
local_to_hw(local),
local->fragmentation_threshold);
return 0;
}

View File

@ -53,51 +53,6 @@ static struct rfkill_gsw_state rfkill_global_states[RFKILL_TYPE_MAX];
static unsigned long rfkill_states_lockdflt[BITS_TO_LONGS(RFKILL_TYPE_MAX)];
static bool rfkill_epo_lock_active;
static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list);
/**
* register_rfkill_notifier - Add notifier to rfkill notifier chain
* @nb: pointer to the new entry to add to the chain
*
* See blocking_notifier_chain_register() for return value and further
* observations.
*
* Adds a notifier to the rfkill notifier chain. The chain will be
* called with a pointer to the relevant rfkill structure as a parameter,
* refer to include/linux/rfkill.h for the possible events.
*
* Notifiers added to this chain are to always return NOTIFY_DONE. This
* chain is a blocking notifier chain: notifiers can sleep.
*
* Calls to this chain may have been done through a workqueue. One must
* assume unordered asynchronous behaviour, there is no way to know if
* actions related to the event that generated the notification have been
* carried out already.
*/
int register_rfkill_notifier(struct notifier_block *nb)
{
BUG_ON(!nb);
return blocking_notifier_chain_register(&rfkill_notifier_list, nb);
}
EXPORT_SYMBOL_GPL(register_rfkill_notifier);
/**
* unregister_rfkill_notifier - remove notifier from rfkill notifier chain
* @nb: pointer to the entry to remove from the chain
*
* See blocking_notifier_chain_unregister() for return value and further
* observations.
*
* Removes a notifier from the rfkill notifier chain.
*/
int unregister_rfkill_notifier(struct notifier_block *nb)
{
BUG_ON(!nb);
return blocking_notifier_chain_unregister(&rfkill_notifier_list, nb);
}
EXPORT_SYMBOL_GPL(unregister_rfkill_notifier);
static void rfkill_led_trigger(struct rfkill *rfkill,
enum rfkill_state state)
@ -124,12 +79,9 @@ static void rfkill_led_trigger_activate(struct led_classdev *led)
}
#endif /* CONFIG_RFKILL_LEDS */
static void notify_rfkill_state_change(struct rfkill *rfkill)
static void rfkill_uevent(struct rfkill *rfkill)
{
rfkill_led_trigger(rfkill, rfkill->state);
blocking_notifier_call_chain(&rfkill_notifier_list,
RFKILL_STATE_CHANGED,
rfkill);
kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE);
}
static void update_rfkill_state(struct rfkill *rfkill)
@ -142,7 +94,7 @@ static void update_rfkill_state(struct rfkill *rfkill)
oldstate = rfkill->state;
rfkill->state = newstate;
if (oldstate != newstate)
notify_rfkill_state_change(rfkill);
rfkill_uevent(rfkill);
}
mutex_unlock(&rfkill->mutex);
}
@ -220,7 +172,7 @@ static int rfkill_toggle_radio(struct rfkill *rfkill,
}
if (force || rfkill->state != oldstate)
notify_rfkill_state_change(rfkill);
rfkill_uevent(rfkill);
return retval;
}
@ -405,7 +357,7 @@ int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state)
rfkill->state = state;
if (state != oldstate)
notify_rfkill_state_change(rfkill);
rfkill_uevent(rfkill);
mutex_unlock(&rfkill->mutex);
@ -618,28 +570,6 @@ static int rfkill_resume(struct device *dev)
#define rfkill_resume NULL
#endif
static int rfkill_blocking_uevent_notifier(struct notifier_block *nb,
unsigned long eventid,
void *data)
{
struct rfkill *rfkill = (struct rfkill *)data;
switch (eventid) {
case RFKILL_STATE_CHANGED:
kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE);
break;
default:
break;
}
return NOTIFY_DONE;
}
static struct notifier_block rfkill_blocking_uevent_nb = {
.notifier_call = rfkill_blocking_uevent_notifier,
.priority = 0,
};
static int rfkill_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct rfkill *rfkill = to_rfkill(dev);
@ -942,14 +872,11 @@ static int __init rfkill_init(void)
return error;
}
register_rfkill_notifier(&rfkill_blocking_uevent_nb);
return 0;
}
static void __exit rfkill_exit(void)
{
unregister_rfkill_notifier(&rfkill_blocking_uevent_nb);
class_unregister(&rfkill_class);
}

View File

@ -8,3 +8,5 @@ obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o
cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o
cfg80211-$(CONFIG_NL80211) += nl80211.o
ccflags-y += -D__CHECK_ENDIAN__

View File

@ -365,6 +365,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
enum nl80211_sec_chan_offset sec_chan_offset =
NL80211_SEC_CHAN_NO_HT;
struct ieee80211_channel *chan;
struct ieee80211_sta_ht_cap *ht_cap;
u32 freq, sec_freq;
if (!rdev->ops->set_channel) {
@ -372,26 +373,25 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
goto bad_res;
}
result = -EINVAL;
if (info->attrs[NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]) {
sec_chan_offset = nla_get_u32(
info->attrs[
sec_chan_offset = nla_get_u32(info->attrs[
NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]);
if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT &&
sec_chan_offset != NL80211_SEC_CHAN_DISABLED &&
sec_chan_offset != NL80211_SEC_CHAN_BELOW &&
sec_chan_offset != NL80211_SEC_CHAN_ABOVE) {
result = -EINVAL;
sec_chan_offset != NL80211_SEC_CHAN_ABOVE)
goto bad_res;
}
}
freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
chan = ieee80211_get_channel(&rdev->wiphy, freq);
if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
/* Primary channel not allowed */
result = -EINVAL;
/* Primary channel not allowed */
if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
goto bad_res;
}
if (sec_chan_offset == NL80211_SEC_CHAN_BELOW)
sec_freq = freq - 20;
else if (sec_chan_offset == NL80211_SEC_CHAN_ABOVE)
@ -399,14 +399,26 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
else
sec_freq = 0;
ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
/* no HT capabilities */
if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT &&
!ht_cap->ht_supported)
goto bad_res;
if (sec_freq) {
struct ieee80211_channel *schan;
schan = ieee80211_get_channel(&rdev->wiphy, sec_freq);
if (!schan || schan->flags & IEEE80211_CHAN_DISABLED) {
/* Secondary channel not allowed */
result = -EINVAL;
/* no 40 MHz capabilities */
if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
(ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
goto bad_res;
schan = ieee80211_get_channel(&rdev->wiphy, sec_freq);
/* Secondary channel not allowed */
if (!schan || schan->flags & IEEE80211_CHAN_DISABLED)
goto bad_res;
}
}
result = rdev->ops->set_channel(&rdev->wiphy, chan,
@ -416,7 +428,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
bad_res:
bad_res:
cfg80211_put_dev(rdev);
return result;
}