1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2016  Realtek Corporation.
5  *
6  * Contact Information:
7  * wlanfae <wlanfae@realtek.com>
8  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
9  * Hsinchu 300, Taiwan.
10  *
11  * Larry Finger <Larry.Finger@lwfinger.net>
12  *
13  *****************************************************************************/
14 
15 #include "halmac_api.h"
16 #include "rtl_halmac.h"
17 #include <linux/module.h>
18 #include <linux/vmalloc.h>
19 
20 #define DEFAULT_INDICATOR_TIMELMT msecs_to_jiffies(1000) /* ms */
21 #define FIRMWARE_MAX_SIZE HALMAC_FW_SIZE_MAX_88XX
22 
23 static struct rtl_halmac_ops rtl_halmac_operation = {
24 	.halmac_init_adapter = rtl_halmac_init_adapter,
25 	.halmac_deinit_adapter = rtl_halmac_deinit_adapter,
26 	.halmac_init_hal = rtl_halmac_init_hal,
27 	.halmac_deinit_hal = rtl_halmac_deinit_hal,
28 	.halmac_poweron = rtl_halmac_poweron,
29 	.halmac_poweroff = rtl_halmac_poweroff,
30 
31 	.halmac_phy_power_switch = rtl_halmac_phy_power_switch,
32 	.halmac_set_mac_address = rtl_halmac_set_mac_address,
33 	.halmac_set_bssid = rtl_halmac_set_bssid,
34 
35 	.halmac_get_physical_efuse_size = rtl_halmac_get_physical_efuse_size,
36 	.halmac_read_physical_efuse_map = rtl_halmac_read_physical_efuse_map,
37 	.halmac_get_logical_efuse_size = rtl_halmac_get_logical_efuse_size,
38 	.halmac_read_logical_efuse_map = rtl_halmac_read_logical_efuse_map,
39 
40 	.halmac_set_bandwidth = rtl_halmac_set_bandwidth,
41 
42 	.halmac_c2h_handle = rtl_halmac_c2h_handle,
43 
44 	.halmac_chk_txdesc = rtl_halmac_chk_txdesc,
45 };
46 
rtl_halmac_get_ops_pointer(void)47 struct rtl_halmac_ops *rtl_halmac_get_ops_pointer(void)
48 {
49 	return &rtl_halmac_operation;
50 }
51 EXPORT_SYMBOL(rtl_halmac_get_ops_pointer);
52 
53 /*
54  * Driver API for HALMAC operations
55  */
56 
_halmac_reg_read_8(void * p,u32 offset)57 static u8 _halmac_reg_read_8(void *p, u32 offset)
58 {
59 	struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
60 
61 	return rtl_read_byte(rtlpriv, offset);
62 }
63 
_halmac_reg_read_16(void * p,u32 offset)64 static u16 _halmac_reg_read_16(void *p, u32 offset)
65 {
66 	struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
67 
68 	return rtl_read_word(rtlpriv, offset);
69 }
70 
_halmac_reg_read_32(void * p,u32 offset)71 static u32 _halmac_reg_read_32(void *p, u32 offset)
72 {
73 	struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
74 
75 	return rtl_read_dword(rtlpriv, offset);
76 }
77 
_halmac_reg_write_8(void * p,u32 offset,u8 val)78 static void _halmac_reg_write_8(void *p, u32 offset, u8 val)
79 {
80 	struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
81 
82 	rtl_write_byte(rtlpriv, offset, val);
83 }
84 
_halmac_reg_write_16(void * p,u32 offset,u16 val)85 static void _halmac_reg_write_16(void *p, u32 offset, u16 val)
86 {
87 	struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
88 
89 	rtl_write_word(rtlpriv, offset, val);
90 }
91 
_halmac_reg_write_32(void * p,u32 offset,u32 val)92 static void _halmac_reg_write_32(void *p, u32 offset, u32 val)
93 {
94 	struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
95 
96 	rtl_write_dword(rtlpriv, offset, val);
97 }
98 
_halmac_write_data_rsvd_page(void * p,u8 * buf,u32 size)99 static bool _halmac_write_data_rsvd_page(void *p, u8 *buf, u32 size)
100 {
101 	struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
102 
103 	if (rtlpriv->cfg->ops->halmac_cb_write_data_rsvd_page &&
104 	    rtlpriv->cfg->ops->halmac_cb_write_data_rsvd_page(rtlpriv, buf,
105 							      size))
106 		return true;
107 
108 	return false;
109 }
110 
_halmac_write_data_h2c(void * p,u8 * buf,u32 size)111 static bool _halmac_write_data_h2c(void *p, u8 *buf, u32 size)
112 {
113 	struct rtl_priv *rtlpriv = (struct rtl_priv *)p;
114 
115 	if (rtlpriv->cfg->ops->halmac_cb_write_data_h2c &&
116 	    rtlpriv->cfg->ops->halmac_cb_write_data_h2c(rtlpriv, buf, size))
117 		return true;
118 
119 	return false;
120 }
121 
122 static const char *const RTL_HALMAC_FEATURE_NAME[] = {
123 	"HALMAC_FEATURE_CFG_PARA",
124 	"HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE",
125 	"HALMAC_FEATURE_DUMP_LOGICAL_EFUSE",
126 	"HALMAC_FEATURE_UPDATE_PACKET",
127 	"HALMAC_FEATURE_UPDATE_DATAPACK",
128 	"HALMAC_FEATURE_RUN_DATAPACK",
129 	"HALMAC_FEATURE_CHANNEL_SWITCH",
130 	"HALMAC_FEATURE_IQK",
131 	"HALMAC_FEATURE_POWER_TRACKING",
132 	"HALMAC_FEATURE_PSD",
133 	"HALMAC_FEATURE_ALL"};
134 
is_valid_id_status(struct rtl_priv * rtlpriv,enum halmac_feature_id id,enum halmac_cmd_process_status status)135 static inline bool is_valid_id_status(struct rtl_priv *rtlpriv,
136 				      enum halmac_feature_id id,
137 				      enum halmac_cmd_process_status status)
138 {
139 	switch (id) {
140 	case HALMAC_FEATURE_CFG_PARA:
141 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
142 			 RTL_HALMAC_FEATURE_NAME[id]);
143 		break;
144 	case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
145 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
146 			 RTL_HALMAC_FEATURE_NAME[id]);
147 		if (status != HALMAC_CMD_PROCESS_DONE) {
148 			RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
149 				 "%s: <WARN> id(%d) unspecified status(%d)!\n",
150 				 __func__, id, status);
151 		}
152 		break;
153 	case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
154 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
155 			 RTL_HALMAC_FEATURE_NAME[id]);
156 		if (status != HALMAC_CMD_PROCESS_DONE) {
157 			RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
158 				 "%s: <WARN> id(%d) unspecified status(%d)!\n",
159 				 __func__, id, status);
160 		}
161 		break;
162 	case HALMAC_FEATURE_UPDATE_PACKET:
163 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
164 			 RTL_HALMAC_FEATURE_NAME[id]);
165 		break;
166 	case HALMAC_FEATURE_UPDATE_DATAPACK:
167 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
168 			 RTL_HALMAC_FEATURE_NAME[id]);
169 		break;
170 	case HALMAC_FEATURE_RUN_DATAPACK:
171 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
172 			 RTL_HALMAC_FEATURE_NAME[id]);
173 		break;
174 	case HALMAC_FEATURE_CHANNEL_SWITCH:
175 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
176 			 RTL_HALMAC_FEATURE_NAME[id]);
177 		break;
178 	case HALMAC_FEATURE_IQK:
179 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
180 			 RTL_HALMAC_FEATURE_NAME[id]);
181 		break;
182 	case HALMAC_FEATURE_POWER_TRACKING:
183 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
184 			 RTL_HALMAC_FEATURE_NAME[id]);
185 		break;
186 	case HALMAC_FEATURE_PSD:
187 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
188 			 RTL_HALMAC_FEATURE_NAME[id]);
189 		break;
190 	case HALMAC_FEATURE_ALL:
191 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: %s\n", __func__,
192 			 RTL_HALMAC_FEATURE_NAME[id]);
193 		break;
194 	default:
195 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
196 			 "%s: unknown feature id(%d)\n", __func__, id);
197 		return false;
198 	}
199 
200 	return true;
201 }
202 
init_halmac_event_with_waittime(struct rtl_priv * rtlpriv,enum halmac_feature_id id,u8 * buf,u32 size,u32 time)203 static int init_halmac_event_with_waittime(struct rtl_priv *rtlpriv,
204 					   enum halmac_feature_id id, u8 *buf,
205 					   u32 size, u32 time)
206 {
207 	struct completion *comp;
208 
209 	if (!rtlpriv->halmac.indicator[id].comp) {
210 		comp = kzalloc(sizeof(*comp), GFP_KERNEL);
211 		if (!comp)
212 			return -1;
213 	} else {
214 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
215 			 "%s: <WARN> id(%d) sctx is not NULL!!\n", __func__,
216 			 id);
217 		comp = rtlpriv->halmac.indicator[id].comp;
218 		rtlpriv->halmac.indicator[id].comp = NULL;
219 	}
220 
221 	init_completion(comp);
222 	rtlpriv->halmac.indicator[id].wait_ms = time;
223 
224 	rtlpriv->halmac.indicator[id].buffer = buf;
225 	rtlpriv->halmac.indicator[id].buf_size = size;
226 	rtlpriv->halmac.indicator[id].ret_size = 0;
227 	rtlpriv->halmac.indicator[id].status = 0;
228 	/* fill sctx at least to sure other variables are all ready! */
229 	rtlpriv->halmac.indicator[id].comp = comp;
230 
231 	return 0;
232 }
233 
init_halmac_event(struct rtl_priv * rtlpriv,enum halmac_feature_id id,u8 * buf,u32 size)234 static inline int init_halmac_event(struct rtl_priv *rtlpriv,
235 				    enum halmac_feature_id id, u8 *buf,
236 				    u32 size)
237 {
238 	return init_halmac_event_with_waittime(rtlpriv, id, buf, size,
239 					       DEFAULT_INDICATOR_TIMELMT);
240 }
241 
free_halmac_event(struct rtl_priv * rtlpriv,enum halmac_feature_id id)242 static void free_halmac_event(struct rtl_priv *rtlpriv,
243 			      enum halmac_feature_id id)
244 {
245 	struct completion *comp;
246 
247 	if (!rtlpriv->halmac.indicator[id].comp)
248 		return;
249 
250 	comp = rtlpriv->halmac.indicator[id].comp;
251 	rtlpriv->halmac.indicator[id].comp = NULL;
252 	kfree(comp);
253 }
254 
wait_halmac_event(struct rtl_priv * rtlpriv,enum halmac_feature_id id)255 static int wait_halmac_event(struct rtl_priv *rtlpriv,
256 			     enum halmac_feature_id id)
257 {
258 	struct completion *comp;
259 	int ret;
260 
261 	comp = rtlpriv->halmac.indicator[id].comp;
262 	if (!comp)
263 		return -1;
264 
265 	ret = wait_for_completion_timeout(
266 		comp, rtlpriv->halmac.indicator[id].wait_ms);
267 	free_halmac_event(rtlpriv, id);
268 	if (ret > 0)
269 		return 0;
270 
271 	return -1;
272 }
273 
274 /*
275  * Return:
276  *	Always return true, HALMAC don't care the return value.
277  */
278 static bool
_halmac_event_indication(void * p,enum halmac_feature_id feature_id,enum halmac_cmd_process_status process_status,u8 * buf,u32 size)279 _halmac_event_indication(void *p, enum halmac_feature_id feature_id,
280 			 enum halmac_cmd_process_status process_status, u8 *buf,
281 			 u32 size)
282 {
283 	struct rtl_priv *rtlpriv;
284 	struct rtl_halmac_indicator *tbl, *indicator;
285 	struct completion *comp;
286 	u32 cpsz;
287 	bool ret;
288 
289 	rtlpriv = (struct rtl_priv *)p;
290 	tbl = rtlpriv->halmac.indicator;
291 
292 	ret = is_valid_id_status(rtlpriv, feature_id, process_status);
293 	if (!ret)
294 		goto exit;
295 
296 	indicator = &tbl[feature_id];
297 	indicator->status = process_status;
298 	indicator->ret_size = size;
299 	if (!indicator->comp) {
300 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
301 			 "%s: No feature id(%d) waiting!!\n", __func__,
302 			 feature_id);
303 		goto exit;
304 	}
305 	comp = indicator->comp;
306 
307 	if (process_status == HALMAC_CMD_PROCESS_ERROR) {
308 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
309 			 "%s: Something wrong id(%d)!!\n", __func__,
310 			 feature_id);
311 		complete(comp); /* may provide error code */
312 		goto exit;
313 	}
314 
315 	if (size > indicator->buf_size) {
316 		RT_TRACE(
317 			rtlpriv, COMP_HALMAC, DBG_LOUD,
318 			"%s: <WARN> id(%d) buffer is not enough(%d<%d), data will be truncated!\n",
319 			__func__, feature_id, indicator->buf_size, size);
320 		cpsz = indicator->buf_size;
321 	} else {
322 		cpsz = size;
323 	}
324 
325 	if (cpsz && indicator->buffer)
326 		memcpy(indicator->buffer, buf, cpsz);
327 
328 	complete(comp);
329 
330 exit:
331 	return true;
332 }
333 
334 static struct halmac_platform_api rtl_halmac_platform_api = {
335 	/* R/W register */
336 	.REG_READ_8 = _halmac_reg_read_8,
337 	.REG_READ_16 = _halmac_reg_read_16,
338 	.REG_READ_32 = _halmac_reg_read_32,
339 	.REG_WRITE_8 = _halmac_reg_write_8,
340 	.REG_WRITE_16 = _halmac_reg_write_16,
341 	.REG_WRITE_32 = _halmac_reg_write_32,
342 
343 	/* Write data */
344 	/* impletement in HAL-IC level */
345 	.SEND_RSVD_PAGE = _halmac_write_data_rsvd_page,
346 	.SEND_H2C_PKT = _halmac_write_data_h2c,
347 
348 	.EVENT_INDICATION = _halmac_event_indication,
349 };
350 
init_priv(struct rtl_halmac * halmac)351 static int init_priv(struct rtl_halmac *halmac)
352 {
353 	struct rtl_halmac_indicator *indicator;
354 	u32 count, size;
355 
356 	halmac->send_general_info = 0;
357 
358 	count = HALMAC_FEATURE_ALL + 1;
359 	size = sizeof(*indicator) * count;
360 	indicator = kzalloc(size, GFP_KERNEL);
361 	if (!indicator)
362 		return -1;
363 	halmac->indicator = indicator;
364 
365 	return 0;
366 }
367 
deinit_priv(struct rtl_halmac * halmac)368 static void deinit_priv(struct rtl_halmac *halmac)
369 {
370 	struct rtl_halmac_indicator *indicator;
371 
372 	indicator = halmac->indicator;
373 	halmac->indicator = NULL;
374 	kfree(indicator);
375 }
376 
rtl_halmac_init_adapter(struct rtl_priv * rtlpriv)377 int rtl_halmac_init_adapter(struct rtl_priv *rtlpriv)
378 {
379 	struct halmac_adapter *halmac;
380 	struct halmac_api *api;
381 	enum halmac_interface intf;
382 	enum halmac_ret_status status;
383 	int err = 0;
384 	struct halmac_platform_api *pf_api = &rtl_halmac_platform_api;
385 
386 	halmac = rtlpriv_to_halmac(rtlpriv);
387 	if (halmac) {
388 		err = 0;
389 		goto out;
390 	}
391 
392 	err = init_priv(&rtlpriv->halmac);
393 	if (err)
394 		goto out;
395 
396 	intf = HALMAC_INTERFACE_PCIE;
397 	status = halmac_init_adapter(rtlpriv, pf_api, intf, &halmac, &api);
398 	if (status != HALMAC_RET_SUCCESS) {
399 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
400 			 "%s: halmac_init_adapter fail!(status=%d)\n", __func__,
401 			 status);
402 		err = -1;
403 		goto out;
404 	}
405 
406 	rtlpriv->halmac.internal = halmac;
407 
408 out:
409 	if (err)
410 		rtl_halmac_deinit_adapter(rtlpriv);
411 
412 	return err;
413 }
414 
rtl_halmac_deinit_adapter(struct rtl_priv * rtlpriv)415 int rtl_halmac_deinit_adapter(struct rtl_priv *rtlpriv)
416 {
417 	struct halmac_adapter *halmac;
418 	enum halmac_ret_status status;
419 	int err = 0;
420 
421 	halmac = rtlpriv_to_halmac(rtlpriv);
422 	if (!halmac) {
423 		err = 0;
424 		goto out;
425 	}
426 
427 	deinit_priv(&rtlpriv->halmac);
428 
429 	halmac_halt_api(halmac);
430 
431 	status = halmac_deinit_adapter(halmac);
432 	rtlpriv->halmac.internal = NULL;
433 	if (status != HALMAC_RET_SUCCESS) {
434 		err = -1;
435 		goto out;
436 	}
437 
438 out:
439 	return err;
440 }
441 
rtl_halmac_poweron(struct rtl_priv * rtlpriv)442 int rtl_halmac_poweron(struct rtl_priv *rtlpriv)
443 {
444 	struct halmac_adapter *halmac;
445 	struct halmac_api *api;
446 	enum halmac_ret_status status;
447 	int err = -1;
448 
449 	halmac = rtlpriv_to_halmac(rtlpriv);
450 	if (!halmac)
451 		goto out;
452 
453 	api = HALMAC_GET_API(halmac);
454 
455 	status = api->halmac_pre_init_system_cfg(halmac);
456 	if (status != HALMAC_RET_SUCCESS)
457 		goto out;
458 
459 	status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_ON);
460 	if (status != HALMAC_RET_SUCCESS)
461 		goto out;
462 
463 	status = api->halmac_init_system_cfg(halmac);
464 	if (status != HALMAC_RET_SUCCESS)
465 		goto out;
466 
467 	err = 0;
468 out:
469 	return err;
470 }
471 
rtl_halmac_poweroff(struct rtl_priv * rtlpriv)472 int rtl_halmac_poweroff(struct rtl_priv *rtlpriv)
473 {
474 	struct halmac_adapter *halmac;
475 	struct halmac_api *api;
476 	enum halmac_ret_status status;
477 	int err = -1;
478 
479 	halmac = rtlpriv_to_halmac(rtlpriv);
480 	if (!halmac)
481 		goto out;
482 
483 	api = HALMAC_GET_API(halmac);
484 
485 	status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_OFF);
486 	if (status != HALMAC_RET_SUCCESS)
487 		goto out;
488 
489 	err = 0;
490 out:
491 	return err;
492 }
493 
494 /*
495  * Note:
496  *	When this function return, the register REG_RCR may be changed.
497  */
rtl_halmac_config_rx_info(struct rtl_priv * rtlpriv,enum halmac_drv_info info)498 int rtl_halmac_config_rx_info(struct rtl_priv *rtlpriv,
499 			      enum halmac_drv_info info)
500 {
501 	struct halmac_adapter *halmac;
502 	struct halmac_api *api;
503 	enum halmac_ret_status status;
504 	int err = -1;
505 
506 	halmac = rtlpriv_to_halmac(rtlpriv);
507 	api = HALMAC_GET_API(halmac);
508 
509 	status = api->halmac_cfg_drv_info(halmac, info);
510 	if (status != HALMAC_RET_SUCCESS)
511 		goto out;
512 
513 	err = 0;
514 out:
515 	return err;
516 }
517 
init_mac_flow(struct rtl_priv * rtlpriv)518 static enum halmac_ret_status init_mac_flow(struct rtl_priv *rtlpriv)
519 {
520 	struct halmac_adapter *halmac;
521 	struct halmac_api *api;
522 	enum halmac_ret_status status;
523 	u8 wifi_test = 0;
524 	int err;
525 
526 	halmac = rtlpriv_to_halmac(rtlpriv);
527 	api = HALMAC_GET_API(halmac);
528 
529 	if (wifi_test)
530 		status = api->halmac_init_mac_cfg(halmac, HALMAC_TRX_MODE_WMM);
531 	else
532 		status = api->halmac_init_mac_cfg(halmac,
533 						  HALMAC_TRX_MODE_NORMAL);
534 	if (status != HALMAC_RET_SUCCESS)
535 		goto out;
536 
537 	err = rtl_halmac_rx_agg_switch(rtlpriv, true);
538 	if (err)
539 		goto out;
540 
541 	if (rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS7])
542 		status = api->halmac_cfg_operation_mode(
543 			halmac, HALMAC_WIRELESS_MODE_AC);
544 	else if (rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS7])
545 		status = api->halmac_cfg_operation_mode(halmac,
546 							HALMAC_WIRELESS_MODE_N);
547 	else if (rtlpriv->cfg->maps[RTL_RC_OFDM_RATE6M])
548 		status = api->halmac_cfg_operation_mode(halmac,
549 							HALMAC_WIRELESS_MODE_G);
550 	else
551 		status = api->halmac_cfg_operation_mode(halmac,
552 							HALMAC_WIRELESS_MODE_B);
553 	if (status != HALMAC_RET_SUCCESS)
554 		goto out;
555 
556 out:
557 	return status;
558 }
559 
_rf_type_drv2halmac(enum rf_type rf_drv)560 static inline enum halmac_rf_type _rf_type_drv2halmac(enum rf_type rf_drv)
561 {
562 	enum halmac_rf_type rf_mac;
563 
564 	switch (rf_drv) {
565 	case RF_1T2R:
566 		rf_mac = HALMAC_RF_1T2R;
567 		break;
568 	case RF_2T2R:
569 		rf_mac = HALMAC_RF_2T2R;
570 		break;
571 	case RF_1T1R:
572 		rf_mac = HALMAC_RF_1T1R;
573 		break;
574 	case RF_2T2R_GREEN:
575 		rf_mac = HALMAC_RF_2T2R_GREEN;
576 		break;
577 	default:
578 		rf_mac = (enum halmac_rf_type)rf_drv;
579 		break;
580 	}
581 
582 	return rf_mac;
583 }
584 
_send_general_info(struct rtl_priv * rtlpriv)585 static int _send_general_info(struct rtl_priv *rtlpriv)
586 {
587 	struct halmac_adapter *halmac;
588 	struct halmac_api *api;
589 	struct halmac_general_info info;
590 	enum halmac_ret_status status;
591 
592 	halmac = rtlpriv_to_halmac(rtlpriv);
593 	if (!halmac)
594 		return -1;
595 	api = HALMAC_GET_API(halmac);
596 
597 	memset(&info, 0, sizeof(info));
598 	info.rfe_type = rtlpriv->rtlhal.rfe_type;
599 	info.rf_type = _rf_type_drv2halmac(rtlpriv->phy.rf_type);
600 
601 	status = api->halmac_send_general_info(halmac, &info);
602 	switch (status) {
603 	case HALMAC_RET_SUCCESS:
604 		break;
605 	case HALMAC_RET_NO_DLFW:
606 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_WARNING,
607 			 "%s: halmac_send_general_info() fail because fw not dl!\n",
608 			 __func__);
609 	/* fall through */
610 	default:
611 		return -1;
612 	}
613 
614 	return 0;
615 }
616 
617 /*
618  * Notices:
619  *	Make sure
620  *	1. rtl_hal_get_hwreg(HW_VAR_RF_TYPE)
621  *	2. HAL_DATA_TYPE.rfe_type
622  *	already ready for use before calling this function.
623  */
_halmac_init_hal(struct rtl_priv * rtlpriv,u8 * fw,u32 fwsize)624 static int _halmac_init_hal(struct rtl_priv *rtlpriv, u8 *fw, u32 fwsize)
625 {
626 	struct halmac_adapter *halmac;
627 	struct halmac_api *api;
628 	enum halmac_ret_status status;
629 	bool ok;
630 	bool fw_ok = false;
631 	int err, err_ret = -1;
632 
633 	halmac = rtlpriv_to_halmac(rtlpriv);
634 	if (!halmac)
635 		goto out;
636 	api = HALMAC_GET_API(halmac);
637 
638 	/* StatePowerOff */
639 
640 	/* SKIP: halmac_init_adapter (Already done before) */
641 
642 	/* halmac_pre_Init_system_cfg */
643 	/* halmac_mac_power_switch(on) */
644 	/* halmac_Init_system_cfg */
645 	err = rtl_halmac_poweron(rtlpriv);
646 	if (err)
647 		goto out;
648 
649 	/* StatePowerOn */
650 
651 	/* DownloadFW */
652 	rtlpriv->halmac.send_general_info = 0;
653 	if (fw && fwsize) {
654 		err = rtl_halmac_dlfw(rtlpriv, fw, fwsize);
655 		if (err)
656 			goto out;
657 		fw_ok = true;
658 	}
659 
660 	/* InitMACFlow */
661 	status = init_mac_flow(rtlpriv);
662 	if (status != HALMAC_RET_SUCCESS)
663 		goto out;
664 
665 	/* halmac_send_general_info */
666 	if (fw_ok) {
667 		rtlpriv->halmac.send_general_info = 0;
668 		err = _send_general_info(rtlpriv);
669 		if (err)
670 			goto out;
671 	} else {
672 		rtlpriv->halmac.send_general_info = 1;
673 	}
674 
675 	/* Init Phy parameter-MAC */
676 	if (rtlpriv->cfg->ops->halmac_cb_init_mac_register)
677 		ok = rtlpriv->cfg->ops->halmac_cb_init_mac_register(rtlpriv);
678 	else
679 		ok = false;
680 
681 	if (!ok)
682 		goto out;
683 
684 	/* StateMacInitialized */
685 
686 	/* halmac_cfg_drv_info */
687 	err = rtl_halmac_config_rx_info(rtlpriv, HALMAC_DRV_INFO_PHY_STATUS);
688 	if (err)
689 		goto out;
690 
691 	/* halmac_set_hw_value(HALMAC_HW_EN_BB_RF) */
692 	/* Init BB, RF */
693 	if (rtlpriv->cfg->ops->halmac_cb_init_bb_rf_register)
694 		ok = rtlpriv->cfg->ops->halmac_cb_init_bb_rf_register(rtlpriv);
695 	else
696 		ok = false;
697 
698 	if (!ok)
699 		goto out;
700 
701 	status = api->halmac_init_interface_cfg(halmac);
702 	if (status != HALMAC_RET_SUCCESS)
703 		goto out;
704 
705 	/* SKIP: halmac_verify_platform_api */
706 	/* SKIP: halmac_h2c_lb */
707 
708 	/* StateRxIdle */
709 
710 	err_ret = 0;
711 out:
712 	return err_ret;
713 }
714 
rtl_halmac_init_hal(struct rtl_priv * rtlpriv)715 int rtl_halmac_init_hal(struct rtl_priv *rtlpriv)
716 {
717 	if (!rtlpriv->rtlhal.pfirmware || rtlpriv->rtlhal.fwsize == 0)
718 		return -1;
719 
720 	return _halmac_init_hal(rtlpriv, rtlpriv->rtlhal.pfirmware,
721 				rtlpriv->rtlhal.fwsize);
722 }
723 
rtl_halmac_deinit_hal(struct rtl_priv * rtlpriv)724 int rtl_halmac_deinit_hal(struct rtl_priv *rtlpriv)
725 {
726 	struct halmac_adapter *halmac;
727 	struct halmac_api *api;
728 	enum halmac_ret_status status;
729 	int err = -1;
730 
731 	halmac = rtlpriv_to_halmac(rtlpriv);
732 	if (!halmac)
733 		goto out;
734 	api = HALMAC_GET_API(halmac);
735 
736 	status = api->halmac_deinit_interface_cfg(halmac);
737 	if (status != HALMAC_RET_SUCCESS)
738 		goto out;
739 
740 	/* rtw_hal_power_off(adapter); */
741 	status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_OFF);
742 	if (status != HALMAC_RET_SUCCESS)
743 		goto out;
744 
745 	err = 0;
746 out:
747 	return err;
748 }
749 
rtl_halmac_self_verify(struct rtl_priv * rtlpriv)750 int rtl_halmac_self_verify(struct rtl_priv *rtlpriv)
751 {
752 	struct halmac_adapter *mac;
753 	struct halmac_api *api;
754 	enum halmac_ret_status status;
755 	int err = -1;
756 
757 	mac = rtlpriv_to_halmac(rtlpriv);
758 	api = HALMAC_GET_API(mac);
759 
760 	status = api->halmac_verify_platform_api(mac);
761 	if (status != HALMAC_RET_SUCCESS)
762 		goto out;
763 
764 	status = api->halmac_h2c_lb(mac);
765 	if (status != HALMAC_RET_SUCCESS)
766 		goto out;
767 
768 	err = 0;
769 out:
770 	return err;
771 }
772 
rtl_halmac_dlfw(struct rtl_priv * rtlpriv,u8 * fw,u32 fwsize)773 int rtl_halmac_dlfw(struct rtl_priv *rtlpriv, u8 *fw, u32 fwsize)
774 {
775 	struct halmac_adapter *mac;
776 	struct halmac_api *api;
777 	enum halmac_ret_status status;
778 	struct halmac_fw_version fw_version;
779 	int err = 0;
780 
781 	mac = rtlpriv_to_halmac(rtlpriv);
782 	api = HALMAC_GET_API(mac);
783 
784 	if ((!fw) || (!fwsize))
785 		return -1;
786 
787 	/* 1. Driver Stop Tx */
788 	/* ToDo */
789 
790 	/* 2. Driver Check Tx FIFO is empty */
791 	/* ToDo */
792 
793 	/* 3. Config MAX download size */
794 	api->halmac_cfg_max_dl_size(mac, 0x1000);
795 
796 	/* 4. Download Firmware */
797 	mac->h2c_packet_seq = 0;
798 	status = api->halmac_download_firmware(mac, fw, fwsize);
799 	if (status != HALMAC_RET_SUCCESS)
800 		return -1;
801 
802 	status = api->halmac_get_fw_version(mac, &fw_version);
803 	if (status == HALMAC_RET_SUCCESS) {
804 		rtlpriv->rtlhal.fw_version = fw_version.version;
805 		rtlpriv->rtlhal.fw_subversion =
806 			(fw_version.sub_version << 8) | (fw_version.sub_index);
807 
808 		RT_TRACE(
809 			rtlpriv, COMP_HALMAC, DBG_DMESG,
810 			"halmac report firmware version %04X.%04X\n",
811 			rtlpriv->rtlhal.fw_version,
812 			rtlpriv->rtlhal.fw_subversion);
813 	}
814 
815 	if (rtlpriv->halmac.send_general_info) {
816 		rtlpriv->halmac.send_general_info = 0;
817 		err = _send_general_info(rtlpriv);
818 	}
819 
820 	/* 5. Driver resume TX if needed */
821 	/* ToDo */
822 
823 	/* 6. Reset driver variables if needed */
824 	/*hal->LastHMEBoxNum = 0;*/
825 
826 	return err;
827 }
828 
829 /*
830  * Description:
831  *	Power on/off BB/RF domain.
832  *
833  * Parameters:
834  *	enable	true/false for power on/off
835  *
836  * Return:
837  *	0	Success
838  *	others	Fail
839  */
rtl_halmac_phy_power_switch(struct rtl_priv * rtlpriv,u8 enable)840 int rtl_halmac_phy_power_switch(struct rtl_priv *rtlpriv, u8 enable)
841 {
842 	struct halmac_adapter *halmac;
843 	struct halmac_api *api;
844 	enum halmac_ret_status status;
845 
846 	halmac = rtlpriv_to_halmac(rtlpriv);
847 	if (!halmac)
848 		return -1;
849 	api = HALMAC_GET_API(halmac);
850 
851 	status = api->halmac_set_hw_value(halmac, HALMAC_HW_EN_BB_RF, &enable);
852 	if (status != HALMAC_RET_SUCCESS)
853 		return -1;
854 
855 	return 0;
856 }
857 
_is_fw_read_cmd_down(struct rtl_priv * rtlpriv,u8 msgbox_num)858 static bool _is_fw_read_cmd_down(struct rtl_priv *rtlpriv, u8 msgbox_num)
859 {
860 	bool read_down = false;
861 	int retry_cnts = 100;
862 	u8 valid;
863 
864 	RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
865 		 "%s, reg_1cc(%x), msg_box(%d)...\n", __func__,
866 		 rtl_read_byte(rtlpriv, REG_HMETFR), msgbox_num);
867 
868 	do {
869 		valid = rtl_read_byte(rtlpriv, REG_HMETFR) & BIT(msgbox_num);
870 		if (valid == 0)
871 			read_down = true;
872 		else
873 			mdelay(1);
874 	} while ((!read_down) && (retry_cnts--));
875 
876 	return read_down;
877 }
878 
rtl_halmac_send_h2c(struct rtl_priv * rtlpriv,u8 * h2c)879 int rtl_halmac_send_h2c(struct rtl_priv *rtlpriv, u8 *h2c)
880 {
881 	u8 h2c_box_num = 0;
882 	u32 msgbox_addr = 0;
883 	u32 msgbox_ex_addr = 0;
884 	__le32 h2c_cmd = 0;
885 	__le32 h2c_cmd_ex = 0;
886 	s32 ret = -1;
887 	unsigned long flag = 0;
888 	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
889 
890 	if (!h2c) {
891 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD, "%s: pbuf is NULL\n",
892 			 __func__);
893 		return ret;
894 	}
895 
896 	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
897 
898 	/* pay attention to if race condition happened in  H2C cmd setting */
899 	h2c_box_num = rtlhal->last_hmeboxnum;
900 
901 	if (!_is_fw_read_cmd_down(rtlpriv, h2c_box_num)) {
902 		RT_TRACE(rtlpriv, COMP_HALMAC, DBG_LOUD,
903 			 " fw read cmd failed...\n");
904 		goto exit;
905 	}
906 
907 	/* Write Ext command(byte 4 -7) */
908 	msgbox_ex_addr = REG_HMEBOX_E0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
909 	memcpy((u8 *)(&h2c_cmd_ex), h2c + 4, EX_MESSAGE_BOX_SIZE);
910 	rtl_write_dword(rtlpriv, msgbox_ex_addr, le32_to_cpu(h2c_cmd_ex));
911 
912 	/* Write command (byte 0 -3 ) */
913 	msgbox_addr = REG_HMEBOX0 + (h2c_box_num * MESSAGE_BOX_SIZE);
914 	memcpy((u8 *)(&h2c_cmd), h2c, 4);
915 	rtl_write_dword(rtlpriv, msgbox_addr, le32_to_cpu(h2c_cmd));
916 
917 	/* update last msg box number */
918 	rtlhal->last_hmeboxnum = (h2c_box_num + 1) % MAX_H2C_BOX_NUMS;
919 	ret = 0;
920 
921 exit:
922 	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
923 	return ret;
924 }
925 
rtl_halmac_c2h_handle(struct rtl_priv * rtlpriv,u8 * c2h,u32 size)926 int rtl_halmac_c2h_handle(struct rtl_priv *rtlpriv, u8 *c2h, u32 size)
927 {
928 	struct halmac_adapter *mac;
929 	struct halmac_api *api;
930 	enum halmac_ret_status status;
931 
932 	mac = rtlpriv_to_halmac(rtlpriv);
933 	api = HALMAC_GET_API(mac);
934 
935 	status = api->halmac_get_c2h_info(mac, c2h, size);
936 	if (status != HALMAC_RET_SUCCESS)
937 		return -1;
938 
939 	return 0;
940 }
941 
rtl_halmac_get_physical_efuse_size(struct rtl_priv * rtlpriv,u32 * size)942 int rtl_halmac_get_physical_efuse_size(struct rtl_priv *rtlpriv, u32 *size)
943 {
944 	struct halmac_adapter *mac;
945 	struct halmac_api *api;
946 	enum halmac_ret_status status;
947 	u32 val;
948 
949 	mac = rtlpriv_to_halmac(rtlpriv);
950 	api = HALMAC_GET_API(mac);
951 
952 	status = api->halmac_get_efuse_size(mac, &val);
953 	if (status != HALMAC_RET_SUCCESS)
954 		return -1;
955 
956 	*size = val;
957 	return 0;
958 }
959 
rtl_halmac_read_physical_efuse_map(struct rtl_priv * rtlpriv,u8 * map,u32 size)960 int rtl_halmac_read_physical_efuse_map(struct rtl_priv *rtlpriv, u8 *map,
961 				       u32 size)
962 {
963 	struct halmac_adapter *mac;
964 	struct halmac_api *api;
965 	enum halmac_ret_status status;
966 	enum halmac_feature_id id;
967 	int ret;
968 
969 	mac = rtlpriv_to_halmac(rtlpriv);
970 	api = HALMAC_GET_API(mac);
971 	id = HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE;
972 
973 	ret = init_halmac_event(rtlpriv, id, map, size);
974 	if (ret)
975 		return -1;
976 
977 	status = api->halmac_dump_efuse_map(mac, HALMAC_EFUSE_R_DRV);
978 	if (status != HALMAC_RET_SUCCESS) {
979 		free_halmac_event(rtlpriv, id);
980 		return -1;
981 	}
982 
983 	ret = wait_halmac_event(rtlpriv, id);
984 	if (ret)
985 		return -1;
986 
987 	return 0;
988 }
989 
rtl_halmac_read_physical_efuse(struct rtl_priv * rtlpriv,u32 offset,u32 cnt,u8 * data)990 int rtl_halmac_read_physical_efuse(struct rtl_priv *rtlpriv, u32 offset,
991 				   u32 cnt, u8 *data)
992 {
993 	struct halmac_adapter *mac;
994 	struct halmac_api *api;
995 	enum halmac_ret_status status;
996 	u8 v;
997 	u32 i;
998 
999 	mac = rtlpriv_to_halmac(rtlpriv);
1000 	api = HALMAC_GET_API(mac);
1001 
1002 	for (i = 0; i < cnt; i++) {
1003 		status = api->halmac_read_efuse(mac, offset + i, &v);
1004 		if (status != HALMAC_RET_SUCCESS)
1005 			return -1;
1006 		data[i] = v;
1007 	}
1008 
1009 	return 0;
1010 }
1011 
rtl_halmac_write_physical_efuse(struct rtl_priv * rtlpriv,u32 offset,u32 cnt,u8 * data)1012 int rtl_halmac_write_physical_efuse(struct rtl_priv *rtlpriv, u32 offset,
1013 				    u32 cnt, u8 *data)
1014 {
1015 	struct halmac_adapter *mac;
1016 	struct halmac_api *api;
1017 	enum halmac_ret_status status;
1018 	u32 i;
1019 
1020 	mac = rtlpriv_to_halmac(rtlpriv);
1021 	api = HALMAC_GET_API(mac);
1022 
1023 	for (i = 0; i < cnt; i++) {
1024 		status = api->halmac_write_efuse(mac, offset + i, data[i]);
1025 		if (status != HALMAC_RET_SUCCESS)
1026 			return -1;
1027 	}
1028 
1029 	return 0;
1030 }
1031 
rtl_halmac_get_logical_efuse_size(struct rtl_priv * rtlpriv,u32 * size)1032 int rtl_halmac_get_logical_efuse_size(struct rtl_priv *rtlpriv, u32 *size)
1033 {
1034 	struct halmac_adapter *mac;
1035 	struct halmac_api *api;
1036 	enum halmac_ret_status status;
1037 	u32 val;
1038 
1039 	mac = rtlpriv_to_halmac(rtlpriv);
1040 	api = HALMAC_GET_API(mac);
1041 
1042 	status = api->halmac_get_logical_efuse_size(mac, &val);
1043 	if (status != HALMAC_RET_SUCCESS)
1044 		return -1;
1045 
1046 	*size = val;
1047 	return 0;
1048 }
1049 
rtl_halmac_read_logical_efuse_map(struct rtl_priv * rtlpriv,u8 * map,u32 size)1050 int rtl_halmac_read_logical_efuse_map(struct rtl_priv *rtlpriv, u8 *map,
1051 				      u32 size)
1052 {
1053 	struct halmac_adapter *mac;
1054 	struct halmac_api *api;
1055 	enum halmac_ret_status status;
1056 	enum halmac_feature_id id;
1057 	int ret;
1058 
1059 	mac = rtlpriv_to_halmac(rtlpriv);
1060 	api = HALMAC_GET_API(mac);
1061 	id = HALMAC_FEATURE_DUMP_LOGICAL_EFUSE;
1062 
1063 	ret = init_halmac_event(rtlpriv, id, map, size);
1064 	if (ret)
1065 		return -1;
1066 
1067 	status = api->halmac_dump_logical_efuse_map(mac, HALMAC_EFUSE_R_AUTO);
1068 	if (status != HALMAC_RET_SUCCESS) {
1069 		free_halmac_event(rtlpriv, id);
1070 		return -1;
1071 	}
1072 
1073 	ret = wait_halmac_event(rtlpriv, id);
1074 	if (ret)
1075 		return -1;
1076 
1077 	return 0;
1078 }
1079 
rtl_halmac_write_logical_efuse_map(struct rtl_priv * rtlpriv,u8 * map,u32 size,u8 * maskmap,u32 masksize)1080 int rtl_halmac_write_logical_efuse_map(struct rtl_priv *rtlpriv, u8 *map,
1081 				       u32 size, u8 *maskmap, u32 masksize)
1082 {
1083 	struct halmac_adapter *mac;
1084 	struct halmac_api *api;
1085 	struct halmac_pg_efuse_info pginfo;
1086 	enum halmac_ret_status status;
1087 
1088 	mac = rtlpriv_to_halmac(rtlpriv);
1089 	api = HALMAC_GET_API(mac);
1090 
1091 	pginfo.efuse_map = map;
1092 	pginfo.efuse_map_size = size;
1093 	pginfo.efuse_mask = maskmap;
1094 	pginfo.efuse_mask_size = masksize;
1095 
1096 	status = api->halmac_pg_efuse_by_map(mac, &pginfo, HALMAC_EFUSE_R_AUTO);
1097 	if (status != HALMAC_RET_SUCCESS)
1098 		return -1;
1099 
1100 	return 0;
1101 }
1102 
rtl_halmac_read_logical_efuse(struct rtl_priv * rtlpriv,u32 offset,u32 cnt,u8 * data)1103 int rtl_halmac_read_logical_efuse(struct rtl_priv *rtlpriv, u32 offset, u32 cnt,
1104 				  u8 *data)
1105 {
1106 	struct halmac_adapter *mac;
1107 	struct halmac_api *api;
1108 	enum halmac_ret_status status;
1109 	u8 v;
1110 	u32 i;
1111 
1112 	mac = rtlpriv_to_halmac(rtlpriv);
1113 	api = HALMAC_GET_API(mac);
1114 
1115 	for (i = 0; i < cnt; i++) {
1116 		status = api->halmac_read_logical_efuse(mac, offset + i, &v);
1117 		if (status != HALMAC_RET_SUCCESS)
1118 			return -1;
1119 		data[i] = v;
1120 	}
1121 
1122 	return 0;
1123 }
1124 
rtl_halmac_write_logical_efuse(struct rtl_priv * rtlpriv,u32 offset,u32 cnt,u8 * data)1125 int rtl_halmac_write_logical_efuse(struct rtl_priv *rtlpriv, u32 offset,
1126 				   u32 cnt, u8 *data)
1127 {
1128 	struct halmac_adapter *mac;
1129 	struct halmac_api *api;
1130 	enum halmac_ret_status status;
1131 	u32 i;
1132 
1133 	mac = rtlpriv_to_halmac(rtlpriv);
1134 	api = HALMAC_GET_API(mac);
1135 
1136 	for (i = 0; i < cnt; i++) {
1137 		status = api->halmac_write_logical_efuse(mac, offset + i,
1138 							 data[i]);
1139 		if (status != HALMAC_RET_SUCCESS)
1140 			return -1;
1141 	}
1142 
1143 	return 0;
1144 }
1145 
rtl_halmac_set_mac_address(struct rtl_priv * rtlpriv,u8 hwport,u8 * addr)1146 int rtl_halmac_set_mac_address(struct rtl_priv *rtlpriv, u8 hwport, u8 *addr)
1147 {
1148 	struct halmac_adapter *halmac;
1149 	struct halmac_api *api;
1150 	u8 port;
1151 	union halmac_wlan_addr hwa;
1152 	enum halmac_ret_status status;
1153 	int err = -1;
1154 
1155 	halmac = rtlpriv_to_halmac(rtlpriv);
1156 	api = HALMAC_GET_API(halmac);
1157 
1158 	port = hwport;
1159 	memset(&hwa, 0, sizeof(hwa));
1160 	memcpy(hwa.address, addr, 6);
1161 
1162 	status = api->halmac_cfg_mac_addr(halmac, port, &hwa);
1163 	if (status != HALMAC_RET_SUCCESS)
1164 		goto out;
1165 
1166 	err = 0;
1167 out:
1168 	return err;
1169 }
1170 
rtl_halmac_set_bssid(struct rtl_priv * rtlpriv,u8 hwport,u8 * addr)1171 int rtl_halmac_set_bssid(struct rtl_priv *rtlpriv, u8 hwport, u8 *addr)
1172 {
1173 	struct halmac_adapter *halmac;
1174 	struct halmac_api *api;
1175 	u8 port;
1176 	union halmac_wlan_addr hwa;
1177 	enum halmac_ret_status status;
1178 	int err = -1;
1179 
1180 	halmac = rtlpriv_to_halmac(rtlpriv);
1181 	api = HALMAC_GET_API(halmac);
1182 	port = hwport;
1183 
1184 	memset(&hwa, 0, sizeof(union halmac_wlan_addr));
1185 	memcpy(hwa.address, addr, 6);
1186 	status = api->halmac_cfg_bssid(halmac, port, &hwa);
1187 	if (status != HALMAC_RET_SUCCESS)
1188 		goto out;
1189 
1190 	err = 0;
1191 out:
1192 	return err;
1193 }
1194 
rtl_halmac_set_bandwidth(struct rtl_priv * rtlpriv,u8 channel,u8 pri_ch_idx,u8 bw)1195 int rtl_halmac_set_bandwidth(struct rtl_priv *rtlpriv, u8 channel,
1196 			     u8 pri_ch_idx, u8 bw)
1197 {
1198 	struct halmac_adapter *mac;
1199 	struct halmac_api *api;
1200 	enum halmac_ret_status status;
1201 
1202 	mac = rtlpriv_to_halmac(rtlpriv);
1203 	api = HALMAC_GET_API(mac);
1204 
1205 	status = api->halmac_cfg_ch_bw(mac, channel, pri_ch_idx, bw);
1206 	if (status != HALMAC_RET_SUCCESS)
1207 		return -1;
1208 
1209 	return 0;
1210 }
1211 
rtl_halmac_get_hw_value(struct rtl_priv * rtlpriv,enum halmac_hw_id hw_id,void * pvalue)1212 int rtl_halmac_get_hw_value(struct rtl_priv *rtlpriv, enum halmac_hw_id hw_id,
1213 			    void *pvalue)
1214 {
1215 	struct halmac_adapter *mac;
1216 	struct halmac_api *api;
1217 	enum halmac_ret_status status;
1218 
1219 	mac = rtlpriv_to_halmac(rtlpriv);
1220 	api = HALMAC_GET_API(mac);
1221 
1222 	status = api->halmac_get_hw_value(mac, hw_id, pvalue);
1223 	if (status != HALMAC_RET_SUCCESS)
1224 		return -1;
1225 
1226 	return 0;
1227 }
1228 
rtl_halmac_dump_fifo(struct rtl_priv * rtlpriv,enum hal_fifo_sel halmac_fifo_sel)1229 int rtl_halmac_dump_fifo(struct rtl_priv *rtlpriv,
1230 			 enum hal_fifo_sel halmac_fifo_sel)
1231 {
1232 	struct halmac_adapter *mac;
1233 	struct halmac_api *api;
1234 	enum halmac_ret_status status;
1235 	u8 *pfifo_map = NULL;
1236 	u32 fifo_size = 0;
1237 	s8 ret = 0;
1238 
1239 	mac = rtlpriv_to_halmac(rtlpriv);
1240 	api = HALMAC_GET_API(mac);
1241 
1242 	fifo_size = api->halmac_get_fifo_size(mac, halmac_fifo_sel);
1243 	if (fifo_size)
1244 		pfifo_map = vmalloc(fifo_size);
1245 	if (!pfifo_map)
1246 		return -1;
1247 
1248 	status = api->halmac_dump_fifo(mac, halmac_fifo_sel, 0, fifo_size,
1249 				       pfifo_map);
1250 
1251 	if (status != HALMAC_RET_SUCCESS) {
1252 		ret = -1;
1253 		goto _exit;
1254 	}
1255 
1256 _exit:
1257 	if (pfifo_map)
1258 		vfree(pfifo_map);
1259 	return ret;
1260 }
1261 
rtl_halmac_rx_agg_switch(struct rtl_priv * rtlpriv,bool enable)1262 int rtl_halmac_rx_agg_switch(struct rtl_priv *rtlpriv, bool enable)
1263 {
1264 	struct halmac_adapter *halmac;
1265 	struct halmac_api *api;
1266 	struct halmac_rxagg_cfg rxaggcfg;
1267 	enum halmac_ret_status status;
1268 	int err = -1;
1269 
1270 	halmac = rtlpriv_to_halmac(rtlpriv);
1271 	api = HALMAC_GET_API(halmac);
1272 	memset((void *)&rxaggcfg, 0, sizeof(rxaggcfg));
1273 
1274 	if (enable) {
1275 		/* enable RX agg. */
1276 		/* PCIE do nothing */
1277 	} else {
1278 		/* disable RX agg. */
1279 		rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
1280 	}
1281 
1282 	status = api->halmac_cfg_rx_aggregation(halmac, &rxaggcfg);
1283 	if (status != HALMAC_RET_SUCCESS)
1284 		goto out;
1285 
1286 	err = 0;
1287 out:
1288 	return err;
1289 }
1290 
rtl_halmac_get_wow_reason(struct rtl_priv * rtlpriv,u8 * reason)1291 int rtl_halmac_get_wow_reason(struct rtl_priv *rtlpriv, u8 *reason)
1292 {
1293 	u8 val8;
1294 	int err = -1;
1295 
1296 	val8 = rtl_read_byte(rtlpriv, 0x1C7);
1297 	if (val8 == 0xEA)
1298 		goto out;
1299 
1300 	*reason = val8;
1301 	err = 0;
1302 out:
1303 	return err;
1304 }
1305 
1306 /*
1307  * Description:
1308  *	Get RX driver info size. RX driver info is a small memory space between
1309  *	scriptor and RX payload.
1310  *
1311  *	+-------------------------+
1312  *	| RX descriptor           |
1313  *	| usually 24 bytes        |
1314  *	+-------------------------+
1315  *	| RX driver info          |
1316  *	| depends on driver cfg   |
1317  *	+-------------------------+
1318  *	| RX paylad               |
1319  *	|                         |
1320  *	+-------------------------+
1321  *
1322  * Parameter:
1323  *	d	pointer to struct dvobj_priv of driver
1324  *	sz	rx driver info size in bytes.
1325  *
1326  * Rteurn:
1327  *	0	Success
1328  *	other	Fail
1329  */
rtl_halmac_get_drv_info_sz(struct rtl_priv * rtlpriv,u8 * sz)1330 int rtl_halmac_get_drv_info_sz(struct rtl_priv *rtlpriv, u8 *sz)
1331 {
1332 	/*	enum halmac_ret_status status; */
1333 	u8 dw = 6; /* max number */
1334 
1335 	*sz = dw * 8;
1336 	return 0;
1337 }
1338 
rtl_halmac_get_rsvd_drv_pg_bndy(struct rtl_priv * rtlpriv,u16 * drv_pg)1339 int rtl_halmac_get_rsvd_drv_pg_bndy(struct rtl_priv *rtlpriv, u16 *drv_pg)
1340 {
1341 	enum halmac_ret_status status;
1342 	struct halmac_adapter *halmac = rtlpriv_to_halmac(rtlpriv);
1343 	struct halmac_api *api = HALMAC_GET_API(halmac);
1344 
1345 	status = api->halmac_get_hw_value(halmac, HALMAC_HW_RSVD_PG_BNDY,
1346 					  drv_pg);
1347 	if (status != HALMAC_RET_SUCCESS)
1348 		return -1;
1349 
1350 	return 0;
1351 }
1352 
rtl_halmac_chk_txdesc(struct rtl_priv * rtlpriv,u8 * txdesc,u32 size)1353 int rtl_halmac_chk_txdesc(struct rtl_priv *rtlpriv, u8 *txdesc, u32 size)
1354 {
1355 	struct halmac_adapter *mac;
1356 	struct halmac_api *api;
1357 	enum halmac_ret_status status;
1358 
1359 	mac = rtlpriv_to_halmac(rtlpriv);
1360 	api = HALMAC_GET_API(mac);
1361 
1362 	status = api->halmac_chk_txdesc(mac, txdesc, size);
1363 
1364 	if (status != HALMAC_RET_SUCCESS)
1365 		return -1;
1366 
1367 	return 0;
1368 }
1369 
1370 MODULE_AUTHOR("Realtek WlanFAE	<wlanfae@realtek.com>");
1371 MODULE_AUTHOR("Larry Finger	<Larry.FInger@lwfinger.net>");
1372 MODULE_LICENSE("GPL");
1373 MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
1374