xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlan/mlan_meas.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /**
2*4882a593Smuzhiyun  * @file mlan_meas.c
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  *  @brief Implementation of measurement interface code with the app/firmware
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  *  Driver implementation for sending and retrieving measurement requests
7*4882a593Smuzhiyun  *    and responses.
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  *  Current use is limited to 802.11h.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  *  Requires use of the following preprocessor define:
12*4882a593Smuzhiyun  *    - ENABLE_MEAS
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  *  Copyright 2008-2021 NXP
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  *  This software file (the File) is distributed by NXP
18*4882a593Smuzhiyun  *  under the terms of the GNU General Public License Version 2, June 1991
19*4882a593Smuzhiyun  *  (the License).  You may use, redistribute and/or modify the File in
20*4882a593Smuzhiyun  *  accordance with the terms and conditions of the License, a copy of which
21*4882a593Smuzhiyun  *  is available by writing to the Free Software Foundation, Inc.,
22*4882a593Smuzhiyun  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
23*4882a593Smuzhiyun  *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
26*4882a593Smuzhiyun  *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
27*4882a593Smuzhiyun  *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
28*4882a593Smuzhiyun  *  this warranty disclaimer.
29*4882a593Smuzhiyun  *
30*4882a593Smuzhiyun  */
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun /*************************************************************
33*4882a593Smuzhiyun Change Log:
34*4882a593Smuzhiyun     03/24/2009: initial version
35*4882a593Smuzhiyun ************************************************************/
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #include "mlan.h"
38*4882a593Smuzhiyun #include "mlan_join.h"
39*4882a593Smuzhiyun #include "mlan_util.h"
40*4882a593Smuzhiyun #include "mlan_fw.h"
41*4882a593Smuzhiyun #include "mlan_main.h"
42*4882a593Smuzhiyun #include "mlan_ioctl.h"
43*4882a593Smuzhiyun #include "mlan_meas.h"
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #ifdef DEBUG_LEVEL2
46*4882a593Smuzhiyun /** String descriptions of the different measurement enums.  Debug display */
47*4882a593Smuzhiyun static const char *meas_type_str[WLAN_MEAS_NUM_TYPES] = {
48*4882a593Smuzhiyun 	"basic",
49*4882a593Smuzhiyun };
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun /********************************************************
52*4882a593Smuzhiyun 			Local Functions
53*4882a593Smuzhiyun ********************************************************/
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun /**
56*4882a593Smuzhiyun  *  @brief Retrieve the measurement string representation of a meas_type enum
57*4882a593Smuzhiyun  *  Used for debug display only
58*4882a593Smuzhiyun  *
59*4882a593Smuzhiyun  *  @param meas_type Measurement type enumeration input for string lookup
60*4882a593Smuzhiyun  *
61*4882a593Smuzhiyun  *  @return         Constant string representing measurement type
62*4882a593Smuzhiyun  */
wlan_meas_get_meas_type_str(MeasType_t meas_type)63*4882a593Smuzhiyun static const char *wlan_meas_get_meas_type_str(MeasType_t meas_type)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	if (meas_type <= WLAN_MEAS_11H_MAX_TYPE)
66*4882a593Smuzhiyun 		return meas_type_str[meas_type];
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	return "Invld";
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun #endif
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun /**
73*4882a593Smuzhiyun  *  @brief Debug print display of the input measurement request
74*4882a593Smuzhiyun  *
75*4882a593Smuzhiyun  *  @param pmeas_req  Pointer to the measurement request to display
76*4882a593Smuzhiyun  *
77*4882a593Smuzhiyun  *  @return          N/A
78*4882a593Smuzhiyun  */
79*4882a593Smuzhiyun static void
wlan_meas_dump_meas_req(const HostCmd_DS_MEASUREMENT_REQUEST * pmeas_req)80*4882a593Smuzhiyun wlan_meas_dump_meas_req(const HostCmd_DS_MEASUREMENT_REQUEST *pmeas_req)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun 	ENTER();
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Req: ------------------------------\n");
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Req: mac_addr: " MACSTR "\n",
87*4882a593Smuzhiyun 	       MAC2STR(pmeas_req->mac_addr));
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Req:  dlgTkn: %d\n", pmeas_req->dialog_token);
90*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Req:    mode: dm[%c] rpt[%c] req[%c]\n",
91*4882a593Smuzhiyun 	       pmeas_req->req_mode.duration_mandatory ? 'X' : ' ',
92*4882a593Smuzhiyun 	       pmeas_req->req_mode.report ? 'X' : ' ',
93*4882a593Smuzhiyun 	       pmeas_req->req_mode.request ? 'X' : ' ');
94*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Req:        : en[%c] par[%c]\n",
95*4882a593Smuzhiyun 	       pmeas_req->req_mode.enable ? 'X' : ' ',
96*4882a593Smuzhiyun 	       pmeas_req->req_mode.parallel ? 'X' : ' ');
97*4882a593Smuzhiyun #ifdef DEBUG_LEVEL2
98*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Req: measTyp: %s\n",
99*4882a593Smuzhiyun 	       wlan_meas_get_meas_type_str(pmeas_req->meas_type));
100*4882a593Smuzhiyun #endif
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	switch (pmeas_req->meas_type) {
103*4882a593Smuzhiyun 	case WLAN_MEAS_BASIC:
104*4882a593Smuzhiyun 		/* Lazy cheat, fields of bas, cca, rpi union match on the
105*4882a593Smuzhiyun 		 * request */
106*4882a593Smuzhiyun 		PRINTM(MINFO, "Meas: Req: chan: %u\n",
107*4882a593Smuzhiyun 		       pmeas_req->req.basic.channel);
108*4882a593Smuzhiyun 		PRINTM(MINFO, "Meas: Req: strt: %llu\n",
109*4882a593Smuzhiyun 		       wlan_le64_to_cpu(pmeas_req->req.basic.start_time));
110*4882a593Smuzhiyun 		PRINTM(MINFO, "Meas: Req:  dur: %u\n",
111*4882a593Smuzhiyun 		       wlan_le16_to_cpu(pmeas_req->req.basic.duration));
112*4882a593Smuzhiyun 		break;
113*4882a593Smuzhiyun 	default:
114*4882a593Smuzhiyun 		PRINTM(MINFO, "Meas: Req: <unhandled>\n");
115*4882a593Smuzhiyun 		break;
116*4882a593Smuzhiyun 	}
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Req: ------------------------------\n");
119*4882a593Smuzhiyun 	LEAVE();
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun /**
123*4882a593Smuzhiyun  *  @brief Debug print display of the input measurement report
124*4882a593Smuzhiyun  *
125*4882a593Smuzhiyun  *  @param pmeas_rpt  Pointer to measurement report to display
126*4882a593Smuzhiyun  *
127*4882a593Smuzhiyun  *  @return          N/A
128*4882a593Smuzhiyun  */
129*4882a593Smuzhiyun static void
wlan_meas_dump_meas_rpt(const HostCmd_DS_MEASUREMENT_REPORT * pmeas_rpt)130*4882a593Smuzhiyun wlan_meas_dump_meas_rpt(const HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun 	MeasType_t type;
133*4882a593Smuzhiyun 	ENTER();
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
136*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Rpt: mac_addr: " MACSTR "\n",
137*4882a593Smuzhiyun 	       MAC2STR(pmeas_rpt->mac_addr));
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Rpt:  dlgTkn: %d\n", pmeas_rpt->dialog_token);
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Rpt: rptMode: (%x): Rfs[%c] ICp[%c] Lt[%c]\n",
142*4882a593Smuzhiyun 	       *(t_u8 *)&pmeas_rpt->rpt_mode,
143*4882a593Smuzhiyun 	       pmeas_rpt->rpt_mode.refused ? 'X' : ' ',
144*4882a593Smuzhiyun 	       pmeas_rpt->rpt_mode.incapable ? 'X' : ' ',
145*4882a593Smuzhiyun 	       pmeas_rpt->rpt_mode.late ? 'X' : ' ');
146*4882a593Smuzhiyun #ifdef DEBUG_LEVEL2
147*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Rpt: measTyp: %s\n",
148*4882a593Smuzhiyun 	       wlan_meas_get_meas_type_str(pmeas_rpt->meas_type));
149*4882a593Smuzhiyun #endif
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	type = wlan_le32_to_cpu(pmeas_rpt->meas_type);
152*4882a593Smuzhiyun 	switch (type) {
153*4882a593Smuzhiyun 	case WLAN_MEAS_BASIC:
154*4882a593Smuzhiyun 		PRINTM(MINFO, "Meas: Rpt: chan: %u\n",
155*4882a593Smuzhiyun 		       pmeas_rpt->rpt.basic.channel);
156*4882a593Smuzhiyun 		PRINTM(MINFO, "Meas: Rpt: strt: %llu\n",
157*4882a593Smuzhiyun 		       wlan_le64_to_cpu(pmeas_rpt->rpt.basic.start_time));
158*4882a593Smuzhiyun 		PRINTM(MINFO, "Meas: Rpt:  dur: %u\n",
159*4882a593Smuzhiyun 		       wlan_le16_to_cpu(pmeas_rpt->rpt.basic.duration));
160*4882a593Smuzhiyun 		PRINTM(MINFO, "Meas: Rpt:  bas: (%x): unmsd[%c], radar[%c]\n",
161*4882a593Smuzhiyun 		       *(t_u8 *)&(pmeas_rpt->rpt.basic.map),
162*4882a593Smuzhiyun 		       pmeas_rpt->rpt.basic.map.unmeasured ? 'X' : ' ',
163*4882a593Smuzhiyun 		       pmeas_rpt->rpt.basic.map.radar ? 'X' : ' ');
164*4882a593Smuzhiyun 		PRINTM(MINFO, "Meas: Rpt:  bas: unidSig[%c] ofdm[%c] bss[%c]\n",
165*4882a593Smuzhiyun 		       pmeas_rpt->rpt.basic.map.unidentified_sig ? 'X' : ' ',
166*4882a593Smuzhiyun 		       pmeas_rpt->rpt.basic.map.ofdm_preamble ? 'X' : ' ',
167*4882a593Smuzhiyun 		       pmeas_rpt->rpt.basic.map.bss ? 'X' : ' ');
168*4882a593Smuzhiyun 		break;
169*4882a593Smuzhiyun 	default:
170*4882a593Smuzhiyun 		PRINTM(MINFO, "Meas: Rpt: <unhandled>\n");
171*4882a593Smuzhiyun 		break;
172*4882a593Smuzhiyun 	}
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
175*4882a593Smuzhiyun 	LEAVE();
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun /**
179*4882a593Smuzhiyun  *  @brief Retrieve a measurement report from the firmware
180*4882a593Smuzhiyun  *
181*4882a593Smuzhiyun  *  Callback from command processing when a measurement report is received
182*4882a593Smuzhiyun  *    from the firmware.  Perform the following when a report is received:
183*4882a593Smuzhiyun  *
184*4882a593Smuzhiyun  *   -# Debug displays the report if compiled with the appropriate flags
185*4882a593Smuzhiyun  *   -# If we are pending on a specific measurement report token, and it
186*4882a593Smuzhiyun  *      matches the received report's token, store the report and wake up
187*4882a593Smuzhiyun  *      any pending threads
188*4882a593Smuzhiyun  *
189*4882a593Smuzhiyun  *  @param pmpriv Private driver information structure
190*4882a593Smuzhiyun  *  @param resp HostCmd_DS_COMMAND struct returned from the firmware command
191*4882a593Smuzhiyun  *              passing a HostCmd_DS_MEASUREMENT_REPORT structure.
192*4882a593Smuzhiyun  *
193*4882a593Smuzhiyun  *  @return     MLAN_STATUS_SUCCESS
194*4882a593Smuzhiyun  */
wlan_meas_cmdresp_get_report(mlan_private * pmpriv,const HostCmd_DS_COMMAND * resp)195*4882a593Smuzhiyun static int wlan_meas_cmdresp_get_report(mlan_private *pmpriv,
196*4882a593Smuzhiyun 					const HostCmd_DS_COMMAND *resp)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun 	mlan_adapter *pmadapter = pmpriv->adapter;
199*4882a593Smuzhiyun 	const HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt = &resp->params.meas_rpt;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	ENTER();
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Rpt: %#x-%u, Seq=%u, Ret=%u\n", resp->command,
204*4882a593Smuzhiyun 	       resp->size, resp->seq_num, resp->result);
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	/* Debug displays the measurement report */
207*4882a593Smuzhiyun 	wlan_meas_dump_meas_rpt(pmeas_rpt);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	/*
210*4882a593Smuzhiyun 	 * Check if we are pending on a measurement report and it matches
211*4882a593Smuzhiyun 	 *  the dialog token of the received report:
212*4882a593Smuzhiyun 	 */
213*4882a593Smuzhiyun 	if (pmadapter->state_meas.meas_rpt_pend_on &&
214*4882a593Smuzhiyun 	    pmadapter->state_meas.meas_rpt_pend_on == pmeas_rpt->dialog_token) {
215*4882a593Smuzhiyun 		PRINTM(MINFO, "Meas: Rpt: RCV'd Pend on meas #%d\n",
216*4882a593Smuzhiyun 		       pmadapter->state_meas.meas_rpt_pend_on);
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 		/* Clear the pending report indicator */
219*4882a593Smuzhiyun 		pmadapter->state_meas.meas_rpt_pend_on = 0;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 		/* Copy the received report into the measurement state for
222*4882a593Smuzhiyun 		 * retrieval */
223*4882a593Smuzhiyun 		memcpy_ext(pmadapter, &pmadapter->state_meas.meas_rpt_returned,
224*4882a593Smuzhiyun 			   pmeas_rpt,
225*4882a593Smuzhiyun 			   sizeof(pmadapter->state_meas.meas_rpt_returned),
226*4882a593Smuzhiyun 			   sizeof(pmadapter->state_meas.meas_rpt_returned));
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 		/*
229*4882a593Smuzhiyun 		 * Wake up any threads pending on the wait queue
230*4882a593Smuzhiyun 		 */
231*4882a593Smuzhiyun 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_MEAS_REPORT, MNULL);
232*4882a593Smuzhiyun 	}
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	LEAVE();
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	return MLAN_STATUS_SUCCESS;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun /**
240*4882a593Smuzhiyun  *  @brief Prepare CMD_MEASURMENT_REPORT firmware command
241*4882a593Smuzhiyun  *
242*4882a593Smuzhiyun  *  @param pmpriv     Private driver information structure
243*4882a593Smuzhiyun  *  @param pcmd_ptr   Output parameter: Pointer to the command being prepared
244*4882a593Smuzhiyun  *                    for the firmware
245*4882a593Smuzhiyun  *  @param pinfo_buf  HostCmd_DS_MEASUREMENT_REQUEST passed as void data block
246*4882a593Smuzhiyun  *
247*4882a593Smuzhiyun  *  @return          MLAN_STATUS_SUCCESS
248*4882a593Smuzhiyun  */
wlan_meas_cmd_request(mlan_private * pmpriv,HostCmd_DS_COMMAND * pcmd_ptr,const void * pinfo_buf)249*4882a593Smuzhiyun static int wlan_meas_cmd_request(mlan_private *pmpriv,
250*4882a593Smuzhiyun 				 HostCmd_DS_COMMAND *pcmd_ptr,
251*4882a593Smuzhiyun 				 const void *pinfo_buf)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	const HostCmd_DS_MEASUREMENT_REQUEST *pmeas_req =
254*4882a593Smuzhiyun 		(HostCmd_DS_MEASUREMENT_REQUEST *)pinfo_buf;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	ENTER();
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	pcmd_ptr->command = HostCmd_CMD_MEASUREMENT_REQUEST;
259*4882a593Smuzhiyun 	pcmd_ptr->size = sizeof(HostCmd_DS_MEASUREMENT_REQUEST) + S_DS_GEN;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	memcpy_ext(pmpriv->adapter, &pcmd_ptr->params.meas_req, pmeas_req,
262*4882a593Smuzhiyun 		   sizeof(pcmd_ptr->params.meas_req),
263*4882a593Smuzhiyun 		   sizeof(pcmd_ptr->params.meas_req));
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	PRINTM(MINFO, "Meas: Req: %#x-%u, Seq=%u, Ret=%u\n", pcmd_ptr->command,
266*4882a593Smuzhiyun 	       pcmd_ptr->size, pcmd_ptr->seq_num, pcmd_ptr->result);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 	wlan_meas_dump_meas_req(pmeas_req);
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	LEAVE();
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	return MLAN_STATUS_SUCCESS;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun /**
276*4882a593Smuzhiyun  *  @brief  Retrieve a measurement report from the firmware
277*4882a593Smuzhiyun  *
278*4882a593Smuzhiyun  *  The firmware will send a EVENT_MEAS_REPORT_RDY event when it
279*4882a593Smuzhiyun  *    completes or receives a measurement report.  The event response
280*4882a593Smuzhiyun  *    handler will then start a HostCmd_CMD_MEASUREMENT_REPORT firmware command
281*4882a593Smuzhiyun  *    which gets completed for transmission to the firmware in this routine.
282*4882a593Smuzhiyun  *
283*4882a593Smuzhiyun  *  @param pmpriv    Private driver information structure
284*4882a593Smuzhiyun  *  @param pcmd_ptr  Output parameter: Pointer to the command being prepared
285*4882a593Smuzhiyun  *                   for the firmware
286*4882a593Smuzhiyun  *
287*4882a593Smuzhiyun  *  @return        MLAN_STATUS_SUCCESS
288*4882a593Smuzhiyun  */
wlan_meas_cmd_get_report(mlan_private * pmpriv,HostCmd_DS_COMMAND * pcmd_ptr)289*4882a593Smuzhiyun static int wlan_meas_cmd_get_report(mlan_private *pmpriv,
290*4882a593Smuzhiyun 				    HostCmd_DS_COMMAND *pcmd_ptr)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun 	ENTER();
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	pcmd_ptr->command = HostCmd_CMD_MEASUREMENT_REPORT;
295*4882a593Smuzhiyun 	pcmd_ptr->size = sizeof(HostCmd_DS_MEASUREMENT_REPORT) + S_DS_GEN;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	memset(pmpriv->adapter, &pcmd_ptr->params.meas_rpt, 0x00,
298*4882a593Smuzhiyun 	       sizeof(pcmd_ptr->params.meas_rpt));
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	/*
301*4882a593Smuzhiyun 	 * Set the meas_rpt.mac_addr to our mac address to get a meas report,
302*4882a593Smuzhiyun 	 *   setting the mac to another STA address instructs the firmware
303*4882a593Smuzhiyun 	 *   to transmit this measurement report frame instead
304*4882a593Smuzhiyun 	 */
305*4882a593Smuzhiyun 	memcpy_ext(pmpriv->adapter, pcmd_ptr->params.meas_rpt.mac_addr,
306*4882a593Smuzhiyun 		   pmpriv->curr_addr,
307*4882a593Smuzhiyun 		   sizeof(pcmd_ptr->params.meas_rpt.mac_addr),
308*4882a593Smuzhiyun 		   sizeof(pcmd_ptr->params.meas_rpt.mac_addr));
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	LEAVE();
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	return MLAN_STATUS_SUCCESS;
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun /********************************************************
316*4882a593Smuzhiyun 			Global functions
317*4882a593Smuzhiyun ********************************************************/
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun /**
320*4882a593Smuzhiyun  *  @brief Send the input measurement request to the firmware.
321*4882a593Smuzhiyun  *
322*4882a593Smuzhiyun  *  If the dialog token in the measurement request is set to 0, the function
323*4882a593Smuzhiyun  *    will use an local static auto-incremented token in the measurement
324*4882a593Smuzhiyun  *    request.  This ensures the dialog token is always set.
325*4882a593Smuzhiyun  *
326*4882a593Smuzhiyun  *  If wait_for_resp_timeout is set, the function will block its return on
327*4882a593Smuzhiyun  *     a timeout or returned measurement report that matches the requests
328*4882a593Smuzhiyun  *     dialog token.
329*4882a593Smuzhiyun  *
330*4882a593Smuzhiyun  *  @param pmpriv                  Private driver information structure
331*4882a593Smuzhiyun  *  @param pmeas_req               Pointer to the measurement request to send
332*4882a593Smuzhiyun  *  @param wait_for_resp_timeout   Timeout value of the measurement request
333*4882a593Smuzhiyun  *                                 in ms.
334*4882a593Smuzhiyun  *  @param pioctl_req              Pointer to IOCTL request buffer
335*4882a593Smuzhiyun  *  @param pmeas_rpt               Output parameter: Pointer for the resulting
336*4882a593Smuzhiyun  *                                 measurement report
337*4882a593Smuzhiyun  *
338*4882a593Smuzhiyun  *  @return
339*4882a593Smuzhiyun  *    - 0 for success
340*4882a593Smuzhiyun  *    - -ETIMEDOUT if the measurement report does not return before
341*4882a593Smuzhiyun  *      the timeout expires
342*4882a593Smuzhiyun  *    - Error return from wlan_prepare_cmd routine otherwise
343*4882a593Smuzhiyun  */
wlan_meas_util_send_req(mlan_private * pmpriv,HostCmd_DS_MEASUREMENT_REQUEST * pmeas_req,t_u32 wait_for_resp_timeout,pmlan_ioctl_req pioctl_req,HostCmd_DS_MEASUREMENT_REPORT * pmeas_rpt)344*4882a593Smuzhiyun int wlan_meas_util_send_req(mlan_private *pmpriv,
345*4882a593Smuzhiyun 			    HostCmd_DS_MEASUREMENT_REQUEST *pmeas_req,
346*4882a593Smuzhiyun 			    t_u32 wait_for_resp_timeout,
347*4882a593Smuzhiyun 			    pmlan_ioctl_req pioctl_req,
348*4882a593Smuzhiyun 			    HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun 	static t_u8 auto_dialog_tok;
351*4882a593Smuzhiyun 	wlan_meas_state_t *pmeas_state = &pmpriv->adapter->state_meas;
352*4882a593Smuzhiyun 	int ret;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	ENTER();
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	/* If dialogTok was set to 0 or not provided, autoset */
357*4882a593Smuzhiyun 	pmeas_req->dialog_token =
358*4882a593Smuzhiyun 		(pmeas_req->dialog_token ? pmeas_req->dialog_token :
359*4882a593Smuzhiyun 					   ++auto_dialog_tok);
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	/* Check for rollover of the dialog token.  Avoid using 0 as a token */
362*4882a593Smuzhiyun 	pmeas_req->dialog_token =
363*4882a593Smuzhiyun 		(pmeas_req->dialog_token ? pmeas_req->dialog_token : 1);
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	/*
366*4882a593Smuzhiyun 	 * If the request is to pend waiting for the result, set the dialog
367*4882a593Smuzhiyun 	 * token of this measurement request in the state structure.  The
368*4882a593Smuzhiyun 	 * measurement report handling routines can then check the incoming
369*4882a593Smuzhiyun 	 * measurement reports for a match with this dialog token.
370*4882a593Smuzhiyun 	 */
371*4882a593Smuzhiyun 	if (wait_for_resp_timeout) {
372*4882a593Smuzhiyun 		pmeas_state->meas_rpt_pend_on = pmeas_req->dialog_token;
373*4882a593Smuzhiyun 		PRINTM(MINFO, "Meas: Req: START Pend on meas #%d\n",
374*4882a593Smuzhiyun 		       pmeas_req->dialog_token);
375*4882a593Smuzhiyun 	}
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	/* Send the measurement request to the firmware */
378*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MEASUREMENT_REQUEST,
379*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
380*4882a593Smuzhiyun 			       (void *)pmeas_req);
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	LEAVE();
383*4882a593Smuzhiyun 	return ret;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun /**
387*4882a593Smuzhiyun  *  @brief  Prepare the HostCmd_DS_Command structure for a measurement command.
388*4882a593Smuzhiyun  *
389*4882a593Smuzhiyun  *  Use the Command field to determine if the command being set up is for
390*4882a593Smuzhiyun  *     11h and call one of the local command handlers accordingly for:
391*4882a593Smuzhiyun  *
392*4882a593Smuzhiyun  *        - HostCmd_CMD_MEASUREMENT_REQUEST
393*4882a593Smuzhiyun  *        - HostCmd_CMD_MEASUREMENT_REPORT
394*4882a593Smuzhiyun  *
395*4882a593Smuzhiyun  *  @param pmpriv     Private driver information structure
396*4882a593Smuzhiyun  *  @param pcmd_ptr   Output parameter: Pointer to the command being prepared
397*4882a593Smuzhiyun  *                    for the firmware
398*4882a593Smuzhiyun  *  @param pinfo_buf  Void buffer passthrough with data necessary for a
399*4882a593Smuzhiyun  *                    specific command type
400*4882a593Smuzhiyun  *
401*4882a593Smuzhiyun  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
402*4882a593Smuzhiyun  *
403*4882a593Smuzhiyun  */
wlan_meas_cmd_process(mlan_private * pmpriv,HostCmd_DS_COMMAND * pcmd_ptr,const void * pinfo_buf)404*4882a593Smuzhiyun int wlan_meas_cmd_process(mlan_private *pmpriv, HostCmd_DS_COMMAND *pcmd_ptr,
405*4882a593Smuzhiyun 			  const void *pinfo_buf)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun 	int ret = MLAN_STATUS_SUCCESS;
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	ENTER();
410*4882a593Smuzhiyun 	switch (pcmd_ptr->command) {
411*4882a593Smuzhiyun 	case HostCmd_CMD_MEASUREMENT_REQUEST:
412*4882a593Smuzhiyun 		ret = wlan_meas_cmd_request(pmpriv, pcmd_ptr, pinfo_buf);
413*4882a593Smuzhiyun 		break;
414*4882a593Smuzhiyun 	case HostCmd_CMD_MEASUREMENT_REPORT:
415*4882a593Smuzhiyun 		ret = wlan_meas_cmd_get_report(pmpriv, pcmd_ptr);
416*4882a593Smuzhiyun 		break;
417*4882a593Smuzhiyun 	default:
418*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
419*4882a593Smuzhiyun 	}
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	pcmd_ptr->command = wlan_cpu_to_le16(pcmd_ptr->command);
422*4882a593Smuzhiyun 	pcmd_ptr->size = wlan_cpu_to_le16(pcmd_ptr->size);
423*4882a593Smuzhiyun 	LEAVE();
424*4882a593Smuzhiyun 	return ret;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun /**
428*4882a593Smuzhiyun  *  @brief Handle the command response from the firmware for a measurement
429*4882a593Smuzhiyun  *         command
430*4882a593Smuzhiyun  *
431*4882a593Smuzhiyun  *  Use the Command field to determine if the command response being
432*4882a593Smuzhiyun  *    is for meas.  Call the local command response handler accordingly for:
433*4882a593Smuzhiyun  *
434*4882a593Smuzhiyun  *        - HostCmd_CMD_802_MEASUREMENT_REQUEST
435*4882a593Smuzhiyun  *        - HostCmd_CMD_802_MEASUREMENT_REPORT
436*4882a593Smuzhiyun  *
437*4882a593Smuzhiyun  *  @param pmpriv Private driver information structure
438*4882a593Smuzhiyun  *  @param resp   HostCmd_DS_COMMAND struct returned from the firmware command
439*4882a593Smuzhiyun  *
440*4882a593Smuzhiyun  *  @return     MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
441*4882a593Smuzhiyun  */
wlan_meas_cmdresp_process(mlan_private * pmpriv,const HostCmd_DS_COMMAND * resp)442*4882a593Smuzhiyun int wlan_meas_cmdresp_process(mlan_private *pmpriv,
443*4882a593Smuzhiyun 			      const HostCmd_DS_COMMAND *resp)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun 	int ret = MLAN_STATUS_SUCCESS;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	ENTER();
448*4882a593Smuzhiyun 	switch (resp->command) {
449*4882a593Smuzhiyun 	case HostCmd_CMD_MEASUREMENT_REQUEST:
450*4882a593Smuzhiyun 		PRINTM(MINFO, "Meas: Req Resp: Sz=%u, Seq=%u, Ret=%u\n",
451*4882a593Smuzhiyun 		       resp->size, resp->seq_num, resp->result);
452*4882a593Smuzhiyun 		break;
453*4882a593Smuzhiyun 	case HostCmd_CMD_MEASUREMENT_REPORT:
454*4882a593Smuzhiyun 		ret = wlan_meas_cmdresp_get_report(pmpriv, resp);
455*4882a593Smuzhiyun 		break;
456*4882a593Smuzhiyun 	default:
457*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
458*4882a593Smuzhiyun 	}
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	LEAVE();
461*4882a593Smuzhiyun 	return ret;
462*4882a593Smuzhiyun }
463