mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
John W. Linville says: ==================== Please pull this batch of fixes intended for the 3.10 stream... Regarding the NFC bits, Samuel says: "This is the first batch of NFC fixes for 3.10, and it contains: - 3 fixes for the NFC MEI support: * We now depend on the correct Kconfig symbol. * We register an MEI event callback whenever we enable an NFC device, otherwise we fail to read anything after an enable/disable cycle. * We only disable an MEI device from its disable mey_phy_ops, preventing useless consecutive disable calls. - An NFC Makefile cleanup, as I forgot to remove a commented out line when moving the LLCP code to the NFC top level directory." As for the mac80211 bits, Johannes says: "This time I have a fix from Stanislaw for a stupid mistake I made in the auth/assoc timeout changes, a fix from Felix for 64-bit traffic counters and one from Helmut for address mask handling in mac80211. I also have a few fixes myself for four different crashes reported by a few people." And Johannes says this about the iwlwifi bit: "This fixes a brown paper-bag bug that we really should've caught in review. More details in the changelog for the fix." On top of that... Arend van Spriel and Hante Meuleman cooperate to send a series of AP and P2P mode fixes for brcmfmac. Gabor Juhos corrects a register offset for AR9550, avoiding a bus error. Dan Carpenter provides a fixup to some dmesg output in the atmel driver. And, finally... Felix Fietkau not only gives us a trio of small AR934x fixes, but also refactors the ath9k aggregation session start/stop handling (using the generic mac80211 support) in order to avoid a deadlock. Please let me know if there are problems! ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
fb68e2f438
27 changed files with 301 additions and 235 deletions
|
@ -68,13 +68,16 @@
|
|||
#define AR9300_BASE_ADDR 0x3ff
|
||||
#define AR9300_BASE_ADDR_512 0x1ff
|
||||
|
||||
#define AR9300_OTP_BASE (AR_SREV_9340(ah) ? 0x30000 : 0x14000)
|
||||
#define AR9300_OTP_STATUS (AR_SREV_9340(ah) ? 0x30018 : 0x15f18)
|
||||
#define AR9300_OTP_BASE \
|
||||
((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30000 : 0x14000)
|
||||
#define AR9300_OTP_STATUS \
|
||||
((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30018 : 0x15f18)
|
||||
#define AR9300_OTP_STATUS_TYPE 0x7
|
||||
#define AR9300_OTP_STATUS_VALID 0x4
|
||||
#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2
|
||||
#define AR9300_OTP_STATUS_SM_BUSY 0x1
|
||||
#define AR9300_OTP_READ_DATA (AR_SREV_9340(ah) ? 0x3001c : 0x15f1c)
|
||||
#define AR9300_OTP_READ_DATA \
|
||||
((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3001c : 0x15f1c)
|
||||
|
||||
enum targetPowerHTRates {
|
||||
HT_TARGET_RATE_0_8_16,
|
||||
|
|
|
@ -334,7 +334,8 @@ static void ar9003_hw_spur_ofdm(struct ath_hw *ah,
|
|||
REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
|
||||
AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 1);
|
||||
|
||||
if (REG_READ_FIELD(ah, AR_PHY_MODE,
|
||||
if (!AR_SREV_9340(ah) &&
|
||||
REG_READ_FIELD(ah, AR_PHY_MODE,
|
||||
AR_PHY_MODE_DYNAMIC) == 0x1)
|
||||
REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
|
||||
AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1);
|
||||
|
|
|
@ -251,10 +251,9 @@ struct ath_atx_tid {
|
|||
int tidno;
|
||||
int baw_head; /* first un-acked tx buffer */
|
||||
int baw_tail; /* next unused tx buffer slot */
|
||||
int sched;
|
||||
int paused;
|
||||
u8 state;
|
||||
bool stop_cb;
|
||||
bool sched;
|
||||
bool paused;
|
||||
bool active;
|
||||
};
|
||||
|
||||
struct ath_node {
|
||||
|
@ -275,10 +274,6 @@ struct ath_node {
|
|||
#endif
|
||||
};
|
||||
|
||||
#define AGGR_CLEANUP BIT(1)
|
||||
#define AGGR_ADDBA_COMPLETE BIT(2)
|
||||
#define AGGR_ADDBA_PROGRESS BIT(3)
|
||||
|
||||
struct ath_tx_control {
|
||||
struct ath_txq *txq;
|
||||
struct ath_node *an;
|
||||
|
@ -352,8 +347,7 @@ void ath_tx_tasklet(struct ath_softc *sc);
|
|||
void ath_tx_edma_tasklet(struct ath_softc *sc);
|
||||
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||
u16 tid, u16 *ssn);
|
||||
bool ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid,
|
||||
bool flush);
|
||||
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
|
||||
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
|
||||
|
||||
void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
|
||||
|
|
|
@ -1172,6 +1172,7 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan)
|
|||
static inline void ath9k_hw_set_dma(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int txbuf_size;
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
|
@ -1225,13 +1226,17 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)
|
|||
* So set the usable tx buf size also to half to
|
||||
* avoid data/delimiter underruns
|
||||
*/
|
||||
REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
|
||||
AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
|
||||
} else if (!AR_SREV_9271(ah)) {
|
||||
REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
|
||||
AR_PCU_TXBUF_CTRL_USABLE_SIZE);
|
||||
txbuf_size = AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE;
|
||||
} else if (AR_SREV_9340_13_OR_LATER(ah)) {
|
||||
/* Uses fewer entries for AR934x v1.3+ to prevent rx overruns */
|
||||
txbuf_size = AR_9340_PCU_TXBUF_CTRL_USABLE_SIZE;
|
||||
} else {
|
||||
txbuf_size = AR_PCU_TXBUF_CTRL_USABLE_SIZE;
|
||||
}
|
||||
|
||||
if (!AR_SREV_9271(ah))
|
||||
REG_WRITE(ah, AR_PCU_TXBUF_CTRL, txbuf_size);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
|
||||
if (AR_SREV_9300_20_OR_LATER(ah))
|
||||
|
@ -1306,9 +1311,13 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
|
|||
AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
|
||||
} else {
|
||||
tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
|
||||
if (tmpReg &
|
||||
(AR_INTR_SYNC_LOCAL_TIMEOUT |
|
||||
AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
|
||||
if (AR_SREV_9340(ah))
|
||||
tmpReg &= AR9340_INTR_SYNC_LOCAL_TIMEOUT;
|
||||
else
|
||||
tmpReg &= AR_INTR_SYNC_LOCAL_TIMEOUT |
|
||||
AR_INTR_SYNC_RADM_CPL_TIMEOUT;
|
||||
|
||||
if (tmpReg) {
|
||||
u32 val;
|
||||
REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
|
||||
|
||||
|
|
|
@ -410,7 +410,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
|
|||
|
||||
REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
|
||||
|
||||
if (AR_SREV_9340(ah))
|
||||
if (AR_SREV_9340(ah) && !AR_SREV_9340_13_OR_LATER(ah))
|
||||
REG_WRITE(ah, AR_DMISC(q),
|
||||
AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1);
|
||||
else
|
||||
|
|
|
@ -1709,7 +1709,8 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
|
|||
flush = true;
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
ath9k_ps_wakeup(sc);
|
||||
if (ath_tx_aggr_stop(sc, sta, tid, flush))
|
||||
ath_tx_aggr_stop(sc, sta, tid);
|
||||
if (!flush)
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
ath9k_ps_restore(sc);
|
||||
break;
|
||||
|
|
|
@ -1227,10 +1227,7 @@ static bool ath_tx_aggr_check(struct ath_softc *sc, struct ieee80211_sta *sta,
|
|||
return false;
|
||||
|
||||
txtid = ATH_AN_2_TID(an, tidno);
|
||||
|
||||
if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS)))
|
||||
return true;
|
||||
return false;
|
||||
return !txtid->active;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -798,6 +798,10 @@
|
|||
#define AR_SREV_REVISION_9485_10 0
|
||||
#define AR_SREV_REVISION_9485_11 1
|
||||
#define AR_SREV_VERSION_9340 0x300
|
||||
#define AR_SREV_REVISION_9340_10 0
|
||||
#define AR_SREV_REVISION_9340_11 1
|
||||
#define AR_SREV_REVISION_9340_12 2
|
||||
#define AR_SREV_REVISION_9340_13 3
|
||||
#define AR_SREV_VERSION_9580 0x1C0
|
||||
#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */
|
||||
#define AR_SREV_VERSION_9462 0x280
|
||||
|
@ -897,6 +901,10 @@
|
|||
#define AR_SREV_9340(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9340))
|
||||
|
||||
#define AR_SREV_9340_13_OR_LATER(_ah) \
|
||||
(AR_SREV_9340((_ah)) && \
|
||||
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9340_13))
|
||||
|
||||
#define AR_SREV_9285E_20(_ah) \
|
||||
(AR_SREV_9285_12_OR_LATER(_ah) && \
|
||||
((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
|
||||
|
@ -1007,6 +1015,8 @@ enum {
|
|||
AR_INTR_SYNC_LOCAL_TIMEOUT |
|
||||
AR_INTR_SYNC_MAC_SLEEP_ACCESS),
|
||||
|
||||
AR9340_INTR_SYNC_LOCAL_TIMEOUT = 0x00000010,
|
||||
|
||||
AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF,
|
||||
|
||||
};
|
||||
|
@ -1881,6 +1891,7 @@ enum {
|
|||
#define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF
|
||||
#define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700
|
||||
#define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380
|
||||
#define AR_9340_PCU_TXBUF_CTRL_USABLE_SIZE 0x500
|
||||
|
||||
#define AR_PCU_MISC_MODE2 0x8344
|
||||
#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002
|
||||
|
|
|
@ -125,24 +125,6 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
|
|||
list_add_tail(&ac->list, &txq->axq_acq);
|
||||
}
|
||||
|
||||
static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
{
|
||||
struct ath_txq *txq = tid->ac->txq;
|
||||
|
||||
WARN_ON(!tid->paused);
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
tid->paused = false;
|
||||
|
||||
if (skb_queue_empty(&tid->buf_q))
|
||||
goto unlock;
|
||||
|
||||
ath_tx_queue_tid(txq, tid);
|
||||
ath_txq_schedule(sc, txq);
|
||||
unlock:
|
||||
ath_txq_unlock_complete(sc, txq);
|
||||
}
|
||||
|
||||
static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
|
@ -164,20 +146,7 @@ static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
|||
ARRAY_SIZE(bf->rates));
|
||||
}
|
||||
|
||||
static void ath_tx_clear_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
{
|
||||
tid->state &= ~AGGR_ADDBA_COMPLETE;
|
||||
tid->state &= ~AGGR_CLEANUP;
|
||||
if (!tid->stop_cb)
|
||||
return;
|
||||
|
||||
ieee80211_start_tx_ba_cb_irqsafe(tid->an->vif, tid->an->sta->addr,
|
||||
tid->tidno);
|
||||
tid->stop_cb = false;
|
||||
}
|
||||
|
||||
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid,
|
||||
bool flush_packets)
|
||||
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
{
|
||||
struct ath_txq *txq = tid->ac->txq;
|
||||
struct sk_buff *skb;
|
||||
|
@ -194,15 +163,16 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid,
|
|||
while ((skb = __skb_dequeue(&tid->buf_q))) {
|
||||
fi = get_frame_info(skb);
|
||||
bf = fi->bf;
|
||||
if (!bf && !flush_packets)
|
||||
bf = ath_tx_setup_buffer(sc, txq, tid, skb);
|
||||
|
||||
if (!bf) {
|
||||
ieee80211_free_txskb(sc->hw, skb);
|
||||
continue;
|
||||
bf = ath_tx_setup_buffer(sc, txq, tid, skb);
|
||||
if (!bf) {
|
||||
ieee80211_free_txskb(sc->hw, skb);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (fi->retries || flush_packets) {
|
||||
if (fi->retries) {
|
||||
list_add_tail(&bf->list, &bf_head);
|
||||
ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
|
||||
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
|
||||
|
@ -213,10 +183,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid,
|
|||
}
|
||||
}
|
||||
|
||||
if (tid->baw_head == tid->baw_tail)
|
||||
ath_tx_clear_tid(sc, tid);
|
||||
|
||||
if (sendbar && !flush_packets) {
|
||||
if (sendbar) {
|
||||
ath_txq_unlock(sc, txq);
|
||||
ath_send_bar(tid, tid->seq_start);
|
||||
ath_txq_lock(sc, txq);
|
||||
|
@ -499,19 +466,19 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
|||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
fi = get_frame_info(skb);
|
||||
|
||||
if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) {
|
||||
if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
|
||||
/*
|
||||
* Outside of the current BlockAck window,
|
||||
* maybe part of a previous session
|
||||
*/
|
||||
txfail = 1;
|
||||
} else if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) {
|
||||
/* transmit completion, subframe is
|
||||
* acked by block ack */
|
||||
acked_cnt++;
|
||||
} else if (!isaggr && txok) {
|
||||
/* transmit completion */
|
||||
acked_cnt++;
|
||||
} else if (tid->state & AGGR_CLEANUP) {
|
||||
/*
|
||||
* cleanup in progress, just fail
|
||||
* the un-acked sub-frames
|
||||
*/
|
||||
txfail = 1;
|
||||
} else if (flush) {
|
||||
txpending = 1;
|
||||
} else if (fi->retries < ATH_MAX_SW_RETRIES) {
|
||||
|
@ -535,7 +502,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
|||
if (bf_next != NULL || !bf_last->bf_stale)
|
||||
list_move_tail(&bf->list, &bf_head);
|
||||
|
||||
if (!txpending || (tid->state & AGGR_CLEANUP)) {
|
||||
if (!txpending) {
|
||||
/*
|
||||
* complete the acked-ones/xretried ones; update
|
||||
* block-ack window
|
||||
|
@ -609,9 +576,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
|||
ath_txq_lock(sc, txq);
|
||||
}
|
||||
|
||||
if (tid->state & AGGR_CLEANUP)
|
||||
ath_tx_flush_tid(sc, tid, false);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
if (needreset)
|
||||
|
@ -1244,9 +1208,6 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
|||
an = (struct ath_node *)sta->drv_priv;
|
||||
txtid = ATH_AN_2_TID(an, tid);
|
||||
|
||||
if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
|
||||
return -EAGAIN;
|
||||
|
||||
/* update ampdu factor/density, they may have changed. This may happen
|
||||
* in HT IBSS when a beacon with HT-info is received after the station
|
||||
* has already been added.
|
||||
|
@ -1258,7 +1219,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
|||
an->mpdudensity = density;
|
||||
}
|
||||
|
||||
txtid->state |= AGGR_ADDBA_PROGRESS;
|
||||
txtid->active = true;
|
||||
txtid->paused = true;
|
||||
*ssn = txtid->seq_start = txtid->seq_next;
|
||||
txtid->bar_index = -1;
|
||||
|
@ -1269,45 +1230,17 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid,
|
||||
bool flush)
|
||||
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
|
||||
{
|
||||
struct ath_node *an = (struct ath_node *)sta->drv_priv;
|
||||
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
|
||||
struct ath_txq *txq = txtid->ac->txq;
|
||||
bool ret = !flush;
|
||||
|
||||
if (flush)
|
||||
txtid->stop_cb = false;
|
||||
|
||||
if (txtid->state & AGGR_CLEANUP)
|
||||
return false;
|
||||
|
||||
if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
|
||||
txtid->state &= ~AGGR_ADDBA_PROGRESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
txtid->active = false;
|
||||
txtid->paused = true;
|
||||
|
||||
/*
|
||||
* If frames are still being transmitted for this TID, they will be
|
||||
* cleaned up during tx completion. To prevent race conditions, this
|
||||
* TID can only be reused after all in-progress subframes have been
|
||||
* completed.
|
||||
*/
|
||||
if (txtid->baw_head != txtid->baw_tail) {
|
||||
txtid->state |= AGGR_CLEANUP;
|
||||
ret = false;
|
||||
txtid->stop_cb = !flush;
|
||||
} else {
|
||||
txtid->state &= ~AGGR_ADDBA_COMPLETE;
|
||||
}
|
||||
|
||||
ath_tx_flush_tid(sc, txtid, flush);
|
||||
ath_tx_flush_tid(sc, txtid);
|
||||
ath_txq_unlock_complete(sc, txq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
|
||||
|
@ -1371,18 +1304,28 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
|
|||
}
|
||||
}
|
||||
|
||||
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
|
||||
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||
u16 tidno)
|
||||
{
|
||||
struct ath_atx_tid *txtid;
|
||||
struct ath_atx_tid *tid;
|
||||
struct ath_node *an;
|
||||
struct ath_txq *txq;
|
||||
|
||||
an = (struct ath_node *)sta->drv_priv;
|
||||
tid = ATH_AN_2_TID(an, tidno);
|
||||
txq = tid->ac->txq;
|
||||
|
||||
txtid = ATH_AN_2_TID(an, tid);
|
||||
txtid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
|
||||
txtid->state |= AGGR_ADDBA_COMPLETE;
|
||||
txtid->state &= ~AGGR_ADDBA_PROGRESS;
|
||||
ath_tx_resume_tid(sc, txtid);
|
||||
ath_txq_lock(sc, txq);
|
||||
|
||||
tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
|
||||
tid->paused = false;
|
||||
|
||||
if (!skb_queue_empty(&tid->buf_q)) {
|
||||
ath_tx_queue_tid(txq, tid);
|
||||
ath_txq_schedule(sc, txq);
|
||||
}
|
||||
|
||||
ath_txq_unlock_complete(sc, txq);
|
||||
}
|
||||
|
||||
/********************/
|
||||
|
@ -2431,13 +2374,10 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
|
|||
tid->baw_head = tid->baw_tail = 0;
|
||||
tid->sched = false;
|
||||
tid->paused = false;
|
||||
tid->state &= ~AGGR_CLEANUP;
|
||||
tid->active = false;
|
||||
__skb_queue_head_init(&tid->buf_q);
|
||||
acno = TID_TO_WME_AC(tidno);
|
||||
tid->ac = &an->ac[acno];
|
||||
tid->state &= ~AGGR_ADDBA_COMPLETE;
|
||||
tid->state &= ~AGGR_ADDBA_PROGRESS;
|
||||
tid->stop_cb = false;
|
||||
}
|
||||
|
||||
for (acno = 0, ac = &an->ac[acno];
|
||||
|
@ -2474,7 +2414,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
|
|||
}
|
||||
|
||||
ath_tid_drain(sc, txq, tid);
|
||||
ath_tx_clear_tid(sc, tid);
|
||||
tid->active = false;
|
||||
|
||||
ath_txq_unlock(sc, txq);
|
||||
}
|
||||
|
|
|
@ -1624,7 +1624,7 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
|
|||
|
||||
netif_carrier_off(dev);
|
||||
|
||||
if (!proc_create_data("driver/atmel", 0, NULL, &atmel_proc_fops, priv));
|
||||
if (!proc_create_data("driver/atmel", 0, NULL, &atmel_proc_fops, priv))
|
||||
printk(KERN_WARNING "atmel: unable to create /proc entry.\n");
|
||||
|
||||
printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %pM\n",
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "tracepoint.h"
|
||||
|
||||
#define PKTFILTER_BUF_SIZE 128
|
||||
#define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */
|
||||
#define BRCMF_DEFAULT_BCN_TIMEOUT 3
|
||||
#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
|
||||
#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
|
||||
|
@ -338,23 +337,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Try to set and enable ARP offload feature, this may fail */
|
||||
err = brcmf_fil_iovar_int_set(ifp, "arp_ol", BRCMF_ARPOL_MODE);
|
||||
if (err) {
|
||||
brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
|
||||
BRCMF_ARPOL_MODE, err);
|
||||
err = 0;
|
||||
} else {
|
||||
err = brcmf_fil_iovar_int_set(ifp, "arpoe", 1);
|
||||
if (err) {
|
||||
brcmf_dbg(TRACE, "failed to enable ARP offload err = %d\n",
|
||||
err);
|
||||
err = 0;
|
||||
} else
|
||||
brcmf_dbg(TRACE, "successfully enabled ARP offload to 0x%x\n",
|
||||
BRCMF_ARPOL_MODE);
|
||||
}
|
||||
|
||||
/* Setup packet filter */
|
||||
brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER);
|
||||
brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER,
|
||||
|
|
|
@ -653,10 +653,13 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
|
|||
|
||||
brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
|
||||
|
||||
ndev->destructor = free_netdev;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
drvr->iflist[ifp->bssidx] = NULL;
|
||||
ndev->netdev_ops = NULL;
|
||||
free_netdev(ndev);
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
|
@ -720,6 +723,9 @@ static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
ifp->drvr->iflist[ifp->bssidx] = NULL;
|
||||
ndev->netdev_ops = NULL;
|
||||
free_netdev(ndev);
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
|
@ -788,6 +794,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
|
|||
struct brcmf_if *ifp;
|
||||
|
||||
ifp = drvr->iflist[bssidx];
|
||||
drvr->iflist[bssidx] = NULL;
|
||||
if (!ifp) {
|
||||
brcmf_err("Null interface, idx=%d\n", bssidx);
|
||||
return;
|
||||
|
@ -808,15 +815,13 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
|
|||
cancel_work_sync(&ifp->setmacaddr_work);
|
||||
cancel_work_sync(&ifp->multicast_work);
|
||||
}
|
||||
|
||||
/* unregister will take care of freeing it */
|
||||
unregister_netdev(ifp->ndev);
|
||||
if (bssidx == 0)
|
||||
brcmf_cfg80211_detach(drvr->config);
|
||||
free_netdev(ifp->ndev);
|
||||
} else {
|
||||
kfree(ifp);
|
||||
}
|
||||
drvr->iflist[bssidx] = NULL;
|
||||
}
|
||||
|
||||
int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
||||
|
@ -925,8 +930,6 @@ int brcmf_bus_start(struct device *dev)
|
|||
brcmf_fws_del_interface(ifp);
|
||||
brcmf_fws_deinit(drvr);
|
||||
}
|
||||
free_netdev(ifp->ndev);
|
||||
drvr->iflist[0] = NULL;
|
||||
if (p2p_ifp) {
|
||||
free_netdev(p2p_ifp->ndev);
|
||||
drvr->iflist[1] = NULL;
|
||||
|
@ -934,7 +937,8 @@ int brcmf_bus_start(struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
if ((brcmf_p2p_enable) && (p2p_ifp))
|
||||
brcmf_net_p2p_attach(p2p_ifp);
|
||||
if (brcmf_net_p2p_attach(p2p_ifp) < 0)
|
||||
brcmf_p2p_enable = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -202,7 +202,8 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
|
|||
return;
|
||||
brcmf_fws_add_interface(ifp);
|
||||
if (!drvr->fweh.evt_handler[BRCMF_E_IF])
|
||||
err = brcmf_net_attach(ifp, false);
|
||||
if (brcmf_net_attach(ifp, false) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ifevent->action == BRCMF_E_IF_CHANGE)
|
||||
|
|
|
@ -23,6 +23,12 @@
|
|||
|
||||
#define BRCMF_FIL_ACTION_FRAME_SIZE 1800
|
||||
|
||||
/* ARP Offload feature flags for arp_ol iovar */
|
||||
#define BRCMF_ARP_OL_AGENT 0x00000001
|
||||
#define BRCMF_ARP_OL_SNOOP 0x00000002
|
||||
#define BRCMF_ARP_OL_HOST_AUTO_REPLY 0x00000004
|
||||
#define BRCMF_ARP_OL_PEER_AUTO_REPLY 0x00000008
|
||||
|
||||
|
||||
enum brcmf_fil_p2p_if_types {
|
||||
BRCMF_FIL_P2P_IF_CLIENT,
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#define IS_P2P_SOCIAL_CHANNEL(channel) ((channel == SOCIAL_CHAN_1) || \
|
||||
(channel == SOCIAL_CHAN_2) || \
|
||||
(channel == SOCIAL_CHAN_3))
|
||||
#define BRCMF_P2P_TEMP_CHAN SOCIAL_CHAN_3
|
||||
#define SOCIAL_CHAN_CNT 3
|
||||
#define AF_PEER_SEARCH_CNT 2
|
||||
|
||||
|
@ -1954,21 +1955,21 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
|
|||
err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
|
||||
if (err < 0) {
|
||||
brcmf_err("set p2p_disc error\n");
|
||||
brcmf_free_vif(p2p_vif);
|
||||
brcmf_free_vif(cfg, p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
/* obtain bsscfg index for P2P discovery */
|
||||
err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
|
||||
if (err < 0) {
|
||||
brcmf_err("retrieving discover bsscfg index failed\n");
|
||||
brcmf_free_vif(p2p_vif);
|
||||
brcmf_free_vif(cfg, p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
/* Verify that firmware uses same bssidx as driver !! */
|
||||
if (p2p_ifp->bssidx != bssidx) {
|
||||
brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
|
||||
bssidx, p2p_ifp->bssidx);
|
||||
brcmf_free_vif(p2p_vif);
|
||||
brcmf_free_vif(cfg, p2p_vif);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1996,7 +1997,7 @@ void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
|
|||
brcmf_p2p_cancel_remain_on_channel(vif->ifp);
|
||||
brcmf_p2p_deinit_discovery(p2p);
|
||||
/* remove discovery interface */
|
||||
brcmf_free_vif(vif);
|
||||
brcmf_free_vif(p2p->cfg, vif);
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
||||
}
|
||||
/* just set it all to zero */
|
||||
|
@ -2013,17 +2014,30 @@ static void brcmf_p2p_get_current_chanspec(struct brcmf_p2p_info *p2p,
|
|||
u16 *chanspec)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_fil_chan_info_le ci;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
struct brcmu_chan ch;
|
||||
s32 err;
|
||||
struct brcmf_bss_info_le *bi;
|
||||
u8 *buf;
|
||||
|
||||
ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
|
||||
|
||||
ch.chnum = 11;
|
||||
|
||||
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, &ci, sizeof(ci));
|
||||
if (!err)
|
||||
ch.chnum = le32_to_cpu(ci.hw_channel);
|
||||
if (brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSSID, mac_addr,
|
||||
ETH_ALEN) == 0) {
|
||||
buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
|
||||
if (buf != NULL) {
|
||||
*(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
|
||||
if (brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
|
||||
buf, WL_BSS_INFO_MAX) == 0) {
|
||||
bi = (struct brcmf_bss_info_le *)(buf + 4);
|
||||
*chanspec = le16_to_cpu(bi->chanspec);
|
||||
kfree(buf);
|
||||
return;
|
||||
}
|
||||
kfree(buf);
|
||||
}
|
||||
}
|
||||
/* Use default channel for P2P */
|
||||
ch.chnum = BRCMF_P2P_TEMP_CHAN;
|
||||
ch.bw = BRCMU_CHAN_BW_20;
|
||||
p2p->cfg->d11inf.encchspec(&ch);
|
||||
*chanspec = ch.chspec;
|
||||
|
@ -2208,7 +2222,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
|
|||
return &p2p_vif->wdev;
|
||||
|
||||
fail:
|
||||
brcmf_free_vif(p2p_vif);
|
||||
brcmf_free_vif(p2p->cfg, p2p_vif);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
|
@ -2217,13 +2231,31 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
|
|||
*
|
||||
* @vif: virtual interface object to delete.
|
||||
*/
|
||||
static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_vif *vif)
|
||||
static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_cfg80211_vif *vif)
|
||||
{
|
||||
struct brcmf_p2p_info *p2p = &vif->ifp->drvr->config->p2p;
|
||||
|
||||
cfg80211_unregister_wdev(&vif->wdev);
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
||||
brcmf_free_vif(vif);
|
||||
cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
||||
brcmf_free_vif(cfg, vif);
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_p2p_free_p2p_if() - free up net device related data.
|
||||
*
|
||||
* @ndev: net device that needs to be freed.
|
||||
*/
|
||||
static void brcmf_p2p_free_p2p_if(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg;
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
ifp = netdev_priv(ndev);
|
||||
cfg = ifp->drvr->config;
|
||||
vif = ifp->vif;
|
||||
|
||||
brcmf_free_vif(cfg, vif);
|
||||
free_netdev(ifp->ndev);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2303,6 +2335,9 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
|
|||
brcmf_err("Registering netdevice failed\n");
|
||||
goto fail;
|
||||
}
|
||||
/* override destructor */
|
||||
ifp->ndev->destructor = brcmf_p2p_free_p2p_if;
|
||||
|
||||
cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif;
|
||||
/* Disable firmware roaming for P2P interface */
|
||||
brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
|
||||
|
@ -2314,7 +2349,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
|
|||
return &ifp->vif->wdev;
|
||||
|
||||
fail:
|
||||
brcmf_free_vif(vif);
|
||||
brcmf_free_vif(cfg, vif);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
|
@ -2350,7 +2385,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
|
|||
break;
|
||||
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
brcmf_p2p_delete_p2pdev(vif);
|
||||
brcmf_p2p_delete_p2pdev(cfg, vif);
|
||||
return 0;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
|
@ -2378,7 +2413,6 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
|
|||
err = 0;
|
||||
}
|
||||
brcmf_cfg80211_arm_vif_event(cfg, NULL);
|
||||
brcmf_free_vif(vif);
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
|
||||
|
||||
return err;
|
||||
|
|
|
@ -459,6 +459,38 @@ send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key)
|
|||
return err;
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_configure_arp_offload(struct brcmf_if *ifp, bool enable)
|
||||
{
|
||||
s32 err;
|
||||
u32 mode;
|
||||
|
||||
if (enable)
|
||||
mode = BRCMF_ARP_OL_AGENT | BRCMF_ARP_OL_PEER_AUTO_REPLY;
|
||||
else
|
||||
mode = 0;
|
||||
|
||||
/* Try to set and enable ARP offload feature, this may fail, then it */
|
||||
/* is simply not supported and err 0 will be returned */
|
||||
err = brcmf_fil_iovar_int_set(ifp, "arp_ol", mode);
|
||||
if (err) {
|
||||
brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
|
||||
mode, err);
|
||||
err = 0;
|
||||
} else {
|
||||
err = brcmf_fil_iovar_int_set(ifp, "arpoe", enable);
|
||||
if (err) {
|
||||
brcmf_dbg(TRACE, "failed to configure (%d) ARP offload err = %d\n",
|
||||
enable, err);
|
||||
err = 0;
|
||||
} else
|
||||
brcmf_dbg(TRACE, "successfully configured (%d) ARP offload to 0x%x\n",
|
||||
enable, mode);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
|
||||
const char *name,
|
||||
enum nl80211_iftype type,
|
||||
|
@ -2216,6 +2248,11 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
|
|||
}
|
||||
|
||||
pm = enabled ? PM_FAST : PM_OFF;
|
||||
/* Do not enable the power save after assoc if it is a p2p interface */
|
||||
if (ifp->vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) {
|
||||
brcmf_dbg(INFO, "Do not enable power save for P2P clients\n");
|
||||
pm = PM_OFF;
|
||||
}
|
||||
brcmf_dbg(INFO, "power save %s\n", (pm ? "enabled" : "disabled"));
|
||||
|
||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm);
|
||||
|
@ -3639,11 +3676,29 @@ brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif,
|
|||
return err;
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_cfg80211_set_channel(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_if *ifp,
|
||||
struct ieee80211_channel *channel)
|
||||
{
|
||||
u16 chanspec;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "band=%d, center_freq=%d\n", channel->band,
|
||||
channel->center_freq);
|
||||
|
||||
chanspec = channel_to_chanspec(&cfg->d11inf, channel);
|
||||
err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
|
||||
struct cfg80211_ap_settings *settings)
|
||||
{
|
||||
s32 ie_offset;
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_tlv *ssid_ie;
|
||||
struct brcmf_ssid_le ssid_le;
|
||||
|
@ -3683,6 +3738,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
|
|||
}
|
||||
|
||||
brcmf_set_mpc(ifp, 0);
|
||||
brcmf_configure_arp_offload(ifp, false);
|
||||
|
||||
/* find the RSN_IE */
|
||||
rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
|
||||
|
@ -3713,6 +3769,12 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
|
|||
|
||||
brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
|
||||
|
||||
err = brcmf_cfg80211_set_channel(cfg, ifp, settings->chandef.chan);
|
||||
if (err < 0) {
|
||||
brcmf_err("Set Channel failed, %d\n", err);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (settings->beacon_interval) {
|
||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
|
||||
settings->beacon_interval);
|
||||
|
@ -3789,8 +3851,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
|
|||
set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
|
||||
|
||||
exit:
|
||||
if (err)
|
||||
if (err) {
|
||||
brcmf_set_mpc(ifp, 1);
|
||||
brcmf_configure_arp_offload(ifp, true);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -3831,6 +3895,7 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
|
|||
brcmf_err("bss_enable config failed %d\n", err);
|
||||
}
|
||||
brcmf_set_mpc(ifp, 1);
|
||||
brcmf_configure_arp_offload(ifp, true);
|
||||
set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
|
||||
clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
|
||||
|
||||
|
@ -4148,7 +4213,7 @@ static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
|
|||
static const struct ieee80211_iface_combination brcmf_iface_combos[] = {
|
||||
{
|
||||
.max_interfaces = BRCMF_IFACE_MAX_CNT,
|
||||
.num_different_channels = 1, /* no multi-channel for now */
|
||||
.num_different_channels = 2,
|
||||
.n_limits = ARRAY_SIZE(brcmf_iface_limits),
|
||||
.limits = brcmf_iface_limits
|
||||
}
|
||||
|
@ -4256,20 +4321,16 @@ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
|
|||
return vif;
|
||||
}
|
||||
|
||||
void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)
|
||||
void brcmf_free_vif(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_cfg80211_vif *vif)
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg;
|
||||
struct wiphy *wiphy;
|
||||
|
||||
wiphy = vif->wdev.wiphy;
|
||||
cfg = wiphy_priv(wiphy);
|
||||
list_del(&vif->list);
|
||||
cfg->vif_cnt--;
|
||||
|
||||
kfree(vif);
|
||||
if (!cfg->vif_cnt) {
|
||||
wiphy_unregister(wiphy);
|
||||
wiphy_free(wiphy);
|
||||
wiphy_unregister(cfg->wiphy);
|
||||
wiphy_free(cfg->wiphy);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4646,7 +4707,6 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
|
|||
return 0;
|
||||
|
||||
case BRCMF_E_IF_DEL:
|
||||
ifp->vif = NULL;
|
||||
mutex_unlock(&event->vif_event_lock);
|
||||
/* event may not be upon user request */
|
||||
if (brcmf_cfg80211_vif_event_armed(cfg))
|
||||
|
@ -4852,8 +4912,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
|
|||
wl_deinit_priv(cfg);
|
||||
|
||||
cfg80211_attach_out:
|
||||
brcmf_free_vif(vif);
|
||||
wiphy_free(wiphy);
|
||||
brcmf_free_vif(cfg, vif);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -4865,7 +4924,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
|
|||
wl_deinit_priv(cfg);
|
||||
brcmf_btcoex_detach(cfg);
|
||||
list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
|
||||
brcmf_free_vif(vif);
|
||||
brcmf_free_vif(cfg, vif);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5229,6 +5288,8 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
|
|||
if (err)
|
||||
goto default_conf_out;
|
||||
|
||||
brcmf_configure_arp_offload(ifp, true);
|
||||
|
||||
cfg->dongle_up = true;
|
||||
default_conf_out:
|
||||
|
||||
|
|
|
@ -487,7 +487,8 @@ enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp);
|
|||
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
|
||||
enum nl80211_iftype type,
|
||||
bool pm_block);
|
||||
void brcmf_free_vif(struct brcmf_cfg80211_vif *vif);
|
||||
void brcmf_free_vif(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_cfg80211_vif *vif);
|
||||
|
||||
s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
|
||||
const u8 *vndr_ie_buf, u32 vndr_ie_len);
|
||||
|
|
|
@ -735,7 +735,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
|||
memcpy(&lq, priv->stations[i].lq,
|
||||
sizeof(struct iwl_link_quality_cmd));
|
||||
|
||||
if (!memcmp(&lq, &zero_lq, sizeof(lq)))
|
||||
if (memcmp(&lq, &zero_lq, sizeof(lq)))
|
||||
send_lq = true;
|
||||
}
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
|
|
@ -28,7 +28,7 @@ config NFC_WILINK
|
|||
|
||||
config NFC_MEI_PHY
|
||||
tristate "MEI bus NFC device support"
|
||||
depends on INTEL_MEI_BUS_NFC && NFC_HCI
|
||||
depends on INTEL_MEI && NFC_HCI
|
||||
help
|
||||
This adds support to use an mei bus nfc device. Select this if you
|
||||
will use an HCI NFC driver for an NFC chip connected behind an
|
||||
|
|
|
@ -64,6 +64,15 @@ int nfc_mei_phy_enable(void *phy_id)
|
|||
return r;
|
||||
}
|
||||
|
||||
r = mei_cl_register_event_cb(phy->device, nfc_mei_event_cb, phy);
|
||||
if (r) {
|
||||
pr_err("MEY_PHY: Event cb registration failed\n");
|
||||
mei_cl_disable_device(phy->device);
|
||||
phy->powered = 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
phy->powered = 1;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -43,24 +43,16 @@ static int microread_mei_probe(struct mei_cl_device *device,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = mei_cl_register_event_cb(device, nfc_mei_event_cb, phy);
|
||||
if (r) {
|
||||
pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
r = microread_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
|
||||
MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
|
||||
&phy->hdev);
|
||||
if (r < 0)
|
||||
goto err_out;
|
||||
if (r < 0) {
|
||||
nfc_mei_phy_free(phy);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
nfc_mei_phy_free(phy);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int microread_mei_remove(struct mei_cl_device *device)
|
||||
|
@ -71,8 +63,6 @@ static int microread_mei_remove(struct mei_cl_device *device)
|
|||
|
||||
microread_remove(phy->hdev);
|
||||
|
||||
nfc_mei_phy_disable(phy);
|
||||
|
||||
nfc_mei_phy_free(phy);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -43,24 +43,16 @@ static int pn544_mei_probe(struct mei_cl_device *device,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = mei_cl_register_event_cb(device, nfc_mei_event_cb, phy);
|
||||
if (r) {
|
||||
pr_err(PN544_DRIVER_NAME ": event cb registration failed\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
r = pn544_hci_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
|
||||
MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
|
||||
&phy->hdev);
|
||||
if (r < 0)
|
||||
goto err_out;
|
||||
if (r < 0) {
|
||||
nfc_mei_phy_free(phy);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
nfc_mei_phy_free(phy);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int pn544_mei_remove(struct mei_cl_device *device)
|
||||
|
@ -71,8 +63,6 @@ static int pn544_mei_remove(struct mei_cl_device *device)
|
|||
|
||||
pn544_hci_remove(phy->hdev);
|
||||
|
||||
nfc_mei_phy_disable(phy);
|
||||
|
||||
nfc_mei_phy_free(phy);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -159,9 +159,10 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
|
||||
static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_sub_if_data *iter;
|
||||
u64 new, mask, tmp;
|
||||
u8 *m;
|
||||
int ret = 0;
|
||||
|
@ -181,11 +182,14 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
|
|||
|
||||
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
|
||||
list_for_each_entry(iter, &local->interfaces, list) {
|
||||
if (iter == sdata)
|
||||
continue;
|
||||
|
||||
m = sdata->vif.addr;
|
||||
if (iter->vif.type == NL80211_IFTYPE_MONITOR)
|
||||
continue;
|
||||
|
||||
m = iter->vif.addr;
|
||||
tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
|
||||
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
|
||||
((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
|
||||
|
@ -209,7 +213,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
|
|||
if (ieee80211_sdata_running(sdata))
|
||||
return -EBUSY;
|
||||
|
||||
ret = ieee80211_verify_mac(sdata->local, sa->sa_data);
|
||||
ret = ieee80211_verify_mac(sdata, sa->sa_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -474,6 +478,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
|
|||
master->control_port_protocol;
|
||||
sdata->control_port_no_encrypt =
|
||||
master->control_port_no_encrypt;
|
||||
sdata->vif.cab_queue = master->vif.cab_queue;
|
||||
memcpy(sdata->vif.hw_queue, master->vif.hw_queue,
|
||||
sizeof(sdata->vif.hw_queue));
|
||||
break;
|
||||
}
|
||||
case NL80211_IFTYPE_AP:
|
||||
|
@ -653,7 +660,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
|
|||
|
||||
ieee80211_recalc_ps(local, -1);
|
||||
|
||||
if (dev) {
|
||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
|
||||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
|
||||
/* XXX: for AP_VLAN, actually track AP queues */
|
||||
netif_tx_start_all_queues(dev);
|
||||
} else if (dev) {
|
||||
unsigned long flags;
|
||||
int n_acs = IEEE80211_NUM_ACS;
|
||||
int ac;
|
||||
|
@ -1479,7 +1490,17 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
|
|||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick address of existing interface in case user changed
|
||||
* MAC address manually, default to perm_addr.
|
||||
*/
|
||||
m = local->hw.wiphy->perm_addr;
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
|
||||
continue;
|
||||
m = sdata->vif.addr;
|
||||
break;
|
||||
}
|
||||
start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
|
||||
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
|
||||
((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
|
||||
|
@ -1696,6 +1717,15 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
|
|||
|
||||
ASSERT_RTNL();
|
||||
|
||||
/*
|
||||
* Close all AP_VLAN interfaces first, as otherwise they
|
||||
* might be closed while the AP interface they belong to
|
||||
* is closed, causing unregister_netdevice_many() to crash.
|
||||
*/
|
||||
list_for_each_entry(sdata, &local->interfaces, list)
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
dev_close(sdata->dev);
|
||||
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
|
||||
list_del(&sdata->list);
|
||||
|
|
|
@ -3321,10 +3321,6 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
|
|||
if (WARN_ON_ONCE(!auth_data))
|
||||
return -EINVAL;
|
||||
|
||||
if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
|
||||
tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||
IEEE80211_TX_INTFL_MLME_CONN_TX;
|
||||
|
||||
auth_data->tries++;
|
||||
|
||||
if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) {
|
||||
|
@ -3358,6 +3354,10 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
|
|||
auth_data->expected_transaction = trans;
|
||||
}
|
||||
|
||||
if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
|
||||
tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||
IEEE80211_TX_INTFL_MLME_CONN_TX;
|
||||
|
||||
ieee80211_send_auth(sdata, trans, auth_data->algorithm, status,
|
||||
auth_data->data, auth_data->data_len,
|
||||
auth_data->bss->bssid,
|
||||
|
@ -3381,12 +3381,12 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
|
|||
* will not answer to direct packet in unassociated state.
|
||||
*/
|
||||
ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
|
||||
NULL, 0, (u32) -1, true, tx_flags,
|
||||
NULL, 0, (u32) -1, true, 0,
|
||||
auth_data->bss->channel, false);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
|
||||
if (tx_flags == 0) {
|
||||
auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
|
||||
ifmgd->auth_data->timeout_started = true;
|
||||
run_again(ifmgd, auth_data->timeout);
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
obj-$(CONFIG_NFC) += nfc.o
|
||||
obj-$(CONFIG_NFC_NCI) += nci/
|
||||
obj-$(CONFIG_NFC_HCI) += hci/
|
||||
#obj-$(CONFIG_NFC_LLCP) += llcp/
|
||||
|
||||
nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \
|
||||
llcp_sock.o
|
||||
|
|
|
@ -3411,7 +3411,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
(u32)sinfo->rx_bytes))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & (STATION_INFO_TX_BYTES |
|
||||
NL80211_STA_INFO_TX_BYTES64)) &&
|
||||
STATION_INFO_TX_BYTES64)) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
|
||||
(u32)sinfo->tx_bytes))
|
||||
goto nla_put_failure;
|
||||
|
|
|
@ -231,6 +231,9 @@ void cfg80211_conn_work(struct work_struct *work)
|
|||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
|
||||
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
||||
if (!wdev->netdev)
|
||||
continue;
|
||||
|
||||
wdev_lock(wdev);
|
||||
if (!netif_running(wdev->netdev)) {
|
||||
wdev_unlock(wdev);
|
||||
|
|
Loading…
Reference in a new issue