1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2017 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 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
16 *
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
21 *
22 * Larry Finger <Larry.Finger@lwfinger.net>
23 *
24 *****************************************************************************/
25
26 /*@************************************************************
27 * include files
28 ************************************************************/
29
30 #include "mp_precomp.h"
31 #include "phydm_precomp.h"
32
33 #ifdef PHYDM_SUPPORT_RSSI_MONITOR
34
phydm_rssi_monitor_h2c(void * dm_void,u8 macid)35 void phydm_rssi_monitor_h2c(void *dm_void, u8 macid)
36 {
37 struct dm_struct *dm = (struct dm_struct *)dm_void;
38 struct ra_table *ra_t = &dm->dm_ra_table;
39 struct cmn_sta_info *sta = dm->phydm_sta_info[macid];
40 struct ra_sta_info *ra = NULL;
41 #ifdef CONFIG_BEAMFORMING
42 struct bf_cmn_info *bf = NULL;
43 #endif
44 u8 h2c[H2C_MAX_LENGTH] = {0};
45 u8 stbc_en, ldpc_en;
46 u8 bf_en = 0;
47 u8 is_rx, is_tx;
48
49 if (is_sta_active(sta)) {
50 ra = &sta->ra_info;
51 } else {
52 PHYDM_DBG(dm, DBG_RSSI_MNTR, "[Warning] %s\n", __func__);
53 return;
54 }
55
56 PHYDM_DBG(dm, DBG_RSSI_MNTR, "%s ======>\n", __func__);
57 PHYDM_DBG(dm, DBG_RSSI_MNTR, "MACID=%d\n", sta->mac_id);
58
59 is_rx = (ra->txrx_state == RX_STATE) ? 1 : 0;
60 is_tx = (ra->txrx_state == TX_STATE) ? 1 : 0;
61 stbc_en = (sta->stbc_en) ? 1 : 0;
62 ldpc_en = (sta->ldpc_en) ? 1 : 0;
63
64 #ifdef CONFIG_BEAMFORMING
65 bf = &sta->bf_info;
66
67 if ((bf->ht_beamform_cap & BEAMFORMING_HT_BEAMFORMEE_ENABLE) ||
68 (bf->vht_beamform_cap & BEAMFORMING_VHT_BEAMFORMEE_ENABLE))
69 bf_en = 1;
70 #endif
71
72 PHYDM_DBG(dm, DBG_RSSI_MNTR, "RA_th_ofst=(( %s%d ))\n",
73 ((ra_t->ra_ofst_direc) ? "+" : "-"), ra_t->ra_th_ofst);
74
75 h2c[0] = sta->mac_id;
76 h2c[1] = 0;
77 h2c[2] = sta->rssi_stat.rssi;
78 h2c[3] = is_rx | (stbc_en << 1) |
79 ((dm->noisy_decision & 0x1) << 2) | (bf_en << 6);
80 h2c[4] = (ra_t->ra_th_ofst & 0x7f) |
81 ((ra_t->ra_ofst_direc & 0x1) << 7);
82 h2c[5] = 0;
83 h2c[6] = ((ra_t->ra_trigger_mode) << 2);
84
85 PHYDM_DBG(dm, DBG_RSSI_MNTR, "PHYDM h2c[0x42]=0x%x %x %x %x %x %x %x\n",
86 h2c[6], h2c[5], h2c[4], h2c[3], h2c[2], h2c[1], h2c[0]);
87
88 #if (RTL8188E_SUPPORT)
89 if (dm->support_ic_type == ODM_RTL8188E)
90 odm_ra_set_rssi_8188e(dm, sta->mac_id, sta->rssi_stat.rssi);
91 else
92 #endif
93 {
94 odm_fill_h2c_cmd(dm, ODM_H2C_RSSI_REPORT, H2C_MAX_LENGTH, h2c);
95 }
96 }
97
98 #if (DM_ODM_SUPPORT_TYPE == ODM_AP)
phydm_sta_rssi_init(void * dm_void,u8 macid,u8 init_rssi)99 void phydm_sta_rssi_init(void *dm_void, u8 macid, u8 init_rssi)
100 {
101 struct dm_struct *dm = (struct dm_struct *)dm_void;
102 struct cmn_sta_info *sta = NULL;
103 struct rssi_info *rssi_t = NULL;
104
105 PHYDM_DBG(dm, DBG_RSSI_MNTR, "%s ======>\n", __func__);
106
107 sta = dm->phydm_sta_info[macid];
108 rssi_t = &sta->rssi_stat;
109
110 rssi_t->rssi_acc = (init_rssi << RSSI_MA);
111 rssi_t->rssi = init_rssi;
112 }
113 #endif
phydm_calculate_rssi_min_max(void * dm_void)114 void phydm_calculate_rssi_min_max(void *dm_void)
115 {
116 struct dm_struct *dm = (struct dm_struct *)dm_void;
117 struct cmn_sta_info *sta;
118 s8 rssi_max_tmp = 0, rssi_min_tmp = 100;
119 u8 i;
120 u8 sta_cnt = 0;
121
122 if (!dm->is_linked)
123 return;
124
125 PHYDM_DBG(dm, DBG_RSSI_MNTR, "%s ======>\n", __func__);
126
127 for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
128 sta = dm->phydm_sta_info[i];
129 if (is_sta_active(sta)) {
130 sta_cnt++;
131
132 if (sta->rssi_stat.rssi < rssi_min_tmp) {
133 rssi_min_tmp = sta->rssi_stat.rssi;
134 dm->rssi_min_macid = i;
135 }
136
137 if (sta->rssi_stat.rssi > rssi_max_tmp) {
138 rssi_max_tmp = sta->rssi_stat.rssi;
139 dm->rssi_max_macid = i;
140 }
141
142 /*@[Send RSSI to FW]*/
143 if (!sta->ra_info.disable_ra)
144 phydm_rssi_monitor_h2c(dm, i);
145
146 if (sta_cnt == dm->number_linked_client)
147 break;
148 }
149 }
150 dm->pre_rssi_min = dm->rssi_min;
151
152 #if (DM_ODM_SUPPORT_TYPE == ODM_AP)
153 if (dm->number_linked_client == 0)
154 return;
155 #endif
156 dm->rssi_max = (u8)rssi_max_tmp;
157 dm->rssi_min = (u8)rssi_min_tmp;
158 }
159
phydm_rssi_monitor_check(void * dm_void)160 void phydm_rssi_monitor_check(void *dm_void)
161 {
162 struct dm_struct *dm = (struct dm_struct *)dm_void;
163
164 if (!(dm->support_ability & ODM_BB_RSSI_MONITOR))
165 return;
166
167 /*@for AP watchdog period = 1 sec*/
168 if ((dm->phydm_sys_up_time % 2) == 1)
169 return;
170
171 PHYDM_DBG(dm, DBG_RSSI_MNTR, "%s ======>\n", __func__);
172
173 phydm_calculate_rssi_min_max(dm);
174
175 PHYDM_DBG(dm, DBG_RSSI_MNTR, "RSSI {max, min} = {%d, %d}\n",
176 dm->rssi_max, dm->rssi_min);
177 }
178
phydm_rssi_monitor_init(void * dm_void)179 void phydm_rssi_monitor_init(void *dm_void)
180 {
181 struct dm_struct *dm = (struct dm_struct *)dm_void;
182 struct ra_table *ra_tab = &dm->dm_ra_table;
183
184 dm->pre_rssi_min = 0;
185 dm->rssi_max = 0;
186 dm->rssi_min = 0;
187 }
188
189 #endif
190