diff options
106 files changed, 5790 insertions, 1419 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 48bacf763e91..61fe86968111 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20660,7 +20660,6 @@ W: https://wireless.wiki.kernel.org/en/users/Drivers/wl12xx W: https://wireless.wiki.kernel.org/en/users/Drivers/wl1251 T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git F: drivers/net/wireless/ti/ -F: include/linux/wl12xx.h TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER M: John Stultz <jstultz@google.com> diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index 5b99d602c87b..9409b9f5711c 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -10,7 +10,6 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/of_platform.h> -#include <linux/wl12xx.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h> #include <linux/power/smartreflex.h> diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 44392b624b20..0a8469e0b13a 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -344,8 +344,10 @@ static int bcma_register_devices(struct bcma_bus *bus) err = bcma_gpio_init(&bus->drv_cc); if (err == -ENOTSUPP) bcma_debug(bus, "GPIO driver not activated\n"); - else if (err) + else if (err) { bcma_err(bus, "Error registering GPIO driver: %i\n", err); + return err; + } if (bus->hosttype == BCMA_HOSTTYPE_SOC) { err = bcma_chipco_watchdog_register(&bus->drv_cc); diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c index a184c09d2f0f..19f61225a708 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.c +++ b/drivers/net/wireless/ath/ar5523/ar5523.c @@ -241,6 +241,11 @@ static void ar5523_cmd_tx_cb(struct urb *urb) } } +static void ar5523_cancel_tx_cmd(struct ar5523 *ar) +{ + usb_kill_urb(ar->tx_cmd.urb_tx); +} + static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata, int ilen, void *odata, int olen, int flags) { @@ -280,6 +285,7 @@ static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata, } if (!wait_for_completion_timeout(&cmd->done, 2 * HZ)) { + ar5523_cancel_tx_cmd(ar); cmd->odata = NULL; ar5523_err(ar, "timeout waiting for command %02x reply\n", code); diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 400f332a7ff0..5eb131ab916f 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -99,6 +99,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = false, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA988X_HW_2_0_VERSION, @@ -138,6 +139,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = false, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA9887_HW_1_0_VERSION, @@ -178,6 +180,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = false, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA6174_HW_3_2_VERSION, @@ -213,6 +216,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = true, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA6174_HW_2_1_VERSION, @@ -252,6 +256,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = false, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA6174_HW_2_1_VERSION, @@ -291,6 +296,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = false, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA6174_HW_3_0_VERSION, @@ -330,6 +336,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = false, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA6174_HW_3_2_VERSION, @@ -373,6 +380,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = true, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA99X0_HW_2_0_DEV_VERSION, @@ -418,6 +426,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = false, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA9984_HW_1_0_DEV_VERSION, @@ -470,6 +479,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = false, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA9888_HW_2_0_DEV_VERSION, @@ -519,6 +529,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = false, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA9377_HW_1_0_DEV_VERSION, @@ -558,6 +569,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = false, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA9377_HW_1_1_DEV_VERSION, @@ -599,6 +611,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = false, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA9377_HW_1_1_DEV_VERSION, @@ -631,6 +644,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = false, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = QCA4019_HW_1_0_DEV_VERSION, @@ -677,6 +691,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = false, .hw_restart_disconnect = false, .use_fw_tx_credits = true, + .delay_unmap_buffer = false, }, { .id = WCN3990_HW_1_0_DEV_VERSION, @@ -709,6 +724,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .dynamic_sar_support = true, .hw_restart_disconnect = true, .use_fw_tx_credits = false, + .delay_unmap_buffer = true, }, }; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index c861e66ef6bc..b9aea1510f7b 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -10,6 +10,7 @@ #include <linux/vmalloc.h> #include <linux/crc32.h> #include <linux/firmware.h> +#include <linux/kstrtox.h> #include "core.h" #include "debug.h" @@ -1975,7 +1976,7 @@ static ssize_t ath10k_write_btcoex(struct file *file, buf[buf_size] = '\0'; - if (strtobool(buf, &val) != 0) + if (kstrtobool(buf, &val) != 0) return -EINVAL; if (!ar->coex_support) @@ -2113,7 +2114,7 @@ static ssize_t ath10k_write_peer_stats(struct file *file, buf[buf_size] = '\0'; - if (strtobool(buf, &val) != 0) + if (kstrtobool(buf, &val) != 0) return -EINVAL; mutex_lock(&ar->conf_mutex); diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 6d1784f74bea..5bfeecb95fca 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -56,6 +56,15 @@ void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep, ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %pK\n", __func__, ep->eid, skb); + /* A corner case where the copy completion is reaching to host but still + * copy engine is processing it due to which host unmaps corresponding + * memory and causes SMMU fault, hence as workaround adding delay + * the unmapping memory to avoid SMMU faults. + */ + if (ar->hw_params.delay_unmap_buffer && + ep->ul_pipe_id == 3) + mdelay(2); + hdr = (struct ath10k_htc_hdr *)skb->data; ath10k_htc_restore_tx_skb(ep->htc, skb); diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index f06cf39204e2..c051a22fce14 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1108,8 +1108,10 @@ struct htt_rx_in_ord_ind { u8 reserved; __le16 msdu_count; union { - struct htt_rx_in_ord_msdu_desc msdu_descs32[0]; - struct htt_rx_in_ord_msdu_desc_ext msdu_descs64[0]; + DECLARE_FLEX_ARRAY(struct htt_rx_in_ord_msdu_desc, + msdu_descs32); + DECLARE_FLEX_ARRAY(struct htt_rx_in_ord_msdu_desc_ext, + msdu_descs64); } __packed; } __packed; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 1b99f3a39a11..9643031a4427 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -637,6 +637,8 @@ struct ath10k_hw_params { bool hw_restart_disconnect; bool use_fw_tx_credits; + + bool delay_unmap_buffer; }; struct htt_resp; diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 876410a47d1d..6b6aa3c36744 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -584,7 +584,14 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb) ath10k_warn(ar, "did not find station from tdls peer event"); goto exit; } + arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id)); + if (!arvif) { + ath10k_warn(ar, "no vif for vdev_id %d found", + __le32_to_cpu(ev->vdev_id)); + goto exit; + } + ieee80211_tdls_oper_request( arvif->vif, station->addr, NL80211_TDLS_TEARDOWN, diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index b99180bc8172..0ab2f190f1ec 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -1641,7 +1641,7 @@ static void ath11k_update_11d(struct work_struct *work) } } -static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) +void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) { struct ath11k *ar; struct ath11k_pdev *pdev; @@ -1677,6 +1677,10 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) ath11k_mac_tx_mgmt_pending_free, ar); idr_destroy(&ar->txmgmt_idr); wake_up(&ar->txmgmt_empty_waitq); + + ar->monitor_vdev_id = -1; + clear_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags); + clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); } wake_up(&ab->wmi_ab.tx_credits_wq); @@ -1730,9 +1734,6 @@ static void ath11k_core_restart(struct work_struct *work) struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work); int ret; - if (!ab->is_reset) - ath11k_core_pre_reconfigure_recovery(ab); - ret = ath11k_core_reconfigure_on_crash(ab); if (ret) { ath11k_err(ab, "failed to reconfigure driver on crash recovery\n"); diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index cf2f52cc4e30..22460b0abf03 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -505,6 +505,8 @@ struct ath11k_sta { u64 ps_start_jiffies; u64 ps_total_duration; bool peer_current_ps_valid; + + u32 bw_prev; }; #define ATH11K_MIN_5G_FREQ 4150 @@ -1157,6 +1159,7 @@ int ath11k_core_check_smbios(struct ath11k_base *ab); void ath11k_core_halt(struct ath11k *ar); int ath11k_core_resume(struct ath11k_base *ab); int ath11k_core_suspend(struct ath11k_base *ab); +void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab); const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, const char *filename); diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 3cbcbb93a1a7..6426a38f8961 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -241,7 +241,10 @@ const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default = { #define ath11k_a_rates (ath11k_legacy_rates + 4) #define ath11k_a_rates_size (ARRAY_SIZE(ath11k_legacy_rates) - 4) -#define ATH11K_MAC_SCAN_TIMEOUT_MSECS 200 /* in msecs */ +#define ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD 200 /* in msecs */ + +/* Overhead due to the processing of channel switch events from FW */ +#define ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD 10 /* in msecs */ static const u32 ath11k_smps_map[] = { [WLAN_HT_CAP_SM_PS_STATIC] = WMI_PEER_SMPS_STATIC, @@ -3612,6 +3615,7 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw, struct scan_req_params arg; int ret = 0; int i; + u32 scan_timeout; mutex_lock(&ar->conf_mutex); @@ -3681,6 +3685,26 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw, ether_addr_copy(arg.mac_mask.addr, req->mac_addr_mask); } + /* if duration is set, default dwell times will be overwritten */ + if (req->duration) { + arg.dwell_time_active = req->duration; + arg.dwell_time_active_2g = req->duration; + arg.dwell_time_active_6g = req->duration; + arg.dwell_time_passive = req->duration; + arg.dwell_time_passive_6g = req->duration; + arg.burst_duration = req->duration; + + scan_timeout = min_t(u32, arg.max_rest_time * + (arg.num_chan - 1) + (req->duration + + ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) * + arg.num_chan, arg.max_scan_time); + } else { + scan_timeout = arg.max_scan_time; + } + + /* Add a margin to account for event/command processing */ + scan_timeout += ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD; + ret = ath11k_start_scan(ar, &arg); if (ret) { ath11k_warn(ar->ab, "failed to start hw scan: %d\n", ret); @@ -3689,10 +3713,8 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw, spin_unlock_bh(&ar->data_lock); } - /* Add a 200ms margin to account for event/command processing */ ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout, - msecs_to_jiffies(arg.max_scan_time + - ATH11K_MAC_SCAN_TIMEOUT_MSECS)); + msecs_to_jiffies(scan_timeout)); exit: kfree(arg.chan_list); @@ -4215,10 +4237,11 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; const u16 *he_mcs_mask; - u32 changed, bw, nss, smps; + u32 changed, bw, nss, smps, bw_prev; int err, num_vht_rates, num_he_rates; const struct cfg80211_bitrate_mask *mask; struct peer_assoc_params peer_arg; + enum wmi_phy_mode peer_phymode; arsta = container_of(wk, struct ath11k_sta, update_wk); sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv); @@ -4239,6 +4262,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) arsta->changed = 0; bw = arsta->bw; + bw_prev = arsta->bw_prev; nss = arsta->nss; smps = arsta->smps; @@ -4252,26 +4276,57 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) ath11k_mac_max_he_nss(he_mcs_mask))); if (changed & IEEE80211_RC_BW_CHANGED) { - /* Send peer assoc command before set peer bandwidth param to - * avoid the mismatch between the peer phymode and the peer - * bandwidth. - */ - ath11k_peer_assoc_prepare(ar, arvif->vif, sta, &peer_arg, true); - - peer_arg.is_assoc = false; - err = ath11k_wmi_send_peer_assoc_cmd(ar, &peer_arg); - if (err) { - ath11k_warn(ar->ab, "failed to send peer assoc for STA %pM vdev %i: %d\n", - sta->addr, arvif->vdev_id, err); - } else if (wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) { + /* Get the peer phymode */ + ath11k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg); + peer_phymode = peer_arg.peer_phymode; + + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM peer bw %d phymode %d\n", + sta->addr, bw, peer_phymode); + + if (bw > bw_prev) { + /* BW is upgraded. In this case we send WMI_PEER_PHYMODE + * followed by WMI_PEER_CHWIDTH + */ + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW upgrade for sta %pM new BW %d, old BW %d\n", + sta->addr, bw, bw_prev); + + err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, + WMI_PEER_PHYMODE, peer_phymode); + + if (err) { + ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n", + sta->addr, peer_phymode, err); + goto err_rc_bw_changed; + } + err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, WMI_PEER_CHWIDTH, bw); + if (err) ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", sta->addr, bw, err); } else { - ath11k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n", - sta->addr, arvif->vdev_id); + /* BW is downgraded. In this case we send WMI_PEER_CHWIDTH + * followed by WMI_PEER_PHYMODE + */ + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW downgrade for sta %pM new BW %d,old BW %d\n", + sta->addr, bw, bw_prev); + + err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, + WMI_PEER_CHWIDTH, bw); + + if (err) { + ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", + sta->addr, bw, err); + goto err_rc_bw_changed; + } + + err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, + WMI_PEER_PHYMODE, peer_phymode); + + if (err) + ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n", + sta->addr, peer_phymode, err); } } @@ -4352,6 +4407,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) } } +err_rc_bw_changed: mutex_unlock(&ar->conf_mutex); } @@ -4505,6 +4561,34 @@ exit: return ret; } +static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar, + struct ieee80211_sta *sta) +{ + u32 bw = WMI_PEER_CHWIDTH_20MHZ; + + switch (sta->deflink.bandwidth) { + case IEEE80211_STA_RX_BW_20: + bw = WMI_PEER_CHWIDTH_20MHZ; + break; + case IEEE80211_STA_RX_BW_40: + bw = WMI_PEER_CHWIDTH_40MHZ; + break; + case IEEE80211_STA_RX_BW_80: + bw = WMI_PEER_CHWIDTH_80MHZ; + break; + case IEEE80211_STA_RX_BW_160: + bw = WMI_PEER_CHWIDTH_160MHZ; + break; + default: + ath11k_warn(ar->ab, "Invalid bandwidth %d for %pM\n", + sta->deflink.bandwidth, sta->addr); + bw = WMI_PEER_CHWIDTH_20MHZ; + break; + } + + return bw; +} + static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -4590,6 +4674,12 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, if (ret) ath11k_warn(ar->ab, "Failed to associate station: %pM\n", sta->addr); + + spin_lock_bh(&ar->data_lock); + /* Set arsta bw and prev bw */ + arsta->bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta); + arsta->bw_prev = arsta->bw; + spin_unlock_bh(&ar->data_lock); } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTHORIZED) { spin_lock_bh(&ar->ab->base_lock); @@ -4713,28 +4803,8 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw, spin_lock_bh(&ar->data_lock); if (changed & IEEE80211_RC_BW_CHANGED) { - bw = WMI_PEER_CHWIDTH_20MHZ; - - switch (sta->deflink.bandwidth) { - case IEEE80211_STA_RX_BW_20: - bw = WMI_PEER_CHWIDTH_20MHZ; - break; - case IEEE80211_STA_RX_BW_40: - bw = WMI_PEER_CHWIDTH_40MHZ; - break; - case IEEE80211_STA_RX_BW_80: - bw = WMI_PEER_CHWIDTH_80MHZ; - break; - case IEEE80211_STA_RX_BW_160: - bw = WMI_PEER_CHWIDTH_160MHZ; - break; - default: - ath11k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n", - sta->deflink.bandwidth, sta->addr); - bw = WMI_PEER_CHWIDTH_20MHZ; - break; - } - + bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta); + arsta->bw_prev = arsta->bw; arsta->bw = bw; } @@ -6163,6 +6233,40 @@ void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab) } } +static int ath11k_mac_vdev_delete(struct ath11k *ar, struct ath11k_vif *arvif) +{ + unsigned long time_left; + struct ieee80211_vif *vif = arvif->vif; + int ret = 0; + + lockdep_assert_held(&ar->conf_mutex); + + reinit_completion(&ar->vdev_delete_done); + + ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id); + if (ret) { + ath11k_warn(ar->ab, "failed to delete WMI vdev %d: %d\n", + arvif->vdev_id, ret); + return ret; + } + + time_left = wait_for_completion_timeout(&ar->vdev_delete_done, + ATH11K_VDEV_DELETE_TIMEOUT_HZ); + if (time_left == 0) { + ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n"); + return -ETIMEDOUT; + } + + ar->ab->free_vdev_map |= 1LL << (arvif->vdev_id); + ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); + ar->num_created_vdevs--; + + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n", + vif->addr, arvif->vdev_id); + + return ret; +} + static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -6373,18 +6477,16 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, ath11k_dp_vdev_tx_attach(ar, arvif); + ath11k_debugfs_add_interface(arvif); + if (vif->type != NL80211_IFTYPE_MONITOR && test_bit(ATH11K_FLAG_MONITOR_CONF_ENABLED, &ar->monitor_flags)) { ret = ath11k_mac_monitor_vdev_create(ar); - if (ret) { + if (ret) ath11k_warn(ar->ab, "failed to create monitor vdev during add interface: %d", ret); - goto err_peer_del; - } } - ath11k_debugfs_add_interface(arvif); - mutex_unlock(&ar->conf_mutex); return 0; @@ -6400,16 +6502,12 @@ err_peer_del: } err_vdev_del: - ath11k_wmi_vdev_delete(ar, arvif->vdev_id); - ar->num_created_vdevs--; - ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); - ab->free_vdev_map |= 1LL << arvif->vdev_id; + ath11k_mac_vdev_delete(ar, arvif); spin_lock_bh(&ar->data_lock); list_del(&arvif->list); spin_unlock_bh(&ar->data_lock); err: - ath11k_debugfs_remove_interface(arvif); mutex_unlock(&ar->conf_mutex); return ret; @@ -6432,7 +6530,6 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw, struct ath11k *ar = hw->priv; struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); struct ath11k_base *ab = ar->ab; - unsigned long time_left; int ret; int i; @@ -6453,29 +6550,13 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw, arvif->vdev_id, ret); } - reinit_completion(&ar->vdev_delete_done); - - ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id); + ret = ath11k_mac_vdev_delete(ar, arvif); if (ret) { - ath11k_warn(ab, "failed to delete WMI vdev %d: %d\n", + ath11k_warn(ab, "failed to delete vdev %d: %d\n", arvif->vdev_id, ret); goto err_vdev_del; } - time_left = wait_for_completion_timeout(&ar->vdev_delete_done, - ATH11K_VDEV_DELETE_TIMEOUT_HZ); - if (time_left == 0) { - ath11k_warn(ab, "Timeout in receiving vdev delete response\n"); - goto err_vdev_del; - } - - ab->free_vdev_map |= 1LL << (arvif->vdev_id); - ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); - ar->num_created_vdevs--; - - ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n", - vif->addr, arvif->vdev_id); - if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); ar->monitor_vdev_id = -1; @@ -9015,6 +9096,9 @@ static int __ath11k_mac_register(struct ath11k *ar) NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP); } + wiphy_ext_feature_set(ar->hw->wiphy, + NL80211_EXT_FEATURE_SET_SCAN_DWELL); + ath11k_reg_init(ar); if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) { diff --git a/drivers/net/wireless/ath/ath11k/pcic.c b/drivers/net/wireless/ath/ath11k/pcic.c index 380f9d37b644..30d66147223f 100644 --- a/drivers/net/wireless/ath/ath11k/pcic.c +++ b/drivers/net/wireless/ath/ath11k/pcic.c @@ -218,9 +218,16 @@ int ath11k_pcic_read(struct ath11k_base *ab, void *buf, u32 start, u32 end) if (wakeup_required && ab->pci.ops->wakeup) { ret = ab->pci.ops->wakeup(ab); if (ret) { - ath11k_warn(ab, "failed to wakeup for read from 0x%x: %d\n", - start, ret); - return ret; + ath11k_warn(ab, + "wakeup failed, data may be invalid: %d", + ret); + /* Even though wakeup() failed, continue processing rather + * than returning because some parts of the data may still + * be valid and useful in some cases, e.g. could give us + * some clues on firmware crash. + * Mislead due to invalid data could be avoided because we + * are aware of the wakeup failure. + */ } } diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index 51de2208b789..145f20a681bd 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -19,6 +19,7 @@ #define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02 #define HOST_CSTATE_BIT 0x04 #define PLATFORM_CAP_PCIE_GLOBAL_RESET 0x08 +#define PLATFORM_CAP_PCIE_PME_D3COLD 0x10 #define FW_BUILD_ID_MASK "QC_IMAGE_VERSION_STRING=" @@ -1752,6 +1753,8 @@ static int ath11k_qmi_host_cap_send(struct ath11k_base *ab) if (ab->hw_params.global_reset) req.nm_modem |= PLATFORM_CAP_PCIE_GLOBAL_RESET; + req.nm_modem |= PLATFORM_CAP_PCIE_PME_D3COLD; + ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi host cap request\n"); ret = qmi_txn_init(&ab->qmi.handle, &txn, @@ -1961,7 +1964,7 @@ static void ath11k_qmi_free_target_mem_chunk(struct ath11k_base *ab) continue; dma_free_coherent(ab->dev, - ab->qmi.target_mem[i].size, + ab->qmi.target_mem[i].prev_size, ab->qmi.target_mem[i].vaddr, ab->qmi.target_mem[i].paddr); ab->qmi.target_mem[i].vaddr = NULL; @@ -1982,12 +1985,12 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab) * in such case, no need to allocate memory for FW again. */ if (chunk->vaddr) { - if (chunk->prev_type == chunk->type || + if (chunk->prev_type == chunk->type && chunk->prev_size == chunk->size) continue; /* cannot reuse the existing chunk */ - dma_free_coherent(ab->dev, chunk->size, + dma_free_coherent(ab->dev, chunk->prev_size, chunk->vaddr, chunk->paddr); chunk->vaddr = NULL; } @@ -3158,6 +3161,9 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) case ATH11K_QMI_EVENT_SERVER_EXIT: set_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags); set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); + + if (!ab->is_reset) + ath11k_core_pre_reconfigure_recovery(ab); break; case ATH11K_QMI_EVENT_REQUEST_MEM: ret = ath11k_qmi_event_mem_request(qmi); diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index fad9f8d308a2..2a8a3e3dcff6 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -6829,7 +6829,7 @@ static void ath11k_wmi_event_peer_sta_ps_state_chg(struct ath11k_base *ab, } ath11k_dbg(ab, ATH11K_DBG_WMI, - "peer sta ps chnange ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n", + "peer sta ps change ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n", ev->peer_macaddr.addr, ev->peer_ps_state, ev->ps_supported_bitmap, ev->peer_ps_valid, ev->peer_ps_timestamp); diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 9bdfcee2f448..eff94bcd1f0a 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -45,11 +45,6 @@ ath9k_hw-y:= \ ar9003_eeprom.o \ ar9003_paprd.o -# FIXME: temporarily silence -Warray-bounds on non W=1+ builds -ifndef KBUILD_EXTRA_WARN -CFLAGS_mac.o += -Wno-array-bounds -endif - ath9k_hw-$(CONFIG_ATH9K_WOW) += ar9003_wow.o ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 3ccf8cfc6b63..2cc23605c9fc 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -20,6 +20,7 @@ #include <linux/etherdevice.h> #include <linux/device.h> #include <linux/interrupt.h> +#include <linux/kstrtox.h> #include <linux/leds.h> #include <linux/completion.h> #include <linux/time.h> diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 4d9002a9d082..1a2e0c7eeb02 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -708,14 +708,13 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) struct rx_buf *rx_buf = (struct rx_buf *)urb->context; struct hif_device_usb *hif_dev = rx_buf->hif_dev; struct sk_buff *skb = rx_buf->skb; - struct sk_buff *nskb; int ret; if (!skb) return; if (!hif_dev) - goto free; + goto free_skb; switch (urb->status) { case 0: @@ -724,7 +723,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) case -ECONNRESET: case -ENODEV: case -ESHUTDOWN: - goto free; + goto free_skb; default: skb_reset_tail_pointer(skb); skb_trim(skb, 0); @@ -735,25 +734,27 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) if (likely(urb->actual_length != 0)) { skb_put(skb, urb->actual_length); - /* Process the command first */ + /* + * Process the command first. + * skb is either freed here or passed to be + * managed to another callback function. + */ ath9k_htc_rx_msg(hif_dev->htc_handle, skb, skb->len, USB_REG_IN_PIPE); - - nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); - if (!nskb) { + skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); + if (!skb) { dev_err(&hif_dev->udev->dev, "ath9k_htc: REG_IN memory allocation failure\n"); - urb->context = NULL; - return; + goto free_rx_buf; } - rx_buf->skb = nskb; + rx_buf->skb = skb; usb_fill_int_urb(urb, hif_dev->udev, usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), - nskb->data, MAX_REG_IN_BUF_SIZE, + skb->data, MAX_REG_IN_BUF_SIZE, ath9k_hif_usb_reg_in_cb, rx_buf, 1); } @@ -762,12 +763,13 @@ resubmit: ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret) { usb_unanchor_urb(urb); - goto free; + goto free_skb; } return; -free: +free_skb: kfree_skb(skb); +free_rx_buf: kfree(rx_buf); urb->context = NULL; } @@ -780,14 +782,10 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); list_for_each_entry_safe(tx_buf, tx_buf_tmp, &hif_dev->tx.tx_buf, list) { - usb_get_urb(tx_buf->urb); - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); - usb_kill_urb(tx_buf->urb); list_del(&tx_buf->list); usb_free_urb(tx_buf->urb); kfree(tx_buf->buf); kfree(tx_buf); - spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); } spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); @@ -1329,10 +1327,24 @@ static int send_eject_command(struct usb_interface *interface) static int ath9k_hif_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { + struct usb_endpoint_descriptor *bulk_in, *bulk_out, *int_in, *int_out; struct usb_device *udev = interface_to_usbdev(interface); + struct usb_host_interface *alt; struct hif_device_usb *hif_dev; int ret = 0; + /* Verify the expected endpoints are present */ + alt = interface->cur_altsetting; + if (usb_find_common_endpoints(alt, &bulk_in, &bulk_out, &int_in, &int_out) < 0 || + usb_endpoint_num(bulk_in) != USB_WLAN_RX_PIPE || + usb_endpoint_num(bulk_out) != USB_WLAN_TX_PIPE || + usb_endpoint_num(int_in) != USB_REG_IN_PIPE || + usb_endpoint_num(int_out) != USB_REG_OUT_PIPE) { + dev_err(&udev->dev, + "ath9k_htc: Device endpoint numbers are not the expected ones\n"); + return -ENODEV; + } + if (id->driver_info == STORAGE_DEVICE) return send_eject_command(interface); diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 039bf0c35fbe..3363fc4e8966 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c @@ -266,7 +266,9 @@ static void ath_mci_set_concur_txprio(struct ath_softc *sc) stomp_txprio[ATH_BTCOEX_STOMP_NONE] = ATH_MCI_INQUIRY_PRIO; } else { - u8 prof_prio[] = { 50, 90, 94, 52 };/* RFCOMM, A2DP, HID, PAN */ + static const u8 prof_prio[] = { + 50, 90, 94, 52 + }; /* RFCOMM, A2DP, HID, PAN */ stomp_txprio[ATH_BTCOEX_STOMP_LOW] = stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0xff; @@ -644,7 +646,9 @@ void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all) struct ath_hw *ah = sc->sc_ah; struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; struct ath9k_channel *chan = ah->curchan; - u32 channelmap[] = {0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff}; + static const u32 channelmap[] = { + 0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff + }; int i; s16 chan_start, chan_end; u16 wlan_chan; diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index 95544ce05acf..8a996ed9a3be 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c @@ -189,7 +189,7 @@ static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, buf[len] = '\0'; - if (strtobool(buf, &start)) + if (kstrtobool(buf, &start)) return -EINVAL; mutex_lock(&sc->mutex); diff --git a/drivers/net/wireless/ath/carl9170/Makefile b/drivers/net/wireless/ath/carl9170/Makefile index 7463baa62fa8..1a81868ce26d 100644 --- a/drivers/net/wireless/ath/carl9170/Makefile +++ b/drivers/net/wireless/ath/carl9170/Makefile @@ -3,8 +3,3 @@ carl9170-objs := main.o usb.o cmd.o mac.o phy.o led.o fw.o tx.o rx.o carl9170-$(CONFIG_CARL9170_DEBUGFS) += debug.o obj-$(CONFIG_CARL9170) += carl9170.o - -# FIXME: temporarily silence -Warray-bounds on non W=1+ builds -ifndef KBUILD_EXTRA_WARN -CFLAGS_cmd.o += -Wno-array-bounds -endif diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h index 0a4e42e806b9..ded2c6d0a759 100644 --- a/drivers/net/wireless/ath/carl9170/wlan.h +++ b/drivers/net/wireless/ath/carl9170/wlan.h @@ -271,7 +271,7 @@ struct ar9170_tx_frame { union { struct ieee80211_hdr i3e; - u8 payload[0]; + DECLARE_FLEX_ARRAY(u8, payload); } data; } __packed; diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 04d1aa0e2d35..c021ebcddee7 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -2154,7 +2154,7 @@ static const struct file_operations fops_led_blink_time = { }; /*---------FW capabilities------------*/ -static int wil_fw_capabilities_debugfs_show(struct seq_file *s, void *data) +static int fw_capabilities_show(struct seq_file *s, void *data) { struct wil6210_priv *wil = s->private; @@ -2163,22 +2163,10 @@ static int wil_fw_capabilities_debugfs_show(struct seq_file *s, void *data) return 0; } - -static int wil_fw_capabilities_seq_open(struct inode *inode, struct file *file) -{ - return single_open(file, wil_fw_capabilities_debugfs_show, - inode->i_private); -} - -static const struct file_operations fops_fw_capabilities = { - .open = wil_fw_capabilities_seq_open, - .release = single_release, - .read = seq_read, - .llseek = seq_lseek, -}; +DEFINE_SHOW_ATTRIBUTE(fw_capabilities); /*---------FW version------------*/ -static int wil_fw_version_debugfs_show(struct seq_file *s, void *data) +static int fw_version_show(struct seq_file *s, void *data) { struct wil6210_priv *wil = s->private; @@ -2189,19 +2177,7 @@ static int wil_fw_version_debugfs_show(struct seq_file *s, void *data) return 0; } - -static int wil_fw_version_seq_open(struct inode *inode, struct file *file) -{ - return single_open(file, wil_fw_version_debugfs_show, - inode->i_private); -} - -static const struct file_operations fops_fw_version = { - .open = wil_fw_version_seq_open, - .release = single_release, - .read = seq_read, - .llseek = seq_lseek, -}; +DEFINE_SHOW_ATTRIBUTE(fw_version); /*---------suspend_stats---------*/ static ssize_t wil_write_suspend_stats(struct file *file, @@ -2366,8 +2342,8 @@ static const struct { {"recovery", 0644, &fops_recovery}, {"led_cfg", 0644, &fops_led_cfg}, {"led_blink_time", 0644, &fops_led_blink_time}, - {"fw_capabilities", 0444, &fops_fw_capabilities}, - {"fw_version", 0444, &fops_fw_version}, + {"fw_capabilities", 0444, &fw_capabilities_fops}, + {"fw_version", 0444, &fw_version_fops}, {"suspend_stats", 0644, &fops_suspend_stats}, {"compressed_rx_status", 0644, &fops_compressed_rx_status}, {"srings", 0444, &srings_fops}, diff --git a/drivers/net/wireless/atmel/atmel.c b/drivers/net/wireless/atmel/atmel.c index ed430b91e2aa..7c2d1c588156 100644 --- a/drivers/net/wireless/atmel/atmel.c +++ b/drivers/net/wireless/atmel/atmel.c @@ -2570,7 +2570,7 @@ static const iw_handler atmel_handler[] = static const iw_handler atmel_private_handler[] = { - IW_HANDLER(SIOCIWFIRSTPRIV, NULL), + NULL, /* SIOCIWFIRSTPRIV */ }; struct atmel_priv_ioctl { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 3f2336062217..ae9507dec74a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -1683,6 +1683,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason, locally_generated, GFP_KERNEL); } clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state); + clear_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state); + clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state); clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status); brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0); if (vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_NONE) { @@ -2313,6 +2315,12 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, return -EOPNOTSUPP; } + if (sme->channel_hint) + chan = sme->channel_hint; + + if (sme->bssid_hint) + sme->bssid = sme->bssid_hint; + if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) { /* A normal (non P2P) connection request setup. */ ie = NULL; @@ -2535,6 +2543,8 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state); clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state); + clear_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &ifp->vif->sme_state); + clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &ifp->vif->sme_state); cfg80211_disconnected(ndev, reason_code, NULL, 0, true, GFP_KERNEL); memcpy(&scbval.ea, &profile->bssid, ETH_ALEN); @@ -6299,6 +6309,10 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, &ifp->vif->sme_state); conn_params.status = WLAN_STATUS_SUCCESS; } else { + clear_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, + &ifp->vif->sme_state); + clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, + &ifp->vif->sme_state); conn_params.status = WLAN_STATUS_AUTH_TIMEOUT; } conn_params.links[0].bssid = profile->bssid; @@ -6396,9 +6410,13 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, } else if (brcmf_is_linkdown(ifp->vif, e)) { brcmf_dbg(CONN, "Linkdown\n"); if (!brcmf_is_ibssmode(ifp->vif) && - test_bit(BRCMF_VIF_STATUS_CONNECTED, - &ifp->vif->sme_state)) { - if (memcmp(profile->bssid, e->addr, ETH_ALEN)) + (test_bit(BRCMF_VIF_STATUS_CONNECTED, + &ifp->vif->sme_state) || + test_bit(BRCMF_VIF_STATUS_CONNECTING, + &ifp->vif->sme_state))) { + if (test_bit(BRCMF_VIF_STATUS_CONNECTED, + &ifp->vif->sme_state) && + memcmp(profile->bssid, e->addr, ETH_ALEN)) return err; brcmf_bss_connect_done(cfg, ndev, e, false); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 74020fa10065..22344e68fd59 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -305,8 +305,12 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) brcmf_info("Firmware: %s %s\n", ri->chipname, buf); /* locate firmware version number for ethtool */ - ptr = strrchr(buf, ' ') + 1; - strscpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); + ptr = strrchr(buf, ' '); + if (!ptr) { + bphy_err(drvr, "Retrieving version number failed"); + goto done; + } + strscpy(ifp->drvr->fwver, ptr + 1, sizeof(ifp->drvr->fwver)); /* Query for 'clmver' to get CLM version info from firmware */ memset(buf, 0, sizeof(buf)); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index f2207793f6e2..09d2f2dc2b46 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -803,6 +803,11 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev, u32 i, j; char end = '\0'; + if (chiprev >= BITS_PER_TYPE(u32)) { + brcmf_err("Invalid chip revision %u\n", chiprev); + return NULL; + } + for (i = 0; i < table_size; i++) { if (mapping_table[i].chipid == chip && mapping_table[i].revmask & BIT(chiprev)) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index 10d9d9c63b28..af8843507f3d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -2424,8 +2424,12 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) brcmf_remove_interface(vif->ifp, true); brcmf_cfg80211_arm_vif_event(cfg, NULL); - if (iftype != NL80211_IFTYPE_P2P_DEVICE) - p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL; + if (iftype != NL80211_IFTYPE_P2P_DEVICE) { + if (vif == p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif) + p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL; + if (vif == p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION2].vif) + p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION2].vif = NULL; + } return err; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index deb0199fcf8c..244ba48cc304 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -1884,7 +1884,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) } rd->len_left = rd->len; - /* read header first for unknow frame length */ + /* read header first for unknown frame length */ sdio_claim_host(bus->sdiodev->func1); if (!rd->len) { ret = brcmf_sdiod_recv_buf(bus->sdiodev, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.c index c1b9ac692d26..9540a05247c2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.c @@ -63,9 +63,6 @@ int brcms_led_register(struct brcms_info *wl) int hwnum = -1; enum gpio_lookup_flags lflags = GPIO_ACTIVE_HIGH; - if (!bcma_gpio || !gpio_is_valid(bcma_gpio->base)) - return -ENODEV; - /* find radio enabled LED */ for (i = 0; i < BRCMS_LED_NO; i++) { u8 led = *leds[i]; diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c index fb2c35bd73bb..7c4cc5f5e1eb 100644 --- a/drivers/net/wireless/cisco/airo.c +++ b/drivers/net/wireless/cisco/airo.c @@ -4807,7 +4807,8 @@ static int get_dec_u16(char *buffer, int *start, int limit) } static int airo_config_commit(struct net_device *dev, - struct iw_request_info *info, void *zwrq, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); static inline int sniffing_mode(struct airo_info *ai) @@ -5814,10 +5815,10 @@ static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid) */ static int airo_get_name(struct net_device *dev, struct iw_request_info *info, - char *cwrq, + union iwreq_data *cwrq, char *extra) { - strcpy(cwrq, "IEEE 802.11-DS"); + strcpy(cwrq->name, "IEEE 802.11-DS"); return 0; } @@ -5827,9 +5828,10 @@ static int airo_get_name(struct net_device *dev, */ static int airo_set_freq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *fwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_freq *fwrq = &wrqu->freq; struct airo_info *local = dev->ml_priv; int rc = -EINPROGRESS; /* Call commit handler */ @@ -5868,9 +5870,10 @@ static int airo_set_freq(struct net_device *dev, */ static int airo_get_freq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *fwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_freq *fwrq = &wrqu->freq; struct airo_info *local = dev->ml_priv; StatusRid status_rid; /* Card status info */ int ch; @@ -5900,9 +5903,10 @@ static int airo_get_freq(struct net_device *dev, */ static int airo_set_essid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_point *dwrq = &wrqu->essid; struct airo_info *local = dev->ml_priv; SsidRid SSID_rid; /* SSIDs */ @@ -5945,9 +5949,10 @@ static int airo_set_essid(struct net_device *dev, */ static int airo_get_essid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_point *dwrq = &wrqu->essid; struct airo_info *local = dev->ml_priv; StatusRid status_rid; /* Card status info */ @@ -5973,9 +5978,10 @@ static int airo_get_essid(struct net_device *dev, */ static int airo_set_wap(struct net_device *dev, struct iw_request_info *info, - struct sockaddr *awrq, + union iwreq_data *wrqu, char *extra) { + struct sockaddr *awrq = &wrqu->ap_addr; struct airo_info *local = dev->ml_priv; Cmd cmd; Resp rsp; @@ -6008,9 +6014,10 @@ static int airo_set_wap(struct net_device *dev, */ static int airo_get_wap(struct net_device *dev, struct iw_request_info *info, - struct sockaddr *awrq, + union iwreq_data *wrqu, char *extra) { + struct sockaddr *awrq = &wrqu->ap_addr; struct airo_info *local = dev->ml_priv; StatusRid status_rid; /* Card status info */ @@ -6029,9 +6036,10 @@ static int airo_get_wap(struct net_device *dev, */ static int airo_set_nick(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_point *dwrq = &wrqu->data; struct airo_info *local = dev->ml_priv; /* Check the size of the string */ @@ -6052,9 +6060,10 @@ static int airo_set_nick(struct net_device *dev, */ static int airo_get_nick(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_point *dwrq = &wrqu->data; struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); @@ -6071,9 +6080,10 @@ static int airo_get_nick(struct net_device *dev, */ static int airo_set_rate(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->bitrate; struct airo_info *local = dev->ml_priv; CapabilityRid cap_rid; /* Card capability info */ u8 brate = 0; @@ -6141,9 +6151,10 @@ static int airo_set_rate(struct net_device *dev, */ static int airo_get_rate(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->bitrate; struct airo_info *local = dev->ml_priv; StatusRid status_rid; /* Card status info */ @@ -6163,9 +6174,10 @@ static int airo_get_rate(struct net_device *dev, */ static int airo_set_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->rts; struct airo_info *local = dev->ml_priv; int rthr = vwrq->value; @@ -6187,9 +6199,10 @@ static int airo_set_rts(struct net_device *dev, */ static int airo_get_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->rts; struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); @@ -6206,9 +6219,9 @@ static int airo_get_rts(struct net_device *dev, */ static int airo_set_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->frag; struct airo_info *local = dev->ml_priv; int fthr = vwrq->value; @@ -6231,9 +6244,10 @@ static int airo_set_frag(struct net_device *dev, */ static int airo_get_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->frag; struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); @@ -6250,9 +6264,10 @@ static int airo_get_frag(struct net_device *dev, */ static int airo_set_mode(struct net_device *dev, struct iw_request_info *info, - __u32 *uwrq, + union iwreq_data *uwrq, char *extra) { + __u32 mode = uwrq->mode; struct airo_info *local = dev->ml_priv; int reset = 0; @@ -6260,7 +6275,7 @@ static int airo_set_mode(struct net_device *dev, if (sniffing_mode(local)) reset = 1; - switch(*uwrq) { + switch (mode) { case IW_MODE_ADHOC: local->config.opmode &= ~MODE_CFG_MASK; local->config.opmode |= MODE_STA_IBSS; @@ -6313,7 +6328,7 @@ static int airo_set_mode(struct net_device *dev, */ static int airo_get_mode(struct net_device *dev, struct iw_request_info *info, - __u32 *uwrq, + union iwreq_data *uwrq, char *extra) { struct airo_info *local = dev->ml_priv; @@ -6322,16 +6337,16 @@ static int airo_get_mode(struct net_device *dev, /* If not managed, assume it's ad-hoc */ switch (local->config.opmode & MODE_CFG_MASK) { case MODE_STA_ESS: - *uwrq = IW_MODE_INFRA; + uwrq->mode = IW_MODE_INFRA; break; case MODE_AP: - *uwrq = IW_MODE_MASTER; + uwrq->mode = IW_MODE_MASTER; break; case MODE_AP_RPTR: - *uwrq = IW_MODE_REPEAT; + uwrq->mode = IW_MODE_REPEAT; break; default: - *uwrq = IW_MODE_ADHOC; + uwrq->mode = IW_MODE_ADHOC; } return 0; @@ -6348,9 +6363,10 @@ static inline int valid_index(struct airo_info *ai, int index) */ static int airo_set_encode(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_point *dwrq = &wrqu->encoding; struct airo_info *local = dev->ml_priv; int perm = (dwrq->flags & IW_ENCODE_TEMP ? 0 : 1); __le16 currentAuthType = local->config.authType; @@ -6447,9 +6463,10 @@ static int airo_set_encode(struct net_device *dev, */ static int airo_get_encode(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_point *dwrq = &wrqu->encoding; struct airo_info *local = dev->ml_priv; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; int wep_key_len; @@ -6794,9 +6811,10 @@ static int airo_get_auth(struct net_device *dev, */ static int airo_set_txpow(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->txpower; struct airo_info *local = dev->ml_priv; CapabilityRid cap_rid; /* Card capability info */ int i; @@ -6831,9 +6849,10 @@ static int airo_set_txpow(struct net_device *dev, */ static int airo_get_txpow(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->txpower; struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); @@ -6851,9 +6870,10 @@ static int airo_get_txpow(struct net_device *dev, */ static int airo_set_retry(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->retry; struct airo_info *local = dev->ml_priv; int rc = -EINVAL; @@ -6889,9 +6909,10 @@ static int airo_set_retry(struct net_device *dev, */ static int airo_get_retry(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->retry; struct airo_info *local = dev->ml_priv; vwrq->disabled = 0; /* Can't be disabled */ @@ -6920,9 +6941,10 @@ static int airo_get_retry(struct net_device *dev, */ static int airo_get_range(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_point *dwrq = &wrqu->data; struct airo_info *local = dev->ml_priv; struct iw_range *range = (struct iw_range *) extra; CapabilityRid cap_rid; /* Card capability info */ @@ -7046,9 +7068,9 @@ static int airo_get_range(struct net_device *dev, */ static int airo_set_power(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->power; struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); @@ -7104,9 +7126,10 @@ static int airo_set_power(struct net_device *dev, */ static int airo_get_power(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->power; struct airo_info *local = dev->ml_priv; __le16 mode; @@ -7135,9 +7158,10 @@ static int airo_get_power(struct net_device *dev, */ static int airo_set_sens(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->sens; struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); @@ -7154,9 +7178,10 @@ static int airo_set_sens(struct net_device *dev, */ static int airo_get_sens(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->sens; struct airo_info *local = dev->ml_priv; readConfigRid(local, 1); @@ -7174,9 +7199,10 @@ static int airo_get_sens(struct net_device *dev, */ static int airo_get_aplist(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_point *dwrq = &wrqu->data; struct airo_info *local = dev->ml_priv; struct sockaddr *address = (struct sockaddr *) extra; struct iw_quality *qual; @@ -7252,7 +7278,7 @@ static int airo_get_aplist(struct net_device *dev, */ static int airo_set_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, + union iwreq_data *wrqu, char *extra) { struct airo_info *ai = dev->ml_priv; @@ -7483,9 +7509,10 @@ static inline char *airo_translate_scan(struct net_device *dev, */ static int airo_get_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, + union iwreq_data *wrqu, char *extra) { + struct iw_point *dwrq = &wrqu->data; struct airo_info *ai = dev->ml_priv; BSSListElement *net; int err = 0; @@ -7527,7 +7554,7 @@ out: */ static int airo_config_commit(struct net_device *dev, struct iw_request_info *info, /* NULL */ - void *zwrq, /* NULL */ + union iwreq_data *wrqu, /* NULL */ char *extra) /* NULL */ { struct airo_info *local = dev->ml_priv; @@ -7577,61 +7604,46 @@ static const struct iw_priv_args airo_private_args[] = { static const iw_handler airo_handler[] = { - (iw_handler) airo_config_commit, /* SIOCSIWCOMMIT */ - (iw_handler) airo_get_name, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) airo_set_freq, /* SIOCSIWFREQ */ - (iw_handler) airo_get_freq, /* SIOCGIWFREQ */ - (iw_handler) airo_set_mode, /* SIOCSIWMODE */ - (iw_handler) airo_get_mode, /* SIOCGIWMODE */ - (iw_handler) airo_set_sens, /* SIOCSIWSENS */ - (iw_handler) airo_get_sens, /* SIOCGIWSENS */ - (iw_handler) NULL, /* SIOCSIWRANGE */ - (iw_handler) airo_get_range, /* SIOCGIWRANGE */ - (iw_handler) NULL, /* SIOCSIWPRIV */ - (iw_handler) NULL, /* SIOCGIWPRIV */ - (iw_handler) NULL, /* SIOCSIWSTATS */ - (iw_handler) NULL, /* SIOCGIWSTATS */ - iw_handler_set_spy, /* SIOCSIWSPY */ - iw_handler_get_spy, /* SIOCGIWSPY */ - iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ - iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ - (iw_handler) airo_set_wap, /* SIOCSIWAP */ - (iw_handler) airo_get_wap, /* SIOCGIWAP */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) airo_get_aplist, /* SIOCGIWAPLIST */ - (iw_handler) airo_set_scan, /* SIOCSIWSCAN */ - (iw_handler) airo_get_scan, /* SIOCGIWSCAN */ - (iw_handler) airo_set_essid, /* SIOCSIWESSID */ - (iw_handler) airo_get_essid, /* SIOCGIWESSID */ - (iw_handler) airo_set_nick, /* SIOCSIWNICKN */ - (iw_handler) airo_get_nick, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) airo_set_rate, /* SIOCSIWRATE */ - (iw_handler) airo_get_rate, /* SIOCGIWRATE */ - (iw_handler) airo_set_rts, /* SIOCSIWRTS */ - (iw_handler) airo_get_rts, /* SIOCGIWRTS */ - (iw_handler) airo_set_frag, /* SIOCSIWFRAG */ - (iw_handler) airo_get_frag, /* SIOCGIWFRAG */ - (iw_handler) airo_set_txpow, /* SIOCSIWTXPOW */ - (iw_handler) airo_get_txpow, /* SIOCGIWTXPOW */ - (iw_handler) airo_set_retry, /* SIOCSIWRETRY */ - (iw_handler) airo_get_retry, /* SIOCGIWRETRY */ - (iw_handler) airo_set_encode, /* SIOCSIWENCODE */ - (iw_handler) airo_get_encode, /* SIOCGIWENCODE */ - (iw_handler) airo_set_power, /* SIOCSIWPOWER */ - (iw_handler) airo_get_power, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCSIWGENIE */ - (iw_handler) NULL, /* SIOCGIWGENIE */ - (iw_handler) airo_set_auth, /* SIOCSIWAUTH */ - (iw_handler) airo_get_auth, /* SIOCGIWAUTH */ - (iw_handler) airo_set_encodeext, /* SIOCSIWENCODEEXT */ - (iw_handler) airo_get_encodeext, /* SIOCGIWENCODEEXT */ - (iw_handler) NULL, /* SIOCSIWPMKSA */ + IW_HANDLER(SIOCSIWCOMMIT, airo_config_commit), + IW_HANDLER(SIOCGIWNAME, airo_get_name), + IW_HANDLER(SIOCSIWFREQ, airo_set_freq), + IW_HANDLER(SIOCGIWFREQ, airo_get_freq), + IW_HANDLER(SIOCSIWMODE, airo_set_mode), + IW_HANDLER(SIOCGIWMODE, airo_get_mode), + IW_HANDLER(SIOCSIWSENS, airo_set_sens), + IW_HANDLER(SIOCGIWSENS, airo_get_sens), + IW_HANDLER(SIOCGIWRANGE, airo_get_range), + IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), + IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), + IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), + IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), + IW_HANDLER(SIOCSIWAP, airo_set_wap), + IW_HANDLER(SIOCGIWAP, airo_get_wap), + IW_HANDLER(SIOCGIWAPLIST, airo_get_aplist), + IW_HANDLER(SIOCSIWSCAN, airo_set_scan), + IW_HANDLER(SIOCGIWSCAN, airo_get_scan), + IW_HANDLER(SIOCSIWESSID, airo_set_essid), + IW_HANDLER(SIOCGIWESSID, airo_get_essid), + IW_HANDLER(SIOCSIWNICKN, airo_set_nick), + IW_HANDLER(SIOCGIWNICKN, airo_get_nick), + IW_HANDLER(SIOCSIWRATE, airo_set_rate), + IW_HANDLER(SIOCGIWRATE, airo_get_rate), + IW_HANDLER(SIOCSIWRTS, airo_set_rts), + IW_HANDLER(SIOCGIWRTS, airo_get_rts), + IW_HANDLER(SIOCSIWFRAG, airo_set_frag), + IW_HANDLER(SIOCGIWFRAG, airo_get_frag), + IW_HANDLER(SIOCSIWTXPOW, airo_set_txpow), + IW_HANDLER(SIOCGIWTXPOW, airo_get_txpow), + IW_HANDLER(SIOCSIWRETRY, airo_set_retry), + IW_HANDLER(SIOCGIWRETRY, airo_get_retry), + IW_HANDLER(SIOCSIWENCODE, airo_set_encode), + IW_HANDLER(SIOCGIWENCODE, airo_get_encode), + IW_HANDLER(SIOCSIWPOWER, airo_set_power), + IW_HANDLER(SIOCGIWPOWER, airo_get_power), + IW_HANDLER(SIOCSIWAUTH, airo_set_auth), + IW_HANDLER(SIOCGIWAUTH, airo_get_auth), + IW_HANDLER(SIOCSIWENCODEEXT, airo_set_encodeext), + IW_HANDLER(SIOCGIWENCODEEXT, airo_get_encodeext), }; /* Note : don't describe AIROIDIFC and AIROOLDIDIFC in here. diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c index 5b483de18c81..ca802af8cddc 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c @@ -2995,20 +2995,6 @@ static void ipw_remove_current_network(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->ieee->lock, flags); } -/* - * Check that card is still alive. - * Reads debug register from domain0. - * If card is present, pre-defined value should - * be found there. - * - * @param priv - * @return 1 if card is present, 0 otherwise - */ -static inline int ipw_alive(struct ipw_priv *priv) -{ - return ipw_read32(priv, 0x90) == 0xd55555d5; -} - /* timeout in msec, attempted in 10-msec quanta */ static int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask, int timeout) @@ -9870,7 +9856,7 @@ static int ipw_wx_sw_reset(struct net_device *dev, /* Rebase the WE IOCTLs to zero for the handler array */ static iw_handler ipw_wx_handlers[] = { - IW_HANDLER(SIOCGIWNAME, (iw_handler)cfg80211_wext_giwname), + IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname), IW_HANDLER(SIOCSIWFREQ, ipw_wx_set_freq), IW_HANDLER(SIOCGIWFREQ, ipw_wx_get_freq), IW_HANDLER(SIOCSIWMODE, ipw_wx_set_mode), diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/wireless/intel/iwlegacy/3945-mac.c index c4503308f3b0..d7e99d50b287 100644 --- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c @@ -1202,8 +1202,6 @@ il3945_rx_handle(struct il_priv *il) D_RX("r = %d, i = %d\n", r, i); while (i != r) { - int len; - rxb = rxq->queue[i]; /* If an RXB doesn't have a Rx queue slot associated with it, @@ -1217,10 +1215,6 @@ il3945_rx_handle(struct il_priv *il) PAGE_SIZE << il->hw_params.rx_page_order, DMA_FROM_DEVICE); pkt = rxb_addr(rxb); - - len = le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK; - len += sizeof(u32); /* account for status word */ - reclaim = il_need_reclaim(il, pkt); /* Based on type of command response or notification, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 110fda65bd21..ec6198f1b38c 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -172,6 +172,13 @@ static const struct iwl_ht_params iwl_22000_ht_params = { BIT(NL80211_BAND_6GHZ), }; +static const struct iwl_ht_params iwl_gl_a_ht_params = { + .stbc = false, /* we explicitly disable STBC for GL step A */ + .ldpc = true, + .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) | + BIT(NL80211_BAND_6GHZ), +}; + #define IWL_DEVICE_22000_COMMON \ .ucode_api_max = IWL_22000_UCODE_API_MAX, \ .ucode_api_min = IWL_22000_UCODE_API_MIN, \ @@ -249,7 +256,7 @@ static const struct iwl_ht_params iwl_22000_ht_params = { }, \ } -#define IWL_DEVICE_BZ \ +#define IWL_DEVICE_BZ_COMMON \ .ucode_api_max = IWL_22000_UCODE_API_MAX, \ .ucode_api_min = IWL_22000_UCODE_API_MIN, \ .led_mode = IWL_LED_RF_STATE, \ @@ -261,12 +268,10 @@ static const struct iwl_ht_params iwl_22000_ht_params = { .dccm2_len = IWL_22000_DCCM2_LEN, \ .smem_offset = IWL_22000_SMEM_OFFSET, \ .smem_len = IWL_22000_SMEM_LEN, \ - .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, \ .apmg_not_supported = true, \ .trans.mq_rx_supported = true, \ .vht_mu_mimo_supported = true, \ .mac_addr_from_csr = 0x30, \ - .ht_params = &iwl_22000_ht_params, \ .nvm_ver = IWL_22000_NVM_VERSION, \ .trans.use_tfh = true, \ .trans.rf_id = true, \ @@ -313,6 +318,14 @@ static const struct iwl_ht_params iwl_22000_ht_params = { }, \ } +#define IWL_DEVICE_BZ \ + IWL_DEVICE_BZ_COMMON, \ + .ht_params = &iwl_22000_ht_params + +#define IWL_DEVICE_GL_A \ + IWL_DEVICE_BZ_COMMON, \ + .ht_params = &iwl_gl_a_ht_params + const struct iwl_cfg_trans_params iwl_qnj_trans_cfg = { .mq_rx_supported = true, .use_tfh = true, @@ -901,6 +914,7 @@ const struct iwl_cfg iwl_cfg_bz_a0_hr_b0 = { .fw_name_pre = IWL_BZ_A_HR_B_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; @@ -908,6 +922,7 @@ const struct iwl_cfg iwl_cfg_bz_a0_gf_a0 = { .fw_name_pre = IWL_BZ_A_GF_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; @@ -915,6 +930,7 @@ const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0 = { .fw_name_pre = IWL_BZ_A_GF4_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; @@ -922,6 +938,7 @@ const struct iwl_cfg iwl_cfg_bz_a0_mr_a0 = { .fw_name_pre = IWL_BZ_A_MR_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; @@ -929,6 +946,7 @@ const struct iwl_cfg iwl_cfg_bz_a0_fm_a0 = { .fw_name_pre = IWL_BZ_A_FM_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; @@ -936,13 +954,15 @@ const struct iwl_cfg iwl_cfg_bz_a0_fm4_a0 = { .fw_name_pre = IWL_BZ_A_FM4_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; const struct iwl_cfg iwl_cfg_gl_a0_fm_a0 = { .fw_name_pre = IWL_GL_A_FM_A_FW_PRE, .uhb_supported = true, - IWL_DEVICE_BZ, + IWL_DEVICE_GL_A, + .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; @@ -950,6 +970,7 @@ const struct iwl_cfg iwl_cfg_gl_b0_fm_b0 = { .fw_name_pre = IWL_GL_B_FM_B_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; @@ -957,6 +978,7 @@ const struct iwl_cfg iwl_cfg_bz_z0_gf_a0 = { .fw_name_pre = IWL_BZ_Z_GF_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; @@ -964,6 +986,7 @@ const struct iwl_cfg iwl_cfg_bnj_a0_fm_a0 = { .fw_name_pre = IWL_BNJ_A_FM_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; @@ -971,6 +994,7 @@ const struct iwl_cfg iwl_cfg_bnj_a0_fm4_a0 = { .fw_name_pre = IWL_BNJ_A_FM4_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; @@ -978,6 +1002,7 @@ const struct iwl_cfg iwl_cfg_bnj_a0_gf_a0 = { .fw_name_pre = IWL_BNJ_A_GF_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; @@ -985,6 +1010,7 @@ const struct iwl_cfg iwl_cfg_bnj_a0_gf4_a0 = { .fw_name_pre = IWL_BNJ_A_GF4_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; @@ -992,6 +1018,7 @@ const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0 = { .fw_name_pre = IWL_BNJ_A_HR_B_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; @@ -999,6 +1026,7 @@ const struct iwl_cfg iwl_cfg_bnj_b0_fm_b0 = { .fw_name_pre = IWL_BNJ_B_FM_B_FW_PRE, .uhb_supported = true, IWL_DEVICE_BZ, + .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h index 43619acc29fd..d07982d8c897 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h @@ -72,6 +72,11 @@ enum iwl_data_path_subcmd_ids { SCD_QUEUE_CONFIG_CMD = 0x17, /** + * @SEC_KEY_CMD: security key command, uses &struct iwl_sec_key_cmd + */ + SEC_KEY_CMD = 0x18, + + /** * @MONITOR_NOTIF: Datapath monitoring notification, using * &struct iwl_datapath_monitor_notif */ @@ -403,4 +408,78 @@ struct iwl_scd_queue_cfg_cmd { } __packed u; /* TX_QUEUE_CFG_CMD_OPERATION_API_U_VER_1 */ } __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_3 */ +/** + * enum iwl_sec_key_flags - security key command key flags + * @IWL_SEC_KEY_FLAG_CIPHER_MASK: cipher mask + * @IWL_SEC_KEY_FLAG_CIPHER_WEP: WEP cipher + * @IWL_SEC_KEY_FLAG_CIPHER_CCMP: CCMP/CMAC cipher + * @IWL_SEC_KEY_FLAG_CIPHER_TKIP: TKIP cipher + * @IWL_SEC_KEY_FLAG_CIPHER_GCMP: GCMP/GMAC cipher + * @IWL_SEC_KEY_FLAG_NO_TX: don't install for TX + * @IWL_SEC_KEY_FLAG_KEY_SIZE: large key size (WEP-104, GCMP-256, GMAC-256) + * @IWL_SEC_KEY_FLAG_MFP: MFP is in used for this key + * @IWL_SEC_KEY_FLAG_MCAST_KEY: this is a multicast key + * @IWL_SEC_KEY_FLAG_SPP_AMSDU: SPP A-MSDU should be used + */ +enum iwl_sec_key_flags { + IWL_SEC_KEY_FLAG_CIPHER_MASK = 0x07, + IWL_SEC_KEY_FLAG_CIPHER_WEP = 0x01, + IWL_SEC_KEY_FLAG_CIPHER_CCMP = 0x02, + IWL_SEC_KEY_FLAG_CIPHER_TKIP = 0x03, + IWL_SEC_KEY_FLAG_CIPHER_GCMP = 0x05, + IWL_SEC_KEY_FLAG_NO_TX = 0x08, + IWL_SEC_KEY_FLAG_KEY_SIZE = 0x10, + IWL_SEC_KEY_FLAG_MFP = 0x20, + IWL_SEC_KEY_FLAG_MCAST_KEY = 0x40, + IWL_SEC_KEY_FLAG_SPP_AMSDU = 0x80, +}; + +#define IWL_SEC_WEP_KEY_OFFSET 3 + +/** + * struct iwl_sec_key_cmd - security key command + * @action: action from &enum iwl_ctxt_action + * @u.add.sta_mask: station mask for the new key + * @u.add.key_id: key ID (0-7) for the new key + * @u.add.key_flags: key flags per &enum iwl_sec_key_flags + * @u.add.key: key material. WEP keys should start from &IWL_SEC_WEP_KEY_OFFSET. + * @u.add.tkip_mic_rx_key: TKIP MIC RX key + * @u.add.tkip_mic_tx_key: TKIP MIC TX key + * @u.add.rx_seq: RX sequence counter value + * @u.add.tx_seq: TX sequence counter value + * @u.modify.old_sta_mask: old station mask + * @u.modify.new_sta_mask: new station mask + * @u.modify.key_id: key ID + * @u.modify.key_flags: new key flags + * @u.remove.sta_mask: station mask + * @u.remove.key_id: key ID + * @u.remove.key_flags: key flags + */ +struct iwl_sec_key_cmd { + __le32 action; + union { + struct { + __le32 sta_mask; + __le32 key_id; + __le32 key_flags; + u8 key[32]; + u8 tkip_mic_rx_key[8]; + u8 tkip_mic_tx_key[8]; + __le64 rx_seq; + __le64 tx_seq; + } __packed add; /* SEC_KEY_ADD_CMD_API_S_VER_1 */ + struct { + __le32 old_sta_mask; + __le32 new_sta_mask; + __le32 key_id; + __le32 key_flags; + } __packed modify; /* SEC_KEY_MODIFY_CMD_API_S_VER_1 */ + struct { + __le32 sta_mask; + __le32 key_id; + __le32 key_flags; + } __packed remove; /* SEC_KEY_REMOVE_CMD_API_S_VER_1 */ + } __packed u; /* SEC_KEY_OPERATION_API_U_VER_1 */ +} __packed; /* SEC_KEY_CMD_API_S_VER_1 */ + #endif /* __iwl_fw_api_datapath_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 3237d4b528b5..6d6c12999645 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -590,6 +590,9 @@ static int iwl_dbg_tlv_alloc_fragments(struct iwl_fw_runtime *fwrt, if (alloc_id != IWL_FW_INI_ALLOCATION_ID_DBGC1) return -EIO; num_frags = 1; + } else if (fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ && + alloc_id > IWL_FW_INI_ALLOCATION_ID_DBGC3) { + return -EIO; } remain_pages = DIV_ROUND_UP(le32_to_cpu(fw_mon_cfg->req_size), @@ -789,7 +792,7 @@ static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt) dram_info->second_word = cpu_to_le32(DRAM_INFO_SECOND_MAGIC_WORD); for (i = IWL_FW_INI_ALLOCATION_ID_DBGC1; - i <= IWL_FW_INI_ALLOCATION_ID_DBGC3; i++) { + i < IWL_FW_INI_ALLOCATION_NUM; i++) { ret = iwl_dbg_tlv_update_dram(fwrt, i, dram_info); if (!ret) dram_alloc = true; @@ -1324,7 +1327,7 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt) "WRT: removing allocation id %d from region id %d\n", le32_to_cpu(reg->dram_alloc_id), i); - failed_alloc &= ~le32_to_cpu(reg->dram_alloc_id); + failed_alloc &= ~BIT(le32_to_cpu(reg->dram_alloc_id)); fwrt->trans->dbg.unsupported_region_msk |= BIT(i); kfree(*active_reg); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index 157d1f31c487..82cf904e0b6d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -377,6 +377,7 @@ enum { #define PREG_PRPH_WPROT_22000 0xA04D00 #define SB_MODIFY_CFG_FLAG 0xA03088 +#define SB_CFG_RESIDES_IN_OTP_MASK 0x10 #define SB_CPU_1_STATUS 0xA01E30 #define SB_CPU_2_STATUS 0xA01E34 #define UMAG_SB_CPU_1_STATUS 0xA038C0 @@ -500,4 +501,7 @@ enum { #define REG_OTP_MINOR 0xA0333C +#define WFPM_LMAC2_PD_NOTIFICATION 0xA033CC +#define WFPM_LMAC2_PD_RE_READ BIT(31) + #endif /* __iwl_prph_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h b/drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h index 67122cfa2292..2b639eef595d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h +++ b/drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h @@ -220,6 +220,7 @@ struct iwl_mei_nvm { /** * enum iwl_mei_pairwise_cipher - cipher for UCAST key * @IWL_MEI_CIPHER_NONE: none + * @IWL_MEI_CIPHER_TKIP: tkip * @IWL_MEI_CIPHER_CCMP: ccmp * @IWL_MEI_CIPHER_GCMP: gcmp * @IWL_MEI_CIPHER_GCMP_256: gcmp 256 @@ -228,6 +229,7 @@ struct iwl_mei_nvm { */ enum iwl_mei_pairwise_cipher { IWL_MEI_CIPHER_NONE = 0, + IWL_MEI_CIPHER_TKIP = 2, IWL_MEI_CIPHER_CCMP = 4, IWL_MEI_CIPHER_GCMP = 8, IWL_MEI_CIPHER_GCMP_256 = 9, @@ -446,9 +448,25 @@ void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_info, void iwl_mei_host_disassociated(void); /** - * iwl_mei_device_down() - must be called when the device is down + * iwl_mei_device_state() - must be called when the device changes up/down state + * @up: true if the device is up, false otherwise. */ -void iwl_mei_device_down(void); +void iwl_mei_device_state(bool up); + +/** + * iwl_mei_pldr_req() - must be called before loading the fw + * + * Return: 0 if the PLDR flow was successful and the fw can be loaded, negative + * value otherwise. + */ +int iwl_mei_pldr_req(void); + +/** + * iwl_mei_alive_notif() - must be called when alive notificaiton is received + * @success: true if received alive notification, false if waiting for the + * notificaiton timed out. + */ +void iwl_mei_alive_notif(bool success); #else @@ -497,7 +515,13 @@ static inline void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_ static inline void iwl_mei_host_disassociated(void) {} -static inline void iwl_mei_device_down(void) +static inline void iwl_mei_device_state(bool up) +{} + +static inline int iwl_mei_pldr_req(void) +{ return 0; } + +static inline void iwl_mei_alive_notif(bool success) {} #endif /* CONFIG_IWLMEI */ diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c index 357f14626cf4..b89989b6399a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/main.c +++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c @@ -147,9 +147,15 @@ struct iwl_mei_filters { * to send CSME_OWNERSHIP_CONFIRMED when the driver completes its down * flow. * @link_prot_state: true when we are in link protection PASSIVE + * @device_down: true if the device is down. Used to remember to send + * CSME_OWNERSHIP_CONFIRMED when the driver is already down. * @csa_throttle_end_wk: used when &csa_throttled is true + * @pldr_wq: the wait queue for PLDR flow + * @pldr_active: PLDR flow is in progress * @data_q_lock: protects the access to the data queues which are * accessed without the mutex. + * @netdev_work: used to defer registering and unregistering of the netdev to + * avoid taking the rtnl lock in the SAP messages handlers. * @sap_seq_no: the sequence number for the SAP messages * @seq_no: the sequence number for the SAP messages * @dbgfs_dir: the debugfs dir entry @@ -167,8 +173,12 @@ struct iwl_mei { bool csa_throttled; bool csme_taking_ownership; bool link_prot_state; + bool device_down; struct delayed_work csa_throttle_end_wk; + wait_queue_head_t pldr_wq; + bool pldr_active; spinlock_t data_q_lock; + struct work_struct netdev_work; atomic_t sap_seq_no; atomic_t seq_no; @@ -588,13 +598,38 @@ static rx_handler_result_t iwl_mei_rx_handler(struct sk_buff **pskb) return res; } +static void iwl_mei_netdev_work(struct work_struct *wk) +{ + struct iwl_mei *mei = + container_of(wk, struct iwl_mei, netdev_work); + struct net_device *netdev; + + /* + * First take rtnl and only then the mutex to avoid an ABBA + * with iwl_mei_set_netdev() + */ + rtnl_lock(); + mutex_lock(&iwl_mei_mutex); + + netdev = rcu_dereference_protected(iwl_mei_cache.netdev, + lockdep_is_held(&iwl_mei_mutex)); + if (netdev) { + if (mei->amt_enabled) + netdev_rx_handler_register(netdev, iwl_mei_rx_handler, + mei); + else + netdev_rx_handler_unregister(netdev); + } + + mutex_unlock(&iwl_mei_mutex); + rtnl_unlock(); +} + static void iwl_mei_handle_rx_start_ok(struct mei_cl_device *cldev, const struct iwl_sap_me_msg_start_ok *rsp, ssize_t len) { - struct iwl_mei *mei = mei_cldev_get_drvdata(cldev); - if (len != sizeof(*rsp)) { dev_err(&cldev->dev, "got invalid SAP_ME_MSG_START_OK from CSME firmware\n"); @@ -613,13 +648,10 @@ iwl_mei_handle_rx_start_ok(struct mei_cl_device *cldev, mutex_lock(&iwl_mei_mutex); set_bit(IWL_MEI_STATUS_SAP_CONNECTED, &iwl_mei_status); - /* wifi driver has registered already */ - if (iwl_mei_cache.ops) { - iwl_mei_send_sap_msg(mei->cldev, - SAP_MSG_NOTIF_WIFIDR_UP); - iwl_mei_cache.ops->sap_connected(iwl_mei_cache.priv); - } - + /* + * We'll receive AMT_STATE SAP message in a bit and + * that will continue the flow + */ mutex_unlock(&iwl_mei_mutex); } @@ -712,6 +744,13 @@ static void iwl_mei_set_init_conf(struct iwl_mei *mei) .val = cpu_to_le32(iwl_mei_cache.rf_kill), }; + /* wifi driver has registered already */ + if (iwl_mei_cache.ops) { + iwl_mei_send_sap_msg(mei->cldev, + SAP_MSG_NOTIF_WIFIDR_UP); + iwl_mei_cache.ops->sap_connected(iwl_mei_cache.priv); + } + iwl_mei_send_sap_msg(mei->cldev, SAP_MSG_NOTIF_WHO_OWNS_NIC); if (iwl_mei_cache.conn_info) { @@ -738,38 +777,23 @@ static void iwl_mei_handle_amt_state(struct mei_cl_device *cldev, const struct iwl_sap_msg_dw *dw) { struct iwl_mei *mei = mei_cldev_get_drvdata(cldev); - struct net_device *netdev; - /* - * First take rtnl and only then the mutex to avoid an ABBA - * with iwl_mei_set_netdev() - */ - rtnl_lock(); mutex_lock(&iwl_mei_mutex); - netdev = rcu_dereference_protected(iwl_mei_cache.netdev, - lockdep_is_held(&iwl_mei_mutex)); - if (mei->amt_enabled == !!le32_to_cpu(dw->val)) goto out; mei->amt_enabled = dw->val; - if (mei->amt_enabled) { - if (netdev) - netdev_rx_handler_register(netdev, iwl_mei_rx_handler, mei); - + if (mei->amt_enabled) iwl_mei_set_init_conf(mei); - } else { - if (iwl_mei_cache.ops) - iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false); - if (netdev) - netdev_rx_handler_unregister(netdev); - } + else if (iwl_mei_cache.ops) + iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false, false); + + schedule_work(&mei->netdev_work); out: mutex_unlock(&iwl_mei_mutex); - rtnl_unlock(); } static void iwl_mei_handle_nic_owner(struct mei_cl_device *cldev, @@ -798,14 +822,18 @@ static void iwl_mei_handle_csme_taking_ownership(struct mei_cl_device *cldev, mei->got_ownership = false; - /* - * Remember to send CSME_OWNERSHIP_CONFIRMED when the wifi driver - * is finished taking the device down. - */ - mei->csme_taking_ownership = true; + if (iwl_mei_cache.ops && !mei->device_down) { + /* + * Remember to send CSME_OWNERSHIP_CONFIRMED when the wifi + * driver is finished taking the device down. + */ + mei->csme_taking_ownership = true; - if (iwl_mei_cache.ops) - iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, true); + iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, true, true); + } else { + iwl_mei_send_sap_msg(cldev, + SAP_MSG_NOTIF_CSME_OWNERSHIP_CONFIRMED); + } } static void iwl_mei_handle_nvm(struct mei_cl_device *cldev, @@ -857,6 +885,15 @@ static void iwl_mei_handle_rx_host_own_req(struct mei_cl_device *cldev, iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, false); } +static void iwl_mei_handle_pldr_ack(struct mei_cl_device *cldev, + const struct iwl_sap_pldr_ack_data *ack) +{ + struct iwl_mei *mei = mei_cldev_get_drvdata(cldev); + + mei->pldr_active = le32_to_cpu(ack->status) == SAP_PLDR_STATUS_SUCCESS; + wake_up_all(&mei->pldr_wq); +} + static void iwl_mei_handle_ping(struct mei_cl_device *cldev, const struct iwl_sap_hdr *hdr) { @@ -937,6 +974,8 @@ static void iwl_mei_handle_sap_msg(struct mei_cl_device *cldev, iwl_mei_handle_can_release_ownership, 0); SAP_MSG_HANDLER(CSME_TAKING_OWNERSHIP, iwl_mei_handle_csme_taking_ownership, 0); + SAP_MSG_HANDLER(PLDR_ACK, iwl_mei_handle_pldr_ack, + sizeof(struct iwl_sap_pldr_ack_data)); default: /* * This is not really an error, there are message that we decided @@ -1313,10 +1352,17 @@ out: } EXPORT_SYMBOL_GPL(iwl_mei_get_nvm); -int iwl_mei_get_ownership(void) +#define IWL_MEI_PLDR_NUM_RETRIES 3 + +int iwl_mei_pldr_req(void) { struct iwl_mei *mei; int ret; + struct iwl_sap_pldr_data msg = { + .hdr.type = cpu_to_le16(SAP_MSG_NOTIF_PLDR), + .hdr.len = cpu_to_le16(sizeof(msg) - sizeof(msg.hdr)), + }; + int i; mutex_lock(&iwl_mei_mutex); @@ -1338,22 +1384,34 @@ int iwl_mei_get_ownership(void) goto out; } - if (mei->got_ownership) { - ret = 0; - goto out; + for (i = 0; i < IWL_MEI_PLDR_NUM_RETRIES; i++) { + ret = iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); + mutex_unlock(&iwl_mei_mutex); + if (ret) + return ret; + + ret = wait_event_timeout(mei->pldr_wq, mei->pldr_active, HZ / 2); + if (ret) + break; + + /* Take the mutex for the next iteration */ + mutex_lock(&iwl_mei_mutex); } - ret = iwl_mei_send_sap_msg(mei->cldev, - SAP_MSG_NOTIF_HOST_ASKS_FOR_NIC_OWNERSHIP); if (ret) - goto out; + return 0; + ret = -ETIMEDOUT; +out: mutex_unlock(&iwl_mei_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(iwl_mei_pldr_req); - ret = wait_event_timeout(mei->get_ownership_wq, - mei->got_ownership, HZ / 2); - if (!ret) - return -ETIMEDOUT; +int iwl_mei_get_ownership(void) +{ + struct iwl_mei *mei; + int ret; mutex_lock(&iwl_mei_mutex); @@ -1370,14 +1428,59 @@ int iwl_mei_get_ownership(void) goto out; } - ret = !mei->got_ownership; + if (!mei->amt_enabled) { + ret = 0; + goto out; + } + + if (mei->got_ownership) { + ret = 0; + goto out; + } + ret = iwl_mei_send_sap_msg(mei->cldev, + SAP_MSG_NOTIF_HOST_ASKS_FOR_NIC_OWNERSHIP); + if (ret) + goto out; + + mutex_unlock(&iwl_mei_mutex); + + ret = wait_event_timeout(mei->get_ownership_wq, + mei->got_ownership, HZ / 2); + return (!ret) ? -ETIMEDOUT : 0; out: mutex_unlock(&iwl_mei_mutex); return ret; } EXPORT_SYMBOL_GPL(iwl_mei_get_ownership); +void iwl_mei_alive_notif(bool success) +{ + struct iwl_mei *mei; + struct iwl_sap_pldr_end_data msg = { + .hdr.type = cpu_to_le16(SAP_MSG_NOTIF_PLDR_END), + .hdr.len = cpu_to_le16(sizeof(msg) - sizeof(msg.hdr)), + .status = success ? cpu_to_le32(SAP_PLDR_STATUS_SUCCESS) : + cpu_to_le32(SAP_PLDR_STATUS_FAILURE), + }; + + mutex_lock(&iwl_mei_mutex); + + if (!iwl_mei_is_connected()) + goto out; + + mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); + if (!mei || !mei->pldr_active) + goto out; + + mei->pldr_active = false; + + iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); +out: + mutex_unlock(&iwl_mei_mutex); +} +EXPORT_SYMBOL_GPL(iwl_mei_alive_notif); + void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_info, const struct iwl_mei_colloc_info *colloc_info) { @@ -1413,10 +1516,7 @@ void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_info, mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); - if (!mei) - goto out; - - if (!mei->amt_enabled) + if (!mei && !mei->amt_enabled) goto out; iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); @@ -1435,7 +1535,7 @@ void iwl_mei_host_disassociated(void) struct iwl_sap_notif_host_link_down msg = { .hdr.type = cpu_to_le16(SAP_MSG_NOTIF_HOST_LINK_DOWN), .hdr.len = cpu_to_le16(sizeof(msg) - sizeof(msg.hdr)), - .type = HOST_LINK_DOWN_TYPE_LONG, + .type = HOST_LINK_DOWN_TYPE_TEMPORARY, }; mutex_lock(&iwl_mei_mutex); @@ -1445,7 +1545,7 @@ void iwl_mei_host_disassociated(void) mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); - if (!mei) + if (!mei && !mei->amt_enabled) goto out; iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); @@ -1481,7 +1581,7 @@ void iwl_mei_set_rfkill_state(bool hw_rfkill, bool sw_rfkill) mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); - if (!mei) + if (!mei && !mei->amt_enabled) goto out; iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); @@ -1510,7 +1610,7 @@ void iwl_mei_set_nic_info(const u8 *mac_address, const u8 *nvm_address) mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); - if (!mei) + if (!mei && !mei->amt_enabled) goto out; iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); @@ -1538,7 +1638,7 @@ void iwl_mei_set_country_code(u16 mcc) mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); - if (!mei) + if (!mei && !mei->amt_enabled) goto out; iwl_mei_send_sap_msg_payload(mei->cldev, &msg.hdr); @@ -1564,7 +1664,7 @@ void iwl_mei_set_power_limit(const __le16 *power_limit) mei = mei_cldev_get_drvdata(iwl_mei_global_cldev); - if (!mei) + if (!mei && !mei->amt_enabled) goto out; memcpy(msg.sar_chain_info_table, power_limit, sizeof(msg.sar_chain_info_table)); @@ -1616,7 +1716,7 @@ out: } EXPORT_SYMBOL_GPL(iwl_mei_set_netdev); -void iwl_mei_device_down(void) +void iwl_mei_device_state(bool up) { struct iwl_mei *mei; @@ -1630,7 +1730,9 @@ void iwl_mei_device_down(void) if (!mei) goto out; - if (!mei->csme_taking_ownership) + mei->device_down = !up; + + if (up || !mei->csme_taking_ownership) goto out; iwl_mei_send_sap_msg(mei->cldev, @@ -1639,7 +1741,7 @@ void iwl_mei_device_down(void) out: mutex_unlock(&iwl_mei_mutex); } -EXPORT_SYMBOL_GPL(iwl_mei_device_down); +EXPORT_SYMBOL_GPL(iwl_mei_device_state); int iwl_mei_register(void *priv, const struct iwl_mei_ops *ops) { @@ -1669,9 +1771,10 @@ int iwl_mei_register(void *priv, const struct iwl_mei_ops *ops) /* we have already a SAP connection */ if (iwl_mei_is_connected()) { - iwl_mei_send_sap_msg(mei->cldev, - SAP_MSG_NOTIF_WIFIDR_UP); - ops->rfkill(priv, mei->link_prot_state); + if (mei->amt_enabled) + iwl_mei_send_sap_msg(mei->cldev, + SAP_MSG_NOTIF_WIFIDR_UP); + ops->rfkill(priv, mei->link_prot_state, false); } } ret = 0; @@ -1817,10 +1920,13 @@ static int iwl_mei_probe(struct mei_cl_device *cldev, INIT_DELAYED_WORK(&mei->csa_throttle_end_wk, iwl_mei_csa_throttle_end_wk); init_waitqueue_head(&mei->get_ownership_wq); + init_waitqueue_head(&mei->pldr_wq); spin_lock_init(&mei->data_q_lock); + INIT_WORK(&mei->netdev_work, iwl_mei_netdev_work); mei_cldev_set_drvdata(cldev, mei); mei->cldev = cldev; + mei->device_down = true; do { ret = iwl_mei_alloc_shared_mem(cldev); @@ -1884,6 +1990,7 @@ free: } #define SEND_SAP_MAX_WAIT_ITERATION 10 +#define IWLMEI_DEVICE_DOWN_WAIT_ITERATION 50 static void iwl_mei_remove(struct mei_cl_device *cldev) { @@ -1894,8 +2001,26 @@ static void iwl_mei_remove(struct mei_cl_device *cldev) * We are being removed while the bus is active, it means we are * going to suspend/ shutdown, so the NIC will disappear. */ - if (mei_cldev_enabled(cldev) && iwl_mei_cache.ops) - iwl_mei_cache.ops->nic_stolen(iwl_mei_cache.priv); + if (mei_cldev_enabled(cldev) && iwl_mei_cache.ops) { + unsigned int iter = IWLMEI_DEVICE_DOWN_WAIT_ITERATION; + bool down = false; + + /* + * In case of suspend, wait for the mac to stop and don't remove + * the interface. This will allow the interface to come back + * on resume. + */ + while (!down && iter--) { + mdelay(1); + + mutex_lock(&iwl_mei_mutex); + down = mei->device_down; + mutex_unlock(&iwl_mei_mutex); + } + + if (!down) + iwl_mei_cache.ops->nic_stolen(iwl_mei_cache.priv); + } if (rcu_access_pointer(iwl_mei_cache.netdev)) { struct net_device *dev; @@ -1921,29 +2046,32 @@ static void iwl_mei_remove(struct mei_cl_device *cldev) mutex_lock(&iwl_mei_mutex); - /* - * Tell CSME that we are going down so that it won't access the - * memory anymore, make sure this message goes through immediately. - */ - mei->csa_throttled = false; - iwl_mei_send_sap_msg(mei->cldev, - SAP_MSG_NOTIF_HOST_GOES_DOWN); + if (mei->amt_enabled) { + /* + * Tell CSME that we are going down so that it won't access the + * memory anymore, make sure this message goes through immediately. + */ + mei->csa_throttled = false; + iwl_mei_send_sap_msg(mei->cldev, + SAP_MSG_NOTIF_HOST_GOES_DOWN); - for (i = 0; i < SEND_SAP_MAX_WAIT_ITERATION; i++) { - if (!iwl_mei_host_to_me_data_pending(mei)) - break; + for (i = 0; i < SEND_SAP_MAX_WAIT_ITERATION; i++) { + if (!iwl_mei_host_to_me_data_pending(mei)) + break; - msleep(5); - } + msleep(20); + } - /* - * If we couldn't make sure that CSME saw the HOST_GOES_DOWN message, - * it means that it will probably keep reading memory that we are going - * to unmap and free, expect IOMMU error messages. - */ - if (i == SEND_SAP_MAX_WAIT_ITERATION) - dev_err(&mei->cldev->dev, - "Couldn't get ACK from CSME on HOST_GOES_DOWN message\n"); + /* + * If we couldn't make sure that CSME saw the HOST_GOES_DOWN + * message, it means that it will probably keep reading memory + * that we are going to unmap and free, expect IOMMU error + * messages. + */ + if (i == SEND_SAP_MAX_WAIT_ITERATION) + dev_err(&mei->cldev->dev, + "Couldn't get ACK from CSME on HOST_GOES_DOWN message\n"); + } mutex_unlock(&iwl_mei_mutex); @@ -1976,6 +2104,7 @@ static void iwl_mei_remove(struct mei_cl_device *cldev) */ cancel_work_sync(&mei->send_csa_msg_wk); cancel_delayed_work_sync(&mei->csa_throttle_end_wk); + cancel_work_sync(&mei->netdev_work); /* * If someone waits for the ownership, let him know that we are going @@ -1983,6 +2112,7 @@ static void iwl_mei_remove(struct mei_cl_device *cldev) * the device. */ wake_up_all(&mei->get_ownership_wq); + wake_up_all(&mei->pldr_wq); mutex_lock(&iwl_mei_mutex); diff --git a/drivers/net/wireless/intel/iwlwifi/mei/net.c b/drivers/net/wireless/intel/iwlwifi/mei/net.c index 3472167c8370..eac46d1a397a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/net.c +++ b/drivers/net/wireless/intel/iwlwifi/mei/net.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2021 Intel Corporation + * Copyright (C) 2021-2022 Intel Corporation */ #include <uapi/linux/if_ether.h> @@ -337,10 +337,14 @@ rx_handler_result_t iwl_mei_rx_filter(struct sk_buff *orig_skb, if (!*pass_to_csme) return RX_HANDLER_PASS; - if (ret == RX_HANDLER_PASS) + if (ret == RX_HANDLER_PASS) { skb = skb_copy(orig_skb, GFP_ATOMIC); - else + + if (!skb) + return RX_HANDLER_PASS; + } else { skb = orig_skb; + } /* CSME wants the MAC header as well, push it back */ skb_push(skb, skb->data - skb_mac_header(skb)); diff --git a/drivers/net/wireless/intel/iwlwifi/mei/sap.h b/drivers/net/wireless/intel/iwlwifi/mei/sap.h index be1456dea484..6c0ad4adbf32 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/sap.h +++ b/drivers/net/wireless/intel/iwlwifi/mei/sap.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2021 Intel Corporation + * Copyright (C) 2021 - 2022 Intel Corporation */ #ifndef __sap_h__ @@ -203,6 +203,7 @@ struct iwl_sap_me_msg_start_ok { * @SAP_MSG_NOTIF_NIC_OWNER: Payload is a DW. See &enum iwl_sap_nic_owner. * @SAP_MSG_NOTIF_CSME_CONN_STATUS: See &struct iwl_sap_notif_conn_status. * @SAP_MSG_NOTIF_NVM: See &struct iwl_sap_nvm. + * @SAP_MSG_NOTIF_PLDR_ACK: See &struct iwl_sap_pldr_ack_data. * @SAP_MSG_NOTIF_FROM_CSME_MAX: Not used. * * @SAP_MSG_NOTIF_FROM_HOST_MIN: Not used. @@ -226,6 +227,8 @@ struct iwl_sap_me_msg_start_ok { * @SAP_MSG_NOTIF_HOST_OWNERSHIP_CONFIRMED: No payload. * @SAP_MSG_NOTIF_SAR_LIMITS: See &struct iwl_sap_notif_sar_limits. * @SAP_MSG_NOTIF_GET_NVM: No payload. Triggers %SAP_MSG_NOTIF_NVM. + * @SAP_MSG_NOTIF_PLDR: See &struct iwl_sap_pldr_data. + * @SAP_MSG_NOTIF_PLDR_END: See &struct iwl_sap_pldr_end_data. * @SAP_MSG_NOTIF_FROM_HOST_MAX: Not used. * * @SAP_MSG_DATA_MIN: Not used. @@ -258,6 +261,8 @@ enum iwl_sap_msg { SAP_MSG_NOTIF_NIC_OWNER = 511, SAP_MSG_NOTIF_CSME_CONN_STATUS = 512, SAP_MSG_NOTIF_NVM = 513, + /* 514 - 517 not supported */ + SAP_MSG_NOTIF_PLDR_ACK = 518, SAP_MSG_NOTIF_FROM_CSME_MAX, SAP_MSG_NOTIF_FROM_HOST_MIN = 1000, @@ -279,6 +284,9 @@ enum iwl_sap_msg { SAP_MSG_NOTIF_HOST_OWNERSHIP_CONFIRMED = 1015, SAP_MSG_NOTIF_SAR_LIMITS = 1016, SAP_MSG_NOTIF_GET_NVM = 1017, + /* 1018 - 1023 not supported */ + SAP_MSG_NOTIF_PLDR = 1024, + SAP_MSG_NOTIF_PLDR_END = 1025, SAP_MSG_NOTIF_FROM_HOST_MAX, SAP_MSG_DATA_MIN = 2000, @@ -334,12 +342,14 @@ enum iwl_sap_wifi_auth_type { /** * enum iwl_sap_wifi_cipher_alg * @SAP_WIFI_CIPHER_ALG_NONE: TBD + * @SAP_WIFI_CIPHER_ALG_TKIP: TBD * @SAP_WIFI_CIPHER_ALG_CCMP: TBD * @SAP_WIFI_CIPHER_ALG_GCMP: TBD * @SAP_WIFI_CIPHER_ALG_GCMP_256: TBD */ enum iwl_sap_wifi_cipher_alg { SAP_WIFI_CIPHER_ALG_NONE = IWL_MEI_CIPHER_NONE, + SAP_WIFI_CIPHER_ALG_TKIP = IWL_MEI_CIPHER_TKIP, SAP_WIFI_CIPHER_ALG_CCMP = IWL_MEI_CIPHER_CCMP, SAP_WIFI_CIPHER_ALG_GCMP = IWL_MEI_CIPHER_GCMP, SAP_WIFI_CIPHER_ALG_GCMP_256 = IWL_MEI_CIPHER_GCMP_256, @@ -730,4 +740,47 @@ struct iwl_sap_cb_data { u8 payload[]; }; +/** + * struct iwl_sap_pldr_data - payload of %SAP_MSG_NOTIF_PLDR + * @hdr: The SAP header. + * @version: SAP message version + */ +struct iwl_sap_pldr_data { + struct iwl_sap_hdr hdr; + __le32 version; +} __packed; + +/** + * enum iwl_sap_pldr_status - + * @SAP_PLDR_STATUS_SUCCESS: PLDR started/ended successfully + * @SAP_PLDR_STATUS_FAILURE: PLDR failed to start/end + */ +enum iwl_sap_pldr_status { + SAP_PLDR_STATUS_SUCCESS = 0, + SAP_PLDR_STATUS_FAILURE = 1, +}; + +/* + * struct iwl_sap_pldr_end_data - payload of %SAP_MSG_NOTIF_PLDR_END + * @hdr: The SAP header. + * @version: SAP message version + * @status: PLDR end status + */ +struct iwl_sap_pldr_end_data { + struct iwl_sap_hdr hdr; + __le32 version; + __le32 status; +} __packed; + +/* + * struct iwl_sap_pldr_ack_data - payload of %SAP_MSG_NOTIF_PLDR_ACK + * @version: SAP message version + * @status: CSME accept/refuse to the PLDR request + */ +struct iwl_sap_pldr_ack_data { + struct iwl_sap_hdr hdr; + __le32 version; + __le32 status; +} __packed; + #endif /* __sap_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile index 11e814b7cad0..b28fcf0cf9cf 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile @@ -7,6 +7,7 @@ iwlmvm-y += power.o coex.o iwlmvm-y += tt.o offloading.o tdls.o iwlmvm-y += ftm-responder.o ftm-initiator.o iwlmvm-y += rfi.o +iwlmvm-y += mld-key.o iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o iwlmvm-$(CONFIG_PM) += d3.o diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 1e8123140973..1ce9450e5add 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2021 Intel Corporation + * Copyright (C) 2012-2014, 2018-2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -1248,7 +1248,7 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len) mvmvif = iwl_mvm_vif_from_mac80211(vif); info = IEEE80211_SKB_CB(beacon); - rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif); + rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif); beacon_cmd.flags = cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate)); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index f041e77af059..ef43f6971cd9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -404,6 +404,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, return -EIO; } + iwl_mei_alive_notif(!ret); + ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait); if (ret) { IWL_ERR(mvm, "Timeout waiting for PNVM load!\n"); @@ -1456,6 +1458,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) struct ieee80211_channel *chan; struct cfg80211_chan_def chandef; struct ieee80211_supported_band *sband = NULL; + u32 sb_cfg; lockdep_assert_held(&mvm->mutex); @@ -1463,6 +1466,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm) if (ret) return ret; + sb_cfg = iwl_read_umac_prph(mvm->trans, SB_MODIFY_CFG_FLAG); + if (!(sb_cfg & SB_CFG_RESIDES_IN_OTP_MASK) && iwl_mei_pldr_req()) + return ret; + ret = iwl_mvm_load_rt_fw(mvm); if (ret) { IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); @@ -1665,6 +1672,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm) iwl_rfi_send_config_cmd(mvm, NULL); } + iwl_mvm_mei_device_state(mvm, true); + IWL_DEBUG_INFO(mvm, "RT uCode started.\n"); return 0; error: diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index de0c545d50fd..83abfe996138 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -788,14 +788,40 @@ static u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size) return ie - beacon; } -u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info, - struct ieee80211_vif *vif) +static u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm, + struct ieee80211_tx_info *info, + struct ieee80211_vif *vif) { + struct ieee80211_supported_band *sband; + unsigned long basic = vif->bss_conf.basic_rates; + u16 lowest_cck = IWL_RATE_COUNT, lowest_ofdm = IWL_RATE_COUNT; u8 rate; - if (info->band == NL80211_BAND_2GHZ && !vif->p2p) - rate = IWL_FIRST_CCK_RATE; - else - rate = IWL_FIRST_OFDM_RATE; + u32 i; + + sband = mvm->hw->wiphy->bands[info->band]; + for_each_set_bit(i, &basic, BITS_PER_LONG) { + u16 hw = sband->bitrates[i].hw_value; + + if (hw >= IWL_FIRST_OFDM_RATE) { + if (lowest_ofdm > hw) + lowest_ofdm = hw; + } else if (lowest_cck > hw) { + lowest_cck = hw; + } + } + + if (info->band == NL80211_BAND_2GHZ && !vif->p2p) { + if (lowest_cck != IWL_RATE_COUNT) + rate = lowest_cck; + else if (lowest_ofdm != IWL_RATE_COUNT) + rate = lowest_ofdm; + else + rate = IWL_RATE_1M_INDEX; + } else if (lowest_ofdm != IWL_RATE_COUNT) { + rate = lowest_ofdm; + } else { + rate = IWL_RATE_6M_INDEX; + } return rate; } @@ -812,6 +838,24 @@ u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx) return flags; } +u8 iwl_mvm_mac_ctxt_get_beacon_rate(struct iwl_mvm *mvm, + struct ieee80211_tx_info *info, + struct ieee80211_vif *vif) +{ + struct ieee80211_supported_band *sband = + mvm->hw->wiphy->bands[info->band]; + u32 legacy = vif->bss_conf.beacon_tx_rate.control[info->band].legacy; + + /* if beacon rate was configured try using it */ + if (hweight32(legacy) == 1) { + u32 rate = ffs(legacy) - 1; + + return sband->bitrates[rate].hw_value; + } + + return iwl_mvm_mac_ctxt_get_lowest_rate(mvm, info, vif); +} + static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct sk_buff *beacon, @@ -842,7 +886,7 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm, cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS); - rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif); + rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif); tx->rate_n_flags |= cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate)); @@ -926,7 +970,7 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(beacon); struct iwl_mac_beacon_cmd beacon_cmd = {}; - u8 rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif); + u8 rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif); u16 flags; struct ieee80211_chanctx_conf *ctx; int channel; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 8464c9b7baf1..a81dd488caa8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -374,6 +374,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->wiphy->n_cipher_suites++; } + wiphy_ext_feature_set(hw->wiphy, + NL80211_EXT_FEATURE_BEACON_RATE_LEGACY); + if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_FTM_CALIBRATED)) { wiphy_ext_feature_set(hw->wiphy, @@ -2306,6 +2309,9 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, */ if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { + /* first remove remaining keys */ + iwl_mvm_sec_key_remove_ap(mvm, vif); + /* * Remove AP station now that * the MAC is unassoc @@ -3059,6 +3065,9 @@ static void iwl_mvm_mei_host_associated(struct iwl_mvm *mvm, return; switch (mvm_sta->pairwise_cipher) { + case WLAN_CIPHER_SUITE_TKIP: + conn_info.pairwise_cipher = IWL_MEI_CIPHER_TKIP; + break; case WLAN_CIPHER_SUITE_CCMP: conn_info.pairwise_cipher = IWL_MEI_CIPHER_CCMP; break; @@ -3461,6 +3470,8 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw, struct iwl_mvm_sta *mvmsta = NULL; struct iwl_mvm_key_pn *ptk_pn; int keyidx = key->keyidx; + u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); + u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0); int ret, i; u8 key_offset; @@ -3600,7 +3611,12 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw, mvmsta->pairwise_cipher = key->cipher; IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n"); - ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, key_offset); + + if (sec_key_ver) + ret = iwl_mvm_sec_key_add(mvm, vif, sta, key); + else + ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, key_offset); + if (ret) { IWL_WARN(mvm, "set key failed\n"); key->hw_key_idx = STA_KEY_IDX_INVALID; @@ -3653,7 +3669,10 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw, } IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n"); - ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key); + if (sec_key_ver) + ret = iwl_mvm_sec_key_del(mvm, vif, sta, key); + else + ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key); break; default: ret = -EINVAL; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c new file mode 100644 index 000000000000..e27c893502f7 --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * Copyright (C) 2022 Intel Corporation + */ +#include <linux/kernel.h> +#include <net/mac80211.h> +#include "mvm.h" +#include "fw/api/context.h" +#include "fw/api/datapath.h" + +static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + + if (vif->type == NL80211_IFTYPE_AP && + !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return BIT(mvmvif->mcast_sta.sta_id); + + if (sta) { + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + + return BIT(mvmsta->sta_id); + } + + if (vif->type == NL80211_IFTYPE_STATION && + mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) + return BIT(mvmvif->ap_sta_id); + + /* invalid */ + return 0; +} + +static u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + u32 flags = 0; + + if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + flags |= IWL_SEC_KEY_FLAG_MCAST_KEY; + + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_WEP104: + flags |= IWL_SEC_KEY_FLAG_KEY_SIZE; + fallthrough; + case WLAN_CIPHER_SUITE_WEP40: + flags |= IWL_SEC_KEY_FLAG_CIPHER_WEP; + break; + case WLAN_CIPHER_SUITE_TKIP: + flags |= IWL_SEC_KEY_FLAG_CIPHER_TKIP; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + case WLAN_CIPHER_SUITE_CCMP: + flags |= IWL_SEC_KEY_FLAG_CIPHER_CCMP; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + flags |= IWL_SEC_KEY_FLAG_KEY_SIZE; + fallthrough; + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + flags |= IWL_SEC_KEY_FLAG_CIPHER_GCMP; + break; + } + + rcu_read_lock(); + if (!sta && vif->type == NL80211_IFTYPE_STATION && + mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) { + u8 sta_id = mvmvif->ap_sta_id; + + sta = rcu_dereference_check(mvm->fw_id_to_mac_id[sta_id], + lockdep_is_held(&mvm->mutex)); + } + + if (!IS_ERR_OR_NULL(sta) && sta->mfp) + flags |= IWL_SEC_KEY_FLAG_MFP; + rcu_read_unlock(); + + return flags; +} + +static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask, + u32 key_flags, u32 keyidx, u32 flags) +{ + u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); + struct iwl_sec_key_cmd cmd = { + .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE), + .u.remove.sta_mask = cpu_to_le32(sta_mask), + .u.remove.key_id = cpu_to_le32(keyidx), + .u.remove.key_flags = cpu_to_le32(key_flags), + }; + + return iwl_mvm_send_cmd_pdu(mvm, cmd_id, flags, sizeof(cmd), &cmd); +} + +int iwl_mvm_sec_key_add(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf) +{ + u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf); + u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf); + u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); + struct iwl_sec_key_cmd cmd = { + .action = cpu_to_le32(FW_CTXT_ACTION_ADD), + .u.add.sta_mask = cpu_to_le32(sta_mask), + .u.add.key_id = cpu_to_le32(keyconf->keyidx), + .u.add.key_flags = cpu_to_le32(key_flags), + .u.add.tx_seq = cpu_to_le64(atomic64_read(&keyconf->tx_pn)), + }; + int ret; + + if (WARN_ON(keyconf->keylen > sizeof(cmd.u.add.key))) + return -EINVAL; + + if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || + keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) + memcpy(cmd.u.add.key + IWL_SEC_WEP_KEY_OFFSET, keyconf->key, + keyconf->keylen); + else + memcpy(cmd.u.add.key, keyconf->key, keyconf->keylen); + + if (keyconf->cipher == WLAN_CIPHER_SUITE_TKIP) { + memcpy(cmd.u.add.tkip_mic_rx_key, + keyconf->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, + 8); + memcpy(cmd.u.add.tkip_mic_tx_key, + keyconf->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, + 8); + } + + ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd); + if (ret) + return ret; + + /* + * For WEP, the same key is used for multicast and unicast so need to + * upload it again. If this fails, remove the original as well. + */ + if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || + keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) { + cmd.u.add.key_flags ^= cpu_to_le32(IWL_SEC_KEY_FLAG_MCAST_KEY); + ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd); + if (ret) + __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, + keyconf->keyidx, 0); + } + + return ret; +} + +static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf, + u32 flags) +{ + u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf); + u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf); + int ret; + + ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx, + flags); + if (ret) + return ret; + + /* For WEP, delete the key again as unicast */ + if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || + keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) { + key_flags ^= IWL_SEC_KEY_FLAG_MCAST_KEY; + ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, + keyconf->keyidx, flags); + } + + return ret; +} + +int iwl_mvm_sec_key_del(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf) +{ + return _iwl_mvm_sec_key_del(mvm, vif, sta, keyconf, 0); +} + +static void iwl_mvm_sec_key_remove_ap_iter(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, + void *data) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + + if (key->hw_key_idx == STA_KEY_IDX_INVALID) + return; + + if (sta) + return; + + _iwl_mvm_sec_key_del(mvm, vif, NULL, key, CMD_ASYNC); + key->hw_key_idx = STA_KEY_IDX_INVALID; +} + +void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); + u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0); + + if (WARN_ON(vif->type != NL80211_IFTYPE_STATION || + mvmvif->ap_sta_id == IWL_MVM_INVALID_STA)) + return; + + if (!sec_key_ver) + return; + + ieee80211_iter_keys_rcu(mvm->hw, vif, + iwl_mvm_sec_key_remove_ap_iter, + NULL); +} diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 97cba526e465..962e304fc2b1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1644,7 +1644,8 @@ int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm, struct sk_buff *beacon, void *data, int len); -u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info, +u8 iwl_mvm_mac_ctxt_get_beacon_rate(struct iwl_mvm *mvm, + struct ieee80211_tx_info *info, struct ieee80211_vif *vif); u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx); @@ -2079,6 +2080,18 @@ void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw, struct dentry *dir); #endif +/* new MLD related APIs */ +int iwl_mvm_sec_key_add(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf); +int iwl_mvm_sec_key_del(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf); +void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm, + struct ieee80211_vif *vif); + int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm, struct iwl_rfi_lut_entry *rfi_table); struct iwl_rfi_freq_table_resp_cmd *iwl_rfi_get_freq_table(struct iwl_mvm *mvm); @@ -2201,10 +2214,10 @@ static inline void iwl_mvm_mei_host_disassociated(struct iwl_mvm *mvm) iwl_mei_host_disassociated(); } -static inline void iwl_mvm_mei_device_down(struct iwl_mvm *mvm) +static inline void iwl_mvm_mei_device_state(struct iwl_mvm *mvm, bool up) { if (mvm->mei_registered) - iwl_mei_device_down(); + iwl_mei_device_state(up); } static inline void iwl_mvm_mei_set_sw_rfkill_state(struct iwl_mvm *mvm) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index d2d42cd48af2..9699433137bc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -547,6 +547,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = { HCMD_NAME(TLC_MNG_CONFIG_CMD), HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD), HCMD_NAME(SCD_QUEUE_CONFIG_CMD), + HCMD_NAME(SEC_KEY_CMD), HCMD_NAME(MONITOR_NOTIF), HCMD_NAME(THERMAL_DUAL_CHAIN_REQUEST), HCMD_NAME(STA_PM_NOTIF), @@ -1375,7 +1376,7 @@ void iwl_mvm_stop_device(struct iwl_mvm *mvm) iwl_trans_stop_device(mvm->trans); iwl_free_fw_paging(&mvm->fwrt); iwl_fw_dump_conf_clear(&mvm->fwrt); - iwl_mvm_mei_device_down(mvm); + iwl_mvm_mei_device_state(mvm, false); } static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 1aadccd8841f..5f782ca1e254 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -1747,10 +1747,12 @@ static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm, rx_status->rate_idx = rate; - if (WARN_ONCE(rate < 0 || rate > 0xFF, - "Invalid rate flags 0x%x, band %d,\n", - rate_n_flags, rx_status->band)) + if ((rate < 0 || rate > 0xFF) && net_ratelimit()) { + IWL_ERR(mvm, "Invalid rate flags 0x%x, band %d,\n", + rate_n_flags, rx_status->band); rx_status->rate_idx = 0; + } + break; } } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index cbd8053a9e35..515dd3e0730d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1954,6 +1954,9 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, if (vif->cfg.assoc) return ret; + /* first remove remaining keys */ + iwl_mvm_sec_key_remove_ap(mvm, vif); + /* unassoc - go ahead - remove the AP STA now */ mvmvif->ap_sta_id = IWL_MVM_INVALID_STA; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 86d20e13bf47..f460332333a7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2021 Intel Corporation + * Copyright (C) 2012-2014, 2018-2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -183,7 +183,10 @@ static u32 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb, struct ieee80211_tx_info *info, bool amsdu) { - if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ) + if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ || + (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_BZ && + CSR_HW_REV_TYPE(mvm->trans->hw_rev) == IWL_CFG_MAC_TYPE_GL && + mvm->trans->hw_rev_step == SILICON_A_STEP)) return iwl_mvm_tx_csum_pre_bz(mvm, skb, info, amsdu); return iwl_mvm_tx_csum_bz(mvm, skb, amsdu); } @@ -1171,9 +1174,15 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, /* From now on, we cannot access info->control */ iwl_mvm_skb_prepare_status(skb, dev_cmd); + /* + * The IV is introduced by the HW for new tx api, and it is not present + * in the skb, hence, don't tell iwl_mvm_mei_tx_copy_to_csme about the + * IV for those devices. + */ if (ieee80211_is_data(fc)) iwl_mvm_mei_tx_copy_to_csme(mvm, skb, - info->control.hw_key ? + info->control.hw_key && + !iwl_mvm_has_new_tx_api(mvm) ? info->control.hw_key->iv_len : 0); if (iwl_trans_tx(mvm->trans, skb, dev_cmd, txq_id)) diff --git a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c index 4e0a0c881697..26287b129d18 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c @@ -91,7 +91,7 @@ static int prism2_get_datarates(struct net_device *dev, u8 *rates) static int prism2_get_name(struct net_device *dev, struct iw_request_info *info, - char *name, char *extra) + union iwreq_data *wrqu, char *extra) { u8 rates[10]; int len, i, over2 = 0; @@ -105,7 +105,7 @@ static int prism2_get_name(struct net_device *dev, } } - strcpy(name, over2 ? "IEEE 802.11b" : "IEEE 802.11-DS"); + strcpy(wrqu->name, over2 ? "IEEE 802.11b" : "IEEE 802.11-DS"); return 0; } @@ -113,8 +113,9 @@ static int prism2_get_name(struct net_device *dev, static int prism2_ioctl_siwencode(struct net_device *dev, struct iw_request_info *info, - struct iw_point *erq, char *keybuf) + union iwreq_data *wrqu, char *keybuf) { + struct iw_point *erq = &wrqu->encoding; struct hostap_interface *iface; local_info_t *local; int i; @@ -215,8 +216,9 @@ static int prism2_ioctl_siwencode(struct net_device *dev, static int prism2_ioctl_giwencode(struct net_device *dev, struct iw_request_info *info, - struct iw_point *erq, char *key) + union iwreq_data *wrqu, char *key) { + struct iw_point *erq = &wrqu->encoding; struct hostap_interface *iface; local_info_t *local; int i, len; @@ -321,8 +323,9 @@ static int hostap_set_rate(struct net_device *dev) static int prism2_ioctl_siwrate(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rrq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->bitrate; struct hostap_interface *iface; local_info_t *local; @@ -381,8 +384,9 @@ static int prism2_ioctl_siwrate(struct net_device *dev, static int prism2_ioctl_giwrate(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rrq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->bitrate; u16 val; struct hostap_interface *iface; local_info_t *local; @@ -440,8 +444,9 @@ static int prism2_ioctl_giwrate(struct net_device *dev, static int prism2_ioctl_siwsens(struct net_device *dev, struct iw_request_info *info, - struct iw_param *sens, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *sens = &wrqu->sens; struct hostap_interface *iface; local_info_t *local; @@ -461,8 +466,9 @@ static int prism2_ioctl_siwsens(struct net_device *dev, static int prism2_ioctl_giwsens(struct net_device *dev, struct iw_request_info *info, - struct iw_param *sens, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *sens = &wrqu->sens; struct hostap_interface *iface; local_info_t *local; __le16 val; @@ -485,8 +491,9 @@ static int prism2_ioctl_giwsens(struct net_device *dev, /* Deprecated in new wireless extension API */ static int prism2_ioctl_giwaplist(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_point *data = &wrqu->data; struct hostap_interface *iface; local_info_t *local; struct sockaddr *addr; @@ -526,8 +533,9 @@ static int prism2_ioctl_giwaplist(struct net_device *dev, static int prism2_ioctl_siwrts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rts = &wrqu->rts; struct hostap_interface *iface; local_info_t *local; __le16 val; @@ -553,8 +561,9 @@ static int prism2_ioctl_siwrts(struct net_device *dev, static int prism2_ioctl_giwrts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rts = &wrqu->rts; struct hostap_interface *iface; local_info_t *local; __le16 val; @@ -576,8 +585,9 @@ static int prism2_ioctl_giwrts(struct net_device *dev, static int prism2_ioctl_siwfrag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rts = &wrqu->rts; struct hostap_interface *iface; local_info_t *local; __le16 val; @@ -603,8 +613,9 @@ static int prism2_ioctl_siwfrag(struct net_device *dev, static int prism2_ioctl_giwfrag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rts = &wrqu->rts; struct hostap_interface *iface; local_info_t *local; __le16 val; @@ -669,8 +680,9 @@ static int hostap_join_ap(struct net_device *dev) static int prism2_ioctl_siwap(struct net_device *dev, struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) + union iwreq_data *wrqu, char *extra) { + struct sockaddr *ap_addr = &wrqu->ap_addr; #ifdef PRISM2_NO_STATION_MODES return -EOPNOTSUPP; #else /* PRISM2_NO_STATION_MODES */ @@ -709,8 +721,9 @@ static int prism2_ioctl_siwap(struct net_device *dev, static int prism2_ioctl_giwap(struct net_device *dev, struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) + union iwreq_data *wrqu, char *extra) { + struct sockaddr *ap_addr = &wrqu->ap_addr; struct hostap_interface *iface; local_info_t *local; @@ -745,8 +758,9 @@ static int prism2_ioctl_giwap(struct net_device *dev, static int prism2_ioctl_siwnickn(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *nickname) + union iwreq_data *wrqu, char *nickname) { + struct iw_point *data = &wrqu->data; struct hostap_interface *iface; local_info_t *local; @@ -766,8 +780,9 @@ static int prism2_ioctl_siwnickn(struct net_device *dev, static int prism2_ioctl_giwnickn(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *nickname) + union iwreq_data *wrqu, char *nickname) { + struct iw_point *data = &wrqu->data; struct hostap_interface *iface; local_info_t *local; int len; @@ -793,8 +808,9 @@ static int prism2_ioctl_giwnickn(struct net_device *dev, static int prism2_ioctl_siwfreq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *freq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_freq *freq = &wrqu->freq; struct hostap_interface *iface; local_info_t *local; @@ -830,8 +846,9 @@ static int prism2_ioctl_siwfreq(struct net_device *dev, static int prism2_ioctl_giwfreq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *freq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_freq *freq = &wrqu->freq; struct hostap_interface *iface; local_info_t *local; u16 val; @@ -874,8 +891,9 @@ static void hostap_monitor_set_type(local_info_t *local) static int prism2_ioctl_siwessid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *ssid) + union iwreq_data *wrqu, char *ssid) { + struct iw_point *data = &wrqu->data; struct hostap_interface *iface; local_info_t *local; @@ -910,8 +928,9 @@ static int prism2_ioctl_siwessid(struct net_device *dev, static int prism2_ioctl_giwessid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *essid) + union iwreq_data *wrqu, char *essid) { + struct iw_point *data = &wrqu->data; struct hostap_interface *iface; local_info_t *local; u16 val; @@ -946,8 +965,9 @@ static int prism2_ioctl_giwessid(struct net_device *dev, static int prism2_ioctl_giwrange(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_point *data = &wrqu->data; struct hostap_interface *iface; local_info_t *local; struct iw_range *range = (struct iw_range *) extra; @@ -1121,8 +1141,9 @@ static int hostap_monitor_mode_disable(local_info_t *local) static int prism2_ioctl_siwmode(struct net_device *dev, struct iw_request_info *info, - __u32 *mode, char *extra) + union iwreq_data *wrqu, char *extra) { + __u32 *mode = &wrqu->mode; struct hostap_interface *iface; local_info_t *local; int double_reset = 0; @@ -1197,8 +1218,9 @@ static int prism2_ioctl_siwmode(struct net_device *dev, static int prism2_ioctl_giwmode(struct net_device *dev, struct iw_request_info *info, - __u32 *mode, char *extra) + union iwreq_data *wrqu, char *extra) { + __u32 *mode = &wrqu->mode; struct hostap_interface *iface; local_info_t *local; @@ -1222,8 +1244,9 @@ static int prism2_ioctl_giwmode(struct net_device *dev, static int prism2_ioctl_siwpower(struct net_device *dev, struct iw_request_info *info, - struct iw_param *wrq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *wrq = &wrqu->power; #ifdef PRISM2_NO_STATION_MODES return -EOPNOTSUPP; #else /* PRISM2_NO_STATION_MODES */ @@ -1281,8 +1304,9 @@ static int prism2_ioctl_siwpower(struct net_device *dev, static int prism2_ioctl_giwpower(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rrq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->power; #ifdef PRISM2_NO_STATION_MODES return -EOPNOTSUPP; #else /* PRISM2_NO_STATION_MODES */ @@ -1339,8 +1363,9 @@ static int prism2_ioctl_giwpower(struct net_device *dev, static int prism2_ioctl_siwretry(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rrq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->retry; struct hostap_interface *iface; local_info_t *local; @@ -1400,8 +1425,9 @@ static int prism2_ioctl_siwretry(struct net_device *dev, static int prism2_ioctl_giwretry(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rrq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->retry; struct hostap_interface *iface; local_info_t *local; __le16 shortretry, longretry, lifetime, altretry; @@ -1494,8 +1520,9 @@ static u16 prism2_txpower_dBm_to_hfa386x(int val) static int prism2_ioctl_siwtxpow(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rrq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->txpower; struct hostap_interface *iface; local_info_t *local; #ifdef RAW_TXPOWER_SETTING @@ -1575,9 +1602,10 @@ static int prism2_ioctl_siwtxpow(struct net_device *dev, static int prism2_ioctl_giwtxpow(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rrq, char *extra) + union iwreq_data *wrqu, char *extra) { #ifdef RAW_TXPOWER_SETTING + struct iw_param *rrq = &wrqu->txpower; struct hostap_interface *iface; local_info_t *local; u16 resp0; @@ -1710,8 +1738,9 @@ static inline int prism2_request_scan(struct net_device *dev) static int prism2_ioctl_siwscan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_point *data = &wrqu->data; struct hostap_interface *iface; local_info_t *local; int ret; @@ -2057,8 +2086,9 @@ static inline int prism2_ioctl_giwscan_sta(struct net_device *dev, static int prism2_ioctl_giwscan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_point *data = &wrqu->data; struct hostap_interface *iface; local_info_t *local; int res; @@ -2303,7 +2333,7 @@ static int prism2_ioctl_priv_inquire(struct net_device *dev, int *i) static int prism2_ioctl_priv_prism2_param(struct net_device *dev, struct iw_request_info *info, - void *wrqu, char *extra) + union iwreq_data *uwrq, char *extra) { struct hostap_interface *iface; local_info_t *local; @@ -2654,7 +2684,7 @@ static int prism2_ioctl_priv_prism2_param(struct net_device *dev, static int prism2_ioctl_priv_get_prism2_param(struct net_device *dev, struct iw_request_info *info, - void *wrqu, char *extra) + union iwreq_data *wrqu, char *extra) { struct hostap_interface *iface; local_info_t *local; @@ -2841,7 +2871,7 @@ static int prism2_ioctl_priv_get_prism2_param(struct net_device *dev, static int prism2_ioctl_priv_readmif(struct net_device *dev, struct iw_request_info *info, - void *wrqu, char *extra) + union iwreq_data *wrqu, char *extra) { struct hostap_interface *iface; local_info_t *local; @@ -2862,7 +2892,7 @@ static int prism2_ioctl_priv_readmif(struct net_device *dev, static int prism2_ioctl_priv_writemif(struct net_device *dev, struct iw_request_info *info, - void *wrqu, char *extra) + union iwreq_data *wrqu, char *extra) { struct hostap_interface *iface; local_info_t *local; @@ -2885,7 +2915,7 @@ static int prism2_ioctl_priv_monitor(struct net_device *dev, int *i) struct hostap_interface *iface; local_info_t *local; int ret = 0; - u32 mode; + union iwreq_data wrqu; iface = netdev_priv(dev); local = iface->local; @@ -2899,8 +2929,8 @@ static int prism2_ioctl_priv_monitor(struct net_device *dev, int *i) if (*i == 0) { /* Disable monitor mode - old mode was not saved, so go to * Master mode */ - mode = IW_MODE_MASTER; - ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL); + wrqu.mode = IW_MODE_MASTER; + ret = prism2_ioctl_siwmode(dev, NULL, &wrqu, NULL); } else if (*i == 1) { /* netlink socket mode is not supported anymore since it did * not separate different devices from each other and was not @@ -2916,8 +2946,8 @@ static int prism2_ioctl_priv_monitor(struct net_device *dev, int *i) local->monitor_type = PRISM2_MONITOR_PRISM; break; } - mode = IW_MODE_MONITOR; - ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL); + wrqu.mode = IW_MODE_MONITOR; + ret = prism2_ioctl_siwmode(dev, NULL, &wrqu, NULL); hostap_monitor_mode_enable(local); } else ret = -EINVAL; @@ -3079,8 +3109,9 @@ static int prism2_set_genericelement(struct net_device *dev, u8 *elem, static int prism2_ioctl_siwauth(struct net_device *dev, struct iw_request_info *info, - struct iw_param *data, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *data = &wrqu->param; struct hostap_interface *iface = netdev_priv(dev); local_info_t *local = iface->local; @@ -3145,8 +3176,9 @@ static int prism2_ioctl_siwauth(struct net_device *dev, static int prism2_ioctl_giwauth(struct net_device *dev, struct iw_request_info *info, - struct iw_param *data, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *data = &wrqu->param; struct hostap_interface *iface = netdev_priv(dev); local_info_t *local = iface->local; @@ -3184,8 +3216,9 @@ static int prism2_ioctl_giwauth(struct net_device *dev, static int prism2_ioctl_siwencodeext(struct net_device *dev, struct iw_request_info *info, - struct iw_point *erq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_point *erq = &wrqu->encoding; struct hostap_interface *iface = netdev_priv(dev); local_info_t *local = iface->local; struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; @@ -3358,8 +3391,9 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, static int prism2_ioctl_giwencodeext(struct net_device *dev, struct iw_request_info *info, - struct iw_point *erq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_point *erq = &wrqu->encoding; struct hostap_interface *iface = netdev_priv(dev); local_info_t *local = iface->local; struct lib80211_crypt_data **crypt; @@ -3666,16 +3700,18 @@ static int prism2_ioctl_set_assoc_ap_addr(local_info_t *local, static int prism2_ioctl_siwgenie(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_point *data = &wrqu->data; return prism2_set_genericelement(dev, extra, data->length); } static int prism2_ioctl_giwgenie(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_point *data = &wrqu->data; struct hostap_interface *iface = netdev_priv(dev); local_info_t *local = iface->local; int len = local->generic_elem_len - 2; @@ -3713,7 +3749,7 @@ static int prism2_ioctl_set_generic_element(local_info_t *local, static int prism2_ioctl_siwmlme(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { struct hostap_interface *iface = netdev_priv(dev); local_info_t *local = iface->local; @@ -3864,70 +3900,56 @@ const struct ethtool_ops prism2_ethtool_ops = { static const iw_handler prism2_handler[] = { - (iw_handler) NULL, /* SIOCSIWCOMMIT */ - (iw_handler) prism2_get_name, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) prism2_ioctl_siwfreq, /* SIOCSIWFREQ */ - (iw_handler) prism2_ioctl_giwfreq, /* SIOCGIWFREQ */ - (iw_handler) prism2_ioctl_siwmode, /* SIOCSIWMODE */ - (iw_handler) prism2_ioctl_giwmode, /* SIOCGIWMODE */ - (iw_handler) prism2_ioctl_siwsens, /* SIOCSIWSENS */ - (iw_handler) prism2_ioctl_giwsens, /* SIOCGIWSENS */ - (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ - (iw_handler) prism2_ioctl_giwrange, /* SIOCGIWRANGE */ - (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ - (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */ - iw_handler_set_spy, /* SIOCSIWSPY */ - iw_handler_get_spy, /* SIOCGIWSPY */ - iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ - iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ - (iw_handler) prism2_ioctl_siwap, /* SIOCSIWAP */ - (iw_handler) prism2_ioctl_giwap, /* SIOCGIWAP */ - (iw_handler) prism2_ioctl_siwmlme, /* SIOCSIWMLME */ - (iw_handler) prism2_ioctl_giwaplist, /* SIOCGIWAPLIST */ - (iw_handler) prism2_ioctl_siwscan, /* SIOCSIWSCAN */ - (iw_handler) prism2_ioctl_giwscan, /* SIOCGIWSCAN */ - (iw_handler) prism2_ioctl_siwessid, /* SIOCSIWESSID */ - (iw_handler) prism2_ioctl_giwessid, /* SIOCGIWESSID */ - (iw_handler) prism2_ioctl_siwnickn, /* SIOCSIWNICKN */ - (iw_handler) prism2_ioctl_giwnickn, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) prism2_ioctl_siwrate, /* SIOCSIWRATE */ - (iw_handler) prism2_ioctl_giwrate, /* SIOCGIWRATE */ - (iw_handler) prism2_ioctl_siwrts, /* SIOCSIWRTS */ - (iw_handler) prism2_ioctl_giwrts, /* SIOCGIWRTS */ - (iw_handler) prism2_ioctl_siwfrag, /* SIOCSIWFRAG */ - (iw_handler) prism2_ioctl_giwfrag, /* SIOCGIWFRAG */ - (iw_handler) prism2_ioctl_siwtxpow, /* SIOCSIWTXPOW */ - (iw_handler) prism2_ioctl_giwtxpow, /* SIOCGIWTXPOW */ - (iw_handler) prism2_ioctl_siwretry, /* SIOCSIWRETRY */ - (iw_handler) prism2_ioctl_giwretry, /* SIOCGIWRETRY */ - (iw_handler) prism2_ioctl_siwencode, /* SIOCSIWENCODE */ - (iw_handler) prism2_ioctl_giwencode, /* SIOCGIWENCODE */ - (iw_handler) prism2_ioctl_siwpower, /* SIOCSIWPOWER */ - (iw_handler) prism2_ioctl_giwpower, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) prism2_ioctl_siwgenie, /* SIOCSIWGENIE */ - (iw_handler) prism2_ioctl_giwgenie, /* SIOCGIWGENIE */ - (iw_handler) prism2_ioctl_siwauth, /* SIOCSIWAUTH */ - (iw_handler) prism2_ioctl_giwauth, /* SIOCGIWAUTH */ - (iw_handler) prism2_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ - (iw_handler) prism2_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */ - (iw_handler) NULL, /* SIOCSIWPMKSA */ - (iw_handler) NULL, /* -- hole -- */ + IW_HANDLER(SIOCGIWNAME, prism2_get_name), + IW_HANDLER(SIOCSIWFREQ, prism2_ioctl_siwfreq), + IW_HANDLER(SIOCGIWFREQ, prism2_ioctl_giwfreq), + IW_HANDLER(SIOCSIWMODE, prism2_ioctl_siwmode), + IW_HANDLER(SIOCGIWMODE, prism2_ioctl_giwmode), + IW_HANDLER(SIOCSIWSENS, prism2_ioctl_siwsens), + IW_HANDLER(SIOCGIWSENS, prism2_ioctl_giwsens), + IW_HANDLER(SIOCGIWRANGE, prism2_ioctl_giwrange), + IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), + IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), + IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), + IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), + IW_HANDLER(SIOCSIWAP, prism2_ioctl_siwap), + IW_HANDLER(SIOCGIWAP, prism2_ioctl_giwap), + IW_HANDLER(SIOCSIWMLME, prism2_ioctl_siwmlme), + IW_HANDLER(SIOCGIWAPLIST, prism2_ioctl_giwaplist), + IW_HANDLER(SIOCSIWSCAN, prism2_ioctl_siwscan), + IW_HANDLER(SIOCGIWSCAN, prism2_ioctl_giwscan), + IW_HANDLER(SIOCSIWESSID, prism2_ioctl_siwessid), + IW_HANDLER(SIOCGIWESSID, prism2_ioctl_giwessid), + IW_HANDLER(SIOCSIWNICKN, prism2_ioctl_siwnickn), + IW_HANDLER(SIOCGIWNICKN, prism2_ioctl_giwnickn), + IW_HANDLER(SIOCSIWRATE, prism2_ioctl_siwrate), + IW_HANDLER(SIOCGIWRATE, prism2_ioctl_giwrate), + IW_HANDLER(SIOCSIWRTS, prism2_ioctl_siwrts), + IW_HANDLER(SIOCGIWRTS, prism2_ioctl_giwrts), + IW_HANDLER(SIOCSIWFRAG, prism2_ioctl_siwfrag), + IW_HANDLER(SIOCGIWFRAG, prism2_ioctl_giwfrag), + IW_HANDLER(SIOCSIWTXPOW, prism2_ioctl_siwtxpow), + IW_HANDLER(SIOCGIWTXPOW, prism2_ioctl_giwtxpow), + IW_HANDLER(SIOCSIWRETRY, prism2_ioctl_siwretry), + IW_HANDLER(SIOCGIWRETRY, prism2_ioctl_giwretry), + IW_HANDLER(SIOCSIWENCODE, prism2_ioctl_siwencode), + IW_HANDLER(SIOCGIWENCODE, prism2_ioctl_giwencode), + IW_HANDLER(SIOCSIWPOWER, prism2_ioctl_siwpower), + IW_HANDLER(SIOCGIWPOWER, prism2_ioctl_giwpower), + IW_HANDLER(SIOCSIWGENIE, prism2_ioctl_siwgenie), + IW_HANDLER(SIOCGIWGENIE, prism2_ioctl_giwgenie), + IW_HANDLER(SIOCSIWAUTH, prism2_ioctl_siwauth), + IW_HANDLER(SIOCGIWAUTH, prism2_ioctl_giwauth), + IW_HANDLER(SIOCSIWENCODEEXT, prism2_ioctl_siwencodeext), + IW_HANDLER(SIOCGIWENCODEEXT, prism2_ioctl_giwencodeext), }; static const iw_handler prism2_private_handler[] = -{ /* SIOCIWFIRSTPRIV + */ - (iw_handler) prism2_ioctl_priv_prism2_param, /* 0 */ - (iw_handler) prism2_ioctl_priv_get_prism2_param, /* 1 */ - (iw_handler) prism2_ioctl_priv_writemif, /* 2 */ - (iw_handler) prism2_ioctl_priv_readmif, /* 3 */ +{ /* SIOCIWFIRSTPRIV + */ + prism2_ioctl_priv_prism2_param, /* 0 */ + prism2_ioctl_priv_get_prism2_param, /* 1 */ + prism2_ioctl_priv_writemif, /* 2 */ + prism2_ioctl_priv_readmif, /* 3 */ }; const struct iw_handler_def hostap_iw_handler_def = @@ -3935,8 +3957,8 @@ const struct iw_handler_def hostap_iw_handler_def = .num_standard = ARRAY_SIZE(prism2_handler), .num_private = ARRAY_SIZE(prism2_private_handler), .num_private_args = ARRAY_SIZE(prism2_priv), - .standard = (iw_handler *) prism2_handler, - .private = (iw_handler *) prism2_private_handler, + .standard = prism2_handler, + .private = prism2_private_handler, .private_args = (struct iw_priv_args *) prism2_priv, .get_wireless_stats = hostap_get_wireless_stats, }; diff --git a/drivers/net/wireless/intersil/orinoco/wext.c b/drivers/net/wireless/intersil/orinoco/wext.c index 4a01260027bc..dea1ff044342 100644 --- a/drivers/net/wireless/intersil/orinoco/wext.c +++ b/drivers/net/wireless/intersil/orinoco/wext.c @@ -154,9 +154,10 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) static int orinoco_ioctl_setwap(struct net_device *dev, struct iw_request_info *info, - struct sockaddr *ap_addr, + union iwreq_data *wrqu, char *extra) { + struct sockaddr *ap_addr = &wrqu->ap_addr; struct orinoco_private *priv = ndev_priv(dev); int err = -EINPROGRESS; /* Call commit handler */ unsigned long flags; @@ -213,9 +214,10 @@ static int orinoco_ioctl_setwap(struct net_device *dev, static int orinoco_ioctl_getwap(struct net_device *dev, struct iw_request_info *info, - struct sockaddr *ap_addr, + union iwreq_data *wrqu, char *extra) { + struct sockaddr *ap_addr = &wrqu->ap_addr; struct orinoco_private *priv = ndev_priv(dev); int err = 0; @@ -234,9 +236,10 @@ static int orinoco_ioctl_getwap(struct net_device *dev, static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_request_info *info, - struct iw_point *erq, + union iwreq_data *wrqu, char *keybuf) { + struct iw_point *erq = &wrqu->encoding; struct orinoco_private *priv = ndev_priv(dev); int index = (erq->flags & IW_ENCODE_INDEX) - 1; int setindex = priv->tx_key; @@ -325,9 +328,10 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_request_info *info, - struct iw_point *erq, + union iwreq_data *wrqu, char *keybuf) { + struct iw_point *erq = &wrqu->encoding; struct orinoco_private *priv = ndev_priv(dev); int index = (erq->flags & IW_ENCODE_INDEX) - 1; unsigned long flags; @@ -361,9 +365,10 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *erq, + union iwreq_data *wrqu, char *essidbuf) { + struct iw_point *erq = &wrqu->essid; struct orinoco_private *priv = ndev_priv(dev); unsigned long flags; @@ -392,9 +397,10 @@ static int orinoco_ioctl_setessid(struct net_device *dev, static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *erq, + union iwreq_data *wrqu, char *essidbuf) { + struct iw_point *erq = &wrqu->essid; struct orinoco_private *priv = ndev_priv(dev); int active; int err = 0; @@ -420,9 +426,10 @@ static int orinoco_ioctl_getessid(struct net_device *dev, static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *frq, + union iwreq_data *wrqu, char *extra) { + struct iw_freq *frq = &wrqu->freq; struct orinoco_private *priv = ndev_priv(dev); int chan = -1; unsigned long flags; @@ -469,9 +476,10 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, static int orinoco_ioctl_getfreq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *frq, + union iwreq_data *wrqu, char *extra) { + struct iw_freq *frq = &wrqu->freq; struct orinoco_private *priv = ndev_priv(dev); int tmp; @@ -488,9 +496,10 @@ static int orinoco_ioctl_getfreq(struct net_device *dev, static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_request_info *info, - struct iw_param *srq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *srq = &wrqu->sens; struct orinoco_private *priv = ndev_priv(dev); struct hermes *hw = &priv->hw; u16 val; @@ -517,9 +526,10 @@ static int orinoco_ioctl_getsens(struct net_device *dev, static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_request_info *info, - struct iw_param *srq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *srq = &wrqu->sens; struct orinoco_private *priv = ndev_priv(dev); int val = srq->value; unsigned long flags; @@ -540,9 +550,10 @@ static int orinoco_ioctl_setsens(struct net_device *dev, static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->bitrate; struct orinoco_private *priv = ndev_priv(dev); int ratemode; int bitrate; /* 100s of kilobits */ @@ -574,9 +585,10 @@ static int orinoco_ioctl_setrate(struct net_device *dev, static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rrq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->bitrate; struct orinoco_private *priv = ndev_priv(dev); int err = 0; int bitrate, automatic; @@ -610,9 +622,10 @@ static int orinoco_ioctl_getrate(struct net_device *dev, static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_request_info *info, - struct iw_param *prq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *prq = &wrqu->power; struct orinoco_private *priv = ndev_priv(dev); int err = -EINPROGRESS; /* Call commit handler */ unsigned long flags; @@ -664,9 +677,10 @@ static int orinoco_ioctl_setpower(struct net_device *dev, static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_request_info *info, - struct iw_param *prq, + union iwreq_data *wrqu, char *extra) { + struct iw_param *prq = &wrqu->power; struct orinoco_private *priv = ndev_priv(dev); struct hermes *hw = &priv->hw; int err = 0; @@ -1097,7 +1111,7 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev, static int orinoco_ioctl_reset(struct net_device *dev, struct iw_request_info *info, - void *wrqu, + union iwreq_data *wrqu, char *extra) { struct orinoco_private *priv = ndev_priv(dev); @@ -1121,7 +1135,7 @@ static int orinoco_ioctl_reset(struct net_device *dev, static int orinoco_ioctl_setibssport(struct net_device *dev, struct iw_request_info *info, - void *wrqu, + union iwreq_data *wrqu, char *extra) { @@ -1143,7 +1157,7 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, static int orinoco_ioctl_getibssport(struct net_device *dev, struct iw_request_info *info, - void *wrqu, + union iwreq_data *wrqu, char *extra) { struct orinoco_private *priv = ndev_priv(dev); @@ -1155,7 +1169,7 @@ static int orinoco_ioctl_getibssport(struct net_device *dev, static int orinoco_ioctl_setport3(struct net_device *dev, struct iw_request_info *info, - void *wrqu, + union iwreq_data *wrqu, char *extra) { struct orinoco_private *priv = ndev_priv(dev); @@ -1201,7 +1215,7 @@ static int orinoco_ioctl_setport3(struct net_device *dev, static int orinoco_ioctl_getport3(struct net_device *dev, struct iw_request_info *info, - void *wrqu, + union iwreq_data *wrqu, char *extra) { struct orinoco_private *priv = ndev_priv(dev); @@ -1213,7 +1227,7 @@ static int orinoco_ioctl_getport3(struct net_device *dev, static int orinoco_ioctl_setpreamble(struct net_device *dev, struct iw_request_info *info, - void *wrqu, + union iwreq_data *wrqu, char *extra) { struct orinoco_private *priv = ndev_priv(dev); @@ -1245,7 +1259,7 @@ static int orinoco_ioctl_setpreamble(struct net_device *dev, static int orinoco_ioctl_getpreamble(struct net_device *dev, struct iw_request_info *info, - void *wrqu, + union iwreq_data *wrqu, char *extra) { struct orinoco_private *priv = ndev_priv(dev); @@ -1265,9 +1279,10 @@ static int orinoco_ioctl_getpreamble(struct net_device *dev, * For Wireless Tools 25 and 26 append "dummy" are the end. */ static int orinoco_ioctl_getrid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, + union iwreq_data *wrqu, char *extra) { + struct iw_point *data = &wrqu->data; struct orinoco_private *priv = ndev_priv(dev); struct hermes *hw = &priv->hw; int rid = data->flags; @@ -1303,7 +1318,7 @@ static int orinoco_ioctl_getrid(struct net_device *dev, /* Commit handler, called after set operations */ static int orinoco_ioctl_commit(struct net_device *dev, struct iw_request_info *info, - void *wrqu, + union iwreq_data *wrqu, char *extra) { struct orinoco_private *priv = ndev_priv(dev); @@ -1347,36 +1362,36 @@ static const struct iw_priv_args orinoco_privtab[] = { */ static const iw_handler orinoco_handler[] = { - IW_HANDLER(SIOCSIWCOMMIT, (iw_handler)orinoco_ioctl_commit), - IW_HANDLER(SIOCGIWNAME, (iw_handler)cfg80211_wext_giwname), - IW_HANDLER(SIOCSIWFREQ, (iw_handler)orinoco_ioctl_setfreq), - IW_HANDLER(SIOCGIWFREQ, (iw_handler)orinoco_ioctl_getfreq), - IW_HANDLER(SIOCSIWMODE, (iw_handler)cfg80211_wext_siwmode), - IW_HANDLER(SIOCGIWMODE, (iw_handler)cfg80211_wext_giwmode), - IW_HANDLER(SIOCSIWSENS, (iw_handler)orinoco_ioctl_setsens), - IW_HANDLER(SIOCGIWSENS, (iw_handler)orinoco_ioctl_getsens), - IW_HANDLER(SIOCGIWRANGE, (iw_handler)cfg80211_wext_giwrange), + IW_HANDLER(SIOCSIWCOMMIT, orinoco_ioctl_commit), + IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname), + IW_HANDLER(SIOCSIWFREQ, orinoco_ioctl_setfreq), + IW_HANDLER(SIOCGIWFREQ, orinoco_ioctl_getfreq), + IW_HANDLER(SIOCSIWMODE, cfg80211_wext_siwmode), + IW_HANDLER(SIOCGIWMODE, cfg80211_wext_giwmode), + IW_HANDLER(SIOCSIWSENS, orinoco_ioctl_setsens), + IW_HANDLER(SIOCGIWSENS, orinoco_ioctl_getsens), + IW_HANDLER(SIOCGIWRANGE, cfg80211_wext_giwrange), IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), - IW_HANDLER(SIOCSIWAP, (iw_handler)orinoco_ioctl_setwap), - IW_HANDLER(SIOCGIWAP, (iw_handler)orinoco_ioctl_getwap), - IW_HANDLER(SIOCSIWSCAN, (iw_handler)cfg80211_wext_siwscan), - IW_HANDLER(SIOCGIWSCAN, (iw_handler)cfg80211_wext_giwscan), - IW_HANDLER(SIOCSIWESSID, (iw_handler)orinoco_ioctl_setessid), - IW_HANDLER(SIOCGIWESSID, (iw_handler)orinoco_ioctl_getessid), - IW_HANDLER(SIOCSIWRATE, (iw_handler)orinoco_ioctl_setrate), - IW_HANDLER(SIOCGIWRATE, (iw_handler)orinoco_ioctl_getrate), - IW_HANDLER(SIOCSIWRTS, (iw_handler)cfg80211_wext_siwrts), - IW_HANDLER(SIOCGIWRTS, (iw_handler)cfg80211_wext_giwrts), - IW_HANDLER(SIOCSIWFRAG, (iw_handler)cfg80211_wext_siwfrag), - IW_HANDLER(SIOCGIWFRAG, (iw_handler)cfg80211_wext_giwfrag), - IW_HANDLER(SIOCGIWRETRY, (iw_handler)cfg80211_wext_giwretry), - IW_HANDLER(SIOCSIWENCODE, (iw_handler)orinoco_ioctl_setiwencode), - IW_HANDLER(SIOCGIWENCODE, (iw_handler)orinoco_ioctl_getiwencode), - IW_HANDLER(SIOCSIWPOWER, (iw_handler)orinoco_ioctl_setpower), - IW_HANDLER(SIOCGIWPOWER, (iw_handler)orinoco_ioctl_getpower), + IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap), + IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap), + IW_HANDLER(SIOCSIWSCAN, cfg80211_wext_siwscan), + IW_HANDLER(SIOCGIWSCAN, cfg80211_wext_giwscan), + IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid), + IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid), + IW_HANDLER(SIOCSIWRATE, orinoco_ioctl_setrate), + IW_HANDLER(SIOCGIWRATE, orinoco_ioctl_getrate), + IW_HANDLER(SIOCSIWRTS, cfg80211_wext_siwrts), + IW_HANDLER(SIOCGIWRTS, cfg80211_wext_giwrts), + IW_HANDLER(SIOCSIWFRAG, cfg80211_wext_siwfrag), + IW_HANDLER(SIOCGIWFRAG, cfg80211_wext_giwfrag), + IW_HANDLER(SIOCGIWRETRY, cfg80211_wext_giwretry), + IW_HANDLER(SIOCSIWENCODE, orinoco_ioctl_setiwencode), + IW_HANDLER(SIOCGIWENCODE, orinoco_ioctl_getiwencode), + IW_HANDLER(SIOCSIWPOWER, orinoco_ioctl_setpower), + IW_HANDLER(SIOCGIWPOWER, orinoco_ioctl_getpower), IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie), IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie), IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme), @@ -1391,15 +1406,15 @@ static const iw_handler orinoco_handler[] = { Added typecasting since we no longer use iwreq_data -- Moustafa */ static const iw_handler orinoco_private_handler[] = { - [0] = (iw_handler)orinoco_ioctl_reset, - [1] = (iw_handler)orinoco_ioctl_reset, - [2] = (iw_handler)orinoco_ioctl_setport3, - [3] = (iw_handler)orinoco_ioctl_getport3, - [4] = (iw_handler)orinoco_ioctl_setpreamble, - [5] = (iw_handler)orinoco_ioctl_getpreamble, - [6] = (iw_handler)orinoco_ioctl_setibssport, - [7] = (iw_handler)orinoco_ioctl_getibssport, - [9] = (iw_handler)orinoco_ioctl_getrid, + [0] = orinoco_ioctl_reset, + [1] = orinoco_ioctl_reset, + [2] = orinoco_ioctl_setport3, + [3] = orinoco_ioctl_getport3, + [4] = orinoco_ioctl_setpreamble, + [5] = orinoco_ioctl_getpreamble, + [6] = orinoco_ioctl_setibssport, + [7] = orinoco_ioctl_getibssport, + [9] = orinoco_ioctl_getrid, }; const struct iw_handler_def orinoco_handler_def = { diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c index bda53cb91f37..52b18f4a774b 100644 --- a/drivers/net/wireless/marvell/mwifiex/debugfs.c +++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c @@ -874,7 +874,7 @@ mwifiex_timeshare_coex_write(struct file *file, const char __user *ubuf, if (copy_from_user(&kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, count))) return -EFAULT; - if (strtobool(kbuf, ×hare_coex)) + if (kstrtobool(kbuf, ×hare_coex)) return -EINVAL; ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX, diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 63f861e6b28a..b95886e1413e 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -10,6 +10,7 @@ #include <linux/completion.h> #include <linux/kernel.h> +#include <linux/kstrtox.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/semaphore.h> diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c index 7390f94cd4ca..a05bda7b9a3b 100644 --- a/drivers/net/wireless/microchip/wilc1000/sdio.c +++ b/drivers/net/wireless/microchip/wilc1000/sdio.c @@ -20,6 +20,7 @@ static const struct sdio_device_id wilc_sdio_ids[] = { { SDIO_DEVICE(SDIO_VENDOR_ID_MICROCHIP_WILC, SDIO_DEVICE_ID_MICROCHIP_WILC1000) }, { }, }; +MODULE_DEVICE_TABLE(sdio, wilc_sdio_ids); #define WILC_SDIO_BLOCK_SIZE 512 diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index ad3f32f4c6e7..136992f0200c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -570,7 +570,7 @@ struct rtl8723au_phy_stats { u8 cck_rpt_b_ofdm_cfosho_b; u8 reserved_1; u8 noise_power_db_msb; - u8 path_cfotail[RTL8723A_MAX_RF_PATHS]; + s8 path_cfotail[RTL8723A_MAX_RF_PATHS]; u8 pcts_mask[RTL8723A_MAX_RF_PATHS]; s8 stream_rxevm[RTL8723A_MAX_RF_PATHS]; u8 path_rxsnr[RTL8723A_MAX_RF_PATHS]; @@ -1323,6 +1323,19 @@ struct rtl8xxxu_ra_report { u8 desc_rate; }; +#define CFO_TH_XTAL_HIGH 20 /* kHz */ +#define CFO_TH_XTAL_LOW 10 /* kHz */ +#define CFO_TH_ATC 80 /* kHz */ + +struct rtl8xxxu_cfo_tracking { + bool adjust; + bool atc_status; + int cfo_tail[2]; + u8 crystal_cap; + u32 packet_count; + u32 packet_count_pre; +}; + struct rtl8xxxu_priv { struct ieee80211_hw *hw; struct usb_device *udev; @@ -1381,9 +1394,9 @@ struct rtl8xxxu_priv { u32 ep_tx_high_queue:1; u32 ep_tx_normal_queue:1; u32 ep_tx_low_queue:1; - u32 has_xtalk:1; u32 rx_buf_aggregation:1; - u8 xtalk; + u32 cck_agc_report_type:1; + u8 default_crystal_cap; unsigned int pipe_interrupt; unsigned int pipe_in; unsigned int pipe_out[TXDESC_QUEUE_MAX]; @@ -1441,6 +1454,7 @@ struct rtl8xxxu_priv { struct sk_buff_head c2hcmd_queue; struct rtl8xxxu_btcoex bt_coex; struct rtl8xxxu_ra_report ra_report; + struct rtl8xxxu_cfo_tracking cfo_tracking; }; struct rtl8xxxu_rx_urb { @@ -1456,6 +1470,7 @@ struct rtl8xxxu_tx_urb { }; struct rtl8xxxu_fileops { + int (*identify_chip) (struct rtl8xxxu_priv *priv); int (*parse_efuse) (struct rtl8xxxu_priv *priv); int (*load_firmware) (struct rtl8xxxu_priv *priv); int (*power_on) (struct rtl8xxxu_priv *priv); @@ -1471,6 +1486,7 @@ struct rtl8xxxu_fileops { int (*parse_rx_desc) (struct rtl8xxxu_priv *priv, struct sk_buff *skb); void (*init_aggregation) (struct rtl8xxxu_priv *priv); void (*init_statistics) (struct rtl8xxxu_priv *priv); + void (*init_burst) (struct rtl8xxxu_priv *priv); void (*enable_rf) (struct rtl8xxxu_priv *priv); void (*disable_rf) (struct rtl8xxxu_priv *priv); void (*usb_quirks) (struct rtl8xxxu_priv *priv); @@ -1485,6 +1501,8 @@ struct rtl8xxxu_fileops { struct rtl8xxxu_txdesc32 *tx_desc, bool sgi, bool short_preamble, bool ampdu_enable, u32 rts_rate); + void (*set_crystal_cap) (struct rtl8xxxu_priv *priv, u8 crystal_cap); + s8 (*cck_rssi) (struct rtl8xxxu_priv *priv, u8 cck_agc_rpt); int writeN_block_size; int rx_agg_buf_size; char tx_desc_size; @@ -1545,6 +1563,10 @@ int rtl8xxxu_init_phy_regs(struct rtl8xxxu_priv *priv, int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, char *fw_name); void rtl8xxxu_firmware_self_reset(struct rtl8xxxu_priv *priv); void rtl8xxxu_power_off(struct rtl8xxxu_priv *priv); +void rtl8xxxu_identify_vendor_1bit(struct rtl8xxxu_priv *priv, u32 vendor); +void rtl8xxxu_identify_vendor_2bits(struct rtl8xxxu_priv *priv, u32 vendor); +void rtl8xxxu_config_endpoints_sie(struct rtl8xxxu_priv *priv); +int rtl8xxxu_config_endpoints_no_sie(struct rtl8xxxu_priv *priv); int rtl8xxxu_read_efuse8(struct rtl8xxxu_priv *priv, u16 offset, u8 *data); void rtl8xxxu_reset_8051(struct rtl8xxxu_priv *priv); int rtl8xxxu_auto_llt_table(struct rtl8xxxu_priv *priv); @@ -1576,6 +1598,7 @@ void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv); void rtl8xxxu_gen1_enable_rf(struct rtl8xxxu_priv *priv); void rtl8xxxu_gen1_disable_rf(struct rtl8xxxu_priv *priv); void rtl8xxxu_gen2_disable_rf(struct rtl8xxxu_priv *priv); +void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv); int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb); int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb); int rtl8xxxu_gen2_channel_to_group(int channel); @@ -1594,6 +1617,8 @@ void rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv, u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5); void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv); +void rtl8723a_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap); +s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt); extern struct rtl8xxxu_fileops rtl8188fu_fops; extern struct rtl8xxxu_fileops rtl8192cu_fops; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c index 0025bb32538d..2c4f403ba68f 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c @@ -321,7 +321,37 @@ static const struct rtl8xxxu_rfregval rtl8188fu_cut_b_radioa_init_table[] = { {0xff, 0xffffffff} }; -static void rtl8xxxu_8188f_channel_to_group(int channel, int *group, int *cck_group) +static int rtl8188fu_identify_chip(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + u32 sys_cfg, vendor; + int ret = 0; + + strscpy(priv->chip_name, "8188FU", sizeof(priv->chip_name)); + priv->rtl_chip = RTL8188F; + priv->rf_paths = 1; + priv->rx_paths = 1; + priv->tx_paths = 1; + priv->has_wifi = 1; + + sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG); + priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK); + if (sys_cfg & SYS_CFG_TRP_VAUX_EN) { + dev_info(dev, "Unsupported test chip\n"); + ret = -ENOTSUPP; + goto out; + } + + vendor = sys_cfg & SYS_CFG_VENDOR_EXT_MASK; + rtl8xxxu_identify_vendor_2bits(priv, vendor); + + ret = rtl8xxxu_config_endpoints_no_sie(priv); + +out: + return ret; +} + +static void rtl8188f_channel_to_group(int channel, int *group, int *cck_group) { if (channel < 3) *group = 0; @@ -347,7 +377,7 @@ rtl8188f_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) u8 cck, ofdmbase, mcsbase; int group, cck_group; - rtl8xxxu_8188f_channel_to_group(channel, &group, &cck_group); + rtl8188f_channel_to_group(channel, &group, &cck_group); cck = priv->cck_tx_power_index_A[cck_group]; @@ -703,7 +733,7 @@ static int rtl8188fu_parse_efuse(struct rtl8xxxu_priv *priv) priv->ofdm_tx_power_diff[0].a = efuse->tx_power_index_A.ht20_ofdm_1s_diff.a; priv->ht20_tx_power_diff[0].a = efuse->tx_power_index_A.ht20_ofdm_1s_diff.b; - priv->xtalk = efuse->xtal_k & 0x3f; + priv->default_crystal_cap = efuse->xtal_k & 0x3f; dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name); dev_info(&priv->udev->dev, "Product: %.7s\n", efuse->device_name); @@ -737,7 +767,6 @@ static void rtl8188fu_init_phy_bb(struct rtl8xxxu_priv *priv) { u8 val8; u16 val16; - u32 val32; /* Enable BB and RF */ val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); @@ -759,12 +788,6 @@ static void rtl8188fu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_init_phy_regs(priv, rtl8188fu_phy_init_table); rtl8xxxu_init_phy_regs(priv, rtl8188f_agc_table); - - val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); - val8 = priv->xtalk; - val32 &= ~0x007FF800; - val32 |= ((val8 | (val8 << 6)) << 11); - rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32); } static int rtl8188fu_init_phy_rf(struct rtl8xxxu_priv *priv) @@ -1636,7 +1659,68 @@ static void rtl8188f_usb_quirks(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val32); } +#define XTAL1 GENMASK(22, 17) +#define XTAL0 GENMASK(16, 11) + +static void rtl8188f_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap) +{ + struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking; + u32 val32; + + if (crystal_cap == cfo->crystal_cap) + return; + + val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); + + dev_dbg(&priv->udev->dev, + "%s: Adjusting crystal cap from 0x%x (actually 0x%lx 0x%lx) to 0x%x\n", + __func__, + cfo->crystal_cap, + FIELD_GET(XTAL1, val32), + FIELD_GET(XTAL0, val32), + crystal_cap); + + val32 &= ~(XTAL1 | XTAL0); + val32 |= FIELD_PREP(XTAL1, crystal_cap) | + FIELD_PREP(XTAL0, crystal_cap); + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32); + + cfo->crystal_cap = crystal_cap; +} + +static s8 rtl8188f_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt) +{ + s8 rx_pwr_all = 0x00; + u8 vga_idx, lna_idx; + + lna_idx = (cck_agc_rpt & 0xE0) >> 5; + vga_idx = cck_agc_rpt & 0x1F; + + switch (lna_idx) { + case 7: + if (vga_idx <= 27) + rx_pwr_all = -100 + 2 * (27 - vga_idx); + else + rx_pwr_all = -100; + break; + case 5: + rx_pwr_all = -74 + 2 * (21 - vga_idx); + break; + case 3: + rx_pwr_all = -60 + 2 * (20 - vga_idx); + break; + case 1: + rx_pwr_all = -44 + 2 * (19 - vga_idx); + break; + default: + break; + } + + return rx_pwr_all; +} + struct rtl8xxxu_fileops rtl8188fu_fops = { + .identify_chip = rtl8188fu_identify_chip, .parse_efuse = rtl8188fu_parse_efuse, .load_firmware = rtl8188fu_load_firmware, .power_on = rtl8188fu_power_on, @@ -1652,6 +1736,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops = { .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .init_aggregation = rtl8188fu_init_aggregation, .init_statistics = rtl8188fu_init_statistics, + .init_burst = rtl8xxxu_init_burst, .enable_rf = rtl8188f_enable_rf, .disable_rf = rtl8188f_disable_rf, .usb_quirks = rtl8188f_usb_quirks, @@ -1659,6 +1744,8 @@ struct rtl8xxxu_fileops rtl8188fu_fops = { .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, .report_connect = rtl8xxxu_gen2_report_connect, .fill_txdesc = rtl8xxxu_fill_txdesc_v2, + .set_crystal_cap = rtl8188f_set_crystal_cap, + .cck_rssi = rtl8188f_cck_rssi, .writeN_block_size = 128, .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24), .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40), diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c index e9bc94edfa79..3bef9ffc8b02 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c @@ -326,6 +326,64 @@ static const struct rtl8xxxu_rfregval rtl8188ru_radioa_1t_highpa_table[] = { {0xff, 0xffffffff} }; +static int rtl8192cu_identify_chip(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + u32 val32, bonding, sys_cfg, vendor; + int ret = 0; + + sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG); + priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK); + if (sys_cfg & SYS_CFG_TRP_VAUX_EN) { + dev_info(dev, "Unsupported test chip\n"); + ret = -ENOTSUPP; + goto out; + } + + if (sys_cfg & SYS_CFG_TYPE_ID) { + bonding = rtl8xxxu_read32(priv, REG_HPON_FSM); + bonding &= HPON_FSM_BONDING_MASK; + if (bonding == HPON_FSM_BONDING_1T2R) { + strscpy(priv->chip_name, "8191CU", sizeof(priv->chip_name)); + priv->tx_paths = 1; + priv->usb_interrupts = 1; + priv->rtl_chip = RTL8191C; + } else { + strscpy(priv->chip_name, "8192CU", sizeof(priv->chip_name)); + priv->tx_paths = 2; + priv->usb_interrupts = 0; + priv->rtl_chip = RTL8192C; + } + priv->rf_paths = 2; + priv->rx_paths = 2; + } else { + strscpy(priv->chip_name, "8188CU", sizeof(priv->chip_name)); + priv->rf_paths = 1; + priv->rx_paths = 1; + priv->tx_paths = 1; + priv->rtl_chip = RTL8188C; + priv->usb_interrupts = 0; + } + priv->has_wifi = 1; + + vendor = sys_cfg & SYS_CFG_VENDOR_ID; + rtl8xxxu_identify_vendor_1bit(priv, vendor); + + val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS); + priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID); + + rtl8xxxu_config_endpoints_sie(priv); + + /* + * Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX + */ + if (!priv->ep_tx_count) + ret = rtl8xxxu_config_endpoints_no_sie(priv); + +out: + return ret; +} + static int rtl8192cu_load_firmware(struct rtl8xxxu_priv *priv) { char *fw_name; @@ -392,7 +450,7 @@ static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv) priv->power_base = &rtl8192c_power_base; if (efuse->rf_regulatory & 0x20) { - sprintf(priv->chip_name, "8188RU"); + strscpy(priv->chip_name, "8188RU", sizeof(priv->chip_name)); priv->rtl_chip = RTL8188R; priv->hi_pa = 1; priv->no_pape = 1; @@ -541,6 +599,7 @@ static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv) } struct rtl8xxxu_fileops rtl8192cu_fops = { + .identify_chip = rtl8192cu_identify_chip, .parse_efuse = rtl8192cu_parse_efuse, .load_firmware = rtl8192cu_load_firmware, .power_on = rtl8192cu_power_on, @@ -561,6 +620,7 @@ struct rtl8xxxu_fileops rtl8192cu_fops = { .update_rate_mask = rtl8xxxu_update_rate_mask, .report_connect = rtl8xxxu_gen1_report_connect, .fill_txdesc = rtl8xxxu_fill_txdesc_v1, + .cck_rssi = rtl8723a_cck_rssi, .writeN_block_size = 128, .rx_agg_buf_size = 16000, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32), diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c index 550290ae9e17..6dc1e5858e77 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c @@ -478,6 +478,53 @@ static const struct rtl8xxxu_rfregval rtl8192eu_radiob_init_table[] = { {0xff, 0xffffffff} }; +static int rtl8192eu_identify_chip(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + u32 val32, bonding, sys_cfg, vendor; + int ret = 0; + + sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG); + priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK); + if (sys_cfg & SYS_CFG_TRP_VAUX_EN) { + dev_info(dev, "Unsupported test chip\n"); + ret = -ENOTSUPP; + goto out; + } + + bonding = rtl8xxxu_read32(priv, REG_HPON_FSM); + bonding &= HPON_FSM_BONDING_MASK; + if (bonding == HPON_FSM_BONDING_1T2R) { + strscpy(priv->chip_name, "8191EU", sizeof(priv->chip_name)); + priv->tx_paths = 1; + priv->rtl_chip = RTL8191E; + } else { + strscpy(priv->chip_name, "8192EU", sizeof(priv->chip_name)); + priv->tx_paths = 2; + priv->rtl_chip = RTL8192E; + } + priv->rf_paths = 2; + priv->rx_paths = 2; + priv->has_wifi = 1; + + vendor = sys_cfg & SYS_CFG_VENDOR_EXT_MASK; + rtl8xxxu_identify_vendor_2bits(priv, vendor); + + val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS); + priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID); + + rtl8xxxu_config_endpoints_sie(priv); + + /* + * Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX + */ + if (!priv->ep_tx_count) + ret = rtl8xxxu_config_endpoints_no_sie(priv); + +out: + return ret; +} + static void rtl8192e_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) { @@ -635,8 +682,7 @@ static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv) efuse->tx_power_index_B.pwr_diff[i - 1].ht40; } - priv->has_xtalk = 1; - priv->xtalk = priv->efuse_wifi.efuse8192eu.xtal_k & 0x3f; + priv->default_crystal_cap = priv->efuse_wifi.efuse8192eu.xtal_k & 0x3f; /* * device_info section seems to be laid out as records @@ -1671,7 +1717,30 @@ static void rtl8192e_enable_rf(struct rtl8xxxu_priv *priv) rtl8xxxu_write8(priv, REG_PAD_CTRL1, val8); } +static s8 rtl8192e_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt) +{ + static const s8 lna_gain_table_0[8] = {15, 9, -10, -21, -23, -27, -43, -44}; + static const s8 lna_gain_table_1[8] = {24, 18, 13, -4, -11, -18, -31, -36}; + + s8 rx_pwr_all = 0x00; + u8 vga_idx, lna_idx; + s8 lna_gain = 0; + + lna_idx = (cck_agc_rpt & 0xE0) >> 5; + vga_idx = cck_agc_rpt & 0x1F; + + if (priv->cck_agc_report_type == 0) + lna_gain = lna_gain_table_0[lna_idx]; + else + lna_gain = lna_gain_table_1[lna_idx]; + + rx_pwr_all = lna_gain - (2 * vga_idx); + + return rx_pwr_all; +} + struct rtl8xxxu_fileops rtl8192eu_fops = { + .identify_chip = rtl8192eu_identify_chip, .parse_efuse = rtl8192eu_parse_efuse, .load_firmware = rtl8192eu_load_firmware, .power_on = rtl8192eu_power_on, @@ -1691,6 +1760,8 @@ struct rtl8xxxu_fileops rtl8192eu_fops = { .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, .report_connect = rtl8xxxu_gen2_report_connect, .fill_txdesc = rtl8xxxu_fill_txdesc_v2, + .set_crystal_cap = rtl8723a_set_crystal_cap, + .cck_rssi = rtl8192e_cck_rssi, .writeN_block_size = 128, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40), .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24), diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c index 44565bf4c1c2..707ac48ecc83 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c @@ -129,6 +129,55 @@ static const struct rtl8xxxu_rfregval rtl8723au_radioa_1t_init_table[] = { {0xff, 0xffffffff} }; +static int rtl8723au_identify_chip(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + u32 val32, sys_cfg, vendor; + int ret = 0; + + sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG); + priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK); + if (sys_cfg & SYS_CFG_TRP_VAUX_EN) { + dev_info(dev, "Unsupported test chip\n"); + ret = -ENOTSUPP; + goto out; + } + + strscpy(priv->chip_name, "8723AU", sizeof(priv->chip_name)); + priv->usb_interrupts = 1; + priv->rtl_chip = RTL8723A; + + priv->rf_paths = 1; + priv->rx_paths = 1; + priv->tx_paths = 1; + + val32 = rtl8xxxu_read32(priv, REG_MULTI_FUNC_CTRL); + if (val32 & MULTI_WIFI_FUNC_EN) + priv->has_wifi = 1; + if (val32 & MULTI_BT_FUNC_EN) + priv->has_bluetooth = 1; + if (val32 & MULTI_GPS_FUNC_EN) + priv->has_gps = 1; + priv->is_multi_func = 1; + + vendor = sys_cfg & SYS_CFG_VENDOR_ID; + rtl8xxxu_identify_vendor_1bit(priv, vendor); + + val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS); + priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID); + + rtl8xxxu_config_endpoints_sie(priv); + + /* + * Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX + */ + if (!priv->ep_tx_count) + ret = rtl8xxxu_config_endpoints_no_sie(priv); + +out: + return ret; +} + static int rtl8723au_parse_efuse(struct rtl8xxxu_priv *priv) { struct rtl8723au_efuse *efuse = &priv->efuse_wifi.efuse8723; @@ -166,10 +215,10 @@ static int rtl8723au_parse_efuse(struct rtl8xxxu_priv *priv) efuse->ht20_max_power_offset, sizeof(efuse->ht20_max_power_offset)); - if (priv->efuse_wifi.efuse8723.version >= 0x01) { - priv->has_xtalk = 1; - priv->xtalk = priv->efuse_wifi.efuse8723.xtal_k & 0x3f; - } + if (priv->efuse_wifi.efuse8723.version >= 0x01) + priv->default_crystal_cap = priv->efuse_wifi.efuse8723.xtal_k & 0x3f; + else + priv->fops->set_crystal_cap = NULL; priv->power_base = &rtl8723a_power_base; @@ -357,7 +406,59 @@ exit: return ret; } +#define XTAL1 GENMASK(23, 18) +#define XTAL0 GENMASK(17, 12) + +void rtl8723a_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap) +{ + struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking; + u32 val32; + + if (crystal_cap == cfo->crystal_cap) + return; + + val32 = rtl8xxxu_read32(priv, REG_MAC_PHY_CTRL); + + dev_dbg(&priv->udev->dev, + "%s: Adjusting crystal cap from 0x%x (actually 0x%lx 0x%lx) to 0x%x\n", + __func__, + cfo->crystal_cap, + FIELD_GET(XTAL1, val32), + FIELD_GET(XTAL0, val32), + crystal_cap); + + val32 &= ~(XTAL1 | XTAL0); + val32 |= FIELD_PREP(XTAL1, crystal_cap) | + FIELD_PREP(XTAL0, crystal_cap); + rtl8xxxu_write32(priv, REG_MAC_PHY_CTRL, val32); + + cfo->crystal_cap = crystal_cap; +} + +s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt) +{ + s8 rx_pwr_all = 0x00; + + switch (cck_agc_rpt & 0xc0) { + case 0xc0: + rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); + break; + case 0x80: + rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); + break; + case 0x40: + rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); + break; + case 0x00: + rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); + break; + } + + return rx_pwr_all; +} + struct rtl8xxxu_fileops rtl8723au_fops = { + .identify_chip = rtl8723au_identify_chip, .parse_efuse = rtl8723au_parse_efuse, .load_firmware = rtl8723au_load_firmware, .power_on = rtl8723au_power_on, @@ -378,6 +479,8 @@ struct rtl8xxxu_fileops rtl8723au_fops = { .update_rate_mask = rtl8xxxu_update_rate_mask, .report_connect = rtl8xxxu_gen1_report_connect, .fill_txdesc = rtl8xxxu_fill_txdesc_v1, + .set_crystal_cap = rtl8723a_set_crystal_cap, + .cck_rssi = rtl8723a_cck_rssi, .writeN_block_size = 1024, .rx_agg_buf_size = 16000, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32), diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c index a27fe06d6f77..a0ec895b61a4 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c @@ -304,6 +304,53 @@ static const struct rtl8xxxu_rfregval rtl8723bu_radioa_1t_init_table[] = { {0xff, 0xffffffff} }; +static int rtl8723bu_identify_chip(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + u32 val32, sys_cfg, vendor; + int ret = 0; + + sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG); + priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK); + if (sys_cfg & SYS_CFG_TRP_VAUX_EN) { + dev_info(dev, "Unsupported test chip\n"); + ret = -ENOTSUPP; + goto out; + } + + strscpy(priv->chip_name, "8723BU", sizeof(priv->chip_name)); + priv->rtl_chip = RTL8723B; + priv->rf_paths = 1; + priv->rx_paths = 1; + priv->tx_paths = 1; + + val32 = rtl8xxxu_read32(priv, REG_MULTI_FUNC_CTRL); + if (val32 & MULTI_WIFI_FUNC_EN) + priv->has_wifi = 1; + if (val32 & MULTI_BT_FUNC_EN) + priv->has_bluetooth = 1; + if (val32 & MULTI_GPS_FUNC_EN) + priv->has_gps = 1; + priv->is_multi_func = 1; + + vendor = sys_cfg & SYS_CFG_VENDOR_EXT_MASK; + rtl8xxxu_identify_vendor_2bits(priv, vendor); + + val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS); + priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID); + + rtl8xxxu_config_endpoints_sie(priv); + + /* + * Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX + */ + if (!priv->ep_tx_count) + ret = rtl8xxxu_config_endpoints_no_sie(priv); + +out: + return ret; +} + static void rtl8723bu_write_btreg(struct rtl8xxxu_priv *priv, u8 reg, u8 data) { struct h2c_cmd h2c; @@ -445,8 +492,7 @@ static int rtl8723bu_parse_efuse(struct rtl8xxxu_priv *priv) efuse->tx_power_index_B.pwr_diff[i - 1].ht40; } - priv->has_xtalk = 1; - priv->xtalk = priv->efuse_wifi.efuse8723bu.xtal_k & 0x3f; + priv->default_crystal_cap = priv->efuse_wifi.efuse8723bu.xtal_k & 0x3f; dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name); dev_info(&priv->udev->dev, "Product: %.41s\n", efuse->device_name); @@ -1640,7 +1686,36 @@ static void rtl8723bu_init_statistics(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_OFDM0_FA_RSTC, val32); } +static s8 rtl8723b_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt) +{ + s8 rx_pwr_all = 0x00; + u8 vga_idx, lna_idx; + + lna_idx = (cck_agc_rpt & 0xE0) >> 5; + vga_idx = cck_agc_rpt & 0x1F; + + switch (lna_idx) { + case 6: + rx_pwr_all = -34 - (2 * vga_idx); + break; + case 4: + rx_pwr_all = -14 - (2 * vga_idx); + break; + case 1: + rx_pwr_all = 6 - (2 * vga_idx); + break; + case 0: + rx_pwr_all = 16 - (2 * vga_idx); + break; + default: + break; + } + + return rx_pwr_all; +} + struct rtl8xxxu_fileops rtl8723bu_fops = { + .identify_chip = rtl8723bu_identify_chip, .parse_efuse = rtl8723bu_parse_efuse, .load_firmware = rtl8723bu_load_firmware, .power_on = rtl8723bu_power_on, @@ -1656,6 +1731,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops = { .parse_rx_desc = rtl8xxxu_parse_rxdesc24, .init_aggregation = rtl8723bu_init_aggregation, .init_statistics = rtl8723bu_init_statistics, + .init_burst = rtl8xxxu_init_burst, .enable_rf = rtl8723b_enable_rf, .disable_rf = rtl8xxxu_gen2_disable_rf, .usb_quirks = rtl8xxxu_gen2_usb_quirks, @@ -1663,6 +1739,8 @@ struct rtl8xxxu_fileops rtl8723bu_fops = { .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, .report_connect = rtl8xxxu_gen2_report_connect, .fill_txdesc = rtl8xxxu_fill_txdesc_v2, + .set_crystal_cap = rtl8723a_set_crystal_cap, + .cck_rssi = rtl8723b_cck_rssi, .writeN_block_size = 1024, .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40), .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24), diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index 65bb4dc8f555..e8fcd531c437 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -1574,30 +1574,14 @@ rtl8xxxu_set_spec_sifs(struct rtl8xxxu_priv *priv, u16 cck, u16 ofdm) static void rtl8xxxu_print_chipinfo(struct rtl8xxxu_priv *priv) { struct device *dev = &priv->udev->dev; - char *cut; + char cut = '?'; - switch (priv->chip_cut) { - case 0: - cut = "A"; - break; - case 1: - cut = "B"; - break; - case 2: - cut = "C"; - break; - case 3: - cut = "D"; - break; - case 4: - cut = "E"; - break; - default: - cut = "unknown"; - } + /* Currently always true: chip_cut is 4 bits. */ + if (priv->chip_cut <= 15) + cut = 'A' + priv->chip_cut; dev_info(dev, - "RTL%s rev %s (%s) %iT%iR, TX queues %i, WiFi=%i, BT=%i, GPS=%i, HI PA=%i\n", + "RTL%s rev %c (%s) %iT%iR, TX queues %i, WiFi=%i, BT=%i, GPS=%i, HI PA=%i\n", priv->chip_name, cut, priv->chip_vendor, priv->tx_paths, priv->rx_paths, priv->ep_tx_count, priv->has_wifi, priv->has_bluetooth, priv->has_gps, priv->hi_pa); @@ -1605,148 +1589,40 @@ static void rtl8xxxu_print_chipinfo(struct rtl8xxxu_priv *priv) dev_info(dev, "RTL%s MAC: %pM\n", priv->chip_name, priv->mac_addr); } -static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) +void rtl8xxxu_identify_vendor_1bit(struct rtl8xxxu_priv *priv, u32 vendor) { - const struct usb_device_descriptor *descriptor = &priv->udev->descriptor; - struct device *dev = &priv->udev->dev; - struct ieee80211_hw *hw = priv->hw; - u32 val32, bonding, sys_cfg; - u16 val16; - - sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG); - priv->chip_cut = (sys_cfg & SYS_CFG_CHIP_VERSION_MASK) >> - SYS_CFG_CHIP_VERSION_SHIFT; - if (sys_cfg & SYS_CFG_TRP_VAUX_EN) { - dev_info(dev, "Unsupported test chip\n"); - return -ENOTSUPP; - } - - if (descriptor->idVendor == USB_VENDOR_ID_REALTEK && - descriptor->idProduct == 0xf179) { - sprintf(priv->chip_name, "8188FU"); - priv->rtl_chip = RTL8188F; - priv->rf_paths = 1; - priv->rx_paths = 1; - priv->tx_paths = 1; - priv->has_wifi = 1; - goto skip_complicated_chip_detection; - } - - if (sys_cfg & SYS_CFG_BT_FUNC) { - if (priv->chip_cut >= 3) { - sprintf(priv->chip_name, "8723BU"); - priv->rtl_chip = RTL8723B; - } else { - sprintf(priv->chip_name, "8723AU"); - priv->usb_interrupts = 1; - priv->rtl_chip = RTL8723A; - } - - priv->rf_paths = 1; - priv->rx_paths = 1; - priv->tx_paths = 1; - - val32 = rtl8xxxu_read32(priv, REG_MULTI_FUNC_CTRL); - if (val32 & MULTI_WIFI_FUNC_EN) - priv->has_wifi = 1; - if (val32 & MULTI_BT_FUNC_EN) - priv->has_bluetooth = 1; - if (val32 & MULTI_GPS_FUNC_EN) - priv->has_gps = 1; - priv->is_multi_func = 1; - } else if (sys_cfg & SYS_CFG_TYPE_ID) { - bonding = rtl8xxxu_read32(priv, REG_HPON_FSM); - bonding &= HPON_FSM_BONDING_MASK; - if (priv->fops->tx_desc_size == - sizeof(struct rtl8xxxu_txdesc40)) { - if (bonding == HPON_FSM_BONDING_1T2R) { - sprintf(priv->chip_name, "8191EU"); - priv->rf_paths = 2; - priv->rx_paths = 2; - priv->tx_paths = 1; - priv->rtl_chip = RTL8191E; - } else { - sprintf(priv->chip_name, "8192EU"); - priv->rf_paths = 2; - priv->rx_paths = 2; - priv->tx_paths = 2; - priv->rtl_chip = RTL8192E; - } - } else if (bonding == HPON_FSM_BONDING_1T2R) { - sprintf(priv->chip_name, "8191CU"); - priv->rf_paths = 2; - priv->rx_paths = 2; - priv->tx_paths = 1; - priv->usb_interrupts = 1; - priv->rtl_chip = RTL8191C; - } else { - sprintf(priv->chip_name, "8192CU"); - priv->rf_paths = 2; - priv->rx_paths = 2; - priv->tx_paths = 2; - priv->usb_interrupts = 0; - priv->rtl_chip = RTL8192C; - } - priv->has_wifi = 1; + if (vendor) { + strscpy(priv->chip_vendor, "UMC", sizeof(priv->chip_vendor)); + priv->vendor_umc = 1; } else { - sprintf(priv->chip_name, "8188CU"); - priv->rf_paths = 1; - priv->rx_paths = 1; - priv->tx_paths = 1; - priv->rtl_chip = RTL8188C; - priv->usb_interrupts = 0; - priv->has_wifi = 1; + strscpy(priv->chip_vendor, "TSMC", sizeof(priv->chip_vendor)); } +} -skip_complicated_chip_detection: - - hw->wiphy->available_antennas_tx = BIT(priv->tx_paths) - 1; - hw->wiphy->available_antennas_rx = BIT(priv->rx_paths) - 1; - - switch (priv->rtl_chip) { - case RTL8188E: - case RTL8188F: - case RTL8192E: - case RTL8723B: - switch (sys_cfg & SYS_CFG_VENDOR_EXT_MASK) { - case SYS_CFG_VENDOR_ID_TSMC: - sprintf(priv->chip_vendor, "TSMC"); - break; - case SYS_CFG_VENDOR_ID_SMIC: - sprintf(priv->chip_vendor, "SMIC"); - priv->vendor_smic = 1; - break; - case SYS_CFG_VENDOR_ID_UMC: - sprintf(priv->chip_vendor, "UMC"); - priv->vendor_umc = 1; - break; - default: - sprintf(priv->chip_vendor, "unknown"); - } +void rtl8xxxu_identify_vendor_2bits(struct rtl8xxxu_priv *priv, u32 vendor) +{ + switch (vendor) { + case SYS_CFG_VENDOR_ID_TSMC: + strscpy(priv->chip_vendor, "TSMC", sizeof(priv->chip_vendor)); + break; + case SYS_CFG_VENDOR_ID_SMIC: + strscpy(priv->chip_vendor, "SMIC", sizeof(priv->chip_vendor)); + priv->vendor_smic = 1; + break; + case SYS_CFG_VENDOR_ID_UMC: + strscpy(priv->chip_vendor, "UMC", sizeof(priv->chip_vendor)); + priv->vendor_umc = 1; break; default: - if (sys_cfg & SYS_CFG_VENDOR_ID) { - sprintf(priv->chip_vendor, "UMC"); - priv->vendor_umc = 1; - } else { - sprintf(priv->chip_vendor, "TSMC"); - } + strscpy(priv->chip_vendor, "unknown", sizeof(priv->chip_vendor)); } +} - val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS); - priv->rom_rev = (val32 & GPIO_RF_RL_ID) >> 28; +void rtl8xxxu_config_endpoints_sie(struct rtl8xxxu_priv *priv) +{ + u16 val16; - /* - * 8188FU vendor driver doesn't use REG_NORMAL_SIE_EP_TX, - * it just decides the queue mapping based on nr_out_eps. - * However, reading the register returns "0x321" which - * results in a wrong ep_tx_count of 3 and most frames - * not being transmitted. - */ - if (priv->rtl_chip == RTL8188F) - val16 = 0; - else - val16 = rtl8xxxu_read16(priv, REG_NORMAL_SIE_EP_TX); + val16 = rtl8xxxu_read16(priv, REG_NORMAL_SIE_EP_TX); if (val16 & NORMAL_SIE_EP_TX_HIGH_MASK) { priv->ep_tx_high_queue = 1; @@ -1762,29 +1638,29 @@ skip_complicated_chip_detection: priv->ep_tx_low_queue = 1; priv->ep_tx_count++; } +} - /* - * Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX - */ - if (!priv->ep_tx_count) { - switch (priv->nr_out_eps) { - case 4: - case 3: - priv->ep_tx_low_queue = 1; - priv->ep_tx_count++; - fallthrough; - case 2: - priv->ep_tx_normal_queue = 1; - priv->ep_tx_count++; - fallthrough; - case 1: - priv->ep_tx_high_queue = 1; - priv->ep_tx_count++; - break; - default: - dev_info(dev, "Unsupported USB TX end-points\n"); - return -ENOTSUPP; - } +int rtl8xxxu_config_endpoints_no_sie(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + + switch (priv->nr_out_eps) { + case 4: + case 3: + priv->ep_tx_low_queue = 1; + priv->ep_tx_count++; + fallthrough; + case 2: + priv->ep_tx_normal_queue = 1; + priv->ep_tx_count++; + fallthrough; + case 1: + priv->ep_tx_high_queue = 1; + priv->ep_tx_count++; + break; + default: + dev_info(dev, "Unsupported USB TX end-points\n"); + return -ENOTSUPP; } return 0; @@ -2031,7 +1907,8 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL); if (val8 & MCU_FW_RAM_SEL) { - pr_info("do the RAM reset\n"); + dev_info(&priv->udev->dev, + "Firmware is already running, resetting the MCU.\n"); rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00); priv->fops->reset_8051(priv); } @@ -2286,7 +2163,6 @@ void rtl8xxxu_gen1_init_phy_bb(struct rtl8xxxu_priv *priv) */ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) { - u8 val8; u32 val32; priv->fops->init_phy_bb(priv); @@ -2351,15 +2227,8 @@ static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_TX_TO_TX, val32); } - if (priv->has_xtalk) { - val32 = rtl8xxxu_read32(priv, REG_MAC_PHY_CTRL); - - val8 = priv->xtalk; - val32 &= 0xff000fff; - val32 |= ((val8 | (val8 << 6)) << 12); - - rtl8xxxu_write32(priv, REG_MAC_PHY_CTRL, val32); - } + if (priv->fops->set_crystal_cap) + priv->fops->set_crystal_cap(priv, priv->default_crystal_cap); if (priv->rtl_chip == RTL8192E) rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x000f81fb); @@ -3909,6 +3778,52 @@ static void rtl8xxxu_init_queue_reserved_page(struct rtl8xxxu_priv *priv) rtl8xxxu_write32(priv, REG_RQPN, val32); } +void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv) +{ + u8 val8; + + /* + * For USB high speed set 512B packets + */ + val8 = rtl8xxxu_read8(priv, REG_RXDMA_PRO_8723B); + u8p_replace_bits(&val8, 1, RXDMA_PRO_DMA_BURST_SIZE); + u8p_replace_bits(&val8, 3, RXDMA_PRO_DMA_BURST_CNT); + val8 |= RXDMA_PRO_DMA_MODE; + rtl8xxxu_write8(priv, REG_RXDMA_PRO_8723B, val8); + + /* + * Enable single packet AMPDU + */ + val8 = rtl8xxxu_read8(priv, REG_HT_SINGLE_AMPDU_8723B); + val8 |= HT_SINGLE_AMPDU_ENABLE; + rtl8xxxu_write8(priv, REG_HT_SINGLE_AMPDU_8723B, val8); + + rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, 0x0c14); + if (priv->rtl_chip == RTL8723B) + val8 = 0x5e; + else if (priv->rtl_chip == RTL8188F) + val8 = 0x70; /* 0x5e would make it very slow */ + rtl8xxxu_write8(priv, REG_AMPDU_MAX_TIME_8723B, val8); + rtl8xxxu_write32(priv, REG_AGGLEN_LMT, 0xffffffff); + rtl8xxxu_write8(priv, REG_RX_PKT_LIMIT, 0x18); + rtl8xxxu_write8(priv, REG_PIFS, 0x00); + if (priv->rtl_chip == RTL8188F) { + rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL, FWHW_TXQ_CTRL_AMPDU_RETRY); + rtl8xxxu_write32(priv, REG_FAST_EDCA_CTRL, 0x03086666); + } + if (priv->rtl_chip == RTL8723B) + val8 = 0x50; + else if (priv->rtl_chip == RTL8188F) + val8 = 0x28; /* 0x50 would make the upload slow */ + rtl8xxxu_write8(priv, REG_USTIME_TSF_8723B, val8); + rtl8xxxu_write8(priv, REG_USTIME_EDCA, val8); + + /* to prevent mac is reseted by bus. */ + val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL); + val8 |= RSV_CTRL_WLOCK_1C | RSV_CTRL_DIS_PRST; + rtl8xxxu_write8(priv, REG_RSV_CTRL, val8); +} + static int rtl8xxxu_init_device(struct ieee80211_hw *hw) { struct rtl8xxxu_priv *priv = hw->priv; @@ -4162,48 +4077,9 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* * Initialize burst parameters */ - if (priv->rtl_chip == RTL8723B || priv->rtl_chip == RTL8188F) { - /* - * For USB high speed set 512B packets - */ - val8 = rtl8xxxu_read8(priv, REG_RXDMA_PRO_8723B); - val8 &= ~(BIT(4) | BIT(5)); - val8 |= BIT(4); - val8 |= BIT(1) | BIT(2) | BIT(3); - rtl8xxxu_write8(priv, REG_RXDMA_PRO_8723B, val8); - - /* - * For USB high speed set 512B packets - */ - val8 = rtl8xxxu_read8(priv, REG_HT_SINGLE_AMPDU_8723B); - val8 |= BIT(7); - rtl8xxxu_write8(priv, REG_HT_SINGLE_AMPDU_8723B, val8); - - rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, 0x0c14); - if (priv->rtl_chip == RTL8723B) - val8 = 0x5e; - else if (priv->rtl_chip == RTL8188F) - val8 = 0x70; /* 0x5e would make it very slow */ - rtl8xxxu_write8(priv, REG_AMPDU_MAX_TIME_8723B, val8); - rtl8xxxu_write32(priv, REG_AGGLEN_LMT, 0xffffffff); - rtl8xxxu_write8(priv, REG_RX_PKT_LIMIT, 0x18); - rtl8xxxu_write8(priv, REG_PIFS, 0x00); - if (priv->rtl_chip == RTL8188F) { - rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL, FWHW_TXQ_CTRL_AMPDU_RETRY); - rtl8xxxu_write32(priv, REG_FAST_EDCA_CTRL, 0x03086666); - } - if (priv->rtl_chip == RTL8723B) - val8 = 0x50; - else if (priv->rtl_chip == RTL8188F) - val8 = 0x28; /* 0x50 would make the upload slow */ - rtl8xxxu_write8(priv, REG_USTIME_TSF_8723B, val8); - rtl8xxxu_write8(priv, REG_USTIME_EDCA, val8); - /* to prevent mac is reseted by bus. */ - val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL); - val8 |= BIT(5) | BIT(6); - rtl8xxxu_write8(priv, REG_RSV_CTRL, val8); - } + if (priv->fops->init_burst) + priv->fops->init_burst(priv); if (fops->init_aggregation) fops->init_aggregation(priv); @@ -4326,7 +4202,39 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) val32 &= 0xfff00fff; val32 |= 0x0007e000; rtl8xxxu_write32(priv, REG_AFE_MISC, val32); + + /* + * 0x824[9] = 0x82C[9] = 0xA80[7] those registers setting + * should be equal or CCK RSSI report may be incorrect + */ + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM2); + priv->cck_agc_report_type = val32 & FPGA0_HSSI_PARM2_CCK_HIGH_PWR; + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XB_HSSI_PARM2); + if (priv->cck_agc_report_type != (bool)(val32 & FPGA0_HSSI_PARM2_CCK_HIGH_PWR)) { + if (priv->cck_agc_report_type) + val32 |= FPGA0_HSSI_PARM2_CCK_HIGH_PWR; + else + val32 &= ~FPGA0_HSSI_PARM2_CCK_HIGH_PWR; + rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM2, val32); + } + + val32 = rtl8xxxu_read32(priv, REG_AGC_RPT); + if (priv->cck_agc_report_type) + val32 |= AGC_RPT_CCK; + else + val32 &= ~AGC_RPT_CCK; + rtl8xxxu_write32(priv, REG_AGC_RPT, val32); } + + /* Initialise the center frequency offset tracking */ + if (priv->fops->set_crystal_cap) { + val32 = rtl8xxxu_read32(priv, REG_OFDM1_CFO_TRACKING); + priv->cfo_tracking.atc_status = val32 & CFO_TRACKING_ATC_STATUS; + priv->cfo_tracking.adjust = true; + priv->cfo_tracking.crystal_cap = priv->default_crystal_cap; + } + exit: return ret; } @@ -5294,7 +5202,8 @@ error: static void rtl8xxxu_rx_parse_phystats(struct rtl8xxxu_priv *priv, struct ieee80211_rx_status *rx_status, struct rtl8723au_phy_stats *phy_stats, - u32 rxmcs) + u32 rxmcs, struct ieee80211_hdr *hdr, + bool crc_icv_err) { if (phy_stats->sgi_en) rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; @@ -5305,21 +5214,23 @@ static void rtl8xxxu_rx_parse_phystats(struct rtl8xxxu_priv *priv, */ u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a; - switch (cck_agc_rpt & 0xc0) { - case 0xc0: - rx_status->signal = -46 - (cck_agc_rpt & 0x3e); - break; - case 0x80: - rx_status->signal = -26 - (cck_agc_rpt & 0x3e); - break; - case 0x40: - rx_status->signal = -12 - (cck_agc_rpt & 0x3e); - break; - case 0x00: - rx_status->signal = 16 - (cck_agc_rpt & 0x3e); - break; - } + rx_status->signal = priv->fops->cck_rssi(priv, cck_agc_rpt); } else { + bool parse_cfo = priv->fops->set_crystal_cap && + priv->vif && + priv->vif->type == NL80211_IFTYPE_STATION && + priv->vif->cfg.assoc && + !crc_icv_err && + !ieee80211_is_ctl(hdr->frame_control) && + ether_addr_equal(priv->vif->bss_conf.bssid, hdr->addr2); + + if (parse_cfo) { + priv->cfo_tracking.cfo_tail[0] = phy_stats->path_cfotail[0]; + priv->cfo_tracking.cfo_tail[1] = phy_stats->path_cfotail[1]; + + priv->cfo_tracking.packet_count++; + } + rx_status->signal = (phy_stats->cck_sig_qual_ofdm_pwdb_all >> 1) - 110; } @@ -5402,7 +5313,8 @@ static void rtl8xxxu_rx_urb_work(struct work_struct *work) rtl8xxxu_queue_rx_urb(priv, rx_urb); break; default: - pr_info("failed to requeue urb %i\n", ret); + dev_warn(&priv->udev->dev, + "failed to requeue urb with error %i\n", ret); skb = (struct sk_buff *)rx_urb->urb.context; dev_kfree_skb(skb); usb_free_urb(&rx_urb->urb); @@ -5802,7 +5714,8 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb) if (rx_desc->phy_stats) rtl8xxxu_rx_parse_phystats(priv, rx_status, phy_stats, - rx_desc->rxmcs); + rx_desc->rxmcs, (struct ieee80211_hdr *)skb->data, + rx_desc->crc32 || rx_desc->icverr); rx_status->mactime = rx_desc->tsfl; rx_status->flag |= RX_FLAG_MACTIME_START; @@ -5873,7 +5786,8 @@ int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb) if (rx_desc->phy_stats) rtl8xxxu_rx_parse_phystats(priv, rx_status, phy_stats, - rx_desc->rxmcs); + rx_desc->rxmcs, (struct ieee80211_hdr *)skb->data, + rx_desc->crc32 || rx_desc->icverr); rx_status->mactime = rx_desc->tsfl; rx_status->flag |= RX_FLAG_MACTIME_START; @@ -6488,6 +6402,94 @@ static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv, } } +static void rtl8xxxu_set_atc_status(struct rtl8xxxu_priv *priv, bool atc_status) +{ + struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking; + u32 val32; + + if (atc_status == cfo->atc_status) + return; + + cfo->atc_status = atc_status; + + val32 = rtl8xxxu_read32(priv, REG_OFDM1_CFO_TRACKING); + if (atc_status) + val32 |= CFO_TRACKING_ATC_STATUS; + else + val32 &= ~CFO_TRACKING_ATC_STATUS; + rtl8xxxu_write32(priv, REG_OFDM1_CFO_TRACKING, val32); +} + +/* Central frequency offset correction */ +static void rtl8xxxu_track_cfo(struct rtl8xxxu_priv *priv) +{ + struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking; + int cfo_khz_a, cfo_khz_b, cfo_average; + int crystal_cap; + + if (!priv->vif || !priv->vif->cfg.assoc) { + /* Reset */ + cfo->adjust = true; + + if (cfo->crystal_cap > priv->default_crystal_cap) + priv->fops->set_crystal_cap(priv, cfo->crystal_cap - 1); + else if (cfo->crystal_cap < priv->default_crystal_cap) + priv->fops->set_crystal_cap(priv, cfo->crystal_cap + 1); + + rtl8xxxu_set_atc_status(priv, true); + + return; + } + + if (cfo->packet_count == cfo->packet_count_pre) + /* No new information. */ + return; + + cfo->packet_count_pre = cfo->packet_count; + + /* CFO_tail[1:0] is S(8,7), (num_subcarrier>>7) x 312.5K = CFO value(K Hz) */ + cfo_khz_a = (int)((cfo->cfo_tail[0] * 3125) / 10) >> 7; + cfo_khz_b = (int)((cfo->cfo_tail[1] * 3125) / 10) >> 7; + + if (priv->tx_paths == 1) + cfo_average = cfo_khz_a; + else + cfo_average = (cfo_khz_a + cfo_khz_b) / 2; + + dev_dbg(&priv->udev->dev, "cfo_average: %d\n", cfo_average); + + if (cfo->adjust) { + if (abs(cfo_average) < CFO_TH_XTAL_LOW) + cfo->adjust = false; + } else { + if (abs(cfo_average) > CFO_TH_XTAL_HIGH) + cfo->adjust = true; + } + + /* + * TODO: We should return here only if bluetooth is enabled. + * See the vendor drivers for how to determine that. + */ + if (priv->has_bluetooth) + return; + + if (!cfo->adjust) + return; + + crystal_cap = cfo->crystal_cap; + + if (cfo_average > CFO_TH_XTAL_LOW) + crystal_cap++; + else if (cfo_average < -CFO_TH_XTAL_LOW) + crystal_cap--; + + crystal_cap = clamp(crystal_cap, 0, 0x3f); + + priv->fops->set_crystal_cap(priv, crystal_cap); + + rtl8xxxu_set_atc_status(priv, abs(cfo_average) >= CFO_TH_ATC); +} + static void rtl8xxxu_watchdog_callback(struct work_struct *work) { struct ieee80211_vif *vif; @@ -6512,6 +6514,10 @@ static void rtl8xxxu_watchdog_callback(struct work_struct *work) rcu_read_unlock(); signal = ieee80211_ave_rssi(vif); + + if (priv->fops->set_crystal_cap) + rtl8xxxu_track_cfo(priv); + rtl8xxxu_refresh_rate_mask(priv, signal, sta); } @@ -6823,12 +6829,15 @@ static int rtl8xxxu_probe(struct usb_interface *interface, if (ret) goto err_set_intfdata; - ret = rtl8xxxu_identify_chip(priv); + ret = priv->fops->identify_chip(priv); if (ret) { dev_err(&udev->dev, "Fatal - failed to identify chip\n"); goto err_set_intfdata; } + hw->wiphy->available_antennas_tx = BIT(priv->tx_paths) - 1; + hw->wiphy->available_antennas_rx = BIT(priv->rx_paths) - 1; + ret = rtl8xxxu_read_efuse(priv); if (ret) { dev_err(&udev->dev, "Fatal - failed to read EFuse\n"); @@ -6893,6 +6902,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface, * The firmware handles rate control */ ieee80211_hw_set(hw, HAS_RATE_CONTROL); + ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); ieee80211_hw_set(hw, AMPDU_AGGREGATION); wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index 35bde1404793..3e79efdfb4c2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -68,6 +68,8 @@ #define REG_SPS_OCP_CFG 0x0018 #define REG_8192E_LDOV12_CTRL 0x0014 #define REG_RSV_CTRL 0x001c +#define RSV_CTRL_WLOCK_1C BIT(5) +#define RSV_CTRL_DIS_PRST BIT(6) #define REG_RF_CTRL 0x001f #define RF_ENABLE BIT(0) @@ -313,7 +315,6 @@ #define SYS_CFG_SPS_SEL BIT(24) /* 1:LDO regulator mode; 0:Switching regulator mode*/ #define SYS_CFG_CHIP_VERSION_MASK 0xf000 /* Bit 12 - 15 */ -#define SYS_CFG_CHIP_VERSION_SHIFT 12 #define REG_GPIO_OUTSTS 0x00f4 /* For RTL8723 only. */ #define GPIO_EFS_HCI_SEL (BIT(0) | BIT(1)) @@ -472,6 +473,9 @@ /* Presumably only found on newer chips such as 8723bu */ #define REG_RX_DMA_CTRL_8723B 0x0286 #define REG_RXDMA_PRO_8723B 0x0290 +#define RXDMA_PRO_DMA_MODE BIT(1) /* Set to 0x1. */ +#define RXDMA_PRO_DMA_BURST_CNT GENMASK(3, 2) /* Set to 0x3. */ +#define RXDMA_PRO_DMA_BURST_SIZE GENMASK(5, 4) /* Set to 0x1. */ #define REG_RF_BB_CMD_ADDR 0x02c0 #define REG_RF_BB_CMD_DATA 0x02c4 @@ -577,6 +581,7 @@ #define REG_STBC_SETTING 0x04c4 #define REG_QUEUE_CTRL 0x04c6 #define REG_HT_SINGLE_AMPDU_8723B 0x04c7 +#define HT_SINGLE_AMPDU_ENABLE BIT(7) #define REG_PROT_MODE_CTRL 0x04c8 #define REG_MAX_AGGR_NUM 0x04ca #define REG_RTS_MAX_AGGR_NUM 0x04cb @@ -960,6 +965,9 @@ #define CCK_PD_TYPE1_LV3_TH 0xdd #define CCK_PD_TYPE1_LV4_TH 0xed +#define REG_AGC_RPT 0xa80 +#define AGC_RPT_CCK BIT(7) + #define REG_CONFIG_ANT_A 0x0b68 #define REG_CONFIG_ANT_B 0x0b6c @@ -1027,6 +1035,7 @@ #define REG_OFDM1_TRX_PATH_ENABLE 0x0d04 #define REG_OFDM1_CFO_TRACKING 0x0d2c +#define CFO_TRACKING_ATC_STATUS BIT(11) #define REG_OFDM1_CSI_FIX_MASK1 0x0d40 #define REG_OFDM1_CSI_FIX_MASK2 0x0d44 diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c index 8043d819fb85..a182cdeb58e2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c @@ -997,7 +997,6 @@ bool rtl92ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index) struct rtl_priv *rtlpriv = rtl_priv(hw); u16 read_point, write_point; bool ret = false; - static u8 stop_report_cnt; struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; { @@ -1038,13 +1037,6 @@ bool rtl92ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index) rtlpriv->psc.rfoff_reason > RF_CHANGE_BY_PS) ret = true; - if (hw_queue < BEACON_QUEUE) { - if (!ret) - stop_report_cnt++; - else - stop_report_cnt = 0; - } - return ret; } diff --git a/drivers/net/wireless/realtek/rtw89/Makefile b/drivers/net/wireless/realtek/rtw89/Makefile index ec0f5da65d6a..2dc48fa10c6b 100644 --- a/drivers/net/wireless/realtek/rtw89/Makefile +++ b/drivers/net/wireless/realtek/rtw89/Makefile @@ -15,6 +15,8 @@ rtw89_core-y += core.o \ chan.o \ ser.o +rtw89_core-$(CONFIG_PM) += wow.o + obj-$(CONFIG_RTW89_8852A) += rtw89_8852a.o rtw89_8852a-objs := rtw8852a.o \ rtw8852a_table.o \ diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index a0fa9639b509..f30aadc41f2b 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -171,7 +171,7 @@ bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitr return true; } -static struct ieee80211_supported_band rtw89_sband_2ghz = { +static const struct ieee80211_supported_band rtw89_sband_2ghz = { .band = NL80211_BAND_2GHZ, .channels = rtw89_channels_2ghz, .n_channels = ARRAY_SIZE(rtw89_channels_2ghz), @@ -181,7 +181,7 @@ static struct ieee80211_supported_band rtw89_sband_2ghz = { .vht_cap = {0}, }; -static struct ieee80211_supported_band rtw89_sband_5ghz = { +static const struct ieee80211_supported_band rtw89_sband_5ghz = { .band = NL80211_BAND_5GHZ, .channels = rtw89_channels_5ghz, .n_channels = ARRAY_SIZE(rtw89_channels_5ghz), @@ -193,7 +193,7 @@ static struct ieee80211_supported_band rtw89_sband_5ghz = { .vht_cap = {0}, }; -static struct ieee80211_supported_band rtw89_sband_6ghz = { +static const struct ieee80211_supported_band rtw89_sband_6ghz = { .band = NL80211_BAND_6GHZ, .channels = rtw89_channels_6ghz, .n_channels = ARRAY_SIZE(rtw89_channels_6ghz), @@ -2204,6 +2204,9 @@ static void rtw89_track_work(struct work_struct *work) track_work.work); bool tfc_changed; + if (test_bit(RTW89_FLAG_FORBIDDEN_TRACK_WROK, rtwdev->flags)) + return; + mutex_lock(&rtwdev->mutex); if (!test_bit(RTW89_FLAG_RUNNING, rtwdev->flags)) @@ -2413,6 +2416,8 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { rtwsta->mac_id = rtw89_core_acquire_bit_map(rtwdev->mac_id_map, RTW89_MAX_MAC_ID_NUM); + if (rtwsta->mac_id == RTW89_MAX_MAC_ID_NUM) + return -ENOSPC; } return 0; @@ -2530,7 +2535,7 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, } /* update cam aid mac_id net_type */ - rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; @@ -2960,7 +2965,7 @@ int rtw89_core_start(struct rtw89_dev *rtwdev) return ret; rtw89_phy_init_bb_reg(rtwdev); - rtw89_phy_init_rf_reg(rtwdev); + rtw89_phy_init_rf_reg(rtwdev, false); rtw89_btc_ntfy_init(rtwdev, BTC_MODE_NORMAL); @@ -3040,6 +3045,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) continue; INIT_LIST_HEAD(&rtwdev->scan_info.pkt_list[band]); } + INIT_LIST_HEAD(&rtwdev->wow.pkt_list); INIT_WORK(&rtwdev->ba_work, rtw89_core_ba_work); INIT_WORK(&rtwdev->txq_work, rtw89_core_txq_work); INIT_DELAYED_WORK(&rtwdev->txq_reinvoke_work, rtw89_core_txq_reinvoke_work); @@ -3271,6 +3277,10 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) hw->wiphy->max_scan_ssids = RTW89_SCANOFLD_MAX_SSID; hw->wiphy->max_scan_ie_len = RTW89_SCANOFLD_MAX_IE_LEN; +#ifdef CONFIG_PM + hw->wiphy->wowlan = rtwdev->chip->wowlan_stub; +#endif + hw->wiphy->tid_config_support.vif |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL); hw->wiphy->tid_config_support.peer |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL); hw->wiphy->tid_config_support.vif |= BIT(NL80211_TID_CONFIG_ATTR_AMSDU_CTRL); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 90bf7bdb6062..b60de6662548 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -178,7 +178,9 @@ enum rtw89_upd_mode { RTW89_ROLE_REMOVE, RTW89_ROLE_TYPE_CHANGE, RTW89_ROLE_INFO_CHANGE, - RTW89_ROLE_CON_DISCONN + RTW89_ROLE_CON_DISCONN, + RTW89_ROLE_BAND_SW, + RTW89_ROLE_FW_RESTORE, }; enum rtw89_self_role { @@ -477,6 +479,20 @@ enum rtw89_regulation_type { RTW89_REGD_NUM, }; +enum rtw89_fw_pkt_ofld_type { + RTW89_PKT_OFLD_TYPE_PROBE_RSP = 0, + RTW89_PKT_OFLD_TYPE_PS_POLL = 1, + RTW89_PKT_OFLD_TYPE_NULL_DATA = 2, + RTW89_PKT_OFLD_TYPE_QOS_NULL = 3, + RTW89_PKT_OFLD_TYPE_CTS2SELF = 4, + RTW89_PKT_OFLD_TYPE_ARP_RSP = 5, + RTW89_PKT_OFLD_TYPE_NDP = 6, + RTW89_PKT_OFLD_TYPE_EAPOL_KEY = 7, + RTW89_PKT_OFLD_TYPE_SA_QUERY = 8, + RTW89_PKT_OFLD_TYPE_PROBE_REQ = 12, + RTW89_PKT_OFLD_TYPE_NUM, +}; + struct rtw89_txpwr_byrate { s8 cck[RTW89_RATE_CCK_MAX]; s8 ofdm[RTW89_RATE_OFDM_MAX]; @@ -636,6 +652,13 @@ enum rtw89_sc_offset { RTW89_SC_40_LOWER = 10, }; +enum rtw89_wow_flags { + RTW89_WOW_FLAG_EN_MAGIC_PKT, + RTW89_WOW_FLAG_EN_REKEY_PKT, + RTW89_WOW_FLAG_EN_DISCONNECT, + RTW89_WOW_FLAG_NUM, +}; + struct rtw89_chan { u8 channel; u8 primary_channel; @@ -2286,6 +2309,16 @@ struct rtw89_hci_ops { */ void (*recovery_start)(struct rtw89_dev *rtwdev); void (*recovery_complete)(struct rtw89_dev *rtwdev); + + void (*ctrl_txdma_ch)(struct rtw89_dev *rtwdev, bool enable); + void (*ctrl_txdma_fw_ch)(struct rtw89_dev *rtwdev, bool enable); + void (*ctrl_trxhci)(struct rtw89_dev *rtwdev, bool enable); + int (*poll_txdma_ch)(struct rtw89_dev *rtwdev); + void (*clr_idx_all)(struct rtw89_dev *rtwdev); + void (*clear)(struct rtw89_dev *rtwdev, struct pci_dev *pdev); + void (*disable_intr)(struct rtw89_dev *rtwdev); + void (*enable_intr)(struct rtw89_dev *rtwdev); + int (*rst_bdram)(struct rtw89_dev *rtwdev); }; struct rtw89_hci_info { @@ -2389,6 +2422,7 @@ enum rtw89_dma_ch { enum rtw89_qta_mode { RTW89_QTA_SCC, RTW89_QTA_DLFW, + RTW89_QTA_WOW, /* keep last */ RTW89_QTA_INVALID, @@ -2623,6 +2657,8 @@ struct rtw89_chip_info { u32 rsvd_ple_ofst; const struct rtw89_hfc_param_ini *hfc_param_ini; const struct rtw89_dle_mem *dle_mem; + u8 wde_qempty_acq_num; + u8 wde_qempty_mgq_sel; u32 rf_base_addr[2]; u8 support_chanctx_num; u8 support_bands; @@ -2724,6 +2760,7 @@ struct rtw89_chip_info { const struct rtw89_imr_info *imr_info; const struct rtw89_rrsr_cfgs *rrsr_cfgs; u32 dma_ch_mask; + const struct wiphy_wowlan_support *wowlan_stub; }; union rtw89_bus_info { @@ -2920,6 +2957,8 @@ enum rtw89_flags { RTW89_FLAG_LOW_POWER_MODE, RTW89_FLAG_INACTIVE_PS, RTW89_FLAG_CRASH_SIMULATING, + RTW89_FLAG_WOWLAN, + RTW89_FLAG_FORBIDDEN_TRACK_WROK, NUM_OF_RTW89_FLAGS, }; @@ -2948,6 +2987,7 @@ struct rtw89_pkt_drop_params { u8 port; u8 mbssid; bool tf_trs; + u32 macid_band_sel[4]; }; struct rtw89_pkt_stat { @@ -3449,6 +3489,31 @@ struct rtw89_phy_efuse_gain { s8 comp[RF_PATH_MAX][RTW89_SUBBAND_NR]; /* S(8, 0) */ }; +#define RTW89_MAX_PATTERN_NUM 18 +#define RTW89_MAX_PATTERN_MASK_SIZE 4 +#define RTW89_MAX_PATTERN_SIZE 128 + +struct rtw89_wow_cam_info { + bool r_w; + u8 idx; + u32 mask[RTW89_MAX_PATTERN_MASK_SIZE]; + u16 crc; + bool negative_pattern_match; + bool skip_mac_hdr; + bool uc; + bool mc; + bool bc; + bool valid; +}; + +struct rtw89_wow_param { + struct ieee80211_vif *wow_vif; + DECLARE_BITMAP(flags, RTW89_WOW_FLAG_NUM); + struct rtw89_wow_cam_info patterns[RTW89_MAX_PATTERN_NUM]; + u8 pattern_cnt; + struct list_head pkt_list; +}; + struct rtw89_dev { struct ieee80211_hw *hw; struct device *dev; @@ -3537,6 +3602,8 @@ struct rtw89_dev { enum rtw89_ps_mode ps_mode; bool lps_enabled; + struct rtw89_wow_param wow; + /* napi structure */ struct net_device netdev; struct napi_struct napi; @@ -3619,6 +3686,66 @@ static inline void rtw89_hci_recovery_complete(struct rtw89_dev *rtwdev) rtwdev->hci.ops->recovery_complete(rtwdev); } +static inline void rtw89_hci_enable_intr(struct rtw89_dev *rtwdev) +{ + if (rtwdev->hci.ops->enable_intr) + rtwdev->hci.ops->enable_intr(rtwdev); +} + +static inline void rtw89_hci_disable_intr(struct rtw89_dev *rtwdev) +{ + if (rtwdev->hci.ops->disable_intr) + rtwdev->hci.ops->disable_intr(rtwdev); +} + +static inline void rtw89_hci_ctrl_txdma_ch(struct rtw89_dev *rtwdev, bool enable) +{ + if (rtwdev->hci.ops->ctrl_txdma_ch) + rtwdev->hci.ops->ctrl_txdma_ch(rtwdev, enable); +} + +static inline void rtw89_hci_ctrl_txdma_fw_ch(struct rtw89_dev *rtwdev, bool enable) +{ + if (rtwdev->hci.ops->ctrl_txdma_fw_ch) + rtwdev->hci.ops->ctrl_txdma_fw_ch(rtwdev, enable); +} + +static inline void rtw89_hci_ctrl_trxhci(struct rtw89_dev *rtwdev, bool enable) +{ + if (rtwdev->hci.ops->ctrl_trxhci) + rtwdev->hci.ops->ctrl_trxhci(rtwdev, enable); +} + +static inline int rtw89_hci_poll_txdma_ch(struct rtw89_dev *rtwdev) +{ + int ret = 0; + + if (rtwdev->hci.ops->poll_txdma_ch) + ret = rtwdev->hci.ops->poll_txdma_ch(rtwdev); + return ret; +} + +static inline void rtw89_hci_clr_idx_all(struct rtw89_dev *rtwdev) +{ + if (rtwdev->hci.ops->clr_idx_all) + rtwdev->hci.ops->clr_idx_all(rtwdev); +} + +static inline int rtw89_hci_rst_bdram(struct rtw89_dev *rtwdev) +{ + int ret = 0; + + if (rtwdev->hci.ops->rst_bdram) + ret = rtwdev->hci.ops->rst_bdram(rtwdev); + return ret; +} + +static inline void rtw89_hci_clear(struct rtw89_dev *rtwdev, struct pci_dev *pdev) +{ + if (rtwdev->hci.ops->clear) + rtwdev->hci.ops->clear(rtwdev, pdev); +} + static inline u8 rtw89_read8(struct rtw89_dev *rtwdev, u32 addr) { return rtwdev->hci.ops->read8(rtwdev, addr); diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index 8f27c883eeab..8297e35bfa52 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -8,6 +8,7 @@ #include "debug.h" #include "fw.h" #include "mac.h" +#include "pci.h" #include "ps.h" #include "reg.h" #include "sar.h" @@ -51,6 +52,22 @@ struct rtw89_debugfs_priv { }; }; +static const u16 rtw89_rate_info_bw_to_mhz_map[] = { + [RATE_INFO_BW_20] = 20, + [RATE_INFO_BW_40] = 40, + [RATE_INFO_BW_80] = 80, + [RATE_INFO_BW_160] = 160, + [RATE_INFO_BW_320] = 320, +}; + +static u16 rtw89_rate_info_bw_to_mhz(enum rate_info_bw bw) +{ + if (bw < ARRAY_SIZE(rtw89_rate_info_bw_to_mhz_map)) + return rtw89_rate_info_bw_to_mhz_map[bw]; + + return 0; +} + static int rtw89_debugfs_single_show(struct seq_file *m, void *v) { struct rtw89_debugfs_priv *debugfs_priv = m->private; @@ -972,7 +989,9 @@ static int rtw89_debug_mac_dump_dle_dbg(struct rtw89_dev *rtwdev, static int rtw89_debug_mac_dump_dmac_dbg(struct rtw89_dev *rtwdev, struct seq_file *m) { - int ret; + const struct rtw89_chip_info *chip = rtwdev->chip; + u32 dmac_err; + int i, ret; ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL); if (ret) { @@ -980,98 +999,347 @@ static int rtw89_debug_mac_dump_dmac_dbg(struct rtw89_dev *rtwdev, return ret; } - seq_printf(m, "R_AX_DMAC_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR)); - seq_printf(m, "[0]R_AX_WDRLS_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_WDRLS_ERR_ISR)); - seq_printf(m, "[1]R_AX_SEC_ERR_IMR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_SEC_ERR_IMR_ISR)); - seq_printf(m, "[2.1]R_AX_MPDU_TX_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_ISR)); - seq_printf(m, "[2.2]R_AX_MPDU_RX_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_ISR)); - seq_printf(m, "[3]R_AX_STA_SCHEDULER_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_ISR)); - seq_printf(m, "[4]R_AX_WDE_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR)); - seq_printf(m, "[5.1]R_AX_TXPKTCTL_ERR_IMR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR)); - seq_printf(m, "[5.2]R_AX_TXPKTCTL_ERR_IMR_ISR_B1=0x%08x\n", - rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR_B1)); - seq_printf(m, "[6]R_AX_PLE_ERR_FLAG_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR)); - seq_printf(m, "[7]R_AX_PKTIN_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_PKTIN_ERR_ISR)); - seq_printf(m, "[8.1]R_AX_OTHER_DISPATCHER_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_ISR)); - seq_printf(m, "[8.2]R_AX_HOST_DISPATCHER_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_ISR)); - seq_printf(m, "[8.3]R_AX_CPU_DISPATCHER_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_ISR)); - seq_printf(m, "[10]R_AX_CPUIO_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_CPUIO_ERR_ISR)); - seq_printf(m, "[11.1]R_AX_BBRPT_COM_ERR_IMR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR_ISR)); - seq_printf(m, "[11.2]R_AX_BBRPT_CHINFO_ERR_IMR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR_ISR)); - seq_printf(m, "[11.3]R_AX_BBRPT_DFS_ERR_IMR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR_ISR)); - seq_printf(m, "[11.4]R_AX_LA_ERRFLAG=0x%08x\n", - rtw89_read32(rtwdev, R_AX_LA_ERRFLAG)); + dmac_err = rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR); + seq_printf(m, "R_AX_DMAC_ERR_ISR=0x%08x\n", dmac_err); + seq_printf(m, "R_AX_DMAC_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_DMAC_ERR_IMR)); + + if (dmac_err) { + seq_printf(m, "R_AX_WDE_ERR_FLAG_CFG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WDE_ERR_FLAG_CFG_NUM1)); + seq_printf(m, "R_AX_PLE_ERR_FLAG_CFG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_CFG_NUM1)); + if (chip->chip_id == RTL8852C) { + seq_printf(m, "R_AX_PLE_ERRFLAG_MSG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PLE_ERRFLAG_MSG)); + seq_printf(m, "R_AX_WDE_ERRFLAG_MSG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WDE_ERRFLAG_MSG)); + seq_printf(m, "R_AX_PLE_DBGERR_LOCKEN=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PLE_DBGERR_LOCKEN)); + seq_printf(m, "R_AX_PLE_DBGERR_STS=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PLE_DBGERR_STS)); + } + } + + if (dmac_err & B_AX_WDRLS_ERR_FLAG) { + seq_printf(m, "R_AX_WDRLS_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WDRLS_ERR_IMR)); + seq_printf(m, "R_AX_WDRLS_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WDRLS_ERR_ISR)); + if (chip->chip_id == RTL8852C) + seq_printf(m, "R_AX_RPQ_RXBD_IDX=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX_V1)); + else + seq_printf(m, "R_AX_RPQ_RXBD_IDX=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX)); + } + + if (dmac_err & B_AX_WSEC_ERR_FLAG) { + if (chip->chip_id == RTL8852C) { + seq_printf(m, "R_AX_SEC_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG_IMR)); + seq_printf(m, "R_AX_SEC_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG)); + seq_printf(m, "R_AX_SEC_ENG_CTRL=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL)); + seq_printf(m, "R_AX_SEC_MPDU_PROC=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC)); + seq_printf(m, "R_AX_SEC_CAM_ACCESS=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS)); + seq_printf(m, "R_AX_SEC_CAM_RDATA=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA)); + seq_printf(m, "R_AX_SEC_DEBUG1=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_DEBUG1)); + seq_printf(m, "R_AX_SEC_TX_DEBUG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG)); + seq_printf(m, "R_AX_SEC_RX_DEBUG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG)); + + rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL, + B_AX_DBG_SEL0, 0x8B); + rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL, + B_AX_DBG_SEL1, 0x8B); + rtw89_write32_mask(rtwdev, R_AX_SYS_STATUS1, + B_AX_SEL_0XC0_MASK, 1); + for (i = 0; i < 0x10; i++) { + rtw89_write32_mask(rtwdev, R_AX_SEC_ENG_CTRL, + B_AX_SEC_DBG_PORT_FIELD_MASK, i); + seq_printf(m, "sel=%x,R_AX_SEC_DEBUG2=0x%08x\n", + i, rtw89_read32(rtwdev, R_AX_SEC_DEBUG2)); + } + } else { + seq_printf(m, "R_AX_SEC_ERR_IMR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_DEBUG)); + seq_printf(m, "R_AX_SEC_ENG_CTRL=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL)); + seq_printf(m, "R_AX_SEC_MPDU_PROC=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC)); + seq_printf(m, "R_AX_SEC_CAM_ACCESS=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS)); + seq_printf(m, "R_AX_SEC_CAM_RDATA=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA)); + seq_printf(m, "R_AX_SEC_CAM_WDATA=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_CAM_WDATA)); + seq_printf(m, "R_AX_SEC_TX_DEBUG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG)); + seq_printf(m, "R_AX_SEC_RX_DEBUG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG)); + seq_printf(m, "R_AX_SEC_TRX_PKT_CNT=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_TRX_PKT_CNT)); + seq_printf(m, "R_AX_SEC_TRX_BLK_CNT=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_TRX_BLK_CNT)); + } + } + + if (dmac_err & B_AX_MPDU_ERR_FLAG) { + seq_printf(m, "R_AX_MPDU_TX_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_IMR)); + seq_printf(m, "R_AX_MPDU_TX_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_ISR)); + seq_printf(m, "R_AX_MPDU_RX_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_IMR)); + seq_printf(m, "R_AX_MPDU_RX_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_ISR)); + } + + if (dmac_err & B_AX_STA_SCHEDULER_ERR_FLAG) { + seq_printf(m, "R_AX_STA_SCHEDULER_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_IMR)); + seq_printf(m, "R_AX_STA_SCHEDULER_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_ISR)); + } + + if (dmac_err & B_AX_WDE_DLE_ERR_FLAG) { + seq_printf(m, "R_AX_WDE_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR)); + seq_printf(m, "R_AX_WDE_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR)); + seq_printf(m, "R_AX_PLE_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR)); + seq_printf(m, "R_AX_PLE_ERR_FLAG_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR)); + } + + if (dmac_err & B_AX_TXPKTCTRL_ERR_FLAG) { + if (chip->chip_id == RTL8852C) { + seq_printf(m, "R_AX_TXPKTCTL_B0_ERRFLAG_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_IMR)); + seq_printf(m, "R_AX_TXPKTCTL_B0_ERRFLAG_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_ISR)); + seq_printf(m, "R_AX_TXPKTCTL_B1_ERRFLAG_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_IMR)); + seq_printf(m, "R_AX_TXPKTCTL_B1_ERRFLAG_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_ISR)); + } else { + seq_printf(m, "R_AX_TXPKTCTL_ERR_IMR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR)); + seq_printf(m, "R_AX_TXPKTCTL_ERR_IMR_ISR_B1=0x%08x\n", + rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR_B1)); + } + } + + if (dmac_err & B_AX_PLE_DLE_ERR_FLAG) { + seq_printf(m, "R_AX_WDE_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR)); + seq_printf(m, "R_AX_WDE_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR)); + seq_printf(m, "R_AX_PLE_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR)); + seq_printf(m, "R_AX_PLE_ERR_FLAG_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR)); + seq_printf(m, "R_AX_WD_CPUQ_OP_0=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_0)); + seq_printf(m, "R_AX_WD_CPUQ_OP_1=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_1)); + seq_printf(m, "R_AX_WD_CPUQ_OP_2=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_2)); + seq_printf(m, "R_AX_WD_CPUQ_OP_STATUS=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_STATUS)); + seq_printf(m, "R_AX_PL_CPUQ_OP_0=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_0)); + seq_printf(m, "R_AX_PL_CPUQ_OP_1=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_1)); + seq_printf(m, "R_AX_PL_CPUQ_OP_2=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_2)); + seq_printf(m, "R_AX_PL_CPUQ_OP_STATUS=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_STATUS)); + if (chip->chip_id == RTL8852C) { + seq_printf(m, "R_AX_RX_CTRL0=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RX_CTRL0)); + seq_printf(m, "R_AX_RX_CTRL1=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RX_CTRL1)); + seq_printf(m, "R_AX_RX_CTRL2=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RX_CTRL2)); + } else { + seq_printf(m, "R_AX_RXDMA_PKT_INFO_0=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_0)); + seq_printf(m, "R_AX_RXDMA_PKT_INFO_1=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_1)); + seq_printf(m, "R_AX_RXDMA_PKT_INFO_2=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_2)); + } + } + + if (dmac_err & B_AX_PKTIN_ERR_FLAG) { + seq_printf(m, "R_AX_PKTIN_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PKTIN_ERR_IMR)); + seq_printf(m, "R_AX_PKTIN_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PKTIN_ERR_ISR)); + } + + if (dmac_err & B_AX_DISPATCH_ERR_FLAG) { + seq_printf(m, "R_AX_HOST_DISPATCHER_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_IMR)); + seq_printf(m, "R_AX_HOST_DISPATCHER_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_ISR)); + seq_printf(m, "R_AX_CPU_DISPATCHER_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_IMR)); + seq_printf(m, "R_AX_CPU_DISPATCHER_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_ISR)); + seq_printf(m, "R_AX_OTHER_DISPATCHER_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_IMR)); + seq_printf(m, "R_AX_OTHER_DISPATCHER_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_ISR)); + } + + if (dmac_err & B_AX_BBRPT_ERR_FLAG) { + if (chip->chip_id == RTL8852C) { + seq_printf(m, "R_AX_BBRPT_COM_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR)); + seq_printf(m, "R_AX_BBRPT_COM_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_ISR)); + seq_printf(m, "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR)); + seq_printf(m, "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR)); + seq_printf(m, "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR)); + seq_printf(m, "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR)); + } else { + seq_printf(m, "R_AX_BBRPT_COM_ERR_IMR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR_ISR)); + seq_printf(m, "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR)); + seq_printf(m, "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR)); + seq_printf(m, "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR)); + seq_printf(m, "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR)); + } + } + + if (dmac_err & B_AX_HAXIDMA_ERR_FLAG && chip->chip_id == RTL8852C) { + seq_printf(m, "R_AX_HAXIDMA_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_HAXI_IDCT_MSK)); + seq_printf(m, "R_AX_HAXIDMA_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_HAXI_IDCT)); + } return 0; } -static int rtw89_debug_mac_dump_cmac_dbg(struct rtw89_dev *rtwdev, - struct seq_file *m) +static int rtw89_debug_mac_dump_cmac_err(struct rtw89_dev *rtwdev, + struct seq_file *m, + enum rtw89_mac_idx band) { + const struct rtw89_chip_info *chip = rtwdev->chip; + u32 offset = 0; + u32 cmac_err; int ret; - ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_CMAC_SEL); + ret = rtw89_mac_check_mac_en(rtwdev, band, RTW89_CMAC_SEL); if (ret) { - seq_puts(m, "[CMAC] : CMAC 0 not enabled\n"); + if (band) + seq_puts(m, "[CMAC] : CMAC1 not enabled\n"); + else + seq_puts(m, "[CMAC] : CMAC0 not enabled\n"); return ret; } - seq_printf(m, "R_AX_CMAC_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR)); - seq_printf(m, "[0]R_AX_SCHEDULE_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_ISR)); - seq_printf(m, "[1]R_AX_PTCL_ISR0=0x%08x\n", - rtw89_read32(rtwdev, R_AX_PTCL_ISR0)); - seq_printf(m, "[3]R_AX_DLE_CTRL=0x%08x\n", - rtw89_read32(rtwdev, R_AX_DLE_CTRL)); - seq_printf(m, "[4]R_AX_PHYINFO_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_ISR)); - seq_printf(m, "[5]R_AX_TXPWR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_TXPWR_ISR)); - seq_printf(m, "[6]R_AX_RMAC_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_RMAC_ERR_ISR)); - seq_printf(m, "[7]R_AX_TMAC_ERR_IMR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_TMAC_ERR_IMR_ISR)); - - ret = rtw89_mac_check_mac_en(rtwdev, 1, RTW89_CMAC_SEL); - if (ret) { - seq_puts(m, "[CMAC] : CMAC 1 not enabled\n"); - return ret; + if (band) + offset = RTW89_MAC_AX_BAND_REG_OFFSET; + + cmac_err = rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset); + seq_printf(m, "R_AX_CMAC_ERR_ISR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset)); + seq_printf(m, "R_AX_CMAC_FUNC_EN [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_CMAC_FUNC_EN + offset)); + seq_printf(m, "R_AX_CK_EN [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_CK_EN + offset)); + + if (cmac_err & B_AX_SCHEDULE_TOP_ERR_IND) { + seq_printf(m, "R_AX_SCHEDULE_ERR_IMR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_IMR + offset)); + seq_printf(m, "R_AX_SCHEDULE_ERR_ISR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_ISR + offset)); } - seq_printf(m, "R_AX_CMAC_ERR_ISR_C1=0x%08x\n", - rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR_C1)); - seq_printf(m, "[0]R_AX_SCHEDULE_ERR_ISR_C1=0x%08x\n", - rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_ISR_C1)); - seq_printf(m, "[1]R_AX_PTCL_ISR0_C1=0x%08x\n", - rtw89_read32(rtwdev, R_AX_PTCL_ISR0_C1)); - seq_printf(m, "[3]R_AX_DLE_CTRL_C1=0x%08x\n", - rtw89_read32(rtwdev, R_AX_DLE_CTRL_C1)); - seq_printf(m, "[4]R_AX_PHYINFO_ERR_ISR_C1=0x%02x\n", - rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_ISR_C1)); - seq_printf(m, "[5]R_AX_TXPWR_ISR_C1=0x%08x\n", - rtw89_read32(rtwdev, R_AX_TXPWR_ISR_C1)); - seq_printf(m, "[6]R_AX_RMAC_ERR_ISR_C1=0x%08x\n", - rtw89_read32(rtwdev, R_AX_RMAC_ERR_ISR_C1)); - seq_printf(m, "[7]R_AX_TMAC_ERR_IMR_ISR_C1=0x%08x\n", - rtw89_read32(rtwdev, R_AX_TMAC_ERR_IMR_ISR_C1)); + if (cmac_err & B_AX_PTCL_TOP_ERR_IND) { + seq_printf(m, "R_AX_PTCL_IMR0 [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_PTCL_IMR0 + offset)); + seq_printf(m, "R_AX_PTCL_ISR0 [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_PTCL_ISR0 + offset)); + } + + if (cmac_err & B_AX_DMA_TOP_ERR_IND) { + if (chip->chip_id == RTL8852C) { + seq_printf(m, "R_AX_RX_ERR_FLAG [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG + offset)); + seq_printf(m, "R_AX_RX_ERR_FLAG_IMR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG_IMR + offset)); + } else { + seq_printf(m, "R_AX_DLE_CTRL [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_DLE_CTRL + offset)); + } + } + + if (cmac_err & B_AX_DMA_TOP_ERR_IND || cmac_err & B_AX_WMAC_RX_ERR_IND) { + if (chip->chip_id == RTL8852C) { + seq_printf(m, "R_AX_PHYINFO_ERR_ISR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_ISR + offset)); + seq_printf(m, "R_AX_PHYINFO_ERR_IMR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR + offset)); + } else { + seq_printf(m, "R_AX_PHYINFO_ERR_IMR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR + offset)); + } + } + + if (cmac_err & B_AX_TXPWR_CTRL_ERR_IND) { + seq_printf(m, "R_AX_TXPWR_IMR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_TXPWR_IMR + offset)); + seq_printf(m, "R_AX_TXPWR_ISR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_TXPWR_ISR + offset)); + } + + if (cmac_err & B_AX_WMAC_TX_ERR_IND) { + if (chip->chip_id == RTL8852C) { + seq_printf(m, "R_AX_TRXPTCL_ERROR_INDICA [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_TRXPTCL_ERROR_INDICA + offset)); + seq_printf(m, "R_AX_TRXPTCL_ERROR_INDICA_MASK [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_TRXPTCL_ERROR_INDICA_MASK + offset)); + } else { + seq_printf(m, "R_AX_TMAC_ERR_IMR_ISR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_TMAC_ERR_IMR_ISR + offset)); + } + seq_printf(m, "R_AX_DBGSEL_TRXPTCL [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_DBGSEL_TRXPTCL + offset)); + } + + seq_printf(m, "R_AX_CMAC_ERR_IMR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_CMAC_ERR_IMR + offset)); + + return 0; +} + +static int rtw89_debug_mac_dump_cmac_dbg(struct rtw89_dev *rtwdev, + struct seq_file *m) +{ + rtw89_debug_mac_dump_cmac_err(rtwdev, m, RTW89_MAC_0); + if (rtwdev->dbcc_en) + rtw89_debug_mac_dump_cmac_err(rtwdev, m, RTW89_MAC_1); return 0; } @@ -1098,6 +1366,303 @@ static const struct rtw89_mac_dbg_port_info dbg_port_ptcl_c1 = { .rd_msk = B_AX_PTCL_DBG_INFO_MASK }; +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx0_5 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0xD, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx6 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x5, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx7 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x9, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx8 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x3, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_tx9_C = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x1, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_txD = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x0, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx0 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0xB, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx1 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x4, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx3 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x8, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx4 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x7, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx5_8 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x1, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_tx9 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x3, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_txA_C = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x0, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx0 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x8, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx1_2 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x0, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx3 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x6, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx4 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x0, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_hdt_rx5 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 2, + .sel_msk = B_AX_DISPATCHER_DBG_SEL_MASK, + .srt = 0x0, + .end = 0x0, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_rx_p0_0 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 1, + .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK, + .srt = 0x0, + .end = 0x3, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_rx_p0_1 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 1, + .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK, + .srt = 0x0, + .end = 0x6, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_rx_p0_2 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 1, + .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK, + .srt = 0x0, + .end = 0x0, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_cdt_rx_p1 = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 1, + .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK, + .srt = 0x8, + .end = 0xE, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_stf_ctrl = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 1, + .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK, + .srt = 0x0, + .end = 0x5, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_addr_ctrl = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 1, + .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK, + .srt = 0x0, + .end = 0x6, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_wde_intf = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 1, + .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK, + .srt = 0x0, + .end = 0xF, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_ple_intf = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 1, + .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK, + .srt = 0x0, + .end = 0x9, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + +static const struct rtw89_mac_dbg_port_info dbg_port_dspt_flow_ctrl = { + .sel_addr = R_AX_DISPATCHER_DBG_PORT, + .sel_byte = 1, + .sel_msk = B_AX_DISPATCHER_CH_SEL_MASK, + .srt = 0x0, + .end = 0x3, + .rd_addr = R_AX_DBG_PORT_SEL, + .rd_byte = 4, + .rd_msk = B_AX_DEBUG_ST_MASK +}; + static const struct rtw89_mac_dbg_port_info dbg_port_sch_c0 = { .sel_addr = R_AX_SCH_DBG_SEL, .sel_byte = 1, @@ -1508,7 +2073,7 @@ static const struct rtw89_mac_dbg_port_info dbg_port_pktinfo = { static const struct rtw89_mac_dbg_port_info dbg_port_pcie_txdma = { .sel_addr = R_AX_PCIE_DBG_CTRL, .sel_byte = 2, - .sel_msk = B_AX_DBG_SEL_MASK, + .sel_msk = B_AX_PCIE_DBG_SEL_MASK, .srt = 0x00, .end = 0x03, .rd_addr = R_AX_DBG_PORT_SEL, @@ -1519,7 +2084,7 @@ static const struct rtw89_mac_dbg_port_info dbg_port_pcie_txdma = { static const struct rtw89_mac_dbg_port_info dbg_port_pcie_rxdma = { .sel_addr = R_AX_PCIE_DBG_CTRL, .sel_byte = 2, - .sel_msk = B_AX_DBG_SEL_MASK, + .sel_msk = B_AX_PCIE_DBG_SEL_MASK, .srt = 0x00, .end = 0x04, .rd_addr = R_AX_DBG_PORT_SEL, @@ -1530,7 +2095,7 @@ static const struct rtw89_mac_dbg_port_info dbg_port_pcie_rxdma = { static const struct rtw89_mac_dbg_port_info dbg_port_pcie_cvt = { .sel_addr = R_AX_PCIE_DBG_CTRL, .sel_byte = 2, - .sel_msk = B_AX_DBG_SEL_MASK, + .sel_msk = B_AX_PCIE_DBG_SEL_MASK, .srt = 0x00, .end = 0x01, .rd_addr = R_AX_DBG_PORT_SEL, @@ -1541,7 +2106,7 @@ static const struct rtw89_mac_dbg_port_info dbg_port_pcie_cvt = { static const struct rtw89_mac_dbg_port_info dbg_port_pcie_cxpl = { .sel_addr = R_AX_PCIE_DBG_CTRL, .sel_byte = 2, - .sel_msk = B_AX_DBG_SEL_MASK, + .sel_msk = B_AX_PCIE_DBG_SEL_MASK, .srt = 0x00, .end = 0x05, .rd_addr = R_AX_DBG_PORT_SEL, @@ -1552,7 +2117,7 @@ static const struct rtw89_mac_dbg_port_info dbg_port_pcie_cxpl = { static const struct rtw89_mac_dbg_port_info dbg_port_pcie_io = { .sel_addr = R_AX_PCIE_DBG_CTRL, .sel_byte = 2, - .sel_msk = B_AX_DBG_SEL_MASK, + .sel_msk = B_AX_PCIE_DBG_SEL_MASK, .srt = 0x00, .end = 0x05, .rd_addr = R_AX_DBG_PORT_SEL, @@ -1563,7 +2128,7 @@ static const struct rtw89_mac_dbg_port_info dbg_port_pcie_io = { static const struct rtw89_mac_dbg_port_info dbg_port_pcie_misc = { .sel_addr = R_AX_PCIE_DBG_CTRL, .sel_byte = 2, - .sel_msk = B_AX_DBG_SEL_MASK, + .sel_msk = B_AX_PCIE_DBG_SEL_MASK, .srt = 0x00, .end = 0x06, .rd_addr = R_AX_DBG_PORT_SEL, @@ -1587,6 +2152,7 @@ rtw89_debug_mac_dbg_port_sel(struct seq_file *m, struct rtw89_dev *rtwdev, u32 sel) { const struct rtw89_mac_dbg_port_info *info; + u32 index; u32 val32; u16 val16; u8 val8; @@ -1862,6 +2428,235 @@ rtw89_debug_mac_dbg_port_sel(struct seq_file *m, info = &dbg_port_pktinfo; seq_puts(m, "Enable pktinfo dump.\n"); break; + case RTW89_DBG_PORT_SEL_DSPT_HDT_TX0: + rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL, + B_AX_DBG_SEL0, 0x80); + rtw89_write32_mask(rtwdev, R_AX_SYS_STATUS1, + B_AX_SEL_0XC0_MASK, 1); + fallthrough; + case RTW89_DBG_PORT_SEL_DSPT_HDT_TX1: + case RTW89_DBG_PORT_SEL_DSPT_HDT_TX2: + case RTW89_DBG_PORT_SEL_DSPT_HDT_TX3: + case RTW89_DBG_PORT_SEL_DSPT_HDT_TX4: + case RTW89_DBG_PORT_SEL_DSPT_HDT_TX5: + info = &dbg_port_dspt_hdt_tx0_5; + index = sel - RTW89_DBG_PORT_SEL_DSPT_HDT_TX0; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 0); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, index); + seq_printf(m, "Enable Dispatcher hdt tx%x dump.\n", index); + break; + case RTW89_DBG_PORT_SEL_DSPT_HDT_TX6: + info = &dbg_port_dspt_hdt_tx6; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 0); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 6); + seq_puts(m, "Enable Dispatcher hdt tx6 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_HDT_TX7: + info = &dbg_port_dspt_hdt_tx7; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 0); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 7); + seq_puts(m, "Enable Dispatcher hdt tx7 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_HDT_TX8: + info = &dbg_port_dspt_hdt_tx8; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 0); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 8); + seq_puts(m, "Enable Dispatcher hdt tx8 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_HDT_TX9: + case RTW89_DBG_PORT_SEL_DSPT_HDT_TXA: + case RTW89_DBG_PORT_SEL_DSPT_HDT_TXB: + case RTW89_DBG_PORT_SEL_DSPT_HDT_TXC: + info = &dbg_port_dspt_hdt_tx9_C; + index = sel + 9 - RTW89_DBG_PORT_SEL_DSPT_HDT_TX9; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 0); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, index); + seq_printf(m, "Enable Dispatcher hdt tx%x dump.\n", index); + break; + case RTW89_DBG_PORT_SEL_DSPT_HDT_TXD: + info = &dbg_port_dspt_hdt_txD; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 0); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 0xD); + seq_puts(m, "Enable Dispatcher hdt txD dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_CDT_TX0: + info = &dbg_port_dspt_cdt_tx0; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 1); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 0); + seq_puts(m, "Enable Dispatcher cdt tx0 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_CDT_TX1: + info = &dbg_port_dspt_cdt_tx1; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 1); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 1); + seq_puts(m, "Enable Dispatcher cdt tx1 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_CDT_TX3: + info = &dbg_port_dspt_cdt_tx3; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 1); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 3); + seq_puts(m, "Enable Dispatcher cdt tx3 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_CDT_TX4: + info = &dbg_port_dspt_cdt_tx4; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 1); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 4); + seq_puts(m, "Enable Dispatcher cdt tx4 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_CDT_TX5: + case RTW89_DBG_PORT_SEL_DSPT_CDT_TX6: + case RTW89_DBG_PORT_SEL_DSPT_CDT_TX7: + case RTW89_DBG_PORT_SEL_DSPT_CDT_TX8: + info = &dbg_port_dspt_cdt_tx5_8; + index = sel + 5 - RTW89_DBG_PORT_SEL_DSPT_CDT_TX5; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 1); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, index); + seq_printf(m, "Enable Dispatcher cdt tx%x dump.\n", index); + break; + case RTW89_DBG_PORT_SEL_DSPT_CDT_TX9: + info = &dbg_port_dspt_cdt_tx9; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 1); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 9); + seq_puts(m, "Enable Dispatcher cdt tx9 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_CDT_TXA: + case RTW89_DBG_PORT_SEL_DSPT_CDT_TXB: + case RTW89_DBG_PORT_SEL_DSPT_CDT_TXC: + info = &dbg_port_dspt_cdt_txA_C; + index = sel + 0xA - RTW89_DBG_PORT_SEL_DSPT_CDT_TXA; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 1); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, index); + seq_printf(m, "Enable Dispatcher cdt tx%x dump.\n", index); + break; + case RTW89_DBG_PORT_SEL_DSPT_HDT_RX0: + info = &dbg_port_dspt_hdt_rx0; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 2); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 0); + seq_puts(m, "Enable Dispatcher hdt rx0 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_HDT_RX1: + case RTW89_DBG_PORT_SEL_DSPT_HDT_RX2: + info = &dbg_port_dspt_hdt_rx1_2; + index = sel + 1 - RTW89_DBG_PORT_SEL_DSPT_HDT_RX1; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 2); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, index); + seq_printf(m, "Enable Dispatcher hdt rx%x dump.\n", index); + break; + case RTW89_DBG_PORT_SEL_DSPT_HDT_RX3: + info = &dbg_port_dspt_hdt_rx3; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 2); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 3); + seq_puts(m, "Enable Dispatcher hdt rx3 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_HDT_RX4: + info = &dbg_port_dspt_hdt_rx4; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 2); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 4); + seq_puts(m, "Enable Dispatcher hdt rx4 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_HDT_RX5: + info = &dbg_port_dspt_hdt_rx5; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 2); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 5); + seq_puts(m, "Enable Dispatcher hdt rx5 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P0_0: + info = &dbg_port_dspt_cdt_rx_p0_0; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 3); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 0); + seq_puts(m, "Enable Dispatcher cdt rx part0 0 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P0: + case RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P0_1: + info = &dbg_port_dspt_cdt_rx_p0_1; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 3); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 1); + seq_puts(m, "Enable Dispatcher cdt rx part0 1 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P0_2: + info = &dbg_port_dspt_cdt_rx_p0_2; + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 3); + rtw89_write16_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_CH_SEL_MASK, 2); + seq_puts(m, "Enable Dispatcher cdt rx part0 2 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P1: + info = &dbg_port_dspt_cdt_rx_p1; + rtw89_write8_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 3); + seq_puts(m, "Enable Dispatcher cdt rx part1 dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_STF_CTRL: + info = &dbg_port_dspt_stf_ctrl; + rtw89_write8_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 4); + seq_puts(m, "Enable Dispatcher stf control dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_ADDR_CTRL: + info = &dbg_port_dspt_addr_ctrl; + rtw89_write8_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 5); + seq_puts(m, "Enable Dispatcher addr control dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_WDE_INTF: + info = &dbg_port_dspt_wde_intf; + rtw89_write8_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 6); + seq_puts(m, "Enable Dispatcher wde interface dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_PLE_INTF: + info = &dbg_port_dspt_ple_intf; + rtw89_write8_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 7); + seq_puts(m, "Enable Dispatcher ple interface dump.\n"); + break; + case RTW89_DBG_PORT_SEL_DSPT_FLOW_CTRL: + info = &dbg_port_dspt_flow_ctrl; + rtw89_write8_mask(rtwdev, info->sel_addr, + B_AX_DISPATCHER_INTN_SEL_MASK, 8); + seq_puts(m, "Enable Dispatcher flow control dump.\n"); + break; case RTW89_DBG_PORT_SEL_PCIE_TXDMA: info = &dbg_port_pcie_txdma; val32 = rtw89_read32(rtwdev, R_AX_DBG_CTRL); @@ -1914,7 +2709,7 @@ rtw89_debug_mac_dbg_port_sel(struct seq_file *m, info = &dbg_port_pcie_misc2; val16 = rtw89_read16(rtwdev, R_AX_PCIE_DBG_CTRL); val16 = u16_replace_bits(val16, PCIE_MISC2_DBG_SEL, - B_AX_DBG_SEL_MASK); + B_AX_PCIE_DBG_SEL_MASK); rtw89_write16(rtwdev, R_AX_PCIE_DBG_CTRL, val16); seq_puts(m, "Enable pcie misc2 dump.\n"); break; @@ -1940,6 +2735,10 @@ static bool is_dbg_port_valid(struct rtw89_dev *rtwdev, u32 sel) sel >= RTW89_DBG_PORT_SEL_WDE_BUFMGN_FREEPG && sel <= RTW89_DBG_PORT_SEL_PKTINFO) return false; + if (rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL) && + sel >= RTW89_DBG_PORT_SEL_DSPT_HDT_TX0 && + sel <= RTW89_DBG_PORT_SEL_DSPT_FLOW_CTRL) + return false; if (rtw89_mac_check_mac_en(rtwdev, 0, RTW89_CMAC_SEL) && sel >= RTW89_DBG_PORT_SEL_PTCL_C0 && sel <= RTW89_DBG_PORT_SEL_TXTF_INFOH_C0) @@ -2010,6 +2809,50 @@ static int rtw89_debug_mac_dbg_port_dump(struct rtw89_dev *rtwdev, case_DBG_SEL(PLE_QUEMGN_QLNKTBL); case_DBG_SEL(PLE_QUEMGN_QEMPTY); case_DBG_SEL(PKTINFO); + case_DBG_SEL(DSPT_HDT_TX0); + case_DBG_SEL(DSPT_HDT_TX1); + case_DBG_SEL(DSPT_HDT_TX2); + case_DBG_SEL(DSPT_HDT_TX3); + case_DBG_SEL(DSPT_HDT_TX4); + case_DBG_SEL(DSPT_HDT_TX5); + case_DBG_SEL(DSPT_HDT_TX6); + case_DBG_SEL(DSPT_HDT_TX7); + case_DBG_SEL(DSPT_HDT_TX8); + case_DBG_SEL(DSPT_HDT_TX9); + case_DBG_SEL(DSPT_HDT_TXA); + case_DBG_SEL(DSPT_HDT_TXB); + case_DBG_SEL(DSPT_HDT_TXC); + case_DBG_SEL(DSPT_HDT_TXD); + case_DBG_SEL(DSPT_HDT_TXE); + case_DBG_SEL(DSPT_HDT_TXF); + case_DBG_SEL(DSPT_CDT_TX0); + case_DBG_SEL(DSPT_CDT_TX1); + case_DBG_SEL(DSPT_CDT_TX3); + case_DBG_SEL(DSPT_CDT_TX4); + case_DBG_SEL(DSPT_CDT_TX5); + case_DBG_SEL(DSPT_CDT_TX6); + case_DBG_SEL(DSPT_CDT_TX7); + case_DBG_SEL(DSPT_CDT_TX8); + case_DBG_SEL(DSPT_CDT_TX9); + case_DBG_SEL(DSPT_CDT_TXA); + case_DBG_SEL(DSPT_CDT_TXB); + case_DBG_SEL(DSPT_CDT_TXC); + case_DBG_SEL(DSPT_HDT_RX0); + case_DBG_SEL(DSPT_HDT_RX1); + case_DBG_SEL(DSPT_HDT_RX2); + case_DBG_SEL(DSPT_HDT_RX3); + case_DBG_SEL(DSPT_HDT_RX4); + case_DBG_SEL(DSPT_HDT_RX5); + case_DBG_SEL(DSPT_CDT_RX_P0); + case_DBG_SEL(DSPT_CDT_RX_P0_0); + case_DBG_SEL(DSPT_CDT_RX_P0_1); + case_DBG_SEL(DSPT_CDT_RX_P0_2); + case_DBG_SEL(DSPT_CDT_RX_P1); + case_DBG_SEL(DSPT_STF_CTRL); + case_DBG_SEL(DSPT_ADDR_CTRL); + case_DBG_SEL(DSPT_WDE_INTF); + case_DBG_SEL(DSPT_PLE_INTF); + case_DBG_SEL(DSPT_FLOW_CTRL); case_DBG_SEL(PCIE_TXDMA); case_DBG_SEL(PCIE_RXDMA); case_DBG_SEL(PCIE_CVT); @@ -2379,6 +3222,7 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) else seq_printf(m, "Legacy %d", rate->legacy); seq_printf(m, "%s", rtwsta->ra_report.might_fallback_legacy ? " FB_G" : ""); + seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(rate->bw)); seq_printf(m, "\t(hw_rate=0x%x)", rtwsta->ra_report.hw_rate); seq_printf(m, "\t==> agg_wait=%d (%d)\n", rtwsta->max_agg_wait, sta->deflink.agg.max_rc_amsdu_len); @@ -2404,6 +3248,7 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) he_gi_str[rate->he_gi] : "N/A"); break; } + seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(status->bw)); seq_printf(m, "\t(hw_rate=0x%x)\n", rtwsta->rx_hw_rate); rssi = ewma_rssi_read(&rtwsta->avg_rssi); diff --git a/drivers/net/wireless/realtek/rtw89/debug.h b/drivers/net/wireless/realtek/rtw89/debug.h index ee243aadde87..e7971583acbc 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.h +++ b/drivers/net/wireless/realtek/rtw89/debug.h @@ -26,6 +26,7 @@ enum rtw89_debug_mask { RTW89_DBG_HW_SCAN = BIT(15), RTW89_DBG_SAR = BIT(16), RTW89_DBG_STATE = BIT(17), + RTW89_DBG_WOW = BIT(18), RTW89_DBG_UNEXP = BIT(31), }; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index d21f87e25ae1..10c5ed21da02 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -85,15 +85,31 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, { struct rtw89_fw_hdr_section_info *section_info; const u8 *fw_end = fw + len; + const u8 *fwdynhdr; const u8 *bin; + u32 base_hdr_len; u32 i; if (!info) return -EINVAL; info->section_num = GET_FW_HDR_SEC_NUM(fw); - info->hdr_len = RTW89_FW_HDR_SIZE + - info->section_num * RTW89_FW_SECTION_HDR_SIZE; + base_hdr_len = RTW89_FW_HDR_SIZE + + info->section_num * RTW89_FW_SECTION_HDR_SIZE; + info->dynamic_hdr_en = GET_FW_HDR_DYN_HDR(fw); + + if (info->dynamic_hdr_en) { + info->hdr_len = GET_FW_HDR_LEN(fw); + info->dynamic_hdr_len = info->hdr_len - base_hdr_len; + fwdynhdr = fw + base_hdr_len; + if (GET_FW_DYNHDR_LEN(fwdynhdr) != info->dynamic_hdr_len) { + rtw89_err(rtwdev, "[ERR]invalid fw dynamic header len\n"); + return -EINVAL; + } + } else { + info->hdr_len = base_hdr_len; + info->dynamic_hdr_len = 0; + } bin = fw + info->hdr_len; @@ -515,6 +531,11 @@ int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type) u8 val; int ret; + rtw89_mac_disable_cpu(rtwdev); + ret = rtw89_mac_enable_cpu(rtwdev, 0, true); + if (ret) + return ret; + if (!fw || !len) { rtw89_err(rtwdev, "fw type %d isn't recognized\n", type); return -ENOENT; @@ -534,7 +555,7 @@ int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type) goto fwdl_err; } - ret = rtw89_fw_download_hdr(rtwdev, fw, info.hdr_len); + ret = rtw89_fw_download_hdr(rtwdev, fw, info.hdr_len - info.dynamic_hdr_len); if (ret) { ret = -EBUSY; goto fwdl_err; @@ -848,6 +869,56 @@ fail: return ret; } +static int rtw89_fw_h2c_add_wow_fw_ofld(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, + enum rtw89_fw_pkt_ofld_type type, + u8 *id) +{ + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_pktofld_info *info; + struct sk_buff *skb; + int ret; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + switch (type) { + case RTW89_PKT_OFLD_TYPE_PS_POLL: + skb = ieee80211_pspoll_get(rtwdev->hw, vif); + break; + case RTW89_PKT_OFLD_TYPE_PROBE_RSP: + skb = ieee80211_proberesp_get(rtwdev->hw, vif); + break; + case RTW89_PKT_OFLD_TYPE_NULL_DATA: + skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, false); + break; + case RTW89_PKT_OFLD_TYPE_QOS_NULL: + skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, true); + break; + default: + goto err; + } + + if (!skb) + goto err; + + list_add_tail(&info->list, &rtw_wow->pkt_list); + ret = rtw89_fw_h2c_add_pkt_offload(rtwdev, &info->id, skb); + kfree_skb(skb); + + if (ret) + return ret; + + *id = info->id; + return 0; + +err: + kfree(info); + return -ENOMEM; +} + #define H2C_GENERAL_PKT_LEN 6 #define H2C_GENERAL_PKT_ID_UND 0xff int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, u8 macid) @@ -2879,6 +2950,7 @@ int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev, case RTW89_PKT_DROP_SEL_MACID_BK_ONCE: case RTW89_PKT_DROP_SEL_MACID_VI_ONCE: case RTW89_PKT_DROP_SEL_MACID_VO_ONCE: + case RTW89_PKT_DROP_SEL_BAND_ONCE: break; default: rtw89_debug(rtwdev, RTW89_DBG_FW, @@ -2894,6 +2966,14 @@ int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev, RTW89_SET_FWCMD_PKT_DROP_PORT(skb->data, params->port); RTW89_SET_FWCMD_PKT_DROP_MBSSID(skb->data, params->mbssid); RTW89_SET_FWCMD_PKT_DROP_ROLE_A_INFO_TF_TRS(skb->data, params->tf_trs); + RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_0(skb->data, + params->macid_band_sel[0]); + RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_1(skb->data, + params->macid_band_sel[1]); + RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_2(skb->data, + params->macid_band_sel[2]); + RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_3(skb->data, + params->macid_band_sel[3]); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, @@ -2913,3 +2993,234 @@ fail: dev_kfree_skb_any(skb); return ret; } + +#define H2C_KEEP_ALIVE_LEN 4 +int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + bool enable) +{ + struct sk_buff *skb; + u8 pkt_id = 0; + int ret; + + if (enable) { + ret = rtw89_fw_h2c_add_wow_fw_ofld(rtwdev, rtwvif, + RTW89_PKT_OFLD_TYPE_NULL_DATA, &pkt_id); + if (ret) + return -EPERM; + } + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_KEEP_ALIVE_LEN); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for keep alive\n"); + return -ENOMEM; + } + + skb_put(skb, H2C_KEEP_ALIVE_LEN); + + RTW89_SET_KEEP_ALIVE_ENABLE(skb->data, enable); + RTW89_SET_KEEP_ALIVE_PKT_NULL_ID(skb->data, pkt_id); + RTW89_SET_KEEP_ALIVE_PERIOD(skb->data, 5); + RTW89_SET_KEEP_ALIVE_MACID(skb->data, rtwvif->mac_id); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, + H2C_CL_MAC_WOW, + H2C_FUNC_KEEP_ALIVE, 0, 1, + H2C_KEEP_ALIVE_LEN); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; + +fail: + dev_kfree_skb_any(skb); + + return ret; +} + +#define H2C_DISCONNECT_DETECT_LEN 8 +int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, bool enable) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct sk_buff *skb; + u8 macid = rtwvif->mac_id; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_DISCONNECT_DETECT_LEN); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for keep alive\n"); + return -ENOMEM; + } + + skb_put(skb, H2C_DISCONNECT_DETECT_LEN); + + if (test_bit(RTW89_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags)) { + RTW89_SET_DISCONNECT_DETECT_ENABLE(skb->data, enable); + RTW89_SET_DISCONNECT_DETECT_DISCONNECT(skb->data, !enable); + RTW89_SET_DISCONNECT_DETECT_MAC_ID(skb->data, macid); + RTW89_SET_DISCONNECT_DETECT_CHECK_PERIOD(skb->data, 100); + RTW89_SET_DISCONNECT_DETECT_TRY_PKT_COUNT(skb->data, 5); + } + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, + H2C_CL_MAC_WOW, + H2C_FUNC_DISCONNECT_DETECT, 0, 1, + H2C_DISCONNECT_DETECT_LEN); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; + +fail: + dev_kfree_skb_any(skb); + + return ret; +} + +#define H2C_WOW_GLOBAL_LEN 8 +int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + bool enable) +{ + struct sk_buff *skb; + u8 macid = rtwvif->mac_id; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WOW_GLOBAL_LEN); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for keep alive\n"); + return -ENOMEM; + } + + skb_put(skb, H2C_WOW_GLOBAL_LEN); + + RTW89_SET_WOW_GLOBAL_ENABLE(skb->data, enable); + RTW89_SET_WOW_GLOBAL_MAC_ID(skb->data, macid); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, + H2C_CL_MAC_WOW, + H2C_FUNC_WOW_GLOBAL, 0, 1, + H2C_WOW_GLOBAL_LEN); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; + +fail: + dev_kfree_skb_any(skb); + + return ret; +} + +#define H2C_WAKEUP_CTRL_LEN 4 +int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, + bool enable) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct sk_buff *skb; + u8 macid = rtwvif->mac_id; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WAKEUP_CTRL_LEN); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for keep alive\n"); + return -ENOMEM; + } + + skb_put(skb, H2C_WAKEUP_CTRL_LEN); + + if (rtw_wow->pattern_cnt) + RTW89_SET_WOW_WAKEUP_CTRL_PATTERN_MATCH_ENABLE(skb->data, enable); + if (test_bit(RTW89_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags)) + RTW89_SET_WOW_WAKEUP_CTRL_MAGIC_ENABLE(skb->data, enable); + if (test_bit(RTW89_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags)) + RTW89_SET_WOW_WAKEUP_CTRL_DEAUTH_ENABLE(skb->data, enable); + + RTW89_SET_WOW_WAKEUP_CTRL_MAC_ID(skb->data, macid); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, + H2C_CL_MAC_WOW, + H2C_FUNC_WAKEUP_CTRL, 0, 1, + H2C_WAKEUP_CTRL_LEN); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; + +fail: + dev_kfree_skb_any(skb); + + return ret; +} + +#define H2C_WOW_CAM_UPD_LEN 24 +int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev, + struct rtw89_wow_cam_info *cam_info) +{ + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WOW_CAM_UPD_LEN); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for keep alive\n"); + return -ENOMEM; + } + + skb_put(skb, H2C_WOW_CAM_UPD_LEN); + + RTW89_SET_WOW_CAM_UPD_R_W(skb->data, cam_info->r_w); + RTW89_SET_WOW_CAM_UPD_IDX(skb->data, cam_info->idx); + if (cam_info->valid) { + RTW89_SET_WOW_CAM_UPD_WKFM1(skb->data, cam_info->mask[0]); + RTW89_SET_WOW_CAM_UPD_WKFM2(skb->data, cam_info->mask[1]); + RTW89_SET_WOW_CAM_UPD_WKFM3(skb->data, cam_info->mask[2]); + RTW89_SET_WOW_CAM_UPD_WKFM4(skb->data, cam_info->mask[3]); + RTW89_SET_WOW_CAM_UPD_CRC(skb->data, cam_info->crc); + RTW89_SET_WOW_CAM_UPD_NEGATIVE_PATTERN_MATCH(skb->data, + cam_info->negative_pattern_match); + RTW89_SET_WOW_CAM_UPD_SKIP_MAC_HDR(skb->data, + cam_info->skip_mac_hdr); + RTW89_SET_WOW_CAM_UPD_UC(skb->data, cam_info->uc); + RTW89_SET_WOW_CAM_UPD_MC(skb->data, cam_info->mc); + RTW89_SET_WOW_CAM_UPD_BC(skb->data, cam_info->bc); + } + RTW89_SET_WOW_CAM_UPD_VALID(skb->data, cam_info->valid); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, + H2C_CL_MAC_WOW, + H2C_FUNC_WOW_CAM_UPD, 0, 1, + H2C_WOW_CAM_UPD_LEN); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 6ef392ef9c6f..509a3eac5ffe 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -176,6 +176,8 @@ struct rtw89_fw_hdr_section_info { struct rtw89_fw_bin_info { u8 section_num; u32 hdr_len; + bool dynamic_hdr_en; + u32 dynamic_hdr_len; struct rtw89_fw_hdr_section_info section_info[FWDL_SECTION_MAX_NUM]; }; @@ -495,6 +497,8 @@ static inline void RTW89_SET_EDCA_PARAM(void *cmd, u32 val) le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(23, 16)) #define GET_FW_HDR_SUBINDEX(fwhdr) \ le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(31, 24)) +#define GET_FW_HDR_LEN(fwhdr) \ + le32_get_bits(*((const __le32 *)(fwhdr) + 3), GENMASK(23, 16)) #define GET_FW_HDR_MONTH(fwhdr) \ le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(7, 0)) #define GET_FW_HDR_DATE(fwhdr) \ @@ -507,8 +511,16 @@ static inline void RTW89_SET_EDCA_PARAM(void *cmd, u32 val) le32_get_bits(*((const __le32 *)(fwhdr) + 5), GENMASK(31, 0)) #define GET_FW_HDR_SEC_NUM(fwhdr) \ le32_get_bits(*((const __le32 *)(fwhdr) + 6), GENMASK(15, 8)) +#define GET_FW_HDR_DYN_HDR(fwhdr) \ + le32_get_bits(*((const __le32 *)(fwhdr) + 7), BIT(16)) #define GET_FW_HDR_CMD_VERSERION(fwhdr) \ le32_get_bits(*((const __le32 *)(fwhdr) + 7), GENMASK(31, 24)) + +#define GET_FW_DYNHDR_LEN(fwdynhdr) \ + le32_get_bits(*((const __le32 *)(fwdynhdr)), GENMASK(31, 0)) +#define GET_FW_DYNHDR_COUNT(fwdynhdr) \ + le32_get_bits(*((const __le32 *)(fwdynhdr) + 1), GENMASK(31, 0)) + static inline void SET_FW_HDR_PART_SIZE(void *fwhdr, u32 val) { le32p_replace_bits((__le32 *)fwhdr + 7, val, GENMASK(15, 0)); @@ -1861,6 +1873,231 @@ static inline void RTW89_SET_FWCMD_PKT_DROP_ROLE_A_INFO_TF_TRS(void *cmd, u32 va le32p_replace_bits((__le32 *)cmd + 1, val, GENMASK(15, 8)); } +static inline void RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_0(void *cmd, u32 val) +{ + le32p_replace_bits((__le32 *)cmd + 2, val, GENMASK(31, 0)); +} + +static inline void RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_1(void *cmd, u32 val) +{ + le32p_replace_bits((__le32 *)cmd + 3, val, GENMASK(31, 0)); +} + +static inline void RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_2(void *cmd, u32 val) +{ + le32p_replace_bits((__le32 *)cmd + 4, val, GENMASK(31, 0)); +} + +static inline void RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_3(void *cmd, u32 val) +{ + le32p_replace_bits((__le32 *)cmd + 5, val, GENMASK(31, 0)); +} + +static inline void RTW89_SET_KEEP_ALIVE_ENABLE(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, GENMASK(1, 0)); +} + +static inline void RTW89_SET_KEEP_ALIVE_PKT_NULL_ID(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, GENMASK(15, 8)); +} + +static inline void RTW89_SET_KEEP_ALIVE_PERIOD(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, GENMASK(24, 16)); +} + +static inline void RTW89_SET_KEEP_ALIVE_MACID(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, GENMASK(31, 24)); +} + +static inline void RTW89_SET_DISCONNECT_DETECT_ENABLE(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(0)); +} + +static inline void RTW89_SET_DISCONNECT_DETECT_TRYOK_BCNFAIL_COUNT_EN(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(1)); +} + +static inline void RTW89_SET_DISCONNECT_DETECT_DISCONNECT(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(2)); +} + +static inline void RTW89_SET_DISCONNECT_DETECT_MAC_ID(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, GENMASK(15, 8)); +} + +static inline void RTW89_SET_DISCONNECT_DETECT_CHECK_PERIOD(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, GENMASK(23, 16)); +} + +static inline void RTW89_SET_DISCONNECT_DETECT_TRY_PKT_COUNT(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, GENMASK(31, 24)); +} + +static inline void RTW89_SET_DISCONNECT_DETECT_TRYOK_BCNFAIL_COUNT_LIMIT(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)(h2c) + 1, val, GENMASK(7, 0)); +} + +static inline void RTW89_SET_WOW_GLOBAL_ENABLE(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(0)); +} + +static inline void RTW89_SET_WOW_GLOBAL_DROP_ALL_PKT(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(1)); +} + +static inline void RTW89_SET_WOW_GLOBAL_RX_PARSE_AFTER_WAKE(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(2)); +} + +static inline void RTW89_SET_WOW_GLOBAL_WAKE_BAR_PULLED(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(3)); +} + +static inline void RTW89_SET_WOW_GLOBAL_MAC_ID(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, GENMASK(15, 8)); +} + +static inline void RTW89_SET_WOW_GLOBAL_PAIRWISE_SEC_ALGO(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, GENMASK(23, 16)); +} + +static inline void RTW89_SET_WOW_GLOBAL_GROUP_SEC_ALGO(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, GENMASK(31, 24)); +} + +static inline void RTW89_SET_WOW_GLOBAL_REMOTECTRL_INFO_CONTENT(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)(h2c) + 1, val, GENMASK(31, 0)); +} + +static inline void RTW89_SET_WOW_WAKEUP_CTRL_PATTERN_MATCH_ENABLE(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(0)); +} + +static inline void RTW89_SET_WOW_WAKEUP_CTRL_MAGIC_ENABLE(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(1)); +} + +static inline void RTW89_SET_WOW_WAKEUP_CTRL_HW_UNICAST_ENABLE(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(2)); +} + +static inline void RTW89_SET_WOW_WAKEUP_CTRL_FW_UNICAST_ENABLE(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(3)); +} + +static inline void RTW89_SET_WOW_WAKEUP_CTRL_DEAUTH_ENABLE(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(4)); +} + +static inline void RTW89_SET_WOW_WAKEUP_CTRL_REKEYP_ENABLE(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(5)); +} + +static inline void RTW89_SET_WOW_WAKEUP_CTRL_EAP_ENABLE(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(6)); +} + +static inline void RTW89_SET_WOW_WAKEUP_CTRL_ALL_DATA_ENABLE(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(7)); +} + +static inline void RTW89_SET_WOW_WAKEUP_CTRL_MAC_ID(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, GENMASK(31, 24)); +} + +static inline void RTW89_SET_WOW_CAM_UPD_R_W(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, BIT(0)); +} + +static inline void RTW89_SET_WOW_CAM_UPD_IDX(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c, val, GENMASK(7, 1)); +} + +static inline void RTW89_SET_WOW_CAM_UPD_WKFM1(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c + 1, val, GENMASK(31, 0)); +} + +static inline void RTW89_SET_WOW_CAM_UPD_WKFM2(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c + 2, val, GENMASK(31, 0)); +} + +static inline void RTW89_SET_WOW_CAM_UPD_WKFM3(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c + 3, val, GENMASK(31, 0)); +} + +static inline void RTW89_SET_WOW_CAM_UPD_WKFM4(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c + 4, val, GENMASK(31, 0)); +} + +static inline void RTW89_SET_WOW_CAM_UPD_CRC(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c + 5, val, GENMASK(15, 0)); +} + +static inline void RTW89_SET_WOW_CAM_UPD_NEGATIVE_PATTERN_MATCH(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c + 5, val, BIT(22)); +} + +static inline void RTW89_SET_WOW_CAM_UPD_SKIP_MAC_HDR(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c + 5, val, BIT(23)); +} + +static inline void RTW89_SET_WOW_CAM_UPD_UC(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c + 5, val, BIT(24)); +} + +static inline void RTW89_SET_WOW_CAM_UPD_MC(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c + 5, val, BIT(25)); +} + +static inline void RTW89_SET_WOW_CAM_UPD_BC(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c + 5, val, BIT(26)); +} + +static inline void RTW89_SET_WOW_CAM_UPD_VALID(void *h2c, u32 val) +{ + le32p_replace_bits((__le32 *)h2c + 5, val, BIT(31)); +} + enum rtw89_btc_btf_h2c_class { BTFC_SET = 0x10, BTFC_GET = 0x11, @@ -2677,6 +2914,14 @@ struct rtw89_fw_h2c_rf_reg_info { #define H2C_FUNC_LOG_CFG 0x0 #define H2C_FUNC_MAC_GENERAL_PKT 0x1 +/* CLASS 1 - WOW */ +#define H2C_CL_MAC_WOW 0x1 +#define H2C_FUNC_KEEP_ALIVE 0x0 +#define H2C_FUNC_DISCONNECT_DETECT 0x1 +#define H2C_FUNC_WOW_GLOBAL 0x2 +#define H2C_FUNC_WAKEUP_CTRL 0x8 +#define H2C_FUNC_WOW_CAM_UPD 0xC + /* CLASS 2 - PS */ #define H2C_CL_MAC_PS 0x2 #define H2C_FUNC_MAC_LPS_PARM 0x0 @@ -2846,7 +3091,21 @@ int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, u8 act, u8 noa_id); int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, bool en); - +int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + bool enable); +int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, bool enable); +int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + bool enable); +int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, bool enable); +int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + bool enable); +int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, bool enable); + +int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev, + struct rtw89_wow_cam_info *cam_info); static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index 3531a859d6c8..ecd603a88134 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -7,6 +7,7 @@ #include "debug.h" #include "fw.h" #include "mac.h" +#include "pci.h" #include "ps.h" #include "reg.h" #include "util.h" @@ -274,106 +275,163 @@ static void rtw89_mac_dump_l0_to_l1(struct rtw89_dev *rtwdev, } } -static void rtw89_mac_dump_err_status(struct rtw89_dev *rtwdev, - enum mac_ax_err_info err) +static void rtw89_mac_dump_dmac_err_status(struct rtw89_dev *rtwdev) { - u32 dmac_err, cmac_err; + const struct rtw89_chip_info *chip = rtwdev->chip; + u32 dmac_err; + int i, ret; - if (err != MAC_AX_ERR_L1_ERR_DMAC && - err != MAC_AX_ERR_L0_PROMOTE_TO_L1 && - err != MAC_AX_ERR_L0_ERR_CMAC0 && - err != MAC_AX_ERR_L0_ERR_CMAC1) + ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL); + if (ret) { + rtw89_warn(rtwdev, "[DMAC] : DMAC not enabled\n"); return; + } - rtw89_info(rtwdev, "--->\nerr=0x%x\n", err); - rtw89_info(rtwdev, "R_AX_SER_DBG_INFO =0x%08x\n", - rtw89_read32(rtwdev, R_AX_SER_DBG_INFO)); - - cmac_err = rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR); - rtw89_info(rtwdev, "R_AX_CMAC_ERR_ISR =0x%08x\n", cmac_err); dmac_err = rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR); - rtw89_info(rtwdev, "R_AX_DMAC_ERR_ISR =0x%08x\n", dmac_err); + rtw89_info(rtwdev, "R_AX_DMAC_ERR_ISR=0x%08x\n", dmac_err); + rtw89_info(rtwdev, "R_AX_DMAC_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_DMAC_ERR_IMR)); if (dmac_err) { - rtw89_info(rtwdev, "R_AX_WDE_ERR_FLAG_CFG =0x%08x ", - rtw89_read32(rtwdev, R_AX_WDE_ERR_FLAG_CFG)); - rtw89_info(rtwdev, "R_AX_PLE_ERR_FLAG_CFG =0x%08x\n", - rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_CFG)); + rtw89_info(rtwdev, "R_AX_WDE_ERR_FLAG_CFG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WDE_ERR_FLAG_CFG_NUM1)); + rtw89_info(rtwdev, "R_AX_PLE_ERR_FLAG_CFG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_CFG_NUM1)); + if (chip->chip_id == RTL8852C) { + rtw89_info(rtwdev, "R_AX_PLE_ERRFLAG_MSG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PLE_ERRFLAG_MSG)); + rtw89_info(rtwdev, "R_AX_WDE_ERRFLAG_MSG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_WDE_ERRFLAG_MSG)); + rtw89_info(rtwdev, "R_AX_PLE_DBGERR_LOCKEN=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PLE_DBGERR_LOCKEN)); + rtw89_info(rtwdev, "R_AX_PLE_DBGERR_STS=0x%08x\n", + rtw89_read32(rtwdev, R_AX_PLE_DBGERR_STS)); + } } if (dmac_err & B_AX_WDRLS_ERR_FLAG) { - rtw89_info(rtwdev, "R_AX_WDRLS_ERR_IMR =0x%08x ", + rtw89_info(rtwdev, "R_AX_WDRLS_ERR_IMR=0x%08x\n", rtw89_read32(rtwdev, R_AX_WDRLS_ERR_IMR)); - rtw89_info(rtwdev, "R_AX_WDRLS_ERR_ISR =0x%08x\n", + rtw89_info(rtwdev, "R_AX_WDRLS_ERR_ISR=0x%08x\n", rtw89_read32(rtwdev, R_AX_WDRLS_ERR_ISR)); + if (chip->chip_id == RTL8852C) + rtw89_info(rtwdev, "R_AX_RPQ_RXBD_IDX=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX_V1)); + else + rtw89_info(rtwdev, "R_AX_RPQ_RXBD_IDX=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX)); } if (dmac_err & B_AX_WSEC_ERR_FLAG) { - rtw89_info(rtwdev, "R_AX_SEC_ERR_IMR_ISR =0x%08x\n", - rtw89_read32(rtwdev, R_AX_SEC_DEBUG)); - rtw89_info(rtwdev, "SEC_local_Register 0x9D00 =0x%08x\n", - rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL)); - rtw89_info(rtwdev, "SEC_local_Register 0x9D04 =0x%08x\n", - rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC)); - rtw89_info(rtwdev, "SEC_local_Register 0x9D10 =0x%08x\n", - rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS)); - rtw89_info(rtwdev, "SEC_local_Register 0x9D14 =0x%08x\n", - rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA)); - rtw89_info(rtwdev, "SEC_local_Register 0x9D18 =0x%08x\n", - rtw89_read32(rtwdev, R_AX_SEC_CAM_WDATA)); - rtw89_info(rtwdev, "SEC_local_Register 0x9D20 =0x%08x\n", - rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG)); - rtw89_info(rtwdev, "SEC_local_Register 0x9D24 =0x%08x\n", - rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG)); - rtw89_info(rtwdev, "SEC_local_Register 0x9D28 =0x%08x\n", - rtw89_read32(rtwdev, R_AX_SEC_TRX_PKT_CNT)); - rtw89_info(rtwdev, "SEC_local_Register 0x9D2C =0x%08x\n", - rtw89_read32(rtwdev, R_AX_SEC_TRX_BLK_CNT)); + if (chip->chip_id == RTL8852C) { + rtw89_info(rtwdev, "R_AX_SEC_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG_IMR)); + rtw89_info(rtwdev, "R_AX_SEC_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG)); + rtw89_info(rtwdev, "R_AX_SEC_ENG_CTRL=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL)); + rtw89_info(rtwdev, "R_AX_SEC_MPDU_PROC=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC)); + rtw89_info(rtwdev, "R_AX_SEC_CAM_ACCESS=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS)); + rtw89_info(rtwdev, "R_AX_SEC_CAM_RDATA=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA)); + rtw89_info(rtwdev, "R_AX_SEC_DEBUG1=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_DEBUG1)); + rtw89_info(rtwdev, "R_AX_SEC_TX_DEBUG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG)); + rtw89_info(rtwdev, "R_AX_SEC_RX_DEBUG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG)); + + rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL, + B_AX_DBG_SEL0, 0x8B); + rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL, + B_AX_DBG_SEL1, 0x8B); + rtw89_write32_mask(rtwdev, R_AX_SYS_STATUS1, + B_AX_SEL_0XC0_MASK, 1); + for (i = 0; i < 0x10; i++) { + rtw89_write32_mask(rtwdev, R_AX_SEC_ENG_CTRL, + B_AX_SEC_DBG_PORT_FIELD_MASK, i); + rtw89_info(rtwdev, "sel=%x,R_AX_SEC_DEBUG2=0x%08x\n", + i, rtw89_read32(rtwdev, R_AX_SEC_DEBUG2)); + } + } else { + rtw89_info(rtwdev, "R_AX_SEC_ERR_IMR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_DEBUG)); + rtw89_info(rtwdev, "R_AX_SEC_ENG_CTRL=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL)); + rtw89_info(rtwdev, "R_AX_SEC_MPDU_PROC=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC)); + rtw89_info(rtwdev, "R_AX_SEC_CAM_ACCESS=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS)); + rtw89_info(rtwdev, "R_AX_SEC_CAM_RDATA=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA)); + rtw89_info(rtwdev, "R_AX_SEC_CAM_WDATA=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_CAM_WDATA)); + rtw89_info(rtwdev, "R_AX_SEC_TX_DEBUG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG)); + rtw89_info(rtwdev, "R_AX_SEC_RX_DEBUG=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG)); + rtw89_info(rtwdev, "R_AX_SEC_TRX_PKT_CNT=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_TRX_PKT_CNT)); + rtw89_info(rtwdev, "R_AX_SEC_TRX_BLK_CNT=0x%08x\n", + rtw89_read32(rtwdev, R_AX_SEC_TRX_BLK_CNT)); + } } if (dmac_err & B_AX_MPDU_ERR_FLAG) { - rtw89_info(rtwdev, "R_AX_MPDU_TX_ERR_IMR =0x%08x ", + rtw89_info(rtwdev, "R_AX_MPDU_TX_ERR_IMR=0x%08x\n", rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_IMR)); - rtw89_info(rtwdev, "R_AX_MPDU_TX_ERR_ISR =0x%08x\n", + rtw89_info(rtwdev, "R_AX_MPDU_TX_ERR_ISR=0x%08x\n", rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_ISR)); - rtw89_info(rtwdev, "R_AX_MPDU_RX_ERR_IMR =0x%08x ", + rtw89_info(rtwdev, "R_AX_MPDU_RX_ERR_IMR=0x%08x\n", rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_IMR)); - rtw89_info(rtwdev, "R_AX_MPDU_RX_ERR_ISR =0x%08x\n", + rtw89_info(rtwdev, "R_AX_MPDU_RX_ERR_ISR=0x%08x\n", rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_ISR)); } if (dmac_err & B_AX_STA_SCHEDULER_ERR_FLAG) { - rtw89_info(rtwdev, "R_AX_STA_SCHEDULER_ERR_IMR =0x%08x ", + rtw89_info(rtwdev, "R_AX_STA_SCHEDULER_ERR_IMR=0x%08x\n", rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_IMR)); - rtw89_info(rtwdev, "R_AX_STA_SCHEDULER_ERR_ISR= 0x%08x\n", + rtw89_info(rtwdev, "R_AX_STA_SCHEDULER_ERR_ISR=0x%08x\n", rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_ISR)); } if (dmac_err & B_AX_WDE_DLE_ERR_FLAG) { - rtw89_info(rtwdev, "R_AX_WDE_ERR_IMR=0x%08x ", + rtw89_info(rtwdev, "R_AX_WDE_ERR_IMR=0x%08x\n", rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR)); rtw89_info(rtwdev, "R_AX_WDE_ERR_ISR=0x%08x\n", rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR)); - rtw89_info(rtwdev, "R_AX_PLE_ERR_IMR=0x%08x ", + rtw89_info(rtwdev, "R_AX_PLE_ERR_IMR=0x%08x\n", rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR)); rtw89_info(rtwdev, "R_AX_PLE_ERR_FLAG_ISR=0x%08x\n", rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR)); - dump_err_status_dispatcher(rtwdev); } if (dmac_err & B_AX_TXPKTCTRL_ERR_FLAG) { - rtw89_info(rtwdev, "R_AX_TXPKTCTL_ERR_IMR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR)); - rtw89_info(rtwdev, "R_AX_TXPKTCTL_ERR_IMR_ISR_B1=0x%08x\n", - rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR_B1)); + if (chip->chip_id == RTL8852C) { + rtw89_info(rtwdev, "R_AX_TXPKTCTL_B0_ERRFLAG_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_IMR)); + rtw89_info(rtwdev, "R_AX_TXPKTCTL_B0_ERRFLAG_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_ISR)); + rtw89_info(rtwdev, "R_AX_TXPKTCTL_B1_ERRFLAG_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_IMR)); + rtw89_info(rtwdev, "R_AX_TXPKTCTL_B1_ERRFLAG_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_ISR)); + } else { + rtw89_info(rtwdev, "R_AX_TXPKTCTL_ERR_IMR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR)); + rtw89_info(rtwdev, "R_AX_TXPKTCTL_ERR_IMR_ISR_B1=0x%08x\n", + rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR_B1)); + } } if (dmac_err & B_AX_PLE_DLE_ERR_FLAG) { - rtw89_info(rtwdev, "R_AX_WDE_ERR_IMR=0x%08x ", + rtw89_info(rtwdev, "R_AX_WDE_ERR_IMR=0x%08x\n", rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR)); rtw89_info(rtwdev, "R_AX_WDE_ERR_ISR=0x%08x\n", rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR)); - rtw89_info(rtwdev, "R_AX_PLE_ERR_IMR=0x%08x ", + rtw89_info(rtwdev, "R_AX_PLE_ERR_IMR=0x%08x\n", rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR)); rtw89_info(rtwdev, "R_AX_PLE_ERR_FLAG_ISR=0x%08x\n", rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR)); @@ -393,86 +451,190 @@ static void rtw89_mac_dump_err_status(struct rtw89_dev *rtwdev, rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_2)); rtw89_info(rtwdev, "R_AX_PL_CPUQ_OP_STATUS=0x%08x\n", rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_STATUS)); - rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_0=0x%08x\n", - rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_0)); - rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_1=0x%08x\n", - rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_1)); - rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_2=0x%08x\n", - rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_2)); - dump_err_status_dispatcher(rtwdev); + if (chip->chip_id == RTL8852C) { + rtw89_info(rtwdev, "R_AX_RX_CTRL0=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RX_CTRL0)); + rtw89_info(rtwdev, "R_AX_RX_CTRL1=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RX_CTRL1)); + rtw89_info(rtwdev, "R_AX_RX_CTRL2=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RX_CTRL2)); + } else { + rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_0=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_0)); + rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_1=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_1)); + rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_2=0x%08x\n", + rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_2)); + } } if (dmac_err & B_AX_PKTIN_ERR_FLAG) { - rtw89_info(rtwdev, "R_AX_PKTIN_ERR_IMR =0x%08x ", - rtw89_read32(rtwdev, R_AX_PKTIN_ERR_IMR)); - rtw89_info(rtwdev, "R_AX_PKTIN_ERR_ISR =0x%08x\n", - rtw89_read32(rtwdev, R_AX_PKTIN_ERR_ISR)); - rtw89_info(rtwdev, "R_AX_PKTIN_ERR_IMR =0x%08x ", + rtw89_info(rtwdev, "R_AX_PKTIN_ERR_IMR=0x%08x\n", rtw89_read32(rtwdev, R_AX_PKTIN_ERR_IMR)); - rtw89_info(rtwdev, "R_AX_PKTIN_ERR_ISR =0x%08x\n", + rtw89_info(rtwdev, "R_AX_PKTIN_ERR_ISR=0x%08x\n", rtw89_read32(rtwdev, R_AX_PKTIN_ERR_ISR)); } - if (dmac_err & B_AX_DISPATCH_ERR_FLAG) - dump_err_status_dispatcher(rtwdev); + if (dmac_err & B_AX_DISPATCH_ERR_FLAG) { + rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_IMR)); + rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_ISR)); + rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_IMR)); + rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_ISR)); + rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_IMR)); + rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_ISR)); + } + + if (dmac_err & B_AX_BBRPT_ERR_FLAG) { + if (chip->chip_id == RTL8852C) { + rtw89_info(rtwdev, "R_AX_BBRPT_COM_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR)); + rtw89_info(rtwdev, "R_AX_BBRPT_COM_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_ISR)); + rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR)); + rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR)); + rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR)); + rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR)); + } else { + rtw89_info(rtwdev, "R_AX_BBRPT_COM_ERR_IMR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR_ISR)); + rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR)); + rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR)); + rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR)); + rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR)); + } + } - if (dmac_err & B_AX_DLE_CPUIO_ERR_FLAG) { - rtw89_info(rtwdev, "R_AX_CPUIO_ERR_IMR=0x%08x ", - rtw89_read32(rtwdev, R_AX_CPUIO_ERR_IMR)); - rtw89_info(rtwdev, "R_AX_CPUIO_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_CPUIO_ERR_ISR)); + if (dmac_err & B_AX_HAXIDMA_ERR_FLAG && chip->chip_id == RTL8852C) { + rtw89_info(rtwdev, "R_AX_HAXIDMA_ERR_IMR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_HAXI_IDCT_MSK)); + rtw89_info(rtwdev, "R_AX_HAXIDMA_ERR_ISR=0x%08x\n", + rtw89_read32(rtwdev, R_AX_HAXI_IDCT)); } +} + +static void rtw89_mac_dump_cmac_err_status(struct rtw89_dev *rtwdev, + u8 band) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + u32 offset = 0; + u32 cmac_err; + int ret; - if (dmac_err & BIT(11)) { - rtw89_info(rtwdev, "R_AX_BBRPT_COM_ERR_IMR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR_ISR)); + ret = rtw89_mac_check_mac_en(rtwdev, band, RTW89_CMAC_SEL); + if (ret) { + if (band) + rtw89_warn(rtwdev, "[CMAC] : CMAC1 not enabled\n"); + else + rtw89_warn(rtwdev, "[CMAC] : CMAC0 not enabled\n"); + return; } + if (band) + offset = RTW89_MAC_AX_BAND_REG_OFFSET; + + cmac_err = rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset); + rtw89_info(rtwdev, "R_AX_CMAC_ERR_ISR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset)); + rtw89_info(rtwdev, "R_AX_CMAC_FUNC_EN [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_CMAC_FUNC_EN + offset)); + rtw89_info(rtwdev, "R_AX_CK_EN [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_CK_EN + offset)); + if (cmac_err & B_AX_SCHEDULE_TOP_ERR_IND) { - rtw89_info(rtwdev, "R_AX_SCHEDULE_ERR_IMR=0x%08x ", - rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_IMR)); - rtw89_info(rtwdev, "R_AX_SCHEDULE_ERR_ISR=0x%04x\n", - rtw89_read16(rtwdev, R_AX_SCHEDULE_ERR_ISR)); + rtw89_info(rtwdev, "R_AX_SCHEDULE_ERR_IMR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_IMR + offset)); + rtw89_info(rtwdev, "R_AX_SCHEDULE_ERR_ISR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_ISR + offset)); } if (cmac_err & B_AX_PTCL_TOP_ERR_IND) { - rtw89_info(rtwdev, "R_AX_PTCL_IMR0=0x%08x ", - rtw89_read32(rtwdev, R_AX_PTCL_IMR0)); - rtw89_info(rtwdev, "R_AX_PTCL_ISR0=0x%08x\n", - rtw89_read32(rtwdev, R_AX_PTCL_ISR0)); + rtw89_info(rtwdev, "R_AX_PTCL_IMR0 [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_PTCL_IMR0 + offset)); + rtw89_info(rtwdev, "R_AX_PTCL_ISR0 [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_PTCL_ISR0 + offset)); } if (cmac_err & B_AX_DMA_TOP_ERR_IND) { - rtw89_info(rtwdev, "R_AX_DLE_CTRL=0x%08x\n", - rtw89_read32(rtwdev, R_AX_DLE_CTRL)); + if (chip->chip_id == RTL8852C) { + rtw89_info(rtwdev, "R_AX_RX_ERR_FLAG [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG + offset)); + rtw89_info(rtwdev, "R_AX_RX_ERR_FLAG_IMR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG_IMR + offset)); + } else { + rtw89_info(rtwdev, "R_AX_DLE_CTRL [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_DLE_CTRL + offset)); + } } - if (cmac_err & B_AX_PHYINTF_ERR_IND) { - rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_IMR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR)); + if (cmac_err & B_AX_DMA_TOP_ERR_IND || cmac_err & B_AX_WMAC_RX_ERR_IND) { + if (chip->chip_id == RTL8852C) { + rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_ISR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_ISR + offset)); + rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_IMR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR + offset)); + } else { + rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_IMR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR + offset)); + } } if (cmac_err & B_AX_TXPWR_CTRL_ERR_IND) { - rtw89_info(rtwdev, "R_AX_TXPWR_IMR=0x%08x ", - rtw89_read32(rtwdev, R_AX_TXPWR_IMR)); - rtw89_info(rtwdev, "R_AX_TXPWR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_TXPWR_ISR)); - } - - if (cmac_err & B_AX_WMAC_RX_ERR_IND) { - rtw89_info(rtwdev, "R_AX_DBGSEL_TRXPTCL=0x%08x ", - rtw89_read32(rtwdev, R_AX_DBGSEL_TRXPTCL)); - rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_ISR=0x%08x\n", - rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_ISR)); + rtw89_info(rtwdev, "R_AX_TXPWR_IMR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_TXPWR_IMR + offset)); + rtw89_info(rtwdev, "R_AX_TXPWR_ISR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_TXPWR_ISR + offset)); } if (cmac_err & B_AX_WMAC_TX_ERR_IND) { - rtw89_info(rtwdev, "R_AX_TMAC_ERR_IMR_ISR=0x%08x ", - rtw89_read32(rtwdev, R_AX_TMAC_ERR_IMR_ISR)); - rtw89_info(rtwdev, "R_AX_DBGSEL_TRXPTCL=0x%08x\n", - rtw89_read32(rtwdev, R_AX_DBGSEL_TRXPTCL)); + if (chip->chip_id == RTL8852C) { + rtw89_info(rtwdev, "R_AX_TRXPTCL_ERROR_INDICA [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_TRXPTCL_ERROR_INDICA + offset)); + rtw89_info(rtwdev, "R_AX_TRXPTCL_ERROR_INDICA_MASK [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_TRXPTCL_ERROR_INDICA_MASK + offset)); + } else { + rtw89_info(rtwdev, "R_AX_TMAC_ERR_IMR_ISR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_TMAC_ERR_IMR_ISR + offset)); + } + rtw89_info(rtwdev, "R_AX_DBGSEL_TRXPTCL [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_DBGSEL_TRXPTCL + offset)); } + rtw89_info(rtwdev, "R_AX_CMAC_ERR_IMR [%d]=0x%08x\n", band, + rtw89_read32(rtwdev, R_AX_CMAC_ERR_IMR + offset)); +} + +static void rtw89_mac_dump_err_status(struct rtw89_dev *rtwdev, + enum mac_ax_err_info err) +{ + if (err != MAC_AX_ERR_L1_ERR_DMAC && + err != MAC_AX_ERR_L0_PROMOTE_TO_L1 && + err != MAC_AX_ERR_L0_ERR_CMAC0 && + err != MAC_AX_ERR_L0_ERR_CMAC1) + return; + + rtw89_info(rtwdev, "--->\nerr=0x%x\n", err); + rtw89_info(rtwdev, "R_AX_SER_DBG_INFO =0x%08x\n", + rtw89_read32(rtwdev, R_AX_SER_DBG_INFO)); + + rtw89_mac_dump_dmac_err_status(rtwdev); + rtw89_mac_dump_cmac_err_status(rtwdev, RTW89_MAC_0); + if (rtwdev->dbcc_en) + rtw89_mac_dump_cmac_err_status(rtwdev, RTW89_MAC_1); + rtwdev->hci.ops->dump_err_status(rtwdev); if (err == MAC_AX_ERR_L0_PROMOTE_TO_L1) @@ -1306,6 +1468,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = { .ple_qt47 = {525, 0, 32, 20, 1034, 13, 1199, 0, 1053, 62, 160, 1037,}, /* PCIE 64 */ .ple_qt58 = {147, 0, 16, 20, 157, 13, 229, 0, 172, 14, 24, 0,}, + /* 8852A PCIE WOW */ + .ple_qt_52a_wow = {264, 0, 32, 20, 64, 13, 1005, 0, 64, 128, 120,}, }; EXPORT_SYMBOL(rtw89_mac_size); @@ -1333,6 +1497,60 @@ static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev, return cfg; } +static bool mac_is_txq_empty(struct rtw89_dev *rtwdev) +{ + struct rtw89_mac_dle_dfi_qempty qempty; + u32 qnum, qtmp, val32, msk32; + int i, j, ret; + + qnum = rtwdev->chip->wde_qempty_acq_num; + qempty.dle_type = DLE_CTRL_TYPE_WDE; + + for (i = 0; i < qnum; i++) { + qempty.grpsel = i; + ret = dle_dfi_qempty(rtwdev, &qempty); + if (ret) { + rtw89_warn(rtwdev, "dle dfi acq empty %d\n", ret); + return false; + } + qtmp = qempty.qempty; + for (j = 0 ; j < QEMP_ACQ_GRP_MACID_NUM; j++) { + val32 = FIELD_GET(QEMP_ACQ_GRP_QSEL_MASK, qtmp); + if (val32 != QEMP_ACQ_GRP_QSEL_MASK) + return false; + qtmp >>= QEMP_ACQ_GRP_QSEL_SH; + } + } + + qempty.grpsel = rtwdev->chip->wde_qempty_mgq_sel; + ret = dle_dfi_qempty(rtwdev, &qempty); + if (ret) { + rtw89_warn(rtwdev, "dle dfi mgq empty %d\n", ret); + return false; + } + msk32 = B_CMAC0_MGQ_NORMAL | B_CMAC0_MGQ_NO_PWRSAV | B_CMAC0_CPUMGQ; + if ((qempty.qempty & msk32) != msk32) + return false; + + if (rtwdev->dbcc_en) { + msk32 |= B_CMAC1_MGQ_NORMAL | B_CMAC1_MGQ_NO_PWRSAV | B_CMAC1_CPUMGQ; + if ((qempty.qempty & msk32) != msk32) + return false; + } + + msk32 = B_AX_WDE_EMPTY_QTA_DMAC_WLAN_CPU | B_AX_WDE_EMPTY_QTA_DMAC_DATA_CPU | + B_AX_PLE_EMPTY_QTA_DMAC_WLAN_CPU | B_AX_PLE_EMPTY_QTA_DMAC_H2C | + B_AX_WDE_EMPTY_QUE_OTHERS | B_AX_PLE_EMPTY_QUE_DMAC_MPDU_TX | + B_AX_WDE_EMPTY_QTA_DMAC_CPUIO | B_AX_PLE_EMPTY_QTA_DMAC_CPUIO | + B_AX_WDE_EMPTY_QUE_DMAC_PKTIN | B_AX_WDE_EMPTY_QTA_DMAC_HIF | + B_AX_PLE_EMPTY_QUE_DMAC_SEC_TX | B_AX_WDE_EMPTY_QTA_DMAC_PKTIN | + B_AX_PLE_EMPTY_QTA_DMAC_B0_TXPL | B_AX_PLE_EMPTY_QTA_DMAC_B1_TXPL | + B_AX_PLE_EMPTY_QTA_DMAC_MPDU_TX; + val32 = rtw89_read32(rtwdev, R_AX_DLE_EMPTY0); + + return (val32 & msk32) == msk32; +} + static inline u32 dle_used_size(const struct rtw89_dle_size *wde, const struct rtw89_dle_size *ple) { @@ -1431,10 +1649,8 @@ static int dle_mix_cfg(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg #define INVALID_QT_WCPU U16_MAX #define SET_QUOTA_VAL(_min_x, _max_x, _module, _idx) \ do { \ - val = ((_min_x) & \ - B_AX_ ## _module ## _MIN_SIZE_MASK) | \ - (((_max_x) << 16) & \ - B_AX_ ## _module ## _MAX_SIZE_MASK); \ + val = u32_encode_bits(_min_x, B_AX_ ## _module ## _MIN_SIZE_MASK) | \ + u32_encode_bits(_max_x, B_AX_ ## _module ## _MAX_SIZE_MASK); \ rtw89_write32(rtwdev, \ R_AX_ ## _module ## _QTA ## _idx ## _CFG, \ val); \ @@ -1478,8 +1694,48 @@ static void ple_quota_cfg(struct rtw89_dev *rtwdev, SET_QUOTA(tx_rpt, PLE, 11); } +int rtw89_mac_resize_ple_rx_quota(struct rtw89_dev *rtwdev, bool wow) +{ + const struct rtw89_ple_quota *min_cfg, *max_cfg; + const struct rtw89_dle_mem *cfg; + u32 val; + + if (rtwdev->chip->chip_id == RTL8852C) + return 0; + + if (rtwdev->mac.qta_mode != RTW89_QTA_SCC) { + rtw89_err(rtwdev, "[ERR]support SCC mode only\n"); + return -EINVAL; + } + + if (wow) + cfg = get_dle_mem_cfg(rtwdev, RTW89_QTA_WOW); + else + cfg = get_dle_mem_cfg(rtwdev, RTW89_QTA_SCC); + if (!cfg) { + rtw89_err(rtwdev, "[ERR]get_dle_mem_cfg\n"); + return -EINVAL; + } + + min_cfg = cfg->ple_min_qt; + max_cfg = cfg->ple_max_qt; + SET_QUOTA(cma0_dma, PLE, 6); + SET_QUOTA(cma1_dma, PLE, 7); + + return 0; +} #undef SET_QUOTA +void rtw89_mac_hw_mgnt_sec(struct rtw89_dev *rtwdev, bool enable) +{ + u32 msk32 = B_AX_UC_MGNT_DEC | B_AX_BMC_MGNT_DEC; + + if (enable) + rtw89_write32_set(rtwdev, R_AX_SEC_ENG_CTRL, msk32); + else + rtw89_write32_clr(rtwdev, R_AX_SEC_ENG_CTRL, msk32); +} + static void dle_quota_cfg(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg, u16 ext_wde_min_qt_wcpu) @@ -1829,10 +2085,10 @@ static int scheduler_init(struct rtw89_dev *rtwdev, u8 mac_idx) return 0; } -static int rtw89_mac_typ_fltr_opt(struct rtw89_dev *rtwdev, - enum rtw89_machdr_frame_type type, - enum rtw89_mac_fwd_target fwd_target, - u8 mac_idx) +int rtw89_mac_typ_fltr_opt(struct rtw89_dev *rtwdev, + enum rtw89_machdr_frame_type type, + enum rtw89_mac_fwd_target fwd_target, + u8 mac_idx) { u32 reg; u32 val; @@ -3116,7 +3372,7 @@ static void rtw89_disable_fw_watchdog(struct rtw89_dev *rtwdev) rtw89_mac_mem_write(rtwdev, R_AX_WDT_STATUS, val32, RTW89_MAC_MEM_CPU_LOCAL); } -static void rtw89_mac_disable_cpu(struct rtw89_dev *rtwdev) +void rtw89_mac_disable_cpu(struct rtw89_dev *rtwdev) { clear_bit(RTW89_FLAG_FW_RDY, rtwdev->flags); @@ -3131,8 +3387,7 @@ static void rtw89_mac_disable_cpu(struct rtw89_dev *rtwdev) rtw89_write32_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); } -static int rtw89_mac_enable_cpu(struct rtw89_dev *rtwdev, u8 boot_reason, - bool dlfw) +int rtw89_mac_enable_cpu(struct rtw89_dev *rtwdev, u8 boot_reason, bool dlfw) { u32 val; int ret; @@ -3271,11 +3526,6 @@ int rtw89_mac_partial_init(struct rtw89_dev *rtwdev) return ret; } - rtw89_mac_disable_cpu(rtwdev); - ret = rtw89_mac_enable_cpu(rtwdev, 0, true); - if (ret) - return ret; - ret = rtw89_fw_download(rtwdev, RTW89_FW_NORMAL); if (ret) return ret; @@ -4867,3 +5117,24 @@ void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) rtw89_mac_pkt_drop_vif_iter, rtwvif); } + +int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx band) +{ + struct rtw89_pkt_drop_params params = {0}; + bool empty; + int i, ret = 0, try_cnt = 3; + + params.mac_band = band; + params.sel = RTW89_PKT_DROP_SEL_BAND_ONCE; + + for (i = 0; i < try_cnt; i++) { + ret = read_poll_timeout(mac_is_txq_empty, empty, empty, 50, + 50000, false, rtwdev); + if (ret) + rtw89_fw_h2c_pkt_drop(rtwdev, ¶ms); + else + return 0; + } + return ret; +} diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index a6cbafb75a2b..045e8ec61a41 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -211,6 +211,51 @@ enum rtw89_mac_dbg_port_sel { RTW89_DBG_PORT_SEL_PLE_QUEMGN_QLNKTBL, RTW89_DBG_PORT_SEL_PLE_QUEMGN_QEMPTY, RTW89_DBG_PORT_SEL_PKTINFO, + /* DISPATCHER related */ + RTW89_DBG_PORT_SEL_DSPT_HDT_TX0, + RTW89_DBG_PORT_SEL_DSPT_HDT_TX1, + RTW89_DBG_PORT_SEL_DSPT_HDT_TX2, + RTW89_DBG_PORT_SEL_DSPT_HDT_TX3, + RTW89_DBG_PORT_SEL_DSPT_HDT_TX4, + RTW89_DBG_PORT_SEL_DSPT_HDT_TX5, + RTW89_DBG_PORT_SEL_DSPT_HDT_TX6, + RTW89_DBG_PORT_SEL_DSPT_HDT_TX7, + RTW89_DBG_PORT_SEL_DSPT_HDT_TX8, + RTW89_DBG_PORT_SEL_DSPT_HDT_TX9, + RTW89_DBG_PORT_SEL_DSPT_HDT_TXA, + RTW89_DBG_PORT_SEL_DSPT_HDT_TXB, + RTW89_DBG_PORT_SEL_DSPT_HDT_TXC, + RTW89_DBG_PORT_SEL_DSPT_HDT_TXD, + RTW89_DBG_PORT_SEL_DSPT_HDT_TXE, + RTW89_DBG_PORT_SEL_DSPT_HDT_TXF, + RTW89_DBG_PORT_SEL_DSPT_CDT_TX0, + RTW89_DBG_PORT_SEL_DSPT_CDT_TX1, + RTW89_DBG_PORT_SEL_DSPT_CDT_TX3, + RTW89_DBG_PORT_SEL_DSPT_CDT_TX4, + RTW89_DBG_PORT_SEL_DSPT_CDT_TX5, + RTW89_DBG_PORT_SEL_DSPT_CDT_TX6, + RTW89_DBG_PORT_SEL_DSPT_CDT_TX7, + RTW89_DBG_PORT_SEL_DSPT_CDT_TX8, + RTW89_DBG_PORT_SEL_DSPT_CDT_TX9, + RTW89_DBG_PORT_SEL_DSPT_CDT_TXA, + RTW89_DBG_PORT_SEL_DSPT_CDT_TXB, + RTW89_DBG_PORT_SEL_DSPT_CDT_TXC, + RTW89_DBG_PORT_SEL_DSPT_HDT_RX0, + RTW89_DBG_PORT_SEL_DSPT_HDT_RX1, + RTW89_DBG_PORT_SEL_DSPT_HDT_RX2, + RTW89_DBG_PORT_SEL_DSPT_HDT_RX3, + RTW89_DBG_PORT_SEL_DSPT_HDT_RX4, + RTW89_DBG_PORT_SEL_DSPT_HDT_RX5, + RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P0, + RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P0_0, + RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P0_1, + RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P0_2, + RTW89_DBG_PORT_SEL_DSPT_CDT_RX_P1, + RTW89_DBG_PORT_SEL_DSPT_STF_CTRL, + RTW89_DBG_PORT_SEL_DSPT_ADDR_CTRL, + RTW89_DBG_PORT_SEL_DSPT_WDE_INTF, + RTW89_DBG_PORT_SEL_DSPT_PLE_INTF, + RTW89_DBG_PORT_SEL_DSPT_FLOW_CTRL, /* PCIE related */ RTW89_DBG_PORT_SEL_PCIE_TXDMA, RTW89_DBG_PORT_SEL_PCIE_RXDMA, @@ -395,6 +440,7 @@ enum rtw89_mac_bf_rrsc_rate { #define ACCESS_CMAC(_addr) \ ({typeof(_addr) __addr = (_addr); \ __addr >= R_AX_CMAC_REG_START && __addr <= R_AX_CMAC_REG_END; }) +#define RTW89_MAC_AX_BAND_REG_OFFSET 0x2000 #define PTCL_IDLE_POLL_CNT 10000 #define SW_CVR_DUR_US 8 @@ -420,6 +466,17 @@ enum rtw89_mac_bf_rrsc_rate { #define S_AX_PLE_PAGE_SEL_128 1 #define S_AX_PLE_PAGE_SEL_256 2 +#define B_CMAC0_MGQ_NORMAL BIT(2) +#define B_CMAC0_MGQ_NO_PWRSAV BIT(3) +#define B_CMAC0_CPUMGQ BIT(4) +#define B_CMAC1_MGQ_NORMAL BIT(10) +#define B_CMAC1_MGQ_NO_PWRSAV BIT(11) +#define B_CMAC1_CPUMGQ BIT(12) + +#define QEMP_ACQ_GRP_MACID_NUM 8 +#define QEMP_ACQ_GRP_QSEL_SH 4 +#define QEMP_ACQ_GRP_QSEL_MASK 0xF + #define SDIO_LOCAL_BASE_ADDR 0x80000000 #define PWR_CMD_WRITE 0 @@ -719,6 +776,7 @@ struct rtw89_mac_size_set { const struct rtw89_ple_quota ple_qt46; const struct rtw89_ple_quota ple_qt47; const struct rtw89_ple_quota ple_qt58; + const struct rtw89_ple_quota ple_qt_52a_wow; }; extern const struct rtw89_mac_size_set rtw89_mac_size; @@ -815,6 +873,8 @@ int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif); +void rtw89_mac_disable_cpu(struct rtw89_dev *rtwdev); +int rtw89_mac_enable_cpu(struct rtw89_dev *rtwdev, u8 boot_reason, bool dlfw); int rtw89_mac_enable_bb_rf(struct rtw89_dev *rtwdev); int rtw89_mac_disable_bb_rf(struct rtw89_dev *rtwdev); @@ -966,6 +1026,16 @@ static inline void rtw89_mac_ctrl_hci_dma_trx(struct rtw89_dev *rtwdev, B_AX_HCI_TXDMA_EN | B_AX_HCI_RXDMA_EN); } +static inline bool rtw89_mac_get_power_state(struct rtw89_dev *rtwdev) +{ + u32 val; + + val = rtw89_read32_mask(rtwdev, R_AX_IC_PWR_STATE, + B_AX_WLMAC_PWR_STE_MASK); + + return !!val; +} + int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, bool resume, u32 tx_time); int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, @@ -1024,5 +1094,12 @@ void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); u16 rtw89_mac_dle_buf_req(struct rtw89_dev *rtwdev, u16 buf_len, bool wd); int rtw89_mac_set_cpuio(struct rtw89_dev *rtwdev, struct rtw89_cpuio_ctrl *ctrl_para, bool wd); +int rtw89_mac_typ_fltr_opt(struct rtw89_dev *rtwdev, + enum rtw89_machdr_frame_type type, + enum rtw89_mac_fwd_target fwd_target, u8 mac_idx); +int rtw89_mac_resize_ple_rx_quota(struct rtw89_dev *rtwdev, bool wow); +int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx band); +void rtw89_mac_hw_mgnt_sec(struct rtw89_dev *rtwdev, bool wow); #endif diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index a296bfa8188f..6e79bf899901 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -14,6 +14,7 @@ #include "sar.h" #include "ser.h" #include "util.h" +#include "wow.h" static void rtw89_ops_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, @@ -916,6 +917,55 @@ static int rtw89_ops_set_tid_config(struct ieee80211_hw *hw, return 0; } +#ifdef CONFIG_PM +static int rtw89_ops_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan) +{ + struct rtw89_dev *rtwdev = hw->priv; + int ret; + + set_bit(RTW89_FLAG_FORBIDDEN_TRACK_WROK, rtwdev->flags); + cancel_delayed_work_sync(&rtwdev->track_work); + + mutex_lock(&rtwdev->mutex); + ret = rtw89_wow_suspend(rtwdev, wowlan); + mutex_unlock(&rtwdev->mutex); + + if (ret) { + rtw89_warn(rtwdev, "failed to suspend for wow %d\n", ret); + clear_bit(RTW89_FLAG_FORBIDDEN_TRACK_WROK, rtwdev->flags); + return 1; + } + + return 0; +} + +static int rtw89_ops_resume(struct ieee80211_hw *hw) +{ + struct rtw89_dev *rtwdev = hw->priv; + int ret; + + mutex_lock(&rtwdev->mutex); + ret = rtw89_wow_resume(rtwdev); + if (ret) + rtw89_warn(rtwdev, "failed to resume for wow %d\n", ret); + mutex_unlock(&rtwdev->mutex); + + clear_bit(RTW89_FLAG_FORBIDDEN_TRACK_WROK, rtwdev->flags); + ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->track_work, + RTW89_TRACK_WORK_PERIOD); + + return ret ? 1 : 0; +} + +static void rtw89_ops_set_wakeup(struct ieee80211_hw *hw, bool enabled) +{ + struct rtw89_dev *rtwdev = hw->priv; + + device_set_wakeup_enable(rtwdev->dev, enabled); +} +#endif + const struct ieee80211_ops rtw89_ops = { .tx = rtw89_ops_tx, .wake_tx_queue = rtw89_ops_wake_tx_queue, @@ -953,5 +1003,10 @@ const struct ieee80211_ops rtw89_ops = { .set_sar_specs = rtw89_ops_set_sar_specs, .sta_rc_update = rtw89_ops_sta_rc_update, .set_tid_config = rtw89_ops_set_tid_config, +#ifdef CONFIG_PM + .suspend = rtw89_ops_suspend, + .resume = rtw89_ops_resume, + .set_wakeup = rtw89_ops_set_wakeup, +#endif }; EXPORT_SYMBOL(rtw89_ops); diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index 5f8e19639362..7aa0af18cdd5 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -186,6 +186,17 @@ static void rtw89_pci_ctrl_txdma_ch_pcie(struct rtw89_dev *rtwdev, bool enable) } } +static void rtw89_pci_ctrl_txdma_fw_ch_pcie(struct rtw89_dev *rtwdev, bool enable) +{ + const struct rtw89_pci_info *info = rtwdev->pci_info; + const struct rtw89_reg_def *dma_stop1 = &info->dma_stop1; + + if (enable) + rtw89_write32_clr(rtwdev, dma_stop1->addr, B_AX_STOP_CH12); + else + rtw89_write32_set(rtwdev, dma_stop1->addr, B_AX_STOP_CH12); +} + static bool rtw89_skb_put_rx_data(struct rtw89_dev *rtwdev, bool fs, bool ls, struct sk_buff *new, @@ -960,8 +971,10 @@ static u32 __rtw89_pci_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[txch]; struct rtw89_pci_tx_wd_ring *wd_ring = &tx_ring->wd_ring; + const struct rtw89_chip_info *chip = rtwdev->chip; u32 bd_cnt, wd_cnt, min_cnt = 0; struct rtw89_pci_rx_ring *rx_ring; + enum rtw89_debug_mask debug_mask; u32 cnt; rx_ring = &rtwpci->rx_rings[RTW89_RXCH_RPQ]; @@ -985,10 +998,20 @@ static u32 __rtw89_pci_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev, bd_cnt = rtw89_pci_get_avail_txbd_num(tx_ring); wd_cnt = wd_ring->curr_num; min_cnt = min(bd_cnt, wd_cnt); - if (min_cnt == 0) - rtw89_debug(rtwdev, rtwpci->low_power ? RTW89_DBG_TXRX : RTW89_DBG_UNEXP, + if (min_cnt == 0) { + /* This message can be frequently shown in low power mode or + * high traffic with 8852B, and we have recognized it as normal + * behavior, so print with mask RTW89_DBG_TXRX in these situations. + */ + if (rtwpci->low_power || chip->chip_id == RTL8852B) + debug_mask = RTW89_DBG_TXRX; + else + debug_mask = RTW89_DBG_UNEXP; + + rtw89_debug(rtwdev, debug_mask, "still no tx resource after reclaim: wd_cnt=%d bd_cnt=%d\n", wd_cnt, bd_cnt); + } out_unlock: spin_unlock_bh(&rtwpci->trx_lock); @@ -2513,7 +2536,7 @@ static int rtw89_pci_ops_mac_pre_init(struct rtw89_dev *rtwdev) /* disable all channels except to FW CMD channel to download firmware */ rtw89_pci_ctrl_txdma_ch_pcie(rtwdev, false); - rtw89_write32_clr(rtwdev, info->dma_stop1.addr, B_AX_STOP_CH12); + rtw89_pci_ctrl_txdma_fw_ch_pcie(rtwdev, true); /* start DMA activities */ rtw89_pci_ctrl_dma_all(rtwdev, true); @@ -3771,6 +3794,16 @@ static const struct rtw89_hci_ops rtw89_pci_ops = { .recovery_start = rtw89_pci_ops_recovery_start, .recovery_complete = rtw89_pci_ops_recovery_complete, + + .ctrl_txdma_ch = rtw89_pci_ctrl_txdma_ch_pcie, + .ctrl_txdma_fw_ch = rtw89_pci_ctrl_txdma_fw_ch_pcie, + .ctrl_trxhci = rtw89_pci_ctrl_dma_trx, + .poll_txdma_ch = rtw89_poll_txdma_ch_idle_pcie, + .clr_idx_all = rtw89_pci_clr_idx_all, + .clear = rtw89_pci_clear_resource, + .disable_intr = rtw89_pci_disable_intr_lock, + .enable_intr = rtw89_pci_enable_intr_lock, + .rst_bdram = rtw89_pci_rst_bdram_pcie, }; int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h index 179740607778..7d033501d4d9 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.h +++ b/drivers/net/wireless/realtek/rtw89/pci.h @@ -202,6 +202,18 @@ #define B_AX_RXP1DMA_INT BIT(1) #define B_AX_RXDMA_INT BIT(0) +#define R_AX_HAXI_IDCT_MSK 0x10B8 +#define B_AX_TXBD_LEN0_ERR_IDCT_MSK BIT(3) +#define B_AX_TXBD_4KBOUND_ERR_IDCT_MSK BIT(2) +#define B_AX_RXMDA_STUCK_IDCT_MSK BIT(1) +#define B_AX_TXMDA_STUCK_IDCT_MSK BIT(0) + +#define R_AX_HAXI_IDCT 0x10BC +#define B_AX_TXBD_LEN0_ERR_IDCT BIT(3) +#define B_AX_TXBD_4KBOUND_ERR_IDCT BIT(2) +#define B_AX_RXMDA_STUCK_IDCT BIT(1) +#define B_AX_TXMDA_STUCK_IDCT BIT(0) + #define R_AX_HAXI_HIMR10 0x11E0 #define B_AX_TXDMA_CH11_INT_EN_V1 BIT(1) #define B_AX_TXDMA_CH10_INT_EN_V1 BIT(0) diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index 35a0d190434a..dd4685698983 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -801,6 +801,11 @@ bool rtw89_phy_write_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, } EXPORT_SYMBOL(rtw89_phy_write_rf_v1); +static bool rtw89_chip_rf_v1(struct rtw89_dev *rtwdev) +{ + return rtwdev->chip->ops->write_rf == rtw89_phy_write_rf_v1; +} + static void rtw89_phy_bb_reset(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { @@ -1123,6 +1128,24 @@ out: return ret; } +static void rtw89_phy_config_rf_reg_noio(struct rtw89_dev *rtwdev, + const struct rtw89_reg2_def *reg, + enum rtw89_rf_path rf_path, + void *extra_data) +{ + u32 addr = reg->addr; + + if (addr == 0xfe || addr == 0xfd || addr == 0xfc || addr == 0xfb || + addr == 0xfa || addr == 0xf9) + return; + + if (rtw89_chip_rf_v1(rtwdev) && addr < 0x100) + return; + + rtw89_phy_cofig_rf_reg_store(rtwdev, reg, rf_path, + (struct rtw89_fw_h2c_rf_reg_info *)extra_data); +} + static void rtw89_phy_config_rf_reg(struct rtw89_dev *rtwdev, const struct rtw89_reg2_def *reg, enum rtw89_rf_path rf_path, @@ -1335,7 +1358,7 @@ static u32 rtw89_phy_nctl_poll(struct rtw89_dev *rtwdev) return rtw89_phy_read32(rtwdev, 0x8080); } -void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev) +void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio) { void (*config)(struct rtw89_dev *rtwdev, const struct rtw89_reg2_def *reg, enum rtw89_rf_path rf_path, void *data); @@ -1351,7 +1374,11 @@ void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev) for (path = RF_PATH_A; path < chip->rf_path_num; path++) { rf_table = chip->rf_table[path]; rf_reg_info->rf_path = rf_table->rf_path; - config = rf_table->config ? rf_table->config : rtw89_phy_config_rf_reg; + if (noio) + config = rtw89_phy_config_rf_reg_noio; + else + config = rf_table->config ? rf_table->config : + rtw89_phy_config_rf_reg; rtw89_phy_init_reg(rtwdev, rf_table, config, (void *)rf_reg_info); if (rtw89_phy_config_rf_reg_fw(rtwdev, rf_reg_info)) rtw89_warn(rtwdev, "rf path %d reg h2c config failed\n", diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index 995c13f6f906..dac69a02e868 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -500,7 +500,7 @@ bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, bool rtw89_phy_write_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, u32 addr, u32 mask, u32 data); void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev); -void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev); +void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio); void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev, const struct rtw89_reg2_def *reg, enum rtw89_rf_path rf_path, diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c index bf41a1141679..40498812205e 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.c +++ b/drivers/net/wireless/realtek/rtw89/ps.c @@ -59,7 +59,7 @@ static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter) rtw89_mac_power_mode_change(rtwdev, enter); } -static void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { if (rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) return; diff --git a/drivers/net/wireless/realtek/rtw89/ps.h b/drivers/net/wireless/realtek/rtw89/ps.h index 0feae3991623..6ac1f7ea5339 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.h +++ b/drivers/net/wireless/realtek/rtw89/ps.h @@ -8,6 +8,7 @@ void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); void rtw89_leave_lps(struct rtw89_dev *rtwdev); void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev); +void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev); void rtw89_enter_ips(struct rtw89_dev *rtwdev); void rtw89_leave_ips(struct rtw89_dev *rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index 2b938d11d238..dbe06542f443 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -326,8 +326,7 @@ #define R_AX_PCIE_DBG_CTRL 0x11C0 #define B_AX_DBG_DUMMY_MASK GENMASK(23, 16) -#define B_AX_DBG_SEL_MASK GENMASK(15, 13) -#define B_AX_PCIE_DBG_SEL BIT(12) +#define B_AX_PCIE_DBG_SEL_MASK GENMASK(15, 13) #define B_AX_MRD_TIMEOUT_EN BIT(10) #define B_AX_ASFF_FULL_NO_STK BIT(1) #define B_AX_EN_STUCK_DBG BIT(0) @@ -545,6 +544,19 @@ #define B_AX_WDE_EMPTY_QUE_CMAC0_MBH BIT(1) #define B_AX_WDE_EMPTY_QUE_CMAC0_ALL_AC BIT(0) +#define R_AX_DLE_EMPTY1 0x8434 +#define B_AX_PLE_EMPTY_QTA_DMAC_WDRLS BIT(20) +#define B_AX_PLE_EMPTY_QTA_CMAC1_DMA_BBRPT BIT(19) +#define B_AX_PLE_EMPTY_QTA_CMAC1_DMA_RX BIT(18) +#define B_AX_PLE_EMPTY_QTA_CMAC0_DMA_RX BIT(17) +#define B_AX_PLE_EMPTY_QTA_DMAC_C2H BIT(16) +#define B_AX_PLE_EMPTY_QUE_DMAC_PLRLS BIT(5) +#define B_AX_PLE_EMPTY_QUE_DMAC_CPUIO BIT(4) +#define B_AX_PLE_EMPTY_QUE_DMAC_SEC_RX BIT(3) +#define B_AX_PLE_EMPTY_QUE_DMAC_MPDU_RX BIT(2) +#define B_AX_PLE_EMPTY_QUE_DMAC_HDP BIT(1) +#define B_AX_WDE_EMPTY_QUE_DMAC_WDRLS BIT(0) + #define R_AX_DMAC_ERR_IMR 0x8520 #define B_AX_DLE_CPUIO_ERR_INT_EN BIT(10) #define B_AX_APB_BRIDGE_ERR_INT_EN BIT(9) @@ -561,6 +573,10 @@ #define DMAC_ERR_IMR_DIS 0 #define R_AX_DMAC_ERR_ISR 0x8524 +#define B_AX_HAXIDMA_ERR_FLAG BIT(14) +#define B_AX_PAXIDMA_ERR_FLAG BIT(13) +#define B_AX_HCI_BUF_ERR_FLAG BIT(12) +#define B_AX_BBRPT_ERR_FLAG BIT(11) #define B_AX_DLE_CPUIO_ERR_FLAG BIT(10) #define B_AX_APB_BRIDGE_ERR_FLAG BIT(9) #define B_AX_DISPATCH_ERR_FLAG BIT(8) @@ -939,6 +955,14 @@ B_AX_STF_OQT_OVERFLOW_ERR_INT_EN | \ B_AX_STF_OQT_UNDERFLOW_ERR_INT_EN) +#define R_AX_DISPATCHER_DBG_PORT 0x8860 +#define B_AX_DISPATCHER_DBG_SEL_MASK GENMASK(11, 8) +#define B_AX_DISPATCHER_INTN_SEL_MASK GENMASK(7, 4) +#define B_AX_DISPATCHER_CH_SEL_MASK GENMASK(3, 0) + +#define R_AX_RX_FUNCTION_STOP 0x8920 +#define B_AX_HDR_RX_STOP BIT(0) + #define R_AX_HCI_FC_CTRL 0x8A00 #define B_AX_HCI_FC_CH12_FULL_COND_MASK GENMASK(11, 10) #define B_AX_HCI_FC_WP_CH811_FULL_COND_MASK GENMASK(9, 8) @@ -1020,7 +1044,13 @@ #define R_AX_WDE_ERRFLAG_MSG 0x8C30 #define B_AX_WDE_ERR_FLAG_MSG_MASK GENMASK(31, 0) -#define R_AX_WDE_ERR_FLAG_CFG 0x8C34 +#define R_AX_WDE_ERR_FLAG_CFG_NUM1 0x8C34 +#define B_AX_WDE_ERR_FLAG_NUM1_VLD BIT(31) +#define B_AX_WDE_ERR_FLAG_NUM1_MSTIDX_MASK GENMASK(27, 24) +#define B_AX_WDE_ERR_FLAG_NUM1_ISRIDX_MASK GENMASK(20, 16) +#define B_AX_WDE_DATCHN_FRZTMR_MODE BIT(2) +#define B_AX_WDE_QUEMGN_FRZTMR_MODE BIT(1) +#define B_AX_WDE_BUFMGN_FRZTMR_MODE BIT(0) #define R_AX_WDE_ERR_IMR 0x8C38 #define B_AX_WDE_DATCHN_RRDY_ERR_INT_EN BIT(27) @@ -1204,7 +1234,59 @@ #define B_AX_PLE_START_BOUND_MASK GENMASK(13, 8) #define B_AX_PLE_PAGE_SEL_MASK GENMASK(1, 0) #define B_AX_PLE_FREE_PAGE_NUM_MASK GENMASK(28, 16) -#define R_AX_PLE_ERR_FLAG_CFG 0x9034 + +#define R_AX_PLE_DBGERR_LOCKEN 0x9020 +#define B_AX_PLE_LOCKEN_DLEPIF07 BIT(7) +#define B_AX_PLE_LOCKEN_DLEPIF06 BIT(6) +#define B_AX_PLE_LOCKEN_DLEPIF05 BIT(5) +#define B_AX_PLE_LOCKEN_DLEPIF04 BIT(4) +#define B_AX_PLE_LOCKEN_DLEPIF03 BIT(3) +#define B_AX_PLE_LOCKEN_DLEPIF02 BIT(2) +#define B_AX_PLE_LOCKEN_DLEPIF01 BIT(1) +#define B_AX_PLE_LOCKEN_DLEPIF00 BIT(0) + +#define R_AX_PLE_DBGERR_STS 0x9024 +#define B_AX_PLE_LOCKON_DLEPIF07 BIT(7) +#define B_AX_PLE_LOCKON_DLEPIF06 BIT(6) +#define B_AX_PLE_LOCKON_DLEPIF05 BIT(5) +#define B_AX_PLE_LOCKON_DLEPIF04 BIT(4) +#define B_AX_PLE_LOCKON_DLEPIF03 BIT(3) +#define B_AX_PLE_LOCKON_DLEPIF02 BIT(2) +#define B_AX_PLE_LOCKON_DLEPIF01 BIT(1) +#define B_AX_PLE_LOCKON_DLEPIF00 BIT(0) + +#define R_AX_PLE_ERR_FLAG_CFG_NUM1 0x9034 +#define B_AX_PLE_ERR_FLAG_NUM1_VLD BIT(31) +#define B_AX_PLE_ERR_FLAG_NUM1_MSTIDX_MASK GENMASK(27, 24) +#define B_AX_PLE_ERR_FLAG_NUM1_ISRIDX_MASK GENMASK(20, 16) +#define B_AX_PLE_DATCHN_FRZTMR_MODE BIT(2) +#define B_AX_PLE_QUEMGN_FRZTMR_MODE BIT(1) +#define B_AX_PLE_BUFMGN_FRZTMR_MODE BIT(0) + +#define R_AX_PLE_ERRFLAG_MSG 0x9030 +#define B_AX_PLE_ERR_FLAG_MSG_MASK GENMASK(31, 0) +#define B_AX_PLE_DATCHN_CAMREQ_ERR_INT_EN BIT(29) +#define B_AX_PLE_DATCHN_ADRERR_ERR_INT_EN BIT(28) +#define B_AX_PLE_BUFMGN_FRZTO_ERR_INT_EN_V1 BIT(9) +#define B_AX_PLE_GETNPG_PGOFST_ERR_INT_EN_V1 BIT(8) +#define B_AX_PLE_GETNPG_STRPG_ERR_INT_EN_V1 BIT(7) +#define B_AX_PLE_BUFREQ_SRCHTAILPG_ERR_INT_EN_V1 BIT(6) +#define B_AX_PLE_BUFRTN_SIZE_ERR_INT_EN_V1 BIT(5) +#define B_AX_PLE_BUFRTN_INVLD_PKTID_ERR_INT_EN_V1 BIT(4) +#define B_AX_PLE_BUFREQ_UNAVAL_ERR_INT_EN_V1 BIT(3) +#define B_AX_PLE_BUFREQ_SIZELMT_INT_EN BIT(2) +#define B_AX_PLE_BUFREQ_SIZE0_INT_EN BIT(1) +#define B_AX_PLE_DATCHN_CAMREQ_ERR BIT(29) +#define B_AX_PLE_DATCHN_ADRERR_ERR BIT(28) +#define B_AX_PLE_BUFMGN_FRZTO_ERR_V1 BIT(9) +#define B_AX_PLE_GETNPG_PGOFST_ERR_V1 BIT(8) +#define B_AX_PLE_GETNPG_STRPG_ERR_V1 BIT(7) +#define B_AX_PLE_BUFREQ_SRCHTAILPG_ERR_V1 BIT(6) +#define B_AX_PLE_BUFRTN_SIZE_ERR_V1 BIT(5) +#define B_AX_PLE_BUFRTN_INVLD_PKTID_ERR_V1 BIT(4) +#define B_AX_PLE_BUFREQ_UNAVAL_ERR_V1 BIT(3) +#define B_AX_PLE_BUFREQ_SIZELMT_ERR BIT(2) +#define B_AX_PLE_BUFREQ_SIZE0_ERR BIT(1) #define R_AX_PLE_ERR_IMR 0x9038 #define B_AX_PLE_DATCHN_RRDY_ERR_INT_EN BIT(27) @@ -1415,6 +1497,19 @@ #define B_AX_BBRPT_COM_NULL_PLPKTID_ERR BIT(16) #define B_AX_BBRPT_COM_NULL_PLPKTID_ERR_INT_EN BIT(0) +#define R_AX_BBRPT_COM_ERR_ISR 0x960C +#define B_AX_BBRPT_COM_NULL_PLPKTID_ERR_INT_V1 BIT(0) + +#define R_AX_BBRPT_CHINFO_ERR_ISR 0x962C +#define B_AX_BBPRT_CHIF_TO_ERR_V1 BIT(7) +#define B_AX_BBPRT_CHIF_NULL_ERR_V1 BIT(6) +#define B_AX_BBPRT_CHIF_LEFT2_ERR_V1 BIT(5) +#define B_AX_BBPRT_CHIF_LEFT1_ERR_V1 BIT(4) +#define B_AX_BBPRT_CHIF_HDRL_ERR_V1 BIT(3) +#define B_AX_BBPRT_CHIF_BOVF_ERR_V1 BIT(2) +#define B_AX_BBPRT_CHIF_OVF_ERR_V1 BIT(1) +#define B_AX_BBPRT_CHIF_BB_TO_ERR_V1 BIT(0) + #define R_AX_BBRPT_CHINFO_ERR_IMR 0x9628 #define B_AX_BBPRT_CHIF_TO_ERR_INT_EN BIT(7) #define B_AX_BBPRT_CHIF_NULL_ERR_INT_EN BIT(6) @@ -1466,6 +1561,9 @@ #define B_AX_BBRPT_DFS_TO_ERR BIT(16) #define B_AX_BBRPT_DFS_TO_ERR_INT_EN BIT(0) +#define R_AX_BBRPT_DFS_ERR_ISR 0x963C +#define B_AX_BBRPT_DFS_TO_ERR_V1 BIT(0) + #define R_AX_LA_ERRFLAG 0x966C #define B_AX_LA_ISR_DATA_LOSS_ERR BIT(16) #define B_AX_LA_IMR_DATA_LOSS_ERR BIT(0) @@ -1557,6 +1655,8 @@ #define R_AX_ACTION_FWD0 0x9C04 #define TRXCFG_MPDU_PROC_ACT_FRWD 0x02A95A95 +#define R_AX_ACTION_FWD1 0x9C08 + #define R_AX_TF_FWD 0x9C14 #define TRXCFG_MPDU_PROC_TF_FRWD 0x0000AA55 @@ -1568,6 +1668,9 @@ #define R_AX_CUT_AMSDU_CTRL 0x9C40 #define TRXCFG_MPDU_PROC_CUT_CTRL 0x010E05F0 +#define R_AX_WOW_CTRL 0x9C50 +#define B_AX_WOW_WOWEN BIT(1) + #define R_AX_MPDU_RX_ERR_ISR 0x9CF0 #define R_AX_MPDU_RX_ERR_IMR 0x9CF4 #define B_AX_RPT_ERR_INT_EN BIT(3) @@ -1576,6 +1679,7 @@ #define B_AX_MPDU_RX_IMR_SET_V1 B_AX_RPT_ERR_INT_EN #define R_AX_SEC_ENG_CTRL 0x9D00 +#define B_AX_SEC_DBG_PORT_FIELD_MASK GENMASK(19, 16) #define B_AX_TX_PARTIAL_MODE BIT(11) #define B_AX_CLK_EN_CGCMP BIT(10) #define B_AX_CLK_EN_WAPI BIT(9) @@ -1605,12 +1709,21 @@ #define R_AX_SEC_TX_DEBUG 0x9D20 #define R_AX_SEC_RX_DEBUG 0x9D24 #define R_AX_SEC_TRX_PKT_CNT 0x9D28 + +#define R_AX_SEC_DEBUG2 0x9D28 +#define B_AX_DBG_READ_SH 2 +#define B_AX_DBG_READ_MSK 0x3fffffff + #define R_AX_SEC_TRX_BLK_CNT 0x9D2C #define R_AX_SEC_ERROR_FLAG_IMR 0x9D2C #define B_AX_RX_HANG_IMR BIT(1) #define B_AX_TX_HANG_IMR BIT(0) +#define R_AX_SEC_ERROR_FLAG 0x9D30 +#define B_AX_RX_HANG_ERROR_V1 BIT(1) +#define B_AX_TX_HANG_ERROR_V1 BIT(0) + #define R_AX_SS_CTRL 0x9E10 #define B_AX_SS_INIT_DONE_1 BIT(31) #define B_AX_SS_WARM_INIT_FLG BIT(29) @@ -1745,6 +1858,28 @@ B_AX_B0_IMR_ERR_PRELD_RLSPKTSZERR | \ B_AX_B0_IMR_ERR_PRELD_ENTNUMCFG) +#define R_AX_TXPKTCTL_B0_ERRFLAG_ISR 0x9F7C +#define B_AX_B0_ISR_ERR_PRELD_EVT3 BIT(23) +#define B_AX_B0_ISR_ERR_PRELD_EVT2 BIT(22) +#define B_AX_B0_ISR_ERR_PRELD_ENTNUMCFG BIT(21) +#define B_AX_B0_ISR_ERR_PRELD_RLSPKTSZERR BIT(20) +#define B_AX_B0_ISR_ERR_MPDUIF_ERR1 BIT(19) +#define B_AX_B0_ISR_ERR_MPDUIF_DATAERR BIT(18) +#define B_AX_B0_ISR_ERR_MPDUINFO_ERR1 BIT(17) +#define B_AX_B0_ISR_ERR_MPDUINFO_RECFG BIT(16) +#define B_AX_B0_ISR_ERR_CMDPSR_TBLSZ BIT(11) +#define B_AX_B0_ISR_ERR_CMDPSR_FRZTO BIT(10) +#define B_AX_B0_ISR_ERR_CMDPSR_CMDTYPE BIT(9) +#define B_AX_B0_ISR_ERR_CMDPSR_1STCMDERR BIT(8) +#define B_AX_B0_ISR_ERR_USRCTL_EVT7 BIT(7) +#define B_AX_B0_ISR_ERR_USRCTL_EVT6 BIT(6) +#define B_AX_B0_ISR_ERR_USRCTL_EVT5 BIT(5) +#define B_AX_B0_ISR_ERR_USRCTL_EVT4 BIT(4) +#define B_AX_B0_ISR_ERR_USRCTL_RLSBMPLEN BIT(3) +#define B_AX_B0_ISR_ERR_USRCTL_RDNRLSCMD BIT(2) +#define B_AX_B0_ISR_ERR_USRCTL_NOINIT BIT(1) +#define B_AX_B0_ISR_ERR_USRCTL_REINIT BIT(0) + #define R_AX_TXPKTCTL_B1_PRELD_CFG0 0x9F88 #define B_AX_B1_PRELD_FEN BIT(31) #define B_AX_B1_PRELD_USEMAXSZ_MASK GENMASK(25, 16) @@ -1792,6 +1927,28 @@ B_AX_B1_IMR_ERR_PRELD_RLSPKTSZERR | \ B_AX_B1_IMR_ERR_PRELD_ENTNUMCFG) +#define R_AX_TXPKTCTL_B1_ERRFLAG_ISR 0x9FBC +#define B_AX_B1_ISR_ERR_PRELD_EVT3 BIT(23) +#define B_AX_B1_ISR_ERR_PRELD_EVT2 BIT(22) +#define B_AX_B1_ISR_ERR_PRELD_ENTNUMCFG BIT(21) +#define B_AX_B1_ISR_ERR_PRELD_RLSPKTSZERR BIT(20) +#define B_AX_B1_ISR_ERR_MPDUIF_ERR1 BIT(19) +#define B_AX_B1_ISR_ERR_MPDUIF_DATAERR BIT(18) +#define B_AX_B1_ISR_ERR_MPDUINFO_ERR1 BIT(17) +#define B_AX_B1_ISR_ERR_MPDUINFO_RECFG BIT(16) +#define B_AX_B1_ISR_ERR_CMDPSR_TBLSZ BIT(11) +#define B_AX_B1_ISR_ERR_CMDPSR_FRZTO BIT(10) +#define B_AX_B1_ISR_ERR_CMDPSR_CMDTYPE BIT(9) +#define B_AX_B1_ISR_ERR_CMDPSR_1STCMDERR BIT(8) +#define B_AX_B1_ISR_ERR_USRCTL_EVT7 BIT(7) +#define B_AX_B1_ISR_ERR_USRCTL_EVT6 BIT(6) +#define B_AX_B1_ISR_ERR_USRCTL_EVT5 BIT(5) +#define B_AX_B1_ISR_ERR_USRCTL_EVT4 BIT(4) +#define B_AX_B1_ISR_ERR_USRCTL_RLSBMPLEN BIT(3) +#define B_AX_B1_ISR_ERR_USRCTL_RDNRLSCMD BIT(2) +#define B_AX_B1_ISR_ERR_USRCTL_NOINIT BIT(1) +#define B_AX_B1_ISR_ERR_USRCTL_REINIT BIT(0) + #define R_AX_AFE_CTRL1 0x0024 #define B_AX_R_SYM_WLCMAC1_P4_PC_EN BIT(4) @@ -2360,6 +2517,41 @@ #define B_AX_DLE_IMR_SET (B_AX_RXSTS_FSM_HANG_ERROR_IMR | \ B_AX_RXDATA_FSM_HANG_ERROR_IMR) +#define R_AX_RX_ERR_FLAG 0xC800 +#define R_AX_RX_ERR_FLAG_C1 0xE800 +#define B_AX_RX_GET_NO_PAGE_ERR BIT(31) +#define B_AX_RX_GET_NULL_PKT_ERR BIT(30) +#define B_AX_RX_RU0_FSM_HANG_ERR BIT(29) +#define B_AX_RX_RU1_FSM_HANG_ERR BIT(28) +#define B_AX_RX_RU2_FSM_HANG_ERR BIT(27) +#define B_AX_RX_RU3_FSM_HANG_ERR BIT(26) +#define B_AX_RX_RU4_FSM_HANG_ERR BIT(25) +#define B_AX_RX_RU5_FSM_HANG_ERR BIT(24) +#define B_AX_RX_RU6_FSM_HANG_ERR BIT(23) +#define B_AX_RX_RU7_FSM_HANG_ERR BIT(22) +#define B_AX_RX_RXSTS_FSM_HANG_ERR BIT(21) +#define B_AX_RX_CSI_FSM_HANG_ERR BIT(20) +#define B_AX_RX_TXRPT_FSM_HANG_ERR BIT(19) +#define B_AX_RX_F2PCMD_FSM_HANG_ERR BIT(18) +#define B_AX_RX_RU0_ZERO_LEN_ERR BIT(17) +#define B_AX_RX_RU1_ZERO_LEN_ERR BIT(16) +#define B_AX_RX_RU2_ZERO_LEN_ERR BIT(15) +#define B_AX_RX_RU3_ZERO_LEN_ERR BIT(14) +#define B_AX_RX_RU4_ZERO_LEN_ERR BIT(13) +#define B_AX_RX_RU5_ZERO_LEN_ERR BIT(12) +#define B_AX_RX_RU6_ZERO_LEN_ERR BIT(11) +#define B_AX_RX_RU7_ZERO_LEN_ERR BIT(10) +#define B_AX_RX_RXSTS_ZERO_LEN_ERR BIT(9) +#define B_AX_RX_CSI_ZERO_LEN_ERR BIT(8) +#define B_AX_PLE_DATA_OPT_FSM_HANG BIT(7) +#define B_AX_PLE_RXDATA_REQ_BUF_FSM_HANG BIT(6) +#define B_AX_PLE_TXRPT_REQ_BUF_FSM_HANG BIT(5) +#define B_AX_PLE_WD_OPT_FSM_HANG BIT(4) +#define B_AX_PLE_ENQ_FSM_HANG BIT(3) +#define B_AX_RXDATA_ENQUE_ORDER_ERR BIT(2) +#define B_AX_RXSTS_ENQUE_ORDER_ERR BIT(1) +#define B_AX_RX_CSI_PKT_NUM_ERR BIT(0) + #define R_AX_RXDMA_CTRL_0 0xC804 #define R_AX_RXDMA_CTRL_0_C1 0xE804 #define B_AX_RXDMA_DBGOUT_EN BIT(31) @@ -2382,6 +2574,49 @@ B_AX_RU2_PTR_FULL_MODE | B_AX_RU3_PTR_FULL_MODE | \ B_AX_CSI_PTR_FULL_MODE | B_AX_RXSTS_PTR_FULL_MODE) +#define R_AX_RX_CTRL0 0xC808 +#define R_AX_RX_CTRL0_C1 0xE808 +#define B_AX_DLE_CLOCK_FORCE_V1 BIT(31) +#define B_AX_TXDMA_CLOCK_FORCE_V1 BIT(30) +#define B_AX_RXDMA_CLOCK_FORCE_V1 BIT(29) +#define B_AX_RXDMA_DEFAULT_PAGE_V1_MASK GENMASK(28, 24) +#define B_AX_RXDMA_CSI_TGT_QUEID_MASK GENMASK(23, 18) +#define B_AX_RXDMA_CSI_TGT_PRID_MASK GENMASK(17, 15) +#define B_AX_RXDMA_DIS_CSI_RELEASE_V1 BIT(14) +#define B_AX_CSI_PTR_FULL_MODE_V1 BIT(13) +#define B_AX_RXDATA_PTR_FULL_MODE BIT(12) +#define B_AX_RXSTS_PTR_FULL_MODE_V1 BIT(11) +#define B_AX_TXRPT_FULL_RSV_DEPTH_V1_MASK GENMASK(10, 8) +#define B_AX_RXDATA_FULL_RSV_DEPTH_MASK GENMASK(7, 5) +#define B_AX_RXSTS_FULL_RSV_DEPTH_V1_MASK GENMASK(4, 2) +#define B_AX_ORDER_FIFO_MASK GENMASK(1, 0) + +#define R_AX_RX_CTRL1 0xC80C +#define R_AX_RX_CTRL1_C1 0xE80C +#define B_AX_RXDMA_TXRPT_QUEUE_ID_SW_EN BIT(31) +#define B_AX_RXDMA_TXRPT_QUEUE_ID_SW_V1_MASK GENMASK(30, 25) +#define B_AX_RXDMA_F2PCMD_QUEUE_ID_SW_EN BIT(24) +#define B_AX_RXDMA_F2PCMD_QUEUE_ID_SW_V1_MASK GENMASK(23, 18) +#define B_AX_RXDMA_TXRPT_QUEUE_ID_TGT_SW_EN BIT(17) +#define B_AX_RXDMA_TXRPT_QUEUE_ID_TGT_SW_1_MASK GENMASK(16, 11) +#define B_AX_RXDMA_F2PCMD_QUEUE_ID_TGT_SW_EN BIT(10) +#define B_AX_RXDMA_F2PCMD_QUEUE_ID_TGT_SW_1_MASK GENMASK(9, 4) +#define B_AX_ORDER_FIFO_OUT BIT(3) +#define B_AX_ORDER_FIFO_EMPTY BIT(2) +#define B_AX_DBG_SEL_MASK GENMASK(1, 0) + +#define R_AX_RX_CTRL2 0xC810 +#define R_AX_RX_CTRL2_C1 0xE810 +#define B_AX_DLE_WDE_STATE_V1_MASK GENMASK(31, 30) +#define B_AX_DLE_PLE_STATE_V1_MASK GENMASK(29, 28) +#define B_AX_DLE_REQ_BUF_STATE_MASK GENMASK(27, 26) +#define B_AX_DLE_ENQ_STATE_V1 BIT(25) +#define B_AX_RX_DBG_SEL_MASK GENMASK(24, 19) +#define B_AX_MACRX_CS_MASK GENMASK(18, 14) +#define B_AX_RXSTS_CS_MASK GENMASK(13, 9) +#define B_AX_ERR_INDICATOR BIT(5) +#define B_AX_TXRPT_CS_MASK GENMASK(4, 0) + #define R_AX_RXDMA_PKT_INFO_0 0xC814 #define R_AX_RXDMA_PKT_INFO_1 0xC818 #define R_AX_RXDMA_PKT_INFO_2 0xC81C @@ -2689,6 +2924,18 @@ B_AX_TMAC_MIMO_CTRL | \ B_AX_RMAC_FTM) +#define R_AX_TRXPTCL_ERROR_INDICA 0xCCC0 +#define R_AX_TRXPTCL_ERROR_INDICA_C1 0xECC0 +#define B_AX_FTM_ERROR_FLAG_CLR BIT(8) +#define B_AX_CSI_ERROR_FLAG_CLR BIT(7) +#define B_AX_MIMOCTRL_ERROR_FLAG_CLR BIT(6) +#define B_AX_RXTB_ERROR_FLAG_CLR BIT(5) +#define B_AX_HWSIGB_GEN_ERROR_FLAG_CLR BIT(4) +#define B_AX_TXPLCP_ERROR_FLAG_CLR BIT(3) +#define B_AX_RESP_ERROR_FLAG_CLR BIT(2) +#define B_AX_TXCTL_ERROR_FLAG_CLR BIT(1) +#define B_AX_MACTX_ERROR_FLAG_CLR BIT(0) + #define R_AX_WMAC_TX_TF_INFO_0 0xCCD0 #define R_AX_WMAC_TX_TF_INFO_0_C1 0xECD0 #define B_AX_WMAC_TX_TF_INFO_SEL_MASK GENMASK(2, 0) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index b5aa8697a098..4cea5fb4327d 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -48,6 +48,10 @@ static const struct rtw89_dle_mem rtw8852a_dle_mem_pcie[] = { &rtw89_mac_size.ple_size0, &rtw89_mac_size.wde_qt0, &rtw89_mac_size.wde_qt0, &rtw89_mac_size.ple_qt4, &rtw89_mac_size.ple_qt5}, + [RTW89_QTA_WOW] = {RTW89_QTA_WOW, &rtw89_mac_size.wde_size0, + &rtw89_mac_size.ple_size0, &rtw89_mac_size.wde_qt0, + &rtw89_mac_size.wde_qt0, &rtw89_mac_size.ple_qt4, + &rtw89_mac_size.ple_qt_52a_wow}, [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size4, &rtw89_mac_size.ple_size4, &rtw89_mac_size.wde_qt4, &rtw89_mac_size.wde_qt4, &rtw89_mac_size.ple_qt13, @@ -1986,6 +1990,15 @@ static void rtw8852a_query_ppdu(struct rtw89_dev *rtwdev, rtw8852a_fill_freq_with_ppdu(rtwdev, phy_ppdu, status); } +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support rtw_wowlan_stub_8852a = { + .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, + .n_patterns = RTW89_MAX_PATTERN_NUM, + .pattern_max_len = RTW89_MAX_PATTERN_SIZE, + .pattern_min_len = 1, +}; +#endif + static const struct rtw89_chip_ops rtw8852a_chip_ops = { .enable_bb_rf = rtw89_mac_enable_bb_rf, .disable_bb_rf = rtw89_mac_disable_bb_rf, @@ -2045,6 +2058,8 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .rsvd_ple_ofst = 0x6f800, .hfc_param_ini = rtw8852a_hfc_param_ini_pcie, .dle_mem = rtw8852a_dle_mem_pcie, + .wde_qempty_acq_num = 16, + .wde_qempty_mgq_sel = 16, .rf_base_addr = {0xc000, 0xd000}, .pwr_on_seq = pwr_on_seq_8852a, .pwr_off_seq = pwr_off_seq_8852a, @@ -2133,6 +2148,9 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .imr_info = &rtw8852a_imr_info, .rrsr_cfgs = &rtw8852a_rrsr_cfgs, .dma_ch_mask = 0, +#ifdef CONFIG_PM + .wowlan_stub = &rtw_wowlan_stub_8852a, +#endif }; EXPORT_SYMBOL(rtw8852a_chip_info); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c index 8fd01502ac5b..722ae34b09c1 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c @@ -1754,7 +1754,7 @@ static void _dpk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, id == 0x14 ? "PWR_CAL" : id == 0x15 ? "DPK_RXAGC" : id == 0x16 ? "KIP_PRESET" : - id == 0x17 ? "KIP_RESOTRE" : "DPK_TXAGC", + id == 0x17 ? "KIP_RESTORE" : "DPK_TXAGC", dpk_cmd); } diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index f6bcac826816..6619ba730719 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -1683,12 +1683,12 @@ static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_phy_idx phy_idx) { + static const u32 ru_alloc_msk[2] = {B_P80_AT_HIGH_FREQ_RU_ALLOC_PHY0, + B_P80_AT_HIGH_FREQ_RU_ALLOC_PHY1}; struct rtw89_hal *hal = &rtwdev->hal; bool cck_en = chan->band_type == RTW89_BAND_2G; u8 pri_ch_idx = chan->pri_ch_idx; u32 mask, reg; - u32 ru_alloc_msk[2] = {B_P80_AT_HIGH_FREQ_RU_ALLOC_PHY0, - B_P80_AT_HIGH_FREQ_RU_ALLOC_PHY1}; u8 ntx_path; if (chan->band_type == RTW89_BAND_2G) @@ -2796,6 +2796,15 @@ static int rtw8852c_mac_disable_bb_rf(struct rtw89_dev *rtwdev) return 0; } +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support rtw_wowlan_stub_8852c = { + .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, + .n_patterns = RTW89_MAX_PATTERN_NUM, + .pattern_max_len = RTW89_MAX_PATTERN_SIZE, + .pattern_min_len = 1, +}; +#endif + static const struct rtw89_chip_ops rtw8852c_chip_ops = { .enable_bb_rf = rtw8852c_mac_enable_bb_rf, .disable_bb_rf = rtw8852c_mac_disable_bb_rf, @@ -2855,6 +2864,8 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .rsvd_ple_ofst = 0x6f800, .hfc_param_ini = rtw8852c_hfc_param_ini_pcie, .dle_mem = rtw8852c_dle_mem_pcie, + .wde_qempty_acq_num = 16, + .wde_qempty_mgq_sel = 16, .rf_base_addr = {0xe000, 0xf000}, .pwr_on_seq = NULL, .pwr_off_seq = NULL, @@ -2947,6 +2958,9 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .imr_info = &rtw8852c_imr_info, .rrsr_cfgs = &rtw8852c_rrsr_cfgs, .dma_ch_mask = 0, +#ifdef CONFIG_PM + .wowlan_stub = &rtw_wowlan_stub_8852c, +#endif }; EXPORT_SYMBOL(rtw8852c_chip_info); diff --git a/drivers/net/wireless/realtek/rtw89/util.h b/drivers/net/wireless/realtek/rtw89/util.h index 1ae80b7561da..e2ed4565025d 100644 --- a/drivers/net/wireless/realtek/rtw89/util.h +++ b/drivers/net/wireless/realtek/rtw89/util.h @@ -44,4 +44,15 @@ static inline s32 s32_div_u32_round_closest(s32 dividend, u32 divisor) return s32_div_u32_round_down(dividend + divisor / 2, divisor, NULL); } +static inline void ether_addr_copy_mask(u8 *dst, const u8 *src, u8 mask) +{ + int i; + + eth_zero_addr(dst); + for (i = 0; i < ETH_ALEN; i++) { + if (mask & BIT(i)) + dst[i] = src[i]; + } +} + #endif diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c new file mode 100644 index 000000000000..b2b826b2e09a --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -0,0 +1,859 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2019-2022 Realtek Corporation + */ +#include "cam.h" +#include "core.h" +#include "debug.h" +#include "fw.h" +#include "mac.h" +#include "phy.h" +#include "ps.h" +#include "reg.h" +#include "util.h" +#include "wow.h" + +static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev) +{ + __rtw89_leave_ps_mode(rtwdev); +} + +static void rtw89_wow_enter_deep_ps(struct rtw89_dev *rtwdev) +{ + struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + + __rtw89_enter_ps_mode(rtwdev, rtwvif); +} + +static void rtw89_wow_enter_lps(struct rtw89_dev *rtwdev) +{ + struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + + rtw89_enter_lps(rtwdev, rtwvif); +} + +static void rtw89_wow_leave_lps(struct rtw89_dev *rtwdev) +{ + rtw89_leave_lps(rtwdev); +} + +static int rtw89_wow_config_mac(struct rtw89_dev *rtwdev, bool enable_wow) +{ + int ret; + + if (enable_wow) { + ret = rtw89_mac_resize_ple_rx_quota(rtwdev, true); + if (ret) { + rtw89_err(rtwdev, "[ERR]patch rx qta %d\n", ret); + return ret; + } + rtw89_write32_set(rtwdev, R_AX_RX_FUNCTION_STOP, B_AX_HDR_RX_STOP); + rtw89_write32_clr(rtwdev, R_AX_RX_FLTR_OPT, B_AX_SNIFFER_MODE); + rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false); + rtw89_write32(rtwdev, R_AX_ACTION_FWD0, 0); + rtw89_write32(rtwdev, R_AX_ACTION_FWD1, 0); + rtw89_write32(rtwdev, R_AX_TF_FWD, 0); + rtw89_write32(rtwdev, R_AX_HW_RPT_FWD, 0); + } else { + ret = rtw89_mac_resize_ple_rx_quota(rtwdev, false); + if (ret) { + rtw89_err(rtwdev, "[ERR]patch rx qta %d\n", ret); + return ret; + } + rtw89_write32_clr(rtwdev, R_AX_RX_FUNCTION_STOP, B_AX_HDR_RX_STOP); + rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); + rtw89_write32(rtwdev, R_AX_ACTION_FWD0, TRXCFG_MPDU_PROC_ACT_FRWD); + rtw89_write32(rtwdev, R_AX_TF_FWD, TRXCFG_MPDU_PROC_TF_FRWD); + } + + return 0; +} + +static void rtw89_wow_set_rx_filter(struct rtw89_dev *rtwdev, bool enable) +{ + enum rtw89_mac_fwd_target fwd_target = enable ? + RTW89_FWD_DONT_CARE : + RTW89_FWD_TO_HOST; + + rtw89_mac_typ_fltr_opt(rtwdev, RTW89_MGNT, fwd_target, RTW89_MAC_0); + rtw89_mac_typ_fltr_opt(rtwdev, RTW89_CTRL, fwd_target, RTW89_MAC_0); + rtw89_mac_typ_fltr_opt(rtwdev, RTW89_DATA, fwd_target, RTW89_MAC_0); +} + +static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev) +{ + enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; + struct cfg80211_wowlan_nd_info nd_info; + struct cfg80211_wowlan_wakeup wakeup = { + .pattern_idx = -1, + }; + u32 wow_reason_reg; + u8 reason; + + if (chip_id == RTL8852A || chip_id == RTL8852B) + wow_reason_reg = R_AX_C2HREG_DATA3 + 3; + else + wow_reason_reg = R_AX_C2HREG_DATA3_V1 + 3; + + reason = rtw89_read8(rtwdev, wow_reason_reg); + + switch (reason) { + case RTW89_WOW_RSN_RX_DEAUTH: + wakeup.disconnect = true; + rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx deauth\n"); + break; + case RTW89_WOW_RSN_DISCONNECT: + wakeup.disconnect = true; + rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: AP is off\n"); + break; + case RTW89_WOW_RSN_RX_MAGIC_PKT: + wakeup.magic_pkt = true; + rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx magic packet\n"); + break; + case RTW89_WOW_RSN_RX_GTK_REKEY: + wakeup.gtk_rekey_failure = true; + rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx gtk rekey\n"); + break; + case RTW89_WOW_RSN_RX_PATTERN_MATCH: + /* Current firmware and driver don't report pattern index + * Use pattern_idx to 0 defaultly. + */ + wakeup.pattern_idx = 0; + rtw89_debug(rtwdev, RTW89_DBG_WOW, "WOW: Rx pattern match packet\n"); + break; + case RTW89_WOW_RSN_RX_NLO: + /* Current firmware and driver don't report ssid index. + * Use 0 for n_matches based on its comment. + */ + nd_info.n_matches = 0; + wakeup.net_detect = &nd_info; + rtw89_debug(rtwdev, RTW89_DBG_WOW, "Rx NLO\n"); + break; + default: + rtw89_warn(rtwdev, "Unknown wakeup reason %x\n", reason); + ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, NULL, + GFP_KERNEL); + return; + } + + ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, &wakeup, + GFP_KERNEL); +} + +static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + + /* Current wowlan function support setting of only one STATION vif. + * So when one suitable vif is found, stop the iteration. + */ + if (rtw_wow->wow_vif || vif->type != NL80211_IFTYPE_STATION) + return; + + switch (rtwvif->net_type) { + case RTW89_NET_TYPE_INFRA: + rtw_wow->wow_vif = vif; + break; + case RTW89_NET_TYPE_NO_LINK: + default: + break; + } +} + +static u16 __rtw89_cal_crc16(u8 data, u16 crc) +{ + u8 shift_in, data_bit; + u8 crc_bit4, crc_bit11, crc_bit15; + u16 crc_result; + int index; + + for (index = 0; index < 8; index++) { + crc_bit15 = crc & BIT(15) ? 1 : 0; + data_bit = data & BIT(index) ? 1 : 0; + shift_in = crc_bit15 ^ data_bit; + + crc_result = crc << 1; + + if (shift_in == 0) + crc_result &= ~BIT(0); + else + crc_result |= BIT(0); + + crc_bit11 = (crc & BIT(11) ? 1 : 0) ^ shift_in; + + if (crc_bit11 == 0) + crc_result &= ~BIT(12); + else + crc_result |= BIT(12); + + crc_bit4 = (crc & BIT(4) ? 1 : 0) ^ shift_in; + + if (crc_bit4 == 0) + crc_result &= ~BIT(5); + else + crc_result |= BIT(5); + + crc = crc_result; + } + return crc; +} + +static u16 rtw89_calc_crc(u8 *pdata, int length) +{ + u16 crc = 0xffff; + int i; + + for (i = 0; i < length; i++) + crc = __rtw89_cal_crc16(pdata[i], crc); + + /* get 1' complement */ + return ~crc; +} + +static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif, + struct rtw89_wow_cam_info *rtw_pattern, + const u8 *pattern, u8 da_mask) +{ + u8 da[ETH_ALEN]; + + ether_addr_copy_mask(da, pattern, da_mask); + + /* Each pattern is divided into different kinds by DA address + * a. DA is broadcast address: set bc = 0; + * b. DA is multicast address: set mc = 0 + * c. DA is unicast address same as dev's mac address: set uc = 0 + * d. DA is unmasked. Also called wildcard type: set uc = bc = mc = 0 + * e. Others is invalid type. + */ + + if (is_broadcast_ether_addr(da)) + rtw_pattern->bc = true; + else if (is_multicast_ether_addr(da)) + rtw_pattern->mc = true; + else if (ether_addr_equal(da, rtwvif->mac_addr) && + da_mask == GENMASK(5, 0)) + rtw_pattern->uc = true; + else if (!da_mask) /*da_mask == 0 mean wildcard*/ + return 0; + else + return -EPERM; + + return 0; +} + +static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, + const struct cfg80211_pkt_pattern *pkt_pattern, + struct rtw89_wow_cam_info *rtw_pattern) +{ + u8 mask_hw[RTW89_MAX_PATTERN_MASK_SIZE * 4] = {0}; + u8 content[RTW89_MAX_PATTERN_SIZE] = {0}; + const u8 *mask; + const u8 *pattern; + u8 mask_len; + u16 count; + u32 len; + int i, ret; + + pattern = pkt_pattern->pattern; + len = pkt_pattern->pattern_len; + mask = pkt_pattern->mask; + mask_len = DIV_ROUND_UP(len, 8); + memset(rtw_pattern, 0, sizeof(*rtw_pattern)); + + ret = rtw89_wow_pattern_get_type(rtwvif, rtw_pattern, pattern, + mask[0] & GENMASK(5, 0)); + if (ret) + return ret; + + /* translate mask from os to mask for hw + * pattern from OS uses 'ethenet frame', like this: + * | 6 | 6 | 2 | 20 | Variable | 4 | + * |--------+--------+------+-----------+------------+-----| + * | 802.3 Mac Header | IP Header | TCP Packet | FCS | + * | DA | SA | Type | + * + * BUT, packet catched by our HW is in '802.11 frame', begin from LLC + * | 24 or 30 | 6 | 2 | 20 | Variable | 4 | + * |-------------------+--------+------+-----------+------------+-----| + * | 802.11 MAC Header | LLC | IP Header | TCP Packet | FCS | + * | Others | Tpye | + * + * Therefore, we need translate mask_from_OS to mask_to_hw. + * We should left-shift mask by 6 bits, then set the new bit[0~5] = 0, + * because new mask[0~5] means 'SA', but our HW packet begins from LLC, + * bit[0~5] corresponds to first 6 Bytes in LLC, they just don't match. + */ + + /* Shift 6 bits */ + for (i = 0; i < mask_len - 1; i++) { + mask_hw[i] = u8_get_bits(mask[i], GENMASK(7, 6)) | + u8_get_bits(mask[i + 1], GENMASK(5, 0)) << 2; + } + mask_hw[i] = u8_get_bits(mask[i], GENMASK(7, 6)); + + /* Set bit 0-5 to zero */ + mask_hw[0] &= ~GENMASK(5, 0); + + memcpy(rtw_pattern->mask, mask_hw, sizeof(rtw_pattern->mask)); + + /* To get the wake up pattern from the mask. + * We do not count first 12 bits which means + * DA[6] and SA[6] in the pattern to match HW design. + */ + count = 0; + for (i = 12; i < len; i++) { + if ((mask[i / 8] >> (i % 8)) & 0x01) { + content[count] = pattern[i]; + count++; + } + } + + rtw_pattern->crc = rtw89_calc_crc(content, count); + + return 0; +} + +static int rtw89_wow_parse_patterns(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, + struct cfg80211_wowlan *wowlan) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_wow_cam_info *rtw_pattern = rtw_wow->patterns; + int i; + int ret; + + if (!wowlan->n_patterns || !wowlan->patterns) + return 0; + + for (i = 0; i < wowlan->n_patterns; i++) { + rtw_pattern = &rtw_wow->patterns[i]; + ret = rtw89_wow_pattern_generate(rtwdev, rtwvif, + &wowlan->patterns[i], + rtw_pattern); + if (ret) { + rtw89_err(rtwdev, "failed to generate pattern(%d)\n", i); + rtw_wow->pattern_cnt = 0; + return ret; + } + + rtw_pattern->r_w = true; + rtw_pattern->idx = i; + rtw_pattern->negative_pattern_match = false; + rtw_pattern->skip_mac_hdr = true; + rtw_pattern->valid = true; + } + rtw_wow->pattern_cnt = wowlan->n_patterns; + + return 0; +} + +static void rtw89_wow_pattern_clear_cam(struct rtw89_dev *rtwdev) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_wow_cam_info *rtw_pattern = rtw_wow->patterns; + int i = 0; + + for (i = 0; i < rtw_wow->pattern_cnt; i++) { + rtw_pattern = &rtw_wow->patterns[i]; + rtw_pattern->valid = false; + rtw89_fw_wow_cam_update(rtwdev, rtw_pattern); + } +} + +static void rtw89_wow_pattern_write(struct rtw89_dev *rtwdev) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_wow_cam_info *rtw_pattern = rtw_wow->patterns; + int i; + + for (i = 0; i < rtw_wow->pattern_cnt; i++) + rtw89_fw_wow_cam_update(rtwdev, rtw_pattern + i); +} + +static void rtw89_wow_pattern_clear(struct rtw89_dev *rtwdev) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + + rtw89_wow_pattern_clear_cam(rtwdev); + + rtw_wow->pattern_cnt = 0; + memset(rtw_wow->patterns, 0, sizeof(rtw_wow->patterns)); +} + +static void rtw89_wow_clear_wakeups(struct rtw89_dev *rtwdev) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + + rtw_wow->wow_vif = NULL; + rtw89_core_release_all_bits_map(rtw_wow->flags, RTW89_WOW_FLAG_NUM); + rtw_wow->pattern_cnt = 0; +} + +static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev, + struct cfg80211_wowlan *wowlan) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_vif *rtwvif; + + if (wowlan->disconnect) + set_bit(RTW89_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags); + if (wowlan->magic_pkt) + set_bit(RTW89_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags); + + rtw89_for_each_rtwvif(rtwdev, rtwvif) + rtw89_wow_vif_iter(rtwdev, rtwvif); + + if (!rtw_wow->wow_vif) + return -EPERM; + + rtwvif = (struct rtw89_vif *)rtw_wow->wow_vif->drv_priv; + return rtw89_wow_parse_patterns(rtwdev, rtwvif, wowlan); +} + +static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; + struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct ieee80211_sta *wow_sta; + struct rtw89_sta *rtwsta = NULL; + bool is_conn = true; + int ret; + + wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid); + if (wow_sta) + rtwsta = (struct rtw89_sta *)wow_sta->drv_priv; + else + is_conn = false; + + if (wow) { + if (rtw_wow->pattern_cnt) + rtwvif->wowlan_pattern = true; + if (test_bit(RTW89_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags)) + rtwvif->wowlan_magic = true; + } else { + rtwvif->wowlan_pattern = false; + rtwvif->wowlan_magic = false; + } + + ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif, wow); + if (ret) { + rtw89_err(rtwdev, "failed to fw wow wakeup ctrl\n"); + return ret; + } + + if (wow) { + ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); + if (ret) { + rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n", + ret); + return ret; + } + } + + ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, !is_conn); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c join info\n"); + return ret; + } + + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c cam\n"); + return ret; + } + + ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif, wow); + if (ret) { + rtw89_err(rtwdev, "failed to fw wow global\n"); + return ret; + } + + return 0; +} + +static int rtw89_wow_check_fw_status(struct rtw89_dev *rtwdev, bool wow_enable) +{ + u8 polling; + int ret; + + ret = read_poll_timeout_atomic(rtw89_read8_mask, polling, + wow_enable == !!polling, + 50, 50000, false, rtwdev, + R_AX_WOW_CTRL, B_AX_WOW_WOWEN); + if (ret) + rtw89_err(rtwdev, "failed to check wow status %s\n", + wow_enable ? "enabled" : "disabled"); + return ret; +} + +static void rtw89_wow_release_pkt_list(struct rtw89_dev *rtwdev) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct list_head *pkt_list = &rtw_wow->pkt_list; + struct rtw89_pktofld_info *info, *tmp; + + list_for_each_entry_safe(info, tmp, pkt_list, list) { + rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id); + rtw89_core_release_bit_map(rtwdev->pkt_offload, + info->id); + list_del(&info->list); + kfree(info); + } +} + +static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) +{ + enum rtw89_fw_type fw_type = wow ? RTW89_FW_WOWLAN : RTW89_FW_NORMAL; + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; + struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct ieee80211_sta *wow_sta; + struct rtw89_sta *rtwsta = NULL; + bool is_conn = true; + int ret; + + rtw89_hci_disable_intr(rtwdev); + + wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid); + if (wow_sta) + rtwsta = (struct rtw89_sta *)wow_sta->drv_priv; + else + is_conn = false; + + ret = rtw89_fw_download(rtwdev, fw_type); + if (ret) { + rtw89_warn(rtwdev, "download fw failed\n"); + return ret; + } + + rtw89_phy_init_rf_reg(rtwdev, true); + + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, + RTW89_ROLE_FW_RESTORE); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c role maintain\n"); + return ret; + } + + ret = rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, wow_vif, wow_sta); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c assoc cmac tbl\n"); + return ret; + } + + if (!is_conn) + rtw89_cam_reset_keys(rtwdev); + + ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, !is_conn); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c join info\n"); + return ret; + } + + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + if (ret) { + rtw89_warn(rtwdev, "failed to send h2c cam\n"); + return ret; + } + + if (is_conn) { + rtw89_phy_ra_assoc(rtwdev, wow_sta); + rtw89_phy_set_bss_color(rtwdev, wow_vif); + rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, wow_vif); + } + + rtw89_mac_hw_mgnt_sec(rtwdev, wow); + rtw89_hci_enable_intr(rtwdev); + + return 0; +} + +static int rtw89_wow_enable_trx_pre(struct rtw89_dev *rtwdev) +{ + int ret; + + rtw89_hci_ctrl_txdma_ch(rtwdev, false); + rtw89_hci_ctrl_txdma_fw_ch(rtwdev, true); + + rtw89_mac_ptk_drop_by_band_and_wait(rtwdev, RTW89_MAC_0); + + ret = rtw89_hci_poll_txdma_ch(rtwdev); + if (ret) { + rtw89_err(rtwdev, "txdma ch busy\n"); + return ret; + } + rtw89_wow_set_rx_filter(rtwdev, true); + + ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false); + if (ret) { + rtw89_err(rtwdev, "cfg ppdu status\n"); + return ret; + } + + return 0; +} + +static int rtw89_wow_enable_trx_post(struct rtw89_dev *rtwdev) +{ + int ret; + + rtw89_hci_disable_intr(rtwdev); + rtw89_hci_ctrl_trxhci(rtwdev, false); + + ret = rtw89_hci_poll_txdma_ch(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to poll txdma ch idle pcie\n"); + return ret; + } + + ret = rtw89_wow_config_mac(rtwdev, true); + if (ret) { + rtw89_err(rtwdev, "failed to config mac\n"); + return ret; + } + + rtw89_wow_set_rx_filter(rtwdev, false); + rtw89_hci_reset(rtwdev); + + return 0; +} + +static int rtw89_wow_disable_trx_pre(struct rtw89_dev *rtwdev) +{ + int ret; + + rtw89_hci_clr_idx_all(rtwdev); + + ret = rtw89_hci_rst_bdram(rtwdev); + if (ret) { + rtw89_warn(rtwdev, "reset bdram busy\n"); + return ret; + } + + rtw89_hci_ctrl_trxhci(rtwdev, true); + rtw89_hci_ctrl_txdma_ch(rtwdev, true); + + ret = rtw89_wow_config_mac(rtwdev, false); + if (ret) { + rtw89_err(rtwdev, "failed to config mac\n"); + return ret; + } + rtw89_hci_enable_intr(rtwdev); + + return 0; +} + +static int rtw89_wow_disable_trx_post(struct rtw89_dev *rtwdev) +{ + int ret; + + ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); + if (ret) + rtw89_err(rtwdev, "cfg ppdu status\n"); + + return ret; +} + +static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_vif *rtwvif = (struct rtw89_vif *)rtw_wow->wow_vif->drv_priv; + int ret; + + rtw89_wow_pattern_write(rtwdev); + + ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, true); + if (ret) { + rtw89_err(rtwdev, "wow: failed to enable keep alive\n"); + return ret; + } + + ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, true); + if (ret) { + rtw89_err(rtwdev, "wow: failed to enable disconnect detect\n"); + goto out; + } + + ret = rtw89_wow_cfg_wake(rtwdev, true); + if (ret) { + rtw89_err(rtwdev, "wow: failed to config wake\n"); + goto out; + } + + ret = rtw89_wow_check_fw_status(rtwdev, true); + if (ret) { + rtw89_err(rtwdev, "wow: failed to check enable fw ready\n"); + goto out; + } + +out: + return ret; +} + +static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_vif *rtwvif = (struct rtw89_vif *)rtw_wow->wow_vif->drv_priv; + int ret; + + rtw89_wow_pattern_clear(rtwdev); + + ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, false); + if (ret) { + rtw89_err(rtwdev, "wow: failed to disable keep alive\n"); + goto out; + } + + rtw89_wow_release_pkt_list(rtwdev); + + ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, false); + if (ret) { + rtw89_err(rtwdev, "wow: failed to disable disconnect detect\n"); + goto out; + } + + ret = rtw89_wow_cfg_wake(rtwdev, false); + if (ret) { + rtw89_err(rtwdev, "wow: failed to disable config wake\n"); + goto out; + } + + ret = rtw89_wow_check_fw_status(rtwdev, false); + if (ret) { + rtw89_err(rtwdev, "wow: failed to check disable fw ready\n"); + goto out; + } + +out: + return ret; +} + +static int rtw89_wow_enable(struct rtw89_dev *rtwdev) +{ + int ret; + + set_bit(RTW89_FLAG_WOWLAN, rtwdev->flags); + + ret = rtw89_wow_enable_trx_pre(rtwdev); + if (ret) { + rtw89_err(rtwdev, "wow: failed to enable trx_pre\n"); + goto out; + } + + ret = rtw89_wow_swap_fw(rtwdev, true); + if (ret) { + rtw89_err(rtwdev, "wow: failed to swap to wow fw\n"); + goto out; + } + + ret = rtw89_wow_fw_start(rtwdev); + if (ret) { + rtw89_err(rtwdev, "wow: failed to let wow fw start\n"); + goto out; + } + + rtw89_wow_enter_lps(rtwdev); + + ret = rtw89_wow_enable_trx_post(rtwdev); + if (ret) { + rtw89_err(rtwdev, "wow: failed to enable trx_post\n"); + goto out; + } + + return 0; + +out: + clear_bit(RTW89_FLAG_WOWLAN, rtwdev->flags); + return ret; +} + +static int rtw89_wow_disable(struct rtw89_dev *rtwdev) +{ + int ret; + + ret = rtw89_wow_disable_trx_pre(rtwdev); + if (ret) { + rtw89_err(rtwdev, "wow: failed to disable trx_pre\n"); + goto out; + } + + rtw89_wow_leave_lps(rtwdev); + + ret = rtw89_wow_fw_stop(rtwdev); + if (ret) { + rtw89_err(rtwdev, "wow: failed to swap to normal fw\n"); + goto out; + } + + ret = rtw89_wow_swap_fw(rtwdev, false); + if (ret) { + rtw89_err(rtwdev, "wow: failed to disable trx_post\n"); + goto out; + } + + ret = rtw89_wow_disable_trx_post(rtwdev); + if (ret) { + rtw89_err(rtwdev, "wow: failed to disable trx_pre\n"); + goto out; + } + +out: + clear_bit(RTW89_FLAG_WOWLAN, rtwdev->flags); + return ret; +} + +int rtw89_wow_resume(struct rtw89_dev *rtwdev) +{ + int ret; + + if (!test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags)) { + rtw89_err(rtwdev, "wow is not enabled\n"); + ret = -EPERM; + goto out; + } + + if (!rtw89_mac_get_power_state(rtwdev)) { + rtw89_err(rtwdev, "chip is no power when resume\n"); + ret = -EPERM; + goto out; + } + + rtw89_wow_leave_deep_ps(rtwdev); + + rtw89_wow_show_wakeup_reason(rtwdev); + + ret = rtw89_wow_disable(rtwdev); + if (ret) + rtw89_err(rtwdev, "failed to disable wow\n"); + +out: + rtw89_wow_clear_wakeups(rtwdev); + return ret; +} + +int rtw89_wow_suspend(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan) +{ + int ret; + + ret = rtw89_wow_set_wakeups(rtwdev, wowlan); + if (ret) { + rtw89_err(rtwdev, "failed to set wakeup event\n"); + return ret; + } + + rtw89_wow_leave_lps(rtwdev); + + ret = rtw89_wow_enable(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to enable wow\n"); + return ret; + } + + rtw89_wow_enter_deep_ps(rtwdev); + + return 0; +} diff --git a/drivers/net/wireless/realtek/rtw89/wow.h b/drivers/net/wireless/realtek/rtw89/wow.h new file mode 100644 index 000000000000..a2f7b2e3cdb4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/wow.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2019-2022 Realtek Corporation + */ + +#ifndef __RTW89_WOW_H__ +#define __RTW89_WOW_H__ + +enum rtw89_wake_reason { + RTW89_WOW_RSN_RX_PTK_REKEY = 0x1, + RTW89_WOW_RSN_RX_GTK_REKEY = 0x2, + RTW89_WOW_RSN_RX_DEAUTH = 0x8, + RTW89_WOW_RSN_DISCONNECT = 0x10, + RTW89_WOW_RSN_RX_MAGIC_PKT = 0x21, + RTW89_WOW_RSN_RX_PATTERN_MATCH = 0x23, + RTW89_WOW_RSN_RX_NLO = 0x55, +}; + +int rtw89_wow_suspend(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan); +int rtw89_wow_resume(struct rtw89_dev *rtwdev); + +#endif diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c index 0f3a80f66b61..ead4d4e04328 100644 --- a/drivers/net/wireless/rsi/rsi_91x_core.c +++ b/drivers/net/wireless/rsi/rsi_91x_core.c @@ -466,7 +466,9 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb) tid, 0); } } - if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { + + if (IEEE80211_SKB_CB(skb)->control.flags & + IEEE80211_TX_CTRL_PORT_CTRL_PROTO) { q_num = MGMT_SOFT_Q; skb->priority = q_num; } diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c index c61f83a7333b..c7460fbba014 100644 --- a/drivers/net/wireless/rsi/rsi_91x_hal.c +++ b/drivers/net/wireless/rsi/rsi_91x_hal.c @@ -162,12 +162,16 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb) u8 header_size; u8 vap_id = 0; u8 dword_align_bytes; + bool tx_eapol; u16 seq_num; info = IEEE80211_SKB_CB(skb); vif = info->control.vif; tx_params = (struct skb_info *)info->driver_data; + tx_eapol = IEEE80211_SKB_CB(skb)->control.flags & + IEEE80211_TX_CTRL_PORT_CTRL_PROTO; + header_size = FRAME_DESC_SZ + sizeof(struct rsi_xtended_desc); if (header_size > skb_headroom(skb)) { rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__); @@ -231,7 +235,7 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb) } } - if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { + if (tx_eapol) { rsi_dbg(INFO_ZONE, "*** Tx EAPOL ***\n"); data_desc->frame_info = cpu_to_le16(RATE_INFO_ENABLE); diff --git a/drivers/net/wireless/ti/Kconfig b/drivers/net/wireless/ti/Kconfig index 7c0b17a76fe2..3fcd9e395f72 100644 --- a/drivers/net/wireless/ti/Kconfig +++ b/drivers/net/wireless/ti/Kconfig @@ -18,12 +18,4 @@ source "drivers/net/wireless/ti/wl18xx/Kconfig" # keep last for automatic dependencies source "drivers/net/wireless/ti/wlcore/Kconfig" -config WILINK_PLATFORM_DATA - bool "TI WiLink platform data" - depends on WLCORE_SDIO || WL1251_SDIO - default y - help - Small platform data bit needed to pass data to the sdio modules. - - endif # WLAN_VENDOR_TI diff --git a/drivers/net/wireless/ti/wilink_platform_data.c b/drivers/net/wireless/ti/wilink_platform_data.c deleted file mode 100644 index 1de6a62d526f..000000000000 --- a/drivers/net/wireless/ti/wilink_platform_data.c +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * This file is part of wl12xx - * - * Copyright (C) 2010-2011 Texas Instruments, Inc. - */ - -#include <linux/module.h> -#include <linux/err.h> -#include <linux/wl12xx.h> - -static struct wl1251_platform_data *wl1251_platform_data; - -int __init wl1251_set_platform_data(const struct wl1251_platform_data *data) -{ - if (wl1251_platform_data) - return -EBUSY; - if (!data) - return -EINVAL; - - wl1251_platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL); - if (!wl1251_platform_data) - return -ENOMEM; - - return 0; -} - -struct wl1251_platform_data *wl1251_get_platform_data(void) -{ - if (!wl1251_platform_data) - return ERR_PTR(-ENODEV); - - return wl1251_platform_data; -} -EXPORT_SYMBOL(wl1251_get_platform_data); diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c index c9a4e9a43400..301bd0043a43 100644 --- a/drivers/net/wireless/ti/wl1251/sdio.c +++ b/drivers/net/wireless/ti/wl1251/sdio.c @@ -12,7 +12,6 @@ #include <linux/mmc/sdio_func.h> #include <linux/mmc/sdio_ids.h> #include <linux/platform_device.h> -#include <linux/wl12xx.h> #include <linux/irq.h> #include <linux/pm_runtime.h> #include <linux/of.h> @@ -197,7 +196,6 @@ static int wl1251_sdio_probe(struct sdio_func *func, struct wl1251 *wl; struct ieee80211_hw *hw; struct wl1251_sdio *wl_sdio; - const struct wl1251_platform_data *wl1251_board_data; struct device_node *np = func->dev.of_node; hw = wl1251_alloc_hw(); @@ -225,11 +223,7 @@ static int wl1251_sdio_probe(struct sdio_func *func, wl->if_priv = wl_sdio; wl->if_ops = &wl1251_sdio_ops; - wl1251_board_data = wl1251_get_platform_data(); - if (!IS_ERR(wl1251_board_data)) { - wl->irq = wl1251_board_data->irq; - wl->use_eeprom = wl1251_board_data->use_eeprom; - } else if (np) { + if (np) { wl->use_eeprom = of_property_read_bool(np, "ti,wl1251-has-eeprom"); wl->irq = of_irq_get(np, 0); if (wl->irq == -EPROBE_DEFER) { diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c index 9df38726e8b0..29292f06bd3d 100644 --- a/drivers/net/wireless/ti/wl1251/spi.c +++ b/drivers/net/wireless/ti/wl1251/spi.c @@ -5,6 +5,7 @@ * Copyright (C) 2008 Nokia Corporation */ +#include <linux/err.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/module.h> @@ -12,16 +13,19 @@ #include <linux/swab.h> #include <linux/crc7.h> #include <linux/spi/spi.h> -#include <linux/wl12xx.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/of.h> -#include <linux/of_gpio.h> #include <linux/regulator/consumer.h> #include "wl1251.h" #include "reg.h" #include "spi.h" +struct wl1251_spi { + struct spi_device *spi; + struct gpio_desc *power_gpio; +}; + static irqreturn_t wl1251_irq(int irq, void *cookie) { struct wl1251 *wl; @@ -35,13 +39,9 @@ static irqreturn_t wl1251_irq(int irq, void *cookie) return IRQ_HANDLED; } -static struct spi_device *wl_to_spi(struct wl1251 *wl) -{ - return wl->if_priv; -} - static void wl1251_spi_reset(struct wl1251 *wl) { + struct wl1251_spi *wl_spi = wl->if_priv; u8 *cmd; struct spi_transfer t; struct spi_message m; @@ -61,7 +61,7 @@ static void wl1251_spi_reset(struct wl1251 *wl) t.len = WSPI_INIT_CMD_LEN; spi_message_add_tail(&t, &m); - spi_sync(wl_to_spi(wl), &m); + spi_sync(wl_spi->spi, &m); wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); @@ -70,6 +70,7 @@ static void wl1251_spi_reset(struct wl1251 *wl) static void wl1251_spi_wake(struct wl1251 *wl) { + struct wl1251_spi *wl_spi = wl->if_priv; struct spi_transfer t; struct spi_message m; u8 *cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); @@ -113,7 +114,7 @@ static void wl1251_spi_wake(struct wl1251 *wl) t.len = WSPI_INIT_CMD_LEN; spi_message_add_tail(&t, &m); - spi_sync(wl_to_spi(wl), &m); + spi_sync(wl_spi->spi, &m); wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); @@ -129,6 +130,7 @@ static void wl1251_spi_reset_wake(struct wl1251 *wl) static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf, size_t len) { + struct wl1251_spi *wl_spi = wl->if_priv; struct spi_transfer t[3]; struct spi_message m; u8 *busy_buf; @@ -158,7 +160,7 @@ static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf, t[2].len = len; spi_message_add_tail(&t[2], &m); - spi_sync(wl_to_spi(wl), &m); + spi_sync(wl_spi->spi, &m); /* FIXME: check busy words */ @@ -169,6 +171,7 @@ static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf, static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf, size_t len) { + struct wl1251_spi *wl_spi = wl->if_priv; struct spi_transfer t[2]; struct spi_message m; u32 *cmd; @@ -191,7 +194,7 @@ static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf, t[1].len = len; spi_message_add_tail(&t[1], &m); - spi_sync(wl_to_spi(wl), &m); + spi_sync(wl_spi->spi, &m); wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); @@ -209,8 +212,10 @@ static void wl1251_spi_disable_irq(struct wl1251 *wl) static int wl1251_spi_set_power(struct wl1251 *wl, bool enable) { - if (gpio_is_valid(wl->power_gpio)) - gpio_set_value(wl->power_gpio, enable); + struct wl1251_spi *wl_spi = wl->if_priv; + + if (wl_spi->power_gpio) + gpiod_set_value_cansleep(wl_spi->power_gpio, enable); return 0; } @@ -226,16 +231,20 @@ static const struct wl1251_if_operations wl1251_spi_ops = { static int wl1251_spi_probe(struct spi_device *spi) { - struct wl1251_platform_data *pdata = dev_get_platdata(&spi->dev); struct device_node *np = spi->dev.of_node; struct ieee80211_hw *hw; + struct wl1251_spi *wl_spi; struct wl1251 *wl; int ret; - if (!np && !pdata) { - wl1251_error("no platform data"); + if (!np) return -ENODEV; - } + + wl_spi = devm_kzalloc(&spi->dev, sizeof(*wl_spi), GFP_KERNEL); + if (!wl_spi) + return -ENOMEM; + + wl_spi->spi = spi; hw = wl1251_alloc_hw(); if (IS_ERR(hw)) @@ -245,7 +254,7 @@ static int wl1251_spi_probe(struct spi_device *spi) SET_IEEE80211_DEV(hw, &spi->dev); spi_set_drvdata(spi, wl); - wl->if_priv = spi; + wl->if_priv = wl_spi; wl->if_ops = &wl1251_spi_ops; /* This is the only SPI value that we need to set here, the rest @@ -259,32 +268,19 @@ static int wl1251_spi_probe(struct spi_device *spi) goto out_free; } - if (np) { - wl->use_eeprom = of_property_read_bool(np, "ti,wl1251-has-eeprom"); - wl->power_gpio = of_get_named_gpio(np, "ti,power-gpio", 0); - } else if (pdata) { - wl->power_gpio = pdata->power_gpio; - wl->use_eeprom = pdata->use_eeprom; - } + wl->use_eeprom = of_property_read_bool(np, "ti,wl1251-has-eeprom"); - if (wl->power_gpio == -EPROBE_DEFER) { - ret = -EPROBE_DEFER; - goto out_free; - } - - if (gpio_is_valid(wl->power_gpio)) { - ret = devm_gpio_request_one(&spi->dev, wl->power_gpio, - GPIOF_OUT_INIT_LOW, "wl1251 power"); - if (ret) { + wl_spi->power_gpio = devm_gpiod_get_optional(&spi->dev, "ti,power", + GPIOD_OUT_LOW); + ret = PTR_ERR_OR_ZERO(wl_spi->power_gpio); + if (ret) { + if (ret != -EPROBE_DEFER) wl1251_error("Failed to request gpio: %d\n", ret); - goto out_free; - } - } else { - wl1251_error("set power gpio missing in platform data"); - ret = -ENODEV; goto out_free; } + gpiod_set_consumer_name(wl_spi->power_gpio, "wl1251 power"); + wl->irq = spi->irq; if (wl->irq < 0) { wl1251_error("irq missing in platform data"); diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h index 23ae07dd4c2e..83adbc3c25dc 100644 --- a/drivers/net/wireless/ti/wl1251/wl1251.h +++ b/drivers/net/wireless/ti/wl1251/wl1251.h @@ -262,7 +262,6 @@ struct wl1251 { void *if_priv; const struct wl1251_if_operations *if_ops; - int power_gpio; int irq; bool use_eeprom; diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 7eae1ec2eb2b..2d2edddc77bd 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -14,7 +14,6 @@ #include <linux/swab.h> #include <linux/crc7.h> #include <linux/spi/spi.h> -#include <linux/wl12xx.h> #include <linux/platform_device.h> #include <linux/of_irq.h> #include <linux/regulator/consumer.h> diff --git a/drivers/net/wireless/zydas/zd1201.c b/drivers/net/wireless/zydas/zd1201.c index 82bc0d44212e..a85fe7e4c6d4 100644 --- a/drivers/net/wireless/zydas/zd1201.c +++ b/drivers/net/wireless/zydas/zd1201.c @@ -886,7 +886,7 @@ static void zd1201_set_multicast(struct net_device *dev) } static int zd1201_config_commit(struct net_device *dev, - struct iw_request_info *info, struct iw_point *data, char *essid) + struct iw_request_info *info, union iwreq_data *wrqu, char *essid) { struct zd1201 *zd = netdev_priv(dev); @@ -894,15 +894,16 @@ static int zd1201_config_commit(struct net_device *dev, } static int zd1201_get_name(struct net_device *dev, - struct iw_request_info *info, char *name, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - strcpy(name, "IEEE 802.11b"); + strcpy(wrqu->name, "IEEE 802.11b"); return 0; } static int zd1201_set_freq(struct net_device *dev, - struct iw_request_info *info, struct iw_freq *freq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct iw_freq *freq = &wrqu->freq; struct zd1201 *zd = netdev_priv(dev); short channel = 0; int err; @@ -922,8 +923,9 @@ static int zd1201_set_freq(struct net_device *dev, } static int zd1201_get_freq(struct net_device *dev, - struct iw_request_info *info, struct iw_freq *freq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct iw_freq *freq = &wrqu->freq; struct zd1201 *zd = netdev_priv(dev); short channel; int err; @@ -938,8 +940,9 @@ static int zd1201_get_freq(struct net_device *dev, } static int zd1201_set_mode(struct net_device *dev, - struct iw_request_info *info, __u32 *mode, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + __u32 *mode = &wrqu->mode; struct zd1201 *zd = netdev_priv(dev); short porttype, monitor = 0; unsigned char buffer[IW_ESSID_MAX_SIZE+2]; @@ -1001,8 +1004,9 @@ static int zd1201_set_mode(struct net_device *dev, } static int zd1201_get_mode(struct net_device *dev, - struct iw_request_info *info, __u32 *mode, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + __u32 *mode = &wrqu->mode; struct zd1201 *zd = netdev_priv(dev); short porttype; int err; @@ -1038,8 +1042,9 @@ static int zd1201_get_mode(struct net_device *dev, } static int zd1201_get_range(struct net_device *dev, - struct iw_request_info *info, struct iw_point *wrq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct iw_point *wrq = &wrqu->data; struct iw_range *range = (struct iw_range *)extra; wrq->length = sizeof(struct iw_range); @@ -1077,8 +1082,9 @@ static int zd1201_get_range(struct net_device *dev, * the stats after asking the bssid. */ static int zd1201_get_wap(struct net_device *dev, - struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct sockaddr *ap_addr = &wrqu->ap_addr; struct zd1201 *zd = netdev_priv(dev); unsigned char buffer[6]; @@ -1098,15 +1104,16 @@ static int zd1201_get_wap(struct net_device *dev, } static int zd1201_set_scan(struct net_device *dev, - struct iw_request_info *info, struct iw_point *srq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { /* We do everything in get_scan */ return 0; } static int zd1201_get_scan(struct net_device *dev, - struct iw_request_info *info, struct iw_point *srq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct iw_point *srq = &wrqu->data; struct zd1201 *zd = netdev_priv(dev); int err, i, j, enabled_save; struct iw_event iwe; @@ -1197,8 +1204,9 @@ static int zd1201_get_scan(struct net_device *dev, } static int zd1201_set_essid(struct net_device *dev, - struct iw_request_info *info, struct iw_point *data, char *essid) + struct iw_request_info *info, union iwreq_data *wrqu, char *essid) { + struct iw_point *data = &wrqu->data; struct zd1201 *zd = netdev_priv(dev); if (data->length > IW_ESSID_MAX_SIZE) @@ -1212,8 +1220,9 @@ static int zd1201_set_essid(struct net_device *dev, } static int zd1201_get_essid(struct net_device *dev, - struct iw_request_info *info, struct iw_point *data, char *essid) + struct iw_request_info *info, union iwreq_data *wrqu, char *essid) { + struct iw_point *data = &wrqu->data; struct zd1201 *zd = netdev_priv(dev); memcpy(essid, zd->essid, zd->essidlen); @@ -1224,8 +1233,9 @@ static int zd1201_get_essid(struct net_device *dev, } static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *nick) + union iwreq_data *wrqu, char *nick) { + struct iw_point *data = &wrqu->data; strcpy(nick, "zd1201"); data->flags = 1; data->length = strlen(nick); @@ -1233,8 +1243,9 @@ static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info, } static int zd1201_set_rate(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->bitrate; struct zd1201 *zd = netdev_priv(dev); short rate; int err; @@ -1266,8 +1277,9 @@ static int zd1201_set_rate(struct net_device *dev, } static int zd1201_get_rate(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->bitrate; struct zd1201 *zd = netdev_priv(dev); short rate; int err; @@ -1299,8 +1311,9 @@ static int zd1201_get_rate(struct net_device *dev, } static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rts = &wrqu->rts; struct zd1201 *zd = netdev_priv(dev); int err; short val = rts->value; @@ -1319,8 +1332,9 @@ static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info, } static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rts = &wrqu->rts; struct zd1201 *zd = netdev_priv(dev); short rtst; int err; @@ -1336,8 +1350,9 @@ static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info, } static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *frag, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *frag = &wrqu->frag; struct zd1201 *zd = netdev_priv(dev); int err; short val = frag->value; @@ -1357,8 +1372,9 @@ static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info, } static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *frag, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *frag = &wrqu->frag; struct zd1201 *zd = netdev_priv(dev); short fragt; int err; @@ -1374,20 +1390,21 @@ static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info, } static int zd1201_set_retry(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { return 0; } static int zd1201_get_retry(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { return 0; } static int zd1201_set_encode(struct net_device *dev, - struct iw_request_info *info, struct iw_point *erq, char *key) + struct iw_request_info *info, union iwreq_data *wrqu, char *key) { + struct iw_point *erq = &wrqu->encoding; struct zd1201 *zd = netdev_priv(dev); short i; int err, rid; @@ -1443,8 +1460,9 @@ static int zd1201_set_encode(struct net_device *dev, } static int zd1201_get_encode(struct net_device *dev, - struct iw_request_info *info, struct iw_point *erq, char *key) + struct iw_request_info *info, union iwreq_data *wrqu, char *key) { + struct iw_point *erq = &wrqu->encoding; struct zd1201 *zd = netdev_priv(dev); short i; int err; @@ -1476,8 +1494,9 @@ static int zd1201_get_encode(struct net_device *dev, } static int zd1201_set_power(struct net_device *dev, - struct iw_request_info *info, struct iw_param *vwrq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->power; struct zd1201 *zd = netdev_priv(dev); short enabled, duration, level; int err; @@ -1515,8 +1534,9 @@ out: } static int zd1201_get_power(struct net_device *dev, - struct iw_request_info *info, struct iw_param *vwrq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct iw_param *vwrq = &wrqu->power; struct zd1201 *zd = netdev_priv(dev); short enabled, level, duration; int err; @@ -1553,57 +1573,37 @@ static int zd1201_get_power(struct net_device *dev, static const iw_handler zd1201_iw_handler[] = { - (iw_handler) zd1201_config_commit, /* SIOCSIWCOMMIT */ - (iw_handler) zd1201_get_name, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) zd1201_set_freq, /* SIOCSIWFREQ */ - (iw_handler) zd1201_get_freq, /* SIOCGIWFREQ */ - (iw_handler) zd1201_set_mode, /* SIOCSIWMODE */ - (iw_handler) zd1201_get_mode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) NULL, /* SIOCGIWSENS */ - (iw_handler) NULL, /* SIOCSIWRANGE */ - (iw_handler) zd1201_get_range, /* SIOCGIWRANGE */ - (iw_handler) NULL, /* SIOCSIWPRIV */ - (iw_handler) NULL, /* SIOCGIWPRIV */ - (iw_handler) NULL, /* SIOCSIWSTATS */ - (iw_handler) NULL, /* SIOCGIWSTATS */ - (iw_handler) NULL, /* SIOCSIWSPY */ - (iw_handler) NULL, /* SIOCGIWSPY */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL/*zd1201_set_wap*/, /* SIOCSIWAP */ - (iw_handler) zd1201_get_wap, /* SIOCGIWAP */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCGIWAPLIST */ - (iw_handler) zd1201_set_scan, /* SIOCSIWSCAN */ - (iw_handler) zd1201_get_scan, /* SIOCGIWSCAN */ - (iw_handler) zd1201_set_essid, /* SIOCSIWESSID */ - (iw_handler) zd1201_get_essid, /* SIOCGIWESSID */ - (iw_handler) NULL, /* SIOCSIWNICKN */ - (iw_handler) zd1201_get_nick, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) zd1201_set_rate, /* SIOCSIWRATE */ - (iw_handler) zd1201_get_rate, /* SIOCGIWRATE */ - (iw_handler) zd1201_set_rts, /* SIOCSIWRTS */ - (iw_handler) zd1201_get_rts, /* SIOCGIWRTS */ - (iw_handler) zd1201_set_frag, /* SIOCSIWFRAG */ - (iw_handler) zd1201_get_frag, /* SIOCGIWFRAG */ - (iw_handler) NULL, /* SIOCSIWTXPOW */ - (iw_handler) NULL, /* SIOCGIWTXPOW */ - (iw_handler) zd1201_set_retry, /* SIOCSIWRETRY */ - (iw_handler) zd1201_get_retry, /* SIOCGIWRETRY */ - (iw_handler) zd1201_set_encode, /* SIOCSIWENCODE */ - (iw_handler) zd1201_get_encode, /* SIOCGIWENCODE */ - (iw_handler) zd1201_set_power, /* SIOCSIWPOWER */ - (iw_handler) zd1201_get_power, /* SIOCGIWPOWER */ + IW_HANDLER(SIOCSIWCOMMIT, zd1201_config_commit), + IW_HANDLER(SIOCGIWNAME, zd1201_get_name), + IW_HANDLER(SIOCSIWFREQ, zd1201_set_freq), + IW_HANDLER(SIOCGIWFREQ, zd1201_get_freq), + IW_HANDLER(SIOCSIWMODE, zd1201_set_mode), + IW_HANDLER(SIOCGIWMODE, zd1201_get_mode), + IW_HANDLER(SIOCGIWRANGE, zd1201_get_range), + IW_HANDLER(SIOCGIWAP, zd1201_get_wap), + IW_HANDLER(SIOCSIWSCAN, zd1201_set_scan), + IW_HANDLER(SIOCGIWSCAN, zd1201_get_scan), + IW_HANDLER(SIOCSIWESSID, zd1201_set_essid), + IW_HANDLER(SIOCGIWESSID, zd1201_get_essid), + IW_HANDLER(SIOCGIWNICKN, zd1201_get_nick), + IW_HANDLER(SIOCSIWRATE, zd1201_set_rate), + IW_HANDLER(SIOCGIWRATE, zd1201_get_rate), + IW_HANDLER(SIOCSIWRTS, zd1201_set_rts), + IW_HANDLER(SIOCGIWRTS, zd1201_get_rts), + IW_HANDLER(SIOCSIWFRAG, zd1201_set_frag), + IW_HANDLER(SIOCGIWFRAG, zd1201_get_frag), + IW_HANDLER(SIOCSIWRETRY, zd1201_set_retry), + IW_HANDLER(SIOCGIWRETRY, zd1201_get_retry), + IW_HANDLER(SIOCSIWENCODE, zd1201_set_encode), + IW_HANDLER(SIOCGIWENCODE, zd1201_get_encode), + IW_HANDLER(SIOCSIWPOWER, zd1201_set_power), + IW_HANDLER(SIOCGIWPOWER, zd1201_get_power), }; static int zd1201_set_hostauth(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->param; struct zd1201 *zd = netdev_priv(dev); if (!zd->ap) @@ -1613,8 +1613,9 @@ static int zd1201_set_hostauth(struct net_device *dev, } static int zd1201_get_hostauth(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->param; struct zd1201 *zd = netdev_priv(dev); short hostauth; int err; @@ -1632,8 +1633,9 @@ static int zd1201_get_hostauth(struct net_device *dev, } static int zd1201_auth_sta(struct net_device *dev, - struct iw_request_info *info, struct sockaddr *sta, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct sockaddr *sta = &wrqu->ap_addr; struct zd1201 *zd = netdev_priv(dev); unsigned char buffer[10]; @@ -1648,8 +1650,9 @@ static int zd1201_auth_sta(struct net_device *dev, } static int zd1201_set_maxassoc(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->param; struct zd1201 *zd = netdev_priv(dev); if (!zd->ap) @@ -1659,8 +1662,9 @@ static int zd1201_set_maxassoc(struct net_device *dev, } static int zd1201_get_maxassoc(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) + struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + struct iw_param *rrq = &wrqu->param; struct zd1201 *zd = netdev_priv(dev); short maxassoc; int err; @@ -1678,12 +1682,12 @@ static int zd1201_get_maxassoc(struct net_device *dev, } static const iw_handler zd1201_private_handler[] = { - (iw_handler) zd1201_set_hostauth, /* ZD1201SIWHOSTAUTH */ - (iw_handler) zd1201_get_hostauth, /* ZD1201GIWHOSTAUTH */ - (iw_handler) zd1201_auth_sta, /* ZD1201SIWAUTHSTA */ - (iw_handler) NULL, /* nothing to get */ - (iw_handler) zd1201_set_maxassoc, /* ZD1201SIMAXASSOC */ - (iw_handler) zd1201_get_maxassoc, /* ZD1201GIMAXASSOC */ + zd1201_set_hostauth, /* ZD1201SIWHOSTAUTH */ + zd1201_get_hostauth, /* ZD1201GIWHOSTAUTH */ + zd1201_auth_sta, /* ZD1201SIWAUTHSTA */ + NULL, /* nothing to get */ + zd1201_set_maxassoc, /* ZD1201SIMAXASSOC */ + zd1201_get_maxassoc, /* ZD1201GIMAXASSOC */ }; static const struct iw_priv_args zd1201_private_args[] = { @@ -1703,8 +1707,8 @@ static const struct iw_handler_def zd1201_iw_handlers = { .num_standard = ARRAY_SIZE(zd1201_iw_handler), .num_private = ARRAY_SIZE(zd1201_private_handler), .num_private_args = ARRAY_SIZE(zd1201_private_args), - .standard = (iw_handler *)zd1201_iw_handler, - .private = (iw_handler *)zd1201_private_handler, + .standard = zd1201_iw_handler, + .private = zd1201_private_handler, .private_args = (struct iw_priv_args *) zd1201_private_args, .get_wireless_stats = zd1201_get_wireless_stats, }; diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 2d94c30ed439..0cb6638b55e5 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -4,7 +4,7 @@ #include <linux/platform_device.h> #include <linux/platform_data/brcmnand.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h> /** ChipCommon core registers. **/ #define BCMA_CC_ID 0x0000 diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h deleted file mode 100644 index 03d61f1d23ab..000000000000 --- a/include/linux/wl12xx.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * This file is part of wl12xx - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Luciano Coelho <luciano.coelho@nokia.com> - */ - -#ifndef _LINUX_WL12XX_H -#define _LINUX_WL12XX_H - -#include <linux/err.h> - -struct wl1251_platform_data { - int power_gpio; - /* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */ - int irq; - bool use_eeprom; -}; - -#ifdef CONFIG_WILINK_PLATFORM_DATA - -int wl1251_set_platform_data(const struct wl1251_platform_data *data); - -struct wl1251_platform_data *wl1251_get_platform_data(void); - -#else - -static inline -int wl1251_set_platform_data(const struct wl1251_platform_data *data) -{ - return -ENOSYS; -} - -static inline -struct wl1251_platform_data *wl1251_get_platform_data(void) -{ - return ERR_PTR(-ENODATA); -} - -#endif - -#endif diff --git a/include/net/cfg80211-wext.h b/include/net/cfg80211-wext.h index ad77caf2ffde..0ee36d97e068 100644 --- a/include/net/cfg80211-wext.h +++ b/include/net/cfg80211-wext.h @@ -19,34 +19,34 @@ */ int cfg80211_wext_giwname(struct net_device *dev, struct iw_request_info *info, - char *name, char *extra); + union iwreq_data *wrqu, char *extra); int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, - u32 *mode, char *extra); + union iwreq_data *wrqu, char *extra); int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, - u32 *mode, char *extra); + union iwreq_data *wrqu, char *extra); int cfg80211_wext_siwscan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); int cfg80211_wext_giwscan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra); + union iwreq_data *wrqu, char *extra); int cfg80211_wext_giwrange(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra); + union iwreq_data *wrqu, char *extra); int cfg80211_wext_siwrts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra); + union iwreq_data *wrqu, char *extra); int cfg80211_wext_giwrts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra); + union iwreq_data *wrqu, char *extra); int cfg80211_wext_siwfrag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *frag, char *extra); + union iwreq_data *wrqu, char *extra); int cfg80211_wext_giwfrag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *frag, char *extra); + union iwreq_data *wrqu, char *extra); int cfg80211_wext_giwretry(struct net_device *dev, struct iw_request_info *info, - struct iw_param *retry, char *extra); + union iwreq_data *wrqu, char *extra); #endif /* __NET_CFG80211_WEXT_H */ diff --git a/net/wireless/scan.c b/net/wireless/scan.c index da752b0cc752..e70302a30013 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -3231,8 +3231,9 @@ static int ieee80211_scan_results(struct cfg80211_registered_device *rdev, int cfg80211_wext_giwscan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_point *data = &wrqu->data; struct cfg80211_registered_device *rdev; int res; diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index ddf340bfa07a..8a24dfca75af 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -25,16 +25,17 @@ int cfg80211_wext_giwname(struct net_device *dev, struct iw_request_info *info, - char *name, char *extra) + union iwreq_data *wrqu, char *extra) { - strcpy(name, "IEEE 802.11"); + strcpy(wrqu->name, "IEEE 802.11"); return 0; } EXPORT_WEXT_HANDLER(cfg80211_wext_giwname); int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, - u32 *mode, char *extra) + union iwreq_data *wrqu, char *extra) { + __u32 *mode = &wrqu->mode; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev; struct vif_params vifparams; @@ -71,8 +72,9 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, EXPORT_WEXT_HANDLER(cfg80211_wext_siwmode); int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, - u32 *mode, char *extra) + union iwreq_data *wrqu, char *extra) { + __u32 *mode = &wrqu->mode; struct wireless_dev *wdev = dev->ieee80211_ptr; if (!wdev) @@ -108,8 +110,9 @@ EXPORT_WEXT_HANDLER(cfg80211_wext_giwmode); int cfg80211_wext_giwrange(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_point *data = &wrqu->data; struct wireless_dev *wdev = dev->ieee80211_ptr; struct iw_range *range = (struct iw_range *) extra; enum nl80211_band band; @@ -251,8 +254,9 @@ int cfg80211_wext_freq(struct iw_freq *freq) int cfg80211_wext_siwrts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rts = &wrqu->rts; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); u32 orts = wdev->wiphy->rts_threshold; @@ -281,8 +285,9 @@ EXPORT_WEXT_HANDLER(cfg80211_wext_siwrts); int cfg80211_wext_giwrts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rts = &wrqu->rts; struct wireless_dev *wdev = dev->ieee80211_ptr; rts->value = wdev->wiphy->rts_threshold; @@ -295,8 +300,9 @@ EXPORT_WEXT_HANDLER(cfg80211_wext_giwrts); int cfg80211_wext_siwfrag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *frag, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *frag = &wrqu->frag; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); u32 ofrag = wdev->wiphy->frag_threshold; @@ -325,8 +331,9 @@ EXPORT_WEXT_HANDLER(cfg80211_wext_siwfrag); int cfg80211_wext_giwfrag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *frag, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *frag = &wrqu->frag; struct wireless_dev *wdev = dev->ieee80211_ptr; frag->value = wdev->wiphy->frag_threshold; @@ -339,8 +346,9 @@ EXPORT_WEXT_HANDLER(cfg80211_wext_giwfrag); static int cfg80211_wext_siwretry(struct net_device *dev, struct iw_request_info *info, - struct iw_param *retry, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *retry = &wrqu->retry; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); u32 changed = 0; @@ -378,8 +386,9 @@ static int cfg80211_wext_siwretry(struct net_device *dev, int cfg80211_wext_giwretry(struct net_device *dev, struct iw_request_info *info, - struct iw_param *retry, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *retry = &wrqu->retry; struct wireless_dev *wdev = dev->ieee80211_ptr; retry->disabled = 0; @@ -588,8 +597,9 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, static int cfg80211_wext_siwencode(struct net_device *dev, struct iw_request_info *info, - struct iw_point *erq, char *keybuf) + union iwreq_data *wrqu, char *keybuf) { + struct iw_point *erq = &wrqu->encoding; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); int idx, err; @@ -664,8 +674,9 @@ out: static int cfg80211_wext_siwencodeext(struct net_device *dev, struct iw_request_info *info, - struct iw_point *erq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_point *erq = &wrqu->encoding; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; @@ -767,8 +778,9 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev, static int cfg80211_wext_giwencode(struct net_device *dev, struct iw_request_info *info, - struct iw_point *erq, char *keybuf) + union iwreq_data *wrqu, char *keybuf) { + struct iw_point *erq = &wrqu->encoding; struct wireless_dev *wdev = dev->ieee80211_ptr; int idx; @@ -804,8 +816,9 @@ static int cfg80211_wext_giwencode(struct net_device *dev, static int cfg80211_wext_siwfreq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *wextfreq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_freq *wextfreq = &wrqu->freq; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); struct cfg80211_chan_def chandef = { @@ -870,8 +883,9 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, static int cfg80211_wext_giwfreq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *freq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_freq *freq = &wrqu->freq; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); struct cfg80211_chan_def chandef = {}; @@ -1147,8 +1161,9 @@ static int cfg80211_set_key_mgt(struct wireless_dev *wdev, u32 key_mgt) static int cfg80211_wext_siwauth(struct net_device *dev, struct iw_request_info *info, - struct iw_param *data, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *data = &wrqu->param; struct wireless_dev *wdev = dev->ieee80211_ptr; if (wdev->iftype != NL80211_IFTYPE_STATION) @@ -1180,7 +1195,7 @@ static int cfg80211_wext_siwauth(struct net_device *dev, static int cfg80211_wext_giwauth(struct net_device *dev, struct iw_request_info *info, - struct iw_param *data, char *extra) + union iwreq_data *wrqu, char *extra) { /* XXX: what do we need? */ @@ -1189,8 +1204,9 @@ static int cfg80211_wext_giwauth(struct net_device *dev, static int cfg80211_wext_siwpower(struct net_device *dev, struct iw_request_info *info, - struct iw_param *wrq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *wrq = &wrqu->power; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); bool ps; @@ -1238,8 +1254,9 @@ static int cfg80211_wext_siwpower(struct net_device *dev, static int cfg80211_wext_giwpower(struct net_device *dev, struct iw_request_info *info, - struct iw_param *wrq, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *wrq = &wrqu->power; struct wireless_dev *wdev = dev->ieee80211_ptr; wrq->disabled = !wdev->ps; @@ -1249,8 +1266,9 @@ static int cfg80211_wext_giwpower(struct net_device *dev, static int cfg80211_wext_siwrate(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rate, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rate = &wrqu->bitrate; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); struct cfg80211_bitrate_mask mask; @@ -1307,8 +1325,9 @@ static int cfg80211_wext_siwrate(struct net_device *dev, static int cfg80211_wext_giwrate(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rate, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_param *rate = &wrqu->bitrate; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); struct station_info sinfo = {}; @@ -1430,8 +1449,9 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) static int cfg80211_wext_siwap(struct net_device *dev, struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) + union iwreq_data *wrqu, char *extra) { + struct sockaddr *ap_addr = &wrqu->ap_addr; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); int ret; @@ -1455,8 +1475,9 @@ static int cfg80211_wext_siwap(struct net_device *dev, static int cfg80211_wext_giwap(struct net_device *dev, struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) + union iwreq_data *wrqu, char *extra) { + struct sockaddr *ap_addr = &wrqu->ap_addr; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); int ret; @@ -1480,8 +1501,9 @@ static int cfg80211_wext_giwap(struct net_device *dev, static int cfg80211_wext_siwessid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *ssid) + union iwreq_data *wrqu, char *ssid) { + struct iw_point *data = &wrqu->data; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); int ret; @@ -1505,8 +1527,9 @@ static int cfg80211_wext_siwessid(struct net_device *dev, static int cfg80211_wext_giwessid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *ssid) + union iwreq_data *wrqu, char *ssid) { + struct iw_point *data = &wrqu->data; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); int ret; @@ -1533,7 +1556,7 @@ static int cfg80211_wext_giwessid(struct net_device *dev, static int cfg80211_wext_siwpmksa(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); @@ -1584,78 +1607,39 @@ static int cfg80211_wext_siwpmksa(struct net_device *dev, return ret; } -#define DEFINE_WEXT_COMPAT_STUB(func, type) \ - static int __ ## func(struct net_device *dev, \ - struct iw_request_info *info, \ - union iwreq_data *wrqu, \ - char *extra) \ - { \ - return func(dev, info, (type *)wrqu, extra); \ - } - -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwname, char) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwfreq, struct iw_freq) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwfreq, struct iw_freq) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwmode, u32) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwmode, u32) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwrange, struct iw_point) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwap, struct sockaddr) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwap, struct sockaddr) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwmlme, struct iw_point) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwscan, struct iw_point) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwessid, struct iw_point) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwessid, struct iw_point) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwrate, struct iw_param) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwrate, struct iw_param) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwrts, struct iw_param) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwrts, struct iw_param) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwfrag, struct iw_param) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwfrag, struct iw_param) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwretry, struct iw_param) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwretry, struct iw_param) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwencode, struct iw_point) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwencode, struct iw_point) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwpower, struct iw_param) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwpower, struct iw_param) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwgenie, struct iw_point) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwauth, struct iw_param) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwauth, struct iw_param) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwencodeext, struct iw_point) -DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwpmksa, struct iw_point) - static const iw_handler cfg80211_handlers[] = { - [IW_IOCTL_IDX(SIOCGIWNAME)] = __cfg80211_wext_giwname, - [IW_IOCTL_IDX(SIOCSIWFREQ)] = __cfg80211_wext_siwfreq, - [IW_IOCTL_IDX(SIOCGIWFREQ)] = __cfg80211_wext_giwfreq, - [IW_IOCTL_IDX(SIOCSIWMODE)] = __cfg80211_wext_siwmode, - [IW_IOCTL_IDX(SIOCGIWMODE)] = __cfg80211_wext_giwmode, - [IW_IOCTL_IDX(SIOCGIWRANGE)] = __cfg80211_wext_giwrange, - [IW_IOCTL_IDX(SIOCSIWAP)] = __cfg80211_wext_siwap, - [IW_IOCTL_IDX(SIOCGIWAP)] = __cfg80211_wext_giwap, - [IW_IOCTL_IDX(SIOCSIWMLME)] = __cfg80211_wext_siwmlme, - [IW_IOCTL_IDX(SIOCSIWSCAN)] = cfg80211_wext_siwscan, - [IW_IOCTL_IDX(SIOCGIWSCAN)] = __cfg80211_wext_giwscan, - [IW_IOCTL_IDX(SIOCSIWESSID)] = __cfg80211_wext_siwessid, - [IW_IOCTL_IDX(SIOCGIWESSID)] = __cfg80211_wext_giwessid, - [IW_IOCTL_IDX(SIOCSIWRATE)] = __cfg80211_wext_siwrate, - [IW_IOCTL_IDX(SIOCGIWRATE)] = __cfg80211_wext_giwrate, - [IW_IOCTL_IDX(SIOCSIWRTS)] = __cfg80211_wext_siwrts, - [IW_IOCTL_IDX(SIOCGIWRTS)] = __cfg80211_wext_giwrts, - [IW_IOCTL_IDX(SIOCSIWFRAG)] = __cfg80211_wext_siwfrag, - [IW_IOCTL_IDX(SIOCGIWFRAG)] = __cfg80211_wext_giwfrag, - [IW_IOCTL_IDX(SIOCSIWTXPOW)] = cfg80211_wext_siwtxpower, - [IW_IOCTL_IDX(SIOCGIWTXPOW)] = cfg80211_wext_giwtxpower, - [IW_IOCTL_IDX(SIOCSIWRETRY)] = __cfg80211_wext_siwretry, - [IW_IOCTL_IDX(SIOCGIWRETRY)] = __cfg80211_wext_giwretry, - [IW_IOCTL_IDX(SIOCSIWENCODE)] = __cfg80211_wext_siwencode, - [IW_IOCTL_IDX(SIOCGIWENCODE)] = __cfg80211_wext_giwencode, - [IW_IOCTL_IDX(SIOCSIWPOWER)] = __cfg80211_wext_siwpower, - [IW_IOCTL_IDX(SIOCGIWPOWER)] = __cfg80211_wext_giwpower, - [IW_IOCTL_IDX(SIOCSIWGENIE)] = __cfg80211_wext_siwgenie, - [IW_IOCTL_IDX(SIOCSIWAUTH)] = __cfg80211_wext_siwauth, - [IW_IOCTL_IDX(SIOCGIWAUTH)] = __cfg80211_wext_giwauth, - [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= __cfg80211_wext_siwencodeext, - [IW_IOCTL_IDX(SIOCSIWPMKSA)] = __cfg80211_wext_siwpmksa, + IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname), + IW_HANDLER(SIOCSIWFREQ, cfg80211_wext_siwfreq), + IW_HANDLER(SIOCGIWFREQ, cfg80211_wext_giwfreq), + IW_HANDLER(SIOCSIWMODE, cfg80211_wext_siwmode), + IW_HANDLER(SIOCGIWMODE, cfg80211_wext_giwmode), + IW_HANDLER(SIOCGIWRANGE, cfg80211_wext_giwrange), + IW_HANDLER(SIOCSIWAP, cfg80211_wext_siwap), + IW_HANDLER(SIOCGIWAP, cfg80211_wext_giwap), + IW_HANDLER(SIOCSIWMLME, cfg80211_wext_siwmlme), + IW_HANDLER(SIOCSIWSCAN, cfg80211_wext_siwscan), + IW_HANDLER(SIOCGIWSCAN, cfg80211_wext_giwscan), + IW_HANDLER(SIOCSIWESSID, cfg80211_wext_siwessid), + IW_HANDLER(SIOCGIWESSID, cfg80211_wext_giwessid), + IW_HANDLER(SIOCSIWRATE, cfg80211_wext_siwrate), + IW_HANDLER(SIOCGIWRATE, cfg80211_wext_giwrate), + IW_HANDLER(SIOCSIWRTS, cfg80211_wext_siwrts), + IW_HANDLER(SIOCGIWRTS, cfg80211_wext_giwrts), + IW_HANDLER(SIOCSIWFRAG, cfg80211_wext_siwfrag), + IW_HANDLER(SIOCGIWFRAG, cfg80211_wext_giwfrag), + IW_HANDLER(SIOCSIWTXPOW, cfg80211_wext_siwtxpower), + IW_HANDLER(SIOCGIWTXPOW, cfg80211_wext_giwtxpower), + IW_HANDLER(SIOCSIWRETRY, cfg80211_wext_siwretry), + IW_HANDLER(SIOCGIWRETRY, cfg80211_wext_giwretry), + IW_HANDLER(SIOCSIWENCODE, cfg80211_wext_siwencode), + IW_HANDLER(SIOCGIWENCODE, cfg80211_wext_giwencode), + IW_HANDLER(SIOCSIWPOWER, cfg80211_wext_siwpower), + IW_HANDLER(SIOCGIWPOWER, cfg80211_wext_giwpower), + IW_HANDLER(SIOCSIWGENIE, cfg80211_wext_siwgenie), + IW_HANDLER(SIOCSIWAUTH, cfg80211_wext_siwauth), + IW_HANDLER(SIOCGIWAUTH, cfg80211_wext_giwauth), + IW_HANDLER(SIOCSIWENCODEEXT, cfg80211_wext_siwencodeext), + IW_HANDLER(SIOCSIWPMKSA, cfg80211_wext_siwpmksa), }; const struct iw_handler_def cfg80211_wext_handler = { diff --git a/net/wireless/wext-compat.h b/net/wireless/wext-compat.h index 8d3cc1552e2f..c02eb789e676 100644 --- a/net/wireless/wext-compat.h +++ b/net/wireless/wext-compat.h @@ -13,7 +13,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *freq, char *extra); + struct iw_freq *wextfreq, char *extra); int cfg80211_ibss_wext_giwfreq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra); @@ -32,7 +32,7 @@ int cfg80211_ibss_wext_giwessid(struct net_device *dev, int cfg80211_mgd_wext_siwfreq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *freq, char *extra); + struct iw_freq *wextfreq, char *extra); int cfg80211_mgd_wext_giwfreq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra); @@ -51,10 +51,10 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev, int cfg80211_wext_siwmlme(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra); + union iwreq_data *wrqu, char *extra); int cfg80211_wext_siwgenie(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra); + union iwreq_data *wrqu, char *extra); int cfg80211_wext_freq(struct iw_freq *freq); diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 68f45afc352d..191c6d98c700 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c @@ -324,8 +324,9 @@ int cfg80211_mgd_wext_giwap(struct net_device *dev, int cfg80211_wext_siwgenie(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { + struct iw_point *data = &wrqu->data; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); u8 *ie = extra; @@ -374,7 +375,7 @@ int cfg80211_wext_siwgenie(struct net_device *dev, int cfg80211_wext_siwmlme(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct iw_mlme *mlme = (struct iw_mlme *)extra; |