Commit 8b7d8287 authored by David S. Miller's avatar David S. Miller

Merge tag 'wireless-drivers-next-for-davem-2018-01-19' of...

Merge tag 'wireless-drivers-next-for-davem-2018-01-19' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
wireless-drivers-next patches for 4.16

Final few patches before the merge window, nothing really special.

ath9k

* add MSI support (not enabled by default yet)

rtlwifi

* support A-MSDU in A-MPDU aggregation
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ef58ca38 5f906693
......@@ -14771,9 +14771,9 @@ S: Maintained
F: drivers/hid/hid-wiimote*
WILOCITY WIL6210 WIRELESS DRIVER
M: Maya Erez <qca_merez@qca.qualcomm.com>
M: Maya Erez <merez@codeaurora.org>
L: linux-wireless@vger.kernel.org
L: wil6210@qca.qualcomm.com
L: wil6210@qti.qualcomm.com
S: Supported
W: http://wireless.kernel.org/en/users/Drivers/wil6210
F: drivers/net/wireless/ath/wil6210/
......
......@@ -321,6 +321,7 @@ struct ath10k_ce_ops {
dma_addr_t buffer, u32 nbytes,
u32 transfer_id, u32 flags);
};
static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
{
return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id;
......
......@@ -1276,7 +1276,10 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
len -= sizeof(*hdr);
data = hdr->data;
if (len < ALIGN(ie_len, 4)) {
/* jump over the padding */
ie_len = ALIGN(ie_len, 4);
if (len < ie_len) {
ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n",
ie_id, ie_len, len);
ret = -EINVAL;
......@@ -1315,9 +1318,6 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
goto out;
}
/* jump over the padding */
ie_len = ALIGN(ie_len, 4);
len -= ie_len;
data += ie_len;
}
......@@ -1448,6 +1448,9 @@ int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
len -= sizeof(*hdr);
data += sizeof(*hdr);
/* jump over the padding */
ie_len = ALIGN(ie_len, 4);
if (len < ie_len) {
ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n",
ie_id, len, ie_len);
......@@ -1553,9 +1556,6 @@ int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
break;
}
/* jump over the padding */
ie_len = ALIGN(ie_len, 4);
len -= ie_len;
data += ie_len;
}
......
......@@ -1856,6 +1856,7 @@ struct ath10k_htt_rx_ops {
void* (*htt_get_vaddr_ring)(struct ath10k_htt *htt);
void (*htt_reset_paddrs_ring)(struct ath10k_htt *htt, int idx);
};
#define RX_HTT_HDR_STATUS_LEN 64
/* This structure layout is programmed via rx ring setup
......
......@@ -1478,13 +1478,10 @@ static int ath10k_pci_dump_memory_section(struct ath10k *ar,
if (!mem_region || !buf)
return 0;
if (mem_region->section_table.size < 0)
return 0;
cur_section = &mem_region->section_table.sections[0];
if (mem_region->start > cur_section->start) {
ath10k_warn(ar, "incorrect memdump region 0x%x with section start addrress 0x%x.\n",
ath10k_warn(ar, "incorrect memdump region 0x%x with section start address 0x%x.\n",
mem_region->start, cur_section->start);
return 0;
}
......
......@@ -922,6 +922,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
AR_IMR_RXERR |
AR_IMR_RXORN |
AR_IMR_BCNMISC;
u32 msi_cfg = 0;
if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
AR_SREV_9561(ah))
......@@ -929,22 +930,30 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
if (AR_SREV_9300_20_OR_LATER(ah)) {
imr_reg |= AR_IMR_RXOK_HP;
if (ah->config.rx_intr_mitigation)
if (ah->config.rx_intr_mitigation) {
imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
else
msi_cfg |= AR_INTCFG_MSI_RXINTM | AR_INTCFG_MSI_RXMINTR;
} else {
imr_reg |= AR_IMR_RXOK_LP;
msi_cfg |= AR_INTCFG_MSI_RXOK;
}
} else {
if (ah->config.rx_intr_mitigation)
if (ah->config.rx_intr_mitigation) {
imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
else
msi_cfg |= AR_INTCFG_MSI_RXINTM | AR_INTCFG_MSI_RXMINTR;
} else {
imr_reg |= AR_IMR_RXOK;
msi_cfg |= AR_INTCFG_MSI_RXOK;
}
}
if (ah->config.tx_intr_mitigation)
if (ah->config.tx_intr_mitigation) {
imr_reg |= AR_IMR_TXINTM | AR_IMR_TXMINTR;
else
msi_cfg |= AR_INTCFG_MSI_TXINTM | AR_INTCFG_MSI_TXMINTR;
} else {
imr_reg |= AR_IMR_TXOK;
msi_cfg |= AR_INTCFG_MSI_TXOK;
}
ENABLE_REGWRITE_BUFFER(ah);
......@@ -952,6 +961,16 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
ah->imrs2_reg |= AR_IMR_S2_GTT;
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
if (ah->msi_enabled) {
ah->msi_reg = REG_READ(ah, AR_PCIE_MSI);
ah->msi_reg |= AR_PCIE_MSI_HW_DBI_WR_EN;
ah->msi_reg &= AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;
REG_WRITE(ah, AR_INTCFG, msi_cfg);
ath_dbg(ath9k_hw_common(ah), ANY,
"value of AR_INTCFG=0x%X, msi_cfg=0x%X\n",
REG_READ(ah, AR_INTCFG), msi_cfg);
}
if (!AR_SREV_9100(ah)) {
REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default);
......
......@@ -977,6 +977,9 @@ struct ath_hw {
bool tpc_enabled;
u8 tx_power[Ar5416RateSize];
u8 tx_power_stbc[Ar5416RateSize];
bool msi_enabled;
u32 msi_mask;
u32 msi_reg;
};
struct ath_bus_ops {
......
......@@ -23,6 +23,7 @@
#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/relay.h>
#include <linux/dmi.h>
#include <net/ieee80211_radiotap.h>
#include "ath9k.h"
......@@ -75,6 +76,10 @@ MODULE_PARM_DESC(use_chanctx, "Enable channel context for concurrency");
#endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */
int ath9k_use_msi;
module_param_named(use_msi, ath9k_use_msi, int, 0444);
MODULE_PARM_DESC(use_msi, "Use MSI instead of INTx if possible");
bool is_ath9k_unloaded;
#ifdef CONFIG_MAC80211_LEDS
......@@ -92,6 +97,56 @@ static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = {
};
#endif
static int __init set_use_msi(const struct dmi_system_id *dmi)
{
ath9k_use_msi = 1;
return 1;
}
static const struct dmi_system_id ath9k_quirks[] __initconst = {
{
.callback = set_use_msi,
.ident = "Dell Inspiron 24-3460",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 24-3460"),
},
},
{
.callback = set_use_msi,
.ident = "Dell Vostro 3262",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3262"),
},
},
{
.callback = set_use_msi,
.ident = "Dell Inspiron 3472",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3472"),
},
},
{
.callback = set_use_msi,
.ident = "Dell Vostro 15-3572",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 15-3572"),
},
},
{
.callback = set_use_msi,
.ident = "Dell Inspiron 14-3473",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 14-3473"),
},
},
{}
};
static void ath9k_deinit_softc(struct ath_softc *sc);
static void ath9k_op_ps_wakeup(struct ath_common *common)
......@@ -1100,6 +1155,8 @@ static int __init ath9k_init(void)
goto err_pci_exit;
}
dmi_check_system(ath9k_quirks);
return 0;
err_pci_exit:
......
......@@ -832,6 +832,43 @@ static void __ath9k_hw_enable_interrupts(struct ath_hw *ah)
}
ath_dbg(common, INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
if (ah->msi_enabled) {
u32 _msi_reg = 0;
u32 i = 0;
u32 msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;
ath_dbg(ath9k_hw_common(ah), INTERRUPT,
"Enabling MSI, msi_mask=0x%X\n", ah->msi_mask);
REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, ah->msi_mask);
REG_WRITE(ah, AR_INTR_PRIO_ASYNC_MASK, ah->msi_mask);
ath_dbg(ath9k_hw_common(ah), INTERRUPT,
"AR_INTR_PRIO_ASYNC_ENABLE=0x%X, AR_INTR_PRIO_ASYNC_MASK=0x%X\n",
REG_READ(ah, AR_INTR_PRIO_ASYNC_ENABLE),
REG_READ(ah, AR_INTR_PRIO_ASYNC_MASK));
if (ah->msi_reg == 0)
ah->msi_reg = REG_READ(ah, AR_PCIE_MSI);
ath_dbg(ath9k_hw_common(ah), INTERRUPT,
"AR_PCIE_MSI=0x%X, ah->msi_reg = 0x%X\n",
AR_PCIE_MSI, ah->msi_reg);
i = 0;
do {
REG_WRITE(ah, AR_PCIE_MSI,
(ah->msi_reg | AR_PCIE_MSI_ENABLE)
& msi_pend_addr_mask);
_msi_reg = REG_READ(ah, AR_PCIE_MSI);
i++;
} while ((_msi_reg & AR_PCIE_MSI_ENABLE) == 0 && i < 200);
if (i >= 200)
ath_err(ath9k_hw_common(ah),
"%s: _msi_reg = 0x%X\n",
__func__, _msi_reg);
}
}
void ath9k_hw_resume_interrupts(struct ath_hw *ah)
......@@ -878,12 +915,21 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah)
if (!(ints & ATH9K_INT_GLOBAL))
ath9k_hw_disable_interrupts(ah);
if (ah->msi_enabled) {
ath_dbg(common, INTERRUPT, "Clearing AR_INTR_PRIO_ASYNC_ENABLE\n");
REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0);
REG_READ(ah, AR_INTR_PRIO_ASYNC_ENABLE);
}
ath_dbg(common, INTERRUPT, "New interrupt mask 0x%x\n", ints);
mask = ints & ATH9K_INT_COMMON;
mask2 = 0;
ah->msi_mask = 0;
if (ints & ATH9K_INT_TX) {
ah->msi_mask |= AR_INTR_PRIO_TX;
if (ah->config.tx_intr_mitigation)
mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
else {
......@@ -898,6 +944,7 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah)
mask |= AR_IMR_TXEOL;
}
if (ints & ATH9K_INT_RX) {
ah->msi_mask |= AR_INTR_PRIO_RXLP | AR_INTR_PRIO_RXHP;
if (AR_SREV_9300_20_OR_LATER(ah)) {
mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;
if (ah->config.rx_intr_mitigation) {
......
......@@ -22,6 +22,8 @@
#include <linux/module.h>
#include "ath9k.h"
extern int ath9k_use_msi;
static const struct pci_device_id ath_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
......@@ -889,6 +891,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
u32 val;
int ret = 0;
char hw_name[64];
int msi_enabled = 0;
if (pcim_enable_device(pdev))
return -EIO;
......@@ -960,7 +963,20 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sc->mem = pcim_iomap_table(pdev)[0];
sc->driver_data = id->driver_data;
ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc);
if (ath9k_use_msi) {
if (pci_enable_msi(pdev) == 0) {
msi_enabled = 1;
dev_err(&pdev->dev, "Using MSI\n");
} else {
dev_err(&pdev->dev, "Using INTx\n");
}
}
if (!msi_enabled)
ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc);
else
ret = request_irq(pdev->irq, ath_isr, 0, "ath9k", sc);
if (ret) {
dev_err(&pdev->dev, "request_irq failed\n");
goto err_irq;
......@@ -974,6 +990,9 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_init;
}
sc->sc_ah->msi_enabled = msi_enabled;
sc->sc_ah->msi_reg = 0;
ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
hw_name, (unsigned long)sc->mem, pdev->irq);
......
......@@ -146,6 +146,14 @@
#define AR_MACMISC_MISC_OBS_BUS_MSB_S 15
#define AR_MACMISC_MISC_OBS_BUS_1 1
#define AR_INTCFG 0x005C
#define AR_INTCFG_MSI_RXOK 0x00000000
#define AR_INTCFG_MSI_RXINTM 0x00000004
#define AR_INTCFG_MSI_RXMINTR 0x00000006
#define AR_INTCFG_MSI_TXOK 0x00000000
#define AR_INTCFG_MSI_TXINTM 0x00000010
#define AR_INTCFG_MSI_TXMINTR 0x00000018
#define AR_DATABUF_SIZE 0x0060
#define AR_DATABUF_SIZE_MASK 0x00000FFF
......@@ -1256,6 +1264,13 @@ enum {
#define AR_PCIE_MSI (AR_SREV_9340(ah) ? 0x40d8 : \
(AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094))
#define AR_PCIE_MSI_ENABLE 0x00000001
#define AR_PCIE_MSI_HW_DBI_WR_EN 0x02000000
#define AR_PCIE_MSI_HW_INT_PENDING_ADDR 0xFFA0C1FF /* bits 8..11: value must be 0x5060 */
#define AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64 0xFFA0C9FF /* bits 8..11: value must be 0x5064 */
#define AR_INTR_PRIO_TX 0x00000001
#define AR_INTR_PRIO_RXLP 0x00000002
#define AR_INTR_PRIO_RXHP 0x00000004
#define AR_INTR_PRIO_SYNC_ENABLE (AR_SREV_9340(ah) ? 0x4088 : 0x40c4)
#define AR_INTR_PRIO_ASYNC_MASK (AR_SREV_9340(ah) ? 0x408c : 0x40c8)
......
......@@ -310,8 +310,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
}
cancel_work_sync(&card->work);
mwifiex_remove_card(adapter);
}
......@@ -2788,7 +2786,10 @@ static void mwifiex_pcie_card_reset_work(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
pci_reset_function(card->dev);
/* We can't afford to wait here; remove() might be waiting on us. If we
* can't grab the device lock, maybe we'll get another chance later.
*/
pci_try_reset_function(card->dev);
}
static void mwifiex_pcie_work(struct work_struct *work)
......
......@@ -399,8 +399,6 @@ mwifiex_sdio_remove(struct sdio_func *func)
mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
}
cancel_work_sync(&card->work);
mwifiex_remove_card(adapter);
}
......
......@@ -186,7 +186,7 @@ void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x2_txwi *txwi,
txwi->pktid = 1;
spin_lock_bh(&dev->mt76.lock);
if (rate->idx < 0 || !rate->count) {
if (wcid && (rate->idx < 0 || !rate->count)) {
txwi->rate = wcid->tx_rate;
max_txpwr_adj = wcid->max_txpwr_adj;
nss = wcid->tx_rate_nss;
......
......@@ -465,13 +465,15 @@ mt76x2_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct mt76x2_dev *dev = hw->priv;
struct mt76x2_sta *msta = (struct mt76x2_sta *) sta->drv_priv;
struct ieee80211_txq *txq = sta->txq[params->tid];
struct mt76_txq *mtxq = (struct mt76_txq *) txq->drv_priv;
u16 tid = params->tid;
u16 *ssn = &params->ssn;
struct mt76_txq *mtxq;
if (!txq)
return -EINVAL;
mtxq = (struct mt76_txq *)txq->drv_priv;
switch (action) {
case IEEE80211_AMPDU_RX_START:
mt76_set(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, BIT(16 + tid));
......
......@@ -395,6 +395,7 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, CONNECTION_MONITOR);
ieee80211_hw_set(hw, MFP_CAPABLE);
ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
/* swlps or hwlps has been set in diff chip in init_sw_vars */
if (rtlpriv->psc.swctrl_lps) {
......@@ -551,7 +552,8 @@ int rtl_init_core(struct ieee80211_hw *hw)
/* <4> locks */
mutex_init(&rtlpriv->locks.conf_mutex);
spin_lock_init(&rtlpriv->locks.ips_lock);
mutex_init(&rtlpriv->locks.ips_mutex);
mutex_init(&rtlpriv->locks.lps_mutex);
spin_lock_init(&rtlpriv->locks.irq_th_lock);
spin_lock_init(&rtlpriv->locks.h2c_lock);
spin_lock_init(&rtlpriv->locks.rf_ps_lock);
......@@ -561,9 +563,7 @@ int rtl_init_core(struct ieee80211_hw *hw)
spin_lock_init(&rtlpriv->locks.c2hcmd_lock);
spin_lock_init(&rtlpriv->locks.scan_list_lock);
spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock);
spin_lock_init(&rtlpriv->locks.check_sendpkt_lock);
spin_lock_init(&rtlpriv->locks.fw_ps_lock);
spin_lock_init(&rtlpriv->locks.lps_lock);
spin_lock_init(&rtlpriv->locks.iqk_lock);
/* <5> init list */
INIT_LIST_HEAD(&rtlpriv->entry_list);
......@@ -1229,7 +1229,6 @@ bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb)
}
if (ieee80211_is_auth(fc)) {
RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
rtl_ips_nic_on(hw);
mac->link_state = MAC80211_LINKING;
/* Dul mac */
......
......@@ -103,8 +103,6 @@ enum btc_msg_type {
BTC_MSG_MAX
};
extern u32 btc_dbg_type[];
/* following is for BTC_MSG_INTERFACE */
#define INTF_INIT BIT0
#define INTF_NOTIFY BIT2
......@@ -153,6 +151,8 @@ struct btc_board_info {
u8 btdm_ant_pos;
u8 single_ant_path; /* current used for 8723b only, 1=>s0, 0=>s1 */
bool tfbga_package;
u8 rfe_type;
};
enum btc_dbg_opcode {
......@@ -280,6 +280,8 @@ enum btc_get_type {
BTC_GET_U4_VENDOR,
BTC_GET_U4_SUPPORTED_VERSION,
BTC_GET_U4_SUPPORTED_FEATURE,
BTC_GET_U4_BT_DEVICE_INFO,
BTC_GET_U4_BT_FORBIDDEN_SLOT_VAL,
BTC_GET_U4_WIFI_IQK_TOTAL,
BTC_GET_U4_WIFI_IQK_OK,
BTC_GET_U4_WIFI_IQK_FAIL,
......@@ -423,50 +425,6 @@ enum btc_notify_type_stack_operation {
BTC_STACK_OP_MAX
};
typedef u8 (*bfp_btc_r1)(void *btc_context, u32 reg_addr);
typedef u16 (*bfp_btc_r2)(void *btc_context, u32 reg_addr);
typedef u32 (*bfp_btc_r4)(void *btc_context, u32 reg_addr);
typedef void (*bfp_btc_w1)(void *btc_context, u32 reg_addr, u32 data);
typedef void (*bfp_btc_w1_bit_mak)(void *btc_context, u32 reg_addr,
u32 bit_mask, u8 data1b);
typedef void (*bfp_btc_w2)(void *btc_context, u32 reg_addr, u16 data);
typedef void (*bfp_btc_w4)(void *btc_context, u32 reg_addr, u32 data);
typedef void (*bfp_btc_local_reg_w1)(void *btc_context, u32 reg_addr, u8 data);
typedef void (*bfp_btc_wr_1byte_bit_mask)(void *btc_context, u32 reg_addr,
u8 bit_mask, u8 data);
typedef void (*bfp_btc_set_bb_reg)(void *btc_context, u32 reg_addr,
u32 bit_mask, u32 data);
typedef u32 (*bfp_btc_get_bb_reg)(void *btc_context, u32 reg_addr,
u32 bit_mask);
typedef void (*bfp_btc_set_rf_reg)(void *btc_context, u8 rf_path, u32 reg_addr,
u32 bit_mask, u32 data);
typedef u32 (*bfp_btc_get_rf_reg)(void *btc_context, u8 rf_path,
u32 reg_addr, u32 bit_mask);
typedef void (*bfp_btc_fill_h2c)(void *btc_context, u8 element_id,
u32 cmd_len, u8 *cmd_buffer);
typedef bool (*bfp_btc_get)(void *btcoexist, u8 get_type, void *out_buf);
typedef bool (*bfp_btc_set)(void *btcoexist, u8 set_type, void *in_buf);
typedef void (*bfp_btc_set_bt_reg)(void *btc_context, u8 reg_type, u32 offset,
u32 value);
typedef void (*bfp_btc_disp_dbg_msg)(void *btcoexist, u8 disp_type,
struct seq_file *m);
struct btc_bt_info {
bool bt_disabled;
u8 rssi_adjust_for_agc_table_on;
......@@ -498,6 +456,17 @@ struct btc_bt_info {
u8 lps_val;
u8 rpwm_val;
u32 ra_mask;
u32 afh_map_l;
u32 afh_map_m;
u16 afh_map_h;
u32 bt_supported_feature;
u32 bt_supported_version;
u32 bt_device_info;
u32 bt_forb_slot_val;
u8 bt_ant_det_val;
u8 bt_ble_scan_type;
u32 bt_ble_scan_para;
};
struct btc_stack_info {
......@@ -553,6 +522,40 @@ enum btc_antenna_pos {
BTC_ANTENNA_AT_AUX_PORT = 0x2,
};
enum btc_mp_h2c_op_code {
BT_OP_GET_BT_VERSION = 0,
BT_OP_WRITE_REG_ADDR = 12,
BT_OP_WRITE_REG_VALUE = 13,
BT_OP_READ_REG = 17,
BT_OP_GET_AFH_MAP_L = 30,
BT_OP_GET_AFH_MAP_M = 31,
BT_OP_GET_AFH_MAP_H = 32,
BT_OP_GET_BT_COEX_SUPPORTED_FEATURE = 42,
BT_OP_GET_BT_COEX_SUPPORTED_VERSION = 43,
BT_OP_GET_BT_ANT_DET_VAL = 44,
BT_OP_GET_BT_BLE_SCAN_PARA = 45,
BT_OP_GET_BT_BLE_SCAN_TYPE = 46,
BT_OP_GET_BT_DEVICE_INFO = 48,
BT_OP_GET_BT_FORBIDDEN_SLOT_VAL = 49,
BT_OP_MAX
};
enum btc_mp_h2c_req_num {
/* 4 bits only */
BT_SEQ_DONT_CARE = 0,
BT_SEQ_GET_BT_VERSION = 0xE,
BT_SEQ_GET_AFH_MAP_L = 0x5,
BT_SEQ_GET_AFH_MAP_M = 0x6,
BT_SEQ_GET_AFH_MAP_H = 0x9,
BT_SEQ_GET_BT_COEX_SUPPORTED_FEATURE = 0x7,
BT_SEQ_GET_BT_COEX_SUPPORTED_VERSION = 0x8,
BT_SEQ_GET_BT_ANT_DET_VAL = 0x2,
BT_SEQ_GET_BT_BLE_SCAN_PARA = 0x3,
BT_SEQ_GET_BT_BLE_SCAN_TYPE = 0x4,
BT_SEQ_GET_BT_DEVICE_INFO = 0xA,
BT_SEQ_GET_BT_FORB_SLOT_VAL = 0xB,
};
struct btc_coexist {
/* make sure only one adapter can bind the data context */
bool binded;
......@@ -576,38 +579,57 @@ struct btc_coexist {
struct btc_statistics statistics;
u8 pwr_mode_val[10];
/* function pointers - io related */
bfp_btc_r1 btc_read_1byte;
bfp_btc_w1 btc_write_1byte;
bfp_btc_w1_bit_mak btc_write_1byte_bitmask;
bfp_btc_r2 btc_read_2byte;
bfp_btc_w2 btc_write_2byte;
bfp_btc_r4 btc_read_4byte;
bfp_btc_w4 btc_write_4byte;
bfp_btc_local_reg_w1 btc_write_local_reg_1byte;
bfp_btc_set_bb_reg btc_set_bb_reg;
bfp_btc_get_bb_reg btc_get_bb_reg;
bfp_btc_set_rf_reg btc_set_rf_reg;
bfp_btc_get_rf_reg btc_get_rf_reg;
bfp_btc_fill_h2c btc_fill_h2c;
struct completion bt_mp_comp;
bfp_btc_disp_dbg_msg btc_disp_dbg_msg;
bfp_btc_get btc_get;
bfp_btc_set btc_set;
bfp_btc_set_bt_reg btc_set_bt_reg;
/* function pointers - io related */
u8 (*btc_read_1byte)(void *btc_context, u32 reg_addr);
void (*btc_write_1byte)(void *btc_context, u32 reg_addr, u32 data);
void (*btc_write_1byte_bitmask)(void *btc_context, u32 reg_addr,
u32 bit_mask, u8 data1b);
u16 (*btc_read_2byte)(void *btc_context, u32 reg_addr);
void (*btc_write_2byte)(void *btc_context, u32 reg_addr, u16 data);
u32 (*btc_read_4byte)(void *btc_context, u32 reg_addr);
void (*btc_write_4byte)(void *btc_context, u32 reg_addr, u32 data);
void (*btc_write_local_reg_1byte)(void *btc_context, u32 reg_addr,
u8 data);
void (*btc_set_bb_reg)(void *btc_context, u32 reg_addr,
u32 bit_mask, u32 data);
u32 (*btc_get_bb_reg)(void *btc_context, u32 reg_addr,
u32 bit_mask);
void (*btc_set_rf_reg)(void *btc_context, u8 rf_path, u32 reg_addr,
u32 bit_mask, u32 data);
u32 (*btc_get_rf_reg)(void *btc_context, u8 rf_path,
u32 reg_addr, u32 bit_mask);
void (*btc_fill_h2c)(void *btc_context, u8 element_id,
u32 cmd_len, u8 *cmd_buffer);
void (*btc_disp_dbg_msg)(void *btcoexist, u8 disp_type,
struct seq_file *m);
bool (*btc_get)(void *btcoexist, u8 get_type, void *out_buf);
bool (*btc_set)(void *btcoexist, u8 set_type, void *in_buf);
void (*btc_set_bt_reg)(void *btc_context, u8 reg_type, u32 offset,
u32 value);
u32 (*btc_get_bt_coex_supported_feature)(void *btcoexist);
u32 (*btc_get_bt_coex_supported_version)(void *btcoexist);
u8 (*btc_get_ant_det_val_from_bt)(void *btcoexist);
u8 (*btc_get_ble_scan_type_from_bt)(void *btcoexist);
u32 (*btc_get_ble_scan_para_from_bt)(void *btcoexist, u8 scan_type);
bool (*btc_get_bt_afh_map_from_bt)(void *btcoexist, u8 map_type,
u8 *afh_map);
};
bool halbtc_is_wifi_uplink(struct rtl_priv *adapter);
extern struct btc_coexist gl_bt_coexist;
#define rtl_btc_coexist(rtlpriv) \
((struct btc_coexist *)((rtlpriv)->btcoexist.btc_context))
bool exhalbtc_initlize_variables(void);
bool exhalbtc_initlize_variables(struct rtl_priv *rtlpriv);
bool exhalbtc_bind_bt_coex_withadapter(void *adapter);
void exhalbtc_power_on_setting(struct btc_coexist *btcoexist);
void exhalbtc_init_hw_config(struct btc_coexist *btcoexist, bool wifi_only);
void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist);
void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type);
......@@ -627,11 +649,12 @@ void exhalbtc_periodical(struct btc_coexist *btcoexist);
void exhalbtc_dbg_control(struct btc_coexist *btcoexist, u8 code, u8 len,
u8 *data);
void exhalbtc_stack_update_profile_info(void);
void exhalbtc_set_hci_version(u16 hci_version);
void exhalbtc_set_bt_patch_version(u16 bt_hci_version, u16 bt_patch_version);
void exhalbtc_update_min_bt_rssi(s8 bt_rssi);
void exhalbtc_set_bt_exist(bool bt_exist);
void exhalbtc_set_chip_type(u8 chip_type);
void exhalbtc_set_hci_version(struct btc_coexist *btcoexist, u16 hci_version);
void exhalbtc_set_bt_patch_version(struct btc_coexist *btcoexist,
u16 bt_hci_version, u16 bt_patch_version);
void exhalbtc_update_min_bt_rssi(struct btc_coexist *btcoexist, s8 bt_rssi);
void exhalbtc_set_bt_exist(struct btc_coexist *btcoexist, bool bt_exist);
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);
......@@ -639,6 +662,7 @@ void exhalbtc_signal_compensation(struct btc_coexist *btcoexist,
u8 *rssi_wifi, u8 *rssi_bt);
void exhalbtc_lps_leave(struct btc_coexist *btcoexist);
void exhalbtc_low_wifi_traffic_notify(struct btc_coexist *btcoexist);
void exhalbtc_set_single_ant_path(u8 single_ant_path);
void exhalbtc_set_single_ant_path(struct btc_coexist *btcoexist,
u8 single_ant_path);
#endif
......@@ -31,7 +31,9 @@
static struct rtl_btc_ops rtl_btc_operation = {
.btc_init_variables = rtl_btc_init_variables,
.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_ips_notify = rtl_btc_ips_notify,
.btc_lps_notify = rtl_btc_lps_notify,
......@@ -57,58 +59,116 @@ static struct rtl_btc_ops rtl_btc_operation = {
void rtl_btc_display_bt_coex_info(struct rtl_priv *rtlpriv, struct seq_file *m)
{
exhalbtc_display_bt_coex_info(&gl_bt_coexist, m);
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist) {
seq_puts(m, "btc_coexist context is NULL!\n");
return;
}
exhalbtc_display_bt_coex_info(btcoexist, m);
}
void rtl_btc_record_pwr_mode(struct rtl_priv *rtlpriv, u8 *buf, u8 len)
{
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
u8 safe_len;
safe_len = sizeof(gl_bt_coexist.pwr_mode_val);
if (!btcoexist)
return;
safe_len = sizeof(btcoexist->pwr_mode_val);
if (safe_len > len)
safe_len = len;
memcpy(gl_bt_coexist.pwr_mode_val, buf, safe_len);
memcpy(btcoexist->pwr_mode_val, buf, safe_len);
}
u8 rtl_btc_get_lps_val(struct rtl_priv *rtlpriv)
{
return gl_bt_coexist.bt_info.lps_val;
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return 0;
return btcoexist->bt_info.lps_val;
}
u8 rtl_btc_get_rpwm_val(struct rtl_priv *rtlpriv)
{
return gl_bt_coexist.bt_info.rpwm_val;
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return 0;
return btcoexist->bt_info.rpwm_val;
}
bool rtl_btc_is_bt_ctrl_lps(struct rtl_priv *rtlpriv)
{
return gl_bt_coexist.bt_info.bt_ctrl_lps;
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return false;
return btcoexist->bt_info.bt_ctrl_lps;
}
bool rtl_btc_is_bt_lps_on(struct rtl_priv *rtlpriv)
{
return gl_bt_coexist.bt_info.bt_lps_on;
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return false;
return btcoexist->bt_info.bt_lps_on;
}
void rtl_btc_get_ampdu_cfg(struct rtl_priv *rtlpriv, u8 *reject_agg,
u8 *ctrl_agg_size, u8 *agg_size)
{
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist) {
*reject_agg = false;
*ctrl_agg_size = false;
return;
}
if (reject_agg)
*reject_agg = gl_bt_coexist.bt_info.reject_agg_pkt;
*reject_agg = btcoexist->bt_info.reject_agg_pkt;
if (ctrl_agg_size)
*ctrl_agg_size = gl_bt_coexist.bt_info.bt_ctrl_agg_buf_size;
*ctrl_agg_size = btcoexist->bt_info.bt_ctrl_agg_buf_size;
if (agg_size)
*agg_size = gl_bt_coexist.bt_info.agg_buf_size;
*agg_size = btcoexist->bt_info.agg_buf_size;
}
static void rtl_btc_alloc_variable(struct rtl_priv *rtlpriv, bool wifi_only)
{
rtlpriv->btcoexist.btc_context =
kzalloc(sizeof(struct btc_coexist), GFP_KERNEL);
}
static void rtl_btc_free_variable(struct rtl_priv *rtlpriv)
{
kfree(rtlpriv->btcoexist.btc_context);
rtlpriv->btcoexist.btc_context = NULL;
}
void rtl_btc_init_variables(struct rtl_priv *rtlpriv)
{
exhalbtc_initlize_variables();
rtl_btc_alloc_variable(rtlpriv, false);
exhalbtc_initlize_variables(rtlpriv);
exhalbtc_bind_bt_coex_withadapter(rtlpriv);
}
void rtl_btc_deinit_variables(struct rtl_priv *rtlpriv)
{
rtl_btc_free_variable(rtlpriv);
}
void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)
{
/* move ant_num, bt_type and single_ant_path to
......@@ -116,67 +176,125 @@ void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)
*/
}
void rtl_btc_power_on_setting(struct rtl_priv *rtlpriv)
{
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return;
exhalbtc_power_on_setting(btcoexist);
}
void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv)
{
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
u8 bt_exist;
bt_exist = rtl_get_hwpg_bt_exist(rtlpriv);
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
"%s, bt_exist is %d\n", __func__, bt_exist);
exhalbtc_init_hw_config(&gl_bt_coexist, !bt_exist);
exhalbtc_init_coex_dm(&gl_bt_coexist);
if (!btcoexist)
return;
exhalbtc_init_hw_config(btcoexist, !bt_exist);
exhalbtc_init_coex_dm(btcoexist);
}
void rtl_btc_ips_notify(struct rtl_priv *rtlpriv, u8 type)
{
exhalbtc_ips_notify(&gl_bt_coexist, type);
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return;
exhalbtc_ips_notify(btcoexist, type);
}
void rtl_btc_lps_notify(struct rtl_priv *rtlpriv, u8 type)
{
exhalbtc_lps_notify(&gl_bt_coexist, type);
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return;
exhalbtc_lps_notify(btcoexist, type);
}
void rtl_btc_scan_notify(struct rtl_priv *rtlpriv, u8 scantype)
{
exhalbtc_scan_notify(&gl_bt_coexist, scantype);
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return;
exhalbtc_scan_notify(btcoexist, scantype);
}
void rtl_btc_connect_notify(struct rtl_priv *rtlpriv, u8 action)
{
exhalbtc_connect_notify(&gl_bt_coexist, action);
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return;
exhalbtc_connect_notify(btcoexist, action);
}
void rtl_btc_mediastatus_notify(struct rtl_priv *rtlpriv,
enum rt_media_status mstatus)
{
exhalbtc_mediastatus_notify(&gl_bt_coexist, mstatus);
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return;
exhalbtc_mediastatus_notify(btcoexist, mstatus);
}
void rtl_btc_periodical(struct rtl_priv *rtlpriv)
{
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return;
/*rtl_bt_dm_monitor();*/
exhalbtc_periodical(&gl_bt_coexist);
exhalbtc_periodical(btcoexist);
}
void rtl_btc_halt_notify(void)
void rtl_btc_halt_notify(struct rtl_priv *rtlpriv)
{
struct btc_coexist *btcoexist = &gl_bt_coexist;
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return;
exhalbtc_halt_notify(btcoexist);
}
void rtl_btc_btinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length)
{
exhalbtc_bt_info_notify(&gl_bt_coexist, tmp_buf, length);
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return;
exhalbtc_bt_info_notify(btcoexist, tmp_buf, length);
}
void rtl_btc_btmpinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length)
{
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
u8 extid, seq, len;
u16 bt_real_fw_ver;
u8 bt_fw_ver;
u8 *data;
if (!btcoexist)
return;
if ((length < 4) || (!tmp_buf))
return;
......@@ -188,20 +306,70 @@ void rtl_btc_btmpinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length)
len = tmp_buf[1] >> 4;
seq = tmp_buf[2] >> 4;
data = &tmp_buf[3];
/* BT Firmware version response */
if (seq == 0x0E) {
switch (seq) {
case BT_SEQ_GET_BT_VERSION:
bt_real_fw_ver = tmp_buf[3] | (tmp_buf[4] << 8);
bt_fw_ver = tmp_buf[5];
gl_bt_coexist.bt_info.bt_real_fw_ver = bt_real_fw_ver;
gl_bt_coexist.bt_info.bt_fw_ver = bt_fw_ver;
btcoexist->bt_info.bt_real_fw_ver = bt_real_fw_ver;
btcoexist->bt_info.bt_fw_ver = bt_fw_ver;
break;
case BT_SEQ_GET_AFH_MAP_L:
btcoexist->bt_info.afh_map_l = le32_to_cpu(*(__le32 *)data);
break;
case BT_SEQ_GET_AFH_MAP_M:
btcoexist->bt_info.afh_map_m = le32_to_cpu(*(__le32 *)data);
break;
case BT_SEQ_GET_AFH_MAP_H:
btcoexist->bt_info.afh_map_h = le16_to_cpu(*(__le16 *)data);
break;
case BT_SEQ_GET_BT_COEX_SUPPORTED_FEATURE:
btcoexist->bt_info.bt_supported_feature = tmp_buf[3] |
(tmp_buf[4] << 8);
break;
case BT_SEQ_GET_BT_COEX_SUPPORTED_VERSION:
btcoexist->bt_info.bt_supported_version = tmp_buf[3] |
(tmp_buf[4] << 8);
break;
case BT_SEQ_GET_BT_ANT_DET_VAL:
btcoexist->bt_info.bt_ant_det_val = tmp_buf[3];
break;
case BT_SEQ_GET_BT_BLE_SCAN_PARA:
btcoexist->bt_info.bt_ble_scan_para = tmp_buf[3] |
(tmp_buf[4] << 8) |
(tmp_buf[5] << 16) |
(tmp_buf[6] << 24);
break;
case BT_SEQ_GET_BT_BLE_SCAN_TYPE:
btcoexist->bt_info.bt_ble_scan_type = tmp_buf[3];
break;
case BT_SEQ_GET_BT_DEVICE_INFO:
btcoexist->bt_info.bt_device_info =
le32_to_cpu(*(__le32 *)data);
break;
case BT_OP_GET_BT_FORBIDDEN_SLOT_VAL:
btcoexist->bt_info.bt_forb_slot_val =
le32_to_cpu(*(__le32 *)data);
break;
}
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
"btmpinfo complete req_num=%d\n", seq);
complete(&btcoexist->bt_mp_comp);
}
bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv)
{
return gl_bt_coexist.bt_info.limited_dig;
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return false;
return btcoexist->bt_info.limited_dig;
}
bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv)
......@@ -233,8 +401,13 @@ bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv)
bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv)
{
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return true;
/* It seems 'bt_disabled' is never be initialized or set. */
if (gl_bt_coexist.bt_info.bt_disabled)
if (btcoexist->bt_info.bt_disabled)
return true;
else
return false;
......@@ -242,7 +415,12 @@ bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv)
void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type)
{
return exhalbtc_special_packet_notify(&gl_bt_coexist, pkt_type);
struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
if (!btcoexist)
return;
return exhalbtc_special_packet_notify(btcoexist, pkt_type);
}
struct rtl_btc_ops *rtl_btc_get_ops_pointer(void)
......
......@@ -28,7 +28,9 @@
#include "halbt_precomp.h"
void rtl_btc_init_variables(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_ips_notify(struct rtl_priv *rtlpriv, u8 type);
void rtl_btc_lps_notify(struct rtl_priv *rtlpriv, u8 type);
......@@ -37,7 +39,7 @@ 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);
void rtl_btc_periodical(struct rtl_priv *rtlpriv);
void rtl_btc_halt_notify(void);
void rtl_btc_halt_notify(struct rtl_priv *rtlpriv);
void rtl_btc_btinfo_notify(struct rtl_priv *rtlpriv, u8 *tmpbuf, u8 length);
void rtl_btc_btmpinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length);
bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv);
......
......@@ -1162,6 +1162,8 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
"BSS_CHANGED_ASSOC\n");
} else {
struct cfg80211_bss *bss = NULL;
mstatus = RT_MEDIA_DISCONNECT;
if (mac->link_state == MAC80211_LINKED)
......@@ -1169,6 +1171,22 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE)
rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
mac->link_state = MAC80211_NOLINK;
bss = cfg80211_get_bss(hw->wiphy, NULL,
(u8 *)mac->bssid, NULL, 0,
IEEE80211_BSS_TYPE_ESS,
IEEE80211_PRIVACY_OFF);
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
"bssid = %pMF\n", mac->bssid);
if (bss) {
cfg80211_unlink_bss(hw->wiphy, bss);
cfg80211_put_bss(hw->wiphy, bss);
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
"cfg80211_unlink !!\n");
}
eth_zero_addr(mac->bssid);
mac->vendor = PEER_UNKNOWN;
mac->mode = 0;
......
......@@ -1841,7 +1841,10 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
u8 rf_timeout = 0;
if (rtlpriv->cfg->ops->get_btc_status())
rtlpriv->btcoexist.btc_ops->btc_halt_notify();
rtlpriv->btcoexist.btc_ops->btc_halt_notify(rtlpriv);
if (rtlpriv->btcoexist.btc_ops)
rtlpriv->btcoexist.btc_ops->btc_deinit_variables(rtlpriv);
/*should be before disable interrupt&adapter
*and will do it immediately.
......
......@@ -51,6 +51,11 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw)
&rtlmac->retry_long);
RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
rtlpriv->cfg->ops->switch_channel(hw);
rtlpriv->cfg->ops->set_channel_access(hw);
rtlpriv->cfg->ops->set_bw_mode(hw,
cfg80211_get_chandef_type(&hw->conf.chandef));
/*<3> Enable Interrupt */
rtlpriv->cfg->ops->enable_interrupt(hw);
......@@ -289,7 +294,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq);
spin_lock(&rtlpriv->locks.ips_lock);
mutex_lock(&rtlpriv->locks.ips_mutex);
if (ppsc->inactiveps) {
rtstate = ppsc->rfpwr_state;
......@@ -306,7 +311,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
ppsc->inactive_pwrstate);
}
}
spin_unlock(&rtlpriv->locks.ips_lock);
mutex_unlock(&rtlpriv->locks.ips_mutex);
}
EXPORT_SYMBOL_GPL(rtl_ips_nic_on);
......@@ -415,7 +420,6 @@ static void rtl_lps_enter_core(struct ieee80211_hw *hw)
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_priv *rtlpriv = rtl_priv(hw);
unsigned long flag;
if (!ppsc->fwctrl_lps)
return;
......@@ -436,7 +440,7 @@ static void rtl_lps_enter_core(struct ieee80211_hw *hw)
if (mac->link_state != MAC80211_LINKED)
return;
spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
mutex_lock(&rtlpriv->locks.lps_mutex);
/* Don't need to check (ppsc->dot11_psmode == EACTIVE), because
* bt_ccoexist may ask to enter lps.
......@@ -446,7 +450,7 @@ static void rtl_lps_enter_core(struct ieee80211_hw *hw)
"Enter 802.11 power save mode...\n");
rtl_lps_set_psmode(hw, EAUTOPS);
spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
mutex_unlock(&rtlpriv->locks.lps_mutex);
}
/* Interrupt safe routine to leave the leisure power save mode.*/
......@@ -455,9 +459,8 @@ static void rtl_lps_leave_core(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
unsigned long flag;
spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
mutex_lock(&rtlpriv->locks.lps_mutex);
if (ppsc->fwctrl_lps) {
if (ppsc->dot11_psmode != EACTIVE) {
......@@ -478,7 +481,7 @@ static void rtl_lps_leave_core(struct ieee80211_hw *hw)
rtl_lps_set_psmode(hw, EACTIVE);
}
}
spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
mutex_unlock(&rtlpriv->locks.lps_mutex);
}
/* For sw LPS*/
......@@ -568,7 +571,6 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
unsigned long flag;
if (!rtlpriv->psc.swctrl_lps)
return;
......@@ -581,9 +583,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
}
spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
mutex_lock(&rtlpriv->locks.lps_mutex);
rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
mutex_unlock(&rtlpriv->locks.lps_mutex);
}
void rtl_swlps_rfon_wq_callback(void *data)
......@@ -600,7 +602,6 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
unsigned long flag;
u8 sleep_intv;
if (!rtlpriv->psc.sw_ps_enabled)
......@@ -624,9 +625,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
}
spin_unlock(&rtlpriv->locks.rf_ps_lock);
spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
mutex_lock(&rtlpriv->locks.lps_mutex);
rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
mutex_unlock(&rtlpriv->locks.lps_mutex);
if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
!RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
......
......@@ -962,7 +962,6 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw,
memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
if (ieee80211_is_auth(fc)) {
RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
rtl_ips_nic_on(hw);
}
if (rtlpriv->psc.sw_ps_enabled) {
......
......@@ -2325,17 +2325,14 @@ struct rtl_hal_cfg {
struct rtl_locks {
/* mutex */
struct mutex conf_mutex;
struct mutex ps_mutex;
struct mutex ips_mutex; /* mutex for enter/leave IPS */
struct mutex lps_mutex; /* mutex for enter/leave LPS */
/*spin lock */
spinlock_t ips_lock;
spinlock_t irq_th_lock;
spinlock_t irq_pci_lock;
spinlock_t tx_lock;
spinlock_t h2c_lock;
spinlock_t rf_ps_lock;
spinlock_t rf_lock;
spinlock_t lps_lock;
spinlock_t waitq_lock;
spinlock_t entry_list_lock;
spinlock_t usb_lock;
......@@ -2348,9 +2345,6 @@ struct rtl_locks {
/*Dual mac*/
spinlock_t cck_and_rw_pagea_lock;
/*Easy concurrent*/
spinlock_t check_sendpkt_lock;
spinlock_t iqk_lock;
};
......@@ -2506,6 +2500,8 @@ struct rtl_btc_info {
struct bt_coexist_info {
struct rtl_btc_ops *btc_ops;
struct rtl_btc_info btc_info;
/* btc context */
void *btc_context;
/* EEPROM BT info. */
u8 eeprom_bt_coexist;
u8 eeprom_bt_type;
......@@ -2562,7 +2558,9 @@ struct bt_coexist_info {
struct rtl_btc_ops {
void (*btc_init_variables) (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_ips_notify) (struct rtl_priv *rtlpriv, u8 type);
void (*btc_lps_notify)(struct rtl_priv *rtlpriv, u8 type);
......@@ -2571,7 +2569,7 @@ struct rtl_btc_ops {
void (*btc_mediastatus_notify) (struct rtl_priv *rtlpriv,
enum rt_media_status mstatus);
void (*btc_periodical) (struct rtl_priv *rtlpriv);
void (*btc_halt_notify) (void);
void (*btc_halt_notify)(struct rtl_priv *rtlpriv);
void (*btc_btinfo_notify) (struct rtl_priv *rtlpriv,
u8 *tmp_buf, u8 length);
void (*btc_btmpinfo_notify)(struct rtl_priv *rtlpriv,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment