/****************************************************************************** * * Copyright(c) 2007 - 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. * * The full GNU General Public License is included in this distribution in the * file called LICENSE. * * Contact Information: * wlanfae * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, * Hsinchu 300, Taiwan. * * Larry Finger * *****************************************************************************/ #include "halbb_precomp.h" void halbb_supportability_dbg(struct bb_info *bb, char input[][16], u32 *_used, char *output, u32 *_out_len) { u32 val[10] = {0}; u64 pre_support_ability, one = 1; u64 comp = 0; u32 used = *_used; u32 out_len = *_out_len; u8 i; for (i = 0; i < 5; i++) { if (input[i + 1]) HALBB_SCAN(input[i + 1], DCMD_DECIMAL, &val[i]); } pre_support_ability = bb->support_ability; comp = bb->support_ability; BB_DBG_CNSL(out_len, used, output + used, out_len - used, "\n================================\n"); if (val[0] == 100) { BB_DBG_CNSL(out_len, used, output + used, out_len - used, "[Supportability] Selection\n"); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "================================\n"); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "00. (( %s ))RA\n", ((comp & BB_RA) ? ("V") : ("."))); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "01. (( %s ))FA_CNT\n", ((comp & BB_FA_CNT) ? ("V") : ("."))); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "02. (( %s ))RSSI_MNTR\n", ((comp & HALBB_FUN_RSVD_2) ? ("V") : ("."))); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "03. (( %s ))DFS\n", ((comp & BB_DFS) ? ("V") : ("."))); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "04. (( %s ))EDCCA\n", ((comp & BB_EDCCA) ? ("V") : ("."))); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "05. (( %s ))ENV_MNTR\n", ((comp & BB_ENVMNTR) ? ("V") : ("."))); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "06. (( %s ))CFO_TRK\n", ((comp & BB_CFO_TRK) ? ("V") : ("."))); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "07. (( %s ))PWR_CTRL\n", ((comp & BB_PWR_CTRL) ? ("V") : ("."))); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "10. (( %s ))ANT_DIV\n", ((comp & DBG_ANT_DIV) ? ("V") : ("."))); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "11. (( %s ))DIG\n", ((comp & BB_DIG) ? ("V") : ("."))); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "13. (( %s ))UL_TB_CTRL\n", ((comp & BB_UL_TB_CTRL) ? ("V") : ("."))); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "31. (( %s ))Dyn CSI RSP\n", ((comp & BB_DCR) ? ("V") : ("."))); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "================================\n"); } else if (val[0] == 101) { bb->support_ability = 0; BB_DBG_CNSL(out_len, used, output + used, out_len - used, "Disable all support_ability components\n"); } else { if (val[1] == 1) { /* @enable */ bb->support_ability |= (one << val[0]); } else if (val[1] == 2) {/* @disable */ bb->support_ability &= ~(one << val[0]); } else { BB_DBG_CNSL(out_len, used, output + used, out_len - used, "[Warning!!!] 1:enable, 2:disable\n"); } } BB_DBG_CNSL(out_len, used, output + used, out_len - used, "pre-supportability = 0x%llx\n", pre_support_ability); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "Cur-supportability = 0x%llx\n", bb->support_ability); BB_DBG_CNSL(out_len, used, output + used, out_len - used, "================================\n"); *_used = used; *_out_len = out_len; } bool halbb_sta_info_init(struct bb_info *bb, struct rtw_phl_stainfo_t *phl_sta_info) { struct bb_sta_info *bb_sta; if (!bb) { BB_WARNING("[%s]*bb = NULL\n", __func__); return false; } if (!phl_sta_info) return false; if (!phl_sta_info->hal_sta) return false; bb_sta = halbb_mem_alloc(bb, sizeof(struct bb_sta_info)); if (!bb_sta) { BB_WARNING("*bb_sta = NULL\n"); return RTW_HAL_STATUS_BB_INIT_FAILURE; } phl_sta_info->hal_sta->bb_sta = (void *)bb_sta; return true; } bool halbb_sta_info_deinit(struct bb_info *bb, struct rtw_phl_stainfo_t *phl_sta_info) { if (!bb) { BB_WARNING("*bb = NULL\n"); return false; } if (!phl_sta_info) return false; if (!phl_sta_info->hal_sta) return false; if (!phl_sta_info->hal_sta->bb_sta) return false; halbb_mem_free(bb, phl_sta_info->hal_sta->bb_sta, sizeof(struct bb_sta_info)); return true; } bool halbb_sta_info_add_entry(struct bb_info *bb, struct rtw_phl_stainfo_t *phl_sta_info) { if (!bb) { BB_WARNING("[%s]*bb = NULL\n", __func__); return false; } if (!phl_sta_info) return false; if ((phl_sta_info->macid) >= PHL_MAX_STA_NUM) return false; bb->phl2bb_macid_table[phl_sta_info->macid] = (u8)phl_sta_info->macid; bb->phl_sta_info[phl_sta_info->macid] = phl_sta_info; return true; } bool halbb_sta_info_delete_entry(struct bb_info *bb, struct rtw_phl_stainfo_t *phl_sta_info) { if (!bb) { BB_WARNING("*bb = NULL\n"); return false; } if (!phl_sta_info) return false; if ((phl_sta_info->macid) >= PHL_MAX_STA_NUM) return false; if (!phl_sta_info->hal_sta) return false; if (!phl_sta_info->hal_sta->bb_sta) return false; bb->sta_exist[phl_sta_info->macid] = false; bb->phl_sta_info[phl_sta_info->macid] = NULL; return true; } void halbb_media_status_update(struct bb_info *bb, struct rtw_phl_stainfo_t *phl_sta_info, bool is_connected) { bb->sta_exist[phl_sta_info->macid] = is_connected; /*Reset MA RSSI*/ if (!is_connected) { phl_sta_info->hal_sta->rssi_stat.rssi = 0; phl_sta_info->hal_sta->rssi_stat.rssi_ma = 0; phl_sta_info->hal_sta->rssi_stat.rssi_ma_path[0] = 0; phl_sta_info->hal_sta->rssi_stat.rssi_ma_path[1] = 0; phl_sta_info->hal_sta->rssi_stat.rssi_ma_path[2] = 0; phl_sta_info->hal_sta->rssi_stat.rssi_ma_path[3] = 0; phl_sta_info->hal_sta->rssi_stat.pkt_cnt_data = 0; phl_sta_info->hal_sta->rssi_stat.rssi_bcn = 0; phl_sta_info->hal_sta->rssi_stat.rssi_bcn_ma = 0; phl_sta_info->hal_sta->rssi_stat.rssi_bcn_ma_path[0] = 0; phl_sta_info->hal_sta->rssi_stat.rssi_bcn_ma_path[1] = 0; phl_sta_info->hal_sta->rssi_stat.rssi_bcn_ma_path[2] = 0; phl_sta_info->hal_sta->rssi_stat.rssi_bcn_ma_path[3] = 0; phl_sta_info->hal_sta->rssi_stat.pkt_cnt_bcn = 0; phl_sta_info->hal_sta->rssi_stat.rssi_ofdm = 0; phl_sta_info->hal_sta->rssi_stat.rssi_cck = 0; phl_sta_info->hal_sta->rssi_stat.snr_ma = 0; } else { phl_sta_info->hal_sta->rssi_stat.ma_factor = RSSI_MA_L; phl_sta_info->hal_sta->rssi_stat.ma_factor_bcn = RSSI_MA_L; } } void halbb_sta_info_dbg(struct bb_info *bb, char input[][16], u32 *_used, char *output, u32 *_out_len) { struct rtw_hal_com_t *hal = bb->hal_com; struct rtw_phl_stainfo_t *phl_sta; struct rtw_rssi_info *rssi_t = NULL; struct rtw_ra_sta_info *ra; char dbg_buf[HALBB_SNPRINT_SIZE] = {0}; u32 val[10] = {0}; u32 tmp = 0; u16 curr_tx_rt = 0; u8 i = 0, j = 0; if (_os_strcmp(input[1], "-h") == 0) { BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "all\n"); return; } if (_os_strcmp(input[1], "all") == 0) { BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, " Assoc_sta_cnt=%d\n\n", hal->assoc_sta_cnt); for (i = 0; i < PHL_MAX_STA_NUM; i++) { if (!bb->sta_exist[i]) continue; phl_sta = bb->phl_sta_info[i]; if (!is_sta_active(phl_sta)) continue; BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "[%d][active=%d] PHL_macid=%d =====================\n", i, phl_sta->active, phl_sta->macid); rssi_t = &phl_sta->hal_sta->rssi_stat; halbb_print_sign_frac_digit(bb, rssi_t->rssi_ma, 16, 5, dbg_buf, HALBB_SNPRINT_SIZE_S); BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "[Data] rssi_avg=%s, MA=1/%02d\n", dbg_buf, 1 << rssi_t->ma_factor); for (j = 0; j < HALBB_MAX_PATH; j++) { halbb_print_sign_frac_digit(bb, rssi_t->rssi_ma_path[j], 16, 5, dbg_buf, HALBB_SNPRINT_SIZE_S); BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, " rssi[%d]= %s\n", j, dbg_buf); } halbb_print_sign_frac_digit(bb, rssi_t->rssi_bcn_ma, 16, 5, dbg_buf, HALBB_SNPRINT_SIZE_S); BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "[Bcn] rssi_avg=%s, MA=1/%02d\n", dbg_buf, 1 << rssi_t->ma_factor_bcn); for (j = 0; j < HALBB_MAX_PATH; j++) { halbb_print_sign_frac_digit(bb, rssi_t->rssi_bcn_ma_path[j], 16, 5, dbg_buf, HALBB_SNPRINT_SIZE_S); BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, " rssi[%d]= %s\n", j, dbg_buf); } BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "rssi_cck=%02d.%d, rssi_ofdm=%02d.%d\n", rssi_t->rssi_cck >> 1, (rssi_t->rssi_cck & 1) * 5, rssi_t->rssi_ofdm >> 1, (rssi_t->rssi_ofdm & 1) * 5); halbb_print_sign_frac_digit(bb, rssi_t->snr_ma, 16, 4, dbg_buf, HALBB_SNPRINT_SIZE_S); BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "SNR_avg=%s dB\n", dbg_buf); ra = &phl_sta->hal_sta->ra_info; curr_tx_rt = (u16)(ra->rpt_rt_i.mcs_ss_idx) | ((u16)(ra->rpt_rt_i.mode) << 7); halbb_print_rate_2_buff(bb, curr_tx_rt, ra->rpt_rt_i.gi_ltf, bb->dbg_buf, HALBB_SNPRINT_SIZE); BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "Tx_Rate=%s (0x%x-%d), PER=(%d), TXBW=(%d)\n", bb->dbg_buf, curr_tx_rt, ra->rpt_rt_i.gi_ltf, ra->curr_retry_ratio, (20 << ra->rpt_rt_i.bw)); BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "======================================\n"); } } } void halbb_traffic_load_decision(struct bb_info *bb) { struct rtw_stats *stat = &bb->phl_com->phl_stats; struct bb_link_info *link = &bb->bb_link_i; u32 max_tp; /*Mbps*/ /*@---TP & Trafic-load caln---*/ link->tx_tp = KB_2_MB(stat->tx_tp_kbits); link->rx_tp = KB_2_MB(stat->rx_tp_kbits); link->total_tp = link->tx_tp + link->rx_tp; max_tp = MAX_2(link->tx_tp, link->rx_tp); /*Mbps*/ BB_DBG(bb, DBG_COMMON_FLOW, "byte_uni{tx,rx}={%llu,%llu}, byte_total{tx,rx}={%llu,%llu}\n", stat->tx_byte_uni, stat->rx_byte_uni, stat->tx_byte_total, stat->rx_byte_total); BB_DBG(bb, DBG_COMMON_FLOW, "TP_kbit{tx,rx}={%d,%d}, TP_MA{tx,rx}={%d,%d}\n", stat->tx_tp_kbits, stat->rx_tp_kbits, stat->tx_moving_average_tp, stat->rx_moving_average_tp); /*@[Calculate TX/RX state]*/ if (link->tx_tp > (link->rx_tp << 1)) link->txrx_state_all = BB_TX_STATE; else if (link->rx_tp > (link->tx_tp << 1)) link->txrx_state_all = BB_RX_STATE; else link->txrx_state_all = BB_BI_DIR_STATE; /*@[Traffic load decision]*/ link->traffic_load_pre = link->traffic_load; if (max_tp > 20) { link->traffic_load = TRAFFIC_HIGH; } else if (max_tp > 5) { link->traffic_load = TRAFFIC_MID; } else if (max_tp > 1) { link->traffic_load = TRAFFIC_LOW; } else if (stat->tx_tp_kbits > 100 || stat->rx_tp_kbits > 100) { /*100Kb*/ link->traffic_load = TRAFFIC_ULTRA_LOW; } else { link->traffic_load = TRAFFIC_NO_TP; } /*@[Calculate consecutive idlel time]*/ if (link->traffic_load == TRAFFIC_NO_TP) link->consecutive_idle_time = 0; else link->consecutive_idle_time += HALBB_WATCHDOG_PERIOD; } void halbb_cmn_info_self_reset(struct bb_info *bb) { struct bb_link_info *link = &bb->bb_link_i; bb->bb_ch_i.rssi_max = 0; bb->bb_ch_i.rssi_min = 0; link->is_one_entry_only = false; link->one_entry_macid = 0; link->one_entry_tp = 0; link->one_entry_tp_active_occur = false; link->one_entry_tp_pre = 0; link->num_linked_client_pre = 0; link->num_active_client_pre = 0; link->num_linked_client = 0; link->num_active_client = 0; } u8 halbb_get_rssi_min(struct bb_info *bb) { struct rtw_hal_com_t *hal = bb->hal_com; struct rtw_phl_stainfo_t *sta; struct rtw_rssi_info *sta_rssi = NULL; u8 sta_cnt = 0; u8 rssi_min = 0xff, rssi_curr = 0; u32 i = 0; if (hal->assoc_sta_cnt == 0) { BB_WARNING("[%s] assoc_sta_cnt=0\n", __func__); return 0; } for (i = 0; i < PHL_MAX_STA_NUM; i++) { if (!bb->sta_exist[i]) continue; sta = bb->phl_sta_info[i]; if (!is_sta_active(sta)) continue; BB_DBG(bb, DBG_COMMON_FLOW, "[%d] macid=%d\n", i, sta->macid); sta_cnt++; sta_rssi = &sta->hal_sta->rssi_stat; if (sta_rssi->rssi != 0) rssi_curr = sta_rssi->rssi; else rssi_curr = sta_rssi->rssi_bcn; /*[RSSI min]*/ if (rssi_curr <= rssi_min) { rssi_min = rssi_curr; } BB_DBG(bb, DBG_COMMON_FLOW, "rssi_min = %d", rssi_min); if (sta_cnt >= hal->assoc_sta_cnt) break; } if (sta_cnt == 0) { BB_WARNING("[%s] sta_cnt=0\n", __func__); return 0; } return rssi_min; } void halbb_cmn_info_self_update(struct bb_info *bb) { struct rtw_hal_com_t *hal = bb->hal_com; struct bb_link_info *link = &bb->bb_link_i; struct rtw_phl_com_t *phl = bb->phl_com; struct dev_cap_t *dev = &phl->dev_cap; struct rtw_phl_stainfo_t *sta; struct rtw_rssi_info *sta_rssi = NULL; struct halbb_mcc_dm *mcc_dm = &bb->mcc_dm; u8 sta_cnt = 0, num_active_client = 0; u8 rssi_min = 0xff, rssi_max = 0, rssi_curr = 0; u8 mcc_rssi_min[MCC_BAND_NUM], mcc_sta_cnt[MCC_BAND_NUM]; u8 j = 0, band_idx = MCC_BAND_NUM, role_ch = 0; u32 i = 0, one_entry_macid_tmp = 0; u32 trx_tp = 0; u32 tp_diff = 0; /*[Link Status Check]*/ link->is_linked = (hal->assoc_sta_cnt != 0) ? true : false; link->first_connect = link->is_linked && !link->is_linked_pre; link->first_disconnect = !link->is_linked && link->is_linked_pre; link->is_linked_pre = link->is_linked; BB_DBG(bb, DBG_COMMON_FLOW, "is_linked = %d, 1st_connect=%d, 1st_disconnect=%d, assoc_sta_cnt=%d\n", link->is_linked, link->first_connect, link->first_disconnect, hal->assoc_sta_cnt); /*[Traffic load information]*/ halbb_traffic_load_decision(bb); link->rx_rate_plurality = halbb_get_plurality_rx_rate_su(bb); link->rx_rate_plurality_mu = halbb_get_plurality_rx_rate_mu(bb); if (!link->is_linked) { if (link->first_disconnect) halbb_cmn_info_self_reset(bb); return; } if (mcc_dm->mcc_status_en) { for (i = 0; i < MCC_BAND_NUM; i++) { mcc_rssi_min[i] = rssi_min; mcc_sta_cnt[i] = 0; } } bb->bb_ch_i.pre_rssi_min = bb->bb_ch_i.rssi_min; for (i = 0; i < PHL_MAX_STA_NUM; i++) { if (!bb->sta_exist[i]) continue; sta = bb->phl_sta_info[i]; if (!is_sta_active(sta)) continue; if ((dev->rfe_type >= 50) && (sta->macid == 0)) continue; BB_DBG(bb, DBG_COMMON_FLOW, "[%d] macid=%d\n", i, sta->macid); sta_cnt++; if (sta_cnt == 1) one_entry_macid_tmp = i; trx_tp = KB_2_MB(sta->stats.tx_tp_kbits + sta->stats.rx_tp_kbits); /*Mbit*/ sta_rssi = &sta->hal_sta->rssi_stat; if (bb->bb_watchdog_mode != BB_WATCHDOG_NORMAL) { rssi_curr = sta_rssi->rssi_bcn; } else { if (sta_rssi->rssi == 0 && sta_rssi->rssi_bcn != 0) rssi_curr = sta_rssi->rssi_bcn; else rssi_curr = sta_rssi->rssi; } if (sta_rssi->pkt_cnt_data > 100) sta_rssi->ma_factor = RSSI_MA_H; else if (sta_rssi->pkt_cnt_data > 20) sta_rssi->ma_factor = RSSI_MA_M; else if (sta_rssi->pkt_cnt_data > 5) sta_rssi->ma_factor = RSSI_MA_L; else sta_rssi->ma_factor = RSSI_MA_UL; if (sta_rssi->pkt_cnt_bcn > 5) sta_rssi->ma_factor_bcn = RSSI_MA_L; else sta_rssi->ma_factor_bcn = RSSI_MA_UL; BB_DBG(bb, DBG_COMMON_FLOW, "pkt_cnt_data=%d, pkt_cnt_bcn=%d, ma_factor=%d, ma_factor_bcn=%d\n", sta_rssi->pkt_cnt_data, sta_rssi->pkt_cnt_bcn, sta_rssi->ma_factor, sta_rssi->ma_factor_bcn); sta_rssi->pkt_cnt_data = 0; sta_rssi->pkt_cnt_bcn = 0; BB_DBG(bb, DBG_COMMON_FLOW, "rssi = %d, rssi_ma = %d", sta->hal_sta->rssi_stat.rssi, sta->hal_sta->rssi_stat.rssi_ma); /*[RSSI min]*/ if (rssi_curr <= rssi_min) { bb->bb_ch_i.rssi_min = rssi_curr; bb->bb_ch_i.rssi_min_macid = sta->macid; rssi_min = rssi_curr; } /*[RSSI max]*/ if (rssi_curr >= rssi_max) { bb->bb_ch_i.rssi_max = rssi_curr; bb->bb_ch_i.rssi_max_macid = sta->macid; rssi_max = rssi_curr; } //BB_DBG(bb, DBG_COMMON_FLOW, "TP: TRX=%d Mb/sec\n", trx_tp); //BB_DBG(bb, DBG_COMMON_FLOW, "TP: TX=%d, RX=%d, kb/sec\n", // sta->stats.tx_tp_kbits, sta->stats.rx_tp_kbits); BB_DBG(bb, DBG_COMMON_FLOW, "rssi_min = %d, rssi_max = %d", rssi_min, rssi_max); if (mcc_dm->mcc_status_en) { if (i == mcc_dm->softap_macid) continue; band_idx = MCC_BAND_NUM; role_ch = sta->wrole->chandef.center_ch; for (j = 0; j < MCC_BAND_NUM; j++) { if (mcc_dm->mcc_rf_ch[j].center_ch == role_ch) { band_idx = j; break; } } if (band_idx == MCC_BAND_NUM) { BB_WARNING("%s, band_idx = %d", __func__, band_idx); continue; } if (rssi_curr <= mcc_rssi_min[band_idx]) mcc_rssi_min[band_idx] = rssi_curr; mcc_sta_cnt[band_idx]++; } if (trx_tp > ACTIVE_TP_THRESHOLD) num_active_client++; if (sta_cnt >= bb->hal_com->assoc_sta_cnt) break; } if (mcc_dm->mcc_status_en) { for (i = 0; i < MCC_BAND_NUM; i++) { mcc_dm->rssi_min[i] = mcc_rssi_min[i]; mcc_dm->sta_cnt[i] = mcc_sta_cnt[i]; } } link->is_one_entry_only = (hal->assoc_sta_cnt == 1) ? true : false; if (link->is_one_entry_only) { link->one_entry_macid = one_entry_macid_tmp; link->one_entry_tp = trx_tp; link->one_entry_tp_active_occur = false; //BB_DBG(bb, DBG_COMMON_FLOW, "one_entry_tp=((%d)), one_entry_tp_pre=((%d))\n", // link->one_entry_tp, link->one_entry_tp_pre); if (link->one_entry_tp > link->one_entry_tp_pre && link->one_entry_tp_pre <= 2) { tp_diff = link->one_entry_tp - link->one_entry_tp_pre; if (tp_diff > link->tp_active_th) link->one_entry_tp_active_occur = true; } link->one_entry_tp_pre = link->one_entry_tp; } link->num_linked_client_pre = link->num_linked_client; link->num_active_client_pre = link->num_active_client; link->num_linked_client = sta_cnt; link->num_active_client = num_active_client; } void halbb_watchdog_reset(struct bb_info *bb) { } void halbb_update_hal_info(struct bb_info *bb) { struct rtw_hal_com_t *hal = bb->hal_com; hal->trx_stat.rx_rate_plurality = bb->bb_link_i.rx_rate_plurality; } void halbb_store_data(struct bb_info *bb) { halbb_cmn_info_rpt_store_data(bb); } void halbb_reset(struct bb_info *bb) { halbb_store_data(bb); #ifdef HALBB_STATISTICS_SUPPORT halbb_statistics_reset(bb); #endif halbb_cmn_info_rpt_reset(bb); } void halbb_watchdog_normal(struct bb_info *bb, enum phl_phy_idx phy_idx) { halbb_cmn_info_self_update(bb); halbb_ic_hw_setting(bb); #ifdef HALBB_ENV_MNTR_SUPPORT halbb_env_mntr(bb); #endif #ifdef HALBB_DIG_SUPPORT halbb_dig(bb); #endif #ifdef HALBB_STATISTICS_SUPPORT halbb_statistics(bb); #endif halbb_basic_dbg_message(bb); halbb_physts_watchdog(bb); if (!bb->adv_bb_dm_en) { BB_DBG(bb, DBG_COMMON_FLOW, "Disable adv halbb dm\n"); halbb_reset(bb); return; } #ifdef HALBB_EDCCA_SUPPORT halbb_edcca(bb); #endif #ifdef HALBB_DFS_SUPPORT halbb_dfs(bb); #endif #ifdef HALBB_CFO_TRK_SUPPORT halbb_cfo_watchdog(bb); #endif #ifdef HALBB_UL_TB_CTRL_SUPPORT halbb_ul_tb_ctrl(bb); #endif #ifdef HALBB_RA_SUPPORT halbb_ra_watchdog(bb); #endif #ifdef HALBB_PWR_CTRL_SUPPORT halbb_pwr_ctrl(bb); #endif #ifdef HALBB_LA_MODE_SUPPORT halbb_la_re_trig_watchdog(bb); #endif #ifdef HALBB_ANT_DIV_SUPPORT halbb_antenna_diversity(bb); #endif halbb_update_hal_info(bb); #ifdef HALBB_DIG_MCC_SUPPORT halbb_mccdm_switch(bb); #endif /*[Rest all counter]*/ halbb_reset(bb); } void halbb_watchdog_low_io(struct bb_info *bb, enum phl_phy_idx phy_idx) { halbb_cmn_info_self_update(bb); halbb_ic_hw_setting_low_io(bb); halbb_basic_dbg_message(bb); #ifdef HALBB_DIG_SUPPORT halbb_dig_lps(bb); #endif #ifdef HALBB_RA_SUPPORT halbb_ra_watchdog(bb); #endif #if 0//def HALBB_EDCCA_SUPPORT halbb_edcca(bb); #endif #if 0//def HALBB_DFS_SUPPORT halbb_dfs(bb); #endif /*[Rest all counter]*/ halbb_reset(bb); } void halbb_watchdog_non_io(struct bb_info *bb, enum phl_phy_idx phy_idx) { halbb_cmn_info_self_update(bb); halbb_ic_hw_setting_non_io(bb); halbb_basic_dbg_message(bb); /*[Rest all counter]*/ halbb_reset(bb); } void halbb_watchdog(struct bb_info *bb, enum bb_watchdog_mode_t mode, enum phl_phy_idx phy_idx) { #ifdef HALBB_DBCC_SUPPORT #ifdef HALBB_DBCC_DVLP_FLAG if (phy_idx == HW_PHY_1) return; #endif bb = halbb_get_curr_bb_pointer(bb, phy_idx); BB_DBG(bb, DBG_COMMON_FLOW, "[%s] phy_idx=%d\n", __func__, bb->bb_phy_idx); #endif bb->bb_sys_up_time += BB_WATCH_DOG_PERIOD; if ((bb->bb_sys_up_time % bb->bb_watchdog_period) != 0) return; if (bb->bb_dbg_i.cr_recorder_en) BB_TRACE("[%s] up_time:%d \n", __func__, bb->bb_sys_up_time); bb->bb_watchdog_mode = mode; BB_DBG(bb, DBG_COMMON_FLOW, "mode=%s\n", ((mode == BB_WATCHDOG_NORMAL) ? "Normal" : ((mode == BB_WATCHDOG_LOW_IO) ? "LowIO" : "NonIO"))); /*=== [HALBB Watchdog] ===============================================*/ if (mode == BB_WATCHDOG_NORMAL) { if(phl_is_mp_mode(bb->phl_com)) { BB_WARNING("[%s] mode=%d", __func__, bb->phl_com->drv_mode); return; } halbb_watchdog_normal(bb, phy_idx); } else if (mode == BB_WATCHDOG_LOW_IO) { halbb_watchdog_low_io(bb, phy_idx); } else { /*if (mode == BB_WATCHDOG_NON_IO)*/ halbb_watchdog_non_io(bb, phy_idx); } if (bb->bb_dbg_i.cr_recorder_en) BB_TRACE("[%s] end\n", __func__); } void halbb_bb_cmd_notify(struct bb_info *bb, void *bb_cmd, enum phl_phy_idx phy_idx) { enum halbb_event_idx_t event_idx = *((enum halbb_event_idx_t *)bb_cmd); BB_DBG(bb, DBG_COMMON_FLOW, "[%s][phy_idx=%d] event_idx=%d\n", __func__, phy_idx, event_idx); if (event_idx == BB_EVENT_TIMER_DIG) { #ifdef HALBB_DIG_TDMA_SUPPORT halbb_tdmadig_io_en(bb); #endif } else if (event_idx == BB_EVENT_TIMER_CFO) { #ifdef HALBB_CFO_TRK_SUPPORT halbb_cfo_acc_io_en(bb); #endif } else if (event_idx == BB_EVENT_TIMER_ANTDIV) { #ifdef HALBB_ANT_DIV_SUPPORT halbb_antdiv_io_en(bb); #endif } else if (event_idx == BB_EVENT_TIMER_TDMA_CR) { #ifdef HALBB_TDMA_CR_SUPPORT halbb_tdma_cr_sel_io_en(bb); #endif } else if (event_idx == BB_EVENT_TIMER_LA) { #ifdef HALBB_LA_MODE_SUPPORT halbb_la_io_en(bb); #endif } else { BB_WARNING("[%s] event_idx=%d\n", __func__, event_idx); } } u8 halbb_pause_func(struct bb_info *bb, enum habb_fun_t pause_func, enum halbb_pause_type pause_type, enum halbb_pause_lv_type lv, u8 val_lehgth, u32 *val_buf) { struct bb_func_hooker_info *func_t = &bb->bb_cmn_hooker->bb_func_hooker_i; s8 *pause_lv_pre = &bb->u8_dummy; u32 *bkp_val = &bb->u32_dummy; u32 ori_val[5] = {0}; u64 pause_func_bitmap = (u64)BIT(pause_func); u8 i = 0; u8 pause_result = PAUSE_FAIL; BB_DBG(bb, DBG_DBG_API, "[%s][%s] LV=%d, Len=%d\n", __func__, ((pause_type == HALBB_PAUSE) ? "Pause" : ((pause_type == HALBB_RESUME) ? "Resume" : ((pause_type == HALBB_PAUSE_NO_SET) ? "Pause no_set" : "Resume_no_recovery"))), lv, val_lehgth); if (lv >= HALBB_PAUSE_MAX_NUM) { BB_WARNING("[%s] LV=%d\n", __func__, lv); return PAUSE_FAIL; } if (pause_func == F_CFO_TRK) { BB_DBG(bb, DBG_DBG_API, "[CFO]\n"); if (val_lehgth > 1) { BB_WARNING("CFO length > 1\n"); return PAUSE_FAIL; } ori_val[0] = (u32)(bb->bb_cfo_trk_i.crystal_cap); //which value? pause_lv_pre = &bb->pause_lv_table.lv_cfo; bkp_val = (u32 *)(&bb->bb_cfo_trk_i.rvrt_val); /*@function pointer hook*/ func_t->pause_bb_dm_handler = halbb_set_cfo_pause_val; } #ifdef HALBB_DIG_SUPPORT else if (pause_func == F_DIG) { BB_DBG(bb, DBG_DBG_API, "[DIG]\n"); if (val_lehgth > DIG_PAUSE_INFO_SIZE) { BB_WARNING("DIG length > %d\n", DIG_PAUSE_INFO_SIZE); return PAUSE_FAIL; } /* {equivalent_rssi, en_pause_by_igi, en_pause_by_pd_low} */ ori_val[0] = (u32)(RSSI_MAX - bb->bb_dig_i.p_cur_dig_unit->igi_fa_rssi); ori_val[1] = val_buf[1]; pause_lv_pre = &bb->pause_lv_table.lv_dig; bkp_val = (u32 *)(&bb->bb_dig_i.rvrt_val); /*@function pointer hook*/ func_t->pause_bb_dm_handler = halbb_set_dig_pause_val; } #endif #ifdef HALBB_EDCCA_SUPPORT else if (pause_func == F_EDCCA) { BB_DBG(bb, DBG_DBG_API, "[EDCCA]\n"); if (val_lehgth > 1) { BB_WARNING("EDCCA length > 1\n"); return PAUSE_FAIL; } ori_val[0] = (u32)(bb->bb_edcca_i.th_h); pause_lv_pre = &bb->pause_lv_table.lv_edcca; bkp_val = (u32 *)(&bb->bb_edcca_i.rvrt_val); /*@function pointer hook*/ func_t->pause_bb_dm_handler = halbb_set_edcca_pause_val; } #endif else { BB_WARNING("Error func idx\n"); return PAUSE_FAIL; } BB_DBG(bb, DBG_DBG_API, "Pause_LV{new , pre} = {%d ,%d}\n", lv, *pause_lv_pre); if (pause_type == HALBB_PAUSE || pause_type == HALBB_PAUSE_NO_SET) { if (lv <= *pause_lv_pre) { BB_DBG(bb, DBG_DBG_API, "[PAUSE FAIL] Pre_LV >= Curr_LV\n"); return PAUSE_FAIL; } if (!(bb->pause_ability & pause_func_bitmap)) { for (i = 0; i < val_lehgth; i++) bkp_val[i] = ori_val[i]; } bb->pause_ability |= pause_func_bitmap; BB_DBG(bb, DBG_DBG_API, "pause_ability=0x%llx\n", bb->pause_ability); if (pause_type == HALBB_PAUSE) { for (i = 0; i < val_lehgth; i++) BB_DBG(bb, DBG_DBG_API, "[PAUSE SUCCESS] val_idx[%d]{New, Ori}={0x%x, 0x%x}\n", i, val_buf[i], bkp_val[i]); func_t->pause_bb_dm_handler(bb, val_buf, val_lehgth); } else { for (i = 0; i < val_lehgth; i++) BB_DBG(bb, DBG_DBG_API, "[PAUSE NO Set: SUCCESS] val_idx[%d]{Ori}={0x%x}\n", i, bkp_val[i]); } *pause_lv_pre = lv; pause_result = PAUSE_SUCCESS; } else if (pause_type == HALBB_RESUME) { if (lv < *pause_lv_pre) { BB_DBG(bb, DBG_DBG_API, "[Resume FAIL] Pre_LV >= Curr_LV\n"); return PAUSE_FAIL; } if ((bb->pause_ability & pause_func_bitmap) == 0) { BB_DBG(bb, DBG_DBG_API, "[RESUME] No Need to Revert\n"); return PAUSE_SUCCESS; } bb->pause_ability &= ~pause_func_bitmap; BB_DBG(bb, DBG_DBG_API, "pause_ability=0x%llx\n", bb->pause_ability); *pause_lv_pre = HALBB_PAUSE_RELEASE; for (i = 0; i < val_lehgth; i++) { BB_DBG(bb, DBG_DBG_API, "[RESUME] val_idx[%d]={0x%x}\n", i, bkp_val[i]); } func_t->pause_bb_dm_handler(bb, bkp_val, val_lehgth); pause_result = PAUSE_SUCCESS; } else if (pause_type == HALBB_RESUME_NO_RECOVERY) { if (lv < *pause_lv_pre) { BB_DBG(bb, DBG_DBG_API, "[Resume FAIL] Pre_LV >= Curr_LV\n"); return PAUSE_FAIL; } if ((bb->pause_ability & pause_func_bitmap) == 0) { BB_DBG(bb, DBG_DBG_API, "[RESUME] No Need to Revert\n"); return PAUSE_SUCCESS; } bb->pause_ability &= ~pause_func_bitmap; BB_DBG(bb, DBG_DBG_API, "pause_ability=0x%llx\n", bb->pause_ability); *pause_lv_pre = HALBB_PAUSE_RELEASE; pause_result = PAUSE_SUCCESS; } else { BB_WARNING("error pause_type\n"); pause_result = PAUSE_FAIL; } return pause_result; } void halbb_pause_func_dbg(struct bb_info *bb, char input[][16], u32 *_used, char *output, u32 *_out_len) { u32 val[10] = {0}; u32 i; u8 len = 0; u32 buf[5] = {0}; u8 pause_result = 0; enum halbb_pause_type type = 0; enum halbb_pause_lv_type lv = 0; u8 halbb_ary_size = bb->bb_cmn_hooker->bb_dm_number; enum habb_fun_t id = F_DEFAULT; /* ==== [Help] ====]*/ if (_os_strcmp(input[1], "-h") == 0) { BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "{Func} {p:pause, pn:pause_no_set, r:Resume, rnc: Resume_no_recov} {lv:0~3} Val[0],...,Val[5]\n"); BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "{dig} {p/pn/r} {lv} {Pwr(|dBm|),hex} {0:apply to ofdm, 1:apply to cck and ofdm}\n"); for (i = 0; i < halbb_ary_size; i++) BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "*%s\n", halbb_func_i[i].name); return; } /* ==== [Function] ====]*/ for (i = 0; i < halbb_ary_size; i++) { if (_os_strcmp(halbb_func_i[i].name, input[1]) == 0) { id = halbb_func_i[i].id; BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "[%s]===>\n", halbb_func_i[i].name); break; } } if (i == halbb_ary_size) { BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "Func not found!\n"); return; } /* ==== [Type] ====]*/ if (_os_strcmp(input[2], "p") == 0) { type = HALBB_PAUSE; } else if (_os_strcmp(input[2], "pn") == 0) { type = HALBB_PAUSE_NO_SET; } else if (_os_strcmp(input[2], "r") == 0) { type = HALBB_RESUME; } else if (_os_strcmp(input[2], "rnc") == 0) { type = HALBB_RESUME_NO_RECOVERY; } else { BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "Set Err\n"); return; } for (i = 1; i < 10; i++) { HALBB_SCAN(input[i + 1], DCMD_HEX, &val[i]); } lv = (enum halbb_pause_lv_type)val[2]; for (i = 0; i < 5; i++) buf[i] = val[3 + i]; if (id == F_CFO_TRK) { len = 1; } else if (id == F_DIG) { len = DIG_PAUSE_INFO_SIZE; } else if (id == F_EDCCA) { len = 1; } else { return; } if (len) { BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "{%s in lv=%d}, pause_val = {%d, %d}\n", ((type == HALBB_PAUSE) ? "Pause" : ((type == HALBB_RESUME) ? "Resume" : "Pause no set")), lv, val[3], val[4]); pause_result = halbb_pause_func(bb, id, type, lv, len, buf); } BB_DBG_CNSL(*_out_len, *_used, output + *_used, *_out_len - *_used, "Set %s\n", (pause_result) ? "Success" : "Fail"); }