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
|
@ -68,13 +68,16 @@
|
||||||
#define AR9300_BASE_ADDR 0x3ff
|
#define AR9300_BASE_ADDR 0x3ff
|
||||||
#define AR9300_BASE_ADDR_512 0x1ff
|
#define AR9300_BASE_ADDR_512 0x1ff
|
||||||
|
|
||||||
#define AR9300_OTP_BASE (AR_SREV_9340(ah) ? 0x30000 : 0x14000)
|
#define AR9300_OTP_BASE \
|
||||||
#define AR9300_OTP_STATUS (AR_SREV_9340(ah) ? 0x30018 : 0x15f18)
|
((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_TYPE 0x7
|
||||||
#define AR9300_OTP_STATUS_VALID 0x4
|
#define AR9300_OTP_STATUS_VALID 0x4
|
||||||
#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2
|
#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2
|
||||||
#define AR9300_OTP_STATUS_SM_BUSY 0x1
|
#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 {
|
enum targetPowerHTRates {
|
||||||
HT_TARGET_RATE_0_8_16,
|
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,
|
REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
|
||||||
AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 1);
|
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)
|
AR_PHY_MODE_DYNAMIC) == 0x1)
|
||||||
REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
|
REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
|
||||||
AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1);
|
AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1);
|
||||||
|
|
|
@ -251,10 +251,9 @@ struct ath_atx_tid {
|
||||||
int tidno;
|
int tidno;
|
||||||
int baw_head; /* first un-acked tx buffer */
|
int baw_head; /* first un-acked tx buffer */
|
||||||
int baw_tail; /* next unused tx buffer slot */
|
int baw_tail; /* next unused tx buffer slot */
|
||||||
int sched;
|
bool sched;
|
||||||
int paused;
|
bool paused;
|
||||||
u8 state;
|
bool active;
|
||||||
bool stop_cb;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ath_node {
|
struct ath_node {
|
||||||
|
@ -275,10 +274,6 @@ struct ath_node {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AGGR_CLEANUP BIT(1)
|
|
||||||
#define AGGR_ADDBA_COMPLETE BIT(2)
|
|
||||||
#define AGGR_ADDBA_PROGRESS BIT(3)
|
|
||||||
|
|
||||||
struct ath_tx_control {
|
struct ath_tx_control {
|
||||||
struct ath_txq *txq;
|
struct ath_txq *txq;
|
||||||
struct ath_node *an;
|
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);
|
void ath_tx_edma_tasklet(struct ath_softc *sc);
|
||||||
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||||
u16 tid, u16 *ssn);
|
u16 tid, u16 *ssn);
|
||||||
bool ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid,
|
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
|
||||||
bool flush);
|
|
||||||
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 tid);
|
||||||
|
|
||||||
void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
|
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)
|
static inline void ath9k_hw_set_dma(struct ath_hw *ah)
|
||||||
{
|
{
|
||||||
struct ath_common *common = ath9k_hw_common(ah);
|
struct ath_common *common = ath9k_hw_common(ah);
|
||||||
|
int txbuf_size;
|
||||||
|
|
||||||
ENABLE_REGWRITE_BUFFER(ah);
|
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
|
* So set the usable tx buf size also to half to
|
||||||
* avoid data/delimiter underruns
|
* avoid data/delimiter underruns
|
||||||
*/
|
*/
|
||||||
REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
|
txbuf_size = AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE;
|
||||||
AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
|
} else if (AR_SREV_9340_13_OR_LATER(ah)) {
|
||||||
} else if (!AR_SREV_9271(ah)) {
|
/* Uses fewer entries for AR934x v1.3+ to prevent rx overruns */
|
||||||
REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
|
txbuf_size = AR_9340_PCU_TXBUF_CTRL_USABLE_SIZE;
|
||||||
AR_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);
|
REGWRITE_BUFFER_FLUSH(ah);
|
||||||
|
|
||||||
if (AR_SREV_9300_20_OR_LATER(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;
|
AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
|
||||||
} else {
|
} else {
|
||||||
tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
|
tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
|
||||||
if (tmpReg &
|
if (AR_SREV_9340(ah))
|
||||||
(AR_INTR_SYNC_LOCAL_TIMEOUT |
|
tmpReg &= AR9340_INTR_SYNC_LOCAL_TIMEOUT;
|
||||||
AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
|
else
|
||||||
|
tmpReg &= AR_INTR_SYNC_LOCAL_TIMEOUT |
|
||||||
|
AR_INTR_SYNC_RADM_CPL_TIMEOUT;
|
||||||
|
|
||||||
|
if (tmpReg) {
|
||||||
u32 val;
|
u32 val;
|
||||||
REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
|
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);
|
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),
|
REG_WRITE(ah, AR_DMISC(q),
|
||||||
AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1);
|
AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1);
|
||||||
else
|
else
|
||||||
|
|
|
@ -1709,7 +1709,8 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
|
||||||
flush = true;
|
flush = true;
|
||||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||||
ath9k_ps_wakeup(sc);
|
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);
|
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||||
ath9k_ps_restore(sc);
|
ath9k_ps_restore(sc);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1227,10 +1227,7 @@ static bool ath_tx_aggr_check(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
txtid = ATH_AN_2_TID(an, tidno);
|
txtid = ATH_AN_2_TID(an, tidno);
|
||||||
|
return !txtid->active;
|
||||||
if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS)))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -798,6 +798,10 @@
|
||||||
#define AR_SREV_REVISION_9485_10 0
|
#define AR_SREV_REVISION_9485_10 0
|
||||||
#define AR_SREV_REVISION_9485_11 1
|
#define AR_SREV_REVISION_9485_11 1
|
||||||
#define AR_SREV_VERSION_9340 0x300
|
#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_VERSION_9580 0x1C0
|
||||||
#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */
|
#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */
|
||||||
#define AR_SREV_VERSION_9462 0x280
|
#define AR_SREV_VERSION_9462 0x280
|
||||||
|
@ -897,6 +901,10 @@
|
||||||
#define AR_SREV_9340(_ah) \
|
#define AR_SREV_9340(_ah) \
|
||||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9340))
|
(((_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) \
|
#define AR_SREV_9285E_20(_ah) \
|
||||||
(AR_SREV_9285_12_OR_LATER(_ah) && \
|
(AR_SREV_9285_12_OR_LATER(_ah) && \
|
||||||
((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
|
((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
|
||||||
|
@ -1007,6 +1015,8 @@ enum {
|
||||||
AR_INTR_SYNC_LOCAL_TIMEOUT |
|
AR_INTR_SYNC_LOCAL_TIMEOUT |
|
||||||
AR_INTR_SYNC_MAC_SLEEP_ACCESS),
|
AR_INTR_SYNC_MAC_SLEEP_ACCESS),
|
||||||
|
|
||||||
|
AR9340_INTR_SYNC_LOCAL_TIMEOUT = 0x00000010,
|
||||||
|
|
||||||
AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF,
|
AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1881,6 +1891,7 @@ enum {
|
||||||
#define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF
|
#define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF
|
||||||
#define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700
|
#define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700
|
||||||
#define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380
|
#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 0x8344
|
||||||
#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002
|
#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);
|
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)
|
static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(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));
|
ARRAY_SIZE(bf->rates));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath_tx_clear_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
static void ath_tx_flush_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)
|
|
||||||
{
|
{
|
||||||
struct ath_txq *txq = tid->ac->txq;
|
struct ath_txq *txq = tid->ac->txq;
|
||||||
struct sk_buff *skb;
|
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))) {
|
while ((skb = __skb_dequeue(&tid->buf_q))) {
|
||||||
fi = get_frame_info(skb);
|
fi = get_frame_info(skb);
|
||||||
bf = fi->bf;
|
bf = fi->bf;
|
||||||
if (!bf && !flush_packets)
|
|
||||||
bf = ath_tx_setup_buffer(sc, txq, tid, skb);
|
|
||||||
|
|
||||||
if (!bf) {
|
if (!bf) {
|
||||||
ieee80211_free_txskb(sc->hw, skb);
|
bf = ath_tx_setup_buffer(sc, txq, tid, skb);
|
||||||
continue;
|
if (!bf) {
|
||||||
|
ieee80211_free_txskb(sc->hw, skb);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fi->retries || flush_packets) {
|
if (fi->retries) {
|
||||||
list_add_tail(&bf->list, &bf_head);
|
list_add_tail(&bf->list, &bf_head);
|
||||||
ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
|
ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
|
||||||
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
|
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)
|
if (sendbar) {
|
||||||
ath_tx_clear_tid(sc, tid);
|
|
||||||
|
|
||||||
if (sendbar && !flush_packets) {
|
|
||||||
ath_txq_unlock(sc, txq);
|
ath_txq_unlock(sc, txq);
|
||||||
ath_send_bar(tid, tid->seq_start);
|
ath_send_bar(tid, tid->seq_start);
|
||||||
ath_txq_lock(sc, txq);
|
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);
|
tx_info = IEEE80211_SKB_CB(skb);
|
||||||
fi = get_frame_info(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
|
/* transmit completion, subframe is
|
||||||
* acked by block ack */
|
* acked by block ack */
|
||||||
acked_cnt++;
|
acked_cnt++;
|
||||||
} else if (!isaggr && txok) {
|
} else if (!isaggr && txok) {
|
||||||
/* transmit completion */
|
/* transmit completion */
|
||||||
acked_cnt++;
|
acked_cnt++;
|
||||||
} else if (tid->state & AGGR_CLEANUP) {
|
|
||||||
/*
|
|
||||||
* cleanup in progress, just fail
|
|
||||||
* the un-acked sub-frames
|
|
||||||
*/
|
|
||||||
txfail = 1;
|
|
||||||
} else if (flush) {
|
} else if (flush) {
|
||||||
txpending = 1;
|
txpending = 1;
|
||||||
} else if (fi->retries < ATH_MAX_SW_RETRIES) {
|
} 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)
|
if (bf_next != NULL || !bf_last->bf_stale)
|
||||||
list_move_tail(&bf->list, &bf_head);
|
list_move_tail(&bf->list, &bf_head);
|
||||||
|
|
||||||
if (!txpending || (tid->state & AGGR_CLEANUP)) {
|
if (!txpending) {
|
||||||
/*
|
/*
|
||||||
* complete the acked-ones/xretried ones; update
|
* complete the acked-ones/xretried ones; update
|
||||||
* block-ack window
|
* 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);
|
ath_txq_lock(sc, txq);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tid->state & AGGR_CLEANUP)
|
|
||||||
ath_tx_flush_tid(sc, tid, false);
|
|
||||||
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (needreset)
|
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;
|
an = (struct ath_node *)sta->drv_priv;
|
||||||
txtid = ATH_AN_2_TID(an, tid);
|
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
|
/* 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
|
* in HT IBSS when a beacon with HT-info is received after the station
|
||||||
* has already been added.
|
* has already been added.
|
||||||
|
@ -1258,7 +1219,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||||
an->mpdudensity = density;
|
an->mpdudensity = density;
|
||||||
}
|
}
|
||||||
|
|
||||||
txtid->state |= AGGR_ADDBA_PROGRESS;
|
txtid->active = true;
|
||||||
txtid->paused = true;
|
txtid->paused = true;
|
||||||
*ssn = txtid->seq_start = txtid->seq_next;
|
*ssn = txtid->seq_start = txtid->seq_next;
|
||||||
txtid->bar_index = -1;
|
txtid->bar_index = -1;
|
||||||
|
@ -1269,45 +1230,17 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid,
|
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
|
||||||
bool flush)
|
|
||||||
{
|
{
|
||||||
struct ath_node *an = (struct ath_node *)sta->drv_priv;
|
struct ath_node *an = (struct ath_node *)sta->drv_priv;
|
||||||
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
|
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
|
||||||
struct ath_txq *txq = txtid->ac->txq;
|
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);
|
ath_txq_lock(sc, txq);
|
||||||
|
txtid->active = false;
|
||||||
txtid->paused = true;
|
txtid->paused = true;
|
||||||
|
ath_tx_flush_tid(sc, txtid);
|
||||||
/*
|
|
||||||
* 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_txq_unlock_complete(sc, txq);
|
ath_txq_unlock_complete(sc, txq);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
|
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_node *an;
|
||||||
|
struct ath_txq *txq;
|
||||||
|
|
||||||
an = (struct ath_node *)sta->drv_priv;
|
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);
|
ath_txq_lock(sc, txq);
|
||||||
txtid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
|
|
||||||
txtid->state |= AGGR_ADDBA_COMPLETE;
|
tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
|
||||||
txtid->state &= ~AGGR_ADDBA_PROGRESS;
|
tid->paused = false;
|
||||||
ath_tx_resume_tid(sc, txtid);
|
|
||||||
|
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->baw_head = tid->baw_tail = 0;
|
||||||
tid->sched = false;
|
tid->sched = false;
|
||||||
tid->paused = false;
|
tid->paused = false;
|
||||||
tid->state &= ~AGGR_CLEANUP;
|
tid->active = false;
|
||||||
__skb_queue_head_init(&tid->buf_q);
|
__skb_queue_head_init(&tid->buf_q);
|
||||||
acno = TID_TO_WME_AC(tidno);
|
acno = TID_TO_WME_AC(tidno);
|
||||||
tid->ac = &an->ac[acno];
|
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];
|
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_tid_drain(sc, txq, tid);
|
||||||
ath_tx_clear_tid(sc, tid);
|
tid->active = false;
|
||||||
|
|
||||||
ath_txq_unlock(sc, txq);
|
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);
|
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_WARNING "atmel: unable to create /proc entry.\n");
|
||||||
|
|
||||||
printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %pM\n",
|
printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %pM\n",
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "tracepoint.h"
|
#include "tracepoint.h"
|
||||||
|
|
||||||
#define PKTFILTER_BUF_SIZE 128
|
#define PKTFILTER_BUF_SIZE 128
|
||||||
#define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */
|
|
||||||
#define BRCMF_DEFAULT_BCN_TIMEOUT 3
|
#define BRCMF_DEFAULT_BCN_TIMEOUT 3
|
||||||
#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
|
#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
|
||||||
#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
|
#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
|
||||||
|
@ -338,23 +337,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
||||||
goto done;
|
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 */
|
/* Setup packet filter */
|
||||||
brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER);
|
brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER);
|
||||||
brcmf_c_pktfilter_offload_enable(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);
|
brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
|
||||||
|
|
||||||
|
ndev->destructor = free_netdev;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
drvr->iflist[ifp->bssidx] = NULL;
|
||||||
ndev->netdev_ops = NULL;
|
ndev->netdev_ops = NULL;
|
||||||
|
free_netdev(ndev);
|
||||||
return -EBADE;
|
return -EBADE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -720,6 +723,9 @@ static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
ifp->drvr->iflist[ifp->bssidx] = NULL;
|
||||||
|
ndev->netdev_ops = NULL;
|
||||||
|
free_netdev(ndev);
|
||||||
return -EBADE;
|
return -EBADE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -788,6 +794,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
|
||||||
struct brcmf_if *ifp;
|
struct brcmf_if *ifp;
|
||||||
|
|
||||||
ifp = drvr->iflist[bssidx];
|
ifp = drvr->iflist[bssidx];
|
||||||
|
drvr->iflist[bssidx] = NULL;
|
||||||
if (!ifp) {
|
if (!ifp) {
|
||||||
brcmf_err("Null interface, idx=%d\n", bssidx);
|
brcmf_err("Null interface, idx=%d\n", bssidx);
|
||||||
return;
|
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->setmacaddr_work);
|
||||||
cancel_work_sync(&ifp->multicast_work);
|
cancel_work_sync(&ifp->multicast_work);
|
||||||
}
|
}
|
||||||
|
/* unregister will take care of freeing it */
|
||||||
unregister_netdev(ifp->ndev);
|
unregister_netdev(ifp->ndev);
|
||||||
if (bssidx == 0)
|
if (bssidx == 0)
|
||||||
brcmf_cfg80211_detach(drvr->config);
|
brcmf_cfg80211_detach(drvr->config);
|
||||||
free_netdev(ifp->ndev);
|
|
||||||
} else {
|
} else {
|
||||||
kfree(ifp);
|
kfree(ifp);
|
||||||
}
|
}
|
||||||
drvr->iflist[bssidx] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
||||||
|
@ -925,8 +930,6 @@ fail:
|
||||||
brcmf_fws_del_interface(ifp);
|
brcmf_fws_del_interface(ifp);
|
||||||
brcmf_fws_deinit(drvr);
|
brcmf_fws_deinit(drvr);
|
||||||
}
|
}
|
||||||
free_netdev(ifp->ndev);
|
|
||||||
drvr->iflist[0] = NULL;
|
|
||||||
if (p2p_ifp) {
|
if (p2p_ifp) {
|
||||||
free_netdev(p2p_ifp->ndev);
|
free_netdev(p2p_ifp->ndev);
|
||||||
drvr->iflist[1] = NULL;
|
drvr->iflist[1] = NULL;
|
||||||
|
@ -934,7 +937,8 @@ fail:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if ((brcmf_p2p_enable) && (p2p_ifp))
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,7 +202,8 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
|
||||||
return;
|
return;
|
||||||
brcmf_fws_add_interface(ifp);
|
brcmf_fws_add_interface(ifp);
|
||||||
if (!drvr->fweh.evt_handler[BRCMF_E_IF])
|
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)
|
if (ifevent->action == BRCMF_E_IF_CHANGE)
|
||||||
|
|
|
@ -23,6 +23,12 @@
|
||||||
|
|
||||||
#define BRCMF_FIL_ACTION_FRAME_SIZE 1800
|
#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 {
|
enum brcmf_fil_p2p_if_types {
|
||||||
BRCMF_FIL_P2P_IF_CLIENT,
|
BRCMF_FIL_P2P_IF_CLIENT,
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#define IS_P2P_SOCIAL_CHANNEL(channel) ((channel == SOCIAL_CHAN_1) || \
|
#define IS_P2P_SOCIAL_CHANNEL(channel) ((channel == SOCIAL_CHAN_1) || \
|
||||||
(channel == SOCIAL_CHAN_2) || \
|
(channel == SOCIAL_CHAN_2) || \
|
||||||
(channel == SOCIAL_CHAN_3))
|
(channel == SOCIAL_CHAN_3))
|
||||||
|
#define BRCMF_P2P_TEMP_CHAN SOCIAL_CHAN_3
|
||||||
#define SOCIAL_CHAN_CNT 3
|
#define SOCIAL_CHAN_CNT 3
|
||||||
#define AF_PEER_SEARCH_CNT 2
|
#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);
|
err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
brcmf_err("set p2p_disc error\n");
|
brcmf_err("set p2p_disc error\n");
|
||||||
brcmf_free_vif(p2p_vif);
|
brcmf_free_vif(cfg, p2p_vif);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
/* obtain bsscfg index for P2P discovery */
|
/* obtain bsscfg index for P2P discovery */
|
||||||
err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
|
err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
brcmf_err("retrieving discover bsscfg index failed\n");
|
brcmf_err("retrieving discover bsscfg index failed\n");
|
||||||
brcmf_free_vif(p2p_vif);
|
brcmf_free_vif(cfg, p2p_vif);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
/* Verify that firmware uses same bssidx as driver !! */
|
/* Verify that firmware uses same bssidx as driver !! */
|
||||||
if (p2p_ifp->bssidx != bssidx) {
|
if (p2p_ifp->bssidx != bssidx) {
|
||||||
brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
|
brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
|
||||||
bssidx, p2p_ifp->bssidx);
|
bssidx, p2p_ifp->bssidx);
|
||||||
brcmf_free_vif(p2p_vif);
|
brcmf_free_vif(cfg, p2p_vif);
|
||||||
goto exit;
|
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_cancel_remain_on_channel(vif->ifp);
|
||||||
brcmf_p2p_deinit_discovery(p2p);
|
brcmf_p2p_deinit_discovery(p2p);
|
||||||
/* remove discovery interface */
|
/* remove discovery interface */
|
||||||
brcmf_free_vif(vif);
|
brcmf_free_vif(p2p->cfg, vif);
|
||||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
||||||
}
|
}
|
||||||
/* just set it all to zero */
|
/* just set it all to zero */
|
||||||
|
@ -2013,17 +2014,30 @@ static void brcmf_p2p_get_current_chanspec(struct brcmf_p2p_info *p2p,
|
||||||
u16 *chanspec)
|
u16 *chanspec)
|
||||||
{
|
{
|
||||||
struct brcmf_if *ifp;
|
struct brcmf_if *ifp;
|
||||||
struct brcmf_fil_chan_info_le ci;
|
u8 mac_addr[ETH_ALEN];
|
||||||
struct brcmu_chan ch;
|
struct brcmu_chan ch;
|
||||||
s32 err;
|
struct brcmf_bss_info_le *bi;
|
||||||
|
u8 *buf;
|
||||||
|
|
||||||
ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
|
ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
|
||||||
|
|
||||||
ch.chnum = 11;
|
if (brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSSID, mac_addr,
|
||||||
|
ETH_ALEN) == 0) {
|
||||||
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, &ci, sizeof(ci));
|
buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
|
||||||
if (!err)
|
if (buf != NULL) {
|
||||||
ch.chnum = le32_to_cpu(ci.hw_channel);
|
*(__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;
|
ch.bw = BRCMU_CHAN_BW_20;
|
||||||
p2p->cfg->d11inf.encchspec(&ch);
|
p2p->cfg->d11inf.encchspec(&ch);
|
||||||
*chanspec = ch.chspec;
|
*chanspec = ch.chspec;
|
||||||
|
@ -2208,7 +2222,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
|
||||||
return &p2p_vif->wdev;
|
return &p2p_vif->wdev;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
brcmf_free_vif(p2p_vif);
|
brcmf_free_vif(p2p->cfg, p2p_vif);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2217,13 +2231,31 @@ fail:
|
||||||
*
|
*
|
||||||
* @vif: virtual interface object to delete.
|
* @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);
|
cfg80211_unregister_wdev(&vif->wdev);
|
||||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
||||||
brcmf_free_vif(vif);
|
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");
|
brcmf_err("Registering netdevice failed\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
/* override destructor */
|
||||||
|
ifp->ndev->destructor = brcmf_p2p_free_p2p_if;
|
||||||
|
|
||||||
cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif;
|
cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif;
|
||||||
/* Disable firmware roaming for P2P interface */
|
/* Disable firmware roaming for P2P interface */
|
||||||
brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
|
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;
|
return &ifp->vif->wdev;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
brcmf_free_vif(vif);
|
brcmf_free_vif(cfg, vif);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2350,7 +2385,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NL80211_IFTYPE_P2P_DEVICE:
|
case NL80211_IFTYPE_P2P_DEVICE:
|
||||||
brcmf_p2p_delete_p2pdev(vif);
|
brcmf_p2p_delete_p2pdev(cfg, vif);
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
@ -2378,7 +2413,6 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
brcmf_cfg80211_arm_vif_event(cfg, NULL);
|
brcmf_cfg80211_arm_vif_event(cfg, NULL);
|
||||||
brcmf_free_vif(vif);
|
|
||||||
p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
|
p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -459,6 +459,38 @@ send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key)
|
||||||
return err;
|
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,
|
static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
|
||||||
const char *name,
|
const char *name,
|
||||||
enum nl80211_iftype type,
|
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;
|
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"));
|
brcmf_dbg(INFO, "power save %s\n", (pm ? "enabled" : "disabled"));
|
||||||
|
|
||||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm);
|
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;
|
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
|
static s32
|
||||||
brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
|
brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
|
||||||
struct cfg80211_ap_settings *settings)
|
struct cfg80211_ap_settings *settings)
|
||||||
{
|
{
|
||||||
s32 ie_offset;
|
s32 ie_offset;
|
||||||
|
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||||
struct brcmf_tlv *ssid_ie;
|
struct brcmf_tlv *ssid_ie;
|
||||||
struct brcmf_ssid_le ssid_le;
|
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_set_mpc(ifp, 0);
|
||||||
|
brcmf_configure_arp_offload(ifp, false);
|
||||||
|
|
||||||
/* find the RSN_IE */
|
/* find the RSN_IE */
|
||||||
rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
|
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);
|
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) {
|
if (settings->beacon_interval) {
|
||||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
|
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
|
||||||
settings->beacon_interval);
|
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);
|
set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (err)
|
if (err) {
|
||||||
brcmf_set_mpc(ifp, 1);
|
brcmf_set_mpc(ifp, 1);
|
||||||
|
brcmf_configure_arp_offload(ifp, true);
|
||||||
|
}
|
||||||
return err;
|
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_err("bss_enable config failed %d\n", err);
|
||||||
}
|
}
|
||||||
brcmf_set_mpc(ifp, 1);
|
brcmf_set_mpc(ifp, 1);
|
||||||
|
brcmf_configure_arp_offload(ifp, true);
|
||||||
set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
|
set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
|
||||||
clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &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[] = {
|
static const struct ieee80211_iface_combination brcmf_iface_combos[] = {
|
||||||
{
|
{
|
||||||
.max_interfaces = BRCMF_IFACE_MAX_CNT,
|
.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),
|
.n_limits = ARRAY_SIZE(brcmf_iface_limits),
|
||||||
.limits = 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;
|
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);
|
list_del(&vif->list);
|
||||||
cfg->vif_cnt--;
|
cfg->vif_cnt--;
|
||||||
|
|
||||||
kfree(vif);
|
kfree(vif);
|
||||||
if (!cfg->vif_cnt) {
|
if (!cfg->vif_cnt) {
|
||||||
wiphy_unregister(wiphy);
|
wiphy_unregister(cfg->wiphy);
|
||||||
wiphy_free(wiphy);
|
wiphy_free(cfg->wiphy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4646,7 +4707,6 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case BRCMF_E_IF_DEL:
|
case BRCMF_E_IF_DEL:
|
||||||
ifp->vif = NULL;
|
|
||||||
mutex_unlock(&event->vif_event_lock);
|
mutex_unlock(&event->vif_event_lock);
|
||||||
/* event may not be upon user request */
|
/* event may not be upon user request */
|
||||||
if (brcmf_cfg80211_vif_event_armed(cfg))
|
if (brcmf_cfg80211_vif_event_armed(cfg))
|
||||||
|
@ -4852,8 +4912,7 @@ cfg80211_p2p_attach_out:
|
||||||
wl_deinit_priv(cfg);
|
wl_deinit_priv(cfg);
|
||||||
|
|
||||||
cfg80211_attach_out:
|
cfg80211_attach_out:
|
||||||
brcmf_free_vif(vif);
|
brcmf_free_vif(cfg, vif);
|
||||||
wiphy_free(wiphy);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4865,7 +4924,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
|
||||||
wl_deinit_priv(cfg);
|
wl_deinit_priv(cfg);
|
||||||
brcmf_btcoex_detach(cfg);
|
brcmf_btcoex_detach(cfg);
|
||||||
list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
|
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)
|
if (err)
|
||||||
goto default_conf_out;
|
goto default_conf_out;
|
||||||
|
|
||||||
|
brcmf_configure_arp_offload(ifp, true);
|
||||||
|
|
||||||
cfg->dongle_up = true;
|
cfg->dongle_up = true;
|
||||||
default_conf_out:
|
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,
|
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
|
||||||
enum nl80211_iftype type,
|
enum nl80211_iftype type,
|
||||||
bool pm_block);
|
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,
|
s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
|
||||||
const u8 *vndr_ie_buf, u32 vndr_ie_len);
|
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,
|
memcpy(&lq, priv->stations[i].lq,
|
||||||
sizeof(struct iwl_link_quality_cmd));
|
sizeof(struct iwl_link_quality_cmd));
|
||||||
|
|
||||||
if (!memcmp(&lq, &zero_lq, sizeof(lq)))
|
if (memcmp(&lq, &zero_lq, sizeof(lq)))
|
||||||
send_lq = true;
|
send_lq = true;
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&priv->sta_lock);
|
spin_unlock_bh(&priv->sta_lock);
|
||||||
|
|
|
@ -28,7 +28,7 @@ config NFC_WILINK
|
||||||
|
|
||||||
config NFC_MEI_PHY
|
config NFC_MEI_PHY
|
||||||
tristate "MEI bus NFC device support"
|
tristate "MEI bus NFC device support"
|
||||||
depends on INTEL_MEI_BUS_NFC && NFC_HCI
|
depends on INTEL_MEI && NFC_HCI
|
||||||
help
|
help
|
||||||
This adds support to use an mei bus nfc device. Select this if you
|
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
|
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;
|
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;
|
phy->powered = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -43,24 +43,16 @@ static int microread_mei_probe(struct mei_cl_device *device,
|
||||||
return -ENOMEM;
|
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,
|
r = microread_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
|
||||||
MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
|
MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
|
||||||
&phy->hdev);
|
&phy->hdev);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
goto err_out;
|
nfc_mei_phy_free(phy);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_out:
|
|
||||||
nfc_mei_phy_free(phy);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int microread_mei_remove(struct mei_cl_device *device)
|
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);
|
microread_remove(phy->hdev);
|
||||||
|
|
||||||
nfc_mei_phy_disable(phy);
|
|
||||||
|
|
||||||
nfc_mei_phy_free(phy);
|
nfc_mei_phy_free(phy);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -43,24 +43,16 @@ static int pn544_mei_probe(struct mei_cl_device *device,
|
||||||
return -ENOMEM;
|
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,
|
r = pn544_hci_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
|
||||||
MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
|
MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
|
||||||
&phy->hdev);
|
&phy->hdev);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
goto err_out;
|
nfc_mei_phy_free(phy);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_out:
|
|
||||||
nfc_mei_phy_free(phy);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pn544_mei_remove(struct mei_cl_device *device)
|
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);
|
pn544_hci_remove(phy->hdev);
|
||||||
|
|
||||||
nfc_mei_phy_disable(phy);
|
|
||||||
|
|
||||||
nfc_mei_phy_free(phy);
|
nfc_mei_phy_free(phy);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -159,9 +159,10 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
|
||||||
return 0;
|
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;
|
u64 new, mask, tmp;
|
||||||
u8 *m;
|
u8 *m;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -181,11 +182,14 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
|
||||||
|
|
||||||
|
|
||||||
mutex_lock(&local->iflist_mtx);
|
mutex_lock(&local->iflist_mtx);
|
||||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
list_for_each_entry(iter, &local->interfaces, list) {
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
|
if (iter == sdata)
|
||||||
continue;
|
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) |
|
tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
|
||||||
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
|
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
|
||||||
((u64)m[4] << 1*8) | ((u64)m[5] << 0*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))
|
if (ieee80211_sdata_running(sdata))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
ret = ieee80211_verify_mac(sdata->local, sa->sa_data);
|
ret = ieee80211_verify_mac(sdata, sa->sa_data);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -474,6 +478,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
|
||||||
master->control_port_protocol;
|
master->control_port_protocol;
|
||||||
sdata->control_port_no_encrypt =
|
sdata->control_port_no_encrypt =
|
||||||
master->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;
|
break;
|
||||||
}
|
}
|
||||||
case NL80211_IFTYPE_AP:
|
case NL80211_IFTYPE_AP:
|
||||||
|
@ -653,7 +660,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
|
||||||
|
|
||||||
ieee80211_recalc_ps(local, -1);
|
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;
|
unsigned long flags;
|
||||||
int n_acs = IEEE80211_NUM_ACS;
|
int n_acs = IEEE80211_NUM_ACS;
|
||||||
int ac;
|
int ac;
|
||||||
|
@ -1479,7 +1490,17 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pick address of existing interface in case user changed
|
||||||
|
* MAC address manually, default to perm_addr.
|
||||||
|
*/
|
||||||
m = local->hw.wiphy->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) |
|
start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
|
||||||
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
|
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
|
||||||
((u64)m[4] << 1*8) | ((u64)m[5] << 0*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();
|
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);
|
mutex_lock(&local->iflist_mtx);
|
||||||
list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
|
list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
|
||||||
list_del(&sdata->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))
|
if (WARN_ON_ONCE(!auth_data))
|
||||||
return -EINVAL;
|
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++;
|
auth_data->tries++;
|
||||||
|
|
||||||
if (auth_data->tries > IEEE80211_AUTH_MAX_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;
|
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,
|
ieee80211_send_auth(sdata, trans, auth_data->algorithm, status,
|
||||||
auth_data->data, auth_data->data_len,
|
auth_data->data, auth_data->data_len,
|
||||||
auth_data->bss->bssid,
|
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.
|
* will not answer to direct packet in unassociated state.
|
||||||
*/
|
*/
|
||||||
ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
|
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);
|
auth_data->bss->channel, false);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
|
if (tx_flags == 0) {
|
||||||
auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
|
auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
|
||||||
ifmgd->auth_data->timeout_started = true;
|
ifmgd->auth_data->timeout_started = true;
|
||||||
run_again(ifmgd, auth_data->timeout);
|
run_again(ifmgd, auth_data->timeout);
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
obj-$(CONFIG_NFC) += nfc.o
|
obj-$(CONFIG_NFC) += nfc.o
|
||||||
obj-$(CONFIG_NFC_NCI) += nci/
|
obj-$(CONFIG_NFC_NCI) += nci/
|
||||||
obj-$(CONFIG_NFC_HCI) += hci/
|
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 \
|
nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \
|
||||||
llcp_sock.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))
|
(u32)sinfo->rx_bytes))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
if ((sinfo->filled & (STATION_INFO_TX_BYTES |
|
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,
|
nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
|
||||||
(u32)sinfo->tx_bytes))
|
(u32)sinfo->tx_bytes))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
|
@ -231,6 +231,9 @@ void cfg80211_conn_work(struct work_struct *work)
|
||||||
mutex_lock(&rdev->sched_scan_mtx);
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
|
|
||||||
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
||||||
|
if (!wdev->netdev)
|
||||||
|
continue;
|
||||||
|
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
if (!netif_running(wdev->netdev)) {
|
if (!netif_running(wdev->netdev)) {
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
|
|
Loading…
Reference in New Issue