Signed-off-by: Felix Fietkau <nbd@openwrt.org> SVN-Revision: 47286master
parent
f79bae2fc0
commit
ec3ee0969e
@ -1,33 +0,0 @@ |
||||
From e15e9231e7a9f81f5264d294fd3fd96a20d92516 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sat, 25 Jul 2015 15:19:17 +0200
|
||||
Subject: [PATCH 3/3] backports: do not add debugfs_create_devm_seqfile() on
|
||||
recent kernel versions
|
||||
|
||||
An #ifdef for the kernel version was missing around the header of
|
||||
debugfs_create_devm_seqfile() and the LINUX_BACKPORT() was also not
|
||||
done.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
backport/backport-include/linux/debugfs.h | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/backport-include/linux/debugfs.h
|
||||
+++ b/backport-include/linux/debugfs.h
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <linux/device.h>
|
||||
#include <generated/utsrelease.h>
|
||||
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
|
||||
+#define debugfs_create_devm_seqfile LINUX_BACKPORT(debugfs_create_devm_seqfile)
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,
|
||||
struct dentry *parent,
|
||||
@@ -20,5 +22,6 @@ static inline struct dentry *debugfs_cre
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
|
||||
|
||||
#endif /* __BACKPORT_DEBUGFS_H_ */
|
@ -1,31 +0,0 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sun, 7 Jun 2015 13:53:35 +0200
|
||||
Subject: [PATCH] ath9k: force rx_clear when disabling rx
|
||||
|
||||
This makes stopping Rx more reliable and should reduce the frequency of
|
||||
Rx related DMA stop warnings
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/mac.c
|
||||
@@ -677,13 +677,15 @@ void ath9k_hw_startpcureceive(struct ath
|
||||
|
||||
ath9k_ani_reset(ah, is_scanning);
|
||||
|
||||
- REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
|
||||
+ REG_CLR_BIT(ah, AR_DIAG_SW,
|
||||
+ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_startpcureceive);
|
||||
|
||||
void ath9k_hw_abortpcurecv(struct ath_hw *ah)
|
||||
{
|
||||
- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
|
||||
+ REG_SET_BIT(ah, AR_DIAG_SW,
|
||||
+ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
|
||||
|
||||
ath9k_hw_disable_mib_counters(ah);
|
||||
}
|
@ -1,121 +0,0 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Thu, 2 Jul 2015 15:20:56 +0200
|
||||
Subject: [PATCH] ath9k: limit retries for powersave response frames
|
||||
|
||||
In some cases, the channel might be busy enough that an ath9k AP's
|
||||
response to PS-Poll frames might be too slow and the station has already
|
||||
gone to sleep. To avoid wasting too much airtime on this, limit the
|
||||
number of retries on such frames and ensure that no sample rate gets
|
||||
used.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -147,10 +147,25 @@ static void ath_send_bar(struct ath_atx_
|
||||
}
|
||||
|
||||
static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
- struct ath_buf *bf)
|
||||
+ struct ath_buf *bf, bool ps)
|
||||
{
|
||||
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu);
|
||||
+
|
||||
+ if (ps) {
|
||||
+ /* Clear the first rate to avoid using a sample rate for PS frames */
|
||||
+ info->control.rates[0].idx = -1;
|
||||
+ info->control.rates[0].count = 0;
|
||||
+ }
|
||||
+
|
||||
ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates,
|
||||
ARRAY_SIZE(bf->rates));
|
||||
+ if (!ps)
|
||||
+ return;
|
||||
+
|
||||
+ if (bf->rates[0].count > 2)
|
||||
+ bf->rates[0].count = 2;
|
||||
+
|
||||
+ bf->rates[1].idx = -1;
|
||||
}
|
||||
|
||||
static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
|
||||
@@ -1430,7 +1445,7 @@ ath_tx_form_burst(struct ath_softc *sc,
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
break;
|
||||
|
||||
- ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||
+ ath_set_rates(tid->an->vif, tid->an->sta, bf, false);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
@@ -1461,7 +1476,7 @@ static bool ath_tx_sched_aggr(struct ath
|
||||
return false;
|
||||
}
|
||||
|
||||
- ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||
+ ath_set_rates(tid->an->vif, tid->an->sta, bf, false);
|
||||
if (aggr)
|
||||
last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf,
|
||||
tid_q, &aggr_len);
|
||||
@@ -1653,7 +1668,7 @@ void ath9k_release_buffered_frames(struc
|
||||
|
||||
__skb_unlink(bf->bf_mpdu, tid_q);
|
||||
list_add_tail(&bf->list, &bf_q);
|
||||
- ath_set_rates(tid->an->vif, tid->an->sta, bf);
|
||||
+ ath_set_rates(tid->an->vif, tid->an->sta, bf, true);
|
||||
if (bf_isampdu(bf)) {
|
||||
ath_tx_addto_baw(sc, tid, bf);
|
||||
bf->bf_state.bf_type &= ~BUF_AGGR;
|
||||
@@ -2318,7 +2333,7 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
struct ath_txq *txq = txctl->txq;
|
||||
struct ath_atx_tid *tid = NULL;
|
||||
struct ath_buf *bf;
|
||||
- bool queue, skip_uapsd = false, ps_resp;
|
||||
+ bool queue, ps_resp;
|
||||
int q, ret;
|
||||
|
||||
if (vif)
|
||||
@@ -2365,13 +2380,13 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
if (!txctl->an)
|
||||
txctl->an = &avp->mcast_node;
|
||||
queue = true;
|
||||
- skip_uapsd = true;
|
||||
+ ps_resp = false;
|
||||
}
|
||||
|
||||
if (txctl->an && queue)
|
||||
tid = ath_get_skb_tid(sc, txctl->an, skb);
|
||||
|
||||
- if (!skip_uapsd && ps_resp) {
|
||||
+ if (ps_resp) {
|
||||
ath_txq_unlock(sc, txq);
|
||||
txq = sc->tx.uapsdq;
|
||||
ath_txq_lock(sc, txq);
|
||||
@@ -2409,7 +2424,7 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
if (txctl->paprd)
|
||||
bf->bf_state.bfs_paprd_timestamp = jiffies;
|
||||
|
||||
- ath_set_rates(vif, sta, bf);
|
||||
+ ath_set_rates(vif, sta, bf, ps_resp);
|
||||
ath_tx_send_normal(sc, txq, tid, skb);
|
||||
|
||||
out:
|
||||
@@ -2448,7 +2463,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
|
||||
break;
|
||||
|
||||
bf->bf_lastbf = bf;
|
||||
- ath_set_rates(vif, NULL, bf);
|
||||
+ ath_set_rates(vif, NULL, bf, false);
|
||||
ath_buf_set_rate(sc, bf, &info, fi->framelen, false);
|
||||
duration += info.rates[0].PktDuration;
|
||||
if (bf_tail)
|
||||
@@ -2968,7 +2983,7 @@ int ath9k_tx99_send(struct ath_softc *sc
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- ath_set_rates(sc->tx99_vif, NULL, bf);
|
||||
+ ath_set_rates(sc->tx99_vif, NULL, bf, false);
|
||||
|
||||
ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, bf->bf_daddr);
|
||||
ath9k_hw_tx99_start(sc->sc_ah, txctl->txq->axq_qnum);
|
@ -1,56 +0,0 @@ |
||||
From: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
|
||||
Date: Fri, 3 Jul 2015 11:45:42 +0530
|
||||
Subject: [PATCH] ath10k: Delay device access after cold reset
|
||||
|
||||
It is observed that during cold reset pcie access right
|
||||
after a write operation to SOC_GLOBAL_RESET_ADDRESS causes
|
||||
Data Bus Error and system hard lockup. The reason
|
||||
for bus error is that pcie needs some time to get
|
||||
back to stable state for any transaction during cold reset. Add
|
||||
delay of 20 msecs after write of SOC_GLOBAL_RESET_ADDRESS
|
||||
to fix this issue.
|
||||
|
||||
Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/pci.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/pci.c
|
||||
@@ -2761,7 +2761,6 @@ static int ath10k_pci_wait_for_target_in
|
||||
|
||||
static int ath10k_pci_cold_reset(struct ath10k *ar)
|
||||
{
|
||||
- int i;
|
||||
u32 val;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n");
|
||||
@@ -2777,23 +2776,18 @@ static int ath10k_pci_cold_reset(struct
|
||||
val |= 1;
|
||||
ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val);
|
||||
|
||||
- for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) {
|
||||
- if (ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) &
|
||||
- RTC_STATE_COLD_RESET_MASK)
|
||||
- break;
|
||||
- msleep(1);
|
||||
- }
|
||||
+ /* After writing into SOC_GLOBAL_RESET to put device into
|
||||
+ * reset and pulling out of reset pcie may not be stable
|
||||
+ * for any immediate pcie register access and cause bus error,
|
||||
+ * add delay before any pcie access request to fix this issue.
|
||||
+ */
|
||||
+ msleep(20);
|
||||
|
||||
/* Pull Target, including PCIe, out of RESET. */
|
||||
val &= ~1;
|
||||
ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val);
|
||||
|
||||
- for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) {
|
||||
- if (!(ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) &
|
||||
- RTC_STATE_COLD_RESET_MASK))
|
||||
- break;
|
||||
- msleep(1);
|
||||
- }
|
||||
+ msleep(20);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset complete\n");
|
||||
|
@ -1,17 +0,0 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Mon, 11 May 2015 18:35:20 +0200
|
||||
Subject: [PATCH] ath9k: add fast-xmit support
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -826,6 +826,7 @@ static void ath9k_set_hw_capab(struct at
|
||||
ieee80211_hw_set(hw, SIGNAL_DBM);
|
||||
ieee80211_hw_set(hw, RX_INCLUDES_FCS);
|
||||
ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
|
||||
+ ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
|
||||
|
||||
if (ath9k_ps_enable)
|
||||
ieee80211_hw_set(hw, SUPPORTS_PS);
|
@ -1,385 +0,0 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 4 Apr 2015 18:39:06 +0200
|
||||
Subject: [PATCH] ath9k: remove struct ath_atx_ac
|
||||
|
||||
struct ath_atx_ac contains a list of active TIDs belonging to one WMM AC.
|
||||
This patch changes the code to track active station TIDs in the txq directly.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -173,14 +173,6 @@ struct ath_txq {
|
||||
struct sk_buff_head complete_q;
|
||||
};
|
||||
|
||||
-struct ath_atx_ac {
|
||||
- struct ath_txq *txq;
|
||||
- struct list_head list;
|
||||
- struct list_head tid_q;
|
||||
- bool clear_ps_filter;
|
||||
- bool sched;
|
||||
-};
|
||||
-
|
||||
struct ath_frame_info {
|
||||
struct ath_buf *bf;
|
||||
u16 framelen;
|
||||
@@ -243,7 +235,7 @@ struct ath_atx_tid {
|
||||
struct sk_buff_head buf_q;
|
||||
struct sk_buff_head retry_q;
|
||||
struct ath_node *an;
|
||||
- struct ath_atx_ac *ac;
|
||||
+ struct ath_txq *txq;
|
||||
unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
|
||||
u16 seq_start;
|
||||
u16 seq_next;
|
||||
@@ -255,6 +247,7 @@ struct ath_atx_tid {
|
||||
s8 bar_index;
|
||||
bool sched;
|
||||
bool active;
|
||||
+ bool clear_ps_filter;
|
||||
};
|
||||
|
||||
struct ath_node {
|
||||
@@ -262,7 +255,6 @@ struct ath_node {
|
||||
struct ieee80211_sta *sta; /* station struct we're part of */
|
||||
struct ieee80211_vif *vif; /* interface with which we're associated */
|
||||
struct ath_atx_tid tid[IEEE80211_NUM_TIDS];
|
||||
- struct ath_atx_ac ac[IEEE80211_NUM_ACS];
|
||||
|
||||
u16 maxampdu;
|
||||
u8 mpdudensity;
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -106,7 +106,6 @@ void ath_txq_unlock_complete(struct ath_
|
||||
static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct ath_atx_tid *tid)
|
||||
{
|
||||
- struct ath_atx_ac *ac = tid->ac;
|
||||
struct list_head *list;
|
||||
struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
|
||||
struct ath_chanctx *ctx = avp->chanctx;
|
||||
@@ -118,15 +117,8 @@ static void ath_tx_queue_tid(struct ath_
|
||||
return;
|
||||
|
||||
tid->sched = true;
|
||||
- list_add_tail(&tid->list, &ac->tid_q);
|
||||
-
|
||||
- if (ac->sched)
|
||||
- return;
|
||||
-
|
||||
- ac->sched = true;
|
||||
-
|
||||
list = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
|
||||
- list_add_tail(&ac->list, list);
|
||||
+ list_add_tail(&tid->list, list);
|
||||
}
|
||||
|
||||
static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
|
||||
@@ -223,7 +215,7 @@ static struct sk_buff *ath_tid_dequeue(s
|
||||
static void
|
||||
ath_tx_tid_change_state(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
{
|
||||
- struct ath_txq *txq = tid->ac->txq;
|
||||
+ struct ath_txq *txq = tid->txq;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
struct sk_buff *skb, *tskb;
|
||||
struct ath_buf *bf;
|
||||
@@ -252,7 +244,7 @@ ath_tx_tid_change_state(struct ath_softc
|
||||
|
||||
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
{
|
||||
- struct ath_txq *txq = tid->ac->txq;
|
||||
+ struct ath_txq *txq = tid->txq;
|
||||
struct sk_buff *skb;
|
||||
struct ath_buf *bf;
|
||||
struct list_head bf_head;
|
||||
@@ -659,7 +651,7 @@ static void ath_tx_complete_aggr(struct
|
||||
ath_tx_queue_tid(sc, txq, tid);
|
||||
|
||||
if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
|
||||
- tid->ac->clear_ps_filter = true;
|
||||
+ tid->clear_ps_filter = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -749,7 +741,7 @@ static u32 ath_lookup_rate(struct ath_so
|
||||
struct ieee80211_tx_rate *rates;
|
||||
u32 max_4ms_framelen, frmlen;
|
||||
u16 aggr_limit, bt_aggr_limit, legacy = 0;
|
||||
- int q = tid->ac->txq->mac80211_qnum;
|
||||
+ int q = tid->txq->mac80211_qnum;
|
||||
int i;
|
||||
|
||||
skb = bf->bf_mpdu;
|
||||
@@ -1486,8 +1478,8 @@ static bool ath_tx_sched_aggr(struct ath
|
||||
if (list_empty(&bf_q))
|
||||
return false;
|
||||
|
||||
- if (tid->ac->clear_ps_filter || tid->an->no_ps_filter) {
|
||||
- tid->ac->clear_ps_filter = false;
|
||||
+ if (tid->clear_ps_filter || tid->an->no_ps_filter) {
|
||||
+ tid->clear_ps_filter = false;
|
||||
tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
|
||||
}
|
||||
|
||||
@@ -1506,7 +1498,7 @@ int ath_tx_aggr_start(struct ath_softc *
|
||||
|
||||
an = (struct ath_node *)sta->drv_priv;
|
||||
txtid = ATH_AN_2_TID(an, tid);
|
||||
- txq = txtid->ac->txq;
|
||||
+ txq = txtid->txq;
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
|
||||
@@ -1540,7 +1532,7 @@ void ath_tx_aggr_stop(struct ath_softc *
|
||||
{
|
||||
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;
|
||||
+ struct ath_txq *txq = txtid->txq;
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
txtid->active = false;
|
||||
@@ -1553,7 +1545,6 @@ void ath_tx_aggr_sleep(struct ieee80211_
|
||||
struct ath_node *an)
|
||||
{
|
||||
struct ath_atx_tid *tid;
|
||||
- struct ath_atx_ac *ac;
|
||||
struct ath_txq *txq;
|
||||
bool buffered;
|
||||
int tidno;
|
||||
@@ -1561,8 +1552,7 @@ void ath_tx_aggr_sleep(struct ieee80211_
|
||||
for (tidno = 0, tid = &an->tid[tidno];
|
||||
tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
|
||||
|
||||
- ac = tid->ac;
|
||||
- txq = ac->txq;
|
||||
+ txq = tid->txq;
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
|
||||
@@ -1576,11 +1566,6 @@ void ath_tx_aggr_sleep(struct ieee80211_
|
||||
tid->sched = false;
|
||||
list_del(&tid->list);
|
||||
|
||||
- if (ac->sched) {
|
||||
- ac->sched = false;
|
||||
- list_del(&ac->list);
|
||||
- }
|
||||
-
|
||||
ath_txq_unlock(sc, txq);
|
||||
|
||||
ieee80211_sta_set_buffered(sta, tidno, buffered);
|
||||
@@ -1590,18 +1575,16 @@ void ath_tx_aggr_sleep(struct ieee80211_
|
||||
void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
|
||||
{
|
||||
struct ath_atx_tid *tid;
|
||||
- struct ath_atx_ac *ac;
|
||||
struct ath_txq *txq;
|
||||
int tidno;
|
||||
|
||||
for (tidno = 0, tid = &an->tid[tidno];
|
||||
tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
|
||||
|
||||
- ac = tid->ac;
|
||||
- txq = ac->txq;
|
||||
+ txq = tid->txq;
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
- ac->clear_ps_filter = true;
|
||||
+ tid->clear_ps_filter = true;
|
||||
|
||||
if (ath_tid_has_buffered(tid)) {
|
||||
ath_tx_queue_tid(sc, txq, tid);
|
||||
@@ -1621,7 +1604,7 @@ void ath_tx_aggr_resume(struct ath_softc
|
||||
|
||||
an = (struct ath_node *)sta->drv_priv;
|
||||
tid = ATH_AN_2_TID(an, tidno);
|
||||
- txq = tid->ac->txq;
|
||||
+ txq = tid->txq;
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
|
||||
@@ -1660,7 +1643,7 @@ void ath9k_release_buffered_frames(struc
|
||||
|
||||
tid = ATH_AN_2_TID(an, i);
|
||||
|
||||
- ath_txq_lock(sc, tid->ac->txq);
|
||||
+ ath_txq_lock(sc, tid->txq);
|
||||
while (nframes > 0) {
|
||||
bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid, &tid_q);
|
||||
if (!bf)
|
||||
@@ -1684,7 +1667,7 @@ void ath9k_release_buffered_frames(struc
|
||||
if (an->sta && !ath_tid_has_buffered(tid))
|
||||
ieee80211_sta_set_buffered(an->sta, i, false);
|
||||
}
|
||||
- ath_txq_unlock_complete(sc, tid->ac->txq);
|
||||
+ ath_txq_unlock_complete(sc, tid->txq);
|
||||
}
|
||||
|
||||
if (list_empty(&bf_q))
|
||||
@@ -1933,9 +1916,8 @@ void ath_tx_cleanupq(struct ath_softc *s
|
||||
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
- struct ath_atx_ac *ac, *last_ac;
|
||||
struct ath_atx_tid *tid, *last_tid;
|
||||
- struct list_head *ac_list;
|
||||
+ struct list_head *tid_list;
|
||||
bool sent = false;
|
||||
|
||||
if (txq->mac80211_qnum < 0)
|
||||
@@ -1945,63 +1927,46 @@ void ath_txq_schedule(struct ath_softc *
|
||||
return;
|
||||
|
||||
spin_lock_bh(&sc->chan_lock);
|
||||
- ac_list = &sc->cur_chan->acq[txq->mac80211_qnum];
|
||||
+ tid_list = &sc->cur_chan->acq[txq->mac80211_qnum];
|
||||
|
||||
- if (list_empty(ac_list)) {
|
||||
+ if (list_empty(tid_list)) {
|
||||
spin_unlock_bh(&sc->chan_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
- last_ac = list_entry(ac_list->prev, struct ath_atx_ac, list);
|
||||
- while (!list_empty(ac_list)) {
|
||||
+ last_tid = list_entry(tid_list->prev, struct ath_atx_tid, list);
|
||||
+ while (!list_empty(tid_list)) {
|
||||
bool stop = false;
|
||||
|
||||
if (sc->cur_chan->stopped)
|
||||
break;
|
||||
|
||||
- ac = list_first_entry(ac_list, struct ath_atx_ac, list);
|
||||
- last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
|
||||
- list_del(&ac->list);
|
||||
- ac->sched = false;
|
||||
-
|
||||
- while (!list_empty(&ac->tid_q)) {
|
||||
-
|
||||
- tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
|
||||
- list);
|
||||
- list_del(&tid->list);
|
||||
- tid->sched = false;
|
||||
-
|
||||
- if (ath_tx_sched_aggr(sc, txq, tid, &stop))
|
||||
- sent = true;
|
||||
-
|
||||
- /*
|
||||
- * add tid to round-robin queue if more frames
|
||||
- * are pending for the tid
|
||||
- */
|
||||
- if (ath_tid_has_buffered(tid))
|
||||
- ath_tx_queue_tid(sc, txq, tid);
|
||||
+ tid = list_first_entry(tid_list, struct ath_atx_tid, list);
|
||||
+ list_del(&tid->list);
|
||||
+ tid->sched = false;
|
||||
|
||||
- if (stop || tid == last_tid)
|
||||
- break;
|
||||
- }
|
||||
+ if (ath_tx_sched_aggr(sc, txq, tid, &stop))
|
||||
+ sent = true;
|
||||
|
||||
- if (!list_empty(&ac->tid_q) && !ac->sched) {
|
||||
- ac->sched = true;
|
||||
- list_add_tail(&ac->list, ac_list);
|
||||
- }
|
||||
+ /*
|
||||
+ * add tid to round-robin queue if more frames
|
||||
+ * are pending for the tid
|
||||
+ */
|
||||
+ if (ath_tid_has_buffered(tid))
|
||||
+ ath_tx_queue_tid(sc, txq, tid);
|
||||
|
||||
if (stop)
|
||||
break;
|
||||
|
||||
- if (ac == last_ac) {
|
||||
+ if (tid == last_tid) {
|
||||
if (!sent)
|
||||
break;
|
||||
|
||||
sent = false;
|
||||
- last_ac = list_entry(ac_list->prev,
|
||||
- struct ath_atx_ac, list);
|
||||
+ last_tid = list_entry(tid_list->prev,
|
||||
+ struct ath_atx_tid, list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2391,10 +2356,10 @@ int ath_tx_start(struct ieee80211_hw *hw
|
||||
txq = sc->tx.uapsdq;
|
||||
ath_txq_lock(sc, txq);
|
||||
} else if (txctl->an && queue) {
|
||||
- WARN_ON(tid->ac->txq != txctl->txq);
|
||||
+ WARN_ON(tid->txq != txctl->txq);
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
|
||||
- tid->ac->clear_ps_filter = true;
|
||||
+ tid->clear_ps_filter = true;
|
||||
|
||||
/*
|
||||
* Add this frame to software queue for scheduling later
|
||||
@@ -2888,7 +2853,6 @@ int ath_tx_init(struct ath_softc *sc, in
|
||||
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
|
||||
{
|
||||
struct ath_atx_tid *tid;
|
||||
- struct ath_atx_ac *ac;
|
||||
int tidno, acno;
|
||||
|
||||
for (tidno = 0, tid = &an->tid[tidno];
|
||||
@@ -2901,24 +2865,16 @@ void ath_tx_node_init(struct ath_softc *
|
||||
tid->baw_head = tid->baw_tail = 0;
|
||||
tid->sched = false;
|
||||
tid->active = false;
|
||||
+ tid->clear_ps_filter = true;
|
||||
__skb_queue_head_init(&tid->buf_q);
|
||||
__skb_queue_head_init(&tid->retry_q);
|
||||
acno = TID_TO_WME_AC(tidno);
|
||||
- tid->ac = &an->ac[acno];
|
||||
- }
|
||||
-
|
||||
- for (acno = 0, ac = &an->ac[acno];
|
||||
- acno < IEEE80211_NUM_ACS; acno++, ac++) {
|
||||
- ac->sched = false;
|
||||
- ac->clear_ps_filter = true;
|
||||
- ac->txq = sc->tx.txq_map[acno];
|
||||
- INIT_LIST_HEAD(&ac->tid_q);
|
||||
+ tid->txq = sc->tx.txq_map[acno];
|
||||
}
|
||||
}
|
||||
|
||||
void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
|
||||
{
|
||||
- struct ath_atx_ac *ac;
|
||||
struct ath_atx_tid *tid;
|
||||
struct ath_txq *txq;
|
||||
int tidno;
|
||||
@@ -2926,8 +2882,7 @@ void ath_tx_node_cleanup(struct ath_soft
|
||||
for (tidno = 0, tid = &an->tid[tidno];
|
||||
tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
|
||||
|
||||
- ac = tid->ac;
|
||||
- txq = ac->txq;
|
||||
+ txq = tid->txq;
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
|
||||
@@ -2936,11 +2891,6 @@ void ath_tx_node_cleanup(struct ath_soft
|
||||
tid->sched = false;
|
||||
}
|
||||
|
||||
- if (ac->sched) {
|
||||
- list_del(&ac->list);
|
||||
- tid->ac->sched = false;
|
||||
- }
|
||||
-
|
||||
ath_tid_drain(sc, txq, tid);
|
||||
tid->active = false;
|
||||
|
@ -1,90 +0,0 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sat, 4 Apr 2015 18:42:33 +0200
|
||||
Subject: [PATCH] ath9k: remove the sched field in struct ath_atx_tid
|
||||
|
||||
Use list_empty(&tid->list) instead
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -245,7 +245,6 @@ struct ath_atx_tid {
|
||||
int baw_tail; /* next unused tx buffer slot */
|
||||
|
||||
s8 bar_index;
|
||||
- bool sched;
|
||||
bool active;
|
||||
bool clear_ps_filter;
|
||||
};
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -113,12 +113,9 @@ static void ath_tx_queue_tid(struct ath_
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
- if (tid->sched)
|
||||
- return;
|
||||
-
|
||||
- tid->sched = true;
|
||||
list = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
|
||||
- list_add_tail(&tid->list, list);
|
||||
+ if (list_empty(&tid->list))
|
||||
+ list_add_tail(&tid->list, list);
|
||||
}
|
||||
|
||||
static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
|
||||
@@ -1556,15 +1553,14 @@ void ath_tx_aggr_sleep(struct ieee80211_
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
|
||||
- if (!tid->sched) {
|
||||
+ if (list_empty(&tid->list)) {
|
||||
ath_txq_unlock(sc, txq);
|
||||
continue;
|
||||
}
|
||||
|
||||
buffered = ath_tid_has_buffered(tid);
|
||||
|
||||
- tid->sched = false;
|
||||
- list_del(&tid->list);
|
||||
+ list_del_init(&tid->list);
|
||||
|
||||
ath_txq_unlock(sc, txq);
|
||||
|
||||
@@ -1944,8 +1940,7 @@ void ath_txq_schedule(struct ath_softc *
|
||||
break;
|
||||
|
||||
tid = list_first_entry(tid_list, struct ath_atx_tid, list);
|
||||
- list_del(&tid->list);
|
||||
- tid->sched = false;
|
||||
+ list_del_init(&tid->list);
|
||||
|
||||
if (ath_tx_sched_aggr(sc, txq, tid, &stop))
|
||||
sent = true;
|
||||
@@ -2863,11 +2858,11 @@ void ath_tx_node_init(struct ath_softc *
|
||||
tid->seq_start = tid->seq_next = 0;
|
||||
tid->baw_size = WME_MAX_BA;
|
||||
tid->baw_head = tid->baw_tail = 0;
|
||||
- tid->sched = false;
|
||||
tid->active = false;
|
||||
tid->clear_ps_filter = true;
|
||||
__skb_queue_head_init(&tid->buf_q);
|
||||
__skb_queue_head_init(&tid->retry_q);
|
||||
+ INIT_LIST_HEAD(&tid->list);
|
||||
acno = TID_TO_WME_AC(tidno);
|
||||
tid->txq = sc->tx.txq_map[acno];
|
||||
}
|
||||
@@ -2886,10 +2881,8 @@ void ath_tx_node_cleanup(struct ath_soft
|
||||
|
||||
ath_txq_lock(sc, txq);
|
||||
|
||||
- if (tid->sched) {
|
||||
- list_del(&tid->list);
|
||||
- tid->sched = false;
|
||||
- }
|
||||
+ if (!list_empty(&tid->list))
|
||||
+ list_del_init(&tid->list);
|
||||
|
||||
ath_tid_drain(sc, txq, tid);
|
||||
tid->active = false;
|
@ -1,161 +0,0 @@ |
||||
From: Denys Vlasenko <dvlasenk@redhat.com>
|
||||
Date: Wed, 15 Jul 2015 14:56:06 +0200
|
||||
Subject: [PATCH] mac80211: Deinline rate_control_rate_init,
|
||||
rate_control_rate_update
|
||||
|
||||
With this .config: http://busybox.net/~vda/kernel_config,
|
||||
after deinlining these functions have sizes and callsite counts
|
||||
as follows:
|
||||
|
||||
rate_control_rate_init: 554 bytes, 8 calls
|
||||
rate_control_rate_update: 1596 bytes, 5 calls
|
||||
|
||||
Total size reduction: about 11 kbytes.
|
||||
|
||||
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
|
||||
CC: John Linville <linville@tuxdriver.com>
|
||||
CC: Michal Kazior <michal.kazior@tieto.com>
|
||||
CC: Johannes Berg <johannes.berg@intel.com>
|
||||
Cc: linux-wireless@vger.kernel.org
|
||||
Cc: netdev@vger.kernel.org
|
||||
CC: linux-kernel@vger.kernel.org
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rate.c
|
||||
+++ b/net/mac80211/rate.c
|
||||
@@ -29,6 +29,65 @@ module_param(ieee80211_default_rc_algo,
|
||||
MODULE_PARM_DESC(ieee80211_default_rc_algo,
|
||||
"Default rate control algorithm for mac80211 to use");
|
||||
|
||||
+void rate_control_rate_init(struct sta_info *sta)
|
||||
+{
|
||||
+ struct ieee80211_local *local = sta->sdata->local;
|
||||
+ struct rate_control_ref *ref = sta->rate_ctrl;
|
||||
+ struct ieee80211_sta *ista = &sta->sta;
|
||||
+ void *priv_sta = sta->rate_ctrl_priv;
|
||||
+ struct ieee80211_supported_band *sband;
|
||||
+ struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
+
|
||||
+ ieee80211_sta_set_rx_nss(sta);
|
||||
+
|
||||
+ if (!ref)
|
||||
+ return;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+
|
||||
+ chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf);
|
||||
+ if (WARN_ON(!chanctx_conf)) {
|
||||
+ rcu_read_unlock();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
|
||||
+
|
||||
+ spin_lock_bh(&sta->rate_ctrl_lock);
|
||||
+ ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista,
|
||||
+ priv_sta);
|
||||
+ spin_unlock_bh(&sta->rate_ctrl_lock);
|
||||
+ rcu_read_unlock();
|
||||
+ set_sta_flag(sta, WLAN_STA_RATE_CONTROL);
|
||||
+}
|
||||
+
|
||||
+void rate_control_rate_update(struct ieee80211_local *local,
|
||||
+ struct ieee80211_supported_band *sband,
|
||||
+ struct sta_info *sta, u32 changed)
|
||||
+{
|
||||
+ struct rate_control_ref *ref = local->rate_ctrl;
|
||||
+ struct ieee80211_sta *ista = &sta->sta;
|
||||
+ void *priv_sta = sta->rate_ctrl_priv;
|
||||
+ struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
+
|
||||
+ if (ref && ref->ops->rate_update) {
|
||||
+ rcu_read_lock();
|
||||
+
|
||||
+ chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf);
|
||||
+ if (WARN_ON(!chanctx_conf)) {
|
||||
+ rcu_read_unlock();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ spin_lock_bh(&sta->rate_ctrl_lock);
|
||||
+ ref->ops->rate_update(ref->priv, sband, &chanctx_conf->def,
|
||||
+ ista, priv_sta, changed);
|
||||
+ spin_unlock_bh(&sta->rate_ctrl_lock);
|
||||
+ rcu_read_unlock();
|
||||
+ }
|
||||
+ drv_sta_rc_update(local, sta->sdata, &sta->sta, changed);
|
||||
+}
|
||||
+
|
||||
int ieee80211_rate_control_register(const struct rate_control_ops *ops)
|
||||
{
|
||||
struct rate_control_alg *alg;
|
||||
--- a/net/mac80211/rate.h
|
||||
+++ b/net/mac80211/rate.h
|
||||
@@ -71,64 +71,10 @@ rate_control_tx_status_noskb(struct ieee
|
||||
spin_unlock_bh(&sta->rate_ctrl_lock);
|
||||
}
|
||||
|
||||
-static inline void rate_control_rate_init(struct sta_info *sta)
|
||||
-{
|
||||
- struct ieee80211_local *local = sta->sdata->local;
|
||||
- struct rate_control_ref *ref = sta->rate_ctrl;
|
||||
- struct ieee80211_sta *ista = &sta->sta;
|
||||
- void *priv_sta = sta->rate_ctrl_priv;
|
||||
- struct ieee80211_supported_band *sband;
|
||||
- struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
-
|
||||
- ieee80211_sta_set_rx_nss(sta);
|
||||
-
|
||||
- if (!ref)
|
||||
- return;
|
||||
-
|
||||
- rcu_read_lock();
|
||||
-
|
||||
- chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf);
|
||||
- if (WARN_ON(!chanctx_conf)) {
|
||||
- rcu_read_unlock();
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
|
||||
-
|
||||
- spin_lock_bh(&sta->rate_ctrl_lock);
|
||||
- ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista,
|
||||
- priv_sta);
|
||||
- spin_unlock_bh(&sta->rate_ctrl_lock);
|
||||
- rcu_read_unlock();
|
||||
- set_sta_flag(sta, WLAN_STA_RATE_CONTROL);
|
||||
-}
|
||||
-
|
||||
-static inline void rate_control_rate_update(struct ieee80211_local *local,
|
||||
+void rate_control_rate_init(struct sta_info *sta);
|
||||
+void rate_control_rate_update(struct ieee80211_local *local,
|
||||
struct ieee80211_supported_band *sband,
|
||||
- struct sta_info *sta, u32 changed)
|
||||
-{
|
||||
- struct rate_control_ref *ref = local->rate_ctrl;
|
||||
- struct ieee80211_sta *ista = &sta->sta;
|
||||
- void *priv_sta = sta->rate_ctrl_priv;
|
||||
- struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
-
|
||||
- if (ref && ref->ops->rate_update) {
|
||||
- rcu_read_lock();
|
||||
-
|
||||
- chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf);
|
||||
- if (WARN_ON(!chanctx_conf)) {
|
||||
- rcu_read_unlock();
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- spin_lock_bh(&sta->rate_ctrl_lock);
|
||||
- ref->ops->rate_update(ref->priv, sband, &chanctx_conf->def,
|
||||
- ista, priv_sta, changed);
|
||||
- spin_unlock_bh(&sta->rate_ctrl_lock);
|
||||
- rcu_read_unlock();
|
||||
- }
|
||||
- drv_sta_rc_update(local, sta->sdata, &sta->sta, changed);
|
||||
-}
|
||||
+ struct sta_info *sta, u32 changed);
|
||||
|
||||
static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
|
||||
struct sta_info *sta, gfp_t gfp)
|
@ -1,116 +0,0 @@ |
||||
From: Denys Vlasenko <dvlasenk@redhat.com>
|
||||
Date: Wed, 15 Jul 2015 14:56:05 +0200
|
||||
Subject: [PATCH] mac80211: Deinline drv_sta_state
|
||||
|
||||
With this .config: http://busybox.net/~vda/kernel_config,
|
||||
after deinlining the function size is 3132 bytes and there are
|
||||
7 callsites.
|
||||
|
||||
Total size reduction: about 20 kbytes.
|
||||
|
||||
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
|
||||
CC: John Linville <linville@tuxdriver.com>
|
||||
CC: Michal Kazior <michal.kazior@tieto.com>
|
||||
Cc: Johannes Berg <johannes.berg@intel.com>
|
||||
Cc: linux-wireless@vger.kernel.org
|
||||
Cc: netdev@vger.kernel.org
|
||||
CC: linux-kernel@vger.kernel.org
|
||||
---
|
||||
create mode 100644 net/mac80211/driver-ops.c
|
||||
|
||||
--- a/net/mac80211/Makefile
|
||||
+++ b/net/mac80211/Makefile
|
||||
@@ -3,6 +3,7 @@ obj-$(CPTCFG_MAC80211) += mac80211.o
|
||||
# mac80211 objects
|
||||
mac80211-y := \
|
||||
main.o status.o \
|
||||
+ driver-ops.o \
|
||||
sta_info.o \
|
||||
wep.o \
|
||||
wpa.o \
|
||||
--- /dev/null
|
||||
+++ b/net/mac80211/driver-ops.c
|
||||
@@ -0,0 +1,41 @@
|
||||
+/*
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+#include <net/mac80211.h>
|
||||
+#include "ieee80211_i.h"
|
||||
+#include "trace.h"
|
||||
+#include "driver-ops.h"
|
||||
+
|
||||
+__must_check
|
||||
+int drv_sta_state(struct ieee80211_local *local,
|
||||
+ struct ieee80211_sub_if_data *sdata,
|
||||
+ struct sta_info *sta,
|
||||
+ enum ieee80211_sta_state old_state,
|
||||
+ enum ieee80211_sta_state new_state)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ might_sleep();
|
||||
+
|
||||
+ sdata = get_bss_sdata(sdata);
|
||||
+ if (!check_sdata_in_driver(sdata))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state);
|
||||
+ if (local->ops->sta_state) {
|
||||
+ ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta,
|
||||
+ old_state, new_state);
|
||||
+ } else if (old_state == IEEE80211_STA_AUTH &&
|
||||
+ new_state == IEEE80211_STA_ASSOC) {
|
||||
+ ret = drv_sta_add(local, sdata, &sta->sta);
|
||||
+ if (ret == 0)
|
||||
+ sta->uploaded = true;
|
||||
+ } else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
+ new_state == IEEE80211_STA_AUTH) {
|
||||
+ drv_sta_remove(local, sdata, &sta->sta);
|
||||
+ }
|
||||
+ trace_drv_return_int(local, ret);
|
||||
+ return ret;
|
||||
+}
|
||||
--- a/net/mac80211/driver-ops.h
|
||||
+++ b/net/mac80211/driver-ops.h
|
||||
@@ -573,37 +573,12 @@ static inline void drv_sta_pre_rcu_remov
|
||||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
-static inline __must_check
|
||||
+__must_check
|
||||
int drv_sta_state(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta,
|
||||
enum ieee80211_sta_state old_state,
|
||||
- enum ieee80211_sta_state new_state)
|
||||
-{
|
||||
- int ret = 0;
|
||||
-
|
||||
- might_sleep();
|
||||
-
|
||||
- sdata = get_bss_sdata(sdata);
|
||||
- if (!check_sdata_in_driver(sdata))
|
||||
- return -EIO;
|
||||
-
|
||||
- trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state);
|
||||
- if (local->ops->sta_state) {
|
||||
- ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta,
|
||||
- old_state, new_state);
|
||||
- } else if (old_state == IEEE80211_STA_AUTH &&
|
||||
- new_state == IEEE80211_STA_ASSOC) {
|
||||
- ret = drv_sta_add(local, sdata, &sta->sta);
|
||||
- if (ret == 0)
|
||||
- sta->uploaded = true;
|
||||
- } else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
- new_state == IEEE80211_STA_AUTH) {
|
||||
- drv_sta_remove(local, sdata, &sta->sta);
|
||||
- }
|
||||
- trace_drv_return_int(local, ret);
|
||||
- return ret;
|
||||
-}
|
||||
+ enum ieee80211_sta_state new_state);
|
||||
|
||||
static inline void drv_sta_rc_update(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
@ -1,30 +0,0 @@ |
||||
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
Date: Wed, 22 Jul 2015 10:42:43 +0200
|
||||
Subject: [PATCH] ath9k: Fix NF CCA limits for AR9287 and AR9227
|
||||
|
||||
The FreeBSD driver [0] uses the same 2G values as for the AR9280 chips.
|
||||
Using the same values in ath9k results in much better throughput for me.
|
||||
|
||||
Before this patch I had a huge amount of packet loss (sometimes up to
|
||||
40%) and the max transfer speed was somewhere around 5Mbit/s. With this
|
||||
patch applied I have zero packet loss and ten times the throughput.
|
||||
My device uses a AR9227 which is the PCI variant of the AR9287.
|
||||
|
||||
[0] http://bxr.su/FreeBSD/sys/dev/ath/ath_hal/ar9002/ar9287.h
|
||||
|
||||
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
|
||||
@@ -610,8 +610,8 @@
|
||||
#define AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ -127
|
||||
#define AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ -116
|
||||
|
||||
-#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -120
|
||||
+#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -112
|
||||
#define AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ -127
|
||||
-#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -110
|
||||
+#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -97
|
||||
|
||||
#endif
|
@ -1,20 +0,0 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Thu, 30 Jul 2015 14:12:25 +0200
|
||||
Subject: [PATCH] mac80211: make local->tx_headroom a multiple of 4
|
||||
|
||||
This ensures that mac80211 generated management frames and beacons are
|
||||
aligned before being passed to the driver
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/main.c
|
||||
+++ b/net/mac80211/main.c
|
||||
@@ -1031,6 +1031,7 @@ int ieee80211_register_hw(struct ieee802
|
||||
*/
|
||||
local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
|
||||
IEEE80211_TX_STATUS_HEADROOM);
|
||||
+ local->tx_headroom = ALIGN(local->tx_headroom, 4);
|
||||
|
||||
debugfs_hw_add(local);
|
||||
|
@ -1,34 +0,0 @@ |
||||
From: Adrien Schildknecht <adrien+dev@schischi.me>
|
||||
Date: Tue, 28 Jul 2015 10:30:16 +0200
|
||||
Subject: [PATCH] mac80211: fix invalid read in minstrel_sort_best_tp_rates()
|
||||
|
||||
At the last iteration of the loop, j may equal zero and thus
|
||||
tp_list[j - 1] causes an invalid read.
|
||||
Changed the logic of the loop so that j - 1 is always >= 0.
|
||||
|
||||
Signed-off-by: Adrien Schildknecht <adrien+dev@schischi.me>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel.c
|
||||
+++ b/net/mac80211/rc80211_minstrel.c
|
||||
@@ -92,14 +92,15 @@ int minstrel_get_tp_avg(struct minstrel_
|
||||
static inline void
|
||||
minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
|
||||
{
|
||||
- int j = MAX_THR_RATES;
|
||||
- struct minstrel_rate_stats *tmp_mrs = &mi->r[j - 1].stats;
|
||||
+ int j;
|
||||
+ struct minstrel_rate_stats *tmp_mrs;
|
||||
struct minstrel_rate_stats *cur_mrs = &mi->r[i].stats;
|
||||
|
||||
- while (j > 0 && (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) >
|
||||
- minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))) {
|
||||
- j--;
|
||||
+ for (j = MAX_THR_RATES; j > 0; --j) {
|
||||
tmp_mrs = &mi->r[tp_list[j - 1]].stats;
|
||||
+ if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) <=
|
||||
+ minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))
|
||||
+ break;
|
||||
}
|
||||
|
||||
if (j < MAX_THR_RATES - 1)
|
@ -1,45 +0,0 @@ |
||||
From: Vineet Gupta <Vineet.Gupta1@synopsys.com>
|
||||
Date: Thu, 9 Jul 2015 13:43:18 +0530
|
||||
Subject: [PATCH] brcmfmac: dhd_sdio.c: use existing atomic_or primitive
|
||||
|
||||
There's already a generic implementation so use that instead.
|
||||
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
|
||||
@@ -2564,15 +2564,6 @@ static inline void brcmf_sdio_clrintr(st
|
||||
}
|
||||
}
|
||||
|
||||
-static void atomic_orr(int val, atomic_t *v)
|
||||
-{
|
||||
- int old_val;
|
||||
-
|
||||
- old_val = atomic_read(v);
|
||||
- while (atomic_cmpxchg(v, old_val, val | old_val) != old_val)
|
||||
- old_val = atomic_read(v);
|
||||
-}
|
||||
-
|
||||
static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
|
||||
{
|
||||
struct brcmf_core *buscore;
|
||||
@@ -2595,7 +2586,7 @@ static int brcmf_sdio_intr_rstatus(struc
|
||||
if (val) {
|
||||
brcmf_sdiod_regwl(bus->sdiodev, addr, val, &ret);
|
||||
bus->sdcnt.f1regdata++;
|
||||
- atomic_orr(val, &bus->intstatus);
|
||||
+ atomic_or(val, &bus->intstatus);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -2712,7 +2703,7 @@ static void brcmf_sdio_dpc(struct brcmf_
|
||||
|
||||
/* Keep still-pending events for next scheduling */
|
||||
if (intstatus)
|
||||
- atomic_orr(intstatus, &bus->intstatus);
|
||||
+ atomic_or(intstatus, &bus->intstatus);
|
||||
|
||||
brcmf_sdio_clrintr(bus);
|
||||
|
@ -1,46 +0,0 @@ |
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Thu, 20 Aug 2015 00:16:42 +0200
|
||||
Subject: [PATCH] brcmfmac: check all combinations when setting wiphy's
|
||||
addresses
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Broadcom is working on better reflection of interface combinations. With
|
||||
upcoming patches we may have 1st combination supporting less interfaces
|
||||
than others.
|
||||
To don't run out of addresses check all combinations to find the one
|
||||
with the greatest max_interfaces value.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -5786,7 +5786,9 @@ static void brcmf_wiphy_wowl_params(stru
|
||||
static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
+ const struct ieee80211_iface_combination *combo;
|
||||
struct ieee80211_supported_band *band;
|
||||
+ u16 max_interfaces = 0;
|
||||
__le32 bandlist[3];
|
||||
u32 n_bands;
|
||||
int err, i;
|
||||
@@ -5799,8 +5801,13 @@ static int brcmf_setup_wiphy(struct wiph
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- for (i = 0; i < wiphy->iface_combinations->max_interfaces &&
|
||||
- i < ARRAY_SIZE(drvr->addresses); i++) {
|
||||
+ for (i = 0, combo = wiphy->iface_combinations;
|
||||
+ i < wiphy->n_iface_combinations; i++, combo++) {
|
||||
+ max_interfaces = max(max_interfaces, combo->max_interfaces);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < max_interfaces && i < ARRAY_SIZE(drvr->addresses);
|
||||
+ i++) {
|
||||
u8 *addr = drvr->addresses[i].addr;
|
||||
|
||||
memcpy(addr, drvr->mac, ETH_ALEN);
|
@ -1,204 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Thu, 20 Aug 2015 22:06:03 +0200
|
||||
Subject: [PATCH] brcmfmac: correct interface combination info
|
||||
|
||||
The interface combination provided by brcmfmac did not truly reflect
|
||||
the combinations supported by driver and/or firmware.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Reviewed-by: Pontus Fuchs <pontusf@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -5695,63 +5695,132 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] =
|
||||
}
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * brcmf_setup_ifmodes() - determine interface modes and combinations.
|
||||
+ *
|
||||
+ * @wiphy: wiphy object.
|
||||
+ * @ifp: interface object needed for feat module api.
|
||||
+ *
|
||||
+ * The interface modes and combinations are determined dynamically here
|
||||
+ * based on firmware functionality.
|
||||
+ *
|
||||
+ * no p2p and no mbss:
|
||||
+ *
|
||||
+ * #STA <= 1, #AP <= 1, channels = 1, 2 total
|
||||
+ *
|
||||
+ * no p2p and mbss:
|
||||
+ *
|
||||
+ * #STA <= 1, #AP <= 1, channels = 1, 2 total
|
||||
+ * #AP <= 4, matching BI, channels = 1, 4 total
|
||||
+ *
|
||||
+ * p2p, no mchan, and mbss:
|
||||
+ *
|
||||
+ * #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 1, 3 total
|
||||
+ * #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
|
||||
+ * #AP <= 4, matching BI, channels = 1, 4 total
|
||||
+ *
|
||||
+ * p2p, mchan, and mbss:
|
||||
+ *
|
||||
+ * #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 2, 3 total
|
||||
+ * #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
|
||||
+ * #AP <= 4, matching BI, channels = 1, 4 total
|
||||
+ */
|
||||
static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
|
||||
{
|
||||
struct ieee80211_iface_combination *combo = NULL;
|
||||
- struct ieee80211_iface_limit *limits = NULL;
|
||||
- int i = 0, max_iface_cnt;
|
||||
+ struct ieee80211_iface_limit *c0_limits = NULL;
|
||||
+ struct ieee80211_iface_limit *p2p_limits = NULL;
|
||||
+ struct ieee80211_iface_limit *mbss_limits = NULL;
|
||||
+ bool mbss, p2p;
|
||||
+ int i, c, n_combos;
|
||||
|
||||
- combo = kzalloc(sizeof(*combo), GFP_KERNEL);
|
||||
+ mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS);
|
||||
+ p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P);
|
||||
+
|
||||
+ n_combos = 1 + !!p2p + !!mbss;
|
||||
+ combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL);
|
||||
if (!combo)
|
||||
goto err;
|
||||
|
||||
- limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL);
|
||||
- if (!limits)
|
||||
+ c0_limits = kcalloc(p2p ? 3 : 2, sizeof(*c0_limits), GFP_KERNEL);
|
||||
+ if (!c0_limits)
|
||||
goto err;
|
||||
|
||||
+ if (p2p) {
|
||||
+ p2p_limits = kcalloc(4, sizeof(*p2p_limits), GFP_KERNEL);
|
||||
+ if (!p2p_limits)
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if (mbss) {
|
||||
+ mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL);
|
||||
+ if (!mbss_limits)
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_AP);
|
||||
|
||||
- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
|
||||
- combo->num_different_channels = 2;
|
||||
- else
|
||||
- combo->num_different_channels = 1;
|
||||
-
|
||||
- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
|
||||
- limits[i].max = 1;
|
||||
- limits[i++].types = BIT(NL80211_IFTYPE_STATION);
|
||||
- limits[i].max = 4;
|
||||
- limits[i++].types = BIT(NL80211_IFTYPE_AP);
|
||||
- max_iface_cnt = 5;
|
||||
- } else {
|
||||
- limits[i].max = 2;
|
||||
- limits[i++].types = BIT(NL80211_IFTYPE_STATION) |
|
||||
- BIT(NL80211_IFTYPE_AP);
|
||||
- max_iface_cnt = 2;
|
||||
- }
|
||||
-
|
||||
- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) {
|
||||
+ c = 0;
|
||||
+ i = 0;
|
||||
+ combo[c].num_different_channels = 1;
|
||||
+ c0_limits[i].max = 1;
|
||||
+ c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
|
||||
+ if (p2p) {
|
||||
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
|
||||
+ combo[c].num_different_channels = 2;
|
||||
wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
- limits[i].max = 1;
|
||||
- limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
- BIT(NL80211_IFTYPE_P2P_GO);
|
||||
- limits[i].max = 1;
|
||||
- limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
- max_iface_cnt += 2;
|
||||
- }
|
||||
- combo->max_interfaces = max_iface_cnt;
|
||||
- combo->limits = limits;
|
||||
- combo->n_limits = i;
|
||||
+ c0_limits[i].max = 1;
|
||||
+ c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
+ c0_limits[i].max = 1;
|
||||
+ c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
+ BIT(NL80211_IFTYPE_P2P_GO);
|
||||
+ } else {
|
||||
+ c0_limits[i].max = 1;
|
||||
+ c0_limits[i++].types = BIT(NL80211_IFTYPE_AP);
|
||||
+ }
|
||||
+ combo[c].max_interfaces = i;
|
||||
+ combo[c].n_limits = i;
|
||||
+ combo[c].limits = c0_limits;
|
||||
+
|
||||
+ if (p2p) {
|
||||
+ c++;
|
||||
+ i = 0;
|
||||
+ combo[c].num_different_channels = 1;
|
||||
+ p2p_limits[i].max = 1;
|
||||
+ p2p_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
|
||||
+ p2p_limits[i].max = 1;
|
||||
+ p2p_limits[i++].types = BIT(NL80211_IFTYPE_AP);
|
||||
+ p2p_limits[i].max = 1;
|
||||
+ p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT);
|
||||
+ p2p_limits[i].max = 1;
|
||||
+ p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
+ combo[c].max_interfaces = i;
|
||||
+ combo[c].n_limits = i;
|
||||
+ combo[c].limits = p2p_limits;
|
||||
+ }
|
||||
|
||||
+ if (mbss) {
|
||||
+ c++;
|
||||
+ combo[c].beacon_int_infra_match = true;
|
||||
+ combo[c].num_different_channels = 1;
|
||||
+ mbss_limits[0].max = 4;
|
||||
+ mbss_limits[0].types = BIT(NL80211_IFTYPE_AP);
|
||||
+ combo[c].max_interfaces = 4;
|
||||
+ combo[c].n_limits = 1;
|
||||
+ combo[c].limits = mbss_limits;
|
||||
+ }
|
||||
+ wiphy->n_iface_combinations = n_combos;
|
||||
wiphy->iface_combinations = combo;
|
||||
- wiphy->n_iface_combinations = 1;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
- kfree(limits);
|
||||
+ kfree(c0_limits);
|
||||
+ kfree(p2p_limits);
|
||||
+ kfree(mbss_limits);
|
||||
kfree(combo);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -6080,11 +6149,15 @@ static void brcmf_cfg80211_reg_notifier(
|
||||
|
||||
static void brcmf_free_wiphy(struct wiphy *wiphy)
|
||||
{
|
||||
+ int i;
|
||||
+
|
||||
if (!wiphy)
|
||||
return;
|
||||
|
||||
- if (wiphy->iface_combinations)
|
||||
- kfree(wiphy->iface_combinations->limits);
|
||||
+ if (wiphy->iface_combinations) {
|
||||
+ for (i = 0; i < wiphy->n_iface_combinations; i++)
|
||||
+ kfree(wiphy->iface_combinations[i].limits);
|
||||
+ }
|
||||
kfree(wiphy->iface_combinations);
|
||||
if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
|
||||
kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
|
@ -1,87 +0,0 @@ |
||||
From: Franky Lin <frankyl@broadcom.com>
|
||||
Date: Thu, 20 Aug 2015 22:06:04 +0200
|
||||
Subject: [PATCH] brcmfmac: add debugfs entry for msgbuf statistics
|
||||
|
||||
Expose ring buffer read/write pointers and other useful statistics
|
||||
through debugfs.
|
||||
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Franky Lin <frankyl@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
@@ -1360,6 +1360,60 @@ void brcmf_msgbuf_delete_flowring(struct
|
||||
}
|
||||
}
|
||||
|
||||
+#ifdef DEBUG
|
||||
+static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data)
|
||||
+{
|
||||
+ struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
|
||||
+ struct brcmf_pub *drvr = bus_if->drvr;
|
||||
+ struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
|
||||
+ struct brcmf_commonring *commonring;
|
||||
+ u16 i;
|
||||
+ struct brcmf_flowring_ring *ring;
|
||||
+ struct brcmf_flowring_hash *hash;
|
||||
+
|
||||
+ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
|
||||
+ seq_printf(seq, "h2d_ctl_submit: rp %4u, wp %4u, depth %4u\n",
|
||||
+ commonring->r_ptr, commonring->w_ptr, commonring->depth);
|
||||
+ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_RXPOST_SUBMIT];
|
||||
+ seq_printf(seq, "h2d_rx_submit: rp %4u, wp %4u, depth %4u\n",
|
||||
+ commonring->r_ptr, commonring->w_ptr, commonring->depth);
|
||||
+ commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_CONTROL_COMPLETE];
|
||||
+ seq_printf(seq, "d2h_ctl_cmplt: rp %4u, wp %4u, depth %4u\n",
|
||||
+ commonring->r_ptr, commonring->w_ptr, commonring->depth);
|
||||
+ commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_TX_COMPLETE];
|
||||
+ seq_printf(seq, "d2h_tx_cmplt: rp %4u, wp %4u, depth %4u\n",
|
||||
+ commonring->r_ptr, commonring->w_ptr, commonring->depth);
|
||||
+ commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE];
|
||||
+ seq_printf(seq, "d2h_rx_cmplt: rp %4u, wp %4u, depth %4u\n",
|
||||
+ commonring->r_ptr, commonring->w_ptr, commonring->depth);
|
||||
+
|
||||
+ seq_printf(seq, "\nh2d_flowrings: depth %u\n",
|
||||
+ BRCMF_H2D_TXFLOWRING_MAX_ITEM);
|
||||
+ seq_puts(seq, "Active flowrings:\n");
|
||||
+ hash = msgbuf->flow->hash;
|
||||
+ for (i = 0; i < msgbuf->flow->nrofrings; i++) {
|
||||
+ if (!msgbuf->flow->rings[i])
|
||||
+ continue;
|
||||
+ ring = msgbuf->flow->rings[i];
|
||||
+ if (ring->status != RING_OPEN)
|
||||
+ continue;
|
||||
+ commonring = msgbuf->flowrings[i];
|
||||
+ hash = &msgbuf->flow->hash[ring->hash_id];
|
||||
+ seq_printf(seq, "id %3u: rp %4u, wp %4u, qlen %4u, blocked %u\n"
|
||||
+ " ifidx %u, fifo %u, da %pM\n",
|
||||
+ i, commonring->r_ptr, commonring->w_ptr,
|
||||
+ skb_queue_len(&ring->skblist), ring->blocked,
|
||||
+ hash->ifidx, hash->fifo, hash->mac);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#else
|
||||
+static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
|
||||
int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
@@ -1460,6 +1514,8 @@ int brcmf_proto_msgbuf_attach(struct brc
|
||||
spin_lock_init(&msgbuf->flowring_work_lock);
|
||||
INIT_LIST_HEAD(&msgbuf->work_queue);
|
||||
|
||||
+ brcmf_debugfs_add_entry(drvr, "msgbuf_stats", brcmf_msgbuf_stats_read);
|
||||
+
|
||||
return 0;
|
||||
|
||||
fail:
|
@ -1,83 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Thu, 20 Aug 2015 22:06:05 +0200
|
||||
Subject: [PATCH] brcmfmac: make use of cfg80211_check_combinations()
|
||||
|
||||
Use cfg80211_check_combinations() so we can bail out early when an
|
||||
interface add or change results in an invalid combination.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -469,6 +469,36 @@ brcmf_find_wpsie(const u8 *parse, u32 le
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
|
||||
+ struct brcmf_cfg80211_vif *vif,
|
||||
+ enum nl80211_iftype new_type)
|
||||
+{
|
||||
+ int iftype_num[NUM_NL80211_IFTYPES];
|
||||
+ struct brcmf_cfg80211_vif *pos;
|
||||
+
|
||||
+ memset(&iftype_num[0], 0, sizeof(iftype_num));
|
||||
+ list_for_each_entry(pos, &cfg->vif_list, list)
|
||||
+ if (pos == vif)
|
||||
+ iftype_num[new_type]++;
|
||||
+ else
|
||||
+ iftype_num[pos->wdev.iftype]++;
|
||||
+
|
||||
+ return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
|
||||
+}
|
||||
+
|
||||
+static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg,
|
||||
+ enum nl80211_iftype new_type)
|
||||
+{
|
||||
+ int iftype_num[NUM_NL80211_IFTYPES];
|
||||
+ struct brcmf_cfg80211_vif *pos;
|
||||
+
|
||||
+ memset(&iftype_num[0], 0, sizeof(iftype_num));
|
||||
+ list_for_each_entry(pos, &cfg->vif_list, list)
|
||||
+ iftype_num[pos->wdev.iftype]++;
|
||||
+
|
||||
+ iftype_num[new_type]++;
|
||||
+ return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
|
||||
+}
|
||||
|
||||
static void convert_key_from_CPU(struct brcmf_wsec_key *key,
|
||||
struct brcmf_wsec_key_le *key_le)
|
||||
@@ -663,8 +693,14 @@ static struct wireless_dev *brcmf_cfg802
|
||||
struct vif_params *params)
|
||||
{
|
||||
struct wireless_dev *wdev;
|
||||
+ int err;
|
||||
|
||||
brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
|
||||
+ err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);
|
||||
+ if (err) {
|
||||
+ brcmf_err("iface validation failed: err=%d\n", err);
|
||||
+ return ERR_PTR(err);
|
||||
+ }
|
||||
switch (type) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
@@ -823,8 +859,12 @@ brcmf_cfg80211_change_iface(struct wiphy
|
||||
s32 ap = 0;
|
||||
s32 err = 0;
|
||||
|
||||
- brcmf_dbg(TRACE, "Enter, ndev=%p, type=%d\n", ndev, type);
|
||||
-
|
||||
+ brcmf_dbg(TRACE, "Enter, idx=%d, type=%d\n", ifp->bssidx, type);
|
||||
+ err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type);
|
||||
+ if (err) {
|
||||
+ brcmf_err("iface validation failed: err=%d\n", err);
|
||||
+ return err;
|
||||
+ }
|
||||
switch (type) {
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
case NL80211_IFTYPE_WDS:
|
@ -1,48 +0,0 @@ |
||||
From: Franky Lin <frankyl@broadcom.com>
|
||||
Date: Thu, 20 Aug 2015 22:06:06 +0200
|
||||
Subject: [PATCH] brcmfmac: block the correct flowring when backup queue
|
||||
overflow
|
||||
|
||||
brcmf_flowring_block blocks the last active flowring under the same
|
||||
interface instead of the one provided by caller. This could lead to a
|
||||
dead lock of netif stop if there are more than one flowring under the
|
||||
interface and the traffic is high enough so brcmf_flowring_enqueue can
|
||||
not unblock the ring right away.
|
||||
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Signed-off-by: Franky Lin <frankyl@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
|
||||
@@ -194,11 +194,15 @@ static void brcmf_flowring_block(struct
|
||||
spin_lock_irqsave(&flow->block_lock, flags);
|
||||
|
||||
ring = flow->rings[flowid];
|
||||
+ if (ring->blocked == blocked) {
|
||||
+ spin_unlock_irqrestore(&flow->block_lock, flags);
|
||||
+ return;
|
||||
+ }
|
||||
ifidx = brcmf_flowring_ifidx_get(flow, flowid);
|
||||
|
||||
currently_blocked = false;
|
||||
for (i = 0; i < flow->nrofrings; i++) {
|
||||
- if (flow->rings[i]) {
|
||||
+ if ((flow->rings[i]) && (i != flowid)) {
|
||||
ring = flow->rings[i];
|
||||
if ((ring->status == RING_OPEN) &&
|
||||
(brcmf_flowring_ifidx_get(flow, i) == ifidx)) {
|
||||
@@ -209,8 +213,8 @@ static void brcmf_flowring_block(struct
|
||||
}
|
||||
}
|
||||
}
|
||||
- ring->blocked = blocked;
|
||||
- if (currently_blocked == blocked) {
|
||||
+ flow->rings[flowid]->blocked = blocked;
|
||||
+ if (currently_blocked) {
|
||||
spin_unlock_irqrestore(&flow->block_lock, flags);
|
||||
return;
|
||||
}
|
@ -1,52 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Thu, 20 Aug 2015 22:06:07 +0200
|
||||
Subject: [PATCH] brcmfmac: bump highest event number for 4339 firmware
|
||||
|
||||
The event mask length is determined by the highest event number
|
||||
that is specified in the driver. When this length is shorter than
|
||||
firmware expects setting event mask will fail and device becomes
|
||||
pretty useless. This issue was reported with bcm4339 firmware that
|
||||
was recently released.
|
||||
|
||||
Reported-by: Pontus Fuchs <pontusf@broadcom.com>
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Reviewed-by: Pontus Fuchs <pontusf@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
|
||||
@@ -85,7 +85,6 @@ struct brcmf_event;
|
||||
BRCMF_ENUM_DEF(IF, 54) \
|
||||
BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \
|
||||
BRCMF_ENUM_DEF(RSSI, 56) \
|
||||
- BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \
|
||||
BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \
|
||||
BRCMF_ENUM_DEF(ACTION_FRAME, 59) \
|
||||
BRCMF_ENUM_DEF(ACTION_FRAME_COMPLETE, 60) \
|
||||
@@ -103,8 +102,7 @@ struct brcmf_event;
|
||||
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
|
||||
BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \
|
||||
BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \
|
||||
- BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \
|
||||
- BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128)
|
||||
+ BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127)
|
||||
|
||||
#define BRCMF_ENUM_DEF(id, val) \
|
||||
BRCMF_E_##id = (val),
|
||||
@@ -112,7 +110,11 @@ struct brcmf_event;
|
||||
/* firmware event codes sent by the dongle */
|
||||
enum brcmf_fweh_event_code {
|
||||
BRCMF_FWEH_EVENT_ENUM_DEFLIST
|
||||
- BRCMF_E_LAST
|
||||
+ /* this determines event mask length which must match
|
||||
+ * minimum length check in device firmware so it is
|
||||
+ * hard-coded here.
|
||||
+ */
|
||||
+ BRCMF_E_LAST = 139
|
||||
};
|
||||
#undef BRCMF_ENUM_DEF
|
||||
|
@ -1,138 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Wed, 26 Aug 2015 22:14:53 +0200
|
||||
Subject: [PATCH] brcmfmac: consolidate ifp lookup in driver core
|
||||
|
||||
In rx path the firmware provide an interface index which is used to
|
||||
map to a struct brcmf_if instance. However, this involves some trick
|
||||
that is done in two places. This is changed by having driver core
|
||||
providing brcmf_get_ifp() function.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
|
||||
@@ -276,6 +276,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
|
||||
struct sk_buff *pktbuf)
|
||||
{
|
||||
struct brcmf_proto_bcdc_header *h;
|
||||
+ struct brcmf_if *ifp;
|
||||
|
||||
brcmf_dbg(BCDC, "Enter\n");
|
||||
|
||||
@@ -289,30 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
|
||||
trace_brcmf_bcdchdr(pktbuf->data);
|
||||
h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
|
||||
|
||||
- *ifidx = BCDC_GET_IF_IDX(h);
|
||||
- if (*ifidx >= BRCMF_MAX_IFS) {
|
||||
- brcmf_err("rx data ifnum out of range (%d)\n", *ifidx);
|
||||
+ ifp = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h));
|
||||
+ if (IS_ERR_OR_NULL(ifp)) {
|
||||
+ brcmf_dbg(INFO, "no matching ifp found\n");
|
||||
return -EBADE;
|
||||
}
|
||||
- /* The ifidx is the idx to map to matching netdev/ifp. When receiving
|
||||
- * events this is easy because it contains the bssidx which maps
|
||||
- * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
|
||||
- * bssidx 1 is used for p2p0 and no data can be received or
|
||||
- * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
|
||||
- */
|
||||
- if (*ifidx)
|
||||
- (*ifidx)++;
|
||||
-
|
||||
if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) !=
|
||||
BCDC_PROTO_VER) {
|
||||
brcmf_err("%s: non-BCDC packet received, flags 0x%x\n",
|
||||
- brcmf_ifname(drvr, *ifidx), h->flags);
|
||||
+ brcmf_ifname(drvr, ifp->ifidx), h->flags);
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
if (h->flags & BCDC_FLAG_SUM_GOOD) {
|
||||
brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
|
||||
- brcmf_ifname(drvr, *ifidx), h->flags);
|
||||
+ brcmf_ifname(drvr, ifp->ifidx), h->flags);
|
||||
pktbuf->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
}
|
||||
|
||||
@@ -320,12 +312,15 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
|
||||
|
||||
skb_pull(pktbuf, BCDC_HEADER_LEN);
|
||||
if (do_fws)
|
||||
- brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf);
|
||||
+ brcmf_fws_hdrpull(drvr, ifp->ifidx, h->data_offset << 2,
|
||||
+ pktbuf);
|
||||
else
|
||||
skb_pull(pktbuf, h->data_offset << 2);
|
||||
|
||||
if (pktbuf->len == 0)
|
||||
return -ENODATA;
|
||||
+
|
||||
+ *ifidx = ifp->ifidx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
@@ -83,6 +83,25 @@ char *brcmf_ifname(struct brcmf_pub *drv
|
||||
return "<if_none>";
|
||||
}
|
||||
|
||||
+struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx)
|
||||
+{
|
||||
+ if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
|
||||
+ brcmf_err("ifidx %d out of range\n", ifidx);
|
||||
+ return ERR_PTR(-ERANGE);
|
||||
+ }
|
||||
+
|
||||
+ /* The ifidx is the idx to map to matching netdev/ifp. When receiving
|
||||
+ * events this is easy because it contains the bssidx which maps
|
||||
+ * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
|
||||
+ * bssidx 1 is used for p2p0 and no data can be received or
|
||||
+ * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
|
||||
+ */
|
||||
+ if (ifidx)
|
||||
+ ifidx++;
|
||||
+
|
||||
+ return drvr->iflist[ifidx];
|
||||
+}
|
||||
+
|
||||
static void _brcmf_set_multicast_list(struct work_struct *work)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
|
||||
@@ -202,7 +202,7 @@ int brcmf_netdev_wait_pend8021x(struct b
|
||||
|
||||
/* Return pointer to interface name */
|
||||
char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
|
||||
-
|
||||
+struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx);
|
||||
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
|
||||
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
|
||||
char *name, u8 *mac_addr);
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
@@ -1081,16 +1081,8 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
- /* The ifidx is the idx to map to matching netdev/ifp. When receiving
|
||||
- * events this is easy because it contains the bssidx which maps
|
||||
- * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
|
||||
- * bssidx 1 is used for p2p0 and no data can be received or
|
||||
- * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
|
||||
- */
|
||||
- if (ifidx)
|
||||
- (ifidx)++;
|
||||
- ifp = msgbuf->drvr->iflist[ifidx];
|
||||
- if (!ifp || !ifp->ndev) {
|
||||
+ ifp = brcmf_get_ifp(msgbuf->drvr, ifidx);
|
||||
+ if (IS_ERR_OR_NULL(ifp) || !ifp->ndev) {
|
||||
brcmf_err("Received pkt for invalid ifidx %d\n", ifidx);
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
return;
|
@ -1,222 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Wed, 26 Aug 2015 22:14:54 +0200
|
||||
Subject: [PATCH] brcmfmac: make brcmf_proto_hdrpull() return struct
|
||||
brcmf_if instance
|
||||
|
||||
Avoid spreading the ifidx in the driver, but have it return the
|
||||
struct brcmf_if instance.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
|
||||
@@ -272,11 +272,11 @@ brcmf_proto_bcdc_hdrpush(struct brcmf_pu
|
||||
}
|
||||
|
||||
static int
|
||||
-brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
|
||||
- struct sk_buff *pktbuf)
|
||||
+brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws,
|
||||
+ struct sk_buff *pktbuf, struct brcmf_if **ifp)
|
||||
{
|
||||
struct brcmf_proto_bcdc_header *h;
|
||||
- struct brcmf_if *ifp;
|
||||
+ struct brcmf_if *tmp_if;
|
||||
|
||||
brcmf_dbg(BCDC, "Enter\n");
|
||||
|
||||
@@ -290,21 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
|
||||
trace_brcmf_bcdchdr(pktbuf->data);
|
||||
h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
|
||||
|
||||
- ifp = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h));
|
||||
- if (IS_ERR_OR_NULL(ifp)) {
|
||||
+ tmp_if = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h));
|
||||
+ if (!tmp_if) {
|
||||
brcmf_dbg(INFO, "no matching ifp found\n");
|
||||
return -EBADE;
|
||||
}
|
||||
if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) !=
|
||||
BCDC_PROTO_VER) {
|
||||
brcmf_err("%s: non-BCDC packet received, flags 0x%x\n",
|
||||
- brcmf_ifname(drvr, ifp->ifidx), h->flags);
|
||||
+ brcmf_ifname(drvr, tmp_if->ifidx), h->flags);
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
if (h->flags & BCDC_FLAG_SUM_GOOD) {
|
||||
brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
|
||||
- brcmf_ifname(drvr, ifp->ifidx), h->flags);
|
||||
+ brcmf_ifname(drvr, tmp_if->ifidx), h->flags);
|
||||
pktbuf->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
}
|
||||
|
||||
@@ -312,7 +312,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
|
||||
|
||||
skb_pull(pktbuf, BCDC_HEADER_LEN);
|
||||
if (do_fws)
|
||||
- brcmf_fws_hdrpull(drvr, ifp->ifidx, h->data_offset << 2,
|
||||
+ brcmf_fws_hdrpull(drvr, tmp_if->ifidx, h->data_offset << 2,
|
||||
pktbuf);
|
||||
else
|
||||
skb_pull(pktbuf, h->data_offset << 2);
|
||||
@@ -320,7 +320,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
|
||||
if (pktbuf->len == 0)
|
||||
return -ENODATA;
|
||||
|
||||
- *ifidx = ifp->ifidx;
|
||||
+ *ifp = tmp_if;
|
||||
return 0;
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
@@ -87,7 +87,7 @@ struct brcmf_if *brcmf_get_ifp(struct br
|
||||
{
|
||||
if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
|
||||
brcmf_err("ifidx %d out of range\n", ifidx);
|
||||
- return ERR_PTR(-ERANGE);
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
/* The ifidx is the idx to map to matching netdev/ifp. When receiving
|
||||
@@ -539,17 +539,15 @@ void brcmf_rx_frame(struct device *dev,
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
struct brcmf_skb_reorder_data *rd;
|
||||
- u8 ifidx;
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
|
||||
|
||||
/* process and remove protocol-specific header */
|
||||
- ret = brcmf_proto_hdrpull(drvr, true, &ifidx, skb);
|
||||
- ifp = drvr->iflist[ifidx];
|
||||
+ ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp);
|
||||
|
||||
if (ret || !ifp || !ifp->ndev) {
|
||||
- if ((ret != -ENODATA) && ifp)
|
||||
+ if (ret != -ENODATA && ifp)
|
||||
ifp->stats.rx_errors++;
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
return;
|
||||
@@ -592,17 +590,17 @@ void brcmf_txcomplete(struct device *dev
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
- u8 ifidx;
|
||||
+ struct brcmf_if *ifp;
|
||||
|
||||
/* await txstatus signal for firmware if active */
|
||||
if (brcmf_fws_fc_active(drvr->fws)) {
|
||||
if (!success)
|
||||
brcmf_fws_bustxfail(drvr->fws, txp);
|
||||
} else {
|
||||
- if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp))
|
||||
+ if (brcmf_proto_hdrpull(drvr, false, txp, &ifp))
|
||||
brcmu_pkt_buf_free_skb(txp);
|
||||
else
|
||||
- brcmf_txfinalize(drvr, txp, ifidx, success);
|
||||
+ brcmf_txfinalize(drvr, txp, ifp->ifidx, success);
|
||||
}
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
|
||||
@@ -1448,7 +1448,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i
|
||||
struct sk_buff *skb;
|
||||
struct brcmf_skbuff_cb *skcb;
|
||||
struct brcmf_fws_mac_descriptor *entry = NULL;
|
||||
- u8 ifidx;
|
||||
+ struct brcmf_if *ifp;
|
||||
|
||||
brcmf_dbg(DATA, "flags %d\n", flags);
|
||||
|
||||
@@ -1497,15 +1497,16 @@ brcmf_fws_txs_process(struct brcmf_fws_i
|
||||
}
|
||||
brcmf_fws_macdesc_return_req_credit(skb);
|
||||
|
||||
- if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) {
|
||||
+ ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
|
||||
+ if (ret) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!remove_from_hanger)
|
||||
- ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx,
|
||||
+ ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx,
|
||||
genbit, seq);
|
||||
if (remove_from_hanger || ret)
|
||||
- brcmf_txfinalize(fws->drvr, skb, ifidx, true);
|
||||
+ brcmf_txfinalize(fws->drvr, skb, ifp->ifidx, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1848,7 +1849,7 @@ static int brcmf_fws_commit_skb(struct b
|
||||
entry->transit_count--;
|
||||
if (entry->suppressed)
|
||||
entry->suppr_transit_count--;
|
||||
- brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
|
||||
+ (void)brcmf_proto_hdrpull(fws->drvr, false, skb, NULL);
|
||||
goto rollback;
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
@@ -522,7 +522,7 @@ static int brcmf_msgbuf_set_dcmd(struct
|
||||
|
||||
|
||||
static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws,
|
||||
- u8 *ifidx, struct sk_buff *skb)
|
||||
+ struct sk_buff *skb, struct brcmf_if **ifp)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -1082,7 +1082,7 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
ifp = brcmf_get_ifp(msgbuf->drvr, ifidx);
|
||||
- if (IS_ERR_OR_NULL(ifp) || !ifp->ndev) {
|
||||
+ if (!ifp || !ifp->ndev) {
|
||||
brcmf_err("Received pkt for invalid ifidx %d\n", ifidx);
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
return;
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/proto.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.h
|
||||
@@ -24,8 +24,8 @@ enum proto_addr_mode {
|
||||
|
||||
|
||||
struct brcmf_proto {
|
||||
- int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
|
||||
- struct sk_buff *skb);
|
||||
+ int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws,
|
||||
+ struct sk_buff *skb, struct brcmf_if **ifp);
|
||||
int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
||||
void *buf, uint len);
|
||||
int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
|
||||
@@ -46,9 +46,19 @@ int brcmf_proto_attach(struct brcmf_pub
|
||||
void brcmf_proto_detach(struct brcmf_pub *drvr);
|
||||
|
||||
static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
|
||||
- u8 *ifidx, struct sk_buff *skb)
|
||||
+ struct sk_buff *skb,
|
||||
+ struct brcmf_if **ifp)
|
||||
{
|
||||
- return drvr->proto->hdrpull(drvr, do_fws, ifidx, skb);
|
||||
+ struct brcmf_if *tmp = NULL;
|
||||
+
|
||||
+ /* assure protocol is always called with
|
||||
+ * non-null initialized pointer.
|
||||
+ */
|
||||
+ if (ifp)
|
||||
+ *ifp = NULL;
|
||||
+ else
|
||||
+ ifp = &tmp;
|
||||
+ return drvr->proto->hdrpull(drvr, do_fws, skb, ifp);
|
||||
}
|
||||
static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx,
|
||||
uint cmd, void *buf, uint len)
|
@ -1,87 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Wed, 26 Aug 2015 22:14:55 +0200
|
||||
Subject: [PATCH] brcmfmac: change parameters for
|
||||
brcmf_remove_interface()
|
||||
|
||||
Just pass the interface to be removed, ie. the struct brcmf_if instance.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -4983,7 +4983,7 @@ brcmf_notify_connect_status_ap(struct br
|
||||
brcmf_dbg(CONN, "AP mode link down\n");
|
||||
complete(&cfg->vif_disabled);
|
||||
if (ifp->vif->mbss)
|
||||
- brcmf_remove_interface(ifp->drvr, ifp->bssidx);
|
||||
+ brcmf_remove_interface(ifp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
@@ -887,12 +887,13 @@ static void brcmf_del_if(struct brcmf_pu
|
||||
}
|
||||
}
|
||||
|
||||
-void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx)
|
||||
+void brcmf_remove_interface(struct brcmf_if *ifp)
|
||||
{
|
||||
- if (drvr->iflist[bssidx]) {
|
||||
- brcmf_fws_del_interface(drvr->iflist[bssidx]);
|
||||
- brcmf_del_if(drvr, bssidx);
|
||||
- }
|
||||
+ if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bssidx] != ifp))
|
||||
+ return;
|
||||
+
|
||||
+ brcmf_fws_del_interface(ifp);
|
||||
+ brcmf_del_if(ifp->drvr, ifp->bssidx);
|
||||
}
|
||||
|
||||
int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr)
|
||||
@@ -1122,7 +1123,7 @@ void brcmf_detach(struct device *dev)
|
||||
|
||||
/* make sure primary interface removed last */
|
||||
for (i = BRCMF_MAX_IFS-1; i > -1; i--)
|
||||
- brcmf_remove_interface(drvr, i);
|
||||
+ brcmf_remove_interface(drvr->iflist[i]);
|
||||
|
||||
brcmf_cfg80211_detach(drvr->config);
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
|
||||
@@ -206,7 +206,7 @@ struct brcmf_if *brcmf_get_ifp(struct br
|
||||
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
|
||||
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
|
||||
char *name, u8 *mac_addr);
|
||||
-void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx);
|
||||
+void brcmf_remove_interface(struct brcmf_if *ifp);
|
||||
int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
|
||||
void brcmf_txflowblock_if(struct brcmf_if *ifp,
|
||||
enum brcmf_netif_stop_reason reason, bool state);
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
|
||||
@@ -222,7 +222,7 @@ static void brcmf_fweh_handle_if_event(s
|
||||
err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
|
||||
|
||||
if (ifp && ifevent->action == BRCMF_E_IF_DEL)
|
||||
- brcmf_remove_interface(drvr, ifevent->bssidx);
|
||||
+ brcmf_remove_interface(ifp);
|
||||
}
|
||||
|
||||
/**
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
|
||||
@@ -2140,7 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(stru
|
||||
{
|
||||
cfg80211_unregister_wdev(&vif->wdev);
|
||||
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
|
||||
- brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx);
|
||||
+ brcmf_remove_interface(vif->ifp);
|
||||
brcmf_free_vif(vif);
|
||||
}
|
||||
|
@ -1,92 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Wed, 26 Aug 2015 22:14:56 +0200
|
||||
Subject: [PATCH] brcmfmac: only call brcmf_cfg80211_detach() when attach
|
||||
was successful
|
||||
|
||||
In brcmf_bus_start() the function brcmf_cfg80211_attach() is called which
|
||||
may fail. If this happens we should not call brcmf_cfg80211_detach() in
|
||||
the failure path as it will result in NULL pointer dereference:
|
||||
|
||||
brcmf_fweh_activate_events: Set event_msgs error (-5)
|
||||
brcmf_bus_start: failed: -5
|
||||
brcmf_sdio_firmware_callback: dongle is not responding
|
||||
BUG: unable to handle kernel NULL pointer dereference at 0000000000000068
|
||||
IP: [<ffffffff811e8f08>] kernfs_find_ns+0x18/0xd0
|
||||
PGD 0
|
||||
Oops: 0000 [#1] SMP
|
||||
Modules linked in: brcmfmac(O) brcmutil(O) cfg80211 auth_rpcgss
|
||||
CPU: 1 PID: 45 Comm: kworker/1:1 Tainted: G O
|
||||
Hardware name: Dell Inc. Latitude E6410/07XJP9, BIOS A07 02/15/2011
|
||||
Workqueue: events request_firmware_work_func
|
||||
task: ffff880036c09ac0 ti: ffff880036dd4000 task.ti: ffff880036dd4000
|
||||
RIP: 0010:[<ffffffff811e8f08>] [<ffffffff811e8f08>] kernfs_find_ns+0x18/0xd0
|
||||
RSP: 0018:ffff880036dd7a28 EFLAGS: 00010246
|
||||
RAX: ffff880036c09ac0 RBX: 0000000000000000 RCX: 000000007fffffff
|
||||
RDX: 0000000000000000 RSI: ffffffff816578b9 RDI: 0000000000000000
|
||||
RBP: ffff880036dd7a48 R08: 0000000000000000 R09: ffff880036c0b340
|
||||
R10: 00000000000002ec R11: ffff880036dd7b08 R12: ffffffff816578b9
|
||||
R13: 0000000000000000 R14: ffffffff816578b9 R15: ffff8800c6c87000
|
||||
FS: 0000000000000000(0000) GS:ffff88012bc40000(0000) knlGS:0000000000000000
|
||||
CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
|
||||
CR2: 0000000000000068 CR3: 0000000001a0b000 CR4: 00000000000006e0
|
||||
Stack:
|
||||
0000000000000000 ffffffff816578b9 0000000000000000 ffff8800c0d003c8
|
||||
ffff880036dd7a78 ffffffff811e8ff5 0000000ffffffff1 ffffffff81a9b060
|
||||
ffff8800c789f880 ffff8800c0d00000 ffff880036dd7a98 ffffffff811ebe0d
|
||||
Call Trace:
|
||||
[<ffffffff811e8ff5>] kernfs_find_and_get_ns+0x35/0x60
|
||||
[<ffffffff811ebe0d>] sysfs_unmerge_group+0x1d/0x60
|
||||
[<ffffffff81404ef2>] dpm_sysfs_remove+0x22/0x60
|
||||
[<ffffffff813f9db9>] device_del+0x49/0x240
|
||||
[<ffffffff815da768>] rfkill_unregister+0x58/0xc0
|
||||
[<ffffffffa06bd91b>] wiphy_unregister+0xab/0x2f0 [cfg80211]
|
||||
[<ffffffffa0742fe3>] brcmf_cfg80211_detach+0x23/0x50 [brcmfmac]
|
||||
[<ffffffffa074d986>] brcmf_detach+0x86/0xe0 [brcmfmac]
|
||||
[<ffffffffa0757de8>] brcmf_sdio_remove+0x48/0x120 [brcmfmac]
|
||||
[<ffffffffa0758ed9>] brcmf_sdiod_remove+0x29/0xd0 [brcmfmac]
|
||||
[<ffffffffa0759031>] brcmf_ops_sdio_remove+0xb1/0x110 [brcmfmac]
|
||||
[<ffffffffa001c267>] sdio_bus_remove+0x37/0x100 [mmc_core]
|
||||
[<ffffffff813fe026>] __device_release_driver+0x96/0x130
|
||||
[<ffffffff813fe0e3>] device_release_driver+0x23/0x30
|
||||
[<ffffffffa0754bc8>] brcmf_sdio_firmware_callback+0x2a8/0x5d0 [brcmfmac]
|
||||
[<ffffffffa074deaf>] brcmf_fw_request_nvram_done+0x15f/0x5e0 [brcmfmac]
|
||||
[<ffffffff8140142f>] ? devres_add+0x3f/0x50
|
||||
[<ffffffff810642b5>] ? usermodehelper_read_unlock+0x15/0x20
|
||||
[<ffffffff81400000>] ? platform_match+0x70/0xa0
|
||||
[<ffffffff8140f400>] request_firmware_work_func+0x30/0x60
|
||||
[<ffffffff8106828c>] process_one_work+0x14c/0x3d0
|
||||
[<ffffffff8106862a>] worker_thread+0x11a/0x450
|
||||
[<ffffffff81068510>] ? process_one_work+0x3d0/0x3d0
|
||||
[<ffffffff8106d692>] kthread+0xd2/0xf0
|
||||
[<ffffffff8106d5c0>] ? kthread_create_on_node+0x180/0x180
|
||||
[<ffffffff815ed35f>] ret_from_fork+0x3f/0x70
|
||||
[<ffffffff8106d5c0>] ? kthread_create_on_node+0x180/0x180
|
||||
Code: e9 40 fe ff ff 48 89 d8 eb 87 66 0f 1f 84 00 00 00 00 00 66 66 66 66
|
||||
90 55 48 89 e5 41 56 49 89 f6 41 55 49 89 d5 31 d2 41 54 53 <0f> b7
|
||||
47 68 48 8b 5f 48 66 c1 e8 05 83 e0 01 4d 85 ed 0f b6 c8
|
||||
RIP [<ffffffff811e8f08>] kernfs_find_ns+0x18/0xd0
|
||||
RSP <ffff880036dd7a28>
|
||||
CR2: 0000000000000068
|
||||
---[ end trace 87d6ec0d3fe46740 ]---
|
||||
|
||||
Reported-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
@@ -1049,7 +1049,10 @@ int brcmf_bus_start(struct device *dev)
|
||||
fail:
|
||||
if (ret < 0) {
|
||||
brcmf_err("failed: %d\n", ret);
|
||||
- brcmf_cfg80211_detach(drvr->config);
|
||||
+ if (drvr->config) {
|
||||
+ brcmf_cfg80211_detach(drvr->config);
|
||||
+ drvr->config = NULL;
|
||||
+ }
|
||||
if (drvr->fws) {
|
||||
brcmf_fws_del_interface(ifp);
|
||||
brcmf_fws_deinit(drvr);
|
@ -1,105 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Wed, 26 Aug 2015 22:14:57 +0200
|
||||
Subject: [PATCH] brcmfmac: correct detection of p2pdev interface event
|
||||
|
||||
The p2pdev interface is setup in firmware resulting in a interface
|
||||
event. This event has role and no-if flag. When role is p2p client
|
||||
and no-if flag is set it indicates that this is the p2pdev interface.
|
||||
This info is used in handling the event and adding interface in the
|
||||
driver.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
@@ -795,7 +795,7 @@ fail:
|
||||
}
|
||||
|
||||
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
|
||||
- char *name, u8 *mac_addr)
|
||||
+ bool is_p2pdev, char *name, u8 *mac_addr)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
struct net_device *ndev;
|
||||
@@ -821,7 +821,7 @@ struct brcmf_if *brcmf_add_if(struct brc
|
||||
}
|
||||
}
|
||||
|
||||
- if (!brcmf_p2p_enable && bssidx == 1) {
|
||||
+ if (!brcmf_p2p_enable && is_p2pdev) {
|
||||
/* this is P2P_DEVICE interface */
|
||||
brcmf_dbg(INFO, "allocate non-netdev interface\n");
|
||||
ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
|
||||
@@ -999,12 +999,12 @@ int brcmf_bus_start(struct device *dev)
|
||||
brcmf_dbg(TRACE, "\n");
|
||||
|
||||
/* add primary networking interface */
|
||||
- ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
|
||||
+ ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL);
|
||||
if (IS_ERR(ifp))
|
||||
return PTR_ERR(ifp);
|
||||
|
||||
if (brcmf_p2p_enable)
|
||||
- p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL);
|
||||
+ p2p_ifp = brcmf_add_if(drvr, 1, 0, false, "p2p%d", NULL);
|
||||
else
|
||||
p2p_ifp = NULL;
|
||||
if (IS_ERR(p2p_ifp))
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
|
||||
@@ -205,7 +205,7 @@ char *brcmf_ifname(struct brcmf_pub *drv
|
||||
struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx);
|
||||
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
|
||||
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
|
||||
- char *name, u8 *mac_addr);
|
||||
+ bool is_p2pdev, char *name, u8 *mac_addr);
|
||||
void brcmf_remove_interface(struct brcmf_if *ifp);
|
||||
int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
|
||||
void brcmf_txflowblock_if(struct brcmf_if *ifp,
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
|
||||
@@ -179,6 +179,7 @@ static void brcmf_fweh_handle_if_event(s
|
||||
{
|
||||
struct brcmf_if_event *ifevent = data;
|
||||
struct brcmf_if *ifp;
|
||||
+ bool is_p2pdev;
|
||||
int err = 0;
|
||||
|
||||
brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n",
|
||||
@@ -186,18 +187,16 @@ static void brcmf_fweh_handle_if_event(s
|
||||
ifevent->flags, ifevent->role);
|
||||
|
||||
/* The P2P Device interface event must not be ignored
|
||||
- * contrary to what firmware tells us. The only way to
|
||||
- * distinguish the P2P Device is by looking at the ifidx
|
||||
- * and bssidx received.
|
||||
+ * contrary to what firmware tells us.
|
||||
*/
|
||||
- if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) &&
|
||||
- (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
|
||||
+ is_p2pdev = (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) &&
|
||||
+ ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT;
|
||||
+ if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
|
||||
brcmf_dbg(EVENT, "event can be ignored\n");
|
||||
return;
|
||||
}
|
||||
if (ifevent->ifidx >= BRCMF_MAX_IFS) {
|
||||
- brcmf_err("invalid interface index: %u\n",
|
||||
- ifevent->ifidx);
|
||||
+ brcmf_err("invalid interface index: %u\n", ifevent->ifidx);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -207,7 +206,7 @@ static void brcmf_fweh_handle_if_event(s
|
||||
brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
|
||||
emsg->addr);
|
||||
ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx,
|
||||
- emsg->ifname, emsg->addr);
|
||||
+ is_p2pdev, emsg->ifname, emsg->addr);
|
||||
if (IS_ERR(ifp))
|
||||
return;
|
||||
brcmf_fws_add_interface(ifp);
|
@ -1,126 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Wed, 26 Aug 2015 22:14:58 +0200
|
||||
Subject: [PATCH] brcmfmac: use brcmf_get_ifp() to map ifidx to struct
|
||||
brcmf_if instance
|
||||
|
||||
The knowledge on how to map the interface index to a struct brcmf_if
|
||||
instance is in brcmf_get_ifp() so use that function when only the
|
||||
interface index is known instead of accessing brcmf_pub::iflist
|
||||
directly.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
|
||||
@@ -149,7 +149,7 @@ static s32 brcmf_btcoex_params_read(stru
|
||||
static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci,
|
||||
bool trump_sco)
|
||||
{
|
||||
- struct brcmf_if *ifp = btci->cfg->pub->iflist[0];
|
||||
+ struct brcmf_if *ifp = brcmf_get_ifp(btci->cfg->pub, 0);
|
||||
|
||||
if (trump_sco && !btci->saved_regs_part2) {
|
||||
/* this should reduce eSCO agressive
|
||||
@@ -468,7 +468,7 @@ int brcmf_btcoex_set_mode(struct brcmf_c
|
||||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy);
|
||||
struct brcmf_btcoex_info *btci = cfg->btcoex;
|
||||
- struct brcmf_if *ifp = cfg->pub->iflist[0];
|
||||
+ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
|
||||
|
||||
switch (mode) {
|
||||
case BRCMF_BTCOEX_DISABLED:
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -6213,7 +6213,7 @@ static void brcmf_free_wiphy(struct wiph
|
||||
struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
|
||||
struct device *busdev)
|
||||
{
|
||||
- struct net_device *ndev = drvr->iflist[0]->ndev;
|
||||
+ struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev;
|
||||
struct brcmf_cfg80211_info *cfg;
|
||||
struct wiphy *wiphy;
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
|
||||
@@ -121,7 +121,7 @@ static void brcmf_feat_iovar_int_set(str
|
||||
|
||||
void brcmf_feat_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
- struct brcmf_if *ifp = drvr->iflist[0];
|
||||
+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
|
||||
|
||||
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
|
||||
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
|
||||
@@ -221,7 +221,7 @@ static void brcmf_flowring_block(struct
|
||||
|
||||
bus_if = dev_get_drvdata(flow->dev);
|
||||
drvr = bus_if->drvr;
|
||||
- ifp = drvr->iflist[ifidx];
|
||||
+ ifp = brcmf_get_ifp(drvr, ifidx);
|
||||
brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW, blocked);
|
||||
|
||||
spin_unlock_irqrestore(&flow->block_lock, flags);
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
|
||||
@@ -334,7 +334,7 @@ void brcmf_fweh_attach(struct brcmf_pub
|
||||
void brcmf_fweh_detach(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct brcmf_fweh_info *fweh = &drvr->fweh;
|
||||
- struct brcmf_if *ifp = drvr->iflist[0];
|
||||
+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
|
||||
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
|
||||
|
||||
if (ifp) {
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
|
||||
@@ -972,7 +972,7 @@ static void
|
||||
brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
|
||||
u8 if_id)
|
||||
{
|
||||
- struct brcmf_if *ifp = fws->drvr->iflist[!if_id ? 0 : if_id + 1];
|
||||
+ struct brcmf_if *ifp = brcmf_get_ifp(fws->drvr, if_id);
|
||||
|
||||
if (WARN_ON(!ifp))
|
||||
return;
|
||||
@@ -2118,6 +2118,7 @@ static int brcmf_debugfs_fws_stats_read(
|
||||
int brcmf_fws_init(struct brcmf_pub *drvr)
|
||||
{
|
||||
struct brcmf_fws_info *fws;
|
||||
+ struct brcmf_if *ifp;
|
||||
u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS;
|
||||
int rc;
|
||||
u32 mode;
|
||||
@@ -2177,21 +2178,22 @@ int brcmf_fws_init(struct brcmf_pub *drv
|
||||
* continue. Set mode back to none indicating not enabled.
|
||||
*/
|
||||
fws->fw_signals = true;
|
||||
- if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) {
|
||||
+ ifp = brcmf_get_ifp(drvr, 0);
|
||||
+ if (brcmf_fil_iovar_int_set(ifp, "tlv", tlv)) {
|
||||
brcmf_err("failed to set bdcv2 tlv signaling\n");
|
||||
fws->fcmode = BRCMF_FWS_FCMODE_NONE;
|
||||
fws->fw_signals = false;
|
||||
}
|
||||
|
||||
- if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1))
|
||||
+ if (brcmf_fil_iovar_int_set(ifp, "ampdu_hostreorder", 1))
|
||||
brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n");
|
||||
|
||||
/* Enable seq number reuse, if supported */
|
||||
- if (brcmf_fil_iovar_int_get(drvr->iflist[0], "wlfc_mode", &mode) == 0) {
|
||||
+ if (brcmf_fil_iovar_int_get(ifp, "wlfc_mode", &mode) == 0) {
|
||||
if (BRCMF_FWS_MODE_GET_REUSESEQ(mode)) {
|
||||
mode = 0;
|
||||
BRCMF_FWS_MODE_SET_REUSESEQ(mode, 1);
|
||||
- if (brcmf_fil_iovar_int_set(drvr->iflist[0],
|
||||
+ if (brcmf_fil_iovar_int_set(ifp,
|
||||
"wlfc_mode", mode) == 0) {
|
||||
BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1);
|
||||
}
|
@ -1,122 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Wed, 26 Aug 2015 22:14:59 +0200
|
||||
Subject: [PATCH] brcmfmac: pass struct brcmf_if instance in
|
||||
brcmf_txfinalize()
|
||||
|
||||
Most call sites of brcmf_txfinalize already have struct brcmf_if
|
||||
instance so pass that to brcmf_txfinalize() as the function
|
||||
needs it anyway.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
@@ -560,17 +560,11 @@ void brcmf_rx_frame(struct device *dev,
|
||||
brcmf_netif_rx(ifp, skb);
|
||||
}
|
||||
|
||||
-void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
|
||||
- bool success)
|
||||
+void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success)
|
||||
{
|
||||
- struct brcmf_if *ifp;
|
||||
struct ethhdr *eh;
|
||||
u16 type;
|
||||
|
||||
- ifp = drvr->iflist[ifidx];
|
||||
- if (!ifp)
|
||||
- goto done;
|
||||
-
|
||||
eh = (struct ethhdr *)(txp->data);
|
||||
type = ntohs(eh->h_proto);
|
||||
|
||||
@@ -582,7 +576,7 @@ void brcmf_txfinalize(struct brcmf_pub *
|
||||
|
||||
if (!success)
|
||||
ifp->stats.tx_errors++;
|
||||
-done:
|
||||
+
|
||||
brcmu_pkt_buf_free_skb(txp);
|
||||
}
|
||||
|
||||
@@ -600,7 +594,7 @@ void brcmf_txcomplete(struct device *dev
|
||||
if (brcmf_proto_hdrpull(drvr, false, txp, &ifp))
|
||||
brcmu_pkt_buf_free_skb(txp);
|
||||
else
|
||||
- brcmf_txfinalize(drvr, txp, ifp->ifidx, success);
|
||||
+ brcmf_txfinalize(ifp, txp, success);
|
||||
}
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
|
||||
@@ -210,8 +210,7 @@ void brcmf_remove_interface(struct brcmf
|
||||
int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
|
||||
void brcmf_txflowblock_if(struct brcmf_if *ifp,
|
||||
enum brcmf_netif_stop_reason reason, bool state);
|
||||
-void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
|
||||
- bool success);
|
||||
+void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
|
||||
void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
|
||||
|
||||
/* Sets dongle media info (drv_version, mac address). */
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
|
||||
@@ -1506,7 +1506,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i
|
||||
ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx,
|
||||
genbit, seq);
|
||||
if (remove_from_hanger || ret)
|
||||
- brcmf_txfinalize(fws->drvr, skb, ifp->ifidx, true);
|
||||
+ brcmf_txfinalize(ifp, skb, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1905,7 +1905,7 @@ int brcmf_fws_process_skb(struct brcmf_i
|
||||
if (fws->avoid_queueing) {
|
||||
rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb);
|
||||
if (rc < 0)
|
||||
- brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
|
||||
+ brcmf_txfinalize(ifp, skb, false);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1929,7 +1929,7 @@ int brcmf_fws_process_skb(struct brcmf_i
|
||||
brcmf_fws_schedule_deq(fws);
|
||||
} else {
|
||||
brcmf_err("drop skb: no hanger slot\n");
|
||||
- brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
|
||||
+ brcmf_txfinalize(ifp, skb, false);
|
||||
rc = -ENOMEM;
|
||||
}
|
||||
brcmf_fws_unlock(fws);
|
||||
@@ -2009,8 +2009,9 @@ static void brcmf_fws_dequeue_worker(str
|
||||
ret = brcmf_proto_txdata(drvr, ifidx, 0, skb);
|
||||
brcmf_fws_lock(fws);
|
||||
if (ret < 0)
|
||||
- brcmf_txfinalize(drvr, skb, ifidx,
|
||||
- false);
|
||||
+ brcmf_txfinalize(brcmf_get_ifp(drvr,
|
||||
+ ifidx),
|
||||
+ skb, false);
|
||||
if (fws->bus_flow_blocked)
|
||||
break;
|
||||
}
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
|
||||
@@ -873,7 +873,11 @@ brcmf_msgbuf_process_txstatus(struct brc
|
||||
commonring = msgbuf->flowrings[flowid];
|
||||
atomic_dec(&commonring->outstanding_tx);
|
||||
|
||||
- brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true);
|
||||
+ /* Hante: i believe this was a bug as tx_status->msg.ifidx was used
|
||||
+ * in brcmf_txfinalize as index in drvr->iflist. Can you confirm/deny?
|
||||
+ */
|
||||
+ brcmf_txfinalize(brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx),
|
||||
+ skb, true);
|
||||
}
|
||||
|
||||
|
@ -1,92 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Wed, 26 Aug 2015 22:15:00 +0200
|
||||
Subject: [PATCH] brcmfmac: add mapping for interface index to bsscfg
|
||||
index
|
||||
|
||||
Because the P2P Device interface in firmware uses the same interface
|
||||
index as the primary interface we use the bsscfg index as index in the
|
||||
struct brcmf_pub::iflist. However, in the data path we get the interface
|
||||
index and not the bsscfg index. So we need a mapping of interface index
|
||||
to bsscfg index, which can be determined upon handle adding the interface.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
@@ -85,21 +85,20 @@ char *brcmf_ifname(struct brcmf_pub *drv
|
||||
|
||||
struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx)
|
||||
{
|
||||
+ struct brcmf_if *ifp;
|
||||
+ s32 bssidx;
|
||||
+
|
||||
if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
|
||||
brcmf_err("ifidx %d out of range\n", ifidx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- /* The ifidx is the idx to map to matching netdev/ifp. When receiving
|
||||
- * events this is easy because it contains the bssidx which maps
|
||||
- * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
|
||||
- * bssidx 1 is used for p2p0 and no data can be received or
|
||||
- * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
|
||||
- */
|
||||
- if (ifidx)
|
||||
- ifidx++;
|
||||
+ ifp = NULL;
|
||||
+ bssidx = drvr->if2bss[ifidx];
|
||||
+ if (bssidx >= 0)
|
||||
+ ifp = drvr->iflist[bssidx];
|
||||
|
||||
- return drvr->iflist[ifidx];
|
||||
+ return ifp;
|
||||
}
|
||||
|
||||
static void _brcmf_set_multicast_list(struct work_struct *work)
|
||||
@@ -831,6 +830,8 @@ struct brcmf_if *brcmf_add_if(struct brc
|
||||
|
||||
ifp = netdev_priv(ndev);
|
||||
ifp->ndev = ndev;
|
||||
+ /* store mapping ifidx to bssidx */
|
||||
+ drvr->if2bss[ifidx] = bssidx;
|
||||
}
|
||||
|
||||
ifp->drvr = drvr;
|
||||
@@ -855,6 +856,7 @@ static void brcmf_del_if(struct brcmf_pu
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
ifp = drvr->iflist[bssidx];
|
||||
+ drvr->if2bss[ifp->ifidx] = -1;
|
||||
drvr->iflist[bssidx] = NULL;
|
||||
if (!ifp) {
|
||||
brcmf_err("Null interface, idx=%d\n", bssidx);
|
||||
@@ -862,6 +864,7 @@ static void brcmf_del_if(struct brcmf_pu
|
||||
}
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
|
||||
if (ifp->ndev) {
|
||||
+ drvr->if2bss[ifp->ifidx] = -1;
|
||||
if (bssidx == 0) {
|
||||
if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
|
||||
rtnl_lock();
|
||||
@@ -926,6 +929,7 @@ int brcmf_attach(struct device *dev)
|
||||
if (!drvr)
|
||||
return -ENOMEM;
|
||||
|
||||
+ memset(drvr->if2bss, 0xFF, sizeof(drvr->if2bss));
|
||||
mutex_init(&drvr->proto_block);
|
||||
|
||||
/* Link to bus module */
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
|
||||
@@ -122,6 +122,7 @@ struct brcmf_pub {
|
||||
struct mac_address addresses[BRCMF_MAX_IFS];
|
||||
|
||||
struct brcmf_if *iflist[BRCMF_MAX_IFS];
|
||||
+ s32 if2bss[BRCMF_MAX_IFS];
|
||||
|
||||
struct mutex proto_block;
|
||||
unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
|
@ -1,103 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Wed, 26 Aug 2015 22:15:01 +0200
|
||||
Subject: [PATCH] brcmfmac: add dedicated debug level for firmware
|
||||
console logging
|
||||
|
||||
Both PCIe and SDIO devices have the possibility to log the firmware
|
||||
console output in kernel log. For PCIe it is logged when PCIE debug
|
||||
level is enabled. For SDIO it is logged when user specifies a non-zero
|
||||
console interval through debugfs. This patch tries to make it a
|
||||
bit more consistent. The firmware console output is only logged when
|
||||
FWCON debug level is enabled.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Reviewed-by: Pontus Fuchs <pontusf@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h
|
||||
@@ -37,6 +37,7 @@
|
||||
#define BRCMF_SDIO_VAL 0x00020000
|
||||
#define BRCMF_MSGBUF_VAL 0x00040000
|
||||
#define BRCMF_PCIE_VAL 0x00080000
|
||||
+#define BRCMF_FWCON_VAL 0x00100000
|
||||
|
||||
/* set default print format */
|
||||
#undef pr_fmt
|
||||
@@ -78,6 +79,7 @@ do { \
|
||||
#define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL)
|
||||
#define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL)
|
||||
#define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL)
|
||||
+#define BRCMF_FWCON_ON() (brcmf_msg_level & BRCMF_FWCON_VAL)
|
||||
|
||||
#else /* defined(DEBUG) || defined(CPTCFG_BRCM_TRACING) */
|
||||
|
||||
@@ -90,6 +92,7 @@ do { \
|
||||
#define BRCMF_GLOM_ON() 0
|
||||
#define BRCMF_EVENT_ON() 0
|
||||
#define BRCMF_FIL_ON() 0
|
||||
+#define BRCMF_FWCON_ON() 0
|
||||
|
||||
#endif /* defined(DEBUG) || defined(CPTCFG_BRCM_TRACING) */
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
@@ -644,7 +644,7 @@ static void brcmf_pcie_bus_console_init(
|
||||
addr = console->base_addr + BRCMF_CONSOLE_BUFSIZE_OFFSET;
|
||||
console->bufsize = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
|
||||
- brcmf_dbg(PCIE, "Console: base %x, buf %x, size %d\n",
|
||||
+ brcmf_dbg(FWCON, "Console: base %x, buf %x, size %d\n",
|
||||
console->base_addr, console->buf_addr, console->bufsize);
|
||||
}
|
||||
|
||||
@@ -656,6 +656,9 @@ static void brcmf_pcie_bus_console_read(
|
||||
u8 ch;
|
||||
u32 newidx;
|
||||
|
||||
+ if (!BRCMF_FWCON_ON())
|
||||
+ return;
|
||||
+
|
||||
console = &devinfo->shared.console;
|
||||
addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET;
|
||||
newidx = brcmf_pcie_read_tcm32(devinfo, addr);
|
||||
@@ -677,7 +680,7 @@ static void brcmf_pcie_bus_console_read(
|
||||
}
|
||||
if (ch == '\n') {
|
||||
console->log_str[console->log_idx] = 0;
|
||||
- brcmf_dbg(PCIE, "CONSOLE: %s", console->log_str);
|
||||
+ pr_debug("CONSOLE: %s", console->log_str);
|
||||
console->log_idx = 0;
|
||||
}
|
||||
}
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
|
||||
@@ -123,6 +123,7 @@ struct rte_console {
|
||||
|
||||
#define BRCMF_FIRSTREAD (1 << 6)
|
||||
|
||||
+#define BRCMF_CONSOLE 10 /* watchdog interval to poll console */
|
||||
|
||||
/* SBSDIO_DEVICE_CTL */
|
||||
|
||||
@@ -3204,6 +3205,8 @@ static void brcmf_sdio_debugfs_create(st
|
||||
if (IS_ERR_OR_NULL(dentry))
|
||||
return;
|
||||
|
||||
+ bus->console_interval = BRCMF_CONSOLE;
|
||||
+
|
||||
brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read);
|
||||
brcmf_debugfs_add_entry(drvr, "counters",
|
||||
brcmf_debugfs_sdio_count_read);
|
||||
@@ -3613,7 +3616,7 @@ static void brcmf_sdio_bus_watchdog(stru
|
||||
}
|
||||
#ifdef DEBUG
|
||||
/* Poll for console output periodically */
|
||||
- if (bus->sdiodev->state == BRCMF_SDIOD_DATA &&
|
||||
+ if (bus->sdiodev->state == BRCMF_SDIOD_DATA && BRCMF_FWCON_ON() &&
|
||||
bus->console_interval != 0) {
|
||||
bus->console.count += BRCMF_WD_POLL_MS;
|
||||
if (bus->console.count >= bus->console_interval) {
|
@ -1,34 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Wed, 26 Aug 2015 22:15:02 +0200
|
||||
Subject: [PATCH] brcmfmac: remove ifidx parameter from
|
||||
brcmf_fws_txstatus_suppressed()
|
||||
|
||||
The brcmf_fws_txstatus_suppressed() function prototype specifies an
|
||||
ifidx parameter which is not used within the function implementation.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
|
||||
@@ -1398,7 +1398,7 @@ done:
|
||||
}
|
||||
|
||||
static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
|
||||
- struct sk_buff *skb, u8 ifidx,
|
||||
+ struct sk_buff *skb,
|
||||
u32 genbit, u16 seq)
|
||||
{
|
||||
struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
|
||||
@@ -1503,7 +1503,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!remove_from_hanger)
|
||||
- ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx,
|
||||
+ ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
|
||||
genbit, seq);
|
||||
if (remove_from_hanger || ret)
|
||||
brcmf_txfinalize(ifp, skb, true);
|
@ -1,97 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Wed, 26 Aug 2015 22:15:03 +0200
|
||||
Subject: [PATCH] brcmfmac: change prototype for brcmf_fws_hdrpull()
|
||||
|
||||
Instead of passing ifidx and drvr just pass struct brcmf_if pointer
|
||||
which holds both parameters.
|
||||
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
|
||||
@@ -312,8 +312,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
|
||||
|
||||
skb_pull(pktbuf, BCDC_HEADER_LEN);
|
||||
if (do_fws)
|
||||
- brcmf_fws_hdrpull(drvr, tmp_if->ifidx, h->data_offset << 2,
|
||||
- pktbuf);
|
||||
+ brcmf_fws_hdrpull(tmp_if, h->data_offset << 2, pktbuf);
|
||||
else
|
||||
skb_pull(pktbuf, h->data_offset << 2);
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
|
||||
@@ -1616,11 +1616,10 @@ static int brcmf_fws_notify_bcmc_credit_
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
|
||||
- struct sk_buff *skb)
|
||||
+void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_skb_reorder_data *rd;
|
||||
- struct brcmf_fws_info *fws = drvr->fws;
|
||||
+ struct brcmf_fws_info *fws = ifp->drvr->fws;
|
||||
u8 *signal_data;
|
||||
s16 data_len;
|
||||
u8 type;
|
||||
@@ -1630,20 +1629,20 @@ int brcmf_fws_hdrpull(struct brcmf_pub *
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(HDRS, "enter: ifidx %d, skblen %u, sig %d\n",
|
||||
- ifidx, skb->len, signal_len);
|
||||
+ ifp->ifidx, skb->len, siglen);
|
||||
|
||||
- WARN_ON(signal_len > skb->len);
|
||||
+ WARN_ON(siglen > skb->len);
|
||||
|
||||
- if (!signal_len)
|
||||
- return 0;
|
||||
+ if (!siglen)
|
||||
+ return;
|
||||
/* if flow control disabled, skip to packet data and leave */
|
||||
if ((!fws) || (!fws->fw_signals)) {
|
||||
- skb_pull(skb, signal_len);
|
||||
- return 0;
|
||||
+ skb_pull(skb, siglen);
|
||||
+ return;
|
||||
}
|
||||
|
||||
fws->stats.header_pulls++;
|
||||
- data_len = signal_len;
|
||||
+ data_len = siglen;
|
||||
signal_data = skb->data;
|
||||
|
||||
status = BRCMF_FWS_RET_OK_NOSCHEDULE;
|
||||
@@ -1731,14 +1730,12 @@ int brcmf_fws_hdrpull(struct brcmf_pub *
|
||||
/* signalling processing result does
|
||||
* not affect the actual ethernet packet.
|
||||
*/
|
||||
- skb_pull(skb, signal_len);
|
||||
+ skb_pull(skb, siglen);
|
||||
|
||||
/* this may be a signal-only packet
|
||||
*/
|
||||
if (skb->len == 0)
|
||||
fws->stats.header_only_pkt++;
|
||||
-
|
||||
- return 0;
|
||||
}
|
||||
|
||||
static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
|
||||
@@ -21,8 +21,7 @@
|
||||
int brcmf_fws_init(struct brcmf_pub *drvr);
|
||||
void brcmf_fws_deinit(struct brcmf_pub *drvr);
|
||||
bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
|
||||
-int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
|
||||
- struct sk_buff *skb);
|
||||
+void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb);
|
||||
int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb);
|
||||
|
||||
void brcmf_fws_reset_interface(struct brcmf_if *ifp);
|
@ -1,99 +0,0 @@ |
||||
From: Arend van Spriel <arend@broadcom.com>
|
||||
Date: Wed, 26 Aug 2015 22:15:04 +0200
|
||||
Subject: [PATCH] brcmfmac: introduce brcmf_net_detach() function
|
||||
|
||||
In case of error during brcmf_bus_start() the network interfaces were
|
||||
freed using free_netdev(). However, the interfaces may have additional
|
||||
memory allocated which is not freed. The netdev has destructor set to
|
||||
brcmf_cfg80211_free_netdev() which frees the additional memory if
|
||||
allocated and call free_netdev(). The brcmf_net_detach() either calls
|
||||
brcmf_cfg80211_free_netdev() directly or uses unregister_netdev() when
|
||||
struct net_device::reg_state indicates the netdev was registered.
|
||||
|
||||
Reported-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
|
||||
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
|
||||
@@ -4747,7 +4747,8 @@ void brcmf_cfg80211_free_netdev(struct n
|
||||
ifp = netdev_priv(ndev);
|
||||
vif = ifp->vif;
|
||||
|
||||
- brcmf_free_vif(vif);
|
||||
+ if (vif)
|
||||
+ brcmf_free_vif(vif);
|
||||
free_netdev(ndev);
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
|
||||
@@ -718,8 +718,6 @@ int brcmf_net_attach(struct brcmf_if *if
|
||||
}
|
||||
|
||||
brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
|
||||
-
|
||||
- ndev->destructor = brcmf_cfg80211_free_netdev;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -729,6 +727,14 @@ fail:
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
+static void brcmf_net_detach(struct net_device *ndev)
|
||||
+{
|
||||
+ if (ndev->reg_state == NETREG_REGISTERED)
|
||||
+ unregister_netdev(ndev);
|
||||
+ else
|
||||
+ brcmf_cfg80211_free_netdev(ndev);
|
||||
+}
|
||||
+
|
||||
static int brcmf_net_p2p_open(struct net_device *ndev)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
@@ -805,8 +811,7 @@ struct brcmf_if *brcmf_add_if(struct brc
|
||||
ifp->ndev->name);
|
||||
if (ifidx) {
|
||||
netif_stop_queue(ifp->ndev);
|
||||
- unregister_netdev(ifp->ndev);
|
||||
- free_netdev(ifp->ndev);
|
||||
+ brcmf_net_detach(ifp->ndev);
|
||||
drvr->iflist[bssidx] = NULL;
|
||||
} else {
|
||||
brcmf_err("ignore IF event\n");
|
||||
@@ -828,6 +833,7 @@ struct brcmf_if *brcmf_add_if(struct brc
|
||||
if (!ndev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
+ ndev->destructor = brcmf_cfg80211_free_netdev;
|
||||
ifp = netdev_priv(ndev);
|
||||
ifp->ndev = ndev;
|
||||
/* store mapping ifidx to bssidx */
|
||||
@@ -879,8 +885,7 @@ static void brcmf_del_if(struct brcmf_pu
|
||||
cancel_work_sync(&ifp->setmacaddr_work);
|
||||
cancel_work_sync(&ifp->multicast_work);
|
||||
}
|
||||
- /* unregister will take care of freeing it */
|
||||
- unregister_netdev(ifp->ndev);
|
||||
+ brcmf_net_detach(ifp->ndev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1056,11 +1061,11 @@ fail:
|
||||
brcmf_fws_deinit(drvr);
|
||||
}
|
||||
if (drvr->iflist[0]) {
|
||||
- free_netdev(ifp->ndev);
|
||||
+ brcmf_net_detach(ifp->ndev);
|
||||
drvr->iflist[0] = NULL;
|
||||
}
|
||||
if (p2p_ifp) {
|
||||
- free_netdev(p2p_ifp->ndev);
|
||||
+ brcmf_net_detach(p2p_ifp->ndev);
|
||||
drvr->iflist[1] = NULL;
|
||||
}
|
||||
return ret;
|
@ -1,193 +0,0 @@ |
||||
From: Hante Meuleman <meuleman@broadcom.com>
|
||||
Date: Thu, 27 Aug 2015 16:14:06 +0200
|
||||
Subject: [PATCH] brcmfmac: Reset PCIE devices after recognition.
|
||||
|
||||
When PCIE type devices are being FW reloaded without being properly
|
||||
reset then the device ends up in a locked state, requiring the
|
||||
device to be completely powered down. This patch adds a reset
|
||||
through watchdog at the moment the device (cores) has been
|
||||
recognized. This will solve warm reboot issues.
|
||||
|
||||
Cc: Rafal Milecki <zajec5@gmail.com>
|
||||
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
|
||||
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
|
||||
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
|
||||
Signed-off-by: Arend van Spriel <arend@broadcom.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
|
||||
@@ -101,6 +101,9 @@
|
||||
/* ARM Cortex M3 core, ID 0x82a */
|
||||
#define BCM4329_CORE_ARM_BASE 0x18002000
|
||||
|
||||
+/* Max possibly supported memory size (limited by IO mapped memory) */
|
||||
+#define BRCMF_CHIP_MAX_MEMSIZE (4 * 1024 * 1024)
|
||||
+
|
||||
#define CORE_SB(base, field) \
|
||||
(base + SBCONFIGOFF + offsetof(struct sbconfig, field))
|
||||
#define SBCOREREV(sbidh) \
|
||||
@@ -687,6 +690,12 @@ static int brcmf_chip_get_raminfo(struct
|
||||
brcmf_err("RAM size is undetermined\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
+
|
||||
+ if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) {
|
||||
+ brcmf_err("RAM size is incorrect\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -899,6 +908,15 @@ static int brcmf_chip_recognition(struct
|
||||
|
||||
/* assure chip is passive for core access */
|
||||
brcmf_chip_set_passive(&ci->pub);
|
||||
+
|
||||
+ /* Call bus specific reset function now. Cores have been determined
|
||||
+ * but further access may require a chip specific reset at this point.
|
||||
+ */
|
||||
+ if (ci->ops->reset) {
|
||||
+ ci->ops->reset(ci->ctx, &ci->pub);
|
||||
+ brcmf_chip_set_passive(&ci->pub);
|
||||
+ }
|
||||
+
|
||||
return brcmf_chip_get_raminfo(ci);
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h
|
||||
@@ -73,6 +73,7 @@ struct brcmf_buscore_ops {
|
||||
u32 (*read32)(void *ctx, u32 addr);
|
||||
void (*write32)(void *ctx, u32 addr, u32 value);
|
||||
int (*prepare)(void *ctx);
|
||||
+ int (*reset)(void *ctx, struct brcmf_chip *chip);
|
||||
int (*setup)(void *ctx, struct brcmf_chip *chip);
|
||||
void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
|
||||
};
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
|
||||
@@ -74,6 +74,8 @@ enum brcmf_pcie_state {
|
||||
#define BRCMF_PCIE_REG_INTMASK 0x94
|
||||
#define BRCMF_PCIE_REG_SBMBX 0x98
|
||||
|
||||
+#define BRCMF_PCIE_REG_LINK_STATUS_CTRL 0xBC
|
||||
+
|
||||
#define BRCMF_PCIE_PCIE2REG_INTMASK 0x24
|
||||
#define BRCMF_PCIE_PCIE2REG_MAILBOXINT 0x48
|
||||
#define BRCMF_PCIE_PCIE2REG_MAILBOXMASK 0x4C
|
||||
@@ -466,6 +468,7 @@ brcmf_pcie_select_core(struct brcmf_pcie
|
||||
|
||||
static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
|
||||
{
|
||||
+ struct brcmf_core *core;
|
||||
u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD,
|
||||
BRCMF_PCIE_CFGREG_PM_CSR,
|
||||
BRCMF_PCIE_CFGREG_MSI_CAP,
|
||||
@@ -484,32 +487,38 @@ static void brcmf_pcie_reset_device(stru
|
||||
if (!devinfo->ci)
|
||||
return;
|
||||
|
||||
+ /* Disable ASPM */
|
||||
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
|
||||
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
|
||||
- BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
|
||||
- lsc = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
|
||||
+ pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
|
||||
+ &lsc);
|
||||
val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB);
|
||||
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, val);
|
||||
+ pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
|
||||
+ val);
|
||||
|
||||
+ /* Watchdog reset */
|
||||
brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);
|
||||
WRITECC32(devinfo, watchdog, 4);
|
||||
msleep(100);
|
||||
|
||||
+ /* Restore ASPM */
|
||||
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
|
||||
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
|
||||
- BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
|
||||
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, lsc);
|
||||
+ pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
|
||||
+ lsc);
|
||||
|
||||
- brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
|
||||
- for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
|
||||
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
|
||||
- cfg_offset[i]);
|
||||
- val = brcmf_pcie_read_reg32(devinfo,
|
||||
- BRCMF_PCIE_PCIE2REG_CONFIGDATA);
|
||||
- brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
|
||||
- cfg_offset[i], val);
|
||||
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA,
|
||||
- val);
|
||||
+ core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
|
||||
+ if (core->rev <= 13) {
|
||||
+ for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
|
||||
+ brcmf_pcie_write_reg32(devinfo,
|
||||
+ BRCMF_PCIE_PCIE2REG_CONFIGADDR,
|
||||
+ cfg_offset[i]);
|
||||
+ val = brcmf_pcie_read_reg32(devinfo,
|
||||
+ BRCMF_PCIE_PCIE2REG_CONFIGDATA);
|
||||
+ brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
|
||||
+ cfg_offset[i], val);
|
||||
+ brcmf_pcie_write_reg32(devinfo,
|
||||
+ BRCMF_PCIE_PCIE2REG_CONFIGDATA,
|
||||
+ val);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,8 +528,6 @@ static void brcmf_pcie_attach(struct brc
|
||||
u32 config;
|
||||
|
||||
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
|
||||
- if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0)
|
||||
- brcmf_pcie_reset_device(devinfo);
|
||||
/* BAR1 window may not be sized properly */
|
||||
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
|
||||
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
|
||||
@@ -1636,6 +1643,23 @@ static int brcmf_pcie_buscoreprep(void *
|
||||
}
|
||||
|
||||
|
||||
+static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
|
||||
+{
|
||||
+ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
|
||||
+ u32 val;
|
||||
+
|
||||
+ devinfo->ci = chip;
|
||||
+ brcmf_pcie_reset_device(devinfo);
|
||||
+
|
||||
+ val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
|
||||
+ if (val != 0xffffffff)
|
||||
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
|
||||
+ val);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip,
|
||||
u32 rstvec)
|
||||
{
|
||||
@@ -1647,6 +1671,7 @@ static void brcmf_pcie_buscore_activate(
|
||||
|
||||
static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
|
||||
.prepare = brcmf_pcie_buscoreprep,
|
||||
+ .reset = brcmf_pcie_buscore_reset,
|
||||
.activate = brcmf_pcie_buscore_activate,
|
||||
.read32 = brcmf_pcie_buscore_read32,
|
||||
.write32 = brcmf_pcie_buscore_write32,
|
||||
@@ -1814,7 +1839,6 @@ brcmf_pcie_remove(struct pci_dev *pdev)
|
||||
brcmf_pcie_intr_disable(devinfo);
|
||||
|
||||
brcmf_detach(&pdev->dev);
|
||||
- brcmf_pcie_reset_device(devinfo);
|
||||
|
||||
kfree(bus->bus_priv.pcie);
|
||||
kfree(bus->msgbuf->flowrings);
|
@ -1,33 +0,0 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Sun, 13 Sep 2015 22:26:10 +0200
|
||||
Subject: [PATCH] ath10k: fix DMA related firmware crashes on multiple devices
|
||||
|
||||
Some platforms really don't like DMA bursts of 256 bytes, and this
|
||||
causes the firmware to crash when sending beacons.
|
||||
Also, changing this based on the firmware version does not seem to make
|
||||
much sense, so use 128 bytes for all versions.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath10k/hw.h
|
||||
@@ -340,7 +340,7 @@ enum ath10k_hw_rate_cck {
|
||||
#define TARGET_10X_MAX_FRAG_ENTRIES 0
|
||||
|
||||
/* 10.2 parameters */
|
||||
-#define TARGET_10_2_DMA_BURST_SIZE 1
|
||||
+#define TARGET_10_2_DMA_BURST_SIZE 0
|
||||
|
||||
/* Target specific defines for WMI-TLV firmware */
|
||||
#define TARGET_TLV_NUM_VDEVS 4
|
||||
@@ -397,7 +397,7 @@ enum ath10k_hw_rate_cck {
|
||||
|
||||
#define TARGET_10_4_TX_DBG_LOG_SIZE 1024
|
||||
#define TARGET_10_4_NUM_WDS_ENTRIES 32
|
||||
-#define TARGET_10_4_DMA_BURST_SIZE 1
|
||||
+#define TARGET_10_4_DMA_BURST_SIZE 0
|
||||
#define TARGET_10_4_MAC_AGGR_DELIM 0
|
||||
#define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1
|
||||
#define TARGET_10_4_VOW_CONFIG 0
|
@ -1,33 +0,0 @@ |
||||
From: Miaoqing Pan <miaoqing@qca.qualcomm.com>
|
||||
Date: Tue, 1 Sep 2015 10:56:09 +0800
|
||||
Subject: [PATCH] ath9k: enable hw manual peak calibration for QCA9561
|
||||
|
||||
This patch fix https://lists.openwrt.org/pipermail/openwrt-devel/
|
||||
2015-August/034979.html. As the peak detect calibration is set
|
||||
incorrectly.
|
||||
|
||||
Signed-off-by: Miaoqing Pan <miaoqing@qca.qualcomm.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
|
||||
@@ -1249,7 +1249,8 @@ static void ar9003_hw_manual_peak_cal(st
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
|
||||
AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0);
|
||||
|
||||
- if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
|
||||
+ if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
|
||||
+ AR_SREV_9561(ah)) {
|
||||
if (is_2g)
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
|
||||
AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR,
|
||||
@@ -1640,7 +1641,8 @@ static bool ar9003_hw_init_cal_soc(struc
|
||||
|
||||
skip_tx_iqcal:
|
||||
if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
|
||||
- if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) {
|
||||
+ if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah) ||
|
||||
+ AR_SREV_9561(ah)) {
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (!(ah->rxchainmask & (1 << i)))
|
||||
continue;
|
@ -1,23 +0,0 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Thu, 24 Sep 2015 14:10:07 +0200
|
||||
Subject: [PATCH] mac80211: fix tx sequence number assignment with software
|
||||
queue + fast-xmit
|
||||
|
||||
When using software queueing, tx sequence number assignment happens at
|
||||
ieee80211_tx_dequeue time, so the fast-xmit codepath must not do that.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -2766,7 +2766,8 @@ static bool ieee80211_xmit_fast(struct i
|
||||
|
||||
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
|
||||
*ieee80211_get_qos_ctl(hdr) = tid;
|
||||
- hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid);
|
||||
+ if (!sta->sta.txq[0])
|
||||
+ hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid);
|
||||
} else {
|
||||
info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
|
||||
hdr->seq_ctrl = cpu_to_le16(sdata->sequence_number);
|
@ -1,45 +0,0 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Thu, 24 Sep 2015 14:11:40 +0200
|
||||
Subject: [PATCH] mac80211: fix handling of PS filtering with fast-xmit
|
||||
|
||||
Fixes dropped packets in the tx path in case a non-PS station triggers
|
||||
the tx filter.
|
||||
|
||||
Cc: stable@vger.kernel.org # 4.2
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/status.c
|
||||
+++ b/net/mac80211/status.c
|
||||
@@ -101,6 +101,7 @@ static void ieee80211_handle_filtered_fr
|
||||
* when it wakes up for the next time.
|
||||
*/
|
||||
set_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT);
|
||||
+ ieee80211_clear_fast_xmit(sta);
|
||||
|
||||
/*
|
||||
* This code races in the following way:
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -1217,8 +1217,10 @@ ieee80211_tx_prepare(struct ieee80211_su
|
||||
|
||||
if (!tx->sta)
|
||||
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
|
||||
- else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT))
|
||||
+ else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT)) {
|
||||
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
|
||||
+ ieee80211_check_fast_xmit(tx->sta);
|
||||
+ }
|
||||
|
||||
info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT;
|
||||
|
||||
@@ -2450,7 +2452,8 @@ void ieee80211_check_fast_xmit(struct st
|
||||
|
||||
if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
|
||||
test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
|
||||
- test_sta_flag(sta, WLAN_STA_PS_DELIVER))
|
||||
+ test_sta_flag(sta, WLAN_STA_PS_DELIVER) ||
|
||||
+ test_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT))
|
||||
goto out;
|
||||
|
||||
if (sdata->noack_map)
|
@ -1,22 +0,0 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Thu, 24 Sep 2015 16:57:37 +0200
|
||||
Subject: [PATCH] ath9k: declare required extra tx headroom
|
||||
|
||||
ath9k inserts padding between the 802.11 header and the data area (to
|
||||
align it). Since it didn't declare this extra required headroom, this
|
||||
led to some nasty issues like randomly dropped packets in some setups.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -875,6 +875,7 @@ static void ath9k_set_hw_capab(struct at
|
||||
hw->max_rate_tries = 10;
|
||||
hw->sta_data_size = sizeof(struct ath_node);
|
||||
hw->vif_data_size = sizeof(struct ath_vif);
|
||||
+ hw->extra_tx_headroom = 4;
|
||||
|
||||
hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
|
||||
hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
|
@ -1,37 +0,0 @@ |
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Mon, 31 Aug 2015 22:59:38 +0200
|
||||
Subject: [PATCH] nl80211: put current TX power in interface info
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Many drivers implement reading current TX power (using either cfg80211
|
||||
or ieee80211 op) but userspace can't get it using nl80211. Right now the
|
||||
only way to access it is to call some wext ioctl.
|
||||
Let's put TX power in interface info reply (callback is wdev specific)
|
||||
just like we do with current channel.
|
||||
To be consistent (e.g. NL80211_CMD_SET_WIPHY) let's use mBm as na unit.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/wireless/nl80211.c
|
||||
+++ b/net/wireless/nl80211.c
|
||||
@@ -2406,6 +2406,16 @@ static int nl80211_send_iface(struct sk_
|
||||
}
|
||||
}
|
||||
|
||||
+ if (rdev->ops->get_tx_power) {
|
||||
+ int dbm, ret;
|
||||
+
|
||||
+ ret = rdev_get_tx_power(rdev, wdev, &dbm);
|
||||
+ if (ret == 0 &&
|
||||
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
|
||||
+ DBM_TO_MBM(dbm)))
|
||||
+ goto nla_put_failure;
|
||||
+ }
|
||||
+
|
||||
if (wdev->ssid_len) {
|
||||
if (nla_put(msg, NL80211_ATTR_SSID, wdev->ssid_len, wdev->ssid))
|
||||
goto nla_put_failure;
|
@ -1,21 +0,0 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Mon, 5 Oct 2015 17:41:25 +0200
|
||||
Subject: [PATCH] mac80211: initialize tid field in struct ieee80211_txq
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/util.c
|
||||
+++ b/net/mac80211/util.c
|
||||
@@ -3288,9 +3288,11 @@ void ieee80211_init_tx_queue(struct ieee
|
||||
if (sta) {
|
||||
txqi->txq.sta = &sta->sta;
|
||||
sta->sta.txq[tid] = &txqi->txq;
|
||||
+ txqi->txq.tid = tid;
|
||||
txqi->txq.ac = ieee802_1d_to_ac[tid & 7];
|
||||
} else {
|
||||
sdata->vif.txq = &txqi->txq;
|
||||
+ txqi->txq.tid = 0;
|
||||
txqi->txq.ac = IEEE80211_AC_BE;
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@ |
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Mon, 8 Jun 2015 16:59:31 +0200
|
||||
Subject: [PATCH] brcmfmac: use bcm47xx platform NVRAM as fallback
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
|
||||
@@ -19,6 +19,9 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
+#if IS_ENABLED(CONFIG_BCM47XX_NVRAM)
|
||||
+#include <linux/bcm47xx_nvram.h>
|
||||
+#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "firmware.h"
|
||||
@@ -424,17 +427,42 @@ struct brcmf_fw {
|
||||
static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
|
||||
{
|
||||
struct brcmf_fw *fwctx = ctx;
|
||||
+#if IS_ENABLED(CONFIG_BCM47XX_NVRAM)
|
||||
+ const u8 *bcm47xx_nvram = NULL;
|
||||
+ size_t bcm47xx_nvram_len;
|
||||
+#endif
|
||||
+ const u8 *data = NULL;
|
||||
+ size_t data_len;
|
||||
u32 nvram_length = 0;
|
||||
void *nvram = NULL;
|
||||
|
||||
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
|
||||
- if (!fw && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
|
||||
+ if (fw) {
|
||||
+ data = fw->data;
|
||||
+ data_len = fw->size;
|
||||
+ }
|
||||
+#if IS_ENABLED(CONFIG_BCM47XX_NVRAM)
|
||||
+ else {
|
||||
+ bcm47xx_nvram = bcm47xx_nvram_get_contents(&bcm47xx_nvram_len);
|
||||
+ if (bcm47xx_nvram) {
|
||||
+ data = bcm47xx_nvram;
|
||||
+ data_len = bcm47xx_nvram_len;
|
||||
+ brcmf_err("Found platform NVRAM (%zu B)\n", data_len);
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+ if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
|
||||
goto fail;
|
||||
|
||||
- if (fw) {
|
||||
- nvram = brcmf_fw_nvram_strip(fw->data, fw->size, &nvram_length,
|
||||
+ if (data) {
|
||||
+ nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length,
|
||||
fwctx->domain_nr, fwctx->bus_nr);
|
||||
- release_firmware(fw);
|
||||
+ if (fw)
|
||||
+ release_firmware(fw);
|
||||
+#if IS_ENABLED(CONFIG_BCM47XX_NVRAM)
|
||||
+ if (bcm47xx_nvram)
|
||||
+ bcm47xx_nvram_release_contents(bcm47xx_nvram);
|
||||
+#endif
|
||||
if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
|
||||
goto fail;
|
||||
}
|
||||
--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h
|
||||
@@ -17,6 +17,8 @@
|
||||
#ifndef BRCMFMAC_DEBUG_H
|
||||
#define BRCMFMAC_DEBUG_H
|
||||
|
||||
+#include <linux/net.h>
|
||||
+
|
||||
/* message levels */
|
||||
#define BRCMF_TRACE_VAL 0x00000002
|
||||
#define BRCMF_INFO_VAL 0x00000004
|
@ -0,0 +1,11 @@ |
||||
--- a/mac80211.c
|
||||
+++ b/mac80211.c
|
||||
@@ -574,7 +574,7 @@ static int mwl_mac80211_ampdu_action(str
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_ampdu_mlme_action action,
|
||||
struct ieee80211_sta *sta,
|
||||
- u16 tid, u16 *ssn, u8 buf_size)
|
||||
+ u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
|
||||
{
|
||||
int rc = 0;
|
||||
struct mwl_priv *priv = hw->priv;
|
Loading…
Reference in new issue