Files
linux-nv-oot/drivers/net/wireless/realtek/rtl8852ce/phl/phl_thermal.c
Shobek Attupurath 7dd632ff96 rtl8852ce: Add base driver v1.19.16.1-0-g1fe335ba1.20240815_PC
- support Android-14
- support Linux kernel 6.9
- support 6G regulation
- support Thermal protection
- support TX shortcut to reduce CPU loading
- fix some coverity issues
- Use RTW regulatory version rtk_8852CE_M.2_2230-67-52
- default enable con-current and MCC

Bug 4667769
Bug 4667981

Change-Id: Iee069ecdd1f00a0b78285d0a4ef5778ed9ace478
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3195601
Tested-by: Shobek Attupurath <sattupurath@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
2025-07-24 10:19:08 +00:00

179 lines
4.8 KiB
C

/******************************************************************************
*
* Copyright(c) 2020 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#define _PHL_THERMAL_C_
#include "phl_headers.h"
#ifdef CONFIG_PHL_THERMAL_PROTECT
static void _phl_thermal_protect_disable_all_txop(
struct phl_info_t *phl_info,
bool disable)
{
struct rtw_phl_com_t *phl_com = phl_info->phl_com;
struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
struct rtw_wifi_role_t *wrole = NULL;
struct rtw_wifi_role_link_t *rlink = NULL;
struct rtw_phl_mld_t *mld = NULL;
struct rtw_phl_stainfo_t *sta = NULL;
struct rtw_edca_param edca = {0};
u8 i = 0;
u8 idx = 0;
for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++) {
if (mr_ctl->role_map & BIT(i)) {
wrole = phl_get_wrole_by_ridx(phl_info, i);
if(wrole){
if(wrole->mstate == MLME_LINKED)
break;
}
wrole = NULL;
continue;
}
}
if(wrole == NULL)
return;
mld = rtw_phl_get_mld_self(phl_info, wrole);
for (idx = 0; idx < wrole->rlink_num; idx++) {
rlink = get_rlink(wrole, idx);
sta = mld->phl_sta[idx];
if(sta == NULL)
return;
for(i = 0; i < 4;i++){
edca.ac = i;
edca.param = sta->asoc_cap.edca[edca.ac].param;
if(disable)
edca.param &= 0x0000FFFF;
if(rtw_hal_set_edca(phl_info->hal, rlink, edca.ac, edca.param)
!= RTW_HAL_STATUS_SUCCESS)
PHL_ERR("%s Config edca fail\n", __FUNCTION__);
}
}
}
static void _phl_thermal_protect_reduce_ampdu_num(
struct phl_info_t *phl_info,
u8 ratio)
{
struct rtw_phl_com_t *phl_com = phl_info->phl_com;
struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
struct rtw_wifi_role_t *wrole = NULL;
struct rtw_phl_mld_t *mld = NULL;
struct rtw_phl_stainfo_t *sta = NULL;
u8 i = 0;
u8 idx = 0;
for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++) {
if (mr_ctl->role_map & BIT(i)) {
wrole = phl_get_wrole_by_ridx(phl_info, i);
if(wrole){
if(wrole->mstate == MLME_LINKED)
break;
}
wrole = NULL;
continue;
}
}
if(wrole == NULL)
return;
mld = rtw_phl_get_mld_self(phl_info, wrole);
for (idx = 0; idx < wrole->rlink_num; idx++) {
sta = mld->phl_sta[idx];
if(sta == NULL)
return;
if(ratio != 0){
if(rtw_hal_thermal_protect_cfg_tx_ampdu(phl_info->hal, sta, ratio)
!= RTW_HAL_STATUS_SUCCESS)
PHL_ERR("%s Thermal protect cfg tx ampdu fail\n", __FUNCTION__);
}
else{
if(sta->asoc_cap.num_ampdu_bk != 0){
sta->asoc_cap.num_ampdu = sta->asoc_cap.num_ampdu_bk;
sta->asoc_cap.num_ampdu_bk = 0;
}
if(rtw_hal_cfg_tx_ampdu(phl_info->hal, sta) !=
RTW_HAL_STATUS_SUCCESS)
PHL_ERR("%s Thermal protect restore tx ampdu fail\n", __FUNCTION__);
}
}
}
void phl_thermal_protect_watchdog(struct phl_info_t *phl_info)
{
struct rtw_phl_com_t *phl_com = phl_info->phl_com;
bool action_changed = false;
u8 min_tx_duty = phl_com->dev_cap.min_tx_duty;
u8 next_tx_duty = THERMAL_NO_TX_DUTY_CTRL;
u8 duty_interval = 1;
if (min_tx_duty == THERMAL_NO_TX_DUTY_CTRL)
return;
if(phl_com->drv_mode != RTW_DRV_MODE_NORMAL &&
phl_com->drv_mode != RTW_DRV_MODE_HIGH_THERMAL)
return;
action_changed = rtw_hal_check_thermal_protect(phl_com, phl_info->hal);
if(action_changed == false)
return;
duty_interval = (THERMAL_NO_TX_DUTY_CTRL - min_tx_duty) / PHL_THERMAL_PROTECT_ACTION_LEVEL_MAX;
if (duty_interval == 0)
duty_interval = 1;
if (phl_com->thermal_protect_action == PHL_THERMAL_PROTECT_ACTION_NONE) {
phl_thermal_protect_stop_tx_duty(phl_info);
} else {
next_tx_duty = THERMAL_TX_DUTY_CTRL_DURATION - (duty_interval * (u8)phl_com->thermal_protect_action);
if (next_tx_duty >= min_tx_duty)
phl_thermal_protect_cfg_tx_duty(phl_info,
THERMAL_TX_DUTY_CTRL_DURATION,
next_tx_duty);
}
}
#endif /* CONFIG_PHL_THERMAL_PROTECT */
void phl_thermal_protect_cfg_tx_duty(
struct phl_info_t *phl_info,
u16 tx_duty_interval,
u8 ratio)
{
enum rtw_hal_status hal_status = RTW_HAL_STATUS_SUCCESS;
hal_status = rtw_hal_thermal_protect_cfg_tx_duty(phl_info->hal,
tx_duty_interval,
ratio);
if(hal_status != RTW_HAL_STATUS_SUCCESS)
PHL_ERR("%s Thermal protect cfg tx duty fail\n", __FUNCTION__);
}
void phl_thermal_protect_stop_tx_duty(struct phl_info_t *phl_info)
{
enum rtw_hal_status hal_status = RTW_HAL_STATUS_SUCCESS;
hal_status = rtw_hal_thermal_protect_stop_tx_duty(phl_info->hal);
if(hal_status != RTW_HAL_STATUS_SUCCESS)
PHL_ERR("%s Thermal protect stop tx duty fail\n", __FUNCTION__);
}