mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-27 00:04:47 +08:00
drivers
- rtw89: large update across the map, e.g. coex, pci(e), etc. - ath9k: uninit memory read fix - ath10k: small peer map fix and a WCN3990 device fix - wfx: underflow stack - the "change MAC address while IFF_UP" change from James we discussed - more MLO work, including a set of fixes for the previous code, now that we have more code we can exercise it more - prevent some features with MLO that aren't ready yet (AP_VLAN and 4-address connections) -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAmMTck0ACgkQB8qZga/f l8RHFg//XLv1kpmN0LfsfrpMxJjM0j+kYV+B3gcAlJQBl/KRJg/09sIYzPORJeH1 xrt9JR4SMkIECJigZCu0icP+c+0YVS0aWXTv8aEHuXDRKN2AbQB4yC7MA+PXHVTA LO2dSVKIfUjBPR1Q05M0kKIpf5KYJWuND7IGO28P8+VF4NIZl2PQ+jCxQY6e2SR6 LB9OuWhQ4QT38LsjbKcRt/994sFOgVO+EuMmNaLyBe85HfXBAZ4ZQEyjezevzCV9 TzqFinzMNU4hIC7ct4cXdHwzrpuTXqKdaOEWMFMsChexsb8R8GrIhaguIiBCtFQ4 vKbL58wZt9mnKUk68hEHNQSWSnusqwxEsy0BHFgjD0KxLbXX1xgup/jZLDDLaJqv 2jZJVy0yeUdSheuloXEO9Fr959/YyxcJtu4ycKbhHP4oIzwRloQucxfx3w2Xb6Dq G/jzofX6eqkUhCKPikBd7m8wx4/B/eezAMlSGucaPC4eGDu+qIDctU5eF10FhE1p CtoFpbnuMghVLxWDeU2MU7Riz4oOSsXT29cP1Qg9W9Vwz0spBL4IcBawbta8/H9t CpuDaUapbPNpSnkumfID7z3O4WL+f7tkTQea8Asv84nJ7ikPhrPlM3bES5qlHpSJ rqjn4k63s0Qkn3NZQRSUC1Rhjk5DTm9ccEx+CeAIlpk6MR2fFtU= =7imA -----END PGP SIGNATURE----- Merge tag 'wireless-next-2022-09-03' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next Johannes Berg says: ==================== drivers - rtw89: large update across the map, e.g. coex, pci(e), etc. - ath9k: uninit memory read fix - ath10k: small peer map fix and a WCN3990 device fix - wfx: underflow stack - the "change MAC address while IFF_UP" change from James we discussed - more MLO work, including a set of fixes for the previous code, now that we have more code we can exercise it more - prevent some features with MLO that aren't ready yet (AP_VLAN and 4-address connections) ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
9837ec955b
@ -98,6 +98,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.tx_stats_over_pktlog = true,
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA988X_HW_2_0_VERSION,
|
||||
@ -136,6 +137,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.tx_stats_over_pktlog = true,
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA9887_HW_1_0_VERSION,
|
||||
@ -175,6 +177,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_3_2_VERSION,
|
||||
@ -209,6 +212,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.supports_peer_stats_info = true,
|
||||
.dynamic_sar_support = true,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_2_1_VERSION,
|
||||
@ -247,6 +251,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_2_1_VERSION,
|
||||
@ -285,6 +290,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_3_0_VERSION,
|
||||
@ -323,6 +329,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA6174_HW_3_2_VERSION,
|
||||
@ -365,6 +372,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.supports_peer_stats_info = true,
|
||||
.dynamic_sar_support = true,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA99X0_HW_2_0_DEV_VERSION,
|
||||
@ -409,6 +417,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA9984_HW_1_0_DEV_VERSION,
|
||||
@ -460,6 +469,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA9888_HW_2_0_DEV_VERSION,
|
||||
@ -508,6 +518,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA9377_HW_1_0_DEV_VERSION,
|
||||
@ -546,6 +557,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA9377_HW_1_1_DEV_VERSION,
|
||||
@ -586,6 +598,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA9377_HW_1_1_DEV_VERSION,
|
||||
@ -617,6 +630,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.credit_size_workaround = true,
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = QCA4019_HW_1_0_DEV_VERSION,
|
||||
@ -662,6 +676,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
.hw_restart_disconnect = false,
|
||||
.use_fw_tx_credits = true,
|
||||
},
|
||||
{
|
||||
.id = WCN3990_HW_1_0_DEV_VERSION,
|
||||
@ -693,6 +708,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = true,
|
||||
.hw_restart_disconnect = true,
|
||||
.use_fw_tx_credits = false,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -947,13 +947,18 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
|
||||
return -ECOMM;
|
||||
}
|
||||
|
||||
htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count);
|
||||
if (ar->hw_params.use_fw_tx_credits)
|
||||
htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count);
|
||||
else
|
||||
htc->total_transmit_credits = 1;
|
||||
|
||||
htc->target_credit_size = __le16_to_cpu(msg->ready.credit_size);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC,
|
||||
"Target ready! transmit resources: %d size:%d\n",
|
||||
"Target ready! transmit resources: %d size:%d actual credits:%d\n",
|
||||
htc->total_transmit_credits,
|
||||
htc->target_credit_size);
|
||||
htc->target_credit_size,
|
||||
msg->ready.credit_count);
|
||||
|
||||
if ((htc->total_transmit_credits == 0) ||
|
||||
(htc->target_credit_size == 0)) {
|
||||
|
@ -635,6 +635,8 @@ struct ath10k_hw_params {
|
||||
bool dynamic_sar_support;
|
||||
|
||||
bool hw_restart_disconnect;
|
||||
|
||||
bool use_fw_tx_credits;
|
||||
};
|
||||
|
||||
struct htt_resp;
|
||||
|
@ -864,11 +864,36 @@ static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_peer_map_cleanup(struct ath10k *ar, struct ath10k_peer *peer)
|
||||
{
|
||||
int peer_id, i;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
for_each_set_bit(peer_id, peer->peer_ids,
|
||||
ATH10K_MAX_NUM_PEER_IDS) {
|
||||
ar->peer_map[peer_id] = NULL;
|
||||
}
|
||||
|
||||
/* Double check that peer is properly un-referenced from
|
||||
* the peer_map
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
|
||||
if (ar->peer_map[i] == peer) {
|
||||
ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n",
|
||||
peer->addr, peer, i);
|
||||
ar->peer_map[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
list_del(&peer->list);
|
||||
kfree(peer);
|
||||
ar->num_peers--;
|
||||
}
|
||||
|
||||
static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
|
||||
{
|
||||
struct ath10k_peer *peer, *tmp;
|
||||
int peer_id;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
@ -880,25 +905,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
|
||||
ath10k_warn(ar, "removing stale peer %pM from vdev_id %d\n",
|
||||
peer->addr, vdev_id);
|
||||
|
||||
for_each_set_bit(peer_id, peer->peer_ids,
|
||||
ATH10K_MAX_NUM_PEER_IDS) {
|
||||
ar->peer_map[peer_id] = NULL;
|
||||
}
|
||||
|
||||
/* Double check that peer is properly un-referenced from
|
||||
* the peer_map
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
|
||||
if (ar->peer_map[i] == peer) {
|
||||
ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n",
|
||||
peer->addr, peer, i);
|
||||
ar->peer_map[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
list_del(&peer->list);
|
||||
kfree(peer);
|
||||
ar->num_peers--;
|
||||
ath10k_peer_map_cleanup(ar, peer);
|
||||
}
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
@ -7621,10 +7628,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
||||
/* Clean up the peer object as well since we
|
||||
* must have failed to do this above.
|
||||
*/
|
||||
list_del(&peer->list);
|
||||
ar->peer_map[i] = NULL;
|
||||
kfree(peer);
|
||||
ar->num_peers--;
|
||||
ath10k_peer_map_cleanup(ar, peer);
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
@ -1014,7 +1014,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
|
||||
|
||||
switch (ie_id) {
|
||||
case ATH6KL_FW_IE_FW_VERSION:
|
||||
strlcpy(ar->wiphy->fw_version, data,
|
||||
strscpy(ar->wiphy->fw_version, data,
|
||||
min(sizeof(ar->wiphy->fw_version), ie_len+1));
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_BOOT,
|
||||
|
@ -364,33 +364,27 @@ ret:
|
||||
}
|
||||
|
||||
static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle,
|
||||
struct sk_buff *skb)
|
||||
struct sk_buff *skb, u32 len)
|
||||
{
|
||||
uint32_t *pattern = (uint32_t *)skb->data;
|
||||
|
||||
switch (*pattern) {
|
||||
case 0x33221199:
|
||||
{
|
||||
if (*pattern == 0x33221199 && len >= sizeof(struct htc_panic_bad_vaddr)) {
|
||||
struct htc_panic_bad_vaddr *htc_panic;
|
||||
htc_panic = (struct htc_panic_bad_vaddr *) skb->data;
|
||||
dev_err(htc_handle->dev, "ath: firmware panic! "
|
||||
"exccause: 0x%08x; pc: 0x%08x; badvaddr: 0x%08x.\n",
|
||||
htc_panic->exccause, htc_panic->pc,
|
||||
htc_panic->badvaddr);
|
||||
break;
|
||||
}
|
||||
case 0x33221299:
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (*pattern == 0x33221299) {
|
||||
struct htc_panic_bad_epid *htc_panic;
|
||||
htc_panic = (struct htc_panic_bad_epid *) skb->data;
|
||||
dev_err(htc_handle->dev, "ath: firmware panic! "
|
||||
"bad epid: 0x%08x\n", htc_panic->epid);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dev_err(htc_handle->dev, "ath: unknown panic pattern!\n");
|
||||
break;
|
||||
return;
|
||||
}
|
||||
dev_err(htc_handle->dev, "ath: unknown panic pattern!\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -411,16 +405,26 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
|
||||
if (!htc_handle || !skb)
|
||||
return;
|
||||
|
||||
/* A valid message requires len >= 8.
|
||||
*
|
||||
* sizeof(struct htc_frame_hdr) == 8
|
||||
* sizeof(struct htc_ready_msg) == 8
|
||||
* sizeof(struct htc_panic_bad_vaddr) == 16
|
||||
* sizeof(struct htc_panic_bad_epid) == 8
|
||||
*/
|
||||
if (unlikely(len < sizeof(struct htc_frame_hdr)))
|
||||
goto invalid;
|
||||
htc_hdr = (struct htc_frame_hdr *) skb->data;
|
||||
epid = htc_hdr->endpoint_id;
|
||||
|
||||
if (epid == 0x99) {
|
||||
ath9k_htc_fw_panic_report(htc_handle, skb);
|
||||
ath9k_htc_fw_panic_report(htc_handle, skb, len);
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (epid < 0 || epid >= ENDPOINT_MAX) {
|
||||
invalid:
|
||||
if (pipe_id != USB_REG_IN_PIPE)
|
||||
dev_kfree_skb_any(skb);
|
||||
else
|
||||
@ -432,21 +436,30 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
|
||||
|
||||
/* Handle trailer */
|
||||
if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) {
|
||||
if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000)
|
||||
if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000) {
|
||||
/* Move past the Watchdog pattern */
|
||||
htc_hdr = (struct htc_frame_hdr *)(skb->data + 4);
|
||||
len -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the message ID */
|
||||
if (unlikely(len < sizeof(struct htc_frame_hdr) + sizeof(__be16)))
|
||||
goto invalid;
|
||||
msg_id = (__be16 *) ((void *) htc_hdr +
|
||||
sizeof(struct htc_frame_hdr));
|
||||
|
||||
/* Now process HTC messages */
|
||||
switch (be16_to_cpu(*msg_id)) {
|
||||
case HTC_MSG_READY_ID:
|
||||
if (unlikely(len < sizeof(struct htc_ready_msg)))
|
||||
goto invalid;
|
||||
htc_process_target_rdy(htc_handle, htc_hdr);
|
||||
break;
|
||||
case HTC_MSG_CONNECT_SERVICE_RESPONSE_ID:
|
||||
if (unlikely(len < sizeof(struct htc_frame_hdr) +
|
||||
sizeof(struct htc_conn_svc_rspmsg)))
|
||||
goto invalid;
|
||||
htc_process_conn_rsp(htc_handle, htc_hdr);
|
||||
break;
|
||||
default:
|
||||
|
@ -105,7 +105,7 @@ static void carl9170_fw_info(struct ar9170 *ar)
|
||||
CARL9170FW_GET_MONTH(fw_date),
|
||||
CARL9170FW_GET_DAY(fw_date));
|
||||
|
||||
strlcpy(ar->hw->wiphy->fw_version, motd_desc->release,
|
||||
strscpy(ar->hw->wiphy->fw_version, motd_desc->release,
|
||||
sizeof(ar->hw->wiphy->fw_version));
|
||||
}
|
||||
}
|
||||
|
@ -1305,7 +1305,7 @@ void wil_get_board_file(struct wil6210_priv *wil, char *buf, size_t len)
|
||||
board_file = WIL_BOARD_FILE_NAME;
|
||||
}
|
||||
|
||||
strlcpy(buf, board_file, len);
|
||||
strscpy(buf, board_file, len);
|
||||
}
|
||||
|
||||
static int wil_get_bl_info(struct wil6210_priv *wil)
|
||||
|
@ -445,7 +445,7 @@ int wil_if_add(struct wil6210_priv *wil)
|
||||
|
||||
wil_dbg_misc(wil, "entered");
|
||||
|
||||
strlcpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version));
|
||||
strscpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version));
|
||||
|
||||
rc = wiphy_register(wiphy);
|
||||
if (rc < 0) {
|
||||
|
@ -780,7 +780,7 @@ static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len)
|
||||
return; /* FW load will fail after timeout */
|
||||
}
|
||||
/* ignore MAC address, we already have it from the boot loader */
|
||||
strlcpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version));
|
||||
strscpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version));
|
||||
|
||||
if (len > offsetof(struct wmi_ready_event, rfc_read_calib_result)) {
|
||||
wil_dbg_wmi(wil, "rfc calibration result %d\n",
|
||||
|
@ -1518,7 +1518,7 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
|
||||
priv->firmware = NULL;
|
||||
priv->firmware_type = fw_type;
|
||||
if (firmware) /* module parameter */
|
||||
strlcpy(priv->firmware_id, firmware, sizeof(priv->firmware_id));
|
||||
strscpy(priv->firmware_id, firmware, sizeof(priv->firmware_id));
|
||||
priv->bus_type = card_present ? BUS_TYPE_PCCARD : BUS_TYPE_PCI;
|
||||
priv->station_state = STATION_STATE_DOWN;
|
||||
priv->do_rx_crc = 0;
|
||||
|
@ -118,7 +118,7 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
|
||||
led->wl = dev->wl;
|
||||
led->index = led_index;
|
||||
led->activelow = activelow;
|
||||
strlcpy(led->name, name, sizeof(led->name));
|
||||
strscpy(led->name, name, sizeof(led->name));
|
||||
atomic_set(&led->state, 0);
|
||||
|
||||
led->led_dev.name = led->name;
|
||||
|
@ -88,7 +88,7 @@ static int b43legacy_register_led(struct b43legacy_wldev *dev,
|
||||
led->dev = dev;
|
||||
led->index = led_index;
|
||||
led->activelow = activelow;
|
||||
strlcpy(led->name, name, sizeof(led->name));
|
||||
strscpy(led->name, name, sizeof(led->name));
|
||||
|
||||
led->led_dev.name = led->name;
|
||||
led->led_dev.default_trigger = default_trigger;
|
||||
|
@ -261,7 +261,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
||||
&revinfo, sizeof(revinfo));
|
||||
if (err < 0) {
|
||||
bphy_err(drvr, "retrieving revision info failed, %d\n", err);
|
||||
strlcpy(ri->chipname, "UNKNOWN", sizeof(ri->chipname));
|
||||
strscpy(ri->chipname, "UNKNOWN", sizeof(ri->chipname));
|
||||
} else {
|
||||
ri->vendorid = le32_to_cpu(revinfo.vendorid);
|
||||
ri->deviceid = le32_to_cpu(revinfo.deviceid);
|
||||
@ -314,7 +314,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
||||
|
||||
/* locate firmware version number for ethtool */
|
||||
ptr = strrchr(buf, ' ') + 1;
|
||||
strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
|
||||
strscpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
|
||||
|
||||
/* Query for 'clmver' to get CLM version info from firmware */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
@ -424,11 +424,11 @@ static void brcmf_mp_attach(void)
|
||||
* if not set then if available use the platform data version. To make
|
||||
* sure it gets initialized at all, always copy the module param version
|
||||
*/
|
||||
strlcpy(brcmf_mp_global.firmware_path, brcmf_firmware_path,
|
||||
strscpy(brcmf_mp_global.firmware_path, brcmf_firmware_path,
|
||||
BRCMF_FW_ALTPATH_LEN);
|
||||
if ((brcmfmac_pdata) && (brcmfmac_pdata->fw_alternative_path) &&
|
||||
(brcmf_mp_global.firmware_path[0] == '\0')) {
|
||||
strlcpy(brcmf_mp_global.firmware_path,
|
||||
strscpy(brcmf_mp_global.firmware_path,
|
||||
brcmfmac_pdata->fw_alternative_path,
|
||||
BRCMF_FW_ALTPATH_LEN);
|
||||
}
|
||||
|
@ -561,10 +561,10 @@ static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
|
||||
|
||||
if (drvr->revinfo.result == 0)
|
||||
brcmu_dotrev_str(drvr->revinfo.driverrev, drev);
|
||||
strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
|
||||
strlcpy(info->version, drev, sizeof(info->version));
|
||||
strlcpy(info->fw_version, drvr->fwver, sizeof(info->fw_version));
|
||||
strlcpy(info->bus_info, dev_name(drvr->bus_if->dev),
|
||||
strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
|
||||
strscpy(info->version, drev, sizeof(info->version));
|
||||
strscpy(info->fw_version, drvr->fwver, sizeof(info->fw_version));
|
||||
strscpy(info->bus_info, dev_name(drvr->bus_if->dev),
|
||||
sizeof(info->bus_info));
|
||||
}
|
||||
|
||||
|
@ -769,7 +769,7 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev,
|
||||
fwnames[j].path[0] = '\0';
|
||||
/* check if firmware path is provided by module parameter */
|
||||
if (brcmf_mp_global.firmware_path[0] != '\0') {
|
||||
strlcpy(fwnames[j].path, mp_path,
|
||||
strscpy(fwnames[j].path, mp_path,
|
||||
BRCMF_FW_NAME_LEN);
|
||||
|
||||
if (end != '/') {
|
||||
|
@ -688,7 +688,7 @@ static void brcmf_fws_macdesc_set_name(struct brcmf_fws_info *fws,
|
||||
struct brcmf_fws_mac_descriptor *desc)
|
||||
{
|
||||
if (desc == &fws->desc.other)
|
||||
strlcpy(desc->name, "MAC-OTHER", sizeof(desc->name));
|
||||
strscpy(desc->name, "MAC-OTHER", sizeof(desc->name));
|
||||
else if (desc->mac_handle)
|
||||
scnprintf(desc->name, sizeof(desc->name), "MAC-%d:%d",
|
||||
desc->mac_handle, desc->interface_id);
|
||||
|
@ -5907,8 +5907,8 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
char fw_ver[64], ucode_ver[64];
|
||||
|
||||
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
|
||||
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
|
||||
strscpy(info->driver, DRV_NAME, sizeof(info->driver));
|
||||
strscpy(info->version, DRV_VERSION, sizeof(info->version));
|
||||
|
||||
ipw2100_get_fwversion(priv, fw_ver, sizeof(fw_ver));
|
||||
ipw2100_get_ucodeversion(priv, ucode_ver, sizeof(ucode_ver));
|
||||
@ -5916,7 +5916,7 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
|
||||
snprintf(info->fw_version, sizeof(info->fw_version), "%s:%d:%s",
|
||||
fw_ver, priv->eeprom_version, ucode_ver);
|
||||
|
||||
strlcpy(info->bus_info, pci_name(priv->pci_dev),
|
||||
strscpy(info->bus_info, pci_name(priv->pci_dev),
|
||||
sizeof(info->bus_info));
|
||||
}
|
||||
|
||||
|
@ -10424,8 +10424,8 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
|
||||
char date[32];
|
||||
u32 len;
|
||||
|
||||
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
|
||||
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
|
||||
strscpy(info->driver, DRV_NAME, sizeof(info->driver));
|
||||
strscpy(info->version, DRV_VERSION, sizeof(info->version));
|
||||
|
||||
len = sizeof(vers);
|
||||
ipw_get_ordinal(p, IPW_ORD_STAT_FW_VERSION, vers, &len);
|
||||
@ -10434,7 +10434,7 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
|
||||
|
||||
snprintf(info->fw_version, sizeof(info->fw_version), "%s (%s)",
|
||||
vers, date);
|
||||
strlcpy(info->bus_info, pci_name(p->pci_dev),
|
||||
strscpy(info->bus_info, pci_name(p->pci_dev),
|
||||
sizeof(info->bus_info));
|
||||
}
|
||||
|
||||
|
@ -3254,7 +3254,7 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr,
|
||||
|
||||
if (count) {
|
||||
char *p = buffer;
|
||||
strlcpy(buffer, buf, sizeof(buffer));
|
||||
strscpy(buffer, buf, sizeof(buffer));
|
||||
channel = simple_strtoul(p, NULL, 0);
|
||||
if (channel)
|
||||
params.channel = channel;
|
||||
|
@ -3848,7 +3848,7 @@ static void prism2_get_drvinfo(struct net_device *dev,
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
strlcpy(info->driver, "hostap", sizeof(info->driver));
|
||||
strscpy(info->driver, "hostap", sizeof(info->driver));
|
||||
snprintf(info->fw_version, sizeof(info->fw_version),
|
||||
"%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
|
||||
(local->sta_fw_ver >> 8) & 0xff,
|
||||
|
@ -652,7 +652,6 @@ struct mac80211_hwsim_data {
|
||||
u32 ciphers[ARRAY_SIZE(hwsim_ciphers)];
|
||||
|
||||
struct mac_address addresses[2];
|
||||
struct ieee80211_chanctx_conf *chanctx;
|
||||
int channels, idx;
|
||||
bool use_chanctx;
|
||||
bool destroy_on_close;
|
||||
@ -1299,6 +1298,8 @@ static void mac80211_hwsim_config_mac_nl(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb;
|
||||
void *msg_head;
|
||||
|
||||
WARN_ON(!is_valid_ether_addr(addr));
|
||||
|
||||
if (!_portid && !hwsim_virtio_enabled)
|
||||
return;
|
||||
|
||||
@ -1561,6 +1562,19 @@ static void mac80211_hwsim_add_vendor_rtap(struct sk_buff *skb)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mac80211_hwsim_rx(struct mac80211_hwsim_data *data,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status));
|
||||
|
||||
mac80211_hwsim_add_vendor_rtap(skb);
|
||||
|
||||
data->rx_pkts++;
|
||||
data->rx_bytes += skb->len;
|
||||
ieee80211_rx_irqsafe(data->hw, skb);
|
||||
}
|
||||
|
||||
static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_channel *chan)
|
||||
@ -1688,13 +1702,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
|
||||
|
||||
rx_status.mactime = now + data2->tsf_offset;
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
|
||||
|
||||
mac80211_hwsim_add_vendor_rtap(nskb);
|
||||
|
||||
data2->rx_pkts++;
|
||||
data2->rx_bytes += nskb->len;
|
||||
ieee80211_rx_irqsafe(data2->hw, nskb);
|
||||
mac80211_hwsim_rx(data2, &rx_status, nskb);
|
||||
}
|
||||
spin_unlock(&hwsim_radio_lock);
|
||||
|
||||
@ -1714,12 +1722,7 @@ mac80211_hwsim_select_tx_link(struct mac80211_hwsim_data *data,
|
||||
if (!vif->valid_links)
|
||||
return &vif->bss_conf;
|
||||
|
||||
/* FIXME: handle multicast TX properly */
|
||||
if (is_multicast_ether_addr(hdr->addr1) || WARN_ON_ONCE(!sta)) {
|
||||
unsigned int first_link = ffs(vif->valid_links) - 1;
|
||||
|
||||
return rcu_dereference(vif->link_conf[first_link]);
|
||||
}
|
||||
WARN_ON(is_multicast_ether_addr(hdr->addr1));
|
||||
|
||||
if (WARN_ON_ONCE(!sta->valid_links))
|
||||
return &vif->bss_conf;
|
||||
@ -2866,11 +2869,6 @@ static int mac80211_hwsim_croc(struct ieee80211_hw *hw,
|
||||
static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct mac80211_hwsim_data *hwsim = hw->priv;
|
||||
|
||||
mutex_lock(&hwsim->mutex);
|
||||
hwsim->chanctx = ctx;
|
||||
mutex_unlock(&hwsim->mutex);
|
||||
hwsim_set_chanctx_magic(ctx);
|
||||
wiphy_dbg(hw->wiphy,
|
||||
"add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
|
||||
@ -2882,11 +2880,6 @@ static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
|
||||
static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct mac80211_hwsim_data *hwsim = hw->priv;
|
||||
|
||||
mutex_lock(&hwsim->mutex);
|
||||
hwsim->chanctx = NULL;
|
||||
mutex_unlock(&hwsim->mutex);
|
||||
wiphy_dbg(hw->wiphy,
|
||||
"remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
|
||||
ctx->def.chan->center_freq, ctx->def.width,
|
||||
@ -2899,11 +2892,6 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
u32 changed)
|
||||
{
|
||||
struct mac80211_hwsim_data *hwsim = hw->priv;
|
||||
|
||||
mutex_lock(&hwsim->mutex);
|
||||
hwsim->chanctx = ctx;
|
||||
mutex_unlock(&hwsim->mutex);
|
||||
hwsim_check_chanctx_magic(ctx);
|
||||
wiphy_dbg(hw->wiphy,
|
||||
"change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
|
||||
@ -3026,6 +3014,8 @@ static int mac80211_hwsim_change_sta_links(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta,
|
||||
u16 old_links, u16 new_links)
|
||||
{
|
||||
hwsim_check_sta_magic(sta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4272,7 +4262,6 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
|
||||
hw->wiphy->max_remain_on_channel_duration = 1000;
|
||||
data->if_combination.radar_detect_widths = 0;
|
||||
data->if_combination.num_different_channels = data->channels;
|
||||
data->chanctx = NULL;
|
||||
} else {
|
||||
data->if_combination.num_different_channels = 1;
|
||||
data->if_combination.radar_detect_widths =
|
||||
@ -4847,13 +4836,9 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
|
||||
if (data2->use_chanctx) {
|
||||
if (data2->tmp_chan)
|
||||
channel = data2->tmp_chan;
|
||||
else if (data2->chanctx)
|
||||
channel = data2->chanctx->def.chan;
|
||||
} else {
|
||||
channel = data2->channel;
|
||||
}
|
||||
if (!channel)
|
||||
goto out;
|
||||
|
||||
if (!hwsim_virtio_enabled) {
|
||||
if (hwsim_net_get_netgroup(genl_info_net(info)) !=
|
||||
@ -4884,6 +4869,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
|
||||
rx_status.freq);
|
||||
if (!iter_data.channel)
|
||||
goto out;
|
||||
rx_status.band = iter_data.channel->band;
|
||||
|
||||
mutex_lock(&data2->mutex);
|
||||
if (!hwsim_chans_compat(iter_data.channel, channel)) {
|
||||
@ -4896,11 +4882,13 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
|
||||
}
|
||||
}
|
||||
mutex_unlock(&data2->mutex);
|
||||
} else if (!channel) {
|
||||
goto out;
|
||||
} else {
|
||||
rx_status.freq = channel->center_freq;
|
||||
rx_status.band = channel->band;
|
||||
}
|
||||
|
||||
rx_status.band = channel->band;
|
||||
rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
|
||||
rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
|
||||
|
||||
@ -4910,10 +4898,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
|
||||
ieee80211_is_probe_resp(hdr->frame_control))
|
||||
rx_status.boottime_ns = ktime_get_boottime_ns();
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
|
||||
data2->rx_pkts++;
|
||||
data2->rx_bytes += skb->len;
|
||||
ieee80211_rx_irqsafe(data2->hw, skb);
|
||||
mac80211_hwsim_rx(data2, &rx_status, skb);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
|
@ -20,8 +20,8 @@ static void lbs_ethtool_get_drvinfo(struct net_device *dev,
|
||||
priv->fwrelease >> 16 & 0xff,
|
||||
priv->fwrelease >> 8 & 0xff,
|
||||
priv->fwrelease & 0xff);
|
||||
strlcpy(info->driver, "libertas", sizeof(info->driver));
|
||||
strlcpy(info->version, lbs_driver_version, sizeof(info->version));
|
||||
strscpy(info->driver, "libertas", sizeof(info->driver));
|
||||
strscpy(info->version, lbs_driver_version, sizeof(info->version));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -997,12 +997,11 @@ bool wilc_wfi_mgmt_frame_rx(struct wilc_vif *vif, u8 *buff, u32 size)
|
||||
{
|
||||
struct wilc *wl = vif->wilc;
|
||||
struct wilc_priv *priv = &vif->priv;
|
||||
int freq, ret;
|
||||
int freq;
|
||||
|
||||
freq = ieee80211_channel_to_frequency(wl->op_ch, NL80211_BAND_2GHZ);
|
||||
ret = cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0);
|
||||
|
||||
return ret;
|
||||
return cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0);
|
||||
}
|
||||
|
||||
void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size)
|
||||
|
@ -229,7 +229,7 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
|
||||
return NULL;
|
||||
|
||||
wl->monitor_dev->type = ARPHRD_IEEE80211_RADIOTAP;
|
||||
strlcpy(wl->monitor_dev->name, name, IFNAMSIZ);
|
||||
strscpy(wl->monitor_dev->name, name, IFNAMSIZ);
|
||||
wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops;
|
||||
wl->monitor_dev->needs_free_netdev = true;
|
||||
|
||||
|
@ -1223,7 +1223,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
|
||||
mac->macinfo.extended_capabilities_len;
|
||||
}
|
||||
|
||||
strlcpy(wiphy->fw_version, hw_info->fw_version,
|
||||
strscpy(wiphy->fw_version, hw_info->fw_version,
|
||||
sizeof(wiphy->fw_version));
|
||||
wiphy->hw_version = hw_info->hw_version;
|
||||
|
||||
|
@ -967,7 +967,7 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
|
||||
hwinfo->total_rx_chain, hwinfo->total_tx_chain,
|
||||
hwinfo->fw_ver);
|
||||
|
||||
strlcpy(hwinfo->fw_version, bld_label, sizeof(hwinfo->fw_version));
|
||||
strscpy(hwinfo->fw_version, bld_label, sizeof(hwinfo->fw_version));
|
||||
hwinfo->hw_version = hw_ver;
|
||||
|
||||
return 0;
|
||||
|
@ -143,7 +143,7 @@ static int rtl8187_register_led(struct ieee80211_hw *dev,
|
||||
led->dev = dev;
|
||||
led->ledpin = ledpin;
|
||||
led->is_radio = is_radio;
|
||||
strlcpy(led->name, name, sizeof(led->name));
|
||||
strscpy(led->name, name, sizeof(led->name));
|
||||
|
||||
led->led_dev.name = led->name;
|
||||
led->led_dev.default_trigger = default_trigger;
|
||||
|
@ -1878,13 +1878,6 @@ static int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv)
|
||||
|
||||
/* We have 8 bits to indicate validity */
|
||||
map_addr = offset * 8;
|
||||
if (map_addr >= EFUSE_MAP_LEN) {
|
||||
dev_warn(dev, "%s: Illegal map_addr (%04x), "
|
||||
"efuse corrupt!\n",
|
||||
__func__, map_addr);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
|
||||
/* Check word enable condition in the section */
|
||||
if (word_mask & BIT(i)) {
|
||||
@ -1895,6 +1888,13 @@ static int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv)
|
||||
ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, &val8);
|
||||
if (ret)
|
||||
goto exit;
|
||||
if (map_addr >= EFUSE_MAP_LEN - 1) {
|
||||
dev_warn(dev, "%s: Illegal map_addr (%04x), "
|
||||
"efuse corrupt!\n",
|
||||
__func__, map_addr);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
priv->efuse_wifi.raw[map_addr++] = val8;
|
||||
|
||||
ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, &val8);
|
||||
|
@ -2093,7 +2093,7 @@ int rtw_core_init(struct rtw_dev *rtwdev)
|
||||
ret = rtw_load_firmware(rtwdev, RTW_NORMAL_FW);
|
||||
if (ret) {
|
||||
rtw_warn(rtwdev, "no firmware loaded\n");
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (chip->wow_fw_name) {
|
||||
@ -2103,11 +2103,15 @@ int rtw_core_init(struct rtw_dev *rtwdev)
|
||||
wait_for_completion(&rtwdev->fw.completion);
|
||||
if (rtwdev->fw.firmware)
|
||||
release_firmware(rtwdev->fw.firmware);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
destroy_workqueue(rtwdev->tx_wq);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rtw_core_init);
|
||||
|
||||
|
@ -12,6 +12,7 @@ rtw89_core-y += core.o \
|
||||
sar.o \
|
||||
coex.o \
|
||||
ps.o \
|
||||
chan.o \
|
||||
ser.o
|
||||
|
||||
obj-$(CONFIG_RTW89_8852A) += rtw89_8852a.o
|
||||
|
235
drivers/net/wireless/realtek/rtw89/chan.c
Normal file
235
drivers/net/wireless/realtek/rtw89/chan.c
Normal file
@ -0,0 +1,235 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) 2020-2022 Realtek Corporation
|
||||
*/
|
||||
|
||||
#include "chan.h"
|
||||
#include "debug.h"
|
||||
|
||||
static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band,
|
||||
u8 center_chan)
|
||||
{
|
||||
switch (band) {
|
||||
default:
|
||||
case RTW89_BAND_2G:
|
||||
switch (center_chan) {
|
||||
default:
|
||||
case 1 ... 14:
|
||||
return RTW89_CH_2G;
|
||||
}
|
||||
case RTW89_BAND_5G:
|
||||
switch (center_chan) {
|
||||
default:
|
||||
case 36 ... 64:
|
||||
return RTW89_CH_5G_BAND_1;
|
||||
case 100 ... 144:
|
||||
return RTW89_CH_5G_BAND_3;
|
||||
case 149 ... 177:
|
||||
return RTW89_CH_5G_BAND_4;
|
||||
}
|
||||
case RTW89_BAND_6G:
|
||||
switch (center_chan) {
|
||||
default:
|
||||
case 1 ... 29:
|
||||
return RTW89_CH_6G_BAND_IDX0;
|
||||
case 33 ... 61:
|
||||
return RTW89_CH_6G_BAND_IDX1;
|
||||
case 65 ... 93:
|
||||
return RTW89_CH_6G_BAND_IDX2;
|
||||
case 97 ... 125:
|
||||
return RTW89_CH_6G_BAND_IDX3;
|
||||
case 129 ... 157:
|
||||
return RTW89_CH_6G_BAND_IDX4;
|
||||
case 161 ... 189:
|
||||
return RTW89_CH_6G_BAND_IDX5;
|
||||
case 193 ... 221:
|
||||
return RTW89_CH_6G_BAND_IDX6;
|
||||
case 225 ... 253:
|
||||
return RTW89_CH_6G_BAND_IDX7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static enum rtw89_sc_offset rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw,
|
||||
u32 center_freq,
|
||||
u32 primary_freq)
|
||||
{
|
||||
u8 primary_chan_idx;
|
||||
u32 offset;
|
||||
|
||||
switch (bw) {
|
||||
default:
|
||||
case RTW89_CHANNEL_WIDTH_20:
|
||||
primary_chan_idx = RTW89_SC_DONT_CARE;
|
||||
break;
|
||||
case RTW89_CHANNEL_WIDTH_40:
|
||||
if (primary_freq > center_freq)
|
||||
primary_chan_idx = RTW89_SC_20_UPPER;
|
||||
else
|
||||
primary_chan_idx = RTW89_SC_20_LOWER;
|
||||
break;
|
||||
case RTW89_CHANNEL_WIDTH_80:
|
||||
case RTW89_CHANNEL_WIDTH_160:
|
||||
if (primary_freq > center_freq) {
|
||||
offset = (primary_freq - center_freq - 10) / 20;
|
||||
primary_chan_idx = RTW89_SC_20_UPPER + offset * 2;
|
||||
} else {
|
||||
offset = (center_freq - primary_freq - 10) / 20;
|
||||
primary_chan_idx = RTW89_SC_20_LOWER + offset * 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return primary_chan_idx;
|
||||
}
|
||||
|
||||
void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
|
||||
enum rtw89_band band, enum rtw89_bandwidth bandwidth)
|
||||
{
|
||||
enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
|
||||
u32 center_freq, primary_freq;
|
||||
|
||||
memset(chan, 0, sizeof(*chan));
|
||||
chan->channel = center_chan;
|
||||
chan->primary_channel = primary_chan;
|
||||
chan->band_type = band;
|
||||
chan->band_width = bandwidth;
|
||||
|
||||
center_freq = ieee80211_channel_to_frequency(center_chan, nl_band);
|
||||
primary_freq = ieee80211_channel_to_frequency(primary_chan, nl_band);
|
||||
|
||||
chan->freq = center_freq;
|
||||
chan->subband_type = rtw89_get_subband_type(band, center_chan);
|
||||
chan->pri_ch_idx = rtw89_get_primary_chan_idx(bandwidth, center_freq,
|
||||
primary_freq);
|
||||
}
|
||||
|
||||
bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_sub_entity_idx idx,
|
||||
const struct rtw89_chan *new)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
struct rtw89_chan *chan = &hal->chan[idx];
|
||||
struct rtw89_chan_rcd *rcd = &hal->chan_rcd[idx];
|
||||
bool band_changed;
|
||||
|
||||
rcd->prev_primary_channel = chan->primary_channel;
|
||||
rcd->prev_band_type = chan->band_type;
|
||||
band_changed = new->band_type != chan->band_type;
|
||||
|
||||
*chan = *new;
|
||||
return band_changed;
|
||||
}
|
||||
|
||||
static void __rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_sub_entity_idx idx,
|
||||
const struct cfg80211_chan_def *chandef,
|
||||
bool from_stack)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
||||
hal->chandef[idx] = *chandef;
|
||||
|
||||
if (from_stack)
|
||||
set_bit(idx, hal->entity_map);
|
||||
}
|
||||
|
||||
void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_sub_entity_idx idx,
|
||||
const struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
__rtw89_config_entity_chandef(rtwdev, idx, chandef, true);
|
||||
}
|
||||
|
||||
static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct cfg80211_chan_def chandef = {0};
|
||||
|
||||
rtw89_get_default_chandef(&chandef);
|
||||
__rtw89_config_entity_chandef(rtwdev, RTW89_SUB_ENTITY_0, &chandef, false);
|
||||
}
|
||||
|
||||
void rtw89_entity_init(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
||||
bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
|
||||
rtw89_config_default_chandef(rtwdev);
|
||||
}
|
||||
|
||||
enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
enum rtw89_entity_mode mode;
|
||||
u8 weight;
|
||||
|
||||
weight = bitmap_weight(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
|
||||
switch (weight) {
|
||||
default:
|
||||
rtw89_warn(rtwdev, "unknown ent chan weight: %d\n", weight);
|
||||
bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
|
||||
fallthrough;
|
||||
case 0:
|
||||
rtw89_config_default_chandef(rtwdev);
|
||||
fallthrough;
|
||||
case 1:
|
||||
mode = RTW89_ENTITY_MODE_SCC;
|
||||
break;
|
||||
}
|
||||
|
||||
rtw89_set_entity_mode(rtwdev, mode);
|
||||
return mode;
|
||||
}
|
||||
|
||||
int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
u8 idx;
|
||||
|
||||
idx = find_first_zero_bit(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
|
||||
if (idx >= chip->support_chanctx_num)
|
||||
return -ENOENT;
|
||||
|
||||
rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
|
||||
rtw89_set_channel(rtwdev);
|
||||
cfg->idx = idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
|
||||
|
||||
clear_bit(cfg->idx, hal->entity_map);
|
||||
rtw89_set_channel(rtwdev);
|
||||
}
|
||||
|
||||
void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
u32 changed)
|
||||
{
|
||||
struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
|
||||
u8 idx = cfg->idx;
|
||||
|
||||
if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) {
|
||||
rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
|
||||
rtw89_set_channel(rtwdev);
|
||||
}
|
||||
}
|
||||
|
||||
int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
}
|
64
drivers/net/wireless/realtek/rtw89/chan.h
Normal file
64
drivers/net/wireless/realtek/rtw89/chan.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
* Copyright(c) 2020-2022 Realtek Corporation
|
||||
*/
|
||||
|
||||
#ifndef __RTW89_CHAN_H__
|
||||
#define __RTW89_CHAN_H__
|
||||
|
||||
#include "core.h"
|
||||
|
||||
static inline bool rtw89_get_entity_state(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
||||
return READ_ONCE(hal->entity_active);
|
||||
}
|
||||
|
||||
static inline void rtw89_set_entity_state(struct rtw89_dev *rtwdev, bool active)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
||||
WRITE_ONCE(hal->entity_active, active);
|
||||
}
|
||||
|
||||
static inline
|
||||
enum rtw89_entity_mode rtw89_get_entity_mode(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
||||
return READ_ONCE(hal->entity_mode);
|
||||
}
|
||||
|
||||
static inline void rtw89_set_entity_mode(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_entity_mode mode)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
||||
WRITE_ONCE(hal->entity_mode, mode);
|
||||
}
|
||||
|
||||
void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
|
||||
enum rtw89_band band, enum rtw89_bandwidth bandwidth);
|
||||
bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_sub_entity_idx idx,
|
||||
const struct rtw89_chan *new);
|
||||
void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_sub_entity_idx idx,
|
||||
const struct cfg80211_chan_def *chandef);
|
||||
void rtw89_entity_init(struct rtw89_dev *rtwdev);
|
||||
enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev);
|
||||
int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
u32 changed);
|
||||
int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -162,17 +162,19 @@ void rtw89_coex_act1_work(struct work_struct *work);
|
||||
void rtw89_coex_bt_devinfo_work(struct work_struct *work);
|
||||
void rtw89_coex_rfk_chk_work(struct work_struct *work);
|
||||
void rtw89_coex_power_on(struct rtw89_dev *rtwdev);
|
||||
void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type);
|
||||
void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type);
|
||||
|
||||
static inline u8 rtw89_btc_phymap(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy_idx,
|
||||
enum rtw89_rf_path_bit paths)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 phy_map;
|
||||
|
||||
phy_map = FIELD_PREP(BTC_RFK_PATH_MAP, paths) |
|
||||
FIELD_PREP(BTC_RFK_PHY_MAP, BIT(phy_idx)) |
|
||||
FIELD_PREP(BTC_RFK_BAND_MAP, hal->current_band_type);
|
||||
FIELD_PREP(BTC_RFK_BAND_MAP, chan->band_type);
|
||||
|
||||
return phy_map;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <linux/udp.h>
|
||||
|
||||
#include "cam.h"
|
||||
#include "chan.h"
|
||||
#include "coex.h"
|
||||
#include "core.h"
|
||||
#include "efuse.h"
|
||||
@ -224,18 +225,22 @@ static void rtw89_traffic_stats_accu(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef,
|
||||
struct rtw89_channel_params *chan_param)
|
||||
void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
cfg80211_chandef_create(chandef, &rtw89_channels_2ghz[0],
|
||||
NL80211_CHAN_NO_HT);
|
||||
}
|
||||
|
||||
static void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef,
|
||||
struct rtw89_chan *chan)
|
||||
{
|
||||
struct ieee80211_channel *channel = chandef->chan;
|
||||
enum nl80211_chan_width width = chandef->width;
|
||||
u32 primary_freq, center_freq;
|
||||
u8 center_chan;
|
||||
u8 bandwidth = RTW89_CHANNEL_WIDTH_20;
|
||||
u8 primary_chan_idx = 0;
|
||||
u32 offset;
|
||||
u8 band;
|
||||
u8 subband;
|
||||
|
||||
center_chan = channel->hw_value;
|
||||
primary_freq = channel->center_freq;
|
||||
@ -245,15 +250,12 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef,
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
case NL80211_CHAN_WIDTH_20:
|
||||
bandwidth = RTW89_CHANNEL_WIDTH_20;
|
||||
primary_chan_idx = RTW89_SC_DONT_CARE;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
bandwidth = RTW89_CHANNEL_WIDTH_40;
|
||||
if (primary_freq > center_freq) {
|
||||
primary_chan_idx = RTW89_SC_20_UPPER;
|
||||
center_chan -= 2;
|
||||
} else {
|
||||
primary_chan_idx = RTW89_SC_20_LOWER;
|
||||
center_chan += 2;
|
||||
}
|
||||
break;
|
||||
@ -262,11 +264,9 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef,
|
||||
bandwidth = nl_to_rtw89_bandwidth(width);
|
||||
if (primary_freq > center_freq) {
|
||||
offset = (primary_freq - center_freq - 10) / 20;
|
||||
primary_chan_idx = RTW89_SC_20_UPPER + offset * 2;
|
||||
center_chan -= 2 + offset * 4;
|
||||
} else {
|
||||
offset = (center_freq - primary_freq - 10) / 20;
|
||||
primary_chan_idx = RTW89_SC_20_LOWER + offset * 2;
|
||||
center_chan += 2 + offset * 4;
|
||||
}
|
||||
break;
|
||||
@ -288,110 +288,76 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef,
|
||||
break;
|
||||
}
|
||||
|
||||
switch (band) {
|
||||
default:
|
||||
case RTW89_BAND_2G:
|
||||
switch (center_chan) {
|
||||
default:
|
||||
case 1 ... 14:
|
||||
subband = RTW89_CH_2G;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RTW89_BAND_5G:
|
||||
switch (center_chan) {
|
||||
default:
|
||||
case 36 ... 64:
|
||||
subband = RTW89_CH_5G_BAND_1;
|
||||
break;
|
||||
case 100 ... 144:
|
||||
subband = RTW89_CH_5G_BAND_3;
|
||||
break;
|
||||
case 149 ... 177:
|
||||
subband = RTW89_CH_5G_BAND_4;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RTW89_BAND_6G:
|
||||
switch (center_chan) {
|
||||
default:
|
||||
case 1 ... 29:
|
||||
subband = RTW89_CH_6G_BAND_IDX0;
|
||||
break;
|
||||
case 33 ... 61:
|
||||
subband = RTW89_CH_6G_BAND_IDX1;
|
||||
break;
|
||||
case 65 ... 93:
|
||||
subband = RTW89_CH_6G_BAND_IDX2;
|
||||
break;
|
||||
case 97 ... 125:
|
||||
subband = RTW89_CH_6G_BAND_IDX3;
|
||||
break;
|
||||
case 129 ... 157:
|
||||
subband = RTW89_CH_6G_BAND_IDX4;
|
||||
break;
|
||||
case 161 ... 189:
|
||||
subband = RTW89_CH_6G_BAND_IDX5;
|
||||
break;
|
||||
case 193 ... 221:
|
||||
subband = RTW89_CH_6G_BAND_IDX6;
|
||||
break;
|
||||
case 225 ... 253:
|
||||
subband = RTW89_CH_6G_BAND_IDX7;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
rtw89_chan_create(chan, center_chan, channel->hw_value, band, bandwidth);
|
||||
}
|
||||
|
||||
chan_param->center_chan = center_chan;
|
||||
chan_param->center_freq = center_freq;
|
||||
chan_param->primary_chan = channel->hw_value;
|
||||
chan_param->bandwidth = bandwidth;
|
||||
chan_param->pri_ch_idx = primary_chan_idx;
|
||||
chan_param->band_type = band;
|
||||
chan_param->subband_type = subband;
|
||||
void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw89_chan *chan;
|
||||
enum rtw89_sub_entity_idx sub_entity_idx;
|
||||
enum rtw89_phy_idx phy_idx;
|
||||
enum rtw89_entity_mode mode;
|
||||
bool entity_active;
|
||||
|
||||
entity_active = rtw89_get_entity_state(rtwdev);
|
||||
if (!entity_active)
|
||||
return;
|
||||
|
||||
mode = rtw89_get_entity_mode(rtwdev);
|
||||
if (WARN(mode != RTW89_ENTITY_MODE_SCC, "Invalid ent mode: %d\n", mode))
|
||||
return;
|
||||
|
||||
sub_entity_idx = RTW89_SUB_ENTITY_0;
|
||||
phy_idx = RTW89_PHY_0;
|
||||
chan = rtw89_chan_get(rtwdev, sub_entity_idx);
|
||||
if (chip->ops->set_txpwr)
|
||||
chip->ops->set_txpwr(rtwdev, chan, phy_idx);
|
||||
}
|
||||
|
||||
void rtw89_set_channel(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct ieee80211_hw *hw = rtwdev->hw;
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
struct rtw89_channel_params ch_param;
|
||||
const struct cfg80211_chan_def *chandef;
|
||||
enum rtw89_sub_entity_idx sub_entity_idx;
|
||||
enum rtw89_mac_idx mac_idx;
|
||||
enum rtw89_phy_idx phy_idx;
|
||||
struct rtw89_chan chan;
|
||||
struct rtw89_channel_help_params bak;
|
||||
u8 center_chan, bandwidth;
|
||||
enum rtw89_entity_mode mode;
|
||||
bool band_changed;
|
||||
bool entity_active;
|
||||
|
||||
rtw89_get_channel_params(&hw->conf.chandef, &ch_param);
|
||||
if (WARN(ch_param.center_chan == 0, "Invalid channel\n"))
|
||||
entity_active = rtw89_get_entity_state(rtwdev);
|
||||
|
||||
mode = rtw89_entity_recalc(rtwdev);
|
||||
if (WARN(mode != RTW89_ENTITY_MODE_SCC, "Invalid ent mode: %d\n", mode))
|
||||
return;
|
||||
|
||||
center_chan = ch_param.center_chan;
|
||||
bandwidth = ch_param.bandwidth;
|
||||
band_changed = hal->current_band_type != ch_param.band_type ||
|
||||
hal->current_channel == 0;
|
||||
sub_entity_idx = RTW89_SUB_ENTITY_0;
|
||||
mac_idx = RTW89_MAC_0;
|
||||
phy_idx = RTW89_PHY_0;
|
||||
chandef = rtw89_chandef_get(rtwdev, sub_entity_idx);
|
||||
rtw89_get_channel_params(chandef, &chan);
|
||||
if (WARN(chan.channel == 0, "Invalid channel\n"))
|
||||
return;
|
||||
|
||||
hal->current_band_width = bandwidth;
|
||||
hal->current_channel = center_chan;
|
||||
hal->current_freq = ch_param.center_freq;
|
||||
hal->prev_primary_channel = hal->current_primary_channel;
|
||||
hal->prev_band_type = hal->current_band_type;
|
||||
hal->current_primary_channel = ch_param.primary_chan;
|
||||
hal->current_band_type = ch_param.band_type;
|
||||
hal->current_subband = ch_param.subband_type;
|
||||
band_changed = rtw89_assign_entity_chan(rtwdev, sub_entity_idx, &chan);
|
||||
|
||||
rtw89_chip_set_channel_prepare(rtwdev, &bak);
|
||||
rtw89_chip_set_channel_prepare(rtwdev, &bak, &chan, mac_idx, phy_idx);
|
||||
|
||||
chip->ops->set_channel(rtwdev, &ch_param);
|
||||
chip->ops->set_channel(rtwdev, &chan, mac_idx, phy_idx);
|
||||
|
||||
rtw89_chip_set_txpwr(rtwdev);
|
||||
rtw89_core_set_chip_txpwr(rtwdev);
|
||||
|
||||
rtw89_chip_set_channel_done(rtwdev, &bak);
|
||||
rtw89_chip_set_channel_done(rtwdev, &bak, &chan, mac_idx, phy_idx);
|
||||
|
||||
if (band_changed) {
|
||||
rtw89_btc_ntfy_switch_band(rtwdev, RTW89_PHY_0, hal->current_band_type);
|
||||
rtw89_chip_rfk_band_changed(rtwdev);
|
||||
if (!entity_active || band_changed) {
|
||||
rtw89_btc_ntfy_switch_band(rtwdev, phy_idx, chan.band_type);
|
||||
rtw89_chip_rfk_band_changed(rtwdev, phy_idx);
|
||||
}
|
||||
|
||||
rtw89_set_entity_state(rtwdev, true);
|
||||
}
|
||||
|
||||
static enum rtw89_core_tx_type
|
||||
@ -529,8 +495,8 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev,
|
||||
struct sk_buff *skb = tx_req->skb;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_vif *vif = tx_info->control.vif;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
u16 lowest_rate = hal->current_band_type == RTW89_BAND_2G ?
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u16 lowest_rate = chan->band_type == RTW89_BAND_2G ?
|
||||
RTW89_HW_RATE_CCK1 : RTW89_HW_RATE_OFDM6;
|
||||
|
||||
if (!vif || !vif->bss_conf.basic_rates || !tx_req->sta)
|
||||
@ -546,6 +512,7 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_vif *vif = tx_req->vif;
|
||||
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
|
||||
struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 qsel, ch_dma;
|
||||
|
||||
qsel = desc_info->hiq ? RTW89_TX_QSEL_B0_HI : RTW89_TX_QSEL_B0_MGMT;
|
||||
@ -564,9 +531,9 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
|
||||
desc_info->data_rate = rtw89_core_get_mgmt_rate(rtwdev, tx_req);
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_TXRX,
|
||||
"tx mgmt frame with rate 0x%x on channel %d (bw %d)\n",
|
||||
desc_info->data_rate, rtwdev->hal.current_channel,
|
||||
rtwdev->hal.current_band_width);
|
||||
"tx mgmt frame with rate 0x%x on channel %d (band %d, bw %d)\n",
|
||||
desc_info->data_rate, chan->channel, chan->band_type,
|
||||
chan->band_width);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -591,15 +558,16 @@ static void rtw89_core_get_no_ul_ofdma_htc(struct rtw89_dev *rtwdev, __le32 *htc
|
||||
};
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 om_bandwidth;
|
||||
|
||||
if (!chip->dis_2g_40m_ul_ofdma ||
|
||||
hal->current_band_type != RTW89_BAND_2G ||
|
||||
hal->current_band_width != RTW89_CHANNEL_WIDTH_40)
|
||||
chan->band_type != RTW89_BAND_2G ||
|
||||
chan->band_width != RTW89_CHANNEL_WIDTH_40)
|
||||
return;
|
||||
|
||||
om_bandwidth = hal->current_band_width < ARRAY_SIZE(rtw89_bandwidth_to_om) ?
|
||||
rtw89_bandwidth_to_om[hal->current_band_width] : 0;
|
||||
om_bandwidth = chan->band_width < ARRAY_SIZE(rtw89_bandwidth_to_om) ?
|
||||
rtw89_bandwidth_to_om[chan->band_width] : 0;
|
||||
*htc = le32_encode_bits(RTW89_HTC_VARIANT_HE, RTW89_HTC_MASK_VARIANT) |
|
||||
le32_encode_bits(RTW89_HTC_VARIANT_HE_CID_OM, RTW89_HTC_MASK_CTL_ID) |
|
||||
le32_encode_bits(hal->rx_nss - 1, RTW89_HTC_MASK_HTC_OM_RX_NSS) |
|
||||
@ -617,6 +585,7 @@ __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev,
|
||||
enum btc_pkt_type pkt_type)
|
||||
{
|
||||
struct ieee80211_sta *sta = tx_req->sta;
|
||||
struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
|
||||
struct sk_buff *skb = tx_req->skb;
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
@ -634,6 +603,9 @@ __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev,
|
||||
if (skb_headroom(skb) < IEEE80211_HT_CTL_LEN)
|
||||
return false;
|
||||
|
||||
if (rtwsta && rtwsta->ra_report.might_fallback_legacy)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -713,7 +685,7 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_vif *vif = tx_req->vif;
|
||||
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
|
||||
struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
|
||||
struct sk_buff *skb = tx_req->skb;
|
||||
u8 tid, tid_indicate;
|
||||
@ -738,7 +710,7 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev,
|
||||
|
||||
if (rate_pattern->enable)
|
||||
desc_info->data_retry_lowest_rate = rate_pattern->rate;
|
||||
else if (hal->current_band_type == RTW89_BAND_2G)
|
||||
else if (chan->band_type == RTW89_BAND_2G)
|
||||
desc_info->data_retry_lowest_rate = RTW89_HW_RATE_CCK1;
|
||||
else
|
||||
desc_info->data_retry_lowest_rate = RTW89_HW_RATE_OFDM6;
|
||||
@ -1448,8 +1420,11 @@ static void rtw89_core_rx_stats(struct rtw89_dev *rtwdev,
|
||||
static void rtw89_correct_cck_chan(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_rx_status *status)
|
||||
{
|
||||
u16 chan = rtwdev->hal.prev_primary_channel;
|
||||
u8 band = chan <= 14 ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
|
||||
const struct rtw89_chan_rcd *rcd =
|
||||
rtw89_chan_rcd_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u16 chan = rcd->prev_primary_channel;
|
||||
u8 band = rcd->prev_band_type == RTW89_BAND_2G ?
|
||||
NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
|
||||
|
||||
if (status->band != NL80211_BAND_2GHZ &&
|
||||
status->encoding == RX_ENC_LEGACY &&
|
||||
@ -1661,19 +1636,20 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_rx_desc_info *desc_info,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
{
|
||||
struct ieee80211_hw *hw = rtwdev->hw;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
const struct cfg80211_chan_def *chandef =
|
||||
rtw89_chandef_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
const struct rtw89_chan *cur = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u16 data_rate;
|
||||
u8 data_rate_mode;
|
||||
|
||||
/* currently using single PHY */
|
||||
rx_status->freq = hw->conf.chandef.chan->center_freq;
|
||||
rx_status->band = hw->conf.chandef.chan->band;
|
||||
rx_status->freq = chandef->chan->center_freq;
|
||||
rx_status->band = chandef->chan->band;
|
||||
|
||||
if (rtwdev->scanning &&
|
||||
RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
|
||||
u8 chan = hal->current_primary_channel;
|
||||
u8 band = hal->current_band_type;
|
||||
u8 chan = cur->primary_channel;
|
||||
u8 band = cur->band_type;
|
||||
enum nl80211_band nl_band;
|
||||
|
||||
nl_band = rtw89_hw_to_nl80211_band(band);
|
||||
@ -2266,45 +2242,69 @@ void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits)
|
||||
bitmap_zero(addr, nbits);
|
||||
}
|
||||
|
||||
int rtw89_core_acquire_sta_ba_entry(struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx)
|
||||
int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx)
|
||||
{
|
||||
struct rtw89_ba_cam_entry *entry;
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
|
||||
struct rtw89_ba_cam_entry *entry = NULL, *tmp;
|
||||
u8 idx;
|
||||
int i;
|
||||
|
||||
idx = rtw89_core_acquire_bit_map(rtwsta->ba_cam_map, RTW89_BA_CAM_NUM);
|
||||
if (idx == RTW89_BA_CAM_NUM) {
|
||||
/* allocate a static BA CAM to tid=0, so replace the existing
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
idx = rtw89_core_acquire_bit_map(cam_info->ba_cam_map, chip->bacam_num);
|
||||
if (idx == chip->bacam_num) {
|
||||
/* allocate a static BA CAM to tid=0/5, so replace the existing
|
||||
* one if BA CAM is full. Hardware will process the original tid
|
||||
* automatically.
|
||||
*/
|
||||
if (tid != 0)
|
||||
if (tid != 0 && tid != 5)
|
||||
return -ENOSPC;
|
||||
|
||||
idx = 0;
|
||||
for_each_set_bit(i, cam_info->ba_cam_map, chip->bacam_num) {
|
||||
tmp = &cam_info->ba_cam_entry[i];
|
||||
if (tmp->tid == 0 || tmp->tid == 5)
|
||||
continue;
|
||||
|
||||
idx = i;
|
||||
entry = tmp;
|
||||
list_del(&entry->list);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!entry)
|
||||
return -ENOSPC;
|
||||
} else {
|
||||
entry = &cam_info->ba_cam_entry[idx];
|
||||
}
|
||||
|
||||
entry = &rtwsta->ba_cam_entry[idx];
|
||||
entry->tid = tid;
|
||||
list_add_tail(&entry->list, &rtwsta->ba_cam_list);
|
||||
|
||||
*cam_idx = idx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtw89_core_release_sta_ba_entry(struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx)
|
||||
int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx)
|
||||
{
|
||||
struct rtw89_ba_cam_entry *entry;
|
||||
int i;
|
||||
struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
|
||||
struct rtw89_ba_cam_entry *entry = NULL, *tmp;
|
||||
u8 idx;
|
||||
|
||||
for (i = 0; i < RTW89_BA_CAM_NUM; i++) {
|
||||
if (!test_bit(i, rtwsta->ba_cam_map))
|
||||
continue;
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
entry = &rtwsta->ba_cam_entry[i];
|
||||
list_for_each_entry_safe(entry, tmp, &rtwsta->ba_cam_list, list) {
|
||||
if (entry->tid != tid)
|
||||
continue;
|
||||
|
||||
rtw89_core_release_bit_map(rtwsta->ba_cam_map, i);
|
||||
*cam_idx = i;
|
||||
idx = entry - cam_info->ba_cam_entry;
|
||||
list_del(&entry->list);
|
||||
|
||||
rtw89_core_release_bit_map(cam_info->ba_cam_map, idx);
|
||||
*cam_idx = idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2367,6 +2367,7 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev,
|
||||
|
||||
rtwsta->rtwvif = rtwvif;
|
||||
rtwsta->prev_rssi = 0;
|
||||
INIT_LIST_HEAD(&rtwsta->ba_cam_list);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
|
||||
rtw89_core_txq_init(rtwdev, sta->txq[i]);
|
||||
@ -2669,8 +2670,7 @@ static void rtw89_init_he_cap(struct rtw89_dev *rtwdev,
|
||||
phy_cap_info = he_cap->he_cap_elem.phy_cap_info;
|
||||
|
||||
he_cap->has_he = true;
|
||||
if (i == NL80211_IFTYPE_AP)
|
||||
mac_cap_info[0] = IEEE80211_HE_MAC_CAP0_HTC_HE;
|
||||
mac_cap_info[0] = IEEE80211_HE_MAC_CAP0_HTC_HE;
|
||||
if (i == NL80211_IFTYPE_STATION)
|
||||
mac_cap_info[1] = IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;
|
||||
mac_cap_info[2] = IEEE80211_HE_MAC_CAP2_ALL_ACK |
|
||||
@ -2706,6 +2706,8 @@ static void rtw89_init_he_cap(struct rtw89_dev *rtwdev,
|
||||
phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU;
|
||||
phy_cap_info[4] = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
|
||||
IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4;
|
||||
if (chip->support_bw160)
|
||||
phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4;
|
||||
phy_cap_info[5] = no_ng16 ? 0 :
|
||||
IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK |
|
||||
IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK;
|
||||
@ -2894,6 +2896,7 @@ int rtw89_core_start(struct rtw89_dev *rtwdev)
|
||||
|
||||
rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON);
|
||||
rtw89_fw_h2c_fw_log(rtwdev, rtwdev->fw.fw_log_enable);
|
||||
rtw89_fw_h2c_init_ba_cam(rtwdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2987,6 +2990,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
|
||||
return ret;
|
||||
}
|
||||
rtw89_ser_init(rtwdev);
|
||||
rtw89_entity_init(rtwdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3007,7 +3011,7 @@ EXPORT_SYMBOL(rtw89_core_deinit);
|
||||
void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
|
||||
const u8 *mac_addr, bool hw_scan)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
|
||||
rtwdev->scanning = true;
|
||||
rtw89_leave_lps(rtwdev);
|
||||
@ -3015,7 +3019,7 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
|
||||
rtw89_leave_ips(rtwdev);
|
||||
|
||||
ether_addr_copy(rtwvif->mac_addr, mac_addr);
|
||||
rtw89_btc_ntfy_scan_start(rtwdev, RTW89_PHY_0, hal->current_band_type);
|
||||
rtw89_btc_ntfy_scan_start(rtwdev, RTW89_PHY_0, chan->band_type);
|
||||
rtw89_chip_rfk_scan(rtwdev, true);
|
||||
rtw89_hci_recalc_int_mit(rtwdev);
|
||||
|
||||
@ -3141,6 +3145,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
|
||||
hw->vif_data_size = sizeof(struct rtw89_vif);
|
||||
hw->sta_data_size = sizeof(struct rtw89_sta);
|
||||
hw->txq_data_size = sizeof(struct rtw89_txq);
|
||||
hw->chanctx_data_size = sizeof(struct rtw89_chanctx_cfg);
|
||||
|
||||
SET_IEEE80211_PERM_ADDR(hw, efuse->addr);
|
||||
|
||||
@ -3234,6 +3239,63 @@ void rtw89_core_unregister(struct rtw89_dev *rtwdev)
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_core_unregister);
|
||||
|
||||
struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
|
||||
u32 bus_data_size,
|
||||
const struct rtw89_chip_info *chip)
|
||||
{
|
||||
struct ieee80211_hw *hw;
|
||||
struct rtw89_dev *rtwdev;
|
||||
struct ieee80211_ops *ops;
|
||||
u32 driver_data_size;
|
||||
u32 early_feat_map = 0;
|
||||
bool no_chanctx;
|
||||
|
||||
rtw89_early_fw_feature_recognize(device, chip, &early_feat_map);
|
||||
|
||||
ops = kmemdup(&rtw89_ops, sizeof(rtw89_ops), GFP_KERNEL);
|
||||
if (!ops)
|
||||
goto err;
|
||||
|
||||
no_chanctx = chip->support_chanctx_num == 0 ||
|
||||
!(early_feat_map & BIT(RTW89_FW_FEATURE_SCAN_OFFLOAD));
|
||||
|
||||
if (no_chanctx) {
|
||||
ops->add_chanctx = NULL;
|
||||
ops->remove_chanctx = NULL;
|
||||
ops->change_chanctx = NULL;
|
||||
ops->assign_vif_chanctx = NULL;
|
||||
ops->unassign_vif_chanctx = NULL;
|
||||
}
|
||||
|
||||
driver_data_size = sizeof(struct rtw89_dev) + bus_data_size;
|
||||
hw = ieee80211_alloc_hw(driver_data_size, ops);
|
||||
if (!hw)
|
||||
goto err;
|
||||
|
||||
rtwdev = hw->priv;
|
||||
rtwdev->hw = hw;
|
||||
rtwdev->dev = device;
|
||||
rtwdev->ops = ops;
|
||||
rtwdev->chip = chip;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_FW, "probe driver %s chanctx\n",
|
||||
no_chanctx ? "without" : "with");
|
||||
|
||||
return rtwdev;
|
||||
|
||||
err:
|
||||
kfree(ops);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_alloc_ieee80211_hw);
|
||||
|
||||
void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
kfree(rtwdev->ops);
|
||||
ieee80211_free_hw(rtwdev->hw);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_free_ieee80211_hw);
|
||||
|
||||
MODULE_AUTHOR("Realtek Corporation");
|
||||
MODULE_DESCRIPTION("Realtek 802.11ax wireless core module");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
@ -542,6 +542,12 @@ enum rtw89_phy_idx {
|
||||
RTW89_PHY_MAX
|
||||
};
|
||||
|
||||
enum rtw89_sub_entity_idx {
|
||||
RTW89_SUB_ENTITY_0 = 0,
|
||||
|
||||
NUM_OF_RTW89_SUB_ENTITY,
|
||||
};
|
||||
|
||||
enum rtw89_rf_path {
|
||||
RF_PATH_A = 0,
|
||||
RF_PATH_B = 1,
|
||||
@ -624,14 +630,23 @@ enum rtw89_sc_offset {
|
||||
RTW89_SC_40_LOWER = 10,
|
||||
};
|
||||
|
||||
struct rtw89_channel_params {
|
||||
u8 center_chan;
|
||||
u32 center_freq;
|
||||
u8 primary_chan;
|
||||
u8 bandwidth;
|
||||
u8 pri_ch_idx;
|
||||
u8 band_type;
|
||||
u8 subband_type;
|
||||
struct rtw89_chan {
|
||||
u8 channel;
|
||||
u8 primary_channel;
|
||||
enum rtw89_band band_type;
|
||||
enum rtw89_bandwidth band_width;
|
||||
|
||||
/* The follow-up are derived from the above. We must ensure that it
|
||||
* is assigned correctly in rtw89_chan_create() if new one is added.
|
||||
*/
|
||||
u32 freq;
|
||||
enum rtw89_subband subband_type;
|
||||
enum rtw89_sc_offset pri_ch_idx;
|
||||
};
|
||||
|
||||
struct rtw89_chan_rcd {
|
||||
u8 prev_primary_channel;
|
||||
enum rtw89_band prev_band_type;
|
||||
};
|
||||
|
||||
struct rtw89_channel_help_params {
|
||||
@ -793,7 +808,7 @@ struct rtw89_mac_ax_gnt {
|
||||
u8 gnt_bt;
|
||||
u8 gnt_wl_sw_en;
|
||||
u8 gnt_wl;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
#define RTW89_MAC_AX_COEX_GNT_NR 2
|
||||
struct rtw89_mac_ax_coex_gnt {
|
||||
@ -848,6 +863,7 @@ enum rtw89_btc_dcnt {
|
||||
BTC_DCNT_SLOT_NONSYNC,
|
||||
BTC_DCNT_BTCNT_FREEZE,
|
||||
BTC_DCNT_WL_SLOT_DRIFT,
|
||||
BTC_DCNT_BT_SLOT_DRIFT,
|
||||
BTC_DCNT_WL_STA_LAST,
|
||||
BTC_DCNT_NUM,
|
||||
};
|
||||
@ -920,12 +936,12 @@ struct rtw89_btc_wl_smap {
|
||||
u32 roaming: 1;
|
||||
u32 _4way: 1;
|
||||
u32 rf_off: 1;
|
||||
u32 lps: 1;
|
||||
u32 lps: 2;
|
||||
u32 ips: 1;
|
||||
u32 init_ok: 1;
|
||||
u32 traffic_dir : 2;
|
||||
u32 rf_off_pre: 1;
|
||||
u32 lps_pre: 1;
|
||||
u32 lps_pre: 2;
|
||||
};
|
||||
|
||||
enum rtw89_tfc_lv {
|
||||
@ -1108,6 +1124,27 @@ struct rtw89_btc_wl_active_role {
|
||||
u16 rx_rate;
|
||||
};
|
||||
|
||||
struct rtw89_btc_wl_active_role_v1 {
|
||||
u8 connected: 1;
|
||||
u8 pid: 3;
|
||||
u8 phy: 1;
|
||||
u8 noa: 1;
|
||||
u8 band: 2;
|
||||
|
||||
u8 client_ps: 1;
|
||||
u8 bw: 7;
|
||||
|
||||
u8 role;
|
||||
u8 ch;
|
||||
|
||||
u16 tx_lvl;
|
||||
u16 rx_lvl;
|
||||
u16 tx_rate;
|
||||
u16 rx_rate;
|
||||
|
||||
u32 noa_duration; /* ms */
|
||||
};
|
||||
|
||||
struct rtw89_btc_wl_role_info_bpos {
|
||||
u16 none: 1;
|
||||
u16 station: 1;
|
||||
@ -1123,6 +1160,12 @@ struct rtw89_btc_wl_role_info_bpos {
|
||||
u16 nan: 1;
|
||||
};
|
||||
|
||||
struct rtw89_btc_wl_scc_ctrl {
|
||||
u8 null_role1;
|
||||
u8 null_role2;
|
||||
u8 ebt_null; /* if tx null at EBT slot */
|
||||
};
|
||||
|
||||
union rtw89_btc_wl_role_info_map {
|
||||
u16 val;
|
||||
struct rtw89_btc_wl_role_info_bpos role;
|
||||
@ -1135,6 +1178,21 @@ struct rtw89_btc_wl_role_info { /* struct size must be n*4 bytes */
|
||||
struct rtw89_btc_wl_active_role active_role[RTW89_PORT_NUM];
|
||||
};
|
||||
|
||||
struct rtw89_btc_wl_role_info_v1 { /* struct size must be n*4 bytes */
|
||||
u8 connect_cnt;
|
||||
u8 link_mode;
|
||||
union rtw89_btc_wl_role_info_map role_map;
|
||||
struct rtw89_btc_wl_active_role_v1 active_role_v1[RTW89_PORT_NUM];
|
||||
u32 mrole_type; /* btc_wl_mrole_type */
|
||||
u32 mrole_noa_duration; /* ms */
|
||||
|
||||
u32 dbcc_en: 1;
|
||||
u32 dbcc_chg: 1;
|
||||
u32 dbcc_2g_phy: 2; /* which phy operate in 2G, HW_PHY_0 or HW_PHY_1 */
|
||||
u32 link_mode_chg: 1;
|
||||
u32 rsvd: 27;
|
||||
};
|
||||
|
||||
struct rtw89_btc_wl_ver_info {
|
||||
u32 fw_coex; /* match with which coex_ver */
|
||||
u32 fw;
|
||||
@ -1240,6 +1298,7 @@ struct rtw89_btc_wl_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_scan_info scan_info;
|
||||
struct rtw89_btc_wl_dbcc_info dbcc_info;
|
||||
struct rtw89_btc_rf_para rf_para;
|
||||
@ -1346,32 +1405,43 @@ struct rtw89_btc_cx {
|
||||
};
|
||||
|
||||
struct rtw89_btc_fbtc_tdma {
|
||||
u8 type;
|
||||
u8 type; /* chip_info::fcxtdma_ver */
|
||||
u8 rxflctrl;
|
||||
u8 txpause;
|
||||
u8 wtgle_n;
|
||||
u8 leak_n;
|
||||
u8 ext_ctrl;
|
||||
u8 rsvd0;
|
||||
u8 rsvd1;
|
||||
u8 rxflctrl_role;
|
||||
u8 option_ctrl;
|
||||
} __packed;
|
||||
|
||||
struct rtw89_btc_fbtc_tdma_v1 {
|
||||
u8 fver; /* chip_info::fcxtdma_ver */
|
||||
u8 rsvd;
|
||||
__le16 rsvd1;
|
||||
struct rtw89_btc_fbtc_tdma tdma;
|
||||
} __packed;
|
||||
|
||||
#define CXMREG_MAX 30
|
||||
#define FCXMAX_STEP 255 /*STEP trace record cnt, Max:65535, default:255*/
|
||||
#define BTCRPT_VER 1
|
||||
#define BTC_CYCLE_SLOT_MAX 48 /* must be even number, non-zero */
|
||||
|
||||
enum rtw89_btc_bt_rfk_counter {
|
||||
enum rtw89_btc_bt_sta_counter {
|
||||
BTC_BCNT_RFK_REQ = 0,
|
||||
BTC_BCNT_RFK_GO = 1,
|
||||
BTC_BCNT_RFK_REJECT = 2,
|
||||
BTC_BCNT_RFK_FAIL = 3,
|
||||
BTC_BCNT_RFK_TIMEOUT = 4,
|
||||
BTC_BCNT_RFK_MAX
|
||||
BTC_BCNT_HI_TX = 5,
|
||||
BTC_BCNT_HI_RX = 6,
|
||||
BTC_BCNT_LO_TX = 7,
|
||||
BTC_BCNT_LO_RX = 8,
|
||||
BTC_BCNT_POLLUTED = 9,
|
||||
BTC_BCNT_STA_MAX
|
||||
};
|
||||
|
||||
struct rtw89_btc_fbtc_rpt_ctrl {
|
||||
u16 fver;
|
||||
u16 fver; /* chip_info::fcxbtcrpt_ver */
|
||||
u16 rpt_cnt; /* tmr counters */
|
||||
u32 wl_fw_coex_ver; /* match which driver's coex version */
|
||||
u32 wl_fw_cx_offload;
|
||||
@ -1384,11 +1454,56 @@ struct rtw89_btc_fbtc_rpt_ctrl {
|
||||
u32 mb_a2dp_empty_cnt; /* a2dp empty count */
|
||||
u32 mb_a2dp_flct_cnt; /* a2dp empty flow control counter */
|
||||
u32 mb_a2dp_full_cnt; /* a2dp empty full counter */
|
||||
u32 bt_rfk_cnt[BTC_BCNT_RFK_MAX];
|
||||
u32 bt_rfk_cnt[BTC_BCNT_HI_TX];
|
||||
u32 c2h_cnt; /* fw send c2h counter */
|
||||
u32 h2c_cnt; /* fw recv h2c counter */
|
||||
} __packed;
|
||||
|
||||
struct rtw89_btc_fbtc_rpt_ctrl_info {
|
||||
__le32 cnt; /* fw report counter */
|
||||
__le32 en; /* report map */
|
||||
__le32 para; /* not used */
|
||||
|
||||
__le32 cnt_c2h; /* fw send c2h counter */
|
||||
__le32 cnt_h2c; /* fw recv h2c counter */
|
||||
__le32 len_c2h; /* The total length of the last C2H */
|
||||
|
||||
__le32 cnt_aoac_rf_on; /* rf-on counter for aoac switch notify */
|
||||
__le32 cnt_aoac_rf_off; /* rf-off counter for aoac switch notify */
|
||||
} __packed;
|
||||
|
||||
struct rtw89_btc_fbtc_rpt_ctrl_wl_fw_info {
|
||||
__le32 cx_ver; /* match which driver's coex version */
|
||||
__le32 cx_offload;
|
||||
__le32 fw_ver;
|
||||
} __packed;
|
||||
|
||||
struct rtw89_btc_fbtc_rpt_ctrl_a2dp_empty {
|
||||
__le32 cnt_empty; /* a2dp empty count */
|
||||
__le32 cnt_flowctrl; /* a2dp empty flow control counter */
|
||||
__le32 cnt_tx;
|
||||
__le32 cnt_ack;
|
||||
__le32 cnt_nack;
|
||||
} __packed;
|
||||
|
||||
struct rtw89_btc_fbtc_rpt_ctrl_bt_mailbox {
|
||||
__le32 cnt_send_ok; /* fw send mailbox ok counter */
|
||||
__le32 cnt_send_fail; /* fw send mailbox fail counter */
|
||||
__le32 cnt_recv; /* fw recv mailbox counter */
|
||||
struct rtw89_btc_fbtc_rpt_ctrl_a2dp_empty a2dp;
|
||||
} __packed;
|
||||
|
||||
struct rtw89_btc_fbtc_rpt_ctrl_v1 {
|
||||
u8 fver;
|
||||
u8 rsvd;
|
||||
__le16 rsvd1;
|
||||
struct rtw89_btc_fbtc_rpt_ctrl_info rpt_info;
|
||||
struct rtw89_btc_fbtc_rpt_ctrl_wl_fw_info wl_fw_info;
|
||||
struct rtw89_btc_fbtc_rpt_ctrl_bt_mailbox bt_mbx_info;
|
||||
__le32 bt_cnt[BTC_BCNT_STA_MAX];
|
||||
struct rtw89_mac_ax_gnt gnt_val[RTW89_PHY_MAX];
|
||||
} __packed;
|
||||
|
||||
enum rtw89_fbtc_ext_ctrl_type {
|
||||
CXECTL_OFF = 0x0, /* tdma off */
|
||||
CXECTL_B2 = 0x1, /* allow B2 (beacon-early) */
|
||||
@ -1457,10 +1572,9 @@ enum { /* STEP TYPE */
|
||||
CXSTEP_MAX,
|
||||
};
|
||||
|
||||
#define FCXGPIODBG_VER 1
|
||||
#define BTC_DBG_MAX1 32
|
||||
struct rtw89_btc_fbtc_gpio_dbg {
|
||||
u8 fver;
|
||||
u8 fver; /* chip_info::fcxgpiodbg_ver */
|
||||
u8 rsvd;
|
||||
u16 rsvd2;
|
||||
u32 en_map; /* which debug signal (see btc_wl_gpio_debug) is enable */
|
||||
@ -1468,9 +1582,8 @@ struct rtw89_btc_fbtc_gpio_dbg {
|
||||
u8 gpio_map[BTC_DBG_MAX1]; /*the debug signals to GPIO-Position */
|
||||
} __packed;
|
||||
|
||||
#define FCXMREG_VER 1
|
||||
struct rtw89_btc_fbtc_mreg_val {
|
||||
u8 fver;
|
||||
u8 fver; /* chip_info::fcxmreg_ver */
|
||||
u8 reg_num;
|
||||
__le16 rsvd;
|
||||
__le32 mreg_val[CXMREG_MAX];
|
||||
@ -1492,16 +1605,14 @@ struct rtw89_btc_fbtc_slot {
|
||||
__le16 cxtype;
|
||||
} __packed;
|
||||
|
||||
#define FCXSLOTS_VER 1
|
||||
struct rtw89_btc_fbtc_slots {
|
||||
u8 fver;
|
||||
u8 fver; /* chip_info::fcxslots_ver */
|
||||
u8 tbl_num;
|
||||
__le16 rsvd;
|
||||
__le32 update_map;
|
||||
struct rtw89_btc_fbtc_slot slot[CXST_MAX];
|
||||
} __packed;
|
||||
|
||||
#define FCXSTEP_VER 2
|
||||
struct rtw89_btc_fbtc_step {
|
||||
u8 type;
|
||||
u8 val;
|
||||
@ -1509,7 +1620,7 @@ struct rtw89_btc_fbtc_step {
|
||||
} __packed;
|
||||
|
||||
struct rtw89_btc_fbtc_steps {
|
||||
u8 fver;
|
||||
u8 fver; /* chip_info::fcxstep_ver */
|
||||
u8 rsvd;
|
||||
__le16 cnt;
|
||||
__le16 pos_old;
|
||||
@ -1517,9 +1628,8 @@ struct rtw89_btc_fbtc_steps {
|
||||
struct rtw89_btc_fbtc_step step[FCXMAX_STEP];
|
||||
} __packed;
|
||||
|
||||
#define FCXCYSTA_VER 2
|
||||
struct rtw89_btc_fbtc_cysta { /* statistics for cycles */
|
||||
u8 fver;
|
||||
u8 fver; /* chip_info::fcxcysta_ver */
|
||||
u8 rsvd;
|
||||
__le16 cycles; /* total cycle number */
|
||||
__le16 cycles_a2dp[CXT_FLCTRL_MAX];
|
||||
@ -1544,19 +1654,71 @@ struct rtw89_btc_fbtc_cysta { /* statistics for cycles */
|
||||
__le16 tslot_cycle[BTC_CYCLE_SLOT_MAX];
|
||||
} __packed;
|
||||
|
||||
#define FCXNULLSTA_VER 1
|
||||
struct rtw89_btc_fbtc_cynullsta { /* cycle null statistics */
|
||||
struct rtw89_btc_fbtc_fdd_try_info {
|
||||
__le16 cycles[CXT_FLCTRL_MAX];
|
||||
__le16 tavg[CXT_FLCTRL_MAX]; /* avg try BT-Slot-TDD/BT-slot-FDD time */
|
||||
__le16 tmax[CXT_FLCTRL_MAX]; /* max try BT-Slot-TDD/BT-slot-FDD time */
|
||||
} __packed;
|
||||
|
||||
struct rtw89_btc_fbtc_cycle_time_info {
|
||||
__le16 tavg[CXT_MAX]; /* avg wl/bt cycle time */
|
||||
__le16 tmax[CXT_MAX]; /* max wl/bt cycle time */
|
||||
__le16 tmaxdiff[CXT_MAX]; /* max wl-wl bt-bt cycle diff time */
|
||||
} __packed;
|
||||
|
||||
struct rtw89_btc_fbtc_a2dp_trx_stat {
|
||||
u8 empty_cnt;
|
||||
u8 retry_cnt;
|
||||
u8 tx_rate;
|
||||
u8 tx_cnt;
|
||||
u8 ack_cnt;
|
||||
u8 nack_cnt;
|
||||
u8 rsvd1;
|
||||
u8 rsvd2;
|
||||
} __packed;
|
||||
|
||||
struct rtw89_btc_fbtc_cycle_a2dp_empty_info {
|
||||
__le16 cnt; /* a2dp empty cnt */
|
||||
__le16 cnt_timeout; /* a2dp empty timeout cnt*/
|
||||
__le16 tavg; /* avg a2dp empty time */
|
||||
__le16 tmax; /* max a2dp empty time */
|
||||
} __packed;
|
||||
|
||||
struct rtw89_btc_fbtc_cycle_leak_info {
|
||||
__le32 cnt_rximr; /* the rximr occur at leak slot */
|
||||
__le16 tavg; /* avg leak-slot time */
|
||||
__le16 tmax; /* max leak-slot time */
|
||||
} __packed;
|
||||
|
||||
struct rtw89_btc_fbtc_cysta_v1 { /* statistics for cycles */
|
||||
u8 fver;
|
||||
u8 rsvd;
|
||||
__le16 cycles; /* total cycle number */
|
||||
__le16 slot_step_time[BTC_CYCLE_SLOT_MAX];
|
||||
struct rtw89_btc_fbtc_cycle_time_info cycle_time;
|
||||
struct rtw89_btc_fbtc_fdd_try_info fdd_try;
|
||||
struct rtw89_btc_fbtc_cycle_a2dp_empty_info a2dp_ept;
|
||||
struct rtw89_btc_fbtc_a2dp_trx_stat a2dp_trx[BTC_CYCLE_SLOT_MAX];
|
||||
struct rtw89_btc_fbtc_cycle_leak_info leak_slot;
|
||||
__le32 slot_cnt[CXST_MAX]; /* slot count */
|
||||
__le32 bcn_cnt[CXBCN_MAX];
|
||||
__le32 collision_cnt; /* counter for event/timer occur at the same time */
|
||||
__le32 skip_cnt;
|
||||
__le32 except_cnt;
|
||||
__le32 except_map;
|
||||
} __packed;
|
||||
|
||||
struct rtw89_btc_fbtc_cynullsta { /* cycle null statistics */
|
||||
u8 fver; /* chip_info::fcxnullsta_ver */
|
||||
u8 rsvd;
|
||||
__le16 rsvd2;
|
||||
__le32 max_t[2]; /* max_t for 0:null0/1:null1 */
|
||||
__le32 avg_t[2]; /* avg_t for 0:null0/1:null1 */
|
||||
__le32 result[2][4]; /* 0:fail, 1:ok, 2:on_time, 3:retry */
|
||||
} __packed;
|
||||
|
||||
#define FCX_BTVER_VER 1
|
||||
struct rtw89_btc_fbtc_btver {
|
||||
u8 fver;
|
||||
u8 fver; /* chip_info::fcxbtver_ver */
|
||||
u8 rsvd;
|
||||
__le16 rsvd2;
|
||||
__le32 coex_ver; /*bit[15:8]->shared, bit[7:0]->non-shared */
|
||||
@ -1564,17 +1726,15 @@ struct rtw89_btc_fbtc_btver {
|
||||
__le32 feature;
|
||||
} __packed;
|
||||
|
||||
#define FCX_BTSCAN_VER 1
|
||||
struct rtw89_btc_fbtc_btscan {
|
||||
u8 fver;
|
||||
u8 fver; /* chip_info::fcxbtscan_ver */
|
||||
u8 rsvd;
|
||||
__le16 rsvd2;
|
||||
u8 scan[6];
|
||||
} __packed;
|
||||
|
||||
#define FCX_BTAFH_VER 1
|
||||
struct rtw89_btc_fbtc_btafh {
|
||||
u8 fver;
|
||||
u8 fver; /* chip_info::fcxbtafh_ver */
|
||||
u8 rsvd;
|
||||
__le16 rsvd2;
|
||||
u8 afh_l[4]; /*bit0:2402, bit1: 2403.... bit31:2433 */
|
||||
@ -1582,9 +1742,8 @@ struct rtw89_btc_fbtc_btafh {
|
||||
u8 afh_h[4]; /*bit0:2466, bit1:2467......bit14:2480 */
|
||||
} __packed;
|
||||
|
||||
#define FCX_BTDEVINFO_VER 1
|
||||
struct rtw89_btc_fbtc_btdevinfo {
|
||||
u8 fver;
|
||||
u8 fver; /* chip_info::fcxbtdevinfo_ver */
|
||||
u8 rsvd;
|
||||
__le16 vendor_id;
|
||||
__le32 dev_name; /* only 24 bits valid */
|
||||
@ -1609,6 +1768,7 @@ struct rtw89_btc_dm {
|
||||
struct rtw89_btc_rf_trx_para rf_trx_para;
|
||||
struct rtw89_btc_wl_tx_limit_para wl_tx_limit;
|
||||
struct rtw89_btc_dm_step dm_step;
|
||||
struct rtw89_btc_wl_scc_ctrl wl_scc;
|
||||
union rtw89_btc_dm_error_map error;
|
||||
u32 cnt_dm[BTC_DCNT_NUM];
|
||||
u32 cnt_notify[BTC_NCNT_NUM];
|
||||
@ -1628,7 +1788,8 @@ struct rtw89_btc_dm {
|
||||
u32 wl_btg_rx: 1;
|
||||
u32 trx_para_level: 8;
|
||||
u32 wl_stb_chg: 1;
|
||||
u32 rsvd: 3;
|
||||
u32 tdma_instant_excute: 1;
|
||||
u32 rsvd: 2;
|
||||
|
||||
u16 slot_dur[CXST_MAX];
|
||||
|
||||
@ -1650,8 +1811,6 @@ struct rtw89_btc_dbg {
|
||||
u32 rb_val;
|
||||
};
|
||||
|
||||
#define FCXTDMA_VER 1
|
||||
|
||||
enum rtw89_btc_btf_fw_event {
|
||||
BTF_EVNT_RPT = 0,
|
||||
BTF_EVNT_BT_INFO = 1,
|
||||
@ -1704,12 +1863,18 @@ struct rtw89_btc_rpt_cmn_info {
|
||||
|
||||
struct rtw89_btc_report_ctrl_state {
|
||||
struct rtw89_btc_rpt_cmn_info cinfo; /* common info, by driver */
|
||||
struct rtw89_btc_fbtc_rpt_ctrl finfo; /* info from fw */
|
||||
union {
|
||||
struct rtw89_btc_fbtc_rpt_ctrl finfo; /* info from fw for 52A*/
|
||||
struct rtw89_btc_fbtc_rpt_ctrl_v1 finfo_v1; /* info from fw for 52C*/
|
||||
};
|
||||
};
|
||||
|
||||
struct rtw89_btc_rpt_fbtc_tdma {
|
||||
struct rtw89_btc_rpt_cmn_info cinfo; /* common info, by driver */
|
||||
struct rtw89_btc_fbtc_tdma finfo; /* info from fw */
|
||||
union {
|
||||
struct rtw89_btc_fbtc_tdma finfo; /* info from fw */
|
||||
struct rtw89_btc_fbtc_tdma_v1 finfo_v1; /* info from fw for 52C*/
|
||||
};
|
||||
};
|
||||
|
||||
struct rtw89_btc_rpt_fbtc_slots {
|
||||
@ -1719,7 +1884,10 @@ struct rtw89_btc_rpt_fbtc_slots {
|
||||
|
||||
struct rtw89_btc_rpt_fbtc_cysta {
|
||||
struct rtw89_btc_rpt_cmn_info cinfo; /* common info, by driver */
|
||||
struct rtw89_btc_fbtc_cysta finfo; /* info from fw */
|
||||
union {
|
||||
struct rtw89_btc_fbtc_cysta finfo; /* info from fw for 52A*/
|
||||
struct rtw89_btc_fbtc_cysta_v1 finfo_v1; /* info from fw for 52C*/
|
||||
};
|
||||
};
|
||||
|
||||
struct rtw89_btc_rpt_fbtc_step {
|
||||
@ -1911,19 +2079,20 @@ struct rtw89_ra_report {
|
||||
struct rate_info txrate;
|
||||
u32 bit_rate;
|
||||
u16 hw_rate;
|
||||
bool might_fallback_legacy;
|
||||
};
|
||||
|
||||
DECLARE_EWMA(rssi, 10, 16);
|
||||
|
||||
#define RTW89_BA_CAM_NUM 2
|
||||
|
||||
struct rtw89_ba_cam_entry {
|
||||
struct list_head list;
|
||||
u8 tid;
|
||||
};
|
||||
|
||||
#define RTW89_MAX_ADDR_CAM_NUM 128
|
||||
#define RTW89_MAX_BSSID_CAM_NUM 20
|
||||
#define RTW89_MAX_SEC_CAM_NUM 128
|
||||
#define RTW89_MAX_BA_CAM_NUM 8
|
||||
#define RTW89_SEC_CAM_IN_ADDR_CAM 7
|
||||
|
||||
struct rtw89_addr_cam_entry {
|
||||
@ -1979,6 +2148,7 @@ struct rtw89_sta {
|
||||
__le32 htc_template;
|
||||
struct rtw89_addr_cam_entry addr_cam; /* AP mode or TDLS peer only */
|
||||
struct rtw89_bssid_cam_entry bssid_cam; /* TDLS peer only */
|
||||
struct list_head ba_cam_list;
|
||||
|
||||
bool use_cfg_mask;
|
||||
struct cfg80211_bitrate_mask mask;
|
||||
@ -1987,9 +2157,6 @@ struct rtw89_sta {
|
||||
u32 ampdu_max_time:4;
|
||||
bool cctl_tx_retry_limit;
|
||||
u32 data_tx_cnt_lmt:6;
|
||||
|
||||
DECLARE_BITMAP(ba_cam_map, RTW89_BA_CAM_NUM);
|
||||
struct rtw89_ba_cam_entry ba_cam_entry[RTW89_BA_CAM_NUM];
|
||||
};
|
||||
|
||||
struct rtw89_efuse {
|
||||
@ -2100,20 +2267,29 @@ struct rtw89_chip_ops {
|
||||
bool (*write_rf)(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
||||
u32 addr, u32 mask, u32 data);
|
||||
void (*set_channel)(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param);
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_mac_idx mac_idx,
|
||||
enum rtw89_phy_idx phy_idx);
|
||||
void (*set_channel_help)(struct rtw89_dev *rtwdev, bool enter,
|
||||
struct rtw89_channel_help_params *p);
|
||||
struct rtw89_channel_help_params *p,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_mac_idx mac_idx,
|
||||
enum rtw89_phy_idx phy_idx);
|
||||
int (*read_efuse)(struct rtw89_dev *rtwdev, u8 *log_map);
|
||||
int (*read_phycap)(struct rtw89_dev *rtwdev, u8 *phycap_map);
|
||||
void (*fem_setup)(struct rtw89_dev *rtwdev);
|
||||
void (*rfk_init)(struct rtw89_dev *rtwdev);
|
||||
void (*rfk_channel)(struct rtw89_dev *rtwdev);
|
||||
void (*rfk_band_changed)(struct rtw89_dev *rtwdev);
|
||||
void (*rfk_band_changed)(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy_idx);
|
||||
void (*rfk_scan)(struct rtw89_dev *rtwdev, bool start);
|
||||
void (*rfk_track)(struct rtw89_dev *rtwdev);
|
||||
void (*power_trim)(struct rtw89_dev *rtwdev);
|
||||
void (*set_txpwr)(struct rtw89_dev *rtwdev);
|
||||
void (*set_txpwr_ctrl)(struct rtw89_dev *rtwdev);
|
||||
void (*set_txpwr)(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx);
|
||||
void (*set_txpwr_ctrl)(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy_idx);
|
||||
int (*init_txpwr_unit)(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
|
||||
u8 (*get_thermal)(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path);
|
||||
void (*ctrl_btg)(struct rtw89_dev *rtwdev, bool btg);
|
||||
@ -2150,6 +2326,7 @@ struct rtw89_chip_ops {
|
||||
void (*btc_bt_aci_imp)(struct rtw89_dev *rtwdev);
|
||||
void (*btc_update_bt_cnt)(struct rtw89_dev *rtwdev);
|
||||
void (*btc_wl_s1_standby)(struct rtw89_dev *rtwdev, bool state);
|
||||
void (*btc_set_policy)(struct rtw89_dev *rtwdev, u16 policy_type);
|
||||
};
|
||||
|
||||
enum rtw89_dma_ch {
|
||||
@ -2384,6 +2561,7 @@ struct rtw89_chip_info {
|
||||
const struct rtw89_hfc_param_ini *hfc_param_ini;
|
||||
const struct rtw89_dle_mem *dle_mem;
|
||||
u32 rf_base_addr[2];
|
||||
u8 support_chanctx_num;
|
||||
u8 support_bands;
|
||||
bool support_bw160;
|
||||
bool hw_sec_hdr;
|
||||
@ -2393,6 +2571,9 @@ struct rtw89_chip_info {
|
||||
u8 acam_num;
|
||||
u8 bcam_num;
|
||||
u8 scam_num;
|
||||
u8 bacam_num;
|
||||
u8 bacam_dynamic_num;
|
||||
bool bacam_v1;
|
||||
|
||||
u8 sec_ctrl_efuse_size;
|
||||
u32 physical_efuse_size;
|
||||
@ -2437,6 +2618,19 @@ struct rtw89_chip_info {
|
||||
u8 scbd;
|
||||
u8 mailbox;
|
||||
|
||||
u8 fcxbtcrpt_ver;
|
||||
u8 fcxtdma_ver;
|
||||
u8 fcxslots_ver;
|
||||
u8 fcxcysta_ver;
|
||||
u8 fcxstep_ver;
|
||||
u8 fcxnullsta_ver;
|
||||
u8 fcxmreg_ver;
|
||||
u8 fcxgpiodbg_ver;
|
||||
u8 fcxbtver_ver;
|
||||
u8 fcxbtscan_ver;
|
||||
u8 fcxbtafh_ver;
|
||||
u8 fcxbtdevinfo_ver;
|
||||
|
||||
u8 afh_guard_ch;
|
||||
const u8 *wl_rssi_thres;
|
||||
const u8 *bt_rssi_thres;
|
||||
@ -2536,6 +2730,18 @@ struct rtw89_fw_suit {
|
||||
#define RTW89_FW_SUIT_VER_CODE(s) \
|
||||
RTW89_FW_VER_CODE((s)->major_ver, (s)->minor_ver, (s)->sub_ver, (s)->sub_idex)
|
||||
|
||||
#define RTW89_MFW_HDR_VER_CODE(mfw_hdr) \
|
||||
RTW89_FW_VER_CODE((mfw_hdr)->ver.major, \
|
||||
(mfw_hdr)->ver.minor, \
|
||||
(mfw_hdr)->ver.sub, \
|
||||
(mfw_hdr)->ver.idx)
|
||||
|
||||
#define RTW89_FW_HDR_VER_CODE(fw_hdr) \
|
||||
RTW89_FW_VER_CODE(GET_FW_HDR_MAJOR_VERSION(fw_hdr), \
|
||||
GET_FW_HDR_MINOR_VERSION(fw_hdr), \
|
||||
GET_FW_HDR_SUBVERSION(fw_hdr), \
|
||||
GET_FW_HDR_SUBINDEX(fw_hdr))
|
||||
|
||||
struct rtw89_fw_info {
|
||||
const struct firmware *firmware;
|
||||
struct rtw89_dev *rtwdev;
|
||||
@ -2558,6 +2764,8 @@ struct rtw89_cam_info {
|
||||
DECLARE_BITMAP(addr_cam_map, RTW89_MAX_ADDR_CAM_NUM);
|
||||
DECLARE_BITMAP(bssid_cam_map, RTW89_MAX_BSSID_CAM_NUM);
|
||||
DECLARE_BITMAP(sec_cam_map, RTW89_MAX_SEC_CAM_NUM);
|
||||
DECLARE_BITMAP(ba_cam_map, RTW89_MAX_BA_CAM_NUM);
|
||||
struct rtw89_ba_cam_entry ba_cam_entry[RTW89_MAX_BA_CAM_NUM];
|
||||
};
|
||||
|
||||
enum rtw89_sar_sources {
|
||||
@ -2599,17 +2807,17 @@ struct rtw89_sar_info {
|
||||
};
|
||||
};
|
||||
|
||||
struct rtw89_chanctx_cfg {
|
||||
enum rtw89_sub_entity_idx idx;
|
||||
};
|
||||
|
||||
enum rtw89_entity_mode {
|
||||
RTW89_ENTITY_MODE_SCC,
|
||||
};
|
||||
|
||||
struct rtw89_hal {
|
||||
u32 rx_fltr;
|
||||
u8 cv;
|
||||
u8 current_channel;
|
||||
u32 current_freq;
|
||||
u8 prev_primary_channel;
|
||||
u8 current_primary_channel;
|
||||
enum rtw89_subband current_subband;
|
||||
u8 current_band_width;
|
||||
u8 prev_band_type;
|
||||
u8 current_band_type;
|
||||
u32 sw_amsdu_max_size;
|
||||
u32 antenna_tx;
|
||||
u32 antenna_rx;
|
||||
@ -2617,6 +2825,15 @@ struct rtw89_hal {
|
||||
u8 rx_nss;
|
||||
bool support_cckpd;
|
||||
bool support_igi;
|
||||
|
||||
DECLARE_BITMAP(entity_map, NUM_OF_RTW89_SUB_ENTITY);
|
||||
struct cfg80211_chan_def chandef[NUM_OF_RTW89_SUB_ENTITY];
|
||||
|
||||
bool entity_active;
|
||||
enum rtw89_entity_mode entity_mode;
|
||||
|
||||
struct rtw89_chan chan[NUM_OF_RTW89_SUB_ENTITY];
|
||||
struct rtw89_chan_rcd chan_rcd[NUM_OF_RTW89_SUB_ENTITY];
|
||||
};
|
||||
|
||||
#define RTW89_MAX_MAC_ID_NUM 128
|
||||
@ -3119,6 +3336,7 @@ struct rtw89_phy_efuse_gain {
|
||||
struct rtw89_dev {
|
||||
struct ieee80211_hw *hw;
|
||||
struct device *dev;
|
||||
const struct ieee80211_ops *ops;
|
||||
|
||||
bool dbcc_en;
|
||||
struct rtw89_hw_scan_info scan_info;
|
||||
@ -3588,16 +3806,51 @@ struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif *rtwvif,
|
||||
|
||||
static inline
|
||||
void rtw89_chip_set_channel_prepare(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_help_params *p)
|
||||
struct rtw89_channel_help_params *p,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_mac_idx mac_idx,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
rtwdev->chip->ops->set_channel_help(rtwdev, true, p);
|
||||
rtwdev->chip->ops->set_channel_help(rtwdev, true, p, chan,
|
||||
mac_idx, phy_idx);
|
||||
}
|
||||
|
||||
static inline
|
||||
void rtw89_chip_set_channel_done(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_help_params *p)
|
||||
struct rtw89_channel_help_params *p,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_mac_idx mac_idx,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
rtwdev->chip->ops->set_channel_help(rtwdev, false, p);
|
||||
rtwdev->chip->ops->set_channel_help(rtwdev, false, p, chan,
|
||||
mac_idx, phy_idx);
|
||||
}
|
||||
|
||||
static inline
|
||||
const struct cfg80211_chan_def *rtw89_chandef_get(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_sub_entity_idx idx)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
||||
return &hal->chandef[idx];
|
||||
}
|
||||
|
||||
static inline
|
||||
const struct rtw89_chan *rtw89_chan_get(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_sub_entity_idx idx)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
||||
return &hal->chan[idx];
|
||||
}
|
||||
|
||||
static inline
|
||||
const struct rtw89_chan_rcd *rtw89_chan_rcd_get(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_sub_entity_idx idx)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
||||
return &hal->chan_rcd[idx];
|
||||
}
|
||||
|
||||
static inline void rtw89_chip_fem_setup(struct rtw89_dev *rtwdev)
|
||||
@ -3632,12 +3885,13 @@ static inline void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev)
|
||||
chip->ops->rfk_channel(rtwdev);
|
||||
}
|
||||
|
||||
static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev)
|
||||
static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (chip->ops->rfk_band_changed)
|
||||
chip->ops->rfk_band_changed(rtwdev);
|
||||
chip->ops->rfk_band_changed(rtwdev, phy_idx);
|
||||
}
|
||||
|
||||
static inline void rtw89_chip_rfk_scan(struct rtw89_dev *rtwdev, bool start)
|
||||
@ -3661,19 +3915,7 @@ static inline void rtw89_chip_set_txpwr_ctrl(struct rtw89_dev *rtwdev)
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (chip->ops->set_txpwr_ctrl)
|
||||
chip->ops->set_txpwr_ctrl(rtwdev);
|
||||
}
|
||||
|
||||
static inline void rtw89_chip_set_txpwr(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
|
||||
if (!ch)
|
||||
return;
|
||||
|
||||
if (chip->ops->set_txpwr)
|
||||
chip->ops->set_txpwr(rtwdev);
|
||||
chip->ops->set_txpwr_ctrl(rtwdev, RTW89_PHY_0);
|
||||
}
|
||||
|
||||
static inline void rtw89_chip_power_trim(struct rtw89_dev *rtwdev)
|
||||
@ -3906,12 +4148,20 @@ int rtw89_core_init(struct rtw89_dev *rtwdev);
|
||||
void rtw89_core_deinit(struct rtw89_dev *rtwdev);
|
||||
int rtw89_core_register(struct rtw89_dev *rtwdev);
|
||||
void rtw89_core_unregister(struct rtw89_dev *rtwdev);
|
||||
struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
|
||||
u32 bus_data_size,
|
||||
const struct rtw89_chip_info *chip);
|
||||
void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev);
|
||||
void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev);
|
||||
void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef);
|
||||
void rtw89_set_channel(struct rtw89_dev *rtwdev);
|
||||
u8 rtw89_core_acquire_bit_map(unsigned long *addr, unsigned long size);
|
||||
void rtw89_core_release_bit_map(unsigned long *addr, u8 bit);
|
||||
void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits);
|
||||
int rtw89_core_acquire_sta_ba_entry(struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx);
|
||||
int rtw89_core_release_sta_ba_entry(struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx);
|
||||
int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx);
|
||||
int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx);
|
||||
void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc);
|
||||
int rtw89_chip_info_setup(struct rtw89_dev *rtwdev);
|
||||
bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate);
|
||||
|
@ -525,7 +525,8 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev,
|
||||
|
||||
static void __print_regd(struct seq_file *m, struct rtw89_dev *rtwdev)
|
||||
{
|
||||
u8 band = rtwdev->hal.current_band_type;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 band = chan->band_type;
|
||||
u8 regd = rtw89_regd_get(rtwdev, band);
|
||||
|
||||
switch (regd) {
|
||||
@ -2305,6 +2306,7 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
|
||||
he_gi_str[rate->he_gi] : "N/A");
|
||||
else
|
||||
seq_printf(m, "Legacy %d", rate->legacy);
|
||||
seq_printf(m, "%s", rtwsta->ra_report.might_fallback_legacy ? " FB_G" : "");
|
||||
seq_printf(m, "\t(hw_rate=0x%x)", rtwsta->ra_report.hw_rate);
|
||||
seq_printf(m, "\t==> agg_wait=%d (%d)\n", rtwsta->max_agg_wait,
|
||||
sta->max_rc_amsdu_len);
|
||||
@ -2433,6 +2435,26 @@ void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
rtw89_dump_addr_cam(m, &rtwvif->addr_cam);
|
||||
}
|
||||
|
||||
static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta *rtwsta)
|
||||
{
|
||||
struct rtw89_vif *rtwvif = rtwsta->rtwvif;
|
||||
struct rtw89_dev *rtwdev = rtwvif->rtwdev;
|
||||
struct rtw89_ba_cam_entry *entry;
|
||||
bool first = true;
|
||||
|
||||
list_for_each_entry(entry, &rtwsta->ba_cam_list, list) {
|
||||
if (first) {
|
||||
seq_puts(m, "\tba_cam ");
|
||||
first = false;
|
||||
} else {
|
||||
seq_puts(m, ", ");
|
||||
}
|
||||
seq_printf(m, "tid[%u]=%d", entry->tid,
|
||||
(int)(entry - rtwdev->cam_info.ba_cam_entry));
|
||||
}
|
||||
seq_puts(m, "\n");
|
||||
}
|
||||
|
||||
static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
|
||||
@ -2441,6 +2463,7 @@ static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta)
|
||||
seq_printf(m, "STA [%d] %pM %s\n", rtwsta->mac_id, sta->addr,
|
||||
sta->tdls ? "(TDLS)" : "");
|
||||
rtw89_dump_addr_cam(m, &rtwsta->addr_cam);
|
||||
rtw89_dump_ba_cam(m, rtwsta);
|
||||
}
|
||||
|
||||
static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v)
|
||||
@ -2449,6 +2472,8 @@ static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v)
|
||||
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
|
||||
struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
seq_puts(m, "map:\n");
|
||||
seq_printf(m, "\tmac_id: %*ph\n", (int)sizeof(rtwdev->mac_id_map),
|
||||
rtwdev->mac_id_map);
|
||||
@ -2458,12 +2483,16 @@ static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v)
|
||||
cam_info->bssid_cam_map);
|
||||
seq_printf(m, "\tsec_cam: %*ph\n", (int)sizeof(cam_info->sec_cam_map),
|
||||
cam_info->sec_cam_map);
|
||||
seq_printf(m, "\tba_cam: %*ph\n", (int)sizeof(cam_info->ba_cam_map),
|
||||
cam_info->ba_cam_map);
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(rtwdev->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL, rtw89_vif_ids_get_iter, m);
|
||||
|
||||
ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_sta_ids_get_iter, m);
|
||||
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
#include "cam.h"
|
||||
#include "chan.h"
|
||||
#include "coex.h"
|
||||
#include "debug.h"
|
||||
#include "fw.h"
|
||||
@ -247,6 +248,46 @@ static void rtw89_fw_recognize_features(struct rtw89_dev *rtwdev)
|
||||
}
|
||||
}
|
||||
|
||||
void rtw89_early_fw_feature_recognize(struct device *device,
|
||||
const struct rtw89_chip_info *chip,
|
||||
u32 *early_feat_map)
|
||||
{
|
||||
union {
|
||||
struct rtw89_mfw_hdr mfw_hdr;
|
||||
u8 fw_hdr[RTW89_FW_HDR_SIZE];
|
||||
} buf = {};
|
||||
const struct firmware *firmware;
|
||||
u32 ver_code;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = request_partial_firmware_into_buf(&firmware, chip->fw_name,
|
||||
device, &buf, sizeof(buf), 0);
|
||||
if (ret) {
|
||||
dev_err(device, "failed to early request firmware: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ver_code = buf.mfw_hdr.sig != RTW89_MFW_SIG ?
|
||||
RTW89_FW_HDR_VER_CODE(&buf.fw_hdr) :
|
||||
RTW89_MFW_HDR_VER_CODE(&buf.mfw_hdr);
|
||||
if (!ver_code)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fw_feat_tbl); i++) {
|
||||
const struct __fw_feat_cfg *ent = &fw_feat_tbl[i];
|
||||
|
||||
if (chip->chip_id != ent->chip_id)
|
||||
continue;
|
||||
|
||||
if (ent->cond(ver_code, ent->ver_code))
|
||||
*early_feat_map |= BIT(ent->feature);
|
||||
}
|
||||
|
||||
out:
|
||||
release_firmware(firmware);
|
||||
}
|
||||
|
||||
int rtw89_fw_recognize(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
int ret;
|
||||
@ -638,14 +679,16 @@ EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v1);
|
||||
int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
|
||||
bool valid, struct ieee80211_ampdu_params *params)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
struct rtw89_vif *rtwvif = rtwsta->rtwvif;
|
||||
u8 macid = rtwsta->mac_id;
|
||||
struct sk_buff *skb;
|
||||
u8 entry_idx;
|
||||
int ret;
|
||||
|
||||
ret = valid ?
|
||||
rtw89_core_acquire_sta_ba_entry(rtwsta, params->tid, &entry_idx) :
|
||||
rtw89_core_release_sta_ba_entry(rtwsta, params->tid, &entry_idx);
|
||||
rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx) :
|
||||
rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx);
|
||||
if (ret) {
|
||||
/* it still works even if we don't have static BA CAM, because
|
||||
* hardware can create dynamic BA CAM automatically.
|
||||
@ -663,7 +706,10 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
|
||||
}
|
||||
skb_put(skb, H2C_BA_CAM_LEN);
|
||||
SET_BA_CAM_MACID(skb->data, macid);
|
||||
SET_BA_CAM_ENTRY_IDX(skb->data, entry_idx);
|
||||
if (chip->bacam_v1)
|
||||
SET_BA_CAM_ENTRY_IDX_V1(skb->data, entry_idx);
|
||||
else
|
||||
SET_BA_CAM_ENTRY_IDX(skb->data, entry_idx);
|
||||
if (!valid)
|
||||
goto end;
|
||||
SET_BA_CAM_VALID(skb->data, valid);
|
||||
@ -676,6 +722,11 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
|
||||
SET_BA_CAM_INIT_REQ(skb->data, 1);
|
||||
SET_BA_CAM_SSN(skb->data, params->ssn);
|
||||
|
||||
if (chip->bacam_v1) {
|
||||
SET_BA_CAM_STD_EN(skb->data, 1);
|
||||
SET_BA_CAM_BAND(skb->data, rtwvif->mac_idx);
|
||||
}
|
||||
|
||||
end:
|
||||
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
|
||||
H2C_CAT_MAC,
|
||||
@ -695,6 +746,56 @@ fail:
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static int rtw89_fw_h2c_init_dynamic_ba_cam_v1(struct rtw89_dev *rtwdev,
|
||||
u8 entry_idx, u8 uid)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_BA_CAM_LEN);
|
||||
if (!skb) {
|
||||
rtw89_err(rtwdev, "failed to alloc skb for dynamic h2c ba cam\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
skb_put(skb, H2C_BA_CAM_LEN);
|
||||
|
||||
SET_BA_CAM_VALID(skb->data, 1);
|
||||
SET_BA_CAM_ENTRY_IDX_V1(skb->data, entry_idx);
|
||||
SET_BA_CAM_UID(skb->data, uid);
|
||||
SET_BA_CAM_BAND(skb->data, 0);
|
||||
SET_BA_CAM_STD_EN(skb->data, 0);
|
||||
|
||||
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
|
||||
H2C_CAT_MAC,
|
||||
H2C_CL_BA_CAM,
|
||||
H2C_FUNC_MAC_BA_CAM, 0, 1,
|
||||
H2C_BA_CAM_LEN);
|
||||
|
||||
if (rtw89_h2c_tx(rtwdev, skb, false)) {
|
||||
rtw89_err(rtwdev, "failed to send h2c\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
u8 entry_idx = chip->bacam_num;
|
||||
u8 uid = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < chip->bacam_dynamic_num; i++) {
|
||||
rtw89_fw_h2c_init_dynamic_ba_cam_v1(rtwdev, entry_idx, uid);
|
||||
entry_idx++;
|
||||
uid++;
|
||||
}
|
||||
}
|
||||
|
||||
#define H2C_LOG_CFG_LEN 12
|
||||
int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable)
|
||||
{
|
||||
@ -926,9 +1027,9 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
|
||||
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
struct sk_buff *skb;
|
||||
u8 pads[RTW89_PPE_BW_NUM];
|
||||
u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
|
||||
@ -947,7 +1048,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
|
||||
SET_CTRL_INFO_OPERATION(skb->data, 1);
|
||||
SET_CMC_TBL_DISRTSFB(skb->data, 1);
|
||||
SET_CMC_TBL_DISDATAFB(skb->data, 1);
|
||||
if (hal->current_band_type == RTW89_BAND_2G)
|
||||
if (chan->band_type == RTW89_BAND_2G)
|
||||
SET_CMC_TBL_RTS_RTY_LOWEST_RATE(skb->data, RTW89_HW_RATE_CCK1);
|
||||
else
|
||||
SET_CMC_TBL_RTS_RTY_LOWEST_RATE(skb->data, RTW89_HW_RATE_OFDM6);
|
||||
@ -1036,8 +1137,8 @@ fail:
|
||||
int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff *skb_beacon;
|
||||
u16 tim_offset;
|
||||
@ -1066,7 +1167,7 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
|
||||
SET_BCN_UPD_MACID(skb->data, rtwvif->mac_id);
|
||||
SET_BCN_UPD_SSN_SEL(skb->data, RTW89_MGMT_HW_SSN_SEL);
|
||||
SET_BCN_UPD_SSN_MODE(skb->data, RTW89_MGMT_HW_SEQ_MODE);
|
||||
SET_BCN_UPD_RATE(skb->data, hal->current_band_type == RTW89_BAND_2G ?
|
||||
SET_BCN_UPD_RATE(skb->data, chan->band_type == RTW89_BAND_2G ?
|
||||
RTW89_HW_RATE_CCK1 : RTW89_HW_RATE_OFDM6);
|
||||
|
||||
skb_put_data(skb, skb_beacon->data, skb_beacon->len);
|
||||
@ -1407,7 +1508,12 @@ fail:
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
#define PORT_DATA_OFFSET 4
|
||||
#define H2C_LEN_CXDRVINFO_ROLE_DBCC_LEN 12
|
||||
#define H2C_LEN_CXDRVINFO_ROLE (4 + 12 * RTW89_PORT_NUM + H2C_LEN_CXDRVHDR)
|
||||
#define H2C_LEN_CXDRVINFO_ROLE_V1 (4 + 16 * RTW89_PORT_NUM + \
|
||||
H2C_LEN_CXDRVINFO_ROLE_DBCC_LEN + \
|
||||
H2C_LEN_CXDRVHDR)
|
||||
int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_btc *btc = &rtwdev->btc;
|
||||
@ -1416,6 +1522,7 @@ int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev)
|
||||
struct rtw89_btc_wl_role_info_bpos *bpos = &role_info->role_map.role;
|
||||
struct rtw89_btc_wl_active_role *active = role_info->active_role;
|
||||
struct sk_buff *skb;
|
||||
u8 offset = 0;
|
||||
u8 *cmd;
|
||||
int i;
|
||||
|
||||
@ -1447,19 +1554,19 @@ int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev)
|
||||
RTW89_SET_FWCMD_CXROLE_ROLE_NAN(cmd, bpos->nan);
|
||||
|
||||
for (i = 0; i < RTW89_PORT_NUM; i++, active++) {
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED(cmd, active->connected, i);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_PID(cmd, active->pid, i);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_PHY(cmd, active->phy, i);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_NOA(cmd, active->noa, i);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_BAND(cmd, active->band, i);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS(cmd, active->client_ps, i);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_BW(cmd, active->bw, i);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_ROLE(cmd, active->role, i);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_CH(cmd, active->ch, i);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_TX_LVL(cmd, active->tx_lvl, i);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_RX_LVL(cmd, active->rx_lvl, i);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_TX_RATE(cmd, active->tx_rate, i);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_RX_RATE(cmd, active->rx_rate, i);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED(cmd, active->connected, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_PID(cmd, active->pid, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_PHY(cmd, active->phy, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_NOA(cmd, active->noa, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_BAND(cmd, active->band, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS(cmd, active->client_ps, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_BW(cmd, active->bw, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_ROLE(cmd, active->role, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_CH(cmd, active->ch, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_TX_LVL(cmd, active->tx_lvl, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_RX_LVL(cmd, active->rx_lvl, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_TX_RATE(cmd, active->tx_rate, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_RX_RATE(cmd, active->rx_rate, i, offset);
|
||||
}
|
||||
|
||||
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
|
||||
@ -1479,6 +1586,87 @@ fail:
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
int rtw89_fw_h2c_cxdrv_role_v1(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_btc *btc = &rtwdev->btc;
|
||||
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
|
||||
struct rtw89_btc_wl_role_info_v1 *role_info = &wl->role_info_v1;
|
||||
struct rtw89_btc_wl_role_info_bpos *bpos = &role_info->role_map.role;
|
||||
struct rtw89_btc_wl_active_role_v1 *active = role_info->active_role_v1;
|
||||
struct sk_buff *skb;
|
||||
u8 *cmd, offset;
|
||||
int i;
|
||||
|
||||
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_CXDRVINFO_ROLE_V1);
|
||||
if (!skb) {
|
||||
rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_role\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
skb_put(skb, H2C_LEN_CXDRVINFO_ROLE_V1);
|
||||
cmd = skb->data;
|
||||
|
||||
RTW89_SET_FWCMD_CXHDR_TYPE(cmd, CXDRVINFO_ROLE);
|
||||
RTW89_SET_FWCMD_CXHDR_LEN(cmd, H2C_LEN_CXDRVINFO_ROLE_V1 - H2C_LEN_CXDRVHDR);
|
||||
|
||||
RTW89_SET_FWCMD_CXROLE_CONNECT_CNT(cmd, role_info->connect_cnt);
|
||||
RTW89_SET_FWCMD_CXROLE_LINK_MODE(cmd, role_info->link_mode);
|
||||
|
||||
RTW89_SET_FWCMD_CXROLE_ROLE_NONE(cmd, bpos->none);
|
||||
RTW89_SET_FWCMD_CXROLE_ROLE_STA(cmd, bpos->station);
|
||||
RTW89_SET_FWCMD_CXROLE_ROLE_AP(cmd, bpos->ap);
|
||||
RTW89_SET_FWCMD_CXROLE_ROLE_VAP(cmd, bpos->vap);
|
||||
RTW89_SET_FWCMD_CXROLE_ROLE_ADHOC(cmd, bpos->adhoc);
|
||||
RTW89_SET_FWCMD_CXROLE_ROLE_ADHOC_MASTER(cmd, bpos->adhoc_master);
|
||||
RTW89_SET_FWCMD_CXROLE_ROLE_MESH(cmd, bpos->mesh);
|
||||
RTW89_SET_FWCMD_CXROLE_ROLE_MONITOR(cmd, bpos->moniter);
|
||||
RTW89_SET_FWCMD_CXROLE_ROLE_P2P_DEV(cmd, bpos->p2p_device);
|
||||
RTW89_SET_FWCMD_CXROLE_ROLE_P2P_GC(cmd, bpos->p2p_gc);
|
||||
RTW89_SET_FWCMD_CXROLE_ROLE_P2P_GO(cmd, bpos->p2p_go);
|
||||
RTW89_SET_FWCMD_CXROLE_ROLE_NAN(cmd, bpos->nan);
|
||||
|
||||
offset = PORT_DATA_OFFSET;
|
||||
for (i = 0; i < RTW89_PORT_NUM; i++, active++) {
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED(cmd, active->connected, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_PID(cmd, active->pid, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_PHY(cmd, active->phy, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_NOA(cmd, active->noa, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_BAND(cmd, active->band, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS(cmd, active->client_ps, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_BW(cmd, active->bw, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_ROLE(cmd, active->role, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_CH(cmd, active->ch, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_TX_LVL(cmd, active->tx_lvl, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_RX_LVL(cmd, active->rx_lvl, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_TX_RATE(cmd, active->tx_rate, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_RX_RATE(cmd, active->rx_rate, i, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_ACT_NOA_DUR(cmd, active->noa_duration, i, offset);
|
||||
}
|
||||
|
||||
offset = H2C_LEN_CXDRVINFO_ROLE_V1 - H2C_LEN_CXDRVINFO_ROLE_DBCC_LEN;
|
||||
RTW89_SET_FWCMD_CXROLE_MROLE_TYPE(cmd, role_info->mrole_type, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_MROLE_NOA(cmd, role_info->mrole_noa_duration, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_DBCC_EN(cmd, role_info->dbcc_en, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_DBCC_CHG(cmd, role_info->dbcc_chg, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_DBCC_2G_PHY(cmd, role_info->dbcc_2g_phy, offset);
|
||||
RTW89_SET_FWCMD_CXROLE_LINK_MODE_CHG(cmd, role_info->link_mode_chg, offset);
|
||||
|
||||
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
|
||||
H2C_CAT_OUTSRC, BTFC_SET,
|
||||
SET_DRV_INFO, 0, 0,
|
||||
H2C_LEN_CXDRVINFO_ROLE_V1);
|
||||
|
||||
if (rtw89_h2c_tx(rtwdev, skb, false)) {
|
||||
rtw89_err(rtwdev, "failed to send h2c\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
#define H2C_LEN_CXDRVINFO_CTRL (4 + H2C_LEN_CXDRVHDR)
|
||||
int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
@ -1788,6 +1976,7 @@ fail:
|
||||
|
||||
int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
struct rtw89_mcc_info *mcc_info = &rtwdev->mcc;
|
||||
struct rtw89_fw_h2c_rf_get_mccch *mccch;
|
||||
struct sk_buff *skb;
|
||||
@ -1804,8 +1993,8 @@ int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev)
|
||||
mccch->ch_1 = cpu_to_le32(mcc_info->ch[1]);
|
||||
mccch->band_0 = cpu_to_le32(mcc_info->band[0]);
|
||||
mccch->band_1 = cpu_to_le32(mcc_info->band[1]);
|
||||
mccch->current_channel = cpu_to_le32(rtwdev->hal.current_channel);
|
||||
mccch->current_band_type = cpu_to_le32(rtwdev->hal.current_band_type);
|
||||
mccch->current_channel = cpu_to_le32(chan->channel);
|
||||
mccch->current_band_type = cpu_to_le32(chan->band_type);
|
||||
|
||||
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
|
||||
H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_NOTIFY,
|
||||
@ -2377,18 +2566,18 @@ out:
|
||||
void rtw89_store_op_chan(struct rtw89_dev *rtwdev, bool backup)
|
||||
{
|
||||
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
const struct rtw89_chan *cur = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
struct rtw89_chan new;
|
||||
|
||||
if (backup) {
|
||||
scan_info->op_pri_ch = hal->current_primary_channel;
|
||||
scan_info->op_chan = hal->current_channel;
|
||||
scan_info->op_bw = hal->current_band_width;
|
||||
scan_info->op_band = hal->current_band_type;
|
||||
scan_info->op_pri_ch = cur->primary_channel;
|
||||
scan_info->op_chan = cur->channel;
|
||||
scan_info->op_bw = cur->band_width;
|
||||
scan_info->op_band = cur->band_type;
|
||||
} else {
|
||||
hal->current_primary_channel = scan_info->op_pri_ch;
|
||||
hal->current_channel = scan_info->op_chan;
|
||||
hal->current_band_width = scan_info->op_bw;
|
||||
hal->current_band_type = scan_info->op_band;
|
||||
rtw89_chan_create(&new, scan_info->op_chan, scan_info->op_pri_ch,
|
||||
scan_info->op_band, scan_info->op_bw);
|
||||
rtw89_assign_entity_chan(rtwdev, RTW89_SUB_ENTITY_0, &new);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2006,69 +2006,104 @@ static inline void RTW89_SET_FWCMD_CXROLE_ROLE_NAN(void *cmd, u16 val)
|
||||
le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(11));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED(void *cmd, u8 val, int n)
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED(void *cmd, u8 val, int n, u8 offset)
|
||||
{
|
||||
u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, BIT(0));
|
||||
u8p_replace_bits((u8 *)cmd + (6 + (12 + offset) * n), val, BIT(0));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_PID(void *cmd, u8 val, int n)
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_PID(void *cmd, u8 val, int n, u8 offset)
|
||||
{
|
||||
u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, GENMASK(3, 1));
|
||||
u8p_replace_bits((u8 *)cmd + (6 + (12 + offset) * n), val, GENMASK(3, 1));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_PHY(void *cmd, u8 val, int n)
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_PHY(void *cmd, u8 val, int n, u8 offset)
|
||||
{
|
||||
u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, BIT(4));
|
||||
u8p_replace_bits((u8 *)cmd + (6 + (12 + offset) * n), val, BIT(4));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_NOA(void *cmd, u8 val, int n)
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_NOA(void *cmd, u8 val, int n, u8 offset)
|
||||
{
|
||||
u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, BIT(5));
|
||||
u8p_replace_bits((u8 *)cmd + (6 + (12 + offset) * n), val, BIT(5));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_BAND(void *cmd, u8 val, int n)
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_BAND(void *cmd, u8 val, int n, u8 offset)
|
||||
{
|
||||
u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, GENMASK(7, 6));
|
||||
u8p_replace_bits((u8 *)cmd + (6 + (12 + offset) * n), val, GENMASK(7, 6));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS(void *cmd, u8 val, int n)
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS(void *cmd, u8 val, int n, u8 offset)
|
||||
{
|
||||
u8p_replace_bits((u8 *)(cmd) + (7 + 12 * (n)), val, BIT(0));
|
||||
u8p_replace_bits((u8 *)cmd + (7 + (12 + offset) * n), val, BIT(0));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_BW(void *cmd, u8 val, int n)
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_BW(void *cmd, u8 val, int n, u8 offset)
|
||||
{
|
||||
u8p_replace_bits((u8 *)(cmd) + (7 + 12 * (n)), val, GENMASK(7, 1));
|
||||
u8p_replace_bits((u8 *)cmd + (7 + (12 + offset) * n), val, GENMASK(7, 1));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_ROLE(void *cmd, u8 val, int n)
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_ROLE(void *cmd, u8 val, int n, u8 offset)
|
||||
{
|
||||
u8p_replace_bits((u8 *)(cmd) + (8 + 12 * (n)), val, GENMASK(7, 0));
|
||||
u8p_replace_bits((u8 *)cmd + (8 + (12 + offset) * n), val, GENMASK(7, 0));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_CH(void *cmd, u8 val, int n)
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_CH(void *cmd, u8 val, int n, u8 offset)
|
||||
{
|
||||
u8p_replace_bits((u8 *)(cmd) + (9 + 12 * (n)), val, GENMASK(7, 0));
|
||||
u8p_replace_bits((u8 *)cmd + (9 + (12 + offset) * n), val, GENMASK(7, 0));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_TX_LVL(void *cmd, u16 val, int n)
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_TX_LVL(void *cmd, u16 val, int n, u8 offset)
|
||||
{
|
||||
le16p_replace_bits((__le16 *)((u8 *)(cmd) + (10 + 12 * (n))), val, GENMASK(15, 0));
|
||||
le16p_replace_bits((__le16 *)((u8 *)cmd + (10 + (12 + offset) * n)), val, GENMASK(15, 0));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_RX_LVL(void *cmd, u16 val, int n)
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_RX_LVL(void *cmd, u16 val, int n, u8 offset)
|
||||
{
|
||||
le16p_replace_bits((__le16 *)((u8 *)(cmd) + (12 + 12 * (n))), val, GENMASK(15, 0));
|
||||
le16p_replace_bits((__le16 *)((u8 *)cmd + (12 + (12 + offset) * n)), val, GENMASK(15, 0));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_TX_RATE(void *cmd, u16 val, int n)
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_TX_RATE(void *cmd, u16 val, int n, u8 offset)
|
||||
{
|
||||
le16p_replace_bits((__le16 *)((u8 *)(cmd) + (14 + 12 * (n))), val, GENMASK(15, 0));
|
||||
le16p_replace_bits((__le16 *)((u8 *)cmd + (14 + (12 + offset) * n)), val, GENMASK(15, 0));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_RX_RATE(void *cmd, u16 val, int n)
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_RX_RATE(void *cmd, u16 val, int n, u8 offset)
|
||||
{
|
||||
le16p_replace_bits((__le16 *)((u8 *)(cmd) + (16 + 12 * (n))), val, GENMASK(15, 0));
|
||||
le16p_replace_bits((__le16 *)((u8 *)cmd + (16 + (12 + offset) * n)), val, GENMASK(15, 0));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_ACT_NOA_DUR(void *cmd, u32 val, int n, u8 offset)
|
||||
{
|
||||
le32p_replace_bits((__le32 *)((u8 *)cmd + (20 + (12 + offset) * n)), val, GENMASK(31, 0));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_MROLE_TYPE(void *cmd, u32 val, u8 offset)
|
||||
{
|
||||
le32p_replace_bits((__le32 *)((u8 *)cmd + offset), val, GENMASK(31, 0));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_MROLE_NOA(void *cmd, u32 val, u8 offset)
|
||||
{
|
||||
le32p_replace_bits((__le32 *)((u8 *)cmd + offset + 4), val, GENMASK(31, 0));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_DBCC_EN(void *cmd, u32 val, u8 offset)
|
||||
{
|
||||
le32p_replace_bits((__le32 *)((u8 *)cmd + offset + 8), val, BIT(0));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_DBCC_CHG(void *cmd, u32 val, u8 offset)
|
||||
{
|
||||
le32p_replace_bits((__le32 *)((u8 *)cmd + offset + 8), val, BIT(1));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_DBCC_2G_PHY(void *cmd, u32 val, u8 offset)
|
||||
{
|
||||
le32p_replace_bits((__le32 *)((u8 *)cmd + offset + 8), val, GENMASK(3, 2));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXROLE_LINK_MODE_CHG(void *cmd, u32 val, u8 offset)
|
||||
{
|
||||
le32p_replace_bits((__le32 *)((u8 *)cmd + offset + 8), val, BIT(4));
|
||||
}
|
||||
|
||||
static inline void RTW89_SET_FWCMD_CXCTRL_MANUAL(void *cmd, u32 val)
|
||||
@ -2446,7 +2481,14 @@ struct rtw89_mfw_info {
|
||||
struct rtw89_mfw_hdr {
|
||||
u8 sig; /* RTW89_MFW_SIG */
|
||||
u8 fw_nr;
|
||||
u8 rsvd[14];
|
||||
u8 rsvd0[2];
|
||||
struct {
|
||||
u8 major;
|
||||
u8 minor;
|
||||
u8 sub;
|
||||
u8 idx;
|
||||
} ver;
|
||||
u8 rsvd1[8];
|
||||
struct rtw89_mfw_info info[];
|
||||
} __packed;
|
||||
|
||||
@ -2563,6 +2605,9 @@ struct rtw89_fw_h2c_rf_get_mccch {
|
||||
|
||||
int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev);
|
||||
int rtw89_fw_recognize(struct rtw89_dev *rtwdev);
|
||||
void rtw89_early_fw_feature_recognize(struct device *device,
|
||||
const struct rtw89_chip_info *chip,
|
||||
u32 *early_feat_map);
|
||||
int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type);
|
||||
int rtw89_load_firmware(struct rtw89_dev *rtwdev);
|
||||
void rtw89_unload_firmware(struct rtw89_dev *rtwdev);
|
||||
@ -2600,6 +2645,7 @@ int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev);
|
||||
int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi);
|
||||
int rtw89_fw_h2c_cxdrv_init(struct rtw89_dev *rtwdev);
|
||||
int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev);
|
||||
int rtw89_fw_h2c_cxdrv_role_v1(struct rtw89_dev *rtwdev);
|
||||
int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev);
|
||||
int rtw89_fw_h2c_cxdrv_rfk(struct rtw89_dev *rtwdev);
|
||||
int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id);
|
||||
@ -2623,6 +2669,7 @@ void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev);
|
||||
int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, u8 macid);
|
||||
int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
|
||||
bool valid, struct ieee80211_ampdu_params *params);
|
||||
void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev);
|
||||
|
||||
int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_lps_parm *lps_param);
|
||||
@ -2643,4 +2690,12 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
|
||||
void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
|
||||
int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev);
|
||||
|
||||
static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (chip->bacam_v1)
|
||||
rtw89_fw_h2c_init_ba_cam_v1(rtwdev);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
#include "cam.h"
|
||||
#include "chan.h"
|
||||
#include "debug.h"
|
||||
#include "fw.h"
|
||||
#include "mac.h"
|
||||
@ -1053,18 +1054,29 @@ void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
|
||||
enum rtw89_rpwm_req_pwr_state state;
|
||||
unsigned long delay = enter ? 10 : 150;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (enter)
|
||||
state = rtw89_mac_get_req_pwr_state(rtwdev);
|
||||
else
|
||||
state = RTW89_MAC_RPWM_REQ_PWR_STATE_ACTIVE;
|
||||
|
||||
rtw89_mac_send_rpwm(rtwdev, state, false);
|
||||
ret = read_poll_timeout_atomic(rtw89_mac_check_cpwm_state, ret, !ret,
|
||||
delay, 15000, false, rtwdev, state);
|
||||
if (ret)
|
||||
rtw89_err(rtwdev, "firmware failed to ack for %s ps mode\n",
|
||||
enter ? "entering" : "leaving");
|
||||
for (i = 0; i < RPWM_TRY_CNT; i++) {
|
||||
rtw89_mac_send_rpwm(rtwdev, state, false);
|
||||
ret = read_poll_timeout_atomic(rtw89_mac_check_cpwm_state, ret,
|
||||
!ret, delay, 15000, false,
|
||||
rtwdev, state);
|
||||
if (!ret)
|
||||
break;
|
||||
|
||||
if (i == RPWM_TRY_CNT - 1)
|
||||
rtw89_err(rtwdev, "firmware failed to ack for %s ps mode\n",
|
||||
enter ? "entering" : "leaving");
|
||||
else
|
||||
rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
|
||||
"%d time firmware failed to ack for %s ps mode\n",
|
||||
i + 1, enter ? "entering" : "leaving");
|
||||
}
|
||||
}
|
||||
|
||||
void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev)
|
||||
@ -1081,7 +1093,6 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw89_pwr_cfg * const *cfg_seq;
|
||||
int (*cfg_func)(struct rtw89_dev *rtwdev);
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
@ -1113,7 +1124,7 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
|
||||
clear_bit(RTW89_FLAG_POWERON, rtwdev->flags);
|
||||
clear_bit(RTW89_FLAG_FW_RDY, rtwdev->flags);
|
||||
rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_PWR_MAJOR);
|
||||
hal->current_channel = 0;
|
||||
rtw89_set_entity_state(rtwdev, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1734,7 +1745,7 @@ static int addr_cam_init(struct rtw89_dev *rtwdev, u8 mac_idx)
|
||||
rtw89_write32(rtwdev, reg, val);
|
||||
|
||||
ret = read_poll_timeout(rtw89_read16, p_val, !(p_val & B_AX_ADDR_CAM_CLR),
|
||||
1, TRXCFG_WAIT_CNT, false, rtwdev, B_AX_ADDR_CAM_CLR);
|
||||
1, TRXCFG_WAIT_CNT, false, rtwdev, reg);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "[ERR]ADDR_CAM reset\n");
|
||||
return ret;
|
||||
@ -1747,13 +1758,19 @@ static int scheduler_init(struct rtw89_dev *rtwdev, u8 mac_idx)
|
||||
{
|
||||
u32 ret;
|
||||
u32 reg;
|
||||
u32 val;
|
||||
|
||||
ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
reg = rtw89_mac_reg_by_idx(R_AX_PREBKF_CFG_1, mac_idx);
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_SIFS_MACTXEN_T1_MASK, SIFS_MACTXEN_T1);
|
||||
if (rtwdev->chip->chip_id == RTL8852C)
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_SIFS_MACTXEN_T1_MASK,
|
||||
SIFS_MACTXEN_T1_V1);
|
||||
else
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_SIFS_MACTXEN_T1_MASK,
|
||||
SIFS_MACTXEN_T1);
|
||||
|
||||
if (rtwdev->chip->chip_id == RTL8852B) {
|
||||
reg = rtw89_mac_reg_by_idx(R_AX_SCH_EXT_CTRL, mac_idx);
|
||||
@ -1764,7 +1781,16 @@ static int scheduler_init(struct rtw89_dev *rtwdev, u8 mac_idx)
|
||||
rtw89_write32_clr(rtwdev, reg, B_AX_BTCCA_EN);
|
||||
|
||||
reg = rtw89_mac_reg_by_idx(R_AX_PREBKF_CFG_0, mac_idx);
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_PREBKF_TIME_MASK, SCH_PREBKF_24US);
|
||||
if (rtwdev->chip->chip_id == RTL8852C) {
|
||||
val = rtw89_read32_mask(rtwdev, R_AX_SEC_ENG_CTRL,
|
||||
B_AX_TX_PARTIAL_MODE);
|
||||
if (!val)
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_PREBKF_TIME_MASK,
|
||||
SCH_PREBKF_24US);
|
||||
} else {
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_PREBKF_TIME_MASK,
|
||||
SCH_PREBKF_24US);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3524,6 +3550,26 @@ static void rtw89_mac_port_cfg_bcn_early(struct rtw89_dev *rtwdev,
|
||||
BCN_ERLY_DEF);
|
||||
}
|
||||
|
||||
static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif)
|
||||
{
|
||||
const struct rtw89_port_reg *p = &rtw_port_base;
|
||||
u16 val;
|
||||
|
||||
if (rtwdev->chip->chip_id != RTL8852C)
|
||||
return;
|
||||
|
||||
if (rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT &&
|
||||
rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION)
|
||||
return;
|
||||
|
||||
val = FIELD_PREP(B_AX_TBTT_SHIFT_OFST_MAG, 1) |
|
||||
B_AX_TBTT_SHIFT_OFST_SIGN;
|
||||
|
||||
rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_shift,
|
||||
B_AX_TBTT_SHIFT_OFST_MASK, val);
|
||||
}
|
||||
|
||||
int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
||||
{
|
||||
int ret;
|
||||
@ -3598,6 +3644,7 @@ int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
||||
rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif);
|
||||
rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif);
|
||||
rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif);
|
||||
rtw89_mac_port_cfg_tbtt_shift(rtwdev, rtwvif);
|
||||
rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif);
|
||||
rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif);
|
||||
rtw89_mac_port_cfg_func_en(rtwdev, rtwvif);
|
||||
@ -3655,7 +3702,7 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
|
||||
u32 len)
|
||||
{
|
||||
struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
struct rtw89_chan new;
|
||||
u8 reason, status, tx_fail, band;
|
||||
u16 chan;
|
||||
|
||||
@ -3681,12 +3728,8 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
|
||||
rtw89_hw_scan_complete(rtwdev, vif, false);
|
||||
break;
|
||||
case RTW89_SCAN_ENTER_CH_NOTIFY:
|
||||
hal->prev_band_type = hal->current_band_type;
|
||||
hal->current_band_type = band;
|
||||
hal->prev_primary_channel = hal->current_primary_channel;
|
||||
hal->current_primary_channel = chan;
|
||||
hal->current_channel = chan;
|
||||
hal->current_band_width = RTW89_CHANNEL_WIDTH_20;
|
||||
rtw89_chan_create(&new, chan, chan, band, RTW89_CHANNEL_WIDTH_20);
|
||||
rtw89_assign_entity_chan(rtwdev, RTW89_SUB_ENTITY_0, &new);
|
||||
if (rtw89_is_op_chan(rtwdev, band, chan)) {
|
||||
rtw89_store_op_chan(rtwdev, false);
|
||||
ieee80211_wake_queues(rtwdev->hw);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define ADDR_CAM_ENT_SIZE 0x40
|
||||
#define BSSID_CAM_ENT_SIZE 0x08
|
||||
#define HFC_PAGE_UNIT 64
|
||||
#define RPWM_TRY_CNT 3
|
||||
|
||||
enum rtw89_mac_hwmod_sel {
|
||||
RTW89_DMAC_SEL = 0,
|
||||
|
@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
#include "cam.h"
|
||||
#include "chan.h"
|
||||
#include "coex.h"
|
||||
#include "debug.h"
|
||||
#include "fw.h"
|
||||
@ -85,8 +86,11 @@ static int rtw89_ops_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
rtw89_config_entity_chandef(rtwdev, RTW89_SUB_ENTITY_0,
|
||||
&hw->conf.chandef);
|
||||
rtw89_set_channel(rtwdev);
|
||||
}
|
||||
|
||||
if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
|
||||
(hw->conf.flags & IEEE80211_CONF_IDLE))
|
||||
@ -235,11 +239,12 @@ static u8 rtw89_aifsn_to_aifs(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif, u8 aifsn)
|
||||
{
|
||||
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 slot_time;
|
||||
u8 sifs;
|
||||
|
||||
slot_time = vif->bss_conf.use_short_slot ? 9 : 20;
|
||||
sifs = rtwdev->hal.current_band_type == RTW89_BAND_5G ? 16 : 10;
|
||||
sifs = chan->band_type == RTW89_BAND_5G ? 16 : 10;
|
||||
|
||||
return aifsn * slot_time + sifs;
|
||||
}
|
||||
@ -772,6 +777,69 @@ static void rtw89_ops_sta_rc_update(struct ieee80211_hw *hw,
|
||||
rtw89_phy_ra_updata_sta(rtwdev, sta, changed);
|
||||
}
|
||||
|
||||
static int rtw89_ops_add_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct rtw89_dev *rtwdev = hw->priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
ret = rtw89_chanctx_ops_add(rtwdev, ctx);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rtw89_ops_remove_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct rtw89_dev *rtwdev = hw->priv;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw89_chanctx_ops_remove(rtwdev, ctx);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
static void rtw89_ops_change_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
u32 changed)
|
||||
{
|
||||
struct rtw89_dev *rtwdev = hw->priv;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw89_chanctx_ops_change(rtwdev, ctx, changed);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
static int rtw89_ops_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct rtw89_dev *rtwdev = hw->priv;
|
||||
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif, ctx);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rtw89_ops_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct rtw89_dev *rtwdev = hw->priv;
|
||||
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif, ctx);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
const struct ieee80211_ops rtw89_ops = {
|
||||
.tx = rtw89_ops_tx,
|
||||
.wake_tx_queue = rtw89_ops_wake_tx_queue,
|
||||
@ -800,6 +868,11 @@ const struct ieee80211_ops rtw89_ops = {
|
||||
.reconfig_complete = rtw89_ops_reconfig_complete,
|
||||
.hw_scan = rtw89_ops_hw_scan,
|
||||
.cancel_hw_scan = rtw89_ops_cancel_hw_scan,
|
||||
.add_chanctx = rtw89_ops_add_chanctx,
|
||||
.remove_chanctx = rtw89_ops_remove_chanctx,
|
||||
.change_chanctx = rtw89_ops_change_chanctx,
|
||||
.assign_vif_chanctx = rtw89_ops_assign_vif_chanctx,
|
||||
.unassign_vif_chanctx = rtw89_ops_unassign_vif_chanctx,
|
||||
.set_sar_specs = rtw89_ops_set_sar_specs,
|
||||
.sta_rc_update = rtw89_ops_sta_rc_update,
|
||||
};
|
||||
|
@ -760,7 +760,8 @@ static irqreturn_t rtw89_pci_interrupt_threadfn(int irq, void *dev)
|
||||
|
||||
enable_intr:
|
||||
spin_lock_irqsave(&rtwpci->irq_lock, flags);
|
||||
rtw89_chip_enable_intr(rtwdev, rtwpci);
|
||||
if (likely(rtwpci->running))
|
||||
rtw89_chip_enable_intr(rtwdev, rtwpci);
|
||||
spin_unlock_irqrestore(&rtwpci->irq_lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -925,10 +926,12 @@ u32 __rtw89_pci_check_and_reclaim_tx_resource_noio(struct rtw89_dev *rtwdev,
|
||||
{
|
||||
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
|
||||
struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[txch];
|
||||
struct rtw89_pci_tx_wd_ring *wd_ring = &tx_ring->wd_ring;
|
||||
u32 cnt;
|
||||
|
||||
spin_lock_bh(&rtwpci->trx_lock);
|
||||
cnt = rtw89_pci_get_avail_txbd_num(tx_ring);
|
||||
cnt = min(cnt, wd_ring->curr_num);
|
||||
spin_unlock_bh(&rtwpci->trx_lock);
|
||||
|
||||
return cnt;
|
||||
@ -1627,6 +1630,8 @@ static void rtw89_pci_ctrl_dma_all(struct rtw89_dev *rtwdev, bool enable)
|
||||
else
|
||||
rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1,
|
||||
B_AX_STOP_AXI_MST);
|
||||
rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1,
|
||||
txhci_en | rxhci_en);
|
||||
if (chip_id == RTL8852C)
|
||||
rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1,
|
||||
B_AX_STOP_AXI_MST);
|
||||
@ -3219,8 +3224,79 @@ static void rtw89_pci_free_irq(struct rtw89_dev *rtwdev,
|
||||
pci_free_irq_vectors(pdev);
|
||||
}
|
||||
|
||||
static u16 gray_code_to_bin(u16 gray_code, u32 bit_num)
|
||||
{
|
||||
u16 bin = 0, gray_bit;
|
||||
u32 bit_idx;
|
||||
|
||||
for (bit_idx = 0; bit_idx < bit_num; bit_idx++) {
|
||||
gray_bit = (gray_code >> bit_idx) & 0x1;
|
||||
if (bit_num - bit_idx > 1)
|
||||
gray_bit ^= (gray_code >> (bit_idx + 1)) & 0x1;
|
||||
bin |= (gray_bit << bit_idx);
|
||||
}
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
||||
static int rtw89_pci_filter_out(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
|
||||
struct pci_dev *pdev = rtwpci->pdev;
|
||||
u16 val16, filter_out_val;
|
||||
u32 val, phy_offset;
|
||||
int ret;
|
||||
|
||||
if (rtwdev->chip->chip_id != RTL8852C)
|
||||
return 0;
|
||||
|
||||
val = rtw89_read32_mask(rtwdev, R_AX_PCIE_MIX_CFG_V1, B_AX_ASPM_CTRL_MASK);
|
||||
if (val == B_AX_ASPM_CTRL_L1)
|
||||
return 0;
|
||||
|
||||
ret = pci_read_config_dword(pdev, RTW89_PCIE_L1_STS_V1, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = FIELD_GET(RTW89_BCFG_LINK_SPEED_MASK, val);
|
||||
if (val == RTW89_PCIE_GEN1_SPEED) {
|
||||
phy_offset = R_RAC_DIRECT_OFFSET_G1;
|
||||
} else if (val == RTW89_PCIE_GEN2_SPEED) {
|
||||
phy_offset = R_RAC_DIRECT_OFFSET_G2;
|
||||
val16 = rtw89_read16(rtwdev, phy_offset + RAC_ANA10 * RAC_MULT);
|
||||
rtw89_write16_set(rtwdev, phy_offset + RAC_ANA10 * RAC_MULT,
|
||||
val16 | B_PCIE_BIT_PINOUT_DIS);
|
||||
rtw89_write16_set(rtwdev, phy_offset + RAC_ANA19 * RAC_MULT,
|
||||
val16 & ~B_PCIE_BIT_RD_SEL);
|
||||
|
||||
val16 = rtw89_read16_mask(rtwdev,
|
||||
phy_offset + RAC_ANA1F * RAC_MULT,
|
||||
FILTER_OUT_EQ_MASK);
|
||||
val16 = gray_code_to_bin(val16, hweight16(val16));
|
||||
filter_out_val = rtw89_read16(rtwdev, phy_offset + RAC_ANA24 *
|
||||
RAC_MULT);
|
||||
filter_out_val &= ~REG_FILTER_OUT_MASK;
|
||||
filter_out_val |= FIELD_PREP(REG_FILTER_OUT_MASK, val16);
|
||||
|
||||
rtw89_write16(rtwdev, phy_offset + RAC_ANA24 * RAC_MULT,
|
||||
filter_out_val);
|
||||
rtw89_write16_set(rtwdev, phy_offset + RAC_ANA0A * RAC_MULT,
|
||||
B_BAC_EQ_SEL);
|
||||
rtw89_write16_set(rtwdev,
|
||||
R_RAC_DIRECT_OFFSET_G1 + RAC_ANA0C * RAC_MULT,
|
||||
B_PCIE_BIT_PSAVE);
|
||||
} else {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
rtw89_write16_set(rtwdev, phy_offset + RAC_ANA0C * RAC_MULT,
|
||||
B_PCIE_BIT_PSAVE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw89_pci_clkreq_set(struct rtw89_dev *rtwdev, bool enable)
|
||||
{
|
||||
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
|
||||
int ret;
|
||||
|
||||
if (rtw89_pci_disable_clkreq)
|
||||
@ -3231,19 +3307,33 @@ static void rtw89_pci_clkreq_set(struct rtw89_dev *rtwdev, bool enable)
|
||||
if (ret)
|
||||
rtw89_err(rtwdev, "failed to set CLKREQ Delay\n");
|
||||
|
||||
if (enable)
|
||||
ret = rtw89_pci_config_byte_set(rtwdev, RTW89_PCIE_L1_CTRL,
|
||||
RTW89_PCIE_BIT_CLK);
|
||||
else
|
||||
ret = rtw89_pci_config_byte_clr(rtwdev, RTW89_PCIE_L1_CTRL,
|
||||
RTW89_PCIE_BIT_CLK);
|
||||
if (ret)
|
||||
rtw89_err(rtwdev, "failed to %s CLKREQ_L1, ret=%d",
|
||||
enable ? "set" : "unset", ret);
|
||||
if (chip_id == RTL8852A) {
|
||||
if (enable)
|
||||
ret = rtw89_pci_config_byte_set(rtwdev,
|
||||
RTW89_PCIE_L1_CTRL,
|
||||
RTW89_PCIE_BIT_CLK);
|
||||
else
|
||||
ret = rtw89_pci_config_byte_clr(rtwdev,
|
||||
RTW89_PCIE_L1_CTRL,
|
||||
RTW89_PCIE_BIT_CLK);
|
||||
if (ret)
|
||||
rtw89_err(rtwdev, "failed to %s CLKREQ_L1, ret=%d",
|
||||
enable ? "set" : "unset", ret);
|
||||
} else if (chip_id == RTL8852C) {
|
||||
rtw89_write32_set(rtwdev, R_AX_PCIE_LAT_CTRL,
|
||||
B_AX_CLK_REQ_SEL_OPT | B_AX_CLK_REQ_SEL);
|
||||
if (enable)
|
||||
rtw89_write32_set(rtwdev, R_AX_L1_CLK_CTRL,
|
||||
B_AX_CLK_REQ_N);
|
||||
else
|
||||
rtw89_write32_clr(rtwdev, R_AX_L1_CLK_CTRL,
|
||||
B_AX_CLK_REQ_N);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw89_pci_aspm_set(struct rtw89_dev *rtwdev, bool enable)
|
||||
{
|
||||
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
|
||||
u8 value = 0;
|
||||
int ret;
|
||||
|
||||
@ -3262,12 +3352,23 @@ static void rtw89_pci_aspm_set(struct rtw89_dev *rtwdev, bool enable)
|
||||
if (ret)
|
||||
rtw89_err(rtwdev, "failed to read ASPM Delay\n");
|
||||
|
||||
if (enable)
|
||||
ret = rtw89_pci_config_byte_set(rtwdev, RTW89_PCIE_L1_CTRL,
|
||||
RTW89_PCIE_BIT_L1);
|
||||
else
|
||||
ret = rtw89_pci_config_byte_clr(rtwdev, RTW89_PCIE_L1_CTRL,
|
||||
RTW89_PCIE_BIT_L1);
|
||||
if (chip_id == RTL8852A || chip_id == RTL8852B) {
|
||||
if (enable)
|
||||
ret = rtw89_pci_config_byte_set(rtwdev,
|
||||
RTW89_PCIE_L1_CTRL,
|
||||
RTW89_PCIE_BIT_L1);
|
||||
else
|
||||
ret = rtw89_pci_config_byte_clr(rtwdev,
|
||||
RTW89_PCIE_L1_CTRL,
|
||||
RTW89_PCIE_BIT_L1);
|
||||
} else if (chip_id == RTL8852C) {
|
||||
if (enable)
|
||||
rtw89_write32_set(rtwdev, R_AX_PCIE_MIX_CFG_V1,
|
||||
B_AX_ASPM_CTRL_L1);
|
||||
else
|
||||
rtw89_write32_clr(rtwdev, R_AX_PCIE_MIX_CFG_V1,
|
||||
B_AX_ASPM_CTRL_L1);
|
||||
}
|
||||
if (ret)
|
||||
rtw89_err(rtwdev, "failed to %s ASPM L1, ret=%d",
|
||||
enable ? "set" : "unset", ret);
|
||||
@ -3328,17 +3429,34 @@ static void rtw89_pci_link_cfg(struct rtw89_dev *rtwdev)
|
||||
|
||||
static void rtw89_pci_l1ss_set(struct rtw89_dev *rtwdev, bool enable)
|
||||
{
|
||||
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
|
||||
int ret;
|
||||
|
||||
if (enable)
|
||||
ret = rtw89_pci_config_byte_set(rtwdev, RTW89_PCIE_TIMER_CTRL,
|
||||
RTW89_PCIE_BIT_L1SUB);
|
||||
else
|
||||
ret = rtw89_pci_config_byte_clr(rtwdev, RTW89_PCIE_TIMER_CTRL,
|
||||
RTW89_PCIE_BIT_L1SUB);
|
||||
if (ret)
|
||||
rtw89_err(rtwdev, "failed to %s L1SS, ret=%d",
|
||||
enable ? "set" : "unset", ret);
|
||||
if (chip_id == RTL8852A || chip_id == RTL8852B) {
|
||||
if (enable)
|
||||
ret = rtw89_pci_config_byte_set(rtwdev,
|
||||
RTW89_PCIE_TIMER_CTRL,
|
||||
RTW89_PCIE_BIT_L1SUB);
|
||||
else
|
||||
ret = rtw89_pci_config_byte_clr(rtwdev,
|
||||
RTW89_PCIE_TIMER_CTRL,
|
||||
RTW89_PCIE_BIT_L1SUB);
|
||||
if (ret)
|
||||
rtw89_err(rtwdev, "failed to %s L1SS, ret=%d",
|
||||
enable ? "set" : "unset", ret);
|
||||
} else if (chip_id == RTL8852C) {
|
||||
ret = rtw89_pci_config_byte_clr(rtwdev, RTW89_PCIE_L1SS_STS_V1,
|
||||
RTW89_PCIE_BIT_ASPM_L11 |
|
||||
RTW89_PCIE_BIT_PCI_L11);
|
||||
if (ret)
|
||||
rtw89_warn(rtwdev, "failed to unset ASPM L1.1, ret=%d", ret);
|
||||
if (enable)
|
||||
rtw89_write32_clr(rtwdev, R_AX_PCIE_MIX_CFG_V1,
|
||||
B_AX_L1SUB_DISABLE);
|
||||
else
|
||||
rtw89_write32_set(rtwdev, R_AX_PCIE_MIX_CFG_V1,
|
||||
B_AX_L1SUB_DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw89_pci_l1ss_cfg(struct rtw89_dev *rtwdev)
|
||||
@ -3535,14 +3653,20 @@ static int __maybe_unused rtw89_pci_suspend(struct device *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = dev_get_drvdata(dev);
|
||||
struct rtw89_dev *rtwdev = hw->priv;
|
||||
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
|
||||
|
||||
rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL,
|
||||
B_AX_PCIE_DIS_L2_CTRL_LDO_HCI);
|
||||
rtw89_write32_set(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6);
|
||||
rtw89_write32_set(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST);
|
||||
rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6);
|
||||
rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1,
|
||||
B_AX_PCIE_PERST_KEEP_REG | B_AX_PCIE_TRAIN_KEEP_REG);
|
||||
if (chip_id == RTL8852A || chip_id == RTL8852B) {
|
||||
rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL,
|
||||
B_AX_PCIE_DIS_L2_CTRL_LDO_HCI);
|
||||
rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1,
|
||||
B_AX_PCIE_PERST_KEEP_REG | B_AX_PCIE_TRAIN_KEEP_REG);
|
||||
} else {
|
||||
rtw89_write32_clr(rtwdev, R_AX_PCIE_PS_CTRL_V1,
|
||||
B_AX_CMAC_EXIT_L1_EN | B_AX_DMAC0_EXIT_L1_EN);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3563,15 +3687,24 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = dev_get_drvdata(dev);
|
||||
struct rtw89_dev *rtwdev = hw->priv;
|
||||
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
|
||||
|
||||
rtw89_write32_set(rtwdev, R_AX_SYS_SDIO_CTRL,
|
||||
B_AX_PCIE_DIS_L2_CTRL_LDO_HCI);
|
||||
rtw89_write32_set(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6);
|
||||
rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST);
|
||||
rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6);
|
||||
rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1,
|
||||
B_AX_PCIE_PERST_KEEP_REG | B_AX_PCIE_TRAIN_KEEP_REG);
|
||||
if (chip_id == RTL8852A || chip_id == RTL8852B) {
|
||||
rtw89_write32_set(rtwdev, R_AX_SYS_SDIO_CTRL,
|
||||
B_AX_PCIE_DIS_L2_CTRL_LDO_HCI);
|
||||
rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1,
|
||||
B_AX_PCIE_PERST_KEEP_REG | B_AX_PCIE_TRAIN_KEEP_REG);
|
||||
} else {
|
||||
rtw89_write32_set(rtwdev, R_AX_PCIE_PS_CTRL_V1,
|
||||
B_AX_CMAC_EXIT_L1_EN | B_AX_DMAC0_EXIT_L1_EN);
|
||||
rtw89_write32_clr(rtwdev, R_AX_PCIE_PS_CTRL_V1,
|
||||
B_AX_SEL_REQ_ENTR_L1);
|
||||
}
|
||||
rtw89_pci_l2_hci_ldo(rtwdev);
|
||||
rtw89_pci_filter_out(rtwdev);
|
||||
rtw89_pci_link_cfg(rtwdev);
|
||||
rtw89_pci_l1ss_cfg(rtwdev);
|
||||
|
||||
@ -3614,27 +3747,23 @@ static const struct rtw89_hci_ops rtw89_pci_ops = {
|
||||
|
||||
int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct ieee80211_hw *hw;
|
||||
struct rtw89_dev *rtwdev;
|
||||
const struct rtw89_driver_info *info;
|
||||
const struct rtw89_pci_info *pci_info;
|
||||
int driver_data_size;
|
||||
int ret;
|
||||
|
||||
driver_data_size = sizeof(struct rtw89_dev) + sizeof(struct rtw89_pci);
|
||||
hw = ieee80211_alloc_hw(driver_data_size, &rtw89_ops);
|
||||
if (!hw) {
|
||||
info = (const struct rtw89_driver_info *)id->driver_data;
|
||||
|
||||
rtwdev = rtw89_alloc_ieee80211_hw(&pdev->dev,
|
||||
sizeof(struct rtw89_pci),
|
||||
info->chip);
|
||||
if (!rtwdev) {
|
||||
dev_err(&pdev->dev, "failed to allocate hw\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info = (const struct rtw89_driver_info *)id->driver_data;
|
||||
pci_info = info->bus.pci;
|
||||
|
||||
rtwdev = hw->priv;
|
||||
rtwdev->hw = hw;
|
||||
rtwdev->dev = &pdev->dev;
|
||||
rtwdev->chip = info->chip;
|
||||
rtwdev->pci_info = info->bus.pci;
|
||||
rtwdev->hci.ops = &rtw89_pci_ops;
|
||||
rtwdev->hci.type = RTW89_HCI_TYPE_PCIE;
|
||||
@ -3667,6 +3796,7 @@ int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
goto err_clear_resource;
|
||||
}
|
||||
|
||||
rtw89_pci_filter_out(rtwdev);
|
||||
rtw89_pci_link_cfg(rtwdev);
|
||||
rtw89_pci_l1ss_cfg(rtwdev);
|
||||
|
||||
@ -3696,7 +3826,7 @@ err_declaim_pci:
|
||||
err_core_deinit:
|
||||
rtw89_core_deinit(rtwdev);
|
||||
err_release_hw:
|
||||
ieee80211_free_hw(hw);
|
||||
rtw89_free_ieee80211_hw(rtwdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -3715,7 +3845,7 @@ void rtw89_pci_remove(struct pci_dev *pdev)
|
||||
rtw89_pci_clear_resource(rtwdev, pdev);
|
||||
rtw89_pci_declaim_device(rtwdev, pdev);
|
||||
rtw89_core_deinit(rtwdev);
|
||||
ieee80211_free_hw(hw);
|
||||
rtw89_free_ieee80211_hw(rtwdev);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_pci_remove);
|
||||
|
||||
|
@ -11,11 +11,18 @@
|
||||
#define MDIO_PG1_G1 1
|
||||
#define MDIO_PG0_G2 2
|
||||
#define MDIO_PG1_G2 3
|
||||
#define RAC_CTRL_PPR 0x00
|
||||
#define RAC_ANA0A 0x0A
|
||||
#define B_BAC_EQ_SEL BIT(5)
|
||||
#define RAC_ANA0C 0x0C
|
||||
#define B_PCIE_BIT_PSAVE BIT(15)
|
||||
#define RAC_ANA10 0x10
|
||||
#define B_PCIE_BIT_PINOUT_DIS BIT(3)
|
||||
#define RAC_REG_REV2 0x1B
|
||||
#define BAC_CMU_EN_DLY_MASK GENMASK(15, 12)
|
||||
#define PCIE_DPHY_DLY_25US 0x1
|
||||
#define RAC_ANA19 0x19
|
||||
#define B_PCIE_BIT_RD_SEL BIT(2)
|
||||
#define RAC_ANA1F 0x1F
|
||||
#define RAC_ANA24 0x24
|
||||
#define B_AX_DEGLITCH GENMASK(11, 8)
|
||||
@ -45,9 +52,26 @@
|
||||
#define B_AX_SEL_REQ_ENTR_L1 BIT(2)
|
||||
#define B_AX_SEL_REQ_EXIT_L1 BIT(0)
|
||||
|
||||
#define R_AX_PCIE_MIX_CFG_V1 0x300C
|
||||
#define B_AX_ASPM_CTRL_L1 BIT(17)
|
||||
#define B_AX_ASPM_CTRL_L0 BIT(16)
|
||||
#define B_AX_ASPM_CTRL_MASK GENMASK(17, 16)
|
||||
#define B_AX_XFER_PENDING_FW BIT(11)
|
||||
#define B_AX_XFER_PENDING BIT(10)
|
||||
#define B_AX_REQ_EXIT_L1 BIT(9)
|
||||
#define B_AX_REQ_ENTR_L1 BIT(8)
|
||||
#define B_AX_L1SUB_DISABLE BIT(0)
|
||||
|
||||
#define R_AX_L1_CLK_CTRL 0x3010
|
||||
#define B_AX_CLK_REQ_N BIT(1)
|
||||
|
||||
#define R_AX_PCIE_BG_CLR 0x303C
|
||||
#define B_AX_BG_CLR_ASYNC_M3 BIT(4)
|
||||
|
||||
#define R_AX_PCIE_LAT_CTRL 0x3044
|
||||
#define B_AX_CLK_REQ_SEL_OPT BIT(1)
|
||||
#define B_AX_CLK_REQ_SEL BIT(0)
|
||||
|
||||
#define R_AX_PCIE_IO_RCY_M1 0x3100
|
||||
#define B_AX_PCIE_IO_RCY_P_M1 BIT(5)
|
||||
#define B_AX_PCIE_IO_RCY_WDT_P_M1 BIT(4)
|
||||
@ -88,7 +112,10 @@
|
||||
#define B_AX_PCIE_WDT_TIMER_S1_MASK GENMASK(31, 0)
|
||||
|
||||
#define R_RAC_DIRECT_OFFSET_G1 0x3800
|
||||
#define FILTER_OUT_EQ_MASK GENMASK(14, 10)
|
||||
#define R_RAC_DIRECT_OFFSET_G2 0x3880
|
||||
#define REG_FILTER_OUT_MASK GENMASK(6, 2)
|
||||
#define RAC_MULT 2
|
||||
|
||||
#define RTW89_PCI_WR_RETRY_CNT 20
|
||||
|
||||
@ -505,6 +532,17 @@
|
||||
#define RTW89_PCI_MULTITAG 8
|
||||
|
||||
/* PCIE CFG register */
|
||||
#define RTW89_PCIE_L1_STS_V1 0x80
|
||||
#define RTW89_BCFG_LINK_SPEED_MASK GENMASK(19, 16)
|
||||
#define RTW89_PCIE_GEN1_SPEED 0x01
|
||||
#define RTW89_PCIE_GEN2_SPEED 0x02
|
||||
#define RTW89_PCIE_PHY_RATE 0x82
|
||||
#define RTW89_PCIE_PHY_RATE_MASK GENMASK(1, 0)
|
||||
#define RTW89_PCIE_L1SS_STS_V1 0x0168
|
||||
#define RTW89_PCIE_BIT_ASPM_L11 BIT(3)
|
||||
#define RTW89_PCIE_BIT_ASPM_L12 BIT(2)
|
||||
#define RTW89_PCIE_BIT_PCI_L11 BIT(1)
|
||||
#define RTW89_PCIE_BIT_PCI_L12 BIT(0)
|
||||
#define RTW89_PCIE_ASPM_CTRL 0x070F
|
||||
#define RTW89_L1DLY_MASK GENMASK(5, 3)
|
||||
#define RTW89_L0DLY_MASK GENMASK(2, 0)
|
||||
@ -516,8 +554,7 @@
|
||||
#define RTW89_PCIE_CLK_CTRL 0x0725
|
||||
#define RTW89_PCIE_RST_MSTATE 0x0B48
|
||||
#define RTW89_PCIE_BIT_CFG_RST_MSTATE BIT(0)
|
||||
#define RTW89_PCIE_PHY_RATE 0x82
|
||||
#define RTW89_PCIE_PHY_RATE_MASK GENMASK(1, 0)
|
||||
|
||||
#define INTF_INTGRA_MINREF_V1 90
|
||||
#define INTF_INTGRA_HOSTREF_V1 100
|
||||
|
||||
|
@ -14,23 +14,14 @@
|
||||
static u16 get_max_amsdu_len(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_ra_report *report)
|
||||
{
|
||||
const struct rate_info *txrate = &report->txrate;
|
||||
u32 bit_rate = report->bit_rate;
|
||||
u8 mcs;
|
||||
|
||||
/* lower than ofdm, do not aggregate */
|
||||
if (bit_rate < 550)
|
||||
return 1;
|
||||
|
||||
/* prevent hardware rate fallback to G mode rate */
|
||||
if (txrate->flags & RATE_INFO_FLAGS_MCS)
|
||||
mcs = txrate->mcs & 0x07;
|
||||
else if (txrate->flags & (RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_HE_MCS))
|
||||
mcs = txrate->mcs;
|
||||
else
|
||||
mcs = 0;
|
||||
|
||||
if (mcs <= 2)
|
||||
/* avoid AMSDU for legacy rate */
|
||||
if (report->might_fallback_legacy)
|
||||
return 1;
|
||||
|
||||
/* lower than 20M vht 2ss mcs8, make it small */
|
||||
@ -142,8 +133,8 @@ static u64 rtw89_phy_ra_mask_recover(u64 ra_mask, u64 ra_mask_bak)
|
||||
|
||||
static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
struct cfg80211_bitrate_mask *mask = &rtwsta->mask;
|
||||
enum nl80211_band band;
|
||||
u64 cfg_mask;
|
||||
@ -151,7 +142,7 @@ static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtw
|
||||
if (!rtwsta->use_cfg_mask)
|
||||
return -1;
|
||||
|
||||
switch (hal->current_band_type) {
|
||||
switch (chan->band_type) {
|
||||
case RTW89_BAND_2G:
|
||||
band = NL80211_BAND_2GHZ;
|
||||
cfg_mask = u64_encode_bits(mask->control[NL80211_BAND_2GHZ].legacy,
|
||||
@ -168,7 +159,7 @@ static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtw
|
||||
RA_MASK_OFDM_RATES);
|
||||
break;
|
||||
default:
|
||||
rtw89_warn(rtwdev, "unhandled band type %d\n", hal->current_band_type);
|
||||
rtw89_warn(rtwdev, "unhandled band type %d\n", chan->band_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -209,6 +200,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif = rtwsta->rtwvif;
|
||||
struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern;
|
||||
struct rtw89_ra_info *ra = &rtwsta->ra;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
const u64 *high_rate_masks = rtw89_ra_mask_ht_rates;
|
||||
u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi);
|
||||
u64 ra_mask = 0;
|
||||
@ -260,7 +252,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
|
||||
ldpc_en = 1;
|
||||
}
|
||||
|
||||
switch (rtwdev->hal.current_band_type) {
|
||||
switch (chan->band_type) {
|
||||
case RTW89_BAND_2G:
|
||||
ra_mask |= sta->deflink.supp_rates[NL80211_BAND_2GHZ];
|
||||
if (sta->deflink.supp_rates[NL80211_BAND_2GHZ] <= 0xf)
|
||||
@ -416,6 +408,7 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
|
||||
struct rtw89_phy_rate_pattern next_pattern = {0};
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
static const u16 hw_rate_he[] = {RTW89_HW_RATE_HE_NSS1_MCS0,
|
||||
RTW89_HW_RATE_HE_NSS2_MCS0,
|
||||
RTW89_HW_RATE_HE_NSS3_MCS0,
|
||||
@ -428,7 +421,7 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
|
||||
RTW89_HW_RATE_MCS8,
|
||||
RTW89_HW_RATE_MCS16,
|
||||
RTW89_HW_RATE_MCS24};
|
||||
u8 band = rtwdev->hal.current_band_type;
|
||||
u8 band = chan->band_type;
|
||||
enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
|
||||
u8 tx_nss = rtwdev->hal.tx_nss;
|
||||
u8 i;
|
||||
@ -542,12 +535,12 @@ void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta)
|
||||
}
|
||||
|
||||
u8 rtw89_phy_get_txsc(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_bandwidth dbw)
|
||||
{
|
||||
enum rtw89_bandwidth cbw = param->bandwidth;
|
||||
u8 pri_ch = param->primary_chan;
|
||||
u8 central_ch = param->center_chan;
|
||||
enum rtw89_bandwidth cbw = chan->band_width;
|
||||
u8 pri_ch = chan->primary_channel;
|
||||
u8 central_ch = chan->channel;
|
||||
u8 txsc_idx = 0;
|
||||
u8 tmp = 0;
|
||||
|
||||
@ -1468,10 +1461,9 @@ EXPORT_SYMBOL(rtw89_phy_load_txpwr_byrate);
|
||||
(txpwr_rf) >> (__c->txpwr_factor_rf - __c->txpwr_factor_mac); \
|
||||
})
|
||||
|
||||
s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev,
|
||||
s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev, u8 band,
|
||||
const struct rtw89_rate_desc *rate_desc)
|
||||
{
|
||||
enum rtw89_band band = rtwdev->hal.current_band_type;
|
||||
s8 *byr;
|
||||
u8 idx;
|
||||
|
||||
@ -1538,11 +1530,10 @@ static u8 rtw89_channel_to_idx(struct rtw89_dev *rtwdev, u8 band, u8 channel)
|
||||
}
|
||||
}
|
||||
|
||||
s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev,
|
||||
s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
|
||||
u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
u8 band = rtwdev->hal.current_band_type;
|
||||
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
|
||||
u8 regd = rtw89_regd_get(rtwdev, band);
|
||||
s8 lmt = 0, sar;
|
||||
@ -1578,11 +1569,12 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_phy_read_txpwr_limit);
|
||||
|
||||
#define __fill_txpwr_limit_nonbf_bf(ptr, bw, ntx, rs, ch) \
|
||||
#define __fill_txpwr_limit_nonbf_bf(ptr, band, bw, ntx, rs, ch) \
|
||||
do { \
|
||||
u8 __i; \
|
||||
for (__i = 0; __i < RTW89_BF_NUM; __i++) \
|
||||
ptr[__i] = rtw89_phy_read_txpwr_limit(rtwdev, \
|
||||
band, \
|
||||
bw, ntx, \
|
||||
rs, __i, \
|
||||
(ch)); \
|
||||
@ -1590,64 +1582,75 @@ EXPORT_SYMBOL(rtw89_phy_read_txpwr_limit);
|
||||
|
||||
static void rtw89_phy_fill_txpwr_limit_20m(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_txpwr_limit *lmt,
|
||||
u8 ntx, u8 ch)
|
||||
u8 band, u8 ntx, u8 ch)
|
||||
{
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->cck_20m, RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->cck_20m, band, RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_CCK, ch);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->cck_40m, RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->cck_40m, band, RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_CCK, ch);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->ofdm, RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_OFDM, ch);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch);
|
||||
}
|
||||
|
||||
static void rtw89_phy_fill_txpwr_limit_40m(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_txpwr_limit *lmt,
|
||||
u8 ntx, u8 ch, u8 pri_ch)
|
||||
u8 band, u8 ntx, u8 ch, u8 pri_ch)
|
||||
{
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->cck_20m, RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->cck_20m, band, RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_CCK, ch - 2);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->cck_40m, RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->cck_40m, band, RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_CCK, ch);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->ofdm, RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_OFDM, pri_ch);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch - 2);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch + 2);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], band,
|
||||
RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_MCS, ch);
|
||||
}
|
||||
|
||||
static void rtw89_phy_fill_txpwr_limit_80m(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_txpwr_limit *lmt,
|
||||
u8 ntx, u8 ch, u8 pri_ch)
|
||||
u8 band, u8 ntx, u8 ch, u8 pri_ch)
|
||||
{
|
||||
s8 val_0p5_n[RTW89_BF_NUM];
|
||||
s8 val_0p5_p[RTW89_BF_NUM];
|
||||
u8 i;
|
||||
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->ofdm, RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_OFDM, pri_ch);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch - 6);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch - 2);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[2], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[2], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch + 2);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[3], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[3], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch + 6);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], band,
|
||||
RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_MCS, ch - 4);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[1], RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[1], band,
|
||||
RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_MCS, ch + 4);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[0], RTW89_CHANNEL_WIDTH_80,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[0], band,
|
||||
RTW89_CHANNEL_WIDTH_80,
|
||||
ntx, RTW89_RS_MCS, ch);
|
||||
|
||||
__fill_txpwr_limit_nonbf_bf(val_0p5_n, RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(val_0p5_n, band, RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_MCS, ch - 4);
|
||||
__fill_txpwr_limit_nonbf_bf(val_0p5_p, RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(val_0p5_p, band, RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_MCS, ch + 4);
|
||||
|
||||
for (i = 0; i < RTW89_BF_NUM; i++)
|
||||
@ -1656,7 +1659,7 @@ static void rtw89_phy_fill_txpwr_limit_80m(struct rtw89_dev *rtwdev,
|
||||
|
||||
static void rtw89_phy_fill_txpwr_limit_160m(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_txpwr_limit *lmt,
|
||||
u8 ntx, u8 ch, u8 pri_ch)
|
||||
u8 band, u8 ntx, u8 ch, u8 pri_ch)
|
||||
{
|
||||
s8 val_0p5_n[RTW89_BF_NUM];
|
||||
s8 val_0p5_p[RTW89_BF_NUM];
|
||||
@ -1665,60 +1668,75 @@ static void rtw89_phy_fill_txpwr_limit_160m(struct rtw89_dev *rtwdev,
|
||||
u8 i;
|
||||
|
||||
/* fill ofdm section */
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->ofdm, RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_OFDM, pri_ch);
|
||||
|
||||
/* fill mcs 20m section */
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch - 14);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch - 10);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[2], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[2], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch - 6);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[3], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[3], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch - 2);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[4], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[4], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch + 2);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[5], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[5], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch + 6);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[6], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[6], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch + 10);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[7], RTW89_CHANNEL_WIDTH_20,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[7], band,
|
||||
RTW89_CHANNEL_WIDTH_20,
|
||||
ntx, RTW89_RS_MCS, ch + 14);
|
||||
|
||||
/* fill mcs 40m section */
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], band,
|
||||
RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_MCS, ch - 12);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[1], RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[1], band,
|
||||
RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_MCS, ch - 4);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[2], RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[2], band,
|
||||
RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_MCS, ch + 4);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[3], RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[3], band,
|
||||
RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_MCS, ch + 12);
|
||||
|
||||
/* fill mcs 80m section */
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[0], RTW89_CHANNEL_WIDTH_80,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[0], band,
|
||||
RTW89_CHANNEL_WIDTH_80,
|
||||
ntx, RTW89_RS_MCS, ch - 8);
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[1], RTW89_CHANNEL_WIDTH_80,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[1], band,
|
||||
RTW89_CHANNEL_WIDTH_80,
|
||||
ntx, RTW89_RS_MCS, ch + 8);
|
||||
|
||||
/* fill mcs 160m section */
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_160m, RTW89_CHANNEL_WIDTH_160,
|
||||
__fill_txpwr_limit_nonbf_bf(lmt->mcs_160m, band,
|
||||
RTW89_CHANNEL_WIDTH_160,
|
||||
ntx, RTW89_RS_MCS, ch);
|
||||
|
||||
/* fill mcs 40m 0p5 section */
|
||||
__fill_txpwr_limit_nonbf_bf(val_0p5_n, RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(val_0p5_n, band, RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_MCS, ch - 4);
|
||||
__fill_txpwr_limit_nonbf_bf(val_0p5_p, RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(val_0p5_p, band, RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_MCS, ch + 4);
|
||||
|
||||
for (i = 0; i < RTW89_BF_NUM; i++)
|
||||
lmt->mcs_40m_0p5[i] = min_t(s8, val_0p5_n[i], val_0p5_p[i]);
|
||||
|
||||
/* fill mcs 40m 2p5 section */
|
||||
__fill_txpwr_limit_nonbf_bf(val_2p5_n, RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(val_2p5_n, band, RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_MCS, ch - 8);
|
||||
__fill_txpwr_limit_nonbf_bf(val_2p5_p, RTW89_CHANNEL_WIDTH_40,
|
||||
__fill_txpwr_limit_nonbf_bf(val_2p5_p, band, RTW89_CHANNEL_WIDTH_40,
|
||||
ntx, RTW89_RS_MCS, ch + 8);
|
||||
|
||||
for (i = 0; i < RTW89_BF_NUM; i++)
|
||||
@ -1726,37 +1744,41 @@ static void rtw89_phy_fill_txpwr_limit_160m(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
void rtw89_phy_fill_txpwr_limit(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
struct rtw89_txpwr_limit *lmt,
|
||||
u8 ntx)
|
||||
{
|
||||
u8 pri_ch = rtwdev->hal.current_primary_channel;
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
u8 bw = rtwdev->hal.current_band_width;
|
||||
u8 band = chan->band_type;
|
||||
u8 pri_ch = chan->primary_channel;
|
||||
u8 ch = chan->channel;
|
||||
u8 bw = chan->band_width;
|
||||
|
||||
memset(lmt, 0, sizeof(*lmt));
|
||||
|
||||
switch (bw) {
|
||||
case RTW89_CHANNEL_WIDTH_20:
|
||||
rtw89_phy_fill_txpwr_limit_20m(rtwdev, lmt, ntx, ch);
|
||||
rtw89_phy_fill_txpwr_limit_20m(rtwdev, lmt, band, ntx, ch);
|
||||
break;
|
||||
case RTW89_CHANNEL_WIDTH_40:
|
||||
rtw89_phy_fill_txpwr_limit_40m(rtwdev, lmt, ntx, ch, pri_ch);
|
||||
rtw89_phy_fill_txpwr_limit_40m(rtwdev, lmt, band, ntx, ch,
|
||||
pri_ch);
|
||||
break;
|
||||
case RTW89_CHANNEL_WIDTH_80:
|
||||
rtw89_phy_fill_txpwr_limit_80m(rtwdev, lmt, ntx, ch, pri_ch);
|
||||
rtw89_phy_fill_txpwr_limit_80m(rtwdev, lmt, band, ntx, ch,
|
||||
pri_ch);
|
||||
break;
|
||||
case RTW89_CHANNEL_WIDTH_160:
|
||||
rtw89_phy_fill_txpwr_limit_160m(rtwdev, lmt, ntx, ch, pri_ch);
|
||||
rtw89_phy_fill_txpwr_limit_160m(rtwdev, lmt, band, ntx, ch,
|
||||
pri_ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_phy_fill_txpwr_limit);
|
||||
|
||||
static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev,
|
||||
static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
|
||||
u8 ru, u8 ntx, u8 ch)
|
||||
{
|
||||
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||
u8 band = rtwdev->hal.current_band_type;
|
||||
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
|
||||
u8 regd = rtw89_regd_get(rtwdev, band);
|
||||
s8 lmt_ru = 0, sar;
|
||||
@ -1794,85 +1816,106 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev,
|
||||
static void
|
||||
rtw89_phy_fill_txpwr_limit_ru_20m(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_txpwr_limit_ru *lmt_ru,
|
||||
u8 ntx, u8 ch)
|
||||
u8 band, u8 ntx, u8 ch)
|
||||
{
|
||||
lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
|
||||
lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU26,
|
||||
ntx, ch);
|
||||
lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
|
||||
lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU52,
|
||||
ntx, ch);
|
||||
lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
|
||||
lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU106,
|
||||
ntx, ch);
|
||||
}
|
||||
|
||||
static void
|
||||
rtw89_phy_fill_txpwr_limit_ru_40m(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_txpwr_limit_ru *lmt_ru,
|
||||
u8 ntx, u8 ch)
|
||||
u8 band, u8 ntx, u8 ch)
|
||||
{
|
||||
lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
|
||||
lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU26,
|
||||
ntx, ch - 2);
|
||||
lmt_ru->ru26[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
|
||||
lmt_ru->ru26[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU26,
|
||||
ntx, ch + 2);
|
||||
lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
|
||||
lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU52,
|
||||
ntx, ch - 2);
|
||||
lmt_ru->ru52[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
|
||||
lmt_ru->ru52[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU52,
|
||||
ntx, ch + 2);
|
||||
lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
|
||||
lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU106,
|
||||
ntx, ch - 2);
|
||||
lmt_ru->ru106[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
|
||||
lmt_ru->ru106[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU106,
|
||||
ntx, ch + 2);
|
||||
}
|
||||
|
||||
static void
|
||||
rtw89_phy_fill_txpwr_limit_ru_80m(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_txpwr_limit_ru *lmt_ru,
|
||||
u8 ntx, u8 ch)
|
||||
u8 band, u8 ntx, u8 ch)
|
||||
{
|
||||
lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
|
||||
lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU26,
|
||||
ntx, ch - 6);
|
||||
lmt_ru->ru26[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
|
||||
lmt_ru->ru26[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU26,
|
||||
ntx, ch - 2);
|
||||
lmt_ru->ru26[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
|
||||
lmt_ru->ru26[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU26,
|
||||
ntx, ch + 2);
|
||||
lmt_ru->ru26[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
|
||||
lmt_ru->ru26[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU26,
|
||||
ntx, ch + 6);
|
||||
lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
|
||||
lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU52,
|
||||
ntx, ch - 6);
|
||||
lmt_ru->ru52[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
|
||||
lmt_ru->ru52[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU52,
|
||||
ntx, ch - 2);
|
||||
lmt_ru->ru52[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
|
||||
lmt_ru->ru52[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU52,
|
||||
ntx, ch + 2);
|
||||
lmt_ru->ru52[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
|
||||
lmt_ru->ru52[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU52,
|
||||
ntx, ch + 6);
|
||||
lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
|
||||
lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU106,
|
||||
ntx, ch - 6);
|
||||
lmt_ru->ru106[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
|
||||
lmt_ru->ru106[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU106,
|
||||
ntx, ch - 2);
|
||||
lmt_ru->ru106[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
|
||||
lmt_ru->ru106[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU106,
|
||||
ntx, ch + 2);
|
||||
lmt_ru->ru106[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
|
||||
lmt_ru->ru106[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU106,
|
||||
ntx, ch + 6);
|
||||
}
|
||||
|
||||
static void
|
||||
rtw89_phy_fill_txpwr_limit_ru_160m(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_txpwr_limit_ru *lmt_ru,
|
||||
u8 ntx, u8 ch)
|
||||
u8 band, u8 ntx, u8 ch)
|
||||
{
|
||||
static const int ofst[] = { -14, -10, -6, -2, 2, 6, 10, 14 };
|
||||
int i;
|
||||
|
||||
static_assert(ARRAY_SIZE(ofst) == RTW89_RU_SEC_NUM);
|
||||
for (i = 0; i < RTW89_RU_SEC_NUM; i++) {
|
||||
lmt_ru->ru26[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev,
|
||||
lmt_ru->ru26[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU26,
|
||||
ntx,
|
||||
ch + ofst[i]);
|
||||
lmt_ru->ru52[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev,
|
||||
lmt_ru->ru52[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU52,
|
||||
ntx,
|
||||
ch + ofst[i]);
|
||||
lmt_ru->ru106[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev,
|
||||
lmt_ru->ru106[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
|
||||
RTW89_RU106,
|
||||
ntx,
|
||||
ch + ofst[i]);
|
||||
@ -1880,26 +1923,32 @@ rtw89_phy_fill_txpwr_limit_ru_160m(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
void rtw89_phy_fill_txpwr_limit_ru(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
struct rtw89_txpwr_limit_ru *lmt_ru,
|
||||
u8 ntx)
|
||||
{
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
u8 bw = rtwdev->hal.current_band_width;
|
||||
u8 band = chan->band_type;
|
||||
u8 ch = chan->channel;
|
||||
u8 bw = chan->band_width;
|
||||
|
||||
memset(lmt_ru, 0, sizeof(*lmt_ru));
|
||||
|
||||
switch (bw) {
|
||||
case RTW89_CHANNEL_WIDTH_20:
|
||||
rtw89_phy_fill_txpwr_limit_ru_20m(rtwdev, lmt_ru, ntx, ch);
|
||||
rtw89_phy_fill_txpwr_limit_ru_20m(rtwdev, lmt_ru, band, ntx,
|
||||
ch);
|
||||
break;
|
||||
case RTW89_CHANNEL_WIDTH_40:
|
||||
rtw89_phy_fill_txpwr_limit_ru_40m(rtwdev, lmt_ru, ntx, ch);
|
||||
rtw89_phy_fill_txpwr_limit_ru_40m(rtwdev, lmt_ru, band, ntx,
|
||||
ch);
|
||||
break;
|
||||
case RTW89_CHANNEL_WIDTH_80:
|
||||
rtw89_phy_fill_txpwr_limit_ru_80m(rtwdev, lmt_ru, ntx, ch);
|
||||
rtw89_phy_fill_txpwr_limit_ru_80m(rtwdev, lmt_ru, band, ntx,
|
||||
ch);
|
||||
break;
|
||||
case RTW89_CHANNEL_WIDTH_160:
|
||||
rtw89_phy_fill_txpwr_limit_ru_160m(rtwdev, lmt_ru, ntx, ch);
|
||||
rtw89_phy_fill_txpwr_limit_ru_160m(rtwdev, lmt_ru, band, ntx,
|
||||
ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1920,6 +1969,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
|
||||
u8 mode, rate, bw, giltf, mac_id;
|
||||
u16 legacy_bitrate;
|
||||
bool valid;
|
||||
u8 mcs = 0;
|
||||
|
||||
mac_id = RTW89_GET_PHY_C2H_RA_RPT_MACID(c2h->data);
|
||||
if (mac_id != rtwsta->mac_id)
|
||||
@ -1936,7 +1986,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
|
||||
return;
|
||||
}
|
||||
|
||||
memset(ra_report, 0, sizeof(*ra_report));
|
||||
memset(&ra_report->txrate, 0, sizeof(ra_report->txrate));
|
||||
|
||||
switch (mode) {
|
||||
case RTW89_RA_RPT_MODE_LEGACY:
|
||||
@ -1952,6 +2002,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
|
||||
ra_report->txrate.mcs = rate;
|
||||
if (giltf)
|
||||
ra_report->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
mcs = ra_report->txrate.mcs & 0x07;
|
||||
break;
|
||||
case RTW89_RA_RPT_MODE_VHT:
|
||||
ra_report->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
|
||||
@ -1959,6 +2010,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
|
||||
ra_report->txrate.nss = FIELD_GET(RTW89_RA_RATE_MASK_NSS, rate) + 1;
|
||||
if (giltf)
|
||||
ra_report->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
mcs = ra_report->txrate.mcs;
|
||||
break;
|
||||
case RTW89_RA_RPT_MODE_HE:
|
||||
ra_report->txrate.flags |= RATE_INFO_FLAGS_HE_MCS;
|
||||
@ -1970,6 +2022,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
|
||||
ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_1_6;
|
||||
else
|
||||
ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_3_2;
|
||||
mcs = ra_report->txrate.mcs;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1977,6 +2030,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
|
||||
ra_report->bit_rate = cfg80211_calculate_bitrate(&ra_report->txrate);
|
||||
ra_report->hw_rate = FIELD_PREP(RTW89_HW_RATE_MASK_MOD, mode) |
|
||||
FIELD_PREP(RTW89_HW_RATE_MASK_VAL, rate);
|
||||
ra_report->might_fallback_legacy = mcs <= 2;
|
||||
sta->max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report);
|
||||
rtwsta->max_agg_wait = sta->max_rc_amsdu_len / 1500 - 1;
|
||||
}
|
||||
@ -3247,10 +3301,11 @@ static void rtw89_phy_dig_update_rssi_info(struct rtw89_dev *rtwdev)
|
||||
static void rtw89_phy_dig_update_para(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_dig_info *dig = &rtwdev->dig;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
bool is_linked = rtwdev->total_sta_assoc > 0;
|
||||
const u16 *fa_th_src = NULL;
|
||||
|
||||
switch (rtwdev->hal.current_band_type) {
|
||||
switch (chan->band_type) {
|
||||
case RTW89_BAND_2G:
|
||||
dig->lna_gain = dig->lna_gain_g;
|
||||
dig->tia_gain = dig->tia_gain_g;
|
||||
@ -3483,7 +3538,8 @@ static void rtw89_phy_dig_config_igi(struct rtw89_dev *rtwdev)
|
||||
static void rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev, u8 rssi,
|
||||
bool enable)
|
||||
{
|
||||
enum rtw89_bandwidth cbw = rtwdev->hal.current_band_width;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
enum rtw89_bandwidth cbw = chan->band_width;
|
||||
struct rtw89_dig_info *dig = &rtwdev->dig;
|
||||
u8 final_rssi = 0, under_region = dig->pd_low_th_ofst;
|
||||
u8 ofdm_cca_th;
|
||||
|
@ -56,7 +56,7 @@
|
||||
#define CFO_TRK_STOP_TH (2 << 2)
|
||||
#define CFO_SW_COMP_FINE_TUNE (2 << 2)
|
||||
#define CFO_PERIOD_CNT 15
|
||||
#define CFO_BOUND 32
|
||||
#define CFO_BOUND 64
|
||||
#define CFO_TP_UPPER 100
|
||||
#define CFO_TP_LOWER 50
|
||||
#define CFO_COMP_PERIOD 250
|
||||
@ -439,7 +439,7 @@ rtw89_rfk_parser(struct rtw89_dev *rtwdev, const struct rtw89_rfk_tbl *tbl);
|
||||
void rtw89_phy_write_reg3_tbl(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_phy_reg3_tbl *tbl);
|
||||
u8 rtw89_phy_get_txsc(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_bandwidth dbw);
|
||||
u32 rtw89_phy_read_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
||||
u32 addr, u32 mask);
|
||||
@ -460,15 +460,17 @@ void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
|
||||
u32 data, enum rtw89_phy_idx phy_idx);
|
||||
void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_txpwr_table *tbl);
|
||||
s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev,
|
||||
s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev, u8 band,
|
||||
const struct rtw89_rate_desc *rate_desc);
|
||||
void rtw89_phy_fill_txpwr_limit(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
struct rtw89_txpwr_limit *lmt,
|
||||
u8 ntx);
|
||||
void rtw89_phy_fill_txpwr_limit_ru(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
struct rtw89_txpwr_limit_ru *lmt_ru,
|
||||
u8 ntx);
|
||||
s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev,
|
||||
s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
|
||||
u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch);
|
||||
void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta);
|
||||
void rtw89_phy_ra_update(struct rtw89_dev *rtwdev);
|
||||
|
@ -143,6 +143,18 @@
|
||||
#define R_AX_PMC_DBG_CTRL2 0x00CC
|
||||
#define B_AX_SYSON_DIS_PMCR_AX_WRMSK BIT(2)
|
||||
|
||||
#define R_AX_PCIE_MIO_INTF 0x00E4
|
||||
#define B_AX_PCIE_MIO_ADDR_PAGE_V1_MASK GENMASK(20, 16)
|
||||
#define B_AX_PCIE_MIO_BYIOREG BIT(13)
|
||||
#define B_AX_PCIE_MIO_RE BIT(12)
|
||||
#define B_AX_PCIE_MIO_WE_MASK GENMASK(11, 8)
|
||||
#define MIO_WRITE_BYTE_ALL 0xF
|
||||
#define B_AX_PCIE_MIO_ADDR_MASK GENMASK(7, 0)
|
||||
#define MIO_ADDR_PAGE_MASK GENMASK(12, 8)
|
||||
|
||||
#define R_AX_PCIE_MIO_INTD 0x00E8
|
||||
#define B_AX_PCIE_MIO_DATA_MASK GENMASK(31, 0)
|
||||
|
||||
#define R_AX_SYS_CFG1 0x00F0
|
||||
#define B_AX_CHIP_VER_MASK GENMASK(15, 12)
|
||||
|
||||
@ -1877,6 +1889,7 @@
|
||||
#define B_AX_SIFS_TIMEOUT_T2_MASK GENMASK(14, 8)
|
||||
#define B_AX_SIFS_MACTXEN_T1_MASK GENMASK(6, 0)
|
||||
#define SIFS_MACTXEN_T1 0x47
|
||||
#define SIFS_MACTXEN_T1_V1 0x41
|
||||
|
||||
#define R_AX_CCA_CFG_0 0xC340
|
||||
#define R_AX_CCA_CFG_0_C1 0xE340
|
||||
@ -2093,6 +2106,8 @@
|
||||
#define R_AX_TBTT_SHIFT_P3 0xC4E8
|
||||
#define R_AX_TBTT_SHIFT_P4 0xC528
|
||||
#define B_AX_TBTT_SHIFT_OFST_MASK GENMASK(11, 0)
|
||||
#define B_AX_TBTT_SHIFT_OFST_SIGN BIT(11)
|
||||
#define B_AX_TBTT_SHIFT_OFST_MAG GENMASK(10, 0)
|
||||
|
||||
#define R_AX_BCN_CNT_TMR_P0 0xC434
|
||||
#define R_AX_BCN_CNT_TMR_P1 0xC474
|
||||
@ -3426,8 +3441,9 @@
|
||||
#define R_MAC_PIN_SEL 0x0734
|
||||
#define B_CH_IDX_SEG0 GENMASK(23, 16)
|
||||
#define R_PLCP_HISTOGRAM 0x0738
|
||||
#define B_STS_DIS_TRIG_BY_BRK BIT(2)
|
||||
#define B_STS_PARSING_TIME GENMASK(19, 16)
|
||||
#define B_STS_DIS_TRIG_BY_FAIL BIT(3)
|
||||
#define B_STS_DIS_TRIG_BY_BRK BIT(2)
|
||||
#define R_PHY_STS_BITMAP_ADDR_START R_PHY_STS_BITMAP_SEARCH_FAIL
|
||||
#define B_PHY_STS_BITMAP_ADDR_MASK GENMASK(6, 2)
|
||||
#define R_PHY_STS_BITMAP_SEARCH_FAIL 0x073C
|
||||
|
@ -346,7 +346,7 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request
|
||||
rtw89_debug_regd(rtwdev, rtwdev->regd, "get from initiator %d, alpha2",
|
||||
request->initiator);
|
||||
|
||||
rtw89_chip_set_txpwr(rtwdev);
|
||||
rtw89_core_set_chip_txpwr(rtwdev);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
@ -660,7 +660,7 @@ static void rtw8852a_power_trim(struct rtw89_dev *rtwdev)
|
||||
}
|
||||
|
||||
static void rtw8852a_set_channel_mac(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
u8 mac_idx)
|
||||
{
|
||||
u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx);
|
||||
@ -669,20 +669,20 @@ static void rtw8852a_set_channel_mac(struct rtw89_dev *rtwdev,
|
||||
u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx);
|
||||
u8 txsc20 = 0, txsc40 = 0;
|
||||
|
||||
switch (param->bandwidth) {
|
||||
switch (chan->band_width) {
|
||||
case RTW89_CHANNEL_WIDTH_80:
|
||||
txsc40 = rtw89_phy_get_txsc(rtwdev, param,
|
||||
txsc40 = rtw89_phy_get_txsc(rtwdev, chan,
|
||||
RTW89_CHANNEL_WIDTH_40);
|
||||
fallthrough;
|
||||
case RTW89_CHANNEL_WIDTH_40:
|
||||
txsc20 = rtw89_phy_get_txsc(rtwdev, param,
|
||||
txsc20 = rtw89_phy_get_txsc(rtwdev, chan,
|
||||
RTW89_CHANNEL_WIDTH_20);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (param->bandwidth) {
|
||||
switch (chan->band_width) {
|
||||
case RTW89_CHANNEL_WIDTH_80:
|
||||
rtw89_write8_mask(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK, BIT(1));
|
||||
rtw89_write32(rtwdev, sub_carr, txsc20 | (txsc40 << 4));
|
||||
@ -699,7 +699,7 @@ static void rtw8852a_set_channel_mac(struct rtw89_dev *rtwdev,
|
||||
break;
|
||||
}
|
||||
|
||||
if (param->center_chan > 14)
|
||||
if (chan->channel > 14)
|
||||
rtw89_write8_set(rtwdev, chk_rate,
|
||||
B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6);
|
||||
else
|
||||
@ -1102,11 +1102,12 @@ static void rtw8852a_bb_sethw(struct rtw89_dev *rtwdev)
|
||||
if (rtwdev->hal.cv <= CHIP_CCV) {
|
||||
rtw89_phy_write32_set(rtwdev, R_RSTB_WATCH_DOG, B_P0_RSTB_WATCH_DOG);
|
||||
rtw89_phy_write32(rtwdev, R_BRK_ASYNC_RST_EN_1, 0x864FA000);
|
||||
rtw89_phy_write32(rtwdev, R_BRK_ASYNC_RST_EN_2, 0x3F);
|
||||
rtw89_phy_write32(rtwdev, R_BRK_ASYNC_RST_EN_2, 0x43F);
|
||||
rtw89_phy_write32(rtwdev, R_BRK_ASYNC_RST_EN_3, 0x7FFF);
|
||||
rtw89_phy_write32_set(rtwdev, R_SPOOF_ASYNC_RST, B_SPOOF_ASYNC_RST);
|
||||
rtw89_phy_write32_set(rtwdev, R_P0_TXPW_RSTB, B_P0_TXPW_RSTB_MANON);
|
||||
rtw89_phy_write32_set(rtwdev, R_P1_TXPW_RSTB, B_P1_TXPW_RSTB_MANON);
|
||||
rtw89_phy_write32_set(rtwdev, R_PLCP_HISTOGRAM, B_STS_PARSING_TIME);
|
||||
}
|
||||
rtw89_phy_write32_mask(rtwdev, R_CFO_TRK0, B_CFO_TRK_MSK, 0x1f);
|
||||
rtw89_phy_write32_mask(rtwdev, R_CFO_TRK1, B_CFO_TRK_MSK, 0x0c);
|
||||
@ -1130,35 +1131,38 @@ static void rtw8852a_bbrst_for_rfk(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static void rtw8852a_set_channel_bb(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
bool cck_en = param->center_chan <= 14;
|
||||
u8 pri_ch_idx = param->pri_ch_idx;
|
||||
bool cck_en = chan->channel <= 14;
|
||||
u8 pri_ch_idx = chan->pri_ch_idx;
|
||||
|
||||
if (cck_en)
|
||||
rtw8852a_ctrl_sco_cck(rtwdev, param->center_chan,
|
||||
param->primary_chan, param->bandwidth);
|
||||
rtw8852a_ctrl_sco_cck(rtwdev, chan->channel,
|
||||
chan->primary_channel,
|
||||
chan->band_width);
|
||||
|
||||
rtw8852a_ctrl_ch(rtwdev, param->center_chan, phy_idx);
|
||||
rtw8852a_ctrl_bw(rtwdev, pri_ch_idx, param->bandwidth, phy_idx);
|
||||
rtw8852a_ctrl_ch(rtwdev, chan->channel, phy_idx);
|
||||
rtw8852a_ctrl_bw(rtwdev, pri_ch_idx, chan->band_width, phy_idx);
|
||||
if (cck_en) {
|
||||
rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0);
|
||||
} else {
|
||||
rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 1);
|
||||
rtw8852a_bbrst_for_rfk(rtwdev, phy_idx);
|
||||
}
|
||||
rtw8852a_spur_elimination(rtwdev, param->center_chan);
|
||||
rtw8852a_spur_elimination(rtwdev, chan->channel);
|
||||
rtw89_phy_write32_mask(rtwdev, R_MAC_PIN_SEL, B_CH_IDX_SEG0,
|
||||
param->primary_chan);
|
||||
chan->primary_channel);
|
||||
rtw8852a_bb_reset_all(rtwdev, phy_idx);
|
||||
}
|
||||
|
||||
static void rtw8852a_set_channel(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *params)
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_mac_idx mac_idx,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
rtw8852a_set_channel_mac(rtwdev, params, RTW89_MAC_0);
|
||||
rtw8852a_set_channel_bb(rtwdev, params, RTW89_PHY_0);
|
||||
rtw8852a_set_channel_mac(rtwdev, chan, mac_idx);
|
||||
rtw8852a_set_channel_bb(rtwdev, chan, phy_idx);
|
||||
}
|
||||
|
||||
static void rtw8852a_dfs_en(struct rtw89_dev *rtwdev, bool en)
|
||||
@ -1209,25 +1213,27 @@ static void rtw8852a_adc_en(struct rtw89_dev *rtwdev, bool en)
|
||||
}
|
||||
|
||||
static void rtw8852a_set_channel_help(struct rtw89_dev *rtwdev, bool enter,
|
||||
struct rtw89_channel_help_params *p)
|
||||
struct rtw89_channel_help_params *p,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_mac_idx mac_idx,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
u8 phy_idx = RTW89_PHY_0;
|
||||
|
||||
if (enter) {
|
||||
rtw89_chip_stop_sch_tx(rtwdev, RTW89_MAC_0, &p->tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false);
|
||||
rtw89_chip_stop_sch_tx(rtwdev, mac_idx, &p->tx_en,
|
||||
RTW89_SCH_TX_SEL_ALL);
|
||||
rtw89_mac_cfg_ppdu_status(rtwdev, mac_idx, false);
|
||||
rtw8852a_dfs_en(rtwdev, false);
|
||||
rtw8852a_tssi_cont_en_phyidx(rtwdev, false, RTW89_PHY_0);
|
||||
rtw8852a_tssi_cont_en_phyidx(rtwdev, false, phy_idx);
|
||||
rtw8852a_adc_en(rtwdev, false);
|
||||
fsleep(40);
|
||||
rtw8852a_bb_reset_en(rtwdev, phy_idx, false);
|
||||
} else {
|
||||
rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
|
||||
rtw89_mac_cfg_ppdu_status(rtwdev, mac_idx, true);
|
||||
rtw8852a_adc_en(rtwdev, true);
|
||||
rtw8852a_dfs_en(rtwdev, true);
|
||||
rtw8852a_tssi_cont_en_phyidx(rtwdev, true, RTW89_PHY_0);
|
||||
rtw8852a_tssi_cont_en_phyidx(rtwdev, true, phy_idx);
|
||||
rtw8852a_bb_reset_en(rtwdev, phy_idx, true);
|
||||
rtw89_chip_resume_sch_tx(rtwdev, RTW89_MAC_0, p->tx_en);
|
||||
rtw89_chip_resume_sch_tx(rtwdev, mac_idx, p->tx_en);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1277,9 +1283,10 @@ static void rtw8852a_rfk_channel(struct rtw89_dev *rtwdev)
|
||||
rtw8852a_dpk(rtwdev, phy_idx);
|
||||
}
|
||||
|
||||
static void rtw8852a_rfk_band_changed(struct rtw89_dev *rtwdev)
|
||||
static void rtw8852a_rfk_band_changed(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
rtw8852a_tssi_scan(rtwdev, RTW89_PHY_0);
|
||||
rtw8852a_tssi_scan(rtwdev, phy_idx);
|
||||
}
|
||||
|
||||
static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev, bool start)
|
||||
@ -1378,9 +1385,11 @@ static void rtw8852a_set_txpwr_ref(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static void rtw8852a_set_txpwr_byrate(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
u8 band = chan->band_type;
|
||||
u8 ch = chan->channel;
|
||||
static const u8 rs[] = {
|
||||
RTW89_RS_CCK,
|
||||
RTW89_RS_OFDM,
|
||||
@ -1406,7 +1415,8 @@ static void rtw8852a_set_txpwr_byrate(struct rtw89_dev *rtwdev,
|
||||
for (j = 0; j < rtw89_rs_idx_max[rs[i]]; j++) {
|
||||
cur.idx = j;
|
||||
shf = (j % 4) * 8;
|
||||
tmp = rtw89_phy_read_txpwr_byrate(rtwdev, &cur);
|
||||
tmp = rtw89_phy_read_txpwr_byrate(rtwdev, band,
|
||||
&cur);
|
||||
val |= (tmp << shf);
|
||||
|
||||
if ((j + 1) % 4)
|
||||
@ -1421,8 +1431,10 @@ static void rtw8852a_set_txpwr_byrate(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static void rtw8852a_set_txpwr_offset(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
u8 band = chan->band_type;
|
||||
struct rtw89_rate_desc desc = {
|
||||
.nss = RTW89_NSS_1,
|
||||
.rs = RTW89_RS_OFFSET,
|
||||
@ -1433,7 +1445,7 @@ static void rtw8852a_set_txpwr_offset(struct rtw89_dev *rtwdev,
|
||||
rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr offset\n");
|
||||
|
||||
for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_MAX; desc.idx++) {
|
||||
v = rtw89_phy_read_txpwr_byrate(rtwdev, &desc);
|
||||
v = rtw89_phy_read_txpwr_byrate(rtwdev, band, &desc);
|
||||
val |= ((v & 0xf) << (4 * desc.idx));
|
||||
}
|
||||
|
||||
@ -1442,29 +1454,31 @@ static void rtw8852a_set_txpwr_offset(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static void rtw8852a_set_txpwr_limit(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
#define __MAC_TXPWR_LMT_PAGE_SIZE 40
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
u8 bw = rtwdev->hal.current_band_width;
|
||||
u8 ch = chan->channel;
|
||||
u8 bw = chan->band_width;
|
||||
struct rtw89_txpwr_limit lmt[NTX_NUM_8852A];
|
||||
u32 addr, val;
|
||||
const s8 *ptr;
|
||||
u8 i, j, k;
|
||||
u8 i, j;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
|
||||
"[TXPWR] set txpwr limit with ch=%d bw=%d\n", ch, bw);
|
||||
|
||||
for (i = 0; i < NTX_NUM_8852A; i++) {
|
||||
rtw89_phy_fill_txpwr_limit(rtwdev, &lmt[i], i);
|
||||
rtw89_phy_fill_txpwr_limit(rtwdev, chan, &lmt[i], i);
|
||||
|
||||
for (j = 0; j < __MAC_TXPWR_LMT_PAGE_SIZE; j += 4) {
|
||||
addr = R_AX_PWR_LMT + j + __MAC_TXPWR_LMT_PAGE_SIZE * i;
|
||||
ptr = (s8 *)&lmt[i] + j;
|
||||
val = 0;
|
||||
|
||||
for (k = 0; k < 4; k++)
|
||||
val |= (ptr[k] << (8 * k));
|
||||
val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
|
||||
FIELD_PREP(GENMASK(15, 8), ptr[1]) |
|
||||
FIELD_PREP(GENMASK(23, 16), ptr[2]) |
|
||||
FIELD_PREP(GENMASK(31, 24), ptr[3]);
|
||||
|
||||
rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
|
||||
}
|
||||
@ -1473,30 +1487,32 @@ static void rtw8852a_set_txpwr_limit(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static void rtw8852a_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
#define __MAC_TXPWR_LMT_RU_PAGE_SIZE 24
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
u8 bw = rtwdev->hal.current_band_width;
|
||||
u8 ch = chan->channel;
|
||||
u8 bw = chan->band_width;
|
||||
struct rtw89_txpwr_limit_ru lmt_ru[NTX_NUM_8852A];
|
||||
u32 addr, val;
|
||||
const s8 *ptr;
|
||||
u8 i, j, k;
|
||||
u8 i, j;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
|
||||
"[TXPWR] set txpwr limit ru with ch=%d bw=%d\n", ch, bw);
|
||||
|
||||
for (i = 0; i < NTX_NUM_8852A; i++) {
|
||||
rtw89_phy_fill_txpwr_limit_ru(rtwdev, &lmt_ru[i], i);
|
||||
rtw89_phy_fill_txpwr_limit_ru(rtwdev, chan, &lmt_ru[i], i);
|
||||
|
||||
for (j = 0; j < __MAC_TXPWR_LMT_RU_PAGE_SIZE; j += 4) {
|
||||
addr = R_AX_PWR_RU_LMT + j +
|
||||
__MAC_TXPWR_LMT_RU_PAGE_SIZE * i;
|
||||
ptr = (s8 *)&lmt_ru[i] + j;
|
||||
val = 0;
|
||||
|
||||
for (k = 0; k < 4; k++)
|
||||
val |= (ptr[k] << (8 * k));
|
||||
val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
|
||||
FIELD_PREP(GENMASK(15, 8), ptr[1]) |
|
||||
FIELD_PREP(GENMASK(23, 16), ptr[2]) |
|
||||
FIELD_PREP(GENMASK(31, 24), ptr[3]);
|
||||
|
||||
rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
|
||||
}
|
||||
@ -1505,17 +1521,20 @@ static void rtw8852a_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
|
||||
#undef __MAC_TXPWR_LMT_RU_PAGE_SIZE
|
||||
}
|
||||
|
||||
static void rtw8852a_set_txpwr(struct rtw89_dev *rtwdev)
|
||||
static void rtw8852a_set_txpwr(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
rtw8852a_set_txpwr_byrate(rtwdev, RTW89_PHY_0);
|
||||
rtw8852a_set_txpwr_limit(rtwdev, RTW89_PHY_0);
|
||||
rtw8852a_set_txpwr_limit_ru(rtwdev, RTW89_PHY_0);
|
||||
rtw8852a_set_txpwr_byrate(rtwdev, chan, phy_idx);
|
||||
rtw8852a_set_txpwr_offset(rtwdev, chan, phy_idx);
|
||||
rtw8852a_set_txpwr_limit(rtwdev, chan, phy_idx);
|
||||
rtw8852a_set_txpwr_limit_ru(rtwdev, chan, phy_idx);
|
||||
}
|
||||
|
||||
static void rtw8852a_set_txpwr_ctrl(struct rtw89_dev *rtwdev)
|
||||
static void rtw8852a_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
rtw8852a_set_txpwr_ref(rtwdev, RTW89_PHY_0);
|
||||
rtw8852a_set_txpwr_offset(rtwdev, RTW89_PHY_0);
|
||||
rtw8852a_set_txpwr_ref(rtwdev, phy_idx);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1592,10 +1611,12 @@ void rtw8852a_bb_set_pmac_tx(struct rtw89_dev *rtwdev,
|
||||
struct rtw8852a_bb_pmac_info *tx_info,
|
||||
enum rtw89_phy_idx idx)
|
||||
{
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
|
||||
if (!tx_info->en_pmac_tx) {
|
||||
rtw8852a_stop_pmac_tx(rtwdev, tx_info, idx);
|
||||
rtw89_phy_write32_idx(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0, idx);
|
||||
if (rtwdev->hal.current_band_type == RTW89_BAND_2G)
|
||||
if (chan->band_type == RTW89_BAND_2G)
|
||||
rtw89_phy_write32_clr(rtwdev, R_RXCCA, B_RXCCA_DIS);
|
||||
return;
|
||||
}
|
||||
@ -2086,6 +2107,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
|
||||
.btc_bt_aci_imp = rtw8852a_btc_bt_aci_imp,
|
||||
.btc_update_bt_cnt = rtw8852a_btc_update_bt_cnt,
|
||||
.btc_wl_s1_standby = rtw8852a_btc_wl_s1_standby,
|
||||
.btc_set_policy = rtw89_btc_set_policy,
|
||||
};
|
||||
|
||||
const struct rtw89_chip_info rtw8852a_chip_info = {
|
||||
@ -2115,6 +2137,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
|
||||
.txpwr_factor_mac = 1,
|
||||
.dig_table = &rtw89_8852a_phy_dig_table,
|
||||
.tssi_dbw_table = NULL,
|
||||
.support_chanctx_num = 1,
|
||||
.support_bands = BIT(NL80211_BAND_2GHZ) |
|
||||
BIT(NL80211_BAND_5GHZ),
|
||||
.support_bw160 = false,
|
||||
@ -2125,6 +2148,9 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
|
||||
.acam_num = 128,
|
||||
.bcam_num = 10,
|
||||
.scam_num = 128,
|
||||
.bacam_num = 2,
|
||||
.bacam_dynamic_num = 4,
|
||||
.bacam_v1 = false,
|
||||
.sec_ctrl_efuse_size = 4,
|
||||
.physical_efuse_size = 1216,
|
||||
.logical_efuse_size = 1536,
|
||||
@ -2138,6 +2164,20 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
|
||||
.btcx_desired = 0x5,
|
||||
.scbd = 0x1,
|
||||
.mailbox = 0x1,
|
||||
|
||||
.fcxbtcrpt_ver = 1,
|
||||
.fcxtdma_ver = 1,
|
||||
.fcxslots_ver = 1,
|
||||
.fcxcysta_ver = 2,
|
||||
.fcxstep_ver = 2,
|
||||
.fcxnullsta_ver = 1,
|
||||
.fcxmreg_ver = 1,
|
||||
.fcxgpiodbg_ver = 1,
|
||||
.fcxbtver_ver = 1,
|
||||
.fcxbtscan_ver = 1,
|
||||
.fcxbtafh_ver = 1,
|
||||
.fcxbtdevinfo_ver = 1,
|
||||
|
||||
.afh_guard_ch = 6,
|
||||
.wl_rssi_thres = rtw89_btc_8852a_wl_rssi_thres,
|
||||
.bt_rssi_thres = rtw89_btc_8852a_bt_rssi_thres,
|
||||
|
@ -1359,7 +1359,7 @@ static void _iqk_get_ch_info(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy, u8 path)
|
||||
{
|
||||
struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u32 reg_rf18 = 0x0, reg_35c = 0x0;
|
||||
u8 idx = 0;
|
||||
u8 get_empty_table = false;
|
||||
@ -1380,9 +1380,9 @@ static void _iqk_get_ch_info(struct rtw89_dev *rtwdev,
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]cfg ch = %d\n", reg_rf18);
|
||||
reg_35c = rtw89_phy_read32_mask(rtwdev, 0x35c, 0x00000c00);
|
||||
|
||||
iqk_info->iqk_band[path] = hal->current_band_type;
|
||||
iqk_info->iqk_bw[path] = hal->current_band_width;
|
||||
iqk_info->iqk_ch[path] = hal->current_channel;
|
||||
iqk_info->iqk_band[path] = chan->band_type;
|
||||
iqk_info->iqk_bw[path] = chan->band_width;
|
||||
iqk_info->iqk_ch[path] = chan->channel;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK,
|
||||
"[IQK]iqk_info->iqk_band[%x] = 0x%x\n", path,
|
||||
@ -1879,13 +1879,12 @@ static void _dpk_information(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
struct rtw89_dpk_info *dpk = &rtwdev->dpk;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 kidx = dpk->cur_idx[path];
|
||||
|
||||
dpk->bp[path][kidx].band = hal->current_band_type;
|
||||
dpk->bp[path][kidx].ch = hal->current_channel;
|
||||
dpk->bp[path][kidx].bw = hal->current_band_width;
|
||||
dpk->bp[path][kidx].band = chan->band_type;
|
||||
dpk->bp[path][kidx].ch = chan->channel;
|
||||
dpk->bp[path][kidx].bw = chan->band_width;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK,
|
||||
"[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n",
|
||||
@ -2358,6 +2357,7 @@ static u8 _dpk_agc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
#define DPK_RXBB_UPPER 0x1f
|
||||
#define DPK_RXBB_LOWER 0
|
||||
#define DPK_GL_CRIT 7
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 tmp_txagc, tmp_rxbb = 0, tmp_gl_idx = 0;
|
||||
u8 agc_cnt = 0;
|
||||
bool limited_rxbb = false;
|
||||
@ -2404,7 +2404,7 @@ static u8 _dpk_agc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
"[DPK] Adjust RXBB (%d) = 0x%x\n", offset,
|
||||
tmp_rxbb);
|
||||
if (offset != 0 || agc_cnt == 0) {
|
||||
if (rtwdev->hal.current_band_width < RTW89_CHANNEL_WIDTH_80)
|
||||
if (chan->band_width < RTW89_CHANNEL_WIDTH_80)
|
||||
_dpk_bypass_rxcfir(rtwdev, path, true);
|
||||
else
|
||||
_dpk_lbk_rxiqk(rtwdev, phy, path);
|
||||
@ -2548,11 +2548,12 @@ static bool _dpk_reload_check(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
struct rtw89_dpk_info *dpk = &rtwdev->dpk;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
bool is_reload = false;
|
||||
u8 idx, cur_band, cur_ch;
|
||||
|
||||
cur_band = rtwdev->hal.current_band_type;
|
||||
cur_ch = rtwdev->hal.current_channel;
|
||||
cur_band = chan->band_type;
|
||||
cur_ch = chan->channel;
|
||||
|
||||
for (idx = 0; idx < RTW89_DPK_BKUP_NUM; idx++) {
|
||||
if (cur_band != dpk->bp[path][idx].band ||
|
||||
@ -2681,12 +2682,13 @@ static void _dpk_cal_select(struct rtw89_dev *rtwdev, bool force,
|
||||
static bool _dpk_bypass_check(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
|
||||
{
|
||||
struct rtw89_fem_info *fem = &rtwdev->fem;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
|
||||
if (fem->epa_2g && rtwdev->hal.current_band_type == RTW89_BAND_2G) {
|
||||
if (fem->epa_2g && chan->band_type == RTW89_BAND_2G) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK,
|
||||
"[DPK] Skip DPK due to 2G_ext_PA exist!!\n");
|
||||
return true;
|
||||
} else if (fem->epa_5g && rtwdev->hal.current_band_type == RTW89_BAND_5G) {
|
||||
} else if (fem->epa_5g && chan->band_type == RTW89_BAND_5G) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK,
|
||||
"[DPK] Skip DPK due to 5G_ext_PA exist!!\n");
|
||||
return true;
|
||||
@ -2842,7 +2844,8 @@ static void _dpk_track(struct rtw89_dev *rtwdev)
|
||||
static void _tssi_rf_setting(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
enum rtw89_band band = rtwdev->hal.current_band_type;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
enum rtw89_band band = chan->band_type;
|
||||
|
||||
if (band == RTW89_BAND_2G)
|
||||
rtw89_write_rf(rtwdev, path, RR_TXPOW, RR_TXPOW_TXG, 0x1);
|
||||
@ -2852,7 +2855,8 @@ static void _tssi_rf_setting(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
|
||||
static void _tssi_set_sys(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
|
||||
{
|
||||
enum rtw89_band band = rtwdev->hal.current_band_type;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
enum rtw89_band band = chan->band_type;
|
||||
|
||||
rtw89_rfk_parser(rtwdev, &rtw8852a_tssi_sys_defs_tbl);
|
||||
rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G,
|
||||
@ -2863,7 +2867,8 @@ static void _tssi_set_sys(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
|
||||
static void _tssi_ini_txpwr_ctrl_bb(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
enum rtw89_band band = rtwdev->hal.current_band_type;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
enum rtw89_band band = chan->band_type;
|
||||
|
||||
rtw89_rfk_parser_by_cond(rtwdev, path == RF_PATH_A,
|
||||
&rtw8852a_tssi_txpwr_ctrl_bb_defs_a_tbl,
|
||||
@ -2905,8 +2910,9 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
|
||||
__val; \
|
||||
})
|
||||
struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
u8 subband = rtwdev->hal.current_subband;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 ch = chan->channel;
|
||||
u8 subband = chan->subband_type;
|
||||
const s8 *thm_up_a = NULL;
|
||||
const s8 *thm_down_a = NULL;
|
||||
const s8 *thm_up_b = NULL;
|
||||
@ -3099,7 +3105,8 @@ static void _tssi_set_txagc_offset_mv_avg(struct rtw89_dev *rtwdev,
|
||||
static void _tssi_pak(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
u8 subband = rtwdev->hal.current_subband;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 subband = chan->subband_type;
|
||||
|
||||
switch (subband) {
|
||||
default:
|
||||
@ -3275,7 +3282,8 @@ static s8 _tssi_get_ofdm_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 ch = chan->channel;
|
||||
u32 gidx, gidx_1st, gidx_2nd;
|
||||
s8 de_1st = 0;
|
||||
s8 de_2nd = 0;
|
||||
@ -3312,7 +3320,8 @@ static s8 _tssi_get_ofdm_trim_de(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 ch = chan->channel;
|
||||
u32 tgidx, tgidx_1st, tgidx_2nd;
|
||||
s8 tde_1st = 0;
|
||||
s8 tde_2nd = 0;
|
||||
@ -3350,6 +3359,7 @@ static void _tssi_set_efuse_to_de(struct rtw89_dev *rtwdev,
|
||||
{
|
||||
#define __DE_MASK 0x003ff000
|
||||
struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
static const u32 r_cck_long[RF_PATH_NUM_8852A] = {0x5858, 0x7858};
|
||||
static const u32 r_cck_short[RF_PATH_NUM_8852A] = {0x5860, 0x7860};
|
||||
static const u32 r_mcs_20m[RF_PATH_NUM_8852A] = {0x5838, 0x7838};
|
||||
@ -3358,7 +3368,7 @@ static void _tssi_set_efuse_to_de(struct rtw89_dev *rtwdev,
|
||||
static const u32 r_mcs_80m_80m[RF_PATH_NUM_8852A] = {0x5850, 0x7850};
|
||||
static const u32 r_mcs_5m[RF_PATH_NUM_8852A] = {0x5828, 0x7828};
|
||||
static const u32 r_mcs_10m[RF_PATH_NUM_8852A] = {0x5830, 0x7830};
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
u8 ch = chan->channel;
|
||||
u8 i, gidx;
|
||||
s8 ofdm_de;
|
||||
s8 trim_de;
|
||||
@ -3478,9 +3488,11 @@ static void _tssi_track(struct rtw89_dev *rtwdev)
|
||||
static void _tssi_high_power(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
|
||||
{
|
||||
struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
|
||||
u8 ch = rtwdev->hal.current_channel, ch_tmp;
|
||||
u8 bw = rtwdev->hal.current_band_width;
|
||||
u8 subband = rtwdev->hal.current_subband;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 ch = chan->channel, ch_tmp;
|
||||
u8 bw = chan->band_width;
|
||||
u8 band = chan->band_type;
|
||||
u8 subband = chan->subband_type;
|
||||
s8 power;
|
||||
s32 xdbm;
|
||||
|
||||
@ -3491,7 +3503,7 @@ static void _tssi_high_power(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
|
||||
else
|
||||
ch_tmp = ch;
|
||||
|
||||
power = rtw89_phy_read_txpwr_limit(rtwdev, bw, RTW89_1TX,
|
||||
power = rtw89_phy_read_txpwr_limit(rtwdev, band, bw, RTW89_1TX,
|
||||
RTW89_RS_MCS, RTW89_NONBF, ch_tmp);
|
||||
|
||||
xdbm = power * 100 / 4;
|
||||
@ -3523,9 +3535,11 @@ static void _tssi_hw_tx(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
static void _tssi_pre_tx(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
|
||||
{
|
||||
struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
const struct rtw89_chip_info *mac_reg = rtwdev->chip;
|
||||
u8 ch = rtwdev->hal.current_channel, ch_tmp;
|
||||
u8 bw = rtwdev->hal.current_band_width;
|
||||
u8 ch = chan->channel, ch_tmp;
|
||||
u8 bw = chan->band_width;
|
||||
u8 band = chan->band_type;
|
||||
u32 tx_en;
|
||||
u8 phy_map = rtw89_btc_phymap(rtwdev, phy, 0);
|
||||
s8 power;
|
||||
@ -3539,8 +3553,9 @@ static void _tssi_pre_tx(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
|
||||
else
|
||||
ch_tmp = ch;
|
||||
|
||||
power = rtw89_phy_read_txpwr_limit(rtwdev, RTW89_CHANNEL_WIDTH_20, RTW89_1TX,
|
||||
RTW89_RS_OFDM, RTW89_NONBF, ch_tmp);
|
||||
power = rtw89_phy_read_txpwr_limit(rtwdev, band, RTW89_CHANNEL_WIDTH_20,
|
||||
RTW89_1TX, RTW89_RS_OFDM,
|
||||
RTW89_NONBF, ch_tmp);
|
||||
|
||||
xdbm = (power * 100) >> mac_reg->txpwr_factor_mac;
|
||||
|
||||
|
@ -567,7 +567,7 @@ static void rtw8852c_power_trim(struct rtw89_dev *rtwdev)
|
||||
}
|
||||
|
||||
static void rtw8852c_set_channel_mac(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
u8 mac_idx)
|
||||
{
|
||||
u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx);
|
||||
@ -578,24 +578,24 @@ static void rtw8852c_set_channel_mac(struct rtw89_dev *rtwdev,
|
||||
u8 rf_mod_val = 0, chk_rate_mask = 0;
|
||||
u32 txsc;
|
||||
|
||||
switch (param->bandwidth) {
|
||||
switch (chan->band_width) {
|
||||
case RTW89_CHANNEL_WIDTH_160:
|
||||
txsc80 = rtw89_phy_get_txsc(rtwdev, param,
|
||||
txsc80 = rtw89_phy_get_txsc(rtwdev, chan,
|
||||
RTW89_CHANNEL_WIDTH_80);
|
||||
fallthrough;
|
||||
case RTW89_CHANNEL_WIDTH_80:
|
||||
txsc40 = rtw89_phy_get_txsc(rtwdev, param,
|
||||
txsc40 = rtw89_phy_get_txsc(rtwdev, chan,
|
||||
RTW89_CHANNEL_WIDTH_40);
|
||||
fallthrough;
|
||||
case RTW89_CHANNEL_WIDTH_40:
|
||||
txsc20 = rtw89_phy_get_txsc(rtwdev, param,
|
||||
txsc20 = rtw89_phy_get_txsc(rtwdev, chan,
|
||||
RTW89_CHANNEL_WIDTH_20);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (param->bandwidth) {
|
||||
switch (chan->band_width) {
|
||||
case RTW89_CHANNEL_WIDTH_160:
|
||||
rf_mod_val = AX_WMAC_RFMOD_160M;
|
||||
txsc = FIELD_PREP(B_AX_TXSC_20M_MASK, txsc20) |
|
||||
@ -620,7 +620,7 @@ static void rtw8852c_set_channel_mac(struct rtw89_dev *rtwdev,
|
||||
rtw89_write8_mask(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK, rf_mod_val);
|
||||
rtw89_write32(rtwdev, sub_carr, txsc);
|
||||
|
||||
switch (param->band_type) {
|
||||
switch (chan->band_type) {
|
||||
case RTW89_BAND_2G:
|
||||
chk_rate_mask = B_AX_BAND_MODE;
|
||||
break;
|
||||
@ -629,7 +629,7 @@ static void rtw8852c_set_channel_mac(struct rtw89_dev *rtwdev,
|
||||
chk_rate_mask = B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6;
|
||||
break;
|
||||
default:
|
||||
rtw89_warn(rtwdev, "Invalid band_type:%d\n", param->band_type);
|
||||
rtw89_warn(rtwdev, "Invalid band_type:%d\n", chan->band_type);
|
||||
return;
|
||||
}
|
||||
rtw89_write8_clr(rtwdev, chk_rate, B_AX_BAND_MODE | B_AX_CHECK_CCK_EN |
|
||||
@ -920,7 +920,7 @@ static void rtw8852c_decode_chan_idx(struct rtw89_dev *rtwdev, u8 chan_idx,
|
||||
}
|
||||
|
||||
static void rtw8852c_set_gain_offset(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
@ -939,7 +939,7 @@ static void rtw8852c_set_gain_offset(struct rtw89_dev *rtwdev,
|
||||
if (rtwdev->dbcc_en && path == RF_PATH_B)
|
||||
phy_idx = RTW89_PHY_1;
|
||||
|
||||
if (param->band_type == RTW89_BAND_2G) {
|
||||
if (chan->band_type == RTW89_BAND_2G) {
|
||||
offset_q0 = efuse_gain->offset[path][RTW89_GAIN_OFFSET_2G_CCK];
|
||||
offset_base_q4 = efuse_gain->offset_base[phy_idx];
|
||||
|
||||
@ -948,7 +948,7 @@ static void rtw8852c_set_gain_offset(struct rtw89_dev *rtwdev,
|
||||
rtw89_phy_write32_mask(rtwdev, R_RPL_OFST, B_RPL_OFST_MASK, tmp & 0x7f);
|
||||
}
|
||||
|
||||
switch (param->subband_type) {
|
||||
switch (chan->subband_type) {
|
||||
default:
|
||||
case RTW89_CH_2G:
|
||||
gain_band = RTW89_GAIN_OFFSET_2G_OFDM;
|
||||
@ -977,14 +977,14 @@ static void rtw8852c_set_gain_offset(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static void rtw8852c_ctrl_ch(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
u8 sco;
|
||||
u16 central_freq = param->center_freq;
|
||||
u8 central_ch = param->center_chan;
|
||||
u8 band = param->band_type;
|
||||
u8 subband = param->subband_type;
|
||||
u16 central_freq = chan->freq;
|
||||
u8 central_ch = chan->channel;
|
||||
u8 band = chan->band_type;
|
||||
u8 subband = chan->subband_type;
|
||||
bool is_2g = band == RTW89_BAND_2G;
|
||||
u8 chan_idx;
|
||||
|
||||
@ -996,7 +996,7 @@ static void rtw8852c_ctrl_ch(struct rtw89_dev *rtwdev,
|
||||
if (phy_idx == RTW89_PHY_0) {
|
||||
/* Path A */
|
||||
rtw8852c_set_gain_error(rtwdev, subband, RF_PATH_A);
|
||||
rtw8852c_set_gain_offset(rtwdev, param, phy_idx, RF_PATH_A);
|
||||
rtw8852c_set_gain_offset(rtwdev, chan, phy_idx, RF_PATH_A);
|
||||
|
||||
if (is_2g)
|
||||
rtw89_phy_write32_idx(rtwdev, R_PATH0_BAND_SEL_V1,
|
||||
@ -1009,7 +1009,7 @@ static void rtw8852c_ctrl_ch(struct rtw89_dev *rtwdev,
|
||||
/* Path B */
|
||||
if (!rtwdev->dbcc_en) {
|
||||
rtw8852c_set_gain_error(rtwdev, subband, RF_PATH_B);
|
||||
rtw8852c_set_gain_offset(rtwdev, param, phy_idx, RF_PATH_B);
|
||||
rtw8852c_set_gain_offset(rtwdev, chan, phy_idx, RF_PATH_B);
|
||||
|
||||
if (is_2g)
|
||||
rtw89_phy_write32_idx(rtwdev,
|
||||
@ -1038,7 +1038,7 @@ static void rtw8852c_ctrl_ch(struct rtw89_dev *rtwdev,
|
||||
} else {
|
||||
/* Path B */
|
||||
rtw8852c_set_gain_error(rtwdev, subband, RF_PATH_B);
|
||||
rtw8852c_set_gain_offset(rtwdev, param, phy_idx, RF_PATH_B);
|
||||
rtw8852c_set_gain_offset(rtwdev, chan, phy_idx, RF_PATH_B);
|
||||
|
||||
if (is_2g)
|
||||
rtw89_phy_write32_idx(rtwdev, R_PATH1_BAND_SEL_V1,
|
||||
@ -1095,7 +1095,7 @@ static void rtw8852c_ctrl_ch(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
}
|
||||
|
||||
chan_idx = rtw8852c_encode_chan_idx(rtwdev, param->primary_chan, band);
|
||||
chan_idx = rtw8852c_encode_chan_idx(rtwdev, chan->primary_channel, band);
|
||||
rtw89_phy_write32_idx(rtwdev, R_MAC_PIN_SEL, B_CH_IDX_SEG0, chan_idx, phy_idx);
|
||||
}
|
||||
|
||||
@ -1246,12 +1246,12 @@ rtw8852c_ctrl_bw(struct rtw89_dev *rtwdev, u8 pri_ch, u8 bw,
|
||||
}
|
||||
|
||||
static u32 rtw8852c_spur_freq(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param)
|
||||
const struct rtw89_chan *chan)
|
||||
{
|
||||
u8 center_chan = param->center_chan;
|
||||
u8 bw = param->bandwidth;
|
||||
u8 center_chan = chan->channel;
|
||||
u8 bw = chan->band_width;
|
||||
|
||||
switch (param->band_type) {
|
||||
switch (chan->band_type) {
|
||||
case RTW89_BAND_2G:
|
||||
if (bw == RTW89_CHANNEL_WIDTH_20) {
|
||||
if (center_chan >= 5 && center_chan <= 8)
|
||||
@ -1285,19 +1285,19 @@ static u32 rtw8852c_spur_freq(struct rtw89_dev *rtwdev,
|
||||
#define MAX_TONE_NUM 2048
|
||||
|
||||
static void rtw8852c_set_csi_tone_idx(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
u32 spur_freq;
|
||||
s32 freq_diff, csi_idx, csi_tone_idx;
|
||||
|
||||
spur_freq = rtw8852c_spur_freq(rtwdev, param);
|
||||
spur_freq = rtw8852c_spur_freq(rtwdev, chan);
|
||||
if (spur_freq == 0) {
|
||||
rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_EN, B_SEG0CSI_EN, 0, phy_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
freq_diff = (spur_freq - param->center_freq) * 1000000;
|
||||
freq_diff = (spur_freq - chan->freq) * 1000000;
|
||||
csi_idx = s32_div_u32_round_closest(freq_diff, CARRIER_SPACING_78_125);
|
||||
s32_div_u32_round_down(csi_idx, MAX_TONE_NUM, &csi_tone_idx);
|
||||
|
||||
@ -1325,7 +1325,7 @@ static const struct rtw89_nbi_reg_def rtw8852c_nbi_reg_def[] = {
|
||||
};
|
||||
|
||||
static void rtw8852c_set_nbi_tone_idx(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
const struct rtw89_nbi_reg_def *nbi = &rtw8852c_nbi_reg_def[path];
|
||||
@ -1335,34 +1335,37 @@ static void rtw8852c_set_nbi_tone_idx(struct rtw89_dev *rtwdev,
|
||||
s32 nbi_frac_idx, nbi_frac_tone_idx;
|
||||
bool notch2_chk = false;
|
||||
|
||||
spur_freq = rtw8852c_spur_freq(rtwdev, param);
|
||||
spur_freq = rtw8852c_spur_freq(rtwdev, chan);
|
||||
if (spur_freq == 0) {
|
||||
rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr, nbi->notch1_en.mask, 0);
|
||||
rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr, nbi->notch1_en.mask, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
fc = param->center_freq;
|
||||
if (param->bandwidth == RTW89_CHANNEL_WIDTH_160) {
|
||||
fc = chan->freq;
|
||||
if (chan->band_width == RTW89_CHANNEL_WIDTH_160) {
|
||||
fc = (spur_freq > fc) ? fc + 40 : fc - 40;
|
||||
if ((fc > spur_freq && param->center_chan < param->primary_chan) ||
|
||||
(fc < spur_freq && param->center_chan > param->primary_chan))
|
||||
if ((fc > spur_freq &&
|
||||
chan->channel < chan->primary_channel) ||
|
||||
(fc < spur_freq &&
|
||||
chan->channel > chan->primary_channel))
|
||||
notch2_chk = true;
|
||||
}
|
||||
|
||||
freq_diff = (spur_freq - fc) * 1000000;
|
||||
nbi_idx = s32_div_u32_round_down(freq_diff, CARRIER_SPACING_312_5, &nbi_frac_idx);
|
||||
|
||||
if (param->bandwidth == RTW89_CHANNEL_WIDTH_20) {
|
||||
if (chan->band_width == RTW89_CHANNEL_WIDTH_20) {
|
||||
s32_div_u32_round_down(nbi_idx + 32, 64, &nbi_tone_idx);
|
||||
} else {
|
||||
u16 tone_para = (param->bandwidth == RTW89_CHANNEL_WIDTH_40) ? 128 : 256;
|
||||
u16 tone_para = (chan->band_width == RTW89_CHANNEL_WIDTH_40) ?
|
||||
128 : 256;
|
||||
|
||||
s32_div_u32_round_down(nbi_idx, tone_para, &nbi_tone_idx);
|
||||
}
|
||||
nbi_frac_tone_idx = s32_div_u32_round_closest(nbi_frac_idx, CARRIER_SPACING_78_125);
|
||||
|
||||
if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 && notch2_chk) {
|
||||
if (chan->band_width == RTW89_CHANNEL_WIDTH_160 && notch2_chk) {
|
||||
rtw89_phy_write32_mask(rtwdev, nbi->notch2_idx.addr,
|
||||
nbi->notch2_idx.mask, nbi_tone_idx);
|
||||
rtw89_phy_write32_mask(rtwdev, nbi->notch2_frac_idx.addr,
|
||||
@ -1404,42 +1407,42 @@ static void rtw8852c_spur_notch(struct rtw89_dev *rtwdev, u32 val,
|
||||
}
|
||||
|
||||
static void rtw8852c_spur_elimination(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
u8 pri_ch_idx,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
rtw8852c_set_csi_tone_idx(rtwdev, param, phy_idx);
|
||||
rtw8852c_set_csi_tone_idx(rtwdev, chan, phy_idx);
|
||||
|
||||
if (phy_idx == RTW89_PHY_0) {
|
||||
if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 &&
|
||||
if (chan->band_width == RTW89_CHANNEL_WIDTH_160 &&
|
||||
(pri_ch_idx == RTW89_SC_20_LOWER ||
|
||||
pri_ch_idx == RTW89_SC_20_UP3X)) {
|
||||
rtw8852c_spur_notch(rtwdev, 0xe7f, RTW89_PHY_0);
|
||||
if (!rtwdev->dbcc_en)
|
||||
rtw8852c_spur_notch(rtwdev, 0xe7f, RTW89_PHY_1);
|
||||
} else if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 &&
|
||||
} else if (chan->band_width == RTW89_CHANNEL_WIDTH_160 &&
|
||||
(pri_ch_idx == RTW89_SC_20_UPPER ||
|
||||
pri_ch_idx == RTW89_SC_20_LOW3X)) {
|
||||
rtw8852c_spur_notch(rtwdev, 0x280, RTW89_PHY_0);
|
||||
if (!rtwdev->dbcc_en)
|
||||
rtw8852c_spur_notch(rtwdev, 0x280, RTW89_PHY_1);
|
||||
} else {
|
||||
rtw8852c_set_nbi_tone_idx(rtwdev, param, RF_PATH_A);
|
||||
rtw8852c_set_nbi_tone_idx(rtwdev, chan, RF_PATH_A);
|
||||
if (!rtwdev->dbcc_en)
|
||||
rtw8852c_set_nbi_tone_idx(rtwdev, param,
|
||||
rtw8852c_set_nbi_tone_idx(rtwdev, chan,
|
||||
RF_PATH_B);
|
||||
}
|
||||
} else {
|
||||
if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 &&
|
||||
if (chan->band_width == RTW89_CHANNEL_WIDTH_160 &&
|
||||
(pri_ch_idx == RTW89_SC_20_LOWER ||
|
||||
pri_ch_idx == RTW89_SC_20_UP3X)) {
|
||||
rtw8852c_spur_notch(rtwdev, 0xe7f, RTW89_PHY_1);
|
||||
} else if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 &&
|
||||
} else if (chan->band_width == RTW89_CHANNEL_WIDTH_160 &&
|
||||
(pri_ch_idx == RTW89_SC_20_UPPER ||
|
||||
pri_ch_idx == RTW89_SC_20_LOW3X)) {
|
||||
rtw8852c_spur_notch(rtwdev, 0x280, RTW89_PHY_1);
|
||||
} else {
|
||||
rtw8852c_set_nbi_tone_idx(rtwdev, param, RF_PATH_B);
|
||||
rtw8852c_set_nbi_tone_idx(rtwdev, chan, RF_PATH_B);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1450,14 +1453,14 @@ static void rtw8852c_spur_elimination(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static void rtw8852c_5m_mask(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
u8 pri_ch = param->primary_chan;
|
||||
u8 pri_ch = chan->primary_channel;
|
||||
bool mask_5m_low;
|
||||
bool mask_5m_en;
|
||||
|
||||
switch (param->bandwidth) {
|
||||
switch (chan->band_width) {
|
||||
case RTW89_CHANNEL_WIDTH_40:
|
||||
mask_5m_en = true;
|
||||
mask_5m_low = pri_ch == 2;
|
||||
@ -1526,11 +1529,9 @@ static void rtw8852c_bb_reset_all(struct rtw89_dev *rtwdev,
|
||||
phy_idx);
|
||||
}
|
||||
|
||||
static void rtw8852c_bb_reset_en(struct rtw89_dev *rtwdev,
|
||||
static void rtw8852c_bb_reset_en(struct rtw89_dev *rtwdev, enum rtw89_band band,
|
||||
enum rtw89_phy_idx phy_idx, bool en)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
||||
if (en) {
|
||||
rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS,
|
||||
B_S0_HW_SI_DIS_W_R_TRIG, 0x0, phy_idx);
|
||||
@ -1538,7 +1539,7 @@ static void rtw8852c_bb_reset_en(struct rtw89_dev *rtwdev,
|
||||
B_S1_HW_SI_DIS_W_R_TRIG, 0x0, phy_idx);
|
||||
rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1,
|
||||
phy_idx);
|
||||
if (hal->current_band_type == RTW89_BAND_2G)
|
||||
if (band == RTW89_BAND_2G)
|
||||
rtw89_phy_write32_mask(rtwdev, R_RXCCA_V1, B_RXCCA_DIS_V1, 0x0);
|
||||
rtw89_phy_write32_mask(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0x0);
|
||||
} else {
|
||||
@ -1690,21 +1691,22 @@ static void rtw8852c_bb_sethw(struct rtw89_dev *rtwdev)
|
||||
}
|
||||
|
||||
static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
bool cck_en = param->band_type == RTW89_BAND_2G;
|
||||
u8 pri_ch_idx = param->pri_ch_idx;
|
||||
bool cck_en = chan->band_type == RTW89_BAND_2G;
|
||||
u8 pri_ch_idx = chan->pri_ch_idx;
|
||||
u32 mask, reg;
|
||||
u32 ru_alloc_msk[2] = {B_P80_AT_HIGH_FREQ_RU_ALLOC_PHY0,
|
||||
B_P80_AT_HIGH_FREQ_RU_ALLOC_PHY1};
|
||||
|
||||
if (param->band_type == RTW89_BAND_2G)
|
||||
rtw8852c_ctrl_sco_cck(rtwdev, param->center_chan,
|
||||
param->primary_chan, param->bandwidth);
|
||||
if (chan->band_type == RTW89_BAND_2G)
|
||||
rtw8852c_ctrl_sco_cck(rtwdev, chan->channel,
|
||||
chan->primary_channel,
|
||||
chan->band_width);
|
||||
|
||||
rtw8852c_ctrl_ch(rtwdev, param, phy_idx);
|
||||
rtw8852c_ctrl_bw(rtwdev, pri_ch_idx, param->bandwidth, phy_idx);
|
||||
rtw8852c_ctrl_ch(rtwdev, chan, phy_idx);
|
||||
rtw8852c_ctrl_bw(rtwdev, pri_ch_idx, chan->band_width, phy_idx);
|
||||
if (cck_en) {
|
||||
rtw89_phy_write32_mask(rtwdev, R_UPD_CLK_ADC, B_ENABLE_CCK, 1);
|
||||
rtw89_phy_write32_mask(rtwdev, R_RXCCA_V1, B_RXCCA_DIS_V1, 0);
|
||||
@ -1717,17 +1719,17 @@ static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev,
|
||||
B_PD_ARBITER_OFF, 0x1, phy_idx);
|
||||
}
|
||||
|
||||
rtw8852c_spur_elimination(rtwdev, param, pri_ch_idx, phy_idx);
|
||||
rtw8852c_ctrl_btg(rtwdev, param->band_type == RTW89_BAND_2G);
|
||||
rtw8852c_5m_mask(rtwdev, param, phy_idx);
|
||||
rtw8852c_spur_elimination(rtwdev, chan, pri_ch_idx, phy_idx);
|
||||
rtw8852c_ctrl_btg(rtwdev, chan->band_type == RTW89_BAND_2G);
|
||||
rtw8852c_5m_mask(rtwdev, chan, phy_idx);
|
||||
|
||||
if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 &&
|
||||
if (chan->band_width == RTW89_CHANNEL_WIDTH_160 &&
|
||||
rtwdev->hal.cv != CHIP_CAV) {
|
||||
rtw89_phy_write32_idx(rtwdev, R_P80_AT_HIGH_FREQ,
|
||||
B_P80_AT_HIGH_FREQ, 0x0, phy_idx);
|
||||
reg = rtw89_mac_reg_by_idx(R_P80_AT_HIGH_FREQ_BB_WRP,
|
||||
phy_idx);
|
||||
if (param->primary_chan > param->center_chan) {
|
||||
if (chan->primary_channel > chan->channel) {
|
||||
rtw89_phy_write32_mask(rtwdev,
|
||||
R_P80_AT_HIGH_FREQ_RU_ALLOC,
|
||||
ru_alloc_msk[phy_idx], 1);
|
||||
@ -1742,8 +1744,8 @@ static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
}
|
||||
|
||||
if (param->band_type == RTW89_BAND_6G &&
|
||||
param->bandwidth == RTW89_CHANNEL_WIDTH_160)
|
||||
if (chan->band_type == RTW89_BAND_6G &&
|
||||
chan->band_width == RTW89_CHANNEL_WIDTH_160)
|
||||
rtw89_phy_write32_idx(rtwdev, R_CDD_EVM_CHK_EN,
|
||||
B_CDD_EVM_CHK_EN, 0, phy_idx);
|
||||
else
|
||||
@ -1773,11 +1775,13 @@ static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static void rtw8852c_set_channel(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *params)
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_mac_idx mac_idx,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
rtw8852c_set_channel_mac(rtwdev, params, RTW89_MAC_0);
|
||||
rtw8852c_set_channel_bb(rtwdev, params, RTW89_PHY_0);
|
||||
rtw8852c_set_channel_rf(rtwdev, params, RTW89_PHY_0);
|
||||
rtw8852c_set_channel_mac(rtwdev, chan, mac_idx);
|
||||
rtw8852c_set_channel_bb(rtwdev, chan, phy_idx);
|
||||
rtw8852c_set_channel_rf(rtwdev, chan, phy_idx);
|
||||
}
|
||||
|
||||
static void rtw8852c_dfs_en(struct rtw89_dev *rtwdev, bool en)
|
||||
@ -1799,25 +1803,27 @@ static void rtw8852c_adc_en(struct rtw89_dev *rtwdev, bool en)
|
||||
}
|
||||
|
||||
static void rtw8852c_set_channel_help(struct rtw89_dev *rtwdev, bool enter,
|
||||
struct rtw89_channel_help_params *p)
|
||||
struct rtw89_channel_help_params *p,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_mac_idx mac_idx,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
u8 phy_idx = RTW89_PHY_0;
|
||||
|
||||
if (enter) {
|
||||
rtw89_chip_stop_sch_tx(rtwdev, RTW89_MAC_0, &p->tx_en, RTW89_SCH_TX_SEL_ALL);
|
||||
rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false);
|
||||
rtw89_chip_stop_sch_tx(rtwdev, mac_idx, &p->tx_en,
|
||||
RTW89_SCH_TX_SEL_ALL);
|
||||
rtw89_mac_cfg_ppdu_status(rtwdev, mac_idx, false);
|
||||
rtw8852c_dfs_en(rtwdev, false);
|
||||
rtw8852c_tssi_cont_en_phyidx(rtwdev, false, RTW89_PHY_0);
|
||||
rtw8852c_tssi_cont_en_phyidx(rtwdev, false, phy_idx);
|
||||
rtw8852c_adc_en(rtwdev, false);
|
||||
fsleep(40);
|
||||
rtw8852c_bb_reset_en(rtwdev, phy_idx, false);
|
||||
rtw8852c_bb_reset_en(rtwdev, chan->band_type, phy_idx, false);
|
||||
} else {
|
||||
rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
|
||||
rtw89_mac_cfg_ppdu_status(rtwdev, mac_idx, true);
|
||||
rtw8852c_adc_en(rtwdev, true);
|
||||
rtw8852c_dfs_en(rtwdev, true);
|
||||
rtw8852c_tssi_cont_en_phyidx(rtwdev, true, RTW89_PHY_0);
|
||||
rtw8852c_bb_reset_en(rtwdev, phy_idx, true);
|
||||
rtw89_chip_resume_sch_tx(rtwdev, RTW89_MAC_0, p->tx_en);
|
||||
rtw8852c_tssi_cont_en_phyidx(rtwdev, true, phy_idx);
|
||||
rtw8852c_bb_reset_en(rtwdev, chan->band_type, phy_idx, true);
|
||||
rtw89_chip_resume_sch_tx(rtwdev, mac_idx, p->tx_en);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1847,9 +1853,10 @@ static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev)
|
||||
rtw89_fw_h2c_rf_ntfy_mcc(rtwdev);
|
||||
}
|
||||
|
||||
static void rtw8852c_rfk_band_changed(struct rtw89_dev *rtwdev)
|
||||
static void rtw8852c_rfk_band_changed(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
rtw8852c_tssi_scan(rtwdev, RTW89_PHY_0);
|
||||
rtw8852c_tssi_scan(rtwdev, phy_idx);
|
||||
}
|
||||
|
||||
static void rtw8852c_rfk_scan(struct rtw89_dev *rtwdev, bool start)
|
||||
@ -1958,9 +1965,11 @@ static void rtw8852c_set_txpwr_ref(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static void rtw8852c_set_txpwr_byrate(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
u8 band = chan->band_type;
|
||||
u8 ch = chan->channel;
|
||||
static const u8 rs[] = {
|
||||
RTW89_RS_CCK,
|
||||
RTW89_RS_OFDM,
|
||||
@ -1986,7 +1995,8 @@ static void rtw8852c_set_txpwr_byrate(struct rtw89_dev *rtwdev,
|
||||
for (j = 0; j < rtw89_rs_idx_max[rs[i]]; j++) {
|
||||
cur.idx = j;
|
||||
shf = (j % 4) * 8;
|
||||
tmp = rtw89_phy_read_txpwr_byrate(rtwdev, &cur);
|
||||
tmp = rtw89_phy_read_txpwr_byrate(rtwdev, band,
|
||||
&cur);
|
||||
val |= (tmp << shf);
|
||||
|
||||
if ((j + 1) % 4)
|
||||
@ -2001,8 +2011,10 @@ static void rtw8852c_set_txpwr_byrate(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static void rtw8852c_set_txpwr_offset(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
u8 band = chan->band_type;
|
||||
struct rtw89_rate_desc desc = {
|
||||
.nss = RTW89_NSS_1,
|
||||
.rs = RTW89_RS_OFFSET,
|
||||
@ -2013,7 +2025,7 @@ static void rtw8852c_set_txpwr_offset(struct rtw89_dev *rtwdev,
|
||||
rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr offset\n");
|
||||
|
||||
for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_MAX; desc.idx++) {
|
||||
v = rtw89_phy_read_txpwr_byrate(rtwdev, &desc);
|
||||
v = rtw89_phy_read_txpwr_byrate(rtwdev, band, &desc);
|
||||
val |= ((v & 0xf) << (4 * desc.idx));
|
||||
}
|
||||
|
||||
@ -2045,7 +2057,8 @@ static void rtw8852c_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev,
|
||||
__DECL_DFIR_ADDR(filter,
|
||||
0x45BC, 0x45CC, 0x45D0, 0x45D4, 0x45D8, 0x45C0,
|
||||
0x45C4, 0x45C8);
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 ch = chan->channel;
|
||||
const u32 *param;
|
||||
int i;
|
||||
|
||||
@ -2076,9 +2089,10 @@ static void rtw8852c_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static void rtw8852c_set_tx_shape(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
u8 band = rtwdev->hal.current_band_type;
|
||||
u8 band = chan->band_type;
|
||||
u8 regd = rtw89_regd_get(rtwdev, band);
|
||||
u8 tx_shape_cck = rtw89_8852c_tx_shape[band][RTW89_RS_CCK][regd];
|
||||
u8 tx_shape_ofdm = rtw89_8852c_tx_shape[band][RTW89_RS_OFDM][regd];
|
||||
@ -2092,29 +2106,31 @@ static void rtw8852c_set_tx_shape(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static void rtw8852c_set_txpwr_limit(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
#define __MAC_TXPWR_LMT_PAGE_SIZE 40
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
u8 bw = rtwdev->hal.current_band_width;
|
||||
u8 ch = chan->channel;
|
||||
u8 bw = chan->band_width;
|
||||
struct rtw89_txpwr_limit lmt[NTX_NUM_8852C];
|
||||
u32 addr, val;
|
||||
const s8 *ptr;
|
||||
u8 i, j, k;
|
||||
u8 i, j;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
|
||||
"[TXPWR] set txpwr limit with ch=%d bw=%d\n", ch, bw);
|
||||
|
||||
for (i = 0; i < NTX_NUM_8852C; i++) {
|
||||
rtw89_phy_fill_txpwr_limit(rtwdev, &lmt[i], i);
|
||||
rtw89_phy_fill_txpwr_limit(rtwdev, chan, &lmt[i], i);
|
||||
|
||||
for (j = 0; j < __MAC_TXPWR_LMT_PAGE_SIZE; j += 4) {
|
||||
addr = R_AX_PWR_LMT + j + __MAC_TXPWR_LMT_PAGE_SIZE * i;
|
||||
ptr = (s8 *)&lmt[i] + j;
|
||||
val = 0;
|
||||
|
||||
for (k = 0; k < 4; k++)
|
||||
val |= (ptr[k] << (8 * k));
|
||||
val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
|
||||
FIELD_PREP(GENMASK(15, 8), ptr[1]) |
|
||||
FIELD_PREP(GENMASK(23, 16), ptr[2]) |
|
||||
FIELD_PREP(GENMASK(31, 24), ptr[3]);
|
||||
|
||||
rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
|
||||
}
|
||||
@ -2123,30 +2139,32 @@ static void rtw8852c_set_txpwr_limit(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
static void rtw8852c_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
#define __MAC_TXPWR_LMT_RU_PAGE_SIZE 24
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
u8 bw = rtwdev->hal.current_band_width;
|
||||
u8 ch = chan->channel;
|
||||
u8 bw = chan->band_width;
|
||||
struct rtw89_txpwr_limit_ru lmt_ru[NTX_NUM_8852C];
|
||||
u32 addr, val;
|
||||
const s8 *ptr;
|
||||
u8 i, j, k;
|
||||
u8 i, j;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
|
||||
"[TXPWR] set txpwr limit ru with ch=%d bw=%d\n", ch, bw);
|
||||
|
||||
for (i = 0; i < NTX_NUM_8852C; i++) {
|
||||
rtw89_phy_fill_txpwr_limit_ru(rtwdev, &lmt_ru[i], i);
|
||||
rtw89_phy_fill_txpwr_limit_ru(rtwdev, chan, &lmt_ru[i], i);
|
||||
|
||||
for (j = 0; j < __MAC_TXPWR_LMT_RU_PAGE_SIZE; j += 4) {
|
||||
addr = R_AX_PWR_RU_LMT + j +
|
||||
__MAC_TXPWR_LMT_RU_PAGE_SIZE * i;
|
||||
ptr = (s8 *)&lmt_ru[i] + j;
|
||||
val = 0;
|
||||
|
||||
for (k = 0; k < 4; k++)
|
||||
val |= (ptr[k] << (8 * k));
|
||||
val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
|
||||
FIELD_PREP(GENMASK(15, 8), ptr[1]) |
|
||||
FIELD_PREP(GENMASK(23, 16), ptr[2]) |
|
||||
FIELD_PREP(GENMASK(31, 24), ptr[3]);
|
||||
|
||||
rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
|
||||
}
|
||||
@ -2155,18 +2173,21 @@ static void rtw8852c_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
|
||||
#undef __MAC_TXPWR_LMT_RU_PAGE_SIZE
|
||||
}
|
||||
|
||||
static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev)
|
||||
static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
rtw8852c_set_txpwr_byrate(rtwdev, RTW89_PHY_0);
|
||||
rtw8852c_set_txpwr_offset(rtwdev, RTW89_PHY_0);
|
||||
rtw8852c_set_tx_shape(rtwdev, RTW89_PHY_0);
|
||||
rtw8852c_set_txpwr_limit(rtwdev, RTW89_PHY_0);
|
||||
rtw8852c_set_txpwr_limit_ru(rtwdev, RTW89_PHY_0);
|
||||
rtw8852c_set_txpwr_byrate(rtwdev, chan, phy_idx);
|
||||
rtw8852c_set_txpwr_offset(rtwdev, chan, phy_idx);
|
||||
rtw8852c_set_tx_shape(rtwdev, chan, phy_idx);
|
||||
rtw8852c_set_txpwr_limit(rtwdev, chan, phy_idx);
|
||||
rtw8852c_set_txpwr_limit_ru(rtwdev, chan, phy_idx);
|
||||
}
|
||||
|
||||
static void rtw8852c_set_txpwr_ctrl(struct rtw89_dev *rtwdev)
|
||||
static void rtw8852c_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
rtw8852c_set_txpwr_ref(rtwdev, RTW89_PHY_0);
|
||||
rtw8852c_set_txpwr_ref(rtwdev, phy_idx);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2222,7 +2243,8 @@ rtw8852c_init_txpwr_unit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
|
||||
|
||||
static void rtw8852c_bb_cfg_rx_path(struct rtw89_dev *rtwdev, u8 rx_path)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 band = chan->band_type;
|
||||
u32 rst_mask0 = B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI;
|
||||
u32 rst_mask1 = B_P1_TXPW_RSTB_MANON | B_P1_TXPW_RSTB_TSSI;
|
||||
|
||||
@ -2316,7 +2338,7 @@ static void rtw8852c_bb_cfg_rx_path(struct rtw89_dev *rtwdev, u8 rx_path)
|
||||
1);
|
||||
rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS,
|
||||
1);
|
||||
rtw8852c_ctrl_btg(rtwdev, hal->current_band_type == RTW89_BAND_2G);
|
||||
rtw8852c_ctrl_btg(rtwdev, band == RTW89_BAND_2G);
|
||||
rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB,
|
||||
rst_mask0, 1);
|
||||
rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB,
|
||||
@ -2773,23 +2795,7 @@ void rtw8852c_btc_bt_aci_imp(struct rtw89_dev *rtwdev)
|
||||
static
|
||||
void rtw8852c_btc_update_bt_cnt(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_btc *btc = &rtwdev->btc;
|
||||
struct rtw89_btc_cx *cx = &btc->cx;
|
||||
u32 val;
|
||||
|
||||
val = rtw89_read32(rtwdev, R_BTC_BT_CNT_HIGH);
|
||||
cx->cnt_bt[BTC_BCNT_HIPRI_TX] = FIELD_GET(B_AX_STATIS_BT_HI_TX_MASK, val);
|
||||
cx->cnt_bt[BTC_BCNT_HIPRI_RX] = FIELD_GET(B_AX_STATIS_BT_HI_RX_MASK, val);
|
||||
|
||||
val = rtw89_read32(rtwdev, R_BTC_BT_CNT_LOW);
|
||||
cx->cnt_bt[BTC_BCNT_LOPRI_TX] = FIELD_GET(B_AX_STATIS_BT_LO_TX_1_MASK, val);
|
||||
cx->cnt_bt[BTC_BCNT_LOPRI_RX] = FIELD_GET(B_AX_STATIS_BT_LO_RX_1_MASK, val);
|
||||
|
||||
/* clock-gate off before reset counter*/
|
||||
rtw89_write32_set(rtwdev, R_AX_BTC_CFG, B_AX_DIS_BTC_CLK_G);
|
||||
rtw89_write32_clr(rtwdev, R_AX_BT_CNT_CFG, B_AX_BT_CNT_RST);
|
||||
rtw89_write32_set(rtwdev, R_AX_BT_CNT_CFG, B_AX_BT_CNT_RST);
|
||||
rtw89_write32_clr(rtwdev, R_AX_BTC_CFG, B_AX_DIS_BTC_CLK_G);
|
||||
/* Feature move to firmware */
|
||||
}
|
||||
|
||||
static
|
||||
@ -2930,6 +2936,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
|
||||
.btc_bt_aci_imp = rtw8852c_btc_bt_aci_imp,
|
||||
.btc_update_bt_cnt = rtw8852c_btc_update_bt_cnt,
|
||||
.btc_wl_s1_standby = rtw8852c_btc_wl_s1_standby,
|
||||
.btc_set_policy = rtw89_btc_set_policy_v1,
|
||||
};
|
||||
|
||||
const struct rtw89_chip_info rtw8852c_chip_info = {
|
||||
@ -2961,6 +2968,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
|
||||
.txpwr_factor_mac = 1,
|
||||
.dig_table = NULL,
|
||||
.tssi_dbw_table = &rtw89_8852c_tssi_dbw_table,
|
||||
.support_chanctx_num = 1,
|
||||
.support_bands = BIT(NL80211_BAND_2GHZ) |
|
||||
BIT(NL80211_BAND_5GHZ) |
|
||||
BIT(NL80211_BAND_6GHZ),
|
||||
@ -2972,6 +2980,9 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
|
||||
.acam_num = 128,
|
||||
.bcam_num = 20,
|
||||
.scam_num = 128,
|
||||
.bacam_num = 8,
|
||||
.bacam_dynamic_num = 8,
|
||||
.bacam_v1 = true,
|
||||
.sec_ctrl_efuse_size = 4,
|
||||
.physical_efuse_size = 1216,
|
||||
.logical_efuse_size = 2048,
|
||||
@ -2985,6 +2996,20 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
|
||||
.btcx_desired = 0x5,
|
||||
.scbd = 0x1,
|
||||
.mailbox = 0x1,
|
||||
|
||||
.fcxbtcrpt_ver = 4,
|
||||
.fcxtdma_ver = 3,
|
||||
.fcxslots_ver = 1,
|
||||
.fcxcysta_ver = 3,
|
||||
.fcxstep_ver = 3,
|
||||
.fcxnullsta_ver = 2,
|
||||
.fcxmreg_ver = 1,
|
||||
.fcxgpiodbg_ver = 1,
|
||||
.fcxbtver_ver = 1,
|
||||
.fcxbtscan_ver = 1,
|
||||
.fcxbtafh_ver = 1,
|
||||
.fcxbtdevinfo_ver = 1,
|
||||
|
||||
.afh_guard_ch = 6,
|
||||
.wl_rssi_thres = rtw89_btc_8852c_wl_rssi_thres,
|
||||
.bt_rssi_thres = rtw89_btc_8852c_bt_rssi_thres,
|
||||
|
@ -1294,14 +1294,14 @@ static void _iqk_by_path(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, u
|
||||
static void _iqk_get_ch_info(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy, u8 path)
|
||||
{
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
|
||||
|
||||
iqk_info->iqk_band[path] = hal->current_band_type;
|
||||
iqk_info->iqk_bw[path] = hal->current_band_width;
|
||||
iqk_info->iqk_ch[path] = hal->current_channel;
|
||||
iqk_info->iqk_band[path] = chan->band_type;
|
||||
iqk_info->iqk_bw[path] = chan->band_width;
|
||||
iqk_info->iqk_ch[path] = chan->channel;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK,
|
||||
"[IQK]iqk_info->iqk_band[%x] = 0x%x\n", path,
|
||||
@ -1691,14 +1691,14 @@ static void _dpk_information(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
struct rtw89_dpk_info *dpk = &rtwdev->dpk;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
||||
u8 kidx = dpk->cur_idx[path];
|
||||
|
||||
dpk->bp[path][kidx].band = hal->current_band_type;
|
||||
dpk->bp[path][kidx].ch = hal->current_channel;
|
||||
dpk->bp[path][kidx].bw = hal->current_band_width;
|
||||
dpk->bp[path][kidx].band = chan->band_type;
|
||||
dpk->bp[path][kidx].ch = chan->channel;
|
||||
dpk->bp[path][kidx].bw = chan->band_width;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK,
|
||||
"[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n",
|
||||
@ -2272,12 +2272,13 @@ static void _dpk_idl_mpa(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
static bool _dpk_reload_check(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
struct rtw89_dpk_info *dpk = &rtwdev->dpk;
|
||||
bool is_reload = false;
|
||||
u8 idx, cur_band, cur_ch;
|
||||
|
||||
cur_band = rtwdev->hal.current_band_type;
|
||||
cur_ch = rtwdev->hal.current_channel;
|
||||
cur_band = chan->band_type;
|
||||
cur_ch = chan->channel;
|
||||
|
||||
for (idx = 0; idx < RTW89_DPK_BKUP_NUM; idx++) {
|
||||
if (cur_band != dpk->bp[path][idx].band ||
|
||||
@ -2530,17 +2531,19 @@ static void _dpk_cal_select(struct rtw89_dev *rtwdev, bool force,
|
||||
static bool _dpk_bypass_check(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
|
||||
{
|
||||
struct rtw89_fem_info *fem = &rtwdev->fem;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 band = chan->band_type;
|
||||
|
||||
if (rtwdev->hal.cv == CHIP_CAV && rtwdev->hal.current_band_type != RTW89_BAND_2G) {
|
||||
if (rtwdev->hal.cv == CHIP_CAV && band != RTW89_BAND_2G) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Skip DPK due to CAV & not 2G!!\n");
|
||||
return true;
|
||||
} else if (fem->epa_2g && rtwdev->hal.current_band_type == RTW89_BAND_2G) {
|
||||
} else if (fem->epa_2g && band == RTW89_BAND_2G) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Skip DPK due to 2G_ext_PA exist!!\n");
|
||||
return true;
|
||||
} else if (fem->epa_5g && rtwdev->hal.current_band_type == RTW89_BAND_5G) {
|
||||
} else if (fem->epa_5g && band == RTW89_BAND_5G) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Skip DPK due to 5G_ext_PA exist!!\n");
|
||||
return true;
|
||||
} else if (fem->epa_6g && rtwdev->hal.current_band_type == RTW89_BAND_6G) {
|
||||
} else if (fem->epa_6g && band == RTW89_BAND_6G) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Skip DPK due to 6G_ext_PA exist!!\n");
|
||||
return true;
|
||||
}
|
||||
@ -2663,7 +2666,8 @@ static void _dpk_track(struct rtw89_dev *rtwdev)
|
||||
static void _tssi_set_sys(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
enum rtw89_band band = rtwdev->hal.current_band_type;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
enum rtw89_band band = chan->band_type;
|
||||
|
||||
rtw89_rfk_parser(rtwdev, &rtw8852c_tssi_sys_defs_tbl);
|
||||
|
||||
@ -2697,7 +2701,8 @@ static void _tssi_ini_txpwr_ctrl_bb_he_tb(struct rtw89_dev *rtwdev,
|
||||
static void _tssi_set_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
enum rtw89_band band = rtwdev->hal.current_band_type;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
enum rtw89_band band = chan->band_type;
|
||||
|
||||
if (path == RF_PATH_A) {
|
||||
rtw89_rfk_parser(rtwdev, &rtw8852c_tssi_dck_defs_a_tbl);
|
||||
@ -2735,8 +2740,9 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
|
||||
__val; \
|
||||
})
|
||||
struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
u8 subband = rtwdev->hal.current_subband;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 ch = chan->channel;
|
||||
u8 subband = chan->subband_type;
|
||||
const s8 *thm_up_a = NULL;
|
||||
const s8 *thm_down_a = NULL;
|
||||
const s8 *thm_up_b = NULL;
|
||||
@ -2908,7 +2914,8 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
|
||||
static void _tssi_slope_cal_org(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
enum rtw89_band band = rtwdev->hal.current_band_type;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
enum rtw89_band band = chan->band_type;
|
||||
|
||||
if (path == RF_PATH_A) {
|
||||
rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G,
|
||||
@ -2924,7 +2931,8 @@ static void _tssi_slope_cal_org(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy
|
||||
static void _tssi_set_aligk_default(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
enum rtw89_band band = rtwdev->hal.current_band_type;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
enum rtw89_band band = chan->band_type;
|
||||
const struct rtw89_rfk_tbl *tbl;
|
||||
|
||||
if (path == RF_PATH_A) {
|
||||
@ -3335,8 +3343,9 @@ static s8 _tssi_get_ofdm_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
|
||||
enum rtw89_band band = rtwdev->hal.current_band_type;
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
enum rtw89_band band = chan->band_type;
|
||||
u8 ch = chan->channel;
|
||||
u32 gidx, gidx_1st, gidx_2nd;
|
||||
s8 de_1st;
|
||||
s8 de_2nd;
|
||||
@ -3398,8 +3407,9 @@ static s8 _tssi_get_ofdm_trim_de(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_rf_path path)
|
||||
{
|
||||
struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
|
||||
enum rtw89_band band = rtwdev->hal.current_band_type;
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
enum rtw89_band band = chan->band_type;
|
||||
u8 ch = chan->channel;
|
||||
u32 tgidx, tgidx_1st, tgidx_2nd;
|
||||
s8 tde_1st = 0;
|
||||
s8 tde_2nd = 0;
|
||||
@ -3462,7 +3472,8 @@ static void _tssi_set_efuse_to_de(struct rtw89_dev *rtwdev,
|
||||
enum rtw89_phy_idx phy)
|
||||
{
|
||||
struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
|
||||
u8 ch = rtwdev->hal.current_channel;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
u8 ch = chan->channel;
|
||||
u8 gidx;
|
||||
s8 ofdm_de;
|
||||
s8 trim_de;
|
||||
@ -3802,15 +3813,17 @@ void rtw8852c_ctrl_bw_ch(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
|
||||
}
|
||||
|
||||
void rtw8852c_set_channel_rf(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
rtw8852c_ctrl_bw_ch(rtwdev, phy_idx, param->center_chan, param->band_type,
|
||||
param->bandwidth);
|
||||
rtw8852c_ctrl_bw_ch(rtwdev, phy_idx, chan->channel,
|
||||
chan->band_type,
|
||||
chan->band_width);
|
||||
}
|
||||
|
||||
void rtw8852c_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
|
||||
{
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
struct rtw89_mcc_info *mcc_info = &rtwdev->mcc;
|
||||
u8 idx = mcc_info->table_idx;
|
||||
int i;
|
||||
@ -3823,8 +3836,8 @@ void rtw8852c_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_i
|
||||
}
|
||||
|
||||
mcc_info->table_idx = idx;
|
||||
mcc_info->ch[idx] = rtwdev->hal.current_channel;
|
||||
mcc_info->band[idx] = rtwdev->hal.current_band_type;
|
||||
mcc_info->ch[idx] = chan->channel;
|
||||
mcc_info->band[idx] = chan->band_type;
|
||||
}
|
||||
|
||||
void rtw8852c_rck(struct rtw89_dev *rtwdev)
|
||||
|
@ -21,7 +21,7 @@ void rtw8852c_tssi_cont_en_phyidx(struct rtw89_dev *rtwdev, bool en, u8 phy_idx)
|
||||
void rtw8852c_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start,
|
||||
enum rtw89_phy_idx phy_idx);
|
||||
void rtw8852c_set_channel_rf(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_channel_params *param,
|
||||
const struct rtw89_chan *chan,
|
||||
enum rtw89_phy_idx phy_idx);
|
||||
void rtw8852c_lck_init(struct rtw89_dev *rtwdev);
|
||||
void rtw8852c_lck_track(struct rtw89_dev *rtwdev);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -81,9 +81,9 @@ static const struct rtw89_sar_span rtw89_sar_overlapping_6ghz[] = {
|
||||
static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, s32 *cfg)
|
||||
{
|
||||
struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common;
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
enum rtw89_band band = hal->current_band_type;
|
||||
u32 center_freq = hal->current_freq;
|
||||
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
|
||||
enum rtw89_band band = chan->band_type;
|
||||
u32 center_freq = chan->freq;
|
||||
const struct rtw89_sar_span *span = NULL;
|
||||
enum rtw89_sar_subband subband_l, subband_h;
|
||||
int idx;
|
||||
@ -228,7 +228,7 @@ static int rtw89_apply_sar_common(struct rtw89_dev *rtwdev,
|
||||
}
|
||||
|
||||
rtw89_sar_set_src(rtwdev, RTW89_SAR_SOURCE_COMMON, cfg_common, sar);
|
||||
rtw89_chip_set_txpwr(rtwdev);
|
||||
rtw89_core_set_chip_txpwr(rtwdev);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <linux/devcoredump.h>
|
||||
|
||||
#include "cam.h"
|
||||
#include "chan.h"
|
||||
#include "debug.h"
|
||||
#include "fw.h"
|
||||
#include "mac.h"
|
||||
@ -152,7 +153,10 @@ static void ser_state_run(struct rtw89_ser *ser, u8 evt)
|
||||
rtw89_debug(rtwdev, RTW89_DBG_SER, "ser: %s receive %s\n",
|
||||
ser_st_name(ser), ser_ev_name(ser, evt));
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw89_leave_lps(rtwdev);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
ser->st_tbl[ser->state].st_func(ser, evt);
|
||||
}
|
||||
|
||||
@ -298,7 +302,7 @@ static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
||||
rtwvif->trigger = false;
|
||||
}
|
||||
|
||||
static void ser_sta_deinit_addr_cam_iter(void *data, struct ieee80211_sta *sta)
|
||||
static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct rtw89_vif *rtwvif = (struct rtw89_vif *)data;
|
||||
struct rtw89_dev *rtwdev = rtwvif->rtwdev;
|
||||
@ -308,15 +312,19 @@ static void ser_sta_deinit_addr_cam_iter(void *data, struct ieee80211_sta *sta)
|
||||
rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam);
|
||||
if (sta->tdls)
|
||||
rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam);
|
||||
|
||||
INIT_LIST_HEAD(&rtwsta->ba_cam_list);
|
||||
}
|
||||
|
||||
static void ser_deinit_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
||||
{
|
||||
ieee80211_iterate_stations_atomic(rtwdev->hw,
|
||||
ser_sta_deinit_addr_cam_iter,
|
||||
ser_sta_deinit_cam_iter,
|
||||
rtwvif);
|
||||
|
||||
rtw89_cam_deinit(rtwdev, rtwvif);
|
||||
|
||||
bitmap_zero(rtwdev->cam_info.ba_cam_map, RTW89_MAX_BA_CAM_NUM);
|
||||
}
|
||||
|
||||
static void ser_reset_mac_binding(struct rtw89_dev *rtwdev)
|
||||
@ -601,6 +609,7 @@ bottom:
|
||||
|
||||
ser_reset_mac_binding(rtwdev);
|
||||
rtw89_core_stop(rtwdev);
|
||||
rtw89_entity_init(rtwdev);
|
||||
INIT_LIST_HEAD(&rtwdev->rtwvifs_list);
|
||||
}
|
||||
|
||||
|
@ -181,7 +181,7 @@ int wfx_send_pds(struct wfx_dev *wdev, u8 *buf, size_t len)
|
||||
while (len > 0) {
|
||||
chunk_type = get_unaligned_le16(buf + 0);
|
||||
chunk_len = get_unaligned_le16(buf + 2);
|
||||
if (chunk_len > len) {
|
||||
if (chunk_len < 4 || chunk_len > len) {
|
||||
dev_err(wdev->dev, "PDS:%d: corrupted file\n", chunk_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1441,7 +1441,7 @@ static void wl3501_detach(struct pcmcia_device *link)
|
||||
static int wl3501_get_name(struct net_device *dev, struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
strlcpy(wrqu->name, "IEEE 802.11-DS", sizeof(wrqu->name));
|
||||
strscpy(wrqu->name, "IEEE 802.11-DS", sizeof(wrqu->name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1652,7 +1652,7 @@ static int wl3501_set_nick(struct net_device *dev, struct iw_request_info *info,
|
||||
|
||||
if (wrqu->data.length > sizeof(this->nick))
|
||||
return -E2BIG;
|
||||
strlcpy(this->nick, extra, wrqu->data.length);
|
||||
strscpy(this->nick, extra, wrqu->data.length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1661,7 +1661,7 @@ static int wl3501_get_nick(struct net_device *dev, struct iw_request_info *info,
|
||||
{
|
||||
struct wl3501_card *this = netdev_priv(dev);
|
||||
|
||||
strlcpy(extra, this->nick, 32);
|
||||
strscpy(extra, this->nick, 32);
|
||||
wrqu->data.length = strlen(extra);
|
||||
return 0;
|
||||
}
|
||||
@ -1965,7 +1965,7 @@ static int wl3501_config(struct pcmcia_device *link)
|
||||
this->firmware_date[0] = '\0';
|
||||
this->rssi = 255;
|
||||
this->chan = iw_default_channel(this->reg_domain);
|
||||
strlcpy(this->nick, "Planet WL3501", sizeof(this->nick));
|
||||
strscpy(this->nick, "Planet WL3501", sizeof(this->nick));
|
||||
spin_lock_init(&this->lock);
|
||||
init_waitqueue_head(&this->wait);
|
||||
netif_start_queue(dev);
|
||||
|
@ -4959,6 +4959,7 @@ enum nl80211_bss_scan_width {
|
||||
* using the nesting index as the antenna number.
|
||||
* @NL80211_BSS_FREQUENCY_OFFSET: frequency offset in KHz
|
||||
* @NL80211_BSS_MLO_LINK_ID: MLO link ID of the BSS (u8).
|
||||
* @NL80211_BSS_MLD_ADDR: MLD address of this BSS if connected to it.
|
||||
* @__NL80211_BSS_AFTER_LAST: internal
|
||||
* @NL80211_BSS_MAX: highest BSS attribute
|
||||
*/
|
||||
@ -4985,6 +4986,7 @@ enum nl80211_bss {
|
||||
NL80211_BSS_CHAIN_SIGNAL,
|
||||
NL80211_BSS_FREQUENCY_OFFSET,
|
||||
NL80211_BSS_MLO_LINK_ID,
|
||||
NL80211_BSS_MLD_ADDR,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_BSS_AFTER_LAST,
|
||||
@ -6281,6 +6283,14 @@ enum nl80211_feature_flags {
|
||||
* @NL80211_EXT_FEATURE_RADAR_BACKGROUND: Device supports background radar/CAC
|
||||
* detection.
|
||||
*
|
||||
* @NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE: Device can perform a MAC address
|
||||
* change without having to bring the underlying network device down
|
||||
* first. For example, in station mode this can be used to vary the
|
||||
* origin MAC address prior to a connection to a new AP for privacy
|
||||
* or other reasons. Note that certain driver specific restrictions
|
||||
* might apply, e.g. no scans in progress, no offchannel operations
|
||||
* in progress, and no active connections.
|
||||
*
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
*/
|
||||
@ -6348,6 +6358,7 @@ enum nl80211_ext_feature_index {
|
||||
NL80211_EXT_FEATURE_BSS_COLOR,
|
||||
NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD,
|
||||
NL80211_EXT_FEATURE_RADAR_BACKGROUND,
|
||||
NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
|
@ -16,6 +16,7 @@ mac80211-y := \
|
||||
s1g.o \
|
||||
ibss.o \
|
||||
iface.o \
|
||||
link.o \
|
||||
rate.o \
|
||||
michael.o \
|
||||
tkip.o \
|
||||
|
@ -226,6 +226,10 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
|
||||
if (params->use_4addr == ifmgd->use_4addr)
|
||||
return 0;
|
||||
|
||||
/* FIXME: no support for 4-addr MLO yet */
|
||||
if (sdata->vif.valid_links)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
sdata->u.mgd.use_4addr = params->use_4addr;
|
||||
if (!ifmgd->associated)
|
||||
return 0;
|
||||
@ -4697,6 +4701,9 @@ static int ieee80211_add_intf_link(struct wiphy *wiphy,
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||
|
||||
if (wdev->use_4addr)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ieee80211_vif_set_links(sdata, wdev->valid_links);
|
||||
}
|
||||
|
||||
|
@ -1811,6 +1811,7 @@ void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
|
||||
u8 reason, bool tx);
|
||||
void ieee80211_mgd_setup_link(struct ieee80211_link_data *link);
|
||||
void ieee80211_mgd_stop_link(struct ieee80211_link_data *link);
|
||||
void ieee80211_mgd_set_link_qos_params(struct ieee80211_link_data *link);
|
||||
|
||||
/* IBSS code */
|
||||
void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
|
||||
@ -1930,9 +1931,6 @@ void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata);
|
||||
int ieee80211_add_virtual_monitor(struct ieee80211_local *local);
|
||||
void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
|
||||
|
||||
int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
|
||||
u16 new_links);
|
||||
|
||||
bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
|
||||
bool update_bss);
|
||||
@ -1943,6 +1941,17 @@ static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
|
||||
return test_bit(SDATA_STATE_RUNNING, &sdata->state);
|
||||
}
|
||||
|
||||
/* link handling */
|
||||
void ieee80211_link_setup(struct ieee80211_link_data *link);
|
||||
void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
|
||||
int link_id,
|
||||
struct ieee80211_link_data *link,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
void ieee80211_link_stop(struct ieee80211_link_data *link);
|
||||
int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
|
||||
u16 new_links);
|
||||
void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
/* tx handling */
|
||||
void ieee80211_clear_tx_pending(struct ieee80211_local *local);
|
||||
void ieee80211_tx_pending(struct tasklet_struct *t);
|
||||
@ -2412,8 +2421,7 @@ bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw, u32 vht_cap_info,
|
||||
const struct ieee80211_vht_operation *oper,
|
||||
const struct ieee80211_ht_operation *htop,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
void ieee80211_chandef_eht_oper(struct ieee80211_sub_if_data *sdata,
|
||||
const struct ieee80211_eht_operation *eht_oper,
|
||||
void ieee80211_chandef_eht_oper(const struct ieee80211_eht_operation *eht_oper,
|
||||
bool support_160, bool support_320,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
|
||||
|
@ -200,15 +200,73 @@ static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ieee80211_can_powered_addr_change(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_roc_work *roc;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_sub_if_data *scan_sdata;
|
||||
int ret = 0;
|
||||
|
||||
/* To be the most flexible here we want to only limit changing the
|
||||
* address if the specific interface is doing offchannel work or
|
||||
* scanning.
|
||||
*/
|
||||
if (netif_carrier_ok(sdata->dev))
|
||||
return -EBUSY;
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
|
||||
/* First check no ROC work is happening on this iface */
|
||||
list_for_each_entry(roc, &local->roc_list, list) {
|
||||
if (roc->sdata != sdata)
|
||||
continue;
|
||||
|
||||
if (roc->started) {
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
/* And if this iface is scanning */
|
||||
if (local->scanning) {
|
||||
scan_sdata = rcu_dereference_protected(local->scan_sdata,
|
||||
lockdep_is_held(&local->mtx));
|
||||
if (sdata == scan_sdata)
|
||||
ret = -EBUSY;
|
||||
}
|
||||
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
/* More interface types could be added here but changing the
|
||||
* address while powered makes the most sense in client modes.
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&local->mtx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ieee80211_change_mac(struct net_device *dev, void *addr)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sockaddr *sa = addr;
|
||||
bool check_dup = true;
|
||||
bool live = false;
|
||||
int ret;
|
||||
|
||||
if (ieee80211_sdata_running(sdata))
|
||||
return -EBUSY;
|
||||
if (ieee80211_sdata_running(sdata)) {
|
||||
ret = ieee80211_can_powered_addr_change(sdata);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
live = true;
|
||||
}
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
|
||||
!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
|
||||
@ -218,6 +276,8 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (live)
|
||||
drv_remove_interface(local, sdata);
|
||||
ret = eth_mac_addr(dev, sa);
|
||||
|
||||
if (ret == 0) {
|
||||
@ -225,6 +285,12 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
|
||||
ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
|
||||
}
|
||||
|
||||
/* Regardless of eth_mac_addr() return we still want to add the
|
||||
* interface back. This should not fail...
|
||||
*/
|
||||
if (live)
|
||||
WARN_ON(drv_add_interface(local, sdata));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -296,6 +362,11 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
|
||||
nsdata->vif.type))
|
||||
return -ENOTUNIQ;
|
||||
|
||||
/* No support for VLAN with MLO yet */
|
||||
if (iftype == NL80211_IFTYPE_AP_VLAN &&
|
||||
nsdata->wdev.use_4addr)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
* can only add VLANs to enabled APs
|
||||
*/
|
||||
@ -368,257 +439,6 @@ static int ieee80211_open(struct net_device *dev)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ieee80211_link_setup(struct ieee80211_link_data *link)
|
||||
{
|
||||
if (link->sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_mgd_setup_link(link);
|
||||
}
|
||||
|
||||
static void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
|
||||
int link_id,
|
||||
struct ieee80211_link_data *link,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
bool deflink = link_id < 0;
|
||||
|
||||
if (link_id < 0)
|
||||
link_id = 0;
|
||||
|
||||
rcu_assign_pointer(sdata->vif.link_conf[link_id], link_conf);
|
||||
rcu_assign_pointer(sdata->link[link_id], link);
|
||||
|
||||
link->sdata = sdata;
|
||||
link->link_id = link_id;
|
||||
link->conf = link_conf;
|
||||
link_conf->link_id = link_id;
|
||||
|
||||
INIT_WORK(&link->csa_finalize_work,
|
||||
ieee80211_csa_finalize_work);
|
||||
INIT_WORK(&link->color_change_finalize_work,
|
||||
ieee80211_color_change_finalize_work);
|
||||
INIT_LIST_HEAD(&link->assigned_chanctx_list);
|
||||
INIT_LIST_HEAD(&link->reserved_chanctx_list);
|
||||
INIT_DELAYED_WORK(&link->dfs_cac_timer_work,
|
||||
ieee80211_dfs_cac_timer_work);
|
||||
|
||||
if (!deflink) {
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
ether_addr_copy(link_conf->addr,
|
||||
sdata->wdev.links[link_id].addr);
|
||||
link_conf->bssid = link_conf->addr;
|
||||
WARN_ON(!(sdata->wdev.valid_links & BIT(link_id)));
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
/* station sets the bssid in ieee80211_mgd_setup_link */
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ieee80211_link_stop(struct ieee80211_link_data *link)
|
||||
{
|
||||
if (link->sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_mgd_stop_link(link);
|
||||
|
||||
ieee80211_link_release_channel(link);
|
||||
}
|
||||
|
||||
struct link_container {
|
||||
struct ieee80211_link_data data;
|
||||
struct ieee80211_bss_conf conf;
|
||||
};
|
||||
|
||||
static void ieee80211_free_links(struct ieee80211_sub_if_data *sdata,
|
||||
struct link_container **links)
|
||||
{
|
||||
LIST_HEAD(keys);
|
||||
unsigned int link_id;
|
||||
|
||||
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
|
||||
if (!links[link_id])
|
||||
continue;
|
||||
ieee80211_remove_link_keys(&links[link_id]->data, &keys);
|
||||
}
|
||||
|
||||
synchronize_rcu();
|
||||
|
||||
ieee80211_free_key_list(sdata->local, &keys);
|
||||
|
||||
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
|
||||
if (!links[link_id])
|
||||
continue;
|
||||
ieee80211_link_stop(&links[link_id]->data);
|
||||
kfree(links[link_id]);
|
||||
}
|
||||
}
|
||||
|
||||
static int ieee80211_check_dup_link_addrs(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
|
||||
struct ieee80211_link_data *link1;
|
||||
|
||||
link1 = sdata_dereference(sdata->link[i], sdata);
|
||||
if (!link1)
|
||||
continue;
|
||||
for (j = i + 1; j < IEEE80211_MLD_MAX_NUM_LINKS; j++) {
|
||||
struct ieee80211_link_data *link2;
|
||||
|
||||
link2 = sdata_dereference(sdata->link[j], sdata);
|
||||
if (!link2)
|
||||
continue;
|
||||
|
||||
if (ether_addr_equal(link1->conf->addr,
|
||||
link2->conf->addr))
|
||||
return -EALREADY;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
|
||||
struct link_container **to_free,
|
||||
u16 new_links)
|
||||
{
|
||||
u16 old_links = sdata->vif.valid_links;
|
||||
unsigned long add = new_links & ~old_links;
|
||||
unsigned long rem = old_links & ~new_links;
|
||||
unsigned int link_id;
|
||||
int ret;
|
||||
struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS] = {}, *link;
|
||||
struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
struct ieee80211_link_data *old_data[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
bool use_deflink = old_links == 0; /* set for error case */
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
memset(to_free, 0, sizeof(links));
|
||||
|
||||
if (old_links == new_links)
|
||||
return 0;
|
||||
|
||||
/* if there were no old links, need to clear the pointers to deflink */
|
||||
if (!old_links)
|
||||
rem |= BIT(0);
|
||||
|
||||
/* allocate new link structures first */
|
||||
for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
link = kzalloc(sizeof(*link), GFP_KERNEL);
|
||||
if (!link) {
|
||||
ret = -ENOMEM;
|
||||
goto free;
|
||||
}
|
||||
links[link_id] = link;
|
||||
}
|
||||
|
||||
/* keep track of the old pointers for the driver */
|
||||
BUILD_BUG_ON(sizeof(old) != sizeof(sdata->vif.link_conf));
|
||||
memcpy(old, sdata->vif.link_conf, sizeof(old));
|
||||
/* and for us in error cases */
|
||||
BUILD_BUG_ON(sizeof(old_data) != sizeof(sdata->link));
|
||||
memcpy(old_data, sdata->link, sizeof(old_data));
|
||||
|
||||
/* grab old links to free later */
|
||||
for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
if (rcu_access_pointer(sdata->link[link_id]) != &sdata->deflink) {
|
||||
/*
|
||||
* we must have allocated the data through this path so
|
||||
* we know we can free both at the same time
|
||||
*/
|
||||
to_free[link_id] = container_of(rcu_access_pointer(sdata->link[link_id]),
|
||||
typeof(*links[link_id]),
|
||||
data);
|
||||
}
|
||||
|
||||
RCU_INIT_POINTER(sdata->link[link_id], NULL);
|
||||
RCU_INIT_POINTER(sdata->vif.link_conf[link_id], NULL);
|
||||
}
|
||||
|
||||
/* link them into data structures */
|
||||
for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
WARN_ON(!use_deflink &&
|
||||
rcu_access_pointer(sdata->link[link_id]) == &sdata->deflink);
|
||||
|
||||
link = links[link_id];
|
||||
ieee80211_link_init(sdata, link_id, &link->data, &link->conf);
|
||||
ieee80211_link_setup(&link->data);
|
||||
}
|
||||
|
||||
if (new_links == 0)
|
||||
ieee80211_link_init(sdata, -1, &sdata->deflink,
|
||||
&sdata->vif.bss_conf);
|
||||
|
||||
sdata->vif.valid_links = new_links;
|
||||
|
||||
ret = ieee80211_check_dup_link_addrs(sdata);
|
||||
if (!ret) {
|
||||
/* tell the driver */
|
||||
ret = drv_change_vif_links(sdata->local, sdata,
|
||||
old_links, new_links,
|
||||
old);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
/* restore config */
|
||||
memcpy(sdata->link, old_data, sizeof(old_data));
|
||||
memcpy(sdata->vif.link_conf, old, sizeof(old));
|
||||
sdata->vif.valid_links = old_links;
|
||||
/* and free (only) the newly allocated links */
|
||||
memset(to_free, 0, sizeof(links));
|
||||
goto free;
|
||||
}
|
||||
|
||||
/* use deflink/bss_conf again if and only if there are no more links */
|
||||
use_deflink = new_links == 0;
|
||||
|
||||
goto deinit;
|
||||
free:
|
||||
/* if we failed during allocation, only free all */
|
||||
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
|
||||
kfree(links[link_id]);
|
||||
links[link_id] = NULL;
|
||||
}
|
||||
deinit:
|
||||
if (use_deflink)
|
||||
ieee80211_link_init(sdata, -1, &sdata->deflink,
|
||||
&sdata->vif.bss_conf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
|
||||
u16 new_links)
|
||||
{
|
||||
struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
int ret;
|
||||
|
||||
ret = ieee80211_vif_update_links(sdata, links, new_links);
|
||||
ieee80211_free_links(sdata, links);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
|
||||
/*
|
||||
* The locking here is different because when we free links
|
||||
* in the station case we need to be able to cancel_work_sync()
|
||||
* something that also takes the lock.
|
||||
*/
|
||||
|
||||
sdata_lock(sdata);
|
||||
ieee80211_vif_update_links(sdata, links, 0);
|
||||
sdata_unlock(sdata);
|
||||
|
||||
ieee80211_free_links(sdata, links);
|
||||
}
|
||||
|
||||
static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_down)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
@ -2407,6 +2227,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
||||
sdata->u.mgd.use_4addr = params->use_4addr;
|
||||
|
||||
ndev->features |= local->hw.netdev_features;
|
||||
ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
|
||||
ndev->hw_features |= ndev->features &
|
||||
MAC80211_SUPPORTED_FEATURES_TX;
|
||||
|
||||
|
@ -865,8 +865,10 @@ int ieee80211_key_link(struct ieee80211_key *key,
|
||||
if (link_id >= 0) {
|
||||
link_sta = rcu_dereference_protected(sta->link[link_id],
|
||||
lockdep_is_held(&sta->local->sta_mtx));
|
||||
if (!link_sta)
|
||||
return -ENOLINK;
|
||||
if (!link_sta) {
|
||||
ret = -ENOLINK;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
old_key = key_mtx_dereference(sdata->local, link_sta->gtk[idx]);
|
||||
|
262
net/mac80211/link.c
Normal file
262
net/mac80211/link.c
Normal file
@ -0,0 +1,262 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* MLO link handling
|
||||
*
|
||||
* Copyright (C) 2022 Intel Corporation
|
||||
*/
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "ieee80211_i.h"
|
||||
#include "driver-ops.h"
|
||||
|
||||
void ieee80211_link_setup(struct ieee80211_link_data *link)
|
||||
{
|
||||
if (link->sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_mgd_setup_link(link);
|
||||
}
|
||||
|
||||
void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
|
||||
int link_id,
|
||||
struct ieee80211_link_data *link,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
bool deflink = link_id < 0;
|
||||
|
||||
if (link_id < 0)
|
||||
link_id = 0;
|
||||
|
||||
rcu_assign_pointer(sdata->vif.link_conf[link_id], link_conf);
|
||||
rcu_assign_pointer(sdata->link[link_id], link);
|
||||
|
||||
link->sdata = sdata;
|
||||
link->link_id = link_id;
|
||||
link->conf = link_conf;
|
||||
link_conf->link_id = link_id;
|
||||
|
||||
INIT_WORK(&link->csa_finalize_work,
|
||||
ieee80211_csa_finalize_work);
|
||||
INIT_WORK(&link->color_change_finalize_work,
|
||||
ieee80211_color_change_finalize_work);
|
||||
INIT_LIST_HEAD(&link->assigned_chanctx_list);
|
||||
INIT_LIST_HEAD(&link->reserved_chanctx_list);
|
||||
INIT_DELAYED_WORK(&link->dfs_cac_timer_work,
|
||||
ieee80211_dfs_cac_timer_work);
|
||||
|
||||
if (!deflink) {
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
ether_addr_copy(link_conf->addr,
|
||||
sdata->wdev.links[link_id].addr);
|
||||
link_conf->bssid = link_conf->addr;
|
||||
WARN_ON(!(sdata->wdev.valid_links & BIT(link_id)));
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
/* station sets the bssid in ieee80211_mgd_setup_link */
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ieee80211_link_stop(struct ieee80211_link_data *link)
|
||||
{
|
||||
if (link->sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_mgd_stop_link(link);
|
||||
|
||||
ieee80211_link_release_channel(link);
|
||||
}
|
||||
|
||||
struct link_container {
|
||||
struct ieee80211_link_data data;
|
||||
struct ieee80211_bss_conf conf;
|
||||
};
|
||||
|
||||
static void ieee80211_free_links(struct ieee80211_sub_if_data *sdata,
|
||||
struct link_container **links)
|
||||
{
|
||||
LIST_HEAD(keys);
|
||||
unsigned int link_id;
|
||||
|
||||
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
|
||||
if (!links[link_id])
|
||||
continue;
|
||||
ieee80211_remove_link_keys(&links[link_id]->data, &keys);
|
||||
}
|
||||
|
||||
synchronize_rcu();
|
||||
|
||||
ieee80211_free_key_list(sdata->local, &keys);
|
||||
|
||||
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
|
||||
if (!links[link_id])
|
||||
continue;
|
||||
ieee80211_link_stop(&links[link_id]->data);
|
||||
kfree(links[link_id]);
|
||||
}
|
||||
}
|
||||
|
||||
static int ieee80211_check_dup_link_addrs(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
|
||||
struct ieee80211_link_data *link1;
|
||||
|
||||
link1 = sdata_dereference(sdata->link[i], sdata);
|
||||
if (!link1)
|
||||
continue;
|
||||
for (j = i + 1; j < IEEE80211_MLD_MAX_NUM_LINKS; j++) {
|
||||
struct ieee80211_link_data *link2;
|
||||
|
||||
link2 = sdata_dereference(sdata->link[j], sdata);
|
||||
if (!link2)
|
||||
continue;
|
||||
|
||||
if (ether_addr_equal(link1->conf->addr,
|
||||
link2->conf->addr))
|
||||
return -EALREADY;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
|
||||
struct link_container **to_free,
|
||||
u16 new_links)
|
||||
{
|
||||
u16 old_links = sdata->vif.valid_links;
|
||||
unsigned long add = new_links & ~old_links;
|
||||
unsigned long rem = old_links & ~new_links;
|
||||
unsigned int link_id;
|
||||
int ret;
|
||||
struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS] = {}, *link;
|
||||
struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
struct ieee80211_link_data *old_data[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
bool use_deflink = old_links == 0; /* set for error case */
|
||||
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
memset(to_free, 0, sizeof(links));
|
||||
|
||||
if (old_links == new_links)
|
||||
return 0;
|
||||
|
||||
/* if there were no old links, need to clear the pointers to deflink */
|
||||
if (!old_links)
|
||||
rem |= BIT(0);
|
||||
|
||||
/* allocate new link structures first */
|
||||
for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
link = kzalloc(sizeof(*link), GFP_KERNEL);
|
||||
if (!link) {
|
||||
ret = -ENOMEM;
|
||||
goto free;
|
||||
}
|
||||
links[link_id] = link;
|
||||
}
|
||||
|
||||
/* keep track of the old pointers for the driver */
|
||||
BUILD_BUG_ON(sizeof(old) != sizeof(sdata->vif.link_conf));
|
||||
memcpy(old, sdata->vif.link_conf, sizeof(old));
|
||||
/* and for us in error cases */
|
||||
BUILD_BUG_ON(sizeof(old_data) != sizeof(sdata->link));
|
||||
memcpy(old_data, sdata->link, sizeof(old_data));
|
||||
|
||||
/* grab old links to free later */
|
||||
for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
if (rcu_access_pointer(sdata->link[link_id]) != &sdata->deflink) {
|
||||
/*
|
||||
* we must have allocated the data through this path so
|
||||
* we know we can free both at the same time
|
||||
*/
|
||||
to_free[link_id] = container_of(rcu_access_pointer(sdata->link[link_id]),
|
||||
typeof(*links[link_id]),
|
||||
data);
|
||||
}
|
||||
|
||||
RCU_INIT_POINTER(sdata->link[link_id], NULL);
|
||||
RCU_INIT_POINTER(sdata->vif.link_conf[link_id], NULL);
|
||||
}
|
||||
|
||||
/* link them into data structures */
|
||||
for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
WARN_ON(!use_deflink &&
|
||||
rcu_access_pointer(sdata->link[link_id]) == &sdata->deflink);
|
||||
|
||||
link = links[link_id];
|
||||
ieee80211_link_init(sdata, link_id, &link->data, &link->conf);
|
||||
ieee80211_link_setup(&link->data);
|
||||
}
|
||||
|
||||
if (new_links == 0)
|
||||
ieee80211_link_init(sdata, -1, &sdata->deflink,
|
||||
&sdata->vif.bss_conf);
|
||||
|
||||
sdata->vif.valid_links = new_links;
|
||||
|
||||
ret = ieee80211_check_dup_link_addrs(sdata);
|
||||
if (!ret) {
|
||||
/* tell the driver */
|
||||
ret = drv_change_vif_links(sdata->local, sdata,
|
||||
old_links, new_links,
|
||||
old);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
/* restore config */
|
||||
memcpy(sdata->link, old_data, sizeof(old_data));
|
||||
memcpy(sdata->vif.link_conf, old, sizeof(old));
|
||||
sdata->vif.valid_links = old_links;
|
||||
/* and free (only) the newly allocated links */
|
||||
memset(to_free, 0, sizeof(links));
|
||||
goto free;
|
||||
}
|
||||
|
||||
/* use deflink/bss_conf again if and only if there are no more links */
|
||||
use_deflink = new_links == 0;
|
||||
|
||||
goto deinit;
|
||||
free:
|
||||
/* if we failed during allocation, only free all */
|
||||
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
|
||||
kfree(links[link_id]);
|
||||
links[link_id] = NULL;
|
||||
}
|
||||
deinit:
|
||||
if (use_deflink)
|
||||
ieee80211_link_init(sdata, -1, &sdata->deflink,
|
||||
&sdata->vif.bss_conf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
|
||||
u16 new_links)
|
||||
{
|
||||
struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
int ret;
|
||||
|
||||
ret = ieee80211_vif_update_links(sdata, links, new_links);
|
||||
ieee80211_free_links(sdata, links);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
|
||||
/*
|
||||
* The locking here is different because when we free links
|
||||
* in the station case we need to be able to cancel_work_sync()
|
||||
* something that also takes the lock.
|
||||
*/
|
||||
|
||||
sdata_lock(sdata);
|
||||
ieee80211_vif_update_links(sdata, links, 0);
|
||||
sdata_unlock(sdata);
|
||||
|
||||
ieee80211_free_links(sdata, links);
|
||||
}
|
@ -699,6 +699,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
|
||||
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS);
|
||||
wiphy_ext_feature_set(wiphy,
|
||||
NL80211_EXT_FEATURE_SCAN_FREQ_KHZ);
|
||||
wiphy_ext_feature_set(wiphy,
|
||||
NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE);
|
||||
|
||||
if (!ops->hw_scan) {
|
||||
wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
|
||||
|
@ -314,7 +314,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
|
||||
if (eht_oper && (eht_oper->params & IEEE80211_EHT_OPER_INFO_PRESENT)) {
|
||||
struct cfg80211_chan_def eht_chandef = *chandef;
|
||||
|
||||
ieee80211_chandef_eht_oper(sdata, eht_oper,
|
||||
ieee80211_chandef_eht_oper(eht_oper,
|
||||
eht_chandef.width ==
|
||||
NL80211_CHAN_WIDTH_160,
|
||||
false, &eht_chandef);
|
||||
@ -2445,6 +2445,29 @@ static void ieee80211_sta_handle_tspec_ac_params_wk(struct work_struct *work)
|
||||
ieee80211_sta_handle_tspec_ac_params(sdata);
|
||||
}
|
||||
|
||||
void ieee80211_mgd_set_link_qos_params(struct ieee80211_link_data *link)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = link->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
struct ieee80211_tx_queue_params *params = link->tx_conf;
|
||||
u8 ac;
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
mlme_dbg(sdata,
|
||||
"WMM AC=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n",
|
||||
ac, params[ac].acm,
|
||||
params[ac].aifs, params[ac].cw_min, params[ac].cw_max,
|
||||
params[ac].txop, params[ac].uapsd,
|
||||
ifmgd->tx_tspec[ac].downgraded);
|
||||
if (!ifmgd->tx_tspec[ac].downgraded &&
|
||||
drv_conf_tx(local, link, ac, ¶ms[ac]))
|
||||
link_err(link,
|
||||
"failed to set TX queue parameters for AC %d\n",
|
||||
ac);
|
||||
}
|
||||
}
|
||||
|
||||
/* MLME */
|
||||
static bool
|
||||
ieee80211_sta_wmm_params(struct ieee80211_local *local,
|
||||
@ -2576,20 +2599,10 @@ ieee80211_sta_wmm_params(struct ieee80211_local *local,
|
||||
}
|
||||
}
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
mlme_dbg(sdata,
|
||||
"WMM AC=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n",
|
||||
ac, params[ac].acm,
|
||||
params[ac].aifs, params[ac].cw_min, params[ac].cw_max,
|
||||
params[ac].txop, params[ac].uapsd,
|
||||
ifmgd->tx_tspec[ac].downgraded);
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
|
||||
link->tx_conf[ac] = params[ac];
|
||||
if (!ifmgd->tx_tspec[ac].downgraded &&
|
||||
drv_conf_tx(local, link, ac, ¶ms[ac]))
|
||||
link_err(link,
|
||||
"failed to set TX queue parameters for AC %d\n",
|
||||
ac);
|
||||
}
|
||||
|
||||
ieee80211_mgd_set_link_qos_params(link);
|
||||
|
||||
/* enable WMM or activate new settings */
|
||||
link->conf->qos = true;
|
||||
@ -6323,6 +6336,8 @@ void ieee80211_mgd_setup_link(struct ieee80211_link_data *link)
|
||||
if (sdata->u.mgd.assoc_data)
|
||||
ether_addr_copy(link->conf->addr,
|
||||
sdata->u.mgd.assoc_data->link[link_id].addr);
|
||||
else if (!is_valid_ether_addr(link->conf->addr))
|
||||
eth_random_addr(link->conf->addr);
|
||||
}
|
||||
|
||||
/* scan finished notification */
|
||||
@ -6410,9 +6425,6 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (mlo && !is_valid_ether_addr(link->conf->addr))
|
||||
eth_random_addr(link->conf->addr);
|
||||
|
||||
if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) {
|
||||
err = -EINVAL;
|
||||
goto out_err;
|
||||
@ -6894,6 +6906,10 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: no support for 4-addr MLO yet */
|
||||
if (sdata->u.mgd.use_4addr && req->link_id >= 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
assoc_data = kzalloc(size, GFP_KERNEL);
|
||||
if (!assoc_data)
|
||||
return -ENOMEM;
|
||||
|
@ -485,7 +485,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
||||
/* Set power back to normal operating levels. */
|
||||
ieee80211_hw_config(local, 0);
|
||||
|
||||
if (!hw_scan) {
|
||||
if (!hw_scan && was_scanning) {
|
||||
ieee80211_configure_filter(local);
|
||||
drv_sw_scan_complete(local, scan_sdata);
|
||||
ieee80211_offchannel_return(local);
|
||||
|
@ -2530,7 +2530,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
if (link)
|
||||
ieee80211_assign_chanctx(local, sdata, link);
|
||||
}
|
||||
sdata_unlock(sdata);
|
||||
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
@ -2549,6 +2548,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
&sdata->deflink.tx_conf[i]);
|
||||
break;
|
||||
}
|
||||
sdata_unlock(sdata);
|
||||
|
||||
/* common change flags for all interface types */
|
||||
changed = BSS_CHANGED_ERP_CTS_PROT |
|
||||
@ -2657,23 +2657,21 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
}
|
||||
|
||||
/* APs are now beaconing, add back stations */
|
||||
mutex_lock(&local->sta_mtx);
|
||||
list_for_each_entry(sta, &local->sta_list, list) {
|
||||
enum ieee80211_sta_state state;
|
||||
|
||||
if (!sta->uploaded)
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
|
||||
if (sta->sdata->vif.type != NL80211_IFTYPE_AP &&
|
||||
sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
|
||||
continue;
|
||||
|
||||
for (state = IEEE80211_STA_NOTEXIST;
|
||||
state < sta->sta_state; state++)
|
||||
WARN_ON(drv_sta_state(local, sta->sdata, sta, state,
|
||||
state + 1));
|
||||
sdata_lock(sdata);
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
case NL80211_IFTYPE_AP:
|
||||
ieee80211_reconfig_stations(sdata);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
|
||||
/* add back keys */
|
||||
list_for_each_entry(sdata, &local->interfaces, list)
|
||||
@ -3512,8 +3510,7 @@ bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw, u32 vht_cap_info,
|
||||
return true;
|
||||
}
|
||||
|
||||
void ieee80211_chandef_eht_oper(struct ieee80211_sub_if_data *sdata,
|
||||
const struct ieee80211_eht_operation *eht_oper,
|
||||
void ieee80211_chandef_eht_oper(const struct ieee80211_eht_operation *eht_oper,
|
||||
bool support_160, bool support_320,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
@ -3689,7 +3686,7 @@ bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
|
||||
support_320 =
|
||||
eht_phy_cap & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
|
||||
|
||||
ieee80211_chandef_eht_oper(sdata, eht_oper, support_160,
|
||||
ieee80211_chandef_eht_oper(eht_oper, support_160,
|
||||
support_320, &he_chandef);
|
||||
}
|
||||
|
||||
|
@ -10182,8 +10182,10 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
|
||||
(nla_put_u32(msg, NL80211_BSS_STATUS,
|
||||
NL80211_BSS_STATUS_ASSOCIATED) ||
|
||||
(wdev->valid_links &&
|
||||
nla_put_u8(msg, NL80211_BSS_MLO_LINK_ID,
|
||||
link_id))))
|
||||
(nla_put_u8(msg, NL80211_BSS_MLO_LINK_ID,
|
||||
link_id) ||
|
||||
nla_put(msg, NL80211_BSS_MLD_ADDR, ETH_ALEN,
|
||||
wdev->u.client.connected_addr)))))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
break;
|
||||
@ -11279,7 +11281,6 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
int mcast_rate[NUM_NL80211_BANDS];
|
||||
u32 nla_rate;
|
||||
int err;
|
||||
|
||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
|
||||
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
|
||||
@ -11298,9 +11299,7 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
|
||||
if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = rdev_set_mcast_rate(rdev, dev, mcast_rate);
|
||||
|
||||
return err;
|
||||
return rdev_set_mcast_rate(rdev, dev, mcast_rate);
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
|
Loading…
Reference in New Issue
Block a user