Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
143b11c03c
@ -144,6 +144,7 @@ struct ath_desc {
|
||||
#define ATH9K_TXDESC_EXT_AND_CTL 0x0080
|
||||
#define ATH9K_TXDESC_VMF 0x0100
|
||||
#define ATH9K_TXDESC_FRAG_IS_ON 0x0200
|
||||
#define ATH9K_TXDESC_CAB 0x0400
|
||||
|
||||
#define ATH9K_RXDESC_INTREQ 0x0020
|
||||
|
||||
@ -564,8 +565,6 @@ enum ath9k_cipher {
|
||||
#define CTL_5GHT40 8
|
||||
|
||||
#define AR_EEPROM_MAC(i) (0x1d+(i))
|
||||
#define EEP_SCALE 100
|
||||
#define EEP_DELTA 10
|
||||
|
||||
#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c
|
||||
#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2
|
||||
@ -606,9 +605,6 @@ struct ath9k_country_entry {
|
||||
#define REG_CLR_BIT(_a, _r, _f) \
|
||||
REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f)
|
||||
|
||||
#define ATH9K_COMP_BUF_MAX_SIZE 9216
|
||||
#define ATH9K_COMP_BUF_ALIGN_SIZE 512
|
||||
|
||||
#define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001
|
||||
|
||||
#define INIT_AIFS 2
|
||||
@ -632,12 +628,6 @@ struct ath9k_country_entry {
|
||||
(IEEE80211_WEP_IVLEN + \
|
||||
IEEE80211_WEP_KIDLEN + \
|
||||
IEEE80211_WEP_CRCLEN))
|
||||
#define IEEE80211_MAX_LEN (2300 + FCS_LEN + \
|
||||
(IEEE80211_WEP_IVLEN + \
|
||||
IEEE80211_WEP_KIDLEN + \
|
||||
IEEE80211_WEP_CRCLEN))
|
||||
|
||||
#define MAX_REG_ADD_COUNT 129
|
||||
#define MAX_RATE_POWER 63
|
||||
|
||||
enum ath9k_power_mode {
|
||||
@ -707,13 +697,6 @@ enum phytype {
|
||||
};
|
||||
#define PHY_CCK PHY_DS
|
||||
|
||||
enum start_adhoc_option {
|
||||
START_ADHOC_NO_11A,
|
||||
START_ADHOC_PER_11D,
|
||||
START_ADHOC_IN_11A,
|
||||
START_ADHOC_IN_11B,
|
||||
};
|
||||
|
||||
enum ath9k_tp_scale {
|
||||
ATH9K_TP_SCALE_MAX = 0,
|
||||
ATH9K_TP_SCALE_50,
|
||||
@ -769,14 +752,11 @@ struct ath9k_node_stats {
|
||||
|
||||
#define ATH9K_RSSI_EP_MULTIPLIER (1<<7)
|
||||
|
||||
enum ath9k_gpio_output_mux_type {
|
||||
ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT,
|
||||
ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
|
||||
ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
|
||||
ATH9K_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
|
||||
ATH9K_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
|
||||
ATH9K_GPIO_OUTPUT_MUX_NUM_ENTRIES
|
||||
};
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6
|
||||
|
||||
enum {
|
||||
ATH9K_RESET_POWER_ON,
|
||||
@ -790,19 +770,20 @@ struct ath_hal {
|
||||
u32 ah_magic;
|
||||
u16 ah_devid;
|
||||
u16 ah_subvendorid;
|
||||
struct ath_softc *ah_sc;
|
||||
void __iomem *ah_sh;
|
||||
u16 ah_countryCode;
|
||||
u32 ah_macVersion;
|
||||
u16 ah_macRev;
|
||||
u16 ah_phyRev;
|
||||
u16 ah_analog5GhzRev;
|
||||
u16 ah_analog2GhzRev;
|
||||
u8 ah_decompMask[ATH9K_DECOMP_MASK_SIZE];
|
||||
u32 ah_flags;
|
||||
|
||||
void __iomem *ah_sh;
|
||||
struct ath_softc *ah_sc;
|
||||
enum ath9k_opmode ah_opmode;
|
||||
struct ath9k_ops_config ah_config;
|
||||
struct ath9k_hw_capabilities ah_caps;
|
||||
|
||||
u16 ah_countryCode;
|
||||
u32 ah_flags;
|
||||
int16_t ah_powerLimit;
|
||||
u16 ah_maxPowerLevel;
|
||||
u32 ah_tpScale;
|
||||
@ -812,15 +793,16 @@ struct ath_hal {
|
||||
u16 ah_currentRD5G;
|
||||
u16 ah_currentRD2G;
|
||||
char ah_iso[4];
|
||||
enum start_adhoc_option ah_adHocMode;
|
||||
bool ah_commonMode;
|
||||
|
||||
struct ath9k_channel ah_channels[150];
|
||||
u32 ah_nchan;
|
||||
struct ath9k_channel *ah_curchan;
|
||||
u32 ah_nchan;
|
||||
|
||||
u16 ah_rfsilent;
|
||||
bool ah_rfkillEnabled;
|
||||
bool ah_isPciExpress;
|
||||
u16 ah_txTrigLevel;
|
||||
|
||||
#ifndef ATH_NF_PER_CHAN
|
||||
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
|
||||
#endif
|
||||
@ -853,7 +835,7 @@ bool ath9k_regd_init_channels(struct ath_hal *ah,
|
||||
u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
|
||||
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah,
|
||||
enum ath9k_int ints);
|
||||
bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
|
||||
bool ath9k_hw_reset(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
enum ath9k_ht_macmode macmode,
|
||||
u8 txchainmask, u8 rxchainmask,
|
||||
@ -1018,4 +1000,7 @@ void ath9k_hw_get_channel_centers(struct ath_hal *ah,
|
||||
bool ath9k_get_channel_edges(struct ath_hal *ah,
|
||||
u16 flags, u16 *low,
|
||||
u16 *high);
|
||||
void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
|
||||
u32 ah_signal_type);
|
||||
void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 value);
|
||||
#endif
|
||||
|
@ -33,7 +33,7 @@ static int ath_beaconq_config(struct ath_softc *sc)
|
||||
struct ath9k_tx_queue_info qi;
|
||||
|
||||
ath9k_hw_get_txq_props(ah, sc->sc_bhalq, &qi);
|
||||
if (sc->sc_opmode == ATH9K_M_HOSTAP) {
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
|
||||
/* Always burst out beacon and CAB traffic. */
|
||||
qi.tqi_aifs = 1;
|
||||
qi.tqi_cwmin = 0;
|
||||
@ -85,7 +85,7 @@ static void ath_beacon_setup(struct ath_softc *sc,
|
||||
|
||||
flags = ATH9K_TXDESC_NOACK;
|
||||
|
||||
if (sc->sc_opmode == ATH9K_M_IBSS &&
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS &&
|
||||
(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
|
||||
ds->ds_link = bf->bf_daddr; /* self-linked */
|
||||
flags |= ATH9K_TXDESC_VEOL;
|
||||
@ -111,24 +111,24 @@ static void ath_beacon_setup(struct ath_softc *sc,
|
||||
rix = 0;
|
||||
rt = sc->sc_currates;
|
||||
rate = rt->info[rix].rateCode;
|
||||
if (sc->sc_flags & ATH_PREAMBLE_SHORT)
|
||||
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
|
||||
rate |= rt->info[rix].shortPreamble;
|
||||
|
||||
ath9k_hw_set11n_txdesc(ah, ds
|
||||
, skb->len + FCS_LEN /* frame length */
|
||||
, ATH9K_PKT_TYPE_BEACON /* Atheros packet type */
|
||||
, avp->av_btxctl.txpower /* txpower XXX */
|
||||
, ATH9K_TXKEYIX_INVALID /* no encryption */
|
||||
, ATH9K_KEY_TYPE_CLEAR /* no encryption */
|
||||
, flags /* no ack, veol for beacons */
|
||||
ath9k_hw_set11n_txdesc(ah, ds,
|
||||
skb->len + FCS_LEN, /* frame length */
|
||||
ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */
|
||||
avp->av_btxctl.txpower, /* txpower XXX */
|
||||
ATH9K_TXKEYIX_INVALID, /* no encryption */
|
||||
ATH9K_KEY_TYPE_CLEAR, /* no encryption */
|
||||
flags /* no ack, veol for beacons */
|
||||
);
|
||||
|
||||
/* NB: beacon's BufLen must be a multiple of 4 bytes */
|
||||
ath9k_hw_filltxdesc(ah, ds
|
||||
, roundup(skb->len, 4) /* buffer length */
|
||||
, true /* first segment */
|
||||
, true /* last segment */
|
||||
, ds /* first descriptor */
|
||||
ath9k_hw_filltxdesc(ah, ds,
|
||||
roundup(skb->len, 4), /* buffer length */
|
||||
true, /* first segment */
|
||||
true, /* last segment */
|
||||
ds /* first descriptor */
|
||||
);
|
||||
|
||||
memzero(series, sizeof(struct ath9k_11n_rate_series) * 4);
|
||||
@ -140,55 +140,6 @@ static void ath_beacon_setup(struct ath_softc *sc,
|
||||
ctsrate, ctsduration, series, 4, 0);
|
||||
}
|
||||
|
||||
/* Move everything from the vap's mcast queue to the hardware cab queue.
|
||||
* Caller must hold mcasq lock and cabq lock
|
||||
* XXX MORE_DATA bit?
|
||||
*/
|
||||
static void empty_mcastq_into_cabq(struct ath_hal *ah,
|
||||
struct ath_txq *mcastq, struct ath_txq *cabq)
|
||||
{
|
||||
struct ath_buf *bfmcast;
|
||||
|
||||
BUG_ON(list_empty(&mcastq->axq_q));
|
||||
|
||||
bfmcast = list_first_entry(&mcastq->axq_q, struct ath_buf, list);
|
||||
|
||||
/* link the descriptors */
|
||||
if (!cabq->axq_link)
|
||||
ath9k_hw_puttxbuf(ah, cabq->axq_qnum, bfmcast->bf_daddr);
|
||||
else
|
||||
*cabq->axq_link = bfmcast->bf_daddr;
|
||||
|
||||
/* append the private vap mcast list to the cabq */
|
||||
|
||||
cabq->axq_depth += mcastq->axq_depth;
|
||||
cabq->axq_totalqueued += mcastq->axq_totalqueued;
|
||||
cabq->axq_linkbuf = mcastq->axq_linkbuf;
|
||||
cabq->axq_link = mcastq->axq_link;
|
||||
list_splice_tail_init(&mcastq->axq_q, &cabq->axq_q);
|
||||
mcastq->axq_depth = 0;
|
||||
mcastq->axq_totalqueued = 0;
|
||||
mcastq->axq_linkbuf = NULL;
|
||||
mcastq->axq_link = NULL;
|
||||
}
|
||||
|
||||
/* This is only run at DTIM. We move everything from the vap's mcast queue
|
||||
* to the hardware cab queue. Caller must hold the mcastq lock. */
|
||||
static void trigger_mcastq(struct ath_hal *ah,
|
||||
struct ath_txq *mcastq, struct ath_txq *cabq)
|
||||
{
|
||||
spin_lock_bh(&cabq->axq_lock);
|
||||
|
||||
if (!list_empty(&mcastq->axq_q))
|
||||
empty_mcastq_into_cabq(ah, mcastq, cabq);
|
||||
|
||||
/* cabq is gated by beacon so it is safe to start here */
|
||||
if (!list_empty(&cabq->axq_q))
|
||||
ath9k_hw_txstart(ah, cabq->axq_qnum);
|
||||
|
||||
spin_unlock_bh(&cabq->axq_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate beacon frame and queue cab data for a vap.
|
||||
*
|
||||
@ -199,19 +150,14 @@ static void trigger_mcastq(struct ath_hal *ah,
|
||||
*/
|
||||
static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ath_buf *bf;
|
||||
struct ath_vap *avp;
|
||||
struct sk_buff *skb;
|
||||
int cabq_depth;
|
||||
int mcastq_depth;
|
||||
int is_beacon_dtim = 0;
|
||||
unsigned int curlen;
|
||||
struct ath_txq *cabq;
|
||||
struct ath_txq *mcastq;
|
||||
struct ieee80211_tx_info *info;
|
||||
avp = sc->sc_vaps[if_id];
|
||||
|
||||
mcastq = &avp->av_mcastq;
|
||||
cabq = sc->sc_cabq;
|
||||
|
||||
ASSERT(avp);
|
||||
@ -223,33 +169,34 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
|
||||
}
|
||||
bf = avp->av_bcbuf;
|
||||
skb = (struct sk_buff *) bf->bf_mpdu;
|
||||
|
||||
/*
|
||||
* Update dynamic beacon contents. If this returns
|
||||
* non-zero then we need to remap the memory because
|
||||
* the beacon frame changed size (probably because
|
||||
* of the TIM bitmap).
|
||||
*/
|
||||
curlen = skb->len;
|
||||
|
||||
/* XXX: spin_lock_bh should not be used here, but sparse bitches
|
||||
* otherwise. We should fix sparse :) */
|
||||
spin_lock_bh(&mcastq->axq_lock);
|
||||
mcastq_depth = avp->av_mcastq.axq_depth;
|
||||
|
||||
if (ath_update_beacon(sc, if_id, &avp->av_boff, skb, mcastq_depth) ==
|
||||
1) {
|
||||
ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE,
|
||||
get_dma_mem_context(bf, bf_dmacontext));
|
||||
bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE,
|
||||
get_dma_mem_context(bf, bf_dmacontext));
|
||||
} else {
|
||||
pci_dma_sync_single_for_cpu(sc->pdev,
|
||||
bf->bf_buf_addr,
|
||||
skb_tailroom(skb),
|
||||
if (skb) {
|
||||
pci_unmap_single(sc->pdev, bf->bf_dmacontext,
|
||||
skb_end_pointer(skb) - skb->head,
|
||||
PCI_DMA_TODEVICE);
|
||||
}
|
||||
|
||||
skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
|
||||
bf->bf_mpdu = skb;
|
||||
if (skb == NULL)
|
||||
return NULL;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
|
||||
/*
|
||||
* TODO: make sure the seq# gets assigned properly (vs. other
|
||||
* TX frames)
|
||||
*/
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
sc->seq_no += 0x10;
|
||||
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
|
||||
hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
|
||||
}
|
||||
bf->bf_buf_addr = bf->bf_dmacontext =
|
||||
pci_map_single(sc->pdev, skb->data,
|
||||
skb_end_pointer(skb) - skb->head,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
|
||||
|
||||
/*
|
||||
* if the CABQ traffic from previous DTIM is pending and the current
|
||||
* beacon is also a DTIM.
|
||||
@ -262,9 +209,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
|
||||
cabq_depth = cabq->axq_depth;
|
||||
spin_unlock_bh(&cabq->axq_lock);
|
||||
|
||||
is_beacon_dtim = avp->av_boff.bo_tim[4] & 1;
|
||||
|
||||
if (mcastq_depth && is_beacon_dtim && cabq_depth) {
|
||||
if (skb && cabq_depth) {
|
||||
/*
|
||||
* Unlock the cabq lock as ath_tx_draintxq acquires
|
||||
* the lock again which is a common function and that
|
||||
@ -284,10 +229,11 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
|
||||
* Enable the CAB queue before the beacon queue to
|
||||
* insure cab frames are triggered by this beacon.
|
||||
*/
|
||||
if (is_beacon_dtim)
|
||||
trigger_mcastq(ah, mcastq, cabq);
|
||||
while (skb) {
|
||||
ath_tx_cabq(sc, skb);
|
||||
skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&mcastq->axq_lock);
|
||||
return bf;
|
||||
}
|
||||
|
||||
@ -375,7 +321,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
|
||||
struct ath_buf, list);
|
||||
list_del(&avp->av_bcbuf->list);
|
||||
|
||||
if (sc->sc_opmode == ATH9K_M_HOSTAP ||
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
|
||||
!(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
|
||||
int slot;
|
||||
/*
|
||||
@ -408,8 +354,9 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
|
||||
bf = avp->av_bcbuf;
|
||||
if (bf->bf_mpdu != NULL) {
|
||||
skb = (struct sk_buff *)bf->bf_mpdu;
|
||||
ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE,
|
||||
get_dma_mem_context(bf, bf_dmacontext));
|
||||
pci_unmap_single(sc->pdev, bf->bf_dmacontext,
|
||||
skb_end_pointer(skb) - skb->head,
|
||||
PCI_DMA_TODEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
}
|
||||
@ -418,7 +365,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
|
||||
* NB: the beacon data buffer must be 32-bit aligned;
|
||||
* we assume the wbuf routines will return us something
|
||||
* with this alignment (perhaps should assert).
|
||||
* FIXME: Fill avp->av_boff.bo_tim,avp->av_btxctl.txpower and
|
||||
* FIXME: Fill avp->av_btxctl.txpower and
|
||||
* avp->av_btxctl.shortPreamble
|
||||
*/
|
||||
skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
|
||||
@ -439,9 +386,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
|
||||
__le64 val;
|
||||
int intval;
|
||||
|
||||
/* FIXME: Use default value for now: Sujith */
|
||||
|
||||
intval = ATH_DEFAULT_BINTVAL;
|
||||
intval = sc->hw->conf.beacon_int ?
|
||||
sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
|
||||
|
||||
/*
|
||||
* The beacon interval is in TU's; the TSF in usecs.
|
||||
@ -466,8 +412,10 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
|
||||
memcpy(&wh[1], &val, sizeof(val));
|
||||
}
|
||||
|
||||
bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE,
|
||||
get_dma_mem_context(bf, bf_dmacontext));
|
||||
bf->bf_buf_addr = bf->bf_dmacontext =
|
||||
pci_map_single(sc->pdev, skb->data,
|
||||
skb_end_pointer(skb) - skb->head,
|
||||
PCI_DMA_TODEVICE);
|
||||
bf->bf_mpdu = skb;
|
||||
|
||||
return 0;
|
||||
@ -493,8 +441,9 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
|
||||
bf = avp->av_bcbuf;
|
||||
if (bf->bf_mpdu != NULL) {
|
||||
struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
|
||||
ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE,
|
||||
get_dma_mem_context(bf, bf_dmacontext));
|
||||
pci_unmap_single(sc->pdev, bf->bf_dmacontext,
|
||||
skb_end_pointer(skb) - skb->head,
|
||||
PCI_DMA_TODEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
}
|
||||
@ -504,30 +453,6 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reclaim beacon resources and return buffer to the pool.
|
||||
*
|
||||
* This function will free any wbuf frames that are still attached to the
|
||||
* beacon buffers in the ATH object. Note that this does not de-allocate
|
||||
* any wbuf objects that are in the transmit queue and have not yet returned
|
||||
* to the ATH object.
|
||||
*/
|
||||
|
||||
void ath_beacon_free(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
|
||||
list_for_each_entry(bf, &sc->sc_bbuf, list) {
|
||||
if (bf->bf_mpdu != NULL) {
|
||||
struct sk_buff *skb = (struct sk_buff *) bf->bf_mpdu;
|
||||
ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE,
|
||||
get_dma_mem_context(bf, bf_dmacontext));
|
||||
dev_kfree_skb_any(skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tasklet for Sending Beacons
|
||||
*
|
||||
@ -540,9 +465,6 @@ void ath_beacon_free(struct ath_softc *sc)
|
||||
|
||||
void ath9k_beacon_tasklet(unsigned long data)
|
||||
{
|
||||
#define TSF_TO_TU(_h,_l) \
|
||||
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
|
||||
|
||||
struct ath_softc *sc = (struct ath_softc *)data;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ath_buf *bf = NULL;
|
||||
@ -555,7 +477,7 @@ void ath9k_beacon_tasklet(unsigned long data)
|
||||
u32 tsftu;
|
||||
u16 intval;
|
||||
|
||||
if (sc->sc_noreset) {
|
||||
if (sc->sc_flags & SC_OP_NO_RESET) {
|
||||
show_cycles = ath9k_hw_GetMibCycleCountsPct(ah,
|
||||
&rx_clear,
|
||||
&rx_frame,
|
||||
@ -577,7 +499,7 @@ void ath9k_beacon_tasklet(unsigned long data)
|
||||
* (in that layer).
|
||||
*/
|
||||
if (sc->sc_bmisscount < BSTUCK_THRESH) {
|
||||
if (sc->sc_noreset) {
|
||||
if (sc->sc_flags & SC_OP_NO_RESET) {
|
||||
DPRINTF(sc, ATH_DBG_BEACON,
|
||||
"%s: missed %u consecutive beacons\n",
|
||||
__func__, sc->sc_bmisscount);
|
||||
@ -605,7 +527,7 @@ void ath9k_beacon_tasklet(unsigned long data)
|
||||
__func__, sc->sc_bmisscount);
|
||||
}
|
||||
} else if (sc->sc_bmisscount >= BSTUCK_THRESH) {
|
||||
if (sc->sc_noreset) {
|
||||
if (sc->sc_flags & SC_OP_NO_RESET) {
|
||||
if (sc->sc_bmisscount == BSTUCK_THRESH) {
|
||||
DPRINTF(sc,
|
||||
ATH_DBG_BEACON,
|
||||
@ -624,7 +546,7 @@ void ath9k_beacon_tasklet(unsigned long data)
|
||||
return;
|
||||
}
|
||||
if (sc->sc_bmisscount != 0) {
|
||||
if (sc->sc_noreset) {
|
||||
if (sc->sc_flags & SC_OP_NO_RESET) {
|
||||
DPRINTF(sc,
|
||||
ATH_DBG_BEACON,
|
||||
"%s: resume beacon xmit after %u misses\n",
|
||||
@ -643,8 +565,8 @@ void ath9k_beacon_tasklet(unsigned long data)
|
||||
* on the tsf to safeguard against missing an swba.
|
||||
*/
|
||||
|
||||
/* FIXME: Use default value for now - Sujith */
|
||||
intval = ATH_DEFAULT_BINTVAL;
|
||||
intval = sc->hw->conf.beacon_int ?
|
||||
sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
|
||||
|
||||
tsf = ath9k_hw_gettsf64(ah);
|
||||
tsftu = TSF_TO_TU(tsf>>32, tsf);
|
||||
@ -704,7 +626,6 @@ void ath9k_beacon_tasklet(unsigned long data)
|
||||
|
||||
sc->ast_be_xmit += bc; /* XXX per-vap? */
|
||||
}
|
||||
#undef TSF_TO_TU
|
||||
}
|
||||
|
||||
/*
|
||||
@ -719,7 +640,7 @@ void ath_bstuck_process(struct ath_softc *sc)
|
||||
DPRINTF(sc, ATH_DBG_BEACON,
|
||||
"%s: stuck beacon; resetting (bmiss count %u)\n",
|
||||
__func__, sc->sc_bmisscount);
|
||||
ath_internal_reset(sc);
|
||||
ath_reset(sc, false);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -740,8 +661,6 @@ void ath_bstuck_process(struct ath_softc *sc)
|
||||
|
||||
void ath_beacon_config(struct ath_softc *sc, int if_id)
|
||||
{
|
||||
#define TSF_TO_TU(_h,_l) \
|
||||
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
u32 nexttbtt, intval;
|
||||
struct ath_beacon_config conf;
|
||||
@ -750,7 +669,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
|
||||
if (if_id != ATH_IF_ID_ANY)
|
||||
av_opmode = sc->sc_vaps[if_id]->av_opmode;
|
||||
else
|
||||
av_opmode = sc->sc_opmode;
|
||||
av_opmode = sc->sc_ah->ah_opmode;
|
||||
|
||||
memzero(&conf, sizeof(struct ath_beacon_config));
|
||||
|
||||
@ -760,7 +679,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
|
||||
* Protocol stack doesn't support dynamic beacon configuration,
|
||||
* use default configurations.
|
||||
*/
|
||||
conf.beacon_interval = ATH_DEFAULT_BINTVAL;
|
||||
conf.beacon_interval = sc->hw->conf.beacon_int ?
|
||||
sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
|
||||
conf.listen_interval = 1;
|
||||
conf.dtim_period = conf.beacon_interval;
|
||||
conf.dtim_count = 1;
|
||||
@ -770,7 +690,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
|
||||
nexttbtt = TSF_TO_TU(get_unaligned_le32(conf.u.last_tstamp + 4),
|
||||
get_unaligned_le32(conf.u.last_tstamp));
|
||||
/* XXX conditionalize multi-bss support? */
|
||||
if (sc->sc_opmode == ATH9K_M_HOSTAP) {
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
|
||||
/*
|
||||
* For multi-bss ap support beacons are either staggered
|
||||
* evenly over N slots or burst together. For the former
|
||||
@ -791,7 +711,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
|
||||
DPRINTF(sc, ATH_DBG_BEACON, "%s: nexttbtt %u intval %u (%u)\n",
|
||||
__func__, nexttbtt, intval, conf.beacon_interval);
|
||||
/* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */
|
||||
if (sc->sc_opmode == ATH9K_M_STA) {
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_STA) {
|
||||
struct ath9k_beacon_state bs;
|
||||
u64 tsf;
|
||||
u32 tsftu;
|
||||
@ -886,19 +806,19 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
|
||||
"cfp:period %u "
|
||||
"maxdur %u "
|
||||
"next %u "
|
||||
"timoffset %u\n"
|
||||
, __func__
|
||||
, (unsigned long long)tsf, tsftu
|
||||
, bs.bs_intval
|
||||
, bs.bs_nexttbtt
|
||||
, bs.bs_dtimperiod
|
||||
, bs.bs_nextdtim
|
||||
, bs.bs_bmissthreshold
|
||||
, bs.bs_sleepduration
|
||||
, bs.bs_cfpperiod
|
||||
, bs.bs_cfpmaxduration
|
||||
, bs.bs_cfpnext
|
||||
, bs.bs_timoffset
|
||||
"timoffset %u\n",
|
||||
__func__,
|
||||
(unsigned long long)tsf, tsftu,
|
||||
bs.bs_intval,
|
||||
bs.bs_nexttbtt,
|
||||
bs.bs_dtimperiod,
|
||||
bs.bs_nextdtim,
|
||||
bs.bs_bmissthreshold,
|
||||
bs.bs_sleepduration,
|
||||
bs.bs_cfpperiod,
|
||||
bs.bs_cfpmaxduration,
|
||||
bs.bs_cfpnext,
|
||||
bs.bs_timoffset
|
||||
);
|
||||
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
@ -911,7 +831,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
if (nexttbtt == intval)
|
||||
intval |= ATH9K_BEACON_RESET_TSF;
|
||||
if (sc->sc_opmode == ATH9K_M_IBSS) {
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
|
||||
/*
|
||||
* Pull nexttbtt forward to reflect the current
|
||||
* TSF .
|
||||
@ -943,7 +863,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
|
||||
if (!(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL))
|
||||
sc->sc_imask |= ATH9K_INT_SWBA;
|
||||
ath_beaconq_config(sc);
|
||||
} else if (sc->sc_opmode == ATH9K_M_HOSTAP) {
|
||||
} else if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
|
||||
/*
|
||||
* In AP mode we enable the beacon timers and
|
||||
* SWBA interrupts to prepare beacon frames.
|
||||
@ -959,11 +879,10 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
|
||||
* When using a self-linked beacon descriptor in
|
||||
* ibss mode load it once here.
|
||||
*/
|
||||
if (sc->sc_opmode == ATH9K_M_IBSS &&
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS &&
|
||||
(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL))
|
||||
ath_beacon_start_adhoc(sc, 0);
|
||||
}
|
||||
#undef TSF_TO_TU
|
||||
}
|
||||
|
||||
/* Function to collect beacon rssi data and resync beacon if necessary */
|
||||
@ -975,5 +894,5 @@ void ath_beacon_sync(struct ath_softc *sc, int if_id)
|
||||
* beacon frame we just received.
|
||||
*/
|
||||
ath_beacon_config(sc, if_id);
|
||||
sc->sc_beacons = 1;
|
||||
sc->sc_flags |= SC_OP_BEACONS;
|
||||
}
|
||||
|
@ -21,9 +21,6 @@
|
||||
|
||||
static int ath_outdoor; /* enable outdoor use */
|
||||
|
||||
static const u8 ath_bcast_mac[ETH_ALEN] =
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
static u32 ath_chainmask_sel_up_rssi_thres =
|
||||
ATH_CHAINMASK_SEL_UP_RSSI_THRES;
|
||||
static u32 ath_chainmask_sel_down_rssi_thres =
|
||||
@ -54,10 +51,8 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz)
|
||||
* Set current operating mode
|
||||
*
|
||||
* This function initializes and fills the rate table in the ATH object based
|
||||
* on the operating mode. The blink rates are also set up here, although
|
||||
* they have been superceeded by the ath_led module.
|
||||
* on the operating mode.
|
||||
*/
|
||||
|
||||
static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode)
|
||||
{
|
||||
const struct ath9k_rate_table *rt;
|
||||
@ -235,7 +230,7 @@ static int ath_setup_channels(struct ath_softc *sc)
|
||||
* Determine mode from channel flags
|
||||
*
|
||||
* This routine will provide the enumerated WIRELESSS_MODE value based
|
||||
* on the settings of the channel flags. If ho valid set of flags
|
||||
* on the settings of the channel flags. If no valid set of flags
|
||||
* exist, the lowest mode (11b) is selected.
|
||||
*/
|
||||
|
||||
@ -260,7 +255,8 @@ static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan)
|
||||
else if (chan->chanmode == CHANNEL_G_HT40MINUS)
|
||||
return ATH9K_MODE_11NG_HT40MINUS;
|
||||
|
||||
/* NB: should not get here */
|
||||
WARN_ON(1); /* should not get here */
|
||||
|
||||
return ATH9K_MODE_11B;
|
||||
}
|
||||
|
||||
@ -275,14 +271,12 @@ static int ath_stop(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %u\n",
|
||||
__func__, sc->sc_invalid);
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %ld\n",
|
||||
__func__, sc->sc_flags & SC_OP_INVALID);
|
||||
|
||||
/*
|
||||
* Shutdown the hardware and driver:
|
||||
* stop output from above
|
||||
* reset 802.11 state machine
|
||||
* (sends station deassoc/deauth frames)
|
||||
* turn off timers
|
||||
* disable interrupts
|
||||
* clear transmit machinery
|
||||
@ -294,10 +288,10 @@ static int ath_stop(struct ath_softc *sc)
|
||||
* hardware is gone (invalid).
|
||||
*/
|
||||
|
||||
if (!sc->sc_invalid)
|
||||
if (!(sc->sc_flags & SC_OP_INVALID))
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
ath_draintxq(sc, false);
|
||||
if (!sc->sc_invalid) {
|
||||
if (!(sc->sc_flags & SC_OP_INVALID)) {
|
||||
ath_stoprecv(sc);
|
||||
ath9k_hw_phy_disable(ah);
|
||||
} else
|
||||
@ -306,56 +300,6 @@ static int ath_stop(struct ath_softc *sc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start Scan
|
||||
*
|
||||
* This function is called when starting a channel scan. It will perform
|
||||
* power save wakeup processing, set the filter for the scan, and get the
|
||||
* chip ready to send broadcast packets out during the scan.
|
||||
*/
|
||||
|
||||
void ath_scan_start(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
u32 rfilt;
|
||||
u32 now = (u32) jiffies_to_msecs(get_timestamp());
|
||||
|
||||
sc->sc_scanning = 1;
|
||||
rfilt = ath_calcrxfilter(sc);
|
||||
ath9k_hw_setrxfilter(ah, rfilt);
|
||||
ath9k_hw_write_associd(ah, ath_bcast_mac, 0);
|
||||
|
||||
/* Restore previous power management state. */
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0\n",
|
||||
now / 1000, now % 1000, __func__, rfilt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan End
|
||||
*
|
||||
* This routine is called by the upper layer when the scan is completed. This
|
||||
* will set the filters back to normal operating mode, set the BSSID to the
|
||||
* correct value, and restore the power save state.
|
||||
*/
|
||||
|
||||
void ath_scan_end(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
u32 rfilt;
|
||||
u32 now = (u32) jiffies_to_msecs(get_timestamp());
|
||||
|
||||
sc->sc_scanning = 0;
|
||||
/* Request for a full reset due to rx packet filter changes */
|
||||
sc->sc_full_reset = 1;
|
||||
rfilt = ath_calcrxfilter(sc);
|
||||
ath9k_hw_setrxfilter(ah, rfilt);
|
||||
ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid);
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0x%x\n",
|
||||
now / 1000, now % 1000, __func__, rfilt, sc->sc_curaid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the current channel
|
||||
*
|
||||
@ -367,25 +311,23 @@ int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
bool fastcc = true, stopped;
|
||||
enum ath9k_ht_macmode ht_macmode;
|
||||
|
||||
if (sc->sc_invalid) /* if the device is invalid or removed */
|
||||
if (sc->sc_flags & SC_OP_INVALID) /* the device is invalid or removed */
|
||||
return -EIO;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG,
|
||||
"%s: %u (%u MHz) -> %u (%u MHz), cflags:%x\n",
|
||||
__func__,
|
||||
ath9k_hw_mhz2ieee(ah, sc->sc_curchan.channel,
|
||||
sc->sc_curchan.channelFlags),
|
||||
sc->sc_curchan.channel,
|
||||
ath9k_hw_mhz2ieee(ah, sc->sc_ah->ah_curchan->channel,
|
||||
sc->sc_ah->ah_curchan->channelFlags),
|
||||
sc->sc_ah->ah_curchan->channel,
|
||||
ath9k_hw_mhz2ieee(ah, hchan->channel, hchan->channelFlags),
|
||||
hchan->channel, hchan->channelFlags);
|
||||
|
||||
ht_macmode = ath_cwm_macmode(sc);
|
||||
|
||||
if (hchan->channel != sc->sc_curchan.channel ||
|
||||
hchan->channelFlags != sc->sc_curchan.channelFlags ||
|
||||
sc->sc_update_chainmask || sc->sc_full_reset) {
|
||||
if (hchan->channel != sc->sc_ah->ah_curchan->channel ||
|
||||
hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags ||
|
||||
(sc->sc_flags & SC_OP_CHAINMASK_UPDATE) ||
|
||||
(sc->sc_flags & SC_OP_FULL_RESET)) {
|
||||
int status;
|
||||
/*
|
||||
* This is only performed if the channel settings have
|
||||
@ -404,12 +346,13 @@ int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
|
||||
* to flush data frames already in queue because of
|
||||
* changing channel. */
|
||||
|
||||
if (!stopped || sc->sc_full_reset)
|
||||
if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
|
||||
fastcc = false;
|
||||
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
if (!ath9k_hw_reset(ah, sc->sc_opmode, hchan,
|
||||
ht_macmode, sc->sc_tx_chainmask,
|
||||
if (!ath9k_hw_reset(ah, hchan,
|
||||
sc->sc_ht_info.tx_chan_width,
|
||||
sc->sc_tx_chainmask,
|
||||
sc->sc_rx_chainmask,
|
||||
sc->sc_ht_extprotspacing,
|
||||
fastcc, &status)) {
|
||||
@ -424,9 +367,8 @@ int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
|
||||
}
|
||||
spin_unlock_bh(&sc->sc_resetlock);
|
||||
|
||||
sc->sc_curchan = *hchan;
|
||||
sc->sc_update_chainmask = 0;
|
||||
sc->sc_full_reset = 0;
|
||||
sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE;
|
||||
sc->sc_flags &= ~SC_OP_FULL_RESET;
|
||||
|
||||
/* Re-enable rx framework */
|
||||
if (ath_startrecv(sc) != 0) {
|
||||
@ -537,7 +479,7 @@ int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an)
|
||||
|
||||
void ath_update_chainmask(struct ath_softc *sc, int is_ht)
|
||||
{
|
||||
sc->sc_update_chainmask = 1;
|
||||
sc->sc_flags |= SC_OP_CHAINMASK_UPDATE;
|
||||
if (is_ht) {
|
||||
sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask;
|
||||
sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask;
|
||||
@ -554,62 +496,6 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht)
|
||||
/* VAP management */
|
||||
/******************/
|
||||
|
||||
/*
|
||||
* VAP in Listen mode
|
||||
*
|
||||
* This routine brings the VAP out of the down state into a "listen" state
|
||||
* where it waits for association requests. This is used in AP and AdHoc
|
||||
* modes.
|
||||
*/
|
||||
|
||||
int ath_vap_listen(struct ath_softc *sc, int if_id)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ath_vap *avp;
|
||||
u32 rfilt = 0;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
avp = sc->sc_vaps[if_id];
|
||||
if (avp == NULL) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n",
|
||||
__func__, if_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SLOW_ANT_DIV
|
||||
ath_slow_ant_div_stop(&sc->sc_antdiv);
|
||||
#endif
|
||||
|
||||
/* update ratectrl about the new state */
|
||||
ath_rate_newstate(sc, avp);
|
||||
|
||||
rfilt = ath_calcrxfilter(sc);
|
||||
ath9k_hw_setrxfilter(ah, rfilt);
|
||||
|
||||
if (sc->sc_opmode == ATH9K_M_STA || sc->sc_opmode == ATH9K_M_IBSS) {
|
||||
memcpy(sc->sc_curbssid, ath_bcast_mac, ETH_ALEN);
|
||||
ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid);
|
||||
} else
|
||||
sc->sc_curaid = 0;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG,
|
||||
"%s: RX filter 0x%x bssid %s aid 0x%x\n",
|
||||
__func__, rfilt, print_mac(mac,
|
||||
sc->sc_curbssid), sc->sc_curaid);
|
||||
|
||||
/*
|
||||
* XXXX
|
||||
* Disable BMISS interrupt when we're not associated
|
||||
*/
|
||||
ath9k_hw_set_interrupts(ah,
|
||||
sc->sc_imask & ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS));
|
||||
sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
|
||||
/* need to reconfigure the beacons when it moves to RUN */
|
||||
sc->sc_beacons = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath_vap_attach(struct ath_softc *sc,
|
||||
int if_id,
|
||||
struct ieee80211_vif *if_data,
|
||||
@ -647,16 +533,13 @@ int ath_vap_attach(struct ath_softc *sc,
|
||||
/* Set the VAP opmode */
|
||||
avp->av_opmode = opmode;
|
||||
avp->av_bslot = -1;
|
||||
INIT_LIST_HEAD(&avp->av_mcastq.axq_q);
|
||||
INIT_LIST_HEAD(&avp->av_mcastq.axq_acq);
|
||||
spin_lock_init(&avp->av_mcastq.axq_lock);
|
||||
|
||||
ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
|
||||
|
||||
sc->sc_vaps[if_id] = avp;
|
||||
sc->sc_nvaps++;
|
||||
/* Set the device opmode */
|
||||
sc->sc_opmode = opmode;
|
||||
sc->sc_ah->ah_opmode = opmode;
|
||||
|
||||
/* default VAP configuration */
|
||||
avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE;
|
||||
@ -689,9 +572,6 @@ int ath_vap_detach(struct ath_softc *sc, int if_id)
|
||||
ath_stoprecv(sc); /* stop recv side */
|
||||
ath_flushrecv(sc); /* flush recv queue */
|
||||
|
||||
/* Reclaim any pending mcast bufs on the vap. */
|
||||
ath_tx_draintxq(sc, &avp->av_mcastq, false);
|
||||
|
||||
kfree(avp);
|
||||
sc->sc_vaps[if_id] = NULL;
|
||||
sc->sc_nvaps--;
|
||||
@ -728,9 +608,9 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
int status;
|
||||
int error = 0;
|
||||
enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc);
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n", __func__, sc->sc_opmode);
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n",
|
||||
__func__, sc->sc_ah->ah_opmode);
|
||||
|
||||
/*
|
||||
* Stop anything previously setup. This is safe
|
||||
@ -752,16 +632,16 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
|
||||
* be followed by initialization of the appropriate bits
|
||||
* and then setup of the interrupt mask.
|
||||
*/
|
||||
sc->sc_curchan = *initial_chan;
|
||||
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan, ht_macmode,
|
||||
if (!ath9k_hw_reset(ah, initial_chan,
|
||||
sc->sc_ht_info.tx_chan_width,
|
||||
sc->sc_tx_chainmask, sc->sc_rx_chainmask,
|
||||
sc->sc_ht_extprotspacing, false, &status)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"%s: unable to reset hardware; hal status %u "
|
||||
"(freq %u flags 0x%x)\n", __func__, status,
|
||||
sc->sc_curchan.channel, sc->sc_curchan.channelFlags);
|
||||
initial_chan->channel, initial_chan->channelFlags);
|
||||
error = -EIO;
|
||||
spin_unlock_bh(&sc->sc_resetlock);
|
||||
goto done;
|
||||
@ -802,7 +682,8 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
|
||||
* Note we only do this (at the moment) for station mode.
|
||||
*/
|
||||
if (ath9k_hw_phycounters(ah) &&
|
||||
((sc->sc_opmode == ATH9K_M_STA) || (sc->sc_opmode == ATH9K_M_IBSS)))
|
||||
((sc->sc_ah->ah_opmode == ATH9K_M_STA) ||
|
||||
(sc->sc_ah->ah_opmode == ATH9K_M_IBSS)))
|
||||
sc->sc_imask |= ATH9K_INT_MIB;
|
||||
/*
|
||||
* Some hardware processes the TIM IE and fires an
|
||||
@ -811,7 +692,7 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
|
||||
* enable the TIM interrupt when operating as station.
|
||||
*/
|
||||
if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) &&
|
||||
(sc->sc_opmode == ATH9K_M_STA) &&
|
||||
(sc->sc_ah->ah_opmode == ATH9K_M_STA) &&
|
||||
!sc->sc_config.swBeaconProcess)
|
||||
sc->sc_imask |= ATH9K_INT_TIM;
|
||||
/*
|
||||
@ -823,34 +704,34 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
|
||||
|
||||
/* XXX: we must make sure h/w is ready and clear invalid flag
|
||||
* before turning on interrupt. */
|
||||
sc->sc_invalid = 0;
|
||||
sc->sc_flags &= ~SC_OP_INVALID;
|
||||
done:
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the hardware w/o losing operational state. This is
|
||||
* basically a more efficient way of doing ath_stop, ath_init,
|
||||
* followed by state transitions to the current 802.11
|
||||
* operational state. Used to recover from errors rx overrun
|
||||
* and to reset the hardware when rf gain settings must be reset.
|
||||
*/
|
||||
|
||||
static int ath_reset_start(struct ath_softc *sc, u32 flag)
|
||||
int ath_reset(struct ath_softc *sc, bool retry_tx)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
int status;
|
||||
int error = 0;
|
||||
|
||||
ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */
|
||||
ath_draintxq(sc, flag & RESET_RETRY_TXQ); /* stop xmit side */
|
||||
ath_stoprecv(sc); /* stop recv side */
|
||||
ath_draintxq(sc, retry_tx); /* stop xmit */
|
||||
ath_stoprecv(sc); /* stop recv */
|
||||
ath_flushrecv(sc); /* flush recv queue */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath_reset_end(struct ath_softc *sc, u32 flag)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
/* Reset chip */
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan,
|
||||
sc->sc_ht_info.tx_chan_width,
|
||||
sc->sc_tx_chainmask, sc->sc_rx_chainmask,
|
||||
sc->sc_ht_extprotspacing, false, &status)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"%s: unable to reset hardware; hal status %u\n",
|
||||
__func__, status);
|
||||
error = -EIO;
|
||||
}
|
||||
spin_unlock_bh(&sc->sc_resetlock);
|
||||
|
||||
if (ath_startrecv(sc) != 0) /* restart recv */
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
@ -861,16 +742,17 @@ static int ath_reset_end(struct ath_softc *sc, u32 flag)
|
||||
* that changes the channel so update any state that
|
||||
* might change as a result.
|
||||
*/
|
||||
ath_setcurmode(sc, ath_chan2mode(&sc->sc_curchan));
|
||||
ath_setcurmode(sc, ath_chan2mode(sc->sc_ah->ah_curchan));
|
||||
|
||||
ath_update_txpow(sc); /* update tx power state */
|
||||
ath_update_txpow(sc);
|
||||
|
||||
if (sc->sc_beacons)
|
||||
if (sc->sc_flags & SC_OP_BEACONS)
|
||||
ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */
|
||||
|
||||
ath9k_hw_set_interrupts(ah, sc->sc_imask);
|
||||
|
||||
/* Restart the txq */
|
||||
if (flag & RESET_RETRY_TXQ) {
|
||||
if (retry_tx) {
|
||||
int i;
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
if (ATH_TXQ_SETUP(sc, i)) {
|
||||
@ -880,28 +762,6 @@ static int ath_reset_end(struct ath_softc *sc, u32 flag)
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath_reset(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
int status;
|
||||
int error = 0;
|
||||
enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc);
|
||||
|
||||
/* NB: indicate channel change so we do a full reset */
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan,
|
||||
ht_macmode,
|
||||
sc->sc_tx_chainmask, sc->sc_rx_chainmask,
|
||||
sc->sc_ht_extprotspacing, false, &status)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"%s: unable to reset hardware; hal status %u\n",
|
||||
__func__, status);
|
||||
error = -EIO;
|
||||
}
|
||||
spin_unlock_bh(&sc->sc_resetlock);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -911,7 +771,7 @@ int ath_suspend(struct ath_softc *sc)
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
|
||||
/* No I/O if device has been surprise removed */
|
||||
if (sc->sc_invalid)
|
||||
if (sc->sc_flags & SC_OP_INVALID)
|
||||
return -EIO;
|
||||
|
||||
/* Shut off the interrupt before setting sc->sc_invalid to '1' */
|
||||
@ -919,7 +779,7 @@ int ath_suspend(struct ath_softc *sc)
|
||||
|
||||
/* XXX: we must make sure h/w will not generate any interrupt
|
||||
* before setting the invalid flag. */
|
||||
sc->sc_invalid = 1;
|
||||
sc->sc_flags |= SC_OP_INVALID;
|
||||
|
||||
/* disable HAL and put h/w to sleep */
|
||||
ath9k_hw_disable(sc->sc_ah);
|
||||
@ -940,7 +800,7 @@ irqreturn_t ath_isr(int irq, void *dev)
|
||||
bool sched = false;
|
||||
|
||||
do {
|
||||
if (sc->sc_invalid) {
|
||||
if (sc->sc_flags & SC_OP_INVALID) {
|
||||
/*
|
||||
* The hardware is not ready/present, don't
|
||||
* touch anything. Note this can happen early
|
||||
@ -1050,7 +910,7 @@ static void ath9k_tasklet(unsigned long data)
|
||||
|
||||
if (status & ATH9K_INT_FATAL) {
|
||||
/* need a chip reset */
|
||||
ath_internal_reset(sc);
|
||||
ath_reset(sc, false);
|
||||
return;
|
||||
} else {
|
||||
|
||||
@ -1093,10 +953,9 @@ int ath_init(u16 devid, struct ath_softc *sc)
|
||||
int status;
|
||||
int error = 0, i;
|
||||
int csz = 0;
|
||||
u32 rd;
|
||||
|
||||
/* XXX: hardware will not be ready until ath_open() being called */
|
||||
sc->sc_invalid = 1;
|
||||
sc->sc_flags |= SC_OP_INVALID;
|
||||
|
||||
sc->sc_debug = DBG_DEFAULT;
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "%s: devid 0x%x\n", __func__, devid);
|
||||
@ -1126,9 +985,6 @@ int ath_init(u16 devid, struct ath_softc *sc)
|
||||
}
|
||||
sc->sc_ah = ah;
|
||||
|
||||
/* Get the chipset-specific aggr limit. */
|
||||
sc->sc_rtsaggrlimit = ah->ah_caps.rts_aggr_limit;
|
||||
|
||||
/* Get the hardware key cache size. */
|
||||
sc->sc_keymax = ah->ah_caps.keycache_size;
|
||||
if (sc->sc_keymax > ATH_KEYMAX) {
|
||||
@ -1162,14 +1018,12 @@ int ath_init(u16 devid, struct ath_softc *sc)
|
||||
* is resposible for filtering this list based on settings
|
||||
* like the phy mode.
|
||||
*/
|
||||
rd = ah->ah_currentRD;
|
||||
|
||||
error = ath_setup_channels(sc);
|
||||
if (error)
|
||||
goto bad;
|
||||
|
||||
/* default to STA mode */
|
||||
sc->sc_opmode = ATH9K_M_MONITOR;
|
||||
sc->sc_ah->ah_opmode = ATH9K_M_MONITOR;
|
||||
|
||||
/* Setup rate tables */
|
||||
|
||||
@ -1240,7 +1094,7 @@ int ath_init(u16 devid, struct ath_softc *sc)
|
||||
|
||||
sc->sc_rc = ath_rate_attach(ah);
|
||||
if (sc->sc_rc == NULL) {
|
||||
error = EIO;
|
||||
error = -EIO;
|
||||
goto bad2;
|
||||
}
|
||||
|
||||
@ -1280,20 +1134,13 @@ int ath_init(u16 devid, struct ath_softc *sc)
|
||||
|
||||
/* 11n Capabilities */
|
||||
if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) {
|
||||
sc->sc_txaggr = 1;
|
||||
sc->sc_rxaggr = 1;
|
||||
sc->sc_flags |= SC_OP_TXAGGR;
|
||||
sc->sc_flags |= SC_OP_RXAGGR;
|
||||
}
|
||||
|
||||
sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask;
|
||||
sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask;
|
||||
|
||||
/* Configuration for rx chain detection */
|
||||
sc->sc_rxchaindetect_ref = 0;
|
||||
sc->sc_rxchaindetect_thresh5GHz = 35;
|
||||
sc->sc_rxchaindetect_thresh2GHz = 35;
|
||||
sc->sc_rxchaindetect_delta5GHz = 30;
|
||||
sc->sc_rxchaindetect_delta2GHz = 30;
|
||||
|
||||
ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
|
||||
sc->sc_defant = ath9k_hw_getdefantenna(ah);
|
||||
|
||||
@ -1337,7 +1184,7 @@ void ath_deinit(struct ath_softc *sc)
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__);
|
||||
|
||||
ath_stop(sc);
|
||||
if (!sc->sc_invalid)
|
||||
if (!(sc->sc_flags & SC_OP_INVALID))
|
||||
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
|
||||
ath_rate_detach(sc->sc_rc);
|
||||
/* cleanup tx queues */
|
||||
@ -1464,9 +1311,9 @@ void ath_newassoc(struct ath_softc *sc,
|
||||
/* if station reassociates, tear down the aggregation state. */
|
||||
if (!isnew) {
|
||||
for (tidno = 0; tidno < WME_NUM_TID; tidno++) {
|
||||
if (sc->sc_txaggr)
|
||||
if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
ath_tx_aggr_teardown(sc, an, tidno);
|
||||
if (sc->sc_rxaggr)
|
||||
if (sc->sc_flags & SC_OP_RXAGGR)
|
||||
ath_rx_aggr_teardown(sc, an, tidno);
|
||||
}
|
||||
}
|
||||
@ -1815,13 +1662,6 @@ void ath_descdma_cleanup(struct ath_softc *sc,
|
||||
/* Utilities */
|
||||
/*************/
|
||||
|
||||
void ath_internal_reset(struct ath_softc *sc)
|
||||
{
|
||||
ath_reset_start(sc, 0);
|
||||
ath_reset(sc);
|
||||
ath_reset_end(sc, 0);
|
||||
}
|
||||
|
||||
int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
|
||||
{
|
||||
int qnum;
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <linux/scatterlist.h>
|
||||
#include <asm/page.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <linux/leds.h>
|
||||
|
||||
#include "ath9k.h"
|
||||
#include "rc.h"
|
||||
@ -79,12 +80,12 @@ struct ath_node;
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TSF_TO_TU(_h,_l) \
|
||||
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
|
||||
|
||||
/* XXX: remove */
|
||||
#define memzero(_buf, _len) memset(_buf, 0, _len)
|
||||
|
||||
#define get_dma_mem_context(var, field) (&((var)->field))
|
||||
#define copy_dma_mem_context(dst, src) (*dst = *src)
|
||||
|
||||
#define ATH9K_BH_STATUS_INTACT 0
|
||||
#define ATH9K_BH_STATUS_CHANGE 1
|
||||
|
||||
@ -95,6 +96,8 @@ static inline unsigned long get_timestamp(void)
|
||||
return ((jiffies / HZ) * 1000) + (jiffies % HZ) * (1000 / HZ);
|
||||
}
|
||||
|
||||
static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
/*************/
|
||||
/* Debugging */
|
||||
/*************/
|
||||
@ -175,11 +178,6 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht);
|
||||
/* Descriptor Management */
|
||||
/*************************/
|
||||
|
||||
/* Number of descriptors per buffer. The only case where we see skbuff
|
||||
chains is due to FF aggregation in the driver. */
|
||||
#define ATH_TXDESC 1
|
||||
/* if there's more fragment for this MSDU */
|
||||
#define ATH_BF_MORE_MPDU 1
|
||||
#define ATH_TXBUF_RESET(_bf) do { \
|
||||
(_bf)->bf_status = 0; \
|
||||
(_bf)->bf_lastbf = NULL; \
|
||||
@ -189,6 +187,20 @@ chains is due to FF aggregation in the driver. */
|
||||
sizeof(struct ath_buf_state)); \
|
||||
} while (0)
|
||||
|
||||
enum buffer_type {
|
||||
BUF_DATA = BIT(0),
|
||||
BUF_AGGR = BIT(1),
|
||||
BUF_AMPDU = BIT(2),
|
||||
BUF_HT = BIT(3),
|
||||
BUF_RETRY = BIT(4),
|
||||
BUF_XRETRY = BIT(5),
|
||||
BUF_SHORT_PREAMBLE = BIT(6),
|
||||
BUF_BAR = BIT(7),
|
||||
BUF_PSPOLL = BIT(8),
|
||||
BUF_AGGR_BURST = BIT(9),
|
||||
BUF_CALC_AIRTIME = BIT(10),
|
||||
};
|
||||
|
||||
struct ath_buf_state {
|
||||
int bfs_nframes; /* # frames in aggregate */
|
||||
u16 bfs_al; /* length of aggregate */
|
||||
@ -197,20 +209,7 @@ struct ath_buf_state {
|
||||
int bfs_tidno; /* tid of this frame */
|
||||
int bfs_retries; /* current retries */
|
||||
struct ath_rc_series bfs_rcs[4]; /* rate series */
|
||||
u8 bfs_isdata:1; /* is a data frame/aggregate */
|
||||
u8 bfs_isaggr:1; /* is an aggregate */
|
||||
u8 bfs_isampdu:1; /* is an a-mpdu, aggregate or not */
|
||||
u8 bfs_ht:1; /* is an HT frame */
|
||||
u8 bfs_isretried:1; /* is retried */
|
||||
u8 bfs_isxretried:1; /* is excessive retried */
|
||||
u8 bfs_shpreamble:1; /* is short preamble */
|
||||
u8 bfs_isbar:1; /* is a BAR */
|
||||
u8 bfs_ispspoll:1; /* is a PS-Poll */
|
||||
u8 bfs_aggrburst:1; /* is a aggr burst */
|
||||
u8 bfs_calcairtime:1; /* requests airtime be calculated
|
||||
when set for tx frame */
|
||||
int bfs_rifsburst_elem; /* RIFS burst/bar */
|
||||
int bfs_nrifsubframes; /* # of elements in burst */
|
||||
u32 bf_type; /* BUF_* (enum buffer_type) */
|
||||
/* key type use to encrypt this frame */
|
||||
enum ath9k_key_type bfs_keytype;
|
||||
};
|
||||
@ -222,26 +221,22 @@ struct ath_buf_state {
|
||||
#define bf_seqno bf_state.bfs_seqno
|
||||
#define bf_tidno bf_state.bfs_tidno
|
||||
#define bf_rcs bf_state.bfs_rcs
|
||||
#define bf_isdata bf_state.bfs_isdata
|
||||
#define bf_isaggr bf_state.bfs_isaggr
|
||||
#define bf_isampdu bf_state.bfs_isampdu
|
||||
#define bf_ht bf_state.bfs_ht
|
||||
#define bf_isretried bf_state.bfs_isretried
|
||||
#define bf_isxretried bf_state.bfs_isxretried
|
||||
#define bf_shpreamble bf_state.bfs_shpreamble
|
||||
#define bf_rifsburst_elem bf_state.bfs_rifsburst_elem
|
||||
#define bf_nrifsubframes bf_state.bfs_nrifsubframes
|
||||
#define bf_keytype bf_state.bfs_keytype
|
||||
#define bf_isbar bf_state.bfs_isbar
|
||||
#define bf_ispspoll bf_state.bfs_ispspoll
|
||||
#define bf_aggrburst bf_state.bfs_aggrburst
|
||||
#define bf_calcairtime bf_state.bfs_calcairtime
|
||||
#define bf_isdata(bf) (bf->bf_state.bf_type & BUF_DATA)
|
||||
#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
|
||||
#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
|
||||
#define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT)
|
||||
#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY)
|
||||
#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY)
|
||||
#define bf_isshpreamble(bf) (bf->bf_state.bf_type & BUF_SHORT_PREAMBLE)
|
||||
#define bf_isbar(bf) (bf->bf_state.bf_type & BUF_BAR)
|
||||
#define bf_ispspoll(bf) (bf->bf_state.bf_type & BUF_PSPOLL)
|
||||
#define bf_isaggrburst(bf) (bf->bf_state.bf_type & BUF_AGGR_BURST)
|
||||
|
||||
/*
|
||||
* Abstraction of a contiguous buffer to transmit/receive. There is only
|
||||
* a single hw descriptor encapsulated here.
|
||||
*/
|
||||
|
||||
struct ath_buf {
|
||||
struct list_head list;
|
||||
struct list_head *last;
|
||||
@ -391,7 +386,7 @@ int ath_rx_input(struct ath_softc *sc,
|
||||
struct sk_buff *skb,
|
||||
struct ath_recv_status *rx_status,
|
||||
enum ATH_RX_TYPE *status);
|
||||
int ath__rx_indicate(struct ath_softc *sc,
|
||||
int _ath_rx_indicate(struct ath_softc *sc,
|
||||
struct sk_buff *skb,
|
||||
struct ath_recv_status *status,
|
||||
u16 keyix);
|
||||
@ -402,8 +397,7 @@ int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb,
|
||||
/* TX */
|
||||
/******/
|
||||
|
||||
#define ATH_FRAG_PER_MSDU 1
|
||||
#define ATH_TXBUF (512/ATH_FRAG_PER_MSDU)
|
||||
#define ATH_TXBUF 512
|
||||
/* max number of transmit attempts (tries) */
|
||||
#define ATH_TXMAXTRY 13
|
||||
/* max number of 11n transmit attempts (tries) */
|
||||
@ -522,7 +516,6 @@ struct ath_tx_control {
|
||||
u32 keyix;
|
||||
int min_rate;
|
||||
int mcast_rate;
|
||||
u16 nextfraglen;
|
||||
struct ath_softc *dev;
|
||||
dma_addr_t dmacontext;
|
||||
};
|
||||
@ -575,6 +568,7 @@ u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum);
|
||||
void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth);
|
||||
void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
struct ath_xmit_status *tx_status, struct ath_node *an);
|
||||
void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
|
||||
|
||||
/**********************/
|
||||
/* Node / Aggregation */
|
||||
@ -585,7 +579,6 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
/* indicates the node is 80211 power save */
|
||||
#define ATH_NODE_PWRSAVE 0x2
|
||||
|
||||
#define ADDBA_TIMEOUT 200 /* 200 milliseconds */
|
||||
#define ADDBA_EXCHANGE_ATTEMPTS 10
|
||||
#define ATH_AGGR_DELIM_SZ 4 /* delimiter size */
|
||||
#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
|
||||
@ -705,9 +698,6 @@ struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr);
|
||||
#define ATH_BCBUF 4 /* number of beacon buffers */
|
||||
#define ATH_DEFAULT_BINTVAL 100 /* default beacon interval in TU */
|
||||
#define ATH_DEFAULT_BMISS_LIMIT 10
|
||||
#define ATH_BEACON_AIFS_DEFAULT 0 /* Default aifs for ap beacon q */
|
||||
#define ATH_BEACON_CWMIN_DEFAULT 0 /* Default cwmin for ap beacon q */
|
||||
#define ATH_BEACON_CWMAX_DEFAULT 0 /* Default cwmax for ap beacon q */
|
||||
#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024)
|
||||
|
||||
/* beacon configuration */
|
||||
@ -724,30 +714,16 @@ struct ath_beacon_config {
|
||||
} u; /* last received beacon/probe response timestamp of this BSS. */
|
||||
};
|
||||
|
||||
/* offsets in a beacon frame for
|
||||
* quick acess of beacon content by low-level driver */
|
||||
struct ath_beacon_offset {
|
||||
u8 *bo_tim; /* start of atim/dtim */
|
||||
};
|
||||
|
||||
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);
|
||||
int ath_beacon_alloc(struct ath_softc *sc, int if_id);
|
||||
void ath_bstuck_process(struct ath_softc *sc);
|
||||
void ath_beacon_tasklet(struct ath_softc *sc, int *needmark);
|
||||
void ath_beacon_free(struct ath_softc *sc);
|
||||
void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp);
|
||||
void ath_beacon_sync(struct ath_softc *sc, int if_id);
|
||||
void ath_update_beacon_info(struct ath_softc *sc, int avgbrssi);
|
||||
void ath_get_beaconconfig(struct ath_softc *sc,
|
||||
int if_id,
|
||||
struct ath_beacon_config *conf);
|
||||
int ath_update_beacon(struct ath_softc *sc,
|
||||
int if_id,
|
||||
struct ath_beacon_offset *bo,
|
||||
struct sk_buff *skb,
|
||||
int mcast);
|
||||
/********/
|
||||
/* VAPs */
|
||||
/********/
|
||||
@ -774,10 +750,8 @@ struct ath_vap {
|
||||
struct ieee80211_vif *av_if_data;
|
||||
enum ath9k_opmode av_opmode; /* VAP operational mode */
|
||||
struct ath_buf *av_bcbuf; /* beacon buffer */
|
||||
struct ath_beacon_offset av_boff; /* dynamic update state */
|
||||
struct ath_tx_control av_btxctl; /* txctl information for beacon */
|
||||
int av_bslot; /* beacon slot index */
|
||||
struct ath_txq av_mcastq; /* multicast transmit queue */
|
||||
struct ath_vap_config av_config;/* vap configuration parameters*/
|
||||
struct ath_rate_node *rc_node;
|
||||
};
|
||||
@ -789,7 +763,6 @@ int ath_vap_attach(struct ath_softc *sc,
|
||||
int ath_vap_detach(struct ath_softc *sc, int if_id);
|
||||
int ath_vap_config(struct ath_softc *sc,
|
||||
int if_id, struct ath_vap_config *if_config);
|
||||
int ath_vap_listen(struct ath_softc *sc, int if_id);
|
||||
|
||||
/*********************/
|
||||
/* Antenna diversity */
|
||||
@ -829,6 +802,27 @@ void ath_slow_ant_div(struct ath_antdiv *antdiv,
|
||||
struct ath_rx_status *rx_stats);
|
||||
void ath_setdefantenna(void *sc, u32 antenna);
|
||||
|
||||
/********************/
|
||||
/* LED Control */
|
||||
/********************/
|
||||
|
||||
#define ATH_LED_PIN 1
|
||||
|
||||
enum ath_led_type {
|
||||
ATH_LED_RADIO,
|
||||
ATH_LED_ASSOC,
|
||||
ATH_LED_TX,
|
||||
ATH_LED_RX
|
||||
};
|
||||
|
||||
struct ath_led {
|
||||
struct ath_softc *sc;
|
||||
struct led_classdev led_cdev;
|
||||
enum ath_led_type led_type;
|
||||
char name[32];
|
||||
bool registered;
|
||||
};
|
||||
|
||||
/********************/
|
||||
/* Main driver core */
|
||||
/********************/
|
||||
@ -841,11 +835,7 @@ void ath_setdefantenna(void *sc, u32 antenna);
|
||||
#define ATH_DEFAULT_NOISE_FLOOR -95
|
||||
#define ATH_REGCLASSIDS_MAX 10
|
||||
#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
|
||||
#define ATH_PREAMBLE_SHORT (1<<0)
|
||||
#define ATH_PROTECT_ENABLE (1<<1)
|
||||
#define ATH_MAX_SW_RETRIES 10
|
||||
/* Num farmes difference in tx to flip default recv */
|
||||
#define ATH_ANTENNA_DIFF 2
|
||||
#define ATH_CHAN_MAX 255
|
||||
#define IEEE80211_WEP_NKID 4 /* number of key ids */
|
||||
#define IEEE80211_RATE_VAL 0x7f
|
||||
@ -859,9 +849,7 @@ void ath_setdefantenna(void *sc, u32 antenna);
|
||||
*/
|
||||
#define ATH_KEYMAX 128 /* max key cache size we handle */
|
||||
|
||||
#define RESET_RETRY_TXQ 0x00000001
|
||||
#define ATH_IF_ID_ANY 0xff
|
||||
|
||||
#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
|
||||
|
||||
#define RSSI_LPF_THRESHOLD -20
|
||||
@ -907,60 +895,61 @@ struct ath_ht_info {
|
||||
u8 ext_chan_offset;
|
||||
};
|
||||
|
||||
#define SC_OP_INVALID BIT(0)
|
||||
#define SC_OP_BEACONS BIT(1)
|
||||
#define SC_OP_RXAGGR BIT(2)
|
||||
#define SC_OP_TXAGGR BIT(3)
|
||||
#define SC_OP_CHAINMASK_UPDATE BIT(4)
|
||||
#define SC_OP_FULL_RESET BIT(5)
|
||||
#define SC_OP_NO_RESET BIT(6)
|
||||
#define SC_OP_PREAMBLE_SHORT BIT(7)
|
||||
#define SC_OP_PROTECT_ENABLE BIT(8)
|
||||
#define SC_OP_RXFLUSH BIT(9)
|
||||
#define SC_OP_LED_ASSOCIATED BIT(10)
|
||||
|
||||
struct ath_softc {
|
||||
struct ieee80211_hw *hw;
|
||||
struct pci_dev *pdev;
|
||||
void __iomem *mem;
|
||||
struct tasklet_struct intr_tq;
|
||||
struct tasklet_struct bcon_tasklet;
|
||||
struct ath_config sc_config; /* load-time parameters */
|
||||
int sc_debug;
|
||||
struct ath_config sc_config;
|
||||
struct ath_hal *sc_ah;
|
||||
struct ath_rate_softc *sc_rc; /* tx rate control support */
|
||||
u32 sc_intrstatus;
|
||||
enum ath9k_opmode sc_opmode; /* current operating mode */
|
||||
struct ath_rate_softc *sc_rc;
|
||||
void __iomem *mem;
|
||||
|
||||
u8 sc_invalid; /* being detached */
|
||||
u8 sc_beacons; /* beacons running */
|
||||
u8 sc_scanning; /* scanning active */
|
||||
u8 sc_txaggr; /* enable 11n tx aggregation */
|
||||
u8 sc_rxaggr; /* enable 11n rx aggregation */
|
||||
u8 sc_update_chainmask; /* change chain mask */
|
||||
u8 sc_full_reset; /* force full reset */
|
||||
enum wireless_mode sc_curmode; /* current phy mode */
|
||||
u16 sc_curtxpow;
|
||||
u16 sc_curaid;
|
||||
u8 sc_curbssid[ETH_ALEN];
|
||||
u8 sc_myaddr[ETH_ALEN];
|
||||
enum PROT_MODE sc_protmode;
|
||||
u8 sc_mcastantenna;
|
||||
u8 sc_txantenna; /* data tx antenna (fixed or auto) */
|
||||
u8 sc_nbcnvaps; /* # of vaps sending beacons */
|
||||
u16 sc_nvaps; /* # of active virtual ap's */
|
||||
struct ath_vap *sc_vaps[ATH_BCBUF];
|
||||
enum ath9k_int sc_imask;
|
||||
u8 sc_bssidmask[ETH_ALEN];
|
||||
u8 sc_defant; /* current default antenna */
|
||||
u8 sc_rxotherant; /* rx's on non-default antenna */
|
||||
|
||||
int sc_debug;
|
||||
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;
|
||||
u8 sc_noreset;
|
||||
int sc_bslot[ATH_BCBUF];
|
||||
u8 sc_tx_chainmask;
|
||||
u8 sc_rx_chainmask;
|
||||
enum ath9k_int sc_imask;
|
||||
enum wireless_mode sc_curmode; /* current phy mode */
|
||||
enum PROT_MODE sc_protmode;
|
||||
|
||||
u8 sc_nbcnvaps; /* # of vaps sending beacons */
|
||||
u16 sc_nvaps; /* # of active virtual ap's */
|
||||
struct ath_vap *sc_vaps[ATH_BCBUF];
|
||||
|
||||
u8 sc_mcastantenna;
|
||||
u8 sc_defant; /* current default antenna */
|
||||
u8 sc_rxotherant; /* rx's on non-default antenna */
|
||||
|
||||
struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */
|
||||
struct list_head node_list;
|
||||
struct ath_ht_info sc_ht_info;
|
||||
int16_t sc_noise_floor; /* signal noise floor in dBm */
|
||||
enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
|
||||
u8 sc_tx_chainmask;
|
||||
u8 sc_rx_chainmask;
|
||||
u8 sc_rxchaindetect_ref;
|
||||
u8 sc_rxchaindetect_thresh5GHz;
|
||||
u8 sc_rxchaindetect_thresh2GHz;
|
||||
u8 sc_rxchaindetect_delta5GHz;
|
||||
u8 sc_rxchaindetect_delta2GHz;
|
||||
u32 sc_rtsaggrlimit; /* Chipset specific aggr limit */
|
||||
u32 sc_flags;
|
||||
|
||||
#ifdef CONFIG_SLOW_ANT_DIV
|
||||
struct ath_antdiv sc_antdiv;
|
||||
#endif
|
||||
@ -981,8 +970,6 @@ struct ath_softc {
|
||||
struct ath_descdma sc_rxdma;
|
||||
int sc_rxbufsize; /* rx size based on mtu */
|
||||
u32 *sc_rxlink; /* link ptr in last RX desc */
|
||||
u32 sc_rxflush; /* rx flush in progress */
|
||||
u64 sc_lastrx; /* tsf of last rx'd frame */
|
||||
|
||||
/* TX */
|
||||
struct list_head sc_txbuf;
|
||||
@ -991,7 +978,7 @@ struct ath_softc {
|
||||
u32 sc_txqsetup;
|
||||
u32 sc_txintrperiod; /* tx interrupt batching */
|
||||
int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME AC -> h/w qnum */
|
||||
u32 sc_ant_tx[8]; /* recent tx frames/antenna */
|
||||
u16 seq_no; /* TX sequence number */
|
||||
|
||||
/* Beacon */
|
||||
struct ath9k_tx_queue_info sc_beacon_qi;
|
||||
@ -1015,7 +1002,6 @@ struct ath_softc {
|
||||
/* Channel, Band */
|
||||
struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX];
|
||||
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
|
||||
struct ath9k_channel sc_curchan;
|
||||
|
||||
/* Locks */
|
||||
spinlock_t sc_rxflushlock;
|
||||
@ -1023,6 +1009,12 @@ struct ath_softc {
|
||||
spinlock_t sc_txbuflock;
|
||||
spinlock_t sc_resetlock;
|
||||
spinlock_t node_lock;
|
||||
|
||||
/* LEDs */
|
||||
struct ath_led radio_led;
|
||||
struct ath_led assoc_led;
|
||||
struct ath_led tx_led;
|
||||
struct ath_led rx_led;
|
||||
};
|
||||
|
||||
int ath_init(u16 devid, struct ath_softc *sc);
|
||||
@ -1030,14 +1022,8 @@ void ath_deinit(struct ath_softc *sc);
|
||||
int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan);
|
||||
int ath_suspend(struct ath_softc *sc);
|
||||
irqreturn_t ath_isr(int irq, void *dev);
|
||||
int ath_reset(struct ath_softc *sc);
|
||||
void ath_scan_start(struct ath_softc *sc);
|
||||
void ath_scan_end(struct ath_softc *sc);
|
||||
int ath_reset(struct ath_softc *sc, bool retry_tx);
|
||||
int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan);
|
||||
void ath_setup_rate(struct ath_softc *sc,
|
||||
enum wireless_mode wMode,
|
||||
enum RATE_TYPE type,
|
||||
const struct ath9k_rate_table *rt);
|
||||
|
||||
/*********************/
|
||||
/* Utility Functions */
|
||||
@ -1056,17 +1042,5 @@ int ath_cabq_update(struct ath_softc *);
|
||||
void ath_get_currentCountry(struct ath_softc *sc,
|
||||
struct ath9k_country_entry *ctry);
|
||||
u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp);
|
||||
void ath_internal_reset(struct ath_softc *sc);
|
||||
u32 ath_chan2flags(struct ieee80211_channel *chan, struct ath_softc *sc);
|
||||
dma_addr_t ath_skb_map_single(struct ath_softc *sc,
|
||||
struct sk_buff *skb,
|
||||
int direction,
|
||||
dma_addr_t *pa);
|
||||
void ath_skb_unmap_single(struct ath_softc *sc,
|
||||
struct sk_buff *skb,
|
||||
int direction,
|
||||
dma_addr_t *pa);
|
||||
void ath_mcast_merge(struct ath_softc *sc, u32 mfilt[2]);
|
||||
enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc);
|
||||
|
||||
#endif /* CORE_H */
|
||||
|
@ -85,29 +85,6 @@ static const struct hal_percal_data adc_init_dc_cal = {
|
||||
ath9k_hw_adc_dccal_calibrate
|
||||
};
|
||||
|
||||
static const struct ath_hal ar5416hal = {
|
||||
AR5416_MAGIC,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
CTRY_DEFAULT,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct ath9k_rate_table ar5416_11a_table = {
|
||||
8,
|
||||
{0},
|
||||
@ -371,7 +348,7 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah)
|
||||
ah->ah_config.intr_mitigation = 0;
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_override_ini(struct ath_hal *ah,
|
||||
static void ath9k_hw_override_ini(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
if (!AR_SREV_5416_V20_OR_LATER(ah)
|
||||
@ -381,7 +358,7 @@ static inline void ath9k_hw_override_ini(struct ath_hal *ah,
|
||||
REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_init_bb(struct ath_hal *ah,
|
||||
static void ath9k_hw_init_bb(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
u32 synthDelay;
|
||||
@ -397,7 +374,7 @@ static inline void ath9k_hw_init_bb(struct ath_hal *ah,
|
||||
udelay(synthDelay + BASE_ACTIVATE_DELAY);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_init_interrupt_masks(struct ath_hal *ah,
|
||||
static void ath9k_hw_init_interrupt_masks(struct ath_hal *ah,
|
||||
enum ath9k_opmode opmode)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
@ -428,7 +405,7 @@ static inline void ath9k_hw_init_interrupt_masks(struct ath_hal *ah,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_init_qos(struct ath_hal *ah)
|
||||
static void ath9k_hw_init_qos(struct ath_hal *ah)
|
||||
{
|
||||
REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
|
||||
REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
|
||||
@ -523,7 +500,7 @@ static inline bool ath9k_hw_nvram_read(struct ath_hal *ah,
|
||||
return ath9k_hw_eeprom_read(ah, off, data);
|
||||
}
|
||||
|
||||
static inline bool ath9k_hw_fill_eeprom(struct ath_hal *ah)
|
||||
static bool ath9k_hw_fill_eeprom(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ar5416_eeprom *eep = &ahp->ah_eeprom;
|
||||
@ -790,7 +767,7 @@ ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_check_eeprom(struct ath_hal *ah)
|
||||
static int ath9k_hw_check_eeprom(struct ath_hal *ah)
|
||||
{
|
||||
u32 sum = 0, el;
|
||||
u16 *eepdata;
|
||||
@ -1196,11 +1173,12 @@ static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid,
|
||||
|
||||
ah = &ahp->ah;
|
||||
|
||||
memcpy(&ahp->ah, &ar5416hal, sizeof(struct ath_hal));
|
||||
|
||||
ah->ah_sc = sc;
|
||||
ah->ah_sh = mem;
|
||||
|
||||
ah->ah_magic = AR5416_MAGIC;
|
||||
ah->ah_countryCode = CTRY_DEFAULT;
|
||||
|
||||
ah->ah_devid = devid;
|
||||
ah->ah_subvendorid = 0;
|
||||
|
||||
@ -1294,7 +1272,7 @@ u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp,
|
||||
}
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_get_radiorev(struct ath_hal *ah)
|
||||
static int ath9k_hw_get_radiorev(struct ath_hal *ah)
|
||||
{
|
||||
u32 val;
|
||||
int i;
|
||||
@ -1307,7 +1285,7 @@ static inline int ath9k_hw_get_radiorev(struct ath_hal *ah)
|
||||
return ath9k_hw_reverse_bits(val, 8);
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_init_macaddr(struct ath_hal *ah)
|
||||
static int ath9k_hw_init_macaddr(struct ath_hal *ah)
|
||||
{
|
||||
u32 sum;
|
||||
int i;
|
||||
@ -1389,7 +1367,7 @@ static u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah,
|
||||
return spur_val;
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_rfattach(struct ath_hal *ah)
|
||||
static int ath9k_hw_rfattach(struct ath_hal *ah)
|
||||
{
|
||||
bool rfStatus = false;
|
||||
int ecode = 0;
|
||||
@ -1434,7 +1412,7 @@ static int ath9k_hw_rf_claim(struct ath_hal *ah)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_init_pll(struct ath_hal *ah,
|
||||
static void ath9k_hw_init_pll(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
u32 pll;
|
||||
@ -1553,7 +1531,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hal *ah, int opmode)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
static void
|
||||
ath9k_hw_set_rfmode(struct ath_hal *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
u32 rfMode = 0;
|
||||
@ -1623,7 +1601,7 @@ static bool ath9k_hw_set_reset(struct ath_hal *ah, int type)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool ath9k_hw_set_reset_power_on(struct ath_hal *ah)
|
||||
static bool ath9k_hw_set_reset_power_on(struct ath_hal *ah)
|
||||
{
|
||||
REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
|
||||
AR_RTC_FORCE_WAKE_ON_INT);
|
||||
@ -1664,7 +1642,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hal *ah,
|
||||
}
|
||||
}
|
||||
|
||||
static inline
|
||||
static
|
||||
struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
@ -2098,7 +2076,7 @@ static void ath9k_hw_ani_attach(struct ath_hal *ah)
|
||||
ahp->ah_procPhyErr |= HAL_PROCESS_ANI;
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_ani_setup(struct ath_hal *ah)
|
||||
static void ath9k_hw_ani_setup(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
int i;
|
||||
@ -2822,32 +2800,11 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hal *ah,
|
||||
}
|
||||
}
|
||||
|
||||
static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
|
||||
enum ath9k_gpio_output_mux_type
|
||||
halSignalType)
|
||||
void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
|
||||
u32 ah_signal_type)
|
||||
{
|
||||
u32 ah_signal_type;
|
||||
u32 gpio_shift;
|
||||
|
||||
static u32 MuxSignalConversionTable[] = {
|
||||
|
||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
|
||||
|
||||
AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
|
||||
|
||||
AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
|
||||
|
||||
AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
|
||||
|
||||
AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
|
||||
};
|
||||
|
||||
if ((halSignalType >= 0)
|
||||
&& (halSignalType < ARRAY_SIZE(MuxSignalConversionTable)))
|
||||
ah_signal_type = MuxSignalConversionTable[halSignalType];
|
||||
else
|
||||
return false;
|
||||
|
||||
ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
|
||||
|
||||
gpio_shift = 2 * gpio;
|
||||
@ -2856,16 +2813,12 @@ static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
|
||||
AR_GPIO_OE_OUT,
|
||||
(AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
|
||||
(AR_GPIO_OE_OUT_DRV << gpio_shift));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio,
|
||||
u32 val)
|
||||
void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val)
|
||||
{
|
||||
REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
|
||||
AR_GPIO_BIT(gpio));
|
||||
return true;
|
||||
}
|
||||
|
||||
static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
|
||||
@ -2883,7 +2836,7 @@ static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
|
||||
}
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_post_attach(struct ath_hal *ah)
|
||||
static int ath9k_hw_post_attach(struct ath_hal *ah)
|
||||
{
|
||||
int ecode;
|
||||
|
||||
@ -3595,7 +3548,7 @@ static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin,
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
static void
|
||||
ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct cal_data_per_freq *pRawDataSet,
|
||||
@ -3777,7 +3730,7 @@ ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah,
|
||||
return;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static bool
|
||||
ath9k_hw_set_power_cal_table(struct ath_hal *ah,
|
||||
struct ar5416_eeprom *pEepData,
|
||||
struct ath9k_channel *chan,
|
||||
@ -3980,7 +3933,7 @@ void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
static void
|
||||
ath9k_hw_get_legacy_target_powers(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct cal_target_power_leg *powInfo,
|
||||
@ -4046,7 +3999,7 @@ ath9k_hw_get_legacy_target_powers(struct ath_hal *ah,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
static void
|
||||
ath9k_hw_get_target_powers(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct cal_target_power_ht *powInfo,
|
||||
@ -4113,7 +4066,7 @@ ath9k_hw_get_target_powers(struct ath_hal *ah,
|
||||
}
|
||||
}
|
||||
|
||||
static inline u16
|
||||
static u16
|
||||
ath9k_hw_get_max_edge_power(u16 freq,
|
||||
struct cal_ctl_edges *pRdEdgesPower,
|
||||
bool is2GHz)
|
||||
@ -4143,7 +4096,7 @@ ath9k_hw_get_max_edge_power(u16 freq,
|
||||
return twiceMaxEdgePower;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static bool
|
||||
ath9k_hw_set_power_per_rate_table(struct ath_hal *ah,
|
||||
struct ar5416_eeprom *pEepData,
|
||||
struct ath9k_channel *chan,
|
||||
@ -5122,7 +5075,7 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah,
|
||||
REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_init_chain_masks(struct ath_hal *ah)
|
||||
static void ath9k_hw_init_chain_masks(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
int rx_chainmask, tx_chainmask;
|
||||
@ -5326,7 +5279,7 @@ bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_init_user_settings(struct ath_hal *ah)
|
||||
static void ath9k_hw_init_user_settings(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
|
||||
@ -5345,7 +5298,7 @@ static inline void ath9k_hw_init_user_settings(struct ath_hal *ah)
|
||||
ath9k_hw_set_global_txtimeout(ah, ahp->ah_globaltxtimeout);
|
||||
}
|
||||
|
||||
static inline int
|
||||
static int
|
||||
ath9k_hw_process_ini(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
enum ath9k_ht_macmode macmode)
|
||||
@ -5476,7 +5429,7 @@ ath9k_hw_process_ini(struct ath_hal *ah,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_setup_calibration(struct ath_hal *ah,
|
||||
static void ath9k_hw_setup_calibration(struct ath_hal *ah,
|
||||
struct hal_cal_list *currCal)
|
||||
{
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
|
||||
@ -5512,7 +5465,7 @@ static inline void ath9k_hw_setup_calibration(struct ath_hal *ah,
|
||||
AR_PHY_TIMING_CTRL4_DO_CAL);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_reset_calibration(struct ath_hal *ah,
|
||||
static void ath9k_hw_reset_calibration(struct ath_hal *ah,
|
||||
struct hal_cal_list *currCal)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
@ -5532,7 +5485,7 @@ static inline void ath9k_hw_reset_calibration(struct ath_hal *ah,
|
||||
ahp->ah_CalSamples = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
static void
|
||||
ath9k_hw_per_calibration(struct ath_hal *ah,
|
||||
struct ath9k_channel *ichan,
|
||||
u8 rxchainmask,
|
||||
@ -5622,7 +5575,7 @@ static inline bool ath9k_hw_run_init_cals(struct ath_hal *ah,
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static bool
|
||||
ath9k_hw_channel_change(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
enum ath9k_ht_macmode macmode)
|
||||
@ -5799,7 +5752,7 @@ static bool ath9k_hw_iscal_supported(struct ath_hal *ah,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline bool ath9k_hw_init_cal(struct ath_hal *ah,
|
||||
static bool ath9k_hw_init_cal(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
@ -5861,7 +5814,7 @@ static inline bool ath9k_hw_init_cal(struct ath_hal *ah,
|
||||
}
|
||||
|
||||
|
||||
bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
|
||||
bool ath9k_hw_reset(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
enum ath9k_ht_macmode macmode,
|
||||
u8 txchainmask, u8 rxchainmask,
|
||||
@ -5945,7 +5898,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
|
||||
else
|
||||
ath9k_hw_set_gpio(ah, 9, 1);
|
||||
}
|
||||
ath9k_hw_cfg_output(ah, 9, ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
ath9k_hw_cfg_output(ah, 9, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
}
|
||||
|
||||
ecode = ath9k_hw_process_ini(ah, chan, macmode);
|
||||
@ -5975,7 +5928,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
|
||||
| (ah->ah_config.
|
||||
ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
|
||||
| ahp->ah_staId1Defaults);
|
||||
ath9k_hw_set_operating_mode(ah, opmode);
|
||||
ath9k_hw_set_operating_mode(ah, ah->ah_opmode);
|
||||
|
||||
REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask));
|
||||
REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4));
|
||||
@ -6005,13 +5958,11 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
|
||||
for (i = 0; i < ah->ah_caps.total_queues; i++)
|
||||
ath9k_hw_resettxqueue(ah, i);
|
||||
|
||||
ath9k_hw_init_interrupt_masks(ah, opmode);
|
||||
ath9k_hw_init_interrupt_masks(ah, ah->ah_opmode);
|
||||
ath9k_hw_init_qos(ah);
|
||||
|
||||
ath9k_hw_init_user_settings(ah);
|
||||
|
||||
ah->ah_opmode = opmode;
|
||||
|
||||
REG_WRITE(ah, AR_STA_ID1,
|
||||
REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
|
||||
|
||||
@ -7678,8 +7629,7 @@ bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q)
|
||||
REG_WRITE(ah, AR_DRETRY_LIMIT(q),
|
||||
SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH)
|
||||
| SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG)
|
||||
| SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)
|
||||
);
|
||||
| SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
|
||||
|
||||
REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
|
||||
REG_WRITE(ah, AR_DMISC(q),
|
||||
@ -8324,15 +8274,7 @@ struct ath_hal *ath9k_hw_attach(u16 devid,
|
||||
*error = -ENXIO;
|
||||
break;
|
||||
}
|
||||
if (ah != NULL) {
|
||||
ah->ah_devid = ah->ah_devid;
|
||||
ah->ah_subvendorid = ah->ah_subvendorid;
|
||||
ah->ah_macVersion = ah->ah_macVersion;
|
||||
ah->ah_macRev = ah->ah_macRev;
|
||||
ah->ah_phyRev = ah->ah_phyRev;
|
||||
ah->ah_analog5GhzRev = ah->ah_analog5GhzRev;
|
||||
ah->ah_analog2GhzRev = ah->ah_analog2GhzRev;
|
||||
}
|
||||
|
||||
return ah;
|
||||
}
|
||||
|
||||
|
@ -314,9 +314,6 @@ struct ar5416_desc {
|
||||
#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \
|
||||
MS(ads->ds_rxstatus0, AR_RxRate) : \
|
||||
(ads->ds_rxstatus3 >> 2) & 0xFF)
|
||||
#define RXSTATUS_DUPLICATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \
|
||||
MS(ads->ds_rxstatus3, AR_Parallel40) : \
|
||||
(ads->ds_rxstatus3 >> 10) & 0x1)
|
||||
|
||||
#define set11nTries(_series, _index) \
|
||||
(SM((_series)[_index].Tries, AR_XmitDataTries##_index))
|
||||
@ -346,9 +343,6 @@ struct ar5416_desc {
|
||||
#define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1)
|
||||
#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD
|
||||
|
||||
#define NUM_CORNER_FIX_BITS_2133 7
|
||||
#define CCK_OFDM_GAIN_DELTA 15
|
||||
|
||||
struct ar5416AniState {
|
||||
struct ath9k_channel c;
|
||||
u8 noiseImmunityLevel;
|
||||
@ -377,9 +371,6 @@ struct ar5416AniState {
|
||||
};
|
||||
|
||||
#define HAL_PROCESS_ANI 0x00000001
|
||||
#define HAL_RADAR_EN 0x80000000
|
||||
#define HAL_AR_EN 0x40000000
|
||||
|
||||
#define DO_ANI(ah) \
|
||||
((AH5416(ah)->ah_procPhyErr & HAL_PROCESS_ANI))
|
||||
|
||||
@ -425,7 +416,6 @@ struct ar5416Stats {
|
||||
#define AR5416_EEP_MINOR_VER_7 0x7
|
||||
#define AR5416_EEP_MINOR_VER_9 0x9
|
||||
|
||||
#define AR5416_EEP_START_LOC 256
|
||||
#define AR5416_NUM_5G_CAL_PIERS 8
|
||||
#define AR5416_NUM_2G_CAL_PIERS 4
|
||||
#define AR5416_NUM_5G_20_TARGET_POWERS 8
|
||||
@ -441,25 +431,10 @@ struct ar5416Stats {
|
||||
#define AR5416_EEPROM_MODAL_SPURS 5
|
||||
#define AR5416_MAX_RATE_POWER 63
|
||||
#define AR5416_NUM_PDADC_VALUES 128
|
||||
#define AR5416_NUM_RATES 16
|
||||
#define AR5416_BCHAN_UNUSED 0xFF
|
||||
#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
|
||||
#define AR5416_EEPMISC_BIG_ENDIAN 0x01
|
||||
#define AR5416_MAX_CHAINS 3
|
||||
#define AR5416_ANT_16S 25
|
||||
|
||||
#define AR5416_NUM_ANT_CHAIN_FIELDS 7
|
||||
#define AR5416_NUM_ANT_COMMON_FIELDS 4
|
||||
#define AR5416_SIZE_ANT_CHAIN_FIELD 3
|
||||
#define AR5416_SIZE_ANT_COMMON_FIELD 4
|
||||
#define AR5416_ANT_CHAIN_MASK 0x7
|
||||
#define AR5416_ANT_COMMON_MASK 0xf
|
||||
#define AR5416_CHAIN_0_IDX 0
|
||||
#define AR5416_CHAIN_1_IDX 1
|
||||
#define AR5416_CHAIN_2_IDX 2
|
||||
|
||||
#define AR5416_PWR_TABLE_OFFSET -5
|
||||
#define AR5416_LEGACY_CHAINMASK 1
|
||||
|
||||
enum eeprom_param {
|
||||
EEP_NFTHRESH_5,
|
||||
@ -696,25 +671,29 @@ struct hal_cal_list {
|
||||
struct ath_hal_5416 {
|
||||
struct ath_hal ah;
|
||||
struct ar5416_eeprom ah_eeprom;
|
||||
struct ar5416Stats ah_stats;
|
||||
struct ath9k_tx_queue_info ah_txq[ATH9K_NUM_TX_QUEUES];
|
||||
void __iomem *ah_cal_mem;
|
||||
|
||||
u8 ah_macaddr[ETH_ALEN];
|
||||
u8 ah_bssid[ETH_ALEN];
|
||||
u8 ah_bssidmask[ETH_ALEN];
|
||||
u16 ah_assocId;
|
||||
|
||||
int16_t ah_curchanRadIndex;
|
||||
u32 ah_maskReg;
|
||||
struct ar5416Stats ah_stats;
|
||||
u32 ah_txDescMask;
|
||||
u32 ah_txOkInterruptMask;
|
||||
u32 ah_txErrInterruptMask;
|
||||
u32 ah_txDescInterruptMask;
|
||||
u32 ah_txEolInterruptMask;
|
||||
u32 ah_txUrnInterruptMask;
|
||||
struct ath9k_tx_queue_info ah_txq[ATH9K_NUM_TX_QUEUES];
|
||||
enum ath9k_power_mode ah_powerMode;
|
||||
bool ah_chipFullSleep;
|
||||
u32 ah_atimWindow;
|
||||
enum ath9k_ant_setting ah_diversityControl;
|
||||
u16 ah_antennaSwitchSwap;
|
||||
enum ath9k_power_mode ah_powerMode;
|
||||
enum ath9k_ant_setting ah_diversityControl;
|
||||
|
||||
/* Calibration */
|
||||
enum hal_cal_types ah_suppCals;
|
||||
struct hal_cal_list ah_iqCalData;
|
||||
struct hal_cal_list ah_adcGainCalData;
|
||||
@ -751,16 +730,16 @@ struct ath_hal_5416 {
|
||||
int32_t sign[AR5416_MAX_CHAINS];
|
||||
} ah_Meas3;
|
||||
u16 ah_CalSamples;
|
||||
u32 ah_tx6PowerInHalfDbm;
|
||||
|
||||
u32 ah_staId1Defaults;
|
||||
u32 ah_miscMode;
|
||||
bool ah_tpcEnabled;
|
||||
u32 ah_beaconInterval;
|
||||
enum {
|
||||
AUTO_32KHZ,
|
||||
USE_32KHZ,
|
||||
DONT_USE_32KHZ,
|
||||
} ah_enable32kHzClock;
|
||||
|
||||
/* RF */
|
||||
u32 *ah_analogBank0Data;
|
||||
u32 *ah_analogBank1Data;
|
||||
u32 *ah_analogBank2Data;
|
||||
@ -770,8 +749,9 @@ struct ath_hal_5416 {
|
||||
u32 *ah_analogBank7Data;
|
||||
u32 *ah_addac5416_21;
|
||||
u32 *ah_bank6Temp;
|
||||
u32 ah_ofdmTxPower;
|
||||
|
||||
int16_t ah_txPowerIndexOffset;
|
||||
u32 ah_beaconInterval;
|
||||
u32 ah_slottime;
|
||||
u32 ah_acktimeout;
|
||||
u32 ah_ctstimeout;
|
||||
@ -780,7 +760,8 @@ struct ath_hal_5416 {
|
||||
u32 ah_gpioSelect;
|
||||
u32 ah_polarity;
|
||||
u32 ah_gpioBit;
|
||||
bool ah_eepEnabled;
|
||||
|
||||
/* ANI */
|
||||
u32 ah_procPhyErr;
|
||||
bool ah_hasHwPhyCounters;
|
||||
u32 ah_aniPeriod;
|
||||
@ -790,18 +771,14 @@ struct ath_hal_5416 {
|
||||
int ah_coarseHigh[5];
|
||||
int ah_coarseLow[5];
|
||||
int ah_firpwr[5];
|
||||
u16 ah_ratesArray[16];
|
||||
enum ath9k_ani_cmd ah_ani_function;
|
||||
|
||||
u32 ah_intrTxqs;
|
||||
bool ah_intrMitigation;
|
||||
u32 ah_cycleCount;
|
||||
u32 ah_ctlBusy;
|
||||
u32 ah_extBusy;
|
||||
enum ath9k_ht_extprotspacing ah_extprotspacing;
|
||||
u8 ah_txchainmask;
|
||||
u8 ah_rxchainmask;
|
||||
int ah_hwp;
|
||||
void __iomem *ah_cal_mem;
|
||||
enum ath9k_ani_cmd ah_ani_function;
|
||||
|
||||
struct ar5416IniArray ah_iniModes;
|
||||
struct ar5416IniArray ah_iniCommon;
|
||||
struct ar5416IniArray ah_iniBank0;
|
||||
@ -820,10 +797,6 @@ struct ath_hal_5416 {
|
||||
|
||||
#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
|
||||
|
||||
#define IS_5416_EMU(ah) \
|
||||
((ah->ah_devid == AR5416_DEVID_EMU) || \
|
||||
(ah->ah_devid == AR5416_DEVID_EMU_PCIE))
|
||||
|
||||
#define ar5416RfDetach(ah) do { \
|
||||
if (AH5416(ah)->ah_rfHal.rfDetach != NULL) \
|
||||
AH5416(ah)->ah_rfHal.rfDetach(ah); \
|
||||
@ -852,10 +825,6 @@ struct ath_hal_5416 {
|
||||
#define COEF_SCALE_S 24
|
||||
#define HT40_CHANNEL_CENTER_SHIFT 10
|
||||
|
||||
#define ar5416CheckOpMode(_opmode) \
|
||||
((_opmode == ATH9K_M_STA) || (_opmode == ATH9K_M_IBSS) || \
|
||||
(_opmode == ATH9K_M_HOSTAP) || (_opmode == ATH9K_M_MONITOR))
|
||||
|
||||
#define AR5416_EEPROM_MAGIC_OFFSET 0x0
|
||||
|
||||
#define AR5416_EEPROM_S 2
|
||||
@ -871,11 +840,6 @@ struct ath_hal_5416 {
|
||||
(((_txchainmask >> 2) & 1) + \
|
||||
((_txchainmask >> 1) & 1) + (_txchainmask & 1))
|
||||
|
||||
#define IS_EEP_MINOR_V3(_ahp) \
|
||||
(ath9k_hw_get_eeprom((_ahp), EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_3)
|
||||
|
||||
#define FIXED_CCA_THRESHOLD 15
|
||||
|
||||
#ifdef __BIG_ENDIAN
|
||||
#define AR5416_EEPROM_MAGIC 0x5aa5
|
||||
#else
|
||||
@ -910,8 +874,6 @@ struct ath_hal_5416 {
|
||||
#define AR_GPIOD_MASK 0x00001FFF
|
||||
#define AR_GPIO_BIT(_gpio) (1 << (_gpio))
|
||||
|
||||
#define MAX_ANALOG_START 319
|
||||
|
||||
#define HAL_EP_RND(x, mul) \
|
||||
((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
|
||||
#define BEACON_RSSI(ahp) \
|
||||
@ -923,8 +885,6 @@ struct ath_hal_5416 {
|
||||
#define AH_TIMEOUT 100000
|
||||
#define AH_TIME_QUANTUM 10
|
||||
|
||||
#define IS(_c, _f) (((_c)->channelFlags & _f) || 0)
|
||||
|
||||
#define AR_KEYTABLE_SIZE 128
|
||||
#define POWER_UP_TIME 200000
|
||||
|
||||
|
@ -22,8 +22,6 @@
|
||||
#define ATH_PCI_VERSION "0.1"
|
||||
|
||||
#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
|
||||
#define IEEE80211_ACTION_CAT_HT 7
|
||||
#define IEEE80211_ACTION_HT_TXCHWIDTH 0
|
||||
|
||||
static char *dev_info = "ath9k";
|
||||
|
||||
@ -212,21 +210,16 @@ static int ath_key_config(struct ath_softc *sc,
|
||||
|
||||
static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
|
||||
{
|
||||
#define ATH_MAX_NUM_KEYS 4
|
||||
int freeslot;
|
||||
|
||||
freeslot = (key->keyidx >= ATH_MAX_NUM_KEYS) ? 1 : 0;
|
||||
freeslot = (key->keyidx >= 4) ? 1 : 0;
|
||||
ath_key_reset(sc, key->keyidx, freeslot);
|
||||
#undef ATH_MAX_NUM_KEYS
|
||||
}
|
||||
|
||||
static void setup_ht_cap(struct ieee80211_ht_info *ht_info)
|
||||
{
|
||||
/* Until mac80211 includes these fields */
|
||||
|
||||
#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
|
||||
#define IEEE80211_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */
|
||||
#define IEEE80211_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */
|
||||
#define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */
|
||||
#define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */
|
||||
|
||||
ht_info->ht_supported = 1;
|
||||
ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH
|
||||
@ -234,8 +227,8 @@ static void setup_ht_cap(struct ieee80211_ht_info *ht_info)
|
||||
|(u16)IEEE80211_HT_CAP_SGI_40
|
||||
|(u16)IEEE80211_HT_CAP_DSSSCCK40;
|
||||
|
||||
ht_info->ampdu_factor = IEEE80211_HT_CAP_MAXRXAMPDU_65536;
|
||||
ht_info->ampdu_density = IEEE80211_HT_CAP_MPDUDENSITY_8;
|
||||
ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
|
||||
ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
|
||||
/* setup supported mcs set */
|
||||
memset(ht_info->supp_mcs_set, 0, 16);
|
||||
ht_info->supp_mcs_set[0] = 0xff;
|
||||
@ -368,6 +361,20 @@ static int ath9k_tx(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
int hdrlen, padsize;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
/*
|
||||
* As a temporary workaround, assign seq# here; this will likely need
|
||||
* to be cleaned up to work better with Beacon transmission and virtual
|
||||
* BSSes.
|
||||
*/
|
||||
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;
|
||||
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
|
||||
hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
|
||||
}
|
||||
|
||||
/* Add the padding after the header if this is not already done */
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
@ -426,10 +433,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
|
||||
case IEEE80211_IF_TYPE_IBSS:
|
||||
ic_opmode = ATH9K_M_IBSS;
|
||||
break;
|
||||
case IEEE80211_IF_TYPE_AP:
|
||||
ic_opmode = ATH9K_M_HOSTAP;
|
||||
break;
|
||||
default:
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"%s: Only STA and IBSS are supported currently\n",
|
||||
__func__);
|
||||
"%s: Interface type %d not yet supported\n",
|
||||
__func__, conf->type);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
@ -472,7 +482,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
|
||||
ath_rate_newstate(sc, avp);
|
||||
|
||||
/* Reclaim beacon resources */
|
||||
if (sc->sc_opmode == ATH9K_M_HOSTAP || sc->sc_opmode == ATH9K_M_IBSS) {
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
|
||||
sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
|
||||
ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
|
||||
ath_beacon_return(sc, avp);
|
||||
}
|
||||
@ -480,7 +491,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
|
||||
/* Set interrupt mask */
|
||||
sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
|
||||
ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL);
|
||||
sc->sc_beacons = 0;
|
||||
sc->sc_flags &= ~SC_OP_BEACONS;
|
||||
|
||||
error = ath_vap_detach(sc, 0);
|
||||
if (error)
|
||||
@ -529,6 +540,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_if_conf *conf)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ath_vap *avp;
|
||||
u32 rfilt = 0;
|
||||
int error, i;
|
||||
@ -541,6 +553,17 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* TODO: Need to decide which hw opmode to use for multi-interface
|
||||
* cases */
|
||||
if (vif->type == IEEE80211_IF_TYPE_AP &&
|
||||
ah->ah_opmode != ATH9K_M_HOSTAP) {
|
||||
ah->ah_opmode = ATH9K_M_HOSTAP;
|
||||
ath9k_hw_setopmode(ah);
|
||||
ath9k_hw_write_associd(ah, sc->sc_myaddr, 0);
|
||||
/* Request full reset to get hw opmode changed properly */
|
||||
sc->sc_flags |= SC_OP_FULL_RESET;
|
||||
}
|
||||
|
||||
if ((conf->changed & IEEE80211_IFCC_BSSID) &&
|
||||
!is_zero_ether_addr(conf->bssid)) {
|
||||
switch (vif->type) {
|
||||
@ -549,10 +572,6 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
|
||||
/* Update ratectrl about the new state */
|
||||
ath_rate_newstate(sc, avp);
|
||||
|
||||
/* Set rx filter */
|
||||
rfilt = ath_calcrxfilter(sc);
|
||||
ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
|
||||
|
||||
/* Set BSSID */
|
||||
memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN);
|
||||
sc->sc_curaid = 0;
|
||||
@ -585,7 +604,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
|
||||
print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
|
||||
|
||||
/* need to reconfigure the beacon */
|
||||
sc->sc_beacons = 0;
|
||||
sc->sc_flags &= ~SC_OP_BEACONS ;
|
||||
|
||||
break;
|
||||
default:
|
||||
@ -594,7 +613,8 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
if ((conf->changed & IEEE80211_IFCC_BEACON) &&
|
||||
(vif->type == IEEE80211_IF_TYPE_IBSS)) {
|
||||
((vif->type == IEEE80211_IF_TYPE_IBSS) ||
|
||||
(vif->type == IEEE80211_IF_TYPE_AP))) {
|
||||
/*
|
||||
* Allocate and setup the beacon frame.
|
||||
*
|
||||
@ -636,8 +656,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
|
||||
FIF_BCN_PRBRESP_PROMISC | \
|
||||
FIF_FCSFAIL)
|
||||
|
||||
/* Accept unicast, bcast and mcast frames */
|
||||
|
||||
/* FIXME: sc->sc_full_reset ? */
|
||||
static void ath9k_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
@ -645,16 +664,22 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
|
||||
struct dev_mc_list *mclist)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
u32 rfilt;
|
||||
|
||||
changed_flags &= SUPPORTED_FILTERS;
|
||||
*total_flags &= SUPPORTED_FILTERS;
|
||||
|
||||
sc->rx_filter = *total_flags;
|
||||
rfilt = ath_calcrxfilter(sc);
|
||||
ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
|
||||
|
||||
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
|
||||
if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
|
||||
ath_scan_start(sc);
|
||||
else
|
||||
ath_scan_end(sc);
|
||||
ath9k_hw_write_associd(sc->sc_ah, ath_bcast_mac, 0);
|
||||
}
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set HW RX filter: 0x%x\n",
|
||||
__func__, sc->rx_filter);
|
||||
}
|
||||
|
||||
static void ath9k_sta_notify(struct ieee80211_hw *hw,
|
||||
@ -831,7 +856,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
|
||||
|
||||
/* Configure the beacon */
|
||||
ath_beacon_config(sc, 0);
|
||||
sc->sc_beacons = 1;
|
||||
sc->sc_flags |= SC_OP_BEACONS;
|
||||
|
||||
/* Reset rssi stats */
|
||||
sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
|
||||
@ -894,9 +919,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
__func__,
|
||||
bss_conf->use_short_preamble);
|
||||
if (bss_conf->use_short_preamble)
|
||||
sc->sc_flags |= ATH_PREAMBLE_SHORT;
|
||||
sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
|
||||
else
|
||||
sc->sc_flags &= ~ATH_PREAMBLE_SHORT;
|
||||
sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
|
||||
@ -905,9 +930,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
bss_conf->use_cts_prot);
|
||||
if (bss_conf->use_cts_prot &&
|
||||
hw->conf.channel->band != IEEE80211_BAND_5GHZ)
|
||||
sc->sc_flags |= ATH_PROTECT_ENABLE;
|
||||
sc->sc_flags |= SC_OP_PROTECT_ENABLE;
|
||||
else
|
||||
sc->sc_flags &= ~ATH_PROTECT_ENABLE;
|
||||
sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_HT) {
|
||||
@ -1035,15 +1060,6 @@ void ath_get_beaconconfig(struct ath_softc *sc,
|
||||
conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
|
||||
}
|
||||
|
||||
int ath_update_beacon(struct ath_softc *sc,
|
||||
int if_id,
|
||||
struct ath_beacon_offset *bo,
|
||||
struct sk_buff *skb,
|
||||
int mcast)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
struct ath_xmit_status *tx_status, struct ath_node *an)
|
||||
{
|
||||
@ -1065,8 +1081,16 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
|
||||
tx_status->flags &= ~ATH_TX_BAR;
|
||||
}
|
||||
if (tx_status->flags)
|
||||
|
||||
if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) {
|
||||
if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
/* Frame was not ACKed, but an ACK was expected */
|
||||
tx_info->status.excessive_retries = 1;
|
||||
}
|
||||
} else {
|
||||
/* Frame was ACKed */
|
||||
tx_info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
}
|
||||
|
||||
tx_info->status.retry_count = tx_status->retries;
|
||||
|
||||
@ -1075,7 +1099,7 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE);
|
||||
}
|
||||
|
||||
int ath__rx_indicate(struct ath_softc *sc,
|
||||
int _ath_rx_indicate(struct ath_softc *sc,
|
||||
struct sk_buff *skb,
|
||||
struct ath_recv_status *status,
|
||||
u16 keyix)
|
||||
@ -1095,9 +1119,6 @@ int ath__rx_indicate(struct ath_softc *sc,
|
||||
skb_pull(skb, padsize);
|
||||
}
|
||||
|
||||
/* remove FCS before passing up to protocol stack */
|
||||
skb_trim(skb, (skb->len - FCS_LEN));
|
||||
|
||||
/* Prepare rx status */
|
||||
ath9k_rx_prepare(sc, skb, status, &rx_status);
|
||||
|
||||
@ -1146,9 +1167,119 @@ int ath_rx_subframe(struct ath_node *an,
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc)
|
||||
/********************************/
|
||||
/* LED functions */
|
||||
/********************************/
|
||||
|
||||
static void ath_led_brightness(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
return sc->sc_ht_info.tx_chan_width;
|
||||
struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
|
||||
struct ath_softc *sc = led->sc;
|
||||
|
||||
switch (brightness) {
|
||||
case LED_OFF:
|
||||
if (led->led_type == ATH_LED_ASSOC ||
|
||||
led->led_type == ATH_LED_RADIO)
|
||||
sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
|
||||
(led->led_type == ATH_LED_RADIO) ? 1 :
|
||||
!!(sc->sc_flags & SC_OP_LED_ASSOCIATED));
|
||||
break;
|
||||
case LED_FULL:
|
||||
if (led->led_type == ATH_LED_ASSOC)
|
||||
sc->sc_flags |= SC_OP_LED_ASSOCIATED;
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
|
||||
char *trigger)
|
||||
{
|
||||
int ret;
|
||||
|
||||
led->sc = sc;
|
||||
led->led_cdev.name = led->name;
|
||||
led->led_cdev.default_trigger = trigger;
|
||||
led->led_cdev.brightness_set = ath_led_brightness;
|
||||
|
||||
ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
|
||||
if (ret)
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Failed to register led:%s", led->name);
|
||||
else
|
||||
led->registered = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath_unregister_led(struct ath_led *led)
|
||||
{
|
||||
if (led->registered) {
|
||||
led_classdev_unregister(&led->led_cdev);
|
||||
led->registered = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath_deinit_leds(struct ath_softc *sc)
|
||||
{
|
||||
ath_unregister_led(&sc->assoc_led);
|
||||
sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
|
||||
ath_unregister_led(&sc->tx_led);
|
||||
ath_unregister_led(&sc->rx_led);
|
||||
ath_unregister_led(&sc->radio_led);
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
|
||||
}
|
||||
|
||||
static void ath_init_leds(struct ath_softc *sc)
|
||||
{
|
||||
char *trigger;
|
||||
int ret;
|
||||
|
||||
/* Configure gpio 1 for output */
|
||||
ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
|
||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
/* LED off, active low */
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
|
||||
|
||||
trigger = ieee80211_get_radio_led_name(sc->hw);
|
||||
snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
|
||||
"ath9k-%s:radio", wiphy_name(sc->hw->wiphy));
|
||||
ret = ath_register_led(sc, &sc->radio_led, trigger);
|
||||
sc->radio_led.led_type = ATH_LED_RADIO;
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
trigger = ieee80211_get_assoc_led_name(sc->hw);
|
||||
snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name),
|
||||
"ath9k-%s:assoc", wiphy_name(sc->hw->wiphy));
|
||||
ret = ath_register_led(sc, &sc->assoc_led, trigger);
|
||||
sc->assoc_led.led_type = ATH_LED_ASSOC;
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
trigger = ieee80211_get_tx_led_name(sc->hw);
|
||||
snprintf(sc->tx_led.name, sizeof(sc->tx_led.name),
|
||||
"ath9k-%s:tx", wiphy_name(sc->hw->wiphy));
|
||||
ret = ath_register_led(sc, &sc->tx_led, trigger);
|
||||
sc->tx_led.led_type = ATH_LED_TX;
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
trigger = ieee80211_get_rx_led_name(sc->hw);
|
||||
snprintf(sc->rx_led.name, sizeof(sc->rx_led.name),
|
||||
"ath9k-%s:rx", wiphy_name(sc->hw->wiphy));
|
||||
ret = ath_register_led(sc, &sc->rx_led, trigger);
|
||||
sc->rx_led.led_type = ATH_LED_RX;
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
ath_deinit_leds(sc);
|
||||
}
|
||||
|
||||
static int ath_detach(struct ath_softc *sc)
|
||||
@ -1157,6 +1288,9 @@ static int ath_detach(struct ath_softc *sc)
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__);
|
||||
|
||||
/* Deinit LED control */
|
||||
ath_deinit_leds(sc);
|
||||
|
||||
/* Unregister hw */
|
||||
|
||||
ieee80211_unregister_hw(hw);
|
||||
@ -1250,18 +1384,21 @@ static int ath_attach(u16 devid,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Initialize LED control */
|
||||
ath_init_leds(sc);
|
||||
|
||||
/* initialize tx/rx engine */
|
||||
|
||||
error = ath_tx_init(sc, ATH_TXBUF);
|
||||
if (error != 0)
|
||||
goto bad1;
|
||||
goto detach;
|
||||
|
||||
error = ath_rx_init(sc, ATH_RXBUF);
|
||||
if (error != 0)
|
||||
goto bad1;
|
||||
goto detach;
|
||||
|
||||
return 0;
|
||||
bad1:
|
||||
detach:
|
||||
ath_detach(sc);
|
||||
bad:
|
||||
return error;
|
||||
@ -1340,7 +1477,9 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
goto bad2;
|
||||
}
|
||||
|
||||
hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
|
||||
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_NOISE_DBM;
|
||||
|
||||
SET_IEEE80211_DEV(hw, &pdev->dev);
|
||||
@ -1404,6 +1543,10 @@ static void ath_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct ath_softc *sc = hw->priv;
|
||||
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_set_power_state(pdev, 3);
|
||||
@ -1413,6 +1556,8 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
|
||||
static int ath_pci_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct ath_softc *sc = hw->priv;
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
@ -1429,6 +1574,11 @@ static int ath_pci_resume(struct pci_dev *pdev)
|
||||
if ((val & 0x0000ff00) != 0)
|
||||
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
|
||||
|
||||
/* Enable LED */
|
||||
ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
|
||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -847,9 +847,9 @@ void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp)
|
||||
/* For half and quarter rate channles use different
|
||||
* rate tables
|
||||
*/
|
||||
if (sc->sc_curchan.channelFlags & CHANNEL_HALF)
|
||||
if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_HALF)
|
||||
ar5416_sethalf_ratetable(asc);
|
||||
else if (sc->sc_curchan.channelFlags & CHANNEL_QUARTER)
|
||||
else if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_QUARTER)
|
||||
ar5416_setquarter_ratetable(asc);
|
||||
else /* full rate */
|
||||
ar5416_setfull_ratetable(asc);
|
||||
@ -1141,7 +1141,7 @@ static void ath_rc_ratefind(struct ath_softc *sc,
|
||||
/*
|
||||
* Return the Tx rate series.
|
||||
*/
|
||||
void ath_rate_findrate(struct ath_softc *sc,
|
||||
static void ath_rate_findrate(struct ath_softc *sc,
|
||||
struct ath_rate_node *ath_rc_priv,
|
||||
int num_tries,
|
||||
int num_rates,
|
||||
@ -1152,7 +1152,8 @@ void ath_rate_findrate(struct ath_softc *sc,
|
||||
{
|
||||
struct ath_vap *avp = ath_rc_priv->avp;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_RATE, "%s", __func__);
|
||||
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
|
||||
|
||||
if (!num_rates || !num_tries)
|
||||
return;
|
||||
|
||||
@ -1174,8 +1175,7 @@ void ath_rate_findrate(struct ath_softc *sc,
|
||||
unsigned int mcs;
|
||||
u8 series_rix = 0;
|
||||
|
||||
series[idx].tries =
|
||||
IEEE80211_RATE_IDX_ENTRY(
|
||||
series[idx].tries = IEEE80211_RATE_IDX_ENTRY(
|
||||
avp->av_config.av_fixed_retryset, idx);
|
||||
|
||||
mcs = IEEE80211_RATE_IDX_ENTRY(
|
||||
@ -1295,8 +1295,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
||||
if (retries >= count)
|
||||
retries = count - 1;
|
||||
if (info_priv->n_bad_frames) {
|
||||
/* new_PER = 7/8*old_PER + 1/8*(currentPER) */
|
||||
/*
|
||||
/* new_PER = 7/8*old_PER + 1/8*(currentPER)
|
||||
* Assuming that n_frames is not 0. The current PER
|
||||
* from the retries is 100 * retries / (retries+1),
|
||||
* since the first retries attempts failed, and the
|
||||
@ -1637,7 +1636,6 @@ static void ath_rc_update(struct ath_softc *sc,
|
||||
xretries, long_retry);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process a tx descriptor for a completed transmit (success or failure).
|
||||
*/
|
||||
@ -1651,8 +1649,8 @@ static void ath_rate_tx_complete(struct ath_softc *sc,
|
||||
struct ath_vap *avp;
|
||||
|
||||
avp = rc_priv->avp;
|
||||
if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE)
|
||||
|| info_priv->tx.ts_status & ATH9K_TXERR_FILT)
|
||||
if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) ||
|
||||
(info_priv->tx.ts_status & ATH9K_TXERR_FILT))
|
||||
return;
|
||||
|
||||
if (info_priv->tx.ts_rssi > 0) {
|
||||
@ -1682,7 +1680,6 @@ static void ath_rate_tx_complete(struct ath_softc *sc,
|
||||
info_priv->tx.ts_longretry);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Update the SIB's rate control information
|
||||
*
|
||||
@ -1701,8 +1698,8 @@ static void ath_rc_sib_update(struct ath_softc *sc,
|
||||
struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc;
|
||||
struct ath_rateset *rateset = negotiated_rates;
|
||||
u8 *ht_mcs = (u8 *)negotiated_htrates;
|
||||
struct ath_tx_ratectrl *rate_ctrl = (struct ath_tx_ratectrl *)
|
||||
(ath_rc_priv);
|
||||
struct ath_tx_ratectrl *rate_ctrl =
|
||||
(struct ath_tx_ratectrl *)ath_rc_priv;
|
||||
u8 i, j, k, hi = 0, hthi = 0;
|
||||
|
||||
rate_table = (struct ath_rate_table *)
|
||||
@ -1824,7 +1821,8 @@ static void ath_setup_rates(struct ieee80211_local *local, struct sta_info *sta)
|
||||
struct ath_rate_node *rc_priv = sta->rate_ctrl_priv;
|
||||
int i, j = 0;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_RATE, "%s", __func__);
|
||||
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
|
||||
|
||||
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
if (sta->supp_rates[local->hw.conf.channel->band] & BIT(i)) {
|
||||
@ -1903,7 +1901,7 @@ static void ath_tx_aggr_resp(struct ath_softc *sc,
|
||||
int state;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
if (!sc->sc_txaggr)
|
||||
if (!(sc->sc_flags & SC_OP_TXAGGR))
|
||||
return;
|
||||
|
||||
txtid = ATH_AN_2_TID(an, tidno);
|
||||
@ -1944,7 +1942,7 @@ static void ath_get_rate(void *priv, struct net_device *dev,
|
||||
struct ath_rate_node *ath_rc_priv;
|
||||
struct ath_node *an;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
int is_probe, chk, ret;
|
||||
int is_probe = FALSE, chk, ret;
|
||||
s8 lowest_idx;
|
||||
__le16 fc = hdr->frame_control;
|
||||
u8 *qc, tid;
|
||||
@ -2035,6 +2033,7 @@ static void ath_rate_init(void *priv, void *priv_sta,
|
||||
struct ieee80211_hw *hw = local_to_hw(local);
|
||||
struct ieee80211_conf *conf = &local->hw.conf;
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_rate_node *ath_rc_priv = priv_sta;
|
||||
int i, j = 0;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
|
||||
@ -2046,12 +2045,11 @@ static void ath_rate_init(void *priv, void *priv_sta,
|
||||
if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
|
||||
for (i = 0; i < MCS_SET_SIZE; i++) {
|
||||
if (conf->ht_conf.supp_mcs_set[i/8] & (1<<(i%8)))
|
||||
((struct ath_rate_node *)
|
||||
priv_sta)->neg_ht_rates.rs_rates[j++] = i;
|
||||
ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
|
||||
if (j == ATH_RATE_MAX)
|
||||
break;
|
||||
}
|
||||
((struct ath_rate_node *)priv_sta)->neg_ht_rates.rs_nrates = j;
|
||||
ath_rc_priv->neg_ht_rates.rs_nrates = j;
|
||||
}
|
||||
ath_rc_node_update(hw, priv_sta);
|
||||
}
|
||||
@ -2066,7 +2064,7 @@ static void *ath_rate_alloc(struct ieee80211_local *local)
|
||||
struct ieee80211_hw *hw = local_to_hw(local);
|
||||
struct ath_softc *sc = hw->priv;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_RATE, "%s", __func__);
|
||||
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
|
||||
return local->hw.priv;
|
||||
}
|
||||
|
||||
@ -2081,14 +2079,17 @@ static void *ath_rate_alloc_sta(void *priv, gfp_t gfp)
|
||||
struct ath_vap *avp = sc->sc_vaps[0];
|
||||
struct ath_rate_node *rate_priv;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_RATE, "%s", __func__);
|
||||
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
|
||||
|
||||
rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp);
|
||||
if (!rate_priv) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "%s:Unable to allocate"
|
||||
"private rate control structure", __func__);
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"%s: Unable to allocate private rc structure\n",
|
||||
__func__);
|
||||
return NULL;
|
||||
}
|
||||
ath_rc_sib_init(rate_priv);
|
||||
|
||||
return rate_priv;
|
||||
}
|
||||
|
||||
|
@ -71,9 +71,6 @@ enum ieee80211_fixed_rate_mode {
|
||||
*/
|
||||
#define IEEE80211_RATE_IDX_ENTRY(val, idx) (((val&(0xff<<(idx*8)))>>(idx*8)))
|
||||
|
||||
#define SHORT_PRE 1
|
||||
#define LONG_PRE 0
|
||||
|
||||
#define WLAN_PHY_HT_20_SS WLAN_RC_PHY_HT_20_SS
|
||||
#define WLAN_PHY_HT_20_DS WLAN_RC_PHY_HT_20_DS
|
||||
#define WLAN_PHY_HT_20_DS_HGI WLAN_RC_PHY_HT_20_DS_HGI
|
||||
@ -135,50 +132,53 @@ enum {
|
||||
#define WLAN_RC_SGI_FLAG (0x04)
|
||||
#define WLAN_RC_HT_FLAG (0x08)
|
||||
|
||||
/* Index into the rate table */
|
||||
#define INIT_RATE_MAX_20 23
|
||||
#define INIT_RATE_MAX_40 40
|
||||
|
||||
#define RATE_TABLE_SIZE 64
|
||||
|
||||
/* XXX: Convert to kdoc */
|
||||
/**
|
||||
* struct ath_rate_table - Rate Control table
|
||||
* @valid: valid for use in rate control
|
||||
* @valid_single_stream: valid for use in rate control for
|
||||
* single stream operation
|
||||
* @phy: CCK/OFDM
|
||||
* @ratekbps: rate in Kbits per second
|
||||
* @user_ratekbps: user rate in Kbits per second
|
||||
* @ratecode: rate that goes into HW descriptors
|
||||
* @short_preamble: Mask for enabling short preamble in ratecode for CCK
|
||||
* @dot11rate: value that goes into supported
|
||||
* rates info element of MLME
|
||||
* @ctrl_rate: Index of next lower basic rate, used for duration computation
|
||||
* @max_4ms_framelen: maximum frame length(bytes) for tx duration
|
||||
* @probe_interval: interval for rate control to probe for other rates
|
||||
* @rssi_reduce_interval: interval for rate control to reduce rssi
|
||||
* @initial_ratemax: initial ratemax value used in ath_rc_sib_update()
|
||||
*/
|
||||
struct ath_rate_table {
|
||||
int rate_cnt;
|
||||
struct {
|
||||
int valid; /* Valid for use in rate control */
|
||||
int valid_single_stream;/* Valid for use in rate control
|
||||
for single stream operation */
|
||||
u8 phy; /* CCK/OFDM/TURBO/XR */
|
||||
u32 ratekbps; /* Rate in Kbits per second */
|
||||
u32 user_ratekbps; /* User rate in KBits per second */
|
||||
u8 ratecode; /* rate that goes into
|
||||
hw descriptors */
|
||||
u8 short_preamble; /* Mask for enabling short preamble
|
||||
in rate code for CCK */
|
||||
u8 dot11rate; /* Value that goes into supported
|
||||
rates info element of MLME */
|
||||
u8 ctrl_rate; /* Index of next lower basic rate,
|
||||
used for duration computation */
|
||||
int8_t rssi_ack_validmin; /* Rate control related */
|
||||
int8_t rssi_ack_deltamin; /* Rate control related */
|
||||
u8 base_index; /* base rate index */
|
||||
u8 cw40index; /* 40cap rate index */
|
||||
u8 sgi_index; /* shortgi rate index */
|
||||
u8 ht_index; /* shortgi rate index */
|
||||
u32 max_4ms_framelen; /* Maximum frame length(bytes)
|
||||
for 4ms tx duration */
|
||||
int valid;
|
||||
int valid_single_stream;
|
||||
u8 phy;
|
||||
u32 ratekbps;
|
||||
u32 user_ratekbps;
|
||||
u8 ratecode;
|
||||
u8 short_preamble;
|
||||
u8 dot11rate;
|
||||
u8 ctrl_rate;
|
||||
int8_t rssi_ack_validmin;
|
||||
int8_t rssi_ack_deltamin;
|
||||
u8 base_index;
|
||||
u8 cw40index;
|
||||
u8 sgi_index;
|
||||
u8 ht_index;
|
||||
u32 max_4ms_framelen;
|
||||
} info[RATE_TABLE_SIZE];
|
||||
u32 probe_interval; /* interval for ratectrl to
|
||||
probe for other rates */
|
||||
u32 rssi_reduce_interval; /* interval for ratectrl
|
||||
to reduce RSSI */
|
||||
u8 initial_ratemax; /* the initial ratemax value used
|
||||
in ath_rc_sib_update() */
|
||||
u32 probe_interval;
|
||||
u32 rssi_reduce_interval;
|
||||
u8 initial_ratemax;
|
||||
};
|
||||
|
||||
#define ATH_RC_PROBE_ALLOWED 0x00000001
|
||||
#define ATH_RC_MINRATE_LASTRATE 0x00000002
|
||||
#define ATH_RC_SHORT_PREAMBLE 0x00000004
|
||||
|
||||
struct ath_rc_series {
|
||||
u8 rix;
|
||||
@ -205,38 +205,52 @@ struct ath_tx_ratectrl_state {
|
||||
u8 per; /* recent estimate of packet error rate (%) */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ath_tx_ratectrl - TX Rate control Information
|
||||
* @state: RC state
|
||||
* @rssi_last: last ACK rssi
|
||||
* @rssi_last_lookup: last ACK rssi used for lookup
|
||||
* @rssi_last_prev: previous last ACK rssi
|
||||
* @rssi_last_prev2: 2nd previous last ACK rssi
|
||||
* @rssi_sum_cnt: count of rssi_sum for averaging
|
||||
* @rssi_sum_rate: rate that we are averaging
|
||||
* @rssi_sum: running sum of rssi for averaging
|
||||
* @probe_rate: rate we are probing at
|
||||
* @rssi_time: msec timestamp for last ack rssi
|
||||
* @rssi_down_time: msec timestamp for last down step
|
||||
* @probe_time: msec timestamp for last probe
|
||||
* @hw_maxretry_pktcnt: num of packets since we got HW max retry error
|
||||
* @max_valid_rate: maximum number of valid rate
|
||||
* @per_down_time: msec timestamp for last PER down step
|
||||
* @valid_phy_ratecnt: valid rate count
|
||||
* @rate_max_phy: phy index for the max rate
|
||||
* @probe_interval: interval for ratectrl to probe for other rates
|
||||
*/
|
||||
struct ath_tx_ratectrl {
|
||||
struct ath_tx_ratectrl_state state[MAX_TX_RATE_TBL]; /* state */
|
||||
int8_t rssi_last; /* last ack rssi */
|
||||
int8_t rssi_last_lookup; /* last ack rssi used for lookup */
|
||||
int8_t rssi_last_prev; /* previous last ack rssi */
|
||||
int8_t rssi_last_prev2; /* 2nd previous last ack rssi */
|
||||
int32_t rssi_sum_cnt; /* count of rssi_sum for averaging */
|
||||
int32_t rssi_sum_rate; /* rate that we are averaging */
|
||||
int32_t rssi_sum; /* running sum of rssi for averaging */
|
||||
u32 valid_txrate_mask; /* mask of valid rates */
|
||||
u8 rate_table_size; /* rate table size */
|
||||
u8 rate_max; /* max rate that has recently worked */
|
||||
u8 probe_rate; /* rate we are probing at */
|
||||
u32 rssi_time; /* msec timestamp for last ack rssi */
|
||||
u32 rssi_down_time; /* msec timestamp for last down step */
|
||||
u32 probe_time; /* msec timestamp for last probe */
|
||||
u8 hw_maxretry_pktcnt; /* num packets since we got
|
||||
HW max retry error */
|
||||
u8 max_valid_rate; /* maximum number of valid rate */
|
||||
u8 valid_rate_index[MAX_TX_RATE_TBL]; /* valid rate index */
|
||||
u32 per_down_time; /* msec timstamp for last
|
||||
PER down step */
|
||||
struct ath_tx_ratectrl_state state[MAX_TX_RATE_TBL];
|
||||
int8_t rssi_last;
|
||||
int8_t rssi_last_lookup;
|
||||
int8_t rssi_last_prev;
|
||||
int8_t rssi_last_prev2;
|
||||
int32_t rssi_sum_cnt;
|
||||
int32_t rssi_sum_rate;
|
||||
int32_t rssi_sum;
|
||||
u8 rate_table_size;
|
||||
u8 probe_rate;
|
||||
u32 rssi_time;
|
||||
u32 rssi_down_time;
|
||||
u32 probe_time;
|
||||
u8 hw_maxretry_pktcnt;
|
||||
u8 max_valid_rate;
|
||||
u8 valid_rate_index[MAX_TX_RATE_TBL];
|
||||
u32 per_down_time;
|
||||
|
||||
/* 11n state */
|
||||
u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; /* valid rate count */
|
||||
u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
|
||||
u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][MAX_TX_RATE_TBL];
|
||||
u8 rc_phy_mode;
|
||||
u8 rate_max_phy; /* Phy index for the max rate */
|
||||
u32 rate_max_lastused; /* msec timstamp of when we
|
||||
last used rateMaxPhy */
|
||||
u32 probe_interval; /* interval for ratectrl to probe
|
||||
for other rates */
|
||||
u8 rate_max_phy;
|
||||
u32 probe_interval;
|
||||
};
|
||||
|
||||
struct ath_rateset {
|
||||
@ -248,29 +262,32 @@ struct ath_rateset {
|
||||
struct ath_rate_softc {
|
||||
/* phy tables that contain rate control data */
|
||||
const void *hw_rate_table[ATH9K_MODE_MAX];
|
||||
int fixedrix; /* -1 or index of fixed rate */
|
||||
|
||||
/* -1 or index of fixed rate */
|
||||
int fixedrix;
|
||||
};
|
||||
|
||||
/* per-node state */
|
||||
struct ath_rate_node {
|
||||
struct ath_tx_ratectrl tx_ratectrl; /* rate control state proper */
|
||||
u32 prev_data_rix; /* rate idx of last data frame */
|
||||
struct ath_tx_ratectrl tx_ratectrl;
|
||||
|
||||
/* map of rate ix -> negotiated rate set ix */
|
||||
u8 rixmap[MAX_TX_RATE_TBL];
|
||||
/* rate idx of last data frame */
|
||||
u32 prev_data_rix;
|
||||
|
||||
/* map of ht rate ix -> negotiated rate set ix */
|
||||
u8 ht_rixmap[MAX_TX_RATE_TBL];
|
||||
/* ht capabilities */
|
||||
u8 ht_cap;
|
||||
|
||||
u8 ht_cap; /* ht capabilities */
|
||||
u8 ant_tx; /* current transmit antenna */
|
||||
/* When TRUE, only single stream Tx possible */
|
||||
u8 single_stream;
|
||||
|
||||
u8 single_stream; /* When TRUE, only single
|
||||
stream Tx possible */
|
||||
struct ath_rateset neg_rates; /* Negotiated rates */
|
||||
struct ath_rateset neg_ht_rates; /* Negotiated HT rates */
|
||||
struct ath_rate_softc *asc; /* back pointer to atheros softc */
|
||||
struct ath_vap *avp; /* back pointer to vap */
|
||||
/* Negotiated rates */
|
||||
struct ath_rateset neg_rates;
|
||||
|
||||
/* Negotiated HT rates */
|
||||
struct ath_rateset neg_ht_rates;
|
||||
|
||||
struct ath_rate_softc *asc;
|
||||
struct ath_vap *avp;
|
||||
};
|
||||
|
||||
/* Driver data of ieee80211_tx_info */
|
||||
@ -296,13 +313,6 @@ void ath_rate_detach(struct ath_rate_softc *asc);
|
||||
void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv);
|
||||
void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp);
|
||||
|
||||
/*
|
||||
* Return the tx rate series.
|
||||
*/
|
||||
void ath_rate_findrate(struct ath_softc *sc, struct ath_rate_node *ath_rc_priv,
|
||||
int num_tries, int num_rates,
|
||||
unsigned int rcflag, struct ath_rc_series[],
|
||||
int *is_probe, int isretry);
|
||||
/*
|
||||
* Return rate index for given Dot11 Rate.
|
||||
*/
|
||||
|
@ -184,7 +184,7 @@ static int ath_ampdu_input(struct ath_softc *sc,
|
||||
tid = qc[0] & 0xf;
|
||||
}
|
||||
|
||||
if (sc->sc_opmode == ATH9K_M_STA) {
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_STA) {
|
||||
/* Drop the frame not belonging to me. */
|
||||
if (memcmp(hdr->addr1, sc->sc_myaddr, ETH_ALEN)) {
|
||||
dev_kfree_skb(skb);
|
||||
@ -448,17 +448,16 @@ static int ath_rx_indicate(struct ath_softc *sc,
|
||||
int type;
|
||||
|
||||
/* indicate frame to the stack, which will free the old skb. */
|
||||
type = ath__rx_indicate(sc, skb, status, keyix);
|
||||
type = _ath_rx_indicate(sc, skb, status, keyix);
|
||||
|
||||
/* allocate a new skb and queue it to for H/W processing */
|
||||
nskb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
|
||||
if (nskb != NULL) {
|
||||
bf->bf_mpdu = nskb;
|
||||
bf->bf_buf_addr = ath_skb_map_single(sc,
|
||||
nskb,
|
||||
PCI_DMA_FROMDEVICE,
|
||||
/* XXX: Remove get_dma_mem_context() */
|
||||
get_dma_mem_context(bf, bf_dmacontext));
|
||||
bf->bf_buf_addr = pci_map_single(sc->pdev, nskb->data,
|
||||
skb_end_pointer(nskb) - nskb->head,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
bf->bf_dmacontext = bf->bf_buf_addr;
|
||||
ATH_RX_CONTEXT(nskb)->ctx_rxbuf = bf;
|
||||
|
||||
/* queue the new wbuf to H/W */
|
||||
@ -504,7 +503,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
|
||||
do {
|
||||
spin_lock_init(&sc->sc_rxflushlock);
|
||||
sc->sc_rxflush = 0;
|
||||
sc->sc_flags &= ~SC_OP_RXFLUSH;
|
||||
spin_lock_init(&sc->sc_rxbuflock);
|
||||
|
||||
/*
|
||||
@ -541,9 +540,10 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
}
|
||||
|
||||
bf->bf_mpdu = skb;
|
||||
bf->bf_buf_addr =
|
||||
ath_skb_map_single(sc, skb, PCI_DMA_FROMDEVICE,
|
||||
get_dma_mem_context(bf, bf_dmacontext));
|
||||
bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data,
|
||||
skb_end_pointer(skb) - skb->head,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
bf->bf_dmacontext = bf->bf_buf_addr;
|
||||
ATH_RX_CONTEXT(skb)->ctx_rxbuf = bf;
|
||||
}
|
||||
sc->sc_rxlink = NULL;
|
||||
@ -597,6 +597,7 @@ void ath_rx_cleanup(struct ath_softc *sc)
|
||||
u32 ath_calcrxfilter(struct ath_softc *sc)
|
||||
{
|
||||
#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
|
||||
|
||||
u32 rfilt;
|
||||
|
||||
rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE)
|
||||
@ -604,25 +605,29 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
|
||||
| ATH9K_RX_FILTER_MCAST;
|
||||
|
||||
/* If not a STA, enable processing of Probe Requests */
|
||||
if (sc->sc_opmode != ATH9K_M_STA)
|
||||
if (sc->sc_ah->ah_opmode != ATH9K_M_STA)
|
||||
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
|
||||
|
||||
/* Can't set HOSTAP into promiscous mode */
|
||||
if (sc->sc_opmode == ATH9K_M_MONITOR) {
|
||||
if (((sc->sc_ah->ah_opmode != ATH9K_M_HOSTAP) &&
|
||||
(sc->rx_filter & FIF_PROMISC_IN_BSS)) ||
|
||||
(sc->sc_ah->ah_opmode == ATH9K_M_MONITOR)) {
|
||||
rfilt |= ATH9K_RX_FILTER_PROM;
|
||||
/* ??? To prevent from sending ACK */
|
||||
rfilt &= ~ATH9K_RX_FILTER_UCAST;
|
||||
}
|
||||
|
||||
if (sc->sc_opmode == ATH9K_M_STA || sc->sc_opmode == ATH9K_M_IBSS ||
|
||||
sc->sc_scanning)
|
||||
if (((sc->sc_ah->ah_opmode == ATH9K_M_STA) &&
|
||||
(sc->rx_filter & FIF_BCN_PRBRESP_PROMISC)) ||
|
||||
(sc->sc_ah->ah_opmode == ATH9K_M_IBSS))
|
||||
rfilt |= ATH9K_RX_FILTER_BEACON;
|
||||
|
||||
/* If in HOSTAP mode, want to enable reception of PSPOLL frames
|
||||
& beacon frames */
|
||||
if (sc->sc_opmode == ATH9K_M_HOSTAP)
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP)
|
||||
rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL);
|
||||
return rfilt;
|
||||
|
||||
#undef RX_FILTER_PRESERVE
|
||||
}
|
||||
|
||||
@ -702,11 +707,11 @@ void ath_flushrecv(struct ath_softc *sc)
|
||||
* progress (see references to sc_rxflush)
|
||||
*/
|
||||
spin_lock_bh(&sc->sc_rxflushlock);
|
||||
sc->sc_rxflush = 1;
|
||||
sc->sc_flags |= SC_OP_RXFLUSH;
|
||||
|
||||
ath_rx_tasklet(sc, 1);
|
||||
|
||||
sc->sc_rxflush = 0;
|
||||
sc->sc_flags &= ~SC_OP_RXFLUSH;
|
||||
spin_unlock_bh(&sc->sc_rxflushlock);
|
||||
}
|
||||
|
||||
@ -719,7 +724,7 @@ int ath_rx_input(struct ath_softc *sc,
|
||||
struct ath_recv_status *rx_status,
|
||||
enum ATH_RX_TYPE *status)
|
||||
{
|
||||
if (is_ampdu && sc->sc_rxaggr) {
|
||||
if (is_ampdu && (sc->sc_flags & SC_OP_RXAGGR)) {
|
||||
*status = ATH_RX_CONSUMED;
|
||||
return ath_ampdu_input(sc, an, skb, rx_status);
|
||||
} else {
|
||||
@ -750,7 +755,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
|
||||
do {
|
||||
/* If handling rx interrupt and flush is in progress => exit */
|
||||
if (sc->sc_rxflush && (flush == 0))
|
||||
if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))
|
||||
break;
|
||||
|
||||
spin_lock_bh(&sc->sc_rxbuflock);
|
||||
@ -900,7 +905,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
* Enable this if you want to see
|
||||
* error frames in Monitor mode.
|
||||
*/
|
||||
if (sc->sc_opmode != ATH9K_M_MONITOR)
|
||||
if (sc->sc_ah->ah_opmode != ATH9K_M_MONITOR)
|
||||
goto rx_next;
|
||||
#endif
|
||||
/* fall thru for monitor mode handling... */
|
||||
@ -945,7 +950,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
|
||||
* decryption and MIC failures. For monitor mode,
|
||||
* we also ignore the CRC error.
|
||||
*/
|
||||
if (sc->sc_opmode == ATH9K_M_MONITOR) {
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR) {
|
||||
if (ds->ds_rxstat.rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
|
||||
ATH9K_RXERR_CRC))
|
||||
@ -1089,7 +1094,7 @@ rx_next:
|
||||
"%s: Reset rx chain mask. "
|
||||
"Do internal reset\n", __func__);
|
||||
ASSERT(flush == 0);
|
||||
ath_internal_reset(sc);
|
||||
ath_reset(sc, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1127,7 +1132,7 @@ int ath_rx_aggr_start(struct ath_softc *sc,
|
||||
rxtid = &an->an_aggr.rx.tid[tid];
|
||||
|
||||
spin_lock_bh(&rxtid->tidlock);
|
||||
if (sc->sc_rxaggr) {
|
||||
if (sc->sc_flags & SC_OP_RXAGGR) {
|
||||
/* Allow aggregation reception
|
||||
* Adjust rx BA window size. Peer might indicate a
|
||||
* zero buffer size for a _dont_care_ condition.
|
||||
@ -1227,7 +1232,7 @@ void ath_rx_aggr_teardown(struct ath_softc *sc,
|
||||
|
||||
void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an)
|
||||
{
|
||||
if (sc->sc_rxaggr) {
|
||||
if (sc->sc_flags & SC_OP_RXAGGR) {
|
||||
struct ath_arx_tid *rxtid;
|
||||
int tidno;
|
||||
|
||||
@ -1259,7 +1264,7 @@ void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an)
|
||||
|
||||
void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
|
||||
{
|
||||
if (sc->sc_rxaggr) {
|
||||
if (sc->sc_flags & SC_OP_RXAGGR) {
|
||||
struct ath_arx_tid *rxtid;
|
||||
int tidno, i;
|
||||
|
||||
@ -1292,27 +1297,3 @@ void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an)
|
||||
{
|
||||
ath_rx_node_cleanup(sc, an);
|
||||
}
|
||||
|
||||
dma_addr_t ath_skb_map_single(struct ath_softc *sc,
|
||||
struct sk_buff *skb,
|
||||
int direction,
|
||||
dma_addr_t *pa)
|
||||
{
|
||||
/*
|
||||
* NB: do NOT use skb->len, which is 0 on initialization.
|
||||
* Use skb's entire data area instead.
|
||||
*/
|
||||
*pa = pci_map_single(sc->pdev, skb->data,
|
||||
skb_end_pointer(skb) - skb->head, direction);
|
||||
return *pa;
|
||||
}
|
||||
|
||||
void ath_skb_unmap_single(struct ath_softc *sc,
|
||||
struct sk_buff *skb,
|
||||
int direction,
|
||||
dma_addr_t *pa)
|
||||
{
|
||||
/* Unmap skb's entire data area */
|
||||
pci_unmap_single(sc->pdev, *pa,
|
||||
skb_end_pointer(skb) - skb->head, direction);
|
||||
}
|
||||
|
@ -899,12 +899,6 @@ enum {
|
||||
#define AR_GPIO_OUTPUT_MUX2 0x4064
|
||||
#define AR_GPIO_OUTPUT_MUX3 0x4068
|
||||
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6
|
||||
|
||||
#define AR_INPUT_STATE 0x406c
|
||||
|
||||
#define AR_EEPROM_STATUS_DATA 0x407c
|
||||
|
@ -59,79 +59,6 @@ static u32 bits_per_symbol[][2] = {
|
||||
|
||||
#define IS_HT_RATE(_rate) ((_rate) & 0x80)
|
||||
|
||||
/*
|
||||
* Insert a chain of ath_buf (descriptors) on a multicast txq
|
||||
* but do NOT start tx DMA on this queue.
|
||||
* NB: must be called with txq lock held
|
||||
*/
|
||||
|
||||
static void ath_tx_mcastqaddbuf(struct ath_softc *sc,
|
||||
struct ath_txq *txq,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ath_buf *bf;
|
||||
|
||||
if (list_empty(head))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Insert the frame on the outbound list and
|
||||
* pass it on to the hardware.
|
||||
*/
|
||||
bf = list_first_entry(head, struct ath_buf, list);
|
||||
|
||||
/*
|
||||
* The CAB queue is started from the SWBA handler since
|
||||
* frames only go out on DTIM and to avoid possible races.
|
||||
*/
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
|
||||
/*
|
||||
* If there is anything in the mcastq, we want to set
|
||||
* the "more data" bit in the last item in the queue to
|
||||
* indicate that there is "more data". It makes sense to add
|
||||
* it here since you are *always* going to have
|
||||
* more data when adding to this queue, no matter where
|
||||
* you call from.
|
||||
*/
|
||||
|
||||
if (txq->axq_depth) {
|
||||
struct ath_buf *lbf;
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
/*
|
||||
* Add the "more data flag" to the last frame
|
||||
*/
|
||||
|
||||
lbf = list_entry(txq->axq_q.prev, struct ath_buf, list);
|
||||
hdr = (struct ieee80211_hdr *)
|
||||
((struct sk_buff *)(lbf->bf_mpdu))->data;
|
||||
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, concat the frame onto the queue
|
||||
*/
|
||||
list_splice_tail_init(head, &txq->axq_q);
|
||||
txq->axq_depth++;
|
||||
txq->axq_totalqueued++;
|
||||
txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
|
||||
|
||||
DPRINTF(sc, ATH_DBG_QUEUE,
|
||||
"%s: txq depth = %d\n", __func__, txq->axq_depth);
|
||||
if (txq->axq_link != NULL) {
|
||||
*txq->axq_link = bf->bf_daddr;
|
||||
DPRINTF(sc, ATH_DBG_XMIT,
|
||||
"%s: link[%u](%p)=%llx (%p)\n",
|
||||
__func__,
|
||||
txq->axq_qnum, txq->axq_link,
|
||||
ito64(bf->bf_daddr), bf->bf_desc);
|
||||
}
|
||||
txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link);
|
||||
ath9k_hw_set_interrupts(ah, sc->sc_imask);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a chain of ath_buf (descriptors) on a txq and
|
||||
* assume the descriptors are already chained together by caller.
|
||||
@ -277,8 +204,6 @@ static int ath_tx_prepare(struct ath_softc *sc,
|
||||
__le16 fc;
|
||||
u8 *qc;
|
||||
|
||||
memset(txctl, 0, sizeof(struct ath_tx_control));
|
||||
|
||||
txctl->dev = sc;
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
@ -302,7 +227,6 @@ static int ath_tx_prepare(struct ath_softc *sc,
|
||||
}
|
||||
|
||||
txctl->if_id = 0;
|
||||
txctl->nextfraglen = 0;
|
||||
txctl->frmlen = skb->len + FCS_LEN - (hdrlen & 3);
|
||||
txctl->txpower = MAX_RATE_POWER; /* FIXME */
|
||||
|
||||
@ -329,12 +253,18 @@ static int ath_tx_prepare(struct ath_softc *sc,
|
||||
|
||||
/* Fill qnum */
|
||||
|
||||
if (unlikely(txctl->flags & ATH9K_TXDESC_CAB)) {
|
||||
txctl->qnum = 0;
|
||||
txq = sc->sc_cabq;
|
||||
} else {
|
||||
txctl->qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
|
||||
txq = &sc->sc_txq[txctl->qnum];
|
||||
}
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
|
||||
/* Try to avoid running out of descriptors */
|
||||
if (txq->axq_depth >= (ATH_TXBUF - 20)) {
|
||||
if (txq->axq_depth >= (ATH_TXBUF - 20) &&
|
||||
!(txctl->flags & ATH9K_TXDESC_CAB)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"%s: TX queue: %d is full, depth: %d\n",
|
||||
__func__,
|
||||
@ -354,12 +284,12 @@ static int ath_tx_prepare(struct ath_softc *sc,
|
||||
|
||||
/* Fill flags */
|
||||
|
||||
txctl->flags = ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
|
||||
txctl->flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
|
||||
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
tx_info->flags |= ATH9K_TXDESC_NOACK;
|
||||
txctl->flags |= ATH9K_TXDESC_NOACK;
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
|
||||
tx_info->flags |= ATH9K_TXDESC_RTSENA;
|
||||
txctl->flags |= ATH9K_TXDESC_RTSENA;
|
||||
|
||||
/*
|
||||
* Setup for rate calculations.
|
||||
@ -392,7 +322,7 @@ static int ath_tx_prepare(struct ath_softc *sc,
|
||||
* incremented by the fragmentation routine.
|
||||
*/
|
||||
if (likely(!(txctl->flags & ATH9K_TXDESC_FRAG_IS_ON)) &&
|
||||
txctl->ht && sc->sc_txaggr) {
|
||||
txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
|
||||
struct ath_atx_tid *tid;
|
||||
|
||||
tid = ATH_AN_2_TID(txctl->an, txctl->tidno);
|
||||
@ -413,35 +343,6 @@ static int ath_tx_prepare(struct ath_softc *sc,
|
||||
}
|
||||
rix = rcs[0].rix;
|
||||
|
||||
/*
|
||||
* Calculate duration. This logically belongs in the 802.11
|
||||
* layer but it lacks sufficient information to calculate it.
|
||||
*/
|
||||
if ((txctl->flags & ATH9K_TXDESC_NOACK) == 0 && !ieee80211_is_ctl(fc)) {
|
||||
u16 dur;
|
||||
/*
|
||||
* XXX not right with fragmentation.
|
||||
*/
|
||||
if (sc->sc_flags & ATH_PREAMBLE_SHORT)
|
||||
dur = rt->info[rix].spAckDuration;
|
||||
else
|
||||
dur = rt->info[rix].lpAckDuration;
|
||||
|
||||
if (le16_to_cpu(hdr->frame_control) &
|
||||
IEEE80211_FCTL_MOREFRAGS) {
|
||||
dur += dur; /* Add additional 'SIFS + ACK' */
|
||||
|
||||
/*
|
||||
** Compute size of next fragment in order to compute
|
||||
** durations needed to update NAV.
|
||||
** The last fragment uses the ACK duration only.
|
||||
** Add time for next fragment.
|
||||
*/
|
||||
dur += ath9k_hw_computetxtime(sc->sc_ah, rt,
|
||||
txctl->nextfraglen,
|
||||
rix, sc->sc_flags & ATH_PREAMBLE_SHORT);
|
||||
}
|
||||
|
||||
if (ieee80211_has_morefrags(fc) ||
|
||||
(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
|
||||
/*
|
||||
@ -456,9 +357,6 @@ static int ath_tx_prepare(struct ath_softc *sc,
|
||||
rcs[0].tries = ATH_TXMAXTRY;
|
||||
}
|
||||
|
||||
hdr->duration_id = cpu_to_le16(dur);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if a tx interrupt should be generated for
|
||||
* this descriptor. We take a tx interrupt to reap
|
||||
@ -484,12 +382,8 @@ static int ath_tx_prepare(struct ath_softc *sc,
|
||||
if (is_multicast_ether_addr(hdr->addr1)) {
|
||||
antenna = sc->sc_mcastantenna + 1;
|
||||
sc->sc_mcastantenna = (sc->sc_mcastantenna + 1) & 0x1;
|
||||
} else
|
||||
antenna = sc->sc_txantenna;
|
||||
}
|
||||
|
||||
#ifdef USE_LEGACY_HAL
|
||||
txctl->antenna = antenna;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -502,7 +396,6 @@ static void ath_tx_complete_buf(struct ath_softc *sc,
|
||||
{
|
||||
struct sk_buff *skb = bf->bf_mpdu;
|
||||
struct ath_xmit_status tx_status;
|
||||
dma_addr_t *pa;
|
||||
|
||||
/*
|
||||
* Set retry information.
|
||||
@ -518,13 +411,12 @@ static void ath_tx_complete_buf(struct ath_softc *sc,
|
||||
if (!txok) {
|
||||
tx_status.flags |= ATH_TX_ERROR;
|
||||
|
||||
if (bf->bf_isxretried)
|
||||
if (bf_isxretried(bf))
|
||||
tx_status.flags |= ATH_TX_XRETRY;
|
||||
}
|
||||
/* Unmap this frame */
|
||||
pa = get_dma_mem_context(bf, bf_dmacontext);
|
||||
pci_unmap_single(sc->pdev,
|
||||
*pa,
|
||||
bf->bf_dmacontext,
|
||||
skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
/* complete this frame */
|
||||
@ -629,7 +521,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc,
|
||||
if (isnodegone || ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
|
||||
return 0;
|
||||
|
||||
isaggr = bf->bf_isaggr;
|
||||
isaggr = bf_isaggr(bf);
|
||||
if (isaggr) {
|
||||
seq_st = ATH_DS_BA_SEQ(ds);
|
||||
memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3);
|
||||
@ -651,7 +543,7 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf)
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
bf->bf_isretried = 1;
|
||||
bf->bf_state.bf_type |= BUF_RETRY;
|
||||
bf->bf_retries++;
|
||||
|
||||
skb = bf->bf_mpdu;
|
||||
@ -698,7 +590,7 @@ static u32 ath_pkt_duration(struct ath_softc *sc,
|
||||
u8 rc;
|
||||
int streams, pktlen;
|
||||
|
||||
pktlen = bf->bf_isaggr ? bf->bf_al : bf->bf_frmlen;
|
||||
pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
|
||||
rc = rt->info[rix].rateCode;
|
||||
|
||||
/*
|
||||
@ -742,7 +634,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
int i, flags, rtsctsena = 0, dynamic_mimops = 0;
|
||||
u32 ctsduration = 0;
|
||||
u8 rix = 0, cix, ctsrate = 0;
|
||||
u32 aggr_limit_with_rts = sc->sc_rtsaggrlimit;
|
||||
u32 aggr_limit_with_rts = ah->ah_caps.rts_aggr_limit;
|
||||
struct ath_node *an = (struct ath_node *) bf->bf_node;
|
||||
|
||||
/*
|
||||
@ -781,7 +673,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
* let rate series flags determine which rates will actually
|
||||
* use RTS.
|
||||
*/
|
||||
if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf->bf_isdata) {
|
||||
if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf_isdata(bf)) {
|
||||
BUG_ON(!an);
|
||||
/*
|
||||
* 802.11g protection not needed, use our default behavior
|
||||
@ -793,7 +685,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
* and the second aggregate should have any protection at all.
|
||||
*/
|
||||
if (an->an_smmode == ATH_SM_PWRSAV_DYNAMIC) {
|
||||
if (!bf->bf_aggrburst) {
|
||||
if (!bf_isaggrburst(bf)) {
|
||||
flags = ATH9K_TXDESC_RTSENA;
|
||||
dynamic_mimops = 1;
|
||||
} else {
|
||||
@ -806,7 +698,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
* Set protection if aggregate protection on
|
||||
*/
|
||||
if (sc->sc_config.ath_aggr_prot &&
|
||||
(!bf->bf_isaggr || (bf->bf_isaggr && bf->bf_al < 8192))) {
|
||||
(!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) {
|
||||
flags = ATH9K_TXDESC_RTSENA;
|
||||
cix = rt->info[sc->sc_protrix].controlRate;
|
||||
rtsctsena = 1;
|
||||
@ -815,7 +707,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
/*
|
||||
* For AR5416 - RTS cannot be followed by a frame larger than 8K.
|
||||
*/
|
||||
if (bf->bf_isaggr && (bf->bf_al > aggr_limit_with_rts)) {
|
||||
if (bf_isaggr(bf) && (bf->bf_al > aggr_limit_with_rts)) {
|
||||
/*
|
||||
* Ensure that in the case of SM Dynamic power save
|
||||
* while we are bursting the second aggregate the
|
||||
@ -832,7 +724,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
/* NB: cix is set above where RTS/CTS is enabled */
|
||||
BUG_ON(cix == 0xff);
|
||||
ctsrate = rt->info[cix].rateCode |
|
||||
(bf->bf_shpreamble ? rt->info[cix].shortPreamble : 0);
|
||||
(bf_isshpreamble(bf) ? rt->info[cix].shortPreamble : 0);
|
||||
|
||||
/*
|
||||
* Setup HAL rate series
|
||||
@ -846,7 +738,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
rix = bf->bf_rcs[i].rix;
|
||||
|
||||
series[i].Rate = rt->info[rix].rateCode |
|
||||
(bf->bf_shpreamble ? rt->info[rix].shortPreamble : 0);
|
||||
(bf_isshpreamble(bf) ? rt->info[rix].shortPreamble : 0);
|
||||
|
||||
series[i].Tries = bf->bf_rcs[i].tries;
|
||||
|
||||
@ -862,7 +754,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
sc, rix, bf,
|
||||
(bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) != 0,
|
||||
(bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG),
|
||||
bf->bf_shpreamble);
|
||||
bf_isshpreamble(bf));
|
||||
|
||||
if ((an->an_smmode == ATH_SM_PWRSAV_STATIC) &&
|
||||
(bf->bf_rcs[i].flags & ATH_RC_DS_FLAG) == 0) {
|
||||
@ -875,7 +767,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
*/
|
||||
series[i].ChSel = sc->sc_tx_chainmask;
|
||||
} else {
|
||||
if (bf->bf_ht)
|
||||
if (bf_isht(bf))
|
||||
series[i].ChSel =
|
||||
ath_chainmask_sel_logic(sc, an);
|
||||
else
|
||||
@ -908,7 +800,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
* use the precalculated ACK durations.
|
||||
*/
|
||||
if (flags & ATH9K_TXDESC_RTSENA) { /* SIFS + CTS */
|
||||
ctsduration += bf->bf_shpreamble ?
|
||||
ctsduration += bf_isshpreamble(bf) ?
|
||||
rt->info[cix].spAckDuration :
|
||||
rt->info[cix].lpAckDuration;
|
||||
}
|
||||
@ -916,7 +808,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
ctsduration += series[0].PktDuration;
|
||||
|
||||
if ((bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { /* SIFS + ACK */
|
||||
ctsduration += bf->bf_shpreamble ?
|
||||
ctsduration += bf_isshpreamble(bf) ?
|
||||
rt->info[rix].spAckDuration :
|
||||
rt->info[rix].lpAckDuration;
|
||||
}
|
||||
@ -932,7 +824,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
|
||||
* set dur_update_en for l-sig computation except for PS-Poll frames
|
||||
*/
|
||||
ath9k_hw_set11n_ratescenario(ah, ds, lastds,
|
||||
!bf->bf_ispspoll,
|
||||
!bf_ispspoll(bf),
|
||||
ctsrate,
|
||||
ctsduration,
|
||||
series, 4, flags);
|
||||
@ -958,7 +850,7 @@ static int ath_tx_send_normal(struct ath_softc *sc,
|
||||
BUG_ON(list_empty(bf_head));
|
||||
|
||||
bf = list_first_entry(bf_head, struct ath_buf, list);
|
||||
bf->bf_isampdu = 0; /* regular HT frame */
|
||||
bf->bf_state.bf_type &= ~BUF_AMPDU; /* regular HT frame */
|
||||
|
||||
skb = (struct sk_buff *)bf->bf_mpdu;
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
@ -998,7 +890,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
|
||||
while (!list_empty(&tid->buf_q)) {
|
||||
bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
|
||||
ASSERT(!bf->bf_isretried);
|
||||
ASSERT(!bf_isretried(bf));
|
||||
list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list);
|
||||
ath_tx_send_normal(sc, txq, tid, &bf_head);
|
||||
}
|
||||
@ -1025,7 +917,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
|
||||
int isaggr, txfail, txpending, sendbar = 0, needreset = 0;
|
||||
int isnodegone = (an->an_flags & ATH_NODE_CLEAN);
|
||||
|
||||
isaggr = bf->bf_isaggr;
|
||||
isaggr = bf_isaggr(bf);
|
||||
if (isaggr) {
|
||||
if (txok) {
|
||||
if (ATH_DS_TX_BA(ds)) {
|
||||
@ -1047,7 +939,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
|
||||
* when perform internal reset in this routine.
|
||||
* Only enable reset in STA mode for now.
|
||||
*/
|
||||
if (sc->sc_opmode == ATH9K_M_STA)
|
||||
if (sc->sc_ah->ah_opmode == ATH9K_M_STA)
|
||||
needreset = 1;
|
||||
}
|
||||
} else {
|
||||
@ -1075,7 +967,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
|
||||
ath_tx_set_retry(sc, bf);
|
||||
txpending = 1;
|
||||
} else {
|
||||
bf->bf_isxretried = 1;
|
||||
bf->bf_state.bf_type |= BUF_XRETRY;
|
||||
txfail = 1;
|
||||
sendbar = 1;
|
||||
}
|
||||
@ -1175,11 +1067,8 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
|
||||
tbf->bf_lastfrm->bf_desc);
|
||||
|
||||
/* copy the DMA context */
|
||||
copy_dma_mem_context(
|
||||
get_dma_mem_context(tbf,
|
||||
bf_dmacontext),
|
||||
get_dma_mem_context(bf_last,
|
||||
bf_dmacontext));
|
||||
tbf->bf_dmacontext =
|
||||
bf_last->bf_dmacontext;
|
||||
}
|
||||
list_add_tail(&tbf->list, &bf_head);
|
||||
} else {
|
||||
@ -1242,7 +1131,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
|
||||
}
|
||||
|
||||
if (needreset)
|
||||
ath_internal_reset(sc);
|
||||
ath_reset(sc, false);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1331,7 +1220,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
|
||||
txq->axq_depth--;
|
||||
|
||||
if (bf->bf_isaggr)
|
||||
if (bf_isaggr(bf))
|
||||
txq->axq_aggr_depth--;
|
||||
|
||||
txok = (ds->ds_txstat.ts_status == 0);
|
||||
@ -1345,14 +1234,14 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
spin_unlock_bh(&sc->sc_txbuflock);
|
||||
}
|
||||
|
||||
if (!bf->bf_isampdu) {
|
||||
if (!bf_isampdu(bf)) {
|
||||
/*
|
||||
* This frame is sent out as a single frame.
|
||||
* Use hardware retry status for this frame.
|
||||
*/
|
||||
bf->bf_retries = ds->ds_txstat.ts_longretry;
|
||||
if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY)
|
||||
bf->bf_isxretried = 1;
|
||||
bf->bf_state.bf_type |= BUF_XRETRY;
|
||||
nbad = 0;
|
||||
} else {
|
||||
nbad = ath_tx_num_badfrms(sc, bf, txok);
|
||||
@ -1368,7 +1257,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
if (ds->ds_txstat.ts_status == 0)
|
||||
nacked++;
|
||||
|
||||
if (bf->bf_isdata) {
|
||||
if (bf_isdata(bf)) {
|
||||
if (isrifs)
|
||||
tmp_ds = bf->bf_rifslast->bf_desc;
|
||||
else
|
||||
@ -1384,7 +1273,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
/*
|
||||
* Complete this transmit unit
|
||||
*/
|
||||
if (bf->bf_isampdu)
|
||||
if (bf_isampdu(bf))
|
||||
ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, txok);
|
||||
else
|
||||
ath_tx_complete_buf(sc, bf, &bf_head, txok, 0);
|
||||
@ -1406,7 +1295,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
/*
|
||||
* schedule any pending packets if aggregation is enabled
|
||||
*/
|
||||
if (sc->sc_txaggr)
|
||||
if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
ath_txq_schedule(sc, txq);
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
}
|
||||
@ -1430,10 +1319,9 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx)
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
int i;
|
||||
int npend = 0;
|
||||
enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc);
|
||||
|
||||
/* XXX return value */
|
||||
if (!sc->sc_invalid) {
|
||||
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]);
|
||||
@ -1454,8 +1342,9 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx)
|
||||
"%s: Unable to stop TxDMA. Reset HAL!\n", __func__);
|
||||
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
if (!ath9k_hw_reset(ah, sc->sc_opmode,
|
||||
&sc->sc_curchan, ht_macmode,
|
||||
if (!ath9k_hw_reset(ah,
|
||||
sc->sc_ah->ah_curchan,
|
||||
sc->sc_ht_info.tx_chan_width,
|
||||
sc->sc_tx_chainmask, sc->sc_rx_chainmask,
|
||||
sc->sc_ht_extprotspacing, true, &status)) {
|
||||
|
||||
@ -1481,7 +1370,7 @@ static void ath_tx_addto_baw(struct ath_softc *sc,
|
||||
{
|
||||
int index, cindex;
|
||||
|
||||
if (bf->bf_isretried)
|
||||
if (bf_isretried(bf))
|
||||
return;
|
||||
|
||||
index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
|
||||
@ -1516,7 +1405,7 @@ static int ath_tx_send_ampdu(struct ath_softc *sc,
|
||||
BUG_ON(list_empty(bf_head));
|
||||
|
||||
bf = list_first_entry(bf_head, struct ath_buf, list);
|
||||
bf->bf_isampdu = 1;
|
||||
bf->bf_state.bf_type |= BUF_AMPDU;
|
||||
bf->bf_seqno = txctl->seqno; /* save seqno and tidno in buffer */
|
||||
bf->bf_tidno = txctl->tidno;
|
||||
|
||||
@ -1860,7 +1749,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc,
|
||||
if (bf->bf_nframes == 1) {
|
||||
ASSERT(bf->bf_lastfrm == bf_last);
|
||||
|
||||
bf->bf_isaggr = 0;
|
||||
bf->bf_state.bf_type &= ~BUF_AGGR;
|
||||
/*
|
||||
* clear aggr bits for every descriptor
|
||||
* XXX TODO: is there a way to optimize it?
|
||||
@ -1877,7 +1766,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc,
|
||||
/*
|
||||
* setup first desc with rate and aggr info
|
||||
*/
|
||||
bf->bf_isaggr = 1;
|
||||
bf->bf_state.bf_type |= BUF_AGGR;
|
||||
ath_buf_set_rate(sc, bf);
|
||||
ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al);
|
||||
|
||||
@ -1925,7 +1814,7 @@ static void ath_tid_drain(struct ath_softc *sc,
|
||||
list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list);
|
||||
|
||||
/* update baw for software retried frame */
|
||||
if (bf->bf_isretried)
|
||||
if (bf_isretried(bf))
|
||||
ath_tx_update_baw(sc, tid, bf->bf_seqno);
|
||||
|
||||
/*
|
||||
@ -1990,13 +1879,18 @@ static int ath_tx_start_dma(struct ath_softc *sc,
|
||||
struct list_head bf_head;
|
||||
struct ath_desc *ds;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ath_txq *txq = &sc->sc_txq[txctl->qnum];
|
||||
struct ath_txq *txq;
|
||||
struct ath_tx_info_priv *tx_info_priv;
|
||||
struct ath_rc_series *rcs;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
__le16 fc = hdr->frame_control;
|
||||
|
||||
if (unlikely(txctl->flags & ATH9K_TXDESC_CAB))
|
||||
txq = sc->sc_cabq;
|
||||
else
|
||||
txq = &sc->sc_txq[txctl->qnum];
|
||||
|
||||
/* For each sglist entry, allocate an ath_buf for DMA */
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
spin_lock_bh(&sc->sc_txbuflock);
|
||||
@ -2014,11 +1908,21 @@ static int ath_tx_start_dma(struct ath_softc *sc,
|
||||
/* set up this buffer */
|
||||
ATH_TXBUF_RESET(bf);
|
||||
bf->bf_frmlen = txctl->frmlen;
|
||||
bf->bf_isdata = ieee80211_is_data(fc);
|
||||
bf->bf_isbar = ieee80211_is_back_req(fc);
|
||||
bf->bf_ispspoll = ieee80211_is_pspoll(fc);
|
||||
|
||||
ieee80211_is_data(fc) ?
|
||||
(bf->bf_state.bf_type |= BUF_DATA) :
|
||||
(bf->bf_state.bf_type &= ~BUF_DATA);
|
||||
ieee80211_is_back_req(fc) ?
|
||||
(bf->bf_state.bf_type |= BUF_BAR) :
|
||||
(bf->bf_state.bf_type &= ~BUF_BAR);
|
||||
ieee80211_is_pspoll(fc) ?
|
||||
(bf->bf_state.bf_type |= BUF_PSPOLL) :
|
||||
(bf->bf_state.bf_type &= ~BUF_PSPOLL);
|
||||
(sc->sc_flags & SC_OP_PREAMBLE_SHORT) ?
|
||||
(bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE) :
|
||||
(bf->bf_state.bf_type &= ~BUF_SHORT_PREAMBLE);
|
||||
|
||||
bf->bf_flags = txctl->flags;
|
||||
bf->bf_shpreamble = sc->sc_flags & ATH_PREAMBLE_SHORT;
|
||||
bf->bf_keytype = txctl->keytype;
|
||||
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
|
||||
rcs = tx_info_priv->rcs;
|
||||
@ -2038,8 +1942,7 @@ static int ath_tx_start_dma(struct ath_softc *sc,
|
||||
/*
|
||||
* Save the DMA context in the first ath_buf
|
||||
*/
|
||||
copy_dma_mem_context(get_dma_mem_context(bf, bf_dmacontext),
|
||||
get_dma_mem_context(txctl, dmacontext));
|
||||
bf->bf_dmacontext = txctl->dmacontext;
|
||||
|
||||
/*
|
||||
* Formulate first tx descriptor with tx controls.
|
||||
@ -2060,11 +1963,13 @@ static int ath_tx_start_dma(struct ath_softc *sc,
|
||||
ds); /* first descriptor */
|
||||
|
||||
bf->bf_lastfrm = bf;
|
||||
bf->bf_ht = txctl->ht;
|
||||
(txctl->ht) ?
|
||||
(bf->bf_state.bf_type |= BUF_HT) :
|
||||
(bf->bf_state.bf_type &= ~BUF_HT);
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
|
||||
if (txctl->ht && sc->sc_txaggr) {
|
||||
if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
|
||||
struct ath_atx_tid *tid = ATH_AN_2_TID(an, txctl->tidno);
|
||||
if (ath_aggr_query(sc, an, txctl->tidno)) {
|
||||
/*
|
||||
@ -2090,26 +1995,6 @@ static int ath_tx_start_dma(struct ath_softc *sc,
|
||||
bf->bf_tidno = txctl->tidno;
|
||||
}
|
||||
|
||||
if (is_multicast_ether_addr(hdr->addr1)) {
|
||||
struct ath_vap *avp = sc->sc_vaps[txctl->if_id];
|
||||
|
||||
/*
|
||||
* When servicing one or more stations in power-save
|
||||
* mode (or) if there is some mcast data waiting on
|
||||
* mcast queue (to prevent out of order delivery of
|
||||
* mcast,bcast packets) multicast frames must be
|
||||
* buffered until after the beacon. We use the private
|
||||
* mcast queue for that.
|
||||
*/
|
||||
/* XXX? more bit in 802.11 frame header */
|
||||
spin_lock_bh(&avp->av_mcastq.axq_lock);
|
||||
if (txctl->ps || avp->av_mcastq.axq_depth)
|
||||
ath_tx_mcastqaddbuf(sc,
|
||||
&avp->av_mcastq, &bf_head);
|
||||
else
|
||||
ath_tx_txqaddbuf(sc, txq, &bf_head);
|
||||
spin_unlock_bh(&avp->av_mcastq.axq_lock);
|
||||
} else
|
||||
ath_tx_txqaddbuf(sc, txq, &bf_head);
|
||||
}
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
@ -2118,30 +2003,31 @@ static int ath_tx_start_dma(struct ath_softc *sc,
|
||||
|
||||
static void xmit_map_sg(struct ath_softc *sc,
|
||||
struct sk_buff *skb,
|
||||
dma_addr_t *pa,
|
||||
struct ath_tx_control *txctl)
|
||||
{
|
||||
struct ath_xmit_status tx_status;
|
||||
struct ath_atx_tid *tid;
|
||||
struct scatterlist sg;
|
||||
|
||||
*pa = pci_map_single(sc->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
|
||||
txctl->dmacontext = pci_map_single(sc->pdev, skb->data,
|
||||
skb->len, PCI_DMA_TODEVICE);
|
||||
|
||||
/* setup S/G list */
|
||||
memset(&sg, 0, sizeof(struct scatterlist));
|
||||
sg_dma_address(&sg) = *pa;
|
||||
sg_dma_address(&sg) = txctl->dmacontext;
|
||||
sg_dma_len(&sg) = skb->len;
|
||||
|
||||
if (ath_tx_start_dma(sc, skb, &sg, 1, txctl) != 0) {
|
||||
/*
|
||||
* We have to do drop frame here.
|
||||
*/
|
||||
pci_unmap_single(sc->pdev, *pa, skb->len, PCI_DMA_TODEVICE);
|
||||
pci_unmap_single(sc->pdev, txctl->dmacontext,
|
||||
skb->len, PCI_DMA_TODEVICE);
|
||||
|
||||
tx_status.retries = 0;
|
||||
tx_status.flags = ATH_TX_ERROR;
|
||||
|
||||
if (txctl->ht && sc->sc_txaggr) {
|
||||
if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
|
||||
/* Reclaim the seqno. */
|
||||
tid = ATH_AN_2_TID((struct ath_node *)
|
||||
txctl->an, txctl->tidno);
|
||||
@ -2162,7 +2048,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
|
||||
|
||||
/* Setup tx descriptors */
|
||||
error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf,
|
||||
"tx", nbufs * ATH_FRAG_PER_MSDU, ATH_TXDESC);
|
||||
"tx", nbufs, 1);
|
||||
if (error != 0) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"%s: failed to allocate tx descriptors: %d\n",
|
||||
@ -2403,6 +2289,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb)
|
||||
struct ath_tx_control txctl;
|
||||
int error = 0;
|
||||
|
||||
memset(&txctl, 0, sizeof(struct ath_tx_control));
|
||||
error = ath_tx_prepare(sc, skb, &txctl);
|
||||
if (error == 0)
|
||||
/*
|
||||
@ -2410,9 +2297,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb)
|
||||
* ath_tx_start_dma() will be called either synchronously
|
||||
* or asynchrounsly once DMA is complete.
|
||||
*/
|
||||
xmit_map_sg(sc, skb,
|
||||
get_dma_mem_context(&txctl, dmacontext),
|
||||
&txctl);
|
||||
xmit_map_sg(sc, skb, &txctl);
|
||||
else
|
||||
ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
|
||||
|
||||
@ -2424,8 +2309,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb)
|
||||
|
||||
void ath_tx_tasklet(struct ath_softc *sc)
|
||||
{
|
||||
u64 tsf = ath9k_hw_gettsf64(sc->sc_ah);
|
||||
int i, nacked = 0;
|
||||
int i;
|
||||
u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
|
||||
|
||||
ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
|
||||
@ -2435,10 +2319,8 @@ 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)))
|
||||
nacked += ath_tx_processq(sc, &sc->sc_txq[i]);
|
||||
ath_tx_processq(sc, &sc->sc_txq[i]);
|
||||
}
|
||||
if (nacked)
|
||||
sc->sc_lastrx = tsf;
|
||||
}
|
||||
|
||||
void ath_tx_draintxq(struct ath_softc *sc,
|
||||
@ -2486,14 +2368,14 @@ void ath_tx_draintxq(struct ath_softc *sc,
|
||||
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
|
||||
if (bf->bf_isampdu)
|
||||
if (bf_isampdu(bf))
|
||||
ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, 0);
|
||||
else
|
||||
ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
|
||||
}
|
||||
|
||||
/* flush any pending frames if aggregation is enabled */
|
||||
if (sc->sc_txaggr) {
|
||||
if (sc->sc_flags & SC_OP_TXAGGR) {
|
||||
if (!retry_tx) {
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
ath_txq_drain_pending_buffers(sc, txq,
|
||||
@ -2509,7 +2391,7 @@ 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_invalid) {
|
||||
if (!(sc->sc_flags & SC_OP_INVALID)) {
|
||||
(void) ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
|
||||
DPRINTF(sc, ATH_DBG_XMIT, "%s: beacon queue %x\n", __func__,
|
||||
ath9k_hw_gettxbuf(sc->sc_ah, sc->sc_bhalq));
|
||||
@ -2536,7 +2418,7 @@ enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc,
|
||||
struct ath_atx_tid *txtid;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
if (!sc->sc_txaggr)
|
||||
if (!(sc->sc_flags & SC_OP_TXAGGR))
|
||||
return AGGR_NOT_REQUIRED;
|
||||
|
||||
/* ADDBA exchange must be completed before sending aggregates */
|
||||
@ -2583,7 +2465,7 @@ int ath_tx_aggr_start(struct ath_softc *sc,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sc->sc_txaggr) {
|
||||
if (sc->sc_flags & SC_OP_TXAGGR) {
|
||||
txtid = ATH_AN_2_TID(an, tid);
|
||||
txtid->addba_exchangeinprogress = 1;
|
||||
ath_tx_pause_tid(sc, txtid);
|
||||
@ -2647,7 +2529,7 @@ void ath_tx_aggr_teardown(struct ath_softc *sc,
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
while (!list_empty(&txtid->buf_q)) {
|
||||
bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
|
||||
if (!bf->bf_isretried) {
|
||||
if (!bf_isretried(bf)) {
|
||||
/*
|
||||
* NB: it's based on the assumption that
|
||||
* software retried frame will always stay
|
||||
@ -2743,7 +2625,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
|
||||
|
||||
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
|
||||
{
|
||||
if (sc->sc_txaggr) {
|
||||
if (sc->sc_flags & SC_OP_TXAGGR) {
|
||||
struct ath_atx_tid *tid;
|
||||
struct ath_atx_ac *ac;
|
||||
int tidno, acno;
|
||||
@ -2855,7 +2737,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc,
|
||||
|
||||
void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an)
|
||||
{
|
||||
if (sc->sc_txaggr) {
|
||||
if (sc->sc_flags & SC_OP_TXAGGR) {
|
||||
struct ath_atx_tid *tid;
|
||||
int tidno, i;
|
||||
|
||||
@ -2869,3 +2751,57 @@ void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
|
||||
{
|
||||
int hdrlen, padsize;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ath_tx_control txctl;
|
||||
|
||||
/*
|
||||
* As a temporary workaround, assign seq# here; this will likely need
|
||||
* to be cleaned up to work better with Beacon transmission and virtual
|
||||
* BSSes.
|
||||
*/
|
||||
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;
|
||||
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
|
||||
hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
|
||||
}
|
||||
|
||||
/* Add the padding after the header if this is not already done */
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
if (hdrlen & 3) {
|
||||
padsize = hdrlen % 4;
|
||||
if (skb_headroom(skb) < padsize) {
|
||||
DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ padding "
|
||||
"failed\n", __func__);
|
||||
dev_kfree_skb_any(skb);
|
||||
return;
|
||||
}
|
||||
skb_push(skb, padsize);
|
||||
memmove(skb->data, skb->data + padsize, hdrlen);
|
||||
}
|
||||
|
||||
DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting CABQ packet, skb: %p\n",
|
||||
__func__,
|
||||
skb);
|
||||
|
||||
memset(&txctl, 0, sizeof(struct ath_tx_control));
|
||||
txctl.flags = ATH9K_TXDESC_CAB;
|
||||
if (ath_tx_prepare(sc, skb, &txctl) == 0) {
|
||||
/*
|
||||
* Start DMA mapping.
|
||||
* ath_tx_start_dma() will be called either synchronously
|
||||
* or asynchrounsly once DMA is complete.
|
||||
*/
|
||||
xmit_map_sg(sc, skb, &txctl);
|
||||
} else {
|
||||
ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
|
||||
DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ failed\n", __func__);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
b43-y += main.o
|
||||
b43-y += tables.o
|
||||
b43-$(CONFIG_B43_NPHY) += tables_nphy.o
|
||||
b43-y += phy.o
|
||||
b43-y += phy_common.o
|
||||
b43-y += phy_g.o
|
||||
b43-y += phy_a.o
|
||||
b43-$(CONFIG_B43_NPHY) += nphy.o
|
||||
b43-y += sysfs.o
|
||||
b43-y += xmit.o
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "leds.h"
|
||||
#include "rfkill.h"
|
||||
#include "lo.h"
|
||||
#include "phy.h"
|
||||
#include "phy_common.h"
|
||||
|
||||
|
||||
/* The unique identifier of the firmware that's officially supported by
|
||||
@ -173,6 +173,11 @@ enum {
|
||||
#define B43_SHM_SH_CHAN 0x00A0 /* Current channel (low 8bit only) */
|
||||
#define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5Ghz channel */
|
||||
#define B43_SHM_SH_BCMCFIFOID 0x0108 /* Last posted cookie to the bcast/mcast FIFO */
|
||||
/* TSSI information */
|
||||
#define B43_SHM_SH_TSSI_CCK 0x0058 /* TSSI for last 4 CCK frames (32bit) */
|
||||
#define B43_SHM_SH_TSSI_OFDM_A 0x0068 /* TSSI for last 4 OFDM frames (32bit) */
|
||||
#define B43_SHM_SH_TSSI_OFDM_G 0x0070 /* TSSI for last 4 OFDM frames (32bit) */
|
||||
#define B43_TSSI_MAX 0x7F /* Max value for one TSSI value */
|
||||
/* SHM_SHARED TX FIFO variables */
|
||||
#define B43_SHM_SH_SIZE01 0x0098 /* TX FIFO size for FIFO 0 (low) and 1 (high) */
|
||||
#define B43_SHM_SH_SIZE23 0x009A /* TX FIFO size for FIFO 2 and 3 */
|
||||
@ -508,122 +513,6 @@ struct b43_iv {
|
||||
} __attribute__((__packed__));
|
||||
|
||||
|
||||
struct b43_phy {
|
||||
/* Band support flags. */
|
||||
bool supports_2ghz;
|
||||
bool supports_5ghz;
|
||||
|
||||
/* GMODE bit enabled? */
|
||||
bool gmode;
|
||||
|
||||
/* Analog Type */
|
||||
u8 analog;
|
||||
/* B43_PHYTYPE_ */
|
||||
u8 type;
|
||||
/* PHY revision number. */
|
||||
u8 rev;
|
||||
|
||||
/* Radio versioning */
|
||||
u16 radio_manuf; /* Radio manufacturer */
|
||||
u16 radio_ver; /* Radio version */
|
||||
u8 radio_rev; /* Radio revision */
|
||||
|
||||
bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */
|
||||
|
||||
/* ACI (adjacent channel interference) flags. */
|
||||
bool aci_enable;
|
||||
bool aci_wlan_automatic;
|
||||
bool aci_hw_rssi;
|
||||
|
||||
/* Radio switched on/off */
|
||||
bool radio_on;
|
||||
struct {
|
||||
/* Values saved when turning the radio off.
|
||||
* They are needed when turning it on again. */
|
||||
bool valid;
|
||||
u16 rfover;
|
||||
u16 rfoverval;
|
||||
} radio_off_context;
|
||||
|
||||
u16 minlowsig[2];
|
||||
u16 minlowsigpos[2];
|
||||
|
||||
/* TSSI to dBm table in use */
|
||||
const s8 *tssi2dbm;
|
||||
/* Target idle TSSI */
|
||||
int tgt_idle_tssi;
|
||||
/* Current idle TSSI */
|
||||
int cur_idle_tssi;
|
||||
|
||||
/* LocalOscillator control values. */
|
||||
struct b43_txpower_lo_control *lo_control;
|
||||
/* Values from b43_calc_loopback_gain() */
|
||||
s16 max_lb_gain; /* Maximum Loopback gain in hdB */
|
||||
s16 trsw_rx_gain; /* TRSW RX gain in hdB */
|
||||
s16 lna_lod_gain; /* LNA lod */
|
||||
s16 lna_gain; /* LNA */
|
||||
s16 pga_gain; /* PGA */
|
||||
|
||||
/* Desired TX power level (in dBm).
|
||||
* This is set by the user and adjusted in b43_phy_xmitpower(). */
|
||||
u8 power_level;
|
||||
/* A-PHY TX Power control value. */
|
||||
u16 txpwr_offset;
|
||||
|
||||
/* Current TX power level attenuation control values */
|
||||
struct b43_bbatt bbatt;
|
||||
struct b43_rfatt rfatt;
|
||||
u8 tx_control; /* B43_TXCTL_XXX */
|
||||
|
||||
/* Hardware Power Control enabled? */
|
||||
bool hardware_power_control;
|
||||
|
||||
/* Current Interference Mitigation mode */
|
||||
int interfmode;
|
||||
/* Stack of saved values from the Interference Mitigation code.
|
||||
* Each value in the stack is layed out as follows:
|
||||
* bit 0-11: offset
|
||||
* bit 12-15: register ID
|
||||
* bit 16-32: value
|
||||
* register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
|
||||
*/
|
||||
#define B43_INTERFSTACK_SIZE 26
|
||||
u32 interfstack[B43_INTERFSTACK_SIZE]; //FIXME: use a data structure
|
||||
|
||||
/* Saved values from the NRSSI Slope calculation */
|
||||
s16 nrssi[2];
|
||||
s32 nrssislope;
|
||||
/* In memory nrssi lookup table. */
|
||||
s8 nrssi_lt[64];
|
||||
|
||||
/* current channel */
|
||||
u8 channel;
|
||||
|
||||
u16 lofcal;
|
||||
|
||||
u16 initval; //FIXME rename?
|
||||
|
||||
/* PHY TX errors counter. */
|
||||
atomic_t txerr_cnt;
|
||||
|
||||
/* The device does address auto increment for the OFDM tables.
|
||||
* We cache the previously used address here and omit the address
|
||||
* write on the next table access, if possible. */
|
||||
u16 ofdmtab_addr; /* The address currently set in hardware. */
|
||||
enum { /* The last data flow direction. */
|
||||
B43_OFDMTAB_DIRECTION_UNKNOWN = 0,
|
||||
B43_OFDMTAB_DIRECTION_READ,
|
||||
B43_OFDMTAB_DIRECTION_WRITE,
|
||||
} ofdmtab_addr_direction;
|
||||
|
||||
#if B43_DEBUG
|
||||
/* Manual TX-power control enabled? */
|
||||
bool manual_txpower_control;
|
||||
/* PHY registers locked by b43_phy_lock()? */
|
||||
bool phy_locked;
|
||||
#endif /* B43_DEBUG */
|
||||
};
|
||||
|
||||
/* Data structures for DMA transmission, per 80211 core. */
|
||||
struct b43_dma {
|
||||
struct b43_dmaring *tx_ring_AC_BK; /* Background */
|
||||
@ -764,6 +653,11 @@ struct b43_wl {
|
||||
struct b43_qos_params qos_params[4];
|
||||
/* Workqueue for updating QOS parameters in hardware. */
|
||||
struct work_struct qos_update_work;
|
||||
|
||||
/* Work for adjustment of the transmission power.
|
||||
* This is scheduled when we determine that the actual TX output
|
||||
* power doesn't match what we want. */
|
||||
struct work_struct txpower_adjust_work;
|
||||
};
|
||||
|
||||
/* In-memory representation of a cached microcode file. */
|
||||
@ -908,6 +802,15 @@ static inline int b43_is_mode(struct b43_wl *wl, int type)
|
||||
return (wl->operating && wl->if_type == type);
|
||||
}
|
||||
|
||||
/**
|
||||
* b43_current_band - Returns the currently used band.
|
||||
* Returns one of IEEE80211_BAND_2GHZ and IEEE80211_BAND_5GHZ.
|
||||
*/
|
||||
static inline enum ieee80211_band b43_current_band(struct b43_wl *wl)
|
||||
{
|
||||
return wl->hw->conf.channel->band;
|
||||
}
|
||||
|
||||
static inline u16 b43_read16(struct b43_wldev *dev, u16 offset)
|
||||
{
|
||||
return ssb_read16(dev->dev, offset);
|
||||
|
@ -443,76 +443,6 @@ out_unlock:
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t txpower_g_read_file(struct b43_wldev *dev,
|
||||
char *buf, size_t bufsize)
|
||||
{
|
||||
ssize_t count = 0;
|
||||
|
||||
if (dev->phy.type != B43_PHYTYPE_G) {
|
||||
fappend("Device is not a G-PHY\n");
|
||||
goto out;
|
||||
}
|
||||
fappend("Control: %s\n", dev->phy.manual_txpower_control ?
|
||||
"MANUAL" : "AUTOMATIC");
|
||||
fappend("Baseband attenuation: %u\n", dev->phy.bbatt.att);
|
||||
fappend("Radio attenuation: %u\n", dev->phy.rfatt.att);
|
||||
fappend("TX Mixer Gain: %s\n",
|
||||
(dev->phy.tx_control & B43_TXCTL_TXMIX) ? "ON" : "OFF");
|
||||
fappend("PA Gain 2dB: %s\n",
|
||||
(dev->phy.tx_control & B43_TXCTL_PA2DB) ? "ON" : "OFF");
|
||||
fappend("PA Gain 3dB: %s\n",
|
||||
(dev->phy.tx_control & B43_TXCTL_PA3DB) ? "ON" : "OFF");
|
||||
fappend("\n\n");
|
||||
fappend("You can write to this file:\n");
|
||||
fappend("Writing \"auto\" enables automatic txpower control.\n");
|
||||
fappend
|
||||
("Writing the attenuation values as \"bbatt rfatt txmix pa2db pa3db\" "
|
||||
"enables manual txpower control.\n");
|
||||
fappend("Example: 5 4 0 0 1\n");
|
||||
fappend("Enables manual control with Baseband attenuation 5, "
|
||||
"Radio attenuation 4, No TX Mixer Gain, "
|
||||
"No PA Gain 2dB, With PA Gain 3dB.\n");
|
||||
out:
|
||||
return count;
|
||||
}
|
||||
|
||||
static int txpower_g_write_file(struct b43_wldev *dev,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
if (dev->phy.type != B43_PHYTYPE_G)
|
||||
return -ENODEV;
|
||||
if ((count >= 4) && (memcmp(buf, "auto", 4) == 0)) {
|
||||
/* Automatic control */
|
||||
dev->phy.manual_txpower_control = 0;
|
||||
b43_phy_xmitpower(dev);
|
||||
} else {
|
||||
int bbatt = 0, rfatt = 0, txmix = 0, pa2db = 0, pa3db = 0;
|
||||
/* Manual control */
|
||||
if (sscanf(buf, "%d %d %d %d %d", &bbatt, &rfatt,
|
||||
&txmix, &pa2db, &pa3db) != 5)
|
||||
return -EINVAL;
|
||||
b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);
|
||||
dev->phy.manual_txpower_control = 1;
|
||||
dev->phy.bbatt.att = bbatt;
|
||||
dev->phy.rfatt.att = rfatt;
|
||||
dev->phy.tx_control = 0;
|
||||
if (txmix)
|
||||
dev->phy.tx_control |= B43_TXCTL_TXMIX;
|
||||
if (pa2db)
|
||||
dev->phy.tx_control |= B43_TXCTL_PA2DB;
|
||||
if (pa3db)
|
||||
dev->phy.tx_control |= B43_TXCTL_PA3DB;
|
||||
b43_phy_lock(dev);
|
||||
b43_radio_lock(dev);
|
||||
b43_set_txpower_g(dev, &dev->phy.bbatt,
|
||||
&dev->phy.rfatt, dev->phy.tx_control);
|
||||
b43_radio_unlock(dev);
|
||||
b43_phy_unlock(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* wl->irq_lock is locked */
|
||||
static int restart_write_file(struct b43_wldev *dev,
|
||||
const char *buf, size_t count)
|
||||
@ -560,7 +490,7 @@ static ssize_t loctls_read_file(struct b43_wldev *dev,
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
lo = phy->lo_control;
|
||||
lo = phy->g->lo_control;
|
||||
fappend("-- Local Oscillator calibration data --\n\n");
|
||||
fappend("HW-power-control enabled: %d\n",
|
||||
dev->phy.hardware_power_control);
|
||||
@ -578,8 +508,8 @@ static ssize_t loctls_read_file(struct b43_wldev *dev,
|
||||
list_for_each_entry(cal, &lo->calib_list, list) {
|
||||
bool active;
|
||||
|
||||
active = (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) &&
|
||||
b43_compare_rfatt(&cal->rfatt, &phy->rfatt));
|
||||
active = (b43_compare_bbatt(&cal->bbatt, &phy->g->bbatt) &&
|
||||
b43_compare_rfatt(&cal->rfatt, &phy->g->rfatt));
|
||||
fappend("BB(%d), RF(%d,%d) -> I=%d, Q=%d "
|
||||
"(expires in %lu sec)%s\n",
|
||||
cal->bbatt.att,
|
||||
@ -763,7 +693,6 @@ B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1);
|
||||
B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1);
|
||||
B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1);
|
||||
B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0);
|
||||
B43_DEBUGFS_FOPS(txpower_g, txpower_g_read_file, txpower_g_write_file, 0);
|
||||
B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1);
|
||||
B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0);
|
||||
|
||||
@ -877,7 +806,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev)
|
||||
ADD_FILE(mmio32write, 0200);
|
||||
ADD_FILE(tsf, 0600);
|
||||
ADD_FILE(txstat, 0400);
|
||||
ADD_FILE(txpower_g, 0600);
|
||||
ADD_FILE(restart, 0200);
|
||||
ADD_FILE(loctls, 0400);
|
||||
|
||||
@ -907,7 +835,6 @@ void b43_debugfs_remove_device(struct b43_wldev *dev)
|
||||
debugfs_remove(e->file_mmio32write.dentry);
|
||||
debugfs_remove(e->file_tsf.dentry);
|
||||
debugfs_remove(e->file_txstat.dentry);
|
||||
debugfs_remove(e->file_txpower_g.dentry);
|
||||
debugfs_remove(e->file_restart.dentry);
|
||||
debugfs_remove(e->file_loctls.dentry);
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
#include "b43.h"
|
||||
#include "lo.h"
|
||||
#include "phy.h"
|
||||
#include "phy_g.h"
|
||||
#include "main.h"
|
||||
|
||||
#include <linux/delay.h>
|
||||
@ -174,7 +174,8 @@ static u16 lo_txctl_register_table(struct b43_wldev *dev,
|
||||
static void lo_measure_txctl_values(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_txpower_lo_control *lo = phy->lo_control;
|
||||
struct b43_phy_g *gphy = phy->g;
|
||||
struct b43_txpower_lo_control *lo = gphy->lo_control;
|
||||
u16 reg, mask;
|
||||
u16 trsw_rx, pga;
|
||||
u16 radio_pctl_reg;
|
||||
@ -195,7 +196,7 @@ static void lo_measure_txctl_values(struct b43_wldev *dev)
|
||||
int lb_gain; /* Loopback gain (in dB) */
|
||||
|
||||
trsw_rx = 0;
|
||||
lb_gain = phy->max_lb_gain / 2;
|
||||
lb_gain = gphy->max_lb_gain / 2;
|
||||
if (lb_gain > 10) {
|
||||
radio_pctl_reg = 0;
|
||||
pga = abs(10 - lb_gain) / 6;
|
||||
@ -226,7 +227,7 @@ static void lo_measure_txctl_values(struct b43_wldev *dev)
|
||||
}
|
||||
b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43)
|
||||
& 0xFFF0) | radio_pctl_reg);
|
||||
b43_phy_set_baseband_attenuation(dev, 2);
|
||||
b43_gphy_set_baseband_attenuation(dev, 2);
|
||||
|
||||
reg = lo_txctl_register_table(dev, &mask, NULL);
|
||||
mask = ~mask;
|
||||
@ -277,7 +278,8 @@ static void lo_measure_txctl_values(struct b43_wldev *dev)
|
||||
static void lo_read_power_vector(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_txpower_lo_control *lo = phy->lo_control;
|
||||
struct b43_phy_g *gphy = phy->g;
|
||||
struct b43_txpower_lo_control *lo = gphy->lo_control;
|
||||
int i;
|
||||
u64 tmp;
|
||||
u64 power_vector = 0;
|
||||
@ -298,6 +300,7 @@ static void lo_measure_gain_values(struct b43_wldev *dev,
|
||||
s16 max_rx_gain, int use_trsw_rx)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_g *gphy = phy->g;
|
||||
u16 tmp;
|
||||
|
||||
if (max_rx_gain < 0)
|
||||
@ -308,7 +311,7 @@ static void lo_measure_gain_values(struct b43_wldev *dev,
|
||||
int trsw_rx_gain;
|
||||
|
||||
if (use_trsw_rx) {
|
||||
trsw_rx_gain = phy->trsw_rx_gain / 2;
|
||||
trsw_rx_gain = gphy->trsw_rx_gain / 2;
|
||||
if (max_rx_gain >= trsw_rx_gain) {
|
||||
trsw_rx_gain = max_rx_gain - trsw_rx_gain;
|
||||
trsw_rx = 0x20;
|
||||
@ -316,38 +319,38 @@ static void lo_measure_gain_values(struct b43_wldev *dev,
|
||||
} else
|
||||
trsw_rx_gain = max_rx_gain;
|
||||
if (trsw_rx_gain < 9) {
|
||||
phy->lna_lod_gain = 0;
|
||||
gphy->lna_lod_gain = 0;
|
||||
} else {
|
||||
phy->lna_lod_gain = 1;
|
||||
gphy->lna_lod_gain = 1;
|
||||
trsw_rx_gain -= 8;
|
||||
}
|
||||
trsw_rx_gain = clamp_val(trsw_rx_gain, 0, 0x2D);
|
||||
phy->pga_gain = trsw_rx_gain / 3;
|
||||
if (phy->pga_gain >= 5) {
|
||||
phy->pga_gain -= 5;
|
||||
phy->lna_gain = 2;
|
||||
gphy->pga_gain = trsw_rx_gain / 3;
|
||||
if (gphy->pga_gain >= 5) {
|
||||
gphy->pga_gain -= 5;
|
||||
gphy->lna_gain = 2;
|
||||
} else
|
||||
phy->lna_gain = 0;
|
||||
gphy->lna_gain = 0;
|
||||
} else {
|
||||
phy->lna_gain = 0;
|
||||
phy->trsw_rx_gain = 0x20;
|
||||
gphy->lna_gain = 0;
|
||||
gphy->trsw_rx_gain = 0x20;
|
||||
if (max_rx_gain >= 0x14) {
|
||||
phy->lna_lod_gain = 1;
|
||||
phy->pga_gain = 2;
|
||||
gphy->lna_lod_gain = 1;
|
||||
gphy->pga_gain = 2;
|
||||
} else if (max_rx_gain >= 0x12) {
|
||||
phy->lna_lod_gain = 1;
|
||||
phy->pga_gain = 1;
|
||||
gphy->lna_lod_gain = 1;
|
||||
gphy->pga_gain = 1;
|
||||
} else if (max_rx_gain >= 0xF) {
|
||||
phy->lna_lod_gain = 1;
|
||||
phy->pga_gain = 0;
|
||||
gphy->lna_lod_gain = 1;
|
||||
gphy->pga_gain = 0;
|
||||
} else {
|
||||
phy->lna_lod_gain = 0;
|
||||
phy->pga_gain = 0;
|
||||
gphy->lna_lod_gain = 0;
|
||||
gphy->pga_gain = 0;
|
||||
}
|
||||
}
|
||||
|
||||
tmp = b43_radio_read16(dev, 0x7A);
|
||||
if (phy->lna_lod_gain == 0)
|
||||
if (gphy->lna_lod_gain == 0)
|
||||
tmp &= ~0x0008;
|
||||
else
|
||||
tmp |= 0x0008;
|
||||
@ -392,10 +395,11 @@ static void lo_measure_setup(struct b43_wldev *dev,
|
||||
{
|
||||
struct ssb_sprom *sprom = &dev->dev->bus->sprom;
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_txpower_lo_control *lo = phy->lo_control;
|
||||
struct b43_phy_g *gphy = phy->g;
|
||||
struct b43_txpower_lo_control *lo = gphy->lo_control;
|
||||
u16 tmp;
|
||||
|
||||
if (b43_has_hardware_pctl(phy)) {
|
||||
if (b43_has_hardware_pctl(dev)) {
|
||||
sav->phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK);
|
||||
sav->phy_extg_01 = b43_phy_read(dev, B43_PHY_EXTG(0x01));
|
||||
sav->phy_dacctl_hwpctl = b43_phy_read(dev, B43_PHY_DACCTL);
|
||||
@ -496,7 +500,7 @@ static void lo_measure_setup(struct b43_wldev *dev,
|
||||
b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802);
|
||||
if (phy->rev >= 2)
|
||||
b43_dummy_transmission(dev);
|
||||
b43_radio_selectchannel(dev, 6, 0);
|
||||
b43_gphy_channel_switch(dev, 6, 0);
|
||||
b43_radio_read16(dev, 0x51); /* dummy read */
|
||||
if (phy->type == B43_PHYTYPE_G)
|
||||
b43_phy_write(dev, B43_PHY_CCK(0x2F), 0);
|
||||
@ -520,18 +524,19 @@ static void lo_measure_restore(struct b43_wldev *dev,
|
||||
struct lo_g_saved_values *sav)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_g *gphy = phy->g;
|
||||
u16 tmp;
|
||||
|
||||
if (phy->rev >= 2) {
|
||||
b43_phy_write(dev, B43_PHY_PGACTL, 0xE300);
|
||||
tmp = (phy->pga_gain << 8);
|
||||
tmp = (gphy->pga_gain << 8);
|
||||
b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA0);
|
||||
udelay(5);
|
||||
b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA2);
|
||||
udelay(2);
|
||||
b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA3);
|
||||
} else {
|
||||
tmp = (phy->pga_gain | 0xEFA0);
|
||||
tmp = (gphy->pga_gain | 0xEFA0);
|
||||
b43_phy_write(dev, B43_PHY_PGACTL, tmp);
|
||||
}
|
||||
if (phy->type == B43_PHYTYPE_G) {
|
||||
@ -572,7 +577,7 @@ static void lo_measure_restore(struct b43_wldev *dev,
|
||||
b43_phy_write(dev, B43_PHY_CCK(0x3E), sav->phy_cck_3E);
|
||||
b43_phy_write(dev, B43_PHY_CRS0, sav->phy_crs0);
|
||||
}
|
||||
if (b43_has_hardware_pctl(phy)) {
|
||||
if (b43_has_hardware_pctl(dev)) {
|
||||
tmp = (sav->phy_lo_mask & 0xBFFF);
|
||||
b43_phy_write(dev, B43_PHY_LO_MASK, tmp);
|
||||
b43_phy_write(dev, B43_PHY_EXTG(0x01), sav->phy_extg_01);
|
||||
@ -580,7 +585,7 @@ static void lo_measure_restore(struct b43_wldev *dev,
|
||||
b43_phy_write(dev, B43_PHY_CCK(0x14), sav->phy_cck_14);
|
||||
b43_phy_write(dev, B43_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
|
||||
}
|
||||
b43_radio_selectchannel(dev, sav->old_channel, 1);
|
||||
b43_gphy_channel_switch(dev, sav->old_channel, 1);
|
||||
}
|
||||
|
||||
struct b43_lo_g_statemachine {
|
||||
@ -597,6 +602,7 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev,
|
||||
struct b43_lo_g_statemachine *d)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_g *gphy = phy->g;
|
||||
struct b43_loctl test_loctl;
|
||||
struct b43_loctl orig_loctl;
|
||||
struct b43_loctl prev_loctl = {
|
||||
@ -646,9 +652,9 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev,
|
||||
test_loctl.q != prev_loctl.q) &&
|
||||
(abs(test_loctl.i) <= 16 && abs(test_loctl.q) <= 16)) {
|
||||
b43_lo_write(dev, &test_loctl);
|
||||
feedth = lo_measure_feedthrough(dev, phy->lna_gain,
|
||||
phy->pga_gain,
|
||||
phy->trsw_rx_gain);
|
||||
feedth = lo_measure_feedthrough(dev, gphy->lna_gain,
|
||||
gphy->pga_gain,
|
||||
gphy->trsw_rx_gain);
|
||||
if (feedth < d->lowest_feedth) {
|
||||
memcpy(probe_loctl, &test_loctl,
|
||||
sizeof(struct b43_loctl));
|
||||
@ -677,6 +683,7 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev,
|
||||
int *max_rx_gain)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_g *gphy = phy->g;
|
||||
struct b43_lo_g_statemachine d;
|
||||
u16 feedth;
|
||||
int found_lower;
|
||||
@ -693,17 +700,17 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev,
|
||||
max_repeat = 4;
|
||||
do {
|
||||
b43_lo_write(dev, &d.min_loctl);
|
||||
feedth = lo_measure_feedthrough(dev, phy->lna_gain,
|
||||
phy->pga_gain,
|
||||
phy->trsw_rx_gain);
|
||||
feedth = lo_measure_feedthrough(dev, gphy->lna_gain,
|
||||
gphy->pga_gain,
|
||||
gphy->trsw_rx_gain);
|
||||
if (feedth < 0x258) {
|
||||
if (feedth >= 0x12C)
|
||||
*max_rx_gain += 6;
|
||||
else
|
||||
*max_rx_gain += 3;
|
||||
feedth = lo_measure_feedthrough(dev, phy->lna_gain,
|
||||
phy->pga_gain,
|
||||
phy->trsw_rx_gain);
|
||||
feedth = lo_measure_feedthrough(dev, gphy->lna_gain,
|
||||
gphy->pga_gain,
|
||||
gphy->trsw_rx_gain);
|
||||
}
|
||||
d.lowest_feedth = feedth;
|
||||
|
||||
@ -752,6 +759,7 @@ struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev,
|
||||
const struct b43_rfatt *rfatt)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_g *gphy = phy->g;
|
||||
struct b43_loctl loctl = {
|
||||
.i = 0,
|
||||
.q = 0,
|
||||
@ -782,11 +790,11 @@ struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev,
|
||||
if (rfatt->with_padmix)
|
||||
max_rx_gain -= pad_mix_gain;
|
||||
if (has_loopback_gain(phy))
|
||||
max_rx_gain += phy->max_lb_gain;
|
||||
max_rx_gain += gphy->max_lb_gain;
|
||||
lo_measure_gain_values(dev, max_rx_gain,
|
||||
has_loopback_gain(phy));
|
||||
|
||||
b43_phy_set_baseband_attenuation(dev, bbatt->att);
|
||||
b43_gphy_set_baseband_attenuation(dev, bbatt->att);
|
||||
lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain);
|
||||
|
||||
lo_measure_restore(dev, &saved_regs);
|
||||
@ -820,7 +828,7 @@ struct b43_lo_calib * b43_get_calib_lo_settings(struct b43_wldev *dev,
|
||||
const struct b43_bbatt *bbatt,
|
||||
const struct b43_rfatt *rfatt)
|
||||
{
|
||||
struct b43_txpower_lo_control *lo = dev->phy.lo_control;
|
||||
struct b43_txpower_lo_control *lo = dev->phy.g->lo_control;
|
||||
struct b43_lo_calib *c;
|
||||
|
||||
c = b43_find_lo_calib(lo, bbatt, rfatt);
|
||||
@ -839,7 +847,8 @@ struct b43_lo_calib * b43_get_calib_lo_settings(struct b43_wldev *dev,
|
||||
void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_txpower_lo_control *lo = phy->lo_control;
|
||||
struct b43_phy_g *gphy = phy->g;
|
||||
struct b43_txpower_lo_control *lo = gphy->lo_control;
|
||||
int i;
|
||||
int rf_offset, bb_offset;
|
||||
const struct b43_rfatt *rfatt;
|
||||
@ -917,14 +926,14 @@ static inline void b43_lo_fixup_rfatt(struct b43_rfatt *rf)
|
||||
|
||||
void b43_lo_g_adjust(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_g *gphy = dev->phy.g;
|
||||
struct b43_lo_calib *cal;
|
||||
struct b43_rfatt rf;
|
||||
|
||||
memcpy(&rf, &phy->rfatt, sizeof(rf));
|
||||
memcpy(&rf, &gphy->rfatt, sizeof(rf));
|
||||
b43_lo_fixup_rfatt(&rf);
|
||||
|
||||
cal = b43_get_calib_lo_settings(dev, &phy->bbatt, &rf);
|
||||
cal = b43_get_calib_lo_settings(dev, &gphy->bbatt, &rf);
|
||||
if (!cal)
|
||||
return;
|
||||
b43_lo_write(dev, &cal->ctl);
|
||||
@ -952,7 +961,8 @@ void b43_lo_g_adjust_to(struct b43_wldev *dev,
|
||||
void b43_lo_g_maintanance_work(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_txpower_lo_control *lo = phy->lo_control;
|
||||
struct b43_phy_g *gphy = phy->g;
|
||||
struct b43_txpower_lo_control *lo = gphy->lo_control;
|
||||
unsigned long now;
|
||||
unsigned long expire;
|
||||
struct b43_lo_calib *cal, *tmp;
|
||||
@ -962,7 +972,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev)
|
||||
if (!lo)
|
||||
return;
|
||||
now = jiffies;
|
||||
hwpctl = b43_has_hardware_pctl(phy);
|
||||
hwpctl = b43_has_hardware_pctl(dev);
|
||||
|
||||
if (hwpctl) {
|
||||
/* Read the power vector and update it, if needed. */
|
||||
@ -983,8 +993,8 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev)
|
||||
if (!time_before(cal->calib_time, expire))
|
||||
continue;
|
||||
/* This item expired. */
|
||||
if (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) &&
|
||||
b43_compare_rfatt(&cal->rfatt, &phy->rfatt)) {
|
||||
if (b43_compare_bbatt(&cal->bbatt, &gphy->bbatt) &&
|
||||
b43_compare_rfatt(&cal->rfatt, &gphy->rfatt)) {
|
||||
B43_WARN_ON(current_item_expired);
|
||||
current_item_expired = 1;
|
||||
}
|
||||
@ -1002,7 +1012,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev)
|
||||
/* Recalibrate currently used LO setting. */
|
||||
if (b43_debug(dev, B43_DBG_LO))
|
||||
b43dbg(dev->wl, "LO: Recalibrating current LO setting\n");
|
||||
cal = b43_calibrate_lo_setting(dev, &phy->bbatt, &phy->rfatt);
|
||||
cal = b43_calibrate_lo_setting(dev, &gphy->bbatt, &gphy->rfatt);
|
||||
if (cal) {
|
||||
list_add(&cal->list, &lo->calib_list);
|
||||
b43_lo_write(dev, &cal->ctl);
|
||||
@ -1013,7 +1023,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev)
|
||||
|
||||
void b43_lo_g_cleanup(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_txpower_lo_control *lo = dev->phy.lo_control;
|
||||
struct b43_txpower_lo_control *lo = dev->phy.g->lo_control;
|
||||
struct b43_lo_calib *cal, *tmp;
|
||||
|
||||
if (!lo)
|
||||
@ -1027,9 +1037,7 @@ void b43_lo_g_cleanup(struct b43_wldev *dev)
|
||||
/* LO Initialization */
|
||||
void b43_lo_g_init(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
|
||||
if (b43_has_hardware_pctl(phy)) {
|
||||
if (b43_has_hardware_pctl(dev)) {
|
||||
lo_read_power_vector(dev);
|
||||
b43_gphy_dc_lt_init(dev, 1);
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
#ifndef B43_LO_H_
|
||||
#define B43_LO_H_
|
||||
|
||||
#include "phy.h"
|
||||
/* G-PHY Local Oscillator */
|
||||
|
||||
#include "phy_g.h"
|
||||
|
||||
struct b43_wldev;
|
||||
|
||||
|
@ -44,7 +44,8 @@
|
||||
#include "b43.h"
|
||||
#include "main.h"
|
||||
#include "debugfs.h"
|
||||
#include "phy.h"
|
||||
#include "phy_common.h"
|
||||
#include "phy_g.h"
|
||||
#include "nphy.h"
|
||||
#include "dma.h"
|
||||
#include "pio.h"
|
||||
@ -1174,6 +1175,8 @@ static void b43_calculate_link_quality(struct b43_wldev *dev)
|
||||
{
|
||||
/* Top half of Link Quality calculation. */
|
||||
|
||||
if (dev->phy.type != B43_PHYTYPE_G)
|
||||
return;
|
||||
if (dev->noisecalc.calculation_running)
|
||||
return;
|
||||
dev->noisecalc.calculation_running = 1;
|
||||
@ -1184,7 +1187,7 @@ static void b43_calculate_link_quality(struct b43_wldev *dev)
|
||||
|
||||
static void handle_irq_noise(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_g *phy = dev->phy.g;
|
||||
u16 tmp;
|
||||
u8 noise[4];
|
||||
u8 i, j;
|
||||
@ -1192,6 +1195,9 @@ static void handle_irq_noise(struct b43_wldev *dev)
|
||||
|
||||
/* Bottom half of Link Quality calculation. */
|
||||
|
||||
if (dev->phy.type != B43_PHYTYPE_G)
|
||||
return;
|
||||
|
||||
/* Possible race condition: It might be possible that the user
|
||||
* changed to a different channel in the meantime since we
|
||||
* started the calculation. We ignore that fact, since it's
|
||||
@ -2688,9 +2694,7 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
|
||||
/* This is the opposite of b43_chip_init() */
|
||||
static void b43_chip_exit(struct b43_wldev *dev)
|
||||
{
|
||||
b43_radio_turn_off(dev, 1);
|
||||
b43_gpio_cleanup(dev);
|
||||
b43_lo_g_cleanup(dev);
|
||||
/* firmware is released later */
|
||||
}
|
||||
|
||||
@ -2700,7 +2704,7 @@ static void b43_chip_exit(struct b43_wldev *dev)
|
||||
static int b43_chip_init(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
int err, tmp;
|
||||
int err;
|
||||
u32 value32, macctl;
|
||||
u16 value16;
|
||||
|
||||
@ -2725,19 +2729,19 @@ static int b43_chip_init(struct b43_wldev *dev)
|
||||
err = b43_upload_initvals(dev);
|
||||
if (err)
|
||||
goto err_gpio_clean;
|
||||
b43_radio_turn_on(dev);
|
||||
|
||||
b43_write16(dev, 0x03E6, 0x0000);
|
||||
err = b43_phy_init(dev);
|
||||
if (err)
|
||||
goto err_radio_off;
|
||||
goto err_gpio_clean;
|
||||
|
||||
/* Select initial Interference Mitigation. */
|
||||
tmp = phy->interfmode;
|
||||
phy->interfmode = B43_INTERFMODE_NONE;
|
||||
b43_radio_set_interference_mitigation(dev, tmp);
|
||||
/* Disable Interference Mitigation. */
|
||||
if (phy->ops->interf_mitigation)
|
||||
phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE);
|
||||
|
||||
b43_set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
|
||||
/* Select the antennae */
|
||||
if (phy->ops->set_rx_antenna)
|
||||
phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
|
||||
b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT);
|
||||
|
||||
if (phy->type == B43_PHYTYPE_B) {
|
||||
@ -2790,8 +2794,6 @@ static int b43_chip_init(struct b43_wldev *dev)
|
||||
out:
|
||||
return err;
|
||||
|
||||
err_radio_off:
|
||||
b43_radio_turn_off(dev, 1);
|
||||
err_gpio_clean:
|
||||
b43_gpio_cleanup(dev);
|
||||
return err;
|
||||
@ -2799,25 +2801,13 @@ err_gpio_clean:
|
||||
|
||||
static void b43_periodic_every60sec(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
const struct b43_phy_operations *ops = dev->phy.ops;
|
||||
|
||||
if (phy->type != B43_PHYTYPE_G)
|
||||
return;
|
||||
if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
|
||||
b43_mac_suspend(dev);
|
||||
b43_calc_nrssi_slope(dev);
|
||||
if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) {
|
||||
u8 old_chan = phy->channel;
|
||||
if (ops->pwork_60sec)
|
||||
ops->pwork_60sec(dev);
|
||||
|
||||
/* VCO Calibration */
|
||||
if (old_chan >= 8)
|
||||
b43_radio_selectchannel(dev, 1, 0);
|
||||
else
|
||||
b43_radio_selectchannel(dev, 13, 0);
|
||||
b43_radio_selectchannel(dev, old_chan, 0);
|
||||
}
|
||||
b43_mac_enable(dev);
|
||||
}
|
||||
/* Force check the TX power emission now. */
|
||||
b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME);
|
||||
}
|
||||
|
||||
static void b43_periodic_every30sec(struct b43_wldev *dev)
|
||||
@ -2845,32 +2835,8 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
|
||||
}
|
||||
}
|
||||
|
||||
if (phy->type == B43_PHYTYPE_G) {
|
||||
//TODO: update_aci_moving_average
|
||||
if (phy->aci_enable && phy->aci_wlan_automatic) {
|
||||
b43_mac_suspend(dev);
|
||||
if (!phy->aci_enable && 1 /*TODO: not scanning? */ ) {
|
||||
if (0 /*TODO: bunch of conditions */ ) {
|
||||
b43_radio_set_interference_mitigation
|
||||
(dev, B43_INTERFMODE_MANUALWLAN);
|
||||
}
|
||||
} else if (1 /*TODO*/) {
|
||||
/*
|
||||
if ((aci_average > 1000) && !(b43_radio_aci_scan(dev))) {
|
||||
b43_radio_set_interference_mitigation(dev,
|
||||
B43_INTERFMODE_NONE);
|
||||
}
|
||||
*/
|
||||
}
|
||||
b43_mac_enable(dev);
|
||||
} else if (phy->interfmode == B43_INTERFMODE_NONWLAN &&
|
||||
phy->rev == 1) {
|
||||
//TODO: implement rev1 workaround
|
||||
}
|
||||
}
|
||||
b43_phy_xmitpower(dev); //FIXME: unless scanning?
|
||||
b43_lo_g_maintanance_work(dev);
|
||||
//TODO for APHY (temperature?)
|
||||
if (phy->ops->pwork_15sec)
|
||||
phy->ops->pwork_15sec(dev);
|
||||
|
||||
atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
|
||||
wmb();
|
||||
@ -3401,7 +3367,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
|
||||
/* Switch to the requested channel.
|
||||
* The firmware takes care of races with the TX handler. */
|
||||
if (conf->channel->hw_value != phy->channel)
|
||||
b43_radio_selectchannel(dev, conf->channel->hw_value, 0);
|
||||
b43_switch_channel(dev, conf->channel->hw_value);
|
||||
|
||||
/* Enable/Disable ShortSlot timing. */
|
||||
if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) !=
|
||||
@ -3417,17 +3383,21 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
|
||||
|
||||
/* Adjust the desired TX power level. */
|
||||
if (conf->power_level != 0) {
|
||||
if (conf->power_level != phy->power_level) {
|
||||
phy->power_level = conf->power_level;
|
||||
b43_phy_xmitpower(dev);
|
||||
spin_lock_irqsave(&wl->irq_lock, flags);
|
||||
if (conf->power_level != phy->desired_txpower) {
|
||||
phy->desired_txpower = conf->power_level;
|
||||
b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME |
|
||||
B43_TXPWR_IGNORE_TSSI);
|
||||
}
|
||||
spin_unlock_irqrestore(&wl->irq_lock, flags);
|
||||
}
|
||||
|
||||
/* Antennas for RX and management frame TX. */
|
||||
antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx);
|
||||
b43_mgmtframe_txantenna(dev, antenna);
|
||||
antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx);
|
||||
b43_set_rx_antenna(dev, antenna);
|
||||
if (phy->ops->set_rx_antenna)
|
||||
phy->ops->set_rx_antenna(dev, antenna);
|
||||
|
||||
/* Update templates for AP/mesh mode. */
|
||||
if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) ||
|
||||
@ -3436,7 +3406,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
|
||||
|
||||
if (!!conf->radio_enabled != phy->radio_on) {
|
||||
if (conf->radio_enabled) {
|
||||
b43_radio_turn_on(dev);
|
||||
b43_software_rfkill(dev, RFKILL_STATE_UNBLOCKED);
|
||||
b43info(dev->wl, "Radio turned on by software\n");
|
||||
if (!dev->radio_hw_enable) {
|
||||
b43info(dev->wl, "The hardware RF-kill button "
|
||||
@ -3444,7 +3414,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
|
||||
"Press the button to turn it on.\n");
|
||||
}
|
||||
} else {
|
||||
b43_radio_turn_off(dev, 0);
|
||||
b43_software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
|
||||
b43info(dev->wl, "Radio turned off by software\n");
|
||||
}
|
||||
}
|
||||
@ -3818,48 +3788,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
|
||||
static void setup_struct_phy_for_init(struct b43_wldev *dev,
|
||||
struct b43_phy *phy)
|
||||
{
|
||||
struct b43_txpower_lo_control *lo;
|
||||
int i;
|
||||
|
||||
memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
|
||||
memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
|
||||
|
||||
phy->aci_enable = 0;
|
||||
phy->aci_wlan_automatic = 0;
|
||||
phy->aci_hw_rssi = 0;
|
||||
|
||||
phy->radio_off_context.valid = 0;
|
||||
|
||||
lo = phy->lo_control;
|
||||
if (lo) {
|
||||
memset(lo, 0, sizeof(*(phy->lo_control)));
|
||||
lo->tx_bias = 0xFF;
|
||||
INIT_LIST_HEAD(&lo->calib_list);
|
||||
}
|
||||
phy->max_lb_gain = 0;
|
||||
phy->trsw_rx_gain = 0;
|
||||
phy->txpwr_offset = 0;
|
||||
|
||||
/* NRSSI */
|
||||
phy->nrssislope = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(phy->nrssi); i++)
|
||||
phy->nrssi[i] = -1000;
|
||||
for (i = 0; i < ARRAY_SIZE(phy->nrssi_lt); i++)
|
||||
phy->nrssi_lt[i] = i;
|
||||
|
||||
phy->lofcal = 0xFFFF;
|
||||
phy->initval = 0xFFFF;
|
||||
|
||||
phy->interfmode = B43_INTERFMODE_NONE;
|
||||
phy->channel = 0xFF;
|
||||
|
||||
phy->hardware_power_control = !!modparam_hwpctl;
|
||||
|
||||
phy->next_txpwr_check_time = jiffies;
|
||||
/* PHY TX errors counter. */
|
||||
atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
|
||||
|
||||
/* OFDM-table address caching. */
|
||||
phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_UNKNOWN;
|
||||
}
|
||||
|
||||
static void setup_struct_wldev_for_init(struct b43_wldev *dev)
|
||||
@ -3995,7 +3927,6 @@ static void b43_set_pretbtt(struct b43_wldev *dev)
|
||||
/* Locking: wl->mutex */
|
||||
static void b43_wireless_core_exit(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
u32 macctl;
|
||||
|
||||
B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED);
|
||||
@ -4016,16 +3947,12 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
|
||||
b43_dma_free(dev);
|
||||
b43_pio_free(dev);
|
||||
b43_chip_exit(dev);
|
||||
b43_radio_turn_off(dev, 1);
|
||||
b43_switch_analog(dev, 0);
|
||||
if (phy->dyn_tssi_tbl)
|
||||
kfree(phy->tssi2dbm);
|
||||
kfree(phy->lo_control);
|
||||
phy->lo_control = NULL;
|
||||
if (dev->wl->current_beacon) {
|
||||
dev_kfree_skb_any(dev->wl->current_beacon);
|
||||
dev->wl->current_beacon = NULL;
|
||||
}
|
||||
b43_phy_exit(dev);
|
||||
|
||||
ssb_device_disable(dev->dev, 0);
|
||||
ssb_bus_may_powerdown(dev->dev->bus);
|
||||
@ -4052,29 +3979,24 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
|
||||
b43_wireless_core_reset(dev, tmp);
|
||||
}
|
||||
|
||||
if ((phy->type == B43_PHYTYPE_B) || (phy->type == B43_PHYTYPE_G)) {
|
||||
phy->lo_control =
|
||||
kzalloc(sizeof(*(phy->lo_control)), GFP_KERNEL);
|
||||
if (!phy->lo_control) {
|
||||
err = -ENOMEM;
|
||||
goto err_busdown;
|
||||
}
|
||||
}
|
||||
setup_struct_wldev_for_init(dev);
|
||||
|
||||
err = b43_phy_init_tssi2dbm_table(dev);
|
||||
err = b43_phy_operations_setup(dev);
|
||||
if (err)
|
||||
goto err_kfree_lo_control;
|
||||
goto err_busdown;
|
||||
|
||||
/* Enable IRQ routing to this device. */
|
||||
ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev);
|
||||
|
||||
b43_imcfglo_timeouts_workaround(dev);
|
||||
b43_bluetooth_coext_disable(dev);
|
||||
b43_phy_early_init(dev);
|
||||
if (phy->ops->prepare) {
|
||||
err = phy->ops->prepare(dev);
|
||||
if (err)
|
||||
goto err_phy_exit;
|
||||
}
|
||||
err = b43_chip_init(dev);
|
||||
if (err)
|
||||
goto err_kfree_tssitbl;
|
||||
goto err_phy_exit;
|
||||
b43_shm_write16(dev, B43_SHM_SHARED,
|
||||
B43_SHM_SH_WLCOREREV, dev->dev->id.revision);
|
||||
hf = b43_hf_read(dev);
|
||||
@ -4140,15 +4062,11 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
|
||||
out:
|
||||
return err;
|
||||
|
||||
err_chip_exit:
|
||||
err_chip_exit:
|
||||
b43_chip_exit(dev);
|
||||
err_kfree_tssitbl:
|
||||
if (phy->dyn_tssi_tbl)
|
||||
kfree(phy->tssi2dbm);
|
||||
err_kfree_lo_control:
|
||||
kfree(phy->lo_control);
|
||||
phy->lo_control = NULL;
|
||||
err_busdown:
|
||||
err_phy_exit:
|
||||
b43_phy_exit(dev);
|
||||
err_busdown:
|
||||
ssb_bus_may_powerdown(bus);
|
||||
B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
|
||||
return err;
|
||||
@ -4291,6 +4209,8 @@ static void b43_op_stop(struct ieee80211_hw *hw)
|
||||
b43_wireless_core_stop(dev);
|
||||
b43_wireless_core_exit(dev);
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
cancel_work_sync(&(wl->txpower_adjust_work));
|
||||
}
|
||||
|
||||
static int b43_op_set_retry_limit(struct ieee80211_hw *hw,
|
||||
@ -4511,7 +4431,6 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
|
||||
wl->current_dev = dev;
|
||||
INIT_WORK(&dev->restart_work, b43_chip_reset);
|
||||
|
||||
b43_radio_turn_off(dev, 1);
|
||||
b43_switch_analog(dev, 0);
|
||||
ssb_device_disable(dev->dev, 0);
|
||||
ssb_bus_may_powerdown(bus);
|
||||
@ -4669,6 +4588,7 @@ static int b43_wireless_init(struct ssb_device *dev)
|
||||
INIT_LIST_HEAD(&wl->devlist);
|
||||
INIT_WORK(&wl->qos_update_work, b43_qos_update_work);
|
||||
INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
|
||||
INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work);
|
||||
|
||||
ssb_set_devtypedata(dev, wl);
|
||||
b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
|
||||
|
@ -34,10 +34,16 @@ void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
|
||||
{//TODO
|
||||
}
|
||||
|
||||
void b43_nphy_xmitpower(struct b43_wldev *dev)
|
||||
static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
|
||||
{//TODO
|
||||
}
|
||||
|
||||
static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
|
||||
bool ignore_tssi)
|
||||
{//TODO
|
||||
return B43_TXPWR_RES_DONE;
|
||||
}
|
||||
|
||||
static void b43_chantab_radio_upload(struct b43_wldev *dev,
|
||||
const struct b43_nphy_channeltab_entry *e)
|
||||
{
|
||||
@ -81,9 +87,8 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
|
||||
//TODO
|
||||
}
|
||||
|
||||
/* Tune the hardware to a new channel. Don't call this directly.
|
||||
* Use b43_radio_selectchannel() */
|
||||
int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel)
|
||||
/* Tune the hardware to a new channel. */
|
||||
static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
|
||||
{
|
||||
const struct b43_nphy_channeltab_entry *tabent;
|
||||
|
||||
@ -162,7 +167,7 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
|
||||
msleep(1);
|
||||
b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
|
||||
msleep(1);
|
||||
b43_radio_selectchannel(dev, dev->phy.channel, 0);
|
||||
nphy_channel_switch(dev, dev->phy.channel);
|
||||
b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9);
|
||||
b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9);
|
||||
b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
|
||||
@ -484,3 +489,136 @@ int b43_phy_initn(struct b43_wldev *dev)
|
||||
b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int b43_nphy_op_allocate(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_n *nphy;
|
||||
|
||||
nphy = kzalloc(sizeof(*nphy), GFP_KERNEL);
|
||||
if (!nphy)
|
||||
return -ENOMEM;
|
||||
dev->phy.n = nphy;
|
||||
|
||||
//TODO init struct b43_phy_n
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int b43_nphy_op_init(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
int err;
|
||||
|
||||
err = b43_phy_initn(dev);
|
||||
if (err)
|
||||
return err;
|
||||
nphy->initialised = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void b43_nphy_op_exit(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_n *nphy = dev->phy.n;
|
||||
|
||||
if (nphy->initialised) {
|
||||
//TODO
|
||||
nphy->initialised = 0;
|
||||
}
|
||||
//TODO
|
||||
kfree(nphy);
|
||||
dev->phy.n = NULL;
|
||||
}
|
||||
|
||||
static inline void check_phyreg(struct b43_wldev *dev, u16 offset)
|
||||
{
|
||||
#if B43_DEBUG
|
||||
if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
|
||||
/* OFDM registers are onnly available on A/G-PHYs */
|
||||
b43err(dev->wl, "Invalid OFDM PHY access at "
|
||||
"0x%04X on N-PHY\n", offset);
|
||||
dump_stack();
|
||||
}
|
||||
if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
|
||||
/* Ext-G registers are only available on G-PHYs */
|
||||
b43err(dev->wl, "Invalid EXT-G PHY access at "
|
||||
"0x%04X on N-PHY\n", offset);
|
||||
dump_stack();
|
||||
}
|
||||
#endif /* B43_DEBUG */
|
||||
}
|
||||
|
||||
static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
|
||||
{
|
||||
check_phyreg(dev, reg);
|
||||
b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
|
||||
return b43_read16(dev, B43_MMIO_PHY_DATA);
|
||||
}
|
||||
|
||||
static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
|
||||
{
|
||||
check_phyreg(dev, reg);
|
||||
b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
|
||||
b43_write16(dev, B43_MMIO_PHY_DATA, value);
|
||||
}
|
||||
|
||||
static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
|
||||
{
|
||||
/* Register 1 is a 32-bit register. */
|
||||
B43_WARN_ON(reg == 1);
|
||||
/* N-PHY needs 0x100 for read access */
|
||||
reg |= 0x100;
|
||||
|
||||
b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
|
||||
return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
|
||||
}
|
||||
|
||||
static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
|
||||
{
|
||||
/* Register 1 is a 32-bit register. */
|
||||
B43_WARN_ON(reg == 1);
|
||||
|
||||
b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
|
||||
b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
|
||||
}
|
||||
|
||||
static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
|
||||
enum rfkill_state state)
|
||||
{//TODO
|
||||
}
|
||||
|
||||
static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
|
||||
unsigned int new_channel)
|
||||
{
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
if ((new_channel < 1) || (new_channel > 14))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (new_channel > 200)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return nphy_channel_switch(dev, new_channel);
|
||||
}
|
||||
|
||||
static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
|
||||
{
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
|
||||
return 1;
|
||||
return 36;
|
||||
}
|
||||
|
||||
const struct b43_phy_operations b43_phyops_n = {
|
||||
.allocate = b43_nphy_op_allocate,
|
||||
.init = b43_nphy_op_init,
|
||||
.exit = b43_nphy_op_exit,
|
||||
.phy_read = b43_nphy_op_read,
|
||||
.phy_write = b43_nphy_op_write,
|
||||
.radio_read = b43_nphy_op_radio_read,
|
||||
.radio_write = b43_nphy_op_radio_write,
|
||||
.software_rfkill = b43_nphy_op_software_rfkill,
|
||||
.switch_channel = b43_nphy_op_switch_channel,
|
||||
.get_default_chan = b43_nphy_op_get_default_chan,
|
||||
.recalc_txpower = b43_nphy_op_recalc_txpower,
|
||||
.adjust_txpower = b43_nphy_op_adjust_txpower,
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef B43_NPHY_H_
|
||||
#define B43_NPHY_H_
|
||||
|
||||
#include "phy.h"
|
||||
#include "phy_common.h"
|
||||
|
||||
|
||||
/* N-PHY registers. */
|
||||
@ -919,54 +919,14 @@
|
||||
|
||||
struct b43_wldev;
|
||||
|
||||
struct b43_phy_n {
|
||||
bool initialised;
|
||||
|
||||
#ifdef CONFIG_B43_NPHY
|
||||
/* N-PHY support enabled */
|
||||
|
||||
int b43_phy_initn(struct b43_wldev *dev);
|
||||
|
||||
void b43_nphy_radio_turn_on(struct b43_wldev *dev);
|
||||
void b43_nphy_radio_turn_off(struct b43_wldev *dev);
|
||||
|
||||
int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel);
|
||||
|
||||
void b43_nphy_xmitpower(struct b43_wldev *dev);
|
||||
void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna);
|
||||
//TODO lots of missing stuff
|
||||
};
|
||||
|
||||
|
||||
#else /* CONFIG_B43_NPHY */
|
||||
/* N-PHY support disabled */
|
||||
struct b43_phy_operations;
|
||||
extern const struct b43_phy_operations b43_phyops_n;
|
||||
|
||||
|
||||
static inline
|
||||
int b43_phy_initn(struct b43_wldev *dev)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline
|
||||
void b43_nphy_radio_turn_on(struct b43_wldev *dev)
|
||||
{
|
||||
}
|
||||
static inline
|
||||
void b43_nphy_radio_turn_off(struct b43_wldev *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline
|
||||
void b43_nphy_xmitpower(struct b43_wldev *dev)
|
||||
{
|
||||
}
|
||||
static inline
|
||||
void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_B43_NPHY */
|
||||
#endif /* B43_NPHY_H_ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,340 +0,0 @@
|
||||
#ifndef B43_PHY_H_
|
||||
#define B43_PHY_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct b43_wldev;
|
||||
struct b43_phy;
|
||||
|
||||
/*** PHY Registers ***/
|
||||
|
||||
/* Routing */
|
||||
#define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */
|
||||
#define B43_PHYROUTE_BASE 0x0000 /* Base registers */
|
||||
#define B43_PHYROUTE_OFDM_GPHY 0x0400 /* OFDM register routing for G-PHYs */
|
||||
#define B43_PHYROUTE_EXT_GPHY 0x0800 /* Extended G-PHY registers */
|
||||
#define B43_PHYROUTE_N_BMODE 0x0C00 /* N-PHY BMODE registers */
|
||||
|
||||
/* CCK (B-PHY) registers. */
|
||||
#define B43_PHY_CCK(reg) ((reg) | B43_PHYROUTE_BASE)
|
||||
/* N-PHY registers. */
|
||||
#define B43_PHY_N(reg) ((reg) | B43_PHYROUTE_BASE)
|
||||
/* N-PHY BMODE registers. */
|
||||
#define B43_PHY_N_BMODE(reg) ((reg) | B43_PHYROUTE_N_BMODE)
|
||||
/* OFDM (A-PHY) registers. */
|
||||
#define B43_PHY_OFDM(reg) ((reg) | B43_PHYROUTE_OFDM_GPHY)
|
||||
/* Extended G-PHY registers. */
|
||||
#define B43_PHY_EXTG(reg) ((reg) | B43_PHYROUTE_EXT_GPHY)
|
||||
|
||||
/* OFDM (A) PHY Registers */
|
||||
#define B43_PHY_VERSION_OFDM B43_PHY_OFDM(0x00) /* Versioning register for A-PHY */
|
||||
#define B43_PHY_BBANDCFG B43_PHY_OFDM(0x01) /* Baseband config */
|
||||
#define B43_PHY_BBANDCFG_RXANT 0x180 /* RX Antenna selection */
|
||||
#define B43_PHY_BBANDCFG_RXANT_SHIFT 7
|
||||
#define B43_PHY_PWRDOWN B43_PHY_OFDM(0x03) /* Powerdown */
|
||||
#define B43_PHY_CRSTHRES1_R1 B43_PHY_OFDM(0x06) /* CRS Threshold 1 (phy.rev 1 only) */
|
||||
#define B43_PHY_LNAHPFCTL B43_PHY_OFDM(0x1C) /* LNA/HPF control */
|
||||
#define B43_PHY_LPFGAINCTL B43_PHY_OFDM(0x20) /* LPF Gain control */
|
||||
#define B43_PHY_ADIVRELATED B43_PHY_OFDM(0x27) /* FIXME rename */
|
||||
#define B43_PHY_CRS0 B43_PHY_OFDM(0x29)
|
||||
#define B43_PHY_CRS0_EN 0x4000
|
||||
#define B43_PHY_PEAK_COUNT B43_PHY_OFDM(0x30)
|
||||
#define B43_PHY_ANTDWELL B43_PHY_OFDM(0x2B) /* Antenna dwell */
|
||||
#define B43_PHY_ANTDWELL_AUTODIV1 0x0100 /* Automatic RX diversity start antenna */
|
||||
#define B43_PHY_ENCORE B43_PHY_OFDM(0x49) /* "Encore" (RangeMax / BroadRange) */
|
||||
#define B43_PHY_ENCORE_EN 0x0200 /* Encore enable */
|
||||
#define B43_PHY_LMS B43_PHY_OFDM(0x55)
|
||||
#define B43_PHY_OFDM61 B43_PHY_OFDM(0x61) /* FIXME rename */
|
||||
#define B43_PHY_OFDM61_10 0x0010 /* FIXME rename */
|
||||
#define B43_PHY_IQBAL B43_PHY_OFDM(0x69) /* I/Q balance */
|
||||
#define B43_PHY_BBTXDC_BIAS B43_PHY_OFDM(0x6B) /* Baseband TX DC bias */
|
||||
#define B43_PHY_OTABLECTL B43_PHY_OFDM(0x72) /* OFDM table control (see below) */
|
||||
#define B43_PHY_OTABLEOFF 0x03FF /* OFDM table offset (see below) */
|
||||
#define B43_PHY_OTABLENR 0xFC00 /* OFDM table number (see below) */
|
||||
#define B43_PHY_OTABLENR_SHIFT 10
|
||||
#define B43_PHY_OTABLEI B43_PHY_OFDM(0x73) /* OFDM table data I */
|
||||
#define B43_PHY_OTABLEQ B43_PHY_OFDM(0x74) /* OFDM table data Q */
|
||||
#define B43_PHY_HPWR_TSSICTL B43_PHY_OFDM(0x78) /* Hardware power TSSI control */
|
||||
#define B43_PHY_ADCCTL B43_PHY_OFDM(0x7A) /* ADC control */
|
||||
#define B43_PHY_IDLE_TSSI B43_PHY_OFDM(0x7B)
|
||||
#define B43_PHY_A_TEMP_SENSE B43_PHY_OFDM(0x7C) /* A PHY temperature sense */
|
||||
#define B43_PHY_NRSSITHRES B43_PHY_OFDM(0x8A) /* NRSSI threshold */
|
||||
#define B43_PHY_ANTWRSETT B43_PHY_OFDM(0x8C) /* Antenna WR settle */
|
||||
#define B43_PHY_ANTWRSETT_ARXDIV 0x2000 /* Automatic RX diversity enabled */
|
||||
#define B43_PHY_CLIPPWRDOWNT B43_PHY_OFDM(0x93) /* Clip powerdown threshold */
|
||||
#define B43_PHY_OFDM9B B43_PHY_OFDM(0x9B) /* FIXME rename */
|
||||
#define B43_PHY_N1P1GAIN B43_PHY_OFDM(0xA0)
|
||||
#define B43_PHY_P1P2GAIN B43_PHY_OFDM(0xA1)
|
||||
#define B43_PHY_N1N2GAIN B43_PHY_OFDM(0xA2)
|
||||
#define B43_PHY_CLIPTHRES B43_PHY_OFDM(0xA3)
|
||||
#define B43_PHY_CLIPN1P2THRES B43_PHY_OFDM(0xA4)
|
||||
#define B43_PHY_CCKSHIFTBITS_WA B43_PHY_OFDM(0xA5) /* CCK shiftbits workaround, FIXME rename */
|
||||
#define B43_PHY_CCKSHIFTBITS B43_PHY_OFDM(0xA7) /* FIXME rename */
|
||||
#define B43_PHY_DIVSRCHIDX B43_PHY_OFDM(0xA8) /* Divider search gain/index */
|
||||
#define B43_PHY_CLIPP2THRES B43_PHY_OFDM(0xA9)
|
||||
#define B43_PHY_CLIPP3THRES B43_PHY_OFDM(0xAA)
|
||||
#define B43_PHY_DIVP1P2GAIN B43_PHY_OFDM(0xAB)
|
||||
#define B43_PHY_DIVSRCHGAINBACK B43_PHY_OFDM(0xAD) /* Divider search gain back */
|
||||
#define B43_PHY_DIVSRCHGAINCHNG B43_PHY_OFDM(0xAE) /* Divider search gain change */
|
||||
#define B43_PHY_CRSTHRES1 B43_PHY_OFDM(0xC0) /* CRS Threshold 1 (phy.rev >= 2 only) */
|
||||
#define B43_PHY_CRSTHRES2 B43_PHY_OFDM(0xC1) /* CRS Threshold 2 (phy.rev >= 2 only) */
|
||||
#define B43_PHY_TSSIP_LTBASE B43_PHY_OFDM(0x380) /* TSSI power lookup table base */
|
||||
#define B43_PHY_DC_LTBASE B43_PHY_OFDM(0x3A0) /* DC lookup table base */
|
||||
#define B43_PHY_GAIN_LTBASE B43_PHY_OFDM(0x3C0) /* Gain lookup table base */
|
||||
|
||||
/* CCK (B) PHY Registers */
|
||||
#define B43_PHY_VERSION_CCK B43_PHY_CCK(0x00) /* Versioning register for B-PHY */
|
||||
#define B43_PHY_CCKBBANDCFG B43_PHY_CCK(0x01) /* Contains antenna 0/1 control bit */
|
||||
#define B43_PHY_PGACTL B43_PHY_CCK(0x15) /* PGA control */
|
||||
#define B43_PHY_PGACTL_LPF 0x1000 /* Low pass filter (?) */
|
||||
#define B43_PHY_PGACTL_LOWBANDW 0x0040 /* Low bandwidth flag */
|
||||
#define B43_PHY_PGACTL_UNKNOWN 0xEFA0
|
||||
#define B43_PHY_FBCTL1 B43_PHY_CCK(0x18) /* Frequency bandwidth control 1 */
|
||||
#define B43_PHY_ITSSI B43_PHY_CCK(0x29) /* Idle TSSI */
|
||||
#define B43_PHY_LO_LEAKAGE B43_PHY_CCK(0x2D) /* Measured LO leakage */
|
||||
#define B43_PHY_ENERGY B43_PHY_CCK(0x33) /* Energy */
|
||||
#define B43_PHY_SYNCCTL B43_PHY_CCK(0x35)
|
||||
#define B43_PHY_FBCTL2 B43_PHY_CCK(0x38) /* Frequency bandwidth control 2 */
|
||||
#define B43_PHY_DACCTL B43_PHY_CCK(0x60) /* DAC control */
|
||||
#define B43_PHY_RCCALOVER B43_PHY_CCK(0x78) /* RC calibration override */
|
||||
|
||||
/* Extended G-PHY Registers */
|
||||
#define B43_PHY_CLASSCTL B43_PHY_EXTG(0x02) /* Classify control */
|
||||
#define B43_PHY_GTABCTL B43_PHY_EXTG(0x03) /* G-PHY table control (see below) */
|
||||
#define B43_PHY_GTABOFF 0x03FF /* G-PHY table offset (see below) */
|
||||
#define B43_PHY_GTABNR 0xFC00 /* G-PHY table number (see below) */
|
||||
#define B43_PHY_GTABNR_SHIFT 10
|
||||
#define B43_PHY_GTABDATA B43_PHY_EXTG(0x04) /* G-PHY table data */
|
||||
#define B43_PHY_LO_MASK B43_PHY_EXTG(0x0F) /* Local Oscillator control mask */
|
||||
#define B43_PHY_LO_CTL B43_PHY_EXTG(0x10) /* Local Oscillator control */
|
||||
#define B43_PHY_RFOVER B43_PHY_EXTG(0x11) /* RF override */
|
||||
#define B43_PHY_RFOVERVAL B43_PHY_EXTG(0x12) /* RF override value */
|
||||
#define B43_PHY_RFOVERVAL_EXTLNA 0x8000
|
||||
#define B43_PHY_RFOVERVAL_LNA 0x7000
|
||||
#define B43_PHY_RFOVERVAL_LNA_SHIFT 12
|
||||
#define B43_PHY_RFOVERVAL_PGA 0x0F00
|
||||
#define B43_PHY_RFOVERVAL_PGA_SHIFT 8
|
||||
#define B43_PHY_RFOVERVAL_UNK 0x0010 /* Unknown, always set. */
|
||||
#define B43_PHY_RFOVERVAL_TRSWRX 0x00E0
|
||||
#define B43_PHY_RFOVERVAL_BW 0x0003 /* Bandwidth flags */
|
||||
#define B43_PHY_RFOVERVAL_BW_LPF 0x0001 /* Low Pass Filter */
|
||||
#define B43_PHY_RFOVERVAL_BW_LBW 0x0002 /* Low Bandwidth (when set), high when unset */
|
||||
#define B43_PHY_ANALOGOVER B43_PHY_EXTG(0x14) /* Analog override */
|
||||
#define B43_PHY_ANALOGOVERVAL B43_PHY_EXTG(0x15) /* Analog override value */
|
||||
|
||||
/*** OFDM table numbers ***/
|
||||
#define B43_OFDMTAB(number, offset) (((number) << B43_PHY_OTABLENR_SHIFT) | (offset))
|
||||
#define B43_OFDMTAB_AGC1 B43_OFDMTAB(0x00, 0)
|
||||
#define B43_OFDMTAB_GAIN0 B43_OFDMTAB(0x00, 0)
|
||||
#define B43_OFDMTAB_GAINX B43_OFDMTAB(0x01, 0) //TODO rename
|
||||
#define B43_OFDMTAB_GAIN1 B43_OFDMTAB(0x01, 4)
|
||||
#define B43_OFDMTAB_AGC3 B43_OFDMTAB(0x02, 0)
|
||||
#define B43_OFDMTAB_GAIN2 B43_OFDMTAB(0x02, 3)
|
||||
#define B43_OFDMTAB_LNAHPFGAIN1 B43_OFDMTAB(0x03, 0)
|
||||
#define B43_OFDMTAB_WRSSI B43_OFDMTAB(0x04, 0)
|
||||
#define B43_OFDMTAB_LNAHPFGAIN2 B43_OFDMTAB(0x04, 0)
|
||||
#define B43_OFDMTAB_NOISESCALE B43_OFDMTAB(0x05, 0)
|
||||
#define B43_OFDMTAB_AGC2 B43_OFDMTAB(0x06, 0)
|
||||
#define B43_OFDMTAB_ROTOR B43_OFDMTAB(0x08, 0)
|
||||
#define B43_OFDMTAB_ADVRETARD B43_OFDMTAB(0x09, 0)
|
||||
#define B43_OFDMTAB_DAC B43_OFDMTAB(0x0C, 0)
|
||||
#define B43_OFDMTAB_DC B43_OFDMTAB(0x0E, 7)
|
||||
#define B43_OFDMTAB_PWRDYN2 B43_OFDMTAB(0x0E, 12)
|
||||
#define B43_OFDMTAB_LNAGAIN B43_OFDMTAB(0x0E, 13)
|
||||
#define B43_OFDMTAB_UNKNOWN_0F B43_OFDMTAB(0x0F, 0) //TODO rename
|
||||
#define B43_OFDMTAB_UNKNOWN_APHY B43_OFDMTAB(0x0F, 7) //TODO rename
|
||||
#define B43_OFDMTAB_LPFGAIN B43_OFDMTAB(0x0F, 12)
|
||||
#define B43_OFDMTAB_RSSI B43_OFDMTAB(0x10, 0)
|
||||
#define B43_OFDMTAB_UNKNOWN_11 B43_OFDMTAB(0x11, 4) //TODO rename
|
||||
#define B43_OFDMTAB_AGC1_R1 B43_OFDMTAB(0x13, 0)
|
||||
#define B43_OFDMTAB_GAINX_R1 B43_OFDMTAB(0x14, 0) //TODO remove!
|
||||
#define B43_OFDMTAB_MINSIGSQ B43_OFDMTAB(0x14, 0)
|
||||
#define B43_OFDMTAB_AGC3_R1 B43_OFDMTAB(0x15, 0)
|
||||
#define B43_OFDMTAB_WRSSI_R1 B43_OFDMTAB(0x15, 4)
|
||||
#define B43_OFDMTAB_TSSI B43_OFDMTAB(0x15, 0)
|
||||
#define B43_OFDMTAB_DACRFPABB B43_OFDMTAB(0x16, 0)
|
||||
#define B43_OFDMTAB_DACOFF B43_OFDMTAB(0x17, 0)
|
||||
#define B43_OFDMTAB_DCBIAS B43_OFDMTAB(0x18, 0)
|
||||
|
||||
u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset);
|
||||
void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
|
||||
u16 offset, u16 value);
|
||||
u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset);
|
||||
void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
|
||||
u16 offset, u32 value);
|
||||
|
||||
/*** G-PHY table numbers */
|
||||
#define B43_GTAB(number, offset) (((number) << B43_PHY_GTABNR_SHIFT) | (offset))
|
||||
#define B43_GTAB_NRSSI B43_GTAB(0x00, 0)
|
||||
#define B43_GTAB_TRFEMW B43_GTAB(0x0C, 0x120)
|
||||
#define B43_GTAB_ORIGTR B43_GTAB(0x2E, 0x298)
|
||||
|
||||
u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset); //TODO implement
|
||||
void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value); //TODO implement
|
||||
|
||||
#define B43_DEFAULT_CHANNEL_A 36
|
||||
#define B43_DEFAULT_CHANNEL_BG 6
|
||||
|
||||
enum {
|
||||
B43_ANTENNA0, /* Antenna 0 */
|
||||
B43_ANTENNA1, /* Antenna 0 */
|
||||
B43_ANTENNA_AUTO1, /* Automatic, starting with antenna 1 */
|
||||
B43_ANTENNA_AUTO0, /* Automatic, starting with antenna 0 */
|
||||
B43_ANTENNA2,
|
||||
B43_ANTENNA3 = 8,
|
||||
|
||||
B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0,
|
||||
B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO,
|
||||
};
|
||||
|
||||
enum {
|
||||
B43_INTERFMODE_NONE,
|
||||
B43_INTERFMODE_NONWLAN,
|
||||
B43_INTERFMODE_MANUALWLAN,
|
||||
B43_INTERFMODE_AUTOWLAN,
|
||||
};
|
||||
|
||||
/* Masks for the different PHY versioning registers. */
|
||||
#define B43_PHYVER_ANALOG 0xF000
|
||||
#define B43_PHYVER_ANALOG_SHIFT 12
|
||||
#define B43_PHYVER_TYPE 0x0F00
|
||||
#define B43_PHYVER_TYPE_SHIFT 8
|
||||
#define B43_PHYVER_VERSION 0x00FF
|
||||
|
||||
void b43_phy_lock(struct b43_wldev *dev);
|
||||
void b43_phy_unlock(struct b43_wldev *dev);
|
||||
|
||||
|
||||
/* Read a value from a PHY register */
|
||||
u16 b43_phy_read(struct b43_wldev *dev, u16 offset);
|
||||
/* Write a value to a PHY register */
|
||||
void b43_phy_write(struct b43_wldev *dev, u16 offset, u16 val);
|
||||
/* Mask a PHY register with a mask */
|
||||
void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask);
|
||||
/* OR a PHY register with a bitmap */
|
||||
void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set);
|
||||
/* Mask and OR a PHY register with a mask and bitmap */
|
||||
void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
|
||||
|
||||
|
||||
int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev);
|
||||
|
||||
void b43_phy_early_init(struct b43_wldev *dev);
|
||||
int b43_phy_init(struct b43_wldev *dev);
|
||||
|
||||
void b43_set_rx_antenna(struct b43_wldev *dev, int antenna);
|
||||
|
||||
void b43_phy_xmitpower(struct b43_wldev *dev);
|
||||
|
||||
/* Returns the boolean whether the board has HardwarePowerControl */
|
||||
bool b43_has_hardware_pctl(struct b43_phy *phy);
|
||||
/* Returns the boolean whether "TX Magnification" is enabled. */
|
||||
#define has_tx_magnification(phy) \
|
||||
(((phy)->rev >= 2) && \
|
||||
((phy)->radio_ver == 0x2050) && \
|
||||
((phy)->radio_rev == 8))
|
||||
/* Card uses the loopback gain stuff */
|
||||
#define has_loopback_gain(phy) \
|
||||
(((phy)->rev > 1) || ((phy)->gmode))
|
||||
|
||||
/* Radio Attenuation (RF Attenuation) */
|
||||
struct b43_rfatt {
|
||||
u8 att; /* Attenuation value */
|
||||
bool with_padmix; /* Flag, PAD Mixer enabled. */
|
||||
};
|
||||
struct b43_rfatt_list {
|
||||
/* Attenuation values list */
|
||||
const struct b43_rfatt *list;
|
||||
u8 len;
|
||||
/* Minimum/Maximum attenuation values */
|
||||
u8 min_val;
|
||||
u8 max_val;
|
||||
};
|
||||
|
||||
/* Returns true, if the values are the same. */
|
||||
static inline bool b43_compare_rfatt(const struct b43_rfatt *a,
|
||||
const struct b43_rfatt *b)
|
||||
{
|
||||
return ((a->att == b->att) &&
|
||||
(a->with_padmix == b->with_padmix));
|
||||
}
|
||||
|
||||
/* Baseband Attenuation */
|
||||
struct b43_bbatt {
|
||||
u8 att; /* Attenuation value */
|
||||
};
|
||||
struct b43_bbatt_list {
|
||||
/* Attenuation values list */
|
||||
const struct b43_bbatt *list;
|
||||
u8 len;
|
||||
/* Minimum/Maximum attenuation values */
|
||||
u8 min_val;
|
||||
u8 max_val;
|
||||
};
|
||||
|
||||
/* Returns true, if the values are the same. */
|
||||
static inline bool b43_compare_bbatt(const struct b43_bbatt *a,
|
||||
const struct b43_bbatt *b)
|
||||
{
|
||||
return (a->att == b->att);
|
||||
}
|
||||
|
||||
/* tx_control bits. */
|
||||
#define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */
|
||||
#define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */
|
||||
#define B43_TXCTL_TXMIX 0x10 /* TX Mixer Gain */
|
||||
|
||||
/* Write BasebandAttenuation value to the device. */
|
||||
void b43_phy_set_baseband_attenuation(struct b43_wldev *dev,
|
||||
u16 baseband_attenuation);
|
||||
|
||||
extern const u8 b43_radio_channel_codes_bg[];
|
||||
|
||||
void b43_radio_lock(struct b43_wldev *dev);
|
||||
void b43_radio_unlock(struct b43_wldev *dev);
|
||||
|
||||
|
||||
/* Read a value from a 16bit radio register */
|
||||
u16 b43_radio_read16(struct b43_wldev *dev, u16 offset);
|
||||
/* Write a value to a 16bit radio register */
|
||||
void b43_radio_write16(struct b43_wldev *dev, u16 offset, u16 val);
|
||||
/* Mask a 16bit radio register with a mask */
|
||||
void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask);
|
||||
/* OR a 16bit radio register with a bitmap */
|
||||
void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set);
|
||||
/* Mask and OR a PHY register with a mask and bitmap */
|
||||
void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
|
||||
|
||||
|
||||
u16 b43_radio_init2050(struct b43_wldev *dev);
|
||||
void b43_radio_init2060(struct b43_wldev *dev);
|
||||
|
||||
void b43_radio_turn_on(struct b43_wldev *dev);
|
||||
void b43_radio_turn_off(struct b43_wldev *dev, bool force);
|
||||
|
||||
int b43_radio_selectchannel(struct b43_wldev *dev, u8 channel,
|
||||
int synthetic_pu_workaround);
|
||||
|
||||
u8 b43_radio_aci_detect(struct b43_wldev *dev, u8 channel);
|
||||
u8 b43_radio_aci_scan(struct b43_wldev *dev);
|
||||
|
||||
int b43_radio_set_interference_mitigation(struct b43_wldev *dev, int mode);
|
||||
|
||||
void b43_calc_nrssi_slope(struct b43_wldev *dev);
|
||||
void b43_calc_nrssi_threshold(struct b43_wldev *dev);
|
||||
s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset);
|
||||
void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val);
|
||||
void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val);
|
||||
void b43_nrssi_mem_update(struct b43_wldev *dev);
|
||||
|
||||
void b43_radio_set_tx_iq(struct b43_wldev *dev);
|
||||
u16 b43_radio_calibrationvalue(struct b43_wldev *dev);
|
||||
|
||||
void b43_put_attenuation_into_ranges(struct b43_wldev *dev,
|
||||
int *_bbatt, int *_rfatt);
|
||||
|
||||
void b43_set_txpower_g(struct b43_wldev *dev,
|
||||
const struct b43_bbatt *bbatt,
|
||||
const struct b43_rfatt *rfatt, u8 tx_control);
|
||||
|
||||
#endif /* B43_PHY_H_ */
|
543
drivers/net/wireless/b43/phy_a.c
Normal file
543
drivers/net/wireless/b43/phy_a.c
Normal file
@ -0,0 +1,543 @@
|
||||
/*
|
||||
|
||||
Broadcom B43 wireless driver
|
||||
IEEE 802.11a PHY driver
|
||||
|
||||
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
|
||||
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
|
||||
Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
|
||||
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
|
||||
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "b43.h"
|
||||
#include "phy_a.h"
|
||||
#include "phy_common.h"
|
||||
#include "wa.h"
|
||||
#include "tables.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
/* Get the freq, as it has to be written to the device. */
|
||||
static inline u16 channel2freq_a(u8 channel)
|
||||
{
|
||||
B43_WARN_ON(channel > 200);
|
||||
|
||||
return (5000 + 5 * channel);
|
||||
}
|
||||
|
||||
static inline u16 freq_r3A_value(u16 frequency)
|
||||
{
|
||||
u16 value;
|
||||
|
||||
if (frequency < 5091)
|
||||
value = 0x0040;
|
||||
else if (frequency < 5321)
|
||||
value = 0x0000;
|
||||
else if (frequency < 5806)
|
||||
value = 0x0080;
|
||||
else
|
||||
value = 0x0040;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void b43_radio_set_tx_iq(struct b43_wldev *dev)
|
||||
{
|
||||
static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
|
||||
static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
|
||||
u16 tmp = b43_radio_read16(dev, 0x001E);
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
for (j = 0; j < 5; j++) {
|
||||
if (tmp == (data_high[i] << 4 | data_low[j])) {
|
||||
b43_phy_write(dev, 0x0069,
|
||||
(i - j) << 8 | 0x00C0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void aphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
|
||||
{
|
||||
u16 freq, r8, tmp;
|
||||
|
||||
freq = channel2freq_a(channel);
|
||||
|
||||
r8 = b43_radio_read16(dev, 0x0008);
|
||||
b43_write16(dev, 0x03F0, freq);
|
||||
b43_radio_write16(dev, 0x0008, r8);
|
||||
|
||||
//TODO: write max channel TX power? to Radio 0x2D
|
||||
tmp = b43_radio_read16(dev, 0x002E);
|
||||
tmp &= 0x0080;
|
||||
//TODO: OR tmp with the Power out estimation for this channel?
|
||||
b43_radio_write16(dev, 0x002E, tmp);
|
||||
|
||||
if (freq >= 4920 && freq <= 5500) {
|
||||
/*
|
||||
* r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
|
||||
* = (freq * 0.025862069
|
||||
*/
|
||||
r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
|
||||
}
|
||||
b43_radio_write16(dev, 0x0007, (r8 << 4) | r8);
|
||||
b43_radio_write16(dev, 0x0020, (r8 << 4) | r8);
|
||||
b43_radio_write16(dev, 0x0021, (r8 << 4) | r8);
|
||||
b43_radio_write16(dev, 0x0022, (b43_radio_read16(dev, 0x0022)
|
||||
& 0x000F) | (r8 << 4));
|
||||
b43_radio_write16(dev, 0x002A, (r8 << 4));
|
||||
b43_radio_write16(dev, 0x002B, (r8 << 4));
|
||||
b43_radio_write16(dev, 0x0008, (b43_radio_read16(dev, 0x0008)
|
||||
& 0x00F0) | (r8 << 4));
|
||||
b43_radio_write16(dev, 0x0029, (b43_radio_read16(dev, 0x0029)
|
||||
& 0xFF0F) | 0x00B0);
|
||||
b43_radio_write16(dev, 0x0035, 0x00AA);
|
||||
b43_radio_write16(dev, 0x0036, 0x0085);
|
||||
b43_radio_write16(dev, 0x003A, (b43_radio_read16(dev, 0x003A)
|
||||
& 0xFF20) |
|
||||
freq_r3A_value(freq));
|
||||
b43_radio_write16(dev, 0x003D,
|
||||
b43_radio_read16(dev, 0x003D) & 0x00FF);
|
||||
b43_radio_write16(dev, 0x0081, (b43_radio_read16(dev, 0x0081)
|
||||
& 0xFF7F) | 0x0080);
|
||||
b43_radio_write16(dev, 0x0035,
|
||||
b43_radio_read16(dev, 0x0035) & 0xFFEF);
|
||||
b43_radio_write16(dev, 0x0035, (b43_radio_read16(dev, 0x0035)
|
||||
& 0xFFEF) | 0x0010);
|
||||
b43_radio_set_tx_iq(dev);
|
||||
//TODO: TSSI2dbm workaround
|
||||
//FIXME b43_phy_xmitpower(dev);
|
||||
}
|
||||
|
||||
void b43_radio_init2060(struct b43_wldev *dev)
|
||||
{
|
||||
b43_radio_write16(dev, 0x0004, 0x00C0);
|
||||
b43_radio_write16(dev, 0x0005, 0x0008);
|
||||
b43_radio_write16(dev, 0x0009, 0x0040);
|
||||
b43_radio_write16(dev, 0x0005, 0x00AA);
|
||||
b43_radio_write16(dev, 0x0032, 0x008F);
|
||||
b43_radio_write16(dev, 0x0006, 0x008F);
|
||||
b43_radio_write16(dev, 0x0034, 0x008F);
|
||||
b43_radio_write16(dev, 0x002C, 0x0007);
|
||||
b43_radio_write16(dev, 0x0082, 0x0080);
|
||||
b43_radio_write16(dev, 0x0080, 0x0000);
|
||||
b43_radio_write16(dev, 0x003F, 0x00DA);
|
||||
b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008);
|
||||
b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0010);
|
||||
b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020);
|
||||
b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020);
|
||||
msleep(1); /* delay 400usec */
|
||||
|
||||
b43_radio_write16(dev, 0x0081,
|
||||
(b43_radio_read16(dev, 0x0081) & ~0x0020) | 0x0010);
|
||||
msleep(1); /* delay 400usec */
|
||||
|
||||
b43_radio_write16(dev, 0x0005,
|
||||
(b43_radio_read16(dev, 0x0005) & ~0x0008) | 0x0008);
|
||||
b43_radio_write16(dev, 0x0085, b43_radio_read16(dev, 0x0085) & ~0x0010);
|
||||
b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008);
|
||||
b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0040);
|
||||
b43_radio_write16(dev, 0x0081,
|
||||
(b43_radio_read16(dev, 0x0081) & ~0x0040) | 0x0040);
|
||||
b43_radio_write16(dev, 0x0005,
|
||||
(b43_radio_read16(dev, 0x0081) & ~0x0008) | 0x0008);
|
||||
b43_phy_write(dev, 0x0063, 0xDDC6);
|
||||
b43_phy_write(dev, 0x0069, 0x07BE);
|
||||
b43_phy_write(dev, 0x006A, 0x0000);
|
||||
|
||||
aphy_channel_switch(dev, dev->phy.ops->get_default_chan(dev));
|
||||
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
static void b43_phy_rssiagc(struct b43_wldev *dev, u8 enable)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dev->phy.rev < 3) {
|
||||
if (enable)
|
||||
for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) {
|
||||
b43_ofdmtab_write16(dev,
|
||||
B43_OFDMTAB_LNAHPFGAIN1, i, 0xFFF8);
|
||||
b43_ofdmtab_write16(dev,
|
||||
B43_OFDMTAB_WRSSI, i, 0xFFF8);
|
||||
}
|
||||
else
|
||||
for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) {
|
||||
b43_ofdmtab_write16(dev,
|
||||
B43_OFDMTAB_LNAHPFGAIN1, i, b43_tab_rssiagc1[i]);
|
||||
b43_ofdmtab_write16(dev,
|
||||
B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc1[i]);
|
||||
}
|
||||
} else {
|
||||
if (enable)
|
||||
for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++)
|
||||
b43_ofdmtab_write16(dev,
|
||||
B43_OFDMTAB_WRSSI, i, 0x0820);
|
||||
else
|
||||
for (i = 0; i < B43_TAB_RSSIAGC2_SIZE; i++)
|
||||
b43_ofdmtab_write16(dev,
|
||||
B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void b43_phy_ww(struct b43_wldev *dev)
|
||||
{
|
||||
u16 b, curr_s, best_s = 0xFFFF;
|
||||
int i;
|
||||
|
||||
b43_phy_write(dev, B43_PHY_CRS0,
|
||||
b43_phy_read(dev, B43_PHY_CRS0) & ~B43_PHY_CRS0_EN);
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0x1B),
|
||||
b43_phy_read(dev, B43_PHY_OFDM(0x1B)) | 0x1000);
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0x82),
|
||||
(b43_phy_read(dev, B43_PHY_OFDM(0x82)) & 0xF0FF) | 0x0300);
|
||||
b43_radio_write16(dev, 0x0009,
|
||||
b43_radio_read16(dev, 0x0009) | 0x0080);
|
||||
b43_radio_write16(dev, 0x0012,
|
||||
(b43_radio_read16(dev, 0x0012) & 0xFFFC) | 0x0002);
|
||||
b43_wa_initgains(dev);
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0xBA), 0x3ED5);
|
||||
b = b43_phy_read(dev, B43_PHY_PWRDOWN);
|
||||
b43_phy_write(dev, B43_PHY_PWRDOWN, (b & 0xFFF8) | 0x0005);
|
||||
b43_radio_write16(dev, 0x0004,
|
||||
b43_radio_read16(dev, 0x0004) | 0x0004);
|
||||
for (i = 0x10; i <= 0x20; i++) {
|
||||
b43_radio_write16(dev, 0x0013, i);
|
||||
curr_s = b43_phy_read(dev, B43_PHY_OTABLEQ) & 0x00FF;
|
||||
if (!curr_s) {
|
||||
best_s = 0x0000;
|
||||
break;
|
||||
} else if (curr_s >= 0x0080)
|
||||
curr_s = 0x0100 - curr_s;
|
||||
if (curr_s < best_s)
|
||||
best_s = curr_s;
|
||||
}
|
||||
b43_phy_write(dev, B43_PHY_PWRDOWN, b);
|
||||
b43_radio_write16(dev, 0x0004,
|
||||
b43_radio_read16(dev, 0x0004) & 0xFFFB);
|
||||
b43_radio_write16(dev, 0x0013, best_s);
|
||||
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 0xFFEC);
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0xB7), 0x1E80);
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0xB6), 0x1C00);
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0xB5), 0x0EC0);
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0xB2), 0x00C0);
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0xB9), 0x1FFF);
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0xBB),
|
||||
(b43_phy_read(dev, B43_PHY_OFDM(0xBB)) & 0xF000) | 0x0053);
|
||||
b43_phy_write(dev, B43_PHY_OFDM61,
|
||||
(b43_phy_read(dev, B43_PHY_OFDM61) & 0xFE1F) | 0x0120);
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0x13),
|
||||
(b43_phy_read(dev, B43_PHY_OFDM(0x13)) & 0x0FFF) | 0x3000);
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0x14),
|
||||
(b43_phy_read(dev, B43_PHY_OFDM(0x14)) & 0x0FFF) | 0x3000);
|
||||
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 6, 0x0017);
|
||||
for (i = 0; i < 6; i++)
|
||||
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, i, 0x000F);
|
||||
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0D, 0x000E);
|
||||
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0E, 0x0011);
|
||||
b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0F, 0x0013);
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0x33), 0x5030);
|
||||
b43_phy_write(dev, B43_PHY_CRS0,
|
||||
b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN);
|
||||
}
|
||||
|
||||
static void hardware_pctl_init_aphy(struct b43_wldev *dev)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
void b43_phy_inita(struct b43_wldev *dev)
|
||||
{
|
||||
struct ssb_bus *bus = dev->dev->bus;
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
|
||||
/* This lowlevel A-PHY init is also called from G-PHY init.
|
||||
* So we must not access phy->a, if called from G-PHY code.
|
||||
*/
|
||||
B43_WARN_ON((phy->type != B43_PHYTYPE_A) &&
|
||||
(phy->type != B43_PHYTYPE_G));
|
||||
|
||||
might_sleep();
|
||||
|
||||
if (phy->rev >= 6) {
|
||||
if (phy->type == B43_PHYTYPE_A)
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0x1B),
|
||||
b43_phy_read(dev, B43_PHY_OFDM(0x1B)) & ~0x1000);
|
||||
if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
|
||||
b43_phy_write(dev, B43_PHY_ENCORE,
|
||||
b43_phy_read(dev, B43_PHY_ENCORE) | 0x0010);
|
||||
else
|
||||
b43_phy_write(dev, B43_PHY_ENCORE,
|
||||
b43_phy_read(dev, B43_PHY_ENCORE) & ~0x1010);
|
||||
}
|
||||
|
||||
b43_wa_all(dev);
|
||||
|
||||
if (phy->type == B43_PHYTYPE_A) {
|
||||
if (phy->gmode && (phy->rev < 3))
|
||||
b43_phy_write(dev, 0x0034,
|
||||
b43_phy_read(dev, 0x0034) | 0x0001);
|
||||
b43_phy_rssiagc(dev, 0);
|
||||
|
||||
b43_phy_write(dev, B43_PHY_CRS0,
|
||||
b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN);
|
||||
|
||||
b43_radio_init2060(dev);
|
||||
|
||||
if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
|
||||
((bus->boardinfo.type == SSB_BOARD_BU4306) ||
|
||||
(bus->boardinfo.type == SSB_BOARD_BU4309))) {
|
||||
; //TODO: A PHY LO
|
||||
}
|
||||
|
||||
if (phy->rev >= 3)
|
||||
b43_phy_ww(dev);
|
||||
|
||||
hardware_pctl_init_aphy(dev);
|
||||
|
||||
//TODO: radar detection
|
||||
}
|
||||
|
||||
if ((phy->type == B43_PHYTYPE_G) &&
|
||||
(dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) {
|
||||
b43_phy_write(dev, B43_PHY_OFDM(0x6E),
|
||||
(b43_phy_read(dev, B43_PHY_OFDM(0x6E))
|
||||
& 0xE000) | 0x3CF);
|
||||
}
|
||||
}
|
||||
|
||||
static int b43_aphy_op_allocate(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_a *aphy;
|
||||
|
||||
aphy = kzalloc(sizeof(*aphy), GFP_KERNEL);
|
||||
if (!aphy)
|
||||
return -ENOMEM;
|
||||
dev->phy.a = aphy;
|
||||
|
||||
//TODO init struct b43_phy_a
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int b43_aphy_op_init(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_a *aphy = dev->phy.a;
|
||||
|
||||
b43_phy_inita(dev);
|
||||
aphy->initialised = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void b43_aphy_op_exit(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy_a *aphy = dev->phy.a;
|
||||
|
||||
if (aphy->initialised) {
|
||||
//TODO
|
||||
aphy->initialised = 0;
|
||||
}
|
||||
//TODO
|
||||
kfree(aphy);
|
||||
dev->phy.a = NULL;
|
||||
}
|
||||
|
||||
static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset)
|
||||
{
|
||||
/* OFDM registers are base-registers for the A-PHY. */
|
||||
if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
|
||||
offset &= ~B43_PHYROUTE;
|
||||
offset |= B43_PHYROUTE_BASE;
|
||||
}
|
||||
|
||||
#if B43_DEBUG
|
||||
if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
|
||||
/* Ext-G registers are only available on G-PHYs */
|
||||
b43err(dev->wl, "Invalid EXT-G PHY access at "
|
||||
"0x%04X on A-PHY\n", offset);
|
||||
dump_stack();
|
||||
}
|
||||
if ((offset & B43_PHYROUTE) == B43_PHYROUTE_N_BMODE) {
|
||||
/* N-BMODE registers are only available on N-PHYs */
|
||||
b43err(dev->wl, "Invalid N-BMODE PHY access at "
|
||||
"0x%04X on A-PHY\n", offset);
|
||||
dump_stack();
|
||||
}
|
||||
#endif /* B43_DEBUG */
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static u16 b43_aphy_op_read(struct b43_wldev *dev, u16 reg)
|
||||
{
|
||||
reg = adjust_phyreg(dev, reg);
|
||||
b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
|
||||
return b43_read16(dev, B43_MMIO_PHY_DATA);
|
||||
}
|
||||
|
||||
static void b43_aphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
|
||||
{
|
||||
reg = adjust_phyreg(dev, reg);
|
||||
b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
|
||||
b43_write16(dev, B43_MMIO_PHY_DATA, value);
|
||||
}
|
||||
|
||||
static u16 b43_aphy_op_radio_read(struct b43_wldev *dev, u16 reg)
|
||||
{
|
||||
/* Register 1 is a 32-bit register. */
|
||||
B43_WARN_ON(reg == 1);
|
||||
/* A-PHY needs 0x40 for read access */
|
||||
reg |= 0x40;
|
||||
|
||||
b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
|
||||
return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
|
||||
}
|
||||
|
||||
static void b43_aphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
|
||||
{
|
||||
/* Register 1 is a 32-bit register. */
|
||||
B43_WARN_ON(reg == 1);
|
||||
|
||||
b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
|
||||
b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
|
||||
}
|
||||
|
||||
static bool b43_aphy_op_supports_hwpctl(struct b43_wldev *dev)
|
||||
{
|
||||
return (dev->phy.rev >= 5);
|
||||
}
|
||||
|
||||
static void b43_aphy_op_software_rfkill(struct b43_wldev *dev,
|
||||
enum rfkill_state state)
|
||||
{//TODO
|
||||
}
|
||||
|
||||
static int b43_aphy_op_switch_channel(struct b43_wldev *dev,
|
||||
unsigned int new_channel)
|
||||
{
|
||||
if (new_channel > 200)
|
||||
return -EINVAL;
|
||||
aphy_channel_switch(dev, new_channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int b43_aphy_op_get_default_chan(struct b43_wldev *dev)
|
||||
{
|
||||
return 36; /* Default to channel 36 */
|
||||
}
|
||||
|
||||
static void b43_aphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
|
||||
{//TODO
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
u64 hf;
|
||||
u16 tmp;
|
||||
int autodiv = 0;
|
||||
|
||||
if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1)
|
||||
autodiv = 1;
|
||||
|
||||
hf = b43_hf_read(dev);
|
||||
hf &= ~B43_HF_ANTDIVHELP;
|
||||
b43_hf_write(dev, hf);
|
||||
|
||||
tmp = b43_phy_read(dev, B43_PHY_BBANDCFG);
|
||||
tmp &= ~B43_PHY_BBANDCFG_RXANT;
|
||||
tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna)
|
||||
<< B43_PHY_BBANDCFG_RXANT_SHIFT;
|
||||
b43_phy_write(dev, B43_PHY_BBANDCFG, tmp);
|
||||
|
||||
if (autodiv) {
|
||||
tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
|
||||
if (antenna == B43_ANTENNA_AUTO0)
|
||||
tmp &= ~B43_PHY_ANTDWELL_AUTODIV1;
|
||||
else
|
||||
tmp |= B43_PHY_ANTDWELL_AUTODIV1;
|
||||
b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
|
||||
}
|
||||
if (phy->rev < 3) {
|
||||
tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
|
||||
tmp = (tmp & 0xFF00) | 0x24;
|
||||
b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
|
||||
} else {
|
||||
tmp = b43_phy_read(dev, B43_PHY_OFDM61);
|
||||
tmp |= 0x10;
|
||||
b43_phy_write(dev, B43_PHY_OFDM61, tmp);
|
||||
if (phy->analog == 3) {
|
||||
b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT,
|
||||
0x1D);
|
||||
b43_phy_write(dev, B43_PHY_ADIVRELATED,
|
||||
8);
|
||||
} else {
|
||||
b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT,
|
||||
0x3A);
|
||||
tmp =
|
||||
b43_phy_read(dev,
|
||||
B43_PHY_ADIVRELATED);
|
||||
tmp = (tmp & 0xFF00) | 8;
|
||||
b43_phy_write(dev, B43_PHY_ADIVRELATED,
|
||||
tmp);
|
||||
}
|
||||
}
|
||||
|
||||
hf |= B43_HF_ANTDIVHELP;
|
||||
b43_hf_write(dev, hf);
|
||||
}
|
||||
|
||||
static void b43_aphy_op_adjust_txpower(struct b43_wldev *dev)
|
||||
{//TODO
|
||||
}
|
||||
|
||||
static enum b43_txpwr_result b43_aphy_op_recalc_txpower(struct b43_wldev *dev,
|
||||
bool ignore_tssi)
|
||||
{//TODO
|
||||
return B43_TXPWR_RES_DONE;
|
||||
}
|
||||
|
||||
static void b43_aphy_op_pwork_15sec(struct b43_wldev *dev)
|
||||
{//TODO
|
||||
}
|
||||
|
||||
static void b43_aphy_op_pwork_60sec(struct b43_wldev *dev)
|
||||
{//TODO
|
||||
}
|
||||
|
||||
const struct b43_phy_operations b43_phyops_a = {
|
||||
.allocate = b43_aphy_op_allocate,
|
||||
.init = b43_aphy_op_init,
|
||||
.exit = b43_aphy_op_exit,
|
||||
.phy_read = b43_aphy_op_read,
|
||||
.phy_write = b43_aphy_op_write,
|
||||
.radio_read = b43_aphy_op_radio_read,
|
||||
.radio_write = b43_aphy_op_radio_write,
|
||||
.supports_hwpctl = b43_aphy_op_supports_hwpctl,
|
||||
.software_rfkill = b43_aphy_op_software_rfkill,
|
||||
.switch_channel = b43_aphy_op_switch_channel,
|
||||
.get_default_chan = b43_aphy_op_get_default_chan,
|
||||
.set_rx_antenna = b43_aphy_op_set_rx_antenna,
|
||||
.recalc_txpower = b43_aphy_op_recalc_txpower,
|
||||
.adjust_txpower = b43_aphy_op_adjust_txpower,
|
||||
.pwork_15sec = b43_aphy_op_pwork_15sec,
|
||||
.pwork_60sec = b43_aphy_op_pwork_60sec,
|
||||
};
|
124
drivers/net/wireless/b43/phy_a.h
Normal file
124
drivers/net/wireless/b43/phy_a.h
Normal file
@ -0,0 +1,124 @@
|
||||
#ifndef LINUX_B43_PHY_A_H_
|
||||
#define LINUX_B43_PHY_A_H_
|
||||
|
||||
#include "phy_common.h"
|
||||
|
||||
|
||||
/* OFDM (A) PHY Registers */
|
||||
#define B43_PHY_VERSION_OFDM B43_PHY_OFDM(0x00) /* Versioning register for A-PHY */
|
||||
#define B43_PHY_BBANDCFG B43_PHY_OFDM(0x01) /* Baseband config */
|
||||
#define B43_PHY_BBANDCFG_RXANT 0x180 /* RX Antenna selection */
|
||||
#define B43_PHY_BBANDCFG_RXANT_SHIFT 7
|
||||
#define B43_PHY_PWRDOWN B43_PHY_OFDM(0x03) /* Powerdown */
|
||||
#define B43_PHY_CRSTHRES1_R1 B43_PHY_OFDM(0x06) /* CRS Threshold 1 (phy.rev 1 only) */
|
||||
#define B43_PHY_LNAHPFCTL B43_PHY_OFDM(0x1C) /* LNA/HPF control */
|
||||
#define B43_PHY_LPFGAINCTL B43_PHY_OFDM(0x20) /* LPF Gain control */
|
||||
#define B43_PHY_ADIVRELATED B43_PHY_OFDM(0x27) /* FIXME rename */
|
||||
#define B43_PHY_CRS0 B43_PHY_OFDM(0x29)
|
||||
#define B43_PHY_CRS0_EN 0x4000
|
||||
#define B43_PHY_PEAK_COUNT B43_PHY_OFDM(0x30)
|
||||
#define B43_PHY_ANTDWELL B43_PHY_OFDM(0x2B) /* Antenna dwell */
|
||||
#define B43_PHY_ANTDWELL_AUTODIV1 0x0100 /* Automatic RX diversity start antenna */
|
||||
#define B43_PHY_ENCORE B43_PHY_OFDM(0x49) /* "Encore" (RangeMax / BroadRange) */
|
||||
#define B43_PHY_ENCORE_EN 0x0200 /* Encore enable */
|
||||
#define B43_PHY_LMS B43_PHY_OFDM(0x55)
|
||||
#define B43_PHY_OFDM61 B43_PHY_OFDM(0x61) /* FIXME rename */
|
||||
#define B43_PHY_OFDM61_10 0x0010 /* FIXME rename */
|
||||
#define B43_PHY_IQBAL B43_PHY_OFDM(0x69) /* I/Q balance */
|
||||
#define B43_PHY_BBTXDC_BIAS B43_PHY_OFDM(0x6B) /* Baseband TX DC bias */
|
||||
#define B43_PHY_OTABLECTL B43_PHY_OFDM(0x72) /* OFDM table control (see below) */
|
||||
#define B43_PHY_OTABLEOFF 0x03FF /* OFDM table offset (see below) */
|
||||
#define B43_PHY_OTABLENR 0xFC00 /* OFDM table number (see below) */
|
||||
#define B43_PHY_OTABLENR_SHIFT 10
|
||||
#define B43_PHY_OTABLEI B43_PHY_OFDM(0x73) /* OFDM table data I */
|
||||
#define B43_PHY_OTABLEQ B43_PHY_OFDM(0x74) /* OFDM table data Q */
|
||||
#define B43_PHY_HPWR_TSSICTL B43_PHY_OFDM(0x78) /* Hardware power TSSI control */
|
||||
#define B43_PHY_ADCCTL B43_PHY_OFDM(0x7A) /* ADC control */
|
||||
#define B43_PHY_IDLE_TSSI B43_PHY_OFDM(0x7B)
|
||||
#define B43_PHY_A_TEMP_SENSE B43_PHY_OFDM(0x7C) /* A PHY temperature sense */
|
||||
#define B43_PHY_NRSSITHRES B43_PHY_OFDM(0x8A) /* NRSSI threshold */
|
||||
#define B43_PHY_ANTWRSETT B43_PHY_OFDM(0x8C) /* Antenna WR settle */
|
||||
#define B43_PHY_ANTWRSETT_ARXDIV 0x2000 /* Automatic RX diversity enabled */
|
||||
#define B43_PHY_CLIPPWRDOWNT B43_PHY_OFDM(0x93) /* Clip powerdown threshold */
|
||||
#define B43_PHY_OFDM9B B43_PHY_OFDM(0x9B) /* FIXME rename */
|
||||
#define B43_PHY_N1P1GAIN B43_PHY_OFDM(0xA0)
|
||||
#define B43_PHY_P1P2GAIN B43_PHY_OFDM(0xA1)
|
||||
#define B43_PHY_N1N2GAIN B43_PHY_OFDM(0xA2)
|
||||
#define B43_PHY_CLIPTHRES B43_PHY_OFDM(0xA3)
|
||||
#define B43_PHY_CLIPN1P2THRES B43_PHY_OFDM(0xA4)
|
||||
#define B43_PHY_CCKSHIFTBITS_WA B43_PHY_OFDM(0xA5) /* CCK shiftbits workaround, FIXME rename */
|
||||
#define B43_PHY_CCKSHIFTBITS B43_PHY_OFDM(0xA7) /* FIXME rename */
|
||||
#define B43_PHY_DIVSRCHIDX B43_PHY_OFDM(0xA8) /* Divider search gain/index */
|
||||
#define B43_PHY_CLIPP2THRES B43_PHY_OFDM(0xA9)
|
||||
#define B43_PHY_CLIPP3THRES B43_PHY_OFDM(0xAA)
|
||||
#define B43_PHY_DIVP1P2GAIN B43_PHY_OFDM(0xAB)
|
||||
#define B43_PHY_DIVSRCHGAINBACK B43_PHY_OFDM(0xAD) /* Divider search gain back */
|
||||
#define B43_PHY_DIVSRCHGAINCHNG B43_PHY_OFDM(0xAE) /* Divider search gain change */
|
||||
#define B43_PHY_CRSTHRES1 B43_PHY_OFDM(0xC0) /* CRS Threshold 1 (phy.rev >= 2 only) */
|
||||
#define B43_PHY_CRSTHRES2 B43_PHY_OFDM(0xC1) /* CRS Threshold 2 (phy.rev >= 2 only) */
|
||||
#define B43_PHY_TSSIP_LTBASE B43_PHY_OFDM(0x380) /* TSSI power lookup table base */
|
||||
#define B43_PHY_DC_LTBASE B43_PHY_OFDM(0x3A0) /* DC lookup table base */
|
||||
#define B43_PHY_GAIN_LTBASE B43_PHY_OFDM(0x3C0) /* Gain lookup table base */
|
||||
|
||||
/*** OFDM table numbers ***/
|
||||
#define B43_OFDMTAB(number, offset) (((number) << B43_PHY_OTABLENR_SHIFT) | (offset))
|
||||
#define B43_OFDMTAB_AGC1 B43_OFDMTAB(0x00, 0)
|
||||
#define B43_OFDMTAB_GAIN0 B43_OFDMTAB(0x00, 0)
|
||||
#define B43_OFDMTAB_GAINX B43_OFDMTAB(0x01, 0) //TODO rename
|
||||
#define B43_OFDMTAB_GAIN1 B43_OFDMTAB(0x01, 4)
|
||||
#define B43_OFDMTAB_AGC3 B43_OFDMTAB(0x02, 0)
|
||||
#define B43_OFDMTAB_GAIN2 B43_OFDMTAB(0x02, 3)
|
||||
#define B43_OFDMTAB_LNAHPFGAIN1 B43_OFDMTAB(0x03, 0)
|
||||
#define B43_OFDMTAB_WRSSI B43_OFDMTAB(0x04, 0)
|
||||
#define B43_OFDMTAB_LNAHPFGAIN2 B43_OFDMTAB(0x04, 0)
|
||||
#define B43_OFDMTAB_NOISESCALE B43_OFDMTAB(0x05, 0)
|
||||
#define B43_OFDMTAB_AGC2 B43_OFDMTAB(0x06, 0)
|
||||
#define B43_OFDMTAB_ROTOR B43_OFDMTAB(0x08, 0)
|
||||
#define B43_OFDMTAB_ADVRETARD B43_OFDMTAB(0x09, 0)
|
||||
#define B43_OFDMTAB_DAC B43_OFDMTAB(0x0C, 0)
|
||||
#define B43_OFDMTAB_DC B43_OFDMTAB(0x0E, 7)
|
||||
#define B43_OFDMTAB_PWRDYN2 B43_OFDMTAB(0x0E, 12)
|
||||
#define B43_OFDMTAB_LNAGAIN B43_OFDMTAB(0x0E, 13)
|
||||
#define B43_OFDMTAB_UNKNOWN_0F B43_OFDMTAB(0x0F, 0) //TODO rename
|
||||
#define B43_OFDMTAB_UNKNOWN_APHY B43_OFDMTAB(0x0F, 7) //TODO rename
|
||||
#define B43_OFDMTAB_LPFGAIN B43_OFDMTAB(0x0F, 12)
|
||||
#define B43_OFDMTAB_RSSI B43_OFDMTAB(0x10, 0)
|
||||
#define B43_OFDMTAB_UNKNOWN_11 B43_OFDMTAB(0x11, 4) //TODO rename
|
||||
#define B43_OFDMTAB_AGC1_R1 B43_OFDMTAB(0x13, 0)
|
||||
#define B43_OFDMTAB_GAINX_R1 B43_OFDMTAB(0x14, 0) //TODO remove!
|
||||
#define B43_OFDMTAB_MINSIGSQ B43_OFDMTAB(0x14, 0)
|
||||
#define B43_OFDMTAB_AGC3_R1 B43_OFDMTAB(0x15, 0)
|
||||
#define B43_OFDMTAB_WRSSI_R1 B43_OFDMTAB(0x15, 4)
|
||||
#define B43_OFDMTAB_TSSI B43_OFDMTAB(0x15, 0)
|
||||
#define B43_OFDMTAB_DACRFPABB B43_OFDMTAB(0x16, 0)
|
||||
#define B43_OFDMTAB_DACOFF B43_OFDMTAB(0x17, 0)
|
||||
#define B43_OFDMTAB_DCBIAS B43_OFDMTAB(0x18, 0)
|
||||
|
||||
u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset);
|
||||
void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
|
||||
u16 offset, u16 value);
|
||||
u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset);
|
||||
void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
|
||||
u16 offset, u32 value);
|
||||
|
||||
|
||||
struct b43_phy_a {
|
||||
bool initialised;
|
||||
|
||||
/* A-PHY TX Power control value. */
|
||||
u16 txpwr_offset;
|
||||
|
||||
//TODO lots of missing stuff
|
||||
};
|
||||
|
||||
/**
|
||||
* b43_phy_inita - Lowlevel A-PHY init routine.
|
||||
* This is _only_ used by the G-PHY code.
|
||||
*/
|
||||
void b43_phy_inita(struct b43_wldev *dev);
|
||||
|
||||
|
||||
struct b43_phy_operations;
|
||||
extern const struct b43_phy_operations b43_phyops_a;
|
||||
|
||||
#endif /* LINUX_B43_PHY_A_H_ */
|
367
drivers/net/wireless/b43/phy_common.c
Normal file
367
drivers/net/wireless/b43/phy_common.c
Normal file
@ -0,0 +1,367 @@
|
||||
/*
|
||||
|
||||
Broadcom B43 wireless driver
|
||||
Common PHY routines
|
||||
|
||||
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
|
||||
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
|
||||
Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
|
||||
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
|
||||
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "phy_common.h"
|
||||
#include "phy_g.h"
|
||||
#include "phy_a.h"
|
||||
#include "nphy.h"
|
||||
#include "b43.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
int b43_phy_operations_setup(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &(dev->phy);
|
||||
int err;
|
||||
|
||||
phy->ops = NULL;
|
||||
|
||||
switch (phy->type) {
|
||||
case B43_PHYTYPE_A:
|
||||
phy->ops = &b43_phyops_a;
|
||||
break;
|
||||
case B43_PHYTYPE_G:
|
||||
phy->ops = &b43_phyops_g;
|
||||
break;
|
||||
case B43_PHYTYPE_N:
|
||||
#ifdef CONFIG_B43_NPHY
|
||||
phy->ops = &b43_phyops_n;
|
||||
#endif
|
||||
break;
|
||||
case B43_PHYTYPE_LP:
|
||||
/* FIXME: Not yet */
|
||||
break;
|
||||
}
|
||||
if (B43_WARN_ON(!phy->ops))
|
||||
return -ENODEV;
|
||||
|
||||
err = phy->ops->allocate(dev);
|
||||
if (err)
|
||||
phy->ops = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int b43_phy_init(struct b43_wldev *dev)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
const struct b43_phy_operations *ops = phy->ops;
|
||||
int err;
|
||||
|
||||
phy->channel = ops->get_default_chan(dev);
|
||||
|
||||
ops->software_rfkill(dev, RFKILL_STATE_UNBLOCKED);
|
||||
err = ops->init(dev);
|
||||
if (err) {
|
||||
b43err(dev->wl, "PHY init failed\n");
|
||||
goto err_block_rf;
|
||||
}
|
||||
/* Make sure to switch hardware and firmware (SHM) to
|
||||
* the default channel. */
|
||||
err = b43_switch_channel(dev, ops->get_default_chan(dev));
|
||||
if (err) {
|
||||
b43err(dev->wl, "PHY init: Channel switch to default failed\n");
|
||||
goto err_phy_exit;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_phy_exit:
|
||||
if (ops->exit)
|
||||
ops->exit(dev);
|
||||
err_block_rf:
|
||||
ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void b43_phy_exit(struct b43_wldev *dev)
|
||||
{
|
||||
const struct b43_phy_operations *ops = dev->phy.ops;
|
||||
|
||||
ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED);
|
||||
if (ops->exit)
|
||||
ops->exit(dev);
|
||||
}
|
||||
|
||||
bool b43_has_hardware_pctl(struct b43_wldev *dev)
|
||||
{
|
||||
if (!dev->phy.hardware_power_control)
|
||||
return 0;
|
||||
if (!dev->phy.ops->supports_hwpctl)
|
||||
return 0;
|
||||
return dev->phy.ops->supports_hwpctl(dev);
|
||||
}
|
||||
|
||||
void b43_radio_lock(struct b43_wldev *dev)
|
||||
{
|
||||
u32 macctl;
|
||||
|
||||
macctl = b43_read32(dev, B43_MMIO_MACCTL);
|
||||
B43_WARN_ON(macctl & B43_MACCTL_RADIOLOCK);
|
||||
macctl |= B43_MACCTL_RADIOLOCK;
|
||||
b43_write32(dev, B43_MMIO_MACCTL, macctl);
|
||||
/* Commit the write and wait for the device
|
||||
* to exit any radio register access. */
|
||||
b43_read32(dev, B43_MMIO_MACCTL);
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
void b43_radio_unlock(struct b43_wldev *dev)
|
||||
{
|
||||
u32 macctl;
|
||||
|
||||
/* Commit any write */
|
||||
b43_read16(dev, B43_MMIO_PHY_VER);
|
||||
/* unlock */
|
||||
macctl = b43_read32(dev, B43_MMIO_MACCTL);
|
||||
B43_WARN_ON(!(macctl & B43_MACCTL_RADIOLOCK));
|
||||
macctl &= ~B43_MACCTL_RADIOLOCK;
|
||||
b43_write32(dev, B43_MMIO_MACCTL, macctl);
|
||||
}
|
||||
|
||||
void b43_phy_lock(struct b43_wldev *dev)
|
||||
{
|
||||
#if B43_DEBUG
|
||||
B43_WARN_ON(dev->phy.phy_locked);
|
||||
dev->phy.phy_locked = 1;
|
||||
#endif
|
||||
B43_WARN_ON(dev->dev->id.revision < 3);
|
||||
|
||||
if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
|
||||
b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
|
||||
}
|
||||
|
||||
void b43_phy_unlock(struct b43_wldev *dev)
|
||||
{
|
||||
#if B43_DEBUG
|
||||
B43_WARN_ON(!dev->phy.phy_locked);
|
||||
dev->phy.phy_locked = 0;
|
||||
#endif
|
||||
B43_WARN_ON(dev->dev->id.revision < 3);
|
||||
|
||||
if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
|
||||
b43_power_saving_ctl_bits(dev, 0);
|
||||
}
|
||||
|
||||
u16 b43_radio_read(struct b43_wldev *dev, u16 reg)
|
||||
{
|
||||
return dev->phy.ops->radio_read(dev, reg);
|
||||
}
|
||||
|
||||
void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
|
||||
{
|
||||
dev->phy.ops->radio_write(dev, reg, value);
|
||||
}
|
||||
|
||||
void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask)
|
||||
{
|
||||
b43_radio_write16(dev, offset,
|
||||
b43_radio_read16(dev, offset) & mask);
|
||||
}
|
||||
|
||||
void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set)
|
||||
{
|
||||
b43_radio_write16(dev, offset,
|
||||
b43_radio_read16(dev, offset) | set);
|
||||
}
|
||||
|
||||
void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
|
||||
{
|
||||
b43_radio_write16(dev, offset,
|
||||
(b43_radio_read16(dev, offset) & mask) | set);
|
||||
}
|
||||
|
||||
u16 b43_phy_read(struct b43_wldev *dev, u16 reg)
|
||||
{
|
||||
return dev->phy.ops->phy_read(dev, reg);
|
||||
}
|
||||
|
||||
void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
|
||||
{
|
||||
dev->phy.ops->phy_write(dev, reg, value);
|
||||
}
|
||||
|
||||
void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
|
||||
{
|
||||
b43_phy_write(dev, offset,
|
||||
b43_phy_read(dev, offset) & mask);
|
||||
}
|
||||
|
||||
void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set)
|
||||
{
|
||||
b43_phy_write(dev, offset,
|
||||
b43_phy_read(dev, offset) | set);
|
||||
}
|
||||
|
||||
void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
|
||||
{
|
||||
b43_phy_write(dev, offset,
|
||||
(b43_phy_read(dev, offset) & mask) | set);
|
||||
}
|
||||
|
||||
int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
|
||||
{
|
||||
struct b43_phy *phy = &(dev->phy);
|
||||
u16 channelcookie, savedcookie;
|
||||
int err;
|
||||
|
||||
if (new_channel == B43_DEFAULT_CHANNEL)
|
||||
new_channel = phy->ops->get_default_chan(dev);
|
||||
|
||||
/* First we set the channel radio code to prevent the
|
||||
* firmware from sending ghost packets.
|
||||
*/
|
||||
channelcookie = new_channel;
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
|
||||
channelcookie |= 0x100;
|
||||
//FIXME set 40Mhz flag if required
|
||||
savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN);
|
||||
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie);
|
||||
|
||||
/* Now try to switch the PHY hardware channel. */
|
||||
err = phy->ops->switch_channel(dev, new_channel);
|
||||
if (err)
|
||||
goto err_restore_cookie;
|
||||
|
||||
dev->phy.channel = new_channel;
|
||||
/* Wait for the radio to tune to the channel and stabilize. */
|
||||
msleep(8);
|
||||
|
||||
return 0;
|
||||
|
||||
err_restore_cookie:
|
||||
b43_shm_write16(dev, B43_SHM_SHARED,
|
||||
B43_SHM_SH_CHAN, savedcookie);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
|
||||
if (state == RFKILL_STATE_HARD_BLOCKED) {
|
||||
/* We cannot hardware-block the device */
|
||||
state = RFKILL_STATE_SOFT_BLOCKED;
|
||||
}
|
||||
|
||||
phy->ops->software_rfkill(dev, state);
|
||||
phy->radio_on = (state == RFKILL_STATE_UNBLOCKED);
|
||||
}
|
||||
|
||||
/**
|
||||
* b43_phy_txpower_adjust_work - TX power workqueue.
|
||||
*
|
||||
* Workqueue for updating the TX power parameters in hardware.
|
||||
*/
|
||||
void b43_phy_txpower_adjust_work(struct work_struct *work)
|
||||
{
|
||||
struct b43_wl *wl = container_of(work, struct b43_wl,
|
||||
txpower_adjust_work);
|
||||
struct b43_wldev *dev;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
dev = wl->current_dev;
|
||||
|
||||
if (likely(dev && (b43_status(dev) >= B43_STAT_STARTED)))
|
||||
dev->phy.ops->adjust_txpower(dev);
|
||||
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
/* Called with wl->irq_lock locked */
|
||||
void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
unsigned long now = jiffies;
|
||||
enum b43_txpwr_result result;
|
||||
|
||||
if (!(flags & B43_TXPWR_IGNORE_TIME)) {
|
||||
/* Check if it's time for a TXpower check. */
|
||||
if (time_before(now, phy->next_txpwr_check_time))
|
||||
return; /* Not yet */
|
||||
}
|
||||
/* The next check will be needed in two seconds, or later. */
|
||||
phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2));
|
||||
|
||||
if ((dev->dev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
|
||||
(dev->dev->bus->boardinfo.type == SSB_BOARD_BU4306))
|
||||
return; /* No software txpower adjustment needed */
|
||||
|
||||
result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI));
|
||||
if (result == B43_TXPWR_RES_DONE)
|
||||
return; /* We are done. */
|
||||
B43_WARN_ON(result != B43_TXPWR_RES_NEED_ADJUST);
|
||||
B43_WARN_ON(phy->ops->adjust_txpower == NULL);
|
||||
|
||||
/* We must adjust the transmission power in hardware.
|
||||
* Schedule b43_phy_txpower_adjust_work(). */
|
||||
queue_work(dev->wl->hw->workqueue, &dev->wl->txpower_adjust_work);
|
||||
}
|
||||
|
||||
int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset)
|
||||
{
|
||||
const bool is_ofdm = (shm_offset != B43_SHM_SH_TSSI_CCK);
|
||||
unsigned int a, b, c, d;
|
||||
unsigned int average;
|
||||
u32 tmp;
|
||||
|
||||
tmp = b43_shm_read32(dev, B43_SHM_SHARED, shm_offset);
|
||||
a = tmp & 0xFF;
|
||||
b = (tmp >> 8) & 0xFF;
|
||||
c = (tmp >> 16) & 0xFF;
|
||||
d = (tmp >> 24) & 0xFF;
|
||||
if (a == 0 || a == B43_TSSI_MAX ||
|
||||
b == 0 || b == B43_TSSI_MAX ||
|
||||
c == 0 || c == B43_TSSI_MAX ||
|
||||
d == 0 || d == B43_TSSI_MAX)
|
||||
return -ENOENT;
|
||||
/* The values are OK. Clear them. */
|
||||
tmp = B43_TSSI_MAX | (B43_TSSI_MAX << 8) |
|
||||
(B43_TSSI_MAX << 16) | (B43_TSSI_MAX << 24);
|
||||
b43_shm_write32(dev, B43_SHM_SHARED, shm_offset, tmp);
|
||||
|
||||
if (is_ofdm) {
|
||||
a = (a + 32) & 0x3F;
|
||||
b = (b + 32) & 0x3F;
|
||||
c = (c + 32) & 0x3F;
|
||||
d = (d + 32) & 0x3F;
|
||||
}
|
||||
|
||||
/* Get the average of the values with 0.5 added to each value. */
|
||||
average = (a + b + c + d + 2) / 4;
|
||||
if (is_ofdm) {
|
||||
/* Adjust for CCK-boost */
|
||||
if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO)
|
||||
& B43_HF_CCKBOOST)
|
||||
average = (average >= 13) ? (average - 13) : 0;
|
||||
}
|
||||
|
||||
return average;
|
||||
}
|
381
drivers/net/wireless/b43/phy_common.h
Normal file
381
drivers/net/wireless/b43/phy_common.h
Normal file
@ -0,0 +1,381 @@
|
||||
#ifndef LINUX_B43_PHY_COMMON_H_
|
||||
#define LINUX_B43_PHY_COMMON_H_
|
||||
|
||||
#include <linux/rfkill.h>
|
||||
|
||||
struct b43_wldev;
|
||||
|
||||
|
||||
/* PHY register routing bits */
|
||||
#define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */
|
||||
#define B43_PHYROUTE_BASE 0x0000 /* Base registers */
|
||||
#define B43_PHYROUTE_OFDM_GPHY 0x0400 /* OFDM register routing for G-PHYs */
|
||||
#define B43_PHYROUTE_EXT_GPHY 0x0800 /* Extended G-PHY registers */
|
||||
#define B43_PHYROUTE_N_BMODE 0x0C00 /* N-PHY BMODE registers */
|
||||
|
||||
/* CCK (B-PHY) registers. */
|
||||
#define B43_PHY_CCK(reg) ((reg) | B43_PHYROUTE_BASE)
|
||||
/* N-PHY registers. */
|
||||
#define B43_PHY_N(reg) ((reg) | B43_PHYROUTE_BASE)
|
||||
/* N-PHY BMODE registers. */
|
||||
#define B43_PHY_N_BMODE(reg) ((reg) | B43_PHYROUTE_N_BMODE)
|
||||
/* OFDM (A-PHY) registers. */
|
||||
#define B43_PHY_OFDM(reg) ((reg) | B43_PHYROUTE_OFDM_GPHY)
|
||||
/* Extended G-PHY registers. */
|
||||
#define B43_PHY_EXTG(reg) ((reg) | B43_PHYROUTE_EXT_GPHY)
|
||||
|
||||
|
||||
/* Masks for the PHY versioning registers. */
|
||||
#define B43_PHYVER_ANALOG 0xF000
|
||||
#define B43_PHYVER_ANALOG_SHIFT 12
|
||||
#define B43_PHYVER_TYPE 0x0F00
|
||||
#define B43_PHYVER_TYPE_SHIFT 8
|
||||
#define B43_PHYVER_VERSION 0x00FF
|
||||
|
||||
/**
|
||||
* enum b43_interference_mitigation - Interference Mitigation mode
|
||||
*
|
||||
* @B43_INTERFMODE_NONE: Disabled
|
||||
* @B43_INTERFMODE_NONWLAN: Non-WLAN Interference Mitigation
|
||||
* @B43_INTERFMODE_MANUALWLAN: WLAN Interference Mitigation
|
||||
* @B43_INTERFMODE_AUTOWLAN: Automatic WLAN Interference Mitigation
|
||||
*/
|
||||
enum b43_interference_mitigation {
|
||||
B43_INTERFMODE_NONE,
|
||||
B43_INTERFMODE_NONWLAN,
|
||||
B43_INTERFMODE_MANUALWLAN,
|
||||
B43_INTERFMODE_AUTOWLAN,
|
||||
};
|
||||
|
||||
/* Antenna identifiers */
|
||||
enum {
|
||||
B43_ANTENNA0, /* Antenna 0 */
|
||||
B43_ANTENNA1, /* Antenna 0 */
|
||||
B43_ANTENNA_AUTO1, /* Automatic, starting with antenna 1 */
|
||||
B43_ANTENNA_AUTO0, /* Automatic, starting with antenna 0 */
|
||||
B43_ANTENNA2,
|
||||
B43_ANTENNA3 = 8,
|
||||
|
||||
B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0,
|
||||
B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum b43_txpwr_result - Return value for the recalc_txpower PHY op.
|
||||
*
|
||||
* @B43_TXPWR_RES_NEED_ADJUST: Values changed. Hardware adjustment is needed.
|
||||
* @B43_TXPWR_RES_DONE: No more work to do. Everything is done.
|
||||
*/
|
||||
enum b43_txpwr_result {
|
||||
B43_TXPWR_RES_NEED_ADJUST,
|
||||
B43_TXPWR_RES_DONE,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct b43_phy_operations - Function pointers for PHY ops.
|
||||
*
|
||||
* @prepare: Prepare the PHY. This is called before @init.
|
||||
* Can be NULL, if not required.
|
||||
* @init: Initialize the PHY.
|
||||
* Must not be NULL.
|
||||
* @exit: Shutdown the PHY and free all data structures.
|
||||
* Can be NULL, if not required.
|
||||
*
|
||||
* @phy_read: Read from a PHY register.
|
||||
* Must not be NULL.
|
||||
* @phy_write: Write to a PHY register.
|
||||
* Must not be NULL.
|
||||
* @radio_read: Read from a Radio register.
|
||||
* Must not be NULL.
|
||||
* @radio_write: Write to a Radio register.
|
||||
* Must not be NULL.
|
||||
*
|
||||
* @supports_hwpctl: Returns a boolean whether Hardware Power Control
|
||||
* is supported or not.
|
||||
* If NULL, hwpctl is assumed to be never supported.
|
||||
* @software_rfkill: Turn the radio ON or OFF.
|
||||
* Possible state values are
|
||||
* RFKILL_STATE_SOFT_BLOCKED or
|
||||
* RFKILL_STATE_UNBLOCKED
|
||||
* Must not be NULL.
|
||||
* @switch_channel: Switch the radio to another channel.
|
||||
* Must not be NULL.
|
||||
* @get_default_chan: Just returns the default channel number.
|
||||
* Must not be NULL.
|
||||
* @set_rx_antenna: Set the antenna used for RX.
|
||||
* Can be NULL, if not supported.
|
||||
* @interf_mitigation: Switch the Interference Mitigation mode.
|
||||
* Can be NULL, if not supported.
|
||||
*
|
||||
* @recalc_txpower: Recalculate the transmission power parameters.
|
||||
* This callback has to recalculate the TX power settings,
|
||||
* but does not need to write them to the hardware, yet.
|
||||
* Returns enum b43_txpwr_result to indicate whether the hardware
|
||||
* needs to be adjusted.
|
||||
* If B43_TXPWR_NEED_ADJUST is returned, @adjust_txpower
|
||||
* will be called later.
|
||||
* If the parameter "ignore_tssi" is true, the TSSI values should
|
||||
* be ignored and a recalculation of the power settings should be
|
||||
* done even if the TSSI values did not change.
|
||||
* This callback is called with wl->irq_lock held and must not sleep.
|
||||
* Must not be NULL.
|
||||
* @adjust_txpower: Write the previously calculated TX power settings
|
||||
* (from @recalc_txpower) to the hardware.
|
||||
* This function may sleep.
|
||||
* Can be NULL, if (and ONLY if) @recalc_txpower _always_
|
||||
* returns B43_TXPWR_RES_DONE.
|
||||
*
|
||||
* @pwork_15sec: Periodic work. Called every 15 seconds.
|
||||
* Can be NULL, if not required.
|
||||
* @pwork_60sec: Periodic work. Called every 60 seconds.
|
||||
* Can be NULL, if not required.
|
||||
*/
|
||||
struct b43_phy_operations {
|
||||
/* Initialisation */
|
||||
int (*allocate)(struct b43_wldev *dev);
|
||||
int (*prepare)(struct b43_wldev *dev);
|
||||
int (*init)(struct b43_wldev *dev);
|
||||
void (*exit)(struct b43_wldev *dev);
|
||||
|
||||
/* Register access */
|
||||
u16 (*phy_read)(struct b43_wldev *dev, u16 reg);
|
||||
void (*phy_write)(struct b43_wldev *dev, u16 reg, u16 value);
|
||||
u16 (*radio_read)(struct b43_wldev *dev, u16 reg);
|
||||
void (*radio_write)(struct b43_wldev *dev, u16 reg, u16 value);
|
||||
|
||||
/* Radio */
|
||||
bool (*supports_hwpctl)(struct b43_wldev *dev);
|
||||
void (*software_rfkill)(struct b43_wldev *dev, enum rfkill_state state);
|
||||
int (*switch_channel)(struct b43_wldev *dev, unsigned int new_channel);
|
||||
unsigned int (*get_default_chan)(struct b43_wldev *dev);
|
||||
void (*set_rx_antenna)(struct b43_wldev *dev, int antenna);
|
||||
int (*interf_mitigation)(struct b43_wldev *dev,
|
||||
enum b43_interference_mitigation new_mode);
|
||||
|
||||
/* Transmission power adjustment */
|
||||
enum b43_txpwr_result (*recalc_txpower)(struct b43_wldev *dev,
|
||||
bool ignore_tssi);
|
||||
void (*adjust_txpower)(struct b43_wldev *dev);
|
||||
|
||||
/* Misc */
|
||||
void (*pwork_15sec)(struct b43_wldev *dev);
|
||||
void (*pwork_60sec)(struct b43_wldev *dev);
|
||||
};
|
||||
|
||||
struct b43_phy_a;
|
||||
struct b43_phy_g;
|
||||
struct b43_phy_n;
|
||||
|
||||
struct b43_phy {
|
||||
/* Hardware operation callbacks. */
|
||||
const struct b43_phy_operations *ops;
|
||||
|
||||
/* Most hardware context information is stored in the standard-
|
||||
* specific data structures pointed to by the pointers below.
|
||||
* Only one of them is valid (the currently enabled PHY). */
|
||||
#ifdef CONFIG_B43_DEBUG
|
||||
/* No union for debug build to force NULL derefs in buggy code. */
|
||||
struct {
|
||||
#else
|
||||
union {
|
||||
#endif
|
||||
/* A-PHY specific information */
|
||||
struct b43_phy_a *a;
|
||||
/* G-PHY specific information */
|
||||
struct b43_phy_g *g;
|
||||
/* N-PHY specific information */
|
||||
struct b43_phy_n *n;
|
||||
};
|
||||
|
||||
/* Band support flags. */
|
||||
bool supports_2ghz;
|
||||
bool supports_5ghz;
|
||||
|
||||
/* GMODE bit enabled? */
|
||||
bool gmode;
|
||||
|
||||
/* Analog Type */
|
||||
u8 analog;
|
||||
/* B43_PHYTYPE_ */
|
||||
u8 type;
|
||||
/* PHY revision number. */
|
||||
u8 rev;
|
||||
|
||||
/* Radio versioning */
|
||||
u16 radio_manuf; /* Radio manufacturer */
|
||||
u16 radio_ver; /* Radio version */
|
||||
u8 radio_rev; /* Radio revision */
|
||||
|
||||
/* Software state of the radio */
|
||||
bool radio_on;
|
||||
|
||||
/* Desired TX power level (in dBm).
|
||||
* This is set by the user and adjusted in b43_phy_xmitpower(). */
|
||||
int desired_txpower;
|
||||
|
||||
/* Hardware Power Control enabled? */
|
||||
bool hardware_power_control;
|
||||
|
||||
/* The time (in absolute jiffies) when the next TX power output
|
||||
* check is needed. */
|
||||
unsigned long next_txpwr_check_time;
|
||||
|
||||
/* current channel */
|
||||
unsigned int channel;
|
||||
|
||||
/* PHY TX errors counter. */
|
||||
atomic_t txerr_cnt;
|
||||
|
||||
#ifdef CONFIG_B43_DEBUG
|
||||
/* PHY registers locked by b43_phy_lock()? */
|
||||
bool phy_locked;
|
||||
#endif /* B43_DEBUG */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* b43_phy_operations_setup - Initialize the PHY operations datastructure
|
||||
* based on the current PHY type.
|
||||
*/
|
||||
int b43_phy_operations_setup(struct b43_wldev *dev);
|
||||
|
||||
/**
|
||||
* b43_phy_init - Initialise the PHY
|
||||
*/
|
||||
int b43_phy_init(struct b43_wldev *dev);
|
||||
|
||||
/**
|
||||
* b43_phy_exit - Cleanup PHY
|
||||
*/
|
||||
void b43_phy_exit(struct b43_wldev *dev);
|
||||
|
||||
/**
|
||||
* b43_has_hardware_pctl - Hardware Power Control supported?
|
||||
* Returns a boolean, whether hardware power control is supported.
|
||||
*/
|
||||
bool b43_has_hardware_pctl(struct b43_wldev *dev);
|
||||
|
||||
/**
|
||||
* b43_phy_read - 16bit PHY register read access
|
||||
*/
|
||||
u16 b43_phy_read(struct b43_wldev *dev, u16 reg);
|
||||
|
||||
/**
|
||||
* b43_phy_write - 16bit PHY register write access
|
||||
*/
|
||||
void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value);
|
||||
|
||||
/**
|
||||
* b43_phy_mask - Mask a PHY register with a mask
|
||||
*/
|
||||
void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask);
|
||||
|
||||
/**
|
||||
* b43_phy_set - OR a PHY register with a bitmap
|
||||
*/
|
||||
void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set);
|
||||
|
||||
/**
|
||||
* b43_phy_maskset - Mask and OR a PHY register with a mask and bitmap
|
||||
*/
|
||||
void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
|
||||
|
||||
/**
|
||||
* b43_radio_read - 16bit Radio register read access
|
||||
*/
|
||||
u16 b43_radio_read(struct b43_wldev *dev, u16 reg);
|
||||
#define b43_radio_read16 b43_radio_read /* DEPRECATED */
|
||||
|
||||
/**
|
||||
* b43_radio_write - 16bit Radio register write access
|
||||
*/
|
||||
void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value);
|
||||
#define b43_radio_write16 b43_radio_write /* DEPRECATED */
|
||||
|
||||
/**
|
||||
* b43_radio_mask - Mask a 16bit radio register with a mask
|
||||
*/
|
||||
void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask);
|
||||
|
||||
/**
|
||||
* b43_radio_set - OR a 16bit radio register with a bitmap
|
||||
*/
|
||||
void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set);
|
||||
|
||||
/**
|
||||
* b43_radio_maskset - Mask and OR a radio register with a mask and bitmap
|
||||
*/
|
||||
void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
|
||||
|
||||
/**
|
||||
* b43_radio_lock - Lock firmware radio register access
|
||||
*/
|
||||
void b43_radio_lock(struct b43_wldev *dev);
|
||||
|
||||
/**
|
||||
* b43_radio_unlock - Unlock firmware radio register access
|
||||
*/
|
||||
void b43_radio_unlock(struct b43_wldev *dev);
|
||||
|
||||
/**
|
||||
* b43_phy_lock - Lock firmware PHY register access
|
||||
*/
|
||||
void b43_phy_lock(struct b43_wldev *dev);
|
||||
|
||||
/**
|
||||
* b43_phy_unlock - Unlock firmware PHY register access
|
||||
*/
|
||||
void b43_phy_unlock(struct b43_wldev *dev);
|
||||
|
||||
/**
|
||||
* b43_switch_channel - Switch to another channel
|
||||
*/
|
||||
int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel);
|
||||
/**
|
||||
* B43_DEFAULT_CHANNEL - Switch to the default channel.
|
||||
*/
|
||||
#define B43_DEFAULT_CHANNEL UINT_MAX
|
||||
|
||||
/**
|
||||
* b43_software_rfkill - Turn the radio ON or OFF in software.
|
||||
*/
|
||||
void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state);
|
||||
|
||||
/**
|
||||
* b43_phy_txpower_check - Check TX power output.
|
||||
*
|
||||
* Compare the current TX power output to the desired power emission
|
||||
* and schedule an adjustment in case it mismatches.
|
||||
* Requires wl->irq_lock locked.
|
||||
*
|
||||
* @flags: OR'ed enum b43_phy_txpower_check_flags flags.
|
||||
* See the docs below.
|
||||
*/
|
||||
void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags);
|
||||
/**
|
||||
* enum b43_phy_txpower_check_flags - Flags for b43_phy_txpower_check()
|
||||
*
|
||||
* @B43_TXPWR_IGNORE_TIME: Ignore the schedule time and force-redo
|
||||
* the check now.
|
||||
* @B43_TXPWR_IGNORE_TSSI: Redo the recalculation, even if the average
|
||||
* TSSI did not change.
|
||||
*/
|
||||
enum b43_phy_txpower_check_flags {
|
||||
B43_TXPWR_IGNORE_TIME = (1 << 0),
|
||||
B43_TXPWR_IGNORE_TSSI = (1 << 1),
|
||||
};
|
||||
|
||||
struct work_struct;
|
||||
void b43_phy_txpower_adjust_work(struct work_struct *work);
|
||||
|
||||
/**
|
||||
* b43_phy_shm_tssi_read - Read the average of the last 4 TSSI from SHM.
|
||||
*
|
||||
* @shm_offset: The SHM address to read the values from.
|
||||
*
|
||||
* Returns the average of the 4 TSSI values, or a negative error code.
|
||||
*/
|
||||
int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset);
|
||||
|
||||
|
||||
#endif /* LINUX_B43_PHY_COMMON_H_ */
|
3251
drivers/net/wireless/b43/phy_g.c
Normal file
3251
drivers/net/wireless/b43/phy_g.c
Normal file
File diff suppressed because it is too large
Load Diff
209
drivers/net/wireless/b43/phy_g.h
Normal file
209
drivers/net/wireless/b43/phy_g.h
Normal file
@ -0,0 +1,209 @@
|
||||
#ifndef LINUX_B43_PHY_G_H_
|
||||
#define LINUX_B43_PHY_G_H_
|
||||
|
||||
/* OFDM PHY registers are defined in the A-PHY header. */
|
||||
#include "phy_a.h"
|
||||
|
||||
/* CCK (B) PHY Registers */
|
||||
#define B43_PHY_VERSION_CCK B43_PHY_CCK(0x00) /* Versioning register for B-PHY */
|
||||
#define B43_PHY_CCKBBANDCFG B43_PHY_CCK(0x01) /* Contains antenna 0/1 control bit */
|
||||
#define B43_PHY_PGACTL B43_PHY_CCK(0x15) /* PGA control */
|
||||
#define B43_PHY_PGACTL_LPF 0x1000 /* Low pass filter (?) */
|
||||
#define B43_PHY_PGACTL_LOWBANDW 0x0040 /* Low bandwidth flag */
|
||||
#define B43_PHY_PGACTL_UNKNOWN 0xEFA0
|
||||
#define B43_PHY_FBCTL1 B43_PHY_CCK(0x18) /* Frequency bandwidth control 1 */
|
||||
#define B43_PHY_ITSSI B43_PHY_CCK(0x29) /* Idle TSSI */
|
||||
#define B43_PHY_LO_LEAKAGE B43_PHY_CCK(0x2D) /* Measured LO leakage */
|
||||
#define B43_PHY_ENERGY B43_PHY_CCK(0x33) /* Energy */
|
||||
#define B43_PHY_SYNCCTL B43_PHY_CCK(0x35)
|
||||
#define B43_PHY_FBCTL2 B43_PHY_CCK(0x38) /* Frequency bandwidth control 2 */
|
||||
#define B43_PHY_DACCTL B43_PHY_CCK(0x60) /* DAC control */
|
||||
#define B43_PHY_RCCALOVER B43_PHY_CCK(0x78) /* RC calibration override */
|
||||
|
||||
/* Extended G-PHY Registers */
|
||||
#define B43_PHY_CLASSCTL B43_PHY_EXTG(0x02) /* Classify control */
|
||||
#define B43_PHY_GTABCTL B43_PHY_EXTG(0x03) /* G-PHY table control (see below) */
|
||||
#define B43_PHY_GTABOFF 0x03FF /* G-PHY table offset (see below) */
|
||||
#define B43_PHY_GTABNR 0xFC00 /* G-PHY table number (see below) */
|
||||
#define B43_PHY_GTABNR_SHIFT 10
|
||||
#define B43_PHY_GTABDATA B43_PHY_EXTG(0x04) /* G-PHY table data */
|
||||
#define B43_PHY_LO_MASK B43_PHY_EXTG(0x0F) /* Local Oscillator control mask */
|
||||
#define B43_PHY_LO_CTL B43_PHY_EXTG(0x10) /* Local Oscillator control */
|
||||
#define B43_PHY_RFOVER B43_PHY_EXTG(0x11) /* RF override */
|
||||
#define B43_PHY_RFOVERVAL B43_PHY_EXTG(0x12) /* RF override value */
|
||||
#define B43_PHY_RFOVERVAL_EXTLNA 0x8000
|
||||
#define B43_PHY_RFOVERVAL_LNA 0x7000
|
||||
#define B43_PHY_RFOVERVAL_LNA_SHIFT 12
|
||||
#define B43_PHY_RFOVERVAL_PGA 0x0F00
|
||||
#define B43_PHY_RFOVERVAL_PGA_SHIFT 8
|
||||
#define B43_PHY_RFOVERVAL_UNK 0x0010 /* Unknown, always set. */
|
||||
#define B43_PHY_RFOVERVAL_TRSWRX 0x00E0
|
||||
#define B43_PHY_RFOVERVAL_BW 0x0003 /* Bandwidth flags */
|
||||
#define B43_PHY_RFOVERVAL_BW_LPF 0x0001 /* Low Pass Filter */
|
||||
#define B43_PHY_RFOVERVAL_BW_LBW 0x0002 /* Low Bandwidth (when set), high when unset */
|
||||
#define B43_PHY_ANALOGOVER B43_PHY_EXTG(0x14) /* Analog override */
|
||||
#define B43_PHY_ANALOGOVERVAL B43_PHY_EXTG(0x15) /* Analog override value */
|
||||
|
||||
|
||||
/*** G-PHY table numbers */
|
||||
#define B43_GTAB(number, offset) (((number) << B43_PHY_GTABNR_SHIFT) | (offset))
|
||||
#define B43_GTAB_NRSSI B43_GTAB(0x00, 0)
|
||||
#define B43_GTAB_TRFEMW B43_GTAB(0x0C, 0x120)
|
||||
#define B43_GTAB_ORIGTR B43_GTAB(0x2E, 0x298)
|
||||
|
||||
u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset);
|
||||
void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value);
|
||||
|
||||
|
||||
/* Returns the boolean whether "TX Magnification" is enabled. */
|
||||
#define has_tx_magnification(phy) \
|
||||
(((phy)->rev >= 2) && \
|
||||
((phy)->radio_ver == 0x2050) && \
|
||||
((phy)->radio_rev == 8))
|
||||
/* Card uses the loopback gain stuff */
|
||||
#define has_loopback_gain(phy) \
|
||||
(((phy)->rev > 1) || ((phy)->gmode))
|
||||
|
||||
/* Radio Attenuation (RF Attenuation) */
|
||||
struct b43_rfatt {
|
||||
u8 att; /* Attenuation value */
|
||||
bool with_padmix; /* Flag, PAD Mixer enabled. */
|
||||
};
|
||||
struct b43_rfatt_list {
|
||||
/* Attenuation values list */
|
||||
const struct b43_rfatt *list;
|
||||
u8 len;
|
||||
/* Minimum/Maximum attenuation values */
|
||||
u8 min_val;
|
||||
u8 max_val;
|
||||
};
|
||||
|
||||
/* Returns true, if the values are the same. */
|
||||
static inline bool b43_compare_rfatt(const struct b43_rfatt *a,
|
||||
const struct b43_rfatt *b)
|
||||
{
|
||||
return ((a->att == b->att) &&
|
||||
(a->with_padmix == b->with_padmix));
|
||||
}
|
||||
|
||||
/* Baseband Attenuation */
|
||||
struct b43_bbatt {
|
||||
u8 att; /* Attenuation value */
|
||||
};
|
||||
struct b43_bbatt_list {
|
||||
/* Attenuation values list */
|
||||
const struct b43_bbatt *list;
|
||||
u8 len;
|
||||
/* Minimum/Maximum attenuation values */
|
||||
u8 min_val;
|
||||
u8 max_val;
|
||||
};
|
||||
|
||||
/* Returns true, if the values are the same. */
|
||||
static inline bool b43_compare_bbatt(const struct b43_bbatt *a,
|
||||
const struct b43_bbatt *b)
|
||||
{
|
||||
return (a->att == b->att);
|
||||
}
|
||||
|
||||
/* tx_control bits. */
|
||||
#define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */
|
||||
#define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */
|
||||
#define B43_TXCTL_TXMIX 0x10 /* TX Mixer Gain */
|
||||
|
||||
struct b43_txpower_lo_control;
|
||||
|
||||
struct b43_phy_g {
|
||||
bool initialised;
|
||||
|
||||
/* ACI (adjacent channel interference) flags. */
|
||||
bool aci_enable;
|
||||
bool aci_wlan_automatic;
|
||||
bool aci_hw_rssi;
|
||||
|
||||
/* Radio switched on/off */
|
||||
bool radio_on;
|
||||
struct {
|
||||
/* Values saved when turning the radio off.
|
||||
* They are needed when turning it on again. */
|
||||
bool valid;
|
||||
u16 rfover;
|
||||
u16 rfoverval;
|
||||
} radio_off_context;
|
||||
|
||||
u16 minlowsig[2];
|
||||
u16 minlowsigpos[2];
|
||||
|
||||
/* Pointer to the table used to convert a
|
||||
* TSSI value to dBm-Q5.2 */
|
||||
const s8 *tssi2dbm;
|
||||
/* tssi2dbm is kmalloc()ed. Only used for free()ing. */
|
||||
bool dyn_tssi_tbl;
|
||||
/* Target idle TSSI */
|
||||
int tgt_idle_tssi;
|
||||
/* Current idle TSSI */
|
||||
int cur_idle_tssi;
|
||||
/* The current average TSSI.
|
||||
* Needs irq_lock, as it's updated in the IRQ path. */
|
||||
u8 average_tssi;
|
||||
/* Current TX power level attenuation control values */
|
||||
struct b43_bbatt bbatt;
|
||||
struct b43_rfatt rfatt;
|
||||
u8 tx_control; /* B43_TXCTL_XXX */
|
||||
/* The calculated attenuation deltas that are used later
|
||||
* when adjusting the actual power output. */
|
||||
int bbatt_delta;
|
||||
int rfatt_delta;
|
||||
|
||||
/* LocalOscillator control values. */
|
||||
struct b43_txpower_lo_control *lo_control;
|
||||
/* Values from b43_calc_loopback_gain() */
|
||||
s16 max_lb_gain; /* Maximum Loopback gain in hdB */
|
||||
s16 trsw_rx_gain; /* TRSW RX gain in hdB */
|
||||
s16 lna_lod_gain; /* LNA lod */
|
||||
s16 lna_gain; /* LNA */
|
||||
s16 pga_gain; /* PGA */
|
||||
|
||||
/* Current Interference Mitigation mode */
|
||||
int interfmode;
|
||||
/* Stack of saved values from the Interference Mitigation code.
|
||||
* Each value in the stack is layed out as follows:
|
||||
* bit 0-11: offset
|
||||
* bit 12-15: register ID
|
||||
* bit 16-32: value
|
||||
* register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
|
||||
*/
|
||||
#define B43_INTERFSTACK_SIZE 26
|
||||
u32 interfstack[B43_INTERFSTACK_SIZE]; //FIXME: use a data structure
|
||||
|
||||
/* Saved values from the NRSSI Slope calculation */
|
||||
s16 nrssi[2];
|
||||
s32 nrssislope;
|
||||
/* In memory nrssi lookup table. */
|
||||
s8 nrssi_lt[64];
|
||||
|
||||
u16 lofcal;
|
||||
|
||||
u16 initval; //FIXME rename?
|
||||
|
||||
/* The device does address auto increment for the OFDM tables.
|
||||
* We cache the previously used address here and omit the address
|
||||
* write on the next table access, if possible. */
|
||||
u16 ofdmtab_addr; /* The address currently set in hardware. */
|
||||
enum { /* The last data flow direction. */
|
||||
B43_OFDMTAB_DIRECTION_UNKNOWN = 0,
|
||||
B43_OFDMTAB_DIRECTION_READ,
|
||||
B43_OFDMTAB_DIRECTION_WRITE,
|
||||
} ofdmtab_addr_direction;
|
||||
};
|
||||
|
||||
void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev,
|
||||
u16 baseband_attenuation);
|
||||
void b43_gphy_channel_switch(struct b43_wldev *dev,
|
||||
unsigned int channel,
|
||||
bool synthetic_pu_workaround);
|
||||
|
||||
struct b43_phy_operations;
|
||||
extern const struct b43_phy_operations b43_phyops_g;
|
||||
|
||||
#endif /* LINUX_B43_PHY_G_H_ */
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "rfkill.h"
|
||||
#include "b43.h"
|
||||
#include "phy_common.h"
|
||||
|
||||
#include <linux/kmod.h>
|
||||
|
||||
@ -114,11 +115,11 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state)
|
||||
goto out_unlock;
|
||||
}
|
||||
if (!dev->phy.radio_on)
|
||||
b43_radio_turn_on(dev);
|
||||
b43_software_rfkill(dev, state);
|
||||
break;
|
||||
case RFKILL_STATE_SOFT_BLOCKED:
|
||||
if (dev->phy.radio_on)
|
||||
b43_radio_turn_off(dev, 0);
|
||||
b43_software_rfkill(dev, state);
|
||||
break;
|
||||
default:
|
||||
b43warn(wl, "Received unexpected rfkill state %d.\n", state);
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "b43.h"
|
||||
#include "sysfs.h"
|
||||
#include "main.h"
|
||||
#include "phy.h"
|
||||
#include "phy_common.h"
|
||||
|
||||
#define GENERIC_FILESIZE 64
|
||||
|
||||
@ -59,7 +59,12 @@ static ssize_t b43_attr_interfmode_show(struct device *dev,
|
||||
|
||||
mutex_lock(&wldev->wl->mutex);
|
||||
|
||||
switch (wldev->phy.interfmode) {
|
||||
if (wldev->phy.type != B43_PHYTYPE_G) {
|
||||
mutex_unlock(&wldev->wl->mutex);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
switch (wldev->phy.g->interfmode) {
|
||||
case B43_INTERFMODE_NONE:
|
||||
count =
|
||||
snprintf(buf, PAGE_SIZE,
|
||||
@ -117,11 +122,15 @@ static ssize_t b43_attr_interfmode_store(struct device *dev,
|
||||
mutex_lock(&wldev->wl->mutex);
|
||||
spin_lock_irqsave(&wldev->wl->irq_lock, flags);
|
||||
|
||||
err = b43_radio_set_interference_mitigation(wldev, mode);
|
||||
if (wldev->phy.ops->interf_mitigation) {
|
||||
err = wldev->phy.ops->interf_mitigation(wldev, mode);
|
||||
if (err) {
|
||||
b43err(wldev->wl, "Interference Mitigation not "
|
||||
"supported by device\n");
|
||||
}
|
||||
} else
|
||||
err = -ENOSYS;
|
||||
|
||||
mmiowb();
|
||||
spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
|
||||
mutex_unlock(&wldev->wl->mutex);
|
||||
|
@ -27,7 +27,8 @@
|
||||
|
||||
#include "b43.h"
|
||||
#include "tables.h"
|
||||
#include "phy.h"
|
||||
#include "phy_g.h"
|
||||
|
||||
|
||||
const u32 b43_tab_rotor[] = {
|
||||
0xFEB93FFD, 0xFEC63FFD, /* 0 */
|
||||
@ -377,17 +378,17 @@ static inline void assert_sizes(void)
|
||||
|
||||
u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_g *gphy = dev->phy.g;
|
||||
u16 addr;
|
||||
|
||||
addr = table + offset;
|
||||
if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
|
||||
(addr - 1 != phy->ofdmtab_addr)) {
|
||||
if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
|
||||
(addr - 1 != gphy->ofdmtab_addr)) {
|
||||
/* The hardware has a different address in memory. Update it. */
|
||||
b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
|
||||
phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
|
||||
gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
|
||||
}
|
||||
phy->ofdmtab_addr = addr;
|
||||
gphy->ofdmtab_addr = addr;
|
||||
|
||||
return b43_phy_read(dev, B43_PHY_OTABLEI);
|
||||
|
||||
@ -398,34 +399,34 @@ u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset)
|
||||
void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
|
||||
u16 offset, u16 value)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_g *gphy = dev->phy.g;
|
||||
u16 addr;
|
||||
|
||||
addr = table + offset;
|
||||
if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
|
||||
(addr - 1 != phy->ofdmtab_addr)) {
|
||||
if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
|
||||
(addr - 1 != gphy->ofdmtab_addr)) {
|
||||
/* The hardware has a different address in memory. Update it. */
|
||||
b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
|
||||
phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
|
||||
gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
|
||||
}
|
||||
phy->ofdmtab_addr = addr;
|
||||
gphy->ofdmtab_addr = addr;
|
||||
b43_phy_write(dev, B43_PHY_OTABLEI, value);
|
||||
}
|
||||
|
||||
u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_g *gphy = dev->phy.g;
|
||||
u32 ret;
|
||||
u16 addr;
|
||||
|
||||
addr = table + offset;
|
||||
if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
|
||||
(addr - 1 != phy->ofdmtab_addr)) {
|
||||
if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
|
||||
(addr - 1 != gphy->ofdmtab_addr)) {
|
||||
/* The hardware has a different address in memory. Update it. */
|
||||
b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
|
||||
phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
|
||||
gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
|
||||
}
|
||||
phy->ofdmtab_addr = addr;
|
||||
gphy->ofdmtab_addr = addr;
|
||||
ret = b43_phy_read(dev, B43_PHY_OTABLEQ);
|
||||
ret <<= 16;
|
||||
ret |= b43_phy_read(dev, B43_PHY_OTABLEI);
|
||||
@ -436,17 +437,17 @@ u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset)
|
||||
void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
|
||||
u16 offset, u32 value)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_g *gphy = dev->phy.g;
|
||||
u16 addr;
|
||||
|
||||
addr = table + offset;
|
||||
if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
|
||||
(addr - 1 != phy->ofdmtab_addr)) {
|
||||
if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
|
||||
(addr - 1 != gphy->ofdmtab_addr)) {
|
||||
/* The hardware has a different address in memory. Update it. */
|
||||
b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
|
||||
phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
|
||||
gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
|
||||
}
|
||||
phy->ofdmtab_addr = addr;
|
||||
gphy->ofdmtab_addr = addr;
|
||||
|
||||
b43_phy_write(dev, B43_PHY_OTABLEI, value);
|
||||
b43_phy_write(dev, B43_PHY_OTABLEQ, (value >> 16));
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include "b43.h"
|
||||
#include "tables_nphy.h"
|
||||
#include "phy.h"
|
||||
#include "phy_common.h"
|
||||
#include "nphy.h"
|
||||
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "b43.h"
|
||||
#include "main.h"
|
||||
#include "tables.h"
|
||||
#include "phy.h"
|
||||
#include "phy_common.h"
|
||||
#include "wa.h"
|
||||
|
||||
static void b43_wa_papd(struct b43_wldev *dev)
|
||||
|
@ -28,7 +28,7 @@
|
||||
*/
|
||||
|
||||
#include "xmit.h"
|
||||
#include "phy.h"
|
||||
#include "phy_common.h"
|
||||
#include "dma.h"
|
||||
#include "pio.h"
|
||||
|
||||
@ -431,6 +431,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev,
|
||||
int adjust_2053, int adjust_2050)
|
||||
{
|
||||
struct b43_phy *phy = &dev->phy;
|
||||
struct b43_phy_g *gphy = phy->g;
|
||||
s32 tmp;
|
||||
|
||||
switch (phy->radio_ver) {
|
||||
@ -450,7 +451,8 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev,
|
||||
boardflags_lo & B43_BFL_RSSI) {
|
||||
if (in_rssi > 63)
|
||||
in_rssi = 63;
|
||||
tmp = phy->nrssi_lt[in_rssi];
|
||||
B43_WARN_ON(phy->type != B43_PHYTYPE_G);
|
||||
tmp = gphy->nrssi_lt[in_rssi];
|
||||
tmp = 31 - tmp;
|
||||
tmp *= -131;
|
||||
tmp /= 128;
|
||||
@ -678,6 +680,8 @@ void b43_handle_txstatus(struct b43_wldev *dev,
|
||||
b43_pio_handle_txstatus(dev, status);
|
||||
else
|
||||
b43_dma_handle_txstatus(dev, status);
|
||||
|
||||
b43_phy_txpower_check(dev, 0);
|
||||
}
|
||||
|
||||
/* Fill out the mac80211 TXstatus report based on the b43-specific
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
@ -27,7 +27,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
@ -27,7 +27,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
@ -27,7 +27,6 @@
|
||||
*****************************************************************************/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "scan.h"
|
||||
#include "cmd.h"
|
||||
|
||||
static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp);
|
||||
|
||||
static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) =
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
@ -20,12 +21,88 @@ static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
|
||||
#define CAPINFO_MASK (~(0xda00))
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function finds common rates between rates and card rates.
|
||||
*
|
||||
* It will fill common rates in rates as output if found.
|
||||
*
|
||||
* NOTE: Setting the MSB of the basic rates need to be taken
|
||||
* care, either before or after calling this function
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param rates the buffer which keeps input and output
|
||||
* @param rates_size the size of rate1 buffer; new size of buffer on return
|
||||
*
|
||||
* @return 0 on success, or -1 on error
|
||||
*/
|
||||
static int get_common_rates(struct lbs_private *priv,
|
||||
u8 *rates,
|
||||
u16 *rates_size)
|
||||
{
|
||||
u8 *card_rates = lbs_bg_rates;
|
||||
size_t num_card_rates = sizeof(lbs_bg_rates);
|
||||
int ret = 0, i, j;
|
||||
u8 tmp[30];
|
||||
size_t tmp_size = 0;
|
||||
|
||||
/* For each rate in card_rates that exists in rate1, copy to tmp */
|
||||
for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
|
||||
for (j = 0; rates[j] && (j < *rates_size); j++) {
|
||||
if (rates[j] == card_rates[i])
|
||||
tmp[tmp_size++] = card_rates[i];
|
||||
}
|
||||
}
|
||||
|
||||
lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
|
||||
lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
|
||||
lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
|
||||
lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
|
||||
|
||||
if (!priv->enablehwauto) {
|
||||
for (i = 0; i < tmp_size; i++) {
|
||||
if (tmp[i] == priv->cur_rate)
|
||||
goto done;
|
||||
}
|
||||
lbs_pr_alert("Previously set fixed data rate %#x isn't "
|
||||
"compatible with the network.\n", priv->cur_rate);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
memset(rates, 0, *rates_size);
|
||||
*rates_size = min_t(int, tmp_size, *rates_size);
|
||||
memcpy(rates, tmp, *rates_size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the MSB on basic rates as the firmware requires
|
||||
*
|
||||
* Scan through an array and set the MSB for basic data rates.
|
||||
*
|
||||
* @param rates buffer of data rates
|
||||
* @param len size of buffer
|
||||
*/
|
||||
static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (rates[i] == 0x02 || rates[i] == 0x04 ||
|
||||
rates[i] == 0x0b || rates[i] == 0x16)
|
||||
rates[i] |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Associate to a specific BSS discovered in a scan
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param pbssdesc Pointer to the BSS descriptor to associate with.
|
||||
* @param assoc_req The association request describing the BSS to associate with
|
||||
*
|
||||
* @return 0-success, otherwise fail
|
||||
*/
|
||||
@ -33,29 +110,29 @@ static int lbs_associate(struct lbs_private *priv,
|
||||
struct assoc_request *assoc_req)
|
||||
{
|
||||
int ret;
|
||||
u8 preamble = RADIO_PREAMBLE_LONG;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_ASSOC);
|
||||
|
||||
ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
|
||||
0, CMD_OPTION_WAITFORRSP,
|
||||
0, assoc_req->bss.bssid);
|
||||
|
||||
if (ret)
|
||||
goto done;
|
||||
goto out;
|
||||
|
||||
/* set preamble to firmware */
|
||||
/* Use short preamble only when both the BSS and firmware support it */
|
||||
if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
|
||||
(assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
|
||||
priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
|
||||
else
|
||||
priv->preamble = CMD_TYPE_LONG_PREAMBLE;
|
||||
preamble = RADIO_PREAMBLE_SHORT;
|
||||
|
||||
lbs_set_radio_control(priv);
|
||||
ret = lbs_set_radio(priv, preamble, 1);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
|
||||
0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
|
||||
|
||||
done:
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
@ -64,17 +141,22 @@ done:
|
||||
* @brief Join an adhoc network found in a previous scan
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param pbssdesc Pointer to a BSS descriptor found in a previous scan
|
||||
* to attempt to join
|
||||
* @param assoc_req The association request describing the BSS to join
|
||||
*
|
||||
* @return 0--success, -1--fail
|
||||
* @return 0 on success, error on failure
|
||||
*/
|
||||
static int lbs_join_adhoc_network(struct lbs_private *priv,
|
||||
static int lbs_adhoc_join(struct lbs_private *priv,
|
||||
struct assoc_request *assoc_req)
|
||||
{
|
||||
struct cmd_ds_802_11_ad_hoc_join cmd;
|
||||
struct bss_descriptor *bss = &assoc_req->bss;
|
||||
u8 preamble = RADIO_PREAMBLE_LONG;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
u16 ratesize = 0;
|
||||
int ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_ASSOC);
|
||||
|
||||
lbs_deb_join("current SSID '%s', ssid length %u\n",
|
||||
escape_essid(priv->curbssparams.ssid,
|
||||
priv->curbssparams.ssid_len),
|
||||
@ -106,29 +188,106 @@ static int lbs_join_adhoc_network(struct lbs_private *priv,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Use shortpreamble only when both creator and card supports
|
||||
short preamble */
|
||||
if (!(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) ||
|
||||
!(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
|
||||
lbs_deb_join("AdhocJoin: Long preamble\n");
|
||||
priv->preamble = CMD_TYPE_LONG_PREAMBLE;
|
||||
} else {
|
||||
/* Use short preamble only when both the BSS and firmware support it */
|
||||
if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
|
||||
(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
|
||||
lbs_deb_join("AdhocJoin: Short preamble\n");
|
||||
priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
|
||||
preamble = RADIO_PREAMBLE_SHORT;
|
||||
}
|
||||
|
||||
lbs_set_radio_control(priv);
|
||||
ret = lbs_set_radio(priv, preamble, 1);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
|
||||
lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
|
||||
|
||||
priv->adhoccreate = 0;
|
||||
priv->curbssparams.channel = bss->channel;
|
||||
|
||||
ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,
|
||||
0, CMD_OPTION_WAITFORRSP,
|
||||
OID_802_11_SSID, assoc_req);
|
||||
/* Build the join command */
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
|
||||
cmd.bss.type = CMD_BSS_TYPE_IBSS;
|
||||
cmd.bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
|
||||
|
||||
memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN);
|
||||
memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len);
|
||||
|
||||
memcpy(&cmd.bss.phyparamset, &bss->phyparamset,
|
||||
sizeof(union ieeetypes_phyparamset));
|
||||
|
||||
memcpy(&cmd.bss.ssparamset, &bss->ssparamset,
|
||||
sizeof(union IEEEtypes_ssparamset));
|
||||
|
||||
cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
|
||||
lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
|
||||
bss->capability, CAPINFO_MASK);
|
||||
|
||||
/* information on BSSID descriptor passed to FW */
|
||||
lbs_deb_join("ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
|
||||
print_mac(mac, cmd.bss.bssid), cmd.bss.ssid);
|
||||
|
||||
/* Only v8 and below support setting these */
|
||||
if (priv->fwrelease < 0x09000000) {
|
||||
/* failtimeout */
|
||||
cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
|
||||
/* probedelay */
|
||||
cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
|
||||
}
|
||||
|
||||
/* Copy Data rates from the rates recorded in scan response */
|
||||
memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates));
|
||||
ratesize = min_t(u16, sizeof(cmd.bss.rates), MAX_RATES);
|
||||
memcpy(cmd.bss.rates, bss->rates, ratesize);
|
||||
if (get_common_rates(priv, cmd.bss.rates, &ratesize)) {
|
||||
lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Copy the ad-hoc creation rates into Current BSS state structure */
|
||||
memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
|
||||
memcpy(&priv->curbssparams.rates, cmd.bss.rates, ratesize);
|
||||
|
||||
/* Set MSB on basic rates as the firmware requires, but _after_
|
||||
* copying to current bss rates.
|
||||
*/
|
||||
lbs_set_basic_rate_flags(cmd.bss.rates, ratesize);
|
||||
|
||||
cmd.bss.ssparamset.ibssparamset.atimwindow = cpu_to_le16(bss->atimwindow);
|
||||
|
||||
if (assoc_req->secinfo.wep_enabled) {
|
||||
u16 tmp = le16_to_cpu(cmd.bss.capability);
|
||||
tmp |= WLAN_CAPABILITY_PRIVACY;
|
||||
cmd.bss.capability = cpu_to_le16(tmp);
|
||||
}
|
||||
|
||||
if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
|
||||
__le32 local_ps_mode = cpu_to_le32(LBS802_11POWERMODECAM);
|
||||
|
||||
/* wake up first */
|
||||
ret = lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
|
||||
CMD_ACT_SET, 0, 0,
|
||||
&local_ps_mode);
|
||||
if (ret) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
|
||||
if (ret == 0)
|
||||
ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd);
|
||||
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -136,39 +295,131 @@ out:
|
||||
* @brief Start an Adhoc Network
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param adhocssid The ssid of the Adhoc Network
|
||||
* @return 0--success, -1--fail
|
||||
* @param assoc_req The association request describing the BSS to start
|
||||
*
|
||||
* @return 0 on success, error on failure
|
||||
*/
|
||||
static int lbs_start_adhoc_network(struct lbs_private *priv,
|
||||
static int lbs_adhoc_start(struct lbs_private *priv,
|
||||
struct assoc_request *assoc_req)
|
||||
{
|
||||
struct cmd_ds_802_11_ad_hoc_start cmd;
|
||||
u8 preamble = RADIO_PREAMBLE_LONG;
|
||||
size_t ratesize = 0;
|
||||
u16 tmpcap = 0;
|
||||
int ret = 0;
|
||||
|
||||
priv->adhoccreate = 1;
|
||||
lbs_deb_enter(LBS_DEB_ASSOC);
|
||||
|
||||
if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
|
||||
lbs_deb_join("AdhocStart: Short preamble\n");
|
||||
priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
|
||||
} else {
|
||||
lbs_deb_join("AdhocStart: Long preamble\n");
|
||||
priv->preamble = CMD_TYPE_LONG_PREAMBLE;
|
||||
lbs_deb_join("ADHOC_START: Will use short preamble\n");
|
||||
preamble = RADIO_PREAMBLE_SHORT;
|
||||
}
|
||||
|
||||
lbs_set_radio_control(priv);
|
||||
ret = lbs_set_radio(priv, preamble, 1);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
|
||||
lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
|
||||
/* Build the start command */
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
|
||||
ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,
|
||||
0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
|
||||
memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len);
|
||||
|
||||
lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n",
|
||||
escape_essid(assoc_req->ssid, assoc_req->ssid_len),
|
||||
assoc_req->ssid_len);
|
||||
|
||||
cmd.bsstype = CMD_BSS_TYPE_IBSS;
|
||||
|
||||
if (priv->beacon_period == 0)
|
||||
priv->beacon_period = MRVDRV_BEACON_INTERVAL;
|
||||
cmd.beaconperiod = cpu_to_le16(priv->beacon_period);
|
||||
|
||||
WARN_ON(!assoc_req->channel);
|
||||
|
||||
/* set Physical parameter set */
|
||||
cmd.phyparamset.dsparamset.elementid = MFIE_TYPE_DS_SET;
|
||||
cmd.phyparamset.dsparamset.len = 1;
|
||||
cmd.phyparamset.dsparamset.currentchan = assoc_req->channel;
|
||||
|
||||
/* set IBSS parameter set */
|
||||
cmd.ssparamset.ibssparamset.elementid = MFIE_TYPE_IBSS_SET;
|
||||
cmd.ssparamset.ibssparamset.len = 2;
|
||||
cmd.ssparamset.ibssparamset.atimwindow = 0;
|
||||
|
||||
/* set capability info */
|
||||
tmpcap = WLAN_CAPABILITY_IBSS;
|
||||
if (assoc_req->secinfo.wep_enabled) {
|
||||
lbs_deb_join("ADHOC_START: WEP enabled, setting privacy on\n");
|
||||
tmpcap |= WLAN_CAPABILITY_PRIVACY;
|
||||
} else
|
||||
lbs_deb_join("ADHOC_START: WEP disabled, setting privacy off\n");
|
||||
|
||||
cmd.capability = cpu_to_le16(tmpcap);
|
||||
|
||||
/* Only v8 and below support setting probe delay */
|
||||
if (priv->fwrelease < 0x09000000)
|
||||
cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
|
||||
|
||||
ratesize = min(sizeof(cmd.rates), sizeof(lbs_bg_rates));
|
||||
memcpy(cmd.rates, lbs_bg_rates, ratesize);
|
||||
|
||||
/* Copy the ad-hoc creating rates into Current BSS state structure */
|
||||
memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
|
||||
memcpy(&priv->curbssparams.rates, &cmd.rates, ratesize);
|
||||
|
||||
/* Set MSB on basic rates as the firmware requires, but _after_
|
||||
* copying to current bss rates.
|
||||
*/
|
||||
lbs_set_basic_rate_flags(cmd.rates, ratesize);
|
||||
|
||||
lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n",
|
||||
cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]);
|
||||
|
||||
if (lbs_create_dnld_countryinfo_11d(priv)) {
|
||||
lbs_deb_join("ADHOC_START: dnld_countryinfo_11d failed\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n",
|
||||
assoc_req->channel, assoc_req->band);
|
||||
|
||||
priv->adhoccreate = 1;
|
||||
priv->mode = IW_MODE_ADHOC;
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd);
|
||||
if (ret == 0)
|
||||
ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd);
|
||||
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_stop_adhoc_network(struct lbs_private *priv)
|
||||
/**
|
||||
* @brief Stop and Ad-Hoc network and exit Ad-Hoc mode
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @return 0 on success, or an error
|
||||
*/
|
||||
int lbs_adhoc_stop(struct lbs_private *priv)
|
||||
{
|
||||
return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,
|
||||
0, CMD_OPTION_WAITFORRSP, 0, NULL);
|
||||
struct cmd_ds_802_11_ad_hoc_stop cmd;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_JOIN);
|
||||
|
||||
memset(&cmd, 0, sizeof (cmd));
|
||||
cmd.hdr.size = cpu_to_le16 (sizeof (cmd));
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd);
|
||||
|
||||
/* Clean up everything even if there was an error */
|
||||
lbs_mac_event_disconnected(priv);
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
|
||||
@ -480,14 +731,14 @@ static int assoc_helper_essid(struct lbs_private *priv,
|
||||
if (bss != NULL) {
|
||||
lbs_deb_assoc("SSID found, will join\n");
|
||||
memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
|
||||
lbs_join_adhoc_network(priv, assoc_req);
|
||||
lbs_adhoc_join(priv, assoc_req);
|
||||
} else {
|
||||
/* else send START command */
|
||||
lbs_deb_assoc("SSID not found, creating adhoc network\n");
|
||||
memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
|
||||
IW_ESSID_MAX_SIZE);
|
||||
assoc_req->bss.ssid_len = assoc_req->ssid_len;
|
||||
lbs_start_adhoc_network(priv, assoc_req);
|
||||
lbs_adhoc_start(priv, assoc_req);
|
||||
}
|
||||
}
|
||||
|
||||
@ -520,7 +771,7 @@ static int assoc_helper_bssid(struct lbs_private *priv,
|
||||
ret = lbs_associate(priv, assoc_req);
|
||||
lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret);
|
||||
} else if (assoc_req->mode == IW_MODE_ADHOC) {
|
||||
lbs_join_adhoc_network(priv, assoc_req);
|
||||
lbs_adhoc_join(priv, assoc_req);
|
||||
}
|
||||
|
||||
out:
|
||||
@ -1029,7 +1280,9 @@ void lbs_association_worker(struct work_struct *work)
|
||||
*/
|
||||
if (priv->mode == IW_MODE_INFRA) {
|
||||
if (should_deauth_infrastructure(priv, assoc_req)) {
|
||||
ret = lbs_send_deauthentication(priv);
|
||||
ret = lbs_cmd_80211_deauthenticate(priv,
|
||||
priv->curbssparams.bssid,
|
||||
WLAN_REASON_DEAUTH_LEAVING);
|
||||
if (ret) {
|
||||
lbs_deb_assoc("Deauthentication due to new "
|
||||
"configuration request failed: %d\n",
|
||||
@ -1038,7 +1291,7 @@ void lbs_association_worker(struct work_struct *work)
|
||||
}
|
||||
} else if (priv->mode == IW_MODE_ADHOC) {
|
||||
if (should_stop_adhoc(priv, assoc_req)) {
|
||||
ret = lbs_stop_adhoc_network(priv);
|
||||
ret = lbs_adhoc_stop(priv);
|
||||
if (ret) {
|
||||
lbs_deb_assoc("Teardown of AdHoc network due to "
|
||||
"new configuration request failed: %d\n",
|
||||
@ -1213,94 +1466,6 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function finds common rates between rate1 and card rates.
|
||||
*
|
||||
* It will fill common rates in rate1 as output if found.
|
||||
*
|
||||
* NOTE: Setting the MSB of the basic rates need to be taken
|
||||
* care, either before or after calling this function
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param rate1 the buffer which keeps input and output
|
||||
* @param rate1_size the size of rate1 buffer; new size of buffer on return
|
||||
*
|
||||
* @return 0 or -1
|
||||
*/
|
||||
static int get_common_rates(struct lbs_private *priv,
|
||||
u8 *rates,
|
||||
u16 *rates_size)
|
||||
{
|
||||
u8 *card_rates = lbs_bg_rates;
|
||||
size_t num_card_rates = sizeof(lbs_bg_rates);
|
||||
int ret = 0, i, j;
|
||||
u8 tmp[30];
|
||||
size_t tmp_size = 0;
|
||||
|
||||
/* For each rate in card_rates that exists in rate1, copy to tmp */
|
||||
for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
|
||||
for (j = 0; rates[j] && (j < *rates_size); j++) {
|
||||
if (rates[j] == card_rates[i])
|
||||
tmp[tmp_size++] = card_rates[i];
|
||||
}
|
||||
}
|
||||
|
||||
lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
|
||||
lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
|
||||
lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
|
||||
lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
|
||||
|
||||
if (!priv->enablehwauto) {
|
||||
for (i = 0; i < tmp_size; i++) {
|
||||
if (tmp[i] == priv->cur_rate)
|
||||
goto done;
|
||||
}
|
||||
lbs_pr_alert("Previously set fixed data rate %#x isn't "
|
||||
"compatible with the network.\n", priv->cur_rate);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
memset(rates, 0, *rates_size);
|
||||
*rates_size = min_t(int, tmp_size, *rates_size);
|
||||
memcpy(rates, tmp, *rates_size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the MSB on basic rates as the firmware requires
|
||||
*
|
||||
* Scan through an array and set the MSB for basic data rates.
|
||||
*
|
||||
* @param rates buffer of data rates
|
||||
* @param len size of buffer
|
||||
*/
|
||||
static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (rates[i] == 0x02 || rates[i] == 0x04 ||
|
||||
rates[i] == 0x0b || rates[i] == 0x16)
|
||||
rates[i] |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send Deauthentication Request
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @return 0--success, -1--fail
|
||||
*/
|
||||
int lbs_send_deauthentication(struct lbs_private *priv)
|
||||
{
|
||||
return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
|
||||
0, CMD_OPTION_WAITFORRSP, 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function prepares command of authenticate.
|
||||
*
|
||||
@ -1353,26 +1518,37 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd)
|
||||
/**
|
||||
* @brief Deauthenticate from a specific BSS
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param bssid The specific BSS to deauthenticate from
|
||||
* @param reason The 802.11 sec. 7.3.1.7 Reason Code for deauthenticating
|
||||
*
|
||||
* @return 0 on success, error on failure
|
||||
*/
|
||||
int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN],
|
||||
u16 reason)
|
||||
{
|
||||
struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
|
||||
struct cmd_ds_802_11_deauthenticate cmd;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_JOIN);
|
||||
|
||||
cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE);
|
||||
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
|
||||
S_DS_GEN);
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
memcpy(cmd.macaddr, &bssid[0], ETH_ALEN);
|
||||
cmd.reasoncode = cpu_to_le16(reason);
|
||||
|
||||
/* set AP MAC address */
|
||||
memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd);
|
||||
|
||||
/* Reason code 3 = Station is leaving */
|
||||
#define REASON_CODE_STA_LEAVING 3
|
||||
dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
|
||||
/* Clean up everything even if there was an error; can't assume that
|
||||
* we're still authenticated to the AP after trying to deauth.
|
||||
*/
|
||||
lbs_mac_event_disconnected(priv);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_JOIN);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_cmd_80211_associate(struct lbs_private *priv,
|
||||
@ -1489,231 +1665,6 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd, void *pdata_buf)
|
||||
{
|
||||
struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
|
||||
int ret = 0;
|
||||
int cmdappendsize = 0;
|
||||
struct assoc_request *assoc_req = pdata_buf;
|
||||
u16 tmpcap = 0;
|
||||
size_t ratesize = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_JOIN);
|
||||
|
||||
if (!priv) {
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START);
|
||||
|
||||
/*
|
||||
* Fill in the parameters for 2 data structures:
|
||||
* 1. cmd_ds_802_11_ad_hoc_start command
|
||||
* 2. priv->scantable[i]
|
||||
*
|
||||
* Driver will fill up SSID, bsstype,IBSS param, Physical Param,
|
||||
* probe delay, and cap info.
|
||||
*
|
||||
* Firmware will fill up beacon period, DTIM, Basic rates
|
||||
* and operational rates.
|
||||
*/
|
||||
|
||||
memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE);
|
||||
memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len);
|
||||
|
||||
lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
|
||||
escape_essid(assoc_req->ssid, assoc_req->ssid_len),
|
||||
assoc_req->ssid_len);
|
||||
|
||||
/* set the BSS type */
|
||||
adhs->bsstype = CMD_BSS_TYPE_IBSS;
|
||||
priv->mode = IW_MODE_ADHOC;
|
||||
if (priv->beacon_period == 0)
|
||||
priv->beacon_period = MRVDRV_BEACON_INTERVAL;
|
||||
adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
|
||||
|
||||
/* set Physical param set */
|
||||
#define DS_PARA_IE_ID 3
|
||||
#define DS_PARA_IE_LEN 1
|
||||
|
||||
adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
|
||||
adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
|
||||
|
||||
WARN_ON(!assoc_req->channel);
|
||||
|
||||
lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
|
||||
assoc_req->channel);
|
||||
|
||||
adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
|
||||
|
||||
/* set IBSS param set */
|
||||
#define IBSS_PARA_IE_ID 6
|
||||
#define IBSS_PARA_IE_LEN 2
|
||||
|
||||
adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
|
||||
adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
|
||||
adhs->ssparamset.ibssparamset.atimwindow = 0;
|
||||
|
||||
/* set capability info */
|
||||
tmpcap = WLAN_CAPABILITY_IBSS;
|
||||
if (assoc_req->secinfo.wep_enabled) {
|
||||
lbs_deb_join("ADHOC_S_CMD: WEP enabled, "
|
||||
"setting privacy on\n");
|
||||
tmpcap |= WLAN_CAPABILITY_PRIVACY;
|
||||
} else {
|
||||
lbs_deb_join("ADHOC_S_CMD: WEP disabled, "
|
||||
"setting privacy off\n");
|
||||
}
|
||||
adhs->capability = cpu_to_le16(tmpcap);
|
||||
|
||||
/* probedelay */
|
||||
adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
|
||||
|
||||
memset(adhs->rates, 0, sizeof(adhs->rates));
|
||||
ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
|
||||
memcpy(adhs->rates, lbs_bg_rates, ratesize);
|
||||
|
||||
/* Copy the ad-hoc creating rates into Current BSS state structure */
|
||||
memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
|
||||
memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
|
||||
|
||||
/* Set MSB on basic rates as the firmware requires, but _after_
|
||||
* copying to current bss rates.
|
||||
*/
|
||||
lbs_set_basic_rate_flags(adhs->rates, ratesize);
|
||||
|
||||
lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
|
||||
adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
|
||||
|
||||
lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
|
||||
|
||||
if (lbs_create_dnld_countryinfo_11d(priv)) {
|
||||
lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
|
||||
S_DS_GEN + cmdappendsize);
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd)
|
||||
{
|
||||
cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
|
||||
cmd->size = cpu_to_le16(S_DS_GEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd, void *pdata_buf)
|
||||
{
|
||||
struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
|
||||
struct assoc_request *assoc_req = pdata_buf;
|
||||
struct bss_descriptor *bss = &assoc_req->bss;
|
||||
int cmdappendsize = 0;
|
||||
int ret = 0;
|
||||
u16 ratesize = 0;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
lbs_deb_enter(LBS_DEB_JOIN);
|
||||
|
||||
cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN);
|
||||
|
||||
join_cmd->bss.type = CMD_BSS_TYPE_IBSS;
|
||||
join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
|
||||
|
||||
memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN);
|
||||
memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len);
|
||||
|
||||
memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset,
|
||||
sizeof(union ieeetypes_phyparamset));
|
||||
|
||||
memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset,
|
||||
sizeof(union IEEEtypes_ssparamset));
|
||||
|
||||
join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
|
||||
lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
|
||||
bss->capability, CAPINFO_MASK);
|
||||
|
||||
/* information on BSSID descriptor passed to FW */
|
||||
lbs_deb_join(
|
||||
"ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
|
||||
print_mac(mac, join_cmd->bss.bssid),
|
||||
join_cmd->bss.ssid);
|
||||
|
||||
/* failtimeout */
|
||||
join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
|
||||
|
||||
/* probedelay */
|
||||
join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
|
||||
|
||||
priv->curbssparams.channel = bss->channel;
|
||||
|
||||
/* Copy Data rates from the rates recorded in scan response */
|
||||
memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
|
||||
ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
|
||||
memcpy(join_cmd->bss.rates, bss->rates, ratesize);
|
||||
if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
|
||||
lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Copy the ad-hoc creating rates into Current BSS state structure */
|
||||
memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
|
||||
memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
|
||||
|
||||
/* Set MSB on basic rates as the firmware requires, but _after_
|
||||
* copying to current bss rates.
|
||||
*/
|
||||
lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
|
||||
|
||||
join_cmd->bss.ssparamset.ibssparamset.atimwindow =
|
||||
cpu_to_le16(bss->atimwindow);
|
||||
|
||||
if (assoc_req->secinfo.wep_enabled) {
|
||||
u16 tmp = le16_to_cpu(join_cmd->bss.capability);
|
||||
tmp |= WLAN_CAPABILITY_PRIVACY;
|
||||
join_cmd->bss.capability = cpu_to_le16(tmp);
|
||||
}
|
||||
|
||||
if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
|
||||
/* wake up first */
|
||||
__le32 Localpsmode;
|
||||
|
||||
Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
|
||||
ret = lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_PS_MODE,
|
||||
CMD_ACT_SET,
|
||||
0, 0, &Localpsmode);
|
||||
|
||||
if (ret) {
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
|
||||
S_DS_GEN + cmdappendsize);
|
||||
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_ret_80211_associate(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp)
|
||||
{
|
||||
@ -1815,34 +1766,19 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_ret_80211_disassociate(struct lbs_private *priv)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_JOIN);
|
||||
|
||||
lbs_mac_event_disconnected(priv);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_JOIN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp)
|
||||
static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp)
|
||||
{
|
||||
int ret = 0;
|
||||
u16 command = le16_to_cpu(resp->command);
|
||||
u16 result = le16_to_cpu(resp->result);
|
||||
struct cmd_ds_802_11_ad_hoc_result *padhocresult;
|
||||
struct cmd_ds_802_11_ad_hoc_result *adhoc_resp;
|
||||
union iwreq_data wrqu;
|
||||
struct bss_descriptor *bss;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
lbs_deb_enter(LBS_DEB_JOIN);
|
||||
|
||||
padhocresult = &resp->params.result;
|
||||
|
||||
lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
|
||||
lbs_deb_join("ADHOC_RESP: command = %x\n", command);
|
||||
lbs_deb_join("ADHOC_RESP: result = %x\n", result);
|
||||
adhoc_resp = (struct cmd_ds_802_11_ad_hoc_result *) resp;
|
||||
|
||||
if (!priv->in_progress_assoc_req) {
|
||||
lbs_deb_join("ADHOC_RESP: no in-progress association "
|
||||
@ -1856,26 +1792,19 @@ int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
|
||||
* Join result code 0 --> SUCCESS
|
||||
*/
|
||||
if (result) {
|
||||
lbs_deb_join("ADHOC_RESP: failed\n");
|
||||
lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result);
|
||||
if (priv->connect_status == LBS_CONNECTED)
|
||||
lbs_mac_event_disconnected(priv);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now the join cmd should be successful
|
||||
* If BSSID has changed use SSID to compare instead of BSSID
|
||||
*/
|
||||
lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
|
||||
escape_essid(bss->ssid, bss->ssid_len));
|
||||
|
||||
/* Send a Media Connected event, according to the Spec */
|
||||
priv->connect_status = LBS_CONNECTED;
|
||||
|
||||
if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
|
||||
/* Update the created network descriptor with the new BSSID */
|
||||
memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN);
|
||||
memcpy(bss->bssid, adhoc_resp->bssid, ETH_ALEN);
|
||||
}
|
||||
|
||||
/* Set the BSSID from the joined/started descriptor */
|
||||
@ -1894,22 +1823,13 @@ int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
|
||||
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
|
||||
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
|
||||
|
||||
lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
|
||||
lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel);
|
||||
lbs_deb_join("ADHOC_RESP: BSSID = %s\n",
|
||||
print_mac(mac, padhocresult->bssid));
|
||||
lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %s, channel %d\n",
|
||||
escape_essid(bss->ssid, bss->ssid_len),
|
||||
print_mac(mac, priv->curbssparams.bssid),
|
||||
priv->curbssparams.channel);
|
||||
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_JOIN);
|
||||
|
||||
lbs_mac_event_disconnected(priv);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_JOIN);
|
||||
return 0;
|
||||
}
|
||||
|
@ -12,28 +12,18 @@ struct cmd_ds_command;
|
||||
int lbs_cmd_80211_authenticate(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd,
|
||||
void *pdata_buf);
|
||||
int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd,
|
||||
void *pdata_buf);
|
||||
int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd);
|
||||
int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd,
|
||||
void *pdata_buf);
|
||||
|
||||
int lbs_adhoc_stop(struct lbs_private *priv);
|
||||
|
||||
int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd);
|
||||
u8 bssid[ETH_ALEN], u16 reason);
|
||||
int lbs_cmd_80211_associate(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd,
|
||||
void *pdata_buf);
|
||||
|
||||
int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp);
|
||||
int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv);
|
||||
int lbs_ret_80211_disassociate(struct lbs_private *priv);
|
||||
int lbs_ret_80211_associate(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp);
|
||||
|
||||
int lbs_stop_adhoc_network(struct lbs_private *priv);
|
||||
|
||||
int lbs_send_deauthentication(struct lbs_private *priv);
|
||||
|
||||
#endif /* _LBS_ASSOC_H */
|
||||
|
@ -614,47 +614,67 @@ static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lbs_cmd_802_11_rf_tx_power(struct cmd_ds_command *cmd,
|
||||
u16 cmd_action, void *pdata_buf)
|
||||
/**
|
||||
* @brief Get the min, max, and current TX power
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param curlevel Current power level in dBm
|
||||
* @param minlevel Minimum supported power level in dBm (optional)
|
||||
* @param maxlevel Maximum supported power level in dBm (optional)
|
||||
*
|
||||
* @return 0 on success, error on failure
|
||||
*/
|
||||
int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
|
||||
s16 *maxlevel)
|
||||
{
|
||||
|
||||
struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp;
|
||||
struct cmd_ds_802_11_rf_tx_power cmd;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
cmd->size =
|
||||
cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN);
|
||||
cmd->command = cpu_to_le16(CMD_802_11_RF_TX_POWER);
|
||||
prtp->action = cpu_to_le16(cmd_action);
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.action = cpu_to_le16(CMD_ACT_GET);
|
||||
|
||||
lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n",
|
||||
le16_to_cpu(cmd->size), le16_to_cpu(cmd->command),
|
||||
le16_to_cpu(prtp->action));
|
||||
|
||||
switch (cmd_action) {
|
||||
case CMD_ACT_TX_POWER_OPT_GET:
|
||||
prtp->action = cpu_to_le16(CMD_ACT_GET);
|
||||
prtp->currentlevel = 0;
|
||||
break;
|
||||
|
||||
case CMD_ACT_TX_POWER_OPT_SET_HIGH:
|
||||
prtp->action = cpu_to_le16(CMD_ACT_SET);
|
||||
prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_HIGH);
|
||||
break;
|
||||
|
||||
case CMD_ACT_TX_POWER_OPT_SET_MID:
|
||||
prtp->action = cpu_to_le16(CMD_ACT_SET);
|
||||
prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_MID);
|
||||
break;
|
||||
|
||||
case CMD_ACT_TX_POWER_OPT_SET_LOW:
|
||||
prtp->action = cpu_to_le16(CMD_ACT_SET);
|
||||
prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf));
|
||||
break;
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
|
||||
if (ret == 0) {
|
||||
*curlevel = le16_to_cpu(cmd.curlevel);
|
||||
if (minlevel)
|
||||
*minlevel = le16_to_cpu(cmd.minlevel);
|
||||
if (maxlevel)
|
||||
*maxlevel = le16_to_cpu(cmd.maxlevel);
|
||||
}
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the TX power
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param dbm The desired power level in dBm
|
||||
*
|
||||
* @return 0 on success, error on failure
|
||||
*/
|
||||
int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
|
||||
{
|
||||
struct cmd_ds_802_11_rf_tx_power cmd;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.action = cpu_to_le16(CMD_ACT_SET);
|
||||
cmd.curlevel = cpu_to_le16(dbm);
|
||||
|
||||
lbs_deb_cmd("SET_RF_TX_POWER: %d dBm\n", dbm);
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
|
||||
@ -1269,41 +1289,47 @@ void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
|
||||
priv->cur_cmd = NULL;
|
||||
}
|
||||
|
||||
int lbs_set_radio_control(struct lbs_private *priv)
|
||||
int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cmd_ds_802_11_radio_control cmd;
|
||||
int ret = -EINVAL;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.action = cpu_to_le16(CMD_ACT_SET);
|
||||
|
||||
switch (priv->preamble) {
|
||||
case CMD_TYPE_SHORT_PREAMBLE:
|
||||
cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE);
|
||||
/* Only v8 and below support setting the preamble */
|
||||
if (priv->fwrelease < 0x09000000) {
|
||||
switch (preamble) {
|
||||
case RADIO_PREAMBLE_SHORT:
|
||||
if (!(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
|
||||
goto out;
|
||||
/* Fall through */
|
||||
case RADIO_PREAMBLE_AUTO:
|
||||
case RADIO_PREAMBLE_LONG:
|
||||
cmd.control = cpu_to_le16(preamble);
|
||||
break;
|
||||
|
||||
case CMD_TYPE_LONG_PREAMBLE:
|
||||
cmd.control = cpu_to_le16(SET_LONG_PREAMBLE);
|
||||
break;
|
||||
|
||||
case CMD_TYPE_AUTO_PREAMBLE:
|
||||
default:
|
||||
cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE);
|
||||
break;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->radioon)
|
||||
cmd.control |= cpu_to_le16(TURN_ON_RF);
|
||||
else
|
||||
cmd.control &= cpu_to_le16(~TURN_ON_RF);
|
||||
if (radio_on)
|
||||
cmd.control |= cpu_to_le16(0x1);
|
||||
else {
|
||||
cmd.control &= cpu_to_le16(~0x1);
|
||||
priv->txpower_cur = 0;
|
||||
}
|
||||
|
||||
lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon,
|
||||
priv->preamble);
|
||||
lbs_deb_cmd("RADIO_CONTROL: radio %s, preamble %d\n",
|
||||
radio_on ? "ON" : "OFF", preamble);
|
||||
|
||||
priv->radio_on = radio_on;
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
|
||||
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
@ -1393,14 +1419,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
|
||||
ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf);
|
||||
break;
|
||||
|
||||
case CMD_802_11_DEAUTHENTICATE:
|
||||
ret = lbs_cmd_80211_deauthenticate(priv, cmdptr);
|
||||
break;
|
||||
|
||||
case CMD_802_11_AD_HOC_START:
|
||||
ret = lbs_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
|
||||
break;
|
||||
|
||||
case CMD_802_11_RESET:
|
||||
ret = lbs_cmd_802_11_reset(cmdptr, cmd_action);
|
||||
break;
|
||||
@ -1420,28 +1438,15 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
|
||||
ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
|
||||
break;
|
||||
|
||||
case CMD_802_11_RF_TX_POWER:
|
||||
ret = lbs_cmd_802_11_rf_tx_power(cmdptr,
|
||||
cmd_action, pdata_buf);
|
||||
break;
|
||||
|
||||
case CMD_802_11_MONITOR_MODE:
|
||||
ret = lbs_cmd_802_11_monitor_mode(cmdptr,
|
||||
cmd_action, pdata_buf);
|
||||
break;
|
||||
|
||||
case CMD_802_11_AD_HOC_JOIN:
|
||||
ret = lbs_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf);
|
||||
break;
|
||||
|
||||
case CMD_802_11_RSSI:
|
||||
ret = lbs_cmd_802_11_rssi(priv, cmdptr);
|
||||
break;
|
||||
|
||||
case CMD_802_11_AD_HOC_STOP:
|
||||
ret = lbs_cmd_80211_ad_hoc_stop(cmdptr);
|
||||
break;
|
||||
|
||||
case CMD_802_11_SET_AFC:
|
||||
case CMD_802_11_GET_AFC:
|
||||
|
||||
|
@ -61,4 +61,10 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
|
||||
int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct assoc_request *assoc);
|
||||
|
||||
int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
|
||||
s16 *maxlevel);
|
||||
int lbs_set_tx_power(struct lbs_private *priv, s16 dbm);
|
||||
|
||||
int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
|
||||
|
||||
#endif /* _LBS_CMD_H */
|
||||
|
@ -188,21 +188,6 @@ static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp)
|
||||
{
|
||||
struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
priv->txpowerlevel = le16_to_cpu(rtp->currentlevel);
|
||||
|
||||
lbs_deb_cmd("TX power currently %d\n", priv->txpowerlevel);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lbs_ret_802_11_rssi(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp)
|
||||
{
|
||||
@ -273,24 +258,10 @@ static inline int handle_cmd_response(struct lbs_private *priv,
|
||||
ret = lbs_ret_80211_associate(priv, resp);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11_DISASSOCIATE):
|
||||
case CMD_RET(CMD_802_11_DEAUTHENTICATE):
|
||||
ret = lbs_ret_80211_disassociate(priv);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11_AD_HOC_START):
|
||||
case CMD_RET(CMD_802_11_AD_HOC_JOIN):
|
||||
ret = lbs_ret_80211_ad_hoc_start(priv, resp);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11_SNMP_MIB):
|
||||
ret = lbs_ret_802_11_snmp_mib(priv, resp);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11_RF_TX_POWER):
|
||||
ret = lbs_ret_802_11_rf_tx_power(priv, resp);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11_SET_AFC):
|
||||
case CMD_RET(CMD_802_11_GET_AFC):
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
@ -309,10 +280,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
|
||||
ret = lbs_ret_802_11_rssi(priv, resp);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11_AD_HOC_STOP):
|
||||
ret = lbs_ret_80211_ad_hoc_stop(priv);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11D_DOMAIN_INFO):
|
||||
ret = lbs_ret_802_11d_domain_info(resp);
|
||||
break;
|
||||
|
@ -34,7 +34,6 @@ int lbs_process_event(struct lbs_private *priv, u32 event);
|
||||
void lbs_queue_event(struct lbs_private *priv, u32 event);
|
||||
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
|
||||
|
||||
int lbs_set_radio_control(struct lbs_private *priv);
|
||||
u32 lbs_fw_index_to_data_rate(u8 index);
|
||||
u8 lbs_data_rate_to_fw_index(u32 rate);
|
||||
|
||||
|
@ -253,7 +253,9 @@ struct lbs_private {
|
||||
u32 connect_status;
|
||||
u32 mesh_connect_status;
|
||||
u16 regioncode;
|
||||
u16 txpowerlevel;
|
||||
s16 txpower_cur;
|
||||
s16 txpower_min;
|
||||
s16 txpower_max;
|
||||
|
||||
/** POWER MANAGEMENT AND PnP SUPPORT */
|
||||
u8 surpriseremoved;
|
||||
@ -291,8 +293,7 @@ struct lbs_private {
|
||||
u16 nextSNRNF;
|
||||
u16 numSNRNF;
|
||||
|
||||
u8 radioon;
|
||||
u32 preamble;
|
||||
u8 radio_on;
|
||||
|
||||
/** data rate stuff */
|
||||
u8 cur_rate;
|
||||
|
@ -61,7 +61,6 @@
|
||||
#define CMD_RF_REG_MAP 0x0023
|
||||
#define CMD_802_11_DEAUTHENTICATE 0x0024
|
||||
#define CMD_802_11_REASSOCIATE 0x0025
|
||||
#define CMD_802_11_DISASSOCIATE 0x0026
|
||||
#define CMD_MAC_CONTROL 0x0028
|
||||
#define CMD_802_11_AD_HOC_START 0x002b
|
||||
#define CMD_802_11_AD_HOC_JOIN 0x002c
|
||||
@ -153,11 +152,6 @@
|
||||
#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100
|
||||
#define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400
|
||||
|
||||
/* Define action or option for CMD_802_11_RADIO_CONTROL */
|
||||
#define CMD_TYPE_AUTO_PREAMBLE 0x0001
|
||||
#define CMD_TYPE_SHORT_PREAMBLE 0x0002
|
||||
#define CMD_TYPE_LONG_PREAMBLE 0x0003
|
||||
|
||||
/* Event flags for CMD_802_11_SUBSCRIBE_EVENT */
|
||||
#define CMD_SUBSCRIBE_RSSI_LOW 0x0001
|
||||
#define CMD_SUBSCRIBE_SNR_LOW 0x0002
|
||||
@ -166,28 +160,14 @@
|
||||
#define CMD_SUBSCRIBE_RSSI_HIGH 0x0010
|
||||
#define CMD_SUBSCRIBE_SNR_HIGH 0x0020
|
||||
|
||||
#define TURN_ON_RF 0x01
|
||||
#define RADIO_ON 0x01
|
||||
#define RADIO_OFF 0x00
|
||||
|
||||
#define SET_AUTO_PREAMBLE 0x05
|
||||
#define SET_SHORT_PREAMBLE 0x03
|
||||
#define SET_LONG_PREAMBLE 0x01
|
||||
#define RADIO_PREAMBLE_LONG 0x00
|
||||
#define RADIO_PREAMBLE_SHORT 0x02
|
||||
#define RADIO_PREAMBLE_AUTO 0x04
|
||||
|
||||
/* Define action or option for CMD_802_11_RF_CHANNEL */
|
||||
#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00
|
||||
#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01
|
||||
|
||||
/* Define action or option for CMD_802_11_RF_TX_POWER */
|
||||
#define CMD_ACT_TX_POWER_OPT_GET 0x0000
|
||||
#define CMD_ACT_TX_POWER_OPT_SET_HIGH 0x8007
|
||||
#define CMD_ACT_TX_POWER_OPT_SET_MID 0x8004
|
||||
#define CMD_ACT_TX_POWER_OPT_SET_LOW 0x8000
|
||||
|
||||
#define CMD_ACT_TX_POWER_INDEX_HIGH 0x0007
|
||||
#define CMD_ACT_TX_POWER_INDEX_MID 0x0004
|
||||
#define CMD_ACT_TX_POWER_INDEX_LOW 0x0000
|
||||
|
||||
/* Define action or option for CMD_802_11_DATA_RATE */
|
||||
#define CMD_ACT_SET_TX_AUTO 0x0000
|
||||
#define CMD_ACT_SET_TX_FIX_RATE 0x0001
|
||||
|
@ -232,7 +232,9 @@ struct cmd_ds_802_11_authenticate {
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_deauthenticate {
|
||||
u8 macaddr[6];
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 macaddr[ETH_ALEN];
|
||||
__le16 reasoncode;
|
||||
};
|
||||
|
||||
@ -251,20 +253,10 @@ struct cmd_ds_802_11_associate {
|
||||
#endif
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_disassociate {
|
||||
u8 destmacaddr[6];
|
||||
__le16 reasoncode;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_associate_rsp {
|
||||
struct ieeetypes_assocrsp assocRsp;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_result {
|
||||
u8 pad[3];
|
||||
u8 bssid[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_set_wep {
|
||||
struct cmd_header hdr;
|
||||
|
||||
@ -435,8 +427,12 @@ struct cmd_ds_802_11_mac_address {
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_rf_tx_power {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 currentlevel;
|
||||
__le16 curlevel;
|
||||
s8 maxlevel;
|
||||
s8 minlevel;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_rf_antenna {
|
||||
@ -507,10 +503,12 @@ struct cmd_ds_802_11_rate_adapt_rateset {
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_start {
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 ssid[IW_ESSID_MAX_SIZE];
|
||||
u8 bsstype;
|
||||
__le16 beaconperiod;
|
||||
u8 dtimperiod;
|
||||
u8 dtimperiod; /* Reserved on v9 and later */
|
||||
union IEEEtypes_ssparamset ssparamset;
|
||||
union ieeetypes_phyparamset phyparamset;
|
||||
__le16 probedelay;
|
||||
@ -519,9 +517,16 @@ struct cmd_ds_802_11_ad_hoc_start {
|
||||
u8 tlv_memory_size_pad[100];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_result {
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 pad[3];
|
||||
u8 bssid[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct adhoc_bssdesc {
|
||||
u8 bssid[6];
|
||||
u8 ssid[32];
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 ssid[IW_ESSID_MAX_SIZE];
|
||||
u8 type;
|
||||
__le16 beaconperiod;
|
||||
u8 dtimperiod;
|
||||
@ -539,10 +544,15 @@ struct adhoc_bssdesc {
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_join {
|
||||
struct adhoc_bssdesc bss;
|
||||
__le16 failtimeout;
|
||||
__le16 probedelay;
|
||||
struct cmd_header hdr;
|
||||
|
||||
struct adhoc_bssdesc bss;
|
||||
__le16 failtimeout; /* Reserved on v9 and later */
|
||||
__le16 probedelay; /* Reserved on v9 and later */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_stop {
|
||||
struct cmd_header hdr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_enable_rsn {
|
||||
@ -693,21 +703,15 @@ struct cmd_ds_command {
|
||||
union {
|
||||
struct cmd_ds_802_11_ps_mode psmode;
|
||||
struct cmd_ds_802_11_associate associate;
|
||||
struct cmd_ds_802_11_deauthenticate deauth;
|
||||
struct cmd_ds_802_11_ad_hoc_start ads;
|
||||
struct cmd_ds_802_11_reset reset;
|
||||
struct cmd_ds_802_11_ad_hoc_result result;
|
||||
struct cmd_ds_802_11_authenticate auth;
|
||||
struct cmd_ds_802_11_get_stat gstat;
|
||||
struct cmd_ds_802_3_get_stat gstat_8023;
|
||||
struct cmd_ds_802_11_snmp_mib smib;
|
||||
struct cmd_ds_802_11_rf_tx_power txp;
|
||||
struct cmd_ds_802_11_rf_antenna rant;
|
||||
struct cmd_ds_802_11_monitor_mode monitor;
|
||||
struct cmd_ds_802_11_ad_hoc_join adj;
|
||||
struct cmd_ds_802_11_rssi rssi;
|
||||
struct cmd_ds_802_11_rssi_rsp rssirsp;
|
||||
struct cmd_ds_802_11_disassociate dassociate;
|
||||
struct cmd_ds_mac_reg_access macreg;
|
||||
struct cmd_ds_bbp_reg_access bbpreg;
|
||||
struct cmd_ds_rf_reg_access rfreg;
|
||||
|
@ -291,9 +291,11 @@ static ssize_t lbs_rtap_set(struct device *dev,
|
||||
if (priv->infra_open || priv->mesh_open)
|
||||
return -EBUSY;
|
||||
if (priv->mode == IW_MODE_INFRA)
|
||||
lbs_send_deauthentication(priv);
|
||||
lbs_cmd_80211_deauthenticate(priv,
|
||||
priv->curbssparams.bssid,
|
||||
WLAN_REASON_DEAUTH_LEAVING);
|
||||
else if (priv->mode == IW_MODE_ADHOC)
|
||||
lbs_stop_adhoc_network(priv);
|
||||
lbs_adhoc_stop(priv);
|
||||
lbs_add_rtap(priv);
|
||||
}
|
||||
priv->monitormode = monitor_mode;
|
||||
@ -956,17 +958,24 @@ EXPORT_SYMBOL_GPL(lbs_resume);
|
||||
static int lbs_setup_firmware(struct lbs_private *priv)
|
||||
{
|
||||
int ret = -1;
|
||||
s16 curlevel = 0, minlevel = 0, maxlevel = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_FW);
|
||||
|
||||
/*
|
||||
* Read MAC address from HW
|
||||
*/
|
||||
/* Read MAC address from firmware */
|
||||
memset(priv->current_addr, 0xff, ETH_ALEN);
|
||||
ret = lbs_update_hw_spec(priv);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
/* Read power levels if available */
|
||||
ret = lbs_get_tx_power(priv, &curlevel, &minlevel, &maxlevel);
|
||||
if (ret == 0) {
|
||||
priv->txpower_cur = curlevel;
|
||||
priv->txpower_min = minlevel;
|
||||
priv->txpower_max = maxlevel;
|
||||
}
|
||||
|
||||
lbs_set_mac_control(priv);
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
|
||||
@ -1042,7 +1051,7 @@ static int lbs_init_adapter(struct lbs_private *priv)
|
||||
priv->mode = IW_MODE_INFRA;
|
||||
priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
|
||||
priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
|
||||
priv->radioon = RADIO_ON;
|
||||
priv->radio_on = 1;
|
||||
priv->enablehwauto = 1;
|
||||
priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
|
||||
priv->psmode = LBS802_11POWERMODECAM;
|
||||
|
@ -944,6 +944,11 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
|
||||
|
||||
lbs_deb_enter(LBS_DEB_WEXT);
|
||||
|
||||
if (!priv->radio_on) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!netif_running(dev)) {
|
||||
ret = -ENETDOWN;
|
||||
goto out;
|
||||
|
@ -120,34 +120,6 @@ static struct chan_freq_power *find_cfp_by_band_and_freq(
|
||||
return cfp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set Radio On/OFF
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @option Radio Option
|
||||
* @return 0 --success, otherwise fail
|
||||
*/
|
||||
static int lbs_radio_ioctl(struct lbs_private *priv, u8 option)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_WEXT);
|
||||
|
||||
if (priv->radioon != option) {
|
||||
lbs_deb_wext("switching radio %s\n", option ? "on" : "off");
|
||||
priv->radioon = option;
|
||||
|
||||
ret = lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_RADIO_CONTROL,
|
||||
CMD_ACT_SET,
|
||||
CMD_OPTION_WAITFORRSP, 0, NULL);
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy active data rates based on adapter mode and status
|
||||
*
|
||||
@ -420,28 +392,30 @@ static int lbs_get_txpow(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *vwrq, char *extra)
|
||||
{
|
||||
int ret = 0;
|
||||
struct lbs_private *priv = dev->priv;
|
||||
s16 curlevel = 0;
|
||||
int ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_WEXT);
|
||||
|
||||
ret = lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_RF_TX_POWER,
|
||||
CMD_ACT_TX_POWER_OPT_GET,
|
||||
CMD_OPTION_WAITFORRSP, 0, NULL);
|
||||
if (!priv->radio_on) {
|
||||
lbs_deb_wext("tx power off\n");
|
||||
vwrq->value = 0;
|
||||
vwrq->disabled = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = lbs_get_tx_power(priv, &curlevel, NULL, NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
lbs_deb_wext("tx power level %d dbm\n", priv->txpowerlevel);
|
||||
vwrq->value = priv->txpowerlevel;
|
||||
lbs_deb_wext("tx power level %d dbm\n", curlevel);
|
||||
priv->txpower_cur = curlevel;
|
||||
|
||||
vwrq->value = curlevel;
|
||||
vwrq->fixed = 1;
|
||||
if (priv->radioon) {
|
||||
vwrq->disabled = 0;
|
||||
vwrq->flags = IW_TXPOW_DBM;
|
||||
} else {
|
||||
vwrq->disabled = 1;
|
||||
}
|
||||
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
|
||||
@ -693,22 +667,12 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
|
||||
|
||||
range->sensitivity = 0;
|
||||
|
||||
/*
|
||||
* Setup the supported power level ranges
|
||||
*/
|
||||
/* Setup the supported power level ranges */
|
||||
memset(range->txpower, 0, sizeof(range->txpower));
|
||||
range->txpower[0] = 5;
|
||||
range->txpower[1] = 7;
|
||||
range->txpower[2] = 9;
|
||||
range->txpower[3] = 11;
|
||||
range->txpower[4] = 13;
|
||||
range->txpower[5] = 15;
|
||||
range->txpower[6] = 17;
|
||||
range->txpower[7] = 19;
|
||||
|
||||
range->num_txpower = 8;
|
||||
range->txpower_capa = IW_TXPOW_DBM;
|
||||
range->txpower_capa |= IW_TXPOW_RANGE;
|
||||
range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE;
|
||||
range->txpower[0] = priv->txpower_min;
|
||||
range->txpower[1] = priv->txpower_max;
|
||||
range->num_txpower = 2;
|
||||
|
||||
range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
|
||||
IW_EVENT_CAPA_MASK(SIOCGIWAP) |
|
||||
@ -998,9 +962,11 @@ static int lbs_mesh_set_freq(struct net_device *dev,
|
||||
if (fwrq->m != priv->curbssparams.channel) {
|
||||
lbs_deb_wext("mesh channel change forces eth disconnect\n");
|
||||
if (priv->mode == IW_MODE_INFRA)
|
||||
lbs_send_deauthentication(priv);
|
||||
lbs_cmd_80211_deauthenticate(priv,
|
||||
priv->curbssparams.bssid,
|
||||
WLAN_REASON_DEAUTH_LEAVING);
|
||||
else if (priv->mode == IW_MODE_ADHOC)
|
||||
lbs_stop_adhoc_network(priv);
|
||||
lbs_adhoc_stop(priv);
|
||||
}
|
||||
lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m);
|
||||
lbs_update_channel(priv);
|
||||
@ -1844,39 +1810,50 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
|
||||
{
|
||||
int ret = 0;
|
||||
struct lbs_private *priv = dev->priv;
|
||||
|
||||
u16 dbm;
|
||||
s16 dbm = (s16) vwrq->value;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_WEXT);
|
||||
|
||||
if (vwrq->disabled) {
|
||||
lbs_radio_ioctl(priv, RADIO_OFF);
|
||||
return 0;
|
||||
lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv->preamble = CMD_TYPE_AUTO_PREAMBLE;
|
||||
|
||||
lbs_radio_ioctl(priv, RADIO_ON);
|
||||
|
||||
if (vwrq->fixed == 0) {
|
||||
/* Auto power control */
|
||||
dbm = priv->txpower_max;
|
||||
} else {
|
||||
/* Userspace check in iwrange if it should use dBm or mW,
|
||||
* therefore this should never happen... Jean II */
|
||||
if ((vwrq->flags & IW_TXPOW_TYPE) == IW_TXPOW_MWATT) {
|
||||
return -EOPNOTSUPP;
|
||||
} else
|
||||
dbm = (u16) vwrq->value;
|
||||
if ((vwrq->flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* auto tx power control */
|
||||
/* Validate requested power level against firmware allowed levels */
|
||||
if (priv->txpower_min && (dbm < priv->txpower_min)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (vwrq->fixed == 0)
|
||||
dbm = 0xffff;
|
||||
if (priv->txpower_max && (dbm > priv->txpower_max)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
lbs_deb_wext("txpower set %d dbm\n", dbm);
|
||||
/* If the radio was off, turn it on */
|
||||
if (!priv->radio_on) {
|
||||
ret = lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 1);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_RF_TX_POWER,
|
||||
CMD_ACT_TX_POWER_OPT_SET_LOW,
|
||||
CMD_OPTION_WAITFORRSP, 0, (void *)&dbm);
|
||||
lbs_deb_wext("txpower set %d dBm\n", dbm);
|
||||
|
||||
ret = lbs_set_tx_power(priv, dbm);
|
||||
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
@ -1928,6 +1905,11 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
|
||||
|
||||
lbs_deb_enter(LBS_DEB_WEXT);
|
||||
|
||||
if (!priv->radio_on) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check the size of the string */
|
||||
if (in_ssid_len > IW_ESSID_MAX_SIZE) {
|
||||
ret = -E2BIG;
|
||||
@ -2005,6 +1987,11 @@ static int lbs_mesh_set_essid(struct net_device *dev,
|
||||
|
||||
lbs_deb_enter(LBS_DEB_WEXT);
|
||||
|
||||
if (!priv->radio_on) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check the size of the string */
|
||||
if (dwrq->length > IW_ESSID_MAX_SIZE) {
|
||||
ret = -E2BIG;
|
||||
@ -2046,6 +2033,9 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
|
||||
|
||||
lbs_deb_enter(LBS_DEB_WEXT);
|
||||
|
||||
if (!priv->radio_on)
|
||||
return -EINVAL;
|
||||
|
||||
if (awrq->sa_family != ARPHRD_ETHER)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -477,9 +477,9 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_rx_status stats;
|
||||
struct rxpd *prxpd;
|
||||
bool is_qos, is_4addr, is_amsdu, need_padding;
|
||||
int need_padding;
|
||||
unsigned int flags;
|
||||
u16 fc, fc_le;
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
prxpd = (struct rxpd *) skb->data;
|
||||
|
||||
@ -497,19 +497,15 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
|
||||
stats.rate_idx = prxpd->rx_rate;
|
||||
skb_pull(skb, sizeof(struct rxpd));
|
||||
|
||||
fc_le = *((__le16 *) skb->data);
|
||||
fc = le16_to_cpu(fc_le);
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
flags = le32_to_cpu(*(__le32 *)(skb->data + 4));
|
||||
|
||||
is_qos = ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
|
||||
(fc & IEEE80211_STYPE_QOS_DATA);
|
||||
is_4addr = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
|
||||
(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
|
||||
is_amsdu = ((fc & 0x8C) == 0x88) &&
|
||||
(*(skb->data + ieee80211_hdrlen(fc_le) - QOS_CONTROL_LEN)
|
||||
& IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
|
||||
need_padding = ieee80211_is_data_qos(hdr->frame_control);
|
||||
need_padding ^= ieee80211_has_a4(hdr->frame_control);
|
||||
need_padding ^= ieee80211_is_data_qos(hdr->frame_control) &&
|
||||
(*ieee80211_get_qos_ctl(hdr) &
|
||||
IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
|
||||
|
||||
need_padding = is_qos ^ is_4addr ^ is_amsdu;
|
||||
if (need_padding) {
|
||||
memmove(skb->data + 2, skb->data, skb->len);
|
||||
skb_reserve(skb, 2);
|
||||
|
@ -446,7 +446,8 @@ static int __init init_mac80211_hwsim(void)
|
||||
SET_IEEE80211_PERM_ADDR(hw, addr);
|
||||
|
||||
hw->channel_change_time = 1;
|
||||
hw->queues = 1;
|
||||
hw->queues = 4;
|
||||
hw->ampdu_queues = 1;
|
||||
|
||||
memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels));
|
||||
memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates));
|
||||
@ -454,6 +455,19 @@ static int __init init_mac80211_hwsim(void)
|
||||
data->band.n_channels = ARRAY_SIZE(hwsim_channels);
|
||||
data->band.bitrates = data->rates;
|
||||
data->band.n_bitrates = ARRAY_SIZE(hwsim_rates);
|
||||
data->band.ht_info.ht_supported = 1;
|
||||
data->band.ht_info.cap = IEEE80211_HT_CAP_SUP_WIDTH |
|
||||
IEEE80211_HT_CAP_GRN_FLD |
|
||||
IEEE80211_HT_CAP_SGI_40 |
|
||||
IEEE80211_HT_CAP_DSSSCCK40;
|
||||
data->band.ht_info.ampdu_factor = 0x3;
|
||||
data->band.ht_info.ampdu_density = 0x6;
|
||||
memset(data->band.ht_info.supp_mcs_set, 0,
|
||||
sizeof(data->band.ht_info.supp_mcs_set));
|
||||
data->band.ht_info.supp_mcs_set[0] = 0xff;
|
||||
data->band.ht_info.supp_mcs_set[1] = 0xff;
|
||||
data->band.ht_info.supp_mcs_set[12] =
|
||||
IEEE80211_HT_CAP_MCS_TX_DEFINED;
|
||||
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band;
|
||||
|
||||
err = ieee80211_register_hw(hw);
|
||||
|
@ -66,7 +66,7 @@ struct p54_common {
|
||||
unsigned int tx_hdr_len;
|
||||
void *cached_vdcf;
|
||||
unsigned int fw_var;
|
||||
struct ieee80211_tx_queue_stats tx_stats[4];
|
||||
struct ieee80211_tx_queue_stats tx_stats[8];
|
||||
};
|
||||
|
||||
int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
|
||||
|
@ -146,23 +146,23 @@ void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
|
||||
|
||||
if (priv->fw_var >= 0x300) {
|
||||
/* Firmware supports QoS, use it! */
|
||||
priv->tx_stats[0].limit = 3;
|
||||
priv->tx_stats[1].limit = 4;
|
||||
priv->tx_stats[2].limit = 3;
|
||||
priv->tx_stats[3].limit = 1;
|
||||
priv->tx_stats[4].limit = 3;
|
||||
priv->tx_stats[5].limit = 4;
|
||||
priv->tx_stats[6].limit = 3;
|
||||
priv->tx_stats[7].limit = 1;
|
||||
dev->queues = 4;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(p54_parse_firmware);
|
||||
|
||||
static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev,
|
||||
static int p54_convert_rev0(struct ieee80211_hw *dev,
|
||||
struct pda_pa_curve_data *curve_data)
|
||||
{
|
||||
struct p54_common *priv = dev->priv;
|
||||
struct pda_pa_curve_data_sample_rev1 *rev1;
|
||||
struct pda_pa_curve_data_sample_rev0 *rev0;
|
||||
struct p54_pa_curve_data_sample *dst;
|
||||
struct pda_pa_curve_data_sample_rev0 *src;
|
||||
size_t cd_len = sizeof(*curve_data) +
|
||||
(curve_data->points_per_channel*sizeof(*rev1) + 2) *
|
||||
(curve_data->points_per_channel*sizeof(*dst) + 2) *
|
||||
curve_data->channels;
|
||||
unsigned int i, j;
|
||||
void *source, *target;
|
||||
@ -180,27 +180,63 @@ static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev,
|
||||
*((__le16 *)target) = *freq;
|
||||
target += sizeof(__le16);
|
||||
for (j = 0; j < curve_data->points_per_channel; j++) {
|
||||
rev1 = target;
|
||||
rev0 = source;
|
||||
dst = target;
|
||||
src = source;
|
||||
|
||||
rev1->rf_power = rev0->rf_power;
|
||||
rev1->pa_detector = rev0->pa_detector;
|
||||
rev1->data_64qam = rev0->pcv;
|
||||
dst->rf_power = src->rf_power;
|
||||
dst->pa_detector = src->pa_detector;
|
||||
dst->data_64qam = src->pcv;
|
||||
/* "invent" the points for the other modulations */
|
||||
#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y)
|
||||
rev1->data_16qam = SUB(rev0->pcv, 12);
|
||||
rev1->data_qpsk = SUB(rev1->data_16qam, 12);
|
||||
rev1->data_bpsk = SUB(rev1->data_qpsk, 12);
|
||||
rev1->data_barker= SUB(rev1->data_bpsk, 14);
|
||||
dst->data_16qam = SUB(src->pcv, 12);
|
||||
dst->data_qpsk = SUB(dst->data_16qam, 12);
|
||||
dst->data_bpsk = SUB(dst->data_qpsk, 12);
|
||||
dst->data_barker = SUB(dst->data_bpsk, 14);
|
||||
#undef SUB
|
||||
target += sizeof(*rev1);
|
||||
source += sizeof(*rev0);
|
||||
target += sizeof(*dst);
|
||||
source += sizeof(*src);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p54_convert_rev1(struct ieee80211_hw *dev,
|
||||
struct pda_pa_curve_data *curve_data)
|
||||
{
|
||||
struct p54_common *priv = dev->priv;
|
||||
struct p54_pa_curve_data_sample *dst;
|
||||
struct pda_pa_curve_data_sample_rev1 *src;
|
||||
size_t cd_len = sizeof(*curve_data) +
|
||||
(curve_data->points_per_channel*sizeof(*dst) + 2) *
|
||||
curve_data->channels;
|
||||
unsigned int i, j;
|
||||
void *source, *target;
|
||||
|
||||
priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
|
||||
if (!priv->curve_data)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
|
||||
source = curve_data->data;
|
||||
target = priv->curve_data->data;
|
||||
for (i = 0; i < curve_data->channels; i++) {
|
||||
__le16 *freq = source;
|
||||
source += sizeof(__le16);
|
||||
*((__le16 *)target) = *freq;
|
||||
target += sizeof(__le16);
|
||||
for (j = 0; j < curve_data->points_per_channel; j++) {
|
||||
memcpy(target, source, sizeof(*src));
|
||||
|
||||
target += sizeof(*dst);
|
||||
source += sizeof(*src);
|
||||
}
|
||||
source++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
|
||||
{
|
||||
struct p54_common *priv = dev->priv;
|
||||
@ -250,27 +286,32 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
|
||||
entry->data[1]*sizeof(*priv->output_limit));
|
||||
priv->output_limit_len = entry->data[1];
|
||||
break;
|
||||
case PDR_PRISM_PA_CAL_CURVE_DATA:
|
||||
if (data_len < sizeof(struct pda_pa_curve_data)) {
|
||||
case PDR_PRISM_PA_CAL_CURVE_DATA: {
|
||||
struct pda_pa_curve_data *curve_data =
|
||||
(struct pda_pa_curve_data *)entry->data;
|
||||
if (data_len < sizeof(*curve_data)) {
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (((struct pda_pa_curve_data *)entry->data)->cal_method_rev) {
|
||||
priv->curve_data = kmalloc(data_len, GFP_KERNEL);
|
||||
if (!priv->curve_data) {
|
||||
err = -ENOMEM;
|
||||
goto err;
|
||||
switch (curve_data->cal_method_rev) {
|
||||
case 0:
|
||||
err = p54_convert_rev0(dev, curve_data);
|
||||
break;
|
||||
case 1:
|
||||
err = p54_convert_rev1(dev, curve_data);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "p54: unknown curve data "
|
||||
"revision %d\n",
|
||||
curve_data->cal_method_rev);
|
||||
err = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(priv->curve_data, entry->data, data_len);
|
||||
} else {
|
||||
err = p54_convert_rev0_to_rev1(dev, (struct pda_pa_curve_data *)entry->data);
|
||||
if (err)
|
||||
goto err;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
|
||||
priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
|
||||
if (!priv->iq_autocal) {
|
||||
@ -377,7 +418,7 @@ static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->queues; i++)
|
||||
if (priv->tx_stats[i].len < priv->tx_stats[i].limit)
|
||||
if (priv->tx_stats[i + 4].len < priv->tx_stats[i + 4].limit)
|
||||
ieee80211_wake_queue(dev, i);
|
||||
}
|
||||
|
||||
@ -391,7 +432,9 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
struct memrecord *range = NULL;
|
||||
u32 freed = 0;
|
||||
u32 last_addr = priv->rx_start;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->tx_queue.lock, flags);
|
||||
while (entry != (struct sk_buff *)&priv->tx_queue) {
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
|
||||
range = (void *)info->driver_data;
|
||||
@ -412,13 +455,15 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
|
||||
last_addr = range->end_addr;
|
||||
__skb_unlink(entry, &priv->tx_queue);
|
||||
spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
|
||||
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
entry_hdr = (struct p54_control_hdr *) entry->data;
|
||||
entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
|
||||
if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
|
||||
pad = entry_data->align[0];
|
||||
|
||||
priv->tx_stats[entry_data->hw_queue - 4].len--;
|
||||
priv->tx_stats[entry_data->hw_queue].len--;
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
if (!(payload->status & 0x01))
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
@ -429,12 +474,14 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
info->status.ack_signal = le16_to_cpu(payload->ack_rssi);
|
||||
skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
|
||||
ieee80211_tx_status_irqsafe(dev, entry);
|
||||
break;
|
||||
goto out;
|
||||
} else
|
||||
last_addr = range->end_addr;
|
||||
entry = entry->next;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
|
||||
|
||||
out:
|
||||
if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
|
||||
sizeof(struct p54_control_hdr))
|
||||
p54_wake_free_queues(dev);
|
||||
@ -559,7 +606,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
u8 rate;
|
||||
u8 cts_rate = 0x20;
|
||||
|
||||
current_queue = &priv->tx_stats[skb_get_queue_mapping(skb)];
|
||||
current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4];
|
||||
if (unlikely(current_queue->len > current_queue->limit))
|
||||
return NETDEV_TX_BUSY;
|
||||
current_queue->len++;
|
||||
@ -672,12 +719,9 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
|
||||
struct p54_control_hdr *hdr;
|
||||
struct p54_tx_control_channel *chan;
|
||||
unsigned int i;
|
||||
size_t payload_len = sizeof(*chan) + sizeof(u32)*2 +
|
||||
sizeof(*chan->curve_data) *
|
||||
priv->curve_data->points_per_channel;
|
||||
void *entry;
|
||||
|
||||
hdr = kzalloc(sizeof(*hdr) + payload_len +
|
||||
hdr = kzalloc(sizeof(*hdr) + sizeof(*chan) +
|
||||
priv->tx_hdr_len, GFP_KERNEL);
|
||||
if (!hdr)
|
||||
return -ENOMEM;
|
||||
@ -689,10 +733,10 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
|
||||
hdr->magic1 = cpu_to_le16(0x8001);
|
||||
hdr->len = cpu_to_le16(sizeof(*chan));
|
||||
hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
|
||||
p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len);
|
||||
p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*chan));
|
||||
|
||||
chan->magic1 = cpu_to_le16(0x1);
|
||||
chan->magic2 = cpu_to_le16(0x0);
|
||||
chan->flags = cpu_to_le16(0x1);
|
||||
chan->dwell = cpu_to_le16(0x0);
|
||||
|
||||
for (i = 0; i < priv->iq_autocal_len; i++) {
|
||||
if (priv->iq_autocal[i].freq != freq)
|
||||
@ -710,35 +754,41 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
|
||||
continue;
|
||||
|
||||
chan->val_barker = 0x38;
|
||||
chan->val_bpsk = priv->output_limit[i].val_bpsk;
|
||||
chan->val_qpsk = priv->output_limit[i].val_qpsk;
|
||||
chan->val_16qam = priv->output_limit[i].val_16qam;
|
||||
chan->val_64qam = priv->output_limit[i].val_64qam;
|
||||
chan->val_bpsk = chan->dup_bpsk =
|
||||
priv->output_limit[i].val_bpsk;
|
||||
chan->val_qpsk = chan->dup_qpsk =
|
||||
priv->output_limit[i].val_qpsk;
|
||||
chan->val_16qam = chan->dup_16qam =
|
||||
priv->output_limit[i].val_16qam;
|
||||
chan->val_64qam = chan->dup_64qam =
|
||||
priv->output_limit[i].val_64qam;
|
||||
break;
|
||||
}
|
||||
if (i == priv->output_limit_len)
|
||||
goto err;
|
||||
|
||||
chan->pa_points_per_curve = priv->curve_data->points_per_channel;
|
||||
|
||||
entry = priv->curve_data->data;
|
||||
for (i = 0; i < priv->curve_data->channels; i++) {
|
||||
if (*((__le16 *)entry) != freq) {
|
||||
entry += sizeof(__le16);
|
||||
entry += sizeof(struct pda_pa_curve_data_sample_rev1) *
|
||||
chan->pa_points_per_curve;
|
||||
entry += sizeof(struct p54_pa_curve_data_sample) *
|
||||
priv->curve_data->points_per_channel;
|
||||
continue;
|
||||
}
|
||||
|
||||
entry += sizeof(__le16);
|
||||
chan->pa_points_per_curve =
|
||||
min(priv->curve_data->points_per_channel, (u8) 8);
|
||||
|
||||
memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) *
|
||||
chan->pa_points_per_curve);
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(hdr->data + payload_len - 4, &chan->val_bpsk, 4);
|
||||
chan->rssical_mul = cpu_to_le16(130);
|
||||
chan->rssical_add = cpu_to_le16(0xfe70); /* -400 */
|
||||
|
||||
priv->tx(dev, hdr, sizeof(*hdr) + payload_len, 1);
|
||||
priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*chan), 1);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
@ -987,7 +1037,7 @@ static int p54_get_tx_stats(struct ieee80211_hw *dev,
|
||||
{
|
||||
struct p54_common *priv = dev->priv;
|
||||
|
||||
memcpy(stats, &priv->tx_stats, sizeof(stats[0]) * dev->queues);
|
||||
memcpy(stats, &priv->tx_stats[4], sizeof(stats[0]) * dev->queues);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1025,7 +1075,11 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
|
||||
dev->channel_change_time = 1000; /* TODO: find actual value */
|
||||
dev->max_signal = 127;
|
||||
|
||||
priv->tx_stats[0].limit = 5;
|
||||
priv->tx_stats[0].limit = 1;
|
||||
priv->tx_stats[1].limit = 1;
|
||||
priv->tx_stats[2].limit = 1;
|
||||
priv->tx_stats[3].limit = 1;
|
||||
priv->tx_stats[4].limit = 5;
|
||||
dev->queues = 1;
|
||||
|
||||
dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 +
|
||||
|
@ -89,6 +89,16 @@ struct pda_pa_curve_data_sample_rev1 {
|
||||
u8 data_qpsk;
|
||||
u8 data_16qam;
|
||||
u8 data_64qam;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct p54_pa_curve_data_sample {
|
||||
u8 rf_power;
|
||||
u8 pa_detector;
|
||||
u8 data_barker;
|
||||
u8 data_bpsk;
|
||||
u8 data_qpsk;
|
||||
u8 data_16qam;
|
||||
u8 data_64qam;
|
||||
u8 padding;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
@ -212,8 +222,8 @@ struct p54_tx_control_filter {
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct p54_tx_control_channel {
|
||||
__le16 magic1;
|
||||
__le16 magic2;
|
||||
__le16 flags;
|
||||
__le16 dwell;
|
||||
u8 padding1[20];
|
||||
struct pda_iq_autocal_entry iq_autocal;
|
||||
u8 pa_points_per_curve;
|
||||
@ -222,8 +232,13 @@ struct p54_tx_control_channel {
|
||||
u8 val_qpsk;
|
||||
u8 val_16qam;
|
||||
u8 val_64qam;
|
||||
struct pda_pa_curve_data_sample_rev1 curve_data[0];
|
||||
/* additional padding/data after curve_data */
|
||||
struct pda_pa_curve_data_sample_rev1 curve_data[8];
|
||||
u8 dup_bpsk;
|
||||
u8 dup_qpsk;
|
||||
u8 dup_16qam;
|
||||
u8 dup_64qam;
|
||||
__le16 rssical_mul;
|
||||
__le16 rssical_add;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct p54_tx_control_led {
|
||||
|
@ -3,6 +3,7 @@
|
||||
* Linux device driver for PCI based Prism54
|
||||
*
|
||||
* Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
|
||||
* Copyright (c) 2008, Christian Lamparter <chunkeey@web.de>
|
||||
*
|
||||
* Based on the islsm (softmac prism54) driver, which is:
|
||||
* Copyright 2004-2006 Jean-Baptiste Note <jean-baptiste.note@m4x.org>, et al.
|
||||
@ -237,20 +238,22 @@ static int p54p_read_eeprom(struct ieee80211_hw *dev)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void p54p_refill_rx_ring(struct ieee80211_hw *dev)
|
||||
static void p54p_refill_rx_ring(struct ieee80211_hw *dev,
|
||||
int ring_index, struct p54p_desc *ring, u32 ring_limit,
|
||||
struct sk_buff **rx_buf)
|
||||
{
|
||||
struct p54p_priv *priv = dev->priv;
|
||||
struct p54p_ring_control *ring_control = priv->ring_control;
|
||||
u32 limit, host_idx, idx;
|
||||
u32 limit, idx, i;
|
||||
|
||||
host_idx = le32_to_cpu(ring_control->host_idx[0]);
|
||||
limit = host_idx;
|
||||
limit -= le32_to_cpu(ring_control->device_idx[0]);
|
||||
limit = ARRAY_SIZE(ring_control->rx_data) - limit;
|
||||
idx = le32_to_cpu(ring_control->host_idx[ring_index]);
|
||||
limit = idx;
|
||||
limit -= le32_to_cpu(ring_control->device_idx[ring_index]);
|
||||
limit = ring_limit - limit;
|
||||
|
||||
idx = host_idx % ARRAY_SIZE(ring_control->rx_data);
|
||||
i = idx % ring_limit;
|
||||
while (limit-- > 1) {
|
||||
struct p54p_desc *desc = &ring_control->rx_data[idx];
|
||||
struct p54p_desc *desc = &ring[i];
|
||||
|
||||
if (!desc->host_addr) {
|
||||
struct sk_buff *skb;
|
||||
@ -267,16 +270,106 @@ static void p54p_refill_rx_ring(struct ieee80211_hw *dev)
|
||||
desc->device_addr = 0; // FIXME: necessary?
|
||||
desc->len = cpu_to_le16(MAX_RX_SIZE);
|
||||
desc->flags = 0;
|
||||
priv->rx_buf[idx] = skb;
|
||||
rx_buf[i] = skb;
|
||||
}
|
||||
|
||||
i++;
|
||||
idx++;
|
||||
host_idx++;
|
||||
idx %= ARRAY_SIZE(ring_control->rx_data);
|
||||
i %= ring_limit;
|
||||
}
|
||||
|
||||
wmb();
|
||||
ring_control->host_idx[0] = cpu_to_le32(host_idx);
|
||||
ring_control->host_idx[ring_index] = cpu_to_le32(idx);
|
||||
}
|
||||
|
||||
static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index,
|
||||
int ring_index, struct p54p_desc *ring, u32 ring_limit,
|
||||
struct sk_buff **rx_buf)
|
||||
{
|
||||
struct p54p_priv *priv = dev->priv;
|
||||
struct p54p_ring_control *ring_control = priv->ring_control;
|
||||
struct p54p_desc *desc;
|
||||
u32 idx, i;
|
||||
|
||||
i = (*index) % ring_limit;
|
||||
(*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]);
|
||||
idx %= ring_limit;
|
||||
while (i != idx) {
|
||||
u16 len;
|
||||
struct sk_buff *skb;
|
||||
desc = &ring[i];
|
||||
len = le16_to_cpu(desc->len);
|
||||
skb = rx_buf[i];
|
||||
|
||||
if (!skb)
|
||||
continue;
|
||||
|
||||
skb_put(skb, len);
|
||||
|
||||
if (p54_rx(dev, skb)) {
|
||||
pci_unmap_single(priv->pdev,
|
||||
le32_to_cpu(desc->host_addr),
|
||||
MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
|
||||
rx_buf[i] = NULL;
|
||||
desc->host_addr = 0;
|
||||
} else {
|
||||
skb_trim(skb, 0);
|
||||
desc->len = cpu_to_le16(MAX_RX_SIZE);
|
||||
}
|
||||
|
||||
i++;
|
||||
i %= ring_limit;
|
||||
}
|
||||
|
||||
p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf);
|
||||
}
|
||||
|
||||
/* caller must hold priv->lock */
|
||||
static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
|
||||
int ring_index, struct p54p_desc *ring, u32 ring_limit,
|
||||
void **tx_buf)
|
||||
{
|
||||
struct p54p_priv *priv = dev->priv;
|
||||
struct p54p_ring_control *ring_control = priv->ring_control;
|
||||
struct p54p_desc *desc;
|
||||
u32 idx, i;
|
||||
|
||||
i = (*index) % ring_limit;
|
||||
(*index) = idx = le32_to_cpu(ring_control->device_idx[1]);
|
||||
idx %= ring_limit;
|
||||
|
||||
while (i != idx) {
|
||||
desc = &ring[i];
|
||||
kfree(tx_buf[i]);
|
||||
tx_buf[i] = NULL;
|
||||
|
||||
pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
|
||||
le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
|
||||
|
||||
desc->host_addr = 0;
|
||||
desc->device_addr = 0;
|
||||
desc->len = 0;
|
||||
desc->flags = 0;
|
||||
|
||||
i++;
|
||||
i %= ring_limit;
|
||||
}
|
||||
}
|
||||
|
||||
static void p54p_rx_tasklet(unsigned long dev_id)
|
||||
{
|
||||
struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id;
|
||||
struct p54p_priv *priv = dev->priv;
|
||||
struct p54p_ring_control *ring_control = priv->ring_control;
|
||||
|
||||
p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt,
|
||||
ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt);
|
||||
|
||||
p54p_check_rx_ring(dev, &priv->rx_idx_data, 0, ring_control->rx_data,
|
||||
ARRAY_SIZE(ring_control->rx_data), priv->rx_buf_data);
|
||||
|
||||
wmb();
|
||||
P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
|
||||
}
|
||||
|
||||
static irqreturn_t p54p_interrupt(int irq, void *dev_id)
|
||||
@ -298,65 +391,18 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id)
|
||||
reg &= P54P_READ(int_enable);
|
||||
|
||||
if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) {
|
||||
struct p54p_desc *desc;
|
||||
u32 idx, i;
|
||||
i = priv->tx_idx;
|
||||
i %= ARRAY_SIZE(ring_control->tx_data);
|
||||
priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]);
|
||||
idx %= ARRAY_SIZE(ring_control->tx_data);
|
||||
p54p_check_tx_ring(dev, &priv->tx_idx_mgmt,
|
||||
3, ring_control->tx_mgmt,
|
||||
ARRAY_SIZE(ring_control->tx_mgmt),
|
||||
priv->tx_buf_mgmt);
|
||||
|
||||
while (i != idx) {
|
||||
desc = &ring_control->tx_data[i];
|
||||
if (priv->tx_buf[i]) {
|
||||
kfree(priv->tx_buf[i]);
|
||||
priv->tx_buf[i] = NULL;
|
||||
}
|
||||
p54p_check_tx_ring(dev, &priv->tx_idx_data,
|
||||
1, ring_control->tx_data,
|
||||
ARRAY_SIZE(ring_control->tx_data),
|
||||
priv->tx_buf_data);
|
||||
|
||||
pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
|
||||
le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
|
||||
tasklet_schedule(&priv->rx_tasklet);
|
||||
|
||||
desc->host_addr = 0;
|
||||
desc->device_addr = 0;
|
||||
desc->len = 0;
|
||||
desc->flags = 0;
|
||||
|
||||
i++;
|
||||
i %= ARRAY_SIZE(ring_control->tx_data);
|
||||
}
|
||||
|
||||
i = priv->rx_idx;
|
||||
i %= ARRAY_SIZE(ring_control->rx_data);
|
||||
priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]);
|
||||
idx %= ARRAY_SIZE(ring_control->rx_data);
|
||||
while (i != idx) {
|
||||
u16 len;
|
||||
struct sk_buff *skb;
|
||||
desc = &ring_control->rx_data[i];
|
||||
len = le16_to_cpu(desc->len);
|
||||
skb = priv->rx_buf[i];
|
||||
|
||||
skb_put(skb, len);
|
||||
|
||||
if (p54_rx(dev, skb)) {
|
||||
pci_unmap_single(priv->pdev,
|
||||
le32_to_cpu(desc->host_addr),
|
||||
MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
|
||||
|
||||
priv->rx_buf[i] = NULL;
|
||||
desc->host_addr = 0;
|
||||
} else {
|
||||
skb_trim(skb, 0);
|
||||
desc->len = cpu_to_le16(MAX_RX_SIZE);
|
||||
}
|
||||
|
||||
i++;
|
||||
i %= ARRAY_SIZE(ring_control->rx_data);
|
||||
}
|
||||
|
||||
p54p_refill_rx_ring(dev);
|
||||
|
||||
wmb();
|
||||
P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
|
||||
} else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
|
||||
complete(&priv->boot_comp);
|
||||
|
||||
@ -392,7 +438,7 @@ static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
|
||||
ring_control->host_idx[1] = cpu_to_le32(idx + 1);
|
||||
|
||||
if (free_on_tx)
|
||||
priv->tx_buf[i] = data;
|
||||
priv->tx_buf_data[i] = data;
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
@ -420,8 +466,14 @@ static int p54p_open(struct ieee80211_hw *dev)
|
||||
}
|
||||
|
||||
memset(priv->ring_control, 0, sizeof(*priv->ring_control));
|
||||
priv->rx_idx = priv->tx_idx = 0;
|
||||
p54p_refill_rx_ring(dev);
|
||||
priv->rx_idx_data = priv->tx_idx_data = 0;
|
||||
priv->rx_idx_mgmt = priv->tx_idx_mgmt = 0;
|
||||
|
||||
p54p_refill_rx_ring(dev, 0, priv->ring_control->rx_data,
|
||||
ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data);
|
||||
|
||||
p54p_refill_rx_ring(dev, 2, priv->ring_control->rx_mgmt,
|
||||
ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt);
|
||||
|
||||
p54p_upload_firmware(dev);
|
||||
|
||||
@ -465,6 +517,8 @@ static void p54p_stop(struct ieee80211_hw *dev)
|
||||
unsigned int i;
|
||||
struct p54p_desc *desc;
|
||||
|
||||
tasklet_kill(&priv->rx_tasklet);
|
||||
|
||||
P54P_WRITE(int_enable, cpu_to_le32(0));
|
||||
P54P_READ(int_enable);
|
||||
udelay(10);
|
||||
@ -473,26 +527,51 @@ static void p54p_stop(struct ieee80211_hw *dev)
|
||||
|
||||
P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(priv->rx_buf); i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) {
|
||||
desc = &ring_control->rx_data[i];
|
||||
if (desc->host_addr)
|
||||
pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
|
||||
pci_unmap_single(priv->pdev,
|
||||
le32_to_cpu(desc->host_addr),
|
||||
MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
|
||||
kfree_skb(priv->rx_buf[i]);
|
||||
priv->rx_buf[i] = NULL;
|
||||
kfree_skb(priv->rx_buf_data[i]);
|
||||
priv->rx_buf_data[i] = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(priv->tx_buf); i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(priv->rx_buf_mgmt); i++) {
|
||||
desc = &ring_control->rx_mgmt[i];
|
||||
if (desc->host_addr)
|
||||
pci_unmap_single(priv->pdev,
|
||||
le32_to_cpu(desc->host_addr),
|
||||
MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
|
||||
kfree_skb(priv->rx_buf_mgmt[i]);
|
||||
priv->rx_buf_mgmt[i] = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(priv->tx_buf_data); i++) {
|
||||
desc = &ring_control->tx_data[i];
|
||||
if (desc->host_addr)
|
||||
pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
|
||||
le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
|
||||
pci_unmap_single(priv->pdev,
|
||||
le32_to_cpu(desc->host_addr),
|
||||
le16_to_cpu(desc->len),
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
kfree(priv->tx_buf[i]);
|
||||
priv->tx_buf[i] = NULL;
|
||||
kfree(priv->tx_buf_data[i]);
|
||||
priv->tx_buf_data[i] = NULL;
|
||||
}
|
||||
|
||||
memset(ring_control, 0, sizeof(ring_control));
|
||||
for (i = 0; i < ARRAY_SIZE(priv->tx_buf_mgmt); i++) {
|
||||
desc = &ring_control->tx_mgmt[i];
|
||||
if (desc->host_addr)
|
||||
pci_unmap_single(priv->pdev,
|
||||
le32_to_cpu(desc->host_addr),
|
||||
le16_to_cpu(desc->len),
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
kfree(priv->tx_buf_mgmt[i]);
|
||||
priv->tx_buf_mgmt[i] = NULL;
|
||||
}
|
||||
|
||||
memset(ring_control, 0, sizeof(*ring_control));
|
||||
}
|
||||
|
||||
static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
@ -585,6 +664,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
|
||||
priv->common.tx = p54p_tx;
|
||||
|
||||
spin_lock_init(&priv->lock);
|
||||
tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev);
|
||||
|
||||
err = ieee80211_register_hw(dev);
|
||||
if (err) {
|
||||
|
@ -92,13 +92,17 @@ struct p54p_priv {
|
||||
struct p54_common common;
|
||||
struct pci_dev *pdev;
|
||||
struct p54p_csr __iomem *map;
|
||||
struct tasklet_struct rx_tasklet;
|
||||
|
||||
spinlock_t lock;
|
||||
struct p54p_ring_control *ring_control;
|
||||
dma_addr_t ring_control_dma;
|
||||
u32 rx_idx, tx_idx;
|
||||
struct sk_buff *rx_buf[8];
|
||||
void *tx_buf[32];
|
||||
u32 rx_idx_data, tx_idx_data;
|
||||
u32 rx_idx_mgmt, tx_idx_mgmt;
|
||||
struct sk_buff *rx_buf_data[8];
|
||||
struct sk_buff *rx_buf_mgmt[4];
|
||||
void *tx_buf_data[32];
|
||||
void *tx_buf_mgmt[4];
|
||||
struct completion boot_comp;
|
||||
};
|
||||
|
||||
|
@ -1241,7 +1241,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
|
||||
if (!reg)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/*
|
||||
|
@ -1316,6 +1316,8 @@ static void rt2500pci_fill_rxdone(struct queue_entry *entry,
|
||||
|
||||
if (rt2x00_get_field32(word0, RXD_W0_OFDM))
|
||||
rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
|
||||
else
|
||||
rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
|
||||
if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
|
||||
rxdesc->dev_flags |= RXDONE_MY_BSS;
|
||||
}
|
||||
@ -1377,7 +1379,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
|
||||
if (!reg)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/*
|
||||
|
@ -1114,8 +1114,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
|
||||
test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
|
||||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT,
|
||||
skb->len - skbdesc->desc_len);
|
||||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
|
||||
rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE);
|
||||
rt2x00_desc_write(txd, 0, word);
|
||||
}
|
||||
@ -1280,6 +1279,8 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,
|
||||
|
||||
if (rt2x00_get_field32(word0, RXD_W0_OFDM))
|
||||
rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
|
||||
else
|
||||
rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
|
||||
if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
|
||||
rxdesc->dev_flags |= RXDONE_MY_BSS;
|
||||
|
||||
@ -1297,7 +1298,7 @@ static void rt2500usb_beacondone(struct urb *urb)
|
||||
struct queue_entry *entry = (struct queue_entry *)urb->context;
|
||||
struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
|
||||
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
|
@ -44,7 +44,7 @@
|
||||
/*
|
||||
* Module information.
|
||||
*/
|
||||
#define DRV_VERSION "2.2.0"
|
||||
#define DRV_VERSION "2.2.1"
|
||||
#define DRV_PROJECT "http://rt2x00.serialmonkey.com"
|
||||
|
||||
/*
|
||||
@ -629,14 +629,13 @@ enum rt2x00_flags {
|
||||
/*
|
||||
* Device state flags
|
||||
*/
|
||||
DEVICE_PRESENT,
|
||||
DEVICE_REGISTERED_HW,
|
||||
DEVICE_INITIALIZED,
|
||||
DEVICE_STARTED,
|
||||
DEVICE_STARTED_SUSPEND,
|
||||
DEVICE_ENABLED_RADIO,
|
||||
DEVICE_DISABLED_RADIO_HW,
|
||||
DEVICE_DIRTY_CONFIG,
|
||||
DEVICE_STATE_PRESENT,
|
||||
DEVICE_STATE_REGISTERED_HW,
|
||||
DEVICE_STATE_INITIALIZED,
|
||||
DEVICE_STATE_STARTED,
|
||||
DEVICE_STATE_STARTED_SUSPEND,
|
||||
DEVICE_STATE_ENABLED_RADIO,
|
||||
DEVICE_STATE_DISABLED_RADIO_HW,
|
||||
|
||||
/*
|
||||
* Driver requirements
|
||||
|
@ -121,7 +121,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
|
||||
* Antenna setup changes require the RX to be disabled,
|
||||
* else the changes will be ignored by the device.
|
||||
*/
|
||||
if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK);
|
||||
|
||||
/*
|
||||
@ -136,7 +136,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00dev->link.ant.active.rx = libconf.ant.rx;
|
||||
rt2x00dev->link.ant.active.tx = libconf.ant.tx;
|
||||
|
||||
if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
*/
|
||||
void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -94,8 +94,8 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
* Don't enable the radio twice.
|
||||
* And check if the hardware button has been disabled.
|
||||
*/
|
||||
if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
|
||||
test_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags))
|
||||
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
|
||||
test_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@ -117,7 +117,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00leds_led_radio(rt2x00dev, true);
|
||||
rt2x00led_led_activity(rt2x00dev, true);
|
||||
|
||||
__set_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags);
|
||||
set_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Enable RX.
|
||||
@ -134,7 +134,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
|
||||
void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
if (!__test_and_clear_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
if (!test_and_clear_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -354,7 +354,7 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
|
||||
* When the radio is shutting down we should
|
||||
* immediately cease all link tuning.
|
||||
*/
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -431,7 +431,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
|
||||
* note that in the spinlock protected area above the delayed_flags
|
||||
* have been cleared correctly.
|
||||
*/
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
if (delayed_flags & DELAYED_UPDATE_BEACON)
|
||||
@ -484,7 +484,7 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
|
||||
|
||||
void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
|
||||
@ -572,7 +572,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
|
||||
|
||||
rt2x00dev->ops->lib->init_txentry(rt2x00dev, entry);
|
||||
|
||||
__clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
|
||||
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
|
||||
rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
|
||||
|
||||
/*
|
||||
@ -653,7 +653,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) &&
|
||||
(rate->plcp == rxdesc.signal)) ||
|
||||
(!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) &&
|
||||
((rxdesc.dev_flags & RXDONE_SIGNAL_BITRATE) &&
|
||||
(rate->bitrate == rxdesc.signal))) {
|
||||
idx = i;
|
||||
break;
|
||||
@ -888,7 +888,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags))
|
||||
if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags))
|
||||
ieee80211_unregister_hw(rt2x00dev->hw);
|
||||
|
||||
if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) {
|
||||
@ -906,6 +906,9 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
struct hw_mode_spec *spec = &rt2x00dev->spec;
|
||||
int status;
|
||||
|
||||
if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Initialize HW modes.
|
||||
*/
|
||||
@ -927,7 +930,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
return status;
|
||||
}
|
||||
|
||||
__set_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags);
|
||||
set_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -937,7 +940,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
*/
|
||||
static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
|
||||
if (!test_and_clear_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -960,7 +963,7 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (test_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
|
||||
if (test_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@ -979,7 +982,7 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
|
||||
return status;
|
||||
}
|
||||
|
||||
__set_bit(DEVICE_INITIALIZED, &rt2x00dev->flags);
|
||||
set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Register the extra components.
|
||||
@ -993,7 +996,7 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (test_bit(DEVICE_STARTED, &rt2x00dev->flags))
|
||||
if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@ -1011,28 +1014,18 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* Enable radio.
|
||||
*/
|
||||
retval = rt2x00lib_enable_radio(rt2x00dev);
|
||||
if (retval) {
|
||||
rt2x00lib_uninitialize(rt2x00dev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
rt2x00dev->intf_ap_count = 0;
|
||||
rt2x00dev->intf_sta_count = 0;
|
||||
rt2x00dev->intf_associated = 0;
|
||||
|
||||
__set_bit(DEVICE_STARTED, &rt2x00dev->flags);
|
||||
__set_bit(DEVICE_DIRTY_CONFIG, &rt2x00dev->flags);
|
||||
set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
|
||||
if (!test_and_clear_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -1044,8 +1037,6 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00dev->intf_ap_count = 0;
|
||||
rt2x00dev->intf_sta_count = 0;
|
||||
rt2x00dev->intf_associated = 0;
|
||||
|
||||
__clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1100,7 +1091,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00rfkill_allocate(rt2x00dev);
|
||||
rt2x00debug_register(rt2x00dev);
|
||||
|
||||
__set_bit(DEVICE_PRESENT, &rt2x00dev->flags);
|
||||
set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -1113,7 +1104,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_probe_dev);
|
||||
|
||||
void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
__clear_bit(DEVICE_PRESENT, &rt2x00dev->flags);
|
||||
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Disable radio.
|
||||
@ -1158,14 +1149,15 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
|
||||
int retval;
|
||||
|
||||
NOTICE(rt2x00dev, "Going to sleep.\n");
|
||||
__clear_bit(DEVICE_PRESENT, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Only continue if mac80211 has open interfaces.
|
||||
*/
|
||||
if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
|
||||
if (!test_and_clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
|
||||
!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
|
||||
goto exit;
|
||||
__set_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags);
|
||||
|
||||
set_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* Disable radio.
|
||||
@ -1237,7 +1229,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* Only continue if mac80211 had open interfaces.
|
||||
*/
|
||||
if (!__test_and_clear_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags))
|
||||
if (!test_and_clear_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@ -1264,7 +1256,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* We are ready again to receive requests from mac80211.
|
||||
*/
|
||||
__set_bit(DEVICE_PRESENT, &rt2x00dev->flags);
|
||||
set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* It is possible that during that mac80211 has attempted
|
||||
@ -1284,7 +1276,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
rt2x00lib_disable_radio(rt2x00dev);
|
||||
rt2x00lib_stop(rt2x00dev);
|
||||
rt2x00lib_uninitialize(rt2x00dev);
|
||||
rt2x00debug_deregister(rt2x00dev);
|
||||
|
||||
|
@ -117,7 +117,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
* Note that we can only stop the TX queues inside the TX path
|
||||
* due to possible race conditions in mac80211.
|
||||
*/
|
||||
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
|
||||
goto exit_fail;
|
||||
|
||||
/*
|
||||
@ -175,7 +175,7 @@ int rt2x00mac_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
|
||||
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
|
||||
return 0;
|
||||
|
||||
return rt2x00lib_start(rt2x00dev);
|
||||
@ -186,7 +186,7 @@ void rt2x00mac_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
|
||||
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
|
||||
return;
|
||||
|
||||
rt2x00lib_stop(rt2x00dev);
|
||||
@ -206,8 +206,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
||||
* Don't allow interfaces to be added
|
||||
* the device has disappeared.
|
||||
*/
|
||||
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
|
||||
!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
|
||||
!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
|
||||
return -ENODEV;
|
||||
|
||||
switch (conf->type) {
|
||||
@ -256,7 +256,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
||||
*/
|
||||
for (i = 0; i < queue->limit; i++) {
|
||||
entry = &queue->entries[i];
|
||||
if (!__test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags))
|
||||
if (!test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags))
|
||||
break;
|
||||
}
|
||||
|
||||
@ -310,7 +310,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
|
||||
* either the device has disappeared or when
|
||||
* no interface is present.
|
||||
*/
|
||||
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
|
||||
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
|
||||
(conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) ||
|
||||
(conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count))
|
||||
return;
|
||||
@ -324,7 +324,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
|
||||
* Release beacon entry so it is available for
|
||||
* new interfaces again.
|
||||
*/
|
||||
__clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags);
|
||||
clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags);
|
||||
|
||||
/*
|
||||
* Make sure the bssid and mac address registers
|
||||
@ -338,45 +338,45 @@ EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
|
||||
int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
int force_reconfig;
|
||||
int radio_on;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* Mac80211 might be calling this function while we are trying
|
||||
* to remove the device or perhaps suspending it.
|
||||
*/
|
||||
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check if we need to disable the radio,
|
||||
* if this is not the case, at least the RX must be disabled.
|
||||
* Only change device state when the radio is enabled. It does not
|
||||
* matter what parameters we have configured when the radio is disabled
|
||||
* because we won't be able to send or receive anyway. Also note that
|
||||
* some configuration parameters (e.g. channel and antenna values) can
|
||||
* only be set when the radio is enabled.
|
||||
*/
|
||||
if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) {
|
||||
if (!conf->radio_enabled)
|
||||
rt2x00lib_disable_radio(rt2x00dev);
|
||||
else
|
||||
radio_on = test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags);
|
||||
if (conf->radio_enabled) {
|
||||
/* For programming the values, we have to turn RX off */
|
||||
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
|
||||
}
|
||||
|
||||
/* Enable the radio */
|
||||
status = rt2x00lib_enable_radio(rt2x00dev);
|
||||
if (unlikely(status))
|
||||
return status;
|
||||
|
||||
/*
|
||||
* When the DEVICE_DIRTY_CONFIG flag is set, the device has recently
|
||||
* been started and the configuration must be forced upon the hardware.
|
||||
* Otherwise registers will not be intialized correctly and could
|
||||
* result in non-working hardware because essential registers aren't
|
||||
* initialized.
|
||||
* When we've just turned on the radio, we want to reprogram
|
||||
* everything to ensure a consistent state
|
||||
*/
|
||||
force_reconfig =
|
||||
__test_and_clear_bit(DEVICE_DIRTY_CONFIG, &rt2x00dev->flags);
|
||||
rt2x00lib_config(rt2x00dev, conf, !radio_on);
|
||||
|
||||
rt2x00lib_config(rt2x00dev, conf, force_reconfig);
|
||||
|
||||
/*
|
||||
* Reenable RX only if the radio should be on.
|
||||
*/
|
||||
if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
/* Turn RX back on */
|
||||
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
|
||||
else if (conf->radio_enabled)
|
||||
return rt2x00lib_enable_radio(rt2x00dev);
|
||||
} else {
|
||||
/* Disable the radio */
|
||||
rt2x00lib_disable_radio(rt2x00dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -395,7 +395,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
|
||||
* Mac80211 might be calling this function while we are trying
|
||||
* to remove the device or perhaps suspending it.
|
||||
*/
|
||||
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
|
||||
return 0;
|
||||
|
||||
spin_lock(&intf->lock);
|
||||
@ -666,10 +666,11 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
|
||||
queue->cw_max = 10; /* cw_min: 2^10 = 1024. */
|
||||
|
||||
queue->aifs = params->aifs;
|
||||
queue->txop = params->txop;
|
||||
|
||||
INFO(rt2x00dev,
|
||||
"Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d.\n",
|
||||
queue_idx, queue->cw_min, queue->cw_max, queue->aifs);
|
||||
"Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d, TXop: %d.\n",
|
||||
queue_idx, queue->cw_min, queue->cw_max, queue->aifs, queue->txop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -100,8 +100,21 @@ void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
|
||||
{
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
|
||||
|
||||
skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
/*
|
||||
* If device has requested headroom, we should make sure that
|
||||
* is also mapped to the DMA so it can be used for transfering
|
||||
* additional descriptor information to the hardware.
|
||||
*/
|
||||
skb_push(skb, rt2x00dev->hw->extra_tx_headroom);
|
||||
|
||||
skbdesc->skb_dma =
|
||||
dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE);
|
||||
|
||||
/*
|
||||
* Restore data pointer to original location again.
|
||||
*/
|
||||
skb_pull(skb, rt2x00dev->hw->extra_tx_headroom);
|
||||
|
||||
skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb);
|
||||
@ -117,7 +130,12 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) {
|
||||
dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len,
|
||||
/*
|
||||
* Add headroom to the skb length, it has been removed
|
||||
* by the driver, but it was actually mapped to DMA.
|
||||
*/
|
||||
dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma,
|
||||
skb->len + rt2x00dev->hw->extra_tx_headroom,
|
||||
DMA_TO_DEVICE);
|
||||
skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX;
|
||||
}
|
||||
@ -356,7 +374,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
|
||||
if (unlikely(rt2x00queue_full(queue)))
|
||||
return -EINVAL;
|
||||
|
||||
if (__test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
|
||||
if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
|
||||
ERROR(queue->rt2x00dev,
|
||||
"Arrived at non-free entry in the non-full queue %d.\n"
|
||||
"Please file bug report to %s.\n",
|
||||
@ -396,7 +414,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
|
||||
* the frame to mac80211 because the skb->cb has now been tainted.
|
||||
*/
|
||||
if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) {
|
||||
__clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
|
||||
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
|
||||
dev_kfree_skb_any(entry->skb);
|
||||
entry->skb = NULL;
|
||||
return 0;
|
||||
@ -405,7 +423,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
|
||||
if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
|
||||
rt2x00queue_map_txskb(queue->rt2x00dev, skb);
|
||||
|
||||
__set_bit(ENTRY_DATA_PENDING, &entry->flags);
|
||||
set_bit(ENTRY_DATA_PENDING, &entry->flags);
|
||||
|
||||
rt2x00queue_index_inc(queue, Q_INDEX);
|
||||
rt2x00queue_write_tx_descriptor(entry, &txdesc);
|
||||
@ -718,6 +736,7 @@ static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
queue->rt2x00dev = rt2x00dev;
|
||||
queue->qid = qid;
|
||||
queue->txop = 0;
|
||||
queue->aifs = 2;
|
||||
queue->cw_min = 5;
|
||||
queue->cw_max = 10;
|
||||
|
@ -140,13 +140,14 @@ static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb)
|
||||
/**
|
||||
* enum rxdone_entry_desc_flags: Flags for &struct rxdone_entry_desc
|
||||
*
|
||||
* @RXDONE_SIGNAL_PLCP: Does the signal field contain the plcp value,
|
||||
* or does it contain the bitrate itself.
|
||||
* @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value.
|
||||
* @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value.
|
||||
* @RXDONE_MY_BSS: Does this frame originate from device's BSS.
|
||||
*/
|
||||
enum rxdone_entry_desc_flags {
|
||||
RXDONE_SIGNAL_PLCP = 1 << 0,
|
||||
RXDONE_MY_BSS = 1 << 1,
|
||||
RXDONE_SIGNAL_BITRATE = 1 << 1,
|
||||
RXDONE_MY_BSS = 1 << 2,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -368,6 +369,7 @@ enum queue_index {
|
||||
* @length: Number of frames in queue.
|
||||
* @index: Index pointers to entry positions in the queue,
|
||||
* use &enum queue_index to get a specific index field.
|
||||
* @txop: maximum burst time.
|
||||
* @aifs: The aifs value for outgoing frames (field ignored in RX queue).
|
||||
* @cw_min: The cw min value for outgoing frames (field ignored in RX queue).
|
||||
* @cw_max: The cw max value for outgoing frames (field ignored in RX queue).
|
||||
@ -387,6 +389,7 @@ struct data_queue {
|
||||
unsigned short length;
|
||||
unsigned short index[Q_INDEX_MAX];
|
||||
|
||||
unsigned short txop;
|
||||
unsigned short aifs;
|
||||
unsigned short cw_min;
|
||||
unsigned short cw_max;
|
||||
|
@ -41,16 +41,16 @@ static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state)
|
||||
/*
|
||||
* Only continue if there are enabled interfaces.
|
||||
*/
|
||||
if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
|
||||
return 0;
|
||||
|
||||
if (state == RFKILL_STATE_UNBLOCKED) {
|
||||
INFO(rt2x00dev, "Hardware button pressed, enabling radio.\n");
|
||||
__clear_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags);
|
||||
clear_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags);
|
||||
retval = rt2x00lib_enable_radio(rt2x00dev);
|
||||
} else if (state == RFKILL_STATE_SOFT_BLOCKED) {
|
||||
INFO(rt2x00dev, "Hardware button pressed, disabling radio.\n");
|
||||
__set_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags);
|
||||
set_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags);
|
||||
rt2x00lib_disable_radio(rt2x00dev);
|
||||
} else {
|
||||
WARNING(rt2x00dev, "Received unexpected rfkill state %d.\n",
|
||||
|
@ -163,15 +163,10 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
|
||||
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
||||
struct txdone_entry_desc txdesc;
|
||||
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
|
||||
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
|
||||
!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Remove the descriptor data from the buffer.
|
||||
*/
|
||||
skb_pull(entry->skb, entry->queue->desc_size);
|
||||
|
||||
/*
|
||||
* Obtain the status about this packet.
|
||||
* Note that when the status is 0 it does not mean the
|
||||
@ -224,6 +219,12 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry)
|
||||
entry->skb->data, length,
|
||||
rt2x00usb_interrupt_txdone, entry);
|
||||
|
||||
/*
|
||||
* Make sure the skb->data pointer points to the frame, not the
|
||||
* descriptor.
|
||||
*/
|
||||
skb_pull(entry->skb, entry->queue->desc_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
|
||||
@ -232,7 +233,7 @@ static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
|
||||
{
|
||||
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
|
||||
|
||||
if (__test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
|
||||
if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
|
||||
usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
@ -283,7 +284,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
|
||||
u8 rxd[32];
|
||||
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
|
||||
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
|
||||
!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
|
||||
return;
|
||||
|
||||
@ -293,7 +294,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
|
||||
* a problem.
|
||||
*/
|
||||
if (urb->actual_length < entry->queue->desc_size || urb->status) {
|
||||
__set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
|
||||
set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
|
||||
usb_submit_urb(urb, GFP_ATOMIC);
|
||||
return;
|
||||
}
|
||||
@ -361,7 +362,7 @@ void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
|
||||
entry->skb->data, entry->skb->len,
|
||||
rt2x00usb_interrupt_rxdone, entry);
|
||||
|
||||
__set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
|
||||
set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
|
||||
usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry);
|
||||
|
@ -1478,16 +1478,6 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
|
||||
rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR0, ®);
|
||||
rt2x00_set_field32(®, AC_TXOP_CSR0_AC0_TX_OP, 0);
|
||||
rt2x00_set_field32(®, AC_TXOP_CSR0_AC1_TX_OP, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR0, reg);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR1, ®);
|
||||
rt2x00_set_field32(®, AC_TXOP_CSR1_AC2_TX_OP, 192);
|
||||
rt2x00_set_field32(®, AC_TXOP_CSR1_AC3_TX_OP, 48);
|
||||
rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
|
||||
|
||||
/*
|
||||
* Clear all beacons
|
||||
* For the Beacon base registers we only need to clear
|
||||
@ -2001,6 +1991,8 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
|
||||
|
||||
if (rt2x00_get_field32(word0, RXD_W0_OFDM))
|
||||
rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
|
||||
else
|
||||
rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
|
||||
if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
|
||||
rxdesc->dev_flags |= RXDONE_MY_BSS;
|
||||
}
|
||||
@ -2121,7 +2113,7 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
|
||||
if (!reg && !reg_mcu)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/*
|
||||
@ -2652,6 +2644,63 @@ static int rt61pci_set_retry_limit(struct ieee80211_hw *hw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
|
||||
const struct ieee80211_tx_queue_params *params)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct data_queue *queue;
|
||||
struct rt2x00_field32 field;
|
||||
int retval;
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* First pass the configuration through rt2x00lib, that will
|
||||
* update the queue settings and validate the input. After that
|
||||
* we are free to update the registers based on the value
|
||||
* in the queue parameter.
|
||||
*/
|
||||
retval = rt2x00mac_conf_tx(hw, queue_idx, params);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
|
||||
|
||||
/* Update WMM TXOP register */
|
||||
if (queue_idx < 2) {
|
||||
field.bit_offset = queue_idx * 16;
|
||||
field.bit_mask = 0xffff << field.bit_offset;
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR0, ®);
|
||||
rt2x00_set_field32(®, field, queue->txop);
|
||||
rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR0, reg);
|
||||
} else if (queue_idx < 4) {
|
||||
field.bit_offset = (queue_idx - 2) * 16;
|
||||
field.bit_mask = 0xffff << field.bit_offset;
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR1, ®);
|
||||
rt2x00_set_field32(®, field, queue->txop);
|
||||
rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
|
||||
}
|
||||
|
||||
/* Update WMM registers */
|
||||
field.bit_offset = queue_idx * 4;
|
||||
field.bit_mask = 0xf << field.bit_offset;
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, AIFSN_CSR, ®);
|
||||
rt2x00_set_field32(®, field, queue->aifs);
|
||||
rt2x00pci_register_write(rt2x00dev, AIFSN_CSR, reg);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, CWMIN_CSR, ®);
|
||||
rt2x00_set_field32(®, field, queue->cw_min);
|
||||
rt2x00pci_register_write(rt2x00dev, CWMIN_CSR, reg);
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, CWMAX_CSR, ®);
|
||||
rt2x00_set_field32(®, field, queue->cw_max);
|
||||
rt2x00pci_register_write(rt2x00dev, CWMAX_CSR, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 rt61pci_get_tsf(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
@ -2679,7 +2728,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
|
||||
.get_stats = rt2x00mac_get_stats,
|
||||
.set_retry_limit = rt61pci_set_retry_limit,
|
||||
.bss_info_changed = rt2x00mac_bss_info_changed,
|
||||
.conf_tx = rt2x00mac_conf_tx,
|
||||
.conf_tx = rt61pci_conf_tx,
|
||||
.get_tx_stats = rt2x00mac_get_tx_stats,
|
||||
.get_tsf = rt61pci_get_tsf,
|
||||
};
|
||||
|
@ -1277,16 +1277,6 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt73usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
|
||||
rt73usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, AC_TXOP_CSR0, ®);
|
||||
rt2x00_set_field32(®, AC_TXOP_CSR0_AC0_TX_OP, 0);
|
||||
rt2x00_set_field32(®, AC_TXOP_CSR0_AC1_TX_OP, 0);
|
||||
rt73usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, AC_TXOP_CSR1, ®);
|
||||
rt2x00_set_field32(®, AC_TXOP_CSR1_AC2_TX_OP, 192);
|
||||
rt2x00_set_field32(®, AC_TXOP_CSR1_AC3_TX_OP, 48);
|
||||
rt73usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, MAC_CSR9, ®);
|
||||
rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0);
|
||||
rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
|
||||
@ -1566,8 +1556,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,
|
||||
test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx);
|
||||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT,
|
||||
skb->len - skbdesc->desc_len);
|
||||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
|
||||
rt2x00_set_field32(&word, TXD_W0_BURST2,
|
||||
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
|
||||
@ -1776,6 +1765,8 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
|
||||
|
||||
if (rt2x00_get_field32(word0, RXD_W0_OFDM))
|
||||
rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
|
||||
else
|
||||
rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
|
||||
if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
|
||||
rxdesc->dev_flags |= RXDONE_MY_BSS;
|
||||
|
||||
@ -2246,6 +2237,63 @@ static int rt73usb_set_retry_limit(struct ieee80211_hw *hw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
|
||||
const struct ieee80211_tx_queue_params *params)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct data_queue *queue;
|
||||
struct rt2x00_field32 field;
|
||||
int retval;
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* First pass the configuration through rt2x00lib, that will
|
||||
* update the queue settings and validate the input. After that
|
||||
* we are free to update the registers based on the value
|
||||
* in the queue parameter.
|
||||
*/
|
||||
retval = rt2x00mac_conf_tx(hw, queue_idx, params);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
|
||||
|
||||
/* Update WMM TXOP register */
|
||||
if (queue_idx < 2) {
|
||||
field.bit_offset = queue_idx * 16;
|
||||
field.bit_mask = 0xffff << field.bit_offset;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, AC_TXOP_CSR0, ®);
|
||||
rt2x00_set_field32(®, field, queue->txop);
|
||||
rt73usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg);
|
||||
} else if (queue_idx < 4) {
|
||||
field.bit_offset = (queue_idx - 2) * 16;
|
||||
field.bit_mask = 0xffff << field.bit_offset;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, AC_TXOP_CSR1, ®);
|
||||
rt2x00_set_field32(®, field, queue->txop);
|
||||
rt73usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
|
||||
}
|
||||
|
||||
/* Update WMM registers */
|
||||
field.bit_offset = queue_idx * 4;
|
||||
field.bit_mask = 0xf << field.bit_offset;
|
||||
|
||||
rt73usb_register_read(rt2x00dev, AIFSN_CSR, ®);
|
||||
rt2x00_set_field32(®, field, queue->aifs);
|
||||
rt73usb_register_write(rt2x00dev, AIFSN_CSR, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, CWMIN_CSR, ®);
|
||||
rt2x00_set_field32(®, field, queue->cw_min);
|
||||
rt73usb_register_write(rt2x00dev, CWMIN_CSR, reg);
|
||||
|
||||
rt73usb_register_read(rt2x00dev, CWMAX_CSR, ®);
|
||||
rt2x00_set_field32(®, field, queue->cw_max);
|
||||
rt73usb_register_write(rt2x00dev, CWMAX_CSR, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Mac80211 demands get_tsf must be atomic.
|
||||
@ -2283,7 +2331,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
|
||||
.get_stats = rt2x00mac_get_stats,
|
||||
.set_retry_limit = rt73usb_set_retry_limit,
|
||||
.bss_info_changed = rt2x00mac_bss_info_changed,
|
||||
.conf_tx = rt2x00mac_conf_tx,
|
||||
.conf_tx = rt73usb_conf_tx,
|
||||
.get_tx_stats = rt2x00mac_get_tx_stats,
|
||||
.get_tsf = rt73usb_get_tsf,
|
||||
};
|
||||
|
@ -327,11 +327,9 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
|
||||
s8 gain;
|
||||
u16 loc[3];
|
||||
|
||||
if (out->revision == 3) { /* rev 3 moved MAC */
|
||||
if (out->revision == 3) /* rev 3 moved MAC */
|
||||
loc[0] = SSB_SPROM3_IL0MAC;
|
||||
loc[1] = SSB_SPROM3_ET0MAC;
|
||||
loc[2] = SSB_SPROM3_ET1MAC;
|
||||
} else {
|
||||
else {
|
||||
loc[0] = SSB_SPROM1_IL0MAC;
|
||||
loc[1] = SSB_SPROM1_ET0MAC;
|
||||
loc[2] = SSB_SPROM1_ET1MAC;
|
||||
@ -340,6 +338,7 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
|
||||
v = in[SPOFF(loc[0]) + i];
|
||||
*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
|
||||
}
|
||||
if (out->revision < 3) { /* only rev 1-2 have et0, et1 */
|
||||
for (i = 0; i < 3; i++) {
|
||||
v = in[SPOFF(loc[1]) + i];
|
||||
*(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
|
||||
@ -348,6 +347,7 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
|
||||
v = in[SPOFF(loc[2]) + i];
|
||||
*(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
|
||||
}
|
||||
}
|
||||
SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
|
||||
SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
|
||||
SSB_SPROM1_ETHPHY_ET1A_SHIFT);
|
||||
@ -399,30 +399,33 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
|
||||
out->antenna_gain.ghz5.a3 = gain;
|
||||
}
|
||||
|
||||
static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in)
|
||||
static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
|
||||
{
|
||||
int i;
|
||||
u16 v;
|
||||
u16 il0mac_offset;
|
||||
|
||||
/* extract the equivalent of the r1 variables */
|
||||
if (out->revision == 4)
|
||||
il0mac_offset = SSB_SPROM4_IL0MAC;
|
||||
else
|
||||
il0mac_offset = SSB_SPROM5_IL0MAC;
|
||||
/* extract the MAC address */
|
||||
for (i = 0; i < 3; i++) {
|
||||
v = in[SPOFF(SSB_SPROM4_IL0MAC) + i];
|
||||
v = in[SPOFF(il0mac_offset) + i];
|
||||
*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
|
||||
}
|
||||
for (i = 0; i < 3; i++) {
|
||||
v = in[SPOFF(SSB_SPROM4_ET0MAC) + i];
|
||||
*(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
|
||||
}
|
||||
for (i = 0; i < 3; i++) {
|
||||
v = in[SPOFF(SSB_SPROM4_ET1MAC) + i];
|
||||
*(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
|
||||
}
|
||||
SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
|
||||
SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
|
||||
SSB_SPROM4_ETHPHY_ET1A_SHIFT);
|
||||
if (out->revision == 4) {
|
||||
SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
|
||||
SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
|
||||
SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
|
||||
} else {
|
||||
SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
|
||||
SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
|
||||
SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
|
||||
}
|
||||
SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
|
||||
SSB_SPROM4_ANTAVAIL_A_SHIFT);
|
||||
SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
|
||||
@ -433,12 +436,21 @@ static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in)
|
||||
SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
|
||||
SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
|
||||
SSB_SPROM4_ITSSI_A_SHIFT);
|
||||
if (out->revision == 4) {
|
||||
SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
|
||||
SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
|
||||
SSB_SPROM4_GPIOA_P1_SHIFT);
|
||||
SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
|
||||
SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
|
||||
SSB_SPROM4_GPIOB_P3_SHIFT);
|
||||
} else {
|
||||
SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
|
||||
SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
|
||||
SSB_SPROM5_GPIOA_P1_SHIFT);
|
||||
SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
|
||||
SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
|
||||
SSB_SPROM5_GPIOB_P3_SHIFT);
|
||||
}
|
||||
|
||||
/* Extract the antenna gain values. */
|
||||
SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
|
||||
@ -462,6 +474,8 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
|
||||
|
||||
out->revision = in[size - 1] & 0x00FF;
|
||||
ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
|
||||
memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */
|
||||
memset(out->et1mac, 0xFF, 6);
|
||||
if ((bus->chip_id & 0xFF00) == 0x4400) {
|
||||
/* Workaround: The BCM44XX chip has a stupid revision
|
||||
* number stored in the SPROM.
|
||||
@ -471,16 +485,16 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
|
||||
} else if (bus->chip_id == 0x4321) {
|
||||
/* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
|
||||
out->revision = 4;
|
||||
sprom_extract_r4(out, in);
|
||||
sprom_extract_r45(out, in);
|
||||
} else {
|
||||
if (out->revision == 0)
|
||||
goto unsupported;
|
||||
if (out->revision >= 1 && out->revision <= 3) {
|
||||
sprom_extract_r123(out, in);
|
||||
}
|
||||
if (out->revision == 4)
|
||||
sprom_extract_r4(out, in);
|
||||
if (out->revision >= 5)
|
||||
if (out->revision == 4 || out->revision == 5)
|
||||
sprom_extract_r45(out, in);
|
||||
if (out->revision > 5)
|
||||
goto unsupported;
|
||||
}
|
||||
|
||||
|
@ -714,6 +714,7 @@ struct ieee80211_ht_addt_info {
|
||||
#define IEEE80211_HT_CAP_SGI_40 0x0040
|
||||
#define IEEE80211_HT_CAP_DELAY_BA 0x0400
|
||||
#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800
|
||||
#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
|
||||
/* 802.11n HT capability AMPDU settings */
|
||||
#define IEEE80211_HT_CAP_AMPDU_FACTOR 0x03
|
||||
#define IEEE80211_HT_CAP_AMPDU_DENSITY 0x1C
|
||||
|
@ -89,6 +89,8 @@
|
||||
* @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC
|
||||
* or, if no MAC address given, all mesh paths, on the interface identified
|
||||
* by %NL80211_ATTR_IFINDEX.
|
||||
* @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by
|
||||
* %NL80211_ATTR_IFINDEX.
|
||||
*
|
||||
* @NL80211_CMD_MAX: highest used command number
|
||||
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||
@ -127,6 +129,8 @@ enum nl80211_commands {
|
||||
NL80211_CMD_NEW_MPATH,
|
||||
NL80211_CMD_DEL_MPATH,
|
||||
|
||||
NL80211_CMD_SET_BSS,
|
||||
|
||||
/* add commands here */
|
||||
|
||||
/* used to define NL80211_CMD_MAX below */
|
||||
@ -134,6 +138,11 @@ enum nl80211_commands {
|
||||
NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
|
||||
};
|
||||
|
||||
/*
|
||||
* Allow user space programs to use #ifdef on new commands by defining them
|
||||
* here
|
||||
*/
|
||||
#define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS
|
||||
|
||||
/**
|
||||
* enum nl80211_attrs - nl80211 netlink attributes
|
||||
@ -192,6 +201,15 @@ enum nl80211_commands {
|
||||
* @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of
|
||||
* &enum nl80211_mntr_flags.
|
||||
*
|
||||
* @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1)
|
||||
* @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled
|
||||
* (u8, 0 or 1)
|
||||
* @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled
|
||||
* (u8, 0 or 1)
|
||||
*
|
||||
* @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from
|
||||
* association request when used with NL80211_CMD_NEW_STATION)
|
||||
*
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
*/
|
||||
@ -235,16 +253,29 @@ enum nl80211_attrs {
|
||||
NL80211_ATTR_MPATH_NEXT_HOP,
|
||||
NL80211_ATTR_MPATH_INFO,
|
||||
|
||||
NL80211_ATTR_BSS_CTS_PROT,
|
||||
NL80211_ATTR_BSS_SHORT_PREAMBLE,
|
||||
NL80211_ATTR_BSS_SHORT_SLOT_TIME,
|
||||
|
||||
NL80211_ATTR_HT_CAPABILITY,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
|
||||
};
|
||||
|
||||
/*
|
||||
* Allow user space programs to use #ifdef on new attributes by defining them
|
||||
* here
|
||||
*/
|
||||
#define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY
|
||||
|
||||
#define NL80211_MAX_SUPP_RATES 32
|
||||
#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0
|
||||
#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16
|
||||
#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
|
||||
#define NL80211_HT_CAPABILITY_LEN 26
|
||||
|
||||
/**
|
||||
* enum nl80211_iftype - (virtual) interface types
|
||||
|
@ -245,8 +245,6 @@
|
||||
|
||||
/* SPROM Revision 3 (inherits most data from rev 2) */
|
||||
#define SSB_SPROM3_IL0MAC 0x104A /* 6 bytes MAC address for 802.11b/g */
|
||||
#define SSB_SPROM3_ET0MAC 0x1050 /* 6 bytes MAC address for Ethernet ?? */
|
||||
#define SSB_SPROM3_ET1MAC 0x1050 /* 6 bytes MAC address for 802.11a ?? */
|
||||
#define SSB_SPROM3_OFDMAPO 0x102C /* A-PHY OFDM Mid Power Offset (4 bytes, BigEndian) */
|
||||
#define SSB_SPROM3_OFDMALPO 0x1030 /* A-PHY OFDM Low Power Offset (4 bytes, BigEndian) */
|
||||
#define SSB_SPROM3_OFDMAHPO 0x1034 /* A-PHY OFDM High Power Offset (4 bytes, BigEndian) */
|
||||
@ -267,8 +265,6 @@
|
||||
|
||||
/* SPROM Revision 4 */
|
||||
#define SSB_SPROM4_IL0MAC 0x104C /* 6 byte MAC address for a/b/g/n */
|
||||
#define SSB_SPROM4_ET0MAC 0x1018 /* 6 bytes MAC address for Ethernet ?? */
|
||||
#define SSB_SPROM4_ET1MAC 0x1018 /* 6 bytes MAC address for 802.11a ?? */
|
||||
#define SSB_SPROM4_ETHPHY 0x105A /* Ethernet PHY settings ?? */
|
||||
#define SSB_SPROM4_ETHPHY_ET0A 0x001F /* MII Address for enet0 */
|
||||
#define SSB_SPROM4_ETHPHY_ET1A 0x03E0 /* MII Address for enet1 */
|
||||
@ -316,6 +312,21 @@
|
||||
#define SSB_SPROM4_PA1B1 0x1090
|
||||
#define SSB_SPROM4_PA1B2 0x1092
|
||||
|
||||
/* SPROM Revision 5 (inherits most data from rev 4) */
|
||||
#define SSB_SPROM5_BFLLO 0x104A /* Boardflags (low 16 bits) */
|
||||
#define SSB_SPROM5_BFLHI 0x104C /* Board Flags Hi */
|
||||
#define SSB_SPROM5_IL0MAC 0x1052 /* 6 byte MAC address for a/b/g/n */
|
||||
#define SSB_SPROM5_CCODE 0x1044 /* Country Code (2 bytes) */
|
||||
#define SSB_SPROM5_GPIOA 0x1076 /* Gen. Purpose IO # 0 and 1 */
|
||||
#define SSB_SPROM5_GPIOA_P0 0x00FF /* Pin 0 */
|
||||
#define SSB_SPROM5_GPIOA_P1 0xFF00 /* Pin 1 */
|
||||
#define SSB_SPROM5_GPIOA_P1_SHIFT 8
|
||||
#define SSB_SPROM5_GPIOB 0x1078 /* Gen. Purpose IO # 2 and 3 */
|
||||
#define SSB_SPROM5_GPIOB_P2 0x00FF /* Pin 2 */
|
||||
#define SSB_SPROM5_GPIOB_P3 0xFF00 /* Pin 3 */
|
||||
#define SSB_SPROM5_GPIOB_P3_SHIFT 8
|
||||
|
||||
|
||||
/* Values for SSB_SPROM1_BINF_CCODE */
|
||||
enum {
|
||||
SSB_SPROM1CCODE_WORLD = 0,
|
||||
|
@ -152,6 +152,7 @@ struct station_parameters {
|
||||
u16 aid;
|
||||
u8 supported_rates_len;
|
||||
u8 plink_action;
|
||||
struct ieee80211_ht_cap *ht_capa;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -268,6 +269,23 @@ struct mpath_info {
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct bss_parameters - BSS parameters
|
||||
*
|
||||
* Used to change BSS parameters (mainly for AP mode).
|
||||
*
|
||||
* @use_cts_prot: Whether to use CTS protection
|
||||
* (0 = no, 1 = yes, -1 = do not change)
|
||||
* @use_short_preamble: Whether the use of short preambles is allowed
|
||||
* (0 = no, 1 = yes, -1 = do not change)
|
||||
* @use_short_slot_time: Whether the use of short slot time is allowed
|
||||
* (0 = no, 1 = yes, -1 = do not change)
|
||||
*/
|
||||
struct bss_parameters {
|
||||
int use_cts_prot;
|
||||
int use_short_preamble;
|
||||
int use_short_slot_time;
|
||||
};
|
||||
|
||||
/* from net/wireless.h */
|
||||
struct wiphy;
|
||||
@ -318,6 +336,8 @@ struct wiphy;
|
||||
* @change_station: Modify a given station.
|
||||
*
|
||||
* @set_mesh_cfg: set mesh parameters (by now, just mesh id)
|
||||
*
|
||||
* @change_bss: Modify parameters for a given BSS.
|
||||
*/
|
||||
struct cfg80211_ops {
|
||||
int (*add_virtual_intf)(struct wiphy *wiphy, char *name,
|
||||
@ -370,6 +390,9 @@ struct cfg80211_ops {
|
||||
int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev,
|
||||
int idx, u8 *dst, u8 *next_hop,
|
||||
struct mpath_info *pinfo);
|
||||
|
||||
int (*change_bss)(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct bss_parameters *params);
|
||||
};
|
||||
|
||||
#endif /* __NET_CFG80211_H */
|
||||
|
@ -158,12 +158,14 @@ struct ieee80211_low_level_stats {
|
||||
* also implies a change in the AID.
|
||||
* @BSS_CHANGED_ERP_CTS_PROT: CTS protection changed
|
||||
* @BSS_CHANGED_ERP_PREAMBLE: preamble changed
|
||||
* @BSS_CHANGED_ERP_SLOT: slot timing changed
|
||||
* @BSS_CHANGED_HT: 802.11n parameters changed
|
||||
*/
|
||||
enum ieee80211_bss_change {
|
||||
BSS_CHANGED_ASSOC = 1<<0,
|
||||
BSS_CHANGED_ERP_CTS_PROT = 1<<1,
|
||||
BSS_CHANGED_ERP_PREAMBLE = 1<<2,
|
||||
BSS_CHANGED_ERP_SLOT = 1<<3,
|
||||
BSS_CHANGED_HT = 1<<4,
|
||||
};
|
||||
|
||||
@ -177,6 +179,7 @@ enum ieee80211_bss_change {
|
||||
* @aid: association ID number, valid only when @assoc is true
|
||||
* @use_cts_prot: use CTS protection
|
||||
* @use_short_preamble: use 802.11b short preamble
|
||||
* @use_short_slot: use short slot time (only relevant for ERP)
|
||||
* @dtim_period: num of beacons before the next DTIM, for PSM
|
||||
* @timestamp: beacon timestamp
|
||||
* @beacon_int: beacon interval
|
||||
@ -192,6 +195,7 @@ struct ieee80211_bss_conf {
|
||||
/* erp related data */
|
||||
bool use_cts_prot;
|
||||
bool use_short_preamble;
|
||||
bool use_short_slot;
|
||||
u8 dtim_period;
|
||||
u16 beacon_int;
|
||||
u16 assoc_capability;
|
||||
@ -420,6 +424,11 @@ struct ieee80211_rx_status {
|
||||
* @IEEE80211_CONF_PS: Enable 802.11 power save mode
|
||||
*/
|
||||
enum ieee80211_conf_flags {
|
||||
/*
|
||||
* TODO: IEEE80211_CONF_SHORT_SLOT_TIME will be removed once drivers
|
||||
* have been converted to use bss_info_changed() for slot time
|
||||
* configuration
|
||||
*/
|
||||
IEEE80211_CONF_SHORT_SLOT_TIME = (1<<0),
|
||||
IEEE80211_CONF_RADIOTAP = (1<<1),
|
||||
IEEE80211_CONF_SUPPORT_HT_MODE = (1<<2),
|
||||
|
@ -674,6 +674,11 @@ static void sta_apply_parameters(struct ieee80211_local *local,
|
||||
sta->supp_rates[local->oper_channel->band] = rates;
|
||||
}
|
||||
|
||||
if (params->ht_capa) {
|
||||
ieee80211_ht_cap_ie_to_ht_info(params->ht_capa,
|
||||
&sta->ht_info);
|
||||
}
|
||||
|
||||
if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
|
||||
switch (params->plink_action) {
|
||||
case PLINK_ACTION_OPEN:
|
||||
@ -1010,6 +1015,42 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ieee80211_change_bss(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
struct bss_parameters *params)
|
||||
{
|
||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
u32 changed = 0;
|
||||
|
||||
if (dev == local->mdev)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
|
||||
if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
|
||||
return -EINVAL;
|
||||
|
||||
if (params->use_cts_prot >= 0) {
|
||||
sdata->bss_conf.use_cts_prot = params->use_cts_prot;
|
||||
changed |= BSS_CHANGED_ERP_CTS_PROT;
|
||||
}
|
||||
if (params->use_short_preamble >= 0) {
|
||||
sdata->bss_conf.use_short_preamble =
|
||||
params->use_short_preamble;
|
||||
changed |= BSS_CHANGED_ERP_PREAMBLE;
|
||||
}
|
||||
if (params->use_short_slot_time >= 0) {
|
||||
sdata->bss_conf.use_short_slot =
|
||||
params->use_short_slot_time;
|
||||
changed |= BSS_CHANGED_ERP_SLOT;
|
||||
}
|
||||
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct cfg80211_ops mac80211_config_ops = {
|
||||
.add_virtual_intf = ieee80211_add_iface,
|
||||
.del_virtual_intf = ieee80211_del_iface,
|
||||
@ -1033,4 +1074,5 @@ struct cfg80211_ops mac80211_config_ops = {
|
||||
.get_mpath = ieee80211_get_mpath,
|
||||
.dump_mpath = ieee80211_dump_mpath,
|
||||
#endif
|
||||
.change_bss = ieee80211_change_bss,
|
||||
};
|
||||
|
@ -79,16 +79,11 @@ struct ieee80211_sta_bss {
|
||||
enum ieee80211_band band;
|
||||
int freq;
|
||||
int signal, noise, qual;
|
||||
u8 *wpa_ie;
|
||||
size_t wpa_ie_len;
|
||||
u8 *rsn_ie;
|
||||
size_t rsn_ie_len;
|
||||
u8 *wmm_ie;
|
||||
size_t wmm_ie_len;
|
||||
u8 *ht_ie;
|
||||
size_t ht_ie_len;
|
||||
u8 *ht_add_ie;
|
||||
size_t ht_add_ie_len;
|
||||
u8 *ies; /* all information elements from the last Beacon or Probe
|
||||
* Response frames; note Beacon frame is not allowed to
|
||||
* override values from Probe Response */
|
||||
size_t ies_len;
|
||||
bool wmm_used;
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
u8 *mesh_id;
|
||||
size_t mesh_id_len;
|
||||
@ -773,6 +768,9 @@ struct ieee80211_ra_tid {
|
||||
|
||||
/* Parsed Information Elements */
|
||||
struct ieee802_11_elems {
|
||||
u8 *ie_start;
|
||||
size_t total_len;
|
||||
|
||||
/* pointers to IEs */
|
||||
u8 *ssid;
|
||||
u8 *supp_rates;
|
||||
|
@ -598,7 +598,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
u16 start_seq_num = 0;
|
||||
u16 start_seq_num;
|
||||
u8 *state;
|
||||
int ret;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
@ -678,6 +678,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
||||
* call back right away, it must see that the flow has begun */
|
||||
*state |= HT_ADDBA_REQUESTED_MSK;
|
||||
|
||||
/* This is slightly racy because the queue isn't stopped */
|
||||
start_seq_num = sta->tid_seq[tid];
|
||||
|
||||
if (local->ops->ampdu_action)
|
||||
ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
|
||||
ra, tid, &start_seq_num);
|
||||
|
@ -98,6 +98,8 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
|
||||
u8 *pos = start;
|
||||
|
||||
memset(elems, 0, sizeof(*elems));
|
||||
elems->ie_start = start;
|
||||
elems->total_len = len;
|
||||
|
||||
while (left >= 2) {
|
||||
u8 id, elen;
|
||||
@ -234,6 +236,27 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
|
||||
}
|
||||
|
||||
|
||||
static u8 * ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie)
|
||||
{
|
||||
u8 *end, *pos;
|
||||
|
||||
pos = bss->ies;
|
||||
if (pos == NULL)
|
||||
return NULL;
|
||||
end = pos + bss->ies_len;
|
||||
|
||||
while (pos + 1 < end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
break;
|
||||
if (pos[0] == ie)
|
||||
return pos;
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int ecw2cw(int ecw)
|
||||
{
|
||||
return (1 << ecw) - 1;
|
||||
@ -737,7 +760,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
u8 *pos, *ies;
|
||||
u8 *pos, *ies, *ht_add_ie;
|
||||
int i, len, count, rates_len, supp_rates_len;
|
||||
u16 capab;
|
||||
struct ieee80211_sta_bss *bss;
|
||||
@ -772,7 +795,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
if (bss) {
|
||||
if (bss->capability & WLAN_CAPABILITY_PRIVACY)
|
||||
capab |= WLAN_CAPABILITY_PRIVACY;
|
||||
if (bss->wmm_ie)
|
||||
if (bss->wmm_used)
|
||||
wmm = 1;
|
||||
|
||||
/* get all rates supported by the device and the AP as
|
||||
@ -894,9 +917,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
/* wmm support is a must to HT */
|
||||
if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) &&
|
||||
sband->ht_info.ht_supported && bss->ht_add_ie) {
|
||||
sband->ht_info.ht_supported &&
|
||||
(ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) {
|
||||
struct ieee80211_ht_addt_info *ht_add_info =
|
||||
(struct ieee80211_ht_addt_info *)bss->ht_add_ie;
|
||||
(struct ieee80211_ht_addt_info *)ht_add_ie;
|
||||
u16 cap = sband->ht_info.cap;
|
||||
__le16 tmp;
|
||||
u32 flags = local->hw.conf.channel->flags;
|
||||
@ -2372,11 +2396,7 @@ ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_i
|
||||
|
||||
static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
|
||||
{
|
||||
kfree(bss->wpa_ie);
|
||||
kfree(bss->rsn_ie);
|
||||
kfree(bss->wmm_ie);
|
||||
kfree(bss->ht_ie);
|
||||
kfree(bss->ht_add_ie);
|
||||
kfree(bss->ies);
|
||||
kfree(bss_mesh_id(bss));
|
||||
kfree(bss_mesh_cfg(bss));
|
||||
kfree(bss);
|
||||
@ -2662,43 +2682,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
||||
bss->has_erp_value = 1;
|
||||
}
|
||||
|
||||
if (elems->ht_cap_elem &&
|
||||
(!bss->ht_ie || bss->ht_ie_len != elems->ht_cap_elem_len ||
|
||||
memcmp(bss->ht_ie, elems->ht_cap_elem, elems->ht_cap_elem_len))) {
|
||||
kfree(bss->ht_ie);
|
||||
bss->ht_ie = kmalloc(elems->ht_cap_elem_len + 2, GFP_ATOMIC);
|
||||
if (bss->ht_ie) {
|
||||
memcpy(bss->ht_ie, elems->ht_cap_elem - 2,
|
||||
elems->ht_cap_elem_len + 2);
|
||||
bss->ht_ie_len = elems->ht_cap_elem_len + 2;
|
||||
} else
|
||||
bss->ht_ie_len = 0;
|
||||
} else if (!elems->ht_cap_elem && bss->ht_ie) {
|
||||
kfree(bss->ht_ie);
|
||||
bss->ht_ie = NULL;
|
||||
bss->ht_ie_len = 0;
|
||||
}
|
||||
|
||||
if (elems->ht_info_elem &&
|
||||
(!bss->ht_add_ie ||
|
||||
bss->ht_add_ie_len != elems->ht_info_elem_len ||
|
||||
memcmp(bss->ht_add_ie, elems->ht_info_elem,
|
||||
elems->ht_info_elem_len))) {
|
||||
kfree(bss->ht_add_ie);
|
||||
bss->ht_add_ie =
|
||||
kmalloc(elems->ht_info_elem_len + 2, GFP_ATOMIC);
|
||||
if (bss->ht_add_ie) {
|
||||
memcpy(bss->ht_add_ie, elems->ht_info_elem - 2,
|
||||
elems->ht_info_elem_len + 2);
|
||||
bss->ht_add_ie_len = elems->ht_info_elem_len + 2;
|
||||
} else
|
||||
bss->ht_add_ie_len = 0;
|
||||
} else if (!elems->ht_info_elem && bss->ht_add_ie) {
|
||||
kfree(bss->ht_add_ie);
|
||||
bss->ht_add_ie = NULL;
|
||||
bss->ht_add_ie_len = 0;
|
||||
}
|
||||
|
||||
bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
|
||||
bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
|
||||
|
||||
@ -2749,88 +2732,17 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
||||
return;
|
||||
}
|
||||
|
||||
if (elems->wpa &&
|
||||
(!bss->wpa_ie || bss->wpa_ie_len != elems->wpa_len ||
|
||||
memcmp(bss->wpa_ie, elems->wpa, elems->wpa_len))) {
|
||||
kfree(bss->wpa_ie);
|
||||
bss->wpa_ie = kmalloc(elems->wpa_len + 2, GFP_ATOMIC);
|
||||
if (bss->wpa_ie) {
|
||||
memcpy(bss->wpa_ie, elems->wpa - 2, elems->wpa_len + 2);
|
||||
bss->wpa_ie_len = elems->wpa_len + 2;
|
||||
} else
|
||||
bss->wpa_ie_len = 0;
|
||||
} else if (!elems->wpa && bss->wpa_ie) {
|
||||
kfree(bss->wpa_ie);
|
||||
bss->wpa_ie = NULL;
|
||||
bss->wpa_ie_len = 0;
|
||||
if (bss->ies == NULL || bss->ies_len < elems->total_len) {
|
||||
kfree(bss->ies);
|
||||
bss->ies = kmalloc(elems->total_len, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
if (elems->rsn &&
|
||||
(!bss->rsn_ie || bss->rsn_ie_len != elems->rsn_len ||
|
||||
memcmp(bss->rsn_ie, elems->rsn, elems->rsn_len))) {
|
||||
kfree(bss->rsn_ie);
|
||||
bss->rsn_ie = kmalloc(elems->rsn_len + 2, GFP_ATOMIC);
|
||||
if (bss->rsn_ie) {
|
||||
memcpy(bss->rsn_ie, elems->rsn - 2, elems->rsn_len + 2);
|
||||
bss->rsn_ie_len = elems->rsn_len + 2;
|
||||
if (bss->ies) {
|
||||
memcpy(bss->ies, elems->ie_start, elems->total_len);
|
||||
bss->ies_len = elems->total_len;
|
||||
} else
|
||||
bss->rsn_ie_len = 0;
|
||||
} else if (!elems->rsn && bss->rsn_ie) {
|
||||
kfree(bss->rsn_ie);
|
||||
bss->rsn_ie = NULL;
|
||||
bss->rsn_ie_len = 0;
|
||||
}
|
||||
bss->ies_len = 0;
|
||||
|
||||
/*
|
||||
* Cf.
|
||||
* http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC
|
||||
*
|
||||
* quoting:
|
||||
*
|
||||
* In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia
|
||||
* Applications with Quality of Service in Wi-Fi Networks," Wi- Fi
|
||||
* Alliance (September 1, 2004) is incorporated by reference herein.
|
||||
* The inclusion of the WMM Parameters in probe responses and
|
||||
* association responses is mandatory for WMM enabled networks. The
|
||||
* inclusion of the WMM Parameters in beacons, however, is optional.
|
||||
*/
|
||||
|
||||
if (elems->wmm_param &&
|
||||
(!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_param_len ||
|
||||
memcmp(bss->wmm_ie, elems->wmm_param, elems->wmm_param_len))) {
|
||||
kfree(bss->wmm_ie);
|
||||
bss->wmm_ie = kmalloc(elems->wmm_param_len + 2, GFP_ATOMIC);
|
||||
if (bss->wmm_ie) {
|
||||
memcpy(bss->wmm_ie, elems->wmm_param - 2,
|
||||
elems->wmm_param_len + 2);
|
||||
bss->wmm_ie_len = elems->wmm_param_len + 2;
|
||||
} else
|
||||
bss->wmm_ie_len = 0;
|
||||
} else if (elems->wmm_info &&
|
||||
(!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_info_len ||
|
||||
memcmp(bss->wmm_ie, elems->wmm_info,
|
||||
elems->wmm_info_len))) {
|
||||
/* As for certain AP's Fifth bit is not set in WMM IE in
|
||||
* beacon frames.So while parsing the beacon frame the
|
||||
* wmm_info structure is used instead of wmm_param.
|
||||
* wmm_info structure was never used to set bss->wmm_ie.
|
||||
* This code fixes this problem by copying the WME
|
||||
* information from wmm_info to bss->wmm_ie and enabling
|
||||
* n-band association.
|
||||
*/
|
||||
kfree(bss->wmm_ie);
|
||||
bss->wmm_ie = kmalloc(elems->wmm_info_len + 2, GFP_ATOMIC);
|
||||
if (bss->wmm_ie) {
|
||||
memcpy(bss->wmm_ie, elems->wmm_info - 2,
|
||||
elems->wmm_info_len + 2);
|
||||
bss->wmm_ie_len = elems->wmm_info_len + 2;
|
||||
} else
|
||||
bss->wmm_ie_len = 0;
|
||||
} else if (!elems->wmm_param && !elems->wmm_info && bss->wmm_ie) {
|
||||
kfree(bss->wmm_ie);
|
||||
bss->wmm_ie = NULL;
|
||||
bss->wmm_ie_len = 0;
|
||||
}
|
||||
bss->wmm_used = elems->wmm_param || elems->wmm_info;
|
||||
|
||||
/* check if we need to merge IBSS */
|
||||
if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon &&
|
||||
@ -4146,6 +4058,48 @@ int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void ieee80211_sta_add_scan_ies(struct iw_request_info *info,
|
||||
struct ieee80211_sta_bss *bss,
|
||||
char **current_ev, char *end_buf)
|
||||
{
|
||||
u8 *pos, *end, *next;
|
||||
struct iw_event iwe;
|
||||
|
||||
if (bss == NULL || bss->ies == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If needed, fragment the IEs buffer (at IE boundaries) into short
|
||||
* enough fragments to fit into IW_GENERIC_IE_MAX octet messages.
|
||||
*/
|
||||
pos = bss->ies;
|
||||
end = pos + bss->ies_len;
|
||||
|
||||
while (end - pos > IW_GENERIC_IE_MAX) {
|
||||
next = pos + 2 + pos[1];
|
||||
while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX)
|
||||
next = next + 2 + next[1];
|
||||
|
||||
memset(&iwe, 0, sizeof(iwe));
|
||||
iwe.cmd = IWEVGENIE;
|
||||
iwe.u.data.length = next - pos;
|
||||
*current_ev = iwe_stream_add_point(info, *current_ev,
|
||||
end_buf, &iwe, pos);
|
||||
|
||||
pos = next;
|
||||
}
|
||||
|
||||
if (end > pos) {
|
||||
memset(&iwe, 0, sizeof(iwe));
|
||||
iwe.cmd = IWEVGENIE;
|
||||
iwe.u.data.length = end - pos;
|
||||
*current_ev = iwe_stream_add_point(info, *current_ev,
|
||||
end_buf, &iwe, pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ieee80211_sta_scan_result(struct ieee80211_local *local,
|
||||
struct iw_request_info *info,
|
||||
@ -4225,29 +4179,7 @@ ieee80211_sta_scan_result(struct ieee80211_local *local,
|
||||
current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
||||
&iwe, "");
|
||||
|
||||
if (bss && bss->wpa_ie) {
|
||||
memset(&iwe, 0, sizeof(iwe));
|
||||
iwe.cmd = IWEVGENIE;
|
||||
iwe.u.data.length = bss->wpa_ie_len;
|
||||
current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
||||
&iwe, bss->wpa_ie);
|
||||
}
|
||||
|
||||
if (bss && bss->rsn_ie) {
|
||||
memset(&iwe, 0, sizeof(iwe));
|
||||
iwe.cmd = IWEVGENIE;
|
||||
iwe.u.data.length = bss->rsn_ie_len;
|
||||
current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
||||
&iwe, bss->rsn_ie);
|
||||
}
|
||||
|
||||
if (bss && bss->ht_ie) {
|
||||
memset(&iwe, 0, sizeof(iwe));
|
||||
iwe.cmd = IWEVGENIE;
|
||||
iwe.u.data.length = bss->ht_ie_len;
|
||||
current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
||||
&iwe, bss->ht_ie);
|
||||
}
|
||||
ieee80211_sta_add_scan_ies(info, bss, ¤t_ev, end_buf);
|
||||
|
||||
if (bss && bss->supp_rates_len > 0) {
|
||||
/* display all supported rates in readable format */
|
||||
|
@ -47,8 +47,6 @@ static unsigned int classify_1d(struct sk_buff *skb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dscp & 0x1c)
|
||||
return 0;
|
||||
return dscp >> 5;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ MODULE_DESCRIPTION("RF switch support");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static LIST_HEAD(rfkill_list); /* list of registered rf switches */
|
||||
static DEFINE_MUTEX(rfkill_mutex);
|
||||
static DEFINE_MUTEX(rfkill_global_mutex);
|
||||
|
||||
static unsigned int rfkill_default_state = RFKILL_STATE_UNBLOCKED;
|
||||
module_param_named(default_state, rfkill_default_state, uint, 0444);
|
||||
@ -76,6 +76,7 @@ static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list);
|
||||
*/
|
||||
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);
|
||||
@ -91,6 +92,7 @@ EXPORT_SYMBOL_GPL(register_rfkill_notifier);
|
||||
*/
|
||||
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);
|
||||
@ -202,6 +204,9 @@ static int rfkill_toggle_radio(struct rfkill *rfkill,
|
||||
* RFKILL_STATE_HARD_BLOCKED */
|
||||
break;
|
||||
default:
|
||||
WARN(1, KERN_WARNING
|
||||
"rfkill: illegal state %d passed as parameter "
|
||||
"to rfkill_toggle_radio\n", state);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -229,14 +234,18 @@ static int rfkill_toggle_radio(struct rfkill *rfkill,
|
||||
* unless a specific switch is claimed by userspace (in which case,
|
||||
* that switch is left alone) or suspended.
|
||||
*
|
||||
* Caller must have acquired rfkill_mutex.
|
||||
* Caller must have acquired rfkill_global_mutex.
|
||||
*/
|
||||
static void __rfkill_switch_all(const enum rfkill_type type,
|
||||
const enum rfkill_state state)
|
||||
{
|
||||
struct rfkill *rfkill;
|
||||
|
||||
if (unlikely(state >= RFKILL_STATE_MAX))
|
||||
if (WARN((state >= RFKILL_STATE_MAX || type >= RFKILL_TYPE_MAX),
|
||||
KERN_WARNING
|
||||
"rfkill: illegal state %d or type %d "
|
||||
"passed as parameter to __rfkill_switch_all\n",
|
||||
state, type))
|
||||
return;
|
||||
|
||||
rfkill_global_states[type].current_state = state;
|
||||
@ -254,14 +263,14 @@ static void __rfkill_switch_all(const enum rfkill_type type,
|
||||
* @type: type of interfaces to be affected
|
||||
* @state: the new state
|
||||
*
|
||||
* Acquires rfkill_mutex and calls __rfkill_switch_all(@type, @state).
|
||||
* Acquires rfkill_global_mutex and calls __rfkill_switch_all(@type, @state).
|
||||
* Please refer to __rfkill_switch_all() for details.
|
||||
*/
|
||||
void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state)
|
||||
{
|
||||
mutex_lock(&rfkill_mutex);
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
__rfkill_switch_all(type, state);
|
||||
mutex_unlock(&rfkill_mutex);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(rfkill_switch_all);
|
||||
|
||||
@ -269,7 +278,7 @@ EXPORT_SYMBOL(rfkill_switch_all);
|
||||
* rfkill_epo - emergency power off all transmitters
|
||||
*
|
||||
* This kicks all non-suspended rfkill devices to RFKILL_STATE_SOFT_BLOCKED,
|
||||
* ignoring everything in its path but rfkill_mutex and rfkill->mutex.
|
||||
* ignoring everything in its path but rfkill_global_mutex and rfkill->mutex.
|
||||
*
|
||||
* The global state before the EPO is saved and can be restored later
|
||||
* using rfkill_restore_states().
|
||||
@ -279,7 +288,8 @@ void rfkill_epo(void)
|
||||
struct rfkill *rfkill;
|
||||
int i;
|
||||
|
||||
mutex_lock(&rfkill_mutex);
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
|
||||
list_for_each_entry(rfkill, &rfkill_list, node) {
|
||||
mutex_lock(&rfkill->mutex);
|
||||
rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1);
|
||||
@ -291,7 +301,7 @@ void rfkill_epo(void)
|
||||
rfkill_global_states[i].current_state =
|
||||
RFKILL_STATE_SOFT_BLOCKED;
|
||||
}
|
||||
mutex_unlock(&rfkill_mutex);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rfkill_epo);
|
||||
|
||||
@ -306,10 +316,11 @@ void rfkill_restore_states(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
mutex_lock(&rfkill_mutex);
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
|
||||
for (i = 0; i < RFKILL_TYPE_MAX; i++)
|
||||
__rfkill_switch_all(i, rfkill_global_states[i].default_state);
|
||||
mutex_unlock(&rfkill_mutex);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rfkill_restore_states);
|
||||
|
||||
@ -334,7 +345,11 @@ int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state)
|
||||
{
|
||||
enum rfkill_state oldstate;
|
||||
|
||||
if (unlikely(state >= RFKILL_STATE_MAX))
|
||||
BUG_ON(!rfkill);
|
||||
if (WARN((state >= RFKILL_STATE_MAX),
|
||||
KERN_WARNING
|
||||
"rfkill: illegal state %d passed as parameter "
|
||||
"to rfkill_force_state\n", state))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&rfkill->mutex);
|
||||
@ -402,12 +417,16 @@ static ssize_t rfkill_state_store(struct device *dev,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
unsigned int state = simple_strtoul(buf, NULL, 0);
|
||||
unsigned long state;
|
||||
int error;
|
||||
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
error = strict_strtoul(buf, 0, &state);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* RFKILL_STATE_HARD_BLOCKED is illegal here... */
|
||||
if (state != RFKILL_STATE_UNBLOCKED &&
|
||||
state != RFKILL_STATE_SOFT_BLOCKED)
|
||||
@ -427,7 +446,7 @@ static ssize_t rfkill_claim_show(struct device *dev,
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
|
||||
return sprintf(buf, "%d", rfkill->user_claim);
|
||||
return sprintf(buf, "%d\n", rfkill->user_claim);
|
||||
}
|
||||
|
||||
static ssize_t rfkill_claim_store(struct device *dev,
|
||||
@ -435,7 +454,8 @@ static ssize_t rfkill_claim_store(struct device *dev,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
bool claim = !!simple_strtoul(buf, NULL, 0);
|
||||
unsigned long claim_tmp;
|
||||
bool claim;
|
||||
int error;
|
||||
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
@ -444,11 +464,16 @@ static ssize_t rfkill_claim_store(struct device *dev,
|
||||
if (rfkill->user_claim_unsupported)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
error = strict_strtoul(buf, 0, &claim_tmp);
|
||||
if (error)
|
||||
return error;
|
||||
claim = !!claim_tmp;
|
||||
|
||||
/*
|
||||
* Take the global lock to make sure the kernel is not in
|
||||
* the middle of rfkill_switch_all
|
||||
*/
|
||||
error = mutex_lock_interruptible(&rfkill_mutex);
|
||||
error = mutex_lock_interruptible(&rfkill_global_mutex);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -463,7 +488,7 @@ static ssize_t rfkill_claim_store(struct device *dev,
|
||||
rfkill->user_claim = claim;
|
||||
}
|
||||
|
||||
mutex_unlock(&rfkill_mutex);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
|
||||
return error ? error : count;
|
||||
}
|
||||
@ -583,10 +608,10 @@ static int rfkill_check_duplicity(const struct rfkill *rfkill)
|
||||
memset(seen, 0, sizeof(seen));
|
||||
|
||||
list_for_each_entry(p, &rfkill_list, node) {
|
||||
if (p == rfkill) {
|
||||
WARN_ON(1);
|
||||
if (WARN((p == rfkill), KERN_WARNING
|
||||
"rfkill: illegal attempt to register "
|
||||
"an already registered rfkill struct\n"))
|
||||
return -EEXIST;
|
||||
}
|
||||
set_bit(p->type, seen);
|
||||
}
|
||||
|
||||
@ -598,7 +623,7 @@ static int rfkill_add_switch(struct rfkill *rfkill)
|
||||
{
|
||||
int error;
|
||||
|
||||
mutex_lock(&rfkill_mutex);
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
|
||||
error = rfkill_check_duplicity(rfkill);
|
||||
if (error < 0)
|
||||
@ -619,16 +644,16 @@ static int rfkill_add_switch(struct rfkill *rfkill)
|
||||
|
||||
error = 0;
|
||||
unlock_out:
|
||||
mutex_unlock(&rfkill_mutex);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void rfkill_remove_switch(struct rfkill *rfkill)
|
||||
{
|
||||
mutex_lock(&rfkill_mutex);
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
list_del_init(&rfkill->node);
|
||||
mutex_unlock(&rfkill_mutex);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
|
||||
mutex_lock(&rfkill->mutex);
|
||||
rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1);
|
||||
@ -654,6 +679,12 @@ struct rfkill * __must_check rfkill_allocate(struct device *parent,
|
||||
struct rfkill *rfkill;
|
||||
struct device *dev;
|
||||
|
||||
if (WARN((type >= RFKILL_TYPE_MAX),
|
||||
KERN_WARNING
|
||||
"rfkill: illegal type %d passed as parameter "
|
||||
"to rfkill_allocate\n", type))
|
||||
return NULL;
|
||||
|
||||
rfkill = kzalloc(sizeof(struct rfkill), GFP_KERNEL);
|
||||
if (!rfkill)
|
||||
return NULL;
|
||||
@ -726,11 +757,12 @@ int __must_check rfkill_register(struct rfkill *rfkill)
|
||||
struct device *dev = &rfkill->dev;
|
||||
int error;
|
||||
|
||||
if (!rfkill->toggle_radio)
|
||||
return -EINVAL;
|
||||
if (rfkill->type >= RFKILL_TYPE_MAX)
|
||||
return -EINVAL;
|
||||
if (rfkill->state >= RFKILL_STATE_MAX)
|
||||
if (WARN((!rfkill || !rfkill->toggle_radio ||
|
||||
rfkill->type >= RFKILL_TYPE_MAX ||
|
||||
rfkill->state >= RFKILL_STATE_MAX),
|
||||
KERN_WARNING
|
||||
"rfkill: attempt to register a "
|
||||
"badly initialized rfkill struct\n"))
|
||||
return -EINVAL;
|
||||
|
||||
snprintf(dev->bus_id, sizeof(dev->bus_id),
|
||||
@ -765,6 +797,7 @@ EXPORT_SYMBOL(rfkill_register);
|
||||
*/
|
||||
void rfkill_unregister(struct rfkill *rfkill)
|
||||
{
|
||||
BUG_ON(!rfkill);
|
||||
device_del(&rfkill->dev);
|
||||
rfkill_remove_switch(rfkill);
|
||||
rfkill_led_trigger_unregister(rfkill);
|
||||
@ -801,12 +834,15 @@ int rfkill_set_default(enum rfkill_type type, enum rfkill_state state)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (type >= RFKILL_TYPE_MAX ||
|
||||
if (WARN((type >= RFKILL_TYPE_MAX ||
|
||||
(state != RFKILL_STATE_SOFT_BLOCKED &&
|
||||
state != RFKILL_STATE_UNBLOCKED))
|
||||
state != RFKILL_STATE_UNBLOCKED)),
|
||||
KERN_WARNING
|
||||
"rfkill: illegal state %d or type %d passed as "
|
||||
"parameter to rfkill_set_default\n", state, type))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&rfkill_mutex);
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
|
||||
if (!test_and_set_bit(type, rfkill_states_lockdflt)) {
|
||||
rfkill_global_states[type].default_state = state;
|
||||
@ -814,7 +850,7 @@ int rfkill_set_default(enum rfkill_type type, enum rfkill_state state)
|
||||
} else
|
||||
error = -EPERM;
|
||||
|
||||
mutex_unlock(&rfkill_mutex);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rfkill_set_default);
|
||||
|
@ -87,6 +87,13 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
|
||||
[NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
|
||||
.len = IEEE80211_MAX_MESH_ID_LEN },
|
||||
[NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
|
||||
|
||||
[NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 },
|
||||
[NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
|
||||
[NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
|
||||
|
||||
[NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY,
|
||||
.len = NL80211_HT_CAPABILITY_LEN },
|
||||
};
|
||||
|
||||
/* message building helper */
|
||||
@ -1125,6 +1132,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
|
||||
params.listen_interval =
|
||||
nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
|
||||
params.ht_capa =
|
||||
nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
|
||||
|
||||
if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
|
||||
¶ms.station_flags))
|
||||
return -EINVAL;
|
||||
@ -1188,6 +1199,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
|
||||
params.listen_interval =
|
||||
nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
|
||||
params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
|
||||
if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
|
||||
params.ht_capa =
|
||||
nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
|
||||
|
||||
if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
|
||||
¶ms.station_flags))
|
||||
@ -1525,6 +1539,48 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *drv;
|
||||
int err;
|
||||
struct net_device *dev;
|
||||
struct bss_parameters params;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
/* default to not changing parameters */
|
||||
params.use_cts_prot = -1;
|
||||
params.use_short_preamble = -1;
|
||||
params.use_short_slot_time = -1;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_BSS_CTS_PROT])
|
||||
params.use_cts_prot =
|
||||
nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]);
|
||||
if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE])
|
||||
params.use_short_preamble =
|
||||
nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]);
|
||||
if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME])
|
||||
params.use_short_slot_time =
|
||||
nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]);
|
||||
|
||||
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!drv->ops->change_bss) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
err = drv->ops->change_bss(&drv->wiphy, dev, ¶ms);
|
||||
rtnl_unlock();
|
||||
|
||||
out:
|
||||
cfg80211_put_dev(drv);
|
||||
dev_put(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct genl_ops nl80211_ops[] = {
|
||||
{
|
||||
.cmd = NL80211_CMD_GET_WIPHY,
|
||||
@ -1656,6 +1712,12 @@ static struct genl_ops nl80211_ops[] = {
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_SET_BSS,
|
||||
.doit = nl80211_set_bss,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
},
|
||||
};
|
||||
|
||||
/* multicast groups */
|
||||
|
Loading…
x
Reference in New Issue
Block a user