/****************************************************************************** * * 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_DM_C_ #include "phl_headers.h" void rtw_phl_set_edcca_mode(void *phl, enum rtw_edcca_mode mode) { struct phl_info_t *phl_info = (struct phl_info_t *)phl; PHL_INFO("[Cert], set phl_com edcca_mode : %d !! \n", mode); phl_info->phl_com->edcca_mode = mode; } enum rtw_edcca_mode rtw_phl_get_edcca_mode(void *phl) { struct phl_info_t *phl_info = (struct phl_info_t *)phl; return phl_info->phl_com->edcca_mode; } #ifdef CONFIG_PCI_HCI #ifdef RTW_WKARD_DYNAMIC_LTR enum rtw_phl_status phl_ltr_sw_trigger(struct rtw_phl_com_t *phl_com, void *hal, enum rtw_pcie_ltr_state state) { enum rtw_hal_status status = RTW_HAL_STATUS_FAILURE; struct bus_sw_cap_t *sw_cap = &phl_com->bus_sw_cap; status = rtw_hal_ltr_sw_trigger(hal, state); if (status == RTW_HAL_STATUS_SUCCESS) { sw_cap->ltr_cur_state = state; sw_cap->ltr_last_trigger_time = _os_get_cur_time_us(); state == RTW_PCIE_LTR_SW_ACT ? sw_cap->ltr_sw_act_tri_cnt++ : sw_cap->ltr_sw_idle_tri_cnt++; return RTW_PHL_STATUS_SUCCESS; } else { return RTW_PHL_STATUS_FAILURE; } } /* Switching sw ctrl will trigger active ltr at the same time to prevent inconsistent state */ /* usage : echo phl ltr set [enable/disable] */ enum rtw_phl_status phl_ltr_sw_ctrl(struct rtw_phl_com_t *phl_com, void *hal, bool enable) { enum rtw_hal_status status = RTW_HAL_STATUS_FAILURE; status = phl_ltr_sw_trigger(phl_com, hal, RTW_PCIE_LTR_SW_ACT); if (status == RTW_HAL_STATUS_SUCCESS) { phl_com->bus_sw_cap.ltr_sw_ctrl = enable; return RTW_PHL_STATUS_SUCCESS; } else { return RTW_PHL_STATUS_FAILURE; } } /* switch to hw control. it's valid that only hw supports hw mode */ /* usage : echo phl ltr set [enable/disable] */ void phl_ltr_hw_ctrl(struct rtw_phl_com_t *phl_com, bool enable) { phl_com->bus_sw_cap.ltr_hw_ctrl = enable; } /* For pm module, this will not trigger active ltr since halmac will take care of*/ void phl_ltr_sw_ctrl_ntfy(struct rtw_phl_com_t *phl_com, bool enable) { phl_com->bus_sw_cap.ltr_sw_ctrl = enable; } u8 phl_ltr_get_cur_state(struct rtw_phl_com_t *phl_com) { return phl_com->bus_sw_cap.ltr_cur_state; } u32 phl_ltr_get_last_trigger_time(struct rtw_phl_com_t *phl_com) { return phl_com->bus_sw_cap.ltr_last_trigger_time; } u32 phl_ltr_get_tri_cnt(struct rtw_phl_com_t *phl_com, enum rtw_pcie_ltr_state state) { struct bus_sw_cap_t *sw_cap = &phl_com->bus_sw_cap; return state == RTW_PCIE_LTR_SW_ACT ? sw_cap->ltr_sw_act_tri_cnt : sw_cap->ltr_sw_idle_tri_cnt; } #define TP_MBPS 100 void phl_ltr_ctrl_watchdog(struct phl_info_t *phl_info) { struct rtw_phl_com_t *phl_com = phl_info->phl_com; struct rtw_stats *sts = &phl_com->phl_stats; u32 tx_tp_m = 0, rx_tp_m = 0; static bool start = false; /* only valid if it's currenlty running hw mode */ if (!rtw_hal_ltr_is_hw_ctrl(phl_com, phl_info->hal)) return; tx_tp_m = sts->tx_tp_kbits >> 10; rx_tp_m = sts->rx_tp_kbits >> 10; /* PHL_INFO("%s tx_tp_m = %u /rx_tp_m = %u \n", __func__, tx_tp_m, rx_tp_m);*/ if ((tx_tp_m > TP_MBPS || rx_tp_m > TP_MBPS) && !start) { start = true; rtw_hal_ltr_en_hw_mode(phl_info->hal, false); rtw_hal_ltr_sw_trigger(phl_info->hal, RTW_PCIE_LTR_SW_ACT); } if (start && tx_tp_m < TP_MBPS && rx_tp_m < TP_MBPS) { start = false; rtw_hal_ltr_en_hw_mode(phl_info->hal, true); } } #endif /* RTW_WKARD_DYNAMIC_LTR */ #endif /* CONFIG_PCI_HCI */