wireless-next patches for v6.10

The first "new features" pull request for v6.10 with changes both in
 stack and in drivers. The big thing in this pull request is that
 wireless subsystem is now almost free of sparse warnings. There's only
 one warning left in ath11k which was introduced in v6.9-rc1 and will
 be fixed via the wireless tree.
 
 Realtek drivers continue to improve, now we have support for RTL8922AE
 and RTL8723CS devices. ath11k also has long waited support for P2P.
 
 This time we have a small conflict in iwlwifi as we didn't consider it
 as major enough to justify merging wireless tree to wireless-next. But
 Stephen has an example merge resolution which should help with fixing
 the conflict:
 
 https://lore.kernel.org/all/20240326100945.765b8caf@canb.auug.org.au/
 
 Major changes:
 
 rtw89
 
 * RTL8922AE Wi-Fi 7 PCI device support
 
 rtw88
 
 * RTL8723CS SDIO device support
 
 iwlwifi
 
 * don't support puncturing in 5 GHz
 
 * support monitor mode on passive channels
 
 * BZ-W device support
 
 * P2P with HE/EHT support
 
 ath11k
 
 * P2P support for QCA6390, WCN6855 and QCA2066
 -----BEGIN PGP SIGNATURE-----
 
 iQFFBAABCgAvFiEEiBjanGPFTz4PRfLobhckVSbrbZsFAmYNIqIRHGt2YWxvQGtl
 cm5lbC5vcmcACgkQbhckVSbrbZt8jAf9H+o91boD34/qVdI5LWEcFhVKEkHpNtwm
 Y1sTKNBEtN1Gs2zcljjO6PqN9N4v2+lA42KSpzP5M42FfpI2aATI2v8jYsKTXOl2
 YVwF+8pDiAsi0YtQTxIthygjzTpsePCfj8z0xJaKGm195T+fMm9UebYETrfxxOp/
 z5StsJIPI0twgSLKKUWvLpX4ESt0l0HLJY1ok99sk4Cj36EKn6b9LbBinDKr6GcQ
 mGNtPyq0j4l0kS5qae9BbXZUohO54o8wiFnApdwGfA7S/kLY7eUtwZy7T050b62P
 zbNafwZbIjrH7dNcGfe6Fdr7PjQYFeI5Nh7dXxqM2LJOQsYXU/tcWQ==
 =WrPE
 -----END PGP SIGNATURE-----

Merge tag 'wireless-next-2024-04-03' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next

Kalle Valo says:

====================
wireless-next patches for v6.10

The first "new features" pull request for v6.10 with changes both in
stack and in drivers. The big thing in this pull request is that
wireless subsystem is now almost free of sparse warnings. There's only
one warning left in ath11k which was introduced in v6.9-rc1 and will
be fixed via the wireless tree.

Realtek drivers continue to improve, now we have support for RTL8922AE
and RTL8723CS devices. ath11k also has long waited support for P2P.

This time we have a small conflict in iwlwifi, Stephen has an example
merge resolution which should help with fixing the conflict:

https://lore.kernel.org/all/20240326100945.765b8caf@canb.auug.org.au/

Major changes:

rtw89
 * RTL8922AE Wi-Fi 7 PCI device support

rtw88
 * RTL8723CS SDIO device support

iwlwifi
 * don't support puncturing in 5 GHz
 * support monitor mode on passive channels
 * BZ-W device support
 * P2P with HE/EHT support

ath11k
 * P2P support for QCA6390, WCN6855 and QCA2066

* tag 'wireless-next-2024-04-03' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (122 commits)
  wifi: mt76: mt7915: workaround dubious x | !y warning
  wifi: mwl8k: Avoid -Wflex-array-member-not-at-end warnings
  wifi: ti: Avoid a hundred -Wflex-array-member-not-at-end warnings
  wifi: iwlwifi: mvm: fix check in iwl_mvm_sta_fw_id_mask
  net: rfkill: gpio: Convert to platform remove callback returning void
  wifi: mac80211: use kvcalloc() for codel vars
  wifi: iwlwifi: reconfigure TLC during HW restart
  wifi: iwlwifi: mvm: don't change BA sessions during restart
  wifi: iwlwifi: mvm: select STA mask only for active links
  wifi: iwlwifi: mvm: set wider BW OFDMA ignore correctly
  wifi: iwlwifi: Add support for LARI_CONFIG_CHANGE_CMD cmd v9
  wifi: iwlwifi: mvm: Declare HE/EHT capabilities support for P2P interfaces
  wifi: iwlwifi: mvm: Remove outdated comment
  wifi: iwlwifi: add support for BZ_W
  wifi: iwlwifi: Print a specific device name.
  wifi: iwlwifi: remove wrong CRF_IDs
  wifi: iwlwifi: remove devices that never came out
  wifi: iwlwifi: mvm: mark EMLSR disabled in cleanup iterator
  wifi: iwlwifi: mvm: fix active link counting during recovery
  wifi: iwlwifi: mvm: assign link STA ID lookups during restart
  ...
====================

Link: https://lore.kernel.org/r/20240403093625.CF515C433C7@smtp.kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2024-04-03 19:36:55 -07:00
commit 8c73e8b595
124 changed files with 7816 additions and 1820 deletions

View File

@ -44,6 +44,7 @@ properties:
- brcm,bcm4366-fmac
- cypress,cyw4373-fmac
- cypress,cyw43012-fmac
- infineon,cyw43439-fmac
- const: brcm,bcm4329-fmac
- enum:
- brcm,bcm4329-fmac

View File

@ -240,15 +240,13 @@ static int bcma_host_soc_probe(struct platform_device *pdev)
return err;
}
static int bcma_host_soc_remove(struct platform_device *pdev)
static void bcma_host_soc_remove(struct platform_device *pdev)
{
struct bcma_bus *bus = platform_get_drvdata(pdev);
bcma_bus_unregister(bus);
iounmap(bus->mmio);
platform_set_drvdata(pdev, NULL);
return 0;
}
static const struct of_device_id bcma_host_soc_of_match[] = {
@ -263,7 +261,7 @@ static struct platform_driver bcma_host_soc_driver = {
.of_match_table = bcma_host_soc_of_match,
},
.probe = bcma_host_soc_probe,
.remove = bcma_host_soc_remove,
.remove_new = bcma_host_soc_remove,
};
int __init bcma_host_soc_register_driver(void)

View File

@ -100,7 +100,7 @@ static ssize_t ath10k_thermal_show_temp(struct device *dev,
spin_unlock_bh(&ar->data_lock);
/* display in millidegree celsius */
ret = snprintf(buf, PAGE_SIZE, "%d\n", temperature * 1000);
ret = sysfs_emit(buf, "%d\n", temperature * 1000);
out:
mutex_unlock(&ar->conf_mutex);
return ret;

View File

@ -1763,12 +1763,32 @@ void ath10k_wmi_put_wmi_channel(struct ath10k *ar, struct wmi_channel *ch,
int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
{
unsigned long time_left;
unsigned long time_left, i;
time_left = wait_for_completion_timeout(&ar->wmi.service_ready,
WMI_SERVICE_READY_TIMEOUT_HZ);
if (!time_left)
return -ETIMEDOUT;
if (!time_left) {
/* Sometimes the PCI HIF doesn't receive interrupt
* for the service ready message even if the buffer
* was completed. PCIe sniffer shows that it's
* because the corresponding CE ring doesn't fires
* it. Workaround here by polling CE rings once.
*/
ath10k_warn(ar, "failed to receive service ready completion, polling..\n");
for (i = 0; i < CE_COUNT; i++)
ath10k_hif_send_complete_check(ar, i, 1);
time_left = wait_for_completion_timeout(&ar->wmi.service_ready,
WMI_SERVICE_READY_TIMEOUT_HZ);
if (!time_left) {
ath10k_warn(ar, "polling timed out\n");
return -ETIMEDOUT;
}
ath10k_warn(ar, "service ready completion received, continuing normally\n");
}
return 0;
}

View File

@ -18,7 +18,8 @@ ath11k-y += core.o \
dbring.o \
hw.o \
pcic.o \
fw.o
fw.o \
p2p.o
ath11k-$(CONFIG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o
ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o

View File

@ -247,7 +247,10 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
},
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP),
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO),
.supports_monitor = false,
.full_monitor_mode = false,
.supports_shadow_regs = true,
@ -416,7 +419,10 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
},
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP),
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO),
.supports_monitor = false,
.full_monitor_mode = false,
.supports_shadow_regs = true,
@ -501,7 +507,10 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
},
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP),
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO),
.supports_monitor = false,
.supports_shadow_regs = true,
.idle_ps = true,
@ -750,7 +759,10 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
},
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP),
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO),
.supports_monitor = false,
.full_monitor_mode = false,
.supports_shadow_regs = true,

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/vmalloc.h>
@ -980,7 +980,7 @@ int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
&fops_simulate_fw_crash);
debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
debugfs_create_file("soc_dp_stats", 0400, ab->debugfs_soc, ab,
&fops_soc_dp_stats);
if (ab->hw_params.sram_dump.start != 0)

View File

@ -1231,14 +1231,7 @@ static int ath11k_mac_vif_setup_ps(struct ath11k_vif *arvif)
enable_ps = arvif->ps;
if (!arvif->is_started) {
/* mac80211 can update vif powersave state while disconnected.
* Firmware doesn't behave nicely and consumes more power than
* necessary if PS is disabled on a non-started vdev. Hence
* force-enable PS for non-running vdevs.
*/
psmode = WMI_STA_PS_MODE_ENABLED;
} else if (enable_ps) {
if (enable_ps) {
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
@ -1430,10 +1423,67 @@ static bool ath11k_mac_set_nontx_vif_params(struct ath11k_vif *tx_arvif,
return false;
}
static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
struct sk_buff *bcn)
static int ath11k_mac_setup_bcn_p2p_ie(struct ath11k_vif *arvif,
struct sk_buff *bcn)
{
struct ath11k *ar = arvif->ar;
struct ieee80211_mgmt *mgmt;
const u8 *p2p_ie;
int ret;
mgmt = (void *)bcn->data;
p2p_ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P,
mgmt->u.beacon.variable,
bcn->len - (mgmt->u.beacon.variable -
bcn->data));
if (!p2p_ie)
return -ENOENT;
ret = ath11k_wmi_p2p_go_bcn_ie(ar, arvif->vdev_id, p2p_ie);
if (ret) {
ath11k_warn(ar->ab, "failed to submit P2P GO bcn ie for vdev %i: %d\n",
arvif->vdev_id, ret);
return ret;
}
return ret;
}
static int ath11k_mac_remove_vendor_ie(struct sk_buff *skb, unsigned int oui,
u8 oui_type, size_t ie_offset)
{
size_t len;
const u8 *next, *end;
u8 *ie;
if (WARN_ON(skb->len < ie_offset))
return -EINVAL;
ie = (u8 *)cfg80211_find_vendor_ie(oui, oui_type,
skb->data + ie_offset,
skb->len - ie_offset);
if (!ie)
return -ENOENT;
len = ie[1] + 2;
end = skb->data + skb->len;
next = ie + len;
if (WARN_ON(next > end))
return -EINVAL;
memmove(ie, next, end - next);
skb_trim(skb, skb->len - len);
return 0;
}
static int ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
struct sk_buff *bcn)
{
struct ath11k_base *ab = arvif->ar->ab;
struct ieee80211_mgmt *mgmt;
int ret = 0;
u8 *ies;
ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
@ -1451,6 +1501,32 @@ static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
arvif->wpaie_present = true;
else
arvif->wpaie_present = false;
if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO)
return ret;
ret = ath11k_mac_setup_bcn_p2p_ie(arvif, bcn);
if (ret) {
ath11k_warn(ab, "failed to setup P2P GO bcn ie: %d\n",
ret);
return ret;
}
/* P2P IE is inserted by firmware automatically (as
* configured above) so remove it from the base beacon
* template to avoid duplicate P2P IEs in beacon frames.
*/
ret = ath11k_mac_remove_vendor_ie(bcn, WLAN_OUI_WFA,
WLAN_OUI_TYPE_WFA_P2P,
offsetof(struct ieee80211_mgmt,
u.beacon.variable));
if (ret) {
ath11k_warn(ab, "failed to remove P2P vendor ie: %d\n",
ret);
return ret;
}
return ret;
}
static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif)
@ -1472,10 +1548,12 @@ static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif)
return -EPERM;
}
if (tx_arvif == arvif)
ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb);
else
if (tx_arvif == arvif) {
if (ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb))
return -EINVAL;
} else {
arvif->wpaie_present = tx_arvif->wpaie_present;
}
for (i = 0; i < beacons->cnt; i++) {
if (tx_arvif != arvif && !nontx_vif_params_set)
@ -1534,10 +1612,12 @@ static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif)
return -EPERM;
}
if (tx_arvif == arvif)
ath11k_mac_set_vif_params(tx_arvif, bcn);
else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn))
if (tx_arvif == arvif) {
if (ath11k_mac_set_vif_params(tx_arvif, bcn))
return -EINVAL;
} else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn)) {
return -EINVAL;
}
ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, 0);
kfree_skb(bcn);
@ -3996,6 +4076,9 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
arg->vdev_id = arvif->vdev_id;
arg->scan_id = ATH11K_SCAN_ID;
if (ar->ab->hw_params.single_pdev_only)
arg->scan_f_filter_prb_req = 1;
if (req->ie_len) {
arg->extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL);
if (!arg->extraie.ptr) {
@ -6570,17 +6653,26 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_STATION:
arvif->vdev_type = WMI_VDEV_TYPE_STA;
if (vif->p2p)
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_CLIENT;
break;
case NL80211_IFTYPE_MESH_POINT:
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S;
fallthrough;
case NL80211_IFTYPE_AP:
arvif->vdev_type = WMI_VDEV_TYPE_AP;
if (vif->p2p)
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_GO;
break;
case NL80211_IFTYPE_MONITOR:
arvif->vdev_type = WMI_VDEV_TYPE_MONITOR;
ar->monitor_vdev_id = bit;
break;
case NL80211_IFTYPE_P2P_DEVICE:
arvif->vdev_type = WMI_VDEV_TYPE_STA;
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
break;
default:
WARN_ON(1);
break;
@ -9253,9 +9345,11 @@ static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
arg->dwell_time_passive = scan_time_msec;
arg->max_scan_time = scan_time_msec;
arg->scan_f_passive = 1;
arg->scan_f_filter_prb_req = 1;
arg->burst_duration = duration;
if (!ar->ab->hw_params.single_pdev_only)
arg->scan_f_filter_prb_req = 1;
ret = ath11k_start_scan(ar, arg);
if (ret) {
ath11k_warn(ar->ab, "failed to start roc scan: %d\n", ret);
@ -9857,12 +9951,18 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
struct ieee80211_iface_combination *combinations;
struct ieee80211_iface_limit *limits;
int n_limits;
bool p2p;
p2p = ab->hw_params.interface_modes & BIT(NL80211_IFTYPE_P2P_DEVICE);
combinations = kzalloc(sizeof(*combinations), GFP_KERNEL);
if (!combinations)
return -ENOMEM;
n_limits = 2;
if (p2p)
n_limits = 3;
else
n_limits = 2;
limits = kcalloc(n_limits, sizeof(*limits), GFP_KERNEL);
if (!limits) {
@ -9870,39 +9970,29 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
return -ENOMEM;
}
limits[0].types |= BIT(NL80211_IFTYPE_STATION);
limits[1].types |= BIT(NL80211_IFTYPE_AP);
if (IS_ENABLED(CONFIG_MAC80211_MESH) &&
ab->hw_params.interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
limits[1].types |= BIT(NL80211_IFTYPE_MESH_POINT);
combinations[0].limits = limits;
combinations[0].n_limits = n_limits;
combinations[0].beacon_int_infra_match = true;
combinations[0].beacon_int_min_gcd = 100;
if (ab->hw_params.support_dual_stations) {
limits[0].max = 2;
limits[0].types |= BIT(NL80211_IFTYPE_STATION);
limits[1].max = 1;
limits[1].types |= BIT(NL80211_IFTYPE_AP);
if (IS_ENABLED(CONFIG_MAC80211_MESH) &&
ab->hw_params.interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
limits[1].types |= BIT(NL80211_IFTYPE_MESH_POINT);
combinations[0].limits = limits;
combinations[0].n_limits = 2;
combinations[0].max_interfaces = ab->hw_params.num_vdevs;
combinations[0].num_different_channels = 2;
combinations[0].beacon_int_infra_match = true;
combinations[0].beacon_int_min_gcd = 100;
} else {
limits[0].max = 1;
limits[0].types |= BIT(NL80211_IFTYPE_STATION);
limits[1].max = 16;
limits[1].types |= BIT(NL80211_IFTYPE_AP);
if (IS_ENABLED(CONFIG_MAC80211_MESH) &&
ab->hw_params.interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
limits[1].types |= BIT(NL80211_IFTYPE_MESH_POINT);
combinations[0].limits = limits;
combinations[0].n_limits = 2;
combinations[0].max_interfaces = 16;
combinations[0].num_different_channels = 1;
combinations[0].beacon_int_infra_match = true;
combinations[0].beacon_int_min_gcd = 100;
combinations[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
BIT(NL80211_CHAN_WIDTH_20) |
BIT(NL80211_CHAN_WIDTH_40) |
@ -9911,6 +10001,13 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
BIT(NL80211_CHAN_WIDTH_160);
}
if (p2p) {
limits[1].types |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO);
limits[2].max = 1;
limits[2].types |= BIT(NL80211_IFTYPE_P2P_DEVICE);
}
ar->hw->wiphy->iface_combinations = combinations;
ar->hw->wiphy->n_iface_combinations = 1;

View File

@ -19,6 +19,7 @@
#define MHI_TIMEOUT_DEFAULT_MS 20000
#define RDDM_DUMP_SIZE 0x420000
#define MHI_CB_INVALID 0xff
static const struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
{
@ -158,9 +159,8 @@ void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab)
ath11k_dbg(ab, ATH11K_DBG_PCI, "mhistatus 0x%x\n", val);
/* Observed on QCA6390 that after SOC_GLOBAL_RESET, MHISTATUS
* has SYSERR bit set and thus need to set MHICTRL_RESET
* to clear SYSERR.
/* After SOC_GLOBAL_RESET, MHISTATUS may still have SYSERR bit set
* and thus need to set MHICTRL_RESET to clear SYSERR.
*/
ath11k_pcic_write32(ab, MHICTRL, MHICTRL_RESET_MASK);
@ -269,6 +269,7 @@ static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
enum mhi_callback cb)
{
struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev);
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
ath11k_dbg(ab, ATH11K_DBG_BOOT, "notify status reason %s\n",
ath11k_mhi_op_callback_to_str(cb));
@ -279,12 +280,21 @@ static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
break;
case MHI_CB_EE_RDDM:
ath11k_warn(ab, "firmware crashed: MHI_CB_EE_RDDM\n");
if (ab_pci->mhi_pre_cb == MHI_CB_EE_RDDM) {
ath11k_dbg(ab, ATH11K_DBG_BOOT,
"do not queue again for consecutive RDDM event\n");
break;
}
if (!(test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags)))
queue_work(ab->workqueue_aux, &ab->reset_work);
break;
default:
break;
}
ab_pci->mhi_pre_cb = cb;
}
static int ath11k_mhi_op_read_reg(struct mhi_controller *mhi_cntrl,
@ -397,6 +407,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
goto free_controller;
}
ab_pci->mhi_pre_cb = MHI_CB_INVALID;
ret = mhi_register_controller(mhi_ctrl, ath11k_mhi_config);
if (ret) {
ath11k_err(ab, "failed to register to mhi bus, err = %d\n", ret);

View File

@ -0,0 +1,149 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "core.h"
#include "wmi.h"
#include "mac.h"
#include "p2p.h"
static void ath11k_p2p_noa_ie_fill(u8 *data, size_t len,
const struct ath11k_wmi_p2p_noa_info *noa)
{
struct ieee80211_p2p_noa_attr *noa_attr;
u8 noa_descriptors, ctwindow;
bool oppps;
__le16 *noa_attr_len;
u16 attr_len;
int i;
ctwindow = u32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_CTWIN_TU);
oppps = u32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_OPP_PS);
noa_descriptors = u32_get_bits(noa->noa_attr,
WMI_P2P_NOA_INFO_DESC_NUM);
/* P2P IE */
data[0] = WLAN_EID_VENDOR_SPECIFIC;
data[1] = len - 2;
data[2] = (WLAN_OUI_WFA >> 16) & 0xff;
data[3] = (WLAN_OUI_WFA >> 8) & 0xff;
data[4] = (WLAN_OUI_WFA >> 0) & 0xff;
data[5] = WLAN_OUI_TYPE_WFA_P2P;
/* NOA ATTR */
data[6] = IEEE80211_P2P_ATTR_ABSENCE_NOTICE;
noa_attr_len = (__le16 *)&data[7]; /* 2 bytes */
noa_attr = (struct ieee80211_p2p_noa_attr *)&data[9];
noa_attr->index = u32_get_bits(noa->noa_attr,
WMI_P2P_NOA_INFO_INDEX);
noa_attr->oppps_ctwindow = ctwindow;
if (oppps)
noa_attr->oppps_ctwindow |= IEEE80211_P2P_OPPPS_ENABLE_BIT;
for (i = 0; i < noa_descriptors; i++) {
noa_attr->desc[i].count = noa->descriptors[i].type_count;
noa_attr->desc[i].duration =
cpu_to_le32(noa->descriptors[i].duration);
noa_attr->desc[i].interval =
cpu_to_le32(noa->descriptors[i].interval);
noa_attr->desc[i].start_time =
cpu_to_le32(noa->descriptors[i].start_time);
}
attr_len = 2; /* index + oppps_ctwindow */
attr_len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc);
*noa_attr_len = __cpu_to_le16(attr_len);
}
static size_t
ath11k_p2p_noa_ie_len_compute(const struct ath11k_wmi_p2p_noa_info *noa)
{
size_t len = 0;
u8 noa_descriptors = u32_get_bits(noa->noa_attr,
WMI_P2P_NOA_INFO_DESC_NUM);
if (!(noa_descriptors) &&
!(u32_get_bits(noa->noa_attr, WMI_P2P_NOA_INFO_OPP_PS)))
return 0;
len += 1 + 1 + 4; /* EID + len + OUI */
len += 1 + 2; /* noa attr + attr len */
len += 1 + 1; /* index + oppps_ctwindow */
len += noa_descriptors *
sizeof(struct ieee80211_p2p_noa_desc);
return len;
}
static void ath11k_p2p_noa_ie_assign(struct ath11k_vif *arvif, void *ie,
size_t len)
{
struct ath11k *ar = arvif->ar;
lockdep_assert_held(&ar->data_lock);
kfree(arvif->u.ap.noa_data);
arvif->u.ap.noa_data = ie;
arvif->u.ap.noa_len = len;
}
static void __ath11k_p2p_noa_update(struct ath11k_vif *arvif,
const struct ath11k_wmi_p2p_noa_info *noa)
{
struct ath11k *ar = arvif->ar;
void *ie;
size_t len;
lockdep_assert_held(&ar->data_lock);
ath11k_p2p_noa_ie_assign(arvif, NULL, 0);
len = ath11k_p2p_noa_ie_len_compute(noa);
if (!len)
return;
ie = kmalloc(len, GFP_ATOMIC);
if (!ie)
return;
ath11k_p2p_noa_ie_fill(ie, len, noa);
ath11k_p2p_noa_ie_assign(arvif, ie, len); }
void ath11k_p2p_noa_update(struct ath11k_vif *arvif,
const struct ath11k_wmi_p2p_noa_info *noa)
{
struct ath11k *ar = arvif->ar;
spin_lock_bh(&ar->data_lock);
__ath11k_p2p_noa_update(arvif, noa);
spin_unlock_bh(&ar->data_lock);
}
static void ath11k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
struct ath11k_p2p_noa_arg *arg = data;
if (arvif->vdev_id != arg->vdev_id)
return;
ath11k_p2p_noa_update(arvif, arg->noa);
}
void ath11k_p2p_noa_update_by_vdev_id(struct ath11k *ar, u32 vdev_id,
const struct ath11k_wmi_p2p_noa_info *noa)
{
struct ath11k_p2p_noa_arg arg = {
.vdev_id = vdev_id,
.noa = noa,
};
ieee80211_iterate_active_interfaces_atomic(ar->hw,
IEEE80211_IFACE_ITER_NORMAL,
ath11k_p2p_noa_update_vdev_iter,
&arg);
}

View File

@ -0,0 +1,22 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH11K_P2P_H
#define ATH11K_P2P_H
#include "wmi.h"
struct ath11k_wmi_p2p_noa_info;
struct ath11k_p2p_noa_arg {
u32 vdev_id;
const struct ath11k_wmi_p2p_noa_info *noa;
};
void ath11k_p2p_noa_update(struct ath11k_vif *arvif,
const struct ath11k_wmi_p2p_noa_info *noa);
void ath11k_p2p_noa_update_by_vdev_id(struct ath11k *ar, u32 vdev_id,
const struct ath11k_wmi_p2p_noa_info *noa);
#endif

View File

@ -64,6 +64,7 @@ struct ath11k_pci {
char amss_path[100];
struct mhi_controller *mhi_ctrl;
const struct ath11k_msi_config *msi_config;
enum mhi_callback mhi_pre_cb;
u32 register_window;
/* protects register_window above */

View File

@ -101,7 +101,7 @@ static ssize_t ath11k_thermal_show_temp(struct device *dev,
spin_unlock_bh(&ar->data_lock);
/* display in millidegree Celsius */
ret = snprintf(buf, PAGE_SIZE, "%d\n", temperature * 1000);
ret = sysfs_emit(buf, "%d\n", temperature * 1000);
out:
mutex_unlock(&ar->conf_mutex);
return ret;

View File

@ -20,6 +20,7 @@
#include "hw.h"
#include "peer.h"
#include "testmode.h"
#include "p2p.h"
struct wmi_tlv_policy {
size_t min_len;
@ -154,6 +155,10 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
.min_len = sizeof(struct wmi_per_chain_rssi_stats) },
[WMI_TAG_TWT_ADD_DIALOG_COMPLETE_EVENT] = {
.min_len = sizeof(struct wmi_twt_add_dialog_event) },
[WMI_TAG_P2P_NOA_INFO] = {
.min_len = sizeof(struct ath11k_wmi_p2p_noa_info) },
[WMI_TAG_P2P_NOA_EVENT] = {
.min_len = sizeof(struct wmi_p2p_noa_event) },
};
#define PRIMAP(_hw_mode_) \
@ -981,7 +986,7 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
FIELD_PREP(WMI_TLV_LEN, 0);
/* Note: This is a nested TLV containing:
* [wmi_tlv][wmi_p2p_noa_descriptor][wmi_tlv]..
* [wmi_tlv][ath11k_wmi_p2p_noa_descriptor][wmi_tlv]..
*/
ptr += sizeof(*tlv);
@ -1704,6 +1709,45 @@ int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar,
return ret;
}
int ath11k_wmi_p2p_go_bcn_ie(struct ath11k *ar, u32 vdev_id,
const u8 *p2p_ie)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct wmi_p2p_go_set_beacon_ie_cmd *cmd;
size_t p2p_ie_len, aligned_len;
struct wmi_tlv *tlv;
struct sk_buff *skb;
int ret, len;
p2p_ie_len = p2p_ie[1] + 2;
aligned_len = roundup(p2p_ie_len, 4);
len = sizeof(*cmd) + TLV_HDR_SIZE + aligned_len;
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
cmd = (struct wmi_p2p_go_set_beacon_ie_cmd *)skb->data;
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_P2P_GO_SET_BEACON_IE) |
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
cmd->vdev_id = vdev_id;
cmd->ie_buf_len = p2p_ie_len;
tlv = (struct wmi_tlv *)cmd->tlv;
tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) |
FIELD_PREP(WMI_TLV_LEN, aligned_len);
memcpy(tlv->value, p2p_ie, p2p_ie_len);
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_P2P_GO_SET_BEACON_IE);
if (ret) {
ath11k_warn(ar->ab, "failed to send WMI_P2P_GO_SET_BEACON_IE\n");
dev_kfree_skb(skb);
}
return ret;
}
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
struct ieee80211_mutable_offsets *offs,
struct sk_buff *bcn, u32 ema_params)
@ -8606,6 +8650,64 @@ static void ath11k_wmi_gtk_offload_status_event(struct ath11k_base *ab,
kfree(tb);
}
static int ath11k_wmi_p2p_noa_event(struct ath11k_base *ab,
struct sk_buff *skb)
{
const void **tb;
const struct wmi_p2p_noa_event *ev;
const struct ath11k_wmi_p2p_noa_info *noa;
struct ath11k *ar;
int ret, vdev_id;
u8 noa_descriptors;
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
return ret;
}
ev = tb[WMI_TAG_P2P_NOA_EVENT];
noa = tb[WMI_TAG_P2P_NOA_INFO];
if (!ev || !noa) {
ret = -EPROTO;
goto out;
}
vdev_id = ev->vdev_id;
noa_descriptors = u32_get_bits(noa->noa_attr,
WMI_P2P_NOA_INFO_DESC_NUM);
if (noa_descriptors > WMI_P2P_MAX_NOA_DESCRIPTORS) {
ath11k_warn(ab, "invalid descriptor num %d in P2P NoA event\n",
noa_descriptors);
return -EINVAL;
goto out;
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
"wmi tlv p2p noa vdev_id %i descriptors %u\n",
vdev_id, noa_descriptors);
rcu_read_lock();
ar = ath11k_mac_get_ar_by_vdev_id(ab, vdev_id);
if (!ar) {
ath11k_warn(ab, "invalid vdev id %d in P2P NoA event\n",
vdev_id);
ret = -EINVAL;
goto unlock;
}
ath11k_p2p_noa_update_by_vdev_id(ar, vdev_id, noa);
unlock:
rcu_read_unlock();
out:
kfree(tb);
return 0;
}
static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
@ -8733,6 +8835,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_GTK_OFFLOAD_STATUS_EVENTID:
ath11k_wmi_gtk_offload_status_event(ab, skb);
break;
case WMI_P2P_NOA_EVENTID:
ath11k_wmi_p2p_noa_event(ab, skb);
break;
default:
ath11k_dbg(ab, ATH11K_DBG_WMI, "unsupported event id 0x%x\n", id);
break;

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH11K_WMI_H
@ -60,13 +60,9 @@ struct wmi_tlv {
#define WLAN_SCAN_MAX_HINT_BSSID 10
#define MAX_RNR_BSS 5
#define WLAN_SCAN_MAX_HINT_S_SSID 10
#define WLAN_SCAN_MAX_HINT_BSSID 10
#define MAX_RNR_BSS 5
#define WLAN_SCAN_PARAMS_MAX_SSID 16
#define WLAN_SCAN_PARAMS_MAX_BSSID 4
#define WLAN_SCAN_PARAMS_MAX_IE_LEN 256
#define WLAN_SCAN_PARAMS_MAX_IE_LEN 512
#define WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG 1
@ -3444,34 +3440,6 @@ struct wmi_bssid_arg {
const u8 *bssid;
};
struct wmi_start_scan_arg {
u32 scan_id;
u32 scan_req_id;
u32 vdev_id;
u32 scan_priority;
u32 notify_scan_events;
u32 dwell_time_active;
u32 dwell_time_passive;
u32 min_rest_time;
u32 max_rest_time;
u32 repeat_probe_time;
u32 probe_spacing_time;
u32 idle_time;
u32 max_scan_time;
u32 probe_delay;
u32 scan_ctrl_flags;
u32 ie_len;
u32 n_channels;
u32 n_ssids;
u32 n_bssids;
u8 ie[WLAN_SCAN_PARAMS_MAX_IE_LEN];
u32 channels[64];
struct wmi_ssid_arg ssids[WLAN_SCAN_PARAMS_MAX_SSID];
struct wmi_bssid_arg bssids[WLAN_SCAN_PARAMS_MAX_BSSID];
};
#define WMI_SCAN_STOP_ONE 0x00000000
#define WMI_SCN_STOP_VAP_ALL 0x01000000
#define WMI_SCAN_STOP_ALL 0x04000000
@ -3630,6 +3598,37 @@ struct wmi_ftm_event_msg {
u8 data[];
} __packed;
#define WMI_P2P_MAX_NOA_DESCRIPTORS 4
struct wmi_p2p_noa_event {
u32 vdev_id;
} __packed;
struct ath11k_wmi_p2p_noa_descriptor {
u32 type_count; /* 255: continuous schedule, 0: reserved */
u32 duration; /* Absent period duration in micro seconds */
u32 interval; /* Absent period interval in micro seconds */
u32 start_time; /* 32 bit tsf time when in starts */
} __packed;
#define WMI_P2P_NOA_INFO_CHANGED_FLAG BIT(0)
#define WMI_P2P_NOA_INFO_INDEX GENMASK(15, 8)
#define WMI_P2P_NOA_INFO_OPP_PS BIT(16)
#define WMI_P2P_NOA_INFO_CTWIN_TU GENMASK(23, 17)
#define WMI_P2P_NOA_INFO_DESC_NUM GENMASK(31, 24)
struct ath11k_wmi_p2p_noa_info {
/* Bit 0 - Flag to indicate an update in NOA schedule
* Bits 7-1 - Reserved
* Bits 15-8 - Index (identifies the instance of NOA sub element)
* Bit 16 - Opp PS state of the AP
* Bits 23-17 - Ctwindow in TUs
* Bits 31-24 - Number of NOA descriptors
*/
u32 noa_attr;
struct ath11k_wmi_p2p_noa_descriptor descriptors[WMI_P2P_MAX_NOA_DESCRIPTORS];
} __packed;
#define WMI_BEACON_TX_BUFFER_SIZE 512
#define WMI_EMA_TMPL_IDX_SHIFT 8
@ -3653,6 +3652,13 @@ struct wmi_bcn_tmpl_cmd {
u32 ema_params;
} __packed;
struct wmi_p2p_go_set_beacon_ie_cmd {
u32 tlv_header;
u32 vdev_id;
u32 ie_buf_len;
u8 tlv[];
} __packed;
struct wmi_key_seq_counter {
u32 key_seq_counter_l;
u32 key_seq_counter_h;
@ -5740,8 +5746,6 @@ struct wmi_debug_log_config_cmd_fixed_param {
u32 value;
} __packed;
#define WMI_MAX_MEM_REQS 32
#define MAX_RADIOS 3
#define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ)
@ -6349,6 +6353,8 @@ int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len);
int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
struct sk_buff *frame);
int ath11k_wmi_p2p_go_bcn_ie(struct ath11k *ar, u32 vdev_id,
const u8 *p2p_ie);
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
struct ieee80211_mutable_offsets *offs,
struct sk_buff *bcn, u32 ema_param);

View File

@ -960,8 +960,9 @@ int ath12k_dp_service_srng(struct ath12k_base *ab,
if (ab->hw_params->ring_mask->host2rxdma[grp_id]) {
struct ath12k_dp *dp = &ab->dp;
struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
LIST_HEAD(list);
ath12k_dp_rx_bufs_replenish(ab, rx_ring, 0);
ath12k_dp_rx_bufs_replenish(ab, rx_ring, &list, 0);
}
/* TODO: Implement handler for other interrupts */
@ -1146,11 +1147,11 @@ void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_vif *arvif)
static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
{
struct ath12k_rx_desc_info *desc_info, *tmp;
struct ath12k_rx_desc_info *desc_info;
struct ath12k_tx_desc_info *tx_desc_info, *tmp1;
struct ath12k_dp *dp = &ab->dp;
struct sk_buff *skb;
int i;
int i, j;
u32 pool_id, tx_spt_page;
if (!dp->spt_info)
@ -1159,16 +1160,23 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
/* RX Descriptor cleanup */
spin_lock_bh(&dp->rx_desc_lock);
list_for_each_entry_safe(desc_info, tmp, &dp->rx_desc_used_list, list) {
list_del(&desc_info->list);
skb = desc_info->skb;
for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) {
desc_info = dp->spt_info->rxbaddr[i];
if (!skb)
continue;
for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
if (!desc_info[j].in_use) {
list_del(&desc_info[j].list);
continue;
}
dma_unmap_single(ab->dev, ATH12K_SKB_RXCB(skb)->paddr,
skb->len + skb_tailroom(skb), DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
skb = desc_info[j].skb;
if (!skb)
continue;
dma_unmap_single(ab->dev, ATH12K_SKB_RXCB(skb)->paddr,
skb->len + skb_tailroom(skb), DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
}
}
for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) {
@ -1444,7 +1452,6 @@ static int ath12k_dp_cc_init(struct ath12k_base *ab)
u32 cmem_base;
INIT_LIST_HEAD(&dp->rx_desc_free_list);
INIT_LIST_HEAD(&dp->rx_desc_used_list);
spin_lock_init(&dp->rx_desc_lock);
for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++) {

View File

@ -282,6 +282,8 @@ struct ath12k_rx_desc_info {
struct sk_buff *skb;
u32 cookie;
u32 magic;
u8 in_use : 1,
reserved : 7;
};
struct ath12k_tx_desc_info {
@ -347,8 +349,7 @@ struct ath12k_dp {
struct ath12k_spt_info *spt_info;
u32 num_spt_pages;
struct list_head rx_desc_free_list;
struct list_head rx_desc_used_list;
/* protects the free and used desc list */
/* protects the free desc list */
spinlock_t rx_desc_lock;
struct list_head tx_desc_free_list[ATH12K_HW_MAX_QUEUES];
@ -377,8 +378,6 @@ struct ath12k_dp {
/* peer meta data */
#define HTT_TCL_META_DATA_PEER_ID GENMASK(15, 2)
#define HTT_TX_WBM_COMP_STATUS_OFFSET 8
/* HTT tx completion is overlaid in wbm_release_ring */
#define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(16, 13)
#define HTT_TX_WBM_COMP_INFO1_REINJECT_REASON GENMASK(3, 0)

View File

@ -261,9 +261,53 @@ static int ath12k_dp_purge_mon_ring(struct ath12k_base *ab)
return -ETIMEDOUT;
}
static size_t ath12k_dp_list_cut_nodes(struct list_head *list,
struct list_head *head,
size_t count)
{
struct list_head *cur;
struct ath12k_rx_desc_info *rx_desc;
size_t nodes = 0;
if (!count) {
INIT_LIST_HEAD(list);
goto out;
}
list_for_each(cur, head) {
if (!count)
break;
rx_desc = list_entry(cur, struct ath12k_rx_desc_info, list);
rx_desc->in_use = true;
count--;
nodes++;
}
list_cut_before(list, head, cur);
out:
return nodes;
}
static void ath12k_dp_rx_enqueue_free(struct ath12k_dp *dp,
struct list_head *used_list)
{
struct ath12k_rx_desc_info *rx_desc, *safe;
/* Reset the use flag */
list_for_each_entry_safe(rx_desc, safe, used_list, list)
rx_desc->in_use = false;
spin_lock_bh(&dp->rx_desc_lock);
list_splice_tail(used_list, &dp->rx_desc_free_list);
spin_unlock_bh(&dp->rx_desc_lock);
}
/* Returns number of Rx buffers replenished */
int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
struct dp_rxdma_ring *rx_ring,
struct list_head *used_list,
int req_entries)
{
struct ath12k_buffer_addr *desc;
@ -292,6 +336,19 @@ int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
req_entries = min(num_free, req_entries);
num_remain = req_entries;
if (!num_remain)
goto out;
/* Get the descriptor from free list */
if (list_empty(used_list)) {
spin_lock_bh(&dp->rx_desc_lock);
req_entries = ath12k_dp_list_cut_nodes(used_list,
&dp->rx_desc_free_list,
num_remain);
spin_unlock_bh(&dp->rx_desc_lock);
num_remain = req_entries;
}
while (num_remain > 0) {
skb = dev_alloc_skb(DP_RX_BUFFER_SIZE +
DP_RX_BUFFER_ALIGN_SIZE);
@ -311,33 +368,20 @@ int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
if (dma_mapping_error(ab->dev, paddr))
goto fail_free_skb;
spin_lock_bh(&dp->rx_desc_lock);
/* Get desc from free list and store in used list
* for cleanup purposes
*
* TODO: pass the removed descs rather than
* add/read to optimize
*/
rx_desc = list_first_entry_or_null(&dp->rx_desc_free_list,
rx_desc = list_first_entry_or_null(used_list,
struct ath12k_rx_desc_info,
list);
if (!rx_desc) {
spin_unlock_bh(&dp->rx_desc_lock);
if (!rx_desc)
goto fail_dma_unmap;
}
rx_desc->skb = skb;
cookie = rx_desc->cookie;
list_del(&rx_desc->list);
list_add_tail(&rx_desc->list, &dp->rx_desc_used_list);
spin_unlock_bh(&dp->rx_desc_lock);
desc = ath12k_hal_srng_src_get_next_entry(ab, srng);
if (!desc)
goto fail_buf_unassign;
goto fail_dma_unmap;
list_del(&rx_desc->list);
ATH12K_SKB_RXCB(skb)->paddr = paddr;
num_remain--;
@ -345,26 +389,19 @@ int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
ath12k_hal_rx_buf_addr_info_set(desc, paddr, cookie, mgr);
}
ath12k_hal_srng_access_end(ab, srng);
goto out;
spin_unlock_bh(&srng->lock);
return req_entries - num_remain;
fail_buf_unassign:
spin_lock_bh(&dp->rx_desc_lock);
list_del(&rx_desc->list);
list_add_tail(&rx_desc->list, &dp->rx_desc_free_list);
rx_desc->skb = NULL;
spin_unlock_bh(&dp->rx_desc_lock);
fail_dma_unmap:
dma_unmap_single(ab->dev, paddr, skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
fail_free_skb:
dev_kfree_skb_any(skb);
out:
ath12k_hal_srng_access_end(ab, srng);
if (!list_empty(used_list))
ath12k_dp_rx_enqueue_free(dp, used_list);
spin_unlock_bh(&srng->lock);
return req_entries - num_remain;
@ -422,13 +459,12 @@ static int ath12k_dp_rxdma_mon_ring_buf_setup(struct ath12k_base *ab,
static int ath12k_dp_rxdma_ring_buf_setup(struct ath12k_base *ab,
struct dp_rxdma_ring *rx_ring)
{
int num_entries;
LIST_HEAD(list);
num_entries = rx_ring->refill_buf_ring.size /
ath12k_hal_srng_get_entrysize(ab, HAL_RXDMA_BUF);
rx_ring->bufs_max = rx_ring->refill_buf_ring.size /
ath12k_hal_srng_get_entrysize(ab, HAL_RXDMA_BUF);
rx_ring->bufs_max = num_entries;
ath12k_dp_rx_bufs_replenish(ab, rx_ring, num_entries);
ath12k_dp_rx_bufs_replenish(ab, rx_ring, &list, 0);
return 0;
}
@ -2585,6 +2621,7 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
struct napi_struct *napi, int budget)
{
LIST_HEAD(rx_desc_used_list);
struct ath12k_rx_desc_info *desc_info;
struct ath12k_dp *dp = &ab->dp;
struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
@ -2637,9 +2674,7 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
msdu = desc_info->skb;
desc_info->skb = NULL;
spin_lock_bh(&dp->rx_desc_lock);
list_move_tail(&desc_info->list, &dp->rx_desc_free_list);
spin_unlock_bh(&dp->rx_desc_lock);
list_add_tail(&desc_info->list, &rx_desc_used_list);
rxcb = ATH12K_SKB_RXCB(msdu);
dma_unmap_single(ab->dev, rxcb->paddr,
@ -2700,7 +2735,8 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int ring_id,
if (!total_msdu_reaped)
goto exit;
ath12k_dp_rx_bufs_replenish(ab, rx_ring, num_buffs_reaped);
ath12k_dp_rx_bufs_replenish(ab, rx_ring, &rx_desc_used_list,
num_buffs_reaped);
ath12k_dp_rx_process_received_packets(ab, napi, &msdu_list,
ring_id);
@ -3021,9 +3057,9 @@ static int ath12k_dp_rx_h_defrag_reo_reinject(struct ath12k *ar,
}
desc_info->skb = defrag_skb;
desc_info->in_use = true;
list_del(&desc_info->list);
list_add_tail(&desc_info->list, &dp->rx_desc_used_list);
spin_unlock_bh(&dp->rx_desc_lock);
ATH12K_SKB_RXCB(defrag_skb)->paddr = buf_paddr;
@ -3085,9 +3121,9 @@ static int ath12k_dp_rx_h_defrag_reo_reinject(struct ath12k *ar,
err_free_desc:
spin_lock_bh(&dp->rx_desc_lock);
list_del(&desc_info->list);
list_add_tail(&desc_info->list, &dp->rx_desc_free_list);
desc_info->in_use = false;
desc_info->skb = NULL;
list_add_tail(&desc_info->list, &dp->rx_desc_free_list);
spin_unlock_bh(&dp->rx_desc_lock);
err_unmap_dma:
dma_unmap_single(ab->dev, buf_paddr, defrag_skb->len + skb_tailroom(defrag_skb),
@ -3304,6 +3340,7 @@ static int ath12k_dp_rx_frag_h_mpdu(struct ath12k *ar,
static int
ath12k_dp_process_rx_err_buf(struct ath12k *ar, struct hal_reo_dest_ring *desc,
struct list_head *used_list,
bool drop, u32 cookie)
{
struct ath12k_base *ab = ar->ab;
@ -3333,9 +3370,8 @@ ath12k_dp_process_rx_err_buf(struct ath12k *ar, struct hal_reo_dest_ring *desc,
msdu = desc_info->skb;
desc_info->skb = NULL;
spin_lock_bh(&ab->dp.rx_desc_lock);
list_move_tail(&desc_info->list, &ab->dp.rx_desc_free_list);
spin_unlock_bh(&ab->dp.rx_desc_lock);
list_add_tail(&desc_info->list, used_list);
rxcb = ATH12K_SKB_RXCB(msdu);
dma_unmap_single(ar->ab->dev, rxcb->paddr,
@ -3391,6 +3427,7 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
struct hal_reo_dest_ring *reo_desc;
struct dp_rxdma_ring *rx_ring;
struct dp_srng *reo_except;
LIST_HEAD(rx_desc_used_list);
u32 desc_bank, num_msdus;
struct hal_srng *srng;
struct ath12k_dp *dp;
@ -3458,7 +3495,9 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
ar = ab->pdevs[pdev_id].ar;
if (!ath12k_dp_process_rx_err_buf(ar, reo_desc, drop,
if (!ath12k_dp_process_rx_err_buf(ar, reo_desc,
&rx_desc_used_list,
drop,
msdu_cookies[i]))
tot_n_bufs_reaped++;
}
@ -3478,7 +3517,8 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
rx_ring = &dp->rx_refill_buf_ring;
ath12k_dp_rx_bufs_replenish(ab, rx_ring, tot_n_bufs_reaped);
ath12k_dp_rx_bufs_replenish(ab, rx_ring, &rx_desc_used_list,
tot_n_bufs_reaped);
return tot_n_bufs_reaped;
}
@ -3695,6 +3735,7 @@ static void ath12k_dp_rx_wbm_err(struct ath12k *ar,
int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
struct napi_struct *napi, int budget)
{
LIST_HEAD(rx_desc_used_list);
struct ath12k *ar;
struct ath12k_dp *dp = &ab->dp;
struct dp_rxdma_ring *rx_ring;
@ -3748,9 +3789,7 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
msdu = desc_info->skb;
desc_info->skb = NULL;
spin_lock_bh(&dp->rx_desc_lock);
list_move_tail(&desc_info->list, &dp->rx_desc_free_list);
spin_unlock_bh(&dp->rx_desc_lock);
list_add_tail(&desc_info->list, &rx_desc_used_list);
rxcb = ATH12K_SKB_RXCB(msdu);
dma_unmap_single(ab->dev, rxcb->paddr,
@ -3786,7 +3825,8 @@ int ath12k_dp_rx_process_wbm_err(struct ath12k_base *ab,
if (!num_buffs_reaped)
goto done;
ath12k_dp_rx_bufs_replenish(ab, rx_ring, num_buffs_reaped);
ath12k_dp_rx_bufs_replenish(ab, rx_ring, &rx_desc_used_list,
num_buffs_reaped);
rcu_read_lock();
while ((msdu = __skb_dequeue(&msdu_list))) {

View File

@ -118,6 +118,7 @@ int ath12k_dp_rx_process(struct ath12k_base *ab, int mac_id,
int budget);
int ath12k_dp_rx_bufs_replenish(struct ath12k_base *ab,
struct dp_rxdma_ring *rx_ring,
struct list_head *used_list,
int req_entries);
int ath12k_dp_rx_pdev_mon_attach(struct ath12k *ar);
int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id);

View File

@ -414,7 +414,7 @@ ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab,
struct ath12k_dp_htt_wbm_tx_status ts = {0};
enum hal_wbm_htt_tx_comp_status wbm_status;
status_desc = desc + HTT_TX_WBM_COMP_STATUS_OFFSET;
status_desc = desc;
wbm_status = le32_get_bits(status_desc->info0,
HTT_TX_WBM_COMP_INFO0_STATUS);

View File

@ -1900,7 +1900,7 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,
if (arg->bw_160)
cmd->peer_flags |= cpu_to_le32(WMI_PEER_160MHZ);
if (arg->bw_320)
cmd->peer_flags |= cpu_to_le32(WMI_PEER_EXT_320MHZ);
cmd->peer_flags_ext |= cpu_to_le32(WMI_PEER_EXT_320MHZ);
/* Typically if STBC is enabled for VHT it should be enabled
* for HT as well

View File

@ -164,10 +164,6 @@ struct wmi_tlv {
#define WLAN_SCAN_MAX_HINT_BSSID 10
#define MAX_RNR_BSS 5
#define WLAN_SCAN_MAX_HINT_S_SSID 10
#define WLAN_SCAN_MAX_HINT_BSSID 10
#define MAX_RNR_BSS 5
#define WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG 1
#define WMI_BA_MODE_BUFFER_SIZE_256 3
@ -3357,34 +3353,6 @@ struct wmi_bssid_arg {
const u8 *bssid;
};
struct wmi_start_scan_arg {
u32 scan_id;
u32 scan_req_id;
u32 vdev_id;
u32 scan_priority;
u32 notify_scan_events;
u32 dwell_time_active;
u32 dwell_time_passive;
u32 min_rest_time;
u32 max_rest_time;
u32 repeat_probe_time;
u32 probe_spacing_time;
u32 idle_time;
u32 max_scan_time;
u32 probe_delay;
u32 scan_ctrl_flags;
u32 ie_len;
u32 n_channels;
u32 n_ssids;
u32 n_bssids;
u8 ie[WLAN_SCAN_PARAMS_MAX_IE_LEN];
u32 channels[64];
struct wmi_ssid_arg ssids[WLAN_SCAN_PARAMS_MAX_SSID];
struct wmi_bssid_arg bssids[WLAN_SCAN_PARAMS_MAX_BSSID];
};
#define WMI_SCAN_STOP_ONE 0x00000000
#define WMI_SCAN_STOP_VAP_ALL 0x01000000
#define WMI_SCAN_STOP_ALL 0x04000000
@ -4776,8 +4744,6 @@ struct wmi_probe_tmpl_cmd {
__le32 buf_len;
} __packed;
#define WMI_MAX_MEM_REQS 32
#define MAX_RADIOS 3
#define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ)

View File

@ -364,8 +364,7 @@ static void ath6kl_htc_tx_prep_pkt(struct htc_packet *packet, u8 flags,
packet->buf -= HTC_HDR_LENGTH;
hdr = (struct htc_frame_hdr *)packet->buf;
/* Endianess? */
put_unaligned((u16)packet->act_len, &hdr->payld_len);
put_unaligned_le16(packet->act_len, &hdr->payld_len);
hdr->flags = flags;
hdr->eid = packet->endpoint;
hdr->ctrl[0] = ctrl0;

View File

@ -237,8 +237,7 @@ static int htc_issue_packets(struct htc_target *target,
packet->info.tx.flags |= HTC_FLAGS_TX_FIXUP_NETBUF;
/* Endianess? */
put_unaligned((u16) payload_len, &htc_hdr->payld_len);
put_unaligned_le16(payload_len, &htc_hdr->payld_len);
htc_hdr->flags = packet->info.tx.flags;
htc_hdr->eid = (u8) packet->endpoint;
htc_hdr->ctrl[0] = 0;

View File

@ -39,6 +39,7 @@ extern int ath9k_modparam_nohwcrypt;
extern int ath9k_led_blink;
extern bool is_ath9k_unloaded;
extern int ath9k_use_chanctx;
extern int ath9k_use_msi;
/*************************/
/* Descriptor Management */

View File

@ -76,7 +76,7 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
static u32 ath9k_dump_4k_modal_eeprom(char *buf, u32 len, u32 size,
struct modal_eep_4k_header *modal_hdr)
{
PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Chain0 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
PR_EEP("Switch Settle", modal_hdr->switchSettling);

View File

@ -79,8 +79,8 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
static u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size,
struct modal_eep_ar9287_header *modal_hdr)
{
PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
PR_EEP("Chain0 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Chain1 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[1]));
PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);

View File

@ -135,9 +135,9 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
struct modal_eep_header *modal_hdr)
{
PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
PR_EEP("Chain2 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[2]));
PR_EEP("Chain0 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[0]));
PR_EEP("Chain1 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[1]));
PR_EEP("Chain2 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[2]));
PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);

View File

@ -21,8 +21,6 @@
#include <linux/module.h>
#include "ath9k.h"
extern int ath9k_use_msi;
static const struct pci_device_id ath_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */

View File

@ -1674,8 +1674,14 @@ static void
ath9k_set_moredata(struct ath_softc *sc, struct ath_buf *bf, bool val)
{
struct ieee80211_hdr *hdr;
u16 mask = cpu_to_le16(IEEE80211_FCTL_MOREDATA);
u16 mask_val = mask * val;
__le16 mask, mask_val;
mask = cpu_to_le16(IEEE80211_FCTL_MOREDATA);
if (val)
mask_val = mask;
else
mask_val = 0;
hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
if ((hdr->frame_control & mask) != mask_val) {

View File

@ -756,9 +756,9 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
if (sta->deflink.vht_cap.vht_supported) {
sta_priv->supported_rates.op_rate_mode = STA_11ac;
sta_priv->supported_rates.vht_rx_mcs_map =
sta->deflink.vht_cap.vht_mcs.rx_mcs_map;
le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map);
sta_priv->supported_rates.vht_tx_mcs_map =
sta->deflink.vht_cap.vht_mcs.tx_mcs_map;
le16_to_cpu(sta->deflink.vht_cap.vht_mcs.tx_mcs_map);
}
}

View File

@ -318,7 +318,7 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
memset(&status, 0, sizeof(status));
bd = (struct wcn36xx_rx_bd *)skb->data;
buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32));
buff_to_be(bd, sizeof(*bd)/sizeof(u32));
wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP,
"BD <<< ", (char *)bd,
sizeof(struct wcn36xx_rx_bd));
@ -692,7 +692,7 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
/* MGMT and CTRL frames are handeld here*/
wcn36xx_set_tx_mgmt(&bd, wcn, &vif_priv, skb, bcast);
buff_to_be((u32 *)&bd, sizeof(bd)/sizeof(u32));
buff_to_be(&bd, sizeof(bd)/sizeof(u32));
bd.tx_bd_sign = 0xbdbdbdbd;
ret = wcn36xx_dxe_tx_frame(wcn, vif_priv, &bd, skb, is_low);

View File

@ -100,11 +100,14 @@ enum wcn36xx_ampdu_state {
#define RF_IRIS_WCN3660 0x3660
#define RF_IRIS_WCN3680 0x3680
static inline void buff_to_be(u32 *buf, size_t len)
static inline void buff_to_be(void *buf, size_t len)
{
__be32 *to = buf;
u32 *from = buf;
int i;
for (i = 0; i < len; i++)
buf[i] = cpu_to_be32(buf[i]);
to[i] = cpu_to_be32(from[i]);
}
struct nv_data {

View File

@ -2735,7 +2735,7 @@ int wil_cfg80211_iface_combinations_from_fw(
return 0;
}
combo = conc->combos;
combo = (const struct wil_fw_concurrency_combo *)(conc + 1);
n_combos = le16_to_cpu(conc->n_combos);
for (i = 0; i < n_combos; i++) {
total_limits += combo->n_limits;
@ -2751,7 +2751,7 @@ int wil_cfg80211_iface_combinations_from_fw(
return -ENOMEM;
iface_limit = (struct ieee80211_iface_limit *)(iface_combinations +
n_combos);
combo = conc->combos;
combo = (const struct wil_fw_concurrency_combo *)(conc + 1);
for (i = 0; i < n_combos; i++) {
iface_combinations[i].max_interfaces = combo->max_interfaces;
iface_combinations[i].num_different_channels =

View File

@ -93,7 +93,6 @@ struct wil_fw_record_concurrency { /* type == wil_fw_type_comment */
/* number of concurrency combinations that follow */
__le16 n_combos;
/* keep last - combinations, variable size by n_combos */
struct wil_fw_concurrency_combo combos[];
} __packed;
/* brd file info encoded inside a comment record */

View File

@ -212,8 +212,8 @@ fw_handle_concurrency(struct wil6210_priv *wil, const void *data,
}
n_combos = le16_to_cpu(rec->n_combos);
remain = size - offsetof(struct wil_fw_record_concurrency, combos);
combo = rec->combos;
remain = size - sizeof(struct wil_fw_record_concurrency);
combo = (const struct wil_fw_concurrency_combo *)(rec + 1);
for (i = 0; i < n_combos; i++) {
if (remain < sizeof(*combo))
goto out_short;

View File

@ -53,19 +53,14 @@ static ssize_t b43_attr_interfmode_show(struct device *dev,
switch (wldev->phy.g->interfmode) {
case B43_INTERFMODE_NONE:
count =
snprintf(buf, PAGE_SIZE,
"0 (No Interference Mitigation)\n");
count = sysfs_emit(buf, "0 (No Interference Mitigation)\n");
break;
case B43_INTERFMODE_NONWLAN:
count =
snprintf(buf, PAGE_SIZE,
"1 (Non-WLAN Interference Mitigation)\n");
count = sysfs_emit(buf,
"1 (Non-WLAN Interference Mitigation)\n");
break;
case B43_INTERFMODE_MANUALWLAN:
count =
snprintf(buf, PAGE_SIZE,
"2 (WLAN Interference Mitigation)\n");
count = sysfs_emit(buf, "2 (WLAN Interference Mitigation)\n");
break;
default:
B43_WARN_ON(1);

View File

@ -75,16 +75,14 @@ static ssize_t b43legacy_attr_interfmode_show(struct device *dev,
switch (wldev->phy.interfmode) {
case B43legacy_INTERFMODE_NONE:
count = snprintf(buf, PAGE_SIZE, "0 (No Interference"
" Mitigation)\n");
count = sysfs_emit(buf, "0 (No Interference Mitigation)\n");
break;
case B43legacy_INTERFMODE_NONWLAN:
count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference"
" Mitigation)\n");
count = sysfs_emit(buf,
"1 (Non-WLAN Interference Mitigation)\n");
break;
case B43legacy_INTERFMODE_MANUALWLAN:
count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference"
" Mitigation)\n");
count = sysfs_emit(buf, "2 (WLAN Interference Mitigation)\n");
break;
default:
B43legacy_WARN_ON(1);
@ -155,11 +153,9 @@ static ssize_t b43legacy_attr_preamble_show(struct device *dev,
mutex_lock(&wldev->wl->mutex);
if (wldev->short_preamble)
count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble"
" enabled)\n");
count = sysfs_emit(buf, "1 (Short Preamble enabled)\n");
else
count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble"
" disabled)\n");
count = sysfs_emit(buf, "0 (Short Preamble disabled)\n");
mutex_unlock(&wldev->wl->mutex);

View File

@ -1675,6 +1675,15 @@ struct brcmf_random_seed_footer {
#define BRCMF_RANDOM_SEED_MAGIC 0xfeedc0de
#define BRCMF_RANDOM_SEED_LENGTH 0x100
static noinline_for_stack void
brcmf_pcie_provide_random_bytes(struct brcmf_pciedev_info *devinfo, u32 address)
{
u8 randbuf[BRCMF_RANDOM_SEED_LENGTH];
get_random_bytes(randbuf, BRCMF_RANDOM_SEED_LENGTH);
memcpy_toio(devinfo->tcm + address, randbuf, BRCMF_RANDOM_SEED_LENGTH);
}
static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
const struct firmware *fw, void *nvram,
u32 nvram_len)
@ -1717,7 +1726,6 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
.length = cpu_to_le32(rand_len),
.magic = cpu_to_le32(BRCMF_RANDOM_SEED_MAGIC),
};
void *randbuf;
/* Some Apple chips/firmwares expect a buffer of random
* data to be present before NVRAM
@ -1729,10 +1737,7 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
sizeof(footer));
address -= rand_len;
randbuf = kzalloc(rand_len, GFP_KERNEL);
get_random_bytes(randbuf, rand_len);
memcpy_toio(devinfo->tcm + address, randbuf, rand_len);
kfree(randbuf);
brcmf_pcie_provide_random_bytes(devinfo, address);
}
} else {
brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",

View File

@ -149,6 +149,8 @@ const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
};
const char iwl_bz_name[] = "Intel(R) TBD Bz device";
const char iwl_fm_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz";
const char iwl_gl_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz";
const char iwl_mtp_name[] = "Intel(R) Wi-Fi 7 BE202 160MHz";
const struct iwl_cfg iwl_cfg_bz = {

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@ -843,6 +843,52 @@ struct iwl_wowlan_info_notif_v2 {
u8 reserved2[2];
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_2 */
/* MAX MLO keys of non-active links that can arrive in the notification */
#define WOWLAN_MAX_MLO_KEYS 18
/**
* enum iwl_wowlan_mlo_gtk_type - GTK types
* @WOWLAN_MLO_GTK_KEY_TYPE_GTK: GTK
* @WOWLAN_MLO_GTK_KEY_TYPE_IGTK: IGTK
* @WOWLAN_MLO_GTK_KEY_TYPE_BIGTK: BIGTK
* @WOWLAN_MLO_GTK_KEY_NUM_TYPES: number of key types
*/
enum iwl_wowlan_mlo_gtk_type {
WOWLAN_MLO_GTK_KEY_TYPE_GTK,
WOWLAN_MLO_GTK_KEY_TYPE_IGTK,
WOWLAN_MLO_GTK_KEY_TYPE_BIGTK,
WOWLAN_MLO_GTK_KEY_NUM_TYPES
}; /* WOWLAN_MLO_GTK_KEY_TYPE_API_E_VER_1 */
/**
* enum iwl_wowlan_mlo_gtk_flag - MLO GTK flags
* @WOWLAN_MLO_GTK_FLAG_KEY_LEN_MSK: 0 for len 16, 1 for len 32
* @WOWLAN_MLO_GTK_FLAG_KEY_ID_MSK: key id (ranges from 0 to 7)
* @WOWLAN_MLO_GTK_FLAG_LINK_ID_MSK: spec link id of the key
* @WOWLAN_MLO_GTK_FLAG_KEY_TYPE_MSK: &enum iwl_wowlan_mlo_gtk_type
* @WOWLAN_MLO_GTK_FLAG_LAST_KEY_MSK: is this the last given key per
* key-type / link-id - the currently used key
*/
enum iwl_wowlan_mlo_gtk_flag {
WOWLAN_MLO_GTK_FLAG_KEY_LEN_MSK = 0x0001,
WOWLAN_MLO_GTK_FLAG_KEY_ID_MSK = 0x000E,
WOWLAN_MLO_GTK_FLAG_LINK_ID_MSK = 0x00F0,
WOWLAN_MLO_GTK_FLAG_KEY_TYPE_MSK = 0x0300,
WOWLAN_MLO_GTK_FLAG_LAST_KEY_MSK = 0x0400
}; /* WOWLAN_MLO_GTK_FLAG_API_E_VER_1 */
/**
* struct iwl_wowlan_mlo_gtk - MLO GTK info
* @key: key material
* @flags: &enum iwl_wowlan_mlo_gtk_flag
* @pn: packet number
*/
struct iwl_wowlan_mlo_gtk {
u8 key[WOWLAN_KEY_MAX_SIZE];
__le16 flags;
u8 pn[6];
} __packed; /* WOWLAN_MLO_GTK_KEY_API_S_VER_1 */
/**
* struct iwl_wowlan_info_notif - WoWLAN information notification
* @gtk: GTK data
@ -859,7 +905,10 @@ struct iwl_wowlan_info_notif_v2 {
* @tid_tear_down: bit mask of tids whose BA sessions were closed
* in suspend state
* @station_id: station id
* @num_mlo_link_keys: number of &struct iwl_wowlan_mlo_gtk structs
* following this notif, or reserved in version < 4
* @reserved2: reserved
* @mlo_gtks: array of GTKs of size num_mlo_link_keys for version >= 4
*/
struct iwl_wowlan_info_notif {
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
@ -875,8 +924,10 @@ struct iwl_wowlan_info_notif {
__le32 received_beacons;
u8 tid_tear_down;
u8 station_id;
u8 reserved2[2];
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_3 */
u8 num_mlo_link_keys;
u8 reserved2;
struct iwl_wowlan_mlo_gtk mlo_gtks[];
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_3, _VER_4 */
/**
* struct iwl_wowlan_wake_pkt_notif - WoWLAN wake packet notification

View File

@ -609,7 +609,7 @@ struct iwl_lari_config_change_cmd_v6 {
/**
* struct iwl_lari_config_change_cmd_v7 - change LARI configuration
* This structure is used also for lari cmd version 8.
* This structure is used also for lari cmd version 8 and 9.
* @config_bitmap: Bitmap of the config commands. Each bit will trigger a
* different predefined FW config operation.
* @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets.
@ -619,6 +619,8 @@ struct iwl_lari_config_change_cmd_v6 {
* @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits
* per country, one to indicate whether to override and the other to
* indicate allow/disallow unii4 channels.
* For LARI cmd version 4 to 8 - bits 0:3 are supported.
* For LARI cmd version 9 - bits 0:5 are supported.
* @chan_state_active_bitmap: Bitmap to enable different bands per country
* or region.
* Each bit represents a country or region, and a band to activate
@ -642,6 +644,7 @@ struct iwl_lari_config_change_cmd_v7 {
} __packed;
/* LARI_CHANGE_CONF_CMD_S_VER_7 */
/* LARI_CHANGE_CONF_CMD_S_VER_8 */
/* LARI_CHANGE_CONF_CMD_S_VER_9 */
/* Activate UNII-1 (5.2GHz) for World Wide */
#define ACTIVATE_5G2_IN_WW_MASK BIT(4)

View File

@ -3,7 +3,7 @@
* Copyright (C) 2012-2014 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
* Copyright (C) 2021-2023 Intel Corporation
* Copyright (C) 2021-2024 Intel Corporation
*/
#ifndef __iwl_fw_api_offload_h__
#define __iwl_fw_api_offload_h__
@ -20,7 +20,7 @@ enum iwl_prot_offload_subcmd_ids {
/**
* @WOWLAN_INFO_NOTIFICATION: Notification in
* &struct iwl_wowlan_info_notif_v1, &struct iwl_wowlan_info_notif_v2,
* or iwl_wowlan_info_notif
* or &struct iwl_wowlan_info_notif
*/
WOWLAN_INFO_NOTIFICATION = 0xFD,

View File

@ -385,6 +385,33 @@ struct iwl_dev_tx_power_cmd_v7 {
__le32 timer_period;
__le32 flags;
} __packed; /* TX_REDUCED_POWER_API_S_VER_7 */
/**
* struct iwl_dev_tx_power_cmd_v8 - TX power reduction command version 8
* @per_chain: per chain restrictions
* @enable_ack_reduction: enable or disable close range ack TX power
* reduction.
* @per_chain_restriction_changed: is per_chain_restriction has changed
* from last command. used if set_mode is
* IWL_TX_POWER_MODE_SET_SAR_TIMER.
* note: if not changed, the command is used for keep alive only.
* @reserved: reserved (padding)
* @timer_period: timer in milliseconds. if expires FW will change to default
* BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER
* @flags: reduce power flags.
* @tpc_vlp_backoff_level: user backoff of UNII5,7 VLP channels in USA.
* Not in use.
*/
struct iwl_dev_tx_power_cmd_v8 {
__le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
u8 enable_ack_reduction;
u8 per_chain_restriction_changed;
u8 reserved[2];
__le32 timer_period;
__le32 flags;
__le32 tpc_vlp_backoff_level;
} __packed; /* TX_REDUCED_POWER_API_S_VER_8 */
/**
* struct iwl_dev_tx_power_cmd - TX power reduction command (multiversion)
* @common: common part of the command
@ -392,6 +419,8 @@ struct iwl_dev_tx_power_cmd_v7 {
* @v4: version 4 part of the command
* @v5: version 5 part of the command
* @v6: version 6 part of the command
* @v7: version 7 part of the command
* @v8: version 8 part of the command
*/
struct iwl_dev_tx_power_cmd {
struct iwl_dev_tx_power_common common;
@ -401,6 +430,7 @@ struct iwl_dev_tx_power_cmd {
struct iwl_dev_tx_power_cmd_v5 v5;
struct iwl_dev_tx_power_cmd_v6 v6;
struct iwl_dev_tx_power_cmd_v7 v7;
struct iwl_dev_tx_power_cmd_v8 v8;
};
};

View File

@ -3084,6 +3084,7 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
if (!test_bit(wk_idx, &fwrt->dump.active_wks))
return;
/* also checks 'desc' for pre-ini mode, since that shadows in union */
if (!dump_data->trig) {
IWL_ERR(fwrt, "dump trigger data is not set\n");
goto out;

View File

@ -395,6 +395,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* @IWL_UCODE_TLV_CAPA_SPP_AMSDU_SUPPORT: Support SPP (signaling and payload
* protected) A-MSDU.
* @IWL_UCODE_TLV_CAPA_SECURE_LTF_SUPPORT: Support secure LTF measurement.
* @IWL_UCODE_TLV_CAPA_MONITOR_PASSIVE_CHANS: Support monitor mode on otherwise
* passive channels
*
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
*/
@ -494,6 +496,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_SNIFF_VALIDATE_SUPPORT = (__force iwl_ucode_tlv_capa_t)116,
IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT = (__force iwl_ucode_tlv_capa_t)117,
IWL_UCODE_TLV_CAPA_SECURE_LTF_SUPPORT = (__force iwl_ucode_tlv_capa_t)121,
IWL_UCODE_TLV_CAPA_MONITOR_PASSIVE_CHANS = (__force iwl_ucode_tlv_capa_t)122,
NUM_IWL_UCODE_TLV_CAPA
/*
* This construction make both sparse (which cannot increment the previous

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2023 Intel Corporation
* Copyright (C) 2023-2024 Intel Corporation
*/
#ifndef __fw_regulatory_h__
@ -132,6 +132,23 @@ enum iwl_dsm_values_indonesia {
DSM_VALUE_INDONESIA_MAX
};
enum iwl_dsm_unii4_bitmap {
DSM_VALUE_UNII4_US_OVERRIDE_MSK = BIT(0),
DSM_VALUE_UNII4_US_EN_MSK = BIT(1),
DSM_VALUE_UNII4_ETSI_OVERRIDE_MSK = BIT(2),
DSM_VALUE_UNII4_ETSI_EN_MSK = BIT(3),
DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK = BIT(4),
DSM_VALUE_UNII4_CANADA_EN_MSK = BIT(5),
};
#define DSM_UNII4_ALLOW_BITMAP_CMD_V8 (DSM_VALUE_UNII4_US_OVERRIDE_MSK | \
DSM_VALUE_UNII4_US_EN_MSK | \
DSM_VALUE_UNII4_ETSI_OVERRIDE_MSK | \
DSM_VALUE_UNII4_ETSI_EN_MSK)
#define DSM_UNII4_ALLOW_BITMAP (DSM_UNII4_ALLOW_BITMAP_CMD_V8 | \
DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK | \
DSM_VALUE_UNII4_CANADA_EN_MSK)
enum iwl_dsm_values_rfi {
DSM_VALUE_RFI_DLVR_DISABLE = BIT(0),
DSM_VALUE_RFI_DDR_DISABLE = BIT(1),

View File

@ -46,6 +46,10 @@ struct iwl_fwrt_shared_mem_cfg {
* struct iwl_fwrt_dump_data - dump data
* @trig: trigger the worker was scheduled upon
* @fw_pkt: packet received from FW
*
* Note that the decision which part of the union is used
* is based on iwl_trans_dbg_ini_valid(): the 'trig' part
* is used if it is %true, the 'desc' part otherwise.
*/
struct iwl_fwrt_dump_data {
union {
@ -54,6 +58,7 @@ struct iwl_fwrt_dump_data {
struct iwl_rx_packet *fw_pkt;
};
struct {
/* must be first to be same as 'trig' */
const struct iwl_fw_dump_desc *desc;
bool monitor_only;
};

View File

@ -11,6 +11,7 @@
#include <linux/netdevice.h>
#include <linux/ieee80211.h>
#include <linux/nl80211.h>
#include <linux/mod_devicetable.h>
#include "iwl-csr.h"
#include "iwl-drv.h"
@ -421,6 +422,7 @@ struct iwl_cfg {
#define IWL_CFG_MAC_TYPE_SC 0x48
#define IWL_CFG_MAC_TYPE_SC2 0x49
#define IWL_CFG_MAC_TYPE_SC2F 0x4A
#define IWL_CFG_MAC_TYPE_BZ_W 0x4B
#define IWL_CFG_RF_TYPE_TH 0x105
#define IWL_CFG_RF_TYPE_TH1 0x108
@ -429,8 +431,6 @@ struct iwl_cfg {
#define IWL_CFG_RF_TYPE_HR2 0x10A
#define IWL_CFG_RF_TYPE_HR1 0x10C
#define IWL_CFG_RF_TYPE_GF 0x10D
#define IWL_CFG_RF_TYPE_MR 0x110
#define IWL_CFG_RF_TYPE_MS 0x111
#define IWL_CFG_RF_TYPE_FM 0x112
#define IWL_CFG_RF_TYPE_WH 0x113
@ -484,6 +484,7 @@ const struct iwl_dev_info *
iwl_pci_find_dev_info(u16 device, u16 subsystem_device,
u16 mac_type, u8 mac_step, u16 rf_type, u8 cdb,
u8 jacket, u8 rf_id, u8 no_160, u8 cores, u8 rf_step);
extern const struct pci_device_id iwl_hw_card_ids[];
#endif
/*
@ -541,6 +542,8 @@ extern const char iwl_ax221_name[];
extern const char iwl_ax231_name[];
extern const char iwl_ax411_name[];
extern const char iwl_bz_name[];
extern const char iwl_fm_name[];
extern const char iwl_gl_name[];
extern const char iwl_mtp_name[];
extern const char iwl_sc_name[];
extern const char iwl_sc2_name[];

View File

@ -192,12 +192,6 @@ const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf)
case IWL_CFG_RF_TYPE_GF:
rf = "gf";
break;
case IWL_CFG_RF_TYPE_MR:
rf = "mr";
break;
case IWL_CFG_RF_TYPE_MS:
rf = "ms";
break;
case IWL_CFG_RF_TYPE_FM:
rf = "fm";
break;

View File

@ -392,11 +392,14 @@ static enum nl80211_band iwl_nl80211_band_from_channel_idx(int ch_idx)
return NL80211_BAND_2GHZ;
}
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
static int iwl_init_channel_map(struct iwl_trans *trans,
const struct iwl_fw *fw,
struct iwl_nvm_data *data,
const void * const nvm_ch_flags,
u32 sbands_flags, bool v4)
{
const struct iwl_cfg *cfg = trans->cfg;
struct device *dev = trans->dev;
int ch_idx;
int n_channels = 0;
struct ieee80211_channel *channel;
@ -478,11 +481,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
else
channel->flags = 0;
/* TODO: Don't put limitations on UHB devices as we still don't
* have NVM for them
*/
if (cfg->uhb_supported)
channel->flags = 0;
if (fw_has_capa(&fw->ucode_capa,
IWL_UCODE_TLV_CAPA_MONITOR_PASSIVE_CHANS))
channel->flags |= IEEE80211_CHAN_CAN_MONITOR;
iwl_nvm_print_channel_flags(dev, IWL_DL_EEPROM,
channel->hw_value, ch_flags);
IWL_DEBUG_EEPROM(dev, "Ch. %d: %ddBm\n",
@ -597,7 +599,8 @@ static const u8 iwl_vendor_caps[] = {
static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
{
.types_mask = BIT(NL80211_IFTYPE_STATION),
.types_mask = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_P2P_CLIENT),
.he_cap = {
.has_he = true,
.he_cap_elem = {
@ -753,7 +756,8 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
},
},
{
.types_mask = BIT(NL80211_IFTYPE_AP),
.types_mask = BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO),
.he_cap = {
.has_he = true,
.he_cap_elem = {
@ -906,7 +910,8 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
u8 tx_chains, u8 rx_chains,
const struct iwl_fw *fw)
{
bool is_ap = iftype_data->types_mask & BIT(NL80211_IFTYPE_AP);
bool is_ap = iftype_data->types_mask & (BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO));
bool no_320;
no_320 = (!trans->trans_cfg->integrated &&
@ -1023,8 +1028,6 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
case IWL_CFG_RF_TYPE_GF:
case IWL_CFG_RF_TYPE_MR:
case IWL_CFG_RF_TYPE_MS:
case IWL_CFG_RF_TYPE_FM:
case IWL_CFG_RF_TYPE_WH:
iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |=
@ -1176,12 +1179,11 @@ static void iwl_init_sbands(struct iwl_trans *trans,
const struct iwl_fw *fw)
{
struct device *dev = trans->dev;
const struct iwl_cfg *cfg = trans->cfg;
int n_channels;
int n_used = 0;
struct ieee80211_supported_band *sband;
n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags,
n_channels = iwl_init_channel_map(trans, fw, data, nvm_ch_flags,
sbands_flags, v4);
sband = &data->bands[NL80211_BAND_2GHZ];
sband->band = NL80211_BAND_2GHZ;

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2005-2014, 2018-2023 Intel Corporation
* Copyright (C) 2005-2014, 2018-2024 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
@ -371,7 +371,10 @@ enum {
#define CNVI_AUX_MISC_CHIP 0xA200B0
#define CNVI_AUX_MISC_CHIP_MAC_STEP(_val) (((_val) & 0xf000000) >> 24)
#define CNVI_AUX_MISC_CHIP_PROD_TYPE(_val) ((_val) & 0xfff)
#define CNVI_AUX_MISC_CHIP_PROD_TYPE_GL 0x910
#define CNVI_AUX_MISC_CHIP_PROD_TYPE_BZ_U 0x930
#define CNVI_AUX_MISC_CHIP_PROD_TYPE_BZ_I 0x900
#define CNVI_AUX_MISC_CHIP_PROD_TYPE_BZ_W 0x901
#define CNVR_AUX_MISC_CHIP 0xA2B800
#define CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM 0xA29890
@ -453,11 +456,7 @@ enum {
#define REG_CRF_ID_TYPE_HR_NONE_CDB_1X1 0x501
#define REG_CRF_ID_TYPE_HR_NONE_CDB_CCP 0x532
#define REG_CRF_ID_TYPE_GF 0x410
#define REG_CRF_ID_TYPE_GF_TC 0xF08
#define REG_CRF_ID_TYPE_MR 0x810
#define REG_CRF_ID_TYPE_FM 0x910
#define REG_CRF_ID_TYPE_FMI 0x930
#define REG_CRF_ID_TYPE_FMR 0x900
#define REG_CRF_ID_TYPE_WHP 0xA10
#define HPM_DEBUG 0xA03440

View File

@ -219,15 +219,13 @@ struct iwl_bt_iterator_data {
static inline
void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_mvm_vif_link_info *link_info,
bool enable, int rssi)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
mvmvif->bf_data.last_bt_coex_event = rssi;
mvmvif->bf_data.bt_coex_max_thold =
link_info->bf_data.last_bt_coex_event = rssi;
link_info->bf_data.bt_coex_max_thold =
enable ? -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH : 0;
mvmvif->bf_data.bt_coex_min_thold =
link_info->bf_data.bt_coex_min_thold =
enable ? -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH : 0;
}
@ -412,8 +410,8 @@ static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
smps_mode, link_id);
iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id,
false);
/* FIXME: should this be per link? */
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
iwl_mvm_bt_coex_enable_rssi_event(mvm, link_info, false,
0);
}
return;
}
@ -508,13 +506,12 @@ static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF ||
!vif->cfg.assoc) {
iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id, false);
/* FIXME: should this be per link? */
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
iwl_mvm_bt_coex_enable_rssi_event(mvm, link_info, false, 0);
return;
}
/* try to get the avg rssi from fw */
ave_rssi = mvmvif->bf_data.ave_beacon_signal;
ave_rssi = link_info->bf_data.ave_beacon_signal;
/* if the RSSI isn't valid, fake it is very low */
if (!ave_rssi)
@ -530,7 +527,7 @@ static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
}
/* Begin to monitor the RSSI: it may influence the reduced Tx power */
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi);
iwl_mvm_bt_coex_enable_rssi_event(mvm, link_info, true, ave_rssi);
}
/* must be called under rcu_read_lock */

View File

@ -1152,7 +1152,8 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
if (ret)
return ret;
return iwl_mvm_send_proto_offload(mvm, vif, false, true, 0);
return iwl_mvm_send_proto_offload(mvm, vif, false, true, 0,
mvm_link->ap_sta_id);
}
static int
@ -1472,6 +1473,9 @@ struct iwl_wowlan_status_data {
struct iwl_multicast_key_data igtk;
struct iwl_multicast_key_data bigtk[WOWLAN_BIGTK_KEYS_NUM];
int num_mlo_keys;
struct iwl_wowlan_mlo_gtk mlo_keys[WOWLAN_MAX_MLO_KEYS];
u8 *wake_packet;
};
@ -1830,6 +1834,10 @@ static void iwl_mvm_d3_find_last_keys(struct ieee80211_hw *hw,
void *_data)
{
struct iwl_mvm_d3_gtk_iter_data *data = _data;
int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
if (link_id >= 0 && key->link_id >= 0 && link_id != key->link_id)
return;
if (data->unhandled_cipher)
return;
@ -1918,6 +1926,10 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
struct iwl_mvm_d3_gtk_iter_data *data = _data;
struct iwl_wowlan_status_data *status = data->status;
s8 keyidx;
int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
if (link_id >= 0 && key->link_id >= 0 && link_id != key->link_id)
return;
if (data->unhandled_cipher)
return;
@ -1973,6 +1985,169 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
}
}
struct iwl_mvm_d3_mlo_old_keys {
u32 cipher[IEEE80211_MLD_MAX_NUM_LINKS][WOWLAN_MLO_GTK_KEY_NUM_TYPES];
struct ieee80211_key_conf *key[IEEE80211_MLD_MAX_NUM_LINKS][8];
};
static void iwl_mvm_mlo_key_ciphers(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key,
void *data)
{
struct iwl_mvm_d3_mlo_old_keys *old_keys = data;
enum iwl_wowlan_mlo_gtk_type key_type;
if (key->link_id < 0)
return;
if (WARN_ON(key->link_id >= IEEE80211_MLD_MAX_NUM_LINKS ||
key->keyidx >= 8))
return;
if (WARN_ON(old_keys->key[key->link_id][key->keyidx]))
return;
switch (key->cipher) {
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
key_type = WOWLAN_MLO_GTK_KEY_TYPE_GTK;
break;
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
case WLAN_CIPHER_SUITE_AES_CMAC:
if (key->keyidx == 4 || key->keyidx == 5) {
key_type = WOWLAN_MLO_GTK_KEY_TYPE_IGTK;
break;
} else if (key->keyidx == 6 || key->keyidx == 7) {
key_type = WOWLAN_MLO_GTK_KEY_TYPE_BIGTK;
break;
}
return;
default:
/* ignore WEP/TKIP or unknown ciphers */
return;
}
old_keys->cipher[key->link_id][key_type] = key->cipher;
old_keys->key[key->link_id][key->keyidx] = key;
}
static bool iwl_mvm_mlo_gtk_rekey(struct iwl_wowlan_status_data *status,
struct ieee80211_vif *vif,
struct iwl_mvm *mvm)
{
int i;
struct iwl_mvm_d3_mlo_old_keys *old_keys;
bool ret = true;
IWL_DEBUG_WOWLAN(mvm, "Num of MLO Keys: %d\n", status->num_mlo_keys);
if (!status->num_mlo_keys)
return true;
old_keys = kzalloc(sizeof(*old_keys), GFP_KERNEL);
if (!old_keys)
return false;
/* find the cipher for each mlo key */
ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_mlo_key_ciphers, old_keys);
for (i = 0; i < status->num_mlo_keys; i++) {
struct iwl_wowlan_mlo_gtk *mlo_key = &status->mlo_keys[i];
struct ieee80211_key_conf *key, *old_key;
struct ieee80211_key_seq seq;
struct {
struct ieee80211_key_conf conf;
u8 key[32];
} conf = {};
u16 flags = le16_to_cpu(mlo_key->flags);
int j, link_id, key_id, key_type;
link_id = u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_LINK_ID_MSK);
key_id = u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_KEY_ID_MSK);
key_type = u16_get_bits(flags,
WOWLAN_MLO_GTK_FLAG_KEY_TYPE_MSK);
if (!(vif->valid_links & BIT(link_id)))
continue;
if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS ||
key_id >= 8 ||
key_type >= WOWLAN_MLO_GTK_KEY_NUM_TYPES))
continue;
conf.conf.cipher = old_keys->cipher[link_id][key_type];
/* WARN_ON? */
if (!conf.conf.cipher)
continue;
conf.conf.keylen = 0;
switch (conf.conf.cipher) {
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_GCMP:
conf.conf.keylen = WLAN_KEY_LEN_CCMP;
break;
case WLAN_CIPHER_SUITE_GCMP_256:
conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;
break;
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128;
break;
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256;
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC;
break;
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256;
break;
}
if (WARN_ON(!conf.conf.keylen ||
conf.conf.keylen > sizeof(conf.key)))
continue;
memcpy(conf.conf.key, mlo_key->key, conf.conf.keylen);
conf.conf.keyidx = key_id;
old_key = old_keys->key[link_id][key_id];
if (old_key) {
IWL_DEBUG_WOWLAN(mvm,
"Remove MLO key id %d, link id %d\n",
key_id, link_id);
ieee80211_remove_key(old_key);
}
IWL_DEBUG_WOWLAN(mvm, "Add MLO key id %d, link id %d\n",
key_id, link_id);
key = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id);
if (WARN_ON(IS_ERR(key))) {
ret = false;
goto out;
}
/*
* mac80211 expects the pn in big-endian
* also note that seq is a union of all cipher types
* (ccmp, gcmp, cmac, gmac), and they all have the same
* pn field (of length 6) so just copy it to ccmp.pn.
*/
for (j = 5; j >= 0; j--)
seq.ccmp.pn[5 - j] = mlo_key->pn[j];
/* group keys are non-QoS and use TID 0 */
ieee80211_set_key_rx_seq(key, 0, &seq);
}
out:
kfree(old_keys);
return ret;
}
static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,
struct ieee80211_vif *vif,
struct iwl_mvm *mvm, u32 gtk_cipher)
@ -2176,6 +2351,9 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
return false;
}
if (!iwl_mvm_mlo_gtk_rekey(status, vif, mvm))
return false;
ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
(void *)&replay_ctr, GFP_KERNEL);
}
@ -2303,9 +2481,10 @@ static void iwl_mvm_convert_bigtk(struct iwl_wowlan_status_data *status,
static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
struct iwl_wowlan_info_notif *data,
struct iwl_wowlan_status_data *status,
u32 len)
u32 len, bool has_mlo_keys)
{
u32 i;
u32 expected_len = sizeof(*data);
if (!data) {
IWL_ERR(mvm, "iwl_wowlan_info_notif data is NULL\n");
@ -2313,7 +2492,11 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
return;
}
if (len < sizeof(*data)) {
if (has_mlo_keys)
expected_len += (data->num_mlo_link_keys *
sizeof(status->mlo_keys[0]));
if (len < expected_len) {
IWL_ERR(mvm, "Invalid WoWLAN info notification!\n");
status = NULL;
return;
@ -2333,6 +2516,17 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
le32_to_cpu(data->num_of_gtk_rekeys);
status->received_beacons = le32_to_cpu(data->received_beacons);
status->tid_tear_down = data->tid_tear_down;
if (has_mlo_keys && data->num_mlo_link_keys) {
status->num_mlo_keys = data->num_mlo_link_keys;
if (IWL_FW_CHECK(mvm,
status->num_mlo_keys > WOWLAN_MAX_MLO_KEYS,
"Too many mlo keys: %d, max %d\n",
status->num_mlo_keys, WOWLAN_MAX_MLO_KEYS))
status->num_mlo_keys = WOWLAN_MAX_MLO_KEYS;
memcpy(status->mlo_keys, data->mlo_gtks,
status->num_mlo_keys * sizeof(status->mlo_keys[0]));
}
}
static void
@ -2553,6 +2747,12 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
int i;
bool keep = false;
struct iwl_mvm_sta *mvm_ap_sta;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int link_id = vif->active_links ? __ffs(vif->active_links) : 0;
struct iwl_mvm_vif_link_info *mvm_link = mvmvif->link[link_id];
if (WARN_ON(!mvm_link))
goto out_unlock;
if (!status)
goto out_unlock;
@ -2560,8 +2760,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
IWL_DEBUG_WOWLAN(mvm, "wakeup reason 0x%x\n",
status->wakeup_reasons);
/* still at hard-coded place 0 for D3 image */
mvm_ap_sta = iwl_mvm_sta_from_staid_protected(mvm, 0);
mvm_ap_sta = iwl_mvm_sta_from_staid_protected(mvm, mvm_link->ap_sta_id);
if (!mvm_ap_sta)
goto out_unlock;
@ -3074,7 +3273,8 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait,
(void *)pkt->data;
iwl_mvm_parse_wowlan_info_notif(mvm, notif,
d3_data->status, len);
d3_data->status, len,
wowlan_info_ver > 3);
}
d3_data->notif_received |= IWL_D3_NOTIF_WOWLAN_INFO;

View File

@ -407,7 +407,7 @@ static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
};
iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
if (mvmvif->bf_data.bf_enabled)
if (mvmvif->bf_enabled)
cmd.bf_enable_beacon_filter = cpu_to_le32(1);
else
cmd.bf_enable_beacon_filter = 0;
@ -692,6 +692,60 @@ static ssize_t iwl_dbgfs_quota_min_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t iwl_dbgfs_int_mlo_scan_write(struct ieee80211_vif *vif,
char *buf, size_t count,
loff_t *ppos)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm;
u32 action;
int ret;
if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
return -EINVAL;
if (kstrtou32(buf, 0, &action))
return -EINVAL;
mutex_lock(&mvm->mutex);
if (!action) {
ret = iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_INT_MLO, false);
} else if (action == 1) {
struct ieee80211_channel *channels[IEEE80211_MLD_MAX_NUM_LINKS];
unsigned long usable_links = ieee80211_vif_usable_links(vif);
size_t n_channels = 0;
u8 link_id;
rcu_read_lock();
for_each_set_bit(link_id, &usable_links,
IEEE80211_MLD_MAX_NUM_LINKS) {
struct ieee80211_bss_conf *link_conf =
rcu_dereference(vif->link_conf[link_id]);
if (WARN_ON_ONCE(!link_conf))
continue;
channels[n_channels++] = link_conf->chanreq.oper.chan;
}
rcu_read_unlock();
if (n_channels)
ret = iwl_mvm_int_mlo_scan_start(mvm, vif, channels,
n_channels);
else
ret = -EINVAL;
} else {
ret = -EINVAL;
}
mutex_unlock(&mvm->mutex);
return ret ?: count;
}
#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
_MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
@ -711,6 +765,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving, 20);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
MVM_DEBUGFS_READ_FILE_OPS(os_device_timediff);
MVM_DEBUGFS_WRITE_FILE_OPS(int_mlo_scan, 32);
void iwl_mvm_vif_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
@ -738,6 +793,9 @@ void iwl_mvm_vif_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo, mvmvif->dbgfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE_VIF(os_device_timediff, mvmvif->dbgfs_dir, 0400);
debugfs_create_bool("ftm_unprotected", 0200, mvmvif->dbgfs_dir,
&mvmvif->ftm_unprotected);
MVM_DEBUGFS_ADD_FILE_VIF(int_mlo_scan, mvmvif->dbgfs_dir, 0200);
if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
mvmvif == mvm->bf_allowed_vif)

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2023 Intel Corporation
* Copyright (C) 2018-2024 Intel Corporation
*/
#include <linux/etherdevice.h>
#include <linux/math64.h>
@ -551,6 +551,15 @@ iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
break;
}
rcu_read_unlock();
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (mvmvif->ftm_unprotected) {
target->sta_id = IWL_MVM_INVALID_STA;
target->initiator_ap_flags &=
~cpu_to_le32(IWL_INITIATOR_AP_FLAGS_PMF);
}
#endif
} else {
target->sta_id = IWL_MVM_INVALID_STA;
}
@ -713,6 +722,12 @@ iwl_mvm_ftm_set_secured_ranging(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
{
struct iwl_mvm_ftm_pasn_entry *entry;
u32 flags = le32_to_cpu(target->initiator_ap_flags);
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (mvmvif->ftm_unprotected)
return;
#endif
if (!(flags & (IWL_INITIATOR_AP_FLAGS_NON_TB |
IWL_INITIATOR_AP_FLAGS_TB)))

View File

@ -896,11 +896,13 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
u32 n_subbands;
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id,
IWL_FW_CMD_VER_UNKNOWN);
if (cmd_ver == 7) {
if (cmd_ver >= 7) {
len = sizeof(cmd.v7);
n_subbands = IWL_NUM_SUB_BANDS_V2;
per_chain = cmd.v7.per_chain[0][0];
cmd.v7.flags = cpu_to_le32(mvm->fwrt.reduced_power_flags);
if (cmd_ver == 8)
len = sizeof(cmd.v8);
} else if (cmd_ver == 6) {
len = sizeof(cmd.v6);
n_subbands = IWL_NUM_SUB_BANDS_V2;
@ -1237,8 +1239,14 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
cmd.oem_11ax_allow_bitmap = cpu_to_le32(value);
ret = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value);
if (!ret)
if (!ret) {
if (cmd_ver < 9)
value &= DSM_UNII4_ALLOW_BITMAP_CMD_V8;
else
value &= DSM_UNII4_ALLOW_BITMAP;
cmd.oem_unii4_allow_bitmap = cpu_to_le32(value);
}
ret = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value);
if (!ret) {
@ -1271,6 +1279,7 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
size_t cmd_size;
switch (cmd_ver) {
case 9:
case 8:
case 7:
cmd_size = sizeof(struct iwl_lari_config_change_cmd_v7);

View File

@ -359,8 +359,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
/* Set this early since we need to have it for the check below */
if (mvm->mld_api_is_used && mvm->nvm_data->sku_cap_11be_enable &&
!iwlwifi_mod_params.disable_11ax &&
!iwlwifi_mod_params.disable_11be)
!iwlwifi_mod_params.disable_11be) {
hw->wiphy->flags |= WIPHY_FLAG_DISABLE_WEXT;
/* we handle this already earlier, but need it for MLO */
ieee80211_hw_set(hw, HANDLES_QUIET_CSA);
}
/* With MLD FW API, it tracks timing by itself,
* no need for any timing from the host
@ -720,6 +723,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
ieee80211_hw_set(hw, DISALLOW_PUNCTURING_5GHZ);
#ifdef CONFIG_PM_SLEEP
if ((unified || mvm->fw->img[IWL_UCODE_WOWLAN].num_sec) &&
mvm->trans->ops->d3_suspend &&
@ -903,6 +908,8 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
&mvmtxq->state) &&
!test_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT,
&mvmtxq->state) &&
!test_bit(IWL_MVM_TXQ_STATE_STOP_AP_CSA,
&mvmtxq->state) &&
!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))) {
skb = ieee80211_tx_dequeue(hw, txq);
@ -1097,15 +1104,21 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data);
spin_unlock_bh(&mvm->time_event_lock);
memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
mvmvif->bf_enabled = false;
mvmvif->ba_enabled = false;
mvmvif->ap_sta = NULL;
mvmvif->esr_active = false;
vif->driver_flags &= ~IEEE80211_VIF_EML_ACTIVE;
for_each_mvm_vif_valid_link(mvmvif, link_id) {
mvmvif->link[link_id]->ap_sta_id = IWL_MVM_INVALID_STA;
mvmvif->link[link_id]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
mvmvif->link[link_id]->phy_ctxt = NULL;
mvmvif->link[link_id]->active = 0;
mvmvif->link[link_id]->igtk = NULL;
memset(&mvmvif->link[link_id]->bf_data, 0,
sizeof(mvmvif->link[link_id]->bf_data));
}
probe_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data,
@ -1332,6 +1345,11 @@ void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
/* Stop internal MLO scan, if running */
mutex_lock(&mvm->mutex);
iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_INT_MLO, false);
mutex_unlock(&mvm->mutex);
flush_work(&mvm->async_handlers_wk);
flush_work(&mvm->add_stream_wk);
@ -1399,7 +1417,9 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (tx_power == IWL_DEFAULT_MAX_TX_POWER)
cmd.common.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER);
if (cmd_ver == 7)
if (cmd_ver == 8)
len = sizeof(cmd.v8);
else if (cmd_ver == 7)
len = sizeof(cmd.v7);
else if (cmd_ver == 6)
len = sizeof(cmd.v6);
@ -1418,6 +1438,20 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, &cmd);
}
static void iwl_mvm_post_csa_tx(void *data, struct ieee80211_sta *sta)
{
struct ieee80211_hw *hw = data;
int i;
for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
struct iwl_mvm_txq *mvmtxq =
iwl_mvm_txq_from_mac80211(sta->txq[i]);
clear_bit(IWL_MVM_TXQ_STATE_STOP_AP_CSA, &mvmtxq->state);
iwl_mvm_mac_itxq_xmit(hw, sta->txq[i]);
}
}
int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf)
@ -1434,6 +1468,7 @@ int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
u8 ap_sta_id = mvmvif->link[link_id]->ap_sta_id;
mvmvif->csa_bcn_pending = false;
mvmvif->csa_blocks_tx = false;
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, ap_sta_id);
if (WARN_ON(!mvmsta)) {
@ -1455,6 +1490,18 @@ int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
iwl_mvm_stop_session_protection(mvm, vif);
}
} else if (vif->type == NL80211_IFTYPE_AP && mvmvif->csa_blocks_tx) {
struct iwl_mvm_txq *mvmtxq =
iwl_mvm_txq_from_mac80211(vif->txq);
clear_bit(IWL_MVM_TXQ_STATE_STOP_AP_CSA, &mvmtxq->state);
local_bh_disable();
iwl_mvm_mac_itxq_xmit(hw, vif->txq);
ieee80211_iterate_stations_atomic(hw, iwl_mvm_post_csa_tx, hw);
local_bh_enable();
mvmvif->csa_blocks_tx = false;
}
mvmvif->ps_disabled = false;
@ -1651,9 +1698,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
}
if (vif->p2p || iwl_fw_lookup_cmd_ver(mvm->fw, PHY_CONTEXT_CMD, 1) < 5)
vif->driver_flags |= IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW;
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
mvm->p2p_device_vif = vif;
@ -2545,6 +2589,7 @@ void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
int link_id;
/* The firmware tracks the MU-MIMO group on its own.
* However, on HW restart we should restore this data.
@ -2560,7 +2605,8 @@ void iwl_mvm_bss_info_changed_station_assoc(struct iwl_mvm *mvm,
iwl_mvm_recalc_multicast(mvm);
/* reset rssi values */
mvmvif->bf_data.ave_beacon_signal = 0;
for_each_mvm_vif_valid_link(mvmvif, link_id)
mvmvif->link[link_id]->bf_data.ave_beacon_signal = 0;
iwl_mvm_bt_coex_vif_change(mvm);
iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_TT,
@ -2601,10 +2647,14 @@ iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm,
}
if (changes & BSS_CHANGED_CQM) {
IWL_DEBUG_MAC80211(mvm, "cqm info_changed\n");
/* reset cqm events tracking */
mvmvif->bf_data.last_cqm_event = 0;
if (mvmvif->bf_data.bf_enabled) {
struct iwl_mvm_vif_link_info *link_info =
mvmvif->link[link_conf->link_id];
IWL_DEBUG_MAC80211(mvm, "CQM info_changed\n");
if (link_info)
link_info->bf_data.last_cqm_event = 0;
if (mvmvif->bf_enabled) {
/* FIXME: need to update per link when FW API will
* support it
*/
@ -5398,7 +5448,7 @@ static int iwl_mvm_old_pre_chan_sw_sta(struct iwl_mvm *mvm,
if (chsw->block_tx)
iwl_mvm_csa_client_absent(mvm, vif);
if (mvmvif->bf_data.bf_enabled) {
if (mvmvif->bf_enabled) {
int ret = iwl_mvm_disable_beacon_filter(mvm, vif);
if (ret)
@ -5411,6 +5461,18 @@ static int iwl_mvm_old_pre_chan_sw_sta(struct iwl_mvm *mvm,
return 0;
}
static void iwl_mvm_csa_block_txqs(void *data, struct ieee80211_sta *sta)
{
int i;
for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
struct iwl_mvm_txq *mvmtxq =
iwl_mvm_txq_from_mac80211(sta->txq[i]);
set_bit(IWL_MVM_TXQ_STATE_STOP_AP_CSA, &mvmtxq->state);
}
}
#define IWL_MAX_CSA_BLOCK_TX 1500
int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@ -5419,11 +5481,13 @@ int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct ieee80211_vif *csa_vif;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_txq *mvmtxq;
int ret;
mutex_lock(&mvm->mutex);
mvmvif->csa_failed = false;
mvmvif->csa_blocks_tx = false;
IWL_DEBUG_MAC80211(mvm, "pre CSA to freq %d\n",
chsw->chandef.center_freq1);
@ -5460,8 +5524,22 @@ int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
mvmvif->csa_target_freq = chsw->chandef.chan->center_freq;
if (!chsw->block_tx)
break;
/* don't need blocking in driver otherwise - mac80211 will do */
if (!ieee80211_hw_check(mvm->hw, HANDLES_QUIET_CSA))
break;
mvmvif->csa_blocks_tx = true;
mvmtxq = iwl_mvm_txq_from_mac80211(vif->txq);
set_bit(IWL_MVM_TXQ_STATE_STOP_AP_CSA, &mvmtxq->state);
ieee80211_iterate_stations_atomic(mvm->hw,
iwl_mvm_csa_block_txqs,
NULL);
break;
case NL80211_IFTYPE_STATION:
mvmvif->csa_blocks_tx = chsw->block_tx;
/*
* In the new flow FW is in charge of timing the switch so there
* is no need for all of this
@ -5626,8 +5704,8 @@ static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop)
void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif;
struct iwl_mvm_sta *mvmsta;
struct ieee80211_sta *sta;
bool ap_sta_done = false;
@ -5639,11 +5717,22 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
return;
}
if (!drop && hweight16(vif->active_links) <= 1) {
int link_id = vif->active_links ? __ffs(vif->active_links) : 0;
struct ieee80211_bss_conf *link_conf;
link_conf = wiphy_dereference(hw->wiphy,
vif->link_conf[link_id]);
if (WARN_ON(!link_conf))
return;
if (link_conf->csa_active && mvmvif->csa_blocks_tx)
drop = true;
}
/* Make sure we're done with the deferred traffic before flushing */
flush_work(&mvm->add_stream_wk);
mutex_lock(&mvm->mutex);
mvmvif = iwl_mvm_vif_from_mac80211(vif);
/* flush the AP-station and all TDLS peers */
for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {

View File

@ -92,6 +92,9 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
mvm->csme_vif = vif;
}
if (vif->p2p || iwl_fw_lookup_cmd_ver(mvm->fw, PHY_CONTEXT_CMD, 1) < 5)
vif->driver_flags |= IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW;
goto out_unlock;
out_free_bf:
@ -189,17 +192,13 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}
static unsigned int iwl_mvm_mld_count_active_links(struct ieee80211_vif *vif)
static unsigned int iwl_mvm_mld_count_active_links(struct iwl_mvm_vif *mvmvif)
{
unsigned int n_active = 0;
int i;
for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
struct ieee80211_bss_conf *link_conf;
link_conf = link_conf_dereference_protected(vif, i);
if (link_conf &&
rcu_access_pointer(link_conf->chanctx_conf))
if (mvmvif->link[i] && mvmvif->link[i]->phy_ctxt)
n_active++;
}
@ -245,18 +244,18 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
{
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
unsigned int n_active = iwl_mvm_mld_count_active_links(mvmvif);
unsigned int link_id = link_conf->link_id;
int ret;
/* if the assigned one was not counted yet, count it now */
if (!rcu_access_pointer(link_conf->chanctx_conf))
n_active++;
if (WARN_ON_ONCE(!mvmvif->link[link_id]))
return -EINVAL;
/* if the assigned one was not counted yet, count it now */
if (!mvmvif->link[link_id]->phy_ctxt)
n_active++;
/* mac parameters such as HE support can change at this stage
* For sta, need first to configure correct state from drv_sta_state
* and only after that update mac config.
@ -296,13 +295,8 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
* this needs the phy context assigned (and in FW?), and we cannot
* do it later because it needs to be initialized as soon as we're
* able to TX on the link, i.e. when active.
*
* Firmware restart isn't quite correct yet for MLO, but we don't
* need to do it in that case anyway since it will happen from the
* normal station state callback.
*/
if (mvmvif->ap_sta &&
!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
if (mvmvif->ap_sta) {
struct ieee80211_link_sta *link_sta;
rcu_read_lock();
@ -416,7 +410,7 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
unsigned int n_active = iwl_mvm_mld_count_active_links(mvmvif);
unsigned int link_id = link_conf->link_id;
/* shouldn't happen, but verify link_id is valid before accessing */

View File

@ -9,7 +9,9 @@
u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
int filter_link_id)
{
struct ieee80211_link_sta *link_sta;
struct iwl_mvm_sta *mvmsta;
struct ieee80211_vif *vif;
unsigned int link_id;
u32 result = 0;
@ -17,26 +19,27 @@ u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
return 0;
mvmsta = iwl_mvm_sta_from_mac80211(sta);
vif = mvmsta->vif;
/* it's easy when the STA is not an MLD */
if (!sta->valid_links)
return BIT(mvmsta->deflink.sta_id);
/* but if it is an MLD, get the mask of all the FW STAs it has ... */
for (link_id = 0; link_id < ARRAY_SIZE(mvmsta->link); link_id++) {
struct iwl_mvm_link_sta *link_sta;
for_each_sta_active_link(vif, sta, link_sta, link_id) {
struct iwl_mvm_link_sta *mvm_link_sta;
/* unless we have a specific link in mind */
if (filter_link_id >= 0 && link_id != filter_link_id)
continue;
link_sta =
mvm_link_sta =
rcu_dereference_check(mvmsta->link[link_id],
lockdep_is_held(&mvm->mutex));
if (!link_sta)
if (!mvm_link_sta)
continue;
result |= BIT(link_sta->sta_id);
result |= BIT(mvm_link_sta->sta_id);
}
return result;
@ -582,14 +585,14 @@ static int iwl_mvm_mld_alloc_sta_links(struct iwl_mvm *mvm,
struct ieee80211_sta *sta)
{
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
struct ieee80211_link_sta *link_sta;
unsigned int link_id;
int ret;
lockdep_assert_held(&mvm->mutex);
for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) {
if (!rcu_access_pointer(sta->link[link_id]) ||
mvm_sta->link[link_id])
for_each_sta_active_link(vif, sta, link_sta, link_id) {
if (WARN_ON(mvm_sta->link[link_id]))
continue;
ret = iwl_mvm_mld_alloc_sta_link(mvm, vif, sta, link_id);
@ -616,9 +619,6 @@ static void iwl_mvm_mld_set_ap_sta_id(struct ieee80211_sta *sta,
}
}
/* FIXME: consider waiting for mac80211 to add the STA instead of allocating
* queues here
*/
static int iwl_mvm_alloc_sta_after_restart(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
@ -989,6 +989,10 @@ static int iwl_mvm_mld_update_sta_baids(struct iwl_mvm *mvm,
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD);
int baid;
/* mac80211 will remove sessions later, but we ignore all that */
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
return 0;
BUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid));
for (baid = 0; baid < ARRAY_SIZE(mvm->baid_map); baid++) {
@ -1122,10 +1126,21 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
}
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
if (WARN_ON(!mvm_sta->link[link_id])) {
struct iwl_mvm_link_sta *mvm_link_sta =
rcu_dereference_protected(mvm_sta->link[link_id],
lockdep_is_held(&mvm->mutex));
u32 sta_id;
if (WARN_ON(!mvm_link_sta)) {
ret = -EINVAL;
goto err;
}
sta_id = mvm_link_sta->sta_id;
rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], sta);
rcu_assign_pointer(mvm->fw_id_to_link_sta[sta_id],
link_sta);
} else {
if (WARN_ON(mvm_sta->link[link_id])) {
ret = -EINVAL;

View File

@ -255,18 +255,14 @@ enum iwl_mvm_low_latency_cause {
};
/**
* struct iwl_mvm_vif_bf_data - beacon filtering related data
* @bf_enabled: indicates if beacon filtering is enabled
* @ba_enabled: indicated if beacon abort is enabled
* struct iwl_mvm_link_bf_data - beacon filtering related data
* @ave_beacon_signal: average beacon signal
* @last_cqm_event: rssi of the last cqm event
* @bt_coex_min_thold: minimum threshold for BT coex
* @bt_coex_max_thold: maximum threshold for BT coex
* @last_bt_coex_event: rssi of the last BT coex event
*/
struct iwl_mvm_vif_bf_data {
bool bf_enabled;
bool ba_enabled;
struct iwl_mvm_link_bf_data {
int ave_beacon_signal;
int last_cqm_event;
int bt_coex_min_thold;
@ -309,6 +305,7 @@ struct iwl_probe_resp_data {
* @listen_lmac: indicates this link is allocated to the listen LMAC
* @mcast_sta: multicast station
* @phy_ctxt: phy context allocated to this link, if any
* @bf_data: beacon filtering data
*/
struct iwl_mvm_vif_link_info {
u8 bssid[ETH_ALEN];
@ -344,6 +341,8 @@ struct iwl_mvm_vif_link_info {
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
u16 mgmt_queue;
struct iwl_mvm_link_bf_data bf_data;
};
/**
@ -371,10 +370,12 @@ struct iwl_mvm_vif_link_info {
* @csa_countdown: indicates that CSA countdown may be started
* @csa_failed: CSA failed to schedule time event, report an error later
* @csa_bcn_pending: indicates that we are waiting for a beacon on a new channel
* @csa_blocks_tx: CSA is blocking TX
* @features: hw features active for this vif
* @ap_beacon_time: AP beacon time for synchronisation (on older FW)
* @bf_enabled: indicates if beacon filtering is enabled
* @ba_enabled: indicated if beacon abort is enabled
* @bcn_prot: beacon protection data (keys; FIXME: needs to be per link)
* @bf_data: beacon filtering data
* @deflink: default link data for use in non-MLO
* @link: link data for each link in MLO
* @esr_active: indicates eSR mode is active
@ -401,7 +402,8 @@ struct iwl_mvm_vif {
bool ps_disabled;
u32 ap_beacon_time;
struct iwl_mvm_vif_bf_data bf_data;
bool bf_enabled;
bool ba_enabled;
#ifdef CONFIG_PM
/* WoWLAN GTK rekey data */
@ -435,6 +437,7 @@ struct iwl_mvm_vif {
struct iwl_dbgfs_bf dbgfs_bf;
struct iwl_mac_power_cmd mac_pwr_cmd;
int dbgfs_quota_min;
bool ftm_unprotected;
#endif
/* FW identified misbehaving AP */
@ -444,6 +447,7 @@ struct iwl_mvm_vif {
bool csa_countdown;
bool csa_failed;
bool csa_bcn_pending;
bool csa_blocks_tx;
u16 csa_target_freq;
u16 csa_count;
u16 csa_misbehave;
@ -490,10 +494,12 @@ enum iwl_scan_status {
IWL_MVM_SCAN_REGULAR = BIT(0),
IWL_MVM_SCAN_SCHED = BIT(1),
IWL_MVM_SCAN_NETDETECT = BIT(2),
IWL_MVM_SCAN_INT_MLO = BIT(3),
IWL_MVM_SCAN_STOPPING_REGULAR = BIT(8),
IWL_MVM_SCAN_STOPPING_SCHED = BIT(9),
IWL_MVM_SCAN_STOPPING_NETDETECT = BIT(10),
IWL_MVM_SCAN_STOPPING_INT_MLO = BIT(11),
IWL_MVM_SCAN_REGULAR_MASK = IWL_MVM_SCAN_REGULAR |
IWL_MVM_SCAN_STOPPING_REGULAR,
@ -501,6 +507,8 @@ enum iwl_scan_status {
IWL_MVM_SCAN_STOPPING_SCHED,
IWL_MVM_SCAN_NETDETECT_MASK = IWL_MVM_SCAN_NETDETECT |
IWL_MVM_SCAN_STOPPING_NETDETECT,
IWL_MVM_SCAN_INT_MLO_MASK = IWL_MVM_SCAN_INT_MLO |
IWL_MVM_SCAN_STOPPING_INT_MLO,
IWL_MVM_SCAN_STOPPING_MASK = 0xff << IWL_MVM_SCAN_STOPPING_SHIFT,
IWL_MVM_SCAN_MASK = 0xff,
@ -754,9 +762,10 @@ struct iwl_mvm_txq {
struct list_head list;
u16 txq_id;
atomic_t tx_request;
#define IWL_MVM_TXQ_STATE_STOP_FULL 0
#define IWL_MVM_TXQ_STATE_STOP_REDIRECT 1
#define IWL_MVM_TXQ_STATE_READY 2
#define IWL_MVM_TXQ_STATE_READY 0
#define IWL_MVM_TXQ_STATE_STOP_FULL 1
#define IWL_MVM_TXQ_STATE_STOP_REDIRECT 2
#define IWL_MVM_TXQ_STATE_STOP_AP_CSA 3
unsigned long state;
};
@ -2005,6 +2014,10 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_scan_ies *ies);
size_t iwl_mvm_scan_size(struct iwl_mvm *mvm);
int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify);
int iwl_mvm_int_mlo_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_channel **channels,
size_t n_channels);
int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm);
void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm);
void iwl_mvm_scan_timeout_wk(struct work_struct *work);
@ -2113,7 +2126,8 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool disable_offloading,
bool offload_ns,
u32 cmd_flags);
u32 cmd_flags,
u8 sta_id);
/* BT Coex */
int iwl_mvm_send_bt_init_conf(struct iwl_mvm *mvm);

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2012-2014, 2021-2022 Intel Corporation
* Copyright (C) 2012-2014, 2021-2022, 2024 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 Intel Deutschland GmbH
*/
@ -30,7 +30,8 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool disable_offloading,
bool offload_ns,
u32 cmd_flags)
u32 cmd_flags,
u8 sta_id)
{
union {
struct iwl_proto_offload_cmd_v1 v1;
@ -205,6 +206,9 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
if (!disable_offloading)
common->enabled = cpu_to_le32(enabled);
if (ver >= 4)
cmd.v4.sta_id = cpu_to_le32(sta_id);
hcmd.len[0] = size;
return iwl_mvm_send_cmd(mvm, &hcmd);
}

View File

@ -79,7 +79,7 @@ void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm,
cmd->bf_roaming_state =
cpu_to_le32(-vif->bss_conf.cqm_rssi_thold);
}
cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->bf_data.ba_enabled);
cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->ba_enabled);
}
static void iwl_mvm_power_log(struct iwl_mvm *mvm,
@ -826,7 +826,7 @@ static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd);
if (!ret)
mvmvif->bf_data.bf_enabled = true;
mvmvif->bf_enabled = true;
return ret;
}
@ -855,7 +855,7 @@ static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
if (!ret)
mvmvif->bf_data.bf_enabled = false;
mvmvif->bf_enabled = false;
return ret;
}
@ -903,16 +903,16 @@ static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm,
.bf_enable_beacon_filter = cpu_to_le32(1),
};
if (!mvmvif->bf_data.bf_enabled)
if (!mvmvif->bf_enabled)
return 0;
if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
mvmvif->bf_data.ba_enabled = !(!mvmvif->pm_enabled ||
mvm->ps_disabled ||
!vif->cfg.ps ||
iwl_mvm_vif_low_latency(mvmvif));
mvmvif->ba_enabled = !(!mvmvif->pm_enabled ||
mvm->ps_disabled ||
!vif->cfg.ps ||
iwl_mvm_vif_low_latency(mvmvif));
return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd);
}

View File

@ -556,12 +556,15 @@ struct iwl_mvm_stat_data_all_macs {
struct iwl_stats_ntfy_per_mac *per_mac;
};
static void iwl_mvm_update_vif_sig(struct ieee80211_vif *vif, int sig)
static void iwl_mvm_update_vif_sig(struct ieee80211_vif *vif, int sig,
struct iwl_mvm_vif_link_info *link_info)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm;
int thold = vif->bss_conf.cqm_rssi_thold;
int hyst = vif->bss_conf.cqm_rssi_hyst;
struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(vif)->mvm;
struct ieee80211_bss_conf *bss_conf =
iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, link_info->fw_link_id,
false);
int thold = bss_conf->cqm_rssi_thold;
int hyst = bss_conf->cqm_rssi_hyst;
int last_event;
if (sig == 0) {
@ -569,23 +572,23 @@ static void iwl_mvm_update_vif_sig(struct ieee80211_vif *vif, int sig)
return;
}
mvmvif->bf_data.ave_beacon_signal = sig;
link_info->bf_data.ave_beacon_signal = sig;
/* BT Coex */
if (mvmvif->bf_data.bt_coex_min_thold !=
mvmvif->bf_data.bt_coex_max_thold) {
last_event = mvmvif->bf_data.last_bt_coex_event;
if (sig > mvmvif->bf_data.bt_coex_max_thold &&
(last_event <= mvmvif->bf_data.bt_coex_min_thold ||
if (link_info->bf_data.bt_coex_min_thold !=
link_info->bf_data.bt_coex_max_thold) {
last_event = link_info->bf_data.last_bt_coex_event;
if (sig > link_info->bf_data.bt_coex_max_thold &&
(last_event <= link_info->bf_data.bt_coex_min_thold ||
last_event == 0)) {
mvmvif->bf_data.last_bt_coex_event = sig;
link_info->bf_data.last_bt_coex_event = sig;
IWL_DEBUG_RX(mvm, "cqm_iterator bt coex high %d\n",
sig);
iwl_mvm_bt_rssi_event(mvm, vif, RSSI_EVENT_HIGH);
} else if (sig < mvmvif->bf_data.bt_coex_min_thold &&
(last_event >= mvmvif->bf_data.bt_coex_max_thold ||
} else if (sig < link_info->bf_data.bt_coex_min_thold &&
(last_event >= link_info->bf_data.bt_coex_max_thold ||
last_event == 0)) {
mvmvif->bf_data.last_bt_coex_event = sig;
link_info->bf_data.last_bt_coex_event = sig;
IWL_DEBUG_RX(mvm, "cqm_iterator bt coex low %d\n",
sig);
iwl_mvm_bt_rssi_event(mvm, vif, RSSI_EVENT_LOW);
@ -596,10 +599,10 @@ static void iwl_mvm_update_vif_sig(struct ieee80211_vif *vif, int sig)
return;
/* CQM Notification */
last_event = mvmvif->bf_data.last_cqm_event;
last_event = link_info->bf_data.last_cqm_event;
if (thold && sig < thold && (last_event == 0 ||
sig < last_event - hyst)) {
mvmvif->bf_data.last_cqm_event = sig;
link_info->bf_data.last_cqm_event = sig;
IWL_DEBUG_RX(mvm, "cqm_iterator cqm low %d\n",
sig);
ieee80211_cqm_rssi_notify(
@ -609,7 +612,7 @@ static void iwl_mvm_update_vif_sig(struct ieee80211_vif *vif, int sig)
GFP_KERNEL);
} else if (sig > thold &&
(last_event == 0 || sig > last_event + hyst)) {
mvmvif->bf_data.last_cqm_event = sig;
link_info->bf_data.last_cqm_event = sig;
IWL_DEBUG_RX(mvm, "cqm_iterator cqm high %d\n",
sig);
ieee80211_cqm_rssi_notify(
@ -651,7 +654,8 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
mvmvif->deflink.beacon_stats.accu_num_beacons +=
mvmvif->deflink.beacon_stats.num_beacons;
iwl_mvm_update_vif_sig(vif, sig);
/* This is used in pre-MLO API so use deflink */
iwl_mvm_update_vif_sig(vif, sig, &mvmvif->deflink);
}
static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,
@ -684,7 +688,9 @@ static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,
mvmvif->deflink.beacon_stats.num_beacons;
sig = -le32_to_cpu(mac_stats->beacon_filter_average_energy);
iwl_mvm_update_vif_sig(vif, sig);
/* This is used in pre-MLO API so use deflink */
iwl_mvm_update_vif_sig(vif, sig, &mvmvif->deflink);
}
static inline void
@ -900,7 +906,7 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,
mvmvif->link[link_id]->beacon_stats.num_beacons;
sig = -le32_to_cpu(link_stats->beacon_filter_average_energy);
iwl_mvm_update_vif_sig(bss_conf->vif, sig);
iwl_mvm_update_vif_sig(bss_conf->vif, sig, link_info);
if (WARN_ONCE(mvmvif->id >= MAC_INDEX_AUX,
"invalid mvmvif id: %d", mvmvif->id))

View File

@ -1377,11 +1377,14 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_2);
}
static u32 iwl_mvm_scan_umac_ooc_priority(struct iwl_mvm_scan_params *params)
static u32 iwl_mvm_scan_umac_ooc_priority(int type)
{
return iwl_mvm_is_regular_scan(params) ?
IWL_SCAN_PRIORITY_EXT_6 :
IWL_SCAN_PRIORITY_EXT_2;
if (type == IWL_MVM_SCAN_REGULAR)
return IWL_SCAN_PRIORITY_EXT_6;
if (type == IWL_MVM_SCAN_INT_MLO)
return IWL_SCAN_PRIORITY_EXT_4;
return IWL_SCAN_PRIORITY_EXT_2;
}
static void
@ -1747,8 +1750,9 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm,
&cp->channel_config[ch_cnt];
u32 s_ssid_bitmap = 0, bssid_bitmap = 0, flags = 0;
u8 j, k, s_max = 0, b_max = 0, n_used_bssid_entries;
bool force_passive, found = false, allow_passive = true,
u8 j, k, n_s_ssids = 0, n_bssids = 0;
u8 max_s_ssids, max_bssids;
bool force_passive = false, found = false, allow_passive = true,
unsolicited_probe_on_chan = false, psc_no_listen = false;
s8 psd_20 = IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED;
@ -1771,20 +1775,15 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm,
cfg->v5.iter_count = 1;
cfg->v5.iter_interval = 0;
/*
* The optimize the scan time, i.e., reduce the scan dwell time
* on each channel, the below logic tries to set 3 direct BSSID
* probe requests for each broadcast probe request with a short
* SSID.
* TODO: improve this logic
*/
n_used_bssid_entries = 3;
for (j = 0; j < params->n_6ghz_params; j++) {
s8 tmp_psd_20;
if (!(scan_6ghz_params[j].channel_idx == i))
continue;
unsolicited_probe_on_chan |=
scan_6ghz_params[j].unsolicited_probe;
/* Use the highest PSD value allowed as advertised by
* APs for this channel
*/
@ -1796,68 +1795,9 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm,
psd_20 < tmp_psd_20))
psd_20 = tmp_psd_20;
found = false;
unsolicited_probe_on_chan |=
scan_6ghz_params[j].unsolicited_probe;
psc_no_listen |= scan_6ghz_params[j].psc_no_listen;
for (k = 0; k < pp->short_ssid_num; k++) {
if (!scan_6ghz_params[j].unsolicited_probe &&
le32_to_cpu(pp->short_ssid[k]) ==
scan_6ghz_params[j].short_ssid) {
/* Relevant short SSID bit set */
if (s_ssid_bitmap & BIT(k)) {
found = true;
break;
}
/*
* Use short SSID only to create a new
* iteration during channel dwell or in
* case that the short SSID has a
* matching SSID, i.e., scan for hidden
* APs.
*/
if (n_used_bssid_entries >= 3) {
s_ssid_bitmap |= BIT(k);
s_max++;
n_used_bssid_entries -= 3;
found = true;
break;
} else if (pp->direct_scan[k].len) {
s_ssid_bitmap |= BIT(k);
s_max++;
found = true;
allow_passive = false;
break;
}
}
}
if (found)
continue;
for (k = 0; k < pp->bssid_num; k++) {
if (!memcmp(&pp->bssid_array[k],
scan_6ghz_params[j].bssid,
ETH_ALEN)) {
if (!(bssid_bitmap & BIT(k))) {
bssid_bitmap |= BIT(k);
b_max++;
n_used_bssid_entries++;
}
break;
}
}
}
if (cfg80211_channel_is_psc(params->channels[i]) &&
psc_no_listen)
flags |= IWL_UHB_CHAN_CFG_FLAG_PSC_CHAN_NO_LISTEN;
if (unsolicited_probe_on_chan)
flags |= IWL_UHB_CHAN_CFG_FLAG_UNSOLICITED_PROBE_RES;
/*
* In the following cases apply passive scan:
* 1. Non fragmented scan:
@ -1878,19 +1818,105 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm,
if (!iwl_mvm_is_scan_fragmented(params->type)) {
if (!cfg80211_channel_is_psc(params->channels[i]) ||
flags & IWL_UHB_CHAN_CFG_FLAG_PSC_CHAN_NO_LISTEN) {
force_passive = (s_max > 3 || b_max > 9);
force_passive |= (unsolicited_probe_on_chan &&
(s_max > 2 || b_max > 6));
if (unsolicited_probe_on_chan) {
max_s_ssids = 2;
max_bssids = 6;
} else {
max_s_ssids = 3;
max_bssids = 9;
}
} else {
force_passive = (s_max > 2 || b_max > 6);
max_s_ssids = 2;
max_bssids = 6;
}
} else if (cfg80211_channel_is_psc(params->channels[i])) {
force_passive = (s_max > 1 || b_max > 3);
max_s_ssids = 1;
max_bssids = 3;
} else {
force_passive = (s_max > 2 || b_max > 6);
force_passive |= (unsolicited_probe_on_chan &&
(s_max > 1 || b_max > 3));
if (unsolicited_probe_on_chan) {
max_s_ssids = 1;
max_bssids = 3;
} else {
max_s_ssids = 2;
max_bssids = 6;
}
}
/*
* The optimize the scan time, i.e., reduce the scan dwell time
* on each channel, the below logic tries to set 3 direct BSSID
* probe requests for each broadcast probe request with a short
* SSID.
* TODO: improve this logic
*/
for (j = 0; j < params->n_6ghz_params; j++) {
if (!(scan_6ghz_params[j].channel_idx == i))
continue;
found = false;
for (k = 0;
k < pp->short_ssid_num && n_s_ssids < max_s_ssids;
k++) {
if (!scan_6ghz_params[j].unsolicited_probe &&
le32_to_cpu(pp->short_ssid[k]) ==
scan_6ghz_params[j].short_ssid) {
/* Relevant short SSID bit set */
if (s_ssid_bitmap & BIT(k)) {
found = true;
break;
}
/*
* Prefer creating BSSID entries unless
* the short SSID probe can be done in
* the same channel dwell iteration.
*
* We also need to create a short SSID
* entry for any hidden AP.
*/
if (3 * n_s_ssids > n_bssids &&
!pp->direct_scan[k].len)
break;
/* Hidden AP, cannot do passive scan */
if (pp->direct_scan[k].len)
allow_passive = false;
s_ssid_bitmap |= BIT(k);
n_s_ssids++;
found = true;
break;
}
}
if (found)
continue;
for (k = 0; k < pp->bssid_num; k++) {
if (!memcmp(&pp->bssid_array[k],
scan_6ghz_params[j].bssid,
ETH_ALEN)) {
if (!(bssid_bitmap & BIT(k))) {
if (n_bssids < max_bssids) {
bssid_bitmap |= BIT(k);
n_bssids++;
} else {
force_passive = TRUE;
}
}
break;
}
}
}
if (cfg80211_channel_is_psc(params->channels[i]) &&
psc_no_listen)
flags |= IWL_UHB_CHAN_CFG_FLAG_PSC_CHAN_NO_LISTEN;
if (unsolicited_probe_on_chan)
flags |= IWL_UHB_CHAN_CFG_FLAG_UNSOLICITED_PROBE_RES;
if ((allow_passive && force_passive) ||
(!(bssid_bitmap | s_ssid_bitmap) &&
!cfg80211_channel_is_psc(params->channels[i])))
@ -2452,7 +2478,7 @@ static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvm->scan_uid_status[uid] = type;
cmd->ooc_priority = cpu_to_le32(iwl_mvm_scan_umac_ooc_priority(params));
cmd->ooc_priority = cpu_to_le32(iwl_mvm_scan_umac_ooc_priority(type));
cmd->uid = cpu_to_le32(uid);
gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);
@ -2489,7 +2515,7 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,
mvm->scan_uid_status[uid] = type;
cmd->ooc_priority = cpu_to_le32(iwl_mvm_scan_umac_ooc_priority(params));
cmd->ooc_priority = cpu_to_le32(iwl_mvm_scan_umac_ooc_priority(type));
cmd->uid = cpu_to_le32(uid);
gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);
@ -2914,9 +2940,11 @@ static void iwl_mvm_fill_respect_p2p_go(struct iwl_mvm *mvm,
}
}
int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct cfg80211_scan_request *req,
struct ieee80211_scan_ies *ies)
static int _iwl_mvm_single_scan_start(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_scan_request *req,
struct ieee80211_scan_ies *ies,
int type)
{
struct iwl_host_cmd hcmd = {
.len = { iwl_mvm_scan_size(mvm), },
@ -2934,7 +2962,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return -EBUSY;
}
ret = iwl_mvm_check_running_scans(mvm, IWL_MVM_SCAN_REGULAR);
ret = iwl_mvm_check_running_scans(mvm, type);
if (ret)
return ret;
@ -2983,8 +3011,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_scan_6ghz_passive_scan(mvm, &params, vif);
uid = iwl_mvm_build_scan_cmd(mvm, vif, &hcmd, &params,
IWL_MVM_SCAN_REGULAR);
uid = iwl_mvm_build_scan_cmd(mvm, vif, &hcmd, &params, type);
if (uid < 0)
return uid;
@ -3004,18 +3031,28 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
}
IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
mvm->scan_status |= type;
if (type == IWL_MVM_SCAN_REGULAR) {
mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
schedule_delayed_work(&mvm->scan_timeout_dwork,
msecs_to_jiffies(SCAN_TIMEOUT));
}
if (params.enable_6ghz_passive)
mvm->last_6ghz_passive_scan_jiffies = jiffies;
schedule_delayed_work(&mvm->scan_timeout_dwork,
msecs_to_jiffies(SCAN_TIMEOUT));
return 0;
}
int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct cfg80211_scan_request *req,
struct ieee80211_scan_ies *ies)
{
return _iwl_mvm_single_scan_start(mvm, vif, req, ies,
IWL_MVM_SCAN_REGULAR);
}
int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
@ -3170,8 +3207,13 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
struct iwl_mvm_vif_link_info *link_info =
scan_vif->link[mvm->scan_link_id];
if (!WARN_ON(!link_info))
/* It is possible that by the time the scan is complete the link
* was already removed and is not valid.
*/
if (link_info)
memcpy(info.tsf_bssid, link_info->bssid, ETH_ALEN);
else
IWL_DEBUG_SCAN(mvm, "Scan link is no longer valid\n");
ieee80211_scan_completed(mvm->hw, &info);
mvm->scan_vif = NULL;
@ -3180,6 +3222,8 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
} else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
ieee80211_sched_scan_stopped(mvm->hw);
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
} else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_INT_MLO) {
IWL_DEBUG_SCAN(mvm, "Internal MLO scan completed\n");
}
mvm->scan_status &= ~mvm->scan_uid_status[uid];
@ -3366,6 +3410,12 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
mvm->scan_uid_status[uid] = 0;
}
uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_INT_MLO);
if (uid >= 0) {
IWL_DEBUG_SCAN(mvm, "Internal MLO scan aborted\n");
mvm->scan_uid_status[uid] = 0;
}
uid = iwl_mvm_scan_uid_by_status(mvm,
IWL_MVM_SCAN_STOPPING_REGULAR);
if (uid >= 0)
@ -3376,6 +3426,11 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
if (uid >= 0)
mvm->scan_uid_status[uid] = 0;
uid = iwl_mvm_scan_uid_by_status(mvm,
IWL_MVM_SCAN_STOPPING_INT_MLO);
if (uid >= 0)
mvm->scan_uid_status[uid] = 0;
/* We shouldn't have any UIDs still set. Loop over all the
* UIDs to make sure there's nothing left there and warn if
* any is found.
@ -3447,3 +3502,50 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify)
return ret;
}
int iwl_mvm_int_mlo_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_channel **channels,
size_t n_channels)
{
struct cfg80211_scan_request *req = NULL;
struct ieee80211_scan_ies ies = {};
size_t size, i;
int ret;
lockdep_assert_held(&mvm->mutex);
IWL_DEBUG_SCAN(mvm, "Starting Internal MLO scan: n_channels=%zu\n",
n_channels);
if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
return -EINVAL;
size = struct_size(req, channels, n_channels);
req = kzalloc(size, GFP_KERNEL);
if (!req)
return -ENOMEM;
/* set the requested channels */
for (i = 0; i < n_channels; i++)
req->channels[i] = channels[i];
req->n_channels = n_channels;
/* set the rates */
for (i = 0; i < NUM_NL80211_BANDS; i++)
if (mvm->hw->wiphy->bands[i])
req->rates[i] =
(1 << mvm->hw->wiphy->bands[i]->n_bitrates) - 1;
req->wdev = ieee80211_vif_to_wdev(vif);
req->wiphy = mvm->hw->wiphy;
req->scan_start = jiffies;
req->tsf_report_link_id = -1;
ret = _iwl_mvm_single_scan_start(mvm, vif, req, &ies,
IWL_MVM_SCAN_INT_MLO);
kfree(req);
IWL_DEBUG_SCAN(mvm, "Internal MLO scan: ret=%d\n", ret);
return ret;
}

View File

@ -33,7 +33,7 @@ extern int _invalid_type;
.driver_data = _ASSIGN_CFG(cfg)
/* Hardware specific file defines the PCI IDs table for that hardware module */
static const struct pci_device_id iwl_hw_card_ids[] = {
VISIBLE_IF_IWLWIFI_KUNIT const struct pci_device_id iwl_hw_card_ids[] = {
#if IS_ENABLED(CONFIG_IWLDVM)
{IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
{IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
@ -492,7 +492,6 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x7AF0, PCI_ANY_ID, iwl_so_trans_cfg)},
{IWL_PCI_DEVICE(0x51F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},
{IWL_PCI_DEVICE(0x51F1, PCI_ANY_ID, iwl_so_long_latency_imr_trans_cfg)},
{IWL_PCI_DEVICE(0x51F1, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},
{IWL_PCI_DEVICE(0x54F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},
{IWL_PCI_DEVICE(0x7F70, PCI_ANY_ID, iwl_so_trans_cfg)},
@ -517,6 +516,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{0}
};
MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_hw_card_ids);
#define _IWL_DEV_INFO(_device, _subdevice, _mac_type, _mac_step, _rf_type, \
_rf_id, _rf_step, _no_160, _cores, _cdb, _cfg, _name) \
@ -944,11 +944,6 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
iwl_cfg_ma, iwl_ax211_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_ma, iwl_ax221_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
@ -1002,18 +997,25 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),
/* Bz */
/* FIXME: need to change the naming according to the actual CRF */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
iwl_cfg_bz, iwl_bz_name),
iwl_cfg_bz, iwl_fm_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ_W, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
iwl_cfg_bz, iwl_fm_name),
/* Ga (Gl) */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_320, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_gl, iwl_bz_name),
iwl_cfg_gl, iwl_gl_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
@ -1100,24 +1102,6 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
/* MsP */
/* For now we use the same FW as MR, but this will change in the future. */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_ms_a0, iwl_ax204_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_ms_a0, iwl_ax204_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_ma, iwl_ax204_name),
/* Sc */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SC, IWL_CFG_ANY,
@ -1150,6 +1134,7 @@ static void get_crf_id(struct iwl_trans *iwl_trans)
{
u32 sd_reg_ver_addr;
u32 val = 0;
u8 step;
if (iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
sd_reg_ver_addr = SD_REG_VER_GEN2;
@ -1168,16 +1153,23 @@ static void get_crf_id(struct iwl_trans *iwl_trans)
iwl_trans->hw_cnv_id =
iwl_read_prph_no_grab(iwl_trans, CNVI_AUX_MISC_CHIP);
/* For BZ-W, take B step also when A step is indicated */
if (CSR_HW_REV_TYPE(iwl_trans->hw_rev) == IWL_CFG_MAC_TYPE_BZ_W)
step = SILICON_B_STEP;
/* In BZ, the MAC step must be read from the CNVI aux register */
if (CSR_HW_REV_TYPE(iwl_trans->hw_rev) == IWL_CFG_MAC_TYPE_BZ) {
u8 step = CNVI_AUX_MISC_CHIP_MAC_STEP(iwl_trans->hw_cnv_id);
step = CNVI_AUX_MISC_CHIP_MAC_STEP(iwl_trans->hw_cnv_id);
/* For BZ-U, take B step also when A step is indicated */
if ((CNVI_AUX_MISC_CHIP_PROD_TYPE(iwl_trans->hw_cnv_id) ==
CNVI_AUX_MISC_CHIP_PROD_TYPE_BZ_U) &&
step == SILICON_A_STEP)
step = SILICON_B_STEP;
}
if (CSR_HW_REV_TYPE(iwl_trans->hw_rev) == IWL_CFG_MAC_TYPE_BZ ||
CSR_HW_REV_TYPE(iwl_trans->hw_rev) == IWL_CFG_MAC_TYPE_BZ_W) {
iwl_trans->hw_rev_step = step;
iwl_trans->hw_rev |= step;
}
@ -1224,12 +1216,7 @@ static int map_crf_id(struct iwl_trans *iwl_trans)
case REG_CRF_ID_TYPE_GF:
iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_GF << 12);
break;
case REG_CRF_ID_TYPE_MR:
iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_MR << 12);
break;
case REG_CRF_ID_TYPE_FM:
case REG_CRF_ID_TYPE_FMI:
case REG_CRF_ID_TYPE_FMR:
iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_FM << 12);
break;
case REG_CRF_ID_TYPE_WHP:

View File

@ -2,9 +2,10 @@
/*
* KUnit tests for the iwlwifi device info table
*
* Copyright (C) 2023 Intel Corporation
* Copyright (C) 2023-2024 Intel Corporation
*/
#include <kunit/test.h>
#include <linux/pci.h>
#include "iwl-drv.h"
#include "iwl-config.h"
@ -41,8 +42,31 @@ static void devinfo_table_order(struct kunit *test)
}
}
static void devinfo_pci_ids(struct kunit *test)
{
struct pci_dev *dev;
dev = kunit_kmalloc(test, sizeof(*dev), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, dev);
for (int i = 0; iwl_hw_card_ids[i].vendor; i++) {
const struct pci_device_id *s, *t;
s = &iwl_hw_card_ids[i];
dev->vendor = s->vendor;
dev->device = s->device;
dev->subsystem_vendor = s->subvendor;
dev->subsystem_device = s->subdevice;
dev->class = s->class;
t = pci_match_id(iwl_hw_card_ids, dev);
KUNIT_EXPECT_PTR_EQ(test, t, s);
}
}
static struct kunit_case devinfo_test_cases[] = {
KUNIT_CASE(devinfo_table_order),
KUNIT_CASE(devinfo_pci_ids),
{}
};

View File

@ -3192,6 +3192,7 @@ MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE(SD8786_DEFAULT_FW_NAME);
MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME);
MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME);
MODULE_FIRMWARE(SD8801_DEFAULT_FW_NAME);
MODULE_FIRMWARE(SD8897_DEFAULT_FW_NAME);
MODULE_FIRMWARE(SD8887_DEFAULT_FW_NAME);
MODULE_FIRMWARE(SD8977_DEFAULT_FW_NAME);

View File

@ -587,12 +587,14 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv, char *fw_image,
}
struct mwl8k_cmd_pkt {
__le16 code;
__le16 length;
__u8 seq_num;
__u8 macid;
__le16 result;
char payload[];
__struct_group(mwl8k_cmd_pkt_hdr, hdr, __packed,
__le16 code;
__le16 length;
__u8 seq_num;
__u8 macid;
__le16 result;
);
char payload[];
} __packed;
/*
@ -2201,7 +2203,7 @@ static void mwl8k_enable_bsses(struct ieee80211_hw *hw, bool enable,
/* Timeout firmware commands after 10s */
#define MWL8K_CMD_TIMEOUT_MS 10000
static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt_hdr *cmd)
{
DECLARE_COMPLETION_ONSTACK(cmd_wait);
struct mwl8k_priv *priv = hw->priv;
@ -2298,7 +2300,7 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
static int mwl8k_post_pervif_cmd(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct mwl8k_cmd_pkt *cmd)
struct mwl8k_cmd_pkt_hdr *cmd)
{
if (vif != NULL)
cmd->macid = MWL8K_VIF(vif)->macid;
@ -2350,7 +2352,7 @@ static void mwl8k_setup_5ghz_band(struct ieee80211_hw *hw)
* CMD_GET_HW_SPEC (STA version).
*/
struct mwl8k_cmd_get_hw_spec_sta {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__u8 hw_rev;
__u8 host_interface;
__le16 num_mcaddrs;
@ -2499,7 +2501,7 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw)
* CMD_GET_HW_SPEC (AP version).
*/
struct mwl8k_cmd_get_hw_spec_ap {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__u8 hw_rev;
__u8 host_interface;
__le16 num_wcb;
@ -2593,7 +2595,7 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw)
* CMD_SET_HW_SPEC.
*/
struct mwl8k_cmd_set_hw_spec {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__u8 hw_rev;
__u8 host_interface;
__le16 num_mcaddrs;
@ -2670,7 +2672,7 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw)
* CMD_MAC_MULTICAST_ADR.
*/
struct mwl8k_cmd_mac_multicast_adr {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 action;
__le16 numaddr;
__u8 addr[][ETH_ALEN];
@ -2681,7 +2683,7 @@ struct mwl8k_cmd_mac_multicast_adr {
#define MWL8K_ENABLE_RX_ALL_MULTICAST 0x0004
#define MWL8K_ENABLE_RX_BROADCAST 0x0008
static struct mwl8k_cmd_pkt *
static struct mwl8k_cmd_pkt_hdr *
__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti,
struct netdev_hw_addr_list *mc_list)
{
@ -2729,7 +2731,7 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti,
* CMD_GET_STAT.
*/
struct mwl8k_cmd_get_stat {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le32 stats[64];
} __packed;
@ -2771,7 +2773,7 @@ static int mwl8k_cmd_get_stat(struct ieee80211_hw *hw,
* CMD_RADIO_CONTROL.
*/
struct mwl8k_cmd_radio_control {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 action;
__le16 control;
__le16 radio_on;
@ -2832,7 +2834,7 @@ mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble)
#define MWL8K_RF_TX_POWER_LEVEL_TOTAL 8
struct mwl8k_cmd_rf_tx_power {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 action;
__le16 support_level;
__le16 current_level;
@ -2866,7 +2868,7 @@ static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm)
#define MWL8K_TX_POWER_LEVEL_TOTAL 12
struct mwl8k_cmd_tx_power {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 action;
__le16 band;
__le16 channel;
@ -2925,7 +2927,7 @@ static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw,
* CMD_RF_ANTENNA.
*/
struct mwl8k_cmd_rf_antenna {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 antenna;
__le16 mode;
} __packed;
@ -2958,7 +2960,7 @@ mwl8k_cmd_rf_antenna(struct ieee80211_hw *hw, int antenna, int mask)
* CMD_SET_BEACON.
*/
struct mwl8k_cmd_set_beacon {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 beacon_len;
__u8 beacon[];
};
@ -2988,7 +2990,7 @@ static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw,
* CMD_SET_PRE_SCAN.
*/
struct mwl8k_cmd_set_pre_scan {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
} __packed;
static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw)
@ -3013,7 +3015,7 @@ static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw)
* CMD_BBP_REG_ACCESS.
*/
struct mwl8k_cmd_bbp_reg_access {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 action;
__le16 offset;
u8 value;
@ -3054,7 +3056,7 @@ mwl8k_cmd_bbp_reg_access(struct ieee80211_hw *hw,
* CMD_SET_POST_SCAN.
*/
struct mwl8k_cmd_set_post_scan {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le32 isibss;
__u8 bssid[ETH_ALEN];
} __packed;
@ -3142,7 +3144,7 @@ static void mwl8k_update_survey(struct mwl8k_priv *priv,
* CMD_SET_RF_CHANNEL.
*/
struct mwl8k_cmd_set_rf_channel {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 action;
__u8 current_channel;
__le32 channel_flags;
@ -3211,7 +3213,7 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw,
#define MWL8K_FRAME_PROT_11N_HT_ALL 0x06
struct mwl8k_cmd_update_set_aid {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 aid;
/* AP's MAC address (BSSID) */
@ -3283,7 +3285,7 @@ mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
* CMD_SET_RATE.
*/
struct mwl8k_cmd_set_rate {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__u8 legacy_rates[14];
/* Bitmap for supported MCS codes. */
@ -3319,7 +3321,7 @@ mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
#define MWL8K_FJ_BEACON_MAXLEN 128
struct mwl8k_cmd_finalize_join {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le32 sleep_interval; /* Number of beacon periods to sleep */
__u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN];
} __packed;
@ -3358,7 +3360,7 @@ static int mwl8k_cmd_finalize_join(struct ieee80211_hw *hw, void *frame,
* CMD_SET_RTS_THRESHOLD.
*/
struct mwl8k_cmd_set_rts_threshold {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 action;
__le16 threshold;
} __packed;
@ -3388,7 +3390,7 @@ mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, int rts_thresh)
* CMD_SET_SLOT.
*/
struct mwl8k_cmd_set_slot {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 action;
__u8 short_slot;
} __packed;
@ -3417,7 +3419,7 @@ static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time)
* CMD_SET_EDCA_PARAMS.
*/
struct mwl8k_cmd_set_edca_params {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
/* See MWL8K_SET_EDCA_XXX below */
__le16 action;
@ -3502,7 +3504,7 @@ mwl8k_cmd_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
* CMD_SET_WMM_MODE.
*/
struct mwl8k_cmd_set_wmm_mode {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 action;
} __packed;
@ -3533,7 +3535,7 @@ static int mwl8k_cmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable)
* CMD_MIMO_CONFIG.
*/
struct mwl8k_cmd_mimo_config {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le32 action;
__u8 rx_antenna_map;
__u8 tx_antenna_map;
@ -3564,7 +3566,7 @@ static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx)
* CMD_USE_FIXED_RATE (STA version).
*/
struct mwl8k_cmd_use_fixed_rate_sta {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le32 action;
__le32 allow_rate_drop;
__le32 num_rates;
@ -3606,7 +3608,7 @@ static int mwl8k_cmd_use_fixed_rate_sta(struct ieee80211_hw *hw)
* CMD_USE_FIXED_RATE (AP version).
*/
struct mwl8k_cmd_use_fixed_rate_ap {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le32 action;
__le32 allow_rate_drop;
__le32 num_rates;
@ -3647,7 +3649,7 @@ mwl8k_cmd_use_fixed_rate_ap(struct ieee80211_hw *hw, int mcast, int mgmt)
* CMD_ENABLE_SNIFFER.
*/
struct mwl8k_cmd_enable_sniffer {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le32 action;
} __packed;
@ -3671,7 +3673,7 @@ static int mwl8k_cmd_enable_sniffer(struct ieee80211_hw *hw, bool enable)
}
struct mwl8k_cmd_update_mac_addr {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
union {
struct {
__le16 mac_type;
@ -3756,7 +3758,7 @@ static inline int mwl8k_cmd_del_mac_addr(struct ieee80211_hw *hw,
* CMD_SET_RATEADAPT_MODE.
*/
struct mwl8k_cmd_set_rate_adapt_mode {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 action;
__le16 mode;
} __packed;
@ -3785,7 +3787,7 @@ static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode)
* CMD_GET_WATCHDOG_BITMAP.
*/
struct mwl8k_cmd_get_watchdog_bitmap {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
u8 bitmap;
} __packed;
@ -3865,7 +3867,7 @@ static void mwl8k_watchdog_ba_events(struct work_struct *work)
* CMD_BSS_START.
*/
struct mwl8k_cmd_bss_start {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le32 enable;
} __packed;
@ -3960,7 +3962,7 @@ struct mwl8k_destroy_ba_stream {
} __packed;
struct mwl8k_cmd_bastream {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le32 action;
union {
struct mwl8k_create_ba_stream create_params;
@ -4070,7 +4072,7 @@ static void mwl8k_destroy_ba(struct ieee80211_hw *hw,
* CMD_SET_NEW_STN.
*/
struct mwl8k_cmd_set_new_stn {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le16 aid;
__u8 mac_addr[6];
__le16 stn_id;
@ -4206,7 +4208,7 @@ static int mwl8k_cmd_set_new_stn_del(struct ieee80211_hw *hw,
#define MIC_KEY_LENGTH 8
struct mwl8k_cmd_update_encryption {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le32 action;
__le32 reserved;
@ -4216,7 +4218,7 @@ struct mwl8k_cmd_update_encryption {
} __packed;
struct mwl8k_cmd_set_key {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
__le32 action;
__le32 reserved;
@ -4504,7 +4506,7 @@ struct peer_capability_info {
} __packed;
struct mwl8k_cmd_update_stadb {
struct mwl8k_cmd_pkt header;
struct mwl8k_cmd_pkt_hdr header;
/* See STADB_ACTION_TYPE */
__le32 action;
@ -5174,7 +5176,7 @@ mwl8k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw,
struct netdev_hw_addr_list *mc_list)
{
struct mwl8k_cmd_pkt *cmd;
struct mwl8k_cmd_pkt_hdr *cmd;
/*
* Synthesize and return a command packet that programs the
@ -5234,7 +5236,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
u64 multicast)
{
struct mwl8k_priv *priv = hw->priv;
struct mwl8k_cmd_pkt *cmd = (void *)(unsigned long)multicast;
struct mwl8k_cmd_pkt_hdr *cmd = (void *)(unsigned long)multicast;
/*
* AP firmware doesn't allow fine-grained control over

View File

@ -523,7 +523,8 @@ mt7915_fw_debug_wm_set(void *data, u64 val)
/* WM CPU info record control */
mt76_clear(dev, MT_CPU_UTIL_CTRL, BIT(0));
mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw.debug_wm);
mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) |
(dev->fw.debug_wm ? 0 : BIT(0)));
mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR, BIT(5));
mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR, BIT(5));
@ -1049,6 +1050,7 @@ static ssize_t
mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
int i, ret, pwr, pwr160 = 0, pwr80 = 0, pwr40 = 0, pwr20 = 0;
struct mt7915_phy *phy = file->private_data;
struct mt7915_dev *dev = phy->dev;
struct mt76_phy *mphy = phy->mt76;
@ -1057,7 +1059,6 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
.band_idx = phy->mt76->band_idx,
};
char buf[100];
int i, ret, pwr160 = 0, pwr80 = 0, pwr40 = 0, pwr20 = 0;
enum mac80211_rx_encoding mode;
u32 offs = 0, len = 0;
@ -1130,8 +1131,8 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
if (ret)
goto out;
mphy->txpower_cur = max(mphy->txpower_cur,
max(pwr160, max(pwr80, max(pwr40, pwr20))));
pwr = max3(pwr80, pwr40, pwr20);
mphy->txpower_cur = max3(mphy->txpower_cur, pwr160, pwr);
out:
mutex_unlock(&dev->mt76.mutex);

View File

@ -59,7 +59,7 @@ struct qtnf_bus {
struct qtnf_qlink_transport trans;
struct qtnf_hw_info hw_info;
struct napi_struct mux_napi;
struct net_device mux_dev;
struct net_device *mux_dev;
struct workqueue_struct *workqueue;
struct workqueue_struct *hprio_workqueue;
struct work_struct fw_work;

View File

@ -372,7 +372,13 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto error;
}
init_dummy_netdev(&bus->mux_dev);
bus->mux_dev = alloc_netdev(0, "dummy", NET_NAME_UNKNOWN,
init_dummy_netdev);
if (!bus->mux_dev) {
ret = -ENOMEM;
goto error;
}
qtnf_pcie_init_irq(pcie_priv, use_msi);
pcie_priv->sysctl_bar = sysctl_bar;
pcie_priv->dmareg_bar = dmareg_bar;
@ -381,11 +387,13 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ret = pcie_priv->probe_cb(bus, tx_bd_size_param, rx_bd_size_param);
if (ret)
goto error;
goto error_free;
qtnf_pcie_bringup_fw_async(bus);
return 0;
error_free:
free_netdev(bus->mux_dev);
error:
destroy_workqueue(pcie_priv->workqueue);
pci_set_drvdata(pdev, NULL);
@ -417,6 +425,7 @@ static void qtnf_pcie_remove(struct pci_dev *dev)
netif_napi_del(&bus->mux_napi);
destroy_workqueue(priv->workqueue);
tasklet_kill(&priv->reclaim_tq);
free_netdev(bus->mux_dev);
qtnf_pcie_free_shm_ipc(priv);
qtnf_debugfs_remove(bus);

View File

@ -761,12 +761,12 @@ static int qtnf_pcie_pearl_rx_poll(struct napi_struct *napi, int budget)
napi_gro_receive(napi, skb);
} else {
pr_debug("drop untagged skb\n");
bus->mux_dev.stats.rx_dropped++;
bus->mux_dev->stats.rx_dropped++;
dev_kfree_skb_any(skb);
}
} else {
if (skb) {
bus->mux_dev.stats.rx_dropped++;
bus->mux_dev->stats.rx_dropped++;
dev_kfree_skb_any(skb);
}
}
@ -1146,7 +1146,7 @@ static int qtnf_pcie_pearl_probe(struct qtnf_bus *bus, unsigned int tx_bd_size,
}
tasklet_setup(&ps->base.reclaim_tq, qtnf_pearl_reclaim_tasklet_fn);
netif_napi_add_weight(&bus->mux_dev, &bus->mux_napi,
netif_napi_add_weight(bus->mux_dev, &bus->mux_napi,
qtnf_pcie_pearl_rx_poll, 10);
ipc_int.fn = qtnf_pcie_pearl_ipc_gen_ep_int;

View File

@ -667,12 +667,12 @@ static int qtnf_topaz_rx_poll(struct napi_struct *napi, int budget)
netif_receive_skb(skb);
} else {
pr_debug("drop untagged skb\n");
bus->mux_dev.stats.rx_dropped++;
bus->mux_dev->stats.rx_dropped++;
dev_kfree_skb_any(skb);
}
} else {
if (skb) {
bus->mux_dev.stats.rx_dropped++;
bus->mux_dev->stats.rx_dropped++;
dev_kfree_skb_any(skb);
}
}
@ -1159,7 +1159,7 @@ static int qtnf_pcie_topaz_probe(struct qtnf_bus *bus,
}
tasklet_setup(&ts->base.reclaim_tq, qtnf_reclaim_tasklet_fn);
netif_napi_add_weight(&bus->mux_dev, &bus->mux_napi,
netif_napi_add_weight(bus->mux_dev, &bus->mux_napi,
qtnf_topaz_rx_poll, 10);
ipc_int.fn = qtnf_topaz_ipc_gen_ep_int;

View File

@ -28,8 +28,16 @@ config RTW88_8822B
config RTW88_8822C
tristate
config RTW88_8723X
tristate
config RTW88_8703B
tristate
select RTW88_8723X
config RTW88_8723D
tristate
select RTW88_8723X
config RTW88_8821C
tristate
@ -122,6 +130,20 @@ config RTW88_8723DS
802.11n SDIO wireless network adapter
config RTW88_8723CS
tristate "Realtek 8723CS SDIO wireless network adapter"
depends on MMC
select RTW88_CORE
select RTW88_SDIO
select RTW88_8703B
help
Select this option to enable support for 8723CS chipset (EXPERIMENTAL)
This module adds support for the 8723CS 802.11n SDIO
wireless network adapter.
If you choose to build a module, it'll be called rtw88_8723cs.
config RTW88_8723DU
tristate "Realtek 8723DU USB wireless network adapter"
depends on USB

View File

@ -44,6 +44,15 @@ rtw88_8822cs-objs := rtw8822cs.o
obj-$(CONFIG_RTW88_8822CU) += rtw88_8822cu.o
rtw88_8822cu-objs := rtw8822cu.o
obj-$(CONFIG_RTW88_8723X) += rtw88_8723x.o
rtw88_8723x-objs := rtw8723x.o
obj-$(CONFIG_RTW88_8703B) += rtw88_8703b.o
rtw88_8703b-objs := rtw8703b.o rtw8703b_tables.o
obj-$(CONFIG_RTW88_8723CS) += rtw88_8723cs.o
rtw88_8723cs-objs := rtw8723cs.o
obj-$(CONFIG_RTW88_8723D) += rtw88_8723d.o
rtw88_8723d-objs := rtw8723d.o rtw8723d_table.o

View File

@ -943,6 +943,12 @@ static int __rtw_download_firmware_legacy(struct rtw_dev *rtwdev,
{
int ret = 0;
/* reset firmware if still present */
if (rtwdev->chip->id == RTW_CHIP_TYPE_8703B &&
rtw_read8_mask(rtwdev, REG_MCUFW_CTRL, BIT_RAM_DL_SEL)) {
rtw_write8(rtwdev, REG_MCUFW_CTRL, 0x00);
}
en_download_firmware_legacy(rtwdev, true);
ret = download_firmware_legacy(rtwdev, fw->firmware->data, fw->firmware->size);
en_download_firmware_legacy(rtwdev, false);

View File

@ -187,6 +187,7 @@ enum rtw_chip_type {
RTW_CHIP_TYPE_8822C,
RTW_CHIP_TYPE_8723D,
RTW_CHIP_TYPE_8821C,
RTW_CHIP_TYPE_8703B,
};
enum rtw_tx_queue_type {
@ -1700,11 +1701,13 @@ struct rtw_dm_info {
s8 delta_power_index[RTW_RF_PATH_MAX];
s8 delta_power_index_last[RTW_RF_PATH_MAX];
u8 default_ofdm_index;
u8 default_cck_index;
bool pwr_trk_triggered;
bool pwr_trk_init_trigger;
struct ewma_thermal avg_thermal[RTW_RF_PATH_MAX];
s8 txagc_remnant_cck;
s8 txagc_remnant_ofdm;
u8 rx_cck_agc_report_type;
/* backup dack results for each path and I/Q */
u32 dack_adck[RTW_RF_PATH_MAX];

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,102 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright Fiona Klute <fiona.klute@gmx.de> */
#ifndef __RTW8703B_H__
#define __RTW8703B_H__
#include "rtw8723x.h"
extern const struct rtw_chip_info rtw8703b_hw_spec;
/* phy status parsing */
#define VGA_BITS GENMASK(4, 0)
#define LNA_L_BITS GENMASK(7, 5)
#define LNA_H_BIT BIT(7)
/* masks for assembling LNA index from high and low bits */
#define BIT_LNA_H_MASK BIT(3)
#define BIT_LNA_L_MASK GENMASK(2, 0)
struct phy_rx_agc_info {
#ifdef __LITTLE_ENDIAN
u8 gain: 7;
u8 trsw: 1;
#else
u8 trsw: 1;
u8 gain: 7;
#endif
} __packed;
/* This struct is called phy_status_rpt_8192cd in the vendor driver,
* there might be potential to share it with drivers for other chips
* of the same generation.
*/
struct phy_status_8703b {
struct phy_rx_agc_info path_agc[2];
u8 ch_corr[2];
u8 cck_sig_qual_ofdm_pwdb_all;
/* for CCK: bits 0:4: VGA index, bits 5:7: LNA index (low) */
u8 cck_agc_rpt_ofdm_cfosho_a;
/* for CCK: bit 7 is high bit of LNA index if long report type */
u8 cck_rpt_b_ofdm_cfosho_b;
u8 reserved_1;
u8 noise_power_db_msb;
s8 path_cfotail[2];
u8 pcts_mask[2];
s8 stream_rxevm[2];
u8 path_rxsnr[2];
u8 noise_power_db_lsb;
u8 reserved_2[3];
u8 stream_csi[2];
u8 stream_target_csi[2];
s8 sig_evm;
u8 reserved_3;
#ifdef __LITTLE_ENDIAN
u8 antsel_rx_keep_2: 1;
u8 sgi_en: 1;
u8 rxsc: 2;
u8 idle_long: 1;
u8 r_ant_train_en: 1;
u8 ant_sel_b: 1;
u8 ant_sel: 1;
#else /* __BIG_ENDIAN */
u8 ant_sel: 1;
u8 ant_sel_b: 1;
u8 r_ant_train_en: 1;
u8 idle_long: 1;
u8 rxsc: 2;
u8 sgi_en: 1;
u8 antsel_rx_keep_2: 1;
#endif
} __packed;
/* Baseband registers */
#define REG_BB_PWR_SAV5_11N 0x0818
/* BIT(11) should be 1 for 8703B *and* 8723D, which means LNA uses 4
* bit for CCK rates in report, not 3. Vendor driver logs a warning if
* it's 0, but handles the case.
*
* Purpose of other parts of this register is unknown, 8723cs driver
* code indicates some other chips use certain bits for antenna
* diversity.
*/
#define REG_BB_AMP 0x0950
#define BIT_MASK_RX_LNA (BIT(11))
/* 0xaXX: 40MHz channel settings */
#define REG_CCK_TXSF2 0x0a24 /* CCK TX filter 2 */
#define REG_CCK_DBG 0x0a28 /* debug port */
#define REG_OFDM0_A_TX_AFE 0x0c84
#define REG_TXIQK_MATRIXB_LSB2_11N 0x0c9c
#define REG_OFDM0_TX_PSD_NOISE 0x0ce4 /* TX pseudo noise weighting */
#define REG_IQK_RDY 0x0e90 /* is != 0 when IQK is done */
/* RF registers */
#define RF_RCK1 0x1E
#define AGG_BURST_NUM 3
#define AGG_BURST_SIZE 0 /* 1K */
#define BIT_MASK_AGG_BURST_NUM (GENMASK(3, 2))
#define BIT_MASK_AGG_BURST_SIZE (GENMASK(5, 4))
#endif /* __RTW8703B_H__ */

View File

@ -0,0 +1,902 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright Fiona Klute <fiona.klute@gmx.de> */
#include "main.h"
#include "phy.h"
#include "rtw8703b_tables.h"
static const struct rtw_phy_pg_cfg_pair rtw8703b_bb_pg[] = {
{ 0, 0, 0, 0x00000e08, 0x0000ff00, 0x00003200, },
{ 0, 0, 0, 0x0000086c, 0xffffff00, 0x32323200, },
{ 0, 0, 0, 0x00000e00, 0xffffffff, 0x34363636, },
{ 0, 0, 0, 0x00000e04, 0xffffffff, 0x28303234, },
{ 0, 0, 0, 0x00000e10, 0xffffffff, 0x30343434, },
{ 0, 0, 0, 0x00000e14, 0xffffffff, 0x26262830, },
};
RTW_DECL_TABLE_BB_PG(rtw8703b_bb_pg);
/* Regd: FCC -> 0, ETSI -> 2, MKK -> 1
* Band: 2.4G -> 0, 5G -> 1
* Bandwidth (bw): 20M -> 0, 40M -> 1, 80M -> 2, 160M -> 3
* Rate Section (rs): CCK -> 0, OFDM -> 1, HT -> 2, VHT -> 3
*/
static const struct rtw_txpwr_lmt_cfg_pair rtw8703b_txpwr_lmt[] = {
{0, 0, 0, 0, 1, 30},
{2, 0, 0, 0, 1, 26},
{1, 0, 0, 0, 1, 32},
{0, 0, 0, 0, 2, 30},
{2, 0, 0, 0, 2, 26},
{1, 0, 0, 0, 2, 32},
{0, 0, 0, 0, 3, 30},
{2, 0, 0, 0, 3, 26},
{1, 0, 0, 0, 3, 32},
{0, 0, 0, 0, 4, 30},
{2, 0, 0, 0, 4, 26},
{1, 0, 0, 0, 4, 32},
{0, 0, 0, 0, 5, 30},
{2, 0, 0, 0, 5, 26},
{1, 0, 0, 0, 5, 32},
{0, 0, 0, 0, 6, 30},
{2, 0, 0, 0, 6, 26},
{1, 0, 0, 0, 6, 32},
{0, 0, 0, 0, 7, 30},
{2, 0, 0, 0, 7, 26},
{1, 0, 0, 0, 7, 32},
{0, 0, 0, 0, 8, 30},
{2, 0, 0, 0, 8, 26},
{1, 0, 0, 0, 8, 32},
{0, 0, 0, 0, 9, 30},
{2, 0, 0, 0, 9, 26},
{1, 0, 0, 0, 9, 32},
{0, 0, 0, 0, 10, 30},
{2, 0, 0, 0, 10, 26},
{1, 0, 0, 0, 10, 32},
{0, 0, 0, 0, 11, 30},
{2, 0, 0, 0, 11, 26},
{1, 0, 0, 0, 11, 32},
{0, 0, 0, 0, 12, 63},
{2, 0, 0, 0, 12, 26},
{1, 0, 0, 0, 12, 32},
{0, 0, 0, 0, 13, 63},
{2, 0, 0, 0, 13, 26},
{1, 0, 0, 0, 13, 32},
{0, 0, 0, 0, 14, 63},
{2, 0, 0, 0, 14, 63},
{1, 0, 0, 0, 14, 32},
{0, 0, 0, 1, 1, 28},
{2, 0, 0, 1, 1, 28},
{1, 0, 0, 1, 1, 28},
{0, 0, 0, 1, 2, 28},
{2, 0, 0, 1, 2, 32},
{1, 0, 0, 1, 2, 32},
{0, 0, 0, 1, 3, 32},
{2, 0, 0, 1, 3, 32},
{1, 0, 0, 1, 3, 32},
{0, 0, 0, 1, 4, 32},
{2, 0, 0, 1, 4, 32},
{1, 0, 0, 1, 4, 32},
{0, 0, 0, 1, 5, 32},
{2, 0, 0, 1, 5, 32},
{1, 0, 0, 1, 5, 32},
{0, 0, 0, 1, 6, 32},
{2, 0, 0, 1, 6, 32},
{1, 0, 0, 1, 6, 32},
{0, 0, 0, 1, 7, 32},
{2, 0, 0, 1, 7, 32},
{1, 0, 0, 1, 7, 32},
{0, 0, 0, 1, 8, 32},
{2, 0, 0, 1, 8, 32},
{1, 0, 0, 1, 8, 32},
{0, 0, 0, 1, 9, 32},
{2, 0, 0, 1, 9, 32},
{1, 0, 0, 1, 9, 32},
{0, 0, 0, 1, 10, 28},
{2, 0, 0, 1, 10, 32},
{1, 0, 0, 1, 10, 32},
{0, 0, 0, 1, 11, 28},
{2, 0, 0, 1, 11, 32},
{1, 0, 0, 1, 11, 32},
{0, 0, 0, 1, 12, 63},
{2, 0, 0, 1, 12, 32},
{1, 0, 0, 1, 12, 32},
{0, 0, 0, 1, 13, 63},
{2, 0, 0, 1, 13, 28},
{1, 0, 0, 1, 13, 28},
{0, 0, 0, 1, 14, 63},
{2, 0, 0, 1, 14, 63},
{1, 0, 0, 1, 14, 63},
{0, 0, 0, 2, 1, 26},
{2, 0, 0, 2, 1, 26},
{1, 0, 0, 2, 1, 28},
{0, 0, 0, 2, 2, 26},
{2, 0, 0, 2, 2, 32},
{1, 0, 0, 2, 2, 32},
{0, 0, 0, 2, 3, 32},
{2, 0, 0, 2, 3, 32},
{1, 0, 0, 2, 3, 32},
{0, 0, 0, 2, 4, 32},
{2, 0, 0, 2, 4, 32},
{1, 0, 0, 2, 4, 32},
{0, 0, 0, 2, 5, 32},
{2, 0, 0, 2, 5, 32},
{1, 0, 0, 2, 5, 32},
{0, 0, 0, 2, 6, 32},
{2, 0, 0, 2, 6, 32},
{1, 0, 0, 2, 6, 32},
{0, 0, 0, 2, 7, 32},
{2, 0, 0, 2, 7, 32},
{1, 0, 0, 2, 7, 32},
{0, 0, 0, 2, 8, 32},
{2, 0, 0, 2, 8, 32},
{1, 0, 0, 2, 8, 32},
{0, 0, 0, 2, 9, 32},
{2, 0, 0, 2, 9, 32},
{1, 0, 0, 2, 9, 32},
{0, 0, 0, 2, 10, 26},
{2, 0, 0, 2, 10, 32},
{1, 0, 0, 2, 10, 32},
{0, 0, 0, 2, 11, 26},
{2, 0, 0, 2, 11, 32},
{1, 0, 0, 2, 11, 32},
{0, 0, 0, 2, 12, 63},
{2, 0, 0, 2, 12, 32},
{1, 0, 0, 2, 12, 32},
{0, 0, 0, 2, 13, 63},
{2, 0, 0, 2, 13, 26},
{1, 0, 0, 2, 13, 28},
{0, 0, 0, 2, 14, 63},
{2, 0, 0, 2, 14, 63},
{1, 0, 0, 2, 14, 63},
{0, 0, 1, 2, 1, 63},
{2, 0, 1, 2, 1, 63},
{1, 0, 1, 2, 1, 63},
{0, 0, 1, 2, 2, 63},
{2, 0, 1, 2, 2, 63},
{1, 0, 1, 2, 2, 63},
{0, 0, 1, 2, 3, 26},
{2, 0, 1, 2, 3, 26},
{1, 0, 1, 2, 3, 26},
{0, 0, 1, 2, 4, 26},
{2, 0, 1, 2, 4, 28},
{1, 0, 1, 2, 4, 26},
{0, 0, 1, 2, 5, 28},
{2, 0, 1, 2, 5, 28},
{1, 0, 1, 2, 5, 26},
{0, 0, 1, 2, 6, 28},
{2, 0, 1, 2, 6, 28},
{1, 0, 1, 2, 6, 26},
{0, 0, 1, 2, 7, 28},
{2, 0, 1, 2, 7, 28},
{1, 0, 1, 2, 7, 26},
{0, 0, 1, 2, 8, 26},
{2, 0, 1, 2, 8, 28},
{1, 0, 1, 2, 8, 26},
{0, 0, 1, 2, 9, 26},
{2, 0, 1, 2, 9, 28},
{1, 0, 1, 2, 9, 26},
{0, 0, 1, 2, 10, 26},
{2, 0, 1, 2, 10, 28},
{1, 0, 1, 2, 10, 26},
{0, 0, 1, 2, 11, 26},
{2, 0, 1, 2, 11, 26},
{1, 0, 1, 2, 11, 26},
{0, 0, 1, 2, 12, 63},
{2, 0, 1, 2, 12, 26},
{1, 0, 1, 2, 12, 26},
{0, 0, 1, 2, 13, 63},
{2, 0, 1, 2, 13, 26},
{1, 0, 1, 2, 13, 26},
{0, 0, 1, 2, 14, 63},
{2, 0, 1, 2, 14, 63},
{1, 0, 1, 2, 14, 63},
};
RTW_DECL_TABLE_TXPWR_LMT(rtw8703b_txpwr_lmt);
static const u32 rtw8703b_mac[] = {
0x02F, 0x00000030,
0x035, 0x00000000,
0x067, 0x00000002,
0x092, 0x00000080,
0x421, 0x0000000F,
0x428, 0x0000000A,
0x429, 0x00000010,
0x430, 0x00000000,
0x431, 0x00000000,
0x432, 0x00000000,
0x433, 0x00000001,
0x434, 0x00000002,
0x435, 0x00000003,
0x436, 0x00000005,
0x437, 0x00000007,
0x438, 0x00000000,
0x439, 0x00000000,
0x43A, 0x00000000,
0x43B, 0x00000001,
0x43C, 0x00000002,
0x43D, 0x00000003,
0x43E, 0x00000005,
0x43F, 0x00000007,
0x440, 0x0000005D,
0x441, 0x00000001,
0x442, 0x00000000,
0x444, 0x00000010,
0x445, 0x00000000,
0x446, 0x00000000,
0x447, 0x00000000,
0x448, 0x00000000,
0x449, 0x000000F0,
0x44A, 0x0000000F,
0x44B, 0x0000003E,
0x44C, 0x00000010,
0x44D, 0x00000000,
0x44E, 0x00000000,
0x44F, 0x00000000,
0x450, 0x00000000,
0x451, 0x000000F0,
0x452, 0x0000000F,
0x453, 0x00000000,
0x456, 0x0000005E,
0x460, 0x00000066,
0x461, 0x00000066,
0x4C8, 0x000000FF,
0x4C9, 0x00000008,
0x4CC, 0x000000FF,
0x4CD, 0x000000FF,
0x4CE, 0x00000001,
0x500, 0x00000026,
0x501, 0x000000A2,
0x502, 0x0000002F,
0x503, 0x00000000,
0x504, 0x00000028,
0x505, 0x000000A3,
0x506, 0x0000005E,
0x507, 0x00000000,
0x508, 0x0000002B,
0x509, 0x000000A4,
0x50A, 0x0000005E,
0x50B, 0x00000000,
0x50C, 0x0000004F,
0x50D, 0x000000A4,
0x50E, 0x00000000,
0x50F, 0x00000000,
0x512, 0x0000001C,
0x514, 0x0000000A,
0x516, 0x0000000A,
0x525, 0x0000004F,
0x550, 0x00000010,
0x551, 0x00000010,
0x559, 0x00000002,
0x55C, 0x00000028,
0x55D, 0x000000FF,
0x605, 0x00000030,
0x608, 0x0000000E,
0x609, 0x0000002A,
0x620, 0x000000FF,
0x621, 0x000000FF,
0x622, 0x000000FF,
0x623, 0x000000FF,
0x624, 0x000000FF,
0x625, 0x000000FF,
0x626, 0x000000FF,
0x627, 0x000000FF,
0x638, 0x00000028,
0x63C, 0x0000000A,
0x63D, 0x0000000A,
0x63E, 0x0000000C,
0x63F, 0x0000000C,
0x640, 0x00000040,
0x642, 0x00000040,
0x643, 0x00000000,
0x652, 0x000000C8,
0x66A, 0x000000B0,
0x66E, 0x00000005,
0x700, 0x00000021,
0x701, 0x00000043,
0x702, 0x00000065,
0x703, 0x00000087,
0x708, 0x00000021,
0x709, 0x00000043,
0x70A, 0x00000065,
0x70B, 0x00000087,
0x765, 0x00000018,
0x76E, 0x00000004,
};
RTW_DECL_TABLE_PHY_COND(rtw8703b_mac, rtw_phy_cfg_mac);
static const u32 rtw8703b_agc[] = {
0xC78, 0xFC000101,
0xC78, 0xFB010101,
0xC78, 0xFA020101,
0xC78, 0xF9030101,
0xC78, 0xF8040101,
0xC78, 0xF7050101,
0xC78, 0xF6060101,
0xC78, 0xF5070101,
0xC78, 0xF4080101,
0xC78, 0xF3090101,
0xC78, 0xF20A0101,
0xC78, 0xF10B0101,
0xC78, 0xF00C0101,
0xC78, 0xEF0D0101,
0xC78, 0xEE0E0101,
0xC78, 0xED0F0101,
0xC78, 0xEC100101,
0xC78, 0xEB110101,
0xC78, 0xEA120101,
0xC78, 0xE9130101,
0xC78, 0xE8140101,
0xC78, 0xE7150101,
0xC78, 0xE6160101,
0xC78, 0xE5170101,
0xC78, 0xE4180101,
0xC78, 0xE3190101,
0xC78, 0x661A0101,
0xC78, 0x651B0101,
0xC78, 0x641C0101,
0xC78, 0x631D0101,
0xC78, 0x071E0101,
0xC78, 0x061F0101,
0xC78, 0x05200101,
0xC78, 0x04210101,
0xC78, 0x03220101,
0xC78, 0xE8230001,
0xC78, 0xE7240001,
0xC78, 0xE6250001,
0xC78, 0xE5260001,
0xC78, 0xE4270001,
0xC78, 0x89280001,
0xC78, 0x88290001,
0xC78, 0x872A0001,
0xC78, 0x862B0001,
0xC78, 0x852C0001,
0xC78, 0x482D0001,
0xC78, 0x472E0001,
0xC78, 0x462F0001,
0xC78, 0x45300001,
0xC78, 0x44310001,
0xC78, 0x07320001,
0xC78, 0x06330001,
0xC78, 0x05340001,
0xC78, 0x04350001,
0xC78, 0x03360001,
0xC78, 0x02370001,
0xC78, 0x01380001,
0xC78, 0x00390001,
0xC78, 0x003A0001,
0xC78, 0x003B0001,
0xC78, 0x003C0001,
0xC78, 0x003D0001,
0xC78, 0x003E0001,
0xC78, 0x003F0001,
0xC78, 0x7F002001,
0xC78, 0x7F012001,
0xC78, 0x7F022001,
0xC78, 0x7F032001,
0xC78, 0x7F042001,
0xC78, 0x7F052001,
0xC78, 0x7F062001,
0xC78, 0x7F072001,
0xC78, 0x7F082001,
0xC78, 0x7F092001,
0xC78, 0x7F0A2001,
0xC78, 0x7F0B2001,
0xC78, 0x7F0C2001,
0xC78, 0x7F0D2001,
0xC78, 0x7F0E2001,
0xC78, 0x7F0F2001,
0xC78, 0x7F102001,
0xC78, 0x7F112001,
0xC78, 0x7E122001,
0xC78, 0x7D132001,
0xC78, 0x7C142001,
0xC78, 0x7B152001,
0xC78, 0x7A162001,
0xC78, 0x79172001,
0xC78, 0x78182001,
0xC78, 0x77192001,
0xC78, 0x761A2001,
0xC78, 0x751B2001,
0xC78, 0x741C2001,
0xC78, 0x731D2001,
0xC78, 0x721E2001,
0xC78, 0x711F2001,
0xC78, 0x70202001,
0xC78, 0x6F212001,
0xC78, 0x6E222001,
0xC78, 0x6D232001,
0xC78, 0x6C242001,
0xC78, 0x6B252001,
0xC78, 0x6A262001,
0xC78, 0x69272001,
0xC78, 0x68282001,
0xC78, 0x67292001,
0xC78, 0x662A2001,
0xC78, 0x652B2001,
0xC78, 0x642C2001,
0xC78, 0x632D2001,
0xC78, 0x622E2001,
0xC78, 0x612F2001,
0xC78, 0x60302001,
0xC78, 0x42312001,
0xC78, 0x41322001,
0xC78, 0x40332001,
0xC78, 0x23342001,
0xC78, 0x22352001,
0xC78, 0x21362001,
0xC78, 0x20372001,
0xC78, 0x00382001,
0xC78, 0x02392001,
0xC78, 0x013A2001,
0xC78, 0x003B2001,
0xC78, 0x003C2001,
0xC78, 0x003D2001,
0xC78, 0x003E2001,
0xC78, 0x003F2001,
0xC78, 0x7F003101,
0xC78, 0x7F013101,
0xC78, 0x7F023101,
0xC78, 0x7F033101,
0xC78, 0x7F043101,
0xC78, 0x7F053101,
0xC78, 0x7F063101,
0xC78, 0x7E073101,
0xC78, 0x7D083101,
0xC78, 0x7C093101,
0xC78, 0x7B0A3101,
0xC78, 0x7A0B3101,
0xC78, 0x790C3101,
0xC78, 0x780D3101,
0xC78, 0x770E3101,
0xC78, 0x760F3101,
0xC78, 0x75103101,
0xC78, 0x74113101,
0xC78, 0x73123101,
0xC78, 0x72133101,
0xC78, 0x71143101,
0xC78, 0x70153101,
0xC78, 0x6F163101,
0xC78, 0x69173101,
0xC78, 0x68183101,
0xC78, 0x67193101,
0xC78, 0x661A3101,
0xC78, 0x651B3101,
0xC78, 0x641C3101,
0xC78, 0x631D3101,
0xC78, 0x621E3101,
0xC78, 0x611F3101,
0xC78, 0x60203101,
0xC78, 0x42213101,
0xC78, 0x41223101,
0xC78, 0x40233101,
0xC78, 0x22243101,
0xC78, 0x21253101,
0xC78, 0x20263101,
0xC78, 0x00273101,
0xC78, 0x00283101,
0xC78, 0x00293101,
0xC78, 0x002A3101,
0xC78, 0x002B3101,
0xC78, 0x002C3101,
0xC78, 0x002D3101,
0xC78, 0x002E3101,
0xC78, 0x002F3101,
0xC78, 0x00303101,
0xC78, 0x00313101,
0xC78, 0x00323101,
0xC78, 0x00333101,
0xC78, 0x00343101,
0xC78, 0x00353101,
0xC78, 0x00363101,
0xC78, 0x00373101,
0xC78, 0x00383101,
0xC78, 0x00393101,
0xC78, 0x003A3101,
0xC78, 0x003B3101,
0xC78, 0x003C3101,
0xC78, 0x003D3101,
0xC78, 0x003E3101,
0xC78, 0x003F3101,
0xC78, 0xFA403101,
0xC78, 0xF9413101,
0xC78, 0xF8423101,
0xC78, 0xF7433101,
0xC78, 0xF6443101,
0xC78, 0xF5453101,
0xC78, 0xF4463101,
0xC78, 0xF3473101,
0xC78, 0xF2483101,
0xC78, 0xE1493101,
0xC78, 0xE04A3101,
0xC78, 0xEF4B3101,
0xC78, 0xEE4C3101,
0xC78, 0xED4D3101,
0xC78, 0xEC4E3101,
0xC78, 0xEB4F3101,
0xC78, 0xEA503101,
0xC78, 0xE9513101,
0xC78, 0xE8523101,
0xC78, 0xE7533101,
0xC78, 0xE6543101,
0xC78, 0xE5553101,
0xC78, 0xE4563101,
0xC78, 0xE3573101,
0xC78, 0xE2583101,
0xC78, 0xE1593101,
0xC78, 0xE05A3101,
0xC78, 0xC25B3101,
0xC78, 0xC15C3101,
0xC78, 0xC05D3101,
0xC78, 0x825E3101,
0xC78, 0x815F3101,
0xC78, 0x80603101,
0xC78, 0x80613101,
0xC78, 0x80623101,
0xC78, 0x80633101,
0xC78, 0x80643101,
0xC78, 0x80653101,
0xC78, 0x80663101,
0xC78, 0x80673101,
0xC78, 0x80683101,
0xC78, 0x80693101,
0xC78, 0x806A3101,
0xC78, 0x806B3101,
0xC78, 0x806C3101,
0xC78, 0x806D3101,
0xC78, 0x806E3101,
0xC78, 0x806F3101,
0xC78, 0x80703101,
0xC78, 0x80713101,
0xC78, 0x80723101,
0xC78, 0x80733101,
0xC78, 0x80743101,
0xC78, 0x80753101,
0xC78, 0x80763101,
0xC78, 0x80773101,
0xC78, 0x80783101,
0xC78, 0x80793101,
0xC78, 0x807A3101,
0xC78, 0x807B3101,
0xC78, 0x807C3101,
0xC78, 0x807D3101,
0xC78, 0x807E3101,
0xC78, 0x807F3101,
0xC78, 0xFF402001,
0xC78, 0xFF412001,
0xC78, 0xFF422001,
0xC78, 0xFF432001,
0xC78, 0xFF442001,
0xC78, 0xFF452001,
0xC78, 0xFF462001,
0xC78, 0xFF472001,
0xC78, 0xFF482001,
0xC78, 0xFF492001,
0xC78, 0xFF4A2001,
0xC78, 0xFF4B2001,
0xC78, 0xFF4C2001,
0xC78, 0xFE4D2001,
0xC78, 0xFD4E2001,
0xC78, 0xFC4F2001,
0xC78, 0xFB502001,
0xC78, 0xFA512001,
0xC78, 0xF9522001,
0xC78, 0xF8532001,
0xC78, 0xF7542001,
0xC78, 0xF6552001,
0xC78, 0xF5562001,
0xC78, 0xF4572001,
0xC78, 0xF3582001,
0xC78, 0xF2592001,
0xC78, 0xF15A2001,
0xC78, 0xF05B2001,
0xC78, 0xEF5C2001,
0xC78, 0xEE5D2001,
0xC78, 0xED5E2001,
0xC78, 0xEC5F2001,
0xC78, 0xEB602001,
0xC78, 0xEA612001,
0xC78, 0xE9622001,
0xC78, 0xE8632001,
0xC78, 0xE7642001,
0xC78, 0xE6652001,
0xC78, 0xE5662001,
0xC78, 0xE4672001,
0xC78, 0xE3682001,
0xC78, 0xC5692001,
0xC78, 0xC46A2001,
0xC78, 0xC36B2001,
0xC78, 0xA46C2001,
0xC78, 0x846D2001,
0xC78, 0x836E2001,
0xC78, 0x826F2001,
0xC78, 0x81702001,
0xC78, 0x80712001,
0xC78, 0x80722001,
0xC78, 0x80732001,
0xC78, 0x80742001,
0xC78, 0x80752001,
0xC78, 0x80762001,
0xC78, 0x80772001,
0xC78, 0x80782001,
0xC78, 0x80792001,
0xC78, 0x807A2001,
0xC78, 0x807B2001,
0xC78, 0x807C2001,
0xC78, 0x807D2001,
0xC78, 0x807E2001,
0xC78, 0x807F2001,
0xC50, 0x69553422,
0xC50, 0x69553420,
};
RTW_DECL_TABLE_PHY_COND(rtw8703b_agc, rtw_phy_cfg_agc);
/* init values for BB registers */
static const u32 rtw8703b_bb[] = {
0x800, 0x83045700,
0x804, 0x00000003,
0x808, 0x0000FC00,
0x80C, 0x0000000A,
0x810, 0x10001331,
0x814, 0x020C3D10,
0x818, 0x02200385,
0x81C, 0x00000000,
0x820, 0x01000100,
0x824, 0x00390204,
0x828, 0x00000000,
0x82C, 0x00000000,
0x830, 0x00000000,
0x834, 0x00000000,
0x838, 0x00000000,
0x83C, 0x00000000,
0x840, 0x00010000,
0x844, 0x00000000,
0x848, 0x00000000,
0x84C, 0x00000000,
0x850, 0x00000000,
0x854, 0x00000000,
0x858, 0x569A11A9,
0x85C, 0x01000014,
0x860, 0x66F60110,
0x864, 0x061F0649,
0x868, 0x00000000,
0x86C, 0x27272700,
0x870, 0x07000760,
0x874, 0x25004000,
0x878, 0x00000808,
0x87C, 0x004F0201,
0x880, 0xB0000B1E,
0x884, 0x00000001,
0x888, 0x00000000,
0x88C, 0xCCC000C0,
0x890, 0x00000800,
0x894, 0xFFFFFFFE,
0x898, 0x40302010,
0x89C, 0x00706050,
0x900, 0x00000000,
0x904, 0x00000023,
0x908, 0x00000000,
0x90C, 0x81121111,
0x910, 0x00000002,
0x914, 0x00000201,
0x948, 0x99000000,
0x94C, 0x00000010,
0x950, 0x20003800,
0x954, 0x4A880000,
0x958, 0x4BC5D87A,
0x95C, 0x04EB9B79,
0xA00, 0x00D047C8,
0xA04, 0x80FF800C,
0xA08, 0x8C838300,
0xA0C, 0x2E7F120F,
0xA10, 0x9500BB78,
0xA14, 0x1114D028,
0xA18, 0x00881117,
0xA1C, 0x89140F00,
0xA20, 0xD1D80000,
0xA24, 0x5A7DA0BD,
0xA28, 0x0000223B,
0xA2C, 0x00D30000,
0xA70, 0x101FBF00,
0xA74, 0x00000007,
0xA78, 0x00008900,
0xA7C, 0x225B0606,
0xA80, 0x2180FA74,
0xA84, 0x00120000,
0xA88, 0x040C0000,
0xA8C, 0x12345678,
0xA90, 0xABCDEF00,
0xA94, 0x001B1B89,
0xA98, 0x05100000,
0xA9C, 0x3F000000,
0xAA0, 0x00000000,
0xB2C, 0x00000000,
0xC00, 0x48071D40,
0xC04, 0x03A05611,
0xC08, 0x000000E4,
0xC0C, 0x6C6C6C6C,
0xC10, 0x18800000,
0xC14, 0x40000100,
0xC18, 0x08800000,
0xC1C, 0x40000100,
0xC20, 0x00000000,
0xC24, 0x00000000,
0xC28, 0x00000000,
0xC2C, 0x00000000,
0xC30, 0x69E9AC4B,
0xC34, 0x31000040,
0xC38, 0x21688080,
0xC3C, 0x000016CC,
0xC40, 0x1F78403F,
0xC44, 0x00010036,
0xC48, 0xEC020107,
0xC4C, 0x007F037F,
0xC50, 0x69553420,
0xC54, 0x43BC0094,
0xC58, 0x00015967,
0xC5C, 0x18250492,
0xC60, 0x00000000,
0xC64, 0x7112848B,
0xC68, 0x47C07BFF,
0xC6C, 0x00000036,
0xC70, 0x2C7F000D,
0xC74, 0x020600DB,
0xC78, 0x0000001F,
0xC7C, 0x00B91612,
0xC80, 0x390000E4,
0xC84, 0x19F60000,
0xC88, 0x40000100,
0xC8C, 0x20200000,
0xC90, 0x00091521,
0xC94, 0x00000000,
0xC98, 0x00121820,
0xC9C, 0x00007F7F,
0xCA0, 0x00000000,
0xCA4, 0x000300A0,
0xCA8, 0x00000000,
0xCAC, 0x00000000,
0xCB0, 0x00000000,
0xCB4, 0x00000000,
0xCB8, 0x00000000,
0xCBC, 0x28000000,
0xCC0, 0x00000000,
0xCC4, 0x00000000,
0xCC8, 0x00000000,
0xCCC, 0x00000000,
0xCD0, 0x00000000,
0xCD4, 0x00000000,
0xCD8, 0x64B22427,
0xCDC, 0x00766932,
0xCE0, 0x00222222,
0xCE4, 0x10000000,
0xCE8, 0x37644302,
0xCEC, 0x2F97D40C,
0xD00, 0x00030740,
0xD04, 0x40020401,
0xD08, 0x0000907F,
0xD0C, 0x20010201,
0xD10, 0xA0633333,
0xD14, 0x3333BC53,
0xD18, 0x7A8F5B6F,
0xD2C, 0xCB979975,
0xD30, 0x00000000,
0xD34, 0x80608000,
0xD38, 0x98000000,
0xD3C, 0x40127353,
0xD40, 0x00000000,
0xD44, 0x00000000,
0xD48, 0x00000000,
0xD4C, 0x00000000,
0xD50, 0x6437140A,
0xD54, 0x00000000,
0xD58, 0x00000282,
0xD5C, 0x30032064,
0xD60, 0x4653DE68,
0xD64, 0x04518A3C,
0xD68, 0x00002101,
0xE00, 0x2D2D2D2D,
0xE04, 0x2D2D2D2D,
0xE08, 0x0390272D,
0xE10, 0x2D2D2D2D,
0xE14, 0x2D2D2D2D,
0xE18, 0x2D2D2D2D,
0xE1C, 0x2D2D2D2D,
0xE28, 0x00000000,
0xE30, 0x1000DC1F,
0xE34, 0x10008C1F,
0xE38, 0x02140102,
0xE3C, 0x681604C2,
0xE40, 0x01007C00,
0xE44, 0x01004800,
0xE48, 0xFB000000,
0xE4C, 0x000028D1,
0xE50, 0x1000DC1F,
0xE54, 0x10008C1F,
0xE58, 0x02140102,
0xE5C, 0x28160D05,
0xE60, 0x00000048,
0xE68, 0x001B25A4,
0xE6C, 0x01C00014,
0xE70, 0x01C00014,
0xE74, 0x02000014,
0xE78, 0x02000014,
0xE7C, 0x02000014,
0xE80, 0x02000014,
0xE84, 0x01C00014,
0xE88, 0x02000014,
0xE8C, 0x01C00014,
0xED0, 0x01C00014,
0xED4, 0x01C00014,
0xED8, 0x01C00014,
0xEDC, 0x00000014,
0xEE0, 0x00000014,
0xEE8, 0x21555448,
0xEEC, 0x03C00014,
0xF14, 0x00000003,
0xF4C, 0x00000000,
0xF00, 0x00000300,
};
RTW_DECL_TABLE_PHY_COND(rtw8703b_bb, rtw_phy_cfg_bb);
static const u32 rtw8703b_rf_a[] = {
0x018, 0x00008C01,
0x0B5, 0x0008C050,
0x0B1, 0x00054258,
0x0B2, 0x00054C00,
0x030, 0x00018000,
0x031, 0x00000027,
0x032, 0x000A7F07,
0x030, 0x00020000,
0x031, 0x00000027,
0x032, 0x000E7D87,
0x01C, 0x000F8635,
0x0EF, 0x00080000,
0x030, 0x00008000,
0x031, 0x00000004,
0x032, 0x00006105,
0x0EF, 0x00000000,
0x0EF, 0x00000400,
0x041, 0x0000BD54,
0x041, 0x00003DD4,
0x041, 0x0000FDD4,
0x0EF, 0x00000000,
0x0DF, 0x00000600,
0x050, 0x0000C6DB,
0x051, 0x00004505,
0x052, 0x0000E31D,
0x053, 0x00040579,
0x054, 0x00000000,
0x055, 0x0008206E,
0x056, 0x00040000,
0x0EF, 0x00000100,
0x034, 0x0000ADD7,
0x034, 0x00009DD4,
0x034, 0x00008DD1,
0x034, 0x00007DCE,
0x034, 0x00006DCB,
0x034, 0x00005CCE,
0x034, 0x000048CD,
0x034, 0x000034CC,
0x034, 0x0000244F,
0x034, 0x0000144C,
0x034, 0x0000004E,
0x0EF, 0x00000000,
0x0EF, 0x00002000,
0x03B, 0x0003801F,
0x03B, 0x00030002,
0x03B, 0x00028001,
0x03B, 0x00020000,
0x03B, 0x00018003,
0x03B, 0x00010002,
0x03B, 0x00008001,
0x03B, 0x00000000,
0x0EF, 0x00000000,
0x082, 0x000C0000,
0x083, 0x000AF025,
0x01E, 0x00000C08,
};
RTW_DECL_TABLE_RF_RADIO(rtw8703b_rf_a, A);

View File

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright Fiona Klute <fiona.klute@gmx.de> */
#ifndef __RTW8703B_TABLES_H__
#define __RTW8703B_TABLES_H__
extern const struct rtw_table rtw8703b_bb_pg_tbl;
extern const struct rtw_table rtw8703b_txpwr_lmt_tbl;
extern const struct rtw_table rtw8703b_mac_tbl;
extern const struct rtw_table rtw8703b_agc_tbl;
extern const struct rtw_table rtw8703b_bb_tbl;
extern const struct rtw_table rtw8703b_rf_a_tbl;
#endif

View File

@ -0,0 +1,34 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright Fiona Klute <fiona.klute@gmx.de> */
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/module.h>
#include "main.h"
#include "rtw8703b.h"
#include "sdio.h"
static const struct sdio_device_id rtw_8723cs_id_table[] = {
{
SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
SDIO_DEVICE_ID_REALTEK_RTW8723CS),
.driver_data = (kernel_ulong_t)&rtw8703b_hw_spec,
},
{}
};
MODULE_DEVICE_TABLE(sdio, rtw_8723cs_id_table);
static struct sdio_driver rtw_8723cs_driver = {
.name = "rtw8723cs",
.id_table = rtw_8723cs_id_table,
.probe = rtw_sdio_probe,
.remove = rtw_sdio_remove,
.drv = {
.pm = &rtw_sdio_pm_ops,
.shutdown = rtw_sdio_shutdown
}};
module_sdio_driver(rtw_8723cs_driver);
MODULE_AUTHOR("Fiona Klute <fiona.klute@gmx.de>");
MODULE_DESCRIPTION("Realtek 802.11n wireless 8723cs driver");
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -9,36 +9,13 @@
#include "tx.h"
#include "rx.h"
#include "phy.h"
#include "rtw8723x.h"
#include "rtw8723d.h"
#include "rtw8723d_table.h"
#include "mac.h"
#include "reg.h"
#include "debug.h"
static const struct rtw_hw_reg rtw8723d_txagc[] = {
[DESC_RATE1M] = { .addr = 0xe08, .mask = 0x0000ff00 },
[DESC_RATE2M] = { .addr = 0x86c, .mask = 0x0000ff00 },
[DESC_RATE5_5M] = { .addr = 0x86c, .mask = 0x00ff0000 },
[DESC_RATE11M] = { .addr = 0x86c, .mask = 0xff000000 },
[DESC_RATE6M] = { .addr = 0xe00, .mask = 0x000000ff },
[DESC_RATE9M] = { .addr = 0xe00, .mask = 0x0000ff00 },
[DESC_RATE12M] = { .addr = 0xe00, .mask = 0x00ff0000 },
[DESC_RATE18M] = { .addr = 0xe00, .mask = 0xff000000 },
[DESC_RATE24M] = { .addr = 0xe04, .mask = 0x000000ff },
[DESC_RATE36M] = { .addr = 0xe04, .mask = 0x0000ff00 },
[DESC_RATE48M] = { .addr = 0xe04, .mask = 0x00ff0000 },
[DESC_RATE54M] = { .addr = 0xe04, .mask = 0xff000000 },
[DESC_RATEMCS0] = { .addr = 0xe10, .mask = 0x000000ff },
[DESC_RATEMCS1] = { .addr = 0xe10, .mask = 0x0000ff00 },
[DESC_RATEMCS2] = { .addr = 0xe10, .mask = 0x00ff0000 },
[DESC_RATEMCS3] = { .addr = 0xe10, .mask = 0xff000000 },
[DESC_RATEMCS4] = { .addr = 0xe14, .mask = 0x000000ff },
[DESC_RATEMCS5] = { .addr = 0xe14, .mask = 0x0000ff00 },
[DESC_RATEMCS6] = { .addr = 0xe14, .mask = 0x00ff0000 },
[DESC_RATEMCS7] = { .addr = 0xe14, .mask = 0xff000000 },
};
#define WLAN_TXQ_RPT_EN 0x1F
#define WLAN_SLOT_TIME 0x09
#define WLAN_RL_VAL 0x3030
#define WLAN_BAR_VAL 0x0201ffff
@ -65,34 +42,6 @@ static const struct rtw_hw_reg rtw8723d_txagc[] = {
#define WLAN_LTR_CTRL1 0xCB004010
#define WLAN_LTR_CTRL2 0x01233425
static void rtw8723d_lck(struct rtw_dev *rtwdev)
{
u32 lc_cal;
u8 val_ctx, rf_val;
int ret;
val_ctx = rtw_read8(rtwdev, REG_CTX);
if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
rtw_write8(rtwdev, REG_CTX, val_ctx & ~BIT_MASK_CTX_TYPE);
else
rtw_write8(rtwdev, REG_TXPAUSE, 0xFF);
lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);
rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal | BIT_LCK);
ret = read_poll_timeout(rtw_read_rf, rf_val, rf_val != 0x1,
10000, 1000000, false,
rtwdev, RF_PATH_A, RF_CFGCH, BIT_LCK);
if (ret)
rtw_warn(rtwdev, "failed to poll LCK status bit\n");
rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal);
if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
rtw_write8(rtwdev, REG_CTX, val_ctx);
else
rtw_write8(rtwdev, REG_TXPAUSE, 0x00);
}
static const u32 rtw8723d_ofdm_swing_table[] = {
0x0b40002d, 0x0c000030, 0x0cc00033, 0x0d800036, 0x0e400039, 0x0f00003c,
0x10000040, 0x11000044, 0x12000048, 0x1300004c, 0x14400051, 0x15800056,
@ -196,7 +145,7 @@ static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev)
rtw_write16_set(rtwdev, REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN);
rtw8723d_lck(rtwdev);
rtw8723x_lck(rtwdev);
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50);
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x20);
@ -204,67 +153,6 @@ static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev)
rtw8723d_pwrtrack_init(rtwdev);
}
static void rtw8723de_efuse_parsing(struct rtw_efuse *efuse,
struct rtw8723d_efuse *map)
{
ether_addr_copy(efuse->addr, map->e.mac_addr);
}
static void rtw8723du_efuse_parsing(struct rtw_efuse *efuse,
struct rtw8723d_efuse *map)
{
ether_addr_copy(efuse->addr, map->u.mac_addr);
}
static void rtw8723ds_efuse_parsing(struct rtw_efuse *efuse,
struct rtw8723d_efuse *map)
{
ether_addr_copy(efuse->addr, map->s.mac_addr);
}
static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
{
struct rtw_efuse *efuse = &rtwdev->efuse;
struct rtw8723d_efuse *map;
int i;
map = (struct rtw8723d_efuse *)log_map;
efuse->rfe_option = 0;
efuse->rf_board_option = map->rf_board_option;
efuse->crystal_cap = map->xtal_k;
efuse->pa_type_2g = map->pa_type;
efuse->lna_type_2g = map->lna_type_2g[0];
efuse->channel_plan = map->channel_plan;
efuse->country_code[0] = map->country_code[0];
efuse->country_code[1] = map->country_code[1];
efuse->bt_setting = map->rf_bt_setting;
efuse->regd = map->rf_board_option & 0x7;
efuse->thermal_meter[0] = map->thermal_meter;
efuse->thermal_meter_k = map->thermal_meter;
efuse->afe = map->afe;
for (i = 0; i < 4; i++)
efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i];
switch (rtw_hci_type(rtwdev)) {
case RTW_HCI_TYPE_PCIE:
rtw8723de_efuse_parsing(efuse, map);
break;
case RTW_HCI_TYPE_USB:
rtw8723du_efuse_parsing(efuse, map);
break;
case RTW_HCI_TYPE_SDIO:
rtw8723ds_efuse_parsing(efuse, map);
break;
default:
/* unsupported now */
return -ENOTSUPP;
}
return 0;
}
static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
struct rtw_rx_pkt_stat *pkt_stat)
{
@ -540,297 +428,11 @@ static void rtw8723d_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw,
rtw8723d_set_channel_bb(rtwdev, channel, bw, primary_chan_idx);
}
#define BIT_CFENDFORM BIT(9)
#define BIT_WMAC_TCR_ERR0 BIT(12)
#define BIT_WMAC_TCR_ERR1 BIT(13)
#define BIT_TCR_CFG (BIT_CFENDFORM | BIT_WMAC_TCR_ERR0 | \
BIT_WMAC_TCR_ERR1)
#define WLAN_RX_FILTER0 0xFFFF
#define WLAN_RX_FILTER1 0x400
#define WLAN_RX_FILTER2 0xFFFF
#define WLAN_RCR_CFG 0x700060CE
static int rtw8723d_mac_init(struct rtw_dev *rtwdev)
{
rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 1, WLAN_TXQ_RPT_EN);
rtw_write32(rtwdev, REG_TCR, BIT_TCR_CFG);
rtw_write16(rtwdev, REG_RXFLTMAP0, WLAN_RX_FILTER0);
rtw_write16(rtwdev, REG_RXFLTMAP1, WLAN_RX_FILTER1);
rtw_write16(rtwdev, REG_RXFLTMAP2, WLAN_RX_FILTER2);
rtw_write32(rtwdev, REG_RCR, WLAN_RCR_CFG);
rtw_write32(rtwdev, REG_INT_MIG, 0);
rtw_write32(rtwdev, REG_MCUTST_1, 0x0);
rtw_write8(rtwdev, REG_MISC_CTRL, BIT_DIS_SECOND_CCA);
rtw_write8(rtwdev, REG_2ND_CCA_CTRL, 0);
return 0;
}
static void rtw8723d_shutdown(struct rtw_dev *rtwdev)
{
rtw_write16_set(rtwdev, REG_HCI_OPT_CTRL, BIT_USB_SUS_DIS);
}
static void rtw8723d_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
{
u8 ldo_pwr;
ldo_pwr = rtw_read8(rtwdev, REG_LDO_EFUSE_CTRL + 3);
if (enable) {
ldo_pwr &= ~BIT_MASK_LDO25_VOLTAGE;
ldo_pwr |= (BIT_LDO25_VOLTAGE_V25 << 4) | BIT_LDO25_EN;
} else {
ldo_pwr &= ~BIT_LDO25_EN;
}
rtw_write8(rtwdev, REG_LDO_EFUSE_CTRL + 3, ldo_pwr);
}
static void
rtw8723d_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs)
{
struct rtw_hal *hal = &rtwdev->hal;
const struct rtw_hw_reg *txagc;
u8 rate, pwr_index;
int j;
for (j = 0; j < rtw_rate_size[rs]; j++) {
rate = rtw_rate_section[rs][j];
pwr_index = hal->tx_pwr_tbl[path][rate];
if (rate >= ARRAY_SIZE(rtw8723d_txagc)) {
rtw_warn(rtwdev, "rate 0x%x isn't supported\n", rate);
continue;
}
txagc = &rtw8723d_txagc[rate];
if (!txagc->addr) {
rtw_warn(rtwdev, "rate 0x%x isn't defined\n", rate);
continue;
}
rtw_write32_mask(rtwdev, txagc->addr, txagc->mask, pwr_index);
}
}
static void rtw8723d_set_tx_power_index(struct rtw_dev *rtwdev)
{
struct rtw_hal *hal = &rtwdev->hal;
int rs, path;
for (path = 0; path < hal->rf_path_num; path++) {
for (rs = 0; rs <= RTW_RATE_SECTION_HT_1S; rs++)
rtw8723d_set_tx_power_index_by_rate(rtwdev, path, rs);
}
}
static void rtw8723d_efuse_grant(struct rtw_dev *rtwdev, bool on)
{
if (on) {
rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
rtw_write16_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_ELDR);
rtw_write16_set(rtwdev, REG_SYS_CLKR, BIT_LOADER_CLK_EN | BIT_ANA8M);
} else {
rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
}
}
static void rtw8723d_false_alarm_statistics(struct rtw_dev *rtwdev)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u32 cck_fa_cnt;
u32 ofdm_fa_cnt;
u32 crc32_cnt;
u32 val32;
/* hold counter */
rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 1);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 1);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KEEP, 1);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KEEP, 1);
cck_fa_cnt = rtw_read32_mask(rtwdev, REG_CCK_FA_LSB_11N, MASKBYTE0);
cck_fa_cnt += rtw_read32_mask(rtwdev, REG_CCK_FA_MSB_11N, MASKBYTE3) << 8;
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE1_11N);
ofdm_fa_cnt = u32_get_bits(val32, BIT_MASK_OFDM_FF_CNT);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_SF_CNT);
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE2_11N);
dm_info->ofdm_cca_cnt = u32_get_bits(val32, BIT_MASK_OFDM_CCA_CNT);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_PF_CNT);
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE3_11N);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_RI_CNT);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_CRC_CNT);
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE4_11N);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_MNS_CNT);
dm_info->cck_fa_cnt = cck_fa_cnt;
dm_info->ofdm_fa_cnt = ofdm_fa_cnt;
dm_info->total_fa_cnt = cck_fa_cnt + ofdm_fa_cnt;
dm_info->cck_err_cnt = rtw_read32(rtwdev, REG_IGI_C_11N);
dm_info->cck_ok_cnt = rtw_read32(rtwdev, REG_IGI_D_11N);
crc32_cnt = rtw_read32(rtwdev, REG_OFDM_CRC32_CNT_11N);
dm_info->ofdm_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_ERR);
dm_info->ofdm_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_OK);
crc32_cnt = rtw_read32(rtwdev, REG_HT_CRC32_CNT_11N);
dm_info->ht_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_ERR);
dm_info->ht_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_OK);
dm_info->vht_err_cnt = 0;
dm_info->vht_ok_cnt = 0;
val32 = rtw_read32(rtwdev, REG_CCK_CCA_CNT_11N);
dm_info->cck_cca_cnt = (u32_get_bits(val32, BIT_MASK_CCK_FA_MSB) << 8) |
u32_get_bits(val32, BIT_MASK_CCK_FA_LSB);
dm_info->total_cca_cnt = dm_info->cck_cca_cnt + dm_info->ofdm_cca_cnt;
/* reset counter */
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 1);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 0);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 1);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 0);
rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 0);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 0);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 0);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 2);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 0);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 2);
rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 1);
rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 0);
}
static const u32 iqk_adda_regs[] = {
0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c,
0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec
};
static const u32 iqk_mac8_regs[] = {0x522, 0x550, 0x551};
static const u32 iqk_mac32_regs[] = {0x40};
static const u32 iqk_bb_regs[] = {
0xc04, 0xc08, 0x874, 0xb68, 0xb6c, 0x870, 0x860, 0x864, 0xa04
};
#define IQK_ADDA_REG_NUM ARRAY_SIZE(iqk_adda_regs)
#define IQK_MAC8_REG_NUM ARRAY_SIZE(iqk_mac8_regs)
#define IQK_MAC32_REG_NUM ARRAY_SIZE(iqk_mac32_regs)
#define IQK_BB_REG_NUM ARRAY_SIZE(iqk_bb_regs)
struct iqk_backup_regs {
u32 adda[IQK_ADDA_REG_NUM];
u8 mac8[IQK_MAC8_REG_NUM];
u32 mac32[IQK_MAC32_REG_NUM];
u32 bb[IQK_BB_REG_NUM];
u32 lte_path;
u32 lte_gnt;
u32 bb_sel_btg;
u8 btg_sel;
u8 igia;
u8 igib;
};
static void rtw8723d_iqk_backup_regs(struct rtw_dev *rtwdev,
struct iqk_backup_regs *backup)
{
int i;
for (i = 0; i < IQK_ADDA_REG_NUM; i++)
backup->adda[i] = rtw_read32(rtwdev, iqk_adda_regs[i]);
for (i = 0; i < IQK_MAC8_REG_NUM; i++)
backup->mac8[i] = rtw_read8(rtwdev, iqk_mac8_regs[i]);
for (i = 0; i < IQK_MAC32_REG_NUM; i++)
backup->mac32[i] = rtw_read32(rtwdev, iqk_mac32_regs[i]);
for (i = 0; i < IQK_BB_REG_NUM; i++)
backup->bb[i] = rtw_read32(rtwdev, iqk_bb_regs[i]);
backup->igia = rtw_read32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0);
backup->igib = rtw_read32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0);
backup->bb_sel_btg = rtw_read32(rtwdev, REG_BB_SEL_BTG);
}
static void rtw8723d_iqk_restore_regs(struct rtw_dev *rtwdev,
const struct iqk_backup_regs *backup)
{
int i;
for (i = 0; i < IQK_ADDA_REG_NUM; i++)
rtw_write32(rtwdev, iqk_adda_regs[i], backup->adda[i]);
for (i = 0; i < IQK_MAC8_REG_NUM; i++)
rtw_write8(rtwdev, iqk_mac8_regs[i], backup->mac8[i]);
for (i = 0; i < IQK_MAC32_REG_NUM; i++)
rtw_write32(rtwdev, iqk_mac32_regs[i], backup->mac32[i]);
for (i = 0; i < IQK_BB_REG_NUM; i++)
rtw_write32(rtwdev, iqk_bb_regs[i], backup->bb[i]);
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50);
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, backup->igia);
rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, 0x50);
rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, backup->igib);
rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x01008c00);
rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x01008c00);
}
static void rtw8723d_iqk_backup_path_ctrl(struct rtw_dev *rtwdev,
struct iqk_backup_regs *backup)
{
backup->btg_sel = rtw_read8(rtwdev, REG_BTG_SEL);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] original 0x67 = 0x%x\n",
backup->btg_sel);
}
static void rtw8723d_iqk_config_path_ctrl(struct rtw_dev *rtwdev)
{
rtw_write32_mask(rtwdev, REG_PAD_CTRL1, BIT_BT_BTG_SEL, 0x1);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] set 0x67 = 0x%x\n",
rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
}
static void rtw8723d_iqk_restore_path_ctrl(struct rtw_dev *rtwdev,
const struct iqk_backup_regs *backup)
{
rtw_write8(rtwdev, REG_BTG_SEL, backup->btg_sel);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] restore 0x67 = 0x%x\n",
rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
}
static void rtw8723d_iqk_backup_lte_path_gnt(struct rtw_dev *rtwdev,
struct iqk_backup_regs *backup)
{
backup->lte_path = rtw_read32(rtwdev, REG_LTECOEX_PATH_CONTROL);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0038);
mdelay(1);
backup->lte_gnt = rtw_read32(rtwdev, REG_LTECOEX_READ_DATA);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] OriginalGNT = 0x%x\n",
backup->lte_gnt);
}
static void rtw8723d_iqk_config_lte_path_gnt(struct rtw_dev *rtwdev)
{
rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, 0x0000ff00);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc0020038);
rtw_write32_mask(rtwdev, REG_LTECOEX_PATH_CONTROL, BIT_LTE_MUX_CTRL_PATH, 0x1);
}
static void rtw8723d_iqk_restore_lte_path_gnt(struct rtw_dev *rtwdev,
const struct iqk_backup_regs *bak)
{
rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, bak->lte_gnt);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc00f0038);
rtw_write32(rtwdev, REG_LTECOEX_PATH_CONTROL, bak->lte_path);
}
struct rtw_8723d_iqk_cfg {
const char *name;
u32 val_bb_sel_btg;
@ -930,6 +532,8 @@ static u8 rtw8723d_iqk_check_rx_failed(struct rtw_dev *rtwdev,
return 0;
}
#define IQK_LTE_WRITE_VAL_8723D 0x0000ff00
static void rtw8723d_iqk_one_shot(struct rtw_dev *rtwdev, bool tx,
const struct rtw_8723d_iqk_cfg *iqk_cfg)
{
@ -937,7 +541,7 @@ static void rtw8723d_iqk_one_shot(struct rtw_dev *rtwdev, bool tx,
/* enter IQK mode */
rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK);
rtw8723d_iqk_config_lte_path_gnt(rtwdev);
rtw8723x_iqk_config_lte_path_gnt(rtwdev, IQK_LTE_WRITE_VAL_8723D);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0054);
mdelay(1);
@ -959,9 +563,9 @@ static void rtw8723d_iqk_one_shot(struct rtw_dev *rtwdev, bool tx,
static void rtw8723d_iqk_txrx_path_post(struct rtw_dev *rtwdev,
const struct rtw_8723d_iqk_cfg *iqk_cfg,
const struct iqk_backup_regs *backup)
const struct rtw8723x_iqk_backup_regs *backup)
{
rtw8723d_iqk_restore_lte_path_gnt(rtwdev, backup);
rtw8723x_iqk_restore_lte_path_gnt(rtwdev, backup);
rtw_write32(rtwdev, REG_BB_SEL_BTG, backup->bb_sel_btg);
/* leave IQK mode */
@ -974,7 +578,7 @@ static void rtw8723d_iqk_txrx_path_post(struct rtw_dev *rtwdev,
static u8 rtw8723d_iqk_tx_path(struct rtw_dev *rtwdev,
const struct rtw_8723d_iqk_cfg *iqk_cfg,
const struct iqk_backup_regs *backup)
const struct rtw8723x_iqk_backup_regs *backup)
{
u8 status;
@ -1033,7 +637,7 @@ static u8 rtw8723d_iqk_tx_path(struct rtw_dev *rtwdev,
static u8 rtw8723d_iqk_rx_path(struct rtw_dev *rtwdev,
const struct rtw_8723d_iqk_cfg *iqk_cfg,
const struct iqk_backup_regs *backup)
const struct rtw8723x_iqk_backup_regs *backup)
{
u32 tx_x, tx_y;
u8 status;
@ -1220,14 +824,6 @@ void rtw8723d_iqk_fill_s0_matrix(struct rtw_dev *rtwdev, const s32 result[])
result[IQK_S0_RX_Y]);
}
static void rtw8723d_iqk_path_adda_on(struct rtw_dev *rtwdev)
{
int i;
for (i = 0; i < IQK_ADDA_REG_NUM; i++)
rtw_write32(rtwdev, iqk_adda_regs[i], 0x03c00016);
}
static void rtw8723d_iqk_config_mac(struct rtw_dev *rtwdev)
{
rtw_write8(rtwdev, REG_TXPAUSE, 0xff);
@ -1245,70 +841,14 @@ void rtw8723d_iqk_rf_standby(struct rtw_dev *rtwdev, enum rtw_rf_path path)
rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK);
}
static
bool rtw8723d_iqk_similarity_cmp(struct rtw_dev *rtwdev, s32 result[][IQK_NR],
u8 c1, u8 c2)
{
u32 i, j, diff;
u32 bitmap = 0;
u8 candidate[PATH_NR] = {IQK_ROUND_INVALID, IQK_ROUND_INVALID};
bool ret = true;
s32 tmp1, tmp2;
for (i = 0; i < IQK_NR; i++) {
tmp1 = iqkxy_to_s32(result[c1][i]);
tmp2 = iqkxy_to_s32(result[c2][i]);
diff = abs(tmp1 - tmp2);
if (diff <= MAX_TOLERANCE)
continue;
if ((i == IQK_S1_RX_X || i == IQK_S0_RX_X) && !bitmap) {
if (result[c1][i] + result[c1][i + 1] == 0)
candidate[i / IQK_SX_NR] = c2;
else if (result[c2][i] + result[c2][i + 1] == 0)
candidate[i / IQK_SX_NR] = c1;
else
bitmap |= BIT(i);
} else {
bitmap |= BIT(i);
}
}
if (bitmap != 0)
goto check_sim;
for (i = 0; i < PATH_NR; i++) {
if (candidate[i] == IQK_ROUND_INVALID)
continue;
for (j = i * IQK_SX_NR; j < i * IQK_SX_NR + 2; j++)
result[IQK_ROUND_HYBRID][j] = result[candidate[i]][j];
ret = false;
}
return ret;
check_sim:
for (i = 0; i < IQK_NR; i++) {
j = i & ~1; /* 2 bits are a pair for IQ[X, Y] */
if (bitmap & GENMASK(j + 1, j))
continue;
result[IQK_ROUND_HYBRID][i] = result[c1][i];
}
return false;
}
#define ADDA_ON_VAL_8723D 0x03c00016
static
void rtw8723d_iqk_precfg_path(struct rtw_dev *rtwdev, enum rtw8723d_path path)
void rtw8723d_iqk_precfg_path(struct rtw_dev *rtwdev, enum rtw8723x_path path)
{
if (path == PATH_S0) {
rtw8723d_iqk_rf_standby(rtwdev, RF_PATH_A);
rtw8723d_iqk_path_adda_on(rtwdev);
rtw8723x_iqk_path_adda_on(rtwdev, ADDA_ON_VAL_8723D);
}
rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK);
@ -1317,13 +857,13 @@ void rtw8723d_iqk_precfg_path(struct rtw_dev *rtwdev, enum rtw8723d_path path)
if (path == PATH_S1) {
rtw8723d_iqk_rf_standby(rtwdev, RF_PATH_B);
rtw8723d_iqk_path_adda_on(rtwdev);
rtw8723x_iqk_path_adda_on(rtwdev, ADDA_ON_VAL_8723D);
}
}
static
void rtw8723d_iqk_one_round(struct rtw_dev *rtwdev, s32 result[][IQK_NR], u8 t,
const struct iqk_backup_regs *backup)
const struct rtw8723x_iqk_backup_regs *backup)
{
u32 i;
u8 s1_ok, s0_ok;
@ -1331,7 +871,7 @@ void rtw8723d_iqk_one_round(struct rtw_dev *rtwdev, s32 result[][IQK_NR], u8 t,
rtw_dbg(rtwdev, RTW_DBG_RFK,
"[IQK] IQ Calibration for 1T1R_S0/S1 for %d times\n", t);
rtw8723d_iqk_path_adda_on(rtwdev);
rtw8723x_iqk_path_adda_on(rtwdev, ADDA_ON_VAL_8723D);
rtw8723d_iqk_config_mac(rtwdev);
rtw_write32_mask(rtwdev, REG_CCK_ANT_SEL_11N, 0x0f000000, 0xf);
rtw_write32(rtwdev, REG_BB_RX_PATH_11N, 0x03a05611);
@ -1427,7 +967,7 @@ static void rtw8723d_phy_calibration(struct rtw_dev *rtwdev)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
s32 result[IQK_ROUND_SIZE][IQK_NR];
struct iqk_backup_regs backup;
struct rtw8723x_iqk_backup_regs backup;
u8 i, j;
u8 final_candidate = IQK_ROUND_INVALID;
bool good;
@ -1436,23 +976,23 @@ static void rtw8723d_phy_calibration(struct rtw_dev *rtwdev)
memset(result, 0, sizeof(result));
rtw8723d_iqk_backup_path_ctrl(rtwdev, &backup);
rtw8723d_iqk_backup_lte_path_gnt(rtwdev, &backup);
rtw8723d_iqk_backup_regs(rtwdev, &backup);
rtw8723x_iqk_backup_path_ctrl(rtwdev, &backup);
rtw8723x_iqk_backup_lte_path_gnt(rtwdev, &backup);
rtw8723x_iqk_backup_regs(rtwdev, &backup);
for (i = IQK_ROUND_0; i <= IQK_ROUND_2; i++) {
rtw8723d_iqk_config_path_ctrl(rtwdev);
rtw8723d_iqk_config_lte_path_gnt(rtwdev);
rtw8723x_iqk_config_path_ctrl(rtwdev);
rtw8723x_iqk_config_lte_path_gnt(rtwdev, IQK_LTE_WRITE_VAL_8723D);
rtw8723d_iqk_one_round(rtwdev, result, i, &backup);
if (i > IQK_ROUND_0)
rtw8723d_iqk_restore_regs(rtwdev, &backup);
rtw8723d_iqk_restore_lte_path_gnt(rtwdev, &backup);
rtw8723d_iqk_restore_path_ctrl(rtwdev, &backup);
rtw8723x_iqk_restore_regs(rtwdev, &backup);
rtw8723x_iqk_restore_lte_path_gnt(rtwdev, &backup);
rtw8723x_iqk_restore_path_ctrl(rtwdev, &backup);
for (j = IQK_ROUND_0; j < i; j++) {
good = rtw8723d_iqk_similarity_cmp(rtwdev, result, j, i);
good = rtw8723x_iqk_similarity_cmp(rtwdev, result, j, i);
if (good) {
final_candidate = j;
@ -1546,26 +1086,6 @@ static void rtw8723d_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
}
/* for coex */
static void rtw8723d_coex_cfg_init(struct rtw_dev *rtwdev)
{
/* enable TBTT nterrupt */
rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
/* BT report packet sample rate */
/* 0x790[5:0]=0x5 */
rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5);
/* enable BT counter statistics */
rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1);
/* enable PTA (3-wire function form BT side) */
rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);
rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_PO_BT_PTA_PINS);
/* enable PTA (tx/rx signal form WiFi side) */
rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN);
}
static void rtw8723d_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
{
}
@ -1671,39 +1191,6 @@ static void rtw8723d_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
}
}
static u8 rtw8723d_pwrtrack_get_limit_ofdm(struct rtw_dev *rtwdev)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u8 tx_rate = dm_info->tx_rate;
u8 limit_ofdm = 30;
switch (tx_rate) {
case DESC_RATE1M...DESC_RATE5_5M:
case DESC_RATE11M:
break;
case DESC_RATE6M...DESC_RATE48M:
limit_ofdm = 36;
break;
case DESC_RATE54M:
limit_ofdm = 34;
break;
case DESC_RATEMCS0...DESC_RATEMCS2:
limit_ofdm = 38;
break;
case DESC_RATEMCS3...DESC_RATEMCS4:
limit_ofdm = 36;
break;
case DESC_RATEMCS5...DESC_RATEMCS7:
limit_ofdm = 34;
break;
default:
rtw_warn(rtwdev, "pwrtrack unhandled tx_rate 0x%x\n", tx_rate);
break;
}
return limit_ofdm;
}
static void rtw8723d_set_iqk_matrix_by_result(struct rtw_dev *rtwdev,
u32 ofdm_swing, u8 rf_path)
{
@ -1845,7 +1332,7 @@ static void rtw8723d_pwrtrack_set(struct rtw_dev *rtwdev, u8 path)
s8 final_ofdm_swing_index;
s8 final_cck_swing_index;
limit_ofdm = rtw8723d_pwrtrack_get_limit_ofdm(rtwdev);
limit_ofdm = rtw8723x_pwrtrack_get_limit_ofdm(rtwdev);
final_ofdm_swing_index = RTW_DEF_OFDM_SWING_INDEX +
dm_info->delta_power_index[path];
@ -1873,26 +1360,6 @@ static void rtw8723d_pwrtrack_set(struct rtw_dev *rtwdev, u8 path)
rtw_phy_set_tx_power_level(rtwdev, hal->current_channel);
}
static void rtw8723d_pwrtrack_set_xtal(struct rtw_dev *rtwdev, u8 therm_path,
u8 delta)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl;
const s8 *pwrtrk_xtal;
s8 xtal_cap;
if (dm_info->thermal_avg[therm_path] >
rtwdev->efuse.thermal_meter[therm_path])
pwrtrk_xtal = tbl->pwrtrk_xtal_p;
else
pwrtrk_xtal = tbl->pwrtrk_xtal_n;
xtal_cap = rtwdev->efuse.crystal_cap & 0x3F;
xtal_cap = clamp_t(s8, xtal_cap + pwrtrk_xtal[delta], 0, 0x3F);
rtw_write32_mask(rtwdev, REG_AFE_CTRL3, BIT_MASK_XTAL,
xtal_cap | (xtal_cap << 6));
}
static void rtw8723d_phy_pwrtrack(struct rtw_dev *rtwdev)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
@ -1912,7 +1379,7 @@ static void rtw8723d_phy_pwrtrack(struct rtw_dev *rtwdev)
do_iqk = rtw_phy_pwrtrack_need_iqk(rtwdev);
if (do_iqk)
rtw8723d_lck(rtwdev);
rtw8723x_lck(rtwdev);
if (dm_info->pwr_trk_init_trigger)
dm_info->pwr_trk_init_trigger = false;
@ -1937,7 +1404,7 @@ static void rtw8723d_phy_pwrtrack(struct rtw_dev *rtwdev)
rtw8723d_pwrtrack_set(rtwdev, path);
}
rtw8723d_pwrtrack_set_xtal(rtwdev, RF_PATH_A, delta);
rtw8723x_pwrtrack_set_xtal(rtwdev, RF_PATH_A, delta);
iqk:
if (do_iqk)
@ -1963,49 +1430,29 @@ static void rtw8723d_pwr_track(struct rtw_dev *rtwdev)
dm_info->pwr_trk_triggered = false;
}
static void rtw8723d_fill_txdesc_checksum(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *txdesc)
{
size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */
__le16 chksum = 0;
__le16 *data = (__le16 *)(txdesc);
struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc;
le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM);
while (words--)
chksum ^= *data++;
chksum = ~chksum;
le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum),
RTW_TX_DESC_W7_TXDESC_CHECKSUM);
}
static struct rtw_chip_ops rtw8723d_ops = {
.phy_set_param = rtw8723d_phy_set_param,
.read_efuse = rtw8723d_read_efuse,
.read_efuse = rtw8723x_read_efuse,
.query_rx_desc = rtw8723d_query_rx_desc,
.set_channel = rtw8723d_set_channel,
.mac_init = rtw8723d_mac_init,
.mac_init = rtw8723x_mac_init,
.shutdown = rtw8723d_shutdown,
.read_rf = rtw_phy_read_rf_sipi,
.write_rf = rtw_phy_write_rf_reg_sipi,
.set_tx_power_index = rtw8723d_set_tx_power_index,
.set_tx_power_index = rtw8723x_set_tx_power_index,
.set_antenna = NULL,
.cfg_ldo25 = rtw8723d_cfg_ldo25,
.efuse_grant = rtw8723d_efuse_grant,
.false_alarm_statistics = rtw8723d_false_alarm_statistics,
.cfg_ldo25 = rtw8723x_cfg_ldo25,
.efuse_grant = rtw8723x_efuse_grant,
.false_alarm_statistics = rtw8723x_false_alarm_statistics,
.phy_calibration = rtw8723d_phy_calibration,
.cck_pd_set = rtw8723d_phy_cck_pd_set,
.pwr_track = rtw8723d_pwr_track,
.config_bfee = NULL,
.set_gid_table = NULL,
.cfg_csi_rate = NULL,
.fill_txdesc_checksum = rtw8723d_fill_txdesc_checksum,
.fill_txdesc_checksum = rtw8723x_fill_txdesc_checksum,
.coex_set_init = rtw8723d_coex_cfg_init,
.coex_set_init = rtw8723x_coex_cfg_init,
.coex_set_ant_switch = NULL,
.coex_set_gnt_fix = rtw8723d_coex_cfg_gnt_fix,
.coex_set_gnt_debug = rtw8723d_coex_cfg_gnt_debug,
@ -2592,22 +2039,6 @@ static const struct rtw_rqpn rqpn_table_8723d[] = {
RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
};
static const struct rtw_prioq_addrs prioq_addrs_8723d = {
.prio[RTW_DMA_MAPPING_EXTRA] = {
.rsvd = REG_RQPN_NPQ + 2, .avail = REG_RQPN_NPQ + 3,
},
.prio[RTW_DMA_MAPPING_LOW] = {
.rsvd = REG_RQPN + 1, .avail = REG_FIFOPAGE_CTRL_2 + 1,
},
.prio[RTW_DMA_MAPPING_NORMAL] = {
.rsvd = REG_RQPN_NPQ, .avail = REG_RQPN_NPQ + 1,
},
.prio[RTW_DMA_MAPPING_HIGH] = {
.rsvd = REG_RQPN, .avail = REG_FIFOPAGE_CTRL_2,
},
.wsize = false,
};
static const struct rtw_intf_phy_para pcie_gen1_param_8723d[] = {
{0x0008, 0x4a22,
RTW_IP_SEL_PHY,
@ -2628,28 +2059,6 @@ static const struct rtw_intf_phy_para_table phy_para_table_8723d = {
.n_gen1_para = ARRAY_SIZE(pcie_gen1_param_8723d),
};
static const struct rtw_hw_reg rtw8723d_dig[] = {
[0] = { .addr = 0xc50, .mask = 0x7f },
[1] = { .addr = 0xc50, .mask = 0x7f },
};
static const struct rtw_hw_reg rtw8723d_dig_cck[] = {
[0] = { .addr = 0xa0c, .mask = 0x3f00 },
};
static const struct rtw_rf_sipi_addr rtw8723d_rf_sipi_addr[] = {
[RF_PATH_A] = { .hssi_1 = 0x820, .lssi_read = 0x8a0,
.hssi_2 = 0x824, .lssi_read_pi = 0x8b8},
[RF_PATH_B] = { .hssi_1 = 0x828, .lssi_read = 0x8a4,
.hssi_2 = 0x82c, .lssi_read_pi = 0x8bc},
};
static const struct rtw_ltecoex_addr rtw8723d_ltecoex_addr = {
.ctrl = REG_LTECOEX_CTRL,
.wdata = REG_LTECOEX_WRITE_DATA,
.rdata = REG_LTECOEX_READ_DATA,
};
static const struct rtw_rfe_def rtw8723d_rfe_defs[] = {
[0] = { .phy_pg_tbl = &rtw8723d_bb_pg_tbl,
.txpwr_lmt_tbl = &rtw8723d_txpwr_lmt_tbl,},
@ -2770,14 +2179,14 @@ const struct rtw_chip_info rtw8723d_hw_spec = {
.pwr_off_seq = card_disable_flow_8723d,
.page_table = page_table_8723d,
.rqpn_table = rqpn_table_8723d,
.prioq_addrs = &prioq_addrs_8723d,
.prioq_addrs = &rtw8723x_common.prioq_addrs,
.intf_table = &phy_para_table_8723d,
.dig = rtw8723d_dig,
.dig_cck = rtw8723d_dig_cck,
.dig = rtw8723x_common.dig,
.dig_cck = rtw8723x_common.dig_cck,
.rf_sipi_addr = {0x840, 0x844},
.rf_sipi_read_addr = rtw8723d_rf_sipi_addr,
.rf_sipi_read_addr = rtw8723x_common.rf_sipi_addr,
.fix_rf_phy_num = 2,
.ltecoex_addr = &rtw8723d_ltecoex_addr,
.ltecoex_addr = &rtw8723x_common.ltecoex_addr,
.mac_tbl = &rtw8723d_mac_tbl,
.agc_tbl = &rtw8723d_agc_tbl,
.bb_tbl = &rtw8723d_bb_tbl,

View File

@ -5,90 +5,7 @@
#ifndef __RTW8723D_H__
#define __RTW8723D_H__
enum rtw8723d_path {
PATH_S1,
PATH_S0,
PATH_NR,
};
enum rtw8723d_iqk_round {
IQK_ROUND_0,
IQK_ROUND_1,
IQK_ROUND_2,
IQK_ROUND_HYBRID,
IQK_ROUND_SIZE,
IQK_ROUND_INVALID = 0xff,
};
enum rtw8723d_iqk_result {
IQK_S1_TX_X,
IQK_S1_TX_Y,
IQK_S1_RX_X,
IQK_S1_RX_Y,
IQK_S0_TX_X,
IQK_S0_TX_Y,
IQK_S0_RX_X,
IQK_S0_RX_Y,
IQK_NR,
IQK_SX_NR = IQK_NR / PATH_NR,
};
struct rtw8723de_efuse {
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
u8 vender_id[2];
u8 device_id[2];
u8 sub_vender_id[2];
u8 sub_device_id[2];
};
struct rtw8723du_efuse {
u8 res4[48]; /* 0xd0 */
u8 vender_id[2]; /* 0x100 */
u8 product_id[2]; /* 0x102 */
u8 usb_option; /* 0x104 */
u8 res5[2]; /* 0x105 */
u8 mac_addr[ETH_ALEN]; /* 0x107 */
};
struct rtw8723ds_efuse {
u8 res4[0x4a]; /* 0xd0 */
u8 mac_addr[ETH_ALEN]; /* 0x11a */
};
struct rtw8723d_efuse {
__le16 rtl_id;
u8 rsvd[2];
u8 afe;
u8 rsvd1[11];
/* power index for four RF paths */
struct rtw_txpwr_idx txpwr_idx_table[4];
u8 channel_plan; /* 0xb8 */
u8 xtal_k;
u8 thermal_meter;
u8 iqk_lck;
u8 pa_type; /* 0xbc */
u8 lna_type_2g[2]; /* 0xbd */
u8 lna_type_5g[2];
u8 rf_board_option;
u8 rf_feature_option;
u8 rf_bt_setting;
u8 eeprom_version;
u8 eeprom_customer_id;
u8 tx_bb_swing_setting_2g;
u8 res_c7;
u8 tx_pwr_calibrate_rate;
u8 rf_antenna_option; /* 0xc9 */
u8 rfe_option;
u8 country_code[2];
u8 res[3];
union {
struct rtw8723de_efuse e;
struct rtw8723du_efuse u;
struct rtw8723ds_efuse s;
};
};
#include "rtw8723x.h"
extern const struct rtw_chip_info rtw8723d_hw_spec;
@ -114,193 +31,9 @@ extern const struct rtw_chip_info rtw8723d_hw_spec;
#define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
static inline s32 iqkxy_to_s32(s32 val)
{
/* val is Q10.8 */
return sign_extend32(val, 9);
}
static inline s32 iqk_mult(s32 x, s32 y, s32 *ext)
{
/* x, y and return value are Q10.8 */
s32 t;
t = x * y;
if (ext)
*ext = (t >> 7) & 0x1; /* Q.16 --> Q.9; get LSB of Q.9 */
return (t >> 8); /* Q.16 --> Q.8 */
}
#define OFDM_SWING_A(swing) FIELD_GET(GENMASK(9, 0), swing)
#define OFDM_SWING_B(swing) FIELD_GET(GENMASK(15, 10), swing)
#define OFDM_SWING_C(swing) FIELD_GET(GENMASK(21, 16), swing)
#define OFDM_SWING_D(swing) FIELD_GET(GENMASK(31, 22), swing)
#define RTW_DEF_OFDM_SWING_INDEX 28
#define RTW_DEF_CCK_SWING_INDEX 28
#define MAX_TOLERANCE 5
#define IQK_TX_X_ERR 0x142
#define IQK_TX_Y_ERR 0x42
#define IQK_RX_X_UPPER 0x11a
#define IQK_RX_X_LOWER 0xe6
#define IQK_RX_Y_LMT 0x1a
#define IQK_TX_OK BIT(0)
#define IQK_RX_OK BIT(1)
#define PATH_IQK_RETRY 2
#define SPUR_THRES 0x16
#define CCK_DFIR_NR 3
#define DIS_3WIRE 0xccf000c0
#define EN_3WIRE 0xccc000c0
#define START_PSD 0x400000
#define FREQ_CH13 0xfccd
#define FREQ_CH14 0xff9a
#define RFCFGCH_CHANNEL_MASK GENMASK(7, 0)
#define RFCFGCH_BW_MASK (BIT(11) | BIT(10))
#define RFCFGCH_BW_20M (BIT(11) | BIT(10))
#define RFCFGCH_BW_40M BIT(10)
#define BIT_MASK_RFMOD BIT(0)
#define BIT_LCK BIT(15)
#define REG_GPIO_INTM 0x0048
#define REG_BTG_SEL 0x0067
#define BIT_MASK_BTG_WL BIT(7)
#define REG_LTECOEX_PATH_CONTROL 0x0070
#define REG_LTECOEX_CTRL 0x07c0
#define REG_LTECOEX_WRITE_DATA 0x07c4
#define REG_LTECOEX_READ_DATA 0x07c8
#define REG_PSDFN 0x0808
#define REG_BB_PWR_SAV1_11N 0x0874
#define REG_ANA_PARAM1 0x0880
#define REG_ANALOG_P4 0x088c
#define REG_PSDRPT 0x08b4
#define REG_FPGA1_RFMOD 0x0900
#define REG_BB_SEL_BTG 0x0948
#define REG_BBRX_DFIR 0x0954
#define BIT_MASK_RXBB_DFIR GENMASK(27, 24)
#define BIT_RXBB_DFIR_EN BIT(19)
#define REG_CCK0_SYS 0x0a00
#define BIT_CCK_SIDE_BAND BIT(4)
#define REG_CCK_ANT_SEL_11N 0x0a04
#define REG_PWRTH 0x0a08
#define REG_CCK_FA_RST_11N 0x0a2c
#define BIT_MASK_CCK_CNT_KEEP BIT(12)
#define BIT_MASK_CCK_CNT_EN BIT(13)
#define BIT_MASK_CCK_CNT_KPEN (BIT_MASK_CCK_CNT_KEEP | BIT_MASK_CCK_CNT_EN)
#define BIT_MASK_CCK_FA_KEEP BIT(14)
#define BIT_MASK_CCK_FA_EN BIT(15)
#define BIT_MASK_CCK_FA_KPEN (BIT_MASK_CCK_FA_KEEP | BIT_MASK_CCK_FA_EN)
#define REG_CCK_FA_LSB_11N 0x0a5c
#define REG_CCK_FA_MSB_11N 0x0a58
#define REG_CCK_CCA_CNT_11N 0x0a60
#define BIT_MASK_CCK_FA_MSB GENMASK(7, 0)
#define BIT_MASK_CCK_FA_LSB GENMASK(15, 8)
#define REG_PWRTH2 0x0aa8
#define REG_CSRATIO 0x0aaa
#define REG_OFDM_FA_HOLDC_11N 0x0c00
#define BIT_MASK_OFDM_FA_KEEP BIT(31)
#define REG_BB_RX_PATH_11N 0x0c04
#define REG_TRMUX_11N 0x0c08
#define REG_OFDM_FA_RSTC_11N 0x0c0c
#define BIT_MASK_OFDM_FA_RST BIT(31)
#define REG_A_RXIQI 0x0c14
#define BIT_MASK_RXIQ_S1_X 0x000003FF
#define BIT_MASK_RXIQ_S1_Y1 0x0000FC00
#define BIT_SET_RXIQ_S1_Y1(y) ((y) & 0x3F)
#define REG_OFDM0_RXDSP 0x0c40
#define BIT_MASK_RXDSP GENMASK(28, 24)
#define BIT_EN_RXDSP BIT(9)
#define REG_OFDM_0_ECCA_THRESHOLD 0x0c4c
#define BIT_MASK_OFDM0_EXT_A BIT(31)
#define BIT_MASK_OFDM0_EXT_C BIT(29)
#define BIT_MASK_OFDM0_EXTS (BIT(31) | BIT(29) | BIT(28))
#define BIT_SET_OFDM0_EXTS(a, c, d) (((a) << 31) | ((c) << 29) | ((d) << 28))
#define REG_OFDM0_XAAGC1 0x0c50
#define REG_OFDM0_XBAGC1 0x0c58
#define REG_AGCRSSI 0x0c78
#define REG_OFDM_0_XA_TX_IQ_IMBALANCE 0x0c80
#define BIT_MASK_TXIQ_ELM_A 0x03ff
#define BIT_SET_TXIQ_ELM_ACD(a, c, d) (((d) << 22) | (((c) & 0x3F) << 16) | \
((a) & 0x03ff))
#define BIT_MASK_TXIQ_ELM_C GENMASK(21, 16)
#define BIT_SET_TXIQ_ELM_C2(c) ((c) & 0x3F)
#define BIT_MASK_TXIQ_ELM_D GENMASK(31, 22)
#define REG_TXIQK_MATRIXA_LSB2_11N 0x0c94
#define BIT_SET_TXIQ_ELM_C1(c) (((c) & 0x000003C0) >> 6)
#define REG_RXIQK_MATRIX_LSB_11N 0x0ca0
#define BIT_MASK_RXIQ_S1_Y2 0xF0000000
#define BIT_SET_RXIQ_S1_Y2(y) (((y) >> 6) & 0xF)
#define REG_TXIQ_AB_S0 0x0cd0
#define BIT_MASK_TXIQ_A_S0 0x000007FE
#define BIT_MASK_TXIQ_A_EXT_S0 BIT(0)
#define BIT_MASK_TXIQ_B_S0 0x0007E000
#define REG_TXIQ_CD_S0 0x0cd4
#define BIT_MASK_TXIQ_C_S0 0x000007FE
#define BIT_MASK_TXIQ_C_EXT_S0 BIT(0)
#define BIT_MASK_TXIQ_D_S0 GENMASK(22, 13)
#define BIT_MASK_TXIQ_D_EXT_S0 BIT(12)
#define REG_RXIQ_AB_S0 0x0cd8
#define BIT_MASK_RXIQ_X_S0 0x000003FF
#define BIT_MASK_RXIQ_Y_S0 0x003FF000
#define REG_OFDM_FA_TYPE1_11N 0x0cf0
#define BIT_MASK_OFDM_FF_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_SF_CNT GENMASK(31, 16)
#define REG_OFDM_FA_RSTD_11N 0x0d00
#define BIT_MASK_OFDM_FA_RST1 BIT(27)
#define BIT_MASK_OFDM_FA_KEEP1 BIT(31)
#define REG_CTX 0x0d03
#define BIT_MASK_CTX_TYPE GENMASK(6, 4)
#define REG_OFDM1_CFOTRK 0x0d2c
#define BIT_EN_CFOTRK BIT(28)
#define REG_OFDM1_CSI1 0x0d40
#define REG_OFDM1_CSI2 0x0d44
#define REG_OFDM1_CSI3 0x0d48
#define REG_OFDM1_CSI4 0x0d4c
#define REG_OFDM_FA_TYPE2_11N 0x0da0
#define BIT_MASK_OFDM_CCA_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_PF_CNT GENMASK(31, 16)
#define REG_OFDM_FA_TYPE3_11N 0x0da4
#define BIT_MASK_OFDM_RI_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_CRC_CNT GENMASK(31, 16)
#define REG_OFDM_FA_TYPE4_11N 0x0da8
#define BIT_MASK_OFDM_MNS_CNT GENMASK(15, 0)
#define REG_FPGA0_IQK_11N 0x0e28
#define BIT_MASK_IQK_MOD 0xffffff00
#define EN_IQK 0x808000
#define RST_IQK 0x000000
#define REG_TXIQK_TONE_A_11N 0x0e30
#define REG_RXIQK_TONE_A_11N 0x0e34
#define REG_TXIQK_PI_A_11N 0x0e38
#define REG_RXIQK_PI_A_11N 0x0e3c
#define REG_TXIQK_11N 0x0e40
#define BIT_SET_TXIQK_11N(x, y) (0x80007C00 | ((x) << 16) | (y))
#define REG_RXIQK_11N 0x0e44
#define REG_IQK_AGC_PTS_11N 0x0e48
#define REG_IQK_AGC_RSP_11N 0x0e4c
#define REG_TX_IQK_TONE_B 0x0e50
#define REG_RX_IQK_TONE_B 0x0e54
#define REG_IQK_RES_TX 0x0e94
#define BIT_MASK_RES_TX GENMASK(25, 16)
#define REG_IQK_RES_TY 0x0e9c
#define BIT_MASK_RES_TY GENMASK(25, 16)
#define REG_IQK_RES_RX 0x0ea4
#define BIT_MASK_RES_RX GENMASK(25, 16)
#define REG_IQK_RES_RY 0x0eac
#define BIT_IQK_TX_FAIL BIT(28)
#define BIT_IQK_RX_FAIL BIT(27)
#define BIT_IQK_DONE BIT(26)
#define BIT_MASK_RES_RY GENMASK(25, 16)
#define REG_PAGE_F_RST_11N 0x0f14
#define BIT_MASK_F_RST_ALL BIT(16)
#define REG_IGI_C_11N 0x0f84
#define REG_IGI_D_11N 0x0f88
#define REG_HT_CRC32_CNT_11N 0x0f90
#define BIT_MASK_HT_CRC_OK GENMASK(15, 0)
#define BIT_MASK_HT_CRC_ERR GENMASK(31, 16)
#define REG_OFDM_CRC32_CNT_11N 0x0f94
#define BIT_MASK_OFDM_LCRC_OK GENMASK(15, 0)
#define BIT_MASK_OFDM_LCRC_ERR GENMASK(31, 16)
#define REG_HT_CRC32_CNT_11N_AGG 0x0fb8
#endif

View File

@ -0,0 +1,721 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright 2024 Fiona Klute
*
* Based on code originally in rtw8723d.[ch],
* Copyright(c) 2018-2019 Realtek Corporation
*/
#include "main.h"
#include "debug.h"
#include "phy.h"
#include "reg.h"
#include "tx.h"
#include "rtw8723x.h"
static const struct rtw_hw_reg rtw8723x_txagc[] = {
[DESC_RATE1M] = { .addr = 0xe08, .mask = 0x0000ff00 },
[DESC_RATE2M] = { .addr = 0x86c, .mask = 0x0000ff00 },
[DESC_RATE5_5M] = { .addr = 0x86c, .mask = 0x00ff0000 },
[DESC_RATE11M] = { .addr = 0x86c, .mask = 0xff000000 },
[DESC_RATE6M] = { .addr = 0xe00, .mask = 0x000000ff },
[DESC_RATE9M] = { .addr = 0xe00, .mask = 0x0000ff00 },
[DESC_RATE12M] = { .addr = 0xe00, .mask = 0x00ff0000 },
[DESC_RATE18M] = { .addr = 0xe00, .mask = 0xff000000 },
[DESC_RATE24M] = { .addr = 0xe04, .mask = 0x000000ff },
[DESC_RATE36M] = { .addr = 0xe04, .mask = 0x0000ff00 },
[DESC_RATE48M] = { .addr = 0xe04, .mask = 0x00ff0000 },
[DESC_RATE54M] = { .addr = 0xe04, .mask = 0xff000000 },
[DESC_RATEMCS0] = { .addr = 0xe10, .mask = 0x000000ff },
[DESC_RATEMCS1] = { .addr = 0xe10, .mask = 0x0000ff00 },
[DESC_RATEMCS2] = { .addr = 0xe10, .mask = 0x00ff0000 },
[DESC_RATEMCS3] = { .addr = 0xe10, .mask = 0xff000000 },
[DESC_RATEMCS4] = { .addr = 0xe14, .mask = 0x000000ff },
[DESC_RATEMCS5] = { .addr = 0xe14, .mask = 0x0000ff00 },
[DESC_RATEMCS6] = { .addr = 0xe14, .mask = 0x00ff0000 },
[DESC_RATEMCS7] = { .addr = 0xe14, .mask = 0xff000000 },
};
static void __rtw8723x_lck(struct rtw_dev *rtwdev)
{
u32 lc_cal;
u8 val_ctx, rf_val;
int ret;
val_ctx = rtw_read8(rtwdev, REG_CTX);
if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
rtw_write8(rtwdev, REG_CTX, val_ctx & ~BIT_MASK_CTX_TYPE);
else
rtw_write8(rtwdev, REG_TXPAUSE, 0xFF);
lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);
rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal | BIT_LCK);
ret = read_poll_timeout(rtw_read_rf, rf_val, rf_val != 0x1,
10000, 1000000, false,
rtwdev, RF_PATH_A, RF_CFGCH, BIT_LCK);
if (ret)
rtw_warn(rtwdev, "failed to poll LCK status bit\n");
rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal);
if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
rtw_write8(rtwdev, REG_CTX, val_ctx);
else
rtw_write8(rtwdev, REG_TXPAUSE, 0x00);
}
#define DBG_EFUSE_VAL(rtwdev, map, name) \
rtw_dbg(rtwdev, RTW_DBG_EFUSE, # name "=0x%02x\n", \
(map)->name)
#define DBG_EFUSE_2BYTE(rtwdev, map, name) \
rtw_dbg(rtwdev, RTW_DBG_EFUSE, # name "=0x%02x%02x\n", \
(map)->name[0], (map)->name[1])
static void rtw8723xe_efuse_debug(struct rtw_dev *rtwdev,
struct rtw8723x_efuse *map)
{
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "mac_addr=%pM\n", map->e.mac_addr);
DBG_EFUSE_2BYTE(rtwdev, map, e.vendor_id);
DBG_EFUSE_2BYTE(rtwdev, map, e.device_id);
DBG_EFUSE_2BYTE(rtwdev, map, e.sub_vendor_id);
DBG_EFUSE_2BYTE(rtwdev, map, e.sub_device_id);
}
static void rtw8723xu_efuse_debug(struct rtw_dev *rtwdev,
struct rtw8723x_efuse *map)
{
DBG_EFUSE_2BYTE(rtwdev, map, u.vendor_id);
DBG_EFUSE_2BYTE(rtwdev, map, u.product_id);
DBG_EFUSE_VAL(rtwdev, map, u.usb_option);
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "mac_addr=%pM\n", map->u.mac_addr);
}
static void rtw8723xs_efuse_debug(struct rtw_dev *rtwdev,
struct rtw8723x_efuse *map)
{
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "mac_addr=%pM\n", map->s.mac_addr);
}
static void __rtw8723x_debug_txpwr_limit(struct rtw_dev *rtwdev,
struct rtw_txpwr_idx *table,
int tx_path_count)
{
if (!rtw_dbg_is_enabled(rtwdev, RTW_DBG_EFUSE))
return;
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"Power index table (2.4G):\n");
/* CCK base */
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "CCK base\n");
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF G0 G1 G2 G3 G4 G5\n");
for (int i = 0; i < tx_path_count; i++)
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"[%c]: %3u %3u %3u %3u %3u %3u\n",
'A' + i,
table[i].pwr_idx_2g.cck_base[0],
table[i].pwr_idx_2g.cck_base[1],
table[i].pwr_idx_2g.cck_base[2],
table[i].pwr_idx_2g.cck_base[3],
table[i].pwr_idx_2g.cck_base[4],
table[i].pwr_idx_2g.cck_base[5]);
/* CCK diff */
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "CCK diff\n");
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF 1S 2S 3S 4S\n");
for (int i = 0; i < tx_path_count; i++)
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"[%c]: %2d %2d %2d %2d\n",
'A' + i, 0 /* no diff for 1S */,
table[i].pwr_idx_2g.ht_2s_diff.cck,
table[i].pwr_idx_2g.ht_3s_diff.cck,
table[i].pwr_idx_2g.ht_4s_diff.cck);
/* BW40-1S base */
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "BW40-1S base\n");
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF G0 G1 G2 G3 G4\n");
for (int i = 0; i < tx_path_count; i++)
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"[%c]: %3u %3u %3u %3u %3u\n",
'A' + i,
table[i].pwr_idx_2g.bw40_base[0],
table[i].pwr_idx_2g.bw40_base[1],
table[i].pwr_idx_2g.bw40_base[2],
table[i].pwr_idx_2g.bw40_base[3],
table[i].pwr_idx_2g.bw40_base[4]);
/* OFDM diff */
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "OFDM diff\n");
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF 1S 2S 3S 4S\n");
for (int i = 0; i < tx_path_count; i++)
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"[%c]: %2d %2d %2d %2d\n",
'A' + i,
table[i].pwr_idx_2g.ht_1s_diff.ofdm,
table[i].pwr_idx_2g.ht_2s_diff.ofdm,
table[i].pwr_idx_2g.ht_3s_diff.ofdm,
table[i].pwr_idx_2g.ht_4s_diff.ofdm);
/* BW20 diff */
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "BW20 diff\n");
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF 1S 2S 3S 4S\n");
for (int i = 0; i < tx_path_count; i++)
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"[%c]: %2d %2d %2d %2d\n",
'A' + i,
table[i].pwr_idx_2g.ht_1s_diff.bw20,
table[i].pwr_idx_2g.ht_2s_diff.bw20,
table[i].pwr_idx_2g.ht_3s_diff.bw20,
table[i].pwr_idx_2g.ht_4s_diff.bw20);
/* BW40 diff */
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "BW40 diff\n");
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF 1S 2S 3S 4S\n");
for (int i = 0; i < tx_path_count; i++)
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"[%c]: %2d %2d %2d %2d\n",
'A' + i, 0 /* no diff for 1S */,
table[i].pwr_idx_2g.ht_2s_diff.bw40,
table[i].pwr_idx_2g.ht_3s_diff.bw40,
table[i].pwr_idx_2g.ht_4s_diff.bw40);
}
static void efuse_debug_dump(struct rtw_dev *rtwdev,
struct rtw8723x_efuse *map)
{
if (!rtw_dbg_is_enabled(rtwdev, RTW_DBG_EFUSE))
return;
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "EFUSE raw logical map:\n");
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1,
(u8 *)map, sizeof(struct rtw8723x_efuse), false);
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "Parsed rtw8723x EFUSE data:\n");
DBG_EFUSE_VAL(rtwdev, map, rtl_id);
DBG_EFUSE_VAL(rtwdev, map, afe);
rtw8723x_debug_txpwr_limit(rtwdev, map->txpwr_idx_table, 4);
DBG_EFUSE_VAL(rtwdev, map, channel_plan);
DBG_EFUSE_VAL(rtwdev, map, xtal_k);
DBG_EFUSE_VAL(rtwdev, map, thermal_meter);
DBG_EFUSE_VAL(rtwdev, map, iqk_lck);
DBG_EFUSE_VAL(rtwdev, map, pa_type);
DBG_EFUSE_2BYTE(rtwdev, map, lna_type_2g);
DBG_EFUSE_2BYTE(rtwdev, map, lna_type_5g);
DBG_EFUSE_VAL(rtwdev, map, rf_board_option);
DBG_EFUSE_VAL(rtwdev, map, rf_feature_option);
DBG_EFUSE_VAL(rtwdev, map, rf_bt_setting);
DBG_EFUSE_VAL(rtwdev, map, eeprom_version);
DBG_EFUSE_VAL(rtwdev, map, eeprom_customer_id);
DBG_EFUSE_VAL(rtwdev, map, tx_bb_swing_setting_2g);
DBG_EFUSE_VAL(rtwdev, map, tx_pwr_calibrate_rate);
DBG_EFUSE_VAL(rtwdev, map, rf_antenna_option);
DBG_EFUSE_VAL(rtwdev, map, rfe_option);
DBG_EFUSE_2BYTE(rtwdev, map, country_code);
switch (rtw_hci_type(rtwdev)) {
case RTW_HCI_TYPE_PCIE:
rtw8723xe_efuse_debug(rtwdev, map);
break;
case RTW_HCI_TYPE_USB:
rtw8723xu_efuse_debug(rtwdev, map);
break;
case RTW_HCI_TYPE_SDIO:
rtw8723xs_efuse_debug(rtwdev, map);
break;
default:
/* unsupported now */
break;
}
}
static void rtw8723xe_efuse_parsing(struct rtw_efuse *efuse,
struct rtw8723x_efuse *map)
{
ether_addr_copy(efuse->addr, map->e.mac_addr);
}
static void rtw8723xu_efuse_parsing(struct rtw_efuse *efuse,
struct rtw8723x_efuse *map)
{
ether_addr_copy(efuse->addr, map->u.mac_addr);
}
static void rtw8723xs_efuse_parsing(struct rtw_efuse *efuse,
struct rtw8723x_efuse *map)
{
ether_addr_copy(efuse->addr, map->s.mac_addr);
}
static int __rtw8723x_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
{
struct rtw_efuse *efuse = &rtwdev->efuse;
struct rtw8723x_efuse *map;
int i;
map = (struct rtw8723x_efuse *)log_map;
efuse_debug_dump(rtwdev, map);
efuse->rfe_option = 0;
efuse->rf_board_option = map->rf_board_option;
efuse->crystal_cap = map->xtal_k;
efuse->pa_type_2g = map->pa_type;
efuse->lna_type_2g = map->lna_type_2g[0];
efuse->channel_plan = map->channel_plan;
efuse->country_code[0] = map->country_code[0];
efuse->country_code[1] = map->country_code[1];
efuse->bt_setting = map->rf_bt_setting;
efuse->regd = map->rf_board_option & 0x7;
efuse->thermal_meter[0] = map->thermal_meter;
efuse->thermal_meter_k = map->thermal_meter;
efuse->afe = map->afe;
for (i = 0; i < 4; i++)
efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i];
switch (rtw_hci_type(rtwdev)) {
case RTW_HCI_TYPE_PCIE:
rtw8723xe_efuse_parsing(efuse, map);
break;
case RTW_HCI_TYPE_USB:
rtw8723xu_efuse_parsing(efuse, map);
break;
case RTW_HCI_TYPE_SDIO:
rtw8723xs_efuse_parsing(efuse, map);
break;
default:
/* unsupported now */
return -EOPNOTSUPP;
}
return 0;
}
#define BIT_CFENDFORM BIT(9)
#define BIT_WMAC_TCR_ERR0 BIT(12)
#define BIT_WMAC_TCR_ERR1 BIT(13)
#define BIT_TCR_CFG (BIT_CFENDFORM | BIT_WMAC_TCR_ERR0 | \
BIT_WMAC_TCR_ERR1)
#define WLAN_RX_FILTER0 0xFFFF
#define WLAN_RX_FILTER1 0x400
#define WLAN_RX_FILTER2 0xFFFF
#define WLAN_RCR_CFG 0x700060CE
static int __rtw8723x_mac_init(struct rtw_dev *rtwdev)
{
rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 1, WLAN_TXQ_RPT_EN);
rtw_write32(rtwdev, REG_TCR, BIT_TCR_CFG);
rtw_write16(rtwdev, REG_RXFLTMAP0, WLAN_RX_FILTER0);
rtw_write16(rtwdev, REG_RXFLTMAP1, WLAN_RX_FILTER1);
rtw_write16(rtwdev, REG_RXFLTMAP2, WLAN_RX_FILTER2);
rtw_write32(rtwdev, REG_RCR, WLAN_RCR_CFG);
rtw_write32(rtwdev, REG_INT_MIG, 0);
rtw_write32(rtwdev, REG_MCUTST_1, 0x0);
rtw_write8(rtwdev, REG_MISC_CTRL, BIT_DIS_SECOND_CCA);
rtw_write8(rtwdev, REG_2ND_CCA_CTRL, 0);
return 0;
}
static void __rtw8723x_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
{
u8 ldo_pwr;
ldo_pwr = rtw_read8(rtwdev, REG_LDO_EFUSE_CTRL + 3);
if (enable) {
ldo_pwr &= ~BIT_MASK_LDO25_VOLTAGE;
ldo_pwr |= (BIT_LDO25_VOLTAGE_V25 << 4) | BIT_LDO25_EN;
} else {
ldo_pwr &= ~BIT_LDO25_EN;
}
rtw_write8(rtwdev, REG_LDO_EFUSE_CTRL + 3, ldo_pwr);
}
static void
rtw8723x_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs)
{
struct rtw_hal *hal = &rtwdev->hal;
const struct rtw_hw_reg *txagc;
u8 rate, pwr_index;
int j;
for (j = 0; j < rtw_rate_size[rs]; j++) {
rate = rtw_rate_section[rs][j];
pwr_index = hal->tx_pwr_tbl[path][rate];
if (rate >= ARRAY_SIZE(rtw8723x_txagc)) {
rtw_warn(rtwdev, "rate 0x%x isn't supported\n", rate);
continue;
}
txagc = &rtw8723x_txagc[rate];
if (!txagc->addr) {
rtw_warn(rtwdev, "rate 0x%x isn't defined\n", rate);
continue;
}
rtw_write32_mask(rtwdev, txagc->addr, txagc->mask, pwr_index);
}
}
static void __rtw8723x_set_tx_power_index(struct rtw_dev *rtwdev)
{
struct rtw_hal *hal = &rtwdev->hal;
int rs, path;
for (path = 0; path < hal->rf_path_num; path++) {
for (rs = 0; rs <= RTW_RATE_SECTION_HT_1S; rs++)
rtw8723x_set_tx_power_index_by_rate(rtwdev, path, rs);
}
}
static void __rtw8723x_efuse_grant(struct rtw_dev *rtwdev, bool on)
{
if (on) {
rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
rtw_write16_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_ELDR);
rtw_write16_set(rtwdev, REG_SYS_CLKR, BIT_LOADER_CLK_EN | BIT_ANA8M);
} else {
rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
}
}
static void __rtw8723x_false_alarm_statistics(struct rtw_dev *rtwdev)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u32 cck_fa_cnt;
u32 ofdm_fa_cnt;
u32 crc32_cnt;
u32 val32;
/* hold counter */
rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 1);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 1);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KEEP, 1);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KEEP, 1);
cck_fa_cnt = rtw_read32_mask(rtwdev, REG_CCK_FA_LSB_11N, MASKBYTE0);
cck_fa_cnt += rtw_read32_mask(rtwdev, REG_CCK_FA_MSB_11N, MASKBYTE3) << 8;
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE1_11N);
ofdm_fa_cnt = u32_get_bits(val32, BIT_MASK_OFDM_FF_CNT);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_SF_CNT);
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE2_11N);
dm_info->ofdm_cca_cnt = u32_get_bits(val32, BIT_MASK_OFDM_CCA_CNT);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_PF_CNT);
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE3_11N);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_RI_CNT);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_CRC_CNT);
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE4_11N);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_MNS_CNT);
dm_info->cck_fa_cnt = cck_fa_cnt;
dm_info->ofdm_fa_cnt = ofdm_fa_cnt;
dm_info->total_fa_cnt = cck_fa_cnt + ofdm_fa_cnt;
dm_info->cck_err_cnt = rtw_read32(rtwdev, REG_IGI_C_11N);
dm_info->cck_ok_cnt = rtw_read32(rtwdev, REG_IGI_D_11N);
crc32_cnt = rtw_read32(rtwdev, REG_OFDM_CRC32_CNT_11N);
dm_info->ofdm_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_ERR);
dm_info->ofdm_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_OK);
crc32_cnt = rtw_read32(rtwdev, REG_HT_CRC32_CNT_11N);
dm_info->ht_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_ERR);
dm_info->ht_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_OK);
dm_info->vht_err_cnt = 0;
dm_info->vht_ok_cnt = 0;
val32 = rtw_read32(rtwdev, REG_CCK_CCA_CNT_11N);
dm_info->cck_cca_cnt = (u32_get_bits(val32, BIT_MASK_CCK_FA_MSB) << 8) |
u32_get_bits(val32, BIT_MASK_CCK_FA_LSB);
dm_info->total_cca_cnt = dm_info->cck_cca_cnt + dm_info->ofdm_cca_cnt;
/* reset counter */
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 1);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 0);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 1);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 0);
rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 0);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 0);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 0);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 2);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 0);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 2);
rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 1);
rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 0);
}
/* IQK (IQ calibration) */
static
void __rtw8723x_iqk_backup_regs(struct rtw_dev *rtwdev,
struct rtw8723x_iqk_backup_regs *backup)
{
int i;
for (i = 0; i < RTW8723X_IQK_ADDA_REG_NUM; i++)
backup->adda[i] = rtw_read32(rtwdev,
rtw8723x_common.iqk_adda_regs[i]);
for (i = 0; i < RTW8723X_IQK_MAC8_REG_NUM; i++)
backup->mac8[i] = rtw_read8(rtwdev,
rtw8723x_common.iqk_mac8_regs[i]);
for (i = 0; i < RTW8723X_IQK_MAC32_REG_NUM; i++)
backup->mac32[i] = rtw_read32(rtwdev,
rtw8723x_common.iqk_mac32_regs[i]);
for (i = 0; i < RTW8723X_IQK_BB_REG_NUM; i++)
backup->bb[i] = rtw_read32(rtwdev,
rtw8723x_common.iqk_bb_regs[i]);
backup->igia = rtw_read32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0);
backup->igib = rtw_read32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0);
backup->bb_sel_btg = rtw_read32(rtwdev, REG_BB_SEL_BTG);
}
static
void __rtw8723x_iqk_restore_regs(struct rtw_dev *rtwdev,
const struct rtw8723x_iqk_backup_regs *backup)
{
int i;
for (i = 0; i < RTW8723X_IQK_ADDA_REG_NUM; i++)
rtw_write32(rtwdev, rtw8723x_common.iqk_adda_regs[i],
backup->adda[i]);
for (i = 0; i < RTW8723X_IQK_MAC8_REG_NUM; i++)
rtw_write8(rtwdev, rtw8723x_common.iqk_mac8_regs[i],
backup->mac8[i]);
for (i = 0; i < RTW8723X_IQK_MAC32_REG_NUM; i++)
rtw_write32(rtwdev, rtw8723x_common.iqk_mac32_regs[i],
backup->mac32[i]);
for (i = 0; i < RTW8723X_IQK_BB_REG_NUM; i++)
rtw_write32(rtwdev, rtw8723x_common.iqk_bb_regs[i],
backup->bb[i]);
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50);
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, backup->igia);
rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, 0x50);
rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, backup->igib);
rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x01008c00);
rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x01008c00);
}
static
bool __rtw8723x_iqk_similarity_cmp(struct rtw_dev *rtwdev,
s32 result[][IQK_NR],
u8 c1, u8 c2)
{
u32 i, j, diff;
u32 bitmap = 0;
u8 candidate[PATH_NR] = {IQK_ROUND_INVALID, IQK_ROUND_INVALID};
bool ret = true;
s32 tmp1, tmp2;
for (i = 0; i < IQK_NR; i++) {
tmp1 = iqkxy_to_s32(result[c1][i]);
tmp2 = iqkxy_to_s32(result[c2][i]);
diff = abs(tmp1 - tmp2);
if (diff <= MAX_TOLERANCE)
continue;
if ((i == IQK_S1_RX_X || i == IQK_S0_RX_X) && !bitmap) {
if (result[c1][i] + result[c1][i + 1] == 0)
candidate[i / IQK_SX_NR] = c2;
else if (result[c2][i] + result[c2][i + 1] == 0)
candidate[i / IQK_SX_NR] = c1;
else
bitmap |= BIT(i);
} else {
bitmap |= BIT(i);
}
}
if (bitmap != 0)
goto check_sim;
for (i = 0; i < PATH_NR; i++) {
if (candidate[i] == IQK_ROUND_INVALID)
continue;
for (j = i * IQK_SX_NR; j < i * IQK_SX_NR + 2; j++)
result[IQK_ROUND_HYBRID][j] = result[candidate[i]][j];
ret = false;
}
return ret;
check_sim:
for (i = 0; i < IQK_NR; i++) {
j = i & ~1; /* 2 bits are a pair for IQ[X, Y] */
if (bitmap & GENMASK(j + 1, j))
continue;
result[IQK_ROUND_HYBRID][i] = result[c1][i];
}
return false;
}
static u8 __rtw8723x_pwrtrack_get_limit_ofdm(struct rtw_dev *rtwdev)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u8 tx_rate = dm_info->tx_rate;
u8 limit_ofdm = 30;
switch (tx_rate) {
case DESC_RATE1M...DESC_RATE5_5M:
case DESC_RATE11M:
break;
case DESC_RATE6M...DESC_RATE48M:
limit_ofdm = 36;
break;
case DESC_RATE54M:
limit_ofdm = 34;
break;
case DESC_RATEMCS0...DESC_RATEMCS2:
limit_ofdm = 38;
break;
case DESC_RATEMCS3...DESC_RATEMCS4:
limit_ofdm = 36;
break;
case DESC_RATEMCS5...DESC_RATEMCS7:
limit_ofdm = 34;
break;
default:
rtw_warn(rtwdev, "pwrtrack unhandled tx_rate 0x%x\n", tx_rate);
break;
}
return limit_ofdm;
}
static
void __rtw8723x_pwrtrack_set_xtal(struct rtw_dev *rtwdev, u8 therm_path,
u8 delta)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl;
const s8 *pwrtrk_xtal;
s8 xtal_cap;
if (dm_info->thermal_avg[therm_path] >
rtwdev->efuse.thermal_meter[therm_path])
pwrtrk_xtal = tbl->pwrtrk_xtal_p;
else
pwrtrk_xtal = tbl->pwrtrk_xtal_n;
xtal_cap = rtwdev->efuse.crystal_cap & 0x3F;
xtal_cap = clamp_t(s8, xtal_cap + pwrtrk_xtal[delta], 0, 0x3F);
rtw_write32_mask(rtwdev, REG_AFE_CTRL3, BIT_MASK_XTAL,
xtal_cap | (xtal_cap << 6));
}
static
void __rtw8723x_fill_txdesc_checksum(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *txdesc)
{
size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */
__le16 chksum = 0;
__le16 *data = (__le16 *)(txdesc);
struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc;
le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM);
while (words--)
chksum ^= *data++;
chksum = ~chksum;
le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum),
RTW_TX_DESC_W7_TXDESC_CHECKSUM);
}
static void __rtw8723x_coex_cfg_init(struct rtw_dev *rtwdev)
{
/* enable TBTT nterrupt */
rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
/* BT report packet sample rate */
/* 0x790[5:0]=0x5 */
rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5);
/* enable BT counter statistics */
rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1);
/* enable PTA (3-wire function form BT side) */
rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);
rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_PO_BT_PTA_PINS);
/* enable PTA (tx/rx signal form WiFi side) */
rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN);
}
const struct rtw8723x_common rtw8723x_common = {
.iqk_adda_regs = {
0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84,
0xe88, 0xe8c, 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec
},
.iqk_mac8_regs = {0x522, 0x550, 0x551},
.iqk_mac32_regs = {0x40},
.iqk_bb_regs = {
0xc04, 0xc08, 0x874, 0xb68, 0xb6c, 0x870, 0x860, 0x864, 0xa04
},
.ltecoex_addr = {
.ctrl = REG_LTECOEX_CTRL,
.wdata = REG_LTECOEX_WRITE_DATA,
.rdata = REG_LTECOEX_READ_DATA,
},
.rf_sipi_addr = {
[RF_PATH_A] = { .hssi_1 = 0x820, .lssi_read = 0x8a0,
.hssi_2 = 0x824, .lssi_read_pi = 0x8b8},
[RF_PATH_B] = { .hssi_1 = 0x828, .lssi_read = 0x8a4,
.hssi_2 = 0x82c, .lssi_read_pi = 0x8bc},
},
.dig = {
[0] = { .addr = 0xc50, .mask = 0x7f },
[1] = { .addr = 0xc50, .mask = 0x7f },
},
.dig_cck = {
[0] = { .addr = 0xa0c, .mask = 0x3f00 },
},
.prioq_addrs = {
.prio[RTW_DMA_MAPPING_EXTRA] = {
.rsvd = REG_RQPN_NPQ + 2, .avail = REG_RQPN_NPQ + 3,
},
.prio[RTW_DMA_MAPPING_LOW] = {
.rsvd = REG_RQPN + 1, .avail = REG_FIFOPAGE_CTRL_2 + 1,
},
.prio[RTW_DMA_MAPPING_NORMAL] = {
.rsvd = REG_RQPN_NPQ, .avail = REG_RQPN_NPQ + 1,
},
.prio[RTW_DMA_MAPPING_HIGH] = {
.rsvd = REG_RQPN, .avail = REG_FIFOPAGE_CTRL_2,
},
.wsize = false,
},
.lck = __rtw8723x_lck,
.read_efuse = __rtw8723x_read_efuse,
.mac_init = __rtw8723x_mac_init,
.cfg_ldo25 = __rtw8723x_cfg_ldo25,
.set_tx_power_index = __rtw8723x_set_tx_power_index,
.efuse_grant = __rtw8723x_efuse_grant,
.false_alarm_statistics = __rtw8723x_false_alarm_statistics,
.iqk_backup_regs = __rtw8723x_iqk_backup_regs,
.iqk_restore_regs = __rtw8723x_iqk_restore_regs,
.iqk_similarity_cmp = __rtw8723x_iqk_similarity_cmp,
.pwrtrack_get_limit_ofdm = __rtw8723x_pwrtrack_get_limit_ofdm,
.pwrtrack_set_xtal = __rtw8723x_pwrtrack_set_xtal,
.coex_cfg_init = __rtw8723x_coex_cfg_init,
.fill_txdesc_checksum = __rtw8723x_fill_txdesc_checksum,
.debug_txpwr_limit = __rtw8723x_debug_txpwr_limit,
};
EXPORT_SYMBOL(rtw8723x_common);
MODULE_AUTHOR("Realtek Corporation");
MODULE_AUTHOR("Fiona Klute <fiona.klute@gmx.de>");
MODULE_DESCRIPTION("Common functions for Realtek 802.11n wireless 8723x drivers");
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -0,0 +1,518 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright 2024 Fiona Klute
*
* Based on code originally in rtw8723d.[ch],
* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW8723X_H__
#define __RTW8723X_H__
#include "main.h"
#include "debug.h"
#include "phy.h"
#include "reg.h"
enum rtw8723x_path {
PATH_S1,
PATH_S0,
PATH_NR,
};
enum rtw8723x_iqk_round {
IQK_ROUND_0,
IQK_ROUND_1,
IQK_ROUND_2,
IQK_ROUND_HYBRID,
IQK_ROUND_SIZE,
IQK_ROUND_INVALID = 0xff,
};
enum rtw8723x_iqk_result {
IQK_S1_TX_X,
IQK_S1_TX_Y,
IQK_S1_RX_X,
IQK_S1_RX_Y,
IQK_S0_TX_X,
IQK_S0_TX_Y,
IQK_S0_RX_X,
IQK_S0_RX_Y,
IQK_NR,
IQK_SX_NR = IQK_NR / PATH_NR,
};
struct rtw8723xe_efuse {
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
u8 vendor_id[2];
u8 device_id[2];
u8 sub_vendor_id[2];
u8 sub_device_id[2];
};
struct rtw8723xu_efuse {
u8 res4[48]; /* 0xd0 */
u8 vendor_id[2]; /* 0x100 */
u8 product_id[2]; /* 0x102 */
u8 usb_option; /* 0x104 */
u8 res5[2]; /* 0x105 */
u8 mac_addr[ETH_ALEN]; /* 0x107 */
};
struct rtw8723xs_efuse {
u8 res4[0x4a]; /* 0xd0 */
u8 mac_addr[ETH_ALEN]; /* 0x11a */
};
struct rtw8723x_efuse {
__le16 rtl_id;
u8 rsvd[2];
u8 afe;
u8 rsvd1[11];
/* power index for four RF paths */
struct rtw_txpwr_idx txpwr_idx_table[4];
u8 channel_plan; /* 0xb8 */
u8 xtal_k;
u8 thermal_meter;
u8 iqk_lck;
u8 pa_type; /* 0xbc */
u8 lna_type_2g[2]; /* 0xbd */
u8 lna_type_5g[2];
u8 rf_board_option;
u8 rf_feature_option;
u8 rf_bt_setting;
u8 eeprom_version;
u8 eeprom_customer_id;
u8 tx_bb_swing_setting_2g;
u8 res_c7;
u8 tx_pwr_calibrate_rate;
u8 rf_antenna_option; /* 0xc9 */
u8 rfe_option;
u8 country_code[2];
u8 res[3];
union {
struct rtw8723xe_efuse e;
struct rtw8723xu_efuse u;
struct rtw8723xs_efuse s;
};
};
#define RTW8723X_IQK_ADDA_REG_NUM 16
#define RTW8723X_IQK_MAC8_REG_NUM 3
#define RTW8723X_IQK_MAC32_REG_NUM 1
#define RTW8723X_IQK_BB_REG_NUM 9
struct rtw8723x_iqk_backup_regs {
u32 adda[RTW8723X_IQK_ADDA_REG_NUM];
u8 mac8[RTW8723X_IQK_MAC8_REG_NUM];
u32 mac32[RTW8723X_IQK_MAC32_REG_NUM];
u32 bb[RTW8723X_IQK_BB_REG_NUM];
u32 lte_path;
u32 lte_gnt;
u32 bb_sel_btg;
u8 btg_sel;
u8 igia;
u8 igib;
};
struct rtw8723x_common {
/* registers that must be backed up before IQK and restored after */
u32 iqk_adda_regs[RTW8723X_IQK_ADDA_REG_NUM];
u32 iqk_mac8_regs[RTW8723X_IQK_MAC8_REG_NUM];
u32 iqk_mac32_regs[RTW8723X_IQK_MAC32_REG_NUM];
u32 iqk_bb_regs[RTW8723X_IQK_BB_REG_NUM];
/* chip register definitions */
struct rtw_ltecoex_addr ltecoex_addr;
struct rtw_rf_sipi_addr rf_sipi_addr[2];
struct rtw_hw_reg dig[2];
struct rtw_hw_reg dig_cck[1];
struct rtw_prioq_addrs prioq_addrs;
/* common functions */
void (*lck)(struct rtw_dev *rtwdev);
int (*read_efuse)(struct rtw_dev *rtwdev, u8 *log_map);
int (*mac_init)(struct rtw_dev *rtwdev);
void (*cfg_ldo25)(struct rtw_dev *rtwdev, bool enable);
void (*set_tx_power_index)(struct rtw_dev *rtwdev);
void (*efuse_grant)(struct rtw_dev *rtwdev, bool on);
void (*false_alarm_statistics)(struct rtw_dev *rtwdev);
void (*iqk_backup_regs)(struct rtw_dev *rtwdev,
struct rtw8723x_iqk_backup_regs *backup);
void (*iqk_restore_regs)(struct rtw_dev *rtwdev,
const struct rtw8723x_iqk_backup_regs *backup);
bool (*iqk_similarity_cmp)(struct rtw_dev *rtwdev, s32 result[][IQK_NR],
u8 c1, u8 c2);
u8 (*pwrtrack_get_limit_ofdm)(struct rtw_dev *rtwdev);
void (*pwrtrack_set_xtal)(struct rtw_dev *rtwdev, u8 therm_path,
u8 delta);
void (*coex_cfg_init)(struct rtw_dev *rtwdev);
void (*fill_txdesc_checksum)(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *txdesc);
void (*debug_txpwr_limit)(struct rtw_dev *rtwdev,
struct rtw_txpwr_idx *table,
int tx_path_count);
};
extern const struct rtw8723x_common rtw8723x_common;
#define PATH_IQK_RETRY 2
#define MAX_TOLERANCE 5
#define IQK_TX_X_ERR 0x142
#define IQK_TX_Y_ERR 0x42
#define IQK_RX_X_ERR 0x132
#define IQK_RX_Y_ERR 0x36
#define IQK_RX_X_UPPER 0x11a
#define IQK_RX_X_LOWER 0xe6
#define IQK_RX_Y_LMT 0x1a
#define IQK_TX_OK BIT(0)
#define IQK_RX_OK BIT(1)
#define WLAN_TXQ_RPT_EN 0x1F
#define SPUR_THRES 0x16
#define DIS_3WIRE 0xccf000c0
#define EN_3WIRE 0xccc000c0
#define START_PSD 0x400000
#define FREQ_CH5 0xfccd
#define FREQ_CH6 0xfc4d
#define FREQ_CH7 0xffcd
#define FREQ_CH8 0xff4d
#define FREQ_CH13 0xfccd
#define FREQ_CH14 0xff9a
#define RFCFGCH_CHANNEL_MASK GENMASK(7, 0)
#define RFCFGCH_BW_MASK (BIT(11) | BIT(10))
#define RFCFGCH_BW_20M (BIT(11) | BIT(10))
#define RFCFGCH_BW_40M BIT(10)
#define BIT_MASK_RFMOD BIT(0)
#define BIT_LCK BIT(15)
#define REG_GPIO_INTM 0x0048
#define REG_BTG_SEL 0x0067
#define BIT_MASK_BTG_WL BIT(7)
#define REG_LTECOEX_PATH_CONTROL 0x0070
#define REG_LTECOEX_CTRL 0x07c0
#define REG_LTECOEX_WRITE_DATA 0x07c4
#define REG_LTECOEX_READ_DATA 0x07c8
#define REG_PSDFN 0x0808
#define REG_BB_PWR_SAV1_11N 0x0874
#define REG_ANA_PARAM1 0x0880
#define REG_ANALOG_P4 0x088c
#define REG_PSDRPT 0x08b4
#define REG_FPGA1_RFMOD 0x0900
#define REG_BB_SEL_BTG 0x0948
#define REG_BBRX_DFIR 0x0954
#define BIT_MASK_RXBB_DFIR GENMASK(27, 24)
#define BIT_RXBB_DFIR_EN BIT(19)
#define REG_CCK0_SYS 0x0a00
#define BIT_CCK_SIDE_BAND BIT(4)
#define REG_CCK_ANT_SEL_11N 0x0a04
#define REG_PWRTH 0x0a08
#define REG_CCK_FA_RST_11N 0x0a2c
#define BIT_MASK_CCK_CNT_KEEP BIT(12)
#define BIT_MASK_CCK_CNT_EN BIT(13)
#define BIT_MASK_CCK_CNT_KPEN (BIT_MASK_CCK_CNT_KEEP | BIT_MASK_CCK_CNT_EN)
#define BIT_MASK_CCK_FA_KEEP BIT(14)
#define BIT_MASK_CCK_FA_EN BIT(15)
#define BIT_MASK_CCK_FA_KPEN (BIT_MASK_CCK_FA_KEEP | BIT_MASK_CCK_FA_EN)
#define REG_CCK_FA_LSB_11N 0x0a5c
#define REG_CCK_FA_MSB_11N 0x0a58
#define REG_CCK_CCA_CNT_11N 0x0a60
#define BIT_MASK_CCK_FA_MSB GENMASK(7, 0)
#define BIT_MASK_CCK_FA_LSB GENMASK(15, 8)
#define REG_PWRTH2 0x0aa8
#define REG_CSRATIO 0x0aaa
#define REG_OFDM_FA_HOLDC_11N 0x0c00
#define BIT_MASK_OFDM_FA_KEEP BIT(31)
#define REG_BB_RX_PATH_11N 0x0c04
#define REG_TRMUX_11N 0x0c08
#define REG_OFDM_FA_RSTC_11N 0x0c0c
#define BIT_MASK_OFDM_FA_RST BIT(31)
#define REG_A_RXIQI 0x0c14
#define BIT_MASK_RXIQ_S1_X 0x000003FF
#define BIT_MASK_RXIQ_S1_Y1 0x0000FC00
#define BIT_SET_RXIQ_S1_Y1(y) ((y) & 0x3F)
#define REG_OFDM0_RXDSP 0x0c40
#define BIT_MASK_RXDSP GENMASK(28, 24)
#define BIT_EN_RXDSP BIT(9)
#define REG_OFDM_0_ECCA_THRESHOLD 0x0c4c
#define BIT_MASK_OFDM0_EXT_A BIT(31)
#define BIT_MASK_OFDM0_EXT_C BIT(29)
#define BIT_MASK_OFDM0_EXTS (BIT(31) | BIT(29) | BIT(28))
#define BIT_SET_OFDM0_EXTS(a, c, d) (((a) << 31) | ((c) << 29) | ((d) << 28))
#define BIT_MASK_OFDM0_EXTS_B (BIT(27) | BIT(25) | BIT(24))
#define BIT_SET_OFDM0_EXTS_B(a, c, d) (((a) << 27) | ((c) << 25) | ((d) << 24))
#define REG_OFDM0_XAAGC1 0x0c50
#define REG_OFDM0_XBAGC1 0x0c58
#define REG_AGCRSSI 0x0c78
#define REG_OFDM_0_XA_TX_IQ_IMBALANCE 0x0c80
#define REG_OFDM_0_XB_TX_IQ_IMBALANCE 0x0c88
#define BIT_MASK_TXIQ_ELM_A 0x03ff
#define BIT_SET_TXIQ_ELM_ACD(a, c, d) (((d) << 22) | (((c) & 0x3F) << 16) | \
((a) & 0x03ff))
#define BIT_MASK_TXIQ_ELM_C GENMASK(21, 16)
#define BIT_SET_TXIQ_ELM_C2(c) ((c) & 0x3F)
#define BIT_MASK_TXIQ_ELM_D GENMASK(31, 22)
#define REG_TXIQK_MATRIXA_LSB2_11N 0x0c94
#define BIT_SET_TXIQ_ELM_C1(c) (((c) & 0x000003C0) >> 6)
#define REG_RXIQK_MATRIX_LSB_11N 0x0ca0
#define BIT_MASK_RXIQ_S1_Y2 0xF0000000
#define BIT_SET_RXIQ_S1_Y2(y) (((y) >> 6) & 0xF)
#define REG_TXIQ_AB_S0 0x0cd0
#define BIT_MASK_TXIQ_A_S0 0x000007FE
#define BIT_MASK_TXIQ_A_EXT_S0 BIT(0)
#define BIT_MASK_TXIQ_B_S0 0x0007E000
#define REG_TXIQ_CD_S0 0x0cd4
#define BIT_MASK_TXIQ_C_S0 0x000007FE
#define BIT_MASK_TXIQ_C_EXT_S0 BIT(0)
#define BIT_MASK_TXIQ_D_S0 GENMASK(22, 13)
#define BIT_MASK_TXIQ_D_EXT_S0 BIT(12)
#define REG_RXIQ_AB_S0 0x0cd8
#define BIT_MASK_RXIQ_X_S0 0x000003FF
#define BIT_MASK_RXIQ_Y_S0 0x003FF000
#define REG_OFDM_FA_TYPE1_11N 0x0cf0
#define BIT_MASK_OFDM_FF_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_SF_CNT GENMASK(31, 16)
#define REG_OFDM_FA_RSTD_11N 0x0d00
#define BIT_MASK_OFDM_FA_RST1 BIT(27)
#define BIT_MASK_OFDM_FA_KEEP1 BIT(31)
#define REG_CTX 0x0d03
#define BIT_MASK_CTX_TYPE GENMASK(6, 4)
#define REG_OFDM1_CFOTRK 0x0d2c
#define BIT_EN_CFOTRK BIT(28)
#define REG_OFDM1_CSI1 0x0d40
#define REG_OFDM1_CSI2 0x0d44
#define REG_OFDM1_CSI3 0x0d48
#define REG_OFDM1_CSI4 0x0d4c
#define REG_OFDM_FA_TYPE2_11N 0x0da0
#define BIT_MASK_OFDM_CCA_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_PF_CNT GENMASK(31, 16)
#define REG_OFDM_FA_TYPE3_11N 0x0da4
#define BIT_MASK_OFDM_RI_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_CRC_CNT GENMASK(31, 16)
#define REG_OFDM_FA_TYPE4_11N 0x0da8
#define BIT_MASK_OFDM_MNS_CNT GENMASK(15, 0)
#define REG_FPGA0_IQK_11N 0x0e28
#define BIT_MASK_IQK_MOD 0xffffff00
#define EN_IQK 0x808000
#define RST_IQK 0x000000
#define REG_TXIQK_TONE_A_11N 0x0e30
#define REG_RXIQK_TONE_A_11N 0x0e34
#define REG_TXIQK_PI_A_11N 0x0e38
#define REG_RXIQK_PI_A_11N 0x0e3c
#define REG_TXIQK_11N 0x0e40
#define BIT_SET_TXIQK_11N(x, y) (0x80007C00 | ((x) << 16) | (y))
#define REG_RXIQK_11N 0x0e44
#define REG_IQK_AGC_PTS_11N 0x0e48
#define REG_IQK_AGC_RSP_11N 0x0e4c
#define REG_TX_IQK_TONE_B 0x0e50
#define REG_RX_IQK_TONE_B 0x0e54
#define REG_TXIQK_PI_B 0x0e58
#define REG_RXIQK_PI_B 0x0e5c
#define REG_IQK_RES_TX 0x0e94
#define BIT_MASK_RES_TX GENMASK(25, 16)
#define REG_IQK_RES_TY 0x0e9c
#define BIT_MASK_RES_TY GENMASK(25, 16)
#define REG_IQK_RES_RX 0x0ea4
#define BIT_MASK_RES_RX GENMASK(25, 16)
#define REG_IQK_RES_RY 0x0eac
#define BIT_IQK_TX_FAIL BIT(28)
#define BIT_IQK_RX_FAIL BIT(27)
#define BIT_IQK_DONE BIT(26)
#define BIT_MASK_RES_RY GENMASK(25, 16)
#define REG_PAGE_F_RST_11N 0x0f14
#define BIT_MASK_F_RST_ALL BIT(16)
#define REG_IGI_C_11N 0x0f84
#define REG_IGI_D_11N 0x0f88
#define REG_HT_CRC32_CNT_11N 0x0f90
#define BIT_MASK_HT_CRC_OK GENMASK(15, 0)
#define BIT_MASK_HT_CRC_ERR GENMASK(31, 16)
#define REG_OFDM_CRC32_CNT_11N 0x0f94
#define BIT_MASK_OFDM_LCRC_OK GENMASK(15, 0)
#define BIT_MASK_OFDM_LCRC_ERR GENMASK(31, 16)
#define REG_HT_CRC32_CNT_11N_AGG 0x0fb8
#define OFDM_SWING_A(swing) FIELD_GET(GENMASK(9, 0), swing)
#define OFDM_SWING_B(swing) FIELD_GET(GENMASK(15, 10), swing)
#define OFDM_SWING_C(swing) FIELD_GET(GENMASK(21, 16), swing)
#define OFDM_SWING_D(swing) FIELD_GET(GENMASK(31, 22), swing)
static inline s32 iqkxy_to_s32(s32 val)
{
/* val is Q10.8 */
return sign_extend32(val, 9);
}
static inline s32 iqk_mult(s32 x, s32 y, s32 *ext)
{
/* x, y and return value are Q10.8 */
s32 t;
t = x * y;
if (ext)
*ext = (t >> 7) & 0x1; /* Q.16 --> Q.9; get LSB of Q.9 */
return (t >> 8); /* Q.16 --> Q.8 */
}
static inline
void rtw8723x_debug_txpwr_limit(struct rtw_dev *rtwdev,
struct rtw_txpwr_idx *table,
int tx_path_count)
{
rtw8723x_common.debug_txpwr_limit(rtwdev, table, tx_path_count);
}
static inline void rtw8723x_lck(struct rtw_dev *rtwdev)
{
rtw8723x_common.lck(rtwdev);
}
static inline int rtw8723x_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
{
return rtw8723x_common.read_efuse(rtwdev, log_map);
}
static inline int rtw8723x_mac_init(struct rtw_dev *rtwdev)
{
return rtw8723x_common.mac_init(rtwdev);
}
static inline void rtw8723x_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
{
rtw8723x_common.cfg_ldo25(rtwdev, enable);
}
static inline void rtw8723x_set_tx_power_index(struct rtw_dev *rtwdev)
{
rtw8723x_common.set_tx_power_index(rtwdev);
}
static inline void rtw8723x_efuse_grant(struct rtw_dev *rtwdev, bool on)
{
rtw8723x_common.efuse_grant(rtwdev, on);
}
static inline void rtw8723x_false_alarm_statistics(struct rtw_dev *rtwdev)
{
rtw8723x_common.false_alarm_statistics(rtwdev);
}
static inline
void rtw8723x_iqk_backup_regs(struct rtw_dev *rtwdev,
struct rtw8723x_iqk_backup_regs *backup)
{
rtw8723x_common.iqk_backup_regs(rtwdev, backup);
}
static inline
void rtw8723x_iqk_restore_regs(struct rtw_dev *rtwdev,
const struct rtw8723x_iqk_backup_regs *backup)
{
rtw8723x_common.iqk_restore_regs(rtwdev, backup);
}
static inline
bool rtw8723x_iqk_similarity_cmp(struct rtw_dev *rtwdev, s32 result[][IQK_NR],
u8 c1, u8 c2)
{
return rtw8723x_common.iqk_similarity_cmp(rtwdev, result, c1, c2);
}
static inline u8 rtw8723x_pwrtrack_get_limit_ofdm(struct rtw_dev *rtwdev)
{
return rtw8723x_common.pwrtrack_get_limit_ofdm(rtwdev);
}
static inline
void rtw8723x_pwrtrack_set_xtal(struct rtw_dev *rtwdev, u8 therm_path,
u8 delta)
{
rtw8723x_common.pwrtrack_set_xtal(rtwdev, therm_path, delta);
}
static inline void rtw8723x_coex_cfg_init(struct rtw_dev *rtwdev)
{
rtw8723x_common.coex_cfg_init(rtwdev);
}
static inline
void rtw8723x_fill_txdesc_checksum(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *txdesc)
{
rtw8723x_common.fill_txdesc_checksum(rtwdev, pkt_info, txdesc);
}
/* IQK helper functions, defined as inline so they can be shared
* without needing an EXPORT_SYMBOL each.
*/
static inline void
rtw8723x_iqk_backup_path_ctrl(struct rtw_dev *rtwdev,
struct rtw8723x_iqk_backup_regs *backup)
{
backup->btg_sel = rtw_read8(rtwdev, REG_BTG_SEL);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] original 0x67 = 0x%x\n",
backup->btg_sel);
}
static inline void rtw8723x_iqk_config_path_ctrl(struct rtw_dev *rtwdev)
{
rtw_write32_mask(rtwdev, REG_PAD_CTRL1, BIT_BT_BTG_SEL, 0x1);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] set 0x67 = 0x%x\n",
rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
}
static inline void
rtw8723x_iqk_restore_path_ctrl(struct rtw_dev *rtwdev,
const struct rtw8723x_iqk_backup_regs *backup)
{
rtw_write8(rtwdev, REG_BTG_SEL, backup->btg_sel);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] restore 0x67 = 0x%x\n",
rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
}
static inline void
rtw8723x_iqk_backup_lte_path_gnt(struct rtw_dev *rtwdev,
struct rtw8723x_iqk_backup_regs *backup)
{
backup->lte_path = rtw_read32(rtwdev, REG_LTECOEX_PATH_CONTROL);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0038);
mdelay(1);
backup->lte_gnt = rtw_read32(rtwdev, REG_LTECOEX_READ_DATA);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] OriginalGNT = 0x%x\n",
backup->lte_gnt);
}
static inline void
rtw8723x_iqk_config_lte_path_gnt(struct rtw_dev *rtwdev,
u32 write_data)
{
rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, write_data);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc0020038);
rtw_write32_mask(rtwdev, REG_LTECOEX_PATH_CONTROL,
BIT_LTE_MUX_CTRL_PATH, 0x1);
}
static inline void
rtw8723x_iqk_restore_lte_path_gnt(struct rtw_dev *rtwdev,
const struct rtw8723x_iqk_backup_regs *bak)
{
rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, bak->lte_gnt);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc00f0038);
rtw_write32(rtwdev, REG_LTECOEX_PATH_CONTROL, bak->lte_path);
}
/* set all ADDA registers to the given value */
static inline void rtw8723x_iqk_path_adda_on(struct rtw_dev *rtwdev, u32 value)
{
for (int i = 0; i < RTW8723X_IQK_ADDA_REG_NUM; i++)
rtw_write32(rtwdev, rtw8723x_common.iqk_adda_regs[i], value);
}
#endif /* __RTW8723X_H__ */

View File

@ -40,6 +40,8 @@ enum rtw_rx_desc_enc {
le32_get_bits(*((__le32 *)(rxdesc) + 0x02), GENMASK(30, 29))
#define GET_RX_DESC_TSFL(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x05), GENMASK(31, 0))
#define GET_RX_DESC_BW(rxdesc) \
(le32_get_bits(*((__le32 *)(rxdesc) + 0x04), GENMASK(31, 24)))
void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct sk_buff *skb);

View File

@ -28,6 +28,9 @@ config RTW89_8852B
config RTW89_8852C
tristate
config RTW89_8922A
tristate
config RTW89_8851BE
tristate "Realtek 8851BE PCI wireless network (Wi-Fi 6) adapter"
depends on PCI
@ -72,6 +75,18 @@ config RTW89_8852CE
802.11ax PCIe wireless network (Wi-Fi 6E) adapter
config RTW89_8922AE
tristate "Realtek 8922AE PCI wireless network (Wi-Fi 7) adapter"
depends on PCI
select RTW89_CORE
select RTW89_PCI
select RTW89_8922A
help
Select this option will enable support for 8922AE chipset
802.11be PCIe wireless network (Wi-Fi 7) adapter
supporting 2x2 2GHz/5GHz/6GHz 4096-QAM 160MHz channels.
config RTW89_DEBUG
bool

View File

@ -4,10 +4,13 @@ obj-$(CONFIG_RTW89_CORE) += rtw89_core.o
rtw89_core-y += core.o \
mac80211.o \
mac.o \
mac_be.o \
phy.o \
phy_be.o \
fw.o \
cam.o \
efuse.o \
efuse_be.o \
regd.o \
sar.o \
coex.o \
@ -54,8 +57,15 @@ rtw89_8852c-objs := rtw8852c.o \
obj-$(CONFIG_RTW89_8852CE) += rtw89_8852ce.o
rtw89_8852ce-objs := rtw8852ce.o
obj-$(CONFIG_RTW89_8922A) += rtw89_8922a.o
rtw89_8922a-objs := rtw8922a.o \
rtw8922a_rfk.o
obj-$(CONFIG_RTW89_8922AE) += rtw89_8922ae.o
rtw89_8922ae-objs := rtw8922ae.o
rtw89_core-$(CONFIG_RTW89_DEBUG) += debug.o
obj-$(CONFIG_RTW89_PCI) += rtw89_pci.o
rtw89_pci-y := pci.o
rtw89_pci-y := pci.o pci_be.o

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@
#include "core.h"
#define BTC_H2C_MAXLEN 2020
#define BTC_TLV_SLOT_ID_LEN_V7 1
enum btc_mode {
BTC_MODE_NORMAL,
@ -201,6 +202,25 @@ enum btc_3cx_type {
BTC_3CX_MAX,
};
enum btc_chip_feature {
BTC_FEAT_PTA_ONOFF_CTRL = BIT(0), /* on/off ctrl by HW (not 0x73[2]) */
BTC_FEAT_NONBTG_GWL_THRU = BIT(1), /* non-BTG GNT_WL!=0 if GNT_BT = 1 */
BTC_FEAT_WLAN_ACT_MUX = BIT(2), /* separate wlan_act/gnt mux */
BTC_FEAT_NEW_BBAPI_FLOW = BIT(3), /* new btg_ctrl/pre_agc_ctrl */
BTC_FEAT_MLO_SUPPORT = BIT(4),
BTC_FEAT_H2C_MACRO = BIT(5),
};
enum btc_wl_mode {
BTC_WL_MODE_11B = 0,
BTC_WL_MODE_11A = 1,
BTC_WL_MODE_11G = 2,
BTC_WL_MODE_HT = 3,
BTC_WL_MODE_VHT = 4,
BTC_WL_MODE_HE = 5,
BTC_WL_MODE_NUM,
};
void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev);
void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev);
void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode);
@ -261,4 +281,56 @@ static inline u16 rtw89_coex_query_bt_req_len(struct rtw89_dev *rtwdev,
return btc->bt_req_len;
}
static inline u32 rtw89_get_antpath_type(u8 phy_map, u8 type)
{
return ((phy_map << 8) + type);
}
static inline
void _slot_set_le(struct rtw89_btc *btc, u8 sid, __le16 dura, __le32 tbl, __le16 type)
{
if (btc->ver->fcxslots == 1) {
btc->dm.slot.v1[sid].dur = dura;
btc->dm.slot.v1[sid].cxtbl = tbl;
btc->dm.slot.v1[sid].cxtype = type;
} else if (btc->ver->fcxslots == 7) {
btc->dm.slot.v7[sid].dur = dura;
btc->dm.slot.v7[sid].cxtype = type;
btc->dm.slot.v7[sid].cxtbl = tbl;
}
}
static inline
void _slot_set(struct rtw89_btc *btc, u8 sid, u16 dura, u32 tbl, u16 type)
{
_slot_set_le(btc, sid, cpu_to_le16(dura), cpu_to_le32(tbl), cpu_to_le16(type));
}
static inline
void _slot_set_dur(struct rtw89_btc *btc, u8 sid, u16 dura)
{
if (btc->ver->fcxslots == 1)
btc->dm.slot.v1[sid].dur = cpu_to_le16(dura);
else if (btc->ver->fcxslots == 7)
btc->dm.slot.v7[sid].dur = cpu_to_le16(dura);
}
static inline
void _slot_set_type(struct rtw89_btc *btc, u8 sid, u16 type)
{
if (btc->ver->fcxslots == 1)
btc->dm.slot.v1[sid].cxtype = cpu_to_le16(type);
else if (btc->ver->fcxslots == 7)
btc->dm.slot.v7[sid].cxtype = cpu_to_le16(type);
}
static inline
void _slot_set_tbl(struct rtw89_btc *btc, u8 sid, u32 tbl)
{
if (btc->ver->fcxslots == 1)
btc->dm.slot.v1[sid].cxtbl = cpu_to_le32(tbl);
else if (btc->ver->fcxslots == 7)
btc->dm.slot.v7[sid].cxtbl = cpu_to_le32(tbl);
}
#endif

View File

@ -799,6 +799,7 @@ struct rtw89_rx_phy_ppdu {
enum rtw89_mac_idx {
RTW89_MAC_0 = 0,
RTW89_MAC_1 = 1,
RTW89_MAC_NUM,
};
enum rtw89_phy_idx {
@ -1230,6 +1231,13 @@ enum rtw89_btc_wl_state_cnt {
BTC_WCNT_RFK_REJECT,
BTC_WCNT_RFK_TIMEOUT,
BTC_WCNT_CH_UPDATE,
BTC_WCNT_DBCC_ALL_2G,
BTC_WCNT_DBCC_CHG,
BTC_WCNT_RX_OK_LAST,
BTC_WCNT_RX_OK_LAST2S,
BTC_WCNT_RX_ERR_LAST,
BTC_WCNT_RX_ERR_LAST2S,
BTC_WCNT_RX_LAST,
BTC_WCNT_NUM
};
@ -1349,6 +1357,14 @@ struct rtw89_traffic_stats {
u16 rx_rate;
};
struct rtw89_btc_chdef {
u8 center_ch;
u8 band;
u8 chan;
enum rtw89_sc_offset offset;
enum rtw89_bandwidth bw;
};
struct rtw89_btc_statistic {
u8 rssi; /* 0%~110% (dBm = rssi -110) */
struct rtw89_traffic_stats traffic;
@ -1357,6 +1373,7 @@ struct rtw89_btc_statistic {
#define BTC_WL_RSSI_THMAX 4
struct rtw89_btc_wl_link_info {
struct rtw89_btc_chdef chdef;
struct rtw89_btc_statistic stat;
enum rtw89_tfc_dir dir;
u8 rssi_state[BTC_WL_RSSI_THMAX];
@ -1370,6 +1387,7 @@ struct rtw89_btc_wl_link_info {
u8 phy;
u8 dtim_period;
u8 mode;
u8 tx_1ss_limit;
u8 mac_id;
u8 tx_retry;
@ -1379,6 +1397,7 @@ struct rtw89_btc_wl_link_info {
u32 tx_time;
u32 client_cnt;
u32 rx_rate_drop_cnt;
u32 noa_duration;
u32 active: 1;
u32 noa: 1;
@ -1589,6 +1608,42 @@ struct rtw89_btc_wl_role_info_v2 { /* struct size must be n*4 bytes */
u32 rsvd: 27;
};
struct rtw89_btc_wl_rlink { /* H2C info, struct size must be n*4 bytes */
u8 connected;
u8 pid;
u8 phy;
u8 noa;
u8 rf_band; /* enum band_type RF band: 2.4G/5G/6G */
u8 active; /* 0:rlink is under doze */
u8 bw; /* enum channel_width */
u8 role; /*enum role_type */
u8 ch;
u8 noa_dur; /* ms */
u8 client_cnt; /* for Role = P2P-Go/AP */
u8 mode; /* wifi protocol */
} __packed;
#define RTW89_BE_BTC_WL_MAX_ROLE_NUMBER 6
struct rtw89_btc_wl_role_info_v8 { /* H2C info, struct size must be n*4 bytes */
u8 connect_cnt;
u8 link_mode;
u8 link_mode_chg;
u8 p2p_2g;
u8 pta_req_band;
u8 dbcc_en; /* 1+1 and 2.4G-included */
u8 dbcc_chg;
u8 dbcc_2g_phy; /* which phy operate in 2G, HW_PHY_0 or HW_PHY_1 */
struct rtw89_btc_wl_rlink rlink[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER][RTW89_MAC_NUM];
u32 role_map;
u32 mrole_type; /* btc_wl_mrole_type */
u32 mrole_noa_duration; /* ms */
} __packed;
struct rtw89_btc_wl_ver_info {
u32 fw_coex; /* match with which coex_ver */
u32 fw;
@ -1724,12 +1779,14 @@ struct rtw89_btc_wl_nhm {
struct rtw89_btc_wl_info {
struct rtw89_btc_wl_link_info link_info[RTW89_PORT_NUM];
struct rtw89_btc_wl_link_info rlink_info[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER][RTW89_MAC_NUM];
struct rtw89_btc_wl_rfk_info rfk_info;
struct rtw89_btc_wl_ver_info ver_info;
struct rtw89_btc_wl_afh_info afh_info;
struct rtw89_btc_wl_role_info role_info;
struct rtw89_btc_wl_role_info_v1 role_info_v1;
struct rtw89_btc_wl_role_info_v2 role_info_v2;
struct rtw89_btc_wl_role_info_v8 role_info_v8;
struct rtw89_btc_wl_scan_info scan_info;
struct rtw89_btc_wl_dbcc_info dbcc_info;
struct rtw89_btc_rf_para rf_para;
@ -1740,7 +1797,10 @@ struct rtw89_btc_wl_info {
u8 rssi_level;
u8 cn_report;
u8 coex_mode;
u8 pta_req_mac;
bool is_5g_hi_channel;
bool pta_reg_mac_chg;
bool bg_mode;
bool scbd_change;
u32 scbd;
@ -2233,6 +2293,40 @@ struct rtw89_btc_fbtc_slots {
struct rtw89_btc_fbtc_slot slot[CXST_MAX];
} __packed;
struct rtw89_btc_fbtc_slot_v7 {
__le16 dur; /* slot duration */
__le16 cxtype;
__le32 cxtbl;
} __packed;
struct rtw89_btc_fbtc_slot_u16 {
__le16 dur; /* slot duration */
__le16 cxtype;
__le16 cxtbl_l16; /* coex table [15:0] */
__le16 cxtbl_h16; /* coex table [31:16] */
} __packed;
struct rtw89_btc_fbtc_1slot_v7 {
u8 fver;
u8 sid; /* slot id */
__le16 rsvd;
struct rtw89_btc_fbtc_slot_v7 slot;
} __packed;
struct rtw89_btc_fbtc_slots_v7 {
u8 fver;
u8 slot_cnt;
u8 rsvd0;
u8 rsvd1;
struct rtw89_btc_fbtc_slot_u16 slot[CXST_MAX];
__le32 update_map;
} __packed;
union rtw89_btc_fbtc_slots_info {
struct rtw89_btc_fbtc_slots v1;
struct rtw89_btc_fbtc_slots_v7 v7;
} __packed;
struct rtw89_btc_fbtc_step {
u8 type;
u8 val;
@ -2551,9 +2645,14 @@ struct rtw89_btc_trx_info {
u32 rx_err_ratio;
};
union rtw89_btc_fbtc_slot_u {
struct rtw89_btc_fbtc_slot v1[CXST_MAX];
struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX];
};
struct rtw89_btc_dm {
struct rtw89_btc_fbtc_slot slot[CXST_MAX];
struct rtw89_btc_fbtc_slot slot_now[CXST_MAX];
union rtw89_btc_fbtc_slot_u slot;
union rtw89_btc_fbtc_slot_u slot_now;
struct rtw89_btc_fbtc_tdma tdma;
struct rtw89_btc_fbtc_tdma tdma_now;
struct rtw89_mac_ax_coex_gnt gnt;
@ -2569,6 +2668,8 @@ struct rtw89_btc_dm {
u32 update_slot_map;
u32 set_ant_path;
u32 e2g_slot_limit;
u32 e2g_slot_nulltx_time;
u32 wl_only: 1;
u32 wl_fw_cx_offload: 1;
@ -2596,6 +2697,7 @@ struct rtw89_btc_dm {
u8 wl_pre_agc: 2;
u8 wl_lna2: 1;
u8 wl_pre_agc_rb: 2;
u8 bt_select: 2; /* 0:s0, 1:s1, 2:s0 & s1, refer to enum btc_bt_index */
};
struct rtw89_btc_ctrl {
@ -2691,7 +2793,7 @@ struct rtw89_btc_rpt_fbtc_tdma {
struct rtw89_btc_rpt_fbtc_slots {
struct rtw89_btc_rpt_cmn_info cinfo; /* common info, by driver */
struct rtw89_btc_fbtc_slots finfo; /* info from fw */
union rtw89_btc_fbtc_slots_info finfo; /* info from fw */
};
struct rtw89_btc_rpt_fbtc_cysta {

View File

@ -4120,6 +4120,48 @@ int rtw89_fw_h2c_cxdrv_role_v2(struct rtw89_dev *rtwdev, u8 type)
return ret;
}
int rtw89_fw_h2c_cxdrv_role_v8(struct rtw89_dev *rtwdev, u8 type)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_wl_role_info_v8 *role = &btc->cx.wl.role_info_v8;
struct rtw89_h2c_cxrole_v8 *h2c;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
if (!skb) {
rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_ctrl\n");
return -ENOMEM;
}
skb_put(skb, len);
h2c = (struct rtw89_h2c_cxrole_v8 *)skb->data;
h2c->hdr.type = type;
h2c->hdr.len = len - H2C_LEN_CXDRVHDR_V7;
memcpy(&h2c->_u8, role, sizeof(h2c->_u8));
h2c->_u32.role_map = cpu_to_le32(role->role_map);
h2c->_u32.mrole_type = cpu_to_le32(role->mrole_type);
h2c->_u32.mrole_noa_duration = cpu_to_le32(role->mrole_noa_duration);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_OUTSRC, BTFC_SET,
SET_DRV_INFO, 0, 0,
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_LEN_CXDRVINFO_CTRL (4 + H2C_LEN_CXDRVHDR)
int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev, u8 type)
{

View File

@ -2395,6 +2395,32 @@ struct rtw89_h2c_cxctrl_v7 {
#define H2C_LEN_CXDRVHDR sizeof(struct rtw89_h2c_cxhdr)
#define H2C_LEN_CXDRVHDR_V7 sizeof(struct rtw89_h2c_cxhdr_v7)
struct rtw89_btc_wl_role_info_v8_u8 {
u8 connect_cnt;
u8 link_mode;
u8 link_mode_chg;
u8 p2p_2g;
u8 pta_req_band;
u8 dbcc_en;
u8 dbcc_chg;
u8 dbcc_2g_phy;
struct rtw89_btc_wl_rlink rlink[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER][RTW89_MAC_NUM];
} __packed;
struct rtw89_btc_wl_role_info_v8_u32 {
__le32 role_map;
__le32 mrole_type;
__le32 mrole_noa_duration;
} __packed;
struct rtw89_h2c_cxrole_v8 {
struct rtw89_h2c_cxhdr hdr;
struct rtw89_btc_wl_role_info_v8_u8 _u8;
struct rtw89_btc_wl_role_info_v8_u32 _u32;
} __packed;
struct rtw89_h2c_cxinit {
struct rtw89_h2c_cxhdr hdr;
u8 ant_type;
@ -4568,6 +4594,7 @@ int rtw89_fw_h2c_cxdrv_init_v7(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_role_v1(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_role_v2(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_role_v8(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_ctrl_v7(struct rtw89_dev *rtwdev, u8 type);
int rtw89_fw_h2c_cxdrv_trx(struct rtw89_dev *rtwdev, u8 type);

View File

@ -122,6 +122,7 @@ static u64 get_eht_ra_mask(struct ieee80211_sta *sta)
struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap;
struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs_nss_20mhz;
struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss;
u8 *he_phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info;
switch (sta->deflink.bandwidth) {
case IEEE80211_STA_RX_BW_320:
@ -132,15 +133,19 @@ static u64 get_eht_ra_mask(struct ieee80211_sta *sta)
mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._160;
/* MCS 9, 11, 13 */
return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3);
case IEEE80211_STA_RX_BW_20:
if (!(he_phy_cap[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
mcs_nss_20mhz = &eht_cap->eht_mcs_nss_supp.only_20mhz;
/* MCS 7, 9, 11, 13 */
return get_eht_mcs_ra_mask(mcs_nss_20mhz->rx_tx_max_nss, 7, 4);
}
fallthrough;
case IEEE80211_STA_RX_BW_80:
default:
mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._80;
/* MCS 9, 11, 13 */
return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3);
case IEEE80211_STA_RX_BW_20:
mcs_nss_20mhz = &eht_cap->eht_mcs_nss_supp.only_20mhz;
/* MCS 7, 9, 11, 13 */
return get_eht_mcs_ra_mask(mcs_nss_20mhz->rx_tx_max_nss, 7, 4);
}
}

View File

@ -2257,6 +2257,138 @@ static void rtw8922a_btc_init_cfg(struct rtw89_dev *rtwdev)
btc->cx.wl.status.map.init_ok = true;
}
static void
rtw8922a_btc_set_wl_txpwr_ctrl(struct rtw89_dev *rtwdev, u32 txpwr_val)
{
u16 ctrl_all_time = u32_get_bits(txpwr_val, GENMASK(15, 0));
u16 ctrl_gnt_bt = u32_get_bits(txpwr_val, GENMASK(31, 16));
switch (ctrl_all_time) {
case 0xffff:
rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_RATE_CTRL,
B_BE_FORCE_PWR_BY_RATE_EN, 0x0);
rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_RATE_CTRL,
B_BE_FORCE_PWR_BY_RATE_VAL, 0x0);
break;
default:
rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_RATE_CTRL,
B_BE_FORCE_PWR_BY_RATE_VAL, ctrl_all_time);
rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_RATE_CTRL,
B_BE_FORCE_PWR_BY_RATE_EN, 0x1);
break;
}
switch (ctrl_gnt_bt) {
case 0xffff:
rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_REG_CTRL,
B_BE_PWR_BT_EN, 0x0);
rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_COEX_CTRL,
B_BE_PWR_BT_VAL, 0x0);
break;
default:
rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_COEX_CTRL,
B_BE_PWR_BT_VAL, ctrl_gnt_bt);
rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, R_BE_PWR_REG_CTRL,
B_BE_PWR_BT_EN, 0x1);
break;
}
}
static
s8 rtw8922a_btc_get_bt_rssi(struct rtw89_dev *rtwdev, s8 val)
{
return clamp_t(s8, val, -100, 0) + 100;
}
static const struct rtw89_btc_rf_trx_para rtw89_btc_8922a_rf_ul[] = {
{255, 0, 0, 7}, /* 0 -> original */
{255, 2, 0, 7}, /* 1 -> for BT-connected ACI issue && BTG co-rx */
{255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */
{255, 0, 0, 7}, /* 3- >reserved for shared-antenna */
{255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */
{255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */
{6, 1, 0, 7},
{13, 1, 0, 7},
{13, 1, 0, 7}
};
static const struct rtw89_btc_rf_trx_para rtw89_btc_8922a_rf_dl[] = {
{255, 0, 0, 7}, /* 0 -> original */
{255, 2, 0, 7}, /* 1 -> reserved for shared-antenna */
{255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */
{255, 0, 0, 7}, /* 3- >reserved for shared-antenna */
{255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */
{255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */
{255, 1, 0, 7},
{255, 1, 0, 7},
{255, 1, 0, 7}
};
static const u8 rtw89_btc_8922a_wl_rssi_thres[BTC_WL_RSSI_THMAX] = {60, 50, 40, 30};
static const u8 rtw89_btc_8922a_bt_rssi_thres[BTC_BT_RSSI_THMAX] = {50, 40, 30, 20};
static const struct rtw89_btc_fbtc_mreg rtw89_btc_8922a_mon_reg[] = {
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe300),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe320),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe324),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe328),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe32c),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe330),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe334),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe338),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe344),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe348),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe34c),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xe350),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0x11a2c),
RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0x11a50),
RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x980),
RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x660),
RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x1660),
RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x418c),
RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x518c),
};
static
void rtw8922a_btc_update_bt_cnt(struct rtw89_dev *rtwdev)
{
/* Feature move to firmware */
}
static
void rtw8922a_btc_wl_s1_standby(struct rtw89_dev *rtwdev, bool state)
{
if (!state) {
rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x80000);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x1);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD1, RFREG_MASK, 0x0c110);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x01018);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x00000);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x80000);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x1);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD1, RFREG_MASK, 0x0c110);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0x01018);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x00000);
} else {
rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x80000);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x1);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD1, RFREG_MASK, 0x0c110);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x09018);
rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x00000);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x80000);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x1);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD1, RFREG_MASK, 0x0c110);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0x09018);
rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x00000);
}
}
static void rtw8922a_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
{
}
static void rtw8922a_fill_freq_with_ppdu(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu,
struct ieee80211_rx_status *status)
@ -2367,6 +2499,13 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = {
.btc_set_rfe = rtw8922a_btc_set_rfe,
.btc_init_cfg = rtw8922a_btc_init_cfg,
.btc_set_wl_pri = NULL,
.btc_set_wl_txpwr_ctrl = rtw8922a_btc_set_wl_txpwr_ctrl,
.btc_get_bt_rssi = rtw8922a_btc_get_bt_rssi,
.btc_update_bt_cnt = rtw8922a_btc_update_bt_cnt,
.btc_wl_s1_standby = rtw8922a_btc_wl_s1_standby,
.btc_set_wl_rx_gain = rtw8922a_btc_set_wl_rx_gain,
.btc_set_policy = rtw89_btc_set_policy_v1,
};
const struct rtw89_chip_info rtw8922a_chip_info = {
@ -2436,7 +2575,22 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
.efuse_blocks = rtw8922a_efuse_blocks,
.phycap_addr = 0x1700,
.phycap_size = 0x38,
.para_ver = 0xf,
.wlcx_desired = 0x07110000,
.btcx_desired = 0x7,
.scbd = 0x1,
.mailbox = 0x1,
.afh_guard_ch = 6,
.wl_rssi_thres = rtw89_btc_8922a_wl_rssi_thres,
.bt_rssi_thres = rtw89_btc_8922a_bt_rssi_thres,
.rssi_tol = 2,
.mon_reg_num = ARRAY_SIZE(rtw89_btc_8922a_mon_reg),
.mon_reg = rtw89_btc_8922a_mon_reg,
.rf_para_ulink_num = ARRAY_SIZE(rtw89_btc_8922a_rf_ul),
.rf_para_ulink = rtw89_btc_8922a_rf_ul,
.rf_para_dlink_num = ARRAY_SIZE(rtw89_btc_8922a_rf_dl),
.rf_para_dlink = rtw89_btc_8922a_rf_dl,
.ps_mode_supported = BIT(RTW89_PS_MODE_RFOFF) |
BIT(RTW89_PS_MODE_CLK_GATED) |
BIT(RTW89_PS_MODE_PWR_GATED),

View File

@ -89,8 +89,6 @@ enum wl1251_commands {
struct wl1251_cmd_header {
u16 id;
u16 status;
/* payload */
u8 data[];
} __packed;
struct wl1251_command {

View File

@ -65,7 +65,6 @@ struct ieee80211_header {
u8 sa[ETH_ALEN];
u8 bssid[ETH_ALEN];
__le16 seq_ctl;
u8 payload[];
} __packed;
struct wl12xx_ie_header {

View File

@ -208,8 +208,6 @@ enum cmd_templ {
struct wl1271_cmd_header {
__le16 id;
__le16 status;
/* payload */
u8 data[];
} __packed;
#define WL1271_CMD_MAX_PARAMS 572

Some files were not shown because too many files have changed in this diff Show More