summaryrefslogtreecommitdiff
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c17
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c24
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c10
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h14
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c17
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_dma.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_init.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_mac.c16
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_main.c36
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2_tx.c6
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/cfg80211.c131
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/cfg80211.h19
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/commands.c222
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/core.c139
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/core.h15
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/event.c4
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c7
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/qlink.h33
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.c129
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c135
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h64
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c89
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.c6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/wifi.h32
30 files changed, 917 insertions, 275 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
index 9f2d0b0cf6e5..2d3a5dd07a3f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
@@ -165,7 +165,7 @@ static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
static int
brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
- void *buf, uint len)
+ void *buf, uint len, int *fwerr)
{
struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
@@ -175,6 +175,7 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
+ *fwerr = 0;
ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false);
if (ret < 0) {
brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n",
@@ -211,25 +212,27 @@ retry:
memcpy(buf, info, len);
}
+ ret = 0;
+
/* Check the ERROR flag */
if (flags & BCDC_DCMD_ERROR)
- ret = le32_to_cpu(msg->status);
-
+ *fwerr = le32_to_cpu(msg->status);
done:
return ret;
}
static int
brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
- void *buf, uint len)
+ void *buf, uint len, int *fwerr)
{
struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
- int ret = 0;
+ int ret;
u32 flags, id;
brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
+ *fwerr = 0;
ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, true);
if (ret < 0)
goto done;
@@ -249,9 +252,11 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
goto done;
}
+ ret = 0;
+
/* Check the ERROR flag */
if (flags & BCDC_DCMD_ERROR)
- ret = le32_to_cpu(msg->status);
+ *fwerr = le32_to_cpu(msg->status);
done:
return ret;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
index f6a2df94dba7..f2cfdd3b2bf1 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
@@ -107,7 +107,7 @@ static s32
brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
{
struct brcmf_pub *drvr = ifp->drvr;
- s32 err;
+ s32 err, fwerr;
if (drvr->bus_if->state != BRCMF_BUS_UP) {
brcmf_err("bus is down. we have nothing to do.\n");
@@ -117,16 +117,20 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
if (data != NULL)
len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
if (set)
- err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len);
+ err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd,
+ data, len, &fwerr);
else
- err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len);
-
- if (err >= 0)
- return 0;
-
- brcmf_dbg(FIL, "Failed: %s (%d)\n",
- brcmf_fil_get_errstr((u32)(-err)), err);
-
+ err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd,
+ data, len, &fwerr);
+
+ if (err) {
+ brcmf_dbg(FIL, "Failed: %s (%d)\n",
+ brcmf_fil_get_errstr((u32)(-err)), err);
+ } else if (fwerr < 0) {
+ brcmf_dbg(FIL, "Firmware error: %s (%d)\n",
+ brcmf_fil_get_errstr((u32)(-fwerr)), fwerr);
+ err = -EBADE;
+ }
return err;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index d2c834c3b2fc..e212a791a072 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -477,7 +477,7 @@ static void brcmf_msgbuf_ioctl_resp_wake(struct brcmf_msgbuf *msgbuf)
static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,
- uint cmd, void *buf, uint len)
+ uint cmd, void *buf, uint len, int *fwerr)
{
struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
struct sk_buff *skb = NULL;
@@ -485,6 +485,7 @@ static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,
int err;
brcmf_dbg(MSGBUF, "ifidx=%d, cmd=%d, len=%d\n", ifidx, cmd, len);
+ *fwerr = 0;
msgbuf->ctl_completed = false;
err = brcmf_msgbuf_tx_ioctl(drvr, ifidx, cmd, buf, len);
if (err)
@@ -508,14 +509,15 @@ static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,
}
brcmu_pkt_buf_free_skb(skb);
- return msgbuf->ioctl_resp_status;
+ *fwerr = msgbuf->ioctl_resp_status;
+ return 0;
}
static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx,
- uint cmd, void *buf, uint len)
+ uint cmd, void *buf, uint len, int *fwerr)
{
- return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len);
+ return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len, fwerr);
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
index 2404f8a7c31c..8a8e08f09ea0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
@@ -30,9 +30,9 @@ struct brcmf_proto {
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);
+ void *buf, uint len, int *fwerr);
int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
- uint len);
+ uint len, int *fwerr);
int (*tx_queue_data)(struct brcmf_pub *drvr, int ifidx,
struct sk_buff *skb);
int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset,
@@ -71,14 +71,16 @@ static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
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)
+ uint cmd, void *buf, uint len,
+ int *fwerr)
{
- return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len);
+ return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len,fwerr);
}
static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx,
- uint cmd, void *buf, uint len)
+ uint cmd, void *buf, uint len,
+ int *fwerr)
{
- return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len);
+ return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len, fwerr);
}
static inline int brcmf_proto_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index aa0880bbea7f..f88d9a15210a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -129,6 +129,7 @@ struct mt76_wcid {
bool tx_rate_set;
u8 tx_rate_nss;
s8 max_txpwr_adj;
+ bool sw_iv;
};
struct mt76_txq {
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c
index 5b452a596016..f936dc9a5476 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c
@@ -460,8 +460,8 @@ void mt76x2_dfs_init_params(struct mt76x2_dev *dev)
{
struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
- tasklet_kill(&dev->dfs_pd.dfs_tasklet);
- if (chandef->chan->flags & IEEE80211_CHAN_RADAR) {
+ if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
+ dev->dfs_pd.region != NL80211_DFS_UNSET) {
mt76x2_dfs_set_bbp_params(dev);
/* enable debug mode */
mt76x2_dfs_set_capture_mode_ctrl(dev, true);
@@ -491,3 +491,16 @@ void mt76x2_dfs_init_detector(struct mt76x2_dev *dev)
(unsigned long)dev);
}
+void mt76x2_dfs_set_domain(struct mt76x2_dev *dev,
+ enum nl80211_dfs_regions region)
+{
+ struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd;
+
+ if (dfs_pd->region != region) {
+ tasklet_disable(&dfs_pd->dfs_tasklet);
+ dfs_pd->region = region;
+ mt76x2_dfs_init_params(dev);
+ tasklet_enable(&dfs_pd->dfs_tasklet);
+ }
+}
+
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h b/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h
index 9ac69b6a116d..8dbc783cc6bc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h
@@ -76,5 +76,7 @@ struct mt76x2_dfs_pattern_detector {
void mt76x2_dfs_init_params(struct mt76x2_dev *dev);
void mt76x2_dfs_init_detector(struct mt76x2_dev *dev);
void mt76x2_dfs_adjust_agc(struct mt76x2_dev *dev);
+void mt76x2_dfs_set_domain(struct mt76x2_dev *dev,
+ enum nl80211_dfs_regions region);
#endif /* __MT76x2_DFS_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_dma.c b/drivers/net/wireless/mediatek/mt76/mt76x2_dma.c
index 0a3f729a7156..fd1ec4743e0b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_dma.c
@@ -55,6 +55,7 @@ mt76x2_init_tx_queue(struct mt76x2_dev *dev, struct mt76_queue *q,
q->regs = dev->mt76.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE;
q->ndesc = n_desc;
+ q->hw_idx = idx;
ret = mt76_queue_alloc(dev, q);
if (ret)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2_init.c
index 4373a2ba5143..7b4851481dd6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_init.c
@@ -614,6 +614,8 @@ void mt76x2_stop_hardware(struct mt76x2_dev *dev)
void mt76x2_cleanup(struct mt76x2_dev *dev)
{
+ tasklet_disable(&dev->dfs_pd.dfs_tasklet);
+ tasklet_disable(&dev->pre_tbtt_tasklet);
mt76x2_stop_hardware(dev);
mt76x2_dma_cleanup(dev);
mt76x2_mcu_cleanup(dev);
@@ -652,7 +654,7 @@ static void mt76x2_regd_notifier(struct wiphy *wiphy,
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct mt76x2_dev *dev = hw->priv;
- dev->dfs_pd.region = request->dfs_region;
+ mt76x2_dfs_set_domain(dev, request->dfs_region);
}
#define CCK_RATE(_idx, _rate) { \
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
index f7c0df0759f7..a7416a01baa4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
@@ -171,10 +171,12 @@ void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x2_txwi *txwi,
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *rate = &info->control.rates[0];
+ struct ieee80211_key_conf *key = info->control.hw_key;
u16 rate_ht_mask = FIELD_PREP(MT_RXWI_RATE_PHY, BIT(1) | BIT(2));
u16 txwi_flags = 0;
u8 nss;
s8 txpwr_adj, max_txpwr_adj;
+ u8 ccmp_pn[8];
memset(txwi, 0, sizeof(*txwi));
@@ -185,6 +187,20 @@ void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x2_txwi *txwi,
txwi->pktid = 1;
+ if (wcid && wcid->sw_iv && key) {
+ u64 pn = atomic64_inc_return(&key->tx_pn);
+ ccmp_pn[0] = pn;
+ ccmp_pn[1] = pn >> 8;
+ ccmp_pn[2] = 0;
+ ccmp_pn[3] = 0x20 | (key->keyidx << 6);
+ ccmp_pn[4] = pn >> 16;
+ ccmp_pn[5] = pn >> 24;
+ ccmp_pn[6] = pn >> 32;
+ ccmp_pn[7] = pn >> 40;
+ txwi->iv = *((u32 *) &ccmp_pn[0]);
+ txwi->eiv = *((u32 *) &ccmp_pn[1]);
+ }
+
spin_lock_bh(&dev->mt76.lock);
if (wcid && (rate->idx < 0 || !rate->count)) {
txwi->rate = wcid->tx_rate;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2_main.c
index 79915cbee3f0..aa5fbb64e218 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_main.c
@@ -127,6 +127,7 @@ mt76x2_set_channel(struct mt76x2_dev *dev, struct cfg80211_chan_def *chandef)
mt76_set_channel(&dev->mt76);
tasklet_disable(&dev->pre_tbtt_tasklet);
+ tasklet_disable(&dev->dfs_pd.dfs_tasklet);
cancel_delayed_work_sync(&dev->cal_work);
mt76x2_mac_stop(dev, true);
@@ -139,6 +140,7 @@ mt76x2_set_channel(struct mt76x2_dev *dev, struct cfg80211_chan_def *chandef)
mt76x2_dfs_init_params(dev);
mt76x2_mac_resume(dev);
+ tasklet_enable(&dev->dfs_pd.dfs_tasklet);
tasklet_enable(&dev->pre_tbtt_tasklet);
return ret;
@@ -355,9 +357,15 @@ mt76x2_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (cmd == SET_KEY) {
key->hw_key_idx = wcid->idx;
wcid->hw_key_idx = idx;
+ if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {
+ key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
+ wcid->sw_iv = true;
+ }
} else {
- if (idx == wcid->hw_key_idx)
+ if (idx == wcid->hw_key_idx) {
wcid->hw_key_idx = -1;
+ wcid->sw_iv = true;
+ }
key = NULL;
}
@@ -380,9 +388,11 @@ mt76x2_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct mt76x2_dev *dev = hw->priv;
- u8 cw_min = 5, cw_max = 10;
+ u8 cw_min = 5, cw_max = 10, qid;
u32 val;
+ qid = dev->mt76.q_tx[queue].hw_idx;
+
if (params->cw_min)
cw_min = fls(params->cw_min);
if (params->cw_max)
@@ -392,26 +402,26 @@ mt76x2_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
FIELD_PREP(MT_EDCA_CFG_AIFSN, params->aifs) |
FIELD_PREP(MT_EDCA_CFG_CWMIN, cw_min) |
FIELD_PREP(MT_EDCA_CFG_CWMAX, cw_max);
- mt76_wr(dev, MT_EDCA_CFG_AC(queue), val);
+ mt76_wr(dev, MT_EDCA_CFG_AC(qid), val);
- val = mt76_rr(dev, MT_WMM_TXOP(queue));
- val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(queue));
- val |= params->txop << MT_WMM_TXOP_SHIFT(queue);
- mt76_wr(dev, MT_WMM_TXOP(queue), val);
+ val = mt76_rr(dev, MT_WMM_TXOP(qid));
+ val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(qid));
+ val |= params->txop << MT_WMM_TXOP_SHIFT(qid);
+ mt76_wr(dev, MT_WMM_TXOP(qid), val);
val = mt76_rr(dev, MT_WMM_AIFSN);
- val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(queue));
- val |= params->aifs << MT_WMM_AIFSN_SHIFT(queue);
+ val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(qid));
+ val |= params->aifs << MT_WMM_AIFSN_SHIFT(qid);
mt76_wr(dev, MT_WMM_AIFSN, val);
val = mt76_rr(dev, MT_WMM_CWMIN);
- val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(queue));
- val |= cw_min << MT_WMM_CWMIN_SHIFT(queue);
+ val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(qid));
+ val |= cw_min << MT_WMM_CWMIN_SHIFT(qid);
mt76_wr(dev, MT_WMM_CWMIN, val);
val = mt76_rr(dev, MT_WMM_CWMAX);
- val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(queue));
- val |= cw_max << MT_WMM_CWMAX_SHIFT(queue);
+ val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(qid));
+ val |= cw_max << MT_WMM_CWMAX_SHIFT(qid);
mt76_wr(dev, MT_WMM_CWMAX, val);
return 0;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c b/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c
index 1a32e1fb8743..534e4bf9a34c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c
@@ -36,7 +36,9 @@ void mt76x2_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
msta = (struct mt76x2_sta *) control->sta->drv_priv;
wcid = &msta->wcid;
- } else if (vif) {
+ }
+
+ if (vif || (!info->control.hw_key && wcid->hw_key_idx != -1)) {
struct mt76x2_vif *mvif;
mvif = (struct mt76x2_vif *) vif->drv_priv;
@@ -166,7 +168,7 @@ int mt76x2_tx_prepare_skb(struct mt76_dev *mdev, void *txwi,
*tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) |
MT_TXD_INFO_80211;
- if (!wcid || wcid->hw_key_idx == 0xff)
+ if (!wcid || wcid->hw_key_idx == 0xff || wcid->sw_iv)
*tx_info |= MT_TXD_INFO_WIV;
return 0;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index abf10996c26a..0398bece5782 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -81,6 +81,41 @@ qtnf_mgmt_stypes[NUM_NL80211_IFTYPES] = {
};
static int
+qtnf_validate_iface_combinations(struct wiphy *wiphy,
+ struct qtnf_vif *change_vif,
+ enum nl80211_iftype new_type)
+{
+ struct qtnf_wmac *mac;
+ struct qtnf_vif *vif;
+ int i;
+ int ret = 0;
+ struct iface_combination_params params = {
+ .num_different_channels = 1,
+ };
+
+ mac = wiphy_priv(wiphy);
+ if (!mac)
+ return -EFAULT;
+
+ for (i = 0; i < QTNF_MAX_INTF; i++) {
+ vif = &mac->iflist[i];
+ if (vif->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED)
+ params.iftype_num[vif->wdev.iftype]++;
+ }
+
+ if (change_vif) {
+ params.iftype_num[new_type]++;
+ params.iftype_num[change_vif->wdev.iftype]--;
+ } else {
+ params.iftype_num[new_type]++;
+ }
+
+ ret = cfg80211_check_combinations(wiphy, &params);
+
+ return ret;
+}
+
+static int
qtnf_change_virtual_intf(struct wiphy *wiphy,
struct net_device *dev,
enum nl80211_iftype type,
@@ -90,6 +125,13 @@ qtnf_change_virtual_intf(struct wiphy *wiphy,
u8 *mac_addr;
int ret;
+ ret = qtnf_validate_iface_combinations(wiphy, vif, type);
+ if (ret) {
+ pr_err("VIF%u.%u combination check: failed to set type %d\n",
+ vif->mac->macid, vif->vifid, type);
+ return ret;
+ }
+
if (params)
mac_addr = params->macaddr;
else
@@ -120,10 +162,6 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
qtnf_scan_done(vif->mac, true);
- if (qtnf_cmd_send_del_intf(vif))
- pr_err("VIF%u.%u: failed to delete VIF\n", vif->mac->macid,
- vif->vifid);
-
/* Stop data */
netif_tx_stop_all_queues(netdev);
if (netif_carrier_ok(netdev))
@@ -132,6 +170,10 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
if (netdev->reg_state == NETREG_REGISTERED)
unregister_netdevice(netdev);
+ if (qtnf_cmd_send_del_intf(vif))
+ pr_err("VIF%u.%u: failed to delete VIF\n", vif->mac->macid,
+ vif->vifid);
+
vif->netdev->ieee80211_ptr = NULL;
vif->netdev = NULL;
vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
@@ -150,12 +192,20 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy,
struct qtnf_wmac *mac;
struct qtnf_vif *vif;
u8 *mac_addr = NULL;
+ int ret;
mac = wiphy_priv(wiphy);
if (!mac)
return ERR_PTR(-EFAULT);
+ ret = qtnf_validate_iface_combinations(wiphy, NULL, type);
+ if (ret) {
+ pr_err("MAC%u invalid combination: failed to add type %d\n",
+ mac->macid, type);
+ return ERR_PTR(ret);
+ }
+
switch (type) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_AP:
@@ -545,19 +595,13 @@ qtnf_del_station(struct wiphy *wiphy, struct net_device *dev,
return ret;
}
-static void qtnf_scan_timeout(struct timer_list *t)
-{
- struct qtnf_wmac *mac = from_timer(mac, t, scan_timeout);
-
- pr_warn("mac%d scan timed out\n", mac->macid);
- qtnf_scan_done(mac, true);
-}
-
static int
qtnf_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
{
struct qtnf_wmac *mac = wiphy_priv(wiphy);
+ cancel_delayed_work_sync(&mac->scan_timeout);
+
mac->scan_req = request;
if (qtnf_cmd_send_scan(mac)) {
@@ -566,9 +610,8 @@ qtnf_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
return -EFAULT;
}
- mac->scan_timeout.function = qtnf_scan_timeout;
- mod_timer(&mac->scan_timeout,
- jiffies + QTNF_SCAN_TIMEOUT_SEC * HZ);
+ queue_delayed_work(mac->bus->workqueue, &mac->scan_timeout,
+ QTNF_SCAN_TIMEOUT_SEC * HZ);
return 0;
}
@@ -629,7 +672,6 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
return ret;
}
- vif->sta_state = QTNF_STA_DISCONNECTED;
return 0;
}
@@ -876,29 +918,29 @@ struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus)
return wiphy;
}
-static int qtnf_wiphy_setup_if_comb(struct wiphy *wiphy,
- struct ieee80211_iface_combination *if_comb,
- const struct qtnf_mac_info *mac_info)
+static int
+qtnf_wiphy_setup_if_comb(struct wiphy *wiphy, struct qtnf_mac_info *mac_info)
{
- size_t max_interfaces = 0;
+ struct ieee80211_iface_combination *if_comb;
+ size_t n_if_comb;
u16 interface_modes = 0;
- size_t i;
+ size_t i, j;
+
+ if_comb = mac_info->if_comb;
+ n_if_comb = mac_info->n_if_comb;
- if (unlikely(!mac_info->limits || !mac_info->n_limits))
+ if (!if_comb || !n_if_comb)
return -ENOENT;
- if_comb->limits = mac_info->limits;
- if_comb->n_limits = mac_info->n_limits;
+ for (i = 0; i < n_if_comb; i++) {
+ if_comb[i].radar_detect_widths = mac_info->radar_detect_widths;
- for (i = 0; i < mac_info->n_limits; i++) {
- max_interfaces += mac_info->limits[i].max;
- interface_modes |= mac_info->limits[i].types;
+ for (j = 0; j < if_comb[i].n_limits; j++)
+ interface_modes |= if_comb[i].limits[j].types;
}
- if_comb->num_different_channels = 1;
- if_comb->beacon_int_infra_match = true;
- if_comb->max_interfaces = max_interfaces;
- if_comb->radar_detect_widths = mac_info->radar_detect_widths;
+ wiphy->iface_combinations = if_comb;
+ wiphy->n_iface_combinations = n_if_comb;
wiphy->interface_modes = interface_modes;
return 0;
@@ -907,7 +949,6 @@ static int qtnf_wiphy_setup_if_comb(struct wiphy *wiphy,
int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
{
struct wiphy *wiphy = priv_to_wiphy(mac);
- struct ieee80211_iface_combination *iface_comb = NULL;
int ret;
if (!wiphy) {
@@ -915,14 +956,6 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
return -EFAULT;
}
- iface_comb = kzalloc(sizeof(*iface_comb), GFP_KERNEL);
- if (!iface_comb)
- return -ENOMEM;
-
- ret = qtnf_wiphy_setup_if_comb(wiphy, iface_comb, &mac->macinfo);
- if (ret)
- goto out;
-
wiphy->frag_threshold = mac->macinfo.frag_thr;
wiphy->rts_threshold = mac->macinfo.rts_thr;
wiphy->retry_short = mac->macinfo.sretry_limit;
@@ -934,11 +967,12 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
wiphy->mgmt_stypes = qtnf_mgmt_stypes;
wiphy->max_remain_on_channel_duration = 5000;
wiphy->max_acl_mac_addrs = mac->macinfo.max_acl_mac_addrs;
-
- wiphy->iface_combinations = iface_comb;
- wiphy->n_iface_combinations = 1;
wiphy->max_num_csa_counters = 2;
+ ret = qtnf_wiphy_setup_if_comb(wiphy, &mac->macinfo);
+ if (ret)
+ goto out;
+
/* Initialize cipher suits */
wiphy->cipher_suites = qtnf_cipher_suites;
wiphy->n_cipher_suites = ARRAY_SIZE(qtnf_cipher_suites);
@@ -972,6 +1006,10 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
}
+ strlcpy(wiphy->fw_version, hw_info->fw_version,
+ sizeof(wiphy->fw_version));
+ wiphy->hw_version = hw_info->hw_version;
+
ret = wiphy_register(wiphy);
if (ret < 0)
goto out;
@@ -983,12 +1021,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
ret = regulatory_hint(wiphy, hw_info->rd->alpha2);
out:
- if (ret) {
- kfree(iface_comb);
- return ret;
- }
-
- return 0;
+ return ret;
}
void qtnf_netdev_updown(struct net_device *ndev, bool up)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
index 66db26613b1f..b73425122a10 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
@@ -28,23 +28,4 @@ void qtnf_band_init_rates(struct ieee80211_supported_band *band);
void qtnf_band_setup_htvht_caps(struct qtnf_mac_info *macinfo,
struct ieee80211_supported_band *band);
-static inline void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted)
-{
- struct cfg80211_scan_info info = {
- .aborted = aborted,
- };
-
- if (timer_pending(&mac->scan_timeout))
- del_timer_sync(&mac->scan_timeout);
-
- mutex_lock(&mac->mac_lock);
-
- if (mac->scan_req) {
- cfg80211_scan_done(mac->scan_req, &info);
- mac->scan_req = NULL;
- }
-
- mutex_unlock(&mac->mac_lock);
-}
-
#endif /* _QTN_FMAC_CFG80211_H_ */
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 6ffe4837bbdb..deca0060eb27 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -187,7 +187,8 @@ static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif,
len += sizeof(struct qlink_tlv_chandef);
if (s->acl)
- len += qtnf_cmd_acl_data_size(s->acl);
+ len += sizeof(struct qlink_tlv_hdr) +
+ qtnf_cmd_acl_data_size(s->acl);
if (len > (sizeof(struct qlink_cmd) + QTNF_MAX_CMD_BUF_SIZE)) {
pr_err("VIF%u.%u: can not fit AP settings: %u\n",
@@ -214,7 +215,7 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_START_AP,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
cmd = (struct qlink_cmd_start_ap *)cmd_skb->data;
@@ -334,7 +335,7 @@ int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif)
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_STOP_AP,
sizeof(struct qlink_cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
@@ -368,7 +369,7 @@ int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg)
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_REGISTER_MGMT,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
@@ -411,7 +412,7 @@ int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_SEND_MGMT_FRAME,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
@@ -457,7 +458,7 @@ int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_MGMT_SET_APPIE,
sizeof(struct qlink_cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_cmd_tlv_ie_set_add(cmd_skb, frame_type, buf, len);
@@ -712,8 +713,7 @@ int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_GET_STA_INFO,
sizeof(*cmd));
-
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
@@ -778,7 +778,7 @@ static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
cmd_type,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
@@ -851,7 +851,7 @@ int qtnf_cmd_send_del_intf(struct qtnf_vif *vif)
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_DEL_INTF,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
@@ -948,6 +948,16 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
struct qtnf_hw_info *hwinfo = &bus->hw_info;
const struct qlink_tlv_hdr *tlv;
const struct qlink_tlv_reg_rule *tlv_rule;
+ const char *bld_name = NULL;
+ const char *bld_rev = NULL;
+ const char *bld_type = NULL;
+ const char *bld_label = NULL;
+ u32 bld_tmstamp = 0;
+ u32 plat_id = 0;
+ const char *hw_id = NULL;
+ const char *calibration_ver = NULL;
+ const char *uboot_ver = NULL;
+ u32 hw_ver = 0;
struct ieee80211_reg_rule *rule;
u16 tlv_type;
u16 tlv_value_len;
@@ -974,6 +984,10 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
hwinfo->rd->alpha2[0] = resp->alpha2[0];
hwinfo->rd->alpha2[1] = resp->alpha2[1];
+ bld_tmstamp = le32_to_cpu(resp->bld_tmstamp);
+ plat_id = le32_to_cpu(resp->plat_id);
+ hw_ver = le32_to_cpu(resp->hw_ver);
+
switch (resp->dfs_region) {
case QLINK_DFS_FCC:
hwinfo->rd->dfs_region = NL80211_DFS_FCC;
@@ -1034,6 +1048,27 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
rule->flags = qtnf_cmd_resp_reg_rule_flags_parse(
le32_to_cpu(tlv_rule->flags));
break;
+ case QTN_TLV_ID_BUILD_NAME:
+ bld_name = (const void *)tlv->val;
+ break;
+ case QTN_TLV_ID_BUILD_REV:
+ bld_rev = (const void *)tlv->val;
+ break;
+ case QTN_TLV_ID_BUILD_TYPE:
+ bld_type = (const void *)tlv->val;
+ break;
+ case QTN_TLV_ID_BUILD_LABEL:
+ bld_label = (const void *)tlv->val;
+ break;
+ case QTN_TLV_ID_HW_ID:
+ hw_id = (const void *)tlv->val;
+ break;
+ case QTN_TLV_ID_CALIBRATION_VER:
+ calibration_ver = (const void *)tlv->val;
+ break;
+ case QTN_TLV_ID_UBOOT_VER:
+ uboot_ver = (const void *)tlv->val;
+ break;
default:
break;
}
@@ -1056,25 +1091,46 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
hwinfo->total_tx_chain, hwinfo->total_rx_chain,
hwinfo->hw_capab);
+ pr_info("\nBuild name: %s" \
+ "\nBuild revision: %s" \
+ "\nBuild type: %s" \
+ "\nBuild label: %s" \
+ "\nBuild timestamp: %lu" \
+ "\nPlatform ID: %lu" \
+ "\nHardware ID: %s" \
+ "\nCalibration version: %s" \
+ "\nU-Boot version: %s" \
+ "\nHardware version: 0x%08x",
+ bld_name, bld_rev, bld_type, bld_label,
+ (unsigned long)bld_tmstamp,
+ (unsigned long)plat_id,
+ hw_id, calibration_ver, uboot_ver, hw_ver);
+
+ strlcpy(hwinfo->fw_version, bld_label, sizeof(hwinfo->fw_version));
+ hwinfo->hw_version = hw_ver;
+
return 0;
}
static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
const u8 *tlv_buf, size_t tlv_buf_size)
{
- struct ieee80211_iface_limit *limits = NULL;
- const struct qlink_iface_limit *limit_record;
- size_t record_count = 0, rec = 0;
- u16 tlv_type, tlv_value_len;
- struct qlink_iface_comb_num *comb;
+ struct ieee80211_iface_combination *comb = NULL;
+ size_t n_comb = 0;
+ struct ieee80211_iface_limit *limits;
+ const struct qlink_iface_comb_num *comb_num;
+ const struct qlink_iface_limit_record *rec;
+ const struct qlink_iface_limit *lim;
+ u16 rec_len;
+ u16 tlv_type;
+ u16 tlv_value_len;
size_t tlv_full_len;
const struct qlink_tlv_hdr *tlv;
u8 *ext_capa = NULL;
u8 *ext_capa_mask = NULL;
u8 ext_capa_len = 0;
u8 ext_capa_mask_len = 0;
-
- mac->macinfo.n_limits = 0;
+ int i = 0;
tlv = (const struct qlink_tlv_hdr *)tlv_buf;
while (tlv_buf_size >= sizeof(struct qlink_tlv_hdr)) {
@@ -1089,52 +1145,77 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
switch (tlv_type) {
case QTN_TLV_ID_NUM_IFACE_COMB:
- if (unlikely(tlv_value_len != sizeof(*comb)))
+ if (tlv_value_len != sizeof(*comb_num))
return -EINVAL;
- comb = (void *)tlv->val;
- record_count = le16_to_cpu(comb->iface_comb_num);
+ comb_num = (void *)tlv->val;
+
+ /* free earlier iface comb memory */
+ qtnf_mac_iface_comb_free(mac);
+
+ mac->macinfo.n_if_comb =
+ le32_to_cpu(comb_num->iface_comb_num);
- mac->macinfo.n_limits = record_count;
- /* free earlier iface limits memory */
- kfree(mac->macinfo.limits);
- mac->macinfo.limits =
- kzalloc(sizeof(*mac->macinfo.limits) *
- record_count, GFP_KERNEL);
+ mac->macinfo.if_comb =
+ kcalloc(mac->macinfo.n_if_comb,
+ sizeof(*mac->macinfo.if_comb),
+ GFP_KERNEL);
- if (unlikely(!mac->macinfo.limits))
+ if (!mac->macinfo.if_comb)
return -ENOMEM;
- limits = mac->macinfo.limits;
+ comb = mac->macinfo.if_comb;
+
+ pr_debug("MAC%u: %zu iface combinations\n",
+ mac->macid, mac->macinfo.n_if_comb);
+
break;
case QTN_TLV_ID_IFACE_LIMIT:
- if (unlikely(!limits)) {
- pr_warn("MAC%u: limits are not inited\n",
+ if (unlikely(!comb)) {
+ pr_warn("MAC%u: no combinations advertised\n",
mac->macid);
return -EINVAL;
}
- if (unlikely(tlv_value_len != sizeof(*limit_record))) {
- pr_warn("MAC%u: record size mismatch\n",
+ if (n_comb >= mac->macinfo.n_if_comb) {
+ pr_warn("MAC%u: combinations count exceeded\n",
mac->macid);
- return -EINVAL;
+ n_comb++;
+ break;
}
- limit_record = (void *)tlv->val;
- limits[rec].max = le16_to_cpu(limit_record->max_num);
- limits[rec].types = qlink_iface_type_to_nl_mask(
- le16_to_cpu(limit_record->type));
+ rec = (void *)tlv->val;
+ rec_len = sizeof(*rec) + rec->n_limits * sizeof(*lim);
- /* supported modes: STA, AP */
- limits[rec].types &= BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_AP_VLAN) |
- BIT(NL80211_IFTYPE_STATION);
+ if (unlikely(tlv_value_len != rec_len)) {
+ pr_warn("MAC%u: record %zu size mismatch\n",
+ mac->macid, n_comb);
+ return -EINVAL;
+ }
- pr_debug("MAC%u: MAX: %u; TYPES: %.4X\n", mac->macid,
- limits[rec].max, limits[rec].types);
+ limits = kzalloc(sizeof(*limits) * rec->n_limits,
+ GFP_KERNEL);
+ if (!limits)
+ return -ENOMEM;
- if (limits[rec].types)
- rec++;
+ comb[n_comb].num_different_channels =
+ rec->num_different_channels;
+ comb[n_comb].max_interfaces =
+ le16_to_cpu(rec->max_interfaces);
+ comb[n_comb].n_limits = rec->n_limits;
+ comb[n_comb].limits = limits;
+
+ for (i = 0; i < rec->n_limits; i++) {
+ lim = &rec->limits[i];
+ limits[i].max = le16_to_cpu(lim->max_num);
+ limits[i].types =
+ qlink_iface_type_to_nl_mask(le16_to_cpu(lim->type));
+ pr_debug("MAC%u: comb[%zu]: MAX:%u TYPES:%.4X\n",
+ mac->macid, n_comb,
+ limits[i].max, limits[i].types);
+ }
+
+ n_comb++;
break;
case WLAN_EID_EXT_CAPABILITY:
if (unlikely(tlv_value_len > U8_MAX))
@@ -1162,9 +1243,9 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
return -EINVAL;
}
- if (mac->macinfo.n_limits != rec) {
+ if (mac->macinfo.n_if_comb != n_comb) {
pr_err("MAC%u: combination mismatch: reported=%zu parsed=%zu\n",
- mac->macid, mac->macinfo.n_limits, rec);
+ mac->macid, mac->macinfo.n_if_comb, n_comb);
return -EINVAL;
}
@@ -1575,7 +1656,7 @@ int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac)
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
QLINK_CMD_MAC_INFO,
sizeof(struct qlink_cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(mac->bus);
@@ -1613,7 +1694,7 @@ int qtnf_cmd_get_hw_info(struct qtnf_bus *bus)
cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
QLINK_CMD_GET_HW_INFO,
sizeof(struct qlink_cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(bus);
@@ -1793,7 +1874,7 @@ int qtnf_cmd_send_init_fw(struct qtnf_bus *bus)
cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD,
QLINK_CMD_FW_INIT,
sizeof(struct qlink_cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(bus);
@@ -1842,7 +1923,7 @@ int qtnf_cmd_send_add_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_ADD_KEY,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
@@ -1895,7 +1976,7 @@ int qtnf_cmd_send_del_key(struct qtnf_vif *vif, u8 key_index, bool pairwise,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_DEL_KEY,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
@@ -1936,7 +2017,7 @@ int qtnf_cmd_send_set_default_key(struct qtnf_vif *vif, u8 key_index,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_SET_DEFAULT_KEY,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
@@ -1971,7 +2052,7 @@ int qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif *vif, u8 key_index)
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_SET_DEFAULT_MGMT_KEY,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
@@ -2026,7 +2107,7 @@ int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_CHANGE_STA,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
@@ -2078,7 +2159,7 @@ int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_DEL_STA,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
@@ -2148,7 +2229,7 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD,
QLINK_CMD_SCAN,
sizeof(struct qlink_cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(mac->bus);
@@ -2218,7 +2299,7 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_CONNECT,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
cmd = (struct qlink_cmd_connect *)cmd_skb->data;
@@ -2320,7 +2401,7 @@ int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code)
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_DISCONNECT,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(vif->mac->bus);
@@ -2354,7 +2435,7 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up)
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_UPDOWN_INTF,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
cmd = (struct qlink_cmd_updown *)cmd_skb->data;
@@ -2515,8 +2596,7 @@ int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, vif->vifid,
QLINK_CMD_CHAN_SWITCH,
sizeof(*cmd));
-
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(mac->bus);
@@ -2568,7 +2648,7 @@ int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef)
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_CHAN_GET,
sizeof(struct qlink_cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
qtnf_bus_lock(bus);
@@ -2607,7 +2687,7 @@ int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_START_CAC,
sizeof(*cmd));
- if (unlikely(!cmd_skb))
+ if (!cmd_skb)
return -ENOMEM;
cmd = (struct qlink_cmd_start_cac *)cmd_skb->data;
@@ -2637,19 +2717,21 @@ int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
{
struct qtnf_bus *bus = vif->mac->bus;
struct sk_buff *cmd_skb;
- struct qlink_cmd_set_mac_acl *cmd;
+ struct qlink_tlv_hdr *tlv;
+ size_t acl_size = qtnf_cmd_acl_data_size(params);
u16 res_code;
int ret;
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
QLINK_CMD_SET_MAC_ACL,
- sizeof(*cmd) +
- qtnf_cmd_acl_data_size(params));
- if (unlikely(!cmd_skb))
+ sizeof(struct qlink_cmd));
+ if (!cmd_skb)
return -ENOMEM;
- cmd = (struct qlink_cmd_set_mac_acl *)cmd_skb->data;
- qlink_acl_data_cfg2q(params, &cmd->acl);
+ tlv = skb_put(cmd_skb, sizeof(*tlv) + acl_size);
+ tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA);
+ tlv->len = cpu_to_le16(acl_size);
+ qlink_acl_data_cfg2q(params, (struct qlink_acl_data *)tlv->val);
qtnf_bus_lock(bus);
ret = qtnf_cmd_send(bus, cmd_skb, &res_code);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c
index ccd982b1c957..cf26c15a84f8 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
@@ -119,9 +119,38 @@ qtnf_netdev_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
/* Netdev handler for getting stats.
*/
-static struct net_device_stats *qtnf_netdev_get_stats(struct net_device *dev)
+static void qtnf_netdev_get_stats64(struct net_device *ndev,
+ struct rtnl_link_stats64 *stats)
{
- return &dev->stats;
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
+ unsigned int start;
+ int cpu;
+
+ netdev_stats_to_stats64(stats, &ndev->stats);
+
+ if (!vif->stats64)
+ return;
+
+ for_each_possible_cpu(cpu) {
+ struct pcpu_sw_netstats *stats64;
+ u64 rx_packets, rx_bytes;
+ u64 tx_packets, tx_bytes;
+
+ stats64 = per_cpu_ptr(vif->stats64, cpu);
+
+ do {
+ start = u64_stats_fetch_begin_irq(&stats64->syncp);
+ rx_packets = stats64->rx_packets;
+ rx_bytes = stats64->rx_bytes;
+ tx_packets = stats64->tx_packets;
+ tx_bytes = stats64->tx_bytes;
+ } while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
+
+ stats->rx_packets += rx_packets;
+ stats->rx_bytes += rx_bytes;
+ stats->tx_packets += tx_packets;
+ stats->tx_bytes += tx_bytes;
+ }
}
/* Netdev handler for transmission timeout.
@@ -156,7 +185,7 @@ const struct net_device_ops qtnf_netdev_ops = {
.ndo_stop = qtnf_netdev_close,
.ndo_start_xmit = qtnf_netdev_hard_start_xmit,
.ndo_tx_timeout = qtnf_netdev_tx_timeout,
- .ndo_get_stats = qtnf_netdev_get_stats,
+ .ndo_get_stats64 = qtnf_netdev_get_stats64,
};
static int qtnf_mac_init_single_band(struct wiphy *wiphy,
@@ -233,6 +262,23 @@ struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac)
return vif;
}
+void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac)
+{
+ struct ieee80211_iface_combination *comb;
+ int i;
+
+ if (mac->macinfo.if_comb) {
+ for (i = 0; i < mac->macinfo.n_if_comb; i++) {
+ comb = &mac->macinfo.if_comb[i];
+ kfree(comb->limits);
+ comb->limits = NULL;
+ }
+
+ kfree(mac->macinfo.if_comb);
+ mac->macinfo.if_comb = NULL;
+ }
+}
+
static void qtnf_vif_reset_handler(struct work_struct *work)
{
struct qtnf_vif *vif = container_of(work, struct qtnf_vif, reset_work);
@@ -265,6 +311,37 @@ static void qtnf_mac_init_primary_intf(struct qtnf_wmac *mac)
vif->cons_tx_timeout_cnt = 0;
}
+static void qtnf_mac_scan_finish(struct qtnf_wmac *mac, bool aborted)
+{
+ struct cfg80211_scan_info info = {
+ .aborted = aborted,
+ };
+
+ mutex_lock(&mac->mac_lock);
+
+ if (mac->scan_req) {
+ cfg80211_scan_done(mac->scan_req, &info);
+ mac->scan_req = NULL;
+ }
+
+ mutex_unlock(&mac->mac_lock);
+}
+
+void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted)
+{
+ cancel_delayed_work_sync(&mac->scan_timeout);
+ qtnf_mac_scan_finish(mac, aborted);
+}
+
+static void qtnf_mac_scan_timeout(struct work_struct *work)
+{
+ struct qtnf_wmac *mac =
+ container_of(work, struct qtnf_wmac, scan_timeout.work);
+
+ pr_warn("MAC%d: scan timed out\n", mac->macid);
+ qtnf_mac_scan_finish(mac, true);
+}
+
static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
unsigned int macid)
{
@@ -288,7 +365,12 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
mac->iflist[i].vifid = i;
qtnf_sta_list_init(&mac->iflist[i].sta_list);
mutex_init(&mac->mac_lock);
- timer_setup(&mac->scan_timeout, NULL, 0);
+ INIT_DELAYED_WORK(&mac->scan_timeout, qtnf_mac_scan_timeout);
+ mac->iflist[i].stats64 =
+ netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+ if (!mac->iflist[i].stats64)
+ pr_warn("VIF%u.%u: per cpu stats allocation failed\n",
+ macid, i);
}
qtnf_mac_init_primary_intf(mac);
@@ -297,6 +379,10 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
return mac;
}
+static const struct ethtool_ops qtnf_ethtool_ops = {
+ .get_drvinfo = cfg80211_get_drvinfo,
+};
+
int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif,
const char *name, unsigned char name_assign_type)
{
@@ -324,6 +410,7 @@ int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif,
dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
dev->watchdog_timeo = QTNF_DEF_WDOG_TIMEOUT;
dev->tx_queue_len = 100;
+ dev->ethtool_ops = &qtnf_ethtool_ops;
qdev_vif = netdev_priv(dev);
*((void **)qdev_vif) = vif;
@@ -364,6 +451,7 @@ static void qtnf_core_mac_detach(struct qtnf_bus *bus, unsigned int macid)
}
rtnl_unlock();
qtnf_sta_list_free(&vif->sta_list);
+ free_percpu(vif->stats64);
}
if (mac->wiphy_registered)
@@ -380,10 +468,9 @@ static void qtnf_core_mac_detach(struct qtnf_bus *bus, unsigned int macid)
wiphy->bands[band] = NULL;
}
- kfree(mac->macinfo.limits);
+ qtnf_mac_iface_comb_free(mac);
kfree(mac->macinfo.extended_capabilities);
kfree(mac->macinfo.extended_capabilities_mask);
- kfree(wiphy->iface_combinations);
wiphy_free(wiphy);
bus->mac[macid] = NULL;
}
@@ -643,6 +730,46 @@ void qtnf_wake_all_queues(struct net_device *ndev)
}
EXPORT_SYMBOL_GPL(qtnf_wake_all_queues);
+void qtnf_update_rx_stats(struct net_device *ndev, const struct sk_buff *skb)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
+ struct pcpu_sw_netstats *stats64;
+
+ if (unlikely(!vif || !vif->stats64)) {
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += skb->len;
+ return;
+ }
+
+ stats64 = this_cpu_ptr(vif->stats64);
+
+ u64_stats_update_begin(&stats64->syncp);
+ stats64->rx_packets++;
+ stats64->rx_bytes += skb->len;
+ u64_stats_update_end(&stats64->syncp);
+}
+EXPORT_SYMBOL_GPL(qtnf_update_rx_stats);
+
+void qtnf_update_tx_stats(struct net_device *ndev, const struct sk_buff *skb)
+{
+ struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
+ struct pcpu_sw_netstats *stats64;
+
+ if (unlikely(!vif || !vif->stats64)) {
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += skb->len;
+ return;
+ }
+
+ stats64 = this_cpu_ptr(vif->stats64);
+
+ u64_stats_update_begin(&stats64->syncp);
+ stats64->tx_packets++;
+ stats64->tx_bytes += skb->len;
+ u64_stats_update_end(&stats64->syncp);
+}
+EXPORT_SYMBOL_GPL(qtnf_update_tx_stats);
+
MODULE_AUTHOR("Quantenna Communications");
MODULE_DESCRIPTION("Quantenna 802.11 wireless LAN FullMAC driver.");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index c10900162297..3b884c80b6ab 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -89,6 +89,8 @@ struct qtnf_vif {
struct qtnf_sta_list sta_list;
unsigned long cons_tx_timeout_cnt;
int generation;
+
+ struct pcpu_sw_netstats __percpu *stats64;
};
struct qtnf_mac_info {
@@ -106,8 +108,8 @@ struct qtnf_mac_info {
u32 max_acl_mac_addrs;
struct ieee80211_ht_cap ht_cap_mod_mask;
struct ieee80211_vht_cap vht_cap_mod_mask;
- struct ieee80211_iface_limit *limits;
- size_t n_limits;
+ struct ieee80211_iface_combination *if_comb;
+ size_t n_if_comb;
u8 *extended_capabilities;
u8 *extended_capabilities_mask;
u8 extended_capabilities_len;
@@ -131,7 +133,7 @@ struct qtnf_wmac {
struct qtnf_vif iflist[QTNF_MAX_INTF];
struct cfg80211_scan_request *scan_req;
struct mutex mac_lock; /* lock during wmac speicific ops */
- struct timer_list scan_timeout;
+ struct delayed_work scan_timeout;
};
struct qtnf_hw_info {
@@ -143,10 +145,13 @@ struct qtnf_hw_info {
struct ieee80211_regdomain *rd;
u8 total_tx_chain;
u8 total_rx_chain;
+ char fw_version[ETHTOOL_FWVERS_LEN];
+ u32 hw_version;
};
struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac);
struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac);
+void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac);
struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus);
int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *priv,
const char *name, unsigned char name_assign_type);
@@ -157,9 +162,13 @@ int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac);
struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid);
struct net_device *qtnf_classify_skb(struct qtnf_bus *bus, struct sk_buff *skb);
void qtnf_wake_all_queues(struct net_device *ndev);
+void qtnf_update_rx_stats(struct net_device *ndev, const struct sk_buff *skb);
+void qtnf_update_tx_stats(struct net_device *ndev, const struct sk_buff *skb);
+
void qtnf_virtual_intf_cleanup(struct net_device *ndev);
void qtnf_netdev_updown(struct net_device *ndev, bool up);
+void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted);
static inline struct qtnf_vif *qtnf_netdev_get_priv(struct net_device *dev)
{
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
index 8a3d2b1194e4..bcd415f96412 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -541,9 +541,9 @@ static int qtnf_event_process_skb(struct qtnf_bus *bus,
if (unlikely(!mac))
return -ENXIO;
- qtnf_bus_lock(bus);
+ rtnl_lock();
res = qtnf_event_parse(mac, skb);
- qtnf_bus_unlock(bus);
+ rtnl_unlock();
return res;
}
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
index 7e487622d87d..6f6190964320 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
@@ -615,8 +615,7 @@ static void qtnf_pcie_data_tx_reclaim(struct qtnf_pcie_bus_priv *priv)
PCI_DMA_TODEVICE);
if (skb->dev) {
- skb->dev->stats.tx_packets++;
- skb->dev->stats.tx_bytes += skb->len;
+ qtnf_update_tx_stats(skb->dev, skb);
if (unlikely(priv->tx_stopped)) {
qtnf_wake_all_queues(skb->dev);
priv->tx_stopped = 0;
@@ -855,9 +854,7 @@ static int qtnf_rx_poll(struct napi_struct *napi, int budget)
skb_put(skb, psize);
ndev = qtnf_classify_skb(bus, skb);
if (likely(ndev)) {
- ndev->stats.rx_packets++;
- ndev->stats.rx_bytes += skb->len;
-
+ qtnf_update_rx_stats(ndev, skb);
skb->protocol = eth_type_trans(skb, ndev);
napi_gro_receive(napi, skb);
} else {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
index 6a1f960228a1..9bf3ae4d1b3b 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h
@@ -19,7 +19,7 @@
#include <linux/ieee80211.h>
-#define QLINK_PROTO_VER 10
+#define QLINK_PROTO_VER 11
#define QLINK_MACID_RSVD 0xFF
#define QLINK_VIFID_RSVD 0xFF
@@ -663,16 +663,6 @@ struct qlink_acl_data {
struct qlink_mac_address mac_addrs[0];
} __packed;
-/**
- * struct qlink_cmd_set_mac_acl - data for QLINK_CMD_SET_MAC_ACL command
- *
- * @acl: ACL data.
- */
-struct qlink_cmd_set_mac_acl {
- struct qlink_cmd chdr;
- struct qlink_acl_data acl;
-} __packed;
-
/* QLINK Command Responses messages related definitions
*/
@@ -774,6 +764,9 @@ struct qlink_resp_get_hw_info {
struct qlink_resp rhdr;
__le32 fw_ver;
__le32 hw_capab;
+ __le32 bld_tmstamp;
+ __le32 plat_id;
+ __le32 hw_ver;
__le16 ql_proto_ver;
u8 num_mac;
u8 mac_bitmap;
@@ -1084,6 +1077,13 @@ enum qlink_tlv_id {
QTN_TLV_ID_IE_SET = 0x0305,
QTN_TLV_ID_EXT_CAPABILITY_MASK = 0x0306,
QTN_TLV_ID_ACL_DATA = 0x0307,
+ QTN_TLV_ID_BUILD_NAME = 0x0401,
+ QTN_TLV_ID_BUILD_REV = 0x0402,
+ QTN_TLV_ID_BUILD_TYPE = 0x0403,
+ QTN_TLV_ID_BUILD_LABEL = 0x0404,
+ QTN_TLV_ID_HW_ID = 0x0405,
+ QTN_TLV_ID_CALIBRATION_VER = 0x0406,
+ QTN_TLV_ID_UBOOT_VER = 0x0407,
};
struct qlink_tlv_hdr {
@@ -1092,13 +1092,20 @@ struct qlink_tlv_hdr {
u8 val[0];
} __packed;
+struct qlink_iface_comb_num {
+ __le32 iface_comb_num;
+} __packed;
+
struct qlink_iface_limit {
__le16 max_num;
__le16 type;
} __packed;
-struct qlink_iface_comb_num {
- __le16 iface_comb_num;
+struct qlink_iface_limit_record {
+ __le16 max_interfaces;
+ u8 num_different_channels;
+ u8 n_limits;
+ struct qlink_iface_limit limits[0];
} __packed;
#define QLINK_RSSI_OFFSET 120
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
index 95e3993d8a33..8828baf26e7b 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
@@ -1172,7 +1172,7 @@ struct rtl8723bu_c2h {
u8 basic_rate:1;
u8 bt_has_reset:1;
- u8 dummy4_1:1;;
+ u8 dummy4_1:1;
u8 ignore_wlan:1;
u8 auto_report:1;
u8 dummy4_2:3;
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index c8ebf738cb2b..d6c03bd5cc65 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -244,7 +244,8 @@ static void _rtl_init_hw_vht_capab(struct ieee80211_hw *hw,
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE ||
+ rtlhal->hw_type == HARDWARE_TYPE_RTL8822BE) {
u16 mcs_map;
vht_cap->vht_supported = true;
@@ -697,14 +698,94 @@ static void _rtl_query_protection_mode(struct ieee80211_hw *hw,
}
}
+u8 rtl_mrate_idx_to_arfr_id(struct ieee80211_hw *hw, u8 rate_index,
+ enum wireless_mode wirelessmode)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_phy *rtlphy = &rtlpriv->phy;
+ u8 ret = 0;
+
+ switch (rate_index) {
+ case RATR_INX_WIRELESS_NGB:
+ if (rtlphy->rf_type == RF_1T1R)
+ ret = RATEID_IDX_BGN_40M_1SS;
+ else
+ ret = RATEID_IDX_BGN_40M_2SS;
+ ; break;
+ case RATR_INX_WIRELESS_N:
+ case RATR_INX_WIRELESS_NG:
+ if (rtlphy->rf_type == RF_1T1R)
+ ret = RATEID_IDX_GN_N1SS;
+ else
+ ret = RATEID_IDX_GN_N2SS;
+ ; break;
+ case RATR_INX_WIRELESS_NB:
+ if (rtlphy->rf_type == RF_1T1R)
+ ret = RATEID_IDX_BGN_20M_1SS_BN;
+ else
+ ret = RATEID_IDX_BGN_20M_2SS_BN;
+ ; break;
+ case RATR_INX_WIRELESS_GB:
+ ret = RATEID_IDX_BG;
+ break;
+ case RATR_INX_WIRELESS_G:
+ ret = RATEID_IDX_G;
+ break;
+ case RATR_INX_WIRELESS_B:
+ ret = RATEID_IDX_B;
+ break;
+ case RATR_INX_WIRELESS_MC:
+ if (wirelessmode == WIRELESS_MODE_B ||
+ wirelessmode == WIRELESS_MODE_G ||
+ wirelessmode == WIRELESS_MODE_N_24G ||
+ wirelessmode == WIRELESS_MODE_AC_24G)
+ ret = RATEID_IDX_BG;
+ else
+ ret = RATEID_IDX_G;
+ break;
+ case RATR_INX_WIRELESS_AC_5N:
+ if (rtlphy->rf_type == RF_1T1R)
+ ret = RATEID_IDX_VHT_1SS;
+ else
+ ret = RATEID_IDX_VHT_2SS;
+ break;
+ case RATR_INX_WIRELESS_AC_24N:
+ if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) {
+ if (rtlphy->rf_type == RF_1T1R)
+ ret = RATEID_IDX_VHT_1SS;
+ else
+ ret = RATEID_IDX_VHT_2SS;
+ } else {
+ if (rtlphy->rf_type == RF_1T1R)
+ ret = RATEID_IDX_MIX1;
+ else
+ ret = RATEID_IDX_MIX2;
+ }
+ break;
+ default:
+ ret = RATEID_IDX_BGN_40M_2SS;
+ break;
+ }
+ return ret;
+}
+EXPORT_SYMBOL(rtl_mrate_idx_to_arfr_id);
+
static void _rtl_txrate_selectmode(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
struct rtl_tcb_desc *tcb_desc)
{
+#define SET_RATE_ID(rate_id) \
+ ({typeof(rate_id) _id = rate_id; \
+ ((rtlpriv->cfg->spec_ver & RTL_SPEC_NEW_RATEID) ? \
+ rtl_mrate_idx_to_arfr_id(hw, _id, \
+ (sta_entry ? sta_entry->wireless_mode : \
+ WIRELESS_MODE_G)) : \
+ _id); })
+
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_sta_info *sta_entry = NULL;
- u8 ratr_index = 7;
+ u8 ratr_index = SET_RATE_ID(RATR_INX_WIRELESS_MC);
if (sta) {
sta_entry = (struct rtl_sta_info *) sta->drv_priv;
@@ -719,7 +800,8 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw,
tcb_desc->hw_rate =
rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M];
tcb_desc->use_driver_rate = 1;
- tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;
+ tcb_desc->ratr_index =
+ SET_RATE_ID(RATR_INX_WIRELESS_MC);
} else {
tcb_desc->ratr_index = ratr_index;
}
@@ -735,22 +817,30 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw,
mac->opmode == NL80211_IFTYPE_MESH_POINT) {
tcb_desc->mac_id = 0;
- if (mac->mode == WIRELESS_MODE_AC_5G)
+ if (sta &&
+ (rtlpriv->cfg->spec_ver & RTL_SPEC_NEW_RATEID))
+ ; /* use sta_entry->ratr_index */
+ else if (mac->mode == WIRELESS_MODE_AC_5G)
tcb_desc->ratr_index =
- RATR_INX_WIRELESS_AC_5N;
+ SET_RATE_ID(RATR_INX_WIRELESS_AC_5N);
else if (mac->mode == WIRELESS_MODE_AC_24G)
tcb_desc->ratr_index =
- RATR_INX_WIRELESS_AC_24N;
+ SET_RATE_ID(RATR_INX_WIRELESS_AC_24N);
else if (mac->mode == WIRELESS_MODE_N_24G)
- tcb_desc->ratr_index = RATR_INX_WIRELESS_NGB;
+ tcb_desc->ratr_index =
+ SET_RATE_ID(RATR_INX_WIRELESS_NGB);
else if (mac->mode == WIRELESS_MODE_N_5G)
- tcb_desc->ratr_index = RATR_INX_WIRELESS_NG;
+ tcb_desc->ratr_index =
+ SET_RATE_ID(RATR_INX_WIRELESS_NG);
else if (mac->mode & WIRELESS_MODE_G)
- tcb_desc->ratr_index = RATR_INX_WIRELESS_GB;
+ tcb_desc->ratr_index =
+ SET_RATE_ID(RATR_INX_WIRELESS_GB);
else if (mac->mode & WIRELESS_MODE_B)
- tcb_desc->ratr_index = RATR_INX_WIRELESS_B;
+ tcb_desc->ratr_index =
+ SET_RATE_ID(RATR_INX_WIRELESS_B);
else if (mac->mode & WIRELESS_MODE_A)
- tcb_desc->ratr_index = RATR_INX_WIRELESS_G;
+ tcb_desc->ratr_index =
+ SET_RATE_ID(RATR_INX_WIRELESS_G);
} else if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_ADHOC) {
@@ -764,6 +854,7 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw,
}
}
}
+#undef SET_RATE_ID
}
static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw,
@@ -1140,9 +1231,19 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc)
{
+#define SET_RATE_ID(rate_id) \
+ ({typeof(rate_id) _id = rate_id; \
+ ((rtlpriv->cfg->spec_ver & RTL_SPEC_NEW_RATEID) ? \
+ rtl_mrate_idx_to_arfr_id(hw, _id, \
+ (sta_entry ? sta_entry->wireless_mode : \
+ WIRELESS_MODE_G)) : \
+ _id); })
+
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
+ struct rtl_sta_info *sta_entry =
+ (sta ? (struct rtl_sta_info *)sta->drv_priv : NULL);
__le16 fc = rtl_get_fc(skb);
@@ -1165,7 +1266,8 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
if (info->control.rates[0].idx == 0 ||
ieee80211_is_nullfunc(fc)) {
tcb_desc->use_driver_rate = true;
- tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;
+ tcb_desc->ratr_index =
+ SET_RATE_ID(RATR_INX_WIRELESS_MC);
tcb_desc->disable_ratefallback = 1;
} else {
@@ -1207,11 +1309,12 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
_rtl_query_protection_mode(hw, tcb_desc, info);
} else {
tcb_desc->use_driver_rate = true;
- tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;
+ tcb_desc->ratr_index = SET_RATE_ID(RATR_INX_WIRELESS_MC);
tcb_desc->disable_ratefallback = 1;
tcb_desc->mac_id = 0;
tcb_desc->packet_bw = false;
}
+#undef SET_RATE_ID
}
EXPORT_SYMBOL(rtl_get_tcb_desc);
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h
index 26735319b38f..acc924635818 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.h
+++ b/drivers/net/wireless/realtek/rtlwifi/base.h
@@ -162,6 +162,8 @@ void rtl_c2hcmd_wq_callback(void *data);
void rtl_c2hcmd_launcher(struct ieee80211_hw *hw, int exec);
void rtl_c2hcmd_enqueue(struct ieee80211_hw *hw, u8 tag, u8 len, u8 *val);
+u8 rtl_mrate_idx_to_arfr_id(struct ieee80211_hw *hw, u8 rate_index,
+ enum wireless_mode wirelessmode);
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta,
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
index af8f3778dc91..1404729441a2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
@@ -29,7 +29,7 @@
* Debug related function
***************************************************/
-const char *const gl_btc_wifi_bw_string[] = {
+static const char *const gl_btc_wifi_bw_string[] = {
"11bg",
"HT20",
"HT40",
@@ -37,7 +37,7 @@ const char *const gl_btc_wifi_bw_string[] = {
"HT160"
};
-const char *const gl_btc_wifi_freq_string[] = {
+static const char *const gl_btc_wifi_freq_string[] = {
"2.4G",
"5G"
};
@@ -95,21 +95,6 @@ static bool is_any_client_connect_to_ap(struct btc_coexist *btcoexist)
return false;
}
-static bool halbtc_is_bt40(struct rtl_priv *adapter)
-{
- struct rtl_priv *rtlpriv = adapter;
- struct rtl_phy *rtlphy = &(rtlpriv->phy);
- bool is_ht40 = true;
- enum ht_channel_width bw = rtlphy->current_chan_bw;
-
- if (bw == HT_CHANNEL_WIDTH_20)
- is_ht40 = false;
- else if (bw == HT_CHANNEL_WIDTH_20_40)
- is_ht40 = true;
-
- return is_ht40;
-}
-
static bool halbtc_legacy(struct rtl_priv *adapter)
{
struct rtl_priv *rtlpriv = adapter;
@@ -135,18 +120,26 @@ bool halbtc_is_wifi_uplink(struct rtl_priv *adapter)
static u32 halbtc_get_wifi_bw(struct btc_coexist *btcoexist)
{
- struct rtl_priv *rtlpriv =
- (struct rtl_priv *)btcoexist->adapter;
+ struct rtl_priv *rtlpriv = btcoexist->adapter;
+ struct rtl_phy *rtlphy = &rtlpriv->phy;
u32 wifi_bw = BTC_WIFI_BW_HT20;
- if (halbtc_is_bt40(rtlpriv)) {
- wifi_bw = BTC_WIFI_BW_HT40;
+ if (halbtc_legacy(rtlpriv)) {
+ wifi_bw = BTC_WIFI_BW_LEGACY;
} else {
- if (halbtc_legacy(rtlpriv))
- wifi_bw = BTC_WIFI_BW_LEGACY;
- else
+ switch (rtlphy->current_chan_bw) {
+ case HT_CHANNEL_WIDTH_20:
wifi_bw = BTC_WIFI_BW_HT20;
+ break;
+ case HT_CHANNEL_WIDTH_20_40:
+ wifi_bw = BTC_WIFI_BW_HT40;
+ break;
+ case HT_CHANNEL_WIDTH_80:
+ wifi_bw = BTC_WIFI_BW_HT80;
+ break;
+ }
}
+
return wifi_bw;
}
@@ -163,7 +156,7 @@ static u8 halbtc_get_wifi_central_chnl(struct btc_coexist *btcoexist)
return chnl;
}
-u8 rtl_get_hwpg_single_ant_path(struct rtl_priv *rtlpriv)
+static u8 rtl_get_hwpg_single_ant_path(struct rtl_priv *rtlpriv)
{
struct rtl_mod_params *mod_params = rtlpriv->cfg->mod_params;
@@ -178,12 +171,12 @@ u8 rtl_get_hwpg_single_ant_path(struct rtl_priv *rtlpriv)
return rtlpriv->btcoexist.btc_info.single_ant_path;
}
-u8 rtl_get_hwpg_bt_type(struct rtl_priv *rtlpriv)
+static u8 rtl_get_hwpg_bt_type(struct rtl_priv *rtlpriv)
{
return rtlpriv->btcoexist.btc_info.bt_type;
}
-u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv)
+static u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv)
{
struct rtl_mod_params *mod_params = rtlpriv->cfg->mod_params;
u8 num;
@@ -200,7 +193,7 @@ u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv)
return num;
}
-u8 rtl_get_hwpg_package_type(struct rtl_priv *rtlpriv)
+static u8 rtl_get_hwpg_package_type(struct rtl_priv *rtlpriv)
{
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
@@ -511,7 +504,7 @@ static u32 halbtc_get_bt_forbidden_slot_val(void *btc_context)
return btcoexist->bt_info.bt_forb_slot_val;
}
-u32 halbtc_get_wifi_link_status(struct btc_coexist *btcoexist)
+static u32 halbtc_get_wifi_link_status(struct btc_coexist *btcoexist)
{
/* return value:
* [31:16] => connected port number
@@ -987,7 +980,8 @@ static void halbtc_write_4byte(void *bt_context, u32 reg_addr, u32 data)
rtl_write_dword(rtlpriv, reg_addr, data);
}
-void halbtc_write_local_reg_1byte(void *btc_context, u32 reg_addr, u8 data)
+static void halbtc_write_local_reg_1byte(void *btc_context, u32 reg_addr,
+ u8 data)
{
struct btc_coexist *btcoexist = (struct btc_coexist *)btc_context;
struct rtl_priv *rtlpriv = btcoexist->adapter;
@@ -1000,22 +994,6 @@ void halbtc_write_local_reg_1byte(void *btc_context, u32 reg_addr, u8 data)
rtl_write_byte(rtlpriv, reg_addr, data);
}
-void halbtc_set_macreg(void *btc_context, u32 reg_addr, u32 bit_mask, u32 data)
-{
- struct btc_coexist *btcoexist = (struct btc_coexist *)btc_context;
- struct rtl_priv *rtlpriv = btcoexist->adapter;
-
- rtl_set_bbreg(rtlpriv->mac80211.hw, reg_addr, bit_mask, data);
-}
-
-u32 halbtc_get_macreg(void *btc_context, u32 reg_addr, u32 bit_mask)
-{
- struct btc_coexist *btcoexist = (struct btc_coexist *)btc_context;
- struct rtl_priv *rtlpriv = btcoexist->adapter;
-
- return rtl_get_bbreg(rtlpriv->mac80211.hw, reg_addr, bit_mask);
-}
-
static void halbtc_set_bbreg(void *bt_context, u32 reg_addr, u32 bit_mask,
u32 data)
{
@@ -1061,6 +1039,7 @@ static void halbtc_fill_h2c_cmd(void *bt_context, u8 element_id,
cmd_len, cmd_buf);
}
+static
void halbtc_set_bt_reg(void *btc_context, u8 reg_type, u32 offset, u32 set_val)
{
struct btc_coexist *btcoexist = (struct btc_coexist *)btc_context;
@@ -1100,7 +1079,7 @@ static void halbtc_display_dbg_msg(void *bt_context, u8 disp_type,
}
}
-bool halbtc_under_ips(struct btc_coexist *btcoexist)
+static bool halbtc_under_ips(struct btc_coexist *btcoexist)
{
struct rtl_priv *rtlpriv = btcoexist->adapter;
struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
@@ -1254,6 +1233,40 @@ bool exhalbtc_initlize_variables(struct rtl_priv *rtlpriv)
return true;
}
+bool exhalbtc_initlize_variables_wifi_only(struct rtl_priv *rtlpriv)
+{
+ struct wifi_only_cfg *wifionly_cfg = rtl_btc_wifi_only(rtlpriv);
+ struct wifi_only_haldata *wifionly_haldata;
+
+ if (!wifionly_cfg)
+ return false;
+
+ wifionly_cfg->adapter = rtlpriv;
+
+ switch (rtlpriv->rtlhal.interface) {
+ case INTF_PCI:
+ wifionly_cfg->chip_interface = BTC_INTF_PCI;
+ break;
+ case INTF_USB:
+ wifionly_cfg->chip_interface = BTC_INTF_USB;
+ break;
+ default:
+ wifionly_cfg->chip_interface = BTC_INTF_UNKNOWN;
+ break;
+ }
+
+ wifionly_haldata = &wifionly_cfg->haldata_info;
+
+ wifionly_haldata->customer_id = CUSTOMER_NORMAL;
+ wifionly_haldata->efuse_pg_antnum = rtl_get_hwpg_ant_num(rtlpriv);
+ wifionly_haldata->efuse_pg_antpath =
+ rtl_get_hwpg_single_ant_path(rtlpriv);
+ wifionly_haldata->rfe_type = rtl_get_hwpg_rfe_type(rtlpriv);
+ wifionly_haldata->ant_div_cfg = 0;
+
+ return true;
+}
+
bool exhalbtc_bind_bt_coex_withadapter(void *adapter)
{
struct rtl_priv *rtlpriv = adapter;
@@ -1317,6 +1330,7 @@ bool exhalbtc_bind_bt_coex_withadapter(void *adapter)
"[BTCoex], Package Type = Non-TFBGA\n");
btcoexist->board_info.rfe_type = rtl_get_hwpg_rfe_type(rtlpriv);
+ btcoexist->board_info.ant_div_cfg = 0;
return true;
}
@@ -1374,6 +1388,10 @@ void exhalbtc_init_hw_config(struct btc_coexist *btcoexist, bool wifi_only)
}
}
+void exhalbtc_init_hw_config_wifi_only(struct wifi_only_cfg *wifionly_cfg)
+{
+}
+
void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist)
{
if (!halbtc_is_bt_coexist_available(btcoexist))
@@ -1500,6 +1518,11 @@ void exhalbtc_scan_notify(struct btc_coexist *btcoexist, u8 type)
halbtc_normal_low_power(btcoexist);
}
+void exhalbtc_scan_notify_wifi_only(struct wifi_only_cfg *wifionly_cfg,
+ u8 is_5g)
+{
+}
+
void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action)
{
u8 asso_type;
@@ -1917,3 +1940,21 @@ void exhalbtc_display_bt_coex_info(struct btc_coexist *btcoexist,
halbtc_normal_low_power(btcoexist);
}
+
+void exhalbtc_switch_band_notify(struct btc_coexist *btcoexist, u8 type)
+{
+ if (!halbtc_is_bt_coexist_available(btcoexist))
+ return;
+
+ if (btcoexist->manual_control)
+ return;
+
+ halbtc_leave_low_power(btcoexist);
+
+ halbtc_normal_low_power(btcoexist);
+}
+
+void exhalbtc_switch_band_notify_wifi_only(struct wifi_only_cfg *wifionly_cfg,
+ u8 is_5g)
+{
+}
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
index 57caaf130a46..8ed217656539 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
@@ -153,6 +153,7 @@ struct btc_board_info {
bool tfbga_package;
u8 rfe_type;
+ u8 ant_div_cfg;
};
enum btc_dbg_opcode {
@@ -190,6 +191,7 @@ enum btc_wifi_bw_mode {
BTC_WIFI_BW_LEGACY = 0x0,
BTC_WIFI_BW_HT20 = 0x1,
BTC_WIFI_BW_HT40 = 0x2,
+ BTC_WIFI_BW_HT80 = 0x3,
BTC_WIFI_BW_MAX
};
@@ -384,6 +386,14 @@ enum btc_notify_type_scan {
BTC_SCAN_MAX
};
+enum btc_notify_type_switchband {
+ BTC_NOT_SWITCH = 0x0,
+ BTC_SWITCH_TO_24G = 0x1,
+ BTC_SWITCH_TO_5G = 0x2,
+ BTC_SWITCH_TO_24G_NOFORSCAN = 0x3,
+ BTC_SWITCH_MAX
+};
+
enum btc_notify_type_associate {
BTC_ASSOCIATE_FINISH = 0x0,
BTC_ASSOCIATE_START = 0x1,
@@ -573,6 +583,8 @@ struct btc_coexist {
*/
bool auto_report_1ant;
bool auto_report_2ant;
+ bool dbg_mode_1ant;
+ bool dbg_mode_2ant;
bool initilized;
bool stop_coex_dm;
bool manual_control;
@@ -626,21 +638,31 @@ bool halbtc_is_wifi_uplink(struct rtl_priv *adapter);
#define rtl_btc_coexist(rtlpriv) \
((struct btc_coexist *)((rtlpriv)->btcoexist.btc_context))
+#define rtl_btc_wifi_only(rtlpriv) \
+ ((struct wifi_only_cfg *)((rtlpriv)->btcoexist.wifi_only_context))
+
+struct wifi_only_cfg;
bool exhalbtc_initlize_variables(struct rtl_priv *rtlpriv);
+bool exhalbtc_initlize_variables_wifi_only(struct rtl_priv *rtlpriv);
bool exhalbtc_bind_bt_coex_withadapter(void *adapter);
void exhalbtc_power_on_setting(struct btc_coexist *btcoexist);
+void exhalbtc_pre_load_firmware(struct btc_coexist *btcoexist);
void exhalbtc_init_hw_config(struct btc_coexist *btcoexist, bool wifi_only);
+void exhalbtc_init_hw_config_wifi_only(struct wifi_only_cfg *wifionly_cfg);
void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist);
void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type);
void exhalbtc_lps_notify(struct btc_coexist *btcoexist, u8 type);
void exhalbtc_scan_notify(struct btc_coexist *btcoexist, u8 type);
+void exhalbtc_scan_notify_wifi_only(struct wifi_only_cfg *wifionly_cfg,
+ u8 is_5g);
void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action);
void exhalbtc_mediastatus_notify(struct btc_coexist *btcoexist,
enum rt_media_status media_status);
void exhalbtc_special_packet_notify(struct btc_coexist *btcoexist, u8 pkt_type);
void exhalbtc_bt_info_notify(struct btc_coexist *btcoexist, u8 *tmp_buf,
u8 length);
+void exhalbtc_rf_status_notify(struct btc_coexist *btcoexist, u8 type);
void exhalbtc_stack_operation_notify(struct btc_coexist *btcoexist, u8 type);
void exhalbtc_halt_notify(struct btc_coexist *btcoexist);
void exhalbtc_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state);
@@ -648,6 +670,8 @@ void exhalbtc_coex_dm_switch(struct btc_coexist *btcoexist);
void exhalbtc_periodical(struct btc_coexist *btcoexist);
void exhalbtc_dbg_control(struct btc_coexist *btcoexist, u8 code, u8 len,
u8 *data);
+void exhalbtc_antenna_detection(struct btc_coexist *btcoexist, u32 cent_freq,
+ u32 offset, u32 span, u32 seconds);
void exhalbtc_stack_update_profile_info(void);
void exhalbtc_set_hci_version(struct btc_coexist *btcoexist, u16 hci_version);
void exhalbtc_set_bt_patch_version(struct btc_coexist *btcoexist,
@@ -658,6 +682,9 @@ void exhalbtc_set_chip_type(struct btc_coexist *btcoexist, u8 chip_type);
void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num);
void exhalbtc_display_bt_coex_info(struct btc_coexist *btcoexist,
struct seq_file *m);
+void exhalbtc_switch_band_notify(struct btc_coexist *btcoexist, u8 type);
+void exhalbtc_switch_band_notify_wifi_only(struct wifi_only_cfg *wifionly_cfg,
+ u8 is_5g);
void exhalbtc_signal_compensation(struct btc_coexist *btcoexist,
u8 *rssi_wifi, u8 *rssi_bt);
void exhalbtc_lps_leave(struct btc_coexist *btcoexist);
@@ -665,4 +692,41 @@ void exhalbtc_low_wifi_traffic_notify(struct btc_coexist *btcoexist);
void exhalbtc_set_single_ant_path(struct btc_coexist *btcoexist,
u8 single_ant_path);
+/* The following are used by wifi_only case */
+enum wifionly_chip_interface {
+ WIFIONLY_INTF_UNKNOWN = 0,
+ WIFIONLY_INTF_PCI = 1,
+ WIFIONLY_INTF_USB = 2,
+ WIFIONLY_INTF_SDIO = 3,
+ WIFIONLY_INTF_MAX
+};
+
+enum wifionly_customer_id {
+ CUSTOMER_NORMAL = 0,
+ CUSTOMER_HP_1 = 1,
+};
+
+struct wifi_only_haldata {
+ u16 customer_id;
+ u8 efuse_pg_antnum;
+ u8 efuse_pg_antpath;
+ u8 rfe_type;
+ u8 ant_div_cfg;
+};
+
+struct wifi_only_cfg {
+ void *adapter;
+ struct wifi_only_haldata haldata_info;
+ enum wifionly_chip_interface chip_interface;
+};
+
+static inline
+void halwifionly_phy_set_bb_reg(struct wifi_only_cfg *wifi_conly_cfg,
+ u32 regaddr, u32 bitmask, u32 data)
+{
+ struct rtl_priv *rtlpriv = (struct rtl_priv *)wifi_conly_cfg->adapter;
+
+ rtl_set_bbreg(rtlpriv->hw, regaddr, bitmask, data);
+}
+
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
index 714c0de099e5..cce4a37ea408 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
@@ -31,13 +31,16 @@
static struct rtl_btc_ops rtl_btc_operation = {
.btc_init_variables = rtl_btc_init_variables,
+ .btc_init_variables_wifi_only = rtl_btc_init_variables_wifi_only,
.btc_deinit_variables = rtl_btc_deinit_variables,
.btc_init_hal_vars = rtl_btc_init_hal_vars,
.btc_power_on_setting = rtl_btc_power_on_setting,
.btc_init_hw_config = rtl_btc_init_hw_config,
+ .btc_init_hw_config_wifi_only = rtl_btc_init_hw_config_wifi_only,
.btc_ips_notify = rtl_btc_ips_notify,
.btc_lps_notify = rtl_btc_lps_notify,
.btc_scan_notify = rtl_btc_scan_notify,
+ .btc_scan_notify_wifi_only = rtl_btc_scan_notify_wifi_only,
.btc_connect_notify = rtl_btc_connect_notify,
.btc_mediastatus_notify = rtl_btc_mediastatus_notify,
.btc_periodical = rtl_btc_periodical,
@@ -48,6 +51,8 @@ static struct rtl_btc_ops rtl_btc_operation = {
.btc_is_disable_edca_turbo = rtl_btc_is_disable_edca_turbo,
.btc_is_bt_disabled = rtl_btc_is_bt_disabled,
.btc_special_packet_notify = rtl_btc_special_packet_notify,
+ .btc_switch_band_notify = rtl_btc_switch_band_notify,
+ .btc_switch_band_notify_wifi_only = rtl_btc_switch_band_notify_wifionly,
.btc_record_pwr_mode = rtl_btc_record_pwr_mode,
.btc_get_lps_val = rtl_btc_get_lps_val,
.btc_get_rpwm_val = rtl_btc_get_rpwm_val,
@@ -146,7 +151,11 @@ void rtl_btc_get_ampdu_cfg(struct rtl_priv *rtlpriv, u8 *reject_agg,
static void rtl_btc_alloc_variable(struct rtl_priv *rtlpriv, bool wifi_only)
{
- rtlpriv->btcoexist.btc_context =
+ if (wifi_only)
+ rtlpriv->btcoexist.wifi_only_context =
+ kzalloc(sizeof(struct wifi_only_cfg), GFP_KERNEL);
+ else
+ rtlpriv->btcoexist.btc_context =
kzalloc(sizeof(struct btc_coexist), GFP_KERNEL);
}
@@ -154,6 +163,9 @@ static void rtl_btc_free_variable(struct rtl_priv *rtlpriv)
{
kfree(rtlpriv->btcoexist.btc_context);
rtlpriv->btcoexist.btc_context = NULL;
+
+ kfree(rtlpriv->btcoexist.wifi_only_context);
+ rtlpriv->btcoexist.wifi_only_context = NULL;
}
void rtl_btc_init_variables(struct rtl_priv *rtlpriv)
@@ -164,6 +176,13 @@ void rtl_btc_init_variables(struct rtl_priv *rtlpriv)
exhalbtc_bind_bt_coex_withadapter(rtlpriv);
}
+void rtl_btc_init_variables_wifi_only(struct rtl_priv *rtlpriv)
+{
+ rtl_btc_alloc_variable(rtlpriv, true);
+
+ exhalbtc_initlize_variables_wifi_only(rtlpriv);
+}
+
void rtl_btc_deinit_variables(struct rtl_priv *rtlpriv)
{
rtl_btc_free_variable(rtlpriv);
@@ -203,6 +222,16 @@ void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv)
exhalbtc_init_coex_dm(btcoexist);
}
+void rtl_btc_init_hw_config_wifi_only(struct rtl_priv *rtlpriv)
+{
+ struct wifi_only_cfg *wifionly_cfg = rtl_btc_wifi_only(rtlpriv);
+
+ if (!wifionly_cfg)
+ return;
+
+ exhalbtc_init_hw_config_wifi_only(wifionly_cfg);
+}
+
void rtl_btc_ips_notify(struct rtl_priv *rtlpriv, u8 type)
{
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
@@ -211,6 +240,14 @@ void rtl_btc_ips_notify(struct rtl_priv *rtlpriv, u8 type)
return;
exhalbtc_ips_notify(btcoexist, type);
+
+ if (type == ERFON) {
+ /* In some situation, it doesn't scan after leaving IPS, and
+ * this will cause btcoex in wrong state.
+ */
+ exhalbtc_scan_notify(btcoexist, 1);
+ exhalbtc_scan_notify(btcoexist, 0);
+ }
}
void rtl_btc_lps_notify(struct rtl_priv *rtlpriv, u8 type)
@@ -233,6 +270,18 @@ void rtl_btc_scan_notify(struct rtl_priv *rtlpriv, u8 scantype)
exhalbtc_scan_notify(btcoexist, scantype);
}
+void rtl_btc_scan_notify_wifi_only(struct rtl_priv *rtlpriv, u8 scantype)
+{
+ struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+ struct wifi_only_cfg *wifionly_cfg = rtl_btc_wifi_only(rtlpriv);
+ u8 is_5g = (rtlhal->current_bandtype == BAND_ON_5G);
+
+ if (!wifionly_cfg)
+ return;
+
+ exhalbtc_scan_notify_wifi_only(wifionly_cfg, is_5g);
+}
+
void rtl_btc_connect_notify(struct rtl_priv *rtlpriv, u8 action)
{
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
@@ -423,6 +472,44 @@ void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type)
return exhalbtc_special_packet_notify(btcoexist, pkt_type);
}
+void rtl_btc_switch_band_notify(struct rtl_priv *rtlpriv, u8 band_type,
+ bool scanning)
+{
+ struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
+ u8 type = BTC_NOT_SWITCH;
+
+ if (!btcoexist)
+ return;
+
+ switch (band_type) {
+ case BAND_ON_2_4G:
+ if (scanning)
+ type = BTC_SWITCH_TO_24G;
+ else
+ type = BTC_SWITCH_TO_24G_NOFORSCAN;
+ break;
+
+ case BAND_ON_5G:
+ type = BTC_SWITCH_TO_5G;
+ break;
+ }
+
+ if (type != BTC_NOT_SWITCH)
+ exhalbtc_switch_band_notify(btcoexist, type);
+}
+
+void rtl_btc_switch_band_notify_wifionly(struct rtl_priv *rtlpriv, u8 band_type,
+ bool scanning)
+{
+ struct wifi_only_cfg *wifionly_cfg = rtl_btc_wifi_only(rtlpriv);
+ u8 is_5g = (band_type == BAND_ON_5G);
+
+ if (!wifionly_cfg)
+ return;
+
+ exhalbtc_switch_band_notify_wifi_only(wifionly_cfg, is_5g);
+}
+
struct rtl_btc_ops *rtl_btc_get_ops_pointer(void)
{
return &rtl_btc_operation;
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
index 8c5098266039..8c996055de71 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
@@ -28,13 +28,16 @@
#include "halbt_precomp.h"
void rtl_btc_init_variables(struct rtl_priv *rtlpriv);
+void rtl_btc_init_variables_wifi_only(struct rtl_priv *rtlpriv);
void rtl_btc_deinit_variables(struct rtl_priv *rtlpriv);
void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv);
void rtl_btc_power_on_setting(struct rtl_priv *rtlpriv);
void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv);
+void rtl_btc_init_hw_config_wifi_only(struct rtl_priv *rtlpriv);
void rtl_btc_ips_notify(struct rtl_priv *rtlpriv, u8 type);
void rtl_btc_lps_notify(struct rtl_priv *rtlpriv, u8 type);
void rtl_btc_scan_notify(struct rtl_priv *rtlpriv, u8 scantype);
+void rtl_btc_scan_notify_wifi_only(struct rtl_priv *rtlpriv, u8 scantype);
void rtl_btc_connect_notify(struct rtl_priv *rtlpriv, u8 action);
void rtl_btc_mediastatus_notify(struct rtl_priv *rtlpriv,
enum rt_media_status mstatus);
@@ -46,6 +49,10 @@ bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv);
bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv);
bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv);
void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type);
+void rtl_btc_switch_band_notify(struct rtl_priv *rtlpriv, u8 band_type,
+ bool scanning);
+void rtl_btc_switch_band_notify_wifionly(struct rtl_priv *rtlpriv, u8 band_type,
+ bool scanning);
void rtl_btc_display_bt_coex_info(struct rtl_priv *rtlpriv, struct seq_file *m);
void rtl_btc_record_pwr_mode(struct rtl_priv *rtlpriv, u8 *buf, u8 len);
u8 rtl_btc_get_lps_val(struct rtl_priv *rtlpriv);
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index a16aa94273e8..cfea57efa7f4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -1453,6 +1453,9 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw,
if (rtlpriv->cfg->ops->get_btc_status())
rtlpriv->btcoexist.btc_ops->btc_scan_notify(rtlpriv, 1);
+ else if (rtlpriv->btcoexist.btc_ops)
+ rtlpriv->btcoexist.btc_ops->btc_scan_notify_wifi_only(rtlpriv,
+ 1);
if (rtlpriv->dm.supp_phymode_switch) {
if (rtlpriv->cfg->ops->chk_switch_dmdp)
@@ -1508,6 +1511,9 @@ static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw,
rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE);
if (rtlpriv->cfg->ops->get_btc_status())
rtlpriv->btcoexist.btc_ops->btc_scan_notify(rtlpriv, 0);
+ else if (rtlpriv->btcoexist.btc_ops)
+ rtlpriv->btcoexist.btc_ops->btc_scan_notify_wifi_only(rtlpriv,
+ 0);
}
static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index aa1d3ae4937f..01ccf8884831 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -1794,6 +1794,7 @@ static int rtl_pci_start(struct ieee80211_hw *hw)
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
+ struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
int err;
@@ -1803,9 +1804,12 @@ static int rtl_pci_start(struct ieee80211_hw *hw)
if (rtlpriv->cfg->ops->get_btc_status &&
rtlpriv->cfg->ops->get_btc_status()) {
rtlpriv->btcoexist.btc_info.ap_num = 36;
- rtlpriv->btcoexist.btc_ops->btc_init_variables(rtlpriv);
- rtlpriv->btcoexist.btc_ops->btc_init_hal_vars(rtlpriv);
+ btc_ops->btc_init_variables(rtlpriv);
+ btc_ops->btc_init_hal_vars(rtlpriv);
+ } else if (btc_ops) {
+ btc_ops->btc_init_variables_wifi_only(rtlpriv);
}
+
err = rtlpriv->cfg->ops->hw_init(hw);
if (err) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index 531c86df54d4..a7aacbc3984e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -873,6 +873,24 @@ enum ratr_table_mode {
RATR_INX_WIRELESS_AC_24N = 9,
};
+enum ratr_table_mode_new {
+ RATEID_IDX_BGN_40M_2SS = 0,
+ RATEID_IDX_BGN_40M_1SS = 1,
+ RATEID_IDX_BGN_20M_2SS_BN = 2,
+ RATEID_IDX_BGN_20M_1SS_BN = 3,
+ RATEID_IDX_GN_N2SS = 4,
+ RATEID_IDX_GN_N1SS = 5,
+ RATEID_IDX_BG = 6,
+ RATEID_IDX_G = 7,
+ RATEID_IDX_B = 8,
+ RATEID_IDX_VHT_2SS = 9,
+ RATEID_IDX_VHT_1SS = 10,
+ RATEID_IDX_MIX1 = 11,
+ RATEID_IDX_MIX2 = 12,
+ RATEID_IDX_VHT_3SS = 13,
+ RATEID_IDX_BGN_3SS = 14,
+};
+
enum rtl_link_state {
MAC80211_NOLINK = 0,
MAC80211_LINKING = 1,
@@ -931,6 +949,10 @@ enum package_type {
PACKAGE_TFBGA79
};
+enum rtl_spec_ver {
+ RTL_SPEC_NEW_RATEID = BIT(0), /* use ratr_table_mode_new */
+};
+
struct octet_string {
u8 *octet;
u16 length;
@@ -2315,6 +2337,7 @@ struct rtl_hal_cfg {
struct rtl_hal_ops *ops;
struct rtl_mod_params *mod_params;
struct rtl_hal_usbint_cfg *usb_interface_cfg;
+ enum rtl_spec_ver spec_ver;
/*this map used for some registers or vars
defined int HAL but used in MAIN */
@@ -2502,6 +2525,7 @@ struct bt_coexist_info {
struct rtl_btc_info btc_info;
/* btc context */
void *btc_context;
+ void *wifi_only_context;
/* EEPROM BT info. */
u8 eeprom_bt_coexist;
u8 eeprom_bt_type;
@@ -2558,13 +2582,17 @@ struct bt_coexist_info {
struct rtl_btc_ops {
void (*btc_init_variables) (struct rtl_priv *rtlpriv);
+ void (*btc_init_variables_wifi_only)(struct rtl_priv *rtlpriv);
void (*btc_deinit_variables)(struct rtl_priv *rtlpriv);
void (*btc_init_hal_vars) (struct rtl_priv *rtlpriv);
void (*btc_power_on_setting)(struct rtl_priv *rtlpriv);
void (*btc_init_hw_config) (struct rtl_priv *rtlpriv);
+ void (*btc_init_hw_config_wifi_only)(struct rtl_priv *rtlpriv);
void (*btc_ips_notify) (struct rtl_priv *rtlpriv, u8 type);
void (*btc_lps_notify)(struct rtl_priv *rtlpriv, u8 type);
void (*btc_scan_notify) (struct rtl_priv *rtlpriv, u8 scantype);
+ void (*btc_scan_notify_wifi_only)(struct rtl_priv *rtlpriv,
+ u8 scantype);
void (*btc_connect_notify) (struct rtl_priv *rtlpriv, u8 action);
void (*btc_mediastatus_notify) (struct rtl_priv *rtlpriv,
enum rt_media_status mstatus);
@@ -2579,6 +2607,10 @@ struct rtl_btc_ops {
bool (*btc_is_bt_disabled) (struct rtl_priv *rtlpriv);
void (*btc_special_packet_notify)(struct rtl_priv *rtlpriv,
u8 pkt_type);
+ void (*btc_switch_band_notify)(struct rtl_priv *rtlpriv, u8 type,
+ bool scanning);
+ void (*btc_switch_band_notify_wifi_only)(struct rtl_priv *rtlpriv,
+ u8 type, bool scanning);
void (*btc_display_bt_coex_info)(struct rtl_priv *rtlpriv,
struct seq_file *m);
void (*btc_record_pwr_mode)(struct rtl_priv *rtlpriv, u8 *buf, u8 len);