aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c7
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_rx.c7
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/Kconfig1
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2100.c2
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2200.h2
-rw-r--r--drivers/net/wireless/intel/iwlegacy/common.c15
-rw-r--r--drivers/net/wireless/intel/iwlegacy/common.h12
-rw-r--r--drivers/net/wireless/marvell/libertas/radiotap.h4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mcu.c7
-rw-r--r--drivers/net/wireless/microchip/wilc1000/mon.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192du/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtw88/usb.c1
-rw-r--r--drivers/net/wireless/realtek/rtw89/coex.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.c48
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim.c4
-rw-r--r--include/net/cfg80211.h44
-rw-r--r--include/net/ieee80211_radiotap.h43
-rw-r--r--net/mac80211/Kconfig2
-rw-r--r--net/mac80211/cfg.c25
-rw-r--r--net/mac80211/ieee80211_i.h5
-rw-r--r--net/mac80211/key.c42
-rw-r--r--net/mac80211/link.c7
-rw-r--r--net/wireless/core.c7
-rw-r--r--net/wireless/scan.c4
26 files changed, 225 insertions, 75 deletions
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index dbaf26d6a7a6..16d07d619b4d 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -3043,9 +3043,14 @@ ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k *ar,
struct sk_buff *msdu)
{
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
+ struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
struct ath10k_wmi *wmi = &ar->wmi;
- idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id);
+ spin_lock_bh(&ar->data_lock);
+ pkt_addr = idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id);
+ spin_unlock_bh(&ar->data_lock);
+
+ kfree(pkt_addr);
return 0;
}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 4861179b2217..5e061f7525a6 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2441,6 +2441,7 @@ wmi_process_mgmt_tx_comp(struct ath10k *ar, struct mgmt_tx_compl_params *param)
dma_unmap_single(ar->dev, pkt_addr->paddr,
msdu->len, DMA_TO_DEVICE);
info = IEEE80211_SKB_CB(msdu);
+ kfree(pkt_addr);
if (param->status) {
info->flags &= ~IEEE80211_TX_STAT_ACK;
@@ -9612,6 +9613,7 @@ static int ath10k_wmi_mgmt_tx_clean_up_pending(int msdu_id, void *ptr,
dma_unmap_single(ar->dev, pkt_addr->paddr,
msdu->len, DMA_TO_DEVICE);
ieee80211_free_txskb(ar->hw, msdu);
+ kfree(pkt_addr);
return 0;
}
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index c087d8a0f5b2..40088e62572e 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -5291,8 +5291,11 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
hal_status == HAL_TLV_STATUS_PPDU_DONE) {
rx_mon_stats->status_ppdu_done++;
pmon->mon_ppdu_status = DP_PPDU_STATUS_DONE;
- ath11k_dp_rx_mon_dest_process(ar, mac_id, budget, napi);
- pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
+ if (!ab->hw_params.full_monitor_mode) {
+ ath11k_dp_rx_mon_dest_process(ar, mac_id,
+ budget, napi);
+ pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
+ }
}
if (ppdu_info->peer_id == HAL_INVALID_PEERID ||
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index f29ac6de7139..19702b6f09c3 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -306,7 +306,7 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
struct sk_buff *skb)
{
struct wil6210_rtap {
- struct ieee80211_radiotap_header rthdr;
+ struct ieee80211_radiotap_header_fixed rthdr;
/* fields should be in the order of bits in rthdr.it_present */
/* flags */
u8 flags;
diff --git a/drivers/net/wireless/broadcom/brcm80211/Kconfig b/drivers/net/wireless/broadcom/brcm80211/Kconfig
index 3a1a35b5672f..19d0c003f626 100644
--- a/drivers/net/wireless/broadcom/brcm80211/Kconfig
+++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig
@@ -27,6 +27,7 @@ source "drivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig"
config BRCM_TRACING
bool "Broadcom device tracing"
depends on BRCMSMAC || BRCMFMAC
+ depends on TRACING
help
If you say Y here, the Broadcom wireless drivers will register
with ftrace to dump event information into the trace ringbuffer.
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
index b6636002c7d2..fe75941c584d 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -2518,7 +2518,7 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i,
* to build this manually element by element, we can write it much
* more efficiently than we can parse it. ORDER MATTERS HERE */
struct ipw_rt_hdr {
- struct ieee80211_radiotap_header rt_hdr;
+ struct ieee80211_radiotap_header_fixed rt_hdr;
s8 rt_dbmsignal; /* signal in dbM, kluged to signed */
} *ipw_rt;
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.h b/drivers/net/wireless/intel/ipw2x00/ipw2200.h
index 8ebf09121e17..226286cb7eb8 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.h
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.h
@@ -1143,7 +1143,7 @@ struct ipw_prom_priv {
* structure is provided regardless of any bits unset.
*/
struct ipw_rt_hdr {
- struct ieee80211_radiotap_header rt_hdr;
+ struct ieee80211_radiotap_header_fixed rt_hdr;
u64 rt_tsf; /* TSF */ /* XXX */
u8 rt_flags; /* radiotap packet flags */
u8 rt_rate; /* rate in 500kb/s */
diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c
index 9d33a66a49b5..958dd4f9bc69 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.c
+++ b/drivers/net/wireless/intel/iwlegacy/common.c
@@ -3122,6 +3122,7 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd)
struct il_cmd_meta *out_meta;
dma_addr_t phys_addr;
unsigned long flags;
+ u8 *out_payload;
u32 idx;
u16 fix_size;
@@ -3157,6 +3158,16 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd)
out_cmd = txq->cmd[idx];
out_meta = &txq->meta[idx];
+ /* The payload is in the same place in regular and huge
+ * command buffers, but we need to let the compiler know when
+ * we're using a larger payload buffer to avoid "field-
+ * spanning write" warnings at run-time for huge commands.
+ */
+ if (cmd->flags & CMD_SIZE_HUGE)
+ out_payload = ((struct il_device_cmd_huge *)out_cmd)->cmd.payload;
+ else
+ out_payload = out_cmd->cmd.payload;
+
if (WARN_ON(out_meta->flags & CMD_MAPPED)) {
spin_unlock_irqrestore(&il->hcmd_lock, flags);
return -ENOSPC;
@@ -3170,7 +3181,7 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd)
out_meta->callback = cmd->callback;
out_cmd->hdr.cmd = cmd->id;
- memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
+ memcpy(out_payload, cmd->data, cmd->len);
/* At this point, the out_cmd now has all of the incoming cmd
* information */
@@ -4962,6 +4973,8 @@ il_pci_resume(struct device *device)
*/
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+ _il_wr(il, CSR_INT, 0xffffffff);
+ _il_wr(il, CSR_FH_INT_STATUS, 0xffffffff);
il_enable_interrupts(il);
if (!(_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
diff --git a/drivers/net/wireless/intel/iwlegacy/common.h b/drivers/net/wireless/intel/iwlegacy/common.h
index 2147781b5fff..725c2a88ddb7 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.h
+++ b/drivers/net/wireless/intel/iwlegacy/common.h
@@ -560,6 +560,18 @@ struct il_device_cmd {
#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct il_device_cmd))
+/**
+ * struct il_device_cmd_huge
+ *
+ * For use when sending huge commands.
+ */
+struct il_device_cmd_huge {
+ struct il_cmd_header hdr; /* uCode API */
+ union {
+ u8 payload[IL_MAX_CMD_SIZE - sizeof(struct il_cmd_header)];
+ } __packed cmd;
+} __packed;
+
struct il_host_cmd {
const void *data;
unsigned long reply_page;
diff --git a/drivers/net/wireless/marvell/libertas/radiotap.h b/drivers/net/wireless/marvell/libertas/radiotap.h
index 1ed5608d353f..d543bfe739dc 100644
--- a/drivers/net/wireless/marvell/libertas/radiotap.h
+++ b/drivers/net/wireless/marvell/libertas/radiotap.h
@@ -2,7 +2,7 @@
#include <net/ieee80211_radiotap.h>
struct tx_radiotap_hdr {
- struct ieee80211_radiotap_header hdr;
+ struct ieee80211_radiotap_header_fixed hdr;
u8 rate;
u8 txpower;
u8 rts_retries;
@@ -31,7 +31,7 @@ struct tx_radiotap_hdr {
#define IEEE80211_FC_DSTODS 0x0300
struct rx_radiotap_hdr {
- struct ieee80211_radiotap_header hdr;
+ struct ieee80211_radiotap_header_fixed hdr;
u8 flags;
u8 rate;
u8 antsignal;
diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c
index 98da82b74094..3353012e8542 100644
--- a/drivers/net/wireless/mediatek/mt76/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mcu.c
@@ -84,13 +84,16 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
mutex_lock(&dev->mcu.mutex);
if (dev->mcu_ops->mcu_skb_prepare_msg) {
+ orig_skb = skb;
ret = dev->mcu_ops->mcu_skb_prepare_msg(dev, skb, cmd, &seq);
if (ret < 0)
goto out;
}
retry:
- orig_skb = skb_get(skb);
+ /* orig skb might be needed for retry, mcu_skb_send_msg consumes it */
+ if (orig_skb)
+ skb_get(orig_skb);
ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, &seq);
if (ret < 0)
goto out;
@@ -105,7 +108,7 @@ retry:
do {
skb = mt76_mcu_get_response(dev, expires);
if (!skb && !test_bit(MT76_MCU_RESET, &dev->phy.state) &&
- retry++ < dev->mcu_ops->max_retry) {
+ orig_skb && retry++ < dev->mcu_ops->max_retry) {
dev_err(dev->dev, "Retry message %08x (seq %d)\n",
cmd, seq);
skb = orig_skb;
diff --git a/drivers/net/wireless/microchip/wilc1000/mon.c b/drivers/net/wireless/microchip/wilc1000/mon.c
index 03b7229a0ff5..c3d27aaec297 100644
--- a/drivers/net/wireless/microchip/wilc1000/mon.c
+++ b/drivers/net/wireless/microchip/wilc1000/mon.c
@@ -7,12 +7,12 @@
#include "cfg80211.h"
struct wilc_wfi_radiotap_hdr {
- struct ieee80211_radiotap_header hdr;
+ struct ieee80211_radiotap_header_fixed hdr;
u8 rate;
} __packed;
struct wilc_wfi_radiotap_cb_hdr {
- struct ieee80211_radiotap_header hdr;
+ struct ieee80211_radiotap_header_fixed hdr;
u8 rate;
u8 dump;
u16 tx_flags;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192du/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192du/sw.c
index d069a81ac617..cc699efa9c79 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192du/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192du/sw.c
@@ -352,7 +352,6 @@ static const struct usb_device_id rtl8192d_usb_ids[] = {
{RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8194, rtl92du_hal_cfg)},
{RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8111, rtl92du_hal_cfg)},
{RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x0193, rtl92du_hal_cfg)},
- {RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0x8171, rtl92du_hal_cfg)},
{RTL_USB_DEVICE(USB_VENDOR_ID_REALTEK, 0xe194, rtl92du_hal_cfg)},
{RTL_USB_DEVICE(0x2019, 0xab2c, rtl92du_hal_cfg)},
{RTL_USB_DEVICE(0x2019, 0xab2d, rtl92du_hal_cfg)},
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index e83ab6fb83f5..b17a429bcd29 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -771,7 +771,6 @@ static void rtw_usb_dynamic_rx_agg_v1(struct rtw_dev *rtwdev, bool enable)
u8 size, timeout;
u16 val16;
- rtw_write32_set(rtwdev, REG_RXDMA_AGG_PG_TH, BIT_EN_PRE_CALC);
rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_AGG_EN);
rtw_write8_clr(rtwdev, REG_RXDMA_AGG_PG_TH + 3, BIT(7));
diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index df51b29142aa..8d27374db83c 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -6445,6 +6445,8 @@ static void _update_wl_info_v7(struct rtw89_dev *rtwdev, u8 rid)
/* todo DBCC related event */
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] wl_info phy_now=%d\n", phy_now);
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g);
if (wl_rinfo->dbcc_en != rtwdev->dbcc_en) {
wl_rinfo->dbcc_chg = 1;
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index 02afeb3acce4..5aef7fa37878 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -3026,24 +3026,54 @@ static void rtw89_pci_declaim_device(struct rtw89_dev *rtwdev,
pci_disable_device(pdev);
}
-static void rtw89_pci_cfg_dac(struct rtw89_dev *rtwdev)
+static bool rtw89_pci_chip_is_manual_dac(struct rtw89_dev *rtwdev)
{
- struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
const struct rtw89_chip_info *chip = rtwdev->chip;
- if (!rtwpci->enable_dac)
- return;
-
switch (chip->chip_id) {
case RTL8852A:
case RTL8852B:
case RTL8851B:
case RTL8852BT:
- break;
+ return true;
default:
- return;
+ return false;
+ }
+}
+
+static bool rtw89_pci_is_dac_compatible_bridge(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+ struct pci_dev *bridge = pci_upstream_bridge(rtwpci->pdev);
+
+ if (!rtw89_pci_chip_is_manual_dac(rtwdev))
+ return true;
+
+ if (!bridge)
+ return false;
+
+ switch (bridge->vendor) {
+ case PCI_VENDOR_ID_INTEL:
+ return true;
+ case PCI_VENDOR_ID_ASMEDIA:
+ if (bridge->device == 0x2806)
+ return true;
+ break;
}
+ return false;
+}
+
+static void rtw89_pci_cfg_dac(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+
+ if (!rtwpci->enable_dac)
+ return;
+
+ if (!rtw89_pci_chip_is_manual_dac(rtwdev))
+ return;
+
rtw89_pci_config_byte_set(rtwdev, RTW89_PCIE_L1_CTRL, RTW89_PCIE_BIT_EN_64BITS);
}
@@ -3061,6 +3091,9 @@ static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev,
goto err;
}
+ if (!rtw89_pci_is_dac_compatible_bridge(rtwdev))
+ goto no_dac;
+
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36));
if (!ret) {
rtwpci->enable_dac = true;
@@ -3073,6 +3106,7 @@ static int rtw89_pci_setup_mapping(struct rtw89_dev *rtwdev,
goto err_release_regions;
}
}
+no_dac:
resource_len = pci_resource_len(pdev, bar_id);
rtwpci->mmap = pci_iomap(pdev, bar_id, resource_len);
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index f0e528abb1b4..3f424f14de4e 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -763,7 +763,7 @@ static const struct rhashtable_params hwsim_rht_params = {
};
struct hwsim_radiotap_hdr {
- struct ieee80211_radiotap_header hdr;
+ struct ieee80211_radiotap_header_fixed hdr;
__le64 rt_tsft;
u8 rt_flags;
u8 rt_rate;
@@ -772,7 +772,7 @@ struct hwsim_radiotap_hdr {
} __packed;
struct hwsim_radiotap_ack_hdr {
- struct ieee80211_radiotap_header hdr;
+ struct ieee80211_radiotap_header_fixed hdr;
u8 rt_flags;
u8 pad;
__le16 rt_channel;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 69ec1eb41a09..941dc62f3027 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -6130,6 +6130,50 @@ void wiphy_delayed_work_flush(struct wiphy *wiphy,
struct wiphy_delayed_work *dwork);
/**
+ * wiphy_delayed_work_pending - Find out whether a wiphy delayable
+ * work item is currently pending.
+ *
+ * @wiphy: the wiphy, for debug purposes
+ * @dwork: the delayed work in question
+ *
+ * Return: true if timer is pending, false otherwise
+ *
+ * How wiphy_delayed_work_queue() works is by setting a timer which
+ * when it expires calls wiphy_work_queue() to queue the wiphy work.
+ * Because wiphy_delayed_work_queue() uses mod_timer(), if it is
+ * called twice and the second call happens before the first call
+ * deadline, the work will rescheduled for the second deadline and
+ * won't run before that.
+ *
+ * wiphy_delayed_work_pending() can be used to detect if calling
+ * wiphy_work_delayed_work_queue() would start a new work schedule
+ * or delayed a previous one. As seen below it cannot be used to
+ * detect precisely if the work has finished to execute nor if it
+ * is currently executing.
+ *
+ * CPU0 CPU1
+ * wiphy_delayed_work_queue(wk)
+ * mod_timer(wk->timer)
+ * wiphy_delayed_work_pending(wk) -> true
+ *
+ * [...]
+ * expire_timers(wk->timer)
+ * detach_timer(wk->timer)
+ * wiphy_delayed_work_pending(wk) -> false
+ * wk->timer->function() |
+ * wiphy_work_queue(wk) | delayed work pending
+ * list_add_tail() | returns false but
+ * queue_work(cfg80211_wiphy_work) | wk->func() has not
+ * | been run yet
+ * [...] |
+ * cfg80211_wiphy_work() |
+ * wk->func() V
+ *
+ */
+bool wiphy_delayed_work_pending(struct wiphy *wiphy,
+ struct wiphy_delayed_work *dwork);
+
+/**
* enum ieee80211_ap_reg_power - regulatory power for an Access Point
*
* @IEEE80211_REG_UNSET_AP: Access Point has no regulatory power mode
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index 02fbc036f34e..813e163ce27c 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -24,25 +24,27 @@
* struct ieee80211_radiotap_header - base radiotap header
*/
struct ieee80211_radiotap_header {
- /**
- * @it_version: radiotap version, always 0
- */
- uint8_t it_version;
-
- /**
- * @it_pad: padding (or alignment)
- */
- uint8_t it_pad;
-
- /**
- * @it_len: overall radiotap header length
- */
- __le16 it_len;
-
- /**
- * @it_present: (first) present word
- */
- __le32 it_present;
+ __struct_group(ieee80211_radiotap_header_fixed, hdr, __packed,
+ /**
+ * @it_version: radiotap version, always 0
+ */
+ uint8_t it_version;
+
+ /**
+ * @it_pad: padding (or alignment)
+ */
+ uint8_t it_pad;
+
+ /**
+ * @it_len: overall radiotap header length
+ */
+ __le16 it_len;
+
+ /**
+ * @it_present: (first) present word
+ */
+ __le32 it_present;
+ );
/**
* @it_optional: all remaining presence bitmaps
@@ -50,6 +52,9 @@ struct ieee80211_radiotap_header {
__le32 it_optional[];
} __packed;
+static_assert(offsetof(struct ieee80211_radiotap_header, it_optional) == sizeof(struct ieee80211_radiotap_header_fixed),
+ "struct member likely outside of __struct_group()");
+
/* version is always 0 */
#define PKTHDR_RADIOTAP_VERSION 0
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 13438cc0a6b1..cf0f7780fb10 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -96,7 +96,7 @@ config MAC80211_DEBUGFS
config MAC80211_MESSAGE_TRACING
bool "Trace all mac80211 debug messages"
- depends on MAC80211
+ depends on MAC80211 && TRACING
help
Select this option to have mac80211 register the
mac80211_msg trace subsystem with tracepoints to
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 847304a3a29a..6dfc61a9acd4 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3046,6 +3046,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
enum nl80211_tx_power_setting txp_type = type;
bool update_txp_type = false;
bool has_monitor = false;
+ int old_power = local->user_power_level;
lockdep_assert_wiphy(local->hw.wiphy);
@@ -3128,6 +3129,10 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
}
}
+ if (local->emulate_chanctx &&
+ (old_power != local->user_power_level))
+ ieee80211_hw_conf_chan(local);
+
return 0;
}
@@ -3138,7 +3143,8 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy,
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
- if (local->ops->get_txpower)
+ if (local->ops->get_txpower &&
+ (sdata->flags & IEEE80211_SDATA_IN_DRIVER))
return drv_get_txpower(local, sdata, dbm);
if (local->emulate_chanctx)
@@ -4826,12 +4832,12 @@ void ieee80211_color_change_finalize_work(struct wiphy *wiphy,
ieee80211_color_change_finalize(link);
}
-void ieee80211_color_collision_detection_work(struct work_struct *work)
+void ieee80211_color_collision_detection_work(struct wiphy *wiphy,
+ struct wiphy_work *work)
{
- struct delayed_work *delayed_work = to_delayed_work(work);
struct ieee80211_link_data *link =
- container_of(delayed_work, struct ieee80211_link_data,
- color_collision_detect_work);
+ container_of(work, struct ieee80211_link_data,
+ color_collision_detect_work.work);
struct ieee80211_sub_if_data *sdata = link->sdata;
cfg80211_obss_color_collision_notify(sdata->dev, link->color_bitmap,
@@ -4884,7 +4890,8 @@ ieee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
return;
}
- if (delayed_work_pending(&link->color_collision_detect_work)) {
+ if (wiphy_delayed_work_pending(sdata->local->hw.wiphy,
+ &link->color_collision_detect_work)) {
rcu_read_unlock();
return;
}
@@ -4893,9 +4900,9 @@ ieee80211_obss_color_collision_notify(struct ieee80211_vif *vif,
/* queue the color collision detection event every 500 ms in order to
* avoid sending too much netlink messages to userspace.
*/
- ieee80211_queue_delayed_work(&sdata->local->hw,
- &link->color_collision_detect_work,
- msecs_to_jiffies(500));
+ wiphy_delayed_work_queue(sdata->local->hw.wiphy,
+ &link->color_collision_detect_work,
+ msecs_to_jiffies(500));
rcu_read_unlock();
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4f0390918b60..04fec7e516cf 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1053,7 +1053,7 @@ struct ieee80211_link_data {
} csa;
struct wiphy_work color_change_finalize_work;
- struct delayed_work color_collision_detect_work;
+ struct wiphy_delayed_work color_collision_detect_work;
u64 color_bitmap;
/* context reservation -- protected with wiphy mutex */
@@ -2005,7 +2005,8 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
/* color change handling */
void ieee80211_color_change_finalize_work(struct wiphy *wiphy,
struct wiphy_work *work);
-void ieee80211_color_collision_detection_work(struct work_struct *work);
+void ieee80211_color_collision_detection_work(struct wiphy *wiphy,
+ struct wiphy_work *work);
/* interface handling */
#define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 6fac3ba00d88..67ecfea22982 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -987,6 +987,26 @@ void ieee80211_reenable_keys(struct ieee80211_sub_if_data *sdata)
}
}
+static void
+ieee80211_key_iter(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_key *key,
+ void (*iter)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key,
+ void *data),
+ void *iter_data)
+{
+ /* skip keys of station in removal process */
+ if (key->sta && key->sta->removed)
+ return;
+ if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
+ return;
+ iter(hw, vif, key->sta ? &key->sta->sta : NULL,
+ &key->conf, iter_data);
+}
+
void ieee80211_iter_keys(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
void (*iter)(struct ieee80211_hw *hw,
@@ -1005,16 +1025,13 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
if (vif) {
sdata = vif_to_sdata(vif);
list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
- iter(hw, &sdata->vif,
- key->sta ? &key->sta->sta : NULL,
- &key->conf, iter_data);
+ ieee80211_key_iter(hw, vif, key, iter, iter_data);
} else {
list_for_each_entry(sdata, &local->interfaces, list)
list_for_each_entry_safe(key, tmp,
&sdata->key_list, list)
- iter(hw, &sdata->vif,
- key->sta ? &key->sta->sta : NULL,
- &key->conf, iter_data);
+ ieee80211_key_iter(hw, &sdata->vif, key,
+ iter, iter_data);
}
}
EXPORT_SYMBOL(ieee80211_iter_keys);
@@ -1031,17 +1048,8 @@ _ieee80211_iter_keys_rcu(struct ieee80211_hw *hw,
{
struct ieee80211_key *key;
- list_for_each_entry_rcu(key, &sdata->key_list, list) {
- /* skip keys of station in removal process */
- if (key->sta && key->sta->removed)
- continue;
- if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
- continue;
-
- iter(hw, &sdata->vif,
- key->sta ? &key->sta->sta : NULL,
- &key->conf, iter_data);
- }
+ list_for_each_entry_rcu(key, &sdata->key_list, list)
+ ieee80211_key_iter(hw, &sdata->vif, key, iter, iter_data);
}
void ieee80211_iter_keys_rcu(struct ieee80211_hw *hw,
diff --git a/net/mac80211/link.c b/net/mac80211/link.c
index 0bbac64d5fa0..46092fbcde90 100644
--- a/net/mac80211/link.c
+++ b/net/mac80211/link.c
@@ -41,8 +41,8 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
ieee80211_csa_finalize_work);
wiphy_work_init(&link->color_change_finalize_work,
ieee80211_color_change_finalize_work);
- INIT_DELAYED_WORK(&link->color_collision_detect_work,
- ieee80211_color_collision_detection_work);
+ wiphy_delayed_work_init(&link->color_collision_detect_work,
+ ieee80211_color_collision_detection_work);
INIT_LIST_HEAD(&link->assigned_chanctx_list);
INIT_LIST_HEAD(&link->reserved_chanctx_list);
wiphy_delayed_work_init(&link->dfs_cac_timer_work,
@@ -72,7 +72,8 @@ void ieee80211_link_stop(struct ieee80211_link_data *link)
if (link->sdata->vif.type == NL80211_IFTYPE_STATION)
ieee80211_mgd_stop_link(link);
- cancel_delayed_work_sync(&link->color_collision_detect_work);
+ wiphy_delayed_work_cancel(link->sdata->local->hw.wiphy,
+ &link->color_collision_detect_work);
wiphy_work_cancel(link->sdata->local->hw.wiphy,
&link->color_change_finalize_work);
wiphy_work_cancel(link->sdata->local->hw.wiphy,
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 661adfc77644..8331064de9dd 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1704,6 +1704,13 @@ void wiphy_delayed_work_flush(struct wiphy *wiphy,
}
EXPORT_SYMBOL_GPL(wiphy_delayed_work_flush);
+bool wiphy_delayed_work_pending(struct wiphy *wiphy,
+ struct wiphy_delayed_work *dwork)
+{
+ return timer_pending(&dwork->timer);
+}
+EXPORT_SYMBOL_GPL(wiphy_delayed_work_pending);
+
static int __init cfg80211_init(void)
{
int err;
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 59a90bf3c0d6..d0aed41ded2f 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -3050,6 +3050,10 @@ cfg80211_parse_ml_elem_sta_data(struct wiphy *wiphy,
freq = ieee80211_channel_to_freq_khz(ap_info->channel, band);
data.channel = ieee80211_get_channel_khz(wiphy, freq);
+ /* Skip if RNR element specifies an unsupported channel */
+ if (!data.channel)
+ continue;
+
/* Skip if BSS entry generated from MBSSID or DIRECT source
* frame data available already.
*/