mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-11 08:14:27 +08:00
wireless-drivers-next patches for 4.11
Mostly smaller changeds and fixes all over, nothing really major standing out. Major changes: iwlwifi * work on support for new A000 devices continues * fix 802.11w, which was failing to due an IGTK bug ath10k * add debugfs file peer_debug_trigger for debugging firmware -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJYnHNpAAoJEG4XJFUm622b48QH/iQ7eCZMSYBOb3QIqJnpEkD/ k1xtch60J/JBTw11mS8TvvqyA19BnLZmLIIbbVWLTPeL5S4MJBGmEISHE9dc3FmY CP//GjQYdxSm7VgZJSUKolQOIsY4kj/WuY4eoJzWiOfaloXHk0ascNrigdXCUSec lRM8sX77KY/30qKJGN/Yc1ccT8zmRa/Skdt7JSHzNKakHiykqvR6NgRa6stf3g5K NJAIrZO7K1Yndr187EsX4mr3ataAeo5+YHxoIReuYq2pcrZ6uSDsO3tJfC+4upqR SrN/x6ds5SUYCKfwy0i/oxwuzYb8hWFH0m+yXhdkNPoaIyhgGHqzCVzdzbaqcDw= =IyB5 -----END PGP SIGNATURE----- Merge tag 'wireless-drivers-next-for-davem-2017-02-09' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next Kalle Valo says: ==================== wireless-drivers-next patches for 4.11 Mostly smaller changeds and fixes all over, nothing really major standing out. Major changes: iwlwifi * work on support for new A000 devices continues * fix 802.11w, which was failing to due an IGTK bug ath10k * add debugfs file peer_debug_trigger for debugging firmware ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
e3f29c4809
@ -3,6 +3,7 @@ config ATH10K
|
||||
depends on MAC80211 && HAS_DMA
|
||||
select ATH_COMMON
|
||||
select CRC32
|
||||
select WANT_DEV_COREDUMP
|
||||
---help---
|
||||
This module adds support for wireless adapters based on
|
||||
Atheros IEEE 802.11ac family of chipsets.
|
||||
|
@ -33,6 +33,9 @@ static const struct of_device_id ath10k_ahb_of_match[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match);
|
||||
|
||||
#define QCA4019_SRAM_ADDR 0x000C0000
|
||||
#define QCA4019_SRAM_LEN 0x00040000 /* 256 kb */
|
||||
|
||||
static inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar)
|
||||
{
|
||||
return &((struct ath10k_pci *)ar->drv_priv)->ahb[0];
|
||||
@ -699,6 +702,25 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 ath10k_ahb_qca4019_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
|
||||
{
|
||||
u32 val = 0, region = addr & 0xfffff;
|
||||
|
||||
val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS);
|
||||
|
||||
if (region >= QCA4019_SRAM_ADDR && region <=
|
||||
(QCA4019_SRAM_ADDR + QCA4019_SRAM_LEN)) {
|
||||
/* SRAM contents for QCA4019 can be directly accessed and
|
||||
* no conversions are required
|
||||
*/
|
||||
val |= region;
|
||||
} else {
|
||||
val |= 0x100000 | region;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static const struct ath10k_hif_ops ath10k_ahb_hif_ops = {
|
||||
.tx_sg = ath10k_pci_hif_tx_sg,
|
||||
.diag_read = ath10k_pci_hif_diag_read,
|
||||
@ -766,6 +788,7 @@ static int ath10k_ahb_probe(struct platform_device *pdev)
|
||||
ar_pci->mem_len = ar_ahb->mem_len;
|
||||
ar_pci->ar = ar;
|
||||
ar_pci->bus_ops = &ath10k_ahb_bus_ops;
|
||||
ar_pci->targ_cpu_to_ce_addr = ath10k_ahb_qca4019_targ_cpu_to_ce_addr;
|
||||
|
||||
ret = ath10k_pci_setup_resource(ar);
|
||||
if (ret) {
|
||||
|
@ -959,9 +959,9 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id,
|
||||
*/
|
||||
dest_ring->base_addr_owner_space_unaligned =
|
||||
dma_zalloc_coherent(ar->dev,
|
||||
(nentries * sizeof(struct ce_desc) +
|
||||
CE_DESC_RING_ALIGN),
|
||||
&base_addr, GFP_KERNEL);
|
||||
(nentries * sizeof(struct ce_desc) +
|
||||
CE_DESC_RING_ALIGN),
|
||||
&base_addr, GFP_KERNEL);
|
||||
if (!dest_ring->base_addr_owner_space_unaligned) {
|
||||
kfree(dest_ring);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
@ -1996,7 +1996,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
|
||||
ar->hw->wiphy->fw_version);
|
||||
|
||||
if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map)) {
|
||||
if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map) &&
|
||||
mode == ATH10K_FIRMWARE_MODE_NORMAL) {
|
||||
val = 0;
|
||||
if (ath10k_peer_stats_enabled(ar))
|
||||
val = WMI_10_4_PEER_STATS;
|
||||
@ -2049,10 +2050,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
* possible to implicitly make it correct by creating a dummy vdev and
|
||||
* then deleting it.
|
||||
*/
|
||||
status = ath10k_core_reset_rx_filter(ar);
|
||||
if (status) {
|
||||
ath10k_err(ar, "failed to reset rx filter: %d\n", status);
|
||||
goto err_hif_stop;
|
||||
if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
|
||||
status = ath10k_core_reset_rx_filter(ar);
|
||||
if (status) {
|
||||
ath10k_err(ar,
|
||||
"failed to reset rx filter: %d\n", status);
|
||||
goto err_hif_stop;
|
||||
}
|
||||
}
|
||||
|
||||
/* If firmware indicates Full Rx Reorder support it must be used in a
|
||||
|
@ -306,6 +306,69 @@ static const struct file_operations fops_delba = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath10k_dbg_sta_read_peer_debug_trigger(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||
struct ath10k *ar = arsta->arvif->ar;
|
||||
char buf[8];
|
||||
int len = 0;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
len = scnprintf(buf, sizeof(buf) - len,
|
||||
"Write 1 to once trigger the debug logs\n");
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||
struct ath10k *ar = arsta->arvif->ar;
|
||||
u8 peer_debug_trigger;
|
||||
int ret;
|
||||
|
||||
if (kstrtou8_from_user(user_buf, count, 0, &peer_debug_trigger))
|
||||
return -EINVAL;
|
||||
|
||||
if (peer_debug_trigger != 1)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON) {
|
||||
ret = -ENETDOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr,
|
||||
WMI_PEER_DEBUG, peer_debug_trigger);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_peer_debug_trigger = {
|
||||
.open = simple_open,
|
||||
.read = ath10k_dbg_sta_read_peer_debug_trigger,
|
||||
.write = ath10k_dbg_sta_write_peer_debug_trigger,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct dentry *dir)
|
||||
{
|
||||
@ -314,4 +377,6 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
debugfs_create_file("addba", S_IWUSR, dir, sta, &fops_addba);
|
||||
debugfs_create_file("addba_resp", S_IWUSR, dir, sta, &fops_addba_resp);
|
||||
debugfs_create_file("delba", S_IWUSR, dir, sta, &fops_delba);
|
||||
debugfs_create_file("peer_debug_trigger", 0600, dir, sta,
|
||||
&fops_peer_debug_trigger);
|
||||
}
|
||||
|
@ -1636,7 +1636,7 @@ struct ath10k_htt {
|
||||
int size;
|
||||
|
||||
/* size - 1 */
|
||||
unsigned size_mask;
|
||||
unsigned int size_mask;
|
||||
|
||||
/* how many rx buffers to keep in the ring */
|
||||
int fill_level;
|
||||
@ -1657,7 +1657,7 @@ struct ath10k_htt {
|
||||
|
||||
/* where HTT SW has processed bufs filled by rx MAC DMA */
|
||||
struct {
|
||||
unsigned msdu_payld;
|
||||
unsigned int msdu_payld;
|
||||
} sw_rd_idx;
|
||||
|
||||
/*
|
||||
@ -1820,7 +1820,7 @@ int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt,
|
||||
|
||||
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb);
|
||||
void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id);
|
||||
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *);
|
||||
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu);
|
||||
int ath10k_htt_tx(struct ath10k_htt *htt,
|
||||
enum ath10k_hw_txrx_mode txmode,
|
||||
struct sk_buff *msdu);
|
||||
|
@ -2492,7 +2492,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
|
||||
skb->data, skb->len);
|
||||
break;
|
||||
};
|
||||
}
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler);
|
||||
|
@ -840,29 +840,33 @@ void ath10k_pci_rx_replenish_retry(unsigned long ptr)
|
||||
ath10k_pci_rx_post(ar);
|
||||
}
|
||||
|
||||
static u32 ath10k_pci_qca988x_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
|
||||
{
|
||||
u32 val = 0, region = addr & 0xfffff;
|
||||
|
||||
val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS)
|
||||
& 0x7ff) << 21;
|
||||
val |= 0x100000 | region;
|
||||
return val;
|
||||
}
|
||||
|
||||
static u32 ath10k_pci_qca99x0_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
|
||||
{
|
||||
u32 val = 0, region = addr & 0xfffff;
|
||||
|
||||
val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS);
|
||||
val |= 0x100000 | region;
|
||||
return val;
|
||||
}
|
||||
|
||||
static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
|
||||
{
|
||||
u32 val = 0;
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
||||
switch (ar->hw_rev) {
|
||||
case ATH10K_HW_QCA988X:
|
||||
case ATH10K_HW_QCA9887:
|
||||
case ATH10K_HW_QCA6174:
|
||||
case ATH10K_HW_QCA9377:
|
||||
val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
|
||||
CORE_CTRL_ADDRESS) &
|
||||
0x7ff) << 21;
|
||||
break;
|
||||
case ATH10K_HW_QCA9888:
|
||||
case ATH10K_HW_QCA99X0:
|
||||
case ATH10K_HW_QCA9984:
|
||||
case ATH10K_HW_QCA4019:
|
||||
val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS);
|
||||
break;
|
||||
}
|
||||
if (WARN_ON_ONCE(!ar_pci->targ_cpu_to_ce_addr))
|
||||
return -ENOTSUPP;
|
||||
|
||||
val |= 0x100000 | (addr & 0xfffff);
|
||||
return val;
|
||||
return ar_pci->targ_cpu_to_ce_addr(ar, addr);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1590,7 +1594,7 @@ void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
|
||||
/* TODO: Find appropriate register configuration for QCA99X0
|
||||
* to mask irq/MSI.
|
||||
*/
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3170,6 +3174,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
bool pci_ps;
|
||||
int (*pci_soft_reset)(struct ath10k *ar);
|
||||
int (*pci_hard_reset)(struct ath10k *ar);
|
||||
u32 (*targ_cpu_to_ce_addr)(struct ath10k *ar, u32 addr);
|
||||
|
||||
switch (pci_dev->device) {
|
||||
case QCA988X_2_0_DEVICE_ID:
|
||||
@ -3177,12 +3182,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
pci_ps = false;
|
||||
pci_soft_reset = ath10k_pci_warm_reset;
|
||||
pci_hard_reset = ath10k_pci_qca988x_chip_reset;
|
||||
targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
|
||||
break;
|
||||
case QCA9887_1_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA9887;
|
||||
pci_ps = false;
|
||||
pci_soft_reset = ath10k_pci_warm_reset;
|
||||
pci_hard_reset = ath10k_pci_qca988x_chip_reset;
|
||||
targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
|
||||
break;
|
||||
case QCA6164_2_1_DEVICE_ID:
|
||||
case QCA6174_2_1_DEVICE_ID:
|
||||
@ -3190,30 +3197,35 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
pci_ps = true;
|
||||
pci_soft_reset = ath10k_pci_warm_reset;
|
||||
pci_hard_reset = ath10k_pci_qca6174_chip_reset;
|
||||
targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
|
||||
break;
|
||||
case QCA99X0_2_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA99X0;
|
||||
pci_ps = false;
|
||||
pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset;
|
||||
pci_hard_reset = ath10k_pci_qca99x0_chip_reset;
|
||||
targ_cpu_to_ce_addr = ath10k_pci_qca99x0_targ_cpu_to_ce_addr;
|
||||
break;
|
||||
case QCA9984_1_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA9984;
|
||||
pci_ps = false;
|
||||
pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset;
|
||||
pci_hard_reset = ath10k_pci_qca99x0_chip_reset;
|
||||
targ_cpu_to_ce_addr = ath10k_pci_qca99x0_targ_cpu_to_ce_addr;
|
||||
break;
|
||||
case QCA9888_2_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA9888;
|
||||
pci_ps = false;
|
||||
pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset;
|
||||
pci_hard_reset = ath10k_pci_qca99x0_chip_reset;
|
||||
targ_cpu_to_ce_addr = ath10k_pci_qca99x0_targ_cpu_to_ce_addr;
|
||||
break;
|
||||
case QCA9377_1_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA9377;
|
||||
pci_ps = true;
|
||||
pci_soft_reset = NULL;
|
||||
pci_hard_reset = ath10k_pci_qca6174_chip_reset;
|
||||
targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
@ -3240,6 +3252,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
ar_pci->bus_ops = &ath10k_pci_bus_ops;
|
||||
ar_pci->pci_soft_reset = pci_soft_reset;
|
||||
ar_pci->pci_hard_reset = pci_hard_reset;
|
||||
ar_pci->targ_cpu_to_ce_addr = targ_cpu_to_ce_addr;
|
||||
|
||||
ar->id.vendor = pdev->vendor;
|
||||
ar->id.device = pdev->device;
|
||||
|
@ -233,6 +233,11 @@ struct ath10k_pci {
|
||||
/* Chip specific pci full reset function */
|
||||
int (*pci_hard_reset)(struct ath10k *ar);
|
||||
|
||||
/* chip specific methods for converting target CPU virtual address
|
||||
* space to CE address space
|
||||
*/
|
||||
u32 (*targ_cpu_to_ce_addr)(struct ath10k *ar, u32 addr);
|
||||
|
||||
/* Keep this entry in the last, memory for struct ath10k_ahb is
|
||||
* allocated (ahb support enabled case) in the continuation of
|
||||
* this struct.
|
||||
|
@ -5811,6 +5811,7 @@ enum wmi_peer_param {
|
||||
WMI_PEER_CHAN_WIDTH = 0x4,
|
||||
WMI_PEER_NSS = 0x5,
|
||||
WMI_PEER_USE_4ADDR = 0x6,
|
||||
WMI_PEER_DEBUG = 0xa,
|
||||
WMI_PEER_DUMMY_VAR = 0xff, /* dummy parameter for STA PS workaround */
|
||||
};
|
||||
|
||||
@ -6604,7 +6605,7 @@ struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
|
||||
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
|
||||
int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
|
||||
u32 cmd_id);
|
||||
void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *);
|
||||
void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *arg);
|
||||
|
||||
void ath10k_wmi_pull_pdev_stats_base(const struct wmi_pdev_stats_base *src,
|
||||
struct ath10k_fw_stats_pdev *dst);
|
||||
|
@ -108,7 +108,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
#define ATH_AGGR_MIN_QDEPTH 2
|
||||
/* minimum h/w qdepth for non-aggregated traffic */
|
||||
#define ATH_NON_AGGR_MIN_QDEPTH 8
|
||||
#define ATH_TX_COMPLETE_POLL_INT 1000
|
||||
#define ATH_HW_CHECK_POLL_INT 1000
|
||||
#define ATH_TXFIFO_DEPTH 8
|
||||
#define ATH_TX_ERROR 0x01
|
||||
|
||||
@ -745,7 +745,7 @@ void ath9k_csa_update(struct ath_softc *sc);
|
||||
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
|
||||
#define ATH_PLL_WORK_INTERVAL 100
|
||||
|
||||
void ath_tx_complete_poll_work(struct work_struct *work);
|
||||
void ath_hw_check_work(struct work_struct *work);
|
||||
void ath_reset_work(struct work_struct *work);
|
||||
bool ath_hw_check(struct ath_softc *sc);
|
||||
void ath_hw_pll_work(struct work_struct *work);
|
||||
@ -998,6 +998,7 @@ struct ath_softc {
|
||||
struct survey_info *cur_survey;
|
||||
struct survey_info survey[ATH9K_NUM_CHANNELS];
|
||||
|
||||
spinlock_t intr_lock;
|
||||
struct tasklet_struct intr_tq;
|
||||
struct tasklet_struct bcon_tasklet;
|
||||
struct ath_hw *sc_ah;
|
||||
@ -1053,7 +1054,7 @@ struct ath_softc {
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
struct ath9k_debug debug;
|
||||
#endif
|
||||
struct delayed_work tx_complete_work;
|
||||
struct delayed_work hw_check_work;
|
||||
struct delayed_work hw_pll_work;
|
||||
struct timer_list sleep_timer;
|
||||
|
||||
|
@ -1603,6 +1603,10 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
|
||||
int count = 50;
|
||||
u32 reg, last_val;
|
||||
|
||||
/* Check if chip failed to wake up */
|
||||
if (REG_READ(ah, AR_CFG) == 0xdeadbeef)
|
||||
return false;
|
||||
|
||||
if (AR_SREV_9300(ah))
|
||||
return !ath9k_hw_detect_mac_hang(ah);
|
||||
|
||||
|
@ -669,6 +669,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
common->bt_ant_diversity = 1;
|
||||
|
||||
spin_lock_init(&common->cc_lock);
|
||||
spin_lock_init(&sc->intr_lock);
|
||||
spin_lock_init(&sc->sc_serial_rw);
|
||||
spin_lock_init(&sc->sc_pm_lock);
|
||||
spin_lock_init(&sc->chan_lock);
|
||||
@ -681,6 +682,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
INIT_WORK(&sc->hw_reset_work, ath_reset_work);
|
||||
INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
|
||||
INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
|
||||
INIT_DELAYED_WORK(&sc->hw_check_work, ath_hw_check_work);
|
||||
|
||||
ath9k_init_channel_context(sc);
|
||||
|
||||
|
@ -20,20 +20,13 @@
|
||||
* TX polling - checks if the TX engine is stuck somewhere
|
||||
* and issues a chip reset if so.
|
||||
*/
|
||||
void ath_tx_complete_poll_work(struct work_struct *work)
|
||||
static bool ath_tx_complete_check(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_softc *sc = container_of(work, struct ath_softc,
|
||||
tx_complete_work.work);
|
||||
struct ath_txq *txq;
|
||||
int i;
|
||||
bool needreset = false;
|
||||
|
||||
|
||||
if (sc->tx99_state) {
|
||||
ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
|
||||
"skip tx hung detection on tx99\n");
|
||||
return;
|
||||
}
|
||||
if (sc->tx99_state)
|
||||
return true;
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||
txq = sc->tx.txq_map[i];
|
||||
@ -41,25 +34,36 @@ void ath_tx_complete_poll_work(struct work_struct *work)
|
||||
ath_txq_lock(sc, txq);
|
||||
if (txq->axq_depth) {
|
||||
if (txq->axq_tx_inprogress) {
|
||||
needreset = true;
|
||||
ath_txq_unlock(sc, txq);
|
||||
break;
|
||||
} else {
|
||||
txq->axq_tx_inprogress = true;
|
||||
goto reset;
|
||||
}
|
||||
|
||||
txq->axq_tx_inprogress = true;
|
||||
}
|
||||
ath_txq_unlock(sc, txq);
|
||||
}
|
||||
|
||||
if (needreset) {
|
||||
ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
|
||||
"tx hung, resetting the chip\n");
|
||||
ath9k_queue_reset(sc, RESET_TYPE_TX_HANG);
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
|
||||
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
|
||||
msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT));
|
||||
reset:
|
||||
ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
|
||||
"tx hung, resetting the chip\n");
|
||||
ath9k_queue_reset(sc, RESET_TYPE_TX_HANG);
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void ath_hw_check_work(struct work_struct *work)
|
||||
{
|
||||
struct ath_softc *sc = container_of(work, struct ath_softc,
|
||||
hw_check_work.work);
|
||||
|
||||
if (!ath_hw_check(sc) ||
|
||||
!ath_tx_complete_check(sc))
|
||||
return;
|
||||
|
||||
ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work,
|
||||
msecs_to_jiffies(ATH_HW_CHECK_POLL_INT));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -805,21 +805,12 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah)
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_disable_interrupts);
|
||||
|
||||
void ath9k_hw_enable_interrupts(struct ath_hw *ah)
|
||||
static void __ath9k_hw_enable_interrupts(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u32 sync_default = AR_INTR_SYNC_DEFAULT;
|
||||
u32 async_mask;
|
||||
|
||||
if (!(ah->imask & ATH9K_INT_GLOBAL))
|
||||
return;
|
||||
|
||||
if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {
|
||||
ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
|
||||
atomic_read(&ah->intr_ref_cnt));
|
||||
return;
|
||||
}
|
||||
|
||||
if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
|
||||
AR_SREV_9561(ah))
|
||||
sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
|
||||
@ -841,6 +832,39 @@ 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));
|
||||
}
|
||||
|
||||
void ath9k_hw_resume_interrupts(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
if (!(ah->imask & ATH9K_INT_GLOBAL))
|
||||
return;
|
||||
|
||||
if (atomic_read(&ah->intr_ref_cnt) != 0) {
|
||||
ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
|
||||
atomic_read(&ah->intr_ref_cnt));
|
||||
return;
|
||||
}
|
||||
|
||||
__ath9k_hw_enable_interrupts(ah);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_resume_interrupts);
|
||||
|
||||
void ath9k_hw_enable_interrupts(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
if (!(ah->imask & ATH9K_INT_GLOBAL))
|
||||
return;
|
||||
|
||||
if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {
|
||||
ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",
|
||||
atomic_read(&ah->intr_ref_cnt));
|
||||
return;
|
||||
}
|
||||
|
||||
__ath9k_hw_enable_interrupts(ah);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
|
||||
|
||||
void ath9k_hw_set_interrupts(struct ath_hw *ah)
|
||||
|
@ -744,6 +744,7 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah);
|
||||
void ath9k_hw_enable_interrupts(struct ath_hw *ah);
|
||||
void ath9k_hw_disable_interrupts(struct ath_hw *ah);
|
||||
void ath9k_hw_kill_interrupts(struct ath_hw *ah);
|
||||
void ath9k_hw_resume_interrupts(struct ath_hw *ah);
|
||||
|
||||
void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
|
||||
|
||||
|
@ -181,7 +181,7 @@ void ath9k_ps_restore(struct ath_softc *sc)
|
||||
static void __ath_cancel_work(struct ath_softc *sc)
|
||||
{
|
||||
cancel_work_sync(&sc->paprd_work);
|
||||
cancel_delayed_work_sync(&sc->tx_complete_work);
|
||||
cancel_delayed_work_sync(&sc->hw_check_work);
|
||||
cancel_delayed_work_sync(&sc->hw_pll_work);
|
||||
|
||||
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
|
||||
@ -198,7 +198,8 @@ void ath_cancel_work(struct ath_softc *sc)
|
||||
|
||||
void ath_restart_work(struct ath_softc *sc)
|
||||
{
|
||||
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
|
||||
ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work,
|
||||
ATH_HW_CHECK_POLL_INT);
|
||||
|
||||
if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9330(sc->sc_ah))
|
||||
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
|
||||
@ -373,21 +374,20 @@ void ath9k_tasklet(unsigned long data)
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
enum ath_reset_type type;
|
||||
unsigned long flags;
|
||||
u32 status = sc->intrstatus;
|
||||
u32 status;
|
||||
u32 rxmask;
|
||||
|
||||
spin_lock_irqsave(&sc->intr_lock, flags);
|
||||
status = sc->intrstatus;
|
||||
sc->intrstatus = 0;
|
||||
spin_unlock_irqrestore(&sc->intr_lock, flags);
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
spin_lock(&sc->sc_pcu_lock);
|
||||
|
||||
if (status & ATH9K_INT_FATAL) {
|
||||
type = RESET_TYPE_FATAL_INT;
|
||||
ath9k_queue_reset(sc, type);
|
||||
|
||||
/*
|
||||
* Increment the ref. counter here so that
|
||||
* interrupts are enabled in the reset routine.
|
||||
*/
|
||||
atomic_inc(&ah->intr_ref_cnt);
|
||||
ath_dbg(common, RESET, "FATAL: Skipping interrupts\n");
|
||||
goto out;
|
||||
}
|
||||
@ -403,11 +403,6 @@ void ath9k_tasklet(unsigned long data)
|
||||
type = RESET_TYPE_BB_WATCHDOG;
|
||||
ath9k_queue_reset(sc, type);
|
||||
|
||||
/*
|
||||
* Increment the ref. counter here so that
|
||||
* interrupts are enabled in the reset routine.
|
||||
*/
|
||||
atomic_inc(&ah->intr_ref_cnt);
|
||||
ath_dbg(common, RESET,
|
||||
"BB_WATCHDOG: Skipping interrupts\n");
|
||||
goto out;
|
||||
@ -420,7 +415,6 @@ void ath9k_tasklet(unsigned long data)
|
||||
if ((sc->gtt_cnt >= MAX_GTT_CNT) && !ath9k_hw_check_alive(ah)) {
|
||||
type = RESET_TYPE_TX_GTT;
|
||||
ath9k_queue_reset(sc, type);
|
||||
atomic_inc(&ah->intr_ref_cnt);
|
||||
ath_dbg(common, RESET,
|
||||
"GTT: Skipping interrupts\n");
|
||||
goto out;
|
||||
@ -477,7 +471,7 @@ void ath9k_tasklet(unsigned long data)
|
||||
ath9k_btcoex_handle_interrupt(sc, status);
|
||||
|
||||
/* re-enable hardware interrupt */
|
||||
ath9k_hw_enable_interrupts(ah);
|
||||
ath9k_hw_resume_interrupts(ah);
|
||||
out:
|
||||
spin_unlock(&sc->sc_pcu_lock);
|
||||
ath9k_ps_restore(sc);
|
||||
@ -541,7 +535,9 @@ irqreturn_t ath_isr(int irq, void *dev)
|
||||
return IRQ_NONE;
|
||||
|
||||
/* Cache the status */
|
||||
sc->intrstatus = status;
|
||||
spin_lock(&sc->intr_lock);
|
||||
sc->intrstatus |= status;
|
||||
spin_unlock(&sc->intr_lock);
|
||||
|
||||
if (status & SCHED_INTR)
|
||||
sched = true;
|
||||
@ -587,7 +583,7 @@ chip_reset:
|
||||
|
||||
if (sched) {
|
||||
/* turn off every interrupt */
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
ath9k_hw_kill_interrupts(ah);
|
||||
tasklet_schedule(&sc->intr_tq);
|
||||
}
|
||||
|
||||
@ -2091,7 +2087,7 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
|
||||
int timeout;
|
||||
bool drain_txq;
|
||||
|
||||
cancel_delayed_work_sync(&sc->tx_complete_work);
|
||||
cancel_delayed_work_sync(&sc->hw_check_work);
|
||||
|
||||
if (ah->ah_flags & AH_UNPLUGGED) {
|
||||
ath_dbg(common, ANY, "Device has been unplugged!\n");
|
||||
@ -2129,7 +2125,8 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
|
||||
ieee80211_queue_delayed_work(hw, &sc->hw_check_work,
|
||||
ATH_HW_CHECK_POLL_INT);
|
||||
}
|
||||
|
||||
static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
|
||||
|
@ -2872,8 +2872,6 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
|
||||
return error;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
|
||||
error = ath_tx_edma_init(sc);
|
||||
|
||||
|
@ -574,6 +574,7 @@ static void wcn36xx_hw_scan_worker(struct work_struct *work)
|
||||
struct cfg80211_scan_request *req = wcn->scan_req;
|
||||
u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX];
|
||||
struct cfg80211_scan_info scan_info = {};
|
||||
bool aborted = false;
|
||||
int i;
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", req->n_channels);
|
||||
@ -585,6 +586,13 @@ static void wcn36xx_hw_scan_worker(struct work_struct *work)
|
||||
|
||||
wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN);
|
||||
for (i = 0; i < req->n_channels; i++) {
|
||||
mutex_lock(&wcn->scan_lock);
|
||||
aborted = wcn->scan_aborted;
|
||||
mutex_unlock(&wcn->scan_lock);
|
||||
|
||||
if (aborted)
|
||||
break;
|
||||
|
||||
wcn->scan_freq = req->channels[i]->center_freq;
|
||||
wcn->scan_band = req->channels[i]->band;
|
||||
|
||||
@ -596,7 +604,7 @@ static void wcn36xx_hw_scan_worker(struct work_struct *work)
|
||||
}
|
||||
wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
|
||||
|
||||
scan_info.aborted = false;
|
||||
scan_info.aborted = aborted;
|
||||
ieee80211_scan_completed(wcn->hw, &scan_info);
|
||||
|
||||
mutex_lock(&wcn->scan_lock);
|
||||
@ -615,6 +623,8 @@ static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
|
||||
mutex_unlock(&wcn->scan_lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
wcn->scan_aborted = false;
|
||||
wcn->scan_req = &hw_req->req;
|
||||
mutex_unlock(&wcn->scan_lock);
|
||||
|
||||
@ -623,6 +633,18 @@ static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wcn36xx_cancel_hw_scan(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wcn36xx *wcn = hw->priv;
|
||||
|
||||
mutex_lock(&wcn->scan_lock);
|
||||
wcn->scan_aborted = true;
|
||||
mutex_unlock(&wcn->scan_lock);
|
||||
|
||||
cancel_work_sync(&wcn->scan_work);
|
||||
}
|
||||
|
||||
static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
|
||||
enum nl80211_band band)
|
||||
{
|
||||
@ -1034,6 +1056,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
|
||||
.tx = wcn36xx_tx,
|
||||
.set_key = wcn36xx_set_key,
|
||||
.hw_scan = wcn36xx_hw_scan,
|
||||
.cancel_hw_scan = wcn36xx_cancel_hw_scan,
|
||||
.bss_info_changed = wcn36xx_bss_info_changed,
|
||||
.set_rts_threshold = wcn36xx_set_rts_threshold,
|
||||
.sta_add = wcn36xx_sta_add,
|
||||
|
@ -220,6 +220,7 @@ struct wcn36xx {
|
||||
int scan_freq;
|
||||
int scan_band;
|
||||
struct mutex scan_lock;
|
||||
bool scan_aborted;
|
||||
|
||||
/* DXE channels */
|
||||
struct wcn36xx_dxe_ch dxe_tx_l_ch; /* TX low */
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include "wil6210.h"
|
||||
#include "wmi.h"
|
||||
|
||||
|
@ -5908,6 +5908,9 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (channel->orig_flags & IEEE80211_CHAN_DISABLED)
|
||||
continue;
|
||||
|
||||
/* assuming the chanspecs order is HT20,
|
||||
* HT40 upper, HT40 lower, and VHT80.
|
||||
*/
|
||||
@ -6509,6 +6512,9 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
|
||||
wiphy->bands[NL80211_BAND_5GHZ] = band;
|
||||
}
|
||||
}
|
||||
|
||||
wiphy_read_of_freq_limits(wiphy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -218,6 +218,22 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_BRCM_TRACING
|
||||
void __brcmf_err(const char *func, const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
pr_err("%s: %pV", func, &vaf);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG)
|
||||
void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)
|
||||
{
|
||||
|
@ -32,16 +32,25 @@ static int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data,
|
||||
{
|
||||
void *dump;
|
||||
size_t ramsize;
|
||||
int err;
|
||||
|
||||
ramsize = brcmf_bus_get_ramsize(bus);
|
||||
if (ramsize) {
|
||||
dump = vzalloc(len + ramsize);
|
||||
if (!dump)
|
||||
return -ENOMEM;
|
||||
memcpy(dump, data, len);
|
||||
brcmf_bus_get_memdump(bus, dump + len, ramsize);
|
||||
dev_coredumpv(bus->dev, dump, len + ramsize, GFP_KERNEL);
|
||||
if (!ramsize)
|
||||
return -ENOTSUPP;
|
||||
|
||||
dump = vzalloc(len + ramsize);
|
||||
if (!dump)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(dump, data, len);
|
||||
err = brcmf_bus_get_memdump(bus, dump + len, ramsize);
|
||||
if (err) {
|
||||
vfree(dump);
|
||||
return err;
|
||||
}
|
||||
|
||||
dev_coredumpv(bus->dev, dump, len + ramsize, GFP_KERNEL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -49,10 +58,18 @@ static int brcmf_debug_psm_watchdog_notify(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *evtmsg,
|
||||
void *data)
|
||||
{
|
||||
int err;
|
||||
|
||||
brcmf_dbg(TRACE, "enter: bsscfgidx=%d\n", ifp->bsscfgidx);
|
||||
|
||||
return brcmf_debug_create_memdump(ifp->drvr->bus_if, data,
|
||||
evtmsg->datalen);
|
||||
brcmf_err("PSM's watchdog has fired!\n");
|
||||
|
||||
err = brcmf_debug_create_memdump(ifp->drvr->bus_if, data,
|
||||
evtmsg->datalen);
|
||||
if (err)
|
||||
brcmf_err("Failed to get memory dump, %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void brcmf_debugfs_init(void)
|
||||
|
@ -45,26 +45,18 @@
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
/* Macro for error messages. net_ratelimit() is used when driver
|
||||
* debugging is not selected. When debugging the driver error
|
||||
* messages are as important as other tracing or even more so.
|
||||
*/
|
||||
#ifndef CONFIG_BRCM_TRACING
|
||||
#ifdef CONFIG_BRCMDBG
|
||||
#define brcmf_err(fmt, ...) pr_err("%s: " fmt, __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define brcmf_err(fmt, ...) \
|
||||
do { \
|
||||
if (net_ratelimit()) \
|
||||
pr_err("%s: " fmt, __func__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#endif
|
||||
#else
|
||||
__printf(2, 3)
|
||||
void __brcmf_err(const char *func, const char *fmt, ...);
|
||||
#define brcmf_err(fmt, ...) \
|
||||
__brcmf_err(__func__, fmt, ##__VA_ARGS__)
|
||||
#endif
|
||||
/* Macro for error messages. When debugging / tracing the driver all error
|
||||
* messages are important to us.
|
||||
*/
|
||||
#define brcmf_err(fmt, ...) \
|
||||
do { \
|
||||
if (IS_ENABLED(CONFIG_BRCMDBG) || \
|
||||
IS_ENABLED(CONFIG_BRCM_TRACING) || \
|
||||
net_ratelimit()) \
|
||||
__brcmf_err(__func__, fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#if defined(DEBUG) || defined(CONFIG_BRCM_TRACING)
|
||||
__printf(3, 4)
|
||||
|
@ -90,13 +90,16 @@ config IWLWIFI_BCAST_FILTERING
|
||||
|
||||
config IWLWIFI_PCIE_RTPM
|
||||
bool "Enable runtime power management mode for PCIe devices"
|
||||
depends on IWLMVM && PM
|
||||
depends on IWLMVM && PM && EXPERT
|
||||
default false
|
||||
help
|
||||
Say Y here to enable runtime power management for PCIe
|
||||
devices. If enabled, the device will go into low power mode
|
||||
when idle for a short period of time, allowing for improved
|
||||
power saving during runtime.
|
||||
power saving during runtime. Note that this feature requires
|
||||
a tight integration with the platform. It is not recommended
|
||||
to enable this feature without proper validation with the
|
||||
specific target platform.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
@ -740,7 +740,10 @@ static u16 rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask,
|
||||
|
||||
/* Find the previous rate that is in the rate mask */
|
||||
i = index - 1;
|
||||
for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
|
||||
if (i >= 0)
|
||||
mask = BIT(i);
|
||||
|
||||
for (; i >= 0; i--, mask >>= 1) {
|
||||
if (rate_mask & mask) {
|
||||
low = i;
|
||||
break;
|
||||
|
@ -72,9 +72,13 @@
|
||||
#define IWL_A000_SMEM_OFFSET 0x400000
|
||||
#define IWL_A000_SMEM_LEN 0x68000
|
||||
|
||||
#define IWL_A000_FW_PRE "iwlwifi-Qu-a0-jf-b0-"
|
||||
#define IWL_A000_MODULE_FIRMWARE(api) \
|
||||
IWL_A000_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_A000_JF_FW_PRE "iwlwifi-Qu-a0-jf-b0-"
|
||||
#define IWL_A000_HR_FW_PRE "iwlwifi-Qu-a0-hr-a0-"
|
||||
|
||||
#define IWL_A000_HR_MODULE_FIRMWARE(api) \
|
||||
IWL_A000_HR_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL_A000_JF_MODULE_FIRMWARE(api) \
|
||||
IWL_A000_JF_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
#define NVM_HW_SECTION_NUM_FAMILY_A000 10
|
||||
|
||||
@ -116,11 +120,12 @@ static const struct iwl_ht_params iwl_a000_ht_params = {
|
||||
.mq_rx_supported = true, \
|
||||
.vht_mu_mimo_supported = true, \
|
||||
.mac_addr_from_csr = true, \
|
||||
.use_tfh = true
|
||||
.use_tfh = true, \
|
||||
.rf_id = true
|
||||
|
||||
const struct iwl_cfg iwla000_2ac_cfg = {
|
||||
const struct iwl_cfg iwla000_2ac_cfg_hr = {
|
||||
.name = "Intel(R) Dual Band Wireless AC a000",
|
||||
.fw_name_pre = IWL_A000_FW_PRE,
|
||||
.fw_name_pre = IWL_A000_HR_FW_PRE,
|
||||
IWL_DEVICE_A000,
|
||||
.ht_params = &iwl_a000_ht_params,
|
||||
.nvm_ver = IWL_A000_NVM_VERSION,
|
||||
@ -128,4 +133,15 @@ const struct iwl_cfg iwla000_2ac_cfg = {
|
||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL_A000_MODULE_FIRMWARE(IWL_A000_UCODE_API_MAX));
|
||||
const struct iwl_cfg iwla000_2ac_cfg_jf = {
|
||||
.name = "Intel(R) Dual Band Wireless AC a000",
|
||||
.fw_name_pre = IWL_A000_JF_FW_PRE,
|
||||
IWL_DEVICE_A000,
|
||||
.ht_params = &iwl_a000_ht_params,
|
||||
.nvm_ver = IWL_A000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL_A000_TX_POWER_VERSION,
|
||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL_A000_HR_MODULE_FIRMWARE(IWL_A000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_A000_JF_MODULE_FIRMWARE(IWL_A000_UCODE_API_MAX));
|
||||
|
@ -455,7 +455,8 @@ extern const struct iwl_cfg iwl9260_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl9270_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl9460_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl9560_2ac_cfg;
|
||||
extern const struct iwl_cfg iwla000_2ac_cfg;
|
||||
extern const struct iwl_cfg iwla000_2ac_cfg_hr;
|
||||
extern const struct iwl_cfg iwla000_2ac_cfg_jf;
|
||||
#endif /* CONFIG_IWLMVM */
|
||||
|
||||
#endif /* __IWL_CONFIG_H__ */
|
||||
|
@ -349,6 +349,7 @@ enum {
|
||||
/* RF_ID value */
|
||||
#define CSR_HW_RF_ID_TYPE_JF (0x00105000)
|
||||
#define CSR_HW_RF_ID_TYPE_LC (0x00101000)
|
||||
#define CSR_HW_RF_ID_TYPE_HR (0x00109000)
|
||||
|
||||
/* EEPROM REG */
|
||||
#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
|
||||
|
@ -102,7 +102,6 @@ static struct dentry *iwl_dbgfs_root;
|
||||
* @op_mode: the running op_mode
|
||||
* @trans: transport layer
|
||||
* @dev: for debug prints only
|
||||
* @cfg: configuration struct
|
||||
* @fw_index: firmware revision to try loading
|
||||
* @firmware_name: composite filename of ucode file to load
|
||||
* @request_firmware_complete: the firmware has been obtained from user space
|
||||
@ -114,7 +113,6 @@ struct iwl_drv {
|
||||
struct iwl_op_mode *op_mode;
|
||||
struct iwl_trans *trans;
|
||||
struct device *dev;
|
||||
const struct iwl_cfg *cfg;
|
||||
|
||||
int fw_index; /* firmware we're trying to load */
|
||||
char firmware_name[64]; /* name of firmware file to load */
|
||||
@ -213,18 +211,18 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw,
|
||||
|
||||
static int iwl_request_firmware(struct iwl_drv *drv, bool first)
|
||||
{
|
||||
const char *name_pre = drv->cfg->fw_name_pre;
|
||||
const char *name_pre = drv->trans->cfg->fw_name_pre;
|
||||
char tag[8];
|
||||
|
||||
if (first) {
|
||||
drv->fw_index = drv->cfg->ucode_api_max;
|
||||
drv->fw_index = drv->trans->cfg->ucode_api_max;
|
||||
sprintf(tag, "%d", drv->fw_index);
|
||||
} else {
|
||||
drv->fw_index--;
|
||||
sprintf(tag, "%d", drv->fw_index);
|
||||
}
|
||||
|
||||
if (drv->fw_index < drv->cfg->ucode_api_min) {
|
||||
if (drv->fw_index < drv->trans->cfg->ucode_api_min) {
|
||||
IWL_ERR(drv, "no suitable firmware found!\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
@ -1207,7 +1205,7 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
|
||||
dbgfs_dir = drv->dbgfs_op_mode;
|
||||
#endif
|
||||
|
||||
op_mode = ops->start(drv->trans, drv->cfg, &drv->fw, dbgfs_dir);
|
||||
op_mode = ops->start(drv->trans, drv->trans->cfg, &drv->fw, dbgfs_dir);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (!op_mode) {
|
||||
@ -1247,8 +1245,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
struct iwlwifi_opmode_table *op;
|
||||
int err;
|
||||
struct iwl_firmware_pieces *pieces;
|
||||
const unsigned int api_max = drv->cfg->ucode_api_max;
|
||||
const unsigned int api_min = drv->cfg->ucode_api_min;
|
||||
const unsigned int api_max = drv->trans->cfg->ucode_api_max;
|
||||
const unsigned int api_min = drv->trans->cfg->ucode_api_min;
|
||||
size_t trigger_tlv_sz[FW_DBG_TRIGGER_MAX];
|
||||
u32 api_ver;
|
||||
int i;
|
||||
@ -1310,7 +1308,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
* In mvm uCode there is no difference between data and instructions
|
||||
* sections.
|
||||
*/
|
||||
if (fw->type == IWL_FW_DVM && validate_sec_sizes(drv, pieces, drv->cfg))
|
||||
if (fw->type == IWL_FW_DVM && validate_sec_sizes(drv, pieces,
|
||||
drv->trans->cfg))
|
||||
goto try_again;
|
||||
|
||||
/* Allocate ucode buffers for card's bus-master loading ... */
|
||||
@ -1408,14 +1407,14 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
fw->init_evtlog_size = (pieces->init_evtlog_size - 16)/12;
|
||||
else
|
||||
fw->init_evtlog_size =
|
||||
drv->cfg->base_params->max_event_log_size;
|
||||
drv->trans->cfg->base_params->max_event_log_size;
|
||||
fw->init_errlog_ptr = pieces->init_errlog_ptr;
|
||||
fw->inst_evtlog_ptr = pieces->inst_evtlog_ptr;
|
||||
if (pieces->inst_evtlog_size)
|
||||
fw->inst_evtlog_size = (pieces->inst_evtlog_size - 16)/12;
|
||||
else
|
||||
fw->inst_evtlog_size =
|
||||
drv->cfg->base_params->max_event_log_size;
|
||||
drv->trans->cfg->base_params->max_event_log_size;
|
||||
fw->inst_errlog_ptr = pieces->inst_errlog_ptr;
|
||||
|
||||
/*
|
||||
@ -1504,8 +1503,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
kfree(pieces);
|
||||
}
|
||||
|
||||
struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
|
||||
const struct iwl_cfg *cfg)
|
||||
struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_drv *drv;
|
||||
int ret;
|
||||
@ -1518,7 +1516,6 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
|
||||
|
||||
drv->trans = trans;
|
||||
drv->dev = trans->dev;
|
||||
drv->cfg = cfg;
|
||||
|
||||
init_completion(&drv->request_firmware_complete);
|
||||
INIT_LIST_HEAD(&drv->list);
|
||||
|
@ -118,15 +118,13 @@ struct iwl_cfg;
|
||||
* iwl_drv_start - start the drv
|
||||
*
|
||||
* @trans_ops: the ops of the transport
|
||||
* @cfg: device specific constants / virtual functions
|
||||
*
|
||||
* starts the driver: fetches the firmware. This should be called by bus
|
||||
* specific system flows implementations. For example, the bus specific probe
|
||||
* function should do bus related operations only, and then call to this
|
||||
* function. It returns the driver object or %NULL if an error occurred.
|
||||
*/
|
||||
struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
|
||||
const struct iwl_cfg *cfg);
|
||||
struct iwl_drv *iwl_drv_start(struct iwl_trans *trans);
|
||||
|
||||
/**
|
||||
* iwl_drv_stop - stop the drv
|
||||
|
@ -91,7 +91,7 @@ void iwl_mvm_set_rekey_data(struct ieee80211_hw *hw,
|
||||
memcpy(mvmvif->rekey_data.kek, data->kek, NL80211_KEK_LEN);
|
||||
memcpy(mvmvif->rekey_data.kck, data->kck, NL80211_KCK_LEN);
|
||||
mvmvif->rekey_data.replay_ctr =
|
||||
cpu_to_le64(be64_to_cpup((__be64 *)&data->replay_ctr));
|
||||
cpu_to_le64(be64_to_cpup((__be64 *)data->replay_ctr));
|
||||
mvmvif->rekey_data.valid = true;
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
@ -1741,7 +1741,7 @@ out:
|
||||
static struct iwl_wowlan_status *
|
||||
iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
u32 base = mvm->error_event_table;
|
||||
u32 base = mvm->error_event_table[0];
|
||||
struct error_table_start {
|
||||
/* cf. struct iwl_error_event_table */
|
||||
u32 valid;
|
||||
|
@ -64,13 +64,14 @@
|
||||
#define __fw_api_mac_h__
|
||||
|
||||
/*
|
||||
* The first MAC indices (starting from 0)
|
||||
* are available to the driver, AUX follows
|
||||
* The first MAC indices (starting from 0) are available to the driver,
|
||||
* AUX indices follows - 1 for non-CDB, 2 for CDB.
|
||||
*/
|
||||
#define MAC_INDEX_AUX 4
|
||||
#define MAC_INDEX_MIN_DRIVER 0
|
||||
#define NUM_MAC_INDEX_DRIVER MAC_INDEX_AUX
|
||||
#define NUM_MAC_INDEX (MAC_INDEX_AUX + 1)
|
||||
#define NUM_MAC_INDEX (NUM_MAC_INDEX_DRIVER + 1)
|
||||
#define NUM_MAC_INDEX_CDB (NUM_MAC_INDEX_DRIVER + 2)
|
||||
|
||||
#define IWL_MVM_STATION_COUNT 16
|
||||
#define IWL_MVM_TDLS_STA_COUNT 4
|
||||
|
@ -453,6 +453,8 @@ enum scan_config_flags {
|
||||
SCAN_CONFIG_FLAG_CLEAR_CAM_MODE = BIT(19),
|
||||
SCAN_CONFIG_FLAG_SET_PROMISC_MODE = BIT(20),
|
||||
SCAN_CONFIG_FLAG_CLEAR_PROMISC_MODE = BIT(21),
|
||||
SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED = BIT(22),
|
||||
SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED = BIT(23),
|
||||
|
||||
/* Bits 26-31 are for num of channels in channel_array */
|
||||
#define SCAN_CONFIG_N_CHANNELS(n) ((n) << 26)
|
||||
@ -485,6 +487,20 @@ enum iwl_channel_flags {
|
||||
IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE = BIT(3),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_scan_dwell
|
||||
* @active: default dwell time for active scan
|
||||
* @passive: default dwell time for passive scan
|
||||
* @fragmented: default dwell time for fragmented scan
|
||||
* @extended: default dwell time for channels 1, 6 and 11
|
||||
*/
|
||||
struct iwl_scan_dwell {
|
||||
u8 active;
|
||||
u8 passive;
|
||||
u8 fragmented;
|
||||
u8 extended;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_scan_config
|
||||
* @flags: enum scan_config_flags
|
||||
@ -493,10 +509,7 @@ enum iwl_channel_flags {
|
||||
* @legacy_rates: default legacy rates - enum scan_config_rates
|
||||
* @out_of_channel_time: default max out of serving channel time
|
||||
* @suspend_time: default max suspend time
|
||||
* @dwell_active: default dwell time for active scan
|
||||
* @dwell_passive: default dwell time for passive scan
|
||||
* @dwell_fragmented: default dwell time for fragmented scan
|
||||
* @dwell_extended: default dwell time for channels 1, 6 and 11
|
||||
* @dwell: dwells for the scan
|
||||
* @mac_addr: default mac address to be used in probes
|
||||
* @bcast_sta_id: the index of the station in the fw
|
||||
* @channel_flags: default channel flags - enum iwl_channel_flags
|
||||
@ -510,16 +523,29 @@ struct iwl_scan_config {
|
||||
__le32 legacy_rates;
|
||||
__le32 out_of_channel_time;
|
||||
__le32 suspend_time;
|
||||
u8 dwell_active;
|
||||
u8 dwell_passive;
|
||||
u8 dwell_fragmented;
|
||||
u8 dwell_extended;
|
||||
struct iwl_scan_dwell dwell;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 bcast_sta_id;
|
||||
u8 channel_flags;
|
||||
u8 channel_array[];
|
||||
} __packed; /* SCAN_CONFIG_DB_CMD_API_S */
|
||||
|
||||
#define SCAN_TWO_LMACS 2
|
||||
|
||||
struct iwl_scan_config_cdb {
|
||||
__le32 flags;
|
||||
__le32 tx_chains;
|
||||
__le32 rx_chains;
|
||||
__le32 legacy_rates;
|
||||
__le32 out_of_channel_time[SCAN_TWO_LMACS];
|
||||
__le32 suspend_time[SCAN_TWO_LMACS];
|
||||
struct iwl_scan_dwell dwell;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 bcast_sta_id;
|
||||
u8 channel_flags;
|
||||
u8 channel_array[];
|
||||
} __packed; /* SCAN_CONFIG_DB_CMD_API_S_3 */
|
||||
|
||||
/**
|
||||
* iwl_umac_scan_flags
|
||||
*@IWL_UMAC_SCAN_FLAG_PREEMPTIVE: scan process triggered by this scan request
|
||||
@ -540,17 +566,18 @@ enum iwl_umac_scan_uid_offsets {
|
||||
};
|
||||
|
||||
enum iwl_umac_scan_general_flags {
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC = BIT(0),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_OVER_BT = BIT(1),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL = BIT(2),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_PASSIVE = BIT(3),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT = BIT(4),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE = BIT(5),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_MULTIPLE_SSID = BIT(6),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED = BIT(7),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED = BIT(8),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_MATCH = BIT(9),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL = BIT(10),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC = BIT(0),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_OVER_BT = BIT(1),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL = BIT(2),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_PASSIVE = BIT(3),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT = BIT(4),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE = BIT(5),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_MULTIPLE_SSID = BIT(6),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED = BIT(7),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED = BIT(8),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_MATCH = BIT(9),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL = BIT(10),
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED = BIT(11),
|
||||
};
|
||||
|
||||
/**
|
||||
@ -610,8 +637,9 @@ struct iwl_scan_req_umac_tail {
|
||||
* @active_dwell: dwell time for active scan
|
||||
* @passive_dwell: dwell time for passive scan
|
||||
* @fragmented_dwell: dwell time for fragmented passive scan
|
||||
* @max_out_time: max out of serving channel time
|
||||
* @suspend_time: max suspend time
|
||||
* @max_out_time: max out of serving channel time, per LMAC - for CDB there
|
||||
* are 2 LMACs
|
||||
* @suspend_time: max suspend time, per LMAC - for CDB there are 2 LMACs
|
||||
* @scan_priority: scan internal prioritization &enum iwl_scan_priority
|
||||
* @channel_flags: &enum iwl_scan_channel_flags
|
||||
* @n_channels: num of channels in scan request
|
||||
@ -631,15 +659,33 @@ struct iwl_scan_req_umac {
|
||||
u8 active_dwell;
|
||||
u8 passive_dwell;
|
||||
u8 fragmented_dwell;
|
||||
__le32 max_out_time;
|
||||
__le32 suspend_time;
|
||||
__le32 scan_priority;
|
||||
/* SCAN_CHANNEL_PARAMS_API_S_VER_4 */
|
||||
u8 channel_flags;
|
||||
u8 n_channels;
|
||||
__le16 reserved;
|
||||
u8 data[];
|
||||
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */
|
||||
union {
|
||||
struct {
|
||||
__le32 max_out_time;
|
||||
__le32 suspend_time;
|
||||
__le32 scan_priority;
|
||||
/* SCAN_CHANNEL_PARAMS_API_S_VER_4 */
|
||||
u8 channel_flags;
|
||||
u8 n_channels;
|
||||
__le16 reserved;
|
||||
u8 data[];
|
||||
} no_cdb; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */
|
||||
struct {
|
||||
__le32 max_out_time[SCAN_TWO_LMACS];
|
||||
__le32 suspend_time[SCAN_TWO_LMACS];
|
||||
__le32 scan_priority;
|
||||
/* SCAN_CHANNEL_PARAMS_API_S_VER_4 */
|
||||
u8 channel_flags;
|
||||
u8 n_channels;
|
||||
__le16 reserved;
|
||||
u8 data[];
|
||||
} cdb; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_5 */
|
||||
};
|
||||
} __packed;
|
||||
|
||||
#define IWL_SCAN_REQ_UMAC_SIZE_CDB sizeof(struct iwl_scan_req_umac)
|
||||
#define IWL_SCAN_REQ_UMAC_SIZE (sizeof(struct iwl_scan_req_umac) - \
|
||||
2 * sizeof(__le32))
|
||||
|
||||
/**
|
||||
* struct iwl_umac_scan_abort
|
||||
|
@ -220,7 +220,7 @@ struct mvm_statistics_bt_activity {
|
||||
__le32 lo_priority_rx_denied_cnt;
|
||||
} __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */
|
||||
|
||||
struct mvm_statistics_general_v8 {
|
||||
struct mvm_statistics_general_common {
|
||||
__le32 radio_temperature;
|
||||
__le32 radio_voltage;
|
||||
struct mvm_statistics_dbg dbg;
|
||||
@ -248,11 +248,22 @@ struct mvm_statistics_general_v8 {
|
||||
__le64 on_time_rf;
|
||||
__le64 on_time_scan;
|
||||
__le64 tx_time;
|
||||
} __packed;
|
||||
|
||||
struct mvm_statistics_general_v8 {
|
||||
struct mvm_statistics_general_common common;
|
||||
__le32 beacon_counter[NUM_MAC_INDEX];
|
||||
u8 beacon_average_energy[NUM_MAC_INDEX];
|
||||
u8 reserved[4 - (NUM_MAC_INDEX % 4)];
|
||||
} __packed; /* STATISTICS_GENERAL_API_S_VER_8 */
|
||||
|
||||
struct mvm_statistics_general_cdb {
|
||||
struct mvm_statistics_general_common common;
|
||||
__le32 beacon_counter[NUM_MAC_INDEX_CDB];
|
||||
u8 beacon_average_energy[NUM_MAC_INDEX_CDB];
|
||||
u8 reserved[4 - (NUM_MAC_INDEX_CDB % 4)];
|
||||
} __packed; /* STATISTICS_GENERAL_API_S_VER_9 */
|
||||
|
||||
/**
|
||||
* struct mvm_statistics_load - RX statistics for multi-queue devices
|
||||
* @air_time: accumulated air time, per mac
|
||||
@ -267,6 +278,13 @@ struct mvm_statistics_load {
|
||||
u8 avg_energy[IWL_MVM_STATION_COUNT];
|
||||
} __packed; /* STATISTICS_RX_MAC_STATION_S_VER_1 */
|
||||
|
||||
struct mvm_statistics_load_cdb {
|
||||
__le32 air_time[NUM_MAC_INDEX_CDB];
|
||||
__le32 byte_count[NUM_MAC_INDEX_CDB];
|
||||
__le32 pkt_count[NUM_MAC_INDEX_CDB];
|
||||
u8 avg_energy[IWL_MVM_STATION_COUNT];
|
||||
} __packed; /* STATISTICS_RX_MAC_STATION_S_VER_2 */
|
||||
|
||||
struct mvm_statistics_rx {
|
||||
struct mvm_statistics_rx_phy ofdm;
|
||||
struct mvm_statistics_rx_phy cck;
|
||||
@ -281,6 +299,7 @@ struct mvm_statistics_rx {
|
||||
* while associated. To disable this behavior, set DISABLE_NOTIF flag in the
|
||||
* STATISTICS_CMD (0x9c), below.
|
||||
*/
|
||||
|
||||
struct iwl_notif_statistics_v10 {
|
||||
__le32 flag;
|
||||
struct mvm_statistics_rx rx;
|
||||
@ -296,6 +315,14 @@ struct iwl_notif_statistics_v11 {
|
||||
struct mvm_statistics_load load_stats;
|
||||
} __packed; /* STATISTICS_NTFY_API_S_VER_11 */
|
||||
|
||||
struct iwl_notif_statistics_cdb {
|
||||
__le32 flag;
|
||||
struct mvm_statistics_rx rx;
|
||||
struct mvm_statistics_tx tx;
|
||||
struct mvm_statistics_general_cdb general;
|
||||
struct mvm_statistics_load_cdb load_stats;
|
||||
} __packed; /* STATISTICS_NTFY_API_S_VER_12 */
|
||||
|
||||
#define IWL_STATISTICS_FLG_CLEAR 0x1
|
||||
#define IWL_STATISTICS_FLG_DISABLE_NOTIF 0x2
|
||||
|
||||
|
@ -672,8 +672,7 @@ struct iwl_mac_beacon_cmd_v6 {
|
||||
} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_6 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_beacon_cmd - beacon template command with offloaded CSA
|
||||
* @tx: the tx commands associated with the beacon frame
|
||||
* struct iwl_mac_beacon_cmd_data - data of beacon template with offloaded CSA
|
||||
* @template_id: currently equal to the mac context id of the coresponding
|
||||
* mac.
|
||||
* @tim_idx: the offset of the tim IE in the beacon
|
||||
@ -682,16 +681,38 @@ struct iwl_mac_beacon_cmd_v6 {
|
||||
* @csa_offset: offset to the CSA IE if present
|
||||
* @frame: the template of the beacon frame
|
||||
*/
|
||||
struct iwl_mac_beacon_cmd {
|
||||
struct iwl_tx_cmd tx;
|
||||
struct iwl_mac_beacon_cmd_data {
|
||||
__le32 template_id;
|
||||
__le32 tim_idx;
|
||||
__le32 tim_size;
|
||||
__le32 ecsa_offset;
|
||||
__le32 csa_offset;
|
||||
struct ieee80211_hdr frame[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_mac_beacon_cmd_v7 - beacon template command with offloaded CSA
|
||||
* @tx: the tx commands associated with the beacon frame
|
||||
* @data: see &iwl_mac_beacon_cmd_data
|
||||
*/
|
||||
struct iwl_mac_beacon_cmd_v7 {
|
||||
struct iwl_tx_cmd tx;
|
||||
struct iwl_mac_beacon_cmd_data data;
|
||||
} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_7 */
|
||||
|
||||
/**
|
||||
* struct iwl_mac_beacon_cmd - beacon template command with offloaded CSA
|
||||
* @byte_cnt: byte count of the beacon frame
|
||||
* @flags: for future use
|
||||
* @data: see &iwl_mac_beacon_cmd_data
|
||||
*/
|
||||
struct iwl_mac_beacon_cmd {
|
||||
__le16 byte_cnt;
|
||||
__le16 flags;
|
||||
__le64 reserved;
|
||||
struct iwl_mac_beacon_cmd_data data;
|
||||
} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_8 */
|
||||
|
||||
struct iwl_beacon_notif {
|
||||
struct iwl_mvm_tx_resp beacon_notify_hdr;
|
||||
__le64 tsf;
|
||||
|
@ -341,6 +341,10 @@ enum iwl_prot_offload_subcmd_ids {
|
||||
STORED_BEACON_NTF = 0xFF,
|
||||
};
|
||||
|
||||
enum iwl_regulatory_and_nvm_subcmd_ids {
|
||||
NVM_ACCESS_COMPLETE = 0x0,
|
||||
};
|
||||
|
||||
enum iwl_fmac_debug_cmds {
|
||||
LMAC_RD_WR = 0x0,
|
||||
UMAC_RD_WR = 0x1,
|
||||
@ -355,6 +359,7 @@ enum {
|
||||
PHY_OPS_GROUP = 0x4,
|
||||
DATA_PATH_GROUP = 0x5,
|
||||
PROT_OFFLOAD_GROUP = 0xb,
|
||||
REGULATORY_AND_NVM_GROUP = 0xc,
|
||||
DEBUG_GROUP = 0xf,
|
||||
};
|
||||
|
||||
@ -593,60 +598,7 @@ enum {
|
||||
|
||||
#define IWL_ALIVE_FLG_RFKILL BIT(0)
|
||||
|
||||
struct mvm_alive_resp_ver1 {
|
||||
__le16 status;
|
||||
__le16 flags;
|
||||
u8 ucode_minor;
|
||||
u8 ucode_major;
|
||||
__le16 id;
|
||||
u8 api_minor;
|
||||
u8 api_major;
|
||||
u8 ver_subtype;
|
||||
u8 ver_type;
|
||||
u8 mac;
|
||||
u8 opt;
|
||||
__le16 reserved2;
|
||||
__le32 timestamp;
|
||||
__le32 error_event_table_ptr; /* SRAM address for error log */
|
||||
__le32 log_event_table_ptr; /* SRAM address for event log */
|
||||
__le32 cpu_register_ptr;
|
||||
__le32 dbgm_config_ptr;
|
||||
__le32 alive_counter_ptr;
|
||||
__le32 scd_base_ptr; /* SRAM address for SCD */
|
||||
} __packed; /* ALIVE_RES_API_S_VER_1 */
|
||||
|
||||
struct mvm_alive_resp_ver2 {
|
||||
__le16 status;
|
||||
__le16 flags;
|
||||
u8 ucode_minor;
|
||||
u8 ucode_major;
|
||||
__le16 id;
|
||||
u8 api_minor;
|
||||
u8 api_major;
|
||||
u8 ver_subtype;
|
||||
u8 ver_type;
|
||||
u8 mac;
|
||||
u8 opt;
|
||||
__le16 reserved2;
|
||||
__le32 timestamp;
|
||||
__le32 error_event_table_ptr; /* SRAM address for error log */
|
||||
__le32 log_event_table_ptr; /* SRAM address for LMAC event log */
|
||||
__le32 cpu_register_ptr;
|
||||
__le32 dbgm_config_ptr;
|
||||
__le32 alive_counter_ptr;
|
||||
__le32 scd_base_ptr; /* SRAM address for SCD */
|
||||
__le32 st_fwrd_addr; /* pointer to Store and forward */
|
||||
__le32 st_fwrd_size;
|
||||
u8 umac_minor; /* UMAC version: minor */
|
||||
u8 umac_major; /* UMAC version: major */
|
||||
__le16 umac_id; /* UMAC version: id */
|
||||
__le32 error_info_addr; /* SRAM address for UMAC error log */
|
||||
__le32 dbg_print_buff_addr;
|
||||
} __packed; /* ALIVE_RES_API_S_VER_2 */
|
||||
|
||||
struct mvm_alive_resp {
|
||||
__le16 status;
|
||||
__le16 flags;
|
||||
struct iwl_lmac_alive {
|
||||
__le32 ucode_minor;
|
||||
__le32 ucode_major;
|
||||
u8 ver_subtype;
|
||||
@ -662,12 +614,29 @@ struct mvm_alive_resp {
|
||||
__le32 scd_base_ptr; /* SRAM address for SCD */
|
||||
__le32 st_fwrd_addr; /* pointer to Store and forward */
|
||||
__le32 st_fwrd_size;
|
||||
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */
|
||||
|
||||
struct iwl_umac_alive {
|
||||
__le32 umac_minor; /* UMAC version: minor */
|
||||
__le32 umac_major; /* UMAC version: major */
|
||||
__le32 error_info_addr; /* SRAM address for UMAC error log */
|
||||
__le32 dbg_print_buff_addr;
|
||||
} __packed; /* UMAC_ALIVE_DATA_API_S_VER_2 */
|
||||
|
||||
struct mvm_alive_resp_v3 {
|
||||
__le16 status;
|
||||
__le16 flags;
|
||||
struct iwl_lmac_alive lmac_data;
|
||||
struct iwl_umac_alive umac_data;
|
||||
} __packed; /* ALIVE_RES_API_S_VER_3 */
|
||||
|
||||
struct mvm_alive_resp {
|
||||
__le16 status;
|
||||
__le16 flags;
|
||||
struct iwl_lmac_alive lmac_data[2];
|
||||
struct iwl_umac_alive umac_data;
|
||||
} __packed; /* ALIVE_RES_API_S_VER_4 */
|
||||
|
||||
/* Error response/notification */
|
||||
enum {
|
||||
FW_ERR_UNKNOWN_CMD = 0x0,
|
||||
@ -708,7 +677,6 @@ struct iwl_error_resp {
|
||||
#define MAX_MACS_IN_BINDING (3)
|
||||
#define MAX_BINDINGS (4)
|
||||
#define AUX_BINDING_INDEX (3)
|
||||
#define MAX_PHYS (4)
|
||||
|
||||
/* Used to extract ID and color from the context dword */
|
||||
#define FW_CTXT_ID_POS (0)
|
||||
@ -1251,13 +1219,16 @@ struct iwl_missed_beacons_notif {
|
||||
* @external_ver: external image version
|
||||
* @status: MFUART loading status
|
||||
* @duration: MFUART loading time
|
||||
* @image_size: MFUART image size in bytes
|
||||
*/
|
||||
struct iwl_mfuart_load_notif {
|
||||
__le32 installed_ver;
|
||||
__le32 external_ver;
|
||||
__le32 status;
|
||||
__le32 duration;
|
||||
} __packed; /*MFU_LOADER_NTFY_API_S_VER_1*/
|
||||
/* image size valid only in v2 of the command */
|
||||
__le32 image_size;
|
||||
} __packed; /*MFU_LOADER_NTFY_API_S_VER_2*/
|
||||
|
||||
/**
|
||||
* struct iwl_set_calib_default_cmd - set default value for calibration.
|
||||
@ -2200,4 +2171,11 @@ struct iwl_dbg_mem_access_rsp {
|
||||
__le32 data[];
|
||||
} __packed; /* DEBUG_(U|L)MAC_RD_WR_RSP_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_nvm_access_complete_cmd - NVM_ACCESS commands are completed
|
||||
*/
|
||||
struct iwl_nvm_access_complete_cmd {
|
||||
__le32 reserved;
|
||||
} __packed; /* NVM_ACCESS_COMPLETE_CMD_API_S_VER_1 */
|
||||
|
||||
#endif /* __fw_api_h__ */
|
||||
|
@ -811,12 +811,16 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
|
||||
struct iwl_fw_error_dump_paging *paging;
|
||||
struct page *pages =
|
||||
mvm->fw_paging_db[i].fw_paging_block;
|
||||
dma_addr_t addr = mvm->fw_paging_db[i].fw_paging_phys;
|
||||
|
||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
|
||||
dump_data->len = cpu_to_le32(sizeof(*paging) +
|
||||
PAGING_BLOCK_SIZE);
|
||||
paging = (void *)dump_data->data;
|
||||
paging->index = cpu_to_le32(i);
|
||||
dma_sync_single_for_cpu(mvm->trans->dev, addr,
|
||||
PAGING_BLOCK_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
memcpy(paging->data, page_address(pages),
|
||||
PAGING_BLOCK_SIZE);
|
||||
dump_data = iwl_fw_error_next_data(dump_data);
|
||||
|
@ -214,6 +214,10 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image)
|
||||
memcpy(page_address(mvm->fw_paging_db[0].fw_paging_block),
|
||||
image->sec[sec_idx].data,
|
||||
mvm->fw_paging_db[0].fw_paging_size);
|
||||
dma_sync_single_for_device(mvm->trans->dev,
|
||||
mvm->fw_paging_db[0].fw_paging_phys,
|
||||
mvm->fw_paging_db[0].fw_paging_size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
IWL_DEBUG_FW(mvm,
|
||||
"Paging: copied %d CSS bytes to first block\n",
|
||||
@ -228,9 +232,16 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image)
|
||||
* loop stop at num_of_paging_blk since that last block is not full.
|
||||
*/
|
||||
for (idx = 1; idx < mvm->num_of_paging_blk; idx++) {
|
||||
memcpy(page_address(mvm->fw_paging_db[idx].fw_paging_block),
|
||||
struct iwl_fw_paging *block = &mvm->fw_paging_db[idx];
|
||||
|
||||
memcpy(page_address(block->fw_paging_block),
|
||||
image->sec[sec_idx].data + offset,
|
||||
mvm->fw_paging_db[idx].fw_paging_size);
|
||||
block->fw_paging_size);
|
||||
dma_sync_single_for_device(mvm->trans->dev,
|
||||
block->fw_paging_phys,
|
||||
block->fw_paging_size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
|
||||
IWL_DEBUG_FW(mvm,
|
||||
"Paging: copied %d paging bytes to block %d\n",
|
||||
@ -242,9 +253,15 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image)
|
||||
|
||||
/* copy the last paging block */
|
||||
if (mvm->num_of_pages_in_last_blk > 0) {
|
||||
memcpy(page_address(mvm->fw_paging_db[idx].fw_paging_block),
|
||||
struct iwl_fw_paging *block = &mvm->fw_paging_db[idx];
|
||||
|
||||
memcpy(page_address(block->fw_paging_block),
|
||||
image->sec[sec_idx].data + offset,
|
||||
FW_PAGING_SIZE * mvm->num_of_pages_in_last_blk);
|
||||
dma_sync_single_for_device(mvm->trans->dev,
|
||||
block->fw_paging_phys,
|
||||
block->fw_paging_size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
IWL_DEBUG_FW(mvm,
|
||||
"Paging: copied %d pages in the last block %d\n",
|
||||
@ -444,81 +461,61 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_mvm *mvm =
|
||||
container_of(notif_wait, struct iwl_mvm, notif_wait);
|
||||
struct iwl_mvm_alive_data *alive_data = data;
|
||||
struct mvm_alive_resp_ver1 *palive1;
|
||||
struct mvm_alive_resp_ver2 *palive2;
|
||||
struct mvm_alive_resp_v3 *palive3;
|
||||
struct mvm_alive_resp *palive;
|
||||
struct iwl_umac_alive *umac;
|
||||
struct iwl_lmac_alive *lmac1;
|
||||
struct iwl_lmac_alive *lmac2 = NULL;
|
||||
u16 status;
|
||||
|
||||
if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive1)) {
|
||||
palive1 = (void *)pkt->data;
|
||||
|
||||
mvm->support_umac_log = false;
|
||||
mvm->error_event_table =
|
||||
le32_to_cpu(palive1->error_event_table_ptr);
|
||||
mvm->log_event_table =
|
||||
le32_to_cpu(palive1->log_event_table_ptr);
|
||||
alive_data->scd_base_addr = le32_to_cpu(palive1->scd_base_ptr);
|
||||
|
||||
alive_data->valid = le16_to_cpu(palive1->status) ==
|
||||
IWL_ALIVE_STATUS_OK;
|
||||
IWL_DEBUG_FW(mvm,
|
||||
"Alive VER1 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
|
||||
le16_to_cpu(palive1->status), palive1->ver_type,
|
||||
palive1->ver_subtype, palive1->flags);
|
||||
} else if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive2)) {
|
||||
palive2 = (void *)pkt->data;
|
||||
|
||||
mvm->error_event_table =
|
||||
le32_to_cpu(palive2->error_event_table_ptr);
|
||||
mvm->log_event_table =
|
||||
le32_to_cpu(palive2->log_event_table_ptr);
|
||||
alive_data->scd_base_addr = le32_to_cpu(palive2->scd_base_ptr);
|
||||
mvm->umac_error_event_table =
|
||||
le32_to_cpu(palive2->error_info_addr);
|
||||
mvm->sf_space.addr = le32_to_cpu(palive2->st_fwrd_addr);
|
||||
mvm->sf_space.size = le32_to_cpu(palive2->st_fwrd_size);
|
||||
|
||||
alive_data->valid = le16_to_cpu(palive2->status) ==
|
||||
IWL_ALIVE_STATUS_OK;
|
||||
if (mvm->umac_error_event_table)
|
||||
mvm->support_umac_log = true;
|
||||
|
||||
IWL_DEBUG_FW(mvm,
|
||||
"Alive VER2 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
|
||||
le16_to_cpu(palive2->status), palive2->ver_type,
|
||||
palive2->ver_subtype, palive2->flags);
|
||||
|
||||
IWL_DEBUG_FW(mvm,
|
||||
"UMAC version: Major - 0x%x, Minor - 0x%x\n",
|
||||
palive2->umac_major, palive2->umac_minor);
|
||||
} else if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) {
|
||||
if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) {
|
||||
palive = (void *)pkt->data;
|
||||
|
||||
mvm->error_event_table =
|
||||
le32_to_cpu(palive->error_event_table_ptr);
|
||||
mvm->log_event_table =
|
||||
le32_to_cpu(palive->log_event_table_ptr);
|
||||
alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr);
|
||||
mvm->umac_error_event_table =
|
||||
le32_to_cpu(palive->error_info_addr);
|
||||
mvm->sf_space.addr = le32_to_cpu(palive->st_fwrd_addr);
|
||||
mvm->sf_space.size = le32_to_cpu(palive->st_fwrd_size);
|
||||
|
||||
alive_data->valid = le16_to_cpu(palive->status) ==
|
||||
IWL_ALIVE_STATUS_OK;
|
||||
if (mvm->umac_error_event_table)
|
||||
mvm->support_umac_log = true;
|
||||
|
||||
IWL_DEBUG_FW(mvm,
|
||||
"Alive VER3 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
|
||||
le16_to_cpu(palive->status), palive->ver_type,
|
||||
palive->ver_subtype, palive->flags);
|
||||
|
||||
IWL_DEBUG_FW(mvm,
|
||||
"UMAC version: Major - 0x%x, Minor - 0x%x\n",
|
||||
le32_to_cpu(palive->umac_major),
|
||||
le32_to_cpu(palive->umac_minor));
|
||||
umac = &palive->umac_data;
|
||||
lmac1 = &palive->lmac_data[0];
|
||||
lmac2 = &palive->lmac_data[1];
|
||||
status = le16_to_cpu(palive->status);
|
||||
} else {
|
||||
palive3 = (void *)pkt->data;
|
||||
umac = &palive3->umac_data;
|
||||
lmac1 = &palive3->lmac_data;
|
||||
status = le16_to_cpu(palive3->status);
|
||||
}
|
||||
|
||||
mvm->error_event_table[0] = le32_to_cpu(lmac1->error_event_table_ptr);
|
||||
if (lmac2)
|
||||
mvm->error_event_table[1] =
|
||||
le32_to_cpu(lmac2->error_event_table_ptr);
|
||||
mvm->log_event_table = le32_to_cpu(lmac1->log_event_table_ptr);
|
||||
mvm->sf_space.addr = le32_to_cpu(lmac1->st_fwrd_addr);
|
||||
mvm->sf_space.size = le32_to_cpu(lmac1->st_fwrd_size);
|
||||
|
||||
mvm->umac_error_event_table = le32_to_cpu(umac->error_info_addr);
|
||||
|
||||
alive_data->scd_base_addr = le32_to_cpu(lmac1->scd_base_ptr);
|
||||
alive_data->valid = status == IWL_ALIVE_STATUS_OK;
|
||||
if (mvm->umac_error_event_table)
|
||||
mvm->support_umac_log = true;
|
||||
|
||||
IWL_DEBUG_FW(mvm,
|
||||
"Alive ucode status 0x%04x revision 0x%01X 0x%01X\n",
|
||||
status, lmac1->ver_type, lmac1->ver_subtype);
|
||||
|
||||
if (lmac2)
|
||||
IWL_DEBUG_FW(mvm, "Alive ucode CDB\n");
|
||||
|
||||
IWL_DEBUG_FW(mvm,
|
||||
"UMAC version: Major - 0x%x, Minor - 0x%x\n",
|
||||
le32_to_cpu(umac->umac_major),
|
||||
le32_to_cpu(umac->umac_minor));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool iwl_wait_init_complete(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt, void *data)
|
||||
{
|
||||
WARN_ON(pkt->hdr.cmd != INIT_COMPLETE_NOTIF);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -537,6 +534,48 @@ static bool iwl_wait_phy_db_entry(struct iwl_notif_wait_data *notif_wait,
|
||||
return false;
|
||||
}
|
||||
|
||||
static int iwl_mvm_init_paging(struct iwl_mvm *mvm)
|
||||
{
|
||||
const struct fw_img *fw = &mvm->fw->img[mvm->cur_ucode];
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Configure and operate fw paging mechanism.
|
||||
* The driver configures the paging flow only once.
|
||||
* The CPU2 paging image is included in the IWL_UCODE_INIT image.
|
||||
*/
|
||||
if (!fw->paging_mem_size)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* When dma is not enabled, the driver needs to copy / write
|
||||
* the downloaded / uploaded page to / from the smem.
|
||||
* This gets the location of the place were the pages are
|
||||
* stored.
|
||||
*/
|
||||
if (!is_device_dma_capable(mvm->trans->dev)) {
|
||||
ret = iwl_trans_get_paging_item(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "failed to get FW paging item\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = iwl_save_fw_paging(mvm, fw);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "failed to save the FW paging image\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iwl_send_paging_cmd(mvm, fw);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "failed to send the paging cmd\n");
|
||||
iwl_free_fw_paging(mvm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
||||
enum iwl_ucode_type ucode_type)
|
||||
{
|
||||
@ -607,40 +646,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
||||
|
||||
iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
|
||||
|
||||
/*
|
||||
* configure and operate fw paging mechanism.
|
||||
* driver configures the paging flow only once, CPU2 paging image
|
||||
* included in the IWL_UCODE_INIT image.
|
||||
*/
|
||||
if (fw->paging_mem_size) {
|
||||
/*
|
||||
* When dma is not enabled, the driver needs to copy / write
|
||||
* the downloaded / uploaded page to / from the smem.
|
||||
* This gets the location of the place were the pages are
|
||||
* stored.
|
||||
*/
|
||||
if (!is_device_dma_capable(mvm->trans->dev)) {
|
||||
ret = iwl_trans_get_paging_item(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "failed to get FW paging item\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = iwl_save_fw_paging(mvm, fw);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "failed to save the FW paging image\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iwl_send_paging_cmd(mvm, fw);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "failed to send the paging cmd\n");
|
||||
iwl_free_fw_paging(mvm);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: all the queues are enabled as part of the interface
|
||||
* initialization, but in firmware restart scenarios they
|
||||
@ -798,6 +803,75 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
||||
{
|
||||
struct iwl_notification_wait init_wait;
|
||||
struct iwl_nvm_access_complete_cmd nvm_complete = {};
|
||||
static const u16 init_complete[] = {
|
||||
INIT_COMPLETE_NOTIF,
|
||||
};
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
iwl_init_notification_wait(&mvm->notif_wait,
|
||||
&init_wait,
|
||||
init_complete,
|
||||
ARRAY_SIZE(init_complete),
|
||||
iwl_wait_init_complete,
|
||||
NULL);
|
||||
|
||||
/* Will also start the device */
|
||||
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* TODO: remove when integrating context info */
|
||||
ret = iwl_mvm_init_paging(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to init paging: %d\n",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Read the NVM only at driver load time, no need to do this twice */
|
||||
if (read_nvm) {
|
||||
/* Read nvm */
|
||||
ret = iwl_nvm_init(mvm, true);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* In case we read the NVM from external file, load it to the NIC */
|
||||
if (mvm->nvm_file_name)
|
||||
iwl_mvm_load_nvm_to_nic(mvm);
|
||||
|
||||
ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
|
||||
if (WARN_ON(ret))
|
||||
goto error;
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
NVM_ACCESS_COMPLETE), 0,
|
||||
sizeof(nvm_complete), &nvm_complete);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to run complete NVM access: %d\n",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* We wait for the INIT complete notification */
|
||||
return iwl_wait_notification(&mvm->notif_wait, &init_wait,
|
||||
MVM_UCODE_ALIVE_TIMEOUT);
|
||||
|
||||
error:
|
||||
iwl_remove_notification(&mvm->notif_wait, &init_wait);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_mvm_parse_shared_mem_a000(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
@ -1058,6 +1132,43 @@ static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (iwl_mvm_has_new_tx_api(mvm))
|
||||
return iwl_run_unified_mvm_ucode(mvm, false);
|
||||
|
||||
ret = iwl_run_init_mvm_ucode(mvm, false);
|
||||
|
||||
if (iwlmvm_mod_params.init_dbg)
|
||||
return 0;
|
||||
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret);
|
||||
/* this can't happen */
|
||||
if (WARN_ON(ret > 0))
|
||||
ret = -ERFKILL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop and start the transport without entering low power
|
||||
* mode. This will save the state of other components on the
|
||||
* device that are triggered by the INIT firwmare (MFUART).
|
||||
*/
|
||||
_iwl_trans_stop_device(mvm->trans, false);
|
||||
ret = _iwl_trans_start_hw(mvm->trans, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return iwl_mvm_init_paging(mvm);
|
||||
}
|
||||
|
||||
int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
{
|
||||
int ret, i;
|
||||
@ -1070,35 +1181,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* If we haven't completed the run of the init ucode during
|
||||
* module loading, load init ucode now
|
||||
* (for example, if we were in RFKILL)
|
||||
*/
|
||||
ret = iwl_run_init_mvm_ucode(mvm, false);
|
||||
|
||||
if (iwlmvm_mod_params.init_dbg)
|
||||
return 0;
|
||||
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret);
|
||||
/* this can't happen */
|
||||
if (WARN_ON(ret > 0))
|
||||
ret = -ERFKILL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop and start the transport without entering low power
|
||||
* mode. This will save the state of other components on the
|
||||
* device that are triggered by the INIT firwmare (MFUART).
|
||||
*/
|
||||
_iwl_trans_stop_device(mvm->trans, false);
|
||||
ret = _iwl_trans_start_hw(mvm->trans, false);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
|
||||
ret = iwl_mvm_load_rt_fw(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
|
||||
goto error;
|
||||
@ -1125,13 +1208,15 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
goto error;
|
||||
|
||||
/* Send phy db control command and then phy db calibration*/
|
||||
ret = iwl_send_phy_db_data(mvm->phy_db);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (!iwl_mvm_has_new_tx_api(mvm)) {
|
||||
ret = iwl_send_phy_db_data(mvm->phy_db);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = iwl_send_phy_cfg_cmd(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
ret = iwl_send_phy_cfg_cmd(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Init RSS configuration */
|
||||
if (iwl_mvm_has_new_rx_api(mvm)) {
|
||||
@ -1317,4 +1402,9 @@ void iwl_mvm_rx_mfuart_notif(struct iwl_mvm *mvm,
|
||||
le32_to_cpu(mfuart_notif->external_ver),
|
||||
le32_to_cpu(mfuart_notif->status),
|
||||
le32_to_cpu(mfuart_notif->duration));
|
||||
|
||||
if (iwl_rx_packet_payload_len(pkt) == sizeof(*mfuart_notif))
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"MFUART: image size: 0x%08x\n",
|
||||
le32_to_cpu(mfuart_notif->image_size));
|
||||
}
|
||||
|
@ -531,38 +531,26 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
/*
|
||||
* If DQA is supported - queues were already disabled, since in
|
||||
* DQA-mode the queues are a property of the STA and not of the
|
||||
* vif, and at this point the STA was already deleted
|
||||
*/
|
||||
if (iwl_mvm_is_dqa_supported(mvm))
|
||||
return;
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
if (!iwl_mvm_is_dqa_supported(mvm))
|
||||
iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
|
||||
IWL_MVM_OFFCHANNEL_QUEUE,
|
||||
IWL_MAX_TID_COUNT, 0);
|
||||
else
|
||||
iwl_mvm_disable_txq(mvm,
|
||||
IWL_MVM_DQA_P2P_DEVICE_QUEUE,
|
||||
vif->hw_queue[0], IWL_MAX_TID_COUNT,
|
||||
0);
|
||||
iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
|
||||
IWL_MVM_OFFCHANNEL_QUEUE,
|
||||
IWL_MAX_TID_COUNT, 0);
|
||||
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue,
|
||||
IWL_MAX_TID_COUNT, 0);
|
||||
|
||||
if (iwl_mvm_is_dqa_supported(mvm))
|
||||
iwl_mvm_disable_txq(mvm,
|
||||
IWL_MVM_DQA_AP_PROBE_RESP_QUEUE,
|
||||
vif->hw_queue[0], IWL_MAX_TID_COUNT,
|
||||
0);
|
||||
/* fall through */
|
||||
default:
|
||||
/*
|
||||
* If DQA is supported - queues were already disabled, since in
|
||||
* DQA-mode the queues are a property of the STA and not of the
|
||||
* vif, and at this point the STA was already deleted
|
||||
*/
|
||||
if (iwl_mvm_is_dqa_supported(mvm))
|
||||
break;
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
|
||||
iwl_mvm_disable_txq(mvm, vif->hw_queue[ac],
|
||||
vif->hw_queue[ac],
|
||||
@ -991,7 +979,7 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
|
||||
}
|
||||
|
||||
static void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
|
||||
struct iwl_mac_beacon_cmd_v6 *beacon_cmd,
|
||||
__le32 *tim_index, __le32 *tim_size,
|
||||
u8 *beacon, u32 frame_size)
|
||||
{
|
||||
u32 tim_idx;
|
||||
@ -1008,8 +996,8 @@ static void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
|
||||
|
||||
/* If TIM field was found, set variables */
|
||||
if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
|
||||
beacon_cmd->tim_idx = cpu_to_le32(tim_idx);
|
||||
beacon_cmd->tim_size = cpu_to_le32((u32)beacon[tim_idx+1]);
|
||||
*tim_index = cpu_to_le32(tim_idx);
|
||||
*tim_size = cpu_to_le32((u32)beacon[tim_idx + 1]);
|
||||
} else {
|
||||
IWL_WARN(mvm, "Unable to find TIM Element in beacon\n");
|
||||
}
|
||||
@ -1043,8 +1031,9 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||
};
|
||||
union {
|
||||
struct iwl_mac_beacon_cmd_v6 beacon_cmd_v6;
|
||||
struct iwl_mac_beacon_cmd beacon_cmd;
|
||||
struct iwl_mac_beacon_cmd_v7 beacon_cmd;
|
||||
} u = {};
|
||||
struct iwl_mac_beacon_cmd beacon_cmd;
|
||||
struct ieee80211_tx_info *info;
|
||||
u32 beacon_skb_len;
|
||||
u32 rate, tx_flags;
|
||||
@ -1054,6 +1043,46 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||
|
||||
beacon_skb_len = beacon->len;
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD)) {
|
||||
u32 csa_offset, ecsa_offset;
|
||||
|
||||
csa_offset = iwl_mvm_find_ie_offset(beacon->data,
|
||||
WLAN_EID_CHANNEL_SWITCH,
|
||||
beacon_skb_len);
|
||||
ecsa_offset =
|
||||
iwl_mvm_find_ie_offset(beacon->data,
|
||||
WLAN_EID_EXT_CHANSWITCH_ANN,
|
||||
beacon_skb_len);
|
||||
|
||||
if (iwl_mvm_has_new_tx_api(mvm)) {
|
||||
beacon_cmd.data.template_id =
|
||||
cpu_to_le32((u32)mvmvif->id);
|
||||
beacon_cmd.data.ecsa_offset = cpu_to_le32(ecsa_offset);
|
||||
beacon_cmd.data.csa_offset = cpu_to_le32(csa_offset);
|
||||
beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon_skb_len);
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
iwl_mvm_mac_ctxt_set_tim(mvm,
|
||||
&beacon_cmd.data.tim_idx,
|
||||
&beacon_cmd.data.tim_size,
|
||||
beacon->data,
|
||||
beacon_skb_len);
|
||||
cmd.len[0] = sizeof(beacon_cmd);
|
||||
cmd.data[0] = &beacon_cmd;
|
||||
goto send;
|
||||
|
||||
} else {
|
||||
u.beacon_cmd.data.ecsa_offset =
|
||||
cpu_to_le32(ecsa_offset);
|
||||
u.beacon_cmd.data.csa_offset = cpu_to_le32(csa_offset);
|
||||
cmd.len[0] = sizeof(u.beacon_cmd);
|
||||
cmd.data[0] = &u;
|
||||
}
|
||||
} else {
|
||||
cmd.len[0] = sizeof(u.beacon_cmd_v6);
|
||||
cmd.data[0] = &u;
|
||||
}
|
||||
|
||||
/* TODO: for now the beacon template id is set to be the mac context id.
|
||||
* Might be better to handle it as another resource ... */
|
||||
u.beacon_cmd_v6.template_id = cpu_to_le32((u32)mvmvif->id);
|
||||
@ -1092,29 +1121,13 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
||||
|
||||
/* Set up TX beacon command fields */
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
iwl_mvm_mac_ctxt_set_tim(mvm, &u.beacon_cmd_v6,
|
||||
iwl_mvm_mac_ctxt_set_tim(mvm, &u.beacon_cmd_v6.tim_idx,
|
||||
&u.beacon_cmd_v6.tim_size,
|
||||
beacon->data,
|
||||
beacon_skb_len);
|
||||
|
||||
send:
|
||||
/* Submit command */
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD)) {
|
||||
u.beacon_cmd.csa_offset =
|
||||
cpu_to_le32(iwl_mvm_find_ie_offset(beacon->data,
|
||||
WLAN_EID_CHANNEL_SWITCH,
|
||||
beacon_skb_len));
|
||||
u.beacon_cmd.ecsa_offset =
|
||||
cpu_to_le32(iwl_mvm_find_ie_offset(beacon->data,
|
||||
WLAN_EID_EXT_CHANSWITCH_ANN,
|
||||
beacon_skb_len));
|
||||
|
||||
cmd.len[0] = sizeof(u.beacon_cmd);
|
||||
} else {
|
||||
cmd.len[0] = sizeof(u.beacon_cmd_v6);
|
||||
}
|
||||
|
||||
cmd.data[0] = &u;
|
||||
cmd.dataflags[0] = 0;
|
||||
cmd.len[1] = beacon_skb_len;
|
||||
cmd.data[1] = beacon->data;
|
||||
|
@ -1210,8 +1210,6 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
|
||||
/* the fw is stopped, the aux sta is dead: clean up driver state */
|
||||
iwl_mvm_del_aux_sta(mvm);
|
||||
|
||||
iwl_free_fw_paging(mvm);
|
||||
|
||||
/*
|
||||
* Clear IN_HW_RESTART flag when stopping the hw (as restart_complete()
|
||||
* won't be called in this case).
|
||||
@ -2010,16 +2008,16 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_UMAC_SCAN))
|
||||
iwl_mvm_config_scan(mvm);
|
||||
} else if (changes & BSS_CHANGED_BEACON_INFO) {
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON_INFO) {
|
||||
/*
|
||||
* We received a beacon _after_ association so
|
||||
* We received a beacon from the associated AP so
|
||||
* remove the session protection.
|
||||
*/
|
||||
iwl_mvm_remove_time_event(mvm, mvmvif,
|
||||
&mvmvif->time_event_data);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON_INFO) {
|
||||
iwl_mvm_sf_update(mvm, vif, false);
|
||||
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
|
||||
}
|
||||
@ -2106,22 +2104,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
|
||||
if (ret)
|
||||
goto out_unbind;
|
||||
|
||||
/* enable the multicast queue, now that we have a station for it */
|
||||
if (iwl_mvm_is_dqa_supported(mvm)) {
|
||||
unsigned int wdg_timeout =
|
||||
iwl_mvm_get_wd_timeout(mvm, vif, false, false);
|
||||
struct iwl_trans_txq_scd_cfg cfg = {
|
||||
.fifo = IWL_MVM_TX_FIFO_MCAST,
|
||||
.sta_id = mvmvif->bcast_sta.sta_id,
|
||||
.tid = IWL_MAX_TID_COUNT,
|
||||
.aggregate = false,
|
||||
.frame_limit = IWL_FRAME_LIMIT,
|
||||
};
|
||||
|
||||
iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
|
||||
&cfg, wdg_timeout);
|
||||
}
|
||||
|
||||
/* must be set before quota calculations */
|
||||
mvmvif->ap_ibss_active = true;
|
||||
|
||||
@ -2554,6 +2536,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||
int ret;
|
||||
|
||||
IWL_DEBUG_MAC80211(mvm, "station %pM state change %d->%d\n",
|
||||
@ -2582,8 +2565,6 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||
if (old_state == IEEE80211_STA_NONE &&
|
||||
new_state == IEEE80211_STA_NOTEXIST &&
|
||||
iwl_mvm_is_dqa_supported(mvm)) {
|
||||
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
iwl_mvm_purge_deferred_tx_frames(mvm, mvm_sta);
|
||||
flush_work(&mvm->add_stream_wk);
|
||||
|
||||
@ -2594,6 +2575,9 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
/* track whether or not the station is associated */
|
||||
mvm_sta->associated = new_state >= IEEE80211_STA_ASSOC;
|
||||
|
||||
if (old_state == IEEE80211_STA_NOTEXIST &&
|
||||
new_state == IEEE80211_STA_NONE) {
|
||||
/*
|
||||
@ -2643,11 +2627,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||
mvmvif->ap_assoc_sta_count++;
|
||||
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
|
||||
}
|
||||
|
||||
iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
|
||||
true);
|
||||
ret = iwl_mvm_update_sta(mvm, vif, sta);
|
||||
if (ret == 0)
|
||||
iwl_mvm_rs_rate_init(mvm, sta,
|
||||
mvmvif->phy_ctxt->channel->band,
|
||||
true);
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTHORIZED) {
|
||||
|
||||
|
@ -739,8 +739,9 @@ struct iwl_mvm {
|
||||
|
||||
enum iwl_ucode_type cur_ucode;
|
||||
bool ucode_loaded;
|
||||
bool hw_registered;
|
||||
bool calibrating;
|
||||
u32 error_event_table;
|
||||
u32 error_event_table[2];
|
||||
u32 log_event_table;
|
||||
u32 umac_error_event_table;
|
||||
bool support_umac_log;
|
||||
@ -1217,6 +1218,19 @@ static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm)
|
||||
return mvm->trans->cfg->use_tfh;
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_is_cdb_supported(struct iwl_mvm *mvm)
|
||||
{
|
||||
/*
|
||||
* TODO:
|
||||
* The issue of how to determine CDB support is still not well defined.
|
||||
* It may be that it will be for all next HW devices and it may be per
|
||||
* FW compilation and it may also differ between different devices.
|
||||
* For now take a ride on the new TX API and get back to it when
|
||||
* it is well defined.
|
||||
*/
|
||||
return iwl_mvm_has_new_tx_api(mvm);
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_is_tt_in_fw(struct iwl_mvm *mvm)
|
||||
{
|
||||
#ifdef CONFIG_THERMAL
|
||||
@ -1257,6 +1271,7 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm);
|
||||
******************/
|
||||
/* uCode */
|
||||
int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm);
|
||||
int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm);
|
||||
|
||||
/* Utils */
|
||||
int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
|
||||
@ -1686,6 +1701,7 @@ void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
|
||||
|
||||
static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
|
||||
{
|
||||
iwl_free_fw_paging(mvm);
|
||||
mvm->ucode_loaded = false;
|
||||
iwl_trans_stop_device(mvm->trans);
|
||||
}
|
||||
|
@ -466,6 +466,13 @@ static const struct iwl_hcmd_names iwl_mvm_prot_offload_names[] = {
|
||||
HCMD_NAME(STORED_BEACON_NTF),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
* Access is done through binary search
|
||||
*/
|
||||
static const struct iwl_hcmd_names iwl_mvm_regulatory_and_nvm_names[] = {
|
||||
HCMD_NAME(NVM_ACCESS_COMPLETE),
|
||||
};
|
||||
|
||||
static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
|
||||
[LEGACY_GROUP] = HCMD_ARR(iwl_mvm_legacy_names),
|
||||
[LONG_GROUP] = HCMD_ARR(iwl_mvm_legacy_names),
|
||||
@ -474,6 +481,8 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
|
||||
[PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names),
|
||||
[DATA_PATH_GROUP] = HCMD_ARR(iwl_mvm_data_path_names),
|
||||
[PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names),
|
||||
[REGULATORY_AND_NVM_GROUP] =
|
||||
HCMD_ARR(iwl_mvm_regulatory_and_nvm_names),
|
||||
};
|
||||
|
||||
/* this forward declaration can avoid to export the function */
|
||||
@ -597,7 +606,10 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
mvm->last_agg_queue = IWL_MVM_DQA_MAX_DATA_QUEUE;
|
||||
}
|
||||
mvm->sf_state = SF_UNINIT;
|
||||
mvm->cur_ucode = IWL_UCODE_INIT;
|
||||
if (iwl_mvm_has_new_tx_api(mvm))
|
||||
mvm->cur_ucode = IWL_UCODE_REGULAR;
|
||||
else
|
||||
mvm->cur_ucode = IWL_UCODE_INIT;
|
||||
mvm->drop_bcn_ap_mode = true;
|
||||
|
||||
mutex_init(&mvm->mutex);
|
||||
@ -720,7 +732,10 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE);
|
||||
err = iwl_run_init_mvm_ucode(mvm, true);
|
||||
if (iwl_mvm_has_new_tx_api(mvm))
|
||||
err = iwl_run_unified_mvm_ucode(mvm, true);
|
||||
else
|
||||
err = iwl_run_init_mvm_ucode(mvm, true);
|
||||
if (!err || !iwlmvm_mod_params.init_dbg)
|
||||
iwl_mvm_stop_device(mvm);
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE);
|
||||
@ -743,6 +758,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
err = iwl_mvm_mac_setup_register(mvm);
|
||||
if (err)
|
||||
goto out_free;
|
||||
mvm->hw_registered = true;
|
||||
|
||||
min_backoff = calc_min_backoff(trans, cfg);
|
||||
iwl_mvm_thermal_initialize(mvm, min_backoff);
|
||||
@ -764,6 +780,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
|
||||
out_unregister:
|
||||
ieee80211_unregister_hw(mvm->hw);
|
||||
mvm->hw_registered = false;
|
||||
iwl_mvm_leds_exit(mvm);
|
||||
iwl_mvm_thermal_exit(mvm);
|
||||
out_free:
|
||||
@ -1192,7 +1209,8 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
|
||||
reprobe->dev = mvm->trans->dev;
|
||||
INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk);
|
||||
schedule_work(&reprobe->work);
|
||||
} else if (mvm->cur_ucode == IWL_UCODE_REGULAR) {
|
||||
} else if (mvm->cur_ucode == IWL_UCODE_REGULAR &&
|
||||
mvm->hw_registered) {
|
||||
/* don't let the transport/FW power down */
|
||||
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
|
||||
|
||||
|
@ -174,6 +174,14 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
|
||||
enum ieee80211_ac_numbers ac;
|
||||
bool tid_found = false;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
/* set advanced pm flag with no uapsd ACs to enable ps-poll */
|
||||
if (mvmvif->dbgfs_pm.use_ps_poll) {
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) {
|
||||
if (!mvmvif->queue_params[ac].uapsd)
|
||||
continue;
|
||||
@ -204,16 +212,6 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
/* set advanced pm flag with no uapsd ACs to enable ps-poll */
|
||||
if (mvmvif->dbgfs_pm.use_ps_poll)
|
||||
cmd->flags |=
|
||||
cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK);
|
||||
|
||||
if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) |
|
||||
@ -601,9 +599,8 @@ static void iwl_mvm_power_ps_disabled_iterator(void *_data, u8* mac,
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
bool *disable_ps = _data;
|
||||
|
||||
if (mvmvif->phy_ctxt)
|
||||
if (mvmvif->phy_ctxt->id < MAX_PHYS)
|
||||
*disable_ps |= mvmvif->ps_disabled;
|
||||
if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX)
|
||||
*disable_ps |= mvmvif->ps_disabled;
|
||||
}
|
||||
|
||||
static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
|
||||
@ -611,6 +608,7 @@ static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_power_vifs *power_iterator = _data;
|
||||
bool active = mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX;
|
||||
|
||||
switch (ieee80211_vif_type_p2p(vif)) {
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
@ -621,34 +619,30 @@ static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
|
||||
/* only a single MAC of the same type */
|
||||
WARN_ON(power_iterator->ap_vif);
|
||||
power_iterator->ap_vif = vif;
|
||||
if (mvmvif->phy_ctxt)
|
||||
if (mvmvif->phy_ctxt->id < MAX_PHYS)
|
||||
power_iterator->ap_active = true;
|
||||
if (active)
|
||||
power_iterator->ap_active = true;
|
||||
break;
|
||||
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
/* only a single MAC of the same type */
|
||||
WARN_ON(power_iterator->monitor_vif);
|
||||
power_iterator->monitor_vif = vif;
|
||||
if (mvmvif->phy_ctxt)
|
||||
if (mvmvif->phy_ctxt->id < MAX_PHYS)
|
||||
power_iterator->monitor_active = true;
|
||||
if (active)
|
||||
power_iterator->monitor_active = true;
|
||||
break;
|
||||
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
/* only a single MAC of the same type */
|
||||
WARN_ON(power_iterator->p2p_vif);
|
||||
power_iterator->p2p_vif = vif;
|
||||
if (mvmvif->phy_ctxt)
|
||||
if (mvmvif->phy_ctxt->id < MAX_PHYS)
|
||||
power_iterator->p2p_active = true;
|
||||
if (active)
|
||||
power_iterator->p2p_active = true;
|
||||
break;
|
||||
|
||||
case NL80211_IFTYPE_STATION:
|
||||
power_iterator->bss_vif = vif;
|
||||
if (mvmvif->phy_ctxt)
|
||||
if (mvmvif->phy_ctxt->id < MAX_PHYS)
|
||||
power_iterator->bss_active = true;
|
||||
if (active)
|
||||
power_iterator->bss_active = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -972,7 +972,9 @@ static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask,
|
||||
|
||||
/* Find the previous rate that is in the rate mask */
|
||||
i = index - 1;
|
||||
for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
|
||||
if (i >= 0)
|
||||
mask = BIT(i);
|
||||
for (; i >= 0; i--, mask >>= 1) {
|
||||
if (rate_mask & mask) {
|
||||
low = i;
|
||||
break;
|
||||
@ -3616,6 +3618,8 @@ int rs_pretty_print_rate(char *buf, const u32 rate)
|
||||
} else if (rate & RATE_MCS_HT_MSK) {
|
||||
type = "HT";
|
||||
mcs = rate & RATE_HT_MCS_INDEX_MSK;
|
||||
nss = ((rate & RATE_HT_MCS_NSS_MSK)
|
||||
>> RATE_HT_MCS_NSS_POS) + 1;
|
||||
} else {
|
||||
type = "Unknown"; /* shouldn't happen */
|
||||
}
|
||||
|
@ -497,8 +497,7 @@ struct iwl_mvm_stat_data {
|
||||
struct iwl_mvm *mvm;
|
||||
__le32 mac_id;
|
||||
u8 beacon_filter_average_energy;
|
||||
struct mvm_statistics_general_v8 *general;
|
||||
struct mvm_statistics_load *load;
|
||||
void *general;
|
||||
};
|
||||
|
||||
static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
|
||||
@ -518,10 +517,26 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
|
||||
* the notification directly.
|
||||
*/
|
||||
if (data->general) {
|
||||
mvmvif->beacon_stats.num_beacons =
|
||||
le32_to_cpu(data->general->beacon_counter[mvmvif->id]);
|
||||
mvmvif->beacon_stats.avg_signal =
|
||||
-data->general->beacon_average_energy[mvmvif->id];
|
||||
u16 vif_id = mvmvif->id;
|
||||
|
||||
if (iwl_mvm_is_cdb_supported(mvm)) {
|
||||
struct mvm_statistics_general_cdb *general =
|
||||
data->general;
|
||||
|
||||
mvmvif->beacon_stats.num_beacons =
|
||||
le32_to_cpu(general->beacon_counter[vif_id]);
|
||||
mvmvif->beacon_stats.avg_signal =
|
||||
-general->beacon_average_energy[vif_id];
|
||||
} else {
|
||||
struct mvm_statistics_general_v8 *general =
|
||||
data->general;
|
||||
|
||||
mvmvif->beacon_stats.num_beacons =
|
||||
le32_to_cpu(general->beacon_counter[vif_id]);
|
||||
mvmvif->beacon_stats.avg_signal =
|
||||
-general->beacon_average_energy[vif_id];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (mvmvif->id != id)
|
||||
@ -615,46 +630,65 @@ iwl_mvm_rx_stats_check_trigger(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt)
|
||||
void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
struct iwl_notif_statistics_v11 *stats = (void *)&pkt->data;
|
||||
struct iwl_notif_statistics_cdb *stats = (void *)&pkt->data;
|
||||
struct iwl_mvm_stat_data data = {
|
||||
.mvm = mvm,
|
||||
};
|
||||
int expected_size = iwl_mvm_has_new_rx_api(mvm) ? sizeof(*stats) :
|
||||
sizeof(struct iwl_notif_statistics_v10);
|
||||
int expected_size;
|
||||
|
||||
if (iwl_mvm_is_cdb_supported(mvm))
|
||||
expected_size = sizeof(*stats);
|
||||
else if (iwl_mvm_has_new_rx_api(mvm))
|
||||
expected_size = sizeof(struct iwl_notif_statistics_v11);
|
||||
else
|
||||
expected_size = sizeof(struct iwl_notif_statistics_v10);
|
||||
|
||||
if (iwl_rx_packet_payload_len(pkt) != expected_size)
|
||||
goto invalid;
|
||||
|
||||
data.mac_id = stats->rx.general.mac_id;
|
||||
data.beacon_filter_average_energy =
|
||||
stats->general.beacon_filter_average_energy;
|
||||
stats->general.common.beacon_filter_average_energy;
|
||||
|
||||
iwl_mvm_update_rx_statistics(mvm, &stats->rx);
|
||||
|
||||
mvm->radio_stats.rx_time = le64_to_cpu(stats->general.rx_time);
|
||||
mvm->radio_stats.tx_time = le64_to_cpu(stats->general.tx_time);
|
||||
mvm->radio_stats.rx_time = le64_to_cpu(stats->general.common.rx_time);
|
||||
mvm->radio_stats.tx_time = le64_to_cpu(stats->general.common.tx_time);
|
||||
mvm->radio_stats.on_time_rf =
|
||||
le64_to_cpu(stats->general.on_time_rf);
|
||||
le64_to_cpu(stats->general.common.on_time_rf);
|
||||
mvm->radio_stats.on_time_scan =
|
||||
le64_to_cpu(stats->general.on_time_scan);
|
||||
le64_to_cpu(stats->general.common.on_time_scan);
|
||||
|
||||
data.general = &stats->general;
|
||||
if (iwl_mvm_has_new_rx_api(mvm)) {
|
||||
int i;
|
||||
u8 *energy;
|
||||
__le32 *bytes, *air_time;
|
||||
|
||||
data.load = &stats->load_stats;
|
||||
if (!iwl_mvm_is_cdb_supported(mvm)) {
|
||||
struct iwl_notif_statistics_v11 *v11 =
|
||||
(void *)&pkt->data;
|
||||
|
||||
energy = (void *)&v11->load_stats.avg_energy;
|
||||
bytes = (void *)&v11->load_stats.byte_count;
|
||||
air_time = (void *)&v11->load_stats.air_time;
|
||||
} else {
|
||||
energy = (void *)&stats->load_stats.avg_energy;
|
||||
bytes = (void *)&stats->load_stats.byte_count;
|
||||
air_time = (void *)&stats->load_stats.air_time;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
|
||||
struct iwl_mvm_sta *sta;
|
||||
|
||||
if (!data.load->avg_energy[i])
|
||||
if (!energy[i])
|
||||
continue;
|
||||
|
||||
sta = iwl_mvm_sta_from_staid_rcu(mvm, i);
|
||||
if (!sta)
|
||||
continue;
|
||||
sta->avg_energy = data.load->avg_energy[i];
|
||||
sta->avg_energy = energy[i];
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
@ -149,8 +149,17 @@ static void iwl_mvm_create_skb(struct sk_buff *skb, struct ieee80211_hdr *hdr,
|
||||
unsigned int headlen, fraglen, pad_len = 0;
|
||||
unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
||||
if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD)
|
||||
if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD) {
|
||||
pad_len = 2;
|
||||
|
||||
/*
|
||||
* If the device inserted padding it means that (it thought)
|
||||
* the 802.11 header wasn't a multiple of 4 bytes long. In
|
||||
* this case, reserve two bytes at the start of the SKB to
|
||||
* align the payload properly in case we end up copying it.
|
||||
*/
|
||||
skb_reserve(skb, pad_len);
|
||||
}
|
||||
len -= pad_len;
|
||||
|
||||
/* If frame is small enough to fit in skb->head, pull it completely.
|
||||
@ -409,7 +418,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
|
||||
|
||||
/* ignore nssn smaller than head sn - this can happen due to timeout */
|
||||
if (iwl_mvm_is_sn_less(nssn, ssn, reorder_buf->buf_size))
|
||||
return;
|
||||
goto set_timer;
|
||||
|
||||
while (iwl_mvm_is_sn_less(ssn, nssn, reorder_buf->buf_size)) {
|
||||
int index = ssn % reorder_buf->buf_size;
|
||||
@ -432,6 +441,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
|
||||
}
|
||||
reorder_buf->head_sn = nssn;
|
||||
|
||||
set_timer:
|
||||
if (reorder_buf->num_stored && !reorder_buf->removed) {
|
||||
u16 index = reorder_buf->head_sn % reorder_buf->buf_size;
|
||||
|
||||
|
@ -197,7 +197,7 @@ static void iwl_mvm_scan_condition_iterator(void *data, u8 *mac,
|
||||
int *global_cnt = data;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_P2P_DEVICE && mvmvif->phy_ctxt &&
|
||||
mvmvif->phy_ctxt->id < MAX_PHYS)
|
||||
mvmvif->phy_ctxt->id < NUM_PHY_CTX)
|
||||
*global_cnt += 1;
|
||||
}
|
||||
|
||||
@ -943,18 +943,92 @@ static __le32 iwl_mvm_scan_config_rates(struct iwl_mvm *mvm)
|
||||
return cpu_to_le32(rates);
|
||||
}
|
||||
|
||||
static void iwl_mvm_fill_scan_dwell(struct iwl_mvm *mvm,
|
||||
struct iwl_scan_dwell *dwell,
|
||||
struct iwl_mvm_scan_timing_params *timing)
|
||||
{
|
||||
dwell->active = timing->dwell_active;
|
||||
dwell->passive = timing->dwell_passive;
|
||||
dwell->fragmented = timing->dwell_fragmented;
|
||||
dwell->extended = timing->dwell_extended;
|
||||
}
|
||||
|
||||
static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels)
|
||||
{
|
||||
struct ieee80211_supported_band *band;
|
||||
int i, j = 0;
|
||||
|
||||
band = &mvm->nvm_data->bands[NL80211_BAND_2GHZ];
|
||||
for (i = 0; i < band->n_channels; i++, j++)
|
||||
channels[j] = band->channels[i].hw_value;
|
||||
band = &mvm->nvm_data->bands[NL80211_BAND_5GHZ];
|
||||
for (i = 0; i < band->n_channels; i++, j++)
|
||||
channels[j] = band->channels[i].hw_value;
|
||||
}
|
||||
|
||||
static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
|
||||
u32 flags, u8 channel_flags)
|
||||
{
|
||||
enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, false);
|
||||
struct iwl_scan_config *cfg = config;
|
||||
|
||||
cfg->flags = cpu_to_le32(flags);
|
||||
cfg->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
|
||||
cfg->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));
|
||||
cfg->legacy_rates = iwl_mvm_scan_config_rates(mvm);
|
||||
cfg->out_of_channel_time = cpu_to_le32(scan_timing[type].max_out_time);
|
||||
cfg->suspend_time = cpu_to_le32(scan_timing[type].suspend_time);
|
||||
|
||||
iwl_mvm_fill_scan_dwell(mvm, &cfg->dwell, &scan_timing[type]);
|
||||
|
||||
memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
|
||||
|
||||
cfg->bcast_sta_id = mvm->aux_sta.sta_id;
|
||||
cfg->channel_flags = channel_flags;
|
||||
|
||||
iwl_mvm_fill_channels(mvm, cfg->channel_array);
|
||||
}
|
||||
|
||||
static void iwl_mvm_fill_scan_config_cdb(struct iwl_mvm *mvm, void *config,
|
||||
u32 flags, u8 channel_flags)
|
||||
{
|
||||
enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, false);
|
||||
struct iwl_scan_config_cdb *cfg = config;
|
||||
|
||||
cfg->flags = cpu_to_le32(flags);
|
||||
cfg->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
|
||||
cfg->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));
|
||||
cfg->legacy_rates = iwl_mvm_scan_config_rates(mvm);
|
||||
cfg->out_of_channel_time[0] =
|
||||
cpu_to_le32(scan_timing[type].max_out_time);
|
||||
cfg->out_of_channel_time[1] =
|
||||
cpu_to_le32(scan_timing[type].max_out_time);
|
||||
cfg->suspend_time[0] = cpu_to_le32(scan_timing[type].suspend_time);
|
||||
cfg->suspend_time[1] = cpu_to_le32(scan_timing[type].suspend_time);
|
||||
|
||||
iwl_mvm_fill_scan_dwell(mvm, &cfg->dwell, &scan_timing[type]);
|
||||
|
||||
memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
|
||||
|
||||
cfg->bcast_sta_id = mvm->aux_sta.sta_id;
|
||||
cfg->channel_flags = channel_flags;
|
||||
|
||||
iwl_mvm_fill_channels(mvm, cfg->channel_array);
|
||||
}
|
||||
|
||||
int iwl_mvm_config_scan(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_scan_config *scan_config;
|
||||
struct ieee80211_supported_band *band;
|
||||
int num_channels =
|
||||
mvm->nvm_data->bands[NL80211_BAND_2GHZ].n_channels +
|
||||
mvm->nvm_data->bands[NL80211_BAND_5GHZ].n_channels;
|
||||
int ret, i, j = 0, cmd_size;
|
||||
void *cfg;
|
||||
int ret, cmd_size;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = iwl_cmd_id(SCAN_CFG_CMD, IWL_ALWAYS_LONG_GROUP, 0),
|
||||
};
|
||||
enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, false);
|
||||
int num_channels =
|
||||
mvm->nvm_data->bands[NL80211_BAND_2GHZ].n_channels +
|
||||
mvm->nvm_data->bands[NL80211_BAND_5GHZ].n_channels;
|
||||
u32 flags;
|
||||
u8 channel_flags;
|
||||
|
||||
if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels))
|
||||
return -ENOBUFS;
|
||||
@ -965,52 +1039,45 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd_size = sizeof(*scan_config) + mvm->fw->ucode_capa.n_scan_channels;
|
||||
if (iwl_mvm_is_cdb_supported(mvm))
|
||||
cmd_size = sizeof(struct iwl_scan_config_cdb);
|
||||
else
|
||||
cmd_size = sizeof(struct iwl_scan_config);
|
||||
cmd_size += mvm->fw->ucode_capa.n_scan_channels;
|
||||
|
||||
scan_config = kzalloc(cmd_size, GFP_KERNEL);
|
||||
if (!scan_config)
|
||||
cfg = kzalloc(cmd_size, GFP_KERNEL);
|
||||
if (!cfg)
|
||||
return -ENOMEM;
|
||||
|
||||
scan_config->flags = cpu_to_le32(SCAN_CONFIG_FLAG_ACTIVATE |
|
||||
SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |
|
||||
SCAN_CONFIG_FLAG_SET_TX_CHAINS |
|
||||
SCAN_CONFIG_FLAG_SET_RX_CHAINS |
|
||||
SCAN_CONFIG_FLAG_SET_AUX_STA_ID |
|
||||
SCAN_CONFIG_FLAG_SET_ALL_TIMES |
|
||||
SCAN_CONFIG_FLAG_SET_LEGACY_RATES |
|
||||
SCAN_CONFIG_FLAG_SET_MAC_ADDR |
|
||||
SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|
|
||||
SCAN_CONFIG_N_CHANNELS(num_channels) |
|
||||
(type == IWL_SCAN_TYPE_FRAGMENTED ?
|
||||
SCAN_CONFIG_FLAG_SET_FRAGMENTED :
|
||||
SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED));
|
||||
scan_config->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
|
||||
scan_config->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));
|
||||
scan_config->legacy_rates = iwl_mvm_scan_config_rates(mvm);
|
||||
scan_config->out_of_channel_time =
|
||||
cpu_to_le32(scan_timing[type].max_out_time);
|
||||
scan_config->suspend_time = cpu_to_le32(scan_timing[type].suspend_time);
|
||||
scan_config->dwell_active = scan_timing[type].dwell_active;
|
||||
scan_config->dwell_passive = scan_timing[type].dwell_passive;
|
||||
scan_config->dwell_fragmented = scan_timing[type].dwell_fragmented;
|
||||
scan_config->dwell_extended = scan_timing[type].dwell_extended;
|
||||
flags = SCAN_CONFIG_FLAG_ACTIVATE |
|
||||
SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |
|
||||
SCAN_CONFIG_FLAG_SET_TX_CHAINS |
|
||||
SCAN_CONFIG_FLAG_SET_RX_CHAINS |
|
||||
SCAN_CONFIG_FLAG_SET_AUX_STA_ID |
|
||||
SCAN_CONFIG_FLAG_SET_ALL_TIMES |
|
||||
SCAN_CONFIG_FLAG_SET_LEGACY_RATES |
|
||||
SCAN_CONFIG_FLAG_SET_MAC_ADDR |
|
||||
SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS |
|
||||
SCAN_CONFIG_N_CHANNELS(num_channels) |
|
||||
(type == IWL_SCAN_TYPE_FRAGMENTED ?
|
||||
SCAN_CONFIG_FLAG_SET_FRAGMENTED :
|
||||
SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED);
|
||||
|
||||
memcpy(&scan_config->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
|
||||
channel_flags = IWL_CHANNEL_FLAG_EBS |
|
||||
IWL_CHANNEL_FLAG_ACCURATE_EBS |
|
||||
IWL_CHANNEL_FLAG_EBS_ADD |
|
||||
IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE;
|
||||
|
||||
scan_config->bcast_sta_id = mvm->aux_sta.sta_id;
|
||||
scan_config->channel_flags = IWL_CHANNEL_FLAG_EBS |
|
||||
IWL_CHANNEL_FLAG_ACCURATE_EBS |
|
||||
IWL_CHANNEL_FLAG_EBS_ADD |
|
||||
IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE;
|
||||
if (iwl_mvm_is_cdb_supported(mvm)) {
|
||||
flags |= (type == IWL_SCAN_TYPE_FRAGMENTED) ?
|
||||
SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED :
|
||||
SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED;
|
||||
iwl_mvm_fill_scan_config_cdb(mvm, cfg, flags, channel_flags);
|
||||
} else {
|
||||
iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags);
|
||||
}
|
||||
|
||||
band = &mvm->nvm_data->bands[NL80211_BAND_2GHZ];
|
||||
for (i = 0; i < band->n_channels; i++, j++)
|
||||
scan_config->channel_array[j] = band->channels[i].hw_value;
|
||||
band = &mvm->nvm_data->bands[NL80211_BAND_5GHZ];
|
||||
for (i = 0; i < band->n_channels; i++, j++)
|
||||
scan_config->channel_array[j] = band->channels[i].hw_value;
|
||||
|
||||
cmd.data[0] = scan_config;
|
||||
cmd.data[0] = cfg;
|
||||
cmd.len[0] = cmd_size;
|
||||
cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
|
||||
|
||||
@ -1020,7 +1087,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
|
||||
if (!ret)
|
||||
mvm->scan_type = type;
|
||||
|
||||
kfree(scan_config);
|
||||
kfree(cfg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1039,19 +1106,31 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
|
||||
struct iwl_scan_req_umac *cmd,
|
||||
struct iwl_mvm_scan_params *params)
|
||||
{
|
||||
struct iwl_mvm_scan_timing_params *timing = &scan_timing[params->type];
|
||||
|
||||
if (params->measurement_dwell) {
|
||||
cmd->active_dwell = params->measurement_dwell;
|
||||
cmd->passive_dwell = params->measurement_dwell;
|
||||
cmd->extended_dwell = params->measurement_dwell;
|
||||
} else {
|
||||
cmd->active_dwell = scan_timing[params->type].dwell_active;
|
||||
cmd->passive_dwell = scan_timing[params->type].dwell_passive;
|
||||
cmd->extended_dwell = scan_timing[params->type].dwell_extended;
|
||||
cmd->active_dwell = timing->dwell_active;
|
||||
cmd->passive_dwell = timing->dwell_passive;
|
||||
cmd->extended_dwell = timing->dwell_extended;
|
||||
}
|
||||
cmd->fragmented_dwell = timing->dwell_fragmented;
|
||||
|
||||
if (iwl_mvm_is_cdb_supported(mvm)) {
|
||||
cmd->cdb.max_out_time[0] = cpu_to_le32(timing->max_out_time);
|
||||
cmd->cdb.suspend_time[0] = cpu_to_le32(timing->suspend_time);
|
||||
cmd->cdb.max_out_time[1] = cpu_to_le32(timing->max_out_time);
|
||||
cmd->cdb.suspend_time[1] = cpu_to_le32(timing->suspend_time);
|
||||
cmd->cdb.scan_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);
|
||||
} else {
|
||||
cmd->no_cdb.max_out_time = cpu_to_le32(timing->max_out_time);
|
||||
cmd->no_cdb.suspend_time = cpu_to_le32(timing->suspend_time);
|
||||
cmd->no_cdb.scan_priority =
|
||||
cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);
|
||||
}
|
||||
cmd->fragmented_dwell = scan_timing[params->type].dwell_fragmented;
|
||||
cmd->max_out_time = cpu_to_le32(scan_timing[params->type].max_out_time);
|
||||
cmd->suspend_time = cpu_to_le32(scan_timing[params->type].suspend_time);
|
||||
cmd->scan_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);
|
||||
|
||||
if (iwl_mvm_is_regular_scan(params))
|
||||
cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6);
|
||||
@ -1063,9 +1142,8 @@ static void
|
||||
iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,
|
||||
struct ieee80211_channel **channels,
|
||||
int n_channels, u32 ssid_bitmap,
|
||||
struct iwl_scan_req_umac *cmd)
|
||||
struct iwl_scan_channel_cfg_umac *channel_cfg)
|
||||
{
|
||||
struct iwl_scan_channel_cfg_umac *channel_cfg = (void *)&cmd->data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_channels; i++) {
|
||||
@ -1088,8 +1166,11 @@ static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
|
||||
if (params->n_ssids == 1 && params->ssids[0].ssid_len != 0)
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT;
|
||||
|
||||
if (params->type == IWL_SCAN_TYPE_FRAGMENTED)
|
||||
if (params->type == IWL_SCAN_TYPE_FRAGMENTED) {
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED;
|
||||
if (iwl_mvm_is_cdb_supported(mvm))
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED;
|
||||
}
|
||||
|
||||
if (iwl_mvm_rrm_scan_needed(mvm))
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED;
|
||||
@ -1126,11 +1207,14 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
int type)
|
||||
{
|
||||
struct iwl_scan_req_umac *cmd = mvm->scan_cmd;
|
||||
struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data +
|
||||
void *cmd_data = iwl_mvm_is_cdb_supported(mvm) ?
|
||||
(void *)&cmd->cdb.data : (void *)&cmd->no_cdb.data;
|
||||
struct iwl_scan_req_umac_tail *sec_part = cmd_data +
|
||||
sizeof(struct iwl_scan_channel_cfg_umac) *
|
||||
mvm->fw->ucode_capa.n_scan_channels;
|
||||
int uid, i;
|
||||
u32 ssid_bitmap = 0;
|
||||
u8 channel_flags = 0;
|
||||
struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
@ -1157,16 +1241,23 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE);
|
||||
|
||||
if (iwl_mvm_scan_use_ebs(mvm, vif))
|
||||
cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS |
|
||||
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
|
||||
IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;
|
||||
channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS |
|
||||
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
|
||||
IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;
|
||||
|
||||
cmd->n_channels = params->n_channels;
|
||||
if (iwl_mvm_is_cdb_supported(mvm)) {
|
||||
cmd->cdb.channel_flags = channel_flags;
|
||||
cmd->cdb.n_channels = params->n_channels;
|
||||
} else {
|
||||
cmd->no_cdb.channel_flags = channel_flags;
|
||||
cmd->no_cdb.n_channels = params->n_channels;
|
||||
}
|
||||
|
||||
iwl_scan_build_ssids(params, sec_part->direct_scan, &ssid_bitmap);
|
||||
|
||||
iwl_mvm_umac_scan_cfg_channels(mvm, params->channels,
|
||||
params->n_channels, ssid_bitmap, cmd);
|
||||
params->n_channels, ssid_bitmap,
|
||||
cmd_data);
|
||||
|
||||
for (i = 0; i < params->n_scan_plans; i++) {
|
||||
struct cfg80211_sched_scan_plan *scan_plan =
|
||||
@ -1601,8 +1692,13 @@ static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type)
|
||||
|
||||
int iwl_mvm_scan_size(struct iwl_mvm *mvm)
|
||||
{
|
||||
int base_size = IWL_SCAN_REQ_UMAC_SIZE;
|
||||
|
||||
if (iwl_mvm_is_cdb_supported(mvm))
|
||||
base_size = IWL_SCAN_REQ_UMAC_SIZE_CDB;
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN))
|
||||
return sizeof(struct iwl_scan_req_umac) +
|
||||
return base_size +
|
||||
sizeof(struct iwl_scan_channel_cfg_umac) *
|
||||
mvm->fw->ucode_capa.n_scan_channels +
|
||||
sizeof(struct iwl_scan_req_umac_tail);
|
||||
|
@ -202,7 +202,8 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT);
|
||||
add_sta_cmd.station_flags |=
|
||||
cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT);
|
||||
add_sta_cmd.assoc_id = cpu_to_le16(sta->aid);
|
||||
if (mvm_sta->associated)
|
||||
add_sta_cmd.assoc_id = cpu_to_le16(sta->aid);
|
||||
|
||||
if (sta->wme) {
|
||||
add_sta_cmd.modify_mask |= STA_MODIFY_UAPSD_ACS;
|
||||
@ -457,6 +458,52 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue)
|
||||
return disable_agg_tids;
|
||||
}
|
||||
|
||||
static int iwl_mvm_free_inactive_queue(struct iwl_mvm *mvm, int queue,
|
||||
bool same_sta)
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
u8 txq_curr_ac, sta_id, tid;
|
||||
unsigned long disable_agg_tids = 0;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
spin_lock_bh(&mvm->queue_info_lock);
|
||||
txq_curr_ac = mvm->queue_info[queue].mac80211_ac;
|
||||
sta_id = mvm->queue_info[queue].ra_sta_id;
|
||||
tid = mvm->queue_info[queue].txq_tid;
|
||||
spin_unlock_bh(&mvm->queue_info_lock);
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
|
||||
|
||||
disable_agg_tids = iwl_mvm_remove_sta_queue_marking(mvm, queue);
|
||||
/* Disable the queue */
|
||||
if (disable_agg_tids)
|
||||
iwl_mvm_invalidate_sta_queue(mvm, queue,
|
||||
disable_agg_tids, false);
|
||||
|
||||
ret = iwl_mvm_disable_txq(mvm, queue,
|
||||
mvmsta->vif->hw_queue[txq_curr_ac],
|
||||
tid, 0);
|
||||
if (ret) {
|
||||
/* Re-mark the inactive queue as inactive */
|
||||
spin_lock_bh(&mvm->queue_info_lock);
|
||||
mvm->queue_info[queue].status = IWL_MVM_QUEUE_INACTIVE;
|
||||
spin_unlock_bh(&mvm->queue_info_lock);
|
||||
IWL_ERR(mvm,
|
||||
"Failed to free inactive queue %d (ret=%d)\n",
|
||||
queue, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If TXQ is allocated to another STA, update removal in FW */
|
||||
if (!same_sta)
|
||||
iwl_mvm_invalidate_sta_queue(mvm, queue, 0, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_get_shared_queue(struct iwl_mvm *mvm,
|
||||
unsigned long tfd_queue_mask, u8 ac)
|
||||
{
|
||||
@ -645,7 +692,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
|
||||
iwl_mvm_get_wd_timeout(mvm, mvmsta->vif, false, false);
|
||||
u8 mac_queue = mvmsta->vif->hw_queue[ac];
|
||||
int queue = -1;
|
||||
bool using_inactive_queue = false;
|
||||
bool using_inactive_queue = false, same_sta = false;
|
||||
unsigned long disable_agg_tids = 0;
|
||||
enum iwl_mvm_agg_state queue_state;
|
||||
bool shared_queue = false;
|
||||
@ -702,6 +749,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
|
||||
mvm->queue_info[queue].status == IWL_MVM_QUEUE_INACTIVE) {
|
||||
mvm->queue_info[queue].status = IWL_MVM_QUEUE_RESERVED;
|
||||
using_inactive_queue = true;
|
||||
same_sta = mvm->queue_info[queue].ra_sta_id == mvmsta->sta_id;
|
||||
IWL_DEBUG_TX_QUEUES(mvm,
|
||||
"Re-assigning TXQ %d: sta_id=%d, tid=%d\n",
|
||||
queue, mvmsta->sta_id, tid);
|
||||
@ -748,38 +796,9 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
|
||||
* first
|
||||
*/
|
||||
if (using_inactive_queue) {
|
||||
u8 txq_curr_ac, sta_id;
|
||||
|
||||
spin_lock_bh(&mvm->queue_info_lock);
|
||||
txq_curr_ac = mvm->queue_info[queue].mac80211_ac;
|
||||
sta_id = mvm->queue_info[queue].ra_sta_id;
|
||||
spin_unlock_bh(&mvm->queue_info_lock);
|
||||
|
||||
disable_agg_tids = iwl_mvm_remove_sta_queue_marking(mvm, queue);
|
||||
/* Disable the queue */
|
||||
if (disable_agg_tids)
|
||||
iwl_mvm_invalidate_sta_queue(mvm, queue,
|
||||
disable_agg_tids, false);
|
||||
|
||||
ret = iwl_mvm_disable_txq(mvm, queue,
|
||||
mvmsta->vif->hw_queue[txq_curr_ac],
|
||||
tid, 0);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm,
|
||||
"Failed to free inactive queue %d (ret=%d)\n",
|
||||
queue, ret);
|
||||
|
||||
/* Re-mark the inactive queue as inactive */
|
||||
spin_lock_bh(&mvm->queue_info_lock);
|
||||
mvm->queue_info[queue].status = IWL_MVM_QUEUE_INACTIVE;
|
||||
spin_unlock_bh(&mvm->queue_info_lock);
|
||||
|
||||
ret = iwl_mvm_free_inactive_queue(mvm, queue, same_sta);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If TXQ is allocated to another STA, update removal in FW */
|
||||
if (sta_id != mvmsta->sta_id)
|
||||
iwl_mvm_invalidate_sta_queue(mvm, queue, 0, true);
|
||||
}
|
||||
|
||||
IWL_DEBUG_TX_QUEUES(mvm,
|
||||
@ -1095,6 +1114,7 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm,
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
int queue;
|
||||
bool using_inactive_queue = false, same_sta = false;
|
||||
|
||||
/*
|
||||
* Check for inactive queues, so we don't reach a situation where we
|
||||
@ -1118,6 +1138,14 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm,
|
||||
spin_unlock_bh(&mvm->queue_info_lock);
|
||||
IWL_ERR(mvm, "No available queues for new station\n");
|
||||
return -ENOSPC;
|
||||
} else if (mvm->queue_info[queue].status == IWL_MVM_QUEUE_INACTIVE) {
|
||||
/*
|
||||
* If this queue is already allocated but inactive we'll need to
|
||||
* first free this queue before enabling it again, we'll mark
|
||||
* it as reserved to make sure no new traffic arrives on it
|
||||
*/
|
||||
using_inactive_queue = true;
|
||||
same_sta = mvm->queue_info[queue].ra_sta_id == mvmsta->sta_id;
|
||||
}
|
||||
mvm->queue_info[queue].status = IWL_MVM_QUEUE_RESERVED;
|
||||
|
||||
@ -1125,6 +1153,9 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm,
|
||||
|
||||
mvmsta->reserved_queue = queue;
|
||||
|
||||
if (using_inactive_queue)
|
||||
iwl_mvm_free_inactive_queue(mvm, queue, same_sta);
|
||||
|
||||
IWL_DEBUG_TX_QUEUES(mvm, "Reserving data queue #%d for sta_id %d\n",
|
||||
queue, mvmsta->sta_id);
|
||||
|
||||
@ -1471,6 +1502,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||
u8 sta_id = mvm_sta->sta_id;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
@ -1479,7 +1511,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
kfree(mvm_sta->dup_data);
|
||||
|
||||
if ((vif->type == NL80211_IFTYPE_STATION &&
|
||||
mvmvif->ap_sta_id == mvm_sta->sta_id) ||
|
||||
mvmvif->ap_sta_id == sta_id) ||
|
||||
iwl_mvm_is_dqa_supported(mvm)){
|
||||
ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
|
||||
if (ret)
|
||||
@ -1495,8 +1527,17 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
ret = iwl_mvm_drain_sta(mvm, mvm_sta, false);
|
||||
|
||||
/* If DQA is supported - the queues can be disabled now */
|
||||
if (iwl_mvm_is_dqa_supported(mvm))
|
||||
if (iwl_mvm_is_dqa_supported(mvm)) {
|
||||
iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta);
|
||||
/*
|
||||
* If pending_frames is set at this point - it must be
|
||||
* driver internal logic error, since queues are empty
|
||||
* and removed successuly.
|
||||
* warn on it but set it to 0 anyway to avoid station
|
||||
* not being removed later in the function
|
||||
*/
|
||||
WARN_ON(atomic_xchg(&mvm->pending_frames[sta_id], 0));
|
||||
}
|
||||
|
||||
/* If there is a TXQ still marked as reserved - free it */
|
||||
if (iwl_mvm_is_dqa_supported(mvm) &&
|
||||
@ -1514,7 +1555,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
if (WARN((*status != IWL_MVM_QUEUE_RESERVED) &&
|
||||
(*status != IWL_MVM_QUEUE_FREE),
|
||||
"sta_id %d reserved txq %d status %d",
|
||||
mvm_sta->sta_id, reserved_txq, *status)) {
|
||||
sta_id, reserved_txq, *status)) {
|
||||
spin_unlock_bh(&mvm->queue_info_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1524,7 +1565,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||
mvmvif->ap_sta_id == mvm_sta->sta_id) {
|
||||
mvmvif->ap_sta_id == sta_id) {
|
||||
/* if associated - we can't remove the AP STA now */
|
||||
if (vif->bss_conf.assoc)
|
||||
return ret;
|
||||
@ -1533,7 +1574,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
|
||||
|
||||
/* clear d0i3_ap_sta_id if no longer relevant */
|
||||
if (mvm->d0i3_ap_sta_id == mvm_sta->sta_id)
|
||||
if (mvm->d0i3_ap_sta_id == sta_id)
|
||||
mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT;
|
||||
}
|
||||
}
|
||||
@ -1542,7 +1583,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
* This shouldn't happen - the TDLS channel switch should be canceled
|
||||
* before the STA is removed.
|
||||
*/
|
||||
if (WARN_ON_ONCE(mvm->tdls_cs.peer.sta_id == mvm_sta->sta_id)) {
|
||||
if (WARN_ON_ONCE(mvm->tdls_cs.peer.sta_id == sta_id)) {
|
||||
mvm->tdls_cs.peer.sta_id = IWL_MVM_STATION_COUNT;
|
||||
cancel_delayed_work(&mvm->tdls_cs.dwork);
|
||||
}
|
||||
@ -1552,21 +1593,20 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
* calls the drain worker.
|
||||
*/
|
||||
spin_lock_bh(&mvm_sta->lock);
|
||||
|
||||
/*
|
||||
* There are frames pending on the AC queues for this station.
|
||||
* We need to wait until all the frames are drained...
|
||||
*/
|
||||
if (atomic_read(&mvm->pending_frames[mvm_sta->sta_id])) {
|
||||
rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
|
||||
if (atomic_read(&mvm->pending_frames[sta_id])) {
|
||||
rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id],
|
||||
ERR_PTR(-EBUSY));
|
||||
spin_unlock_bh(&mvm_sta->lock);
|
||||
|
||||
/* disable TDLS sta queues on drain complete */
|
||||
if (sta->tdls) {
|
||||
mvm->tfd_drained[mvm_sta->sta_id] =
|
||||
mvm_sta->tfd_queue_msk;
|
||||
IWL_DEBUG_TDLS(mvm, "Draining TDLS sta %d\n",
|
||||
mvm_sta->sta_id);
|
||||
mvm->tfd_drained[sta_id] = mvm_sta->tfd_queue_msk;
|
||||
IWL_DEBUG_TDLS(mvm, "Draining TDLS sta %d\n", sta_id);
|
||||
}
|
||||
|
||||
ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
|
||||
@ -1750,6 +1790,7 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
struct iwl_mvm_int_sta *bsta = &mvmvif->bcast_sta;
|
||||
static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
const u8 *baddr = _baddr;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
@ -1765,19 +1806,16 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
iwl_mvm_get_wd_timeout(mvm, vif, false, false);
|
||||
int queue;
|
||||
|
||||
if ((vif->type == NL80211_IFTYPE_AP) &&
|
||||
(mvmvif->bcast_sta.tfd_queue_msk &
|
||||
BIT(IWL_MVM_DQA_AP_PROBE_RESP_QUEUE)))
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
|
||||
else if ((vif->type == NL80211_IFTYPE_P2P_DEVICE) &&
|
||||
(mvmvif->bcast_sta.tfd_queue_msk &
|
||||
BIT(IWL_MVM_DQA_P2P_DEVICE_QUEUE)))
|
||||
else if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
||||
queue = IWL_MVM_DQA_P2P_DEVICE_QUEUE;
|
||||
else if (WARN(1, "Missed required TXQ for adding bcast STA\n"))
|
||||
else if (WARN(1, "Missing required TXQ for adding bcast STA\n"))
|
||||
return -EINVAL;
|
||||
|
||||
iwl_mvm_enable_txq(mvm, queue, vif->hw_queue[0], 0, &cfg,
|
||||
wdg_timeout);
|
||||
bsta->tfd_queue_msk |= BIT(queue);
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC)
|
||||
@ -1786,8 +1824,67 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
if (WARN_ON_ONCE(bsta->sta_id == IWL_MVM_STATION_COUNT))
|
||||
return -ENOSPC;
|
||||
|
||||
return iwl_mvm_add_int_sta_common(mvm, bsta, baddr,
|
||||
mvmvif->id, mvmvif->color);
|
||||
ret = iwl_mvm_add_int_sta_common(mvm, bsta, baddr,
|
||||
mvmvif->id, mvmvif->color);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* In AP vif type, we also need to enable the cab_queue. However, we
|
||||
* have to enable it after the ADD_STA command is sent, otherwise the
|
||||
* FW will throw an assert once we send the ADD_STA command (it'll
|
||||
* detect a mismatch in the tfd_queue_msk, as we can't add the
|
||||
* enabled-cab_queue to the mask)
|
||||
*/
|
||||
if (iwl_mvm_is_dqa_supported(mvm) &&
|
||||
vif->type == NL80211_IFTYPE_AP) {
|
||||
struct iwl_trans_txq_scd_cfg cfg = {
|
||||
.fifo = IWL_MVM_TX_FIFO_MCAST,
|
||||
.sta_id = mvmvif->bcast_sta.sta_id,
|
||||
.tid = IWL_MAX_TID_COUNT,
|
||||
.aggregate = false,
|
||||
.frame_limit = IWL_FRAME_LIMIT,
|
||||
};
|
||||
unsigned int wdg_timeout =
|
||||
iwl_mvm_get_wd_timeout(mvm, vif, false, false);
|
||||
|
||||
iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue,
|
||||
0, &cfg, wdg_timeout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue,
|
||||
IWL_MAX_TID_COUNT, 0);
|
||||
|
||||
if (mvmvif->bcast_sta.tfd_queue_msk &
|
||||
BIT(IWL_MVM_DQA_AP_PROBE_RESP_QUEUE)) {
|
||||
iwl_mvm_disable_txq(mvm,
|
||||
IWL_MVM_DQA_AP_PROBE_RESP_QUEUE,
|
||||
vif->hw_queue[0], IWL_MAX_TID_COUNT,
|
||||
0);
|
||||
mvmvif->bcast_sta.tfd_queue_msk &=
|
||||
~BIT(IWL_MVM_DQA_AP_PROBE_RESP_QUEUE);
|
||||
}
|
||||
|
||||
if (mvmvif->bcast_sta.tfd_queue_msk &
|
||||
BIT(IWL_MVM_DQA_P2P_DEVICE_QUEUE)) {
|
||||
iwl_mvm_disable_txq(mvm,
|
||||
IWL_MVM_DQA_P2P_DEVICE_QUEUE,
|
||||
vif->hw_queue[0], IWL_MAX_TID_COUNT,
|
||||
0);
|
||||
mvmvif->bcast_sta.tfd_queue_msk &=
|
||||
~BIT(IWL_MVM_DQA_P2P_DEVICE_QUEUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send the FW a request to remove the station from it's internal data
|
||||
@ -1799,6 +1896,9 @@ int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (iwl_mvm_is_dqa_supported(mvm))
|
||||
iwl_mvm_free_bcast_sta_queues(mvm, vif);
|
||||
|
||||
ret = iwl_mvm_rm_sta_common(mvm, mvmvif->bcast_sta.sta_id);
|
||||
if (ret)
|
||||
IWL_WARN(mvm, "Failed sending remove station\n");
|
||||
@ -1812,22 +1912,16 @@ int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (!iwl_mvm_is_dqa_supported(mvm))
|
||||
if (!iwl_mvm_is_dqa_supported(mvm)) {
|
||||
qmask = iwl_mvm_mac_get_queues_mask(vif);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
/*
|
||||
* The firmware defines the TFD queue mask to only be relevant
|
||||
* for *unicast* queues, so the multicast (CAB) queue shouldn't
|
||||
* be included.
|
||||
* be included. This only happens in NL80211_IFTYPE_AP vif type,
|
||||
* so the next line will only have an effect there.
|
||||
*/
|
||||
qmask &= ~BIT(vif->cab_queue);
|
||||
|
||||
if (iwl_mvm_is_dqa_supported(mvm))
|
||||
qmask |= BIT(IWL_MVM_DQA_AP_PROBE_RESP_QUEUE);
|
||||
} else if (iwl_mvm_is_dqa_supported(mvm) &&
|
||||
vif->type == NL80211_IFTYPE_P2P_DEVICE) {
|
||||
qmask |= BIT(IWL_MVM_DQA_P2P_DEVICE_QUEUE);
|
||||
}
|
||||
|
||||
return iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta, qmask,
|
||||
@ -2232,6 +2326,13 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
IWL_ERR(mvm, "Failed to allocate agg queue\n");
|
||||
goto release_locks;
|
||||
}
|
||||
/*
|
||||
* TXQ shouldn't be in inactive mode for non-DQA, so getting
|
||||
* an inactive queue from iwl_mvm_find_free_queue() is
|
||||
* certainly a bug
|
||||
*/
|
||||
WARN_ON(mvm->queue_info[txq_id].status ==
|
||||
IWL_MVM_QUEUE_INACTIVE);
|
||||
|
||||
/* TXQ hasn't yet been enabled, so mark it only as reserved */
|
||||
mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_RESERVED;
|
||||
@ -2947,6 +3048,11 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
|
||||
|
||||
/* Get the station from the mvm local station table */
|
||||
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
|
||||
if (!mvm_sta) {
|
||||
IWL_ERR(mvm, "Failed to find station\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
sta_id = mvm_sta->sta_id;
|
||||
|
||||
IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
|
||||
keyconf->keyidx, sta_id);
|
||||
@ -2974,8 +3080,6 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
sta_id = mvm_sta->sta_id;
|
||||
|
||||
ret = __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, mcast);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -437,6 +437,7 @@ struct iwl_mvm_sta {
|
||||
bool disable_tx;
|
||||
bool tlc_amsdu;
|
||||
bool sleeping;
|
||||
bool associated;
|
||||
u8 agg_tids;
|
||||
u8 sleep_tx_count;
|
||||
u8 avg_energy;
|
||||
|
@ -202,7 +202,6 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
struct iwl_tx_cmd *tx_cmd,
|
||||
struct ieee80211_tx_info *info, u8 sta_id)
|
||||
{
|
||||
struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags);
|
||||
@ -284,9 +283,8 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
tx_flags |= TX_CMD_FLG_WRITE_TX_POWER;
|
||||
|
||||
tx_cmd->tx_flags = cpu_to_le32(tx_flags);
|
||||
/* Total # bytes to be transmitted */
|
||||
tx_cmd->len = cpu_to_le16((u16)skb->len +
|
||||
(uintptr_t)skb_info->driver_data[0]);
|
||||
/* Total # bytes to be transmitted - PCIe code will adjust for A-MSDU */
|
||||
tx_cmd->len = cpu_to_le16((u16)skb->len);
|
||||
tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
|
||||
tx_cmd->sta_id = sta_id;
|
||||
|
||||
@ -466,7 +464,6 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta, u8 sta_id)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
|
||||
struct iwl_device_cmd *dev_cmd;
|
||||
struct iwl_tx_cmd *tx_cmd;
|
||||
|
||||
@ -486,12 +483,18 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
|
||||
iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control);
|
||||
|
||||
return dev_cmd;
|
||||
}
|
||||
|
||||
static void iwl_mvm_skb_prepare_status(struct sk_buff *skb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
memset(&skb_info->status, 0, sizeof(skb_info->status));
|
||||
memset(skb_info->driver_data, 0, sizeof(skb_info->driver_data));
|
||||
|
||||
skb_info->driver_data[1] = dev_cmd;
|
||||
|
||||
return dev_cmd;
|
||||
skb_info->driver_data[1] = cmd;
|
||||
}
|
||||
|
||||
static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
|
||||
@ -503,15 +506,17 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
|
||||
switch (info->control.vif->type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
/*
|
||||
* handle legacy hostapd as well, where station may be added
|
||||
* only after assoc.
|
||||
* Handle legacy hostapd as well, where station may be added
|
||||
* only after assoc. Take care of the case where we send a
|
||||
* deauth to a station that we don't have.
|
||||
*/
|
||||
if (ieee80211_is_probe_resp(fc) || ieee80211_is_auth(fc))
|
||||
if (ieee80211_is_probe_resp(fc) || ieee80211_is_auth(fc) ||
|
||||
ieee80211_is_deauth(fc))
|
||||
return IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
|
||||
if (info->hw_queue == info->control.vif->cab_queue)
|
||||
return info->hw_queue;
|
||||
|
||||
WARN_ON_ONCE(1);
|
||||
WARN_ONCE(1, "fc=0x%02x", le16_to_cpu(fc));
|
||||
return IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
if (ieee80211_is_mgmt(fc))
|
||||
@ -543,9 +548,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
|
||||
* queue. STATION (HS2.0) uses the auxiliary context of the FW,
|
||||
* and hence needs to be sent on the aux queue
|
||||
*/
|
||||
if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
|
||||
if (skb_info->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
|
||||
skb_info->control.vif->type == NL80211_IFTYPE_STATION)
|
||||
IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue;
|
||||
skb_info->hw_queue = mvm->aux_queue;
|
||||
|
||||
memcpy(&info, skb->cb, sizeof(info));
|
||||
|
||||
@ -557,9 +562,6 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
|
||||
info.hw_queue != info.control.vif->cab_queue)))
|
||||
return -1;
|
||||
|
||||
/* This holds the amsdu headers length */
|
||||
skb_info->driver_data[0] = (void *)(uintptr_t)0;
|
||||
|
||||
queue = info.hw_queue;
|
||||
|
||||
/*
|
||||
@ -570,9 +572,10 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
|
||||
* (this is not possible for unicast packets as a TLDS discovery
|
||||
* response are sent without a station entry); otherwise use the
|
||||
* AUX station.
|
||||
* In DQA mode, if vif is of type STATION and frames are not multicast,
|
||||
* they should be sent from the BSS queue. For example, TDLS setup
|
||||
* frames should be sent on this queue, as they go through the AP.
|
||||
* In DQA mode, if vif is of type STATION and frames are not multicast
|
||||
* or offchannel, they should be sent from the BSS queue.
|
||||
* For example, TDLS setup frames should be sent on this queue,
|
||||
* as they go through the AP.
|
||||
*/
|
||||
sta_id = mvm->aux_sta.sta_id;
|
||||
if (info.control.vif) {
|
||||
@ -594,7 +597,8 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
|
||||
if (ap_sta_id != IWL_MVM_STATION_COUNT)
|
||||
sta_id = ap_sta_id;
|
||||
} else if (iwl_mvm_is_dqa_supported(mvm) &&
|
||||
info.control.vif->type == NL80211_IFTYPE_STATION) {
|
||||
info.control.vif->type == NL80211_IFTYPE_STATION &&
|
||||
queue != mvm->aux_queue) {
|
||||
queue = IWL_MVM_DQA_BSS_CLIENT_QUEUE;
|
||||
}
|
||||
}
|
||||
@ -605,6 +609,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
|
||||
if (!dev_cmd)
|
||||
return -1;
|
||||
|
||||
/* From now on, we cannot access info->control */
|
||||
iwl_mvm_skb_prepare_status(skb, dev_cmd);
|
||||
|
||||
tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
|
||||
|
||||
/* Copy MAC header from skb into command buffer */
|
||||
@ -641,7 +648,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
unsigned int num_subframes, tcp_payload_len, subf_len, max_amsdu_len;
|
||||
bool ipv4 = (skb->protocol == htons(ETH_P_IP));
|
||||
u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0;
|
||||
u16 amsdu_add, snap_ip_tcp, pad, i = 0;
|
||||
u16 snap_ip_tcp, pad, i = 0;
|
||||
unsigned int dbg_max_amsdu_len;
|
||||
netdev_features_t netdev_features = NETIF_F_CSUM_MASK | NETIF_F_SG;
|
||||
u8 *qc, tid, txf;
|
||||
@ -743,21 +750,6 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
|
||||
/* This skb fits in one single A-MSDU */
|
||||
if (num_subframes * mss >= tcp_payload_len) {
|
||||
struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
/*
|
||||
* Compute the length of all the data added for the A-MSDU.
|
||||
* This will be used to compute the length to write in the TX
|
||||
* command. We have: SNAP + IP + TCP for n -1 subframes and
|
||||
* ETH header for n subframes. Note that the original skb
|
||||
* already had one set of SNAP / IP / TCP headers.
|
||||
*/
|
||||
num_subframes = DIV_ROUND_UP(tcp_payload_len, mss);
|
||||
amsdu_add = num_subframes * sizeof(struct ethhdr) +
|
||||
(num_subframes - 1) * (snap_ip_tcp + pad);
|
||||
/* This holds the amsdu headers length */
|
||||
skb_info->driver_data[0] = (void *)(uintptr_t)amsdu_add;
|
||||
|
||||
__skb_queue_tail(mpdus_skb, skb);
|
||||
return 0;
|
||||
}
|
||||
@ -796,14 +788,6 @@ segment:
|
||||
ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes);
|
||||
|
||||
if (tcp_payload_len > mss) {
|
||||
struct ieee80211_tx_info *skb_info =
|
||||
IEEE80211_SKB_CB(tmp);
|
||||
|
||||
num_subframes = DIV_ROUND_UP(tcp_payload_len, mss);
|
||||
amsdu_add = num_subframes * sizeof(struct ethhdr) +
|
||||
(num_subframes - 1) * (snap_ip_tcp + pad);
|
||||
skb_info->driver_data[0] =
|
||||
(void *)(uintptr_t)amsdu_add;
|
||||
skb_shinfo(tmp)->gso_size = mss;
|
||||
} else {
|
||||
qc = ieee80211_get_qos_ctl((void *)tmp->data);
|
||||
@ -915,7 +899,6 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
goto drop;
|
||||
|
||||
tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
|
||||
/* From now on, we cannot access info->control */
|
||||
|
||||
/*
|
||||
* we handle that entirely ourselves -- for uAPSD the firmware
|
||||
@ -926,6 +909,10 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
|
||||
spin_lock(&mvmsta->lock);
|
||||
|
||||
/* nullfunc frames should go to the MGMT queue regardless of QOS,
|
||||
* the condition of !ieee80211_is_qos_nullfunc(fc) keeps the default
|
||||
* assignment of MGMT TID
|
||||
*/
|
||||
if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
|
||||
u8 *qc = NULL;
|
||||
qc = ieee80211_get_qos_ctl(hdr);
|
||||
@ -938,27 +925,13 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
|
||||
hdr->seq_ctrl |= cpu_to_le16(seq_number);
|
||||
is_ampdu = info->flags & IEEE80211_TX_CTL_AMPDU;
|
||||
} else if (iwl_mvm_is_dqa_supported(mvm) &&
|
||||
(ieee80211_is_qos_nullfunc(fc) ||
|
||||
ieee80211_is_nullfunc(fc))) {
|
||||
/*
|
||||
* nullfunc frames should go to the MGMT queue regardless of QOS
|
||||
*/
|
||||
tid = IWL_MAX_TID_COUNT;
|
||||
if (WARN_ON_ONCE(is_ampdu &&
|
||||
mvmsta->tid_data[tid].state != IWL_AGG_ON))
|
||||
goto drop_unlock_sta;
|
||||
}
|
||||
|
||||
if (iwl_mvm_is_dqa_supported(mvm)) {
|
||||
if (iwl_mvm_is_dqa_supported(mvm) || is_ampdu)
|
||||
txq_id = mvmsta->tid_data[tid].txq_id;
|
||||
|
||||
if (ieee80211_is_mgmt(fc))
|
||||
tx_cmd->tid_tspec = IWL_TID_NON_QOS;
|
||||
}
|
||||
|
||||
/* Copy MAC header from skb into command buffer */
|
||||
memcpy(tx_cmd->hdr, hdr, hdrlen);
|
||||
|
||||
WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM);
|
||||
|
||||
if (sta->tdls && !iwl_mvm_is_dqa_supported(mvm)) {
|
||||
/* default to TID 0 for non-QoS packets */
|
||||
u8 tdls_tid = tid == IWL_MAX_TID_COUNT ? 0 : tid;
|
||||
@ -966,11 +939,10 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
txq_id = mvmsta->hw_queue[tid_to_mac80211_ac[tdls_tid]];
|
||||
}
|
||||
|
||||
if (is_ampdu) {
|
||||
if (WARN_ON_ONCE(mvmsta->tid_data[tid].state != IWL_AGG_ON))
|
||||
goto drop_unlock_sta;
|
||||
txq_id = mvmsta->tid_data[tid].txq_id;
|
||||
}
|
||||
/* Copy MAC header from skb into command buffer */
|
||||
memcpy(tx_cmd->hdr, hdr, hdrlen);
|
||||
|
||||
WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM);
|
||||
|
||||
/* Check if TXQ needs to be allocated or re-activated */
|
||||
if (unlikely(txq_id == IEEE80211_INVAL_HW_QUEUE ||
|
||||
@ -1022,6 +994,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x\n", mvmsta->sta_id,
|
||||
tid, txq_id, IEEE80211_SEQ_TO_SN(seq_number));
|
||||
|
||||
/* From now on, we cannot access info->control */
|
||||
iwl_mvm_skb_prepare_status(skb, dev_cmd);
|
||||
|
||||
if (iwl_trans_tx(mvm->trans, skb, dev_cmd, txq_id))
|
||||
goto drop_unlock_sta;
|
||||
|
||||
@ -1031,7 +1006,10 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
spin_unlock(&mvmsta->lock);
|
||||
|
||||
/* Increase pending frames count if this isn't AMPDU */
|
||||
if (!is_ampdu)
|
||||
if ((iwl_mvm_is_dqa_supported(mvm) &&
|
||||
mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_ON &&
|
||||
mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_STARTING) ||
|
||||
(!iwl_mvm_is_dqa_supported(mvm) && !is_ampdu))
|
||||
atomic_inc(&mvm->pending_frames[mvmsta->sta_id]);
|
||||
|
||||
return 0;
|
||||
@ -1047,7 +1025,6 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_tx_info info;
|
||||
struct sk_buff_head mpdus_skbs;
|
||||
unsigned int payload_len;
|
||||
@ -1061,9 +1038,6 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
|
||||
memcpy(&info, skb->cb, sizeof(info));
|
||||
|
||||
/* This holds the amsdu headers length */
|
||||
skb_info->driver_data[0] = (void *)(uintptr_t)0;
|
||||
|
||||
if (!skb_is_gso(skb))
|
||||
return iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
|
||||
|
||||
@ -1302,8 +1276,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
||||
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
|
||||
/* inform mac80211 about what happened with the frame */
|
||||
switch (status & TX_STATUS_MSK) {
|
||||
case TX_STATUS_SUCCESS:
|
||||
@ -1326,10 +1298,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
||||
(void *)(uintptr_t)le32_to_cpu(tx_resp->initial_rate);
|
||||
|
||||
/* Single frame failure in an AMPDU queue => send BAR */
|
||||
if (txq_id >= mvm->first_agg_queue &&
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU &&
|
||||
!(info->flags & IEEE80211_TX_STAT_ACK) &&
|
||||
!(info->flags & IEEE80211_TX_STAT_TX_FILTERED))
|
||||
info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
|
||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
|
||||
/* W/A FW bug: seq_ctl is wrong when the status isn't success */
|
||||
if (status != TX_STATUS_SUCCESS) {
|
||||
@ -1364,7 +1337,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
||||
ieee80211_tx_status(mvm->hw, skb);
|
||||
}
|
||||
|
||||
if (txq_id >= mvm->first_agg_queue) {
|
||||
if (iwl_mvm_is_dqa_supported(mvm) || txq_id >= mvm->first_agg_queue) {
|
||||
/* If this is an aggregation queue, we use the ssn since:
|
||||
* ssn = wifi seq_num % 256.
|
||||
* The seq_ctl is the sequence control of the packet to which
|
||||
|
@ -497,13 +497,11 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm)
|
||||
IWL_ERR(mvm, "0x%08X | isr status reg\n", table.nic_isr_pref);
|
||||
}
|
||||
|
||||
void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
||||
static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u32 base)
|
||||
{
|
||||
struct iwl_trans *trans = mvm->trans;
|
||||
struct iwl_error_event_table table;
|
||||
u32 base;
|
||||
|
||||
base = mvm->error_event_table;
|
||||
if (mvm->cur_ucode == IWL_UCODE_INIT) {
|
||||
if (!base)
|
||||
base = mvm->fw->init_errlog_ptr;
|
||||
@ -574,6 +572,14 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
||||
IWL_ERR(mvm, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel);
|
||||
IWL_ERR(mvm, "0x%08X | timestamp\n", table.u_timestamp);
|
||||
IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler);
|
||||
}
|
||||
|
||||
void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
||||
{
|
||||
iwl_mvm_dump_lmac_error_log(mvm, mvm->error_event_table[0]);
|
||||
|
||||
if (mvm->error_event_table[1])
|
||||
iwl_mvm_dump_lmac_error_log(mvm, mvm->error_event_table[1]);
|
||||
|
||||
if (mvm->support_umac_log)
|
||||
iwl_mvm_dump_umac_error_log(mvm);
|
||||
@ -649,8 +655,8 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
|
||||
/* Make sure this TID isn't already enabled */
|
||||
if (mvm->queue_info[queue].tid_bitmap & BIT(cfg->tid)) {
|
||||
spin_unlock_bh(&mvm->queue_info_lock);
|
||||
IWL_ERR(mvm, "Trying to enable TXQ with existing TID %d\n",
|
||||
cfg->tid);
|
||||
IWL_ERR(mvm, "Trying to enable TXQ %d with existing TID %d\n",
|
||||
queue, cfg->tid);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -533,7 +533,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
||||
{IWL_PCI_DEVICE(0xA370, 0x1030, iwl9560_2ac_cfg)},
|
||||
|
||||
/* a000 Series */
|
||||
{IWL_PCI_DEVICE(0x2720, 0x0A10, iwla000_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x2720, 0x0A10, iwla000_2ac_cfg_hr)},
|
||||
#endif /* CONFIG_IWLMVM */
|
||||
|
||||
{0}
|
||||
@ -673,11 +673,17 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
cfg = &iwl9000lc_2ac_cfg;
|
||||
iwl_trans->cfg = cfg;
|
||||
}
|
||||
|
||||
if (cfg == &iwla000_2ac_cfg_hr &&
|
||||
iwl_trans->hw_rf_id == CSR_HW_RF_ID_TYPE_JF) {
|
||||
cfg = &iwla000_2ac_cfg_jf;
|
||||
iwl_trans->cfg = cfg;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pci_set_drvdata(pdev, iwl_trans);
|
||||
iwl_trans->drv = iwl_drv_start(iwl_trans, cfg);
|
||||
iwl_trans->drv = iwl_drv_start(iwl_trans);
|
||||
|
||||
if (IS_ERR(iwl_trans->drv)) {
|
||||
ret = PTR_ERR(iwl_trans->drv);
|
||||
@ -778,13 +784,14 @@ static int iwl_pci_resume(struct device *device)
|
||||
|
||||
/*
|
||||
* Enable rfkill interrupt (in order to keep track of
|
||||
* the rfkill status)
|
||||
* the rfkill status). Must be locked to avoid processing
|
||||
* a possible rfkill interrupt between reading the state
|
||||
* and calling iwl_trans_pcie_rf_kill() with it.
|
||||
*/
|
||||
mutex_lock(&trans_pcie->mutex);
|
||||
iwl_enable_rfkill_int(trans);
|
||||
|
||||
hw_rfkill = iwl_is_rfkill_set(trans);
|
||||
|
||||
mutex_lock(&trans_pcie->mutex);
|
||||
iwl_trans_pcie_rf_kill(trans, hw_rfkill);
|
||||
mutex_unlock(&trans_pcie->mutex);
|
||||
|
||||
|
@ -279,7 +279,7 @@ struct iwl_txq {
|
||||
bool frozen;
|
||||
u8 active;
|
||||
bool ampdu;
|
||||
bool block;
|
||||
int block;
|
||||
unsigned long wd_timeout;
|
||||
struct sk_buff_head overflow_q;
|
||||
|
||||
@ -670,6 +670,8 @@ static inline u8 get_cmd_index(struct iwl_txq *q, u32 index)
|
||||
|
||||
static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
|
||||
{
|
||||
lockdep_assert_held(&IWL_TRANS_GET_PCIE_TRANS(trans)->mutex);
|
||||
|
||||
return !(iwl_read32(trans, CSR_GP_CNTRL) &
|
||||
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
|
||||
}
|
||||
|
@ -1607,17 +1607,19 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
|
||||
if (inta & CSR_INT_BIT_RF_KILL) {
|
||||
bool hw_rfkill;
|
||||
|
||||
mutex_lock(&trans_pcie->mutex);
|
||||
hw_rfkill = iwl_is_rfkill_set(trans);
|
||||
if (hw_rfkill)
|
||||
set_bit(STATUS_RFKILL, &trans->status);
|
||||
|
||||
IWL_WARN(trans, "RF_KILL bit toggled to %s.\n",
|
||||
hw_rfkill ? "disable radio" : "enable radio");
|
||||
|
||||
isr_stats->rfkill++;
|
||||
|
||||
mutex_lock(&trans_pcie->mutex);
|
||||
iwl_trans_pcie_rf_kill(trans, hw_rfkill);
|
||||
mutex_unlock(&trans_pcie->mutex);
|
||||
if (hw_rfkill) {
|
||||
set_bit(STATUS_RFKILL, &trans->status);
|
||||
if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE,
|
||||
&trans->status))
|
||||
IWL_DEBUG_RF_KILL(trans,
|
||||
@ -1952,17 +1954,19 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
|
||||
if (inta_hw & MSIX_HW_INT_CAUSES_REG_RF_KILL) {
|
||||
bool hw_rfkill;
|
||||
|
||||
mutex_lock(&trans_pcie->mutex);
|
||||
hw_rfkill = iwl_is_rfkill_set(trans);
|
||||
if (hw_rfkill)
|
||||
set_bit(STATUS_RFKILL, &trans->status);
|
||||
|
||||
IWL_WARN(trans, "RF_KILL bit toggled to %s.\n",
|
||||
hw_rfkill ? "disable radio" : "enable radio");
|
||||
|
||||
isr_stats->rfkill++;
|
||||
|
||||
mutex_lock(&trans_pcie->mutex);
|
||||
iwl_trans_pcie_rf_kill(trans, hw_rfkill);
|
||||
mutex_unlock(&trans_pcie->mutex);
|
||||
if (hw_rfkill) {
|
||||
set_bit(STATUS_RFKILL, &trans->status);
|
||||
if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE,
|
||||
&trans->status))
|
||||
IWL_DEBUG_RF_KILL(trans,
|
||||
|
@ -1076,6 +1076,123 @@ static bool iwl_trans_check_hw_rf_kill(struct iwl_trans *trans)
|
||||
return hw_rfkill;
|
||||
}
|
||||
|
||||
struct iwl_causes_list {
|
||||
u32 cause_num;
|
||||
u32 mask_reg;
|
||||
u8 addr;
|
||||
};
|
||||
|
||||
static struct iwl_causes_list causes_list[] = {
|
||||
{MSIX_FH_INT_CAUSES_D2S_CH0_NUM, CSR_MSIX_FH_INT_MASK_AD, 0},
|
||||
{MSIX_FH_INT_CAUSES_D2S_CH1_NUM, CSR_MSIX_FH_INT_MASK_AD, 0x1},
|
||||
{MSIX_FH_INT_CAUSES_S2D, CSR_MSIX_FH_INT_MASK_AD, 0x3},
|
||||
{MSIX_FH_INT_CAUSES_FH_ERR, CSR_MSIX_FH_INT_MASK_AD, 0x5},
|
||||
{MSIX_HW_INT_CAUSES_REG_ALIVE, CSR_MSIX_HW_INT_MASK_AD, 0x10},
|
||||
{MSIX_HW_INT_CAUSES_REG_WAKEUP, CSR_MSIX_HW_INT_MASK_AD, 0x11},
|
||||
{MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16},
|
||||
{MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17},
|
||||
{MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18},
|
||||
{MSIX_HW_INT_CAUSES_REG_SW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x29},
|
||||
{MSIX_HW_INT_CAUSES_REG_SCD, CSR_MSIX_HW_INT_MASK_AD, 0x2A},
|
||||
{MSIX_HW_INT_CAUSES_REG_FH_TX, CSR_MSIX_HW_INT_MASK_AD, 0x2B},
|
||||
{MSIX_HW_INT_CAUSES_REG_HW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x2D},
|
||||
{MSIX_HW_INT_CAUSES_REG_HAP, CSR_MSIX_HW_INT_MASK_AD, 0x2E},
|
||||
};
|
||||
|
||||
static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Access all non RX causes and map them to the default irq.
|
||||
* In case we are missing at least one interrupt vector,
|
||||
* the first interrupt vector will serve non-RX and FBQ causes.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(causes_list); i++) {
|
||||
iwl_write8(trans, CSR_MSIX_IVAR(causes_list[i].addr), val);
|
||||
iwl_clear_bit(trans, causes_list[i].mask_reg,
|
||||
causes_list[i].cause_num);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_pcie_map_rx_causes(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
u32 offset =
|
||||
trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_FIRST_RSS ? 1 : 0;
|
||||
u32 val, idx;
|
||||
|
||||
/*
|
||||
* The first RX queue - fallback queue, which is designated for
|
||||
* management frame, command responses etc, is always mapped to the
|
||||
* first interrupt vector. The other RX queues are mapped to
|
||||
* the other (N - 2) interrupt vectors.
|
||||
*/
|
||||
val = BIT(MSIX_FH_INT_CAUSES_Q(0));
|
||||
for (idx = 1; idx < trans->num_rx_queues; idx++) {
|
||||
iwl_write8(trans, CSR_MSIX_RX_IVAR(idx),
|
||||
MSIX_FH_INT_CAUSES_Q(idx - offset));
|
||||
val |= BIT(MSIX_FH_INT_CAUSES_Q(idx));
|
||||
}
|
||||
iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, ~val);
|
||||
|
||||
val = MSIX_FH_INT_CAUSES_Q(0);
|
||||
if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX)
|
||||
val |= MSIX_NON_AUTO_CLEAR_CAUSE;
|
||||
iwl_write8(trans, CSR_MSIX_RX_IVAR(0), val);
|
||||
|
||||
if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_FIRST_RSS)
|
||||
iwl_write8(trans, CSR_MSIX_RX_IVAR(1), val);
|
||||
}
|
||||
|
||||
static void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie)
|
||||
{
|
||||
struct iwl_trans *trans = trans_pcie->trans;
|
||||
|
||||
if (!trans_pcie->msix_enabled) {
|
||||
if (trans->cfg->mq_rx_supported &&
|
||||
test_bit(STATUS_DEVICE_ENABLED, &trans->status))
|
||||
iwl_write_prph(trans, UREG_CHICK,
|
||||
UREG_CHICK_MSI_ENABLE);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* The IVAR table needs to be configured again after reset,
|
||||
* but if the device is disabled, we can't write to
|
||||
* prph.
|
||||
*/
|
||||
if (test_bit(STATUS_DEVICE_ENABLED, &trans->status))
|
||||
iwl_write_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE);
|
||||
|
||||
/*
|
||||
* Each cause from the causes list above and the RX causes is
|
||||
* represented as a byte in the IVAR table. The first nibble
|
||||
* represents the bound interrupt vector of the cause, the second
|
||||
* represents no auto clear for this cause. This will be set if its
|
||||
* interrupt vector is bound to serve other causes.
|
||||
*/
|
||||
iwl_pcie_map_rx_causes(trans);
|
||||
|
||||
iwl_pcie_map_non_rx_causes(trans);
|
||||
}
|
||||
|
||||
static void iwl_pcie_init_msix(struct iwl_trans_pcie *trans_pcie)
|
||||
{
|
||||
struct iwl_trans *trans = trans_pcie->trans;
|
||||
|
||||
iwl_pcie_conf_msix_hw(trans_pcie);
|
||||
|
||||
if (!trans_pcie->msix_enabled)
|
||||
return;
|
||||
|
||||
trans_pcie->fh_init_mask = ~iwl_read32(trans, CSR_MSIX_FH_INT_MASK_AD);
|
||||
trans_pcie->fh_mask = trans_pcie->fh_init_mask;
|
||||
trans_pcie->hw_init_mask = ~iwl_read32(trans, CSR_MSIX_HW_INT_MASK_AD);
|
||||
trans_pcie->hw_mask = trans_pcie->hw_init_mask;
|
||||
}
|
||||
|
||||
static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
@ -1128,6 +1245,15 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
|
||||
iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
/*
|
||||
* Upon stop, the IVAR table gets erased, so msi-x won't
|
||||
* work. This causes a bug in RF-KILL flows, since the interrupt
|
||||
* that enables radio won't fire on the correct irq, and the
|
||||
* driver won't be able to handle the interrupt.
|
||||
* Configure the IVAR table again after reset.
|
||||
*/
|
||||
iwl_pcie_conf_msix_hw(trans_pcie);
|
||||
|
||||
/*
|
||||
* Upon stop, the APM issues an interrupt if HW RF kill is set.
|
||||
* This is a bug in certain verions of the hardware.
|
||||
@ -1346,6 +1472,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
||||
enum iwl_d3_status *status,
|
||||
bool test, bool reset)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
@ -1358,11 +1485,15 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
||||
iwl_pcie_enable_rx_wake(trans, true);
|
||||
|
||||
/*
|
||||
* Also enables interrupts - none will happen as the device doesn't
|
||||
* know we're waking it up, only when the opmode actually tells it
|
||||
* after this call.
|
||||
* Reconfigure IVAR table in case of MSIX or reset ict table in
|
||||
* MSI mode since HW reset erased it.
|
||||
* Also enables interrupts - none will happen as
|
||||
* the device doesn't know we're waking it up, only when
|
||||
* the opmode actually tells it after this call.
|
||||
*/
|
||||
iwl_pcie_reset_ict(trans);
|
||||
iwl_pcie_conf_msix_hw(trans_pcie);
|
||||
if (!trans_pcie->msix_enabled)
|
||||
iwl_pcie_reset_ict(trans);
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
@ -1405,109 +1536,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct iwl_causes_list {
|
||||
u32 cause_num;
|
||||
u32 mask_reg;
|
||||
u8 addr;
|
||||
};
|
||||
|
||||
static struct iwl_causes_list causes_list[] = {
|
||||
{MSIX_FH_INT_CAUSES_D2S_CH0_NUM, CSR_MSIX_FH_INT_MASK_AD, 0},
|
||||
{MSIX_FH_INT_CAUSES_D2S_CH1_NUM, CSR_MSIX_FH_INT_MASK_AD, 0x1},
|
||||
{MSIX_FH_INT_CAUSES_S2D, CSR_MSIX_FH_INT_MASK_AD, 0x3},
|
||||
{MSIX_FH_INT_CAUSES_FH_ERR, CSR_MSIX_FH_INT_MASK_AD, 0x5},
|
||||
{MSIX_HW_INT_CAUSES_REG_ALIVE, CSR_MSIX_HW_INT_MASK_AD, 0x10},
|
||||
{MSIX_HW_INT_CAUSES_REG_WAKEUP, CSR_MSIX_HW_INT_MASK_AD, 0x11},
|
||||
{MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16},
|
||||
{MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17},
|
||||
{MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18},
|
||||
{MSIX_HW_INT_CAUSES_REG_SW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x29},
|
||||
{MSIX_HW_INT_CAUSES_REG_SCD, CSR_MSIX_HW_INT_MASK_AD, 0x2A},
|
||||
{MSIX_HW_INT_CAUSES_REG_FH_TX, CSR_MSIX_HW_INT_MASK_AD, 0x2B},
|
||||
{MSIX_HW_INT_CAUSES_REG_HW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x2D},
|
||||
{MSIX_HW_INT_CAUSES_REG_HAP, CSR_MSIX_HW_INT_MASK_AD, 0x2E},
|
||||
};
|
||||
|
||||
static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Access all non RX causes and map them to the default irq.
|
||||
* In case we are missing at least one interrupt vector,
|
||||
* the first interrupt vector will serve non-RX and FBQ causes.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(causes_list); i++) {
|
||||
iwl_write8(trans, CSR_MSIX_IVAR(causes_list[i].addr), val);
|
||||
iwl_clear_bit(trans, causes_list[i].mask_reg,
|
||||
causes_list[i].cause_num);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_pcie_map_rx_causes(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
u32 offset =
|
||||
trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_FIRST_RSS ? 1 : 0;
|
||||
u32 val, idx;
|
||||
|
||||
/*
|
||||
* The first RX queue - fallback queue, which is designated for
|
||||
* management frame, command responses etc, is always mapped to the
|
||||
* first interrupt vector. The other RX queues are mapped to
|
||||
* the other (N - 2) interrupt vectors.
|
||||
*/
|
||||
val = BIT(MSIX_FH_INT_CAUSES_Q(0));
|
||||
for (idx = 1; idx < trans->num_rx_queues; idx++) {
|
||||
iwl_write8(trans, CSR_MSIX_RX_IVAR(idx),
|
||||
MSIX_FH_INT_CAUSES_Q(idx - offset));
|
||||
val |= BIT(MSIX_FH_INT_CAUSES_Q(idx));
|
||||
}
|
||||
iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, ~val);
|
||||
|
||||
val = MSIX_FH_INT_CAUSES_Q(0);
|
||||
if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX)
|
||||
val |= MSIX_NON_AUTO_CLEAR_CAUSE;
|
||||
iwl_write8(trans, CSR_MSIX_RX_IVAR(0), val);
|
||||
|
||||
if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_FIRST_RSS)
|
||||
iwl_write8(trans, CSR_MSIX_RX_IVAR(1), val);
|
||||
}
|
||||
|
||||
static void iwl_pcie_init_msix(struct iwl_trans_pcie *trans_pcie)
|
||||
{
|
||||
struct iwl_trans *trans = trans_pcie->trans;
|
||||
|
||||
if (!trans_pcie->msix_enabled) {
|
||||
if (trans->cfg->mq_rx_supported)
|
||||
iwl_write_prph(trans, UREG_CHICK,
|
||||
UREG_CHICK_MSI_ENABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
iwl_write_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE);
|
||||
|
||||
/*
|
||||
* Each cause from the causes list above and the RX causes is
|
||||
* represented as a byte in the IVAR table. The first nibble
|
||||
* represents the bound interrupt vector of the cause, the second
|
||||
* represents no auto clear for this cause. This will be set if its
|
||||
* interrupt vector is bound to serve other causes.
|
||||
*/
|
||||
iwl_pcie_map_rx_causes(trans);
|
||||
|
||||
iwl_pcie_map_non_rx_causes(trans);
|
||||
|
||||
trans_pcie->fh_init_mask =
|
||||
~iwl_read32(trans, CSR_MSIX_FH_INT_MASK_AD);
|
||||
trans_pcie->fh_mask = trans_pcie->fh_init_mask;
|
||||
trans_pcie->hw_init_mask =
|
||||
~iwl_read32(trans, CSR_MSIX_HW_INT_MASK_AD);
|
||||
trans_pcie->hw_mask = trans_pcie->hw_init_mask;
|
||||
}
|
||||
|
||||
static void iwl_pcie_set_interrupt_capa(struct pci_dev *pdev,
|
||||
struct iwl_trans *trans)
|
||||
{
|
||||
@ -1675,6 +1703,7 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
|
||||
iwl_pcie_apm_init(trans);
|
||||
|
||||
iwl_pcie_init_msix(trans_pcie);
|
||||
|
||||
/* From now on, the op_mode will be kept updated about RF kill state */
|
||||
iwl_enable_rfkill_int(trans);
|
||||
|
||||
@ -2953,16 +2982,12 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
PCIE_LINK_STATE_CLKPM);
|
||||
}
|
||||
|
||||
if (cfg->mq_rx_supported)
|
||||
addr_size = 64;
|
||||
else
|
||||
addr_size = 36;
|
||||
|
||||
if (cfg->use_tfh) {
|
||||
addr_size = 64;
|
||||
trans_pcie->max_tbs = IWL_TFH_NUM_TBS;
|
||||
trans_pcie->tfd_size = sizeof(struct iwl_tfh_tfd);
|
||||
|
||||
} else {
|
||||
addr_size = 36;
|
||||
trans_pcie->max_tbs = IWL_NUM_OF_TBS;
|
||||
trans_pcie->tfd_size = sizeof(struct iwl_tfd);
|
||||
}
|
||||
|
@ -2096,6 +2096,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
struct iwl_cmd_meta *out_meta,
|
||||
struct iwl_device_cmd *dev_cmd, u16 tb1_len)
|
||||
{
|
||||
struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
|
||||
struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room;
|
||||
@ -2145,6 +2146,13 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
*/
|
||||
skb_pull(skb, hdr_len + iv_len);
|
||||
|
||||
/*
|
||||
* Remove the length of all the headers that we don't actually
|
||||
* have in the MPDU by themselves, but that we duplicate into
|
||||
* all the different MSDUs inside the A-MSDU.
|
||||
*/
|
||||
le16_add_cpu(&tx_cmd->len, -snap_ip_tcp_hdrlen);
|
||||
|
||||
tso_start(skb, &tso);
|
||||
|
||||
while (total_len) {
|
||||
@ -2155,7 +2163,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
unsigned int hdr_tb_len;
|
||||
dma_addr_t hdr_tb_phys;
|
||||
struct tcphdr *tcph;
|
||||
u8 *iph;
|
||||
u8 *iph, *subf_hdrs_start = hdr_page->pos;
|
||||
|
||||
total_len -= data_left;
|
||||
|
||||
@ -2216,6 +2224,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
hdr_tb_len, false);
|
||||
trace_iwlwifi_dev_tx_tso_chunk(trans->dev, start_hdr,
|
||||
hdr_tb_len);
|
||||
/* add this subframe's headers' length to the tx_cmd */
|
||||
le16_add_cpu(&tx_cmd->len, hdr_page->pos - subf_hdrs_start);
|
||||
|
||||
/* prepare the start_hdr for the next subframe */
|
||||
start_hdr = hdr_page->pos;
|
||||
@ -2408,9 +2418,10 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
tb1_len = len;
|
||||
}
|
||||
|
||||
/* The first TB points to bi-directional DMA data */
|
||||
memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
|
||||
IWL_FIRST_TB_SIZE);
|
||||
/*
|
||||
* The first TB points to bi-directional DMA data, we'll
|
||||
* memcpy the data into it later.
|
||||
*/
|
||||
iwl_pcie_txq_build_tfd(trans, txq, tb0_phys,
|
||||
IWL_FIRST_TB_SIZE, true);
|
||||
|
||||
@ -2434,6 +2445,10 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* building the A-MSDU might have changed this data, so memcpy it now */
|
||||
memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
|
||||
IWL_FIRST_TB_SIZE);
|
||||
|
||||
tfd = iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr);
|
||||
/* Set up entry for this TFD in Tx byte-count array */
|
||||
iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len),
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <linux/timer.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <uapi/linux/if_arp.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#define MWIFIEX_BSS_COEX_COUNT 2
|
||||
#define MWIFIEX_MAX_BSS_NUM (3)
|
||||
|
@ -1159,8 +1159,6 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
|
||||
encrypt_key.is_rx_seq_valid = true;
|
||||
}
|
||||
} else {
|
||||
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
|
||||
return 0;
|
||||
encrypt_key.key_disable = true;
|
||||
if (mac_addr)
|
||||
memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
|
||||
|
@ -1200,7 +1200,7 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
|
||||
/*
|
||||
* Dump beacon to userspace through debugfs.
|
||||
*/
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry);
|
||||
out:
|
||||
/*
|
||||
* Enable beaconing again.
|
||||
|
@ -1349,7 +1349,7 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
|
||||
/*
|
||||
* Dump beacon to userspace through debugfs.
|
||||
*/
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry);
|
||||
out:
|
||||
/*
|
||||
* Enable beaconing again.
|
||||
|
@ -1170,7 +1170,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry,
|
||||
/*
|
||||
* Dump beacon to userspace through debugfs.
|
||||
*/
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry);
|
||||
|
||||
/*
|
||||
* USB devices cannot blindly pass the skb->len as the
|
||||
|
@ -1014,7 +1014,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
|
||||
/*
|
||||
* Dump beacon to userspace through debugfs.
|
||||
*/
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry);
|
||||
|
||||
/*
|
||||
* Write entire beacon with TXWI and padding to register.
|
||||
|
@ -1400,11 +1400,11 @@ void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop);
|
||||
*/
|
||||
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
|
||||
void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
|
||||
enum rt2x00_dump_type type, struct sk_buff *skb);
|
||||
enum rt2x00_dump_type type, struct queue_entry *entry);
|
||||
#else
|
||||
static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
|
||||
enum rt2x00_dump_type type,
|
||||
struct sk_buff *skb)
|
||||
struct queue_entry *entry)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
|
||||
|
@ -157,9 +157,10 @@ void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
|
||||
}
|
||||
|
||||
void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
|
||||
enum rt2x00_dump_type type, struct sk_buff *skb)
|
||||
enum rt2x00_dump_type type, struct queue_entry *entry)
|
||||
{
|
||||
struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
|
||||
struct sk_buff *skb = entry->skb;
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
|
||||
struct sk_buff *skbcopy;
|
||||
struct rt2x00dump_hdr *dump_hdr;
|
||||
@ -196,8 +197,8 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
|
||||
dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
|
||||
dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev);
|
||||
dump_hdr->type = cpu_to_le16(type);
|
||||
dump_hdr->queue_index = skbdesc->entry->queue->qid;
|
||||
dump_hdr->entry_index = skbdesc->entry->entry_idx;
|
||||
dump_hdr->queue_index = entry->queue->qid;
|
||||
dump_hdr->entry_index = entry->entry_idx;
|
||||
dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
|
||||
dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
|
||||
|
||||
|
@ -363,7 +363,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
|
||||
* Send frame to debugfs immediately, after this call is completed
|
||||
* we are going to overwrite the skb->cb array.
|
||||
*/
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb);
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry);
|
||||
|
||||
/*
|
||||
* Determine if the frame has been successfully transmitted and
|
||||
@ -772,7 +772,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
|
||||
*/
|
||||
rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc);
|
||||
rt2x00debug_update_crypto(rt2x00dev, &rxdesc);
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry);
|
||||
|
||||
/*
|
||||
* Initialize RX status information, and send frame
|
||||
@ -1436,21 +1436,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
|
||||
cancel_work_sync(&rt2x00dev->intf_work);
|
||||
cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
|
||||
cancel_work_sync(&rt2x00dev->sleep_work);
|
||||
#if IS_ENABLED(CONFIG_RT2X00_LIB_USB)
|
||||
if (rt2x00_is_usb(rt2x00dev)) {
|
||||
usb_kill_anchored_urbs(rt2x00dev->anchor);
|
||||
hrtimer_cancel(&rt2x00dev->txstatus_timer);
|
||||
cancel_work_sync(&rt2x00dev->rxdone_work);
|
||||
cancel_work_sync(&rt2x00dev->txdone_work);
|
||||
}
|
||||
#endif
|
||||
if (rt2x00dev->workqueue)
|
||||
destroy_workqueue(rt2x00dev->workqueue);
|
||||
|
||||
/*
|
||||
* Free the tx status fifo.
|
||||
*/
|
||||
kfifo_free(&rt2x00dev->txstatus_fifo);
|
||||
|
||||
/*
|
||||
* Kill the tx status tasklet.
|
||||
@ -1466,6 +1451,14 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
|
||||
*/
|
||||
rt2x00lib_uninitialize(rt2x00dev);
|
||||
|
||||
if (rt2x00dev->workqueue)
|
||||
destroy_workqueue(rt2x00dev->workqueue);
|
||||
|
||||
/*
|
||||
* Free the tx status fifo.
|
||||
*/
|
||||
kfifo_free(&rt2x00dev->txstatus_fifo);
|
||||
|
||||
/*
|
||||
* Free extra components
|
||||
*/
|
||||
|
@ -83,7 +83,6 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp)
|
||||
*/
|
||||
skbdesc = get_skb_frame_desc(skb);
|
||||
memset(skbdesc, 0, sizeof(*skbdesc));
|
||||
skbdesc->entry = entry;
|
||||
|
||||
if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DMA)) {
|
||||
dma_addr_t skb_dma;
|
||||
@ -544,7 +543,7 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
|
||||
* All processing on the frame has been completed, this means
|
||||
* it is now ready to be dumped to userspace through debugfs.
|
||||
*/
|
||||
rt2x00debug_dump_frame(queue->rt2x00dev, DUMP_FRAME_TX, entry->skb);
|
||||
rt2x00debug_dump_frame(queue->rt2x00dev, DUMP_FRAME_TX, entry);
|
||||
}
|
||||
|
||||
static void rt2x00queue_kick_tx_queue(struct data_queue *queue,
|
||||
@ -689,7 +688,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
|
||||
goto out;
|
||||
}
|
||||
|
||||
skbdesc->entry = entry;
|
||||
entry->skb = skb;
|
||||
|
||||
/*
|
||||
@ -774,7 +772,6 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
|
||||
*/
|
||||
skbdesc = get_skb_frame_desc(intf->beacon->skb);
|
||||
memset(skbdesc, 0, sizeof(*skbdesc));
|
||||
skbdesc->entry = intf->beacon;
|
||||
|
||||
/*
|
||||
* Send beacon to hardware.
|
||||
|
@ -116,8 +116,6 @@ struct skb_frame_desc {
|
||||
__le32 iv[2];
|
||||
|
||||
dma_addr_t skb_dma;
|
||||
|
||||
struct queue_entry *entry;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -319,10 +319,8 @@ static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void *data)
|
||||
entry->skb->data, length,
|
||||
rt2x00usb_interrupt_txdone, entry);
|
||||
|
||||
usb_anchor_urb(entry_priv->urb, rt2x00dev->anchor);
|
||||
status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
|
||||
if (status) {
|
||||
usb_unanchor_urb(entry_priv->urb);
|
||||
if (status == -ENODEV)
|
||||
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
|
||||
@ -410,10 +408,8 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void *data)
|
||||
entry->skb->data, entry->skb->len,
|
||||
rt2x00usb_interrupt_rxdone, entry);
|
||||
|
||||
usb_anchor_urb(entry_priv->urb, rt2x00dev->anchor);
|
||||
status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
|
||||
if (status) {
|
||||
usb_unanchor_urb(entry_priv->urb);
|
||||
if (status == -ENODEV)
|
||||
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
|
||||
@ -744,6 +740,11 @@ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct data_queue *queue;
|
||||
|
||||
usb_kill_anchored_urbs(rt2x00dev->anchor);
|
||||
hrtimer_cancel(&rt2x00dev->txstatus_timer);
|
||||
cancel_work_sync(&rt2x00dev->rxdone_work);
|
||||
cancel_work_sync(&rt2x00dev->txdone_work);
|
||||
|
||||
queue_for_each(rt2x00dev, queue)
|
||||
rt2x00usb_free_entries(queue);
|
||||
}
|
||||
@ -824,10 +825,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
|
||||
if (retval)
|
||||
goto exit_free_device;
|
||||
|
||||
retval = rt2x00lib_probe_dev(rt2x00dev);
|
||||
if (retval)
|
||||
goto exit_free_reg;
|
||||
|
||||
rt2x00dev->anchor = devm_kmalloc(&usb_dev->dev,
|
||||
sizeof(struct usb_anchor),
|
||||
GFP_KERNEL);
|
||||
@ -835,10 +832,17 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
|
||||
retval = -ENOMEM;
|
||||
goto exit_free_reg;
|
||||
}
|
||||
|
||||
init_usb_anchor(rt2x00dev->anchor);
|
||||
|
||||
retval = rt2x00lib_probe_dev(rt2x00dev);
|
||||
if (retval)
|
||||
goto exit_free_anchor;
|
||||
|
||||
return 0;
|
||||
|
||||
exit_free_anchor:
|
||||
usb_kill_anchored_urbs(rt2x00dev->anchor);
|
||||
|
||||
exit_free_reg:
|
||||
rt2x00usb_free_reg(rt2x00dev);
|
||||
|
||||
|
@ -1903,8 +1903,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
|
||||
|
||||
rt2x00_desc_read(txd, 5, &word);
|
||||
rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
|
||||
rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE,
|
||||
skbdesc->entry->entry_idx);
|
||||
rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx);
|
||||
rt2x00_set_field32(&word, TXD_W5_TX_POWER,
|
||||
TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power));
|
||||
rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
|
||||
@ -1989,7 +1988,7 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
|
||||
/*
|
||||
* Dump beacon to userspace through debugfs.
|
||||
*/
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry);
|
||||
|
||||
/*
|
||||
* Write entire beacon with descriptor and padding to register.
|
||||
|
@ -1557,7 +1557,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
|
||||
/*
|
||||
* Dump beacon to userspace through debugfs.
|
||||
*/
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry);
|
||||
|
||||
/*
|
||||
* Write entire beacon with descriptor and padding to register.
|
||||
|
@ -475,6 +475,8 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
|
||||
(void *)rtl_swlps_rfon_wq_callback);
|
||||
INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq,
|
||||
(void *)rtl_fwevt_wq_callback);
|
||||
INIT_DELAYED_WORK(&rtlpriv->works.c2hcmd_wq,
|
||||
(void *)rtl_c2hcmd_wq_callback);
|
||||
|
||||
}
|
||||
|
||||
@ -489,6 +491,7 @@ void rtl_deinit_deferred_work(struct ieee80211_hw *hw)
|
||||
cancel_delayed_work(&rtlpriv->works.ps_work);
|
||||
cancel_delayed_work(&rtlpriv->works.ps_rfon_wq);
|
||||
cancel_delayed_work(&rtlpriv->works.fwevt_wq);
|
||||
cancel_delayed_work(&rtlpriv->works.c2hcmd_wq);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rtl_deinit_deferred_work);
|
||||
|
||||
@ -556,6 +559,7 @@ int rtl_init_core(struct ieee80211_hw *hw)
|
||||
spin_lock_init(&rtlpriv->locks.rf_lock);
|
||||
spin_lock_init(&rtlpriv->locks.waitq_lock);
|
||||
spin_lock_init(&rtlpriv->locks.entry_list_lock);
|
||||
spin_lock_init(&rtlpriv->locks.c2hcmd_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);
|
||||
@ -563,6 +567,7 @@ int rtl_init_core(struct ieee80211_hw *hw)
|
||||
spin_lock_init(&rtlpriv->locks.iqk_lock);
|
||||
/* <5> init list */
|
||||
INIT_LIST_HEAD(&rtlpriv->entry_list);
|
||||
INIT_LIST_HEAD(&rtlpriv->c2hcmd_list);
|
||||
|
||||
rtlmac->link_state = MAC80211_NOLINK;
|
||||
|
||||
@ -575,6 +580,7 @@ EXPORT_SYMBOL_GPL(rtl_init_core);
|
||||
|
||||
void rtl_deinit_core(struct ieee80211_hw *hw)
|
||||
{
|
||||
rtl_c2hcmd_launcher(hw, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rtl_deinit_core);
|
||||
|
||||
@ -1729,6 +1735,93 @@ void rtl_fwevt_wq_callback(void *data)
|
||||
|
||||
rtlpriv->cfg->ops->c2h_command_handle(hw);
|
||||
}
|
||||
|
||||
void rtl_c2hcmd_enqueue(struct ieee80211_hw *hw, u8 tag, u8 len, u8 *val)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
unsigned long flags;
|
||||
struct rtl_c2hcmd *c2hcmd;
|
||||
|
||||
c2hcmd = kmalloc(sizeof(*c2hcmd), GFP_KERNEL);
|
||||
|
||||
if (!c2hcmd)
|
||||
goto label_err;
|
||||
|
||||
c2hcmd->val = kmalloc(len, GFP_KERNEL);
|
||||
|
||||
if (!c2hcmd->val)
|
||||
goto label_err2;
|
||||
|
||||
/* fill data */
|
||||
c2hcmd->tag = tag;
|
||||
c2hcmd->len = len;
|
||||
memcpy(c2hcmd->val, val, len);
|
||||
|
||||
/* enqueue */
|
||||
spin_lock_irqsave(&rtlpriv->locks.c2hcmd_lock, flags);
|
||||
|
||||
list_add_tail(&c2hcmd->list, &rtlpriv->c2hcmd_list);
|
||||
|
||||
spin_unlock_irqrestore(&rtlpriv->locks.c2hcmd_lock, flags);
|
||||
|
||||
/* wake up wq */
|
||||
queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.c2hcmd_wq, 0);
|
||||
|
||||
return;
|
||||
|
||||
label_err2:
|
||||
kfree(c2hcmd);
|
||||
|
||||
label_err:
|
||||
RT_TRACE(rtlpriv, COMP_CMD, DBG_WARNING,
|
||||
"C2H cmd enqueue fail.\n");
|
||||
}
|
||||
EXPORT_SYMBOL(rtl_c2hcmd_enqueue);
|
||||
|
||||
void rtl_c2hcmd_launcher(struct ieee80211_hw *hw, int exec)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
unsigned long flags;
|
||||
struct rtl_c2hcmd *c2hcmd;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 200; i++) {
|
||||
/* dequeue a task */
|
||||
spin_lock_irqsave(&rtlpriv->locks.c2hcmd_lock, flags);
|
||||
|
||||
c2hcmd = list_first_entry_or_null(&rtlpriv->c2hcmd_list,
|
||||
struct rtl_c2hcmd, list);
|
||||
|
||||
if (c2hcmd)
|
||||
list_del(&c2hcmd->list);
|
||||
|
||||
spin_unlock_irqrestore(&rtlpriv->locks.c2hcmd_lock, flags);
|
||||
|
||||
/* do it */
|
||||
if (!c2hcmd)
|
||||
break;
|
||||
|
||||
if (rtlpriv->cfg->ops->c2h_content_parsing && exec)
|
||||
rtlpriv->cfg->ops->c2h_content_parsing(hw,
|
||||
c2hcmd->tag, c2hcmd->len, c2hcmd->val);
|
||||
|
||||
/* free */
|
||||
kfree(c2hcmd->val);
|
||||
|
||||
kfree(c2hcmd);
|
||||
}
|
||||
}
|
||||
|
||||
void rtl_c2hcmd_wq_callback(void *data)
|
||||
{
|
||||
struct rtl_works *rtlworks = container_of_dwork_rtl(data,
|
||||
struct rtl_works,
|
||||
c2hcmd_wq);
|
||||
struct ieee80211_hw *hw = rtlworks->hw;
|
||||
|
||||
rtl_c2hcmd_launcher(hw, 1);
|
||||
}
|
||||
|
||||
void rtl_easy_concurrent_retrytimer_callback(unsigned long data)
|
||||
{
|
||||
struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
|
||||
|
@ -136,6 +136,9 @@ int rtl_rx_agg_stop(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta, u16 tid);
|
||||
void rtl_watchdog_wq_callback(void *data);
|
||||
void rtl_fwevt_wq_callback(void *data);
|
||||
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);
|
||||
|
||||
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_info *info,
|
||||
|
@ -1,4 +1,8 @@
|
||||
btcoexist-objs := halbtc8723b2ant.o \
|
||||
btcoexist-objs := halbtc8192e2ant.o \
|
||||
halbtc8723b1ant.o \
|
||||
halbtc8723b2ant.o \
|
||||
halbtc8821a1ant.o \
|
||||
halbtc8821a2ant.o \
|
||||
halbtcoutsrc.o \
|
||||
rtl_btc.o
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -141,11 +141,40 @@ static u8 halbtc_get_wifi_central_chnl(struct btc_coexist *btcoexist)
|
||||
|
||||
if (rtlphy->current_channel != 0)
|
||||
chnl = rtlphy->current_channel;
|
||||
btc_alg_dbg(ALGO_TRACE,
|
||||
"static halbtc_get_wifi_central_chnl:%d\n", chnl);
|
||||
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
|
||||
"static halbtc_get_wifi_central_chnl:%d\n", chnl);
|
||||
return chnl;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return rtlpriv->btcoexist.btc_info.bt_type;
|
||||
}
|
||||
|
||||
u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv)
|
||||
{
|
||||
u8 num;
|
||||
|
||||
if (rtlpriv->btcoexist.btc_info.ant_num == ANT_X2)
|
||||
num = 2;
|
||||
else
|
||||
num = 1;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
u8 rtl_get_hwpg_package_type(struct rtl_priv *rtlpriv)
|
||||
{
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
|
||||
|
||||
return rtlhal->package_type;
|
||||
}
|
||||
|
||||
static void halbtc_leave_lps(struct btc_coexist *btcoexist)
|
||||
{
|
||||
struct rtl_priv *rtlpriv;
|
||||
@ -335,6 +364,9 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf)
|
||||
case BTC_GET_U4_BT_PATCH_VER:
|
||||
*u32_tmp = halbtc_get_bt_patch_version(btcoexist);
|
||||
break;
|
||||
case BTC_GET_U4_VENDOR:
|
||||
*u32_tmp = BTC_VENDOR_OTHER;
|
||||
break;
|
||||
case BTC_GET_U1_WIFI_DOT11_CHNL:
|
||||
*u8_tmp = rtlphy->current_channel;
|
||||
break;
|
||||
|
@ -116,18 +116,6 @@ extern u32 btc_dbg_type[];
|
||||
#define WIFI_P2P_GO_CONNECTED BIT3
|
||||
#define WIFI_P2P_GC_CONNECTED BIT4
|
||||
|
||||
#define btc_alg_dbg(dbgflag, fmt, ...) \
|
||||
do { \
|
||||
if (unlikely(btc_dbg_type[BTC_MSG_ALGORITHM] & dbgflag)) \
|
||||
printk(KERN_DEBUG fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define btc_iface_dbg(dbgflag, fmt, ...) \
|
||||
do { \
|
||||
if (unlikely(btc_dbg_type[BTC_MSG_INTERFACE] & dbgflag)) \
|
||||
printk(KERN_DEBUG fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define BTC_RSSI_HIGH(_rssi_) \
|
||||
((_rssi_ == BTC_RSSI_STATE_HIGH || \
|
||||
_rssi_ == BTC_RSSI_STATE_STAY_HIGH) ? true : false)
|
||||
@ -228,6 +216,7 @@ enum btc_get_type {
|
||||
BTC_GET_U4_WIFI_FW_VER,
|
||||
BTC_GET_U4_WIFI_LINK_STATUS,
|
||||
BTC_GET_U4_BT_PATCH_VER,
|
||||
BTC_GET_U4_VENDOR,
|
||||
|
||||
/* type u1Byte */
|
||||
BTC_GET_U1_WIFI_DOT11_CHNL,
|
||||
@ -245,6 +234,12 @@ enum btc_get_type {
|
||||
BTC_GET_MAX
|
||||
};
|
||||
|
||||
enum btc_vendor {
|
||||
BTC_VENDOR_LENOVO,
|
||||
BTC_VENDOR_ASUS,
|
||||
BTC_VENDOR_OTHER
|
||||
};
|
||||
|
||||
enum btc_set_type {
|
||||
/* type bool */
|
||||
BTC_SET_BL_BT_DISABLE,
|
||||
@ -263,6 +258,7 @@ enum btc_set_type {
|
||||
/* type trigger some action */
|
||||
BTC_SET_ACT_GET_BT_RSSI,
|
||||
BTC_SET_ACT_AGGREGATE_CTRL,
|
||||
BTC_SET_ACT_ANTPOSREGRISTRY_CTRL,
|
||||
|
||||
/********* for 1Ant **********/
|
||||
/* type bool */
|
||||
|
@ -178,17 +178,6 @@ struct rtl_btc_ops *rtl_btc_get_ops_pointer(void)
|
||||
}
|
||||
EXPORT_SYMBOL(rtl_btc_get_ops_pointer);
|
||||
|
||||
u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv)
|
||||
{
|
||||
u8 num;
|
||||
|
||||
if (rtlpriv->btcoexist.btc_info.ant_num == ANT_X2)
|
||||
num = 2;
|
||||
else
|
||||
num = 1;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
enum rt_media_status mgnt_link_status_query(struct ieee80211_hw *hw)
|
||||
{
|
||||
@ -209,11 +198,6 @@ u8 rtl_get_hwpg_bt_exist(struct rtl_priv *rtlpriv)
|
||||
return rtlpriv->btcoexist.btc_info.btcoexist;
|
||||
}
|
||||
|
||||
u8 rtl_get_hwpg_bt_type(struct rtl_priv *rtlpriv)
|
||||
{
|
||||
return rtlpriv->btcoexist.btc_info.bt_type;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Page He <page_he@realsil.com.cn>");
|
||||
MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
|
||||
MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>");
|
||||
|
@ -46,9 +46,12 @@ void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type);
|
||||
|
||||
struct rtl_btc_ops *rtl_btc_get_ops_pointer(void);
|
||||
|
||||
u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv);
|
||||
u8 rtl_get_hwpg_bt_exist(struct rtl_priv *rtlpriv);
|
||||
u8 rtl_get_hwpg_bt_type(struct rtl_priv *rtlpriv);
|
||||
u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv);
|
||||
u8 rtl_get_hwpg_single_ant_path(struct rtl_priv *rtlpriv);
|
||||
u8 rtl_get_hwpg_package_type(struct rtl_priv *rtlpriv);
|
||||
|
||||
enum rt_media_status mgnt_link_status_query(struct ieee80211_hw *hw);
|
||||
|
||||
#endif
|
||||
|
@ -45,12 +45,13 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
|
||||
|
||||
u32 target_command;
|
||||
u32 target_content = 0;
|
||||
u8 entry_i;
|
||||
int entry_i;
|
||||
|
||||
RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_DMESG, "Key content :",
|
||||
key_cont_128, 16);
|
||||
|
||||
for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
|
||||
/* 0-1 config + mac, 2-5 fill 128key,6-7 are reserved */
|
||||
for (entry_i = CAM_CONTENT_COUNT - 1; entry_i >= 0; entry_i--) {
|
||||
target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
|
||||
target_command = target_command | BIT(31) | BIT(16);
|
||||
|
||||
@ -102,7 +103,6 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
|
||||
target_content);
|
||||
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
|
||||
target_command);
|
||||
udelay(100);
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
|
||||
"WRITE A4: %x\n", target_content);
|
||||
|
@ -233,6 +233,7 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
||||
int err = 0;
|
||||
u8 retry_limit = 0x30;
|
||||
|
||||
if (mac->vif) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
|
||||
@ -271,6 +272,7 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
|
||||
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
|
||||
(u8 *)(&mac->basic_rates));
|
||||
|
||||
retry_limit = 0x07;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
mac->p2p = P2P_ROLE_GO;
|
||||
@ -287,6 +289,8 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
|
||||
mac->basic_rates = 0xff0;
|
||||
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
|
||||
(u8 *)(&mac->basic_rates));
|
||||
|
||||
retry_limit = 0x07;
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
|
||||
@ -300,6 +304,8 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
|
||||
mac->basic_rates = 0xff0;
|
||||
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
|
||||
(u8 *)(&mac->basic_rates));
|
||||
|
||||
retry_limit = 0x07;
|
||||
break;
|
||||
default:
|
||||
pr_err("operation mode %d is not supported!\n",
|
||||
@ -321,6 +327,10 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
|
||||
memcpy(mac->mac_addr, vif->addr, ETH_ALEN);
|
||||
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
|
||||
|
||||
mac->retry_long = retry_limit;
|
||||
mac->retry_short = retry_limit;
|
||||
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT,
|
||||
(u8 *)(&retry_limit));
|
||||
out:
|
||||
mutex_unlock(&rtlpriv->locks.conf_mutex);
|
||||
return err;
|
||||
@ -645,10 +655,15 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
|
||||
"IEEE80211_CONF_CHANGE_RETRY_LIMITS %x\n",
|
||||
hw->conf.long_frame_max_tx_count);
|
||||
mac->retry_long = hw->conf.long_frame_max_tx_count;
|
||||
mac->retry_short = hw->conf.long_frame_max_tx_count;
|
||||
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT,
|
||||
/* brought up everything changes (changed == ~0) indicates first
|
||||
* open, so use our default value instead of that of wiphy.
|
||||
*/
|
||||
if (changed != ~0) {
|
||||
mac->retry_long = hw->conf.long_frame_max_tx_count;
|
||||
mac->retry_short = hw->conf.long_frame_max_tx_count;
|
||||
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT,
|
||||
(u8 *)(&hw->conf.long_frame_max_tx_count));
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL &&
|
||||
|
@ -73,8 +73,6 @@ static void efuse_word_enable_data_read(u8 word_en, u8 *sourdata,
|
||||
u8 *targetdata);
|
||||
static u8 enable_efuse_data_write(struct ieee80211_hw *hw,
|
||||
u16 efuse_addr, u8 word_en, u8 *data);
|
||||
static void efuse_power_switch(struct ieee80211_hw *hw, u8 write,
|
||||
u8 pwrstate);
|
||||
static u16 efuse_get_current_size(struct ieee80211_hw *hw);
|
||||
static u8 efuse_calculate_word_cnts(u8 word_en);
|
||||
|
||||
@ -1124,7 +1122,7 @@ static u8 enable_efuse_data_write(struct ieee80211_hw *hw,
|
||||
return badworden;
|
||||
}
|
||||
|
||||
static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate)
|
||||
void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
@ -1210,6 +1208,7 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate)
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(efuse_power_switch);
|
||||
|
||||
static u16 efuse_get_current_size(struct ieee80211_hw *hw)
|
||||
{
|
||||
|
@ -109,6 +109,7 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw);
|
||||
void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw);
|
||||
void efuse_force_write_vendor_Id(struct ieee80211_hw *hw);
|
||||
void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx);
|
||||
void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate);
|
||||
int rtl_get_hwinfo(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv,
|
||||
int max_size, u8 *hwinfo, int *params);
|
||||
void rtl_fill_dummy(u8 *pfwbuf, u32 *pfwlen);
|
||||
|
@ -1213,6 +1213,10 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw,
|
||||
mac->current_ampdu_density = 7;
|
||||
mac->current_ampdu_factor = 3;
|
||||
|
||||
/*Retry Limit*/
|
||||
mac->retry_short = 7;
|
||||
mac->retry_long = 7;
|
||||
|
||||
/*QOS*/
|
||||
rtlpci->acm_method = EACMWAY2_SW;
|
||||
|
||||
@ -1813,6 +1817,7 @@ static int rtl_pci_start(struct ieee80211_hw *hw)
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(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));
|
||||
|
||||
int err;
|
||||
|
||||
@ -1830,6 +1835,8 @@ static int rtl_pci_start(struct ieee80211_hw *hw)
|
||||
"Failed to config hardware!\n");
|
||||
return err;
|
||||
}
|
||||
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT,
|
||||
&rtlmac->retry_long);
|
||||
|
||||
rtlpriv->cfg->ops->enable_interrupt(hw);
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "enable_interrupt OK\n");
|
||||
|
@ -271,10 +271,10 @@ struct mp_adapter {
|
||||
};
|
||||
|
||||
struct rtl_pci_priv {
|
||||
struct bt_coexist_info bt_coexist;
|
||||
struct rtl_led_ctl ledctl;
|
||||
struct rtl_pci dev;
|
||||
struct mp_adapter ndis_adapter;
|
||||
struct rtl_led_ctl ledctl;
|
||||
struct bt_coexist_info bt_coexist;
|
||||
};
|
||||
|
||||
#define rtl_pcipriv(hw) (((struct rtl_pci_priv *)(rtl_priv(hw))->priv))
|
||||
|
@ -34,6 +34,7 @@ bool rtl_ps_enable_nic(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));
|
||||
struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
|
||||
|
||||
/*<1> reset trx ring */
|
||||
if (rtlhal->interface == INTF_PCI)
|
||||
@ -46,6 +47,8 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw)
|
||||
/*<2> Enable Adapter */
|
||||
if (rtlpriv->cfg->ops->hw_init(hw))
|
||||
return false;
|
||||
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT,
|
||||
&rtlmac->retry_long);
|
||||
RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
|
||||
|
||||
/*<3> Enable Interrupt */
|
||||
|
@ -817,19 +817,18 @@ static bool _rtl88ee_llt_table_init(struct ieee80211_hw *hw)
|
||||
static void _rtl88ee_gen_refresh_led_state(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
|
||||
struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
|
||||
struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
|
||||
|
||||
if (rtlpriv->rtlhal.up_first_time)
|
||||
return;
|
||||
|
||||
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
|
||||
rtl88ee_sw_led_on(hw, pLed0);
|
||||
rtl88ee_sw_led_on(hw, pled0);
|
||||
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
|
||||
rtl88ee_sw_led_on(hw, pLed0);
|
||||
rtl88ee_sw_led_on(hw, pled0);
|
||||
else
|
||||
rtl88ee_sw_led_off(hw, pLed0);
|
||||
rtl88ee_sw_led_off(hw, pled0);
|
||||
}
|
||||
|
||||
static bool _rtl88ee_init_mac(struct ieee80211_hw *hw)
|
||||
@ -1931,14 +1930,13 @@ exit:
|
||||
static void _rtl88ee_hal_customized_behavior(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
|
||||
pcipriv->ledctl.led_opendrain = true;
|
||||
rtlpriv->ledctl.led_opendrain = true;
|
||||
|
||||
switch (rtlhal->oem_id) {
|
||||
case RT_CID_819X_HP:
|
||||
pcipriv->ledctl.led_opendrain = true;
|
||||
rtlpriv->ledctl.led_opendrain = true;
|
||||
break;
|
||||
case RT_CID_819X_LENOVO:
|
||||
case RT_CID_DEFAULT:
|
||||
|
@ -67,7 +67,6 @@ void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
u8 ledcfg;
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
|
||||
@ -79,7 +78,7 @@ void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
case LED_PIN_LED0:
|
||||
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
|
||||
ledcfg &= 0xf0;
|
||||
if (pcipriv->ledctl.led_opendrain) {
|
||||
if (rtlpriv->ledctl.led_opendrain) {
|
||||
rtl_write_byte(rtlpriv, REG_LEDCFG2,
|
||||
(ledcfg | BIT(3) | BIT(5) | BIT(6)));
|
||||
ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG);
|
||||
@ -104,24 +103,26 @@ void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
|
||||
void rtl88ee_init_sw_leds(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
_rtl88ee_init_led(hw, &pcipriv->ledctl.sw_led0, LED_PIN_LED0);
|
||||
_rtl88ee_init_led(hw, &pcipriv->ledctl.sw_led1, LED_PIN_LED1);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
||||
_rtl88ee_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
|
||||
_rtl88ee_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
|
||||
}
|
||||
|
||||
static void _rtl88ee_sw_led_control(struct ieee80211_hw *hw,
|
||||
enum led_ctl_mode ledaction)
|
||||
{
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
|
||||
|
||||
switch (ledaction) {
|
||||
case LED_CTL_POWER_ON:
|
||||
case LED_CTL_LINK:
|
||||
case LED_CTL_NO_LINK:
|
||||
rtl88ee_sw_led_on(hw, pLed0);
|
||||
rtl88ee_sw_led_on(hw, pled0);
|
||||
break;
|
||||
case LED_CTL_POWER_OFF:
|
||||
rtl88ee_sw_led_off(hw, pLed0);
|
||||
rtl88ee_sw_led_off(hw, pled0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -638,7 +638,6 @@ EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo);
|
||||
static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
||||
|
||||
static u64 last_txok_cnt;
|
||||
@ -651,20 +650,20 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
|
||||
u32 edca_be_dl = 0x5ea42b;
|
||||
bool bt_change_edca = false;
|
||||
|
||||
if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) ||
|
||||
(last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) {
|
||||
if ((last_bt_edca_ul != rtlpriv->btcoexist.bt_edca_ul) ||
|
||||
(last_bt_edca_dl != rtlpriv->btcoexist.bt_edca_dl)) {
|
||||
rtlpriv->dm.current_turbo_edca = false;
|
||||
last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
|
||||
last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl;
|
||||
last_bt_edca_ul = rtlpriv->btcoexist.bt_edca_ul;
|
||||
last_bt_edca_dl = rtlpriv->btcoexist.bt_edca_dl;
|
||||
}
|
||||
|
||||
if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) {
|
||||
edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
|
||||
if (rtlpriv->btcoexist.bt_edca_ul != 0) {
|
||||
edca_be_ul = rtlpriv->btcoexist.bt_edca_ul;
|
||||
bt_change_edca = true;
|
||||
}
|
||||
|
||||
if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) {
|
||||
edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl;
|
||||
if (rtlpriv->btcoexist.bt_edca_dl != 0) {
|
||||
edca_be_ul = rtlpriv->btcoexist.bt_edca_dl;
|
||||
bt_change_edca = true;
|
||||
}
|
||||
|
||||
@ -673,7 +672,7 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) {
|
||||
if ((!mac->ht_enable) && (!rtlpriv->btcoexist.bt_coexistence)) {
|
||||
if (!(edca_be_ul & 0xffff0000))
|
||||
edca_be_ul |= 0x005e0000;
|
||||
|
||||
@ -1471,7 +1470,6 @@ EXPORT_SYMBOL(rtl92c_dm_watchdog);
|
||||
u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
long undec_sm_pwdb;
|
||||
u8 curr_bt_rssi_state = 0x00;
|
||||
|
||||
@ -1510,8 +1508,8 @@ u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw)
|
||||
else
|
||||
curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW);
|
||||
|
||||
if (curr_bt_rssi_state != rtlpcipriv->bt_coexist.bt_rssi_state) {
|
||||
rtlpcipriv->bt_coexist.bt_rssi_state = curr_bt_rssi_state;
|
||||
if (curr_bt_rssi_state != rtlpriv->btcoexist.bt_rssi_state) {
|
||||
rtlpriv->btcoexist.bt_rssi_state = curr_bt_rssi_state;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -1522,7 +1520,6 @@ EXPORT_SYMBOL(rtl92c_bt_rssi_state_change);
|
||||
static bool rtl92c_bt_state_change(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
|
||||
u32 polling, ratio_tx, ratio_pri;
|
||||
u32 bt_tx, bt_pri;
|
||||
@ -1542,14 +1539,14 @@ static bool rtl92c_bt_state_change(struct ieee80211_hw *hw)
|
||||
return false;
|
||||
|
||||
bt_state &= BIT_OFFSET_LEN_MASK_32(0, 1);
|
||||
if (bt_state != rtlpcipriv->bt_coexist.bt_cur_state) {
|
||||
rtlpcipriv->bt_coexist.bt_cur_state = bt_state;
|
||||
if (bt_state != rtlpriv->btcoexist.bt_cur_state) {
|
||||
rtlpriv->btcoexist.bt_cur_state = bt_state;
|
||||
|
||||
if (rtlpcipriv->bt_coexist.reg_bt_sco == 3) {
|
||||
rtlpcipriv->bt_coexist.bt_service = BT_IDLE;
|
||||
if (rtlpriv->btcoexist.reg_bt_sco == 3) {
|
||||
rtlpriv->btcoexist.bt_service = BT_IDLE;
|
||||
|
||||
bt_state = bt_state |
|
||||
((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ?
|
||||
((rtlpriv->btcoexist.bt_ant_isolation == 1) ?
|
||||
0 : BIT_OFFSET_LEN_MASK_32(1, 1)) |
|
||||
BIT_OFFSET_LEN_MASK_32(2, 1);
|
||||
rtl_write_byte(rtlpriv, 0x4fd, bt_state);
|
||||
@ -1559,10 +1556,10 @@ static bool rtl92c_bt_state_change(struct ieee80211_hw *hw)
|
||||
|
||||
ratio_tx = bt_tx * 1000 / polling;
|
||||
ratio_pri = bt_pri * 1000 / polling;
|
||||
rtlpcipriv->bt_coexist.ratio_tx = ratio_tx;
|
||||
rtlpcipriv->bt_coexist.ratio_pri = ratio_pri;
|
||||
rtlpriv->btcoexist.ratio_tx = ratio_tx;
|
||||
rtlpriv->btcoexist.ratio_pri = ratio_pri;
|
||||
|
||||
if (bt_state && rtlpcipriv->bt_coexist.reg_bt_sco == 3) {
|
||||
if (bt_state && rtlpriv->btcoexist.reg_bt_sco == 3) {
|
||||
|
||||
if ((ratio_tx < 30) && (ratio_pri < 30))
|
||||
cur_service_type = BT_IDLE;
|
||||
@ -1577,17 +1574,17 @@ static bool rtl92c_bt_state_change(struct ieee80211_hw *hw)
|
||||
else
|
||||
cur_service_type = BT_OTHER_ACTION;
|
||||
|
||||
if (cur_service_type != rtlpcipriv->bt_coexist.bt_service) {
|
||||
rtlpcipriv->bt_coexist.bt_service = cur_service_type;
|
||||
if (cur_service_type != rtlpriv->btcoexist.bt_service) {
|
||||
rtlpriv->btcoexist.bt_service = cur_service_type;
|
||||
bt_state = bt_state |
|
||||
((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ?
|
||||
((rtlpriv->btcoexist.bt_ant_isolation == 1) ?
|
||||
0 : BIT_OFFSET_LEN_MASK_32(1, 1)) |
|
||||
((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) ?
|
||||
((rtlpriv->btcoexist.bt_service != BT_IDLE) ?
|
||||
0 : BIT_OFFSET_LEN_MASK_32(2, 1));
|
||||
|
||||
/* Add interrupt migration when bt is not ini
|
||||
* idle state (no traffic). */
|
||||
if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) {
|
||||
if (rtlpriv->btcoexist.bt_service != BT_IDLE) {
|
||||
rtl_write_word(rtlpriv, 0x504, 0x0ccc);
|
||||
rtl_write_byte(rtlpriv, 0x506, 0x54);
|
||||
rtl_write_byte(rtlpriv, 0x507, 0x54);
|
||||
@ -1626,80 +1623,77 @@ static bool rtl92c_bt_wifi_connect_change(struct ieee80211_hw *hw)
|
||||
static void rtl92c_bt_set_normal(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
|
||||
|
||||
if (rtlpcipriv->bt_coexist.bt_service == BT_OTHERBUSY) {
|
||||
rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72b;
|
||||
rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72b;
|
||||
} else if (rtlpcipriv->bt_coexist.bt_service == BT_BUSY) {
|
||||
rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82f;
|
||||
rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82f;
|
||||
} else if (rtlpcipriv->bt_coexist.bt_service == BT_SCO) {
|
||||
if (rtlpcipriv->bt_coexist.ratio_tx > 160) {
|
||||
rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72f;
|
||||
rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72f;
|
||||
if (rtlpriv->btcoexist.bt_service == BT_OTHERBUSY) {
|
||||
rtlpriv->btcoexist.bt_edca_ul = 0x5ea72b;
|
||||
rtlpriv->btcoexist.bt_edca_dl = 0x5ea72b;
|
||||
} else if (rtlpriv->btcoexist.bt_service == BT_BUSY) {
|
||||
rtlpriv->btcoexist.bt_edca_ul = 0x5eb82f;
|
||||
rtlpriv->btcoexist.bt_edca_dl = 0x5eb82f;
|
||||
} else if (rtlpriv->btcoexist.bt_service == BT_SCO) {
|
||||
if (rtlpriv->btcoexist.ratio_tx > 160) {
|
||||
rtlpriv->btcoexist.bt_edca_ul = 0x5ea72f;
|
||||
rtlpriv->btcoexist.bt_edca_dl = 0x5ea72f;
|
||||
} else {
|
||||
rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea32b;
|
||||
rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea42b;
|
||||
rtlpriv->btcoexist.bt_edca_ul = 0x5ea32b;
|
||||
rtlpriv->btcoexist.bt_edca_dl = 0x5ea42b;
|
||||
}
|
||||
} else {
|
||||
rtlpcipriv->bt_coexist.bt_edca_ul = 0;
|
||||
rtlpcipriv->bt_coexist.bt_edca_dl = 0;
|
||||
rtlpriv->btcoexist.bt_edca_ul = 0;
|
||||
rtlpriv->btcoexist.bt_edca_dl = 0;
|
||||
}
|
||||
|
||||
if ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) &&
|
||||
(rtlpriv->mac80211.mode == WIRELESS_MODE_G ||
|
||||
if ((rtlpriv->btcoexist.bt_service != BT_IDLE) &&
|
||||
(rtlpriv->mac80211.mode == WIRELESS_MODE_G ||
|
||||
(rtlpriv->mac80211.mode == (WIRELESS_MODE_G | WIRELESS_MODE_B))) &&
|
||||
(rtlpcipriv->bt_coexist.bt_rssi_state &
|
||||
(rtlpriv->btcoexist.bt_rssi_state &
|
||||
BT_RSSI_STATE_BG_EDCA_LOW)) {
|
||||
rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82b;
|
||||
rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82b;
|
||||
rtlpriv->btcoexist.bt_edca_ul = 0x5eb82b;
|
||||
rtlpriv->btcoexist.bt_edca_dl = 0x5eb82b;
|
||||
}
|
||||
}
|
||||
|
||||
static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
|
||||
|
||||
/* Only enable HW BT coexist when BT in "Busy" state. */
|
||||
if (rtlpriv->mac80211.vendor == PEER_CISCO &&
|
||||
rtlpcipriv->bt_coexist.bt_service == BT_OTHER_ACTION) {
|
||||
rtlpriv->btcoexist.bt_service == BT_OTHER_ACTION) {
|
||||
rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
|
||||
} else {
|
||||
if ((rtlpcipriv->bt_coexist.bt_service == BT_BUSY) &&
|
||||
(rtlpcipriv->bt_coexist.bt_rssi_state &
|
||||
if ((rtlpriv->btcoexist.bt_service == BT_BUSY) &&
|
||||
(rtlpriv->btcoexist.bt_rssi_state &
|
||||
BT_RSSI_STATE_NORMAL_POWER)) {
|
||||
rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
|
||||
} else if ((rtlpcipriv->bt_coexist.bt_service ==
|
||||
} else if ((rtlpriv->btcoexist.bt_service ==
|
||||
BT_OTHER_ACTION) && (rtlpriv->mac80211.mode <
|
||||
WIRELESS_MODE_N_24G) &&
|
||||
(rtlpcipriv->bt_coexist.bt_rssi_state &
|
||||
(rtlpriv->btcoexist.bt_rssi_state &
|
||||
BT_RSSI_STATE_SPECIAL_LOW)) {
|
||||
rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
|
||||
} else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) {
|
||||
} else if (rtlpriv->btcoexist.bt_service == BT_PAN) {
|
||||
rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
|
||||
} else {
|
||||
rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
|
||||
}
|
||||
}
|
||||
|
||||
if (rtlpcipriv->bt_coexist.bt_service == BT_PAN)
|
||||
if (rtlpriv->btcoexist.bt_service == BT_PAN)
|
||||
rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x10100);
|
||||
else
|
||||
rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x0);
|
||||
|
||||
if (rtlpcipriv->bt_coexist.bt_rssi_state &
|
||||
if (rtlpriv->btcoexist.bt_rssi_state &
|
||||
BT_RSSI_STATE_NORMAL_POWER) {
|
||||
rtl92c_bt_set_normal(hw);
|
||||
} else {
|
||||
rtlpcipriv->bt_coexist.bt_edca_ul = 0;
|
||||
rtlpcipriv->bt_coexist.bt_edca_dl = 0;
|
||||
rtlpriv->btcoexist.bt_edca_ul = 0;
|
||||
rtlpriv->btcoexist.bt_edca_dl = 0;
|
||||
}
|
||||
|
||||
if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) {
|
||||
if (rtlpriv->btcoexist.bt_service != BT_IDLE) {
|
||||
rtlpriv->cfg->ops->set_rfreg(hw,
|
||||
RF90_PATH_A,
|
||||
0x1e,
|
||||
@ -1707,12 +1701,12 @@ static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte)
|
||||
} else {
|
||||
rtlpriv->cfg->ops->set_rfreg(hw,
|
||||
RF90_PATH_A, 0x1e, 0xf0,
|
||||
rtlpcipriv->bt_coexist.bt_rfreg_origin_1e);
|
||||
rtlpriv->btcoexist.bt_rfreg_origin_1e);
|
||||
}
|
||||
|
||||
if (!rtlpriv->dm.dynamic_txpower_enable) {
|
||||
if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) {
|
||||
if (rtlpcipriv->bt_coexist.bt_rssi_state &
|
||||
if (rtlpriv->btcoexist.bt_service != BT_IDLE) {
|
||||
if (rtlpriv->btcoexist.bt_rssi_state &
|
||||
BT_RSSI_STATE_TXPOWER_LOW) {
|
||||
rtlpriv->dm.dynamic_txhighpower_lvl =
|
||||
TXHIGHPWRLEVEL_BT2;
|
||||
@ -1732,37 +1726,34 @@ static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte)
|
||||
static void rtl92c_check_bt_change(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
u8 tmp1byte = 0;
|
||||
|
||||
if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version) &&
|
||||
rtlpcipriv->bt_coexist.bt_coexistence)
|
||||
rtlpriv->btcoexist.bt_coexistence)
|
||||
tmp1byte |= BIT(5);
|
||||
if (rtlpcipriv->bt_coexist.bt_cur_state) {
|
||||
if (rtlpcipriv->bt_coexist.bt_ant_isolation)
|
||||
if (rtlpriv->btcoexist.bt_cur_state) {
|
||||
if (rtlpriv->btcoexist.bt_ant_isolation)
|
||||
rtl92c_bt_ant_isolation(hw, tmp1byte);
|
||||
} else {
|
||||
rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
|
||||
rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0,
|
||||
rtlpcipriv->bt_coexist.bt_rfreg_origin_1e);
|
||||
rtlpriv->btcoexist.bt_rfreg_origin_1e);
|
||||
|
||||
rtlpcipriv->bt_coexist.bt_edca_ul = 0;
|
||||
rtlpcipriv->bt_coexist.bt_edca_dl = 0;
|
||||
rtlpriv->btcoexist.bt_edca_ul = 0;
|
||||
rtlpriv->btcoexist.bt_edca_dl = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
bool wifi_connect_change;
|
||||
bool bt_state_change;
|
||||
bool rssi_state_change;
|
||||
|
||||
if ((rtlpcipriv->bt_coexist.bt_coexistence) &&
|
||||
(rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) {
|
||||
|
||||
if ((rtlpriv->btcoexist.bt_coexistence) &&
|
||||
(rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4)) {
|
||||
wifi_connect_change = rtl92c_bt_wifi_connect_change(hw);
|
||||
bt_state_change = rtl92c_bt_state_change(hw);
|
||||
rssi_state_change = rtl92c_bt_rssi_state_change(hw);
|
||||
|
@ -148,7 +148,6 @@ void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
|
||||
void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
@ -276,8 +275,8 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
|
||||
u8 *p_regtoset = NULL;
|
||||
u8 index = 0;
|
||||
|
||||
if ((rtlpcipriv->bt_coexist.bt_coexistence) &&
|
||||
(rtlpcipriv->bt_coexist.bt_coexist_type ==
|
||||
if ((rtlpriv->btcoexist.bt_coexistence) &&
|
||||
(rtlpriv->btcoexist.bt_coexist_type ==
|
||||
BT_CSR_BC4))
|
||||
p_regtoset = regtoset_bt;
|
||||
else
|
||||
@ -655,26 +654,25 @@ static bool _rtl92ce_llt_table_init(struct ieee80211_hw *hw)
|
||||
|
||||
static void _rtl92ce_gen_refresh_led_state(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
|
||||
struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
|
||||
struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
|
||||
|
||||
if (rtlpci->up_first_time)
|
||||
return;
|
||||
|
||||
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
|
||||
rtl92ce_sw_led_on(hw, pLed0);
|
||||
rtl92ce_sw_led_on(hw, pled0);
|
||||
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
|
||||
rtl92ce_sw_led_on(hw, pLed0);
|
||||
rtl92ce_sw_led_on(hw, pled0);
|
||||
else
|
||||
rtl92ce_sw_led_off(hw, pLed0);
|
||||
rtl92ce_sw_led_off(hw, pled0);
|
||||
}
|
||||
|
||||
static bool _rtl92ce_init_mac(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
|
||||
@ -683,7 +681,7 @@ static bool _rtl92ce_init_mac(struct ieee80211_hw *hw)
|
||||
u16 retry;
|
||||
|
||||
rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00);
|
||||
if (rtlpcipriv->bt_coexist.bt_coexistence) {
|
||||
if (rtlpriv->btcoexist.bt_coexistence) {
|
||||
u32 value32;
|
||||
value32 = rtl_read_dword(rtlpriv, REG_APS_FSMCO);
|
||||
value32 |= (SOP_ABG | SOP_AMB | XOP_BTCK);
|
||||
@ -692,7 +690,7 @@ static bool _rtl92ce_init_mac(struct ieee80211_hw *hw)
|
||||
rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
|
||||
rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F);
|
||||
|
||||
if (rtlpcipriv->bt_coexist.bt_coexistence) {
|
||||
if (rtlpriv->btcoexist.bt_coexistence) {
|
||||
u32 u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL);
|
||||
|
||||
u4b_tmp &= (~0x00024800);
|
||||
@ -726,7 +724,7 @@ static bool _rtl92ce_init_mac(struct ieee80211_hw *hw)
|
||||
rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82);
|
||||
udelay(2);
|
||||
|
||||
if (rtlpcipriv->bt_coexist.bt_coexistence) {
|
||||
if (rtlpriv->btcoexist.bt_coexistence) {
|
||||
bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+2) & 0xfd;
|
||||
rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+2, bytetmp);
|
||||
}
|
||||
@ -798,7 +796,6 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
u8 reg_bw_opmode;
|
||||
u32 reg_prsr;
|
||||
|
||||
@ -828,8 +825,8 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw)
|
||||
rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000);
|
||||
rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504);
|
||||
|
||||
if ((rtlpcipriv->bt_coexist.bt_coexistence) &&
|
||||
(rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4))
|
||||
if ((rtlpriv->btcoexist.bt_coexistence) &&
|
||||
(rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4))
|
||||
rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x97427431);
|
||||
else
|
||||
rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841);
|
||||
@ -848,8 +845,8 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw)
|
||||
rtl_write_byte(rtlpriv, REG_PIFS, 0x1C);
|
||||
rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
|
||||
|
||||
if ((rtlpcipriv->bt_coexist.bt_coexistence) &&
|
||||
(rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) {
|
||||
if ((rtlpriv->btcoexist.bt_coexistence) &&
|
||||
(rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4)) {
|
||||
rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020);
|
||||
rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0402);
|
||||
} else {
|
||||
@ -857,8 +854,8 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw)
|
||||
rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020);
|
||||
}
|
||||
|
||||
if ((rtlpcipriv->bt_coexist.bt_coexistence) &&
|
||||
(rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4))
|
||||
if ((rtlpriv->btcoexist.bt_coexistence) &&
|
||||
(rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4))
|
||||
rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666);
|
||||
else
|
||||
rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666);
|
||||
@ -1313,7 +1310,6 @@ void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)
|
||||
static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
|
||||
u8 u1b_tmp;
|
||||
u32 u4b_tmp;
|
||||
@ -1331,9 +1327,9 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
|
||||
rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
|
||||
rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000);
|
||||
u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL);
|
||||
if ((rtlpcipriv->bt_coexist.bt_coexistence) &&
|
||||
((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) ||
|
||||
(rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8))) {
|
||||
if ((rtlpriv->btcoexist.bt_coexistence) &&
|
||||
((rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4) ||
|
||||
(rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC8))) {
|
||||
rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00F30000 |
|
||||
(u1b_tmp << 8));
|
||||
} else {
|
||||
@ -1345,7 +1341,7 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
|
||||
rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80);
|
||||
if (!IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version))
|
||||
rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
|
||||
if (rtlpcipriv->bt_coexist.bt_coexistence) {
|
||||
if (rtlpriv->btcoexist.bt_coexistence) {
|
||||
u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL);
|
||||
u4b_tmp |= 0x03824800;
|
||||
rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, u4b_tmp);
|
||||
@ -1724,12 +1720,11 @@ exit:
|
||||
static void _rtl92ce_hal_customized_behavior(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
|
||||
switch (rtlhal->oem_id) {
|
||||
case RT_CID_819X_HP:
|
||||
pcipriv->ledctl.led_opendrain = true;
|
||||
rtlpriv->ledctl.led_opendrain = true;
|
||||
break;
|
||||
case RT_CID_819X_LENOVO:
|
||||
case RT_CID_DEFAULT:
|
||||
@ -1782,7 +1777,6 @@ static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_phy *rtlphy = &(rtlpriv->phy);
|
||||
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
@ -1838,12 +1832,12 @@ static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw,
|
||||
break;
|
||||
}
|
||||
|
||||
if ((rtlpcipriv->bt_coexist.bt_coexistence) &&
|
||||
(rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) &&
|
||||
(rtlpcipriv->bt_coexist.bt_cur_state) &&
|
||||
(rtlpcipriv->bt_coexist.bt_ant_isolation) &&
|
||||
((rtlpcipriv->bt_coexist.bt_service == BT_SCO) ||
|
||||
(rtlpcipriv->bt_coexist.bt_service == BT_BUSY)))
|
||||
if ((rtlpriv->btcoexist.bt_coexistence) &&
|
||||
(rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4) &&
|
||||
(rtlpriv->btcoexist.bt_cur_state) &&
|
||||
(rtlpriv->btcoexist.bt_ant_isolation) &&
|
||||
((rtlpriv->btcoexist.bt_service == BT_SCO) ||
|
||||
(rtlpriv->btcoexist.bt_service == BT_BUSY)))
|
||||
ratr_value &= 0x0fffcfc0;
|
||||
else
|
||||
ratr_value &= 0x0FFFFFFF;
|
||||
@ -2237,65 +2231,64 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index,
|
||||
|
||||
static void rtl8192ce_bt_var_init(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
||||
rtlpcipriv->bt_coexist.bt_coexistence =
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_coexist;
|
||||
rtlpcipriv->bt_coexist.bt_ant_num =
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_ant_num;
|
||||
rtlpcipriv->bt_coexist.bt_coexist_type =
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_type;
|
||||
rtlpriv->btcoexist.bt_coexistence =
|
||||
rtlpriv->btcoexist.eeprom_bt_coexist;
|
||||
rtlpriv->btcoexist.bt_ant_num =
|
||||
rtlpriv->btcoexist.eeprom_bt_ant_num;
|
||||
rtlpriv->btcoexist.bt_coexist_type =
|
||||
rtlpriv->btcoexist.eeprom_bt_type;
|
||||
|
||||
if (rtlpcipriv->bt_coexist.reg_bt_iso == 2)
|
||||
rtlpcipriv->bt_coexist.bt_ant_isolation =
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_ant_isol;
|
||||
if (rtlpriv->btcoexist.reg_bt_iso == 2)
|
||||
rtlpriv->btcoexist.bt_ant_isolation =
|
||||
rtlpriv->btcoexist.eeprom_bt_ant_isol;
|
||||
else
|
||||
rtlpcipriv->bt_coexist.bt_ant_isolation =
|
||||
rtlpcipriv->bt_coexist.reg_bt_iso;
|
||||
rtlpriv->btcoexist.bt_ant_isolation =
|
||||
rtlpriv->btcoexist.reg_bt_iso;
|
||||
|
||||
rtlpcipriv->bt_coexist.bt_radio_shared_type =
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_radio_shared;
|
||||
rtlpriv->btcoexist.bt_radio_shared_type =
|
||||
rtlpriv->btcoexist.eeprom_bt_radio_shared;
|
||||
|
||||
if (rtlpcipriv->bt_coexist.bt_coexistence) {
|
||||
|
||||
if (rtlpcipriv->bt_coexist.reg_bt_sco == 1)
|
||||
rtlpcipriv->bt_coexist.bt_service = BT_OTHER_ACTION;
|
||||
else if (rtlpcipriv->bt_coexist.reg_bt_sco == 2)
|
||||
rtlpcipriv->bt_coexist.bt_service = BT_SCO;
|
||||
else if (rtlpcipriv->bt_coexist.reg_bt_sco == 4)
|
||||
rtlpcipriv->bt_coexist.bt_service = BT_BUSY;
|
||||
else if (rtlpcipriv->bt_coexist.reg_bt_sco == 5)
|
||||
rtlpcipriv->bt_coexist.bt_service = BT_OTHERBUSY;
|
||||
if (rtlpriv->btcoexist.bt_coexistence) {
|
||||
if (rtlpriv->btcoexist.reg_bt_sco == 1)
|
||||
rtlpriv->btcoexist.bt_service = BT_OTHER_ACTION;
|
||||
else if (rtlpriv->btcoexist.reg_bt_sco == 2)
|
||||
rtlpriv->btcoexist.bt_service = BT_SCO;
|
||||
else if (rtlpriv->btcoexist.reg_bt_sco == 4)
|
||||
rtlpriv->btcoexist.bt_service = BT_BUSY;
|
||||
else if (rtlpriv->btcoexist.reg_bt_sco == 5)
|
||||
rtlpriv->btcoexist.bt_service = BT_OTHERBUSY;
|
||||
else
|
||||
rtlpcipriv->bt_coexist.bt_service = BT_IDLE;
|
||||
rtlpriv->btcoexist.bt_service = BT_IDLE;
|
||||
|
||||
rtlpcipriv->bt_coexist.bt_edca_ul = 0;
|
||||
rtlpcipriv->bt_coexist.bt_edca_dl = 0;
|
||||
rtlpcipriv->bt_coexist.bt_rssi_state = 0xff;
|
||||
rtlpriv->btcoexist.bt_edca_ul = 0;
|
||||
rtlpriv->btcoexist.bt_edca_dl = 0;
|
||||
rtlpriv->btcoexist.bt_rssi_state = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
|
||||
bool auto_load_fail, u8 *hwinfo)
|
||||
{
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
u8 val;
|
||||
|
||||
if (!auto_load_fail) {
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_coexist =
|
||||
rtlpriv->btcoexist.eeprom_bt_coexist =
|
||||
((hwinfo[RF_OPTION1] & 0xe0) >> 5);
|
||||
val = hwinfo[RF_OPTION4];
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_type = ((val & 0xe) >> 1);
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_ant_num = (val & 0x1);
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_ant_isol = ((val & 0x10) >> 4);
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_radio_shared =
|
||||
rtlpriv->btcoexist.eeprom_bt_type = ((val & 0xe) >> 1);
|
||||
rtlpriv->btcoexist.eeprom_bt_ant_num = (val & 0x1);
|
||||
rtlpriv->btcoexist.eeprom_bt_ant_isol = ((val & 0x10) >> 4);
|
||||
rtlpriv->btcoexist.eeprom_bt_radio_shared =
|
||||
((val & 0x20) >> 5);
|
||||
} else {
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_coexist = 0;
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_type = BT_2WIRE;
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_ant_num = ANT_X2;
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_ant_isol = 0;
|
||||
rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = BT_RADIO_SHARED;
|
||||
rtlpriv->btcoexist.eeprom_bt_coexist = 0;
|
||||
rtlpriv->btcoexist.eeprom_bt_type = BT_2WIRE;
|
||||
rtlpriv->btcoexist.eeprom_bt_ant_num = ANT_X2;
|
||||
rtlpriv->btcoexist.eeprom_bt_ant_isol = 0;
|
||||
rtlpriv->btcoexist.eeprom_bt_radio_shared = BT_RADIO_SHARED;
|
||||
}
|
||||
|
||||
rtl8192ce_bt_var_init(hw);
|
||||
@ -2303,14 +2296,14 @@ void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
|
||||
|
||||
void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
||||
/* 0:Low, 1:High, 2:From Efuse. */
|
||||
rtlpcipriv->bt_coexist.reg_bt_iso = 2;
|
||||
rtlpriv->btcoexist.reg_bt_iso = 2;
|
||||
/* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */
|
||||
rtlpcipriv->bt_coexist.reg_bt_sco = 3;
|
||||
rtlpriv->btcoexist.reg_bt_sco = 3;
|
||||
/* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */
|
||||
rtlpcipriv->bt_coexist.reg_bt_sco = 0;
|
||||
rtlpriv->btcoexist.reg_bt_sco = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -2318,23 +2311,22 @@ void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_phy *rtlphy = &(rtlpriv->phy);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
|
||||
u8 u1_tmp;
|
||||
|
||||
if (rtlpcipriv->bt_coexist.bt_coexistence &&
|
||||
((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) ||
|
||||
rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8)) {
|
||||
if (rtlpriv->btcoexist.bt_coexistence &&
|
||||
((rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4) ||
|
||||
rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC8)) {
|
||||
|
||||
if (rtlpcipriv->bt_coexist.bt_ant_isolation)
|
||||
if (rtlpriv->btcoexist.bt_ant_isolation)
|
||||
rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
|
||||
|
||||
u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) &
|
||||
BIT_OFFSET_LEN_MASK_32(0, 1);
|
||||
u1_tmp = u1_tmp |
|
||||
((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ?
|
||||
((rtlpriv->btcoexist.bt_ant_isolation == 1) ?
|
||||
0 : BIT_OFFSET_LEN_MASK_32(1, 1)) |
|
||||
((rtlpcipriv->bt_coexist.bt_service == BT_SCO) ?
|
||||
((rtlpriv->btcoexist.bt_service == BT_SCO) ?
|
||||
0 : BIT_OFFSET_LEN_MASK_32(2, 1));
|
||||
rtl_write_byte(rtlpriv, 0x4fd, u1_tmp);
|
||||
|
||||
|
@ -67,7 +67,6 @@ void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
u8 ledcfg;
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
|
||||
@ -80,7 +79,7 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
break;
|
||||
case LED_PIN_LED0:
|
||||
ledcfg &= 0xf0;
|
||||
if (pcipriv->ledctl.led_opendrain)
|
||||
if (rtlpriv->ledctl.led_opendrain)
|
||||
rtl_write_byte(rtlpriv, REG_LEDCFG2,
|
||||
(ledcfg | BIT(1) | BIT(5) | BIT(6)));
|
||||
else
|
||||
@ -100,24 +99,26 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
|
||||
void rtl92ce_init_sw_leds(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
_rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0);
|
||||
_rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
||||
_rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
|
||||
_rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
|
||||
}
|
||||
|
||||
static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw,
|
||||
enum led_ctl_mode ledaction)
|
||||
{
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
|
||||
|
||||
switch (ledaction) {
|
||||
case LED_CTL_POWER_ON:
|
||||
case LED_CTL_LINK:
|
||||
case LED_CTL_NO_LINK:
|
||||
rtl92ce_sw_led_on(hw, pLed0);
|
||||
rtl92ce_sw_led_on(hw, pled0);
|
||||
break;
|
||||
case LED_CTL_POWER_OFF:
|
||||
rtl92ce_sw_led_off(hw, pLed0);
|
||||
rtl92ce_sw_led_off(hw, pled0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -393,12 +393,11 @@ exit:
|
||||
static void _rtl92cu_hal_customized_behavior(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
|
||||
switch (rtlhal->oem_id) {
|
||||
case RT_CID_819X_HP:
|
||||
usb_priv->ledctl.led_opendrain = true;
|
||||
rtlpriv->ledctl.led_opendrain = true;
|
||||
break;
|
||||
case RT_CID_819X_LENOVO:
|
||||
case RT_CID_DEFAULT:
|
||||
|
@ -67,7 +67,6 @@ void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw);
|
||||
u8 ledcfg;
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
|
||||
@ -78,7 +77,7 @@ void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
break;
|
||||
case LED_PIN_LED0:
|
||||
ledcfg &= 0xf0;
|
||||
if (usbpriv->ledctl.led_opendrain)
|
||||
if (rtlpriv->ledctl.led_opendrain)
|
||||
rtl_write_byte(rtlpriv, REG_LEDCFG2,
|
||||
(ledcfg | BIT(1) | BIT(5) | BIT(6)));
|
||||
else
|
||||
@ -99,16 +98,18 @@ void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
|
||||
void rtl92cu_init_sw_leds(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw);
|
||||
_rtl92cu_init_led(hw, &(usbpriv->ledctl.sw_led0), LED_PIN_LED0);
|
||||
_rtl92cu_init_led(hw, &(usbpriv->ledctl.sw_led1), LED_PIN_LED1);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
||||
_rtl92cu_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
|
||||
_rtl92cu_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
|
||||
}
|
||||
|
||||
void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw);
|
||||
_rtl92cu_deInit_led(&(usbpriv->ledctl.sw_led0));
|
||||
_rtl92cu_deInit_led(&(usbpriv->ledctl.sw_led1));
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
||||
_rtl92cu_deInit_led(&rtlpriv->ledctl.sw_led0);
|
||||
_rtl92cu_deInit_led(&rtlpriv->ledctl.sw_led1);
|
||||
}
|
||||
|
||||
static void _rtl92cu_sw_led_control(struct ieee80211_hw *hw,
|
||||
|
@ -614,19 +614,19 @@ static bool _rtl92de_llt_table_init(struct ieee80211_hw *hw)
|
||||
|
||||
static void _rtl92de_gen_refresh_led_state(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
|
||||
struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
|
||||
struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
|
||||
|
||||
if (rtlpci->up_first_time)
|
||||
return;
|
||||
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
|
||||
rtl92de_sw_led_on(hw, pLed0);
|
||||
rtl92de_sw_led_on(hw, pled0);
|
||||
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
|
||||
rtl92de_sw_led_on(hw, pLed0);
|
||||
rtl92de_sw_led_on(hw, pled0);
|
||||
else
|
||||
rtl92de_sw_led_off(hw, pLed0);
|
||||
rtl92de_sw_led_off(hw, pled0);
|
||||
}
|
||||
|
||||
static bool _rtl92de_init_mac(struct ieee80211_hw *hw)
|
||||
|
@ -76,7 +76,6 @@ void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
u8 ledcfg;
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
|
||||
@ -89,7 +88,7 @@ void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
break;
|
||||
case LED_PIN_LED0:
|
||||
ledcfg &= 0xf0;
|
||||
if (pcipriv->ledctl.led_opendrain)
|
||||
if (rtlpriv->ledctl.led_opendrain)
|
||||
rtl_write_byte(rtlpriv, REG_LEDCFG2,
|
||||
(ledcfg | BIT(1) | BIT(5) | BIT(6)));
|
||||
else
|
||||
@ -110,24 +109,26 @@ void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
|
||||
|
||||
void rtl92de_init_sw_leds(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
_rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0);
|
||||
_rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
||||
_rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
|
||||
_rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
|
||||
}
|
||||
|
||||
static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw,
|
||||
enum led_ctl_mode ledaction)
|
||||
{
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
|
||||
|
||||
switch (ledaction) {
|
||||
case LED_CTL_POWER_ON:
|
||||
case LED_CTL_LINK:
|
||||
case LED_CTL_NO_LINK:
|
||||
rtl92de_sw_led_on(hw, pLed0);
|
||||
rtl92de_sw_led_on(hw, pled0);
|
||||
break;
|
||||
case LED_CTL_POWER_OFF:
|
||||
rtl92de_sw_led_off(hw, pLed0);
|
||||
rtl92de_sw_led_off(hw, pled0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user