766 lines
26 KiB
C
766 lines
26 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_P2PPS_C_
|
|
#include "phl_headers.h"
|
|
#ifdef RTW_WKARD_P2PPS_REFINE
|
|
#ifdef CONFIG_PHL_P2PPS
|
|
enum rtw_phl_status phl_p2pps_init(struct phl_info_t *phl)
|
|
{
|
|
enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
|
|
struct rtw_phl_com_t *phl_com = phl->phl_com;
|
|
struct rtw_phl_p2pps_info *info;
|
|
|
|
info = (struct rtw_phl_p2pps_info *)_os_mem_alloc(phl_to_drvpriv(phl),
|
|
sizeof(*info));
|
|
if (info == NULL)
|
|
return RTW_PHL_STATUS_RESOURCE;
|
|
_os_mem_set(phl_to_drvpriv(phl),
|
|
info, 0, sizeof(*info));
|
|
phl_com->p2pps_info = (void*)info;
|
|
info->phl_info = phl;
|
|
_os_spinlock_init(phl_to_drvpriv(phl), &info->p2pps_lock);
|
|
return status;
|
|
}
|
|
|
|
void phl_p2pps_deinit(struct phl_info_t *phl_info)
|
|
{
|
|
struct rtw_phl_com_t *phl_com = phl_info->phl_com;
|
|
struct rtw_phl_p2pps_info *info ;
|
|
info = (struct rtw_phl_p2pps_info *)phl_com->p2pps_info;
|
|
if (info) {
|
|
_os_spinlock_free(phl_to_drvpriv(phl_info), &info->p2pps_lock);
|
|
_os_mem_free(phl_to_drvpriv(phl_info), info, sizeof(*info));
|
|
}
|
|
phl_com->p2pps_info = NULL;
|
|
}
|
|
|
|
void
|
|
_phl_p2pps_dump_single_noa_desc(struct rtw_phl_noa_desc *desc)
|
|
{
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_single_noa_desc():enable = %d\n",
|
|
desc->enable);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_single_noa_desc():start_t_h = 0x%x\n",
|
|
desc->start_t_h);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_single_noa_desc():start_t_l = 0x%x\n",
|
|
desc->start_t_l);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_single_noa_desc():interval = %d\n",
|
|
desc->interval);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_single_noa_desc():duration = %d\n",
|
|
desc->duration);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_single_noa_desc():count = %d\n",
|
|
desc->count);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_single_noa_desc():noa_id = %d\n",
|
|
desc->noa_id);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_single_noa_desc():tag = %d\n",
|
|
desc->tag);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_single_noa_desc():w_role = 0x%p\n",
|
|
desc->w_role);
|
|
}
|
|
|
|
void
|
|
_phl_p2pps_dump_noa_table(struct rtw_phl_p2pps_info *psinfo,
|
|
struct rtw_phl_noa_info *info)
|
|
{
|
|
void *drvpriv = phlcom_to_drvpriv(psinfo->phl_info->phl_com);
|
|
struct rtw_phl_noa_desc *desc = NULL;
|
|
u8 i = 0;
|
|
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_noa_table():====>\n");
|
|
_os_spinlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA] info.en_desc_num = %d, pause = %d\n",
|
|
info->en_desc_num, info->paused);
|
|
for (i = 0; i < MAX_NOA_DESC; i++) {
|
|
desc = &info->noa_desc[i];
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]================DESC[%d]==================\n",
|
|
i);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_noa_table():enable = %d\n",
|
|
desc->enable);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_noa_table():start_t_h = 0x%x\n",
|
|
desc->start_t_h);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_noa_table():start_t_l = 0x%x\n",
|
|
desc->start_t_l);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_noa_table():interval = %d\n",
|
|
desc->interval);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_noa_table():duration = %d\n",
|
|
desc->duration);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_noa_table():count = %d\n",
|
|
desc->count);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_noa_table():noa_id = %d\n",
|
|
desc->noa_id);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_noa_table():tag = %d\n",
|
|
desc->tag);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_dump_noa_table():w_role = 0x%p\n",
|
|
desc->w_role);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]================DESC[%d]==================\n",
|
|
i);
|
|
}
|
|
_os_spinunlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
}
|
|
|
|
struct rtw_phl_noa_info *
|
|
_phl_p2pps_get_noa_info_by_role(struct rtw_phl_p2pps_info *psinfo,
|
|
struct rtw_wifi_role_t *wrole)
|
|
{
|
|
u8 idx = get_role_idx(wrole);
|
|
return &psinfo->noa_info[idx];
|
|
}
|
|
|
|
struct rtw_phl_noa_desc *
|
|
_phl_p2pps_get_first_noa_desc_with_cnt255(struct phl_info_t *phl,
|
|
struct rtw_phl_noa_info *info)
|
|
{
|
|
u8 i = 0;
|
|
|
|
struct rtw_phl_noa_desc *tmp_desc;
|
|
for (i = 0; i < MAX_NOA_DESC; i++) {
|
|
tmp_desc = &info->noa_desc[i];
|
|
if(tmp_desc->count == 255 && tmp_desc->enable) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_get_first_noa_desc_with_cnt255():get desc, tag = %d!!\n",
|
|
tmp_desc->tag);
|
|
return tmp_desc;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef RTW_WKARD_P2PPS_SINGLE_NOA
|
|
|
|
u8
|
|
_phl_p2pps_query_mcc_inprog_wkard(struct phl_info_t *phl_info,
|
|
struct rtw_wifi_role_t *w_role)
|
|
{
|
|
u8 ret = false;
|
|
#ifdef CONFIG_MCC_SUPPORT
|
|
//ret = phl_mr_query_mcc_inprogress(phl_info, w_role,
|
|
// RTW_PHL_MCC_CHK_INPROGRESS);
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
struct rtw_wifi_role_t *
|
|
_phl_get_role_by_band_port(struct phl_info_t* phl_info,
|
|
u8 hw_band,
|
|
u8 hw_port)
|
|
{
|
|
struct rtw_phl_com_t *phl_com = phl_info->phl_com;
|
|
struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
|
|
struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[hw_band]);
|
|
struct rtw_wifi_role_t *wrole = NULL;
|
|
u8 ridx = 0;
|
|
|
|
for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
|
|
if (!(band_ctrl->role_map & BIT(ridx)))
|
|
continue;
|
|
wrole = rtw_phl_get_wrole_by_ridx(phl_info->phl_com, ridx);
|
|
if (wrole == NULL)
|
|
continue;
|
|
if (wrole->hw_band == hw_band && wrole->hw_port == hw_port) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_get_role_by_band_port():role_id(%d) hw_band = %d, hw_port = %d\n",
|
|
ridx, wrole->hw_band, wrole->hw_port);
|
|
return wrole;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
_phl_p2pps_calc_next_noa_s_time(struct phl_info_t *phl_info,
|
|
struct rtw_wifi_role_t *w_role,
|
|
struct rtw_phl_tsf32_tog_rpt *rpt,
|
|
struct rtw_phl_noa_desc *orig_desc,
|
|
struct rtw_phl_noa_desc *new_desc)
|
|
{
|
|
void *d = phl_to_drvpriv(phl_info);
|
|
u64 new_st = 0, old_st = 0;
|
|
u64 tog_t = 0, delta_t = 0, intv_cnt = 0;
|
|
|
|
_os_mem_cpy(d, new_desc, orig_desc, sizeof(*orig_desc));
|
|
old_st = (((u64)orig_desc->start_t_h << 32) | orig_desc->start_t_l);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_calc_next_noa_s_time():old_st: 0x%08x %08x\n",
|
|
(u32)(old_st >> 32), (u32)old_st);
|
|
tog_t = (((u64)rpt->tsf_h << 32) | rpt->tsf_l);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_calc_next_noa_s_time():tog_t = 0x%08x %08x\n",
|
|
(u32)(tog_t >> 32), (u32)tog_t);
|
|
delta_t = tog_t - old_st;
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_calc_next_noa_s_time():delta_t = 0x%08x %08x\n",
|
|
(u32)(delta_t >> 32), (u32)delta_t);
|
|
intv_cnt = _os_division64(delta_t, new_desc->interval) + 1;
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_calc_next_noa_s_time():intv_cnt = 0x%08x %08x\n",
|
|
(u32)(intv_cnt >> 32), (u32)intv_cnt);
|
|
new_st = old_st + (intv_cnt * new_desc->interval);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_calc_next_noa_s_time():new_st = 0x%08x %08x\n",
|
|
(u32)(new_st >> 32), (u32)new_st);
|
|
new_desc->start_t_h = new_st >> 32;
|
|
new_desc->start_t_l = new_st & 0xFFFFFFFF;
|
|
}
|
|
|
|
void _phl_p2pps_ap_on_tsf32_tog(struct phl_info_t* phl_info,
|
|
struct rtw_wifi_role_t *wrole,
|
|
struct rtw_phl_tsf32_tog_rpt *rpt)
|
|
{
|
|
struct rtw_phl_p2pps_info *psinfo = phl_to_p2pps_info(phl_info);
|
|
struct rtw_phl_noa_info *info = NULL;
|
|
struct rtw_phl_noa_desc *orig_desc = NULL;
|
|
struct rtw_phl_noa_desc new_desc = {0};
|
|
void *d = phl_to_drvpriv(phl_info);
|
|
|
|
info = _phl_p2pps_get_noa_info_by_role(psinfo, wrole);
|
|
orig_desc = _phl_p2pps_get_first_noa_desc_with_cnt255(phl_info, info);
|
|
if (orig_desc) {
|
|
_phl_p2pps_calc_next_noa_s_time(phl_info, wrole, rpt,
|
|
orig_desc, &new_desc);
|
|
_os_mem_cpy(d, orig_desc, &new_desc, sizeof(new_desc));
|
|
_phl_p2pps_dump_single_noa_desc(&new_desc);
|
|
if(psinfo->ops.tsf32_tog_update_single_noa)
|
|
psinfo->ops.tsf32_tog_update_single_noa(d, wrole, &new_desc);
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void phl_p2pps_tsf32_tog_handler(struct phl_info_t* phl_info)
|
|
{
|
|
void *hal = phl_info->hal;
|
|
struct rtw_phl_tsf32_tog_rpt rpt = {0};
|
|
struct rtw_wifi_role_t *wrole = NULL;
|
|
enum rtw_hal_status h_stat;
|
|
|
|
h_stat = rtw_hal_get_tsf32_tog_rpt(hal, &rpt);
|
|
if (h_stat != RTW_HAL_STATUS_SUCCESS)
|
|
return;
|
|
if (!rpt.valid) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_WARNING_, "[NOA]phl_p2pps_tsf32_tog_handler():report not valid!!\n");
|
|
return;
|
|
}
|
|
wrole = _phl_get_role_by_band_port(phl_info, rpt.band, rpt.port);
|
|
if (wrole) {
|
|
if (wrole->type == PHL_RTYPE_AP) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]phl_p2pps_tsf32_tog_handler():role(%d) is AP/GO mode, handle noa update\n",
|
|
wrole->id);
|
|
#ifdef RTW_WKARD_P2PPS_SINGLE_NOA
|
|
_phl_p2pps_ap_on_tsf32_tog(phl_info, wrole, &rpt);
|
|
#endif
|
|
} else if (wrole->type == PHL_RTYPE_STATION) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]phl_p2pps_tsf32_tog_handler():role(%d) is STA/GO mode, currently do nothing\n",
|
|
wrole->id);
|
|
/*Call NoA disable all?*/
|
|
}
|
|
} else {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_WARNING_, "[NOA]phl_p2pps_tsf32_tog_handler():NULL ROLE!!, hwband = %d, hwport = %d\n",
|
|
rpt.band, rpt.port);
|
|
}
|
|
}
|
|
|
|
void
|
|
_phl_p2pps_copy_noa_desc(struct rtw_phl_p2pps_info *psinfo,
|
|
struct rtw_phl_noa_desc *dest,
|
|
struct rtw_phl_noa_desc *src)
|
|
{
|
|
void *drvpriv = phlcom_to_drvpriv(psinfo->phl_info->phl_com);
|
|
|
|
_os_spinlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
_os_mem_cpy(drvpriv, dest, src, sizeof(struct rtw_phl_noa_desc));
|
|
_os_spinunlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
}
|
|
|
|
void
|
|
_phl_p2pps_clear_noa_desc(struct rtw_phl_p2pps_info *psinfo,
|
|
struct rtw_phl_noa_desc *desc)
|
|
{
|
|
void *drvpriv = phlcom_to_drvpriv(psinfo->phl_info->phl_com);
|
|
|
|
_os_spinlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
_os_mem_set(drvpriv, desc, 0, sizeof(struct rtw_phl_noa_desc));
|
|
_os_spinunlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
}
|
|
|
|
void
|
|
_phl_p2pps_noa_increase_desc(struct rtw_phl_p2pps_info *psinfo,
|
|
struct rtw_phl_noa_info *info)
|
|
{
|
|
void *drvpriv = phlcom_to_drvpriv(psinfo->phl_info->phl_com);
|
|
|
|
_os_spinlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
info->en_desc_num++;
|
|
_os_spinunlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
}
|
|
|
|
void
|
|
_phl_p2pps_noa_decrease_desc(struct rtw_phl_p2pps_info *psinfo,
|
|
struct rtw_phl_noa_info *info)
|
|
{
|
|
void *drvpriv = phlcom_to_drvpriv(psinfo->phl_info->phl_com);
|
|
|
|
_os_spinlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
if (info->en_desc_num > 0)
|
|
info->en_desc_num--;
|
|
else
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_WARNING_, "[NOA]_phl_p2pps_noa_decrease_desc():info->en_desc_num == 0! Flow error\n");
|
|
_os_spinunlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
}
|
|
|
|
u8
|
|
_phl_p2pps_noa_should_activate(struct rtw_phl_p2pps_info *psinfo,
|
|
struct rtw_phl_noa_desc *in_desc)
|
|
{
|
|
u8 ret = true;
|
|
if (in_desc->tag == P2PPS_TRIG_GO) {
|
|
ret = true;
|
|
} else if (in_desc->tag == P2PPS_TRIG_GC) {
|
|
ret = true;
|
|
} else if (in_desc->tag == P2PPS_TRIG_GC_255) {
|
|
ret = true;
|
|
} else if (in_desc->tag == P2PPS_TRIG_2G_SCC_1AP_1STA_BT) {
|
|
ret = true;
|
|
} else if (in_desc->tag == P2PPS_TRIG_MCC) {
|
|
ret = false;
|
|
#ifdef RTW_WKARD_P2PPS_NOA_MCC
|
|
goto exit;
|
|
#endif
|
|
}
|
|
#ifdef RTW_WKARD_P2PPS_SINGLE_NOA
|
|
/*Currently should only notify MRC for limit request*/
|
|
/*Under count == 255 case */
|
|
if (in_desc->count != 255) {
|
|
if (_phl_p2pps_query_mcc_inprog_wkard(psinfo->phl_info,
|
|
in_desc->w_role)) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_WARNING_, "[NOA]_phl_p2pps_noa_should_activate():mcc in progress and noa requset != 255, currently not handling!\n");
|
|
ret = false;
|
|
}
|
|
} else {
|
|
/* open when mr ready*/
|
|
/*
|
|
if (phl_mr_noa_dur_lim_change(psinfo->phl_info,
|
|
in_desc->w_role, in_desc)) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_noa_should_activate():mrc take over this req!\n");
|
|
ret = false;
|
|
}
|
|
*/
|
|
}
|
|
#endif
|
|
exit:
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_noa_should_activate():tag = %d, return = %d\n",
|
|
in_desc->tag, ret);
|
|
return ret;
|
|
}
|
|
|
|
u8
|
|
_phl_p2pps_noa_is_all_disable(struct rtw_phl_p2pps_info *psinfo,
|
|
struct rtw_phl_noa_info *info)
|
|
{
|
|
u8 i = 0;
|
|
void *drvpriv = phlcom_to_drvpriv(psinfo->phl_info->phl_com);
|
|
_os_spinlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
for (i = 0; i < MAX_NOA_DESC; i++) {
|
|
struct rtw_phl_noa_desc *desc = &info->noa_desc[i];
|
|
if(desc->enable) {
|
|
_os_spinunlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
return false;
|
|
}
|
|
}
|
|
_os_spinunlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
return true;
|
|
}
|
|
|
|
u8
|
|
_phl_p2pps_noa_assign_noaid(struct rtw_phl_p2pps_info *psinfo,
|
|
struct rtw_phl_noa_info *info,
|
|
struct rtw_phl_noa_desc *desc)
|
|
{
|
|
u8 max = 0, id = NOAID_NONE, i = 0;
|
|
void *drvpriv = phlcom_to_drvpriv(psinfo->phl_info->phl_com);
|
|
|
|
_os_spinlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
if (info->en_desc_num == 0) {
|
|
id = 0;/*not inited flow*/
|
|
} else {
|
|
|
|
for (i = 0; i < MAX_NOA_DESC; i++) {
|
|
|
|
if (info->noa_desc[i].noa_id == NOAID_NONE)
|
|
continue;
|
|
if (info->noa_desc[i].noa_id > max)
|
|
max = info->noa_desc[i].noa_id;
|
|
}
|
|
if(max != 0)
|
|
id = max + 1;
|
|
else id = 0;
|
|
}
|
|
_os_spinunlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_noa_assign_noaid(): Final ID = %d.\n",
|
|
id);
|
|
return id;
|
|
}
|
|
|
|
enum rtw_phl_status
|
|
_phl_p2pps_noa_disable(struct rtw_phl_p2pps_info *psinfo,
|
|
struct rtw_phl_noa_info *noa_info,
|
|
struct rtw_phl_noa_desc *noa_desc,
|
|
u8 clear_desc)
|
|
{
|
|
enum rtw_phl_status ret = RTW_PHL_STATUS_FAILURE;
|
|
enum rtw_hal_status hal_ret = RTW_HAL_STATUS_FAILURE;
|
|
void *drvpriv = phlcom_to_drvpriv(psinfo->phl_info->phl_com);
|
|
void *hal = psinfo->phl_info->hal;
|
|
struct rtw_phl_stainfo_t *sta_info;
|
|
struct rtw_wifi_role_t *w_role = NULL;
|
|
struct phl_info_t *phl_info = psinfo->phl_info;
|
|
u8 en_to_fw = 0;
|
|
u8 idx = 0;
|
|
|
|
if (noa_info->paused && clear_desc) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_noa_disable():NoA info is in puase state, clear desc only!\n");
|
|
_phl_p2pps_clear_noa_desc(psinfo,noa_desc);
|
|
return RTW_PHL_STATUS_SUCCESS;
|
|
}
|
|
|
|
w_role = noa_desc->w_role;
|
|
|
|
_os_spinlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
en_to_fw = (noa_desc->noa_id != NOAID_NONE && noa_desc->enable);
|
|
_os_spinunlock(drvpriv, &psinfo->p2pps_lock, _bh, NULL);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NoA]%s(): en_to_fw(%d), clear_desc(%d)\n",
|
|
__func__, en_to_fw, clear_desc);
|
|
if (en_to_fw) {
|
|
sta_info = rtw_phl_get_stainfo_self(psinfo->phl_info,
|
|
noa_desc->w_role);
|
|
hal_ret = rtw_hal_noa_disable(hal, noa_info, noa_desc,
|
|
sta_info->macid);
|
|
if (hal_ret!= RTW_HAL_STATUS_SUCCESS) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_ERR_, "[NOA]_phl_p2pps_noa_disable():NoA Disable fail! tag = %d, ID = %d, HAL return = %d\n",
|
|
noa_desc->tag, noa_desc->noa_id, hal_ret);
|
|
ret = RTW_PHL_STATUS_FAILURE;
|
|
} else {
|
|
_phl_p2pps_noa_decrease_desc(psinfo,noa_info);
|
|
ret = RTW_PHL_STATUS_SUCCESS;
|
|
if (clear_desc)
|
|
_phl_p2pps_clear_noa_desc(psinfo,noa_desc);
|
|
}
|
|
} else {
|
|
/*not enabled to fw case*/
|
|
ret = RTW_PHL_STATUS_SUCCESS;
|
|
if (clear_desc)
|
|
_phl_p2pps_clear_noa_desc(psinfo,noa_desc);
|
|
}
|
|
|
|
if(RTW_PHL_STATUS_SUCCESS == ret) {
|
|
if(NULL != w_role) {
|
|
/* notify BTC */
|
|
/* copy noa_desc array to w_role*/
|
|
for (idx = 0; idx < MAX_NOA_DESC; idx ++) {
|
|
_phl_p2pps_copy_noa_desc(psinfo,
|
|
w_role->noa_desc + idx,
|
|
noa_info->noa_desc + idx);
|
|
}
|
|
phl_role_noa_notify(phl_info, w_role);
|
|
} else {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_WARNING_, "[NOA]_phl_p2pps_noa_disable():w_role in noa_desc is NULL, not to notify to BTC\n");
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void _phl_p2pps_noa_disable_all(struct phl_info_t *phl,
|
|
struct rtw_wifi_role_t *w_role)
|
|
{
|
|
struct rtw_phl_p2pps_info *psinfo = phl_to_p2pps_info(phl);
|
|
u8 role_id = get_role_idx(w_role);
|
|
struct rtw_phl_noa_info *noa_info = &psinfo->noa_info[role_id];
|
|
u8 i = 0;
|
|
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_noa_disable_all():====>\n");
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_noa_disable_all():Disable all NoA for wrole(%d)!\n",
|
|
role_id);
|
|
_phl_p2pps_dump_noa_table(phl_to_p2pps_info(phl),noa_info);
|
|
for (i = 0; i < MAX_NOA_DESC; i++) {
|
|
struct rtw_phl_noa_desc *desc = &noa_info->noa_desc[i];
|
|
if (desc->enable) {
|
|
_phl_p2pps_noa_disable(psinfo, noa_info, desc, true);
|
|
}
|
|
}
|
|
noa_info->paused = false;
|
|
_phl_p2pps_dump_noa_table(phl_to_p2pps_info(phl),noa_info);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_noa_disable_all():<====\n");
|
|
}
|
|
|
|
enum rtw_phl_status
|
|
_phl_p2pps_noa_enable(struct rtw_phl_p2pps_info *psinfo,
|
|
struct rtw_phl_noa_info *noa_info,
|
|
struct rtw_phl_noa_desc *noa_desc,
|
|
struct rtw_phl_noa_desc *in_desc)
|
|
{
|
|
enum rtw_phl_status ret = RTW_PHL_STATUS_FAILURE;
|
|
enum rtw_hal_status hal_ret = RTW_HAL_STATUS_FAILURE;
|
|
void *hal = psinfo->phl_info->hal;
|
|
struct rtw_phl_stainfo_t *sta_info;
|
|
struct rtw_wifi_role_t *w_role = NULL;
|
|
struct phl_info_t *phl_info = psinfo->phl_info;
|
|
u8 idx = 0;
|
|
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NoA]%s()\n",
|
|
__func__);
|
|
_phl_p2pps_copy_noa_desc(psinfo, noa_desc, in_desc);
|
|
|
|
/* get w_role */
|
|
w_role = noa_desc->w_role;
|
|
|
|
if(NULL != w_role) {
|
|
/* notify BTC */
|
|
/* copy noa_desc array to w_role */
|
|
for (idx = 0; idx < MAX_NOA_DESC; idx ++) {
|
|
_phl_p2pps_copy_noa_desc(psinfo,
|
|
w_role->noa_desc+idx,
|
|
noa_info->noa_desc+idx);
|
|
}
|
|
phl_role_noa_notify(phl_info, w_role);
|
|
} else {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_WARNING_, "[NOA]_phl_p2pps_noa_enable():w_role in noa_desc is NULL, not to notify to BTC\n");
|
|
}
|
|
|
|
if (noa_info->paused) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_noa_enable():NoA is in pause state, record request and leave\n");
|
|
return RTW_PHL_STATUS_SUCCESS;
|
|
}
|
|
if (_phl_p2pps_noa_should_activate(psinfo, noa_desc)) {
|
|
noa_desc->noa_id = _phl_p2pps_noa_assign_noaid(psinfo, noa_info,
|
|
noa_desc);
|
|
sta_info = rtw_phl_get_stainfo_self(psinfo->phl_info,
|
|
noa_desc->w_role);
|
|
hal_ret = rtw_hal_noa_enable(hal, noa_info, noa_desc,
|
|
sta_info->macid);
|
|
if (hal_ret != RTW_HAL_STATUS_SUCCESS) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_ERR_, "[NOA]_phl_p2pps_noa_enable():NoA enable fail! tag = %d, ID = %d, HAL return = %d\n",
|
|
noa_desc->tag, noa_desc->noa_id, hal_ret);
|
|
noa_desc->noa_id = NOAID_NONE;
|
|
if (hal_ret == RTW_HAL_STATUS_RESOURCE)
|
|
ret = RTW_PHL_STATUS_RESOURCE;
|
|
else
|
|
ret = RTW_PHL_STATUS_FAILURE;
|
|
} else {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]_phl_p2pps_noa_enable():NoA enable SUCCESS! tag = %d, ID = %d, HAL return = %d\n",
|
|
noa_desc->tag, noa_desc->noa_id, hal_ret);
|
|
_phl_p2pps_noa_increase_desc(psinfo,noa_info);
|
|
|
|
ret = RTW_PHL_STATUS_SUCCESS;
|
|
}
|
|
} else {
|
|
noa_desc->noa_id = NOAID_NONE; /*not activate*/
|
|
ret = RTW_PHL_STATUS_SUCCESS;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
phl_p2pps_noa_resume_all(struct phl_info_t *phl,
|
|
struct rtw_wifi_role_t *w_role)
|
|
{
|
|
struct rtw_phl_p2pps_info *psinfo = phl_to_p2pps_info(phl);
|
|
u8 role_idx = get_role_idx(w_role);
|
|
struct rtw_phl_noa_info *noa_info = &psinfo->noa_info[role_idx];
|
|
u8 i = 0;
|
|
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]phl_p2pps_noa_resume_all():====>\n");
|
|
if (!noa_info->paused) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]phl_p2pps_noa_resume_all():NoA not paused on role:%d\n",
|
|
w_role->id);
|
|
goto exit;
|
|
}
|
|
// _phl_p2pps_dump_noa_table(phl_to_p2pps_info(phl),noa_info);
|
|
noa_info->paused = false;
|
|
for (i = 0; i < MAX_NOA_DESC; i++) {
|
|
struct rtw_phl_noa_desc *desc = &noa_info->noa_desc[i];
|
|
if(desc->enable)
|
|
_phl_p2pps_noa_enable(psinfo, noa_info, desc, desc);
|
|
}
|
|
// _phl_p2pps_dump_noa_table(phl_to_p2pps_info(phl),noa_info);
|
|
exit:
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]phl_p2pps_noa_resume_all():<====\n");
|
|
}
|
|
|
|
void
|
|
phl_p2pps_noa_all_role_resume(struct phl_info_t *phl_info, u8 band_idx)
|
|
{
|
|
struct rtw_phl_com_t *phl_com = phl_info->phl_com;
|
|
struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
|
|
struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[band_idx]);
|
|
struct rtw_wifi_role_t *wrole = NULL;
|
|
u8 ridx = 0;
|
|
|
|
for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
|
|
if (!(band_ctrl->role_map & BIT(ridx)))
|
|
continue;
|
|
wrole = rtw_phl_get_wrole_by_ridx(phl_info->phl_com, ridx);
|
|
if (wrole == NULL)
|
|
continue;
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]p2pps_noa_all_role_resume():role_id(%d)\n",
|
|
ridx);
|
|
phl_p2pps_noa_resume_all(phl_info, wrole);
|
|
}
|
|
}
|
|
|
|
void
|
|
phl_p2pps_noa_pause_all(struct phl_info_t *phl,
|
|
struct rtw_wifi_role_t *w_role)
|
|
{
|
|
struct rtw_phl_p2pps_info *psinfo = phl_to_p2pps_info(phl);
|
|
u8 role_idx = get_role_idx(w_role);
|
|
struct rtw_phl_noa_info *noa_info = &psinfo->noa_info[role_idx];
|
|
u8 i = 0;
|
|
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]phl_p2pps_noa_pause_all():====>\n");
|
|
//_phl_p2pps_dump_noa_table(phl_to_p2pps_info(phl),noa_info);
|
|
if (noa_info->paused) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]phl_p2pps_noa_pause_all():This role(%d) NoA is in pause state\n",
|
|
role_idx);
|
|
goto exit;
|
|
}
|
|
noa_info->paused = true;
|
|
for (i = 0; i < MAX_NOA_DESC; i++) {
|
|
struct rtw_phl_noa_desc *desc = &noa_info->noa_desc[i];
|
|
_phl_p2pps_noa_disable(psinfo, noa_info, desc, false);
|
|
}
|
|
//_phl_p2pps_dump_noa_table(phl_to_p2pps_info(phl),noa_info);
|
|
exit:
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]phl_p2pps_noa_pause_all():<====\n");
|
|
}
|
|
|
|
void phl_p2pps_noa_all_role_pause(struct phl_info_t *phl_info, u8 band_idx)
|
|
{
|
|
struct rtw_phl_com_t *phl_com = phl_info->phl_com;
|
|
struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
|
|
struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[band_idx]);
|
|
struct rtw_wifi_role_t *wrole = NULL;
|
|
u8 ridx = 0;
|
|
|
|
for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
|
|
if (!(band_ctrl->role_map & BIT(ridx)))
|
|
continue;
|
|
wrole = rtw_phl_get_wrole_by_ridx(phl_info->phl_com, ridx);
|
|
if (wrole == NULL)
|
|
continue;
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]phl_p2pps_noa_all_role_pause():role_id(%d)\n",
|
|
ridx);
|
|
phl_p2pps_noa_pause_all(phl_info, wrole);
|
|
}
|
|
}
|
|
|
|
void phl_p2pps_noa_disable_all(struct phl_info_t *phl_info,
|
|
struct rtw_wifi_role_t *w_role)
|
|
{
|
|
#ifdef RTW_WKARD_P2PPS_SINGLE_NOA
|
|
struct rtw_phl_noa_desc dis_desc = {0};
|
|
/*for notify MR for limitation disabled*/
|
|
dis_desc.enable = false;
|
|
dis_desc.w_role = w_role;
|
|
/*open when mr ready*/
|
|
//phl_mr_noa_dur_lim_change(phl_info, w_role, &dis_desc);
|
|
#endif
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]phl_p2pps_noa_disable_all():====>\n");
|
|
_phl_p2pps_noa_disable_all(phl_info, w_role);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]phl_p2pps_noa_disable_all():Disable TSF 32 TOG for role %d\n",
|
|
w_role->id);
|
|
rtw_hal_tsf32_tog_disable(phl_info->hal, w_role);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]phl_p2pps_noa_disable_all():<====\n");
|
|
}
|
|
|
|
void phl_p2pps_query_noa_with_cnt255(struct phl_info_t* phl_info,
|
|
struct rtw_wifi_role_t *w_role, struct rtw_phl_noa_desc *desc)
|
|
{
|
|
struct rtw_phl_p2pps_info *psinfo = phl_to_p2pps_info(phl_info);
|
|
u8 role_idx = get_role_idx(w_role);
|
|
struct rtw_phl_noa_info *info = &psinfo->noa_info[role_idx];
|
|
struct rtw_phl_noa_desc *tmp_desc = NULL;
|
|
|
|
tmp_desc = _phl_p2pps_get_first_noa_desc_with_cnt255(phl_info, info);
|
|
if (tmp_desc) {
|
|
_phl_p2pps_copy_noa_desc(psinfo, desc, tmp_desc);
|
|
} else {
|
|
desc->enable = false;
|
|
desc->w_role = w_role;
|
|
}
|
|
}
|
|
|
|
enum rtw_phl_status
|
|
rtw_phl_p2pps_noa_update(void *phl,
|
|
struct rtw_phl_noa_desc *in_desc)
|
|
{
|
|
enum rtw_phl_status ret= RTW_PHL_STATUS_FAILURE;
|
|
struct phl_info_t *phl_info = (struct phl_info_t *)phl;
|
|
struct rtw_phl_p2pps_info *psinfo = phl_to_p2pps_info(phl_info);
|
|
struct rtw_wifi_role_t *w_role = in_desc->w_role;
|
|
u8 role_id = get_role_idx(w_role);
|
|
struct rtw_phl_noa_info *noa_info = &psinfo->noa_info[role_id];
|
|
u8 desc_idx = in_desc->tag;
|
|
struct rtw_phl_noa_desc *noa_desc = &noa_info->noa_desc[desc_idx];
|
|
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]rtw_phl_p2pps_noa_update():DUMP BEFORE!\n");
|
|
_phl_p2pps_dump_noa_table(psinfo, noa_info);
|
|
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]rtw_phl_p2pps_noa_update():cur FW en desc num = %d\n",
|
|
noa_info->en_desc_num);
|
|
if (in_desc->enable) {
|
|
if (_phl_p2pps_noa_is_all_disable(psinfo, noa_info)) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]rtw_phl_p2pps_noa_update():roleid(%d) Enable TSF 32 Toggle!\n",
|
|
role_id);
|
|
rtw_hal_tsf32_tog_enable(phl_info->hal, in_desc->w_role);
|
|
/*todo set TSF_ BIT TOG H2C ON*/
|
|
}
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]rtw_phl_p2pps_noa_update():Tag = %d, NoA enable request!\n",
|
|
in_desc->tag);
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]rtw_phl_p2pps_noa_update():Tag = %d, NoA disable origninl req first!\n",
|
|
in_desc->tag);
|
|
_phl_p2pps_noa_disable(psinfo, noa_info, noa_desc, true);
|
|
ret = _phl_p2pps_noa_enable(psinfo, noa_info, noa_desc,
|
|
in_desc);
|
|
} else {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]rtw_phl_p2pps_noa_update():Tag = %d, NoA disable request!\n",
|
|
in_desc->tag);
|
|
ret = _phl_p2pps_noa_disable(psinfo, noa_info, noa_desc, true);
|
|
if (_phl_p2pps_noa_is_all_disable(psinfo, noa_info)) {
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]rtw_phl_p2pps_noa_update():roleid(%d) Disable TSF 32 Toggle!\n",
|
|
role_id);
|
|
rtw_hal_tsf32_tog_disable(phl_info->hal, in_desc->w_role);
|
|
/*todo set TSF_ BIT TOG H2C OFF*/
|
|
}
|
|
}
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]rtw_phl_p2pps_noa_update():DUMP AFTER!\n");
|
|
_phl_p2pps_dump_noa_table(psinfo, noa_info);
|
|
return ret;
|
|
}
|
|
|
|
void rtw_phl_p2pps_noa_disable_all(void *phl,
|
|
struct rtw_wifi_role_t *w_role)
|
|
{
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "[NOA]rtw_phl_p2pps_noa_disable_all()!\n");
|
|
phl_p2pps_noa_disable_all((struct phl_info_t *)phl, w_role);
|
|
}
|
|
|
|
void rtw_phl_p2pps_init_ops(void *phl,
|
|
struct rtw_phl_p2pps_ops *ops)
|
|
{
|
|
struct phl_info_t *phl_info = (struct phl_info_t *)phl;
|
|
struct rtw_phl_p2pps_info *psinfo = NULL;
|
|
|
|
psinfo = phl_to_p2pps_info(phl_info);
|
|
psinfo->ops.priv = ops->priv;
|
|
psinfo->ops.tsf32_tog_update_noa = ops->tsf32_tog_update_noa;
|
|
psinfo->ops.tsf32_tog_update_single_noa = ops->tsf32_tog_update_single_noa;
|
|
PHL_TRACE(COMP_PHL_P2PPS, _PHL_INFO_, "rtw_phl_p2pps_init_ops(): init ok\n");
|
|
}
|
|
#endif
|
|
#endif
|