1 /******************************************************************************
2 *
3 * Copyright(c) 2019 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15 #define _PHL_PS_DBG_CMD_C_
16 #include "../phl_headers.h"
17 #ifdef CONFIG_POWER_SAVE
18 struct phl_ps_cmd_info {
19 char name[16];
20 u8 id;
21 };
22
23 enum PHL_PS_CMD_ID {
24 PHL_PS_HELP,
25 PHL_PS_SHOW,
26 PHL_PS_TEST,
27 PHL_PS_STOP_PS
28 };
29
30 struct phl_ps_cmd_info phl_ps_cmd_i[] = {
31 {"-h", PHL_PS_HELP},
32 {"show", PHL_PS_SHOW},
33 {"test", PHL_PS_TEST},
34 {"stop_ps", PHL_PS_STOP_PS}
35 };
36
37 /* echo phl ps show */
_phl_ps_cmd_show(struct phl_info_t * phl_info,u32 * used,char input[][MAX_ARGV],u32 input_num,char * output,u32 out_len)38 static void _phl_ps_cmd_show(struct phl_info_t *phl_info, u32 *used, char input[][MAX_ARGV],
39 u32 input_num, char *output, u32 out_len)
40 {
41 if (phl_info == NULL)
42 return;
43
44 phl_ps_dbg_dump(phl_info, used, input, input_num, output, out_len);
45 }
46
47 /* debug to disable power saving */
_phl_ps_cmd_stop_ps(struct phl_info_t * phl_info,u32 * used,char input[][MAX_ARGV],u32 input_num,char * output,u32 out_len)48 static void _phl_ps_cmd_stop_ps(struct phl_info_t *phl_info, u32 *used, char input[][MAX_ARGV],
49 u32 input_num, char *output, u32 out_len)
50 {
51 if (phl_info == NULL)
52 return;
53
54 phl_ps_dbg_stop_ps(phl_info, used, input, input_num, output, out_len);
55 }
56
_phl_ps_cmd_test_ps(struct phl_info_t * phl_info,u32 * used,char input[][MAX_ARGV],u32 input_num,char * output,u32 out_len)57 static void _phl_ps_cmd_test_ps(struct phl_info_t *phl_info, u32 *used, char input[][MAX_ARGV],
58 u32 input_num, char *output, u32 out_len)
59 {
60 if (phl_info == NULL)
61 return;
62
63 phl_ps_dbg_test_ps(phl_info, used, input, input_num, output, out_len);
64 }
65
phl_ps_cmd_parser(struct phl_info_t * phl_info,char input[][MAX_ARGV],u32 input_num,char * output,u32 out_len)66 void phl_ps_cmd_parser(struct phl_info_t *phl_info, char input[][MAX_ARGV],
67 u32 input_num, char *output, u32 out_len)
68 {
69 u32 used = 0;
70 u8 id = 0;
71 u32 i;
72 u32 array_size = sizeof(phl_ps_cmd_i) / sizeof(struct phl_ps_cmd_info);
73
74 PS_CNSL(out_len, used, output + used, out_len - used, "\n");
75
76 /* Parsing Cmd ID */
77 if (input_num) {
78 for (i = 0; i < array_size; i++) {
79 if (!_os_strcmp(phl_ps_cmd_i[i].name, input[1])) {
80 id = phl_ps_cmd_i[i].id;
81 break;
82 }
83 }
84 }
85
86 switch (id) {
87 case PHL_PS_TEST:
88 _phl_ps_cmd_test_ps(phl_info, &used, input, input_num,
89 output, out_len);
90 break;
91 case PHL_PS_SHOW:
92 _phl_ps_cmd_show(phl_info, &used, input, input_num,
93 output, out_len);
94 break;
95 case PHL_PS_STOP_PS:
96 _phl_ps_cmd_stop_ps(phl_info, &used, input, input_num,
97 output, out_len);
98 break;
99 default:
100 PS_CNSL(out_len, used, output + used, out_len - used,
101 "command not supported !!\n");
102
103 /* fall through */
104 case PHL_PS_HELP:
105 PS_CNSL(out_len, used, output + used, out_len - used,
106 "PS cmd ==>\n");
107
108 for (i = 0; i < array_size - 1; i++)
109 PS_CNSL(out_len, used, output + used, out_len - used,
110 " %s\n", phl_ps_cmd_i[i + 1].name);
111 break;
112 }
113 }
114
phl_ps_dbg_dump(struct phl_info_t * phl_info,u32 * used,char input[][MAX_ARGV],u32 input_num,char * output,u32 out_len)115 void phl_ps_dbg_dump(struct phl_info_t *phl_info, u32 *used,
116 char input[][MAX_ARGV], u32 input_num, char *output, u32 out_len)
117 {
118 struct phl_module_op_info op_info = {0};
119 struct phl_cmd_ps_basic_info info = {0};
120 struct rtw_ps_cap_t *ps_cap = NULL;
121
122 PS_CNSL(out_len, *used, output + *used, out_len - *used,
123 "========== Basic Info ==========\n");
124
125 op_info.op_code = PS_MDL_OP_BASIC_INFO;
126 op_info.inbuf = (u8 *)&info;
127 #ifdef CONFIG_CMD_DISP
128 if (phl_disp_eng_query_bk_module_info(phl_info, HW_BAND_0,
129 PHL_MDL_POWER_MGNT, &op_info) != RTW_PHL_STATUS_SUCCESS)
130 return;
131
132 PS_CNSL(out_len, *used, output + *used, out_len - *used,
133 "ps_mode: %s, cur_pwr_lvl: %s\
134 \nap_active: %s, gc_active: %s\
135 \ntx traffic lvl: %s, rx traffic lvl: %s\n",
136 phl_ps_ps_mode_to_str(info.ps_mode), phl_ps_pwr_lvl_to_str(info.cur_pwr_lvl),
137 (info.ap_active == true ? "yes" : "no"), (info.gc_active == true ? "yes" : "no"),
138 phl_tfc_lvl_to_str(phl_info->phl_com->phl_stats.tx_traffic.lvl), phl_tfc_lvl_to_str(phl_info->phl_com->phl_stats.rx_traffic.lvl));
139
140 if (info.sta != NULL) {
141 PS_CNSL(out_len, *used, output + *used, out_len - *used,
142 "chnl: %d, rssi: %d, rssi_bcn: %d\n",
143 info.sta->chandef.chan, rtw_hal_get_sta_rssi(info.sta), phl_get_min_rssi_bcn(phl_info));
144 }
145
146 PS_CNSL(out_len, *used, output + *used, out_len - *used,
147 "========== Advanced Info ==========\n");
148
149 PS_CNSL(out_len, *used, output + *used, out_len - *used,
150 "last enter reason: %s\
151 \nlast leave reason: %s\
152 \nreject all pwr req: %s\
153 \nbtc req pwr: %s\
154 \nruntime stop reason: %d\n",
155 info.enter_rson,
156 info.leave_rson,
157 (info.rej_pwr_req == true ? "yes" : "no"),
158 (info.btc_req_pwr == true ? "yes" : "no"),
159 info.rt_stop_rson);
160
161 PS_CNSL(out_len, *used, output + *used, out_len - *used,
162 "========== Capability ==========\n");
163
164 ps_cap = _get_ps_cap(phl_info);
165
166 PS_CNSL(out_len, *used, output + *used, out_len - *used,
167 "init_rf_state: %s, init_rt_stop_rson: 0x%x, leave_fail_act: 0x%x\
168 \nlps: %s, lps_cap: %s, lps_pause_tx: %d\
169 \nawake_interval: %d, listen_bcn_mode: %d, smart_ps_mode: %d\
170 \nrssi_enter_threshold: %d, rssi_leave_threshold: %d, rssi_diff_threshold: %d\
171 \nips: %s, ips_cap: %s\n",
172 (ps_cap->init_rf_state ? "off" : "on"), ps_cap->init_rt_stop_rson, ps_cap->leave_fail_act,
173 phl_ps_op_mode_to_str(ps_cap->lps_en), phl_ps_pwr_lvl_to_str(phl_ps_judge_pwr_lvl(ps_cap->lps_cap, PS_MODE_LPS, true)), ps_cap->lps_pause_tx,
174 ps_cap->lps_awake_interval, ps_cap->lps_listen_bcn_mode, ps_cap->lps_smart_ps_mode,
175 ps_cap->lps_rssi_enter_threshold, ps_cap->lps_rssi_leave_threshold, ps_cap->lps_rssi_diff_threshold,
176 phl_ps_op_mode_to_str(ps_cap->ips_en), phl_ps_pwr_lvl_to_str(phl_ps_judge_pwr_lvl(ps_cap->ips_cap, PS_MODE_IPS, true)));
177
178 #else
179 PS_CNSL(out_len, *used, output + *used, out_len - *used,
180 "Not support.\n");
181 #endif
182 }
183
phl_ps_dbg_stop_ps(struct phl_info_t * phl_info,u32 * used,char input[][MAX_ARGV],u32 input_num,char * output,u32 out_len)184 void phl_ps_dbg_stop_ps(struct phl_info_t *phl_info, u32 *used,
185 char input[][MAX_ARGV], u32 input_num, char *output, u32 out_len)
186 {
187 u32 stop = 0;
188 bool ps_en = false;
189 struct rtw_phl_com_t *phl_com = phl_info->phl_com;
190
191 do {
192 if (input_num < 3){
193 PS_CNSL(out_len, *used, output + *used, out_len - *used,
194 "[DBG] echo phl ps stop_ps <0/1>\n");
195 break;
196 }
197
198 if (!_get_hex_from_string(input[2], &stop))
199 break;
200
201 if ((phl_com->dev_sw_cap.ps_cap.ips_en != PS_OP_MODE_AUTO)&&
202 (phl_com->dev_sw_cap.ps_cap.lps_en != PS_OP_MODE_AUTO)){
203 PS_CNSL(out_len, *used, output + *used, out_len - *used,
204 "One of ips or lps should set PS_OP_MODE_AUTO\n");
205 break;
206 }
207
208 if (stop)
209 ps_en = false;
210 else
211 ps_en = true;
212
213 rtw_phl_ps_set_rt_cap((void*)phl_info, HW_BAND_0, ps_en, PS_RT_DEBUG);
214
215 } while (0);
216 }
217
phl_ps_dbg_test_ps(struct phl_info_t * phl_info,u32 * used,char input[][MAX_ARGV],u32 input_num,char * output,u32 out_len)218 void phl_ps_dbg_test_ps(struct phl_info_t *phl_info, u32 *used,
219 char input[][MAX_ARGV], u32 input_num, char *output, u32 out_len)
220 {
221 u32 enter = 0;
222 u8 ps_mode = PS_MODE_NONE;
223
224 do {
225 if (input_num < 4){
226 PS_CNSL(out_len, *used, output + *used, out_len - *used,
227 "[DBG] echo phl ps test <ips/lps> <0/1>\n");
228 break;
229 }
230
231 if (!_os_strcmp(input[2], "lps")) {
232 ps_mode = PS_MODE_LPS;
233 } else if (!_os_strcmp(input[2], "ips")) {
234 ps_mode = PS_MODE_IPS;
235 } else {
236 break;
237 }
238
239 if (!_get_hex_from_string(input[3], &enter))
240 break;
241
242 phl_ps_dbg_set_ps(phl_info, ps_mode, (enter ? true : false));
243
244 } while (0);
245 }
246
247 #endif /* CONFIG_POWER_SAVE */
248