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:
David S. Miller
2013-05-31 02:38:19 -07:00
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,
+2 -1
View File
@@ -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);
+4 -10
View File
@@ -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);
+17 -8
View File
@@ -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);
+1 -1
View File
@@ -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
+2 -1
View File
@@ -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;
+1 -4
View File
@@ -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;
}
+11
View File
@@ -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
+39 -99
View File
@@ -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);
}
+1 -1
View File
@@ -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 @@ fail:
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 @@ fail:
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,
+54 -20
View File
@@ -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 @@ fail:
*
* @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 @@ cfg80211_p2p_attach_out:
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);
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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
+9
View File
@@ -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;

Some files were not shown because too many files have changed in this diff Show More