android13/external/wifi_driver/rtl8822es/hal/hal_pwr_table.c

729 lines
20 KiB
C

/******************************************************************************
*
* Copyright(c) 2007 - 2022 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 _HAL_PWR_TABLE_C_
#include <drv_types.h>
#include <hal_data.h>
#if CONFIG_TXPWR_LIMIT
const char *const _txpwr_lmt_rs_str[] = {
[TXPWR_LMT_RS_CCK] = "CCK",
[TXPWR_LMT_RS_OFDM] = "OFDM",
[TXPWR_LMT_RS_HT] = "HT",
[TXPWR_LMT_RS_VHT] = "VHT",
[TXPWR_LMT_RS_NUM] = "UNKNOWN",
};
void hal_txpwr_lmt_reg_exc_add_with_nlen(struct hal_com_data *hal_data, const char *country, u8 domain, const char *reg_name, u32 nlen)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
struct lmt_reg_exc *ent;
if (!reg_name || !nlen) {
rtw_warn_on(1);
goto exit;
}
ent = rtw_zmalloc(sizeof(struct lmt_reg_exc) + nlen + 1);
if (!ent)
goto exit;
_rtw_init_listhead(&ent->list);
if (country)
_rtw_memcpy(ent->country, country, 2);
ent->domain = domain;
_rtw_memcpy(ent->reg_name, reg_name, nlen);
_rtw_mutex_lock_interruptible(&tb->lock);
rtw_list_insert_tail(&ent->list, &tb->reg_exc_list);
tb->reg_exc_num++;
_rtw_mutex_unlock(&tb->lock);
exit:
return;
}
void hal_txpwr_lmt_reg_exc_add(struct hal_com_data *hal_data, const char *country, u8 domain, const char *reg_name)
{
hal_txpwr_lmt_reg_exc_add_with_nlen(hal_data, country, domain, reg_name, strlen(reg_name));
}
static struct lmt_reg_exc *_hal_txpwr_lmt_reg_exc_search(struct hal_com_data *hal_data, const char *country, u8 domain)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
struct lmt_reg_exc *ent;
_list *cur, *head;
u8 match = 0;
head = &tb->reg_exc_list;
cur = get_next(head);
while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
u8 has_country;
ent = LIST_CONTAINOR(cur, struct lmt_reg_exc, list);
cur = get_next(cur);
has_country = (ent->country[0] == '\0' && ent->country[1] == '\0') ? 0 : 1;
/* entry has country condition to match */
if (has_country) {
if (!country)
continue;
if (ent->country[0] != country[0]
|| ent->country[1] != country[1])
continue;
}
/* entry has domain condition to match */
if (ent->domain != 0xFF) {
if (domain == 0xFF)
continue;
if (ent->domain != domain)
continue;
}
match = 1;
break;
}
if (match)
return ent;
else
return NULL;
}
struct lmt_reg_exc *hal_txpwr_lmt_reg_exc_search(struct hal_com_data *hal_data, const char *country, u8 domain)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
struct lmt_reg_exc *ent;
_rtw_mutex_lock_interruptible(&tb->lock);
ent = _hal_txpwr_lmt_reg_exc_search(hal_data, country, domain);
_rtw_mutex_unlock(&tb->lock);
return ent;
}
void hal_txpwr_lmt_reg_exc_list_free(struct hal_com_data *hal_data)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
struct lmt_reg_exc *ent;
_list *cur, *head;
_rtw_mutex_lock_interruptible(&tb->lock);
head = &tb->reg_exc_list;
cur = get_next(head);
while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
ent = LIST_CONTAINOR(cur, struct lmt_reg_exc, list);
cur = get_next(cur);
rtw_list_delete(&ent->list);
rtw_mfree((u8 *)ent, sizeof(struct lmt_reg_exc) + strlen(ent->reg_name) + 1);
}
tb->reg_exc_num = 0;
_rtw_mutex_unlock(&tb->lock);
}
static void _dump_txpwr_lmt_reg_exc_list(void *sel, struct hal_com_data *hal_data)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
struct lmt_reg_exc *ent;
_list *cur, *head;
RTW_PRINT_SEL(sel, "reg_exc_num:%u\n", tb->reg_exc_num);
if (!tb->reg_exc_num)
goto exit;
RTW_PRINT_SEL(sel, "%-7s %-6s %-8s\n", "country", "domain", "reg_name");
head = &tb->reg_exc_list;
cur = get_next(head);
while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
u8 has_country;
ent = LIST_CONTAINOR(cur, struct lmt_reg_exc, list);
cur = get_next(cur);
has_country = (ent->country[0] == '\0' && ent->country[1] == '\0') ? 0 : 1;
RTW_PRINT_SEL(sel, " %c%c 0x%02x %s\n"
, has_country ? ent->country[0] : '-'
, has_country ? ent->country[1] : '-'
, ent->domain
, ent->reg_name
);
}
exit:
return;
}
void dump_txpwr_lmt_reg_exc_list(void *sel, struct hal_com_data *hal_data)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
_rtw_mutex_lock_interruptible(&tb->lock);
_dump_txpwr_lmt_reg_exc_list(sel, hal_data);
_rtw_mutex_unlock(&tb->lock);
}
/* search matcing first, if not found, alloc one */
void hal_txpwr_lmt_reg_add_with_nlen(struct hal_com_data *hal_data, const char *name, u32 nlen
, u8 band, u8 bw, u8 tlrs, u8 ntx_idx, u8 ch_idx, s8 lmt)
{
struct hal_spec_t *hal_spec = &hal_data->hal_spec;
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
struct lmt_reg *ent;
_list *cur, *head;
s8 pre_lmt;
u8 ch;
if (!name || !nlen) {
rtw_warn_on(1);
goto exit;
}
_rtw_mutex_lock_interruptible(&tb->lock);
/* search for existed entry */
head = &tb->reg_list;
cur = get_next(head);
while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
ent = LIST_CONTAINOR(cur, struct lmt_reg, list);
cur = get_next(cur);
if (strlen(ent->name) == nlen
&& _rtw_memcmp(ent->name, name, nlen) == _TRUE)
goto chk_lmt_val;
}
/* alloc new one */
ent = rtw_zvmalloc(sizeof(struct lmt_reg) + nlen + 1);
if (!ent)
goto release_lock;
_rtw_init_listhead(&ent->list);
_rtw_memcpy(ent->name, name, nlen);
{
u8 j, k, l, m;
for (j = 0; j < MAX_2_4G_BANDWIDTH_NUM; ++j)
for (k = 0; k < TXPWR_LMT_RS_NUM_2G; ++k)
for (m = 0; m < CENTER_CH_2G_NUM; ++m)
for (l = 0; l < MAX_TX_COUNT; ++l)
ent->lmt_2g[j][k][m][l] = hal_spec->txgi_max;
#if CONFIG_IEEE80211_BAND_5GHZ
for (j = 0; j < MAX_5G_BANDWIDTH_NUM; ++j)
for (k = 0; k < TXPWR_LMT_RS_NUM_5G; ++k)
for (m = 0; m < CENTER_CH_5G_ALL_NUM; ++m)
for (l = 0; l < MAX_TX_COUNT; ++l)
ent->lmt_5g[j][k][m][l] = hal_spec->txgi_max;
#endif
}
rtw_list_insert_tail(&ent->list, &tb->reg_list);
tb->reg_num++;
chk_lmt_val:
if (band == BAND_ON_2_4G) {
pre_lmt = ent->lmt_2g[bw][tlrs][ch_idx][ntx_idx];
ch = ch_idx + 1;
}
#if CONFIG_IEEE80211_BAND_5GHZ
else if (band == BAND_ON_5G) {
pre_lmt = ent->lmt_5g[bw][tlrs - 1][ch_idx][ntx_idx];
ch = center_ch_5g_all[ch_idx];
}
#endif
else
goto release_lock;
if (pre_lmt != hal_spec->txgi_max)
RTW_PRINT("duplicate txpwr_lmt for [%s][%s][%s][%s][%uT][%d]\n"
, name, band_str(band), ch_width_str(bw), txpwr_lmt_rs_str(tlrs), ntx_idx + 1, ch);
lmt = rtw_min(pre_lmt, lmt);
if (band == BAND_ON_2_4G)
ent->lmt_2g[bw][tlrs][ch_idx][ntx_idx] = lmt;
#if CONFIG_IEEE80211_BAND_5GHZ
else if (band == BAND_ON_5G)
ent->lmt_5g[bw][tlrs - 1][ch_idx][ntx_idx] = lmt;
#endif
if (0)
RTW_PRINT("%s, %4s, %6s, %7s, %uT, ch%3d = %d\n"
, name, band_str(band), ch_width_str(bw), txpwr_lmt_rs_str(tlrs), ntx_idx + 1
, ch, lmt);
release_lock:
_rtw_mutex_unlock(&tb->lock);
exit:
return;
}
void hal_txpwr_lmt_reg_add(struct hal_com_data *hal_data, const char *name
, u8 band, u8 bw, u8 tlrs, u8 ntx_idx, u8 ch_idx, s8 lmt)
{
hal_txpwr_lmt_reg_add_with_nlen(hal_data, name, strlen(name)
, band, bw, tlrs, ntx_idx, ch_idx, lmt);
}
struct lmt_reg *_hal_txpwr_lmt_reg_get_by_name(struct hal_com_data *hal_data, const char *name)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
struct lmt_reg *ent;
_list *cur, *head;
u8 found = 0;
head = &tb->reg_list;
cur = get_next(head);
while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
ent = LIST_CONTAINOR(cur, struct lmt_reg, list);
cur = get_next(cur);
if (strcmp(ent->name, name) == 0) {
found = 1;
break;
}
}
if (found)
return ent;
return NULL;
}
struct lmt_reg *hal_txpwr_lmt_reg_get_by_name(struct hal_com_data *hal_data, const char *name)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
struct lmt_reg *ent;
_rtw_mutex_lock_interruptible(&tb->lock);
ent = _hal_txpwr_lmt_reg_get_by_name(hal_data, name);
_rtw_mutex_unlock(&tb->lock);
return ent;
}
static void hal_txpwr_clear_current_lmt_reg_names(struct hal_com_data *hal_data, enum band_type band)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
if (band >= BAND_MAX)
return;
if (tb->cur_reg_names[band]) {
rtw_mfree(tb->cur_reg_names[band], tb->cur_reg_names_len[band]);
tb->cur_reg_names[band] = NULL;
}
tb->cur_reg_names_len[band] = 0;
}
static void hal_txpwr_clear_all_current_lmt_reg_names(struct hal_com_data *hal_data)
{
u8 band;
for (band = 0; band < BAND_MAX; band++)
hal_txpwr_clear_current_lmt_reg_names(hal_data, band);
}
void hal_txpwr_set_current_lmt_regs(struct hal_com_data *hal_data, enum band_type band, char *names, int names_len)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
if (band >= BAND_MAX)
return;
_rtw_mutex_lock_interruptible(&tb->lock);
hal_txpwr_clear_current_lmt_reg_names(hal_data, band);
if (names && names_len) {
tb->cur_reg_names[band] = rtw_malloc(names_len);
if (tb->cur_reg_names[band]) {
_rtw_memcpy(tb->cur_reg_names[band], names, names_len);
tb->cur_reg_names_len[band] = names_len;
}
}
_rtw_mutex_unlock(&tb->lock);
}
void hal_txpwr_get_current_lmt_regs(struct hal_com_data *hal_data, enum band_type band, char **names, int *names_len)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
if (!names || !names_len)
return;
*names = NULL;
*names_len = 0;
if (band >= BAND_MAX)
return;
_rtw_mutex_lock_interruptible(&tb->lock);
if (tb->cur_reg_names[band] && tb->cur_reg_names_len[band]) {
*names = rtw_malloc(tb->cur_reg_names_len[band]);
if (*names) {
_rtw_memcpy(*names, tb->cur_reg_names[band], tb->cur_reg_names_len[band]);
*names_len = tb->cur_reg_names_len[band];
}
}
_rtw_mutex_unlock(&tb->lock);
}
bool hal_txpwr_is_current_lmt_reg(struct hal_com_data *hal_data, const char *name)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
int band;
const char *reg_names, *pos;
int reg_names_len;
for (band = 0; band < BAND_MAX; band++) {
reg_names = tb->cur_reg_names[band];
reg_names_len = tb->cur_reg_names_len[band];
if (!reg_names)
continue;
ustrs_for_each_str(reg_names, reg_names_len, pos) {
if (strcmp(name, pos) == 0)
return true;
}
}
return false;
}
void hal_txpwr_lmt_reg_list_free(struct hal_com_data *hal_data)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
struct lmt_reg *ent;
_list *cur, *head;
_rtw_mutex_lock_interruptible(&tb->lock);
head = &tb->reg_list;
cur = get_next(head);
while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
ent = LIST_CONTAINOR(cur, struct lmt_reg, list);
cur = get_next(cur);
rtw_list_delete(&ent->list);
rtw_vmfree((u8 *)ent, sizeof(struct lmt_reg) + strlen(ent->name) + 1);
}
tb->reg_num = 0;
hal_txpwr_clear_all_current_lmt_reg_names(hal_data);
_rtw_mutex_unlock(&tb->lock);
}
void hal_txpwr_lmt_tb_init(struct hal_com_data *hal_data)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
_rtw_mutex_init(&tb->lock);
_rtw_init_listhead(&tb->reg_exc_list);
_rtw_init_listhead(&tb->reg_list);
}
void hal_txpwr_lmt_tb_deinit(struct hal_com_data *hal_data)
{
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
hal_txpwr_lmt_reg_exc_list_free(hal_data);
hal_txpwr_lmt_reg_list_free(hal_data);
_rtw_mutex_free(&tb->lock);
}
void dump_txpwr_lmt(void *sel, _adapter *adapter)
{
#define TMP_STR_LEN 16
struct hal_com_data *hal_data = GET_HAL_DATA(adapter);
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
struct txpwr_lmt_tb_t *tb = &hal_data->txpwr_lmt_tb;
char fmt[16];
char tmp_str[TMP_STR_LEN];
s8 *lmt_idx = NULL;
int bw, band, ch_num, tlrs, ntx_idx, rs, i, path;
u8 ch, n, rfpath_num;
_rtw_mutex_lock_interruptible(&tb->lock);
_dump_txpwr_lmt_reg_exc_list(sel, hal_data);
RTW_PRINT_SEL(sel, "\n");
if (!tb->reg_num)
goto release_lock;
lmt_idx = rtw_malloc(sizeof(s8) * RF_PATH_MAX * tb->reg_num);
if (!lmt_idx) {
RTW_ERR("%s alloc fail\n", __func__);
goto release_lock;
}
RTW_PRINT_SEL(sel, "lmt_2g_cck_ofdm_state:0x%02x\n", tb->lmt_2g_cck_ofdm_state);
#if CONFIG_IEEE80211_BAND_5GHZ
if (IS_HARDWARE_TYPE_JAGUAR_ALL(adapter)) {
RTW_PRINT_SEL(sel, "lmt_5g_cck_ofdm_state:0x%02x\n", tb->lmt_5g_cck_ofdm_state);
RTW_PRINT_SEL(sel, "lmt_5g_20_40_ref:0x%02x\n", tb->lmt_5g_20_40_ref);
}
#endif
RTW_PRINT_SEL(sel, "\n");
for (band = BAND_ON_2_4G; band <= BAND_ON_5G; band++) {
if (!hal_is_band_support(adapter, band))
continue;
rfpath_num = (band == BAND_ON_2_4G ? hal_spec->rfpath_num_2g : hal_spec->rfpath_num_5g);
for (bw = 0; bw < MAX_5G_BANDWIDTH_NUM; bw++) {
if (bw >= CHANNEL_WIDTH_160)
break;
if (band == BAND_ON_2_4G && bw >= CHANNEL_WIDTH_80)
break;
if (band == BAND_ON_2_4G)
ch_num = CENTER_CH_2G_NUM;
#if CONFIG_IEEE80211_BAND_5GHZ
else if (band == BAND_ON_5G)
ch_num = center_chs_5g_num(bw);
#endif
else
ch_num = 0;
if (ch_num == 0) {
rtw_warn_on(1);
break;
}
for (tlrs = TXPWR_LMT_RS_CCK; tlrs < TXPWR_LMT_RS_NUM; tlrs++) {
if (band == BAND_ON_2_4G && tlrs == TXPWR_LMT_RS_VHT)
continue;
if (band == BAND_ON_5G && tlrs == TXPWR_LMT_RS_CCK)
continue;
if (bw > CHANNEL_WIDTH_20 && (tlrs == TXPWR_LMT_RS_CCK || tlrs == TXPWR_LMT_RS_OFDM))
continue;
if (bw > CHANNEL_WIDTH_40 && tlrs == TXPWR_LMT_RS_HT)
continue;
if (tlrs == TXPWR_LMT_RS_VHT && !IS_HARDWARE_TYPE_JAGUAR_ALL(adapter))
continue;
for (ntx_idx = RF_1TX; ntx_idx < MAX_TX_COUNT; ntx_idx++) {
struct lmt_reg *ent;
_list *cur, *head;
if (ntx_idx + 1 > hal_data->max_tx_cnt)
continue;
/* bypass CCK multi-TX is not defined */
if (tlrs == TXPWR_LMT_RS_CCK && ntx_idx > RF_1TX) {
if (band == BAND_ON_2_4G
&& !(tb->lmt_2g_cck_ofdm_state & (TXPWR_LMT_HAS_CCK_1T << ntx_idx)))
continue;
}
/* bypass OFDM multi-TX is not defined */
if (tlrs == TXPWR_LMT_RS_OFDM && ntx_idx > RF_1TX) {
if (band == BAND_ON_2_4G
&& !(tb->lmt_2g_cck_ofdm_state & (TXPWR_LMT_HAS_OFDM_1T << ntx_idx)))
continue;
#if CONFIG_IEEE80211_BAND_5GHZ
if (band == BAND_ON_5G
&& !(tb->lmt_5g_cck_ofdm_state & (TXPWR_LMT_HAS_OFDM_1T << ntx_idx)))
continue;
#endif
}
/* bypass 5G 20M, 40M pure reference */
#if CONFIG_IEEE80211_BAND_5GHZ
if (band == BAND_ON_5G && (bw == CHANNEL_WIDTH_20 || bw == CHANNEL_WIDTH_40)) {
if (tb->lmt_5g_20_40_ref == TXPWR_LMT_REF_HT_FROM_VHT) {
if (tlrs == TXPWR_LMT_RS_HT)
continue;
} else if (tb->lmt_5g_20_40_ref == TXPWR_LMT_REF_VHT_FROM_HT) {
if (tlrs == TXPWR_LMT_RS_VHT && bw <= CHANNEL_WIDTH_40)
continue;
}
}
#endif
/* choose n-SS mapping rate section to get lmt diff value */
if (tlrs == TXPWR_LMT_RS_CCK)
rs = CCK;
else if (tlrs == TXPWR_LMT_RS_OFDM)
rs = OFDM;
else if (tlrs == TXPWR_LMT_RS_HT)
rs = HT_1SS + ntx_idx;
else if (tlrs == TXPWR_LMT_RS_VHT)
rs = VHT_1SS + ntx_idx;
else {
RTW_ERR("%s invalid tlrs %u\n", __func__, tlrs);
continue;
}
RTW_PRINT_SEL(sel, "[%s][%s][%s][%uT]\n"
, band_str(band)
, ch_width_str(bw)
, txpwr_lmt_rs_str(tlrs)
, ntx_idx + 1
);
/* header for limit in db */
RTW_PRINT_SEL(sel, "%3s ", "ch");
head = &tb->reg_list;
cur = get_next(head);
while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
ent = LIST_CONTAINOR(cur, struct lmt_reg, list);
cur = get_next(cur);
sprintf(fmt, "%%%zus%%s ", strlen(ent->name) >= 6 ? 1 : 6 - strlen(ent->name));
snprintf(tmp_str, TMP_STR_LEN, fmt
, hal_txpwr_is_current_lmt_reg(hal_data, ent->name) ? "*" : ""
, ent->name);
_RTW_PRINT_SEL(sel, "%s", tmp_str);
}
sprintf(fmt, "%%%zus%%s ", strlen(txpwr_lmt_str(TXPWR_LMT_WW)) >= 6 ? 1 : 6 - strlen(txpwr_lmt_str(TXPWR_LMT_WW)));
snprintf(tmp_str, TMP_STR_LEN, fmt
, hal_txpwr_is_current_lmt_reg(hal_data, txpwr_lmt_str(TXPWR_LMT_WW)) ? "*" : ""
, txpwr_lmt_str(TXPWR_LMT_WW));
_RTW_PRINT_SEL(sel, "%s", tmp_str);
/* header for limit offset */
for (path = 0; path < RF_PATH_MAX; path++) {
if (path >= rfpath_num)
break;
_RTW_PRINT_SEL(sel, "|");
head = &tb->reg_list;
cur = get_next(head);
while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
ent = LIST_CONTAINOR(cur, struct lmt_reg, list);
cur = get_next(cur);
_RTW_PRINT_SEL(sel, "%3c "
, hal_txpwr_is_current_lmt_reg(hal_data, ent->name) ? rf_path_char(path) : ' ');
}
_RTW_PRINT_SEL(sel, "%3c "
, hal_txpwr_is_current_lmt_reg(hal_data, txpwr_lmt_str(TXPWR_LMT_WW)) ? rf_path_char(path) : ' ');
}
_RTW_PRINT_SEL(sel, "\n");
for (n = 0; n < ch_num; n++) {
s8 lmt;
s8 lmt_offset;
u8 base;
if (band == BAND_ON_2_4G)
ch = n + 1;
#if CONFIG_IEEE80211_BAND_5GHZ
else if (band == BAND_ON_5G)
ch = center_chs_5g(bw, n);
#endif
else
ch = 0;
if (ch == 0) {
rtw_warn_on(1);
break;
}
/* dump limit in dBm */
RTW_PRINT_SEL(sel, "%3u ", ch);
head = &tb->reg_list;
cur = get_next(head);
while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
ent = LIST_CONTAINOR(cur, struct lmt_reg, list);
cur = get_next(cur);
lmt = phy_get_txpwr_lmt(adapter, ent->name, band, bw, tlrs, ntx_idx, ch, 0);
txpwr_idx_get_dbm_str(lmt, hal_spec->txgi_max, hal_spec->txgi_pdbm, strlen(ent->name), tmp_str, TMP_STR_LEN);
_RTW_PRINT_SEL(sel, "%s ", tmp_str);
}
lmt = phy_get_txpwr_lmt(adapter, txpwr_lmt_str(TXPWR_LMT_WW), band, bw, tlrs, ntx_idx, ch, 0);
txpwr_idx_get_dbm_str(lmt, hal_spec->txgi_max, hal_spec->txgi_pdbm, strlen(txpwr_lmt_str(TXPWR_LMT_WW)), tmp_str, TMP_STR_LEN);
_RTW_PRINT_SEL(sel, "%s ", tmp_str);
/* dump limit offset of each path */
for (path = RF_PATH_A; path < RF_PATH_MAX; path++) {
if (path >= rfpath_num)
break;
base = phy_get_target_txpwr(adapter, band, path, rs);
_RTW_PRINT_SEL(sel, "|");
head = &tb->reg_list;
cur = get_next(head);
i = 0;
while ((rtw_end_of_queue_search(head, cur)) == _FALSE) {
ent = LIST_CONTAINOR(cur, struct lmt_reg, list);
cur = get_next(cur);
lmt_offset = phy_get_txpwr_lmt_diff(adapter, ent->name, band, bw, path, rs, tlrs, ntx_idx, ch, 0);
if (lmt_offset == hal_spec->txgi_max) {
*(lmt_idx + i * RF_PATH_MAX + path) = hal_spec->txgi_max;
_RTW_PRINT_SEL(sel, "%3s ", "NA");
} else {
*(lmt_idx + i * RF_PATH_MAX + path) = lmt_offset + base;
_RTW_PRINT_SEL(sel, "%3d ", lmt_offset);
}
i++;
}
lmt_offset = phy_get_txpwr_lmt_diff(adapter, txpwr_lmt_str(TXPWR_LMT_WW), band, bw, path, rs, tlrs, ntx_idx, ch, 0);
if (lmt_offset == hal_spec->txgi_max)
_RTW_PRINT_SEL(sel, "%3s ", "NA");
else
_RTW_PRINT_SEL(sel, "%3d ", lmt_offset);
}
/* compare limit_idx of each path, print 'x' when mismatch */
if (rfpath_num > 1) {
for (i = 0; i < tb->reg_num; i++) {
for (path = 0; path < RF_PATH_MAX; path++) {
if (path >= rfpath_num)
break;
if (*(lmt_idx + i * RF_PATH_MAX + path) != *(lmt_idx + i * RF_PATH_MAX + ((path + 1) % rfpath_num)))
break;
}
if (path >= rfpath_num)
_RTW_PRINT_SEL(sel, " ");
else
_RTW_PRINT_SEL(sel, "x");
}
}
_RTW_PRINT_SEL(sel, "\n");
}
RTW_PRINT_SEL(sel, "\n");
}
} /* loop for rate sections */
} /* loop for bandwidths */
} /* loop for bands */
if (lmt_idx)
rtw_mfree(lmt_idx, sizeof(s8) * RF_PATH_MAX * tb->reg_num);
release_lock:
_rtw_mutex_unlock(&tb->lock);
}
#endif /* CONFIG_TXPWR_LIMIT */