1 /* SPDX-License-Identifier: GPL-2.0 */
2 /******************************************************************************
3 *
4 * Copyright(c) 2015 - 2019 Realtek Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 *****************************************************************************/
16 #define _HAL_HALMAC_C_
17
18 #include <drv_types.h> /* PADAPTER, struct dvobj_priv, SDIO_ERR_VAL8 and etc. */
19 #include <hal_data.h> /* efuse, PHAL_DATA_TYPE and etc. */
20 #include "hal_halmac.h" /* dvobj_to_halmac() and ect. */
21
22 /*
23 * HALMAC take return value 0 for fail and 1 for success to replace
24 * _FALSE/_TRUE after V1_04_09
25 */
26 #define RTW_HALMAC_FAIL 0
27 #define RTW_HALMAC_SUCCESS 1
28
29 #define DEFAULT_INDICATOR_TIMELMT 1000 /* ms */
30 #define MSG_PREFIX "[HALMAC]"
31
32 #define RTW_HALMAC_DLFW_MEM_NO_STOP_TX
33 #define RTW_HALMAC_FILTER_DRV_C2H /* Block C2H owner=driver */
34
35 /*
36 * Driver API for HALMAC operations
37 */
38
39 #ifdef CONFIG_SDIO_HCI
40 #include <rtw_sdio.h>
41
_halmac_mac_reg_page0_chk(const char * func,struct dvobj_priv * dvobj,u32 offset)42 static u8 _halmac_mac_reg_page0_chk(const char *func, struct dvobj_priv *dvobj, u32 offset)
43 {
44 #if defined(CONFIG_IO_CHECK_IN_ANA_LOW_CLK) && defined(CONFIG_LPS_LCLK)
45 struct pwrctrl_priv *pwrpriv = &dvobj->pwrctl_priv;
46 u32 mac_reg_offset = 0;
47
48 if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
49 return _TRUE;
50
51 if (pwrpriv->lps_level == LPS_NORMAL)
52 return _TRUE;
53
54 if (pwrpriv->rpwm >= PS_STATE_S2)
55 return _TRUE;
56
57 if (offset & (WLAN_IOREG_DEVICE_ID << 13)) { /*WLAN_IOREG_OFFSET*/
58 mac_reg_offset = offset & HALMAC_WLAN_MAC_REG_MSK;
59 if (mac_reg_offset < 0x100) {
60 RTW_ERR(FUNC_ADPT_FMT
61 "access MAC REG -0x%04x in PS-mode:0x%02x (rpwm:0x%02x, lps_level:0x%02x)\n",
62 FUNC_ADPT_ARG(dvobj_get_primary_adapter(dvobj)), mac_reg_offset,
63 pwrpriv->pwr_mode, pwrpriv->rpwm, pwrpriv->lps_level);
64 rtw_warn_on(1);
65 return _FALSE;
66 }
67 }
68 #endif
69 return _TRUE;
70 }
71
_halmac_sdio_cmd52_read(void * p,u32 offset)72 static u8 _halmac_sdio_cmd52_read(void *p, u32 offset)
73 {
74 struct dvobj_priv *d;
75 u8 val;
76 u8 ret;
77
78
79 d = (struct dvobj_priv *)p;
80 _halmac_mac_reg_page0_chk(__func__, d, offset);
81 ret = rtw_sdio_read_cmd52(d, offset, &val, 1);
82 if (_FAIL == ret) {
83 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
84 return SDIO_ERR_VAL8;
85 }
86
87 return val;
88 }
89
_halmac_sdio_cmd52_write(void * p,u32 offset,u8 val)90 static void _halmac_sdio_cmd52_write(void *p, u32 offset, u8 val)
91 {
92 struct dvobj_priv *d;
93 u8 ret;
94
95
96 d = (struct dvobj_priv *)p;
97 _halmac_mac_reg_page0_chk(__func__, d, offset);
98 ret = rtw_sdio_write_cmd52(d, offset, &val, 1);
99 if (_FAIL == ret)
100 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
101 }
102
_halmac_sdio_reg_read_8(void * p,u32 offset)103 static u8 _halmac_sdio_reg_read_8(void *p, u32 offset)
104 {
105 struct dvobj_priv *d;
106 u8 *pbuf;
107 u8 val;
108 u8 ret;
109
110
111 d = (struct dvobj_priv *)p;
112 val = SDIO_ERR_VAL8;
113 _halmac_mac_reg_page0_chk(__func__, d, offset);
114 pbuf = rtw_zmalloc(1);
115 if (!pbuf)
116 return val;
117
118 ret = rtw_sdio_read_cmd53(d, offset, pbuf, 1);
119 if (ret == _FAIL) {
120 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
121 goto exit;
122 }
123
124 val = *pbuf;
125
126 exit:
127 rtw_mfree(pbuf, 1);
128
129 return val;
130 }
131
_halmac_sdio_reg_read_16(void * p,u32 offset)132 static u16 _halmac_sdio_reg_read_16(void *p, u32 offset)
133 {
134 struct dvobj_priv *d;
135 u8 *pbuf;
136 u16 val;
137 u8 ret;
138
139
140 d = (struct dvobj_priv *)p;
141 val = SDIO_ERR_VAL16;
142 _halmac_mac_reg_page0_chk(__func__, d, offset);
143 pbuf = rtw_zmalloc(2);
144 if (!pbuf)
145 return val;
146
147 ret = rtw_sdio_read_cmd53(d, offset, pbuf, 2);
148 if (ret == _FAIL) {
149 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
150 goto exit;
151 }
152
153 val = le16_to_cpu(*(u16 *)pbuf);
154
155 exit:
156 rtw_mfree(pbuf, 2);
157
158 return val;
159 }
160
_halmac_sdio_reg_read_32(void * p,u32 offset)161 static u32 _halmac_sdio_reg_read_32(void *p, u32 offset)
162 {
163 struct dvobj_priv *d;
164 u8 *pbuf;
165 u32 val;
166 u8 ret;
167
168
169 d = (struct dvobj_priv *)p;
170 val = SDIO_ERR_VAL32;
171 _halmac_mac_reg_page0_chk(__func__, d, offset);
172 pbuf = rtw_zmalloc(4);
173 if (!pbuf)
174 return val;
175
176 ret = rtw_sdio_read_cmd53(d, offset, pbuf, 4);
177 if (ret == _FAIL) {
178 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
179 goto exit;
180 }
181
182 val = le32_to_cpu(*(u32 *)pbuf);
183
184 exit:
185 rtw_mfree(pbuf, 4);
186
187 return val;
188 }
189
_halmac_sdio_reg_read_n(void * p,u32 offset,u32 size,u8 * data)190 static u8 _halmac_sdio_reg_read_n(void *p, u32 offset, u32 size, u8 *data)
191 {
192 struct dvobj_priv *d = (struct dvobj_priv *)p;
193 u8 *pbuf;
194 u8 ret;
195 u8 rst = RTW_HALMAC_FAIL;
196 u32 sdio_read_size;
197
198
199 if (!data)
200 return rst;
201
202 sdio_read_size = RND4(size);
203 sdio_read_size = rtw_sdio_cmd53_align_size(d, sdio_read_size);
204
205 pbuf = rtw_zmalloc(sdio_read_size);
206 if (!pbuf)
207 return rst;
208
209 ret = rtw_sdio_read_cmd53(d, offset, pbuf, sdio_read_size);
210 if (ret == _FAIL) {
211 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
212 goto exit;
213 }
214
215 _rtw_memcpy(data, pbuf, size);
216 rst = RTW_HALMAC_SUCCESS;
217 exit:
218 rtw_mfree(pbuf, sdio_read_size);
219
220 return rst;
221 }
222
_halmac_sdio_reg_write_8(void * p,u32 offset,u8 val)223 static void _halmac_sdio_reg_write_8(void *p, u32 offset, u8 val)
224 {
225 struct dvobj_priv *d;
226 u8 *pbuf;
227 u8 ret;
228
229
230 d = (struct dvobj_priv *)p;
231 _halmac_mac_reg_page0_chk(__func__, d, offset);
232 pbuf = rtw_zmalloc(1);
233 if (!pbuf)
234 return;
235 _rtw_memcpy(pbuf, &val, 1);
236
237 ret = rtw_sdio_write_cmd53(d, offset, pbuf, 1);
238 if (ret == _FAIL)
239 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
240
241 rtw_mfree(pbuf, 1);
242 }
243
_halmac_sdio_reg_write_16(void * p,u32 offset,u16 val)244 static void _halmac_sdio_reg_write_16(void *p, u32 offset, u16 val)
245 {
246 struct dvobj_priv *d;
247 u8 *pbuf;
248 u8 ret;
249
250
251 d = (struct dvobj_priv *)p;
252 _halmac_mac_reg_page0_chk(__func__, d, offset);
253 val = cpu_to_le16(val);
254 pbuf = rtw_zmalloc(2);
255 if (!pbuf)
256 return;
257 _rtw_memcpy(pbuf, &val, 2);
258
259 ret = rtw_sdio_write_cmd53(d, offset, pbuf, 2);
260 if (ret == _FAIL)
261 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
262
263 rtw_mfree(pbuf, 2);
264 }
265
_halmac_sdio_reg_write_32(void * p,u32 offset,u32 val)266 static void _halmac_sdio_reg_write_32(void *p, u32 offset, u32 val)
267 {
268 struct dvobj_priv *d;
269 u8 *pbuf;
270 u8 ret;
271
272
273 d = (struct dvobj_priv *)p;
274 _halmac_mac_reg_page0_chk(__func__, d, offset);
275 val = cpu_to_le32(val);
276 pbuf = rtw_zmalloc(4);
277 if (!pbuf)
278 return;
279 _rtw_memcpy(pbuf, &val, 4);
280
281 ret = rtw_sdio_write_cmd53(d, offset, pbuf, 4);
282 if (ret == _FAIL)
283 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
284
285 rtw_mfree(pbuf, 4);
286 }
287
_halmac_sdio_read_cia(void * p,u32 offset)288 static u8 _halmac_sdio_read_cia(void *p, u32 offset)
289 {
290 struct dvobj_priv *d;
291 u8 data = 0;
292 u8 ret;
293
294
295 d = (struct dvobj_priv *)p;
296
297 ret = rtw_sdio_f0_read(d, offset, &data, 1);
298 if (ret == _FAIL)
299 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
300
301 return data;
302 }
303
304 #else /* !CONFIG_SDIO_HCI */
305
_halmac_reg_read_8(void * p,u32 offset)306 static u8 _halmac_reg_read_8(void *p, u32 offset)
307 {
308 struct dvobj_priv *d;
309 PADAPTER adapter;
310
311
312 d = (struct dvobj_priv *)p;
313 adapter = dvobj_get_primary_adapter(d);
314
315 return _rtw_read8(adapter, offset);
316 }
317
_halmac_reg_read_16(void * p,u32 offset)318 static u16 _halmac_reg_read_16(void *p, u32 offset)
319 {
320 struct dvobj_priv *d;
321 PADAPTER adapter;
322
323
324 d = (struct dvobj_priv *)p;
325 adapter = dvobj_get_primary_adapter(d);
326
327 return _rtw_read16(adapter, offset);
328 }
329
_halmac_reg_read_32(void * p,u32 offset)330 static u32 _halmac_reg_read_32(void *p, u32 offset)
331 {
332 struct dvobj_priv *d;
333 PADAPTER adapter;
334
335
336 d = (struct dvobj_priv *)p;
337 adapter = dvobj_get_primary_adapter(d);
338
339 return _rtw_read32(adapter, offset);
340 }
341
_halmac_reg_write_8(void * p,u32 offset,u8 val)342 static void _halmac_reg_write_8(void *p, u32 offset, u8 val)
343 {
344 struct dvobj_priv *d;
345 PADAPTER adapter;
346 int err;
347
348
349 d = (struct dvobj_priv *)p;
350 adapter = dvobj_get_primary_adapter(d);
351
352 err = _rtw_write8(adapter, offset, val);
353 if (err == _FAIL)
354 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
355 }
356
_halmac_reg_write_16(void * p,u32 offset,u16 val)357 static void _halmac_reg_write_16(void *p, u32 offset, u16 val)
358 {
359 struct dvobj_priv *d;
360 PADAPTER adapter;
361 int err;
362
363
364 d = (struct dvobj_priv *)p;
365 adapter = dvobj_get_primary_adapter(d);
366
367 err = _rtw_write16(adapter, offset, val);
368 if (err == _FAIL)
369 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
370 }
371
_halmac_reg_write_32(void * p,u32 offset,u32 val)372 static void _halmac_reg_write_32(void *p, u32 offset, u32 val)
373 {
374 struct dvobj_priv *d;
375 PADAPTER adapter;
376 int err;
377
378
379 d = (struct dvobj_priv *)p;
380 adapter = dvobj_get_primary_adapter(d);
381
382 err = _rtw_write32(adapter, offset, val);
383 if (err == _FAIL)
384 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
385 }
386 #endif /* !CONFIG_SDIO_HCI */
387
388 #ifdef DBG_IO
_halmac_reg_read_monitor(void * p,u32 addr,u32 len,u32 val,const char * caller,const u32 line)389 static void _halmac_reg_read_monitor(void *p, u32 addr, u32 len, u32 val
390 , const char *caller, const u32 line)
391 {
392 struct dvobj_priv *d = (struct dvobj_priv *)p;
393 _adapter *adapter = dvobj_get_primary_adapter(d);
394
395 dbg_rtw_reg_read_monitor(adapter, addr, len, val, caller, line);
396 }
397
_halmac_reg_write_monitor(void * p,u32 addr,u32 len,u32 val,const char * caller,const u32 line)398 static void _halmac_reg_write_monitor(void *p, u32 addr, u32 len, u32 val
399 , const char *caller, const u32 line)
400 {
401 struct dvobj_priv *d = (struct dvobj_priv *)p;
402 _adapter *adapter = dvobj_get_primary_adapter(d);
403
404 dbg_rtw_reg_write_monitor(adapter, addr, len, val, caller, line);
405 }
406 #endif
407
_halmac_mfree(void * p,void * buffer,u32 size)408 static u8 _halmac_mfree(void *p, void *buffer, u32 size)
409 {
410 rtw_mfree(buffer, size);
411 return RTW_HALMAC_SUCCESS;
412 }
413
_halmac_malloc(void * p,u32 size)414 static void *_halmac_malloc(void *p, u32 size)
415 {
416 return rtw_zmalloc(size);
417 }
418
_halmac_memcpy(void * p,void * dest,void * src,u32 size)419 static u8 _halmac_memcpy(void *p, void *dest, void *src, u32 size)
420 {
421 _rtw_memcpy(dest, src, size);
422 return RTW_HALMAC_SUCCESS;
423 }
424
_halmac_memset(void * p,void * addr,u8 value,u32 size)425 static u8 _halmac_memset(void *p, void *addr, u8 value, u32 size)
426 {
427 _rtw_memset(addr, value, size);
428 return RTW_HALMAC_SUCCESS;
429 }
430
_halmac_udelay(void * p,u32 us)431 static void _halmac_udelay(void *p, u32 us)
432 {
433 /* Most hardware polling wait time < 50us) */
434 if (us <= 50)
435 rtw_udelay_os(us);
436 else if (us <= 1000)
437 rtw_usleep_os(us);
438 else
439 rtw_msleep_os(RTW_DIV_ROUND_UP(us, 1000));
440 }
441
_halmac_mutex_init(void * p,HALMAC_MUTEX * pMutex)442 static u8 _halmac_mutex_init(void *p, HALMAC_MUTEX *pMutex)
443 {
444 _rtw_mutex_init(pMutex);
445 return RTW_HALMAC_SUCCESS;
446 }
447
_halmac_mutex_deinit(void * p,HALMAC_MUTEX * pMutex)448 static u8 _halmac_mutex_deinit(void *p, HALMAC_MUTEX *pMutex)
449 {
450 _rtw_mutex_free(pMutex);
451 return RTW_HALMAC_SUCCESS;
452 }
453
_halmac_mutex_lock(void * p,HALMAC_MUTEX * pMutex)454 static u8 _halmac_mutex_lock(void *p, HALMAC_MUTEX *pMutex)
455 {
456 int err;
457
458 err = _enter_critical_mutex(pMutex, NULL);
459 if (err)
460 return RTW_HALMAC_FAIL;
461
462 return RTW_HALMAC_SUCCESS;
463 }
464
_halmac_mutex_unlock(void * p,HALMAC_MUTEX * pMutex)465 static u8 _halmac_mutex_unlock(void *p, HALMAC_MUTEX *pMutex)
466 {
467 _exit_critical_mutex(pMutex, NULL);
468 return RTW_HALMAC_SUCCESS;
469 }
470
471 #ifndef CONFIG_SDIO_HCI
472 #define DBG_MSG_FILTER
473 #endif
474
475 #ifdef DBG_MSG_FILTER
is_msg_allowed(uint drv_lv,u8 msg_lv)476 static u8 is_msg_allowed(uint drv_lv, u8 msg_lv)
477 {
478 switch (drv_lv) {
479 case _DRV_NONE_:
480 return _FALSE;
481
482 case _DRV_ALWAYS_:
483 if (msg_lv > HALMAC_DBG_ALWAYS)
484 return _FALSE;
485 break;
486 case _DRV_ERR_:
487 if (msg_lv > HALMAC_DBG_ERR)
488 return _FALSE;
489 break;
490 case _DRV_WARNING_:
491 if (msg_lv > HALMAC_DBG_WARN)
492 return _FALSE;
493 break;
494 case _DRV_INFO_:
495 if (msg_lv >= HALMAC_DBG_TRACE)
496 return _FALSE;
497 break;
498 }
499
500 return _TRUE;
501 }
502 #endif /* DBG_MSG_FILTER */
503
_halmac_msg_print(void * p,u32 msg_type,u8 msg_level,s8 * fmt,...)504 static u8 _halmac_msg_print(void *p, u32 msg_type, u8 msg_level, s8 *fmt, ...)
505 {
506 #define MSG_LEN 100
507 va_list args;
508 u8 str[MSG_LEN] = {0};
509 #ifdef DBG_MSG_FILTER
510 uint drv_level = _DRV_NONE_;
511 #endif
512 int err;
513 u8 ret = RTW_HALMAC_SUCCESS;
514
515
516 #ifdef DBG_MSG_FILTER
517 #ifdef CONFIG_RTW_DEBUG
518 drv_level = rtw_drv_log_level;
519 #endif
520 if (is_msg_allowed(drv_level, msg_level) == _FALSE)
521 return ret;
522 #endif
523
524 str[0] = '\n';
525 va_start(args, fmt);
526 err = vsnprintf(str, MSG_LEN, fmt, args);
527 va_end(args);
528
529 /* An output error is encountered */
530 if (err < 0)
531 return RTW_HALMAC_FAIL;
532 /* Output may be truncated due to size limit */
533 if ((err == (MSG_LEN - 1)) && (str[MSG_LEN - 2] != '\n'))
534 ret = RTW_HALMAC_FAIL;
535
536 if (msg_level == HALMAC_DBG_ALWAYS)
537 RTW_PRINT(MSG_PREFIX "%s", str);
538 else if (msg_level <= HALMAC_DBG_ERR)
539 RTW_ERR(MSG_PREFIX "%s", str);
540 else if (msg_level <= HALMAC_DBG_WARN)
541 RTW_WARN(MSG_PREFIX "%s", str);
542 else
543 RTW_DBG(MSG_PREFIX "%s", str);
544
545 return ret;
546 }
547
_halmac_buff_print(void * p,u32 msg_type,u8 msg_level,s8 * buf,u32 size)548 static u8 _halmac_buff_print(void *p, u32 msg_type, u8 msg_level, s8 *buf, u32 size)
549 {
550 if (msg_level <= HALMAC_DBG_WARN)
551 RTW_INFO_DUMP(MSG_PREFIX, buf, size);
552 else
553 RTW_DBG_DUMP(MSG_PREFIX, buf, size);
554
555 return RTW_HALMAC_SUCCESS;
556 }
557
558
559 const char *const RTW_HALMAC_FEATURE_NAME[] = {
560 "HALMAC_FEATURE_CFG_PARA",
561 "HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE",
562 "HALMAC_FEATURE_DUMP_LOGICAL_EFUSE",
563 "HALMAC_FEATURE_DUMP_LOGICAL_EFUSE_MASK",
564 "HALMAC_FEATURE_UPDATE_PACKET",
565 "HALMAC_FEATURE_SEND_SCAN_PACKET",
566 "HALMAC_FEATURE_DROP_SCAN_PACKET",
567 "HALMAC_FEATURE_UPDATE_DATAPACK",
568 "HALMAC_FEATURE_RUN_DATAPACK",
569 "HALMAC_FEATURE_CHANNEL_SWITCH",
570 "HALMAC_FEATURE_IQK",
571 "HALMAC_FEATURE_POWER_TRACKING",
572 "HALMAC_FEATURE_PSD",
573 "HALMAC_FEATURE_FW_SNDING",
574 "HALMAC_FEATURE_DPK",
575 "HALMAC_FEATURE_ALL"
576 };
577
is_valid_id_status(enum halmac_feature_id id,enum halmac_cmd_process_status status)578 static inline u8 is_valid_id_status(enum halmac_feature_id id, enum halmac_cmd_process_status status)
579 {
580 switch (id) {
581 case HALMAC_FEATURE_CFG_PARA:
582 RTW_DBG("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
583 break;
584 case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
585 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
586 if (HALMAC_CMD_PROCESS_DONE != status)
587 RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
588 __FUNCTION__, id, status);
589 break;
590 case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
591 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
592 if (HALMAC_CMD_PROCESS_DONE != status)
593 RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
594 __FUNCTION__, id, status);
595 break;
596 case HALMAC_FEATURE_UPDATE_PACKET:
597 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
598 if (status != HALMAC_CMD_PROCESS_DONE)
599 RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
600 __FUNCTION__, id, status);
601 break;
602 case HALMAC_FEATURE_UPDATE_DATAPACK:
603 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
604 break;
605 case HALMAC_FEATURE_RUN_DATAPACK:
606 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
607 break;
608 case HALMAC_FEATURE_CHANNEL_SWITCH:
609 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
610 if ((status != HALMAC_CMD_PROCESS_DONE) && (status != HALMAC_CMD_PROCESS_RCVD))
611 RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
612 __FUNCTION__, id, status);
613 if (status == HALMAC_CMD_PROCESS_DONE)
614 return _FALSE;
615 break;
616 case HALMAC_FEATURE_IQK:
617 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
618 break;
619 case HALMAC_FEATURE_POWER_TRACKING:
620 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
621 break;
622 case HALMAC_FEATURE_PSD:
623 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
624 break;
625 case HALMAC_FEATURE_FW_SNDING:
626 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
627 break;
628 case HALMAC_FEATURE_DPK:
629 if (status == HALMAC_CMD_PROCESS_RCVD)
630 return _FALSE;
631 if ((status != HALMAC_CMD_PROCESS_DONE)
632 || (status != HALMAC_CMD_PROCESS_ERROR))
633 RTW_WARN("%s: %s unexpected status(0x%x)!\n",
634 __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id],
635 status);
636 break;
637 case HALMAC_FEATURE_ALL:
638 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
639 break;
640 default:
641 RTW_ERR("%s: unknown feature id(%d)\n", __FUNCTION__, id);
642 return _FALSE;
643 }
644
645 return _TRUE;
646 }
647
init_halmac_event_with_waittime(struct dvobj_priv * d,enum halmac_feature_id id,u8 * buf,u32 size,u32 time)648 static int init_halmac_event_with_waittime(struct dvobj_priv *d, enum halmac_feature_id id, u8 *buf, u32 size, u32 time)
649 {
650 struct submit_ctx *sctx;
651
652
653 if (!d->hmpriv.indicator[id].sctx) {
654 sctx = (struct submit_ctx *)rtw_zmalloc(sizeof(*sctx));
655 if (!sctx)
656 return -1;
657 } else {
658 RTW_WARN("%s: id(%d) sctx is not NULL!!\n", __FUNCTION__, id);
659 sctx = d->hmpriv.indicator[id].sctx;
660 d->hmpriv.indicator[id].sctx = NULL;
661 }
662
663 rtw_sctx_init(sctx, time);
664 d->hmpriv.indicator[id].buffer = buf;
665 d->hmpriv.indicator[id].buf_size = size;
666 d->hmpriv.indicator[id].ret_size = 0;
667 d->hmpriv.indicator[id].status = 0;
668 /* fill sctx at least to sure other variables are all ready! */
669 d->hmpriv.indicator[id].sctx = sctx;
670
671 return 0;
672 }
673
init_halmac_event(struct dvobj_priv * d,enum halmac_feature_id id,u8 * buf,u32 size)674 static inline int init_halmac_event(struct dvobj_priv *d, enum halmac_feature_id id, u8 *buf, u32 size)
675 {
676 return init_halmac_event_with_waittime(d, id, buf, size, DEFAULT_INDICATOR_TIMELMT);
677 }
678
free_halmac_event(struct dvobj_priv * d,enum halmac_feature_id id)679 static void free_halmac_event(struct dvobj_priv *d, enum halmac_feature_id id)
680 {
681 struct submit_ctx *sctx;
682
683
684 if (!d->hmpriv.indicator[id].sctx)
685 return;
686
687 sctx = d->hmpriv.indicator[id].sctx;
688 d->hmpriv.indicator[id].sctx = NULL;
689 rtw_mfree((u8 *)sctx, sizeof(*sctx));
690 }
691
wait_halmac_event(struct dvobj_priv * d,enum halmac_feature_id id)692 static int wait_halmac_event(struct dvobj_priv *d, enum halmac_feature_id id)
693 {
694 struct halmac_adapter *mac;
695 struct halmac_api *api;
696 struct submit_ctx *sctx;
697 int status;
698 int ret;
699
700
701 sctx = d->hmpriv.indicator[id].sctx;
702 if (!sctx)
703 return -1;
704
705 ret = rtw_sctx_wait(sctx, RTW_HALMAC_FEATURE_NAME[id]);
706 status = sctx->status;
707 free_halmac_event(d, id);
708 if (_SUCCESS == ret)
709 return 0;
710
711 /* If no one change sctx->status, it is timeout case */
712 if (status == 0)
713 status = RTW_SCTX_DONE_TIMEOUT;
714 RTW_ERR("%s: id(%d, %s) status=0x%x ! Reset HALMAC state!\n",
715 __FUNCTION__, id, RTW_HALMAC_FEATURE_NAME[id], status);
716 mac = dvobj_to_halmac(d);
717 api = HALMAC_GET_API(mac);
718 api->halmac_reset_feature(mac, id);
719
720 return -1;
721 }
722
723 /*
724 * Return:
725 * Always return RTW_HALMAC_SUCCESS, HALMAC don't care the return value.
726 */
_halmac_event_indication(void * p,enum halmac_feature_id feature_id,enum halmac_cmd_process_status process_status,u8 * buf,u32 size)727 static u8 _halmac_event_indication(void *p, enum halmac_feature_id feature_id,
728 enum halmac_cmd_process_status process_status,
729 u8 *buf, u32 size)
730 {
731 struct dvobj_priv *d;
732 PADAPTER adapter;
733 PHAL_DATA_TYPE hal;
734 struct halmac_indicator *tbl, *indicator;
735 struct submit_ctx *sctx;
736 u32 cpsz;
737 u8 ret;
738
739
740 d = (struct dvobj_priv *)p;
741 adapter = dvobj_get_primary_adapter(d);
742 hal = GET_HAL_DATA(adapter);
743 tbl = d->hmpriv.indicator;
744
745 /* Filter(Skip) middle status indication */
746 ret = is_valid_id_status(feature_id, process_status);
747 if (_FALSE == ret)
748 goto exit;
749
750 indicator = &tbl[feature_id];
751 indicator->status = process_status;
752 indicator->ret_size = size;
753 if (!indicator->sctx) {
754 RTW_WARN("%s: id(%d, %s) is not waiting!!\n", __FUNCTION__,
755 feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
756 goto exit;
757 }
758 sctx = indicator->sctx;
759
760 if (HALMAC_CMD_PROCESS_ERROR == process_status) {
761 RTW_ERR("%s: id(%d, %s) Something wrong!!\n", __FUNCTION__,
762 feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
763 if ((size == 1) && buf)
764 RTW_ERR("%s: error code=0x%x\n", __FUNCTION__, *buf);
765 rtw_sctx_done_err(&sctx, RTW_SCTX_DONE_UNKNOWN);
766 goto exit;
767 }
768
769 if (size > indicator->buf_size) {
770 RTW_WARN("%s: id(%d, %s) buffer is not enough(%d<%d), "
771 "and data will be truncated!\n",
772 __FUNCTION__,
773 feature_id, RTW_HALMAC_FEATURE_NAME[feature_id],
774 indicator->buf_size, size);
775 cpsz = indicator->buf_size;
776 } else {
777 cpsz = size;
778 }
779 if (cpsz && indicator->buffer)
780 _rtw_memcpy(indicator->buffer, buf, cpsz);
781
782 rtw_sctx_done(&sctx);
783
784 exit:
785 return RTW_HALMAC_SUCCESS;
786 }
787
788 struct halmac_platform_api rtw_halmac_platform_api = {
789 /* R/W register */
790 #ifdef CONFIG_SDIO_HCI
791 .SDIO_CMD52_READ = _halmac_sdio_cmd52_read,
792 .SDIO_CMD53_READ_8 = _halmac_sdio_reg_read_8,
793 .SDIO_CMD53_READ_16 = _halmac_sdio_reg_read_16,
794 .SDIO_CMD53_READ_32 = _halmac_sdio_reg_read_32,
795 .SDIO_CMD53_READ_N = _halmac_sdio_reg_read_n,
796 .SDIO_CMD52_WRITE = _halmac_sdio_cmd52_write,
797 .SDIO_CMD53_WRITE_8 = _halmac_sdio_reg_write_8,
798 .SDIO_CMD53_WRITE_16 = _halmac_sdio_reg_write_16,
799 .SDIO_CMD53_WRITE_32 = _halmac_sdio_reg_write_32,
800 .SDIO_CMD52_CIA_READ = _halmac_sdio_read_cia,
801 #endif /* CONFIG_SDIO_HCI */
802 #if defined(CONFIG_USB_HCI) || defined(CONFIG_PCI_HCI)
803 .REG_READ_8 = _halmac_reg_read_8,
804 .REG_READ_16 = _halmac_reg_read_16,
805 .REG_READ_32 = _halmac_reg_read_32,
806 .REG_WRITE_8 = _halmac_reg_write_8,
807 .REG_WRITE_16 = _halmac_reg_write_16,
808 .REG_WRITE_32 = _halmac_reg_write_32,
809 #endif /* CONFIG_USB_HCI || CONFIG_PCI_HCI */
810
811 #ifdef DBG_IO
812 .READ_MONITOR = _halmac_reg_read_monitor,
813 .WRITE_MONITOR = _halmac_reg_write_monitor,
814 #endif
815
816 /* Write data */
817 #if 0
818 /* impletement in HAL-IC level */
819 .SEND_RSVD_PAGE = sdio_write_data_rsvd_page,
820 .SEND_H2C_PKT = sdio_write_data_h2c,
821 #endif
822 /* Memory allocate */
823 .RTL_FREE = _halmac_mfree,
824 .RTL_MALLOC = _halmac_malloc,
825 .RTL_MEMCPY = _halmac_memcpy,
826 .RTL_MEMSET = _halmac_memset,
827
828 /* Sleep */
829 .RTL_DELAY_US = _halmac_udelay,
830
831 /* Process Synchronization */
832 .MUTEX_INIT = _halmac_mutex_init,
833 .MUTEX_DEINIT = _halmac_mutex_deinit,
834 .MUTEX_LOCK = _halmac_mutex_lock,
835 .MUTEX_UNLOCK = _halmac_mutex_unlock,
836
837 .MSG_PRINT = _halmac_msg_print,
838 .BUFF_PRINT = _halmac_buff_print,
839 .EVENT_INDICATION = _halmac_event_indication,
840 };
841
rtw_halmac_read8(struct intf_hdl * pintfhdl,u32 addr)842 u8 rtw_halmac_read8(struct intf_hdl *pintfhdl, u32 addr)
843 {
844 struct halmac_adapter *mac;
845 struct halmac_api *api;
846
847
848 /* WARNING: pintf_dev should not be null! */
849 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
850 api = HALMAC_GET_API(mac);
851
852 return api->halmac_reg_read_8(mac, addr);
853 }
854
rtw_halmac_read16(struct intf_hdl * pintfhdl,u32 addr)855 u16 rtw_halmac_read16(struct intf_hdl *pintfhdl, u32 addr)
856 {
857 struct halmac_adapter *mac;
858 struct halmac_api *api;
859
860
861 /* WARNING: pintf_dev should not be null! */
862 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
863 api = HALMAC_GET_API(mac);
864
865 return api->halmac_reg_read_16(mac, addr);
866 }
867
rtw_halmac_read32(struct intf_hdl * pintfhdl,u32 addr)868 u32 rtw_halmac_read32(struct intf_hdl *pintfhdl, u32 addr)
869 {
870 struct halmac_adapter *mac;
871 struct halmac_api *api;
872
873
874 /* WARNING: pintf_dev should not be null! */
875 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
876 api = HALMAC_GET_API(mac);
877
878 return api->halmac_reg_read_32(mac, addr);
879 }
880
_read_register(struct dvobj_priv * d,u32 addr,u32 cnt,u8 * buf)881 static void _read_register(struct dvobj_priv *d, u32 addr, u32 cnt, u8 *buf)
882 {
883 #if 1
884 struct _ADAPTER *a;
885 u32 i, n;
886 u16 val16;
887 u32 val32;
888
889
890 a = dvobj_get_primary_adapter(d);
891
892 i = addr & 0x3;
893 /* Handle address not start from 4 bytes alignment case */
894 if (i) {
895 val32 = cpu_to_le32(rtw_read32(a, addr & ~0x3));
896 n = 4 - i;
897 _rtw_memcpy(buf, ((u8 *)&val32) + i, n);
898 i = n;
899 cnt -= n;
900 }
901
902 while (cnt) {
903 if (cnt >= 4)
904 n = 4;
905 else if (cnt >= 2)
906 n = 2;
907 else
908 n = 1;
909 cnt -= n;
910
911 switch (n) {
912 case 1:
913 buf[i] = rtw_read8(a, addr+i);
914 i++;
915 break;
916 case 2:
917 val16 = cpu_to_le16(rtw_read16(a, addr+i));
918 _rtw_memcpy(&buf[i], &val16, 2);
919 i += 2;
920 break;
921 case 4:
922 val32 = cpu_to_le32(rtw_read32(a, addr+i));
923 _rtw_memcpy(&buf[i], &val32, 4);
924 i += 4;
925 break;
926 }
927 }
928 #else
929 struct _ADAPTER *a;
930 u32 i;
931
932
933 a = dvobj_get_primary_adapter(d);
934 for (i = 0; i < cnt; i++)
935 buf[i] = rtw_read8(a, addr + i);
936 #endif
937 }
938
939 #ifdef CONFIG_SDIO_HCI
_sdio_read_local(struct dvobj_priv * d,u32 addr,u32 cnt,u8 * buf)940 static int _sdio_read_local(struct dvobj_priv *d, u32 addr, u32 cnt, u8 *buf)
941 {
942 struct halmac_adapter *mac;
943 struct halmac_api *api;
944 enum halmac_ret_status status;
945
946
947 if (buf == NULL)
948 return -1;
949
950 mac = dvobj_to_halmac(d);
951 api = HALMAC_GET_API(mac);
952
953 status = api->halmac_reg_sdio_cmd53_read_n(mac, addr, cnt, buf);
954 if (status != HALMAC_RET_SUCCESS) {
955 RTW_ERR("%s: addr=0x%08x cnt=%d err=%d\n",
956 __FUNCTION__, addr, cnt, status);
957 return -1;
958 }
959
960 return 0;
961 }
962 #endif /* CONFIG_SDIO_HCI */
963
rtw_halmac_read_mem(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * pmem)964 void rtw_halmac_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem)
965 {
966 struct dvobj_priv *d;
967
968
969 if (pmem == NULL) {
970 RTW_ERR("pmem is NULL\n");
971 return;
972 }
973
974 d = pintfhdl->pintf_dev;
975
976 #ifdef CONFIG_SDIO_HCI
977 if (addr & 0xFFFF0000) {
978 int err = 0;
979
980 err = _sdio_read_local(d, addr, cnt, pmem);
981 if (!err)
982 return;
983 }
984 #endif /* CONFIG_SDIO_HCI */
985
986 _read_register(d, addr, cnt, pmem);
987 }
988
989 #ifdef CONFIG_SDIO_INDIRECT_ACCESS
rtw_halmac_iread8(struct intf_hdl * pintfhdl,u32 addr)990 u8 rtw_halmac_iread8(struct intf_hdl *pintfhdl, u32 addr)
991 {
992 struct halmac_adapter *mac;
993 struct halmac_api *api;
994
995 /* WARNING: pintf_dev should not be null! */
996 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
997 api = HALMAC_GET_API(mac);
998
999 /*return api->halmac_reg_read_indirect_8(mac, addr);*/
1000 return api->halmac_reg_read_8(mac, addr);
1001 }
1002
rtw_halmac_iread16(struct intf_hdl * pintfhdl,u32 addr)1003 u16 rtw_halmac_iread16(struct intf_hdl *pintfhdl, u32 addr)
1004 {
1005 struct halmac_adapter *mac;
1006 struct halmac_api *api;
1007 u16 val16 = 0;
1008
1009 /* WARNING: pintf_dev should not be null! */
1010 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
1011 api = HALMAC_GET_API(mac);
1012
1013 /*return api->halmac_reg_read_indirect_16(mac, addr);*/
1014 return api->halmac_reg_read_16(mac, addr);
1015 }
1016
rtw_halmac_iread32(struct intf_hdl * pintfhdl,u32 addr)1017 u32 rtw_halmac_iread32(struct intf_hdl *pintfhdl, u32 addr)
1018 {
1019 struct halmac_adapter *mac;
1020 struct halmac_api *api;
1021
1022
1023 /* WARNING: pintf_dev should not be null! */
1024 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
1025 api = HALMAC_GET_API(mac);
1026
1027 return api->halmac_reg_read_indirect_32(mac, addr);
1028 }
1029 #endif /* CONFIG_SDIO_INDIRECT_ACCESS */
1030
rtw_halmac_write8(struct intf_hdl * pintfhdl,u32 addr,u8 value)1031 int rtw_halmac_write8(struct intf_hdl *pintfhdl, u32 addr, u8 value)
1032 {
1033 struct halmac_adapter *mac;
1034 struct halmac_api *api;
1035 enum halmac_ret_status status;
1036
1037
1038 /* WARNING: pintf_dev should not be null! */
1039 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
1040 api = HALMAC_GET_API(mac);
1041
1042 status = api->halmac_reg_write_8(mac, addr, value);
1043
1044 if (status == HALMAC_RET_SUCCESS)
1045 return 0;
1046
1047 return -1;
1048 }
1049
rtw_halmac_write16(struct intf_hdl * pintfhdl,u32 addr,u16 value)1050 int rtw_halmac_write16(struct intf_hdl *pintfhdl, u32 addr, u16 value)
1051 {
1052 struct halmac_adapter *mac;
1053 struct halmac_api *api;
1054 enum halmac_ret_status status;
1055
1056
1057 /* WARNING: pintf_dev should not be null! */
1058 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
1059 api = HALMAC_GET_API(mac);
1060
1061 status = api->halmac_reg_write_16(mac, addr, value);
1062
1063 if (status == HALMAC_RET_SUCCESS)
1064 return 0;
1065
1066 return -1;
1067 }
1068
rtw_halmac_write32(struct intf_hdl * pintfhdl,u32 addr,u32 value)1069 int rtw_halmac_write32(struct intf_hdl *pintfhdl, u32 addr, u32 value)
1070 {
1071 struct halmac_adapter *mac;
1072 struct halmac_api *api;
1073 enum halmac_ret_status status;
1074
1075
1076 /* WARNING: pintf_dev should not be null! */
1077 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
1078 api = HALMAC_GET_API(mac);
1079
1080 status = api->halmac_reg_write_32(mac, addr, value);
1081
1082 if (status == HALMAC_RET_SUCCESS)
1083 return 0;
1084
1085 return -1;
1086 }
1087
init_write_rsvd_page_size(struct dvobj_priv * d)1088 static int init_write_rsvd_page_size(struct dvobj_priv *d)
1089 {
1090 struct halmac_adapter *mac;
1091 struct halmac_api *api;
1092 u32 size = 0;
1093 struct halmac_ofld_func_info ofld_info;
1094 enum halmac_ret_status status;
1095 int err = 0;
1096
1097
1098 #ifdef CONFIG_USB_HCI
1099 /* for USB do not exceed MAX_CMDBUF_SZ */
1100 size = 0x1000;
1101 #elif defined(CONFIG_PCI_HCI)
1102 size = MAX_CMDBUF_SZ - TXDESC_OFFSET;
1103 #elif defined(CONFIG_SDIO_HCI)
1104 size = 0x7000; /* 28KB */
1105 #else
1106 /* Use HALMAC default setting and don't call any function */
1107 return 0;
1108 #endif
1109 #if 0 /* Fail to pass coverity DEADCODE check */
1110 /* If size==0, use HALMAC default setting and don't call any function */
1111 if (!size)
1112 return 0;
1113 #endif
1114 err = rtw_halmac_set_max_dl_fw_size(d, size);
1115 if (err) {
1116 RTW_ERR("%s: Fail to set max download fw size!\n", __FUNCTION__);
1117 return -1;
1118 }
1119
1120 mac = dvobj_to_halmac(d);
1121 api = HALMAC_GET_API(mac);
1122
1123 _rtw_memset(&ofld_info, 0, sizeof(ofld_info));
1124 ofld_info.halmac_malloc_max_sz = 0xFFFFFFFF;
1125 ofld_info.rsvd_pg_drv_buf_max_sz = size;
1126 status = api->halmac_ofld_func_cfg(mac, &ofld_info);
1127 if (status != HALMAC_RET_SUCCESS) {
1128 RTW_ERR("%s: Fail to config offload parameters!\n", __FUNCTION__);
1129 return -1;
1130 }
1131
1132 return 0;
1133 }
1134
init_priv(struct halmacpriv * priv)1135 static int init_priv(struct halmacpriv *priv)
1136 {
1137 struct halmac_indicator *indicator;
1138 u32 count, size;
1139
1140
1141 if (priv->indicator)
1142 RTW_WARN("%s: HALMAC private data is not CLEAR!\n", __FUNCTION__);
1143 count = HALMAC_FEATURE_ALL + 1;
1144 size = sizeof(*indicator) * count;
1145 indicator = (struct halmac_indicator *)rtw_zmalloc(size);
1146 if (!indicator)
1147 return -1;
1148 priv->indicator = indicator;
1149
1150 return 0;
1151 }
1152
deinit_priv(struct halmacpriv * priv)1153 static void deinit_priv(struct halmacpriv *priv)
1154 {
1155 struct halmac_indicator *indicator;
1156
1157
1158 indicator = priv->indicator;
1159 priv->indicator = NULL;
1160 if (indicator) {
1161 u32 count, size;
1162
1163 count = HALMAC_FEATURE_ALL + 1;
1164 #ifdef CONFIG_RTW_DEBUG
1165 {
1166 struct submit_ctx *sctx;
1167 u32 i;
1168
1169 for (i = 0; i < count; i++) {
1170 if (!indicator[i].sctx)
1171 continue;
1172
1173 RTW_WARN("%s: %s id(%d) sctx still exist!!\n",
1174 __FUNCTION__, RTW_HALMAC_FEATURE_NAME[i], i);
1175 sctx = indicator[i].sctx;
1176 indicator[i].sctx = NULL;
1177 rtw_mfree((u8 *)sctx, sizeof(*sctx));
1178 }
1179 }
1180 #endif /* !CONFIG_RTW_DEBUG */
1181 size = sizeof(*indicator) * count;
1182 rtw_mfree((u8 *)indicator, size);
1183 }
1184 }
1185
1186 #ifdef CONFIG_SDIO_HCI
_sdio_ver_drv2halmac(struct dvobj_priv * d)1187 static enum halmac_sdio_spec_ver _sdio_ver_drv2halmac(struct dvobj_priv *d)
1188 {
1189 bool v3;
1190 enum halmac_sdio_spec_ver ver;
1191
1192
1193 v3 = rtw_is_sdio30(dvobj_get_primary_adapter(d));
1194 if (v3)
1195 ver = HALMAC_SDIO_SPEC_VER_3_00;
1196 else
1197 ver = HALMAC_SDIO_SPEC_VER_2_00;
1198
1199 return ver;
1200 }
1201 #endif /* CONFIG_SDIO_HCI */
1202
rtw_halmac_get_version(char * str,u32 len)1203 void rtw_halmac_get_version(char *str, u32 len)
1204 {
1205 enum halmac_ret_status status;
1206 struct halmac_ver ver;
1207
1208
1209 status = halmac_get_version(&ver);
1210 if (status != HALMAC_RET_SUCCESS)
1211 return;
1212
1213 rtw_sprintf(str, len, "V%d_%02d_%02d",
1214 ver.major_ver, ver.prototype_ver, ver.minor_ver);
1215 }
1216
rtw_halmac_init_adapter(struct dvobj_priv * d,struct halmac_platform_api * pf_api)1217 int rtw_halmac_init_adapter(struct dvobj_priv *d, struct halmac_platform_api *pf_api)
1218 {
1219 struct halmac_adapter *halmac;
1220 struct halmac_api *api;
1221 enum halmac_interface intf;
1222 enum halmac_ret_status status;
1223 int err = 0;
1224 #ifdef CONFIG_SDIO_HCI
1225 struct halmac_sdio_hw_info info;
1226 #endif /* CONFIG_SDIO_HCI */
1227
1228
1229 halmac = dvobj_to_halmac(d);
1230 if (halmac) {
1231 RTW_WARN("%s: initialize already completed!\n", __FUNCTION__);
1232 goto error;
1233 }
1234
1235 err = init_priv(&d->hmpriv);
1236 if (err)
1237 goto error;
1238
1239 #ifdef CONFIG_SDIO_HCI
1240 intf = HALMAC_INTERFACE_SDIO;
1241 #elif defined(CONFIG_USB_HCI)
1242 intf = HALMAC_INTERFACE_USB;
1243 #elif defined(CONFIG_PCI_HCI)
1244 intf = HALMAC_INTERFACE_PCIE;
1245 #else
1246 #warning "INTERFACE(CONFIG_XXX_HCI) not be defined!!"
1247 intf = HALMAC_INTERFACE_UNDEFINE;
1248 #endif
1249 status = halmac_init_adapter(d, pf_api, intf, &halmac, &api);
1250 if (HALMAC_RET_SUCCESS != status) {
1251 RTW_ERR("%s: halmac_init_adapter fail!(status=%d)\n", __FUNCTION__, status);
1252 err = -1;
1253 if (halmac)
1254 goto deinit;
1255 goto free;
1256 }
1257
1258 dvobj_set_halmac(d, halmac);
1259
1260 status = api->halmac_interface_integration_tuning(halmac);
1261 if (status != HALMAC_RET_SUCCESS) {
1262 RTW_ERR("%s: halmac_interface_integration_tuning fail!(status=%d)\n", __FUNCTION__, status);
1263 err = -1;
1264 goto deinit;
1265 }
1266
1267 status = api->halmac_phy_cfg(halmac, HALMAC_INTF_PHY_PLATFORM_ALL);
1268 if (status != HALMAC_RET_SUCCESS) {
1269 RTW_ERR("%s: halmac_phy_cfg fail!(status=%d)\n", __FUNCTION__, status);
1270 err = -1;
1271 goto deinit;
1272 }
1273
1274 init_write_rsvd_page_size(d);
1275
1276 #ifdef CONFIG_SDIO_HCI
1277 _rtw_memset(&info, 0, sizeof(info));
1278 info.spec_ver = _sdio_ver_drv2halmac(d);
1279 /* Convert clock speed unit to MHz from Hz */
1280 info.clock_speed = RTW_DIV_ROUND_UP(rtw_sdio_get_clock(d), 1000000);
1281 info.block_size = rtw_sdio_get_block_size(d);
1282 if (d->hmpriv.sdio_io_indir == 2)
1283 info.io_indir_flag = 0;
1284 else
1285 info.io_indir_flag = 1; /* Default enable indirect I/O */
1286 RTW_DBG("%s: SDIO ver=%u clock=%uMHz blk_size=%u bytes, io_indir=%u\n",
1287 __FUNCTION__, info.spec_ver+2, info.clock_speed,
1288 info.block_size, info.io_indir_flag);
1289 status = api->halmac_sdio_hw_info(halmac, &info);
1290 if (status != HALMAC_RET_SUCCESS) {
1291 RTW_ERR("%s: halmac_sdio_hw_info fail!(status=%d)\n",
1292 __FUNCTION__, status);
1293 err = -1;
1294 goto deinit;
1295 }
1296 #endif /* CONFIG_SDIO_HCI */
1297
1298 return 0;
1299
1300 deinit:
1301 status = halmac_deinit_adapter(halmac);
1302 dvobj_set_halmac(d, NULL);
1303 if (status != HALMAC_RET_SUCCESS)
1304 RTW_ERR("%s: halmac_deinit_adapter fail!(status=%d)\n",
1305 __FUNCTION__, status);
1306
1307 free:
1308 deinit_priv(&d->hmpriv);
1309
1310 error:
1311 return err;
1312 }
1313
rtw_halmac_deinit_adapter(struct dvobj_priv * d)1314 int rtw_halmac_deinit_adapter(struct dvobj_priv *d)
1315 {
1316 struct halmac_adapter *halmac;
1317 enum halmac_ret_status status;
1318 int err = 0;
1319
1320
1321 halmac = dvobj_to_halmac(d);
1322 if (halmac) {
1323 status = halmac_deinit_adapter(halmac);
1324 dvobj_set_halmac(d, NULL);
1325 if (status != HALMAC_RET_SUCCESS)
1326 err = -1;
1327 }
1328
1329 deinit_priv(&d->hmpriv);
1330
1331 return err;
1332 }
1333
_hw_port_drv2halmac(enum _hw_port hwport)1334 static inline enum halmac_portid _hw_port_drv2halmac(enum _hw_port hwport)
1335 {
1336 enum halmac_portid port = HALMAC_PORTID_NUM;
1337
1338
1339 switch (hwport) {
1340 case HW_PORT0:
1341 port = HALMAC_PORTID0;
1342 break;
1343 case HW_PORT1:
1344 port = HALMAC_PORTID1;
1345 break;
1346 case HW_PORT2:
1347 port = HALMAC_PORTID2;
1348 break;
1349 case HW_PORT3:
1350 port = HALMAC_PORTID3;
1351 break;
1352 case HW_PORT4:
1353 port = HALMAC_PORTID4;
1354 break;
1355 default:
1356 break;
1357 }
1358
1359 return port;
1360 }
1361
_network_type_drv2halmac(u8 type)1362 static enum halmac_network_type_select _network_type_drv2halmac(u8 type)
1363 {
1364 enum halmac_network_type_select network = HALMAC_NETWORK_UNDEFINE;
1365
1366
1367 switch (type) {
1368 case _HW_STATE_NOLINK_:
1369 case _HW_STATE_MONITOR_:
1370 network = HALMAC_NETWORK_NO_LINK;
1371 break;
1372
1373 case _HW_STATE_ADHOC_:
1374 network = HALMAC_NETWORK_ADHOC;
1375 break;
1376
1377 case _HW_STATE_STATION_:
1378 network = HALMAC_NETWORK_INFRASTRUCTURE;
1379 break;
1380
1381 case _HW_STATE_AP_:
1382 network = HALMAC_NETWORK_AP;
1383 break;
1384 }
1385
1386 return network;
1387 }
1388
_network_type_halmac2drv(enum halmac_network_type_select network)1389 static u8 _network_type_halmac2drv(enum halmac_network_type_select network)
1390 {
1391 u8 type = _HW_STATE_NOLINK_;
1392
1393
1394 switch (network) {
1395 case HALMAC_NETWORK_NO_LINK:
1396 case HALMAC_NETWORK_UNDEFINE:
1397 type = _HW_STATE_NOLINK_;
1398 break;
1399
1400 case HALMAC_NETWORK_ADHOC:
1401 type = _HW_STATE_ADHOC_;
1402 break;
1403
1404 case HALMAC_NETWORK_INFRASTRUCTURE:
1405 type = _HW_STATE_STATION_;
1406 break;
1407
1408 case HALMAC_NETWORK_AP:
1409 type = _HW_STATE_AP_;
1410 break;
1411 }
1412
1413 return type;
1414 }
1415
_beacon_ctrl_halmac2drv(struct halmac_bcn_ctrl * ctrl,struct rtw_halmac_bcn_ctrl * drv_ctrl)1416 static void _beacon_ctrl_halmac2drv(struct halmac_bcn_ctrl *ctrl,
1417 struct rtw_halmac_bcn_ctrl *drv_ctrl)
1418 {
1419 drv_ctrl->rx_bssid_fit = ctrl->dis_rx_bssid_fit ? 0 : 1;
1420 drv_ctrl->txbcn_rpt = ctrl->en_txbcn_rpt ? 1 : 0;
1421 drv_ctrl->tsf_update = ctrl->dis_tsf_udt ? 0 : 1;
1422 drv_ctrl->enable_bcn = ctrl->en_bcn ? 1 : 0;
1423 drv_ctrl->rxbcn_rpt = ctrl->en_rxbcn_rpt ? 1 : 0;
1424 drv_ctrl->p2p_ctwin = ctrl->en_p2p_ctwin ? 1 : 0;
1425 drv_ctrl->p2p_bcn_area = ctrl->en_p2p_bcn_area ? 1 : 0;
1426 }
1427
_beacon_ctrl_drv2halmac(struct rtw_halmac_bcn_ctrl * drv_ctrl,struct halmac_bcn_ctrl * ctrl)1428 static void _beacon_ctrl_drv2halmac(struct rtw_halmac_bcn_ctrl *drv_ctrl,
1429 struct halmac_bcn_ctrl *ctrl)
1430 {
1431 ctrl->dis_rx_bssid_fit = drv_ctrl->rx_bssid_fit ? 0 : 1;
1432 ctrl->en_txbcn_rpt = drv_ctrl->txbcn_rpt ? 1 : 0;
1433 ctrl->dis_tsf_udt = drv_ctrl->tsf_update ? 0 : 1;
1434 ctrl->en_bcn = drv_ctrl->enable_bcn ? 1 : 0;
1435 ctrl->en_rxbcn_rpt = drv_ctrl->rxbcn_rpt ? 1 : 0;
1436 ctrl->en_p2p_ctwin = drv_ctrl->p2p_ctwin ? 1 : 0;
1437 ctrl->en_p2p_bcn_area = drv_ctrl->p2p_bcn_area ? 1 : 0;
1438 }
1439
rtw_halmac_get_hw_value(struct dvobj_priv * d,enum halmac_hw_id hw_id,void * pvalue)1440 int rtw_halmac_get_hw_value(struct dvobj_priv *d, enum halmac_hw_id hw_id, void *pvalue)
1441 {
1442 struct halmac_adapter *mac;
1443 struct halmac_api *api;
1444 enum halmac_ret_status status;
1445
1446
1447 mac = dvobj_to_halmac(d);
1448 api = HALMAC_GET_API(mac);
1449
1450 status = api->halmac_get_hw_value(mac, hw_id, pvalue);
1451 if (HALMAC_RET_SUCCESS != status)
1452 return -1;
1453
1454 return 0;
1455 }
1456
1457 /**
1458 * rtw_halmac_get_tx_fifo_size() - TX FIFO size
1459 * @d: struct dvobj_priv*
1460 * @size: TX FIFO size, unit is byte.
1461 *
1462 * Get TX FIFO size(byte) from HALMAC.
1463 *
1464 * Return 0 for OK, otherwise fail.
1465 */
rtw_halmac_get_tx_fifo_size(struct dvobj_priv * d,u32 * size)1466 int rtw_halmac_get_tx_fifo_size(struct dvobj_priv *d, u32 *size)
1467 {
1468 struct halmac_adapter *halmac;
1469 struct halmac_api *api;
1470 enum halmac_ret_status status;
1471 u32 val = 0;
1472
1473
1474 halmac = dvobj_to_halmac(d);
1475 api = HALMAC_GET_API(halmac);
1476
1477 status = api->halmac_get_hw_value(halmac, HALMAC_HW_TXFIFO_SIZE, &val);
1478 if (status != HALMAC_RET_SUCCESS)
1479 return -1;
1480
1481 *size = val;
1482
1483 return 0;
1484 }
1485
1486 /**
1487 * rtw_halmac_get_rx_fifo_size() - RX FIFO size
1488 * @d: struct dvobj_priv*
1489 * @size: RX FIFO size, unit is byte
1490 *
1491 * Get RX FIFO size(byte) from HALMAC.
1492 *
1493 * Return 0 for OK, otherwise fail.
1494 */
rtw_halmac_get_rx_fifo_size(struct dvobj_priv * d,u32 * size)1495 int rtw_halmac_get_rx_fifo_size(struct dvobj_priv *d, u32 *size)
1496 {
1497 struct halmac_adapter *halmac;
1498 struct halmac_api *api;
1499 enum halmac_ret_status status;
1500 u32 val = 0;
1501
1502
1503 halmac = dvobj_to_halmac(d);
1504 api = HALMAC_GET_API(halmac);
1505
1506 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RXFIFO_SIZE, &val);
1507 if (status != HALMAC_RET_SUCCESS)
1508 return -1;
1509
1510 *size = val;
1511
1512 return 0;
1513 }
1514
1515 /**
1516 * rtw_halmac_get_rsvd_drv_pg_bndy() - Reserve page boundary of driver
1517 * @d: struct dvobj_priv*
1518 * @size: Page size, unit is byte
1519 *
1520 * Get reserve page boundary of driver from HALMAC.
1521 *
1522 * Return 0 for OK, otherwise fail.
1523 */
rtw_halmac_get_rsvd_drv_pg_bndy(struct dvobj_priv * d,u16 * bndy)1524 int rtw_halmac_get_rsvd_drv_pg_bndy(struct dvobj_priv *d, u16 *bndy)
1525 {
1526 struct halmac_adapter *halmac;
1527 struct halmac_api *api;
1528 enum halmac_ret_status status;
1529 u16 val = 0;
1530
1531
1532 halmac = dvobj_to_halmac(d);
1533 api = HALMAC_GET_API(halmac);
1534
1535 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RSVD_PG_BNDY, &val);
1536 if (status != HALMAC_RET_SUCCESS)
1537 return -1;
1538
1539 *bndy = val;
1540
1541 return 0;
1542 }
1543
1544 /**
1545 * rtw_halmac_get_page_size() - Page size
1546 * @d: struct dvobj_priv*
1547 * @size: Page size, unit is byte
1548 *
1549 * Get TX/RX page size(byte) from HALMAC.
1550 *
1551 * Return 0 for OK, otherwise fail.
1552 */
rtw_halmac_get_page_size(struct dvobj_priv * d,u32 * size)1553 int rtw_halmac_get_page_size(struct dvobj_priv *d, u32 *size)
1554 {
1555 struct halmac_adapter *halmac;
1556 struct halmac_api *api;
1557 enum halmac_ret_status status;
1558 u32 val = 0;
1559
1560
1561 halmac = dvobj_to_halmac(d);
1562 api = HALMAC_GET_API(halmac);
1563
1564 status = api->halmac_get_hw_value(halmac, HALMAC_HW_PAGE_SIZE, &val);
1565 if (status != HALMAC_RET_SUCCESS)
1566 return -1;
1567
1568 *size = val;
1569
1570 return 0;
1571 }
1572
1573 /**
1574 * rtw_halmac_get_tx_agg_align_size() - TX aggregation align size
1575 * @d: struct dvobj_priv*
1576 * @size: TX aggregation align size, unit is byte
1577 *
1578 * Get TX aggregation align size(byte) from HALMAC.
1579 *
1580 * Return 0 for OK, otherwise fail.
1581 */
rtw_halmac_get_tx_agg_align_size(struct dvobj_priv * d,u16 * size)1582 int rtw_halmac_get_tx_agg_align_size(struct dvobj_priv *d, u16 *size)
1583 {
1584 struct halmac_adapter *halmac;
1585 struct halmac_api *api;
1586 enum halmac_ret_status status;
1587 u16 val = 0;
1588
1589
1590 halmac = dvobj_to_halmac(d);
1591 api = HALMAC_GET_API(halmac);
1592
1593 status = api->halmac_get_hw_value(halmac, HALMAC_HW_TX_AGG_ALIGN_SIZE, &val);
1594 if (status != HALMAC_RET_SUCCESS)
1595 return -1;
1596
1597 *size = val;
1598
1599 return 0;
1600 }
1601
1602 /**
1603 * rtw_halmac_get_rx_agg_align_size() - RX aggregation align size
1604 * @d: struct dvobj_priv*
1605 * @size: RX aggregation align size, unit is byte
1606 *
1607 * Get RX aggregation align size(byte) from HALMAC.
1608 *
1609 * Return 0 for OK, otherwise fail.
1610 */
rtw_halmac_get_rx_agg_align_size(struct dvobj_priv * d,u8 * size)1611 int rtw_halmac_get_rx_agg_align_size(struct dvobj_priv *d, u8 *size)
1612 {
1613 struct halmac_adapter *halmac;
1614 struct halmac_api *api;
1615 enum halmac_ret_status status;
1616 u8 val = 0;
1617
1618
1619 halmac = dvobj_to_halmac(d);
1620 api = HALMAC_GET_API(halmac);
1621
1622 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RX_AGG_ALIGN_SIZE, &val);
1623 if (status != HALMAC_RET_SUCCESS)
1624 return -1;
1625
1626 *size = val;
1627
1628 return 0;
1629 }
1630
1631 /*
1632 * Description:
1633 * Get RX driver info size. RX driver info is a small memory space between
1634 * scriptor and RX payload.
1635 *
1636 * +-------------------------+
1637 * | RX descriptor |
1638 * | usually 24 bytes |
1639 * +-------------------------+
1640 * | RX driver info |
1641 * | depends on driver cfg |
1642 * +-------------------------+
1643 * | RX paylad |
1644 * | |
1645 * +-------------------------+
1646 *
1647 * Parameter:
1648 * d pointer to struct dvobj_priv of driver
1649 * sz rx driver info size in bytes.
1650 *
1651 * Return:
1652 * 0 Success
1653 * other Fail
1654 */
rtw_halmac_get_rx_drv_info_sz(struct dvobj_priv * d,u8 * sz)1655 int rtw_halmac_get_rx_drv_info_sz(struct dvobj_priv *d, u8 *sz)
1656 {
1657 enum halmac_ret_status status;
1658 struct halmac_adapter *halmac = dvobj_to_halmac(d);
1659 struct halmac_api *api = HALMAC_GET_API(halmac);
1660 u8 dw = 0;
1661
1662 status = api->halmac_get_hw_value(halmac, HALMAC_HW_DRV_INFO_SIZE, &dw);
1663 if (status != HALMAC_RET_SUCCESS)
1664 return -1;
1665
1666 *sz = dw * 8;
1667 return 0;
1668 }
1669
1670 /**
1671 * rtw_halmac_get_tx_desc_size() - TX descriptor size
1672 * @d: struct dvobj_priv*
1673 * @size: TX descriptor size, unit is byte.
1674 *
1675 * Get TX descriptor size(byte) from HALMAC.
1676 *
1677 * Return 0 for OK, otherwise fail.
1678 */
rtw_halmac_get_tx_desc_size(struct dvobj_priv * d,u32 * size)1679 int rtw_halmac_get_tx_desc_size(struct dvobj_priv *d, u32 *size)
1680 {
1681 struct halmac_adapter *halmac;
1682 struct halmac_api *api;
1683 enum halmac_ret_status status;
1684 u32 val = 0;
1685
1686
1687 halmac = dvobj_to_halmac(d);
1688 api = HALMAC_GET_API(halmac);
1689
1690 status = api->halmac_get_hw_value(halmac, HALMAC_HW_TX_DESC_SIZE, &val);
1691 if (status != HALMAC_RET_SUCCESS)
1692 return -1;
1693
1694 *size = val;
1695
1696 return 0;
1697 }
1698
1699 /**
1700 * rtw_halmac_get_rx_desc_size() - RX descriptor size
1701 * @d: struct dvobj_priv*
1702 * @size: RX descriptor size, unit is byte.
1703 *
1704 * Get RX descriptor size(byte) from HALMAC.
1705 *
1706 * Return 0 for OK, otherwise fail.
1707 */
rtw_halmac_get_rx_desc_size(struct dvobj_priv * d,u32 * size)1708 int rtw_halmac_get_rx_desc_size(struct dvobj_priv *d, u32 *size)
1709 {
1710 struct halmac_adapter *halmac;
1711 struct halmac_api *api;
1712 enum halmac_ret_status status;
1713 u32 val = 0;
1714
1715
1716 halmac = dvobj_to_halmac(d);
1717 api = HALMAC_GET_API(halmac);
1718
1719 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RX_DESC_SIZE, &val);
1720 if (status != HALMAC_RET_SUCCESS)
1721 return -1;
1722
1723 *size = val;
1724
1725 return 0;
1726 }
1727
1728 /**
1729 * rtw_halmac_get_tx_dma_ch_map() - Get TX DMA channel Map for tx desc
1730 * @d: struct dvobj_priv*
1731 * @dma_ch_map: return map of QSEL to DMA channel
1732 * @map_size: size of dma_ch_map
1733 * Suggest size to be last valid QSEL(QSLT_CMD)+1 or full QSLT
1734 * size(0x20)
1735 *
1736 * 8814B would need this to get mapping of QSEL to DMA channel for TX desc.
1737 *
1738 * Return 0 for OK, otherwise fail.
1739 */
rtw_halmac_get_tx_dma_ch_map(struct dvobj_priv * d,u8 * dma_ch_map,u8 map_size)1740 int rtw_halmac_get_tx_dma_ch_map(struct dvobj_priv *d, u8 *dma_ch_map, u8 map_size)
1741 {
1742 struct halmac_adapter *halmac;
1743 struct halmac_api *api;
1744 enum halmac_ret_status status;
1745 struct halmac_rqpn_ch_map map;
1746 enum halmac_dma_ch channel = HALMAC_DMA_CH_UNDEFINE;
1747 u8 qsel;
1748
1749
1750 halmac = dvobj_to_halmac(d);
1751 api = HALMAC_GET_API(halmac);
1752
1753 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RQPN_CH_MAPPING, &map);
1754 if (status != HALMAC_RET_SUCCESS)
1755 return -1;
1756
1757 for (qsel = 0; qsel < map_size; qsel++) {
1758 switch (qsel) {
1759 /*case QSLT_VO:*/
1760 case 0x06:
1761 case 0x07:
1762 channel = map.dma_map_vo;
1763 break;
1764 /*case QSLT_VI:*/
1765 case 0x04:
1766 case 0x05:
1767 channel = map.dma_map_vi;
1768 break;
1769 /*case QSLT_BE:*/
1770 case 0x00:
1771 case 0x03:
1772 channel = map.dma_map_be;
1773 break;
1774 /*case QSLT_BK:*/
1775 case 0x01:
1776 case 0x02:
1777 channel = map.dma_map_bk;
1778 break;
1779 /*case QSLT_BEACON:*/
1780 case 0x10:
1781 channel = HALMAC_DMA_CH_BCN;
1782 break;
1783 /*case QSLT_HIGH:*/
1784 case 0x11:
1785 channel = map.dma_map_hi;
1786 break;
1787 /*case QSLT_MGNT:*/
1788 case 0x12:
1789 channel = map.dma_map_mg;
1790 break;
1791 /*case QSLT_CMD:*/
1792 case 0x13:
1793 channel = HALMAC_DMA_CH_H2C;
1794 break;
1795 default:
1796 /*RTW_ERR("%s: invalid qsel=0x%x\n", __FUNCTION__, qsel);*/
1797 channel = HALMAC_DMA_CH_UNDEFINE;
1798 break;
1799 }
1800 dma_ch_map[qsel] = (u8)channel;
1801 }
1802
1803 return 0;
1804 }
1805
1806 /**
1807 * rtw_halmac_get_fw_max_size() - Firmware MAX size
1808 * @d: struct dvobj_priv*
1809 * @size: MAX Firmware size, unit is byte.
1810 *
1811 * Get Firmware MAX size(byte) from HALMAC.
1812 *
1813 * Return 0 for OK, otherwise fail.
1814 */
rtw_halmac_get_fw_max_size(struct dvobj_priv * d,u32 * size)1815 static int rtw_halmac_get_fw_max_size(struct dvobj_priv *d, u32 *size)
1816 {
1817 struct halmac_adapter *halmac;
1818 struct halmac_api *api;
1819 enum halmac_ret_status status;
1820 u32 val = 0;
1821
1822
1823 halmac = dvobj_to_halmac(d);
1824 api = HALMAC_GET_API(halmac);
1825
1826 status = api->halmac_get_hw_value(halmac, HALMAC_HW_FW_MAX_SIZE, &val);
1827 if (status != HALMAC_RET_SUCCESS)
1828 return -1;
1829
1830 *size = val;
1831
1832 return 0;
1833 }
1834
1835 /**
1836 * rtw_halmac_get_ori_h2c_size() - Original H2C MAX size
1837 * @d: struct dvobj_priv*
1838 * @size: H2C MAX size, unit is byte.
1839 *
1840 * Get original H2C MAX size(byte) from HALMAC.
1841 *
1842 * Return 0 for OK, otherwise fail.
1843 */
rtw_halmac_get_ori_h2c_size(struct dvobj_priv * d,u32 * size)1844 int rtw_halmac_get_ori_h2c_size(struct dvobj_priv *d, u32 *size)
1845 {
1846 struct halmac_adapter *halmac;
1847 struct halmac_api *api;
1848 enum halmac_ret_status status;
1849 u32 val = 0;
1850
1851
1852 halmac = dvobj_to_halmac(d);
1853 api = HALMAC_GET_API(halmac);
1854
1855 status = api->halmac_get_hw_value(halmac, HALMAC_HW_ORI_H2C_SIZE, &val);
1856 if (status != HALMAC_RET_SUCCESS)
1857 return -1;
1858
1859 *size = val;
1860
1861 return 0;
1862 }
1863
rtw_halmac_get_oqt_size(struct dvobj_priv * d,u8 * size)1864 int rtw_halmac_get_oqt_size(struct dvobj_priv *d, u8 *size)
1865 {
1866 enum halmac_ret_status status;
1867 struct halmac_adapter *halmac;
1868 struct halmac_api *api;
1869 u8 val;
1870
1871
1872 if (!size)
1873 return -1;
1874
1875 halmac = dvobj_to_halmac(d);
1876 api = HALMAC_GET_API(halmac);
1877
1878 status = api->halmac_get_hw_value(halmac, HALMAC_HW_AC_OQT_SIZE, &val);
1879 if (status != HALMAC_RET_SUCCESS)
1880 return -1;
1881
1882 *size = val;
1883 return 0;
1884 }
1885
rtw_halmac_get_ac_queue_number(struct dvobj_priv * d,u8 * num)1886 int rtw_halmac_get_ac_queue_number(struct dvobj_priv *d, u8 *num)
1887 {
1888 enum halmac_ret_status status;
1889 struct halmac_adapter *halmac;
1890 struct halmac_api *api;
1891 u8 val;
1892
1893
1894 if (!num)
1895 return -1;
1896
1897 halmac = dvobj_to_halmac(d);
1898 api = HALMAC_GET_API(halmac);
1899
1900 status = api->halmac_get_hw_value(halmac, HALMAC_HW_AC_QUEUE_NUM, &val);
1901 if (status != HALMAC_RET_SUCCESS)
1902 return -1;
1903
1904 *num = val;
1905 return 0;
1906 }
1907
1908 /**
1909 * rtw_halmac_get_mac_address() - Get MAC address of specific port
1910 * @d: struct dvobj_priv*
1911 * @hwport: port
1912 * @addr: buffer for storing MAC address
1913 *
1914 * Get MAC address of specific port from HALMAC.
1915 *
1916 * Return 0 for OK, otherwise fail.
1917 */
rtw_halmac_get_mac_address(struct dvobj_priv * d,enum _hw_port hwport,u8 * addr)1918 int rtw_halmac_get_mac_address(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
1919 {
1920 struct halmac_adapter *halmac;
1921 struct halmac_api *api;
1922 enum halmac_portid port;
1923 union halmac_wlan_addr hwa;
1924 enum halmac_ret_status status;
1925 int err = -1;
1926
1927
1928 if (!addr)
1929 goto out;
1930
1931 halmac = dvobj_to_halmac(d);
1932 api = HALMAC_GET_API(halmac);
1933 port = _hw_port_drv2halmac(hwport);
1934 _rtw_memset(&hwa, 0, sizeof(hwa));
1935
1936 status = api->halmac_get_mac_addr(halmac, port, &hwa);
1937 if (status != HALMAC_RET_SUCCESS)
1938 goto out;
1939
1940 _rtw_memcpy(addr, hwa.addr, 6);
1941
1942 err = 0;
1943 out:
1944 return err;
1945 }
1946
1947 /**
1948 * rtw_halmac_get_network_type() - Get network type of specific port
1949 * @d: struct dvobj_priv*
1950 * @hwport: port
1951 * @type: buffer to put network type (_HW_STATE_*)
1952 *
1953 * Get network type of specific port from HALMAC.
1954 *
1955 * Return 0 for OK, otherwise fail.
1956 */
rtw_halmac_get_network_type(struct dvobj_priv * d,enum _hw_port hwport,u8 * type)1957 int rtw_halmac_get_network_type(struct dvobj_priv *d, enum _hw_port hwport, u8 *type)
1958 {
1959 #if 0
1960 struct halmac_adapter *halmac;
1961 struct halmac_api *api;
1962 enum halmac_portid port;
1963 enum halmac_network_type_select network;
1964 enum halmac_ret_status status;
1965 int err = -1;
1966
1967
1968 halmac = dvobj_to_halmac(d);
1969 api = HALMAC_GET_API(halmac);
1970 port = _hw_port_drv2halmac(hwport);
1971 network = HALMAC_NETWORK_UNDEFINE;
1972
1973 status = api->halmac_get_net_type(halmac, port, &network);
1974 if (status != HALMAC_RET_SUCCESS)
1975 goto out;
1976
1977 *type = _network_type_halmac2drv(network);
1978
1979 err = 0;
1980 out:
1981 return err;
1982 #else
1983 struct _ADAPTER *a;
1984 enum halmac_portid port;
1985 enum halmac_network_type_select network;
1986 u32 val;
1987 int err = -1;
1988
1989
1990 a = dvobj_get_primary_adapter(d);
1991 port = _hw_port_drv2halmac(hwport);
1992 network = HALMAC_NETWORK_UNDEFINE;
1993
1994 switch (port) {
1995 case HALMAC_PORTID0:
1996 val = rtw_read32(a, REG_CR);
1997 network = BIT_GET_NETYPE0(val);
1998 break;
1999
2000 case HALMAC_PORTID1:
2001 val = rtw_read32(a, REG_CR);
2002 network = BIT_GET_NETYPE1(val);
2003 break;
2004
2005 case HALMAC_PORTID2:
2006 val = rtw_read32(a, REG_CR_EXT);
2007 network = BIT_GET_NETYPE2(val);
2008 break;
2009
2010 case HALMAC_PORTID3:
2011 val = rtw_read32(a, REG_CR_EXT);
2012 network = BIT_GET_NETYPE3(val);
2013 break;
2014
2015 case HALMAC_PORTID4:
2016 val = rtw_read32(a, REG_CR_EXT);
2017 network = BIT_GET_NETYPE4(val);
2018 break;
2019
2020 default:
2021 goto out;
2022 }
2023
2024 *type = _network_type_halmac2drv(network);
2025
2026 err = 0;
2027 out:
2028 return err;
2029 #endif
2030 }
2031
2032 /**
2033 * rtw_halmac_get_bcn_ctrl() - Get beacon control setting of specific port
2034 * @d: struct dvobj_priv*
2035 * @hwport: port
2036 * @bcn_ctrl: setting of beacon control
2037 *
2038 * Get beacon control setting of specific port from HALMAC.
2039 *
2040 * Return 0 for OK, otherwise fail.
2041 */
rtw_halmac_get_bcn_ctrl(struct dvobj_priv * d,enum _hw_port hwport,struct rtw_halmac_bcn_ctrl * bcn_ctrl)2042 int rtw_halmac_get_bcn_ctrl(struct dvobj_priv *d, enum _hw_port hwport,
2043 struct rtw_halmac_bcn_ctrl *bcn_ctrl)
2044 {
2045 struct halmac_adapter *halmac;
2046 struct halmac_api *api;
2047 enum halmac_portid port;
2048 struct halmac_bcn_ctrl ctrl;
2049 enum halmac_ret_status status;
2050 int err = -1;
2051
2052
2053 halmac = dvobj_to_halmac(d);
2054 api = HALMAC_GET_API(halmac);
2055 port = _hw_port_drv2halmac(hwport);
2056 _rtw_memset(&ctrl, 0, sizeof(ctrl));
2057
2058 status = api->halmac_rw_bcn_ctrl(halmac, port, 0, &ctrl);
2059 if (status != HALMAC_RET_SUCCESS)
2060 goto out;
2061 _beacon_ctrl_halmac2drv(&ctrl, bcn_ctrl);
2062
2063 err = 0;
2064 out:
2065 return err;
2066 }
2067
2068 /*
2069 * Note:
2070 * When this function return, the register REG_RCR may be changed.
2071 */
rtw_halmac_config_rx_info(struct dvobj_priv * d,enum halmac_drv_info info)2072 int rtw_halmac_config_rx_info(struct dvobj_priv *d, enum halmac_drv_info info)
2073 {
2074 struct halmac_adapter *halmac;
2075 struct halmac_api *api;
2076 enum halmac_ret_status status;
2077 int err = -1;
2078
2079
2080 halmac = dvobj_to_halmac(d);
2081 api = HALMAC_GET_API(halmac);
2082
2083 status = api->halmac_cfg_drv_info(halmac, info);
2084 if (status != HALMAC_RET_SUCCESS)
2085 goto out;
2086
2087 err = 0;
2088 out:
2089 /* Sync driver RCR cache with register setting */
2090 rtw_hal_get_hwreg(dvobj_get_primary_adapter(d), HW_VAR_RCR, NULL);
2091
2092 return err;
2093 }
2094
2095 /**
2096 * rtw_halmac_set_max_dl_fw_size() - Set the MAX download firmware size
2097 * @d: struct dvobj_priv*
2098 * @size: the max download firmware size in one I/O
2099 *
2100 * Set the max download firmware size in one I/O.
2101 * Please also consider the max size of the callback function "SEND_RSVD_PAGE"
2102 * could accept, because download firmware would call "SEND_RSVD_PAGE" to send
2103 * firmware to IC.
2104 *
2105 * If the value of "size" is not even, it would be rounded down to nearest
2106 * even, and 0 and 1 are both invalid value.
2107 *
2108 * Return 0 for setting OK, otherwise fail.
2109 */
rtw_halmac_set_max_dl_fw_size(struct dvobj_priv * d,u32 size)2110 int rtw_halmac_set_max_dl_fw_size(struct dvobj_priv *d, u32 size)
2111 {
2112 struct halmac_adapter *mac;
2113 struct halmac_api *api;
2114 enum halmac_ret_status status;
2115
2116
2117 if (!size || (size == 1))
2118 return -1;
2119
2120 mac = dvobj_to_halmac(d);
2121 if (!mac) {
2122 RTW_ERR("%s: HALMAC is not ready!!\n", __FUNCTION__);
2123 return -1;
2124 }
2125 api = HALMAC_GET_API(mac);
2126
2127 size &= ~1; /* round down to even */
2128 status = api->halmac_cfg_max_dl_size(mac, size);
2129 if (status != HALMAC_RET_SUCCESS) {
2130 RTW_WARN("%s: Fail to cfg_max_dl_size(%d), err=%d!!\n",
2131 __FUNCTION__, size, status);
2132 return -1;
2133 }
2134
2135 return 0;
2136 }
2137
2138 /**
2139 * rtw_halmac_set_mac_address() - Set mac address of specific port
2140 * @d: struct dvobj_priv*
2141 * @hwport: port
2142 * @addr: mac address
2143 *
2144 * Set self mac address of specific port to HALMAC.
2145 *
2146 * Return 0 for OK, otherwise fail.
2147 */
rtw_halmac_set_mac_address(struct dvobj_priv * d,enum _hw_port hwport,u8 * addr)2148 int rtw_halmac_set_mac_address(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
2149 {
2150 struct halmac_adapter *halmac;
2151 struct halmac_api *api;
2152 enum halmac_portid port;
2153 union halmac_wlan_addr hwa;
2154 enum halmac_ret_status status;
2155 int err = -1;
2156
2157
2158 halmac = dvobj_to_halmac(d);
2159 api = HALMAC_GET_API(halmac);
2160
2161 port = _hw_port_drv2halmac(hwport);
2162 _rtw_memset(&hwa, 0, sizeof(hwa));
2163 _rtw_memcpy(hwa.addr, addr, 6);
2164
2165 status = api->halmac_cfg_mac_addr(halmac, port, &hwa);
2166 if (status != HALMAC_RET_SUCCESS)
2167 goto out;
2168
2169 err = 0;
2170 out:
2171 return err;
2172 }
2173
2174 /**
2175 * rtw_halmac_set_bssid() - Set BSSID of specific port
2176 * @d: struct dvobj_priv*
2177 * @hwport: port
2178 * @addr: BSSID, mac address of AP
2179 *
2180 * Set BSSID of specific port to HALMAC.
2181 *
2182 * Return 0 for OK, otherwise fail.
2183 */
rtw_halmac_set_bssid(struct dvobj_priv * d,enum _hw_port hwport,u8 * addr)2184 int rtw_halmac_set_bssid(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
2185 {
2186 struct halmac_adapter *halmac;
2187 struct halmac_api *api;
2188 enum halmac_portid port;
2189 union halmac_wlan_addr hwa;
2190 enum halmac_ret_status status;
2191 int err = -1;
2192
2193
2194 halmac = dvobj_to_halmac(d);
2195 api = HALMAC_GET_API(halmac);
2196 port = _hw_port_drv2halmac(hwport);
2197
2198 _rtw_memset(&hwa, 0, sizeof(hwa));
2199 _rtw_memcpy(hwa.addr, addr, 6);
2200 status = api->halmac_cfg_bssid(halmac, port, &hwa);
2201 if (status != HALMAC_RET_SUCCESS)
2202 goto out;
2203
2204 err = 0;
2205 out:
2206 return err;
2207 }
2208
2209 /**
2210 * rtw_halmac_set_tx_address() - Set transmitter address of specific port
2211 * @d: struct dvobj_priv*
2212 * @hwport: port
2213 * @addr: transmitter address
2214 *
2215 * Set transmitter address of specific port to HALMAC.
2216 *
2217 * Return 0 for OK, otherwise fail.
2218 */
rtw_halmac_set_tx_address(struct dvobj_priv * d,enum _hw_port hwport,u8 * addr)2219 int rtw_halmac_set_tx_address(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
2220 {
2221 struct halmac_adapter *halmac;
2222 struct halmac_api *api;
2223 enum halmac_portid port;
2224 union halmac_wlan_addr hwa;
2225 enum halmac_ret_status status;
2226 int err = -1;
2227
2228
2229 halmac = dvobj_to_halmac(d);
2230 api = HALMAC_GET_API(halmac);
2231 port = _hw_port_drv2halmac(hwport);
2232 _rtw_memset(&hwa, 0, sizeof(hwa));
2233 _rtw_memcpy(hwa.addr, addr, 6);
2234
2235 status = api->halmac_cfg_transmitter_addr(halmac, port, &hwa);
2236 if (status != HALMAC_RET_SUCCESS)
2237 goto out;
2238
2239 err = 0;
2240 out:
2241 return err;
2242 }
2243
2244 /**
2245 * rtw_halmac_set_network_type() - Set network type of specific port
2246 * @d: struct dvobj_priv*
2247 * @hwport: port
2248 * @type: network type (_HW_STATE_*)
2249 *
2250 * Set network type of specific port to HALMAC.
2251 *
2252 * Return 0 for OK, otherwise fail.
2253 */
rtw_halmac_set_network_type(struct dvobj_priv * d,enum _hw_port hwport,u8 type)2254 int rtw_halmac_set_network_type(struct dvobj_priv *d, enum _hw_port hwport, u8 type)
2255 {
2256 struct halmac_adapter *halmac;
2257 struct halmac_api *api;
2258 enum halmac_portid port;
2259 enum halmac_network_type_select network;
2260 enum halmac_ret_status status;
2261 int err = -1;
2262
2263
2264 halmac = dvobj_to_halmac(d);
2265 api = HALMAC_GET_API(halmac);
2266 port = _hw_port_drv2halmac(hwport);
2267 network = _network_type_drv2halmac(type);
2268
2269 status = api->halmac_cfg_net_type(halmac, port, network);
2270 if (status != HALMAC_RET_SUCCESS)
2271 goto out;
2272
2273 err = 0;
2274 out:
2275 return err;
2276 }
2277
2278 /**
2279 * rtw_halmac_reset_tsf() - Reset TSF timer of specific port
2280 * @d: struct dvobj_priv*
2281 * @hwport: port
2282 *
2283 * Notice HALMAC to reset timing synchronization function(TSF) timer of
2284 * specific port.
2285 *
2286 * Return 0 for OK, otherwise fail.
2287 */
rtw_halmac_reset_tsf(struct dvobj_priv * d,enum _hw_port hwport)2288 int rtw_halmac_reset_tsf(struct dvobj_priv *d, enum _hw_port hwport)
2289 {
2290 struct halmac_adapter *halmac;
2291 struct halmac_api *api;
2292 enum halmac_portid port;
2293 enum halmac_ret_status status;
2294 int err = -1;
2295
2296
2297 halmac = dvobj_to_halmac(d);
2298 api = HALMAC_GET_API(halmac);
2299 port = _hw_port_drv2halmac(hwport);
2300
2301 status = api->halmac_cfg_tsf_rst(halmac, port);
2302 if (status != HALMAC_RET_SUCCESS)
2303 goto out;
2304
2305 err = 0;
2306 out:
2307 return err;
2308 }
2309
2310 /**
2311 * rtw_halmac_set_bcn_interval() - Set beacon interval of each port
2312 * @d: struct dvobj_priv*
2313 * @hwport: port
2314 * @space: beacon interval, unit is ms
2315 *
2316 * Set beacon interval of specific port to HALMAC.
2317 *
2318 * Return 0 for OK, otherwise fail.
2319 */
rtw_halmac_set_bcn_interval(struct dvobj_priv * d,enum _hw_port hwport,u32 interval)2320 int rtw_halmac_set_bcn_interval(struct dvobj_priv *d, enum _hw_port hwport,
2321 u32 interval)
2322 {
2323 struct halmac_adapter *halmac;
2324 struct halmac_api *api;
2325 enum halmac_portid port;
2326 enum halmac_ret_status status;
2327 int err = -1;
2328
2329
2330 halmac = dvobj_to_halmac(d);
2331 api = HALMAC_GET_API(halmac);
2332 port = _hw_port_drv2halmac(hwport);
2333
2334 status = api->halmac_cfg_bcn_space(halmac, port, interval);
2335 if (status != HALMAC_RET_SUCCESS)
2336 goto out;
2337
2338 err = 0;
2339 out:
2340 return err;
2341 }
2342
2343 /**
2344 * rtw_halmac_set_bcn_ctrl() - Set beacon control setting of each port
2345 * @d: struct dvobj_priv*
2346 * @hwport: port
2347 * @bcn_ctrl: setting of beacon control
2348 *
2349 * Set beacon control setting of specific port to HALMAC.
2350 *
2351 * Return 0 for OK, otherwise fail.
2352 */
rtw_halmac_set_bcn_ctrl(struct dvobj_priv * d,enum _hw_port hwport,struct rtw_halmac_bcn_ctrl * bcn_ctrl)2353 int rtw_halmac_set_bcn_ctrl(struct dvobj_priv *d, enum _hw_port hwport,
2354 struct rtw_halmac_bcn_ctrl *bcn_ctrl)
2355 {
2356 struct halmac_adapter *halmac;
2357 struct halmac_api *api;
2358 enum halmac_portid port;
2359 struct halmac_bcn_ctrl ctrl;
2360 enum halmac_ret_status status;
2361 int err = -1;
2362
2363
2364 halmac = dvobj_to_halmac(d);
2365 api = HALMAC_GET_API(halmac);
2366 port = _hw_port_drv2halmac(hwport);
2367 _rtw_memset(&ctrl, 0, sizeof(ctrl));
2368 _beacon_ctrl_drv2halmac(bcn_ctrl, &ctrl);
2369
2370 status = api->halmac_rw_bcn_ctrl(halmac, port, 1, &ctrl);
2371 if (status != HALMAC_RET_SUCCESS)
2372 goto out;
2373
2374 err = 0;
2375 out:
2376 return err;
2377 }
2378
2379 /**
2380 * rtw_halmac_set_aid() - Set association identifier(AID) of specific port
2381 * @d: struct dvobj_priv*
2382 * @hwport: port
2383 * @aid: Association identifier
2384 *
2385 * Set association identifier(AID) of specific port to HALMAC.
2386 *
2387 * Return 0 for OK, otherwise fail.
2388 */
rtw_halmac_set_aid(struct dvobj_priv * d,enum _hw_port hwport,u16 aid)2389 int rtw_halmac_set_aid(struct dvobj_priv *d, enum _hw_port hwport, u16 aid)
2390 {
2391 struct halmac_adapter *halmac;
2392 struct halmac_api *api;
2393 enum halmac_portid port;
2394 enum halmac_ret_status status;
2395 int err = -1;
2396
2397
2398 halmac = dvobj_to_halmac(d);
2399 api = HALMAC_GET_API(halmac);
2400 port = _hw_port_drv2halmac(hwport);
2401
2402 #if 0
2403 status = api->halmac_cfg_aid(halmac, port, aid);
2404 if (status != HALMAC_RET_SUCCESS)
2405 goto out;
2406 #else
2407 {
2408 struct _ADAPTER *a;
2409 u32 addr;
2410 u16 val;
2411
2412 a = dvobj_get_primary_adapter(d);
2413
2414 switch (port) {
2415 case 0:
2416 addr = REG_BCN_PSR_RPT;
2417 val = rtw_read16(a, addr);
2418 val = BIT_SET_PS_AID_0(val, aid);
2419 rtw_write16(a, addr, val);
2420 break;
2421
2422 case 1:
2423 addr = REG_BCN_PSR_RPT1;
2424 val = rtw_read16(a, addr);
2425 val = BIT_SET_PS_AID_1(val, aid);
2426 rtw_write16(a, addr, val);
2427 break;
2428
2429 case 2:
2430 addr = REG_BCN_PSR_RPT2;
2431 val = rtw_read16(a, addr);
2432 val = BIT_SET_PS_AID_2(val, aid);
2433 rtw_write16(a, addr, val);
2434 break;
2435
2436 case 3:
2437 addr = REG_BCN_PSR_RPT3;
2438 val = rtw_read16(a, addr);
2439 val = BIT_SET_PS_AID_3(val, aid);
2440 rtw_write16(a, addr, val);
2441 break;
2442
2443 case 4:
2444 addr = REG_BCN_PSR_RPT4;
2445 val = rtw_read16(a, addr);
2446 val = BIT_SET_PS_AID_4(val, aid);
2447 rtw_write16(a, addr, val);
2448 break;
2449
2450 default:
2451 goto out;
2452 }
2453 }
2454 #endif
2455
2456 err = 0;
2457 out:
2458 return err;
2459 }
2460
rtw_halmac_set_bandwidth(struct dvobj_priv * d,u8 channel,u8 pri_ch_idx,u8 bw)2461 int rtw_halmac_set_bandwidth(struct dvobj_priv *d, u8 channel, u8 pri_ch_idx, u8 bw)
2462 {
2463 struct halmac_adapter *mac;
2464 struct halmac_api *api;
2465 enum halmac_ret_status status;
2466
2467
2468 mac = dvobj_to_halmac(d);
2469 api = HALMAC_GET_API(mac);
2470
2471 status = api->halmac_cfg_ch_bw(mac, channel, pri_ch_idx, bw);
2472 if (HALMAC_RET_SUCCESS != status)
2473 return -1;
2474
2475 return 0;
2476 }
2477
2478 /**
2479 * rtw_halmac_set_edca() - config edca parameter
2480 * @d: struct dvobj_priv*
2481 * @queue: XMIT_[VO/VI/BE/BK]_QUEUE
2482 * @aifs: Arbitration inter-frame space(AIFS)
2483 * @cw: Contention window(CW)
2484 * @txop: MAX Transmit Opportunity(TXOP)
2485 *
2486 * Return: 0 if process OK, otherwise -1.
2487 */
rtw_halmac_set_edca(struct dvobj_priv * d,u8 queue,u8 aifs,u8 cw,u16 txop)2488 int rtw_halmac_set_edca(struct dvobj_priv *d, u8 queue, u8 aifs, u8 cw, u16 txop)
2489 {
2490 struct halmac_adapter *mac;
2491 struct halmac_api *api;
2492 enum halmac_acq_id ac;
2493 struct halmac_edca_para edca;
2494 enum halmac_ret_status status;
2495
2496
2497 mac = dvobj_to_halmac(d);
2498 api = HALMAC_GET_API(mac);
2499
2500 switch (queue) {
2501 case XMIT_VO_QUEUE:
2502 ac = HALMAC_ACQ_ID_VO;
2503 break;
2504 case XMIT_VI_QUEUE:
2505 ac = HALMAC_ACQ_ID_VI;
2506 break;
2507 case XMIT_BE_QUEUE:
2508 ac = HALMAC_ACQ_ID_BE;
2509 break;
2510 case XMIT_BK_QUEUE:
2511 ac = HALMAC_ACQ_ID_BK;
2512 break;
2513 default:
2514 return -1;
2515 }
2516
2517 edca.aifs = aifs;
2518 edca.cw = cw;
2519 edca.txop_limit = txop;
2520
2521 status = api->halmac_cfg_edca_para(mac, ac, &edca);
2522 if (status != HALMAC_RET_SUCCESS)
2523 return -1;
2524
2525 return 0;
2526 }
2527
2528 /**
2529 * rtw_halmac_set_rts_full_bw() - Send RTS to all covered channels
2530 * @d: struct dvobj_priv*
2531 * @enable: _TRUE(enable), _FALSE(disable)
2532 *
2533 * Hradware will duplicate RTS packet to all channels which are covered in used
2534 * bandwidth.
2535 *
2536 * Return 0 if process OK, otherwise -1.
2537 */
rtw_halmac_set_rts_full_bw(struct dvobj_priv * d,u8 enable)2538 int rtw_halmac_set_rts_full_bw(struct dvobj_priv *d, u8 enable)
2539 {
2540 struct halmac_adapter *mac;
2541 struct halmac_api *api;
2542 enum halmac_ret_status status;
2543 u8 full;
2544
2545
2546 mac = dvobj_to_halmac(d);
2547 api = HALMAC_GET_API(mac);
2548 full = (enable == _TRUE) ? 1 : 0;
2549
2550 status = api->halmac_set_hw_value(mac, HALMAC_HW_RTS_FULL_BW, &full);
2551 if (HALMAC_RET_SUCCESS != status)
2552 return -1;
2553
2554 return 0;
2555 }
2556
2557 #ifdef RTW_HALMAC_DBG_POWER_SWITCH
_dump_mac_reg(struct dvobj_priv * d,u32 start,u32 end)2558 static void _dump_mac_reg(struct dvobj_priv *d, u32 start, u32 end)
2559 {
2560 struct _ADAPTER *adapter;
2561 int i, j = 1;
2562
2563
2564 adapter = dvobj_get_primary_adapter(d);
2565 for (i = start; i < end; i += 4) {
2566 if (j % 4 == 1)
2567 RTW_PRINT("0x%04x", i);
2568 _RTW_PRINT(" 0x%08x ", rtw_read32(adapter, i));
2569 if ((j++) % 4 == 0)
2570 _RTW_PRINT("\n");
2571 }
2572 }
2573
dump_dbg_val(struct _ADAPTER * a,u32 reg)2574 void dump_dbg_val(struct _ADAPTER *a, u32 reg)
2575 {
2576 u32 v32;
2577
2578
2579 rtw_write8(a, 0x3A, reg);
2580 v32 = rtw_read32(a, 0xC0);
2581 RTW_PRINT("0x3A = %02x, 0xC0 = 0x%08x\n",reg, v32);
2582 }
2583
2584 #ifdef CONFIG_PCI_HCI
_dump_pcie_cfg_space(struct dvobj_priv * d)2585 static void _dump_pcie_cfg_space(struct dvobj_priv *d)
2586 {
2587 struct _ADAPTER *padapter = dvobj_get_primary_adapter(d);
2588 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
2589 struct pci_dev *pdev = pdvobjpriv->ppcidev;
2590 struct pci_dev *bridge_pdev = pdev->bus->self;
2591
2592 u32 tmp[4] = { 0 };
2593 u32 i, j;
2594
2595 RTW_PRINT("\n***** PCI Device Configuration Space *****\n\n");
2596
2597 for(i = 0; i < 0x100; i += 0x10)
2598 {
2599 for (j = 0 ; j < 4 ; j++)
2600 pci_read_config_dword(pdev, i + j * 4, tmp+j);
2601
2602 RTW_PRINT("%03x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
2603 i, tmp[0] & 0xFF, (tmp[0] >> 8) & 0xFF, (tmp[0] >> 16) & 0xFF, (tmp[0] >> 24) & 0xFF,
2604 tmp[1] & 0xFF, (tmp[1] >> 8) & 0xFF, (tmp[1] >> 16) & 0xFF, (tmp[1] >> 24) & 0xFF,
2605 tmp[2] & 0xFF, (tmp[2] >> 8) & 0xFF, (tmp[2] >> 16) & 0xFF, (tmp[2] >> 24) & 0xFF,
2606 tmp[3] & 0xFF, (tmp[3] >> 8) & 0xFF, (tmp[3] >> 16) & 0xFF, (tmp[3] >> 24) & 0xFF);
2607 }
2608
2609 RTW_PRINT("\n***** PCI Host Device Configuration Space*****\n\n");
2610
2611 for(i = 0; i < 0x100; i += 0x10)
2612 {
2613 for (j = 0 ; j < 4 ; j++)
2614 pci_read_config_dword(bridge_pdev, i + j * 4, tmp+j);
2615
2616 RTW_PRINT("%03x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
2617 i, tmp[0] & 0xFF, (tmp[0] >> 8) & 0xFF, (tmp[0] >> 16) & 0xFF, (tmp[0] >> 24) & 0xFF,
2618 tmp[1] & 0xFF, (tmp[1] >> 8) & 0xFF, (tmp[1] >> 16) & 0xFF, (tmp[1] >> 24) & 0xFF,
2619 tmp[2] & 0xFF, (tmp[2] >> 8) & 0xFF, (tmp[2] >> 16) & 0xFF, (tmp[2] >> 24) & 0xFF,
2620 tmp[3] & 0xFF, (tmp[3] >> 8) & 0xFF, (tmp[3] >> 16) & 0xFF, (tmp[3] >> 24) & 0xFF);
2621 }
2622 }
2623 #endif
2624
_dump_mac_reg_for_power_switch(struct dvobj_priv * d,const char * caller,char * desc)2625 static void _dump_mac_reg_for_power_switch(struct dvobj_priv *d,
2626 const char* caller, char* desc)
2627 {
2628 struct _ADAPTER *a;
2629 u8 v8;
2630
2631
2632 RTW_PRINT("%s: %s\n", caller, desc);
2633 RTW_PRINT("======= MAC REG =======\n");
2634 /* page 0/1 */
2635 _dump_mac_reg(d, 0x0, 0x200);
2636 _dump_mac_reg(d, 0x300, 0x400); /* also dump page 3 */
2637
2638 /* dump debug register */
2639 a = dvobj_get_primary_adapter(d);
2640
2641 #ifdef CONFIG_PCI_HCI
2642 _dump_pcie_cfg_space(d);
2643
2644 v8 = rtw_read8(a, 0xF6) | 0x01;
2645 rtw_write8(a, 0xF6, v8);
2646 RTW_PRINT("0xF6 = %02x\n", v8);
2647
2648 dump_dbg_val(a, 0x63);
2649 dump_dbg_val(a, 0x64);
2650 dump_dbg_val(a, 0x68);
2651 dump_dbg_val(a, 0x69);
2652 dump_dbg_val(a, 0x6a);
2653 dump_dbg_val(a, 0x6b);
2654 dump_dbg_val(a, 0x71);
2655 dump_dbg_val(a, 0x72);
2656 #endif
2657 }
2658
_power_switch(struct halmac_adapter * halmac,struct halmac_api * api,enum halmac_mac_power pwr)2659 static enum halmac_ret_status _power_switch(struct halmac_adapter *halmac,
2660 struct halmac_api *api,
2661 enum halmac_mac_power pwr)
2662 {
2663 enum halmac_ret_status status;
2664 char desc[80] = {0};
2665
2666
2667 rtw_sprintf(desc, 80, "before calling power %s",
2668 (pwr==HALMAC_MAC_POWER_ON)?"on":"off");
2669 _dump_mac_reg_for_power_switch((struct dvobj_priv *)halmac->drv_adapter,
2670 __FUNCTION__, desc);
2671
2672 status = api->halmac_mac_power_switch(halmac, pwr);
2673 RTW_PRINT("%s: status=%d\n", __FUNCTION__, status);
2674
2675 rtw_sprintf(desc, 80, "after calling power %s",
2676 (pwr==HALMAC_MAC_POWER_ON)?"on":"off");
2677 _dump_mac_reg_for_power_switch((struct dvobj_priv *)halmac->drv_adapter,
2678 __FUNCTION__, desc);
2679
2680 return status;
2681 }
2682 #else /* !RTW_HALMAC_DBG_POWER_SWITCH */
2683 #define _power_switch(mac, api, pwr) (api)->halmac_mac_power_switch(mac, pwr)
2684 #endif /* !RTW_HALMAC_DBG_POWER_SWITCH */
2685
2686 /*
2687 * Description:
2688 * Power on device hardware.
2689 * [Notice!] If device's power state is on before,
2690 * it would be power off first and turn on power again.
2691 *
2692 * Return:
2693 * 0 power on success
2694 * -1 power on fail
2695 * -2 power state unchange
2696 */
rtw_halmac_poweron(struct dvobj_priv * d)2697 int rtw_halmac_poweron(struct dvobj_priv *d)
2698 {
2699 struct halmac_adapter *halmac;
2700 struct halmac_api *api;
2701 enum halmac_ret_status status;
2702 int err = -1;
2703 #if defined(CONFIG_PCI_HCI) && defined(CONFIG_RTL8822B)
2704 struct _ADAPTER *a;
2705 u8 v8;
2706 u32 addr;
2707
2708 a = dvobj_get_primary_adapter(d);
2709 #endif
2710
2711 halmac = dvobj_to_halmac(d);
2712 if (!halmac)
2713 goto out;
2714
2715 api = HALMAC_GET_API(halmac);
2716
2717 status = api->halmac_pre_init_system_cfg(halmac);
2718 if (status != HALMAC_RET_SUCCESS)
2719 goto out;
2720
2721 #ifdef CONFIG_SDIO_HCI
2722 status = api->halmac_sdio_cmd53_4byte(halmac, HALMAC_SDIO_CMD53_4BYTE_MODE_RW);
2723 if (status != HALMAC_RET_SUCCESS)
2724 goto out;
2725 #endif /* CONFIG_SDIO_HCI */
2726
2727 #if defined(CONFIG_PCI_HCI) && defined(CONFIG_RTL8822B)
2728 addr = 0x3F3;
2729 v8 = rtw_read8(a, addr);
2730 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v8);
2731 /* are we in pcie debug mode? */
2732 if (!(v8 & BIT(2))) {
2733 RTW_PRINT("%s: Enable pcie debug mode\n", __FUNCTION__);
2734 v8 |= BIT(2);
2735 v8 = rtw_write8(a, addr, v8);
2736 }
2737 #endif
2738
2739 status = _power_switch(halmac, api, HALMAC_MAC_POWER_ON);
2740 if (HALMAC_RET_PWR_UNCHANGE == status) {
2741
2742 #if defined(CONFIG_PCI_HCI) && defined(CONFIG_RTL8822B)
2743 addr = 0x3F3;
2744 v8 = rtw_read8(a, addr);
2745 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v8);
2746
2747 /* are we in pcie debug mode? */
2748 if (!(v8 & BIT(2))) {
2749 RTW_PRINT("%s: Enable pcie debug mode\n", __FUNCTION__);
2750 v8 |= BIT(2);
2751 v8 = rtw_write8(a, addr, v8);
2752 } else if (v8 & BIT(0)) {
2753 /* DMA stuck */
2754 addr = 0x1350;
2755 v8 = rtw_read8(a, addr);
2756 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v8);
2757 RTW_PRINT("%s: recover DMA stuck\n", __FUNCTION__);
2758 v8 |= BIT(6);
2759 v8 = rtw_write8(a, addr, v8);
2760 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v8);
2761 }
2762 #endif
2763 /*
2764 * Work around for warm reboot but device not power off,
2765 * but it would also fall into this case when auto power on is enabled.
2766 */
2767 _power_switch(halmac, api, HALMAC_MAC_POWER_OFF);
2768 status = _power_switch(halmac, api, HALMAC_MAC_POWER_ON);
2769 RTW_WARN("%s: Power state abnormal, try to recover...%s\n",
2770 __FUNCTION__, (HALMAC_RET_SUCCESS == status)?"OK":"FAIL!");
2771 }
2772 if (HALMAC_RET_SUCCESS != status) {
2773 if (HALMAC_RET_PWR_UNCHANGE == status)
2774 err = -2;
2775 goto out;
2776 }
2777
2778 status = api->halmac_init_system_cfg(halmac);
2779 if (status != HALMAC_RET_SUCCESS)
2780 goto out;
2781
2782 err = 0;
2783 out:
2784 return err;
2785 }
2786
2787 /*
2788 * Description:
2789 * Power off device hardware.
2790 *
2791 * Return:
2792 * 0 Power off success
2793 * -1 Power off fail
2794 */
rtw_halmac_poweroff(struct dvobj_priv * d)2795 int rtw_halmac_poweroff(struct dvobj_priv *d)
2796 {
2797 struct halmac_adapter *halmac;
2798 struct halmac_api *api;
2799 enum halmac_ret_status status;
2800 int err = -1;
2801
2802
2803 halmac = dvobj_to_halmac(d);
2804 if (!halmac)
2805 goto out;
2806
2807 api = HALMAC_GET_API(halmac);
2808
2809 status = _power_switch(halmac, api, HALMAC_MAC_POWER_OFF);
2810 if ((HALMAC_RET_SUCCESS != status)
2811 && (HALMAC_RET_PWR_UNCHANGE != status))
2812 goto out;
2813
2814 err = 0;
2815 out:
2816 return err;
2817 }
2818
2819 #ifdef CONFIG_SUPPORT_TRX_SHARED
_trx_share_mode_drv2halmac(u8 trx_share_mode)2820 static inline enum halmac_rx_fifo_expanding_mode _trx_share_mode_drv2halmac(u8 trx_share_mode)
2821 {
2822 if (0 == trx_share_mode)
2823 return HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE;
2824 else if (1 == trx_share_mode)
2825 return HALMAC_RX_FIFO_EXPANDING_MODE_1_BLOCK;
2826 else if (2 == trx_share_mode)
2827 return HALMAC_RX_FIFO_EXPANDING_MODE_2_BLOCK;
2828 else if (3 == trx_share_mode)
2829 return HALMAC_RX_FIFO_EXPANDING_MODE_3_BLOCK;
2830 else
2831 return HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE;
2832 }
2833
_rtw_get_trx_share_mode(struct _ADAPTER * adapter)2834 static enum halmac_rx_fifo_expanding_mode _rtw_get_trx_share_mode(struct _ADAPTER *adapter)
2835 {
2836 struct registry_priv *registry_par = &adapter->registrypriv;
2837
2838 return _trx_share_mode_drv2halmac(registry_par->trx_share_mode);
2839 }
2840
dump_trx_share_mode(void * sel,struct _ADAPTER * adapter)2841 void dump_trx_share_mode(void *sel, struct _ADAPTER *adapter)
2842 {
2843 struct registry_priv *registry_par = &adapter->registrypriv;
2844 u8 mode = _trx_share_mode_drv2halmac(registry_par->trx_share_mode);
2845
2846 if (HALMAC_RX_FIFO_EXPANDING_MODE_1_BLOCK == mode)
2847 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_1");
2848 else if (HALMAC_RX_FIFO_EXPANDING_MODE_2_BLOCK == mode)
2849 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_2");
2850 else if (HALMAC_RX_FIFO_EXPANDING_MODE_3_BLOCK == mode)
2851 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_3");
2852 else
2853 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "DISABLE");
2854 }
2855 #endif
2856
_rsvd_page_num_drv2halmac(u16 num)2857 static enum halmac_drv_rsvd_pg_num _rsvd_page_num_drv2halmac(u16 num)
2858 {
2859 if (num <= 8)
2860 return HALMAC_RSVD_PG_NUM8;
2861 if (num <= 16)
2862 return HALMAC_RSVD_PG_NUM16;
2863 if (num <= 24)
2864 return HALMAC_RSVD_PG_NUM24;
2865 if (num <= 32)
2866 return HALMAC_RSVD_PG_NUM32;
2867 if (num <= 64)
2868 return HALMAC_RSVD_PG_NUM64;
2869 if (num <= 128)
2870 return HALMAC_RSVD_PG_NUM128;
2871
2872 if (num > 256)
2873 RTW_WARN("%s: Fail to allocate RSVD page(%d)!!"
2874 " The MAX RSVD page number is 256...\n",
2875 __FUNCTION__, num);
2876
2877 return HALMAC_RSVD_PG_NUM256;
2878 }
2879
_rsvd_page_num_halmac2drv(enum halmac_drv_rsvd_pg_num rsvd_page_number)2880 static u16 _rsvd_page_num_halmac2drv(enum halmac_drv_rsvd_pg_num rsvd_page_number)
2881 {
2882 u16 num = 0;
2883
2884
2885 switch (rsvd_page_number) {
2886 case HALMAC_RSVD_PG_NUM8:
2887 num = 8;
2888 break;
2889
2890 case HALMAC_RSVD_PG_NUM16:
2891 num = 16;
2892 break;
2893
2894 case HALMAC_RSVD_PG_NUM24:
2895 num = 24;
2896 break;
2897
2898 case HALMAC_RSVD_PG_NUM32:
2899 num = 32;
2900 break;
2901
2902 case HALMAC_RSVD_PG_NUM64:
2903 num = 64;
2904 break;
2905
2906 case HALMAC_RSVD_PG_NUM128:
2907 num = 128;
2908 break;
2909
2910 case HALMAC_RSVD_PG_NUM256:
2911 num = 256;
2912 break;
2913 }
2914
2915 return num;
2916 }
2917
_choose_trx_mode(struct dvobj_priv * d)2918 static enum halmac_trx_mode _choose_trx_mode(struct dvobj_priv *d)
2919 {
2920 PADAPTER p;
2921
2922
2923 p = dvobj_get_primary_adapter(d);
2924
2925 if (p->registrypriv.wifi_spec)
2926 return HALMAC_TRX_MODE_WMM;
2927
2928 #ifdef CONFIG_SUPPORT_TRX_SHARED
2929 if (_rtw_get_trx_share_mode(p))
2930 return HALMAC_TRX_MODE_TRXSHARE;
2931 #endif
2932
2933 return HALMAC_TRX_MODE_NORMAL;
2934 }
2935
_rf_type_drv2halmac(enum rf_type rf_drv)2936 static inline enum halmac_rf_type _rf_type_drv2halmac(enum rf_type rf_drv)
2937 {
2938 enum halmac_rf_type rf_mac;
2939
2940
2941 switch (rf_drv) {
2942 case RF_1T1R:
2943 rf_mac = HALMAC_RF_1T1R;
2944 break;
2945 case RF_1T2R:
2946 rf_mac = HALMAC_RF_1T2R;
2947 break;
2948 case RF_2T2R:
2949 rf_mac = HALMAC_RF_2T2R;
2950 break;
2951 case RF_2T3R:
2952 rf_mac = HALMAC_RF_2T3R;
2953 break;
2954 case RF_2T4R:
2955 rf_mac = HALMAC_RF_2T4R;
2956 break;
2957 case RF_3T3R:
2958 rf_mac = HALMAC_RF_3T3R;
2959 break;
2960 case RF_3T4R:
2961 rf_mac = HALMAC_RF_3T4R;
2962 break;
2963 case RF_4T4R:
2964 rf_mac = HALMAC_RF_4T4R;
2965 break;
2966 default:
2967 rf_mac = HALMAC_RF_MAX_TYPE;
2968 RTW_ERR("%s: Invalid RF type(0x%x)!\n", __FUNCTION__, rf_drv);
2969 break;
2970 }
2971
2972 return rf_mac;
2973 }
2974
_rf_type_halmac2drv(enum halmac_rf_type rf_mac)2975 static inline enum rf_type _rf_type_halmac2drv(enum halmac_rf_type rf_mac)
2976 {
2977 enum rf_type rf_drv;
2978
2979
2980 switch (rf_mac) {
2981 case HALMAC_RF_1T2R:
2982 rf_drv = RF_1T2R;
2983 break;
2984 case HALMAC_RF_2T4R:
2985 rf_drv = RF_2T4R;
2986 break;
2987 case HALMAC_RF_2T2R:
2988 case HALMAC_RF_2T2R_GREEN:
2989 rf_drv = RF_2T2R;
2990 break;
2991 case HALMAC_RF_2T3R:
2992 rf_drv = RF_2T3R;
2993 break;
2994 case HALMAC_RF_1T1R:
2995 rf_drv = RF_1T1R;
2996 break;
2997 case HALMAC_RF_3T3R:
2998 rf_drv = RF_3T3R;
2999 break;
3000 case HALMAC_RF_3T4R:
3001 rf_drv = RF_3T4R;
3002 break;
3003 case HALMAC_RF_4T4R:
3004 rf_drv = RF_4T4R;
3005 break;
3006 default:
3007 rf_drv = RF_TYPE_MAX;
3008 RTW_ERR("%s: Invalid RF type(0x%x)!\n", __FUNCTION__, rf_mac);
3009 break;
3010 }
3011
3012 return rf_drv;
3013 }
3014
_cut_version_drv2phydm(enum tag_HAL_Cut_Version_Definition cut_drv)3015 static enum odm_cut_version _cut_version_drv2phydm(
3016 enum tag_HAL_Cut_Version_Definition cut_drv)
3017 {
3018 enum odm_cut_version cut_phydm = ODM_CUT_A;
3019 u32 diff;
3020
3021
3022 if (cut_drv > K_CUT_VERSION)
3023 RTW_WARN("%s: unknown cut_ver=%d !!\n", __FUNCTION__, cut_drv);
3024
3025 diff = cut_drv - A_CUT_VERSION;
3026 cut_phydm += diff;
3027
3028 return cut_phydm;
3029 }
3030
_send_general_info_by_reg(struct dvobj_priv * d,struct halmac_general_info * info)3031 static int _send_general_info_by_reg(struct dvobj_priv *d,
3032 struct halmac_general_info *info)
3033 {
3034 struct _ADAPTER *a;
3035 struct hal_com_data *hal;
3036 enum tag_HAL_Cut_Version_Definition cut_drv;
3037 enum rf_type rftype;
3038 enum odm_cut_version cut_phydm;
3039 u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
3040
3041
3042 a = dvobj_get_primary_adapter(d);
3043 hal = GET_HAL_DATA(a);
3044 rftype = _rf_type_halmac2drv(info->rf_type);
3045 cut_drv = GET_CVID_CUT_VERSION(hal->version_id);
3046 cut_phydm = _cut_version_drv2phydm(cut_drv);
3047
3048 #define CLASS_GENERAL_INFO_REG 0x02
3049 #define CMD_ID_GENERAL_INFO_REG 0x0C
3050 #define GENERAL_INFO_REG_SET_CMD_ID(buf, v) SET_BITS_TO_LE_4BYTE(buf, 0, 5, v)
3051 #define GENERAL_INFO_REG_SET_CLASS(buf, v) SET_BITS_TO_LE_4BYTE(buf, 5, 3, v)
3052 #define GENERAL_INFO_REG_SET_RFE_TYPE(buf, v) SET_BITS_TO_LE_4BYTE(buf, 8, 8, v)
3053 #define GENERAL_INFO_REG_SET_RF_TYPE(buf, v) SET_BITS_TO_LE_4BYTE(buf, 16, 8, v)
3054 #define GENERAL_INFO_REG_SET_CUT_VERSION(buf, v) SET_BITS_TO_LE_4BYTE(buf, 24, 8, v)
3055 #define GENERAL_INFO_REG_SET_RX_ANT_STATUS(buf, v) SET_BITS_TO_LE_1BYTE(buf+4, 0, 4, v)
3056 #define GENERAL_INFO_REG_SET_TX_ANT_STATUS(buf, v) SET_BITS_TO_LE_1BYTE(buf+4, 4, 4, v)
3057
3058 GENERAL_INFO_REG_SET_CMD_ID(h2c, CMD_ID_GENERAL_INFO_REG);
3059 GENERAL_INFO_REG_SET_CLASS(h2c, CLASS_GENERAL_INFO_REG);
3060 GENERAL_INFO_REG_SET_RFE_TYPE(h2c, info->rfe_type);
3061 GENERAL_INFO_REG_SET_RF_TYPE(h2c, rftype);
3062 GENERAL_INFO_REG_SET_CUT_VERSION(h2c, cut_phydm);
3063 GENERAL_INFO_REG_SET_RX_ANT_STATUS(h2c, info->rx_ant_status);
3064 GENERAL_INFO_REG_SET_TX_ANT_STATUS(h2c, info->tx_ant_status);
3065
3066 return rtw_halmac_send_h2c(d, h2c);
3067 }
3068
_send_general_info(struct dvobj_priv * d)3069 static int _send_general_info(struct dvobj_priv *d)
3070 {
3071 struct _ADAPTER *adapter;
3072 struct hal_com_data *hal;
3073 struct halmac_adapter *halmac;
3074 struct halmac_api *api;
3075 struct halmac_general_info info;
3076 enum halmac_ret_status status;
3077 enum rf_type rf = RF_1T1R;
3078 enum bb_path txpath = BB_PATH_A;
3079 enum bb_path rxpath = BB_PATH_A;
3080 int err;
3081
3082
3083 adapter = dvobj_get_primary_adapter(d);
3084 hal = GET_HAL_DATA(adapter);
3085 halmac = dvobj_to_halmac(d);
3086 if (!halmac)
3087 return -1;
3088 api = HALMAC_GET_API(halmac);
3089
3090 _rtw_memset(&info, 0, sizeof(info));
3091 info.rfe_type = (u8)hal->rfe_type;
3092 rtw_hal_get_trx_path(d, &rf, &txpath, &rxpath);
3093 info.rf_type = _rf_type_drv2halmac(rf);
3094 info.tx_ant_status = (u8)txpath;
3095 info.rx_ant_status = (u8)rxpath;
3096 info.ext_pa = 0; /* 2.4G or 5G? format not known */
3097 info.package_type = hal->PackageType;
3098 info.mp_mode = adapter->registrypriv.mp_mode;
3099
3100 status = api->halmac_send_general_info(halmac, &info);
3101 switch (status) {
3102 case HALMAC_RET_SUCCESS:
3103 break;
3104 case HALMAC_RET_NO_DLFW:
3105 RTW_WARN("%s: halmac_send_general_info() fail because fw not dl!\n",
3106 __FUNCTION__);
3107 /* go through */
3108 default:
3109 return -1;
3110 }
3111
3112 err = _send_general_info_by_reg(d, &info);
3113 if (err) {
3114 RTW_ERR("%s: Fail to send general info by register!\n",
3115 __FUNCTION__);
3116 return -1;
3117 }
3118
3119 return 0;
3120 }
3121
_cfg_drv_rsvd_pg_num(struct dvobj_priv * d)3122 static int _cfg_drv_rsvd_pg_num(struct dvobj_priv *d)
3123 {
3124 struct _ADAPTER *a;
3125 struct hal_com_data *hal;
3126 struct halmac_adapter *halmac;
3127 struct halmac_api *api;
3128 enum halmac_drv_rsvd_pg_num rsvd_page_number;
3129 enum halmac_ret_status status;
3130 u16 drv_rsvd_num;
3131 int ret = 0;
3132
3133
3134 a = dvobj_get_primary_adapter(d);
3135 hal = GET_HAL_DATA(a);
3136 halmac = dvobj_to_halmac(d);
3137 api = HALMAC_GET_API(halmac);
3138
3139 drv_rsvd_num = rtw_hal_get_rsvd_page_num(a);
3140 rsvd_page_number = _rsvd_page_num_drv2halmac(drv_rsvd_num);
3141 status = api->halmac_cfg_drv_rsvd_pg_num(halmac, rsvd_page_number);
3142 if (status != HALMAC_RET_SUCCESS) {
3143 ret = -1;
3144 goto exit;
3145 }
3146 hal->drv_rsvd_page_number = _rsvd_page_num_halmac2drv(rsvd_page_number);
3147
3148 exit:
3149 #ifndef DBG_RSVD_PAGE_CFG
3150 if (drv_rsvd_num != _rsvd_page_num_halmac2drv(rsvd_page_number))
3151 #endif
3152 RTW_INFO("%s: request %d pages => halmac %d pages %s\n"
3153 , __FUNCTION__, drv_rsvd_num, _rsvd_page_num_halmac2drv(rsvd_page_number)
3154 , ret ? "fail" : "success");
3155
3156 return ret;
3157 }
3158
_debug_dlfw_fail(struct dvobj_priv * d)3159 static void _debug_dlfw_fail(struct dvobj_priv *d)
3160 {
3161 struct _ADAPTER *a;
3162 u32 addr;
3163 u32 v32, i, n;
3164
3165
3166 a = dvobj_get_primary_adapter(d);
3167
3168 /* read 0x80[15:0], 0x10F8[31:0] once */
3169 addr = 0x80;
3170 v32 = rtw_read16(a, addr);
3171 RTW_PRINT("%s: 0x%X = 0x%04x\n", __FUNCTION__, addr, v32);
3172
3173 addr = 0x10F8;
3174 v32 = rtw_read32(a, addr);
3175 RTW_PRINT("%s: 0x%X = 0x%08x\n", __FUNCTION__, addr, v32);
3176
3177 /* read 0x10FC[31:0], 5 times */
3178 addr = 0x10FC;
3179 n = 5;
3180 for (i = 0; i < n; i++) {
3181 v32 = rtw_read32(a, addr);
3182 RTW_PRINT("%s: 0x%X = 0x%08x (%u/%u)\n",
3183 __FUNCTION__, addr, v32, i, n);
3184 }
3185
3186 /*
3187 * write 0x3A[7:0]=0x28 and 0xF6[7:0]=0x01
3188 * and then read 0xC0[31:0] 5 times
3189 */
3190 addr = 0x3A;
3191 v32 = 0x28;
3192 rtw_write8(a, addr, (u8)v32);
3193 v32 = rtw_read8(a, addr);
3194 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v32);
3195
3196 addr = 0xF6;
3197 v32 = 0x1;
3198 rtw_write8(a, addr, (u8)v32);
3199 v32 = rtw_read8(a, addr);
3200 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v32);
3201
3202 addr = 0xC0;
3203 n = 5;
3204 for (i = 0; i < n; i++) {
3205 v32 = rtw_read32(a, addr);
3206 RTW_PRINT("%s: 0x%X = 0x%08x (%u/%u)\n",
3207 __FUNCTION__, addr, v32, i, n);
3208 }
3209
3210 mac_reg_dump(NULL, a);
3211 #ifdef CONFIG_SDIO_HCI
3212 RTW_PRINT("======= SDIO Local REG =======\n");
3213 sdio_local_reg_dump(NULL, a);
3214 RTW_PRINT("======= SDIO CCCR REG =======\n");
3215 sd_f0_reg_dump(NULL, a);
3216 #endif /* CONFIG_SDIO_HCI */
3217
3218 /* read 0x80 after 10 secs */
3219 rtw_msleep_os(10000);
3220 addr = 0x80;
3221 v32 = rtw_read16(a, addr);
3222 RTW_PRINT("%s: 0x%X = 0x%04x (after 10 secs)\n",
3223 __FUNCTION__, addr, v32);
3224 }
3225
_enter_cpu_sleep_mode(struct dvobj_priv * d)3226 static enum halmac_ret_status _enter_cpu_sleep_mode(struct dvobj_priv *d)
3227 {
3228 struct hal_com_data *hal;
3229 struct halmac_adapter *mac;
3230 struct halmac_api *api;
3231
3232
3233 hal = GET_HAL_DATA(dvobj_get_primary_adapter(d));
3234 mac = dvobj_to_halmac(d);
3235 api = HALMAC_GET_API(mac);
3236
3237 #ifdef CONFIG_RTL8822B
3238 /* Support after firmware version 21 */
3239 if (hal->firmware_version < 21)
3240 return HALMAC_RET_NOT_SUPPORT;
3241 #elif defined(CONFIG_RTL8821C)
3242 /* Support after firmware version 13.6 or 16 */
3243 if (hal->firmware_version == 13) {
3244 if (hal->firmware_sub_version < 6)
3245 return HALMAC_RET_NOT_SUPPORT;
3246 } else if (hal->firmware_version < 16) {
3247 return HALMAC_RET_NOT_SUPPORT;
3248 }
3249 #endif
3250
3251 return api->halmac_enter_cpu_sleep_mode(mac);
3252 }
3253
3254 /*
3255 * _cpu_sleep() - Let IC CPU enter sleep mode
3256 * @d: struct dvobj_priv*
3257 * @timeout: time limit of wait, unit is ms
3258 * 0 for no limit
3259 *
3260 * Return 0 for CPU in sleep mode, otherwise fail to enter sleep mode.
3261 * Error codes definition are as follow:
3262 * -1 HALMAC enter sleep return fail
3263 * -2 HALMAC get CPU mode return fail
3264 * -110 timeout
3265 */
_cpu_sleep(struct dvobj_priv * d,u32 timeout)3266 static int _cpu_sleep(struct dvobj_priv *d, u32 timeout)
3267 {
3268 struct halmac_adapter *mac;
3269 struct halmac_api *api;
3270 enum halmac_ret_status status;
3271 enum halmac_wlcpu_mode mode = HALMAC_WLCPU_UNDEFINE;
3272 systime start_t;
3273 s32 period = 0;
3274 u32 cnt = 0;
3275 int err = 0;
3276
3277
3278 mac = dvobj_to_halmac(d);
3279 api = HALMAC_GET_API(mac);
3280
3281 start_t = rtw_get_current_time();
3282
3283 status = _enter_cpu_sleep_mode(d);
3284 if (status != HALMAC_RET_SUCCESS) {
3285 if (status != HALMAC_RET_NOT_SUPPORT)
3286 err = -1;
3287 goto exit;
3288 }
3289
3290 do {
3291 cnt++;
3292
3293 mode = HALMAC_WLCPU_UNDEFINE;
3294 status = api->halmac_get_cpu_mode(mac, &mode);
3295
3296 period = rtw_get_passing_time_ms(start_t);
3297
3298 if (status != HALMAC_RET_SUCCESS) {
3299 err = -2;
3300 break;
3301 }
3302 if (mode == HALMAC_WLCPU_SLEEP)
3303 break;
3304 if (period > timeout) {
3305 err = -110;
3306 break;
3307 }
3308
3309 rtw_msleep_os(1);
3310 } while (1);
3311
3312 exit:
3313 if (err)
3314 RTW_ERR("%s: Fail to enter sleep mode! (%d, %d)\n",
3315 __FUNCTION__, status, mode);
3316
3317 RTW_INFO("%s: Cost %dms to polling %u times. (err=%d)\n",
3318 __FUNCTION__, period, cnt, err);
3319
3320 return err;
3321 }
3322
_init_trx_cfg_drv(struct dvobj_priv * d)3323 static void _init_trx_cfg_drv(struct dvobj_priv *d)
3324 {
3325 #ifdef CONFIG_PCI_HCI
3326 rtw_hal_irp_reset(dvobj_get_primary_adapter(d));
3327 #endif
3328 }
3329
3330 /*
3331 * Description:
3332 * Downlaod Firmware Flow
3333 *
3334 * Parameters:
3335 * d pointer of struct dvobj_priv
3336 * fw firmware array
3337 * fwsize firmware size
3338 * re_dl re-download firmware or not
3339 * 0: run in init hal flow, not re-download
3340 * 1: it is a stand alone operation, not in init hal flow
3341 *
3342 * Return:
3343 * 0 Success
3344 * others Fail
3345 */
download_fw(struct dvobj_priv * d,u8 * fw,u32 fwsize,u8 re_dl)3346 static int download_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize, u8 re_dl)
3347 {
3348 PHAL_DATA_TYPE hal;
3349 struct halmac_adapter *mac;
3350 struct halmac_api *api;
3351 struct halmac_fw_version fw_vesion;
3352 enum halmac_ret_status status;
3353 int err = 0;
3354
3355
3356 hal = GET_HAL_DATA(dvobj_get_primary_adapter(d));
3357 mac = dvobj_to_halmac(d);
3358 api = HALMAC_GET_API(mac);
3359
3360 if ((!fw) || (!fwsize))
3361 return -1;
3362
3363 /* 1. Driver Stop Tx */
3364 /* ToDo */
3365
3366 /* 2. Driver Check Tx FIFO is empty */
3367 err = rtw_halmac_txfifo_wait_empty(d, 2000); /* wait 2s */
3368 if (err) {
3369 err = -1;
3370 goto resume_tx;
3371 }
3372
3373 /* 3. Config MAX download size */
3374 /*
3375 * Already done in rtw_halmac_init_adapter() or
3376 * somewhere calling rtw_halmac_set_max_dl_fw_size().
3377 */
3378
3379 if (re_dl) {
3380 /* 4. Enter IC CPU sleep mode */
3381 err = _cpu_sleep(d, 2000);
3382 if (err) {
3383 RTW_ERR("%s: IC CPU fail to enter sleep mode!(%d)\n",
3384 __FUNCTION__, err);
3385 /* skip this error */
3386 err = 0;
3387 }
3388 }
3389
3390 /* 5. Download Firmware */
3391 status = api->halmac_download_firmware(mac, fw, fwsize);
3392 if (status != HALMAC_RET_SUCCESS) {
3393 RTW_ERR("%s: download firmware FAIL! status=0x%02x\n",
3394 __FUNCTION__, status);
3395 _debug_dlfw_fail(d);
3396 err = -1;
3397 goto resume_tx;
3398 }
3399
3400 /* 5.1. (Driver) Reset driver variables if needed */
3401 hal->LastHMEBoxNum = 0;
3402
3403 /* 5.2. (Driver) Get FW version */
3404 status = api->halmac_get_fw_version(mac, &fw_vesion);
3405 if (status == HALMAC_RET_SUCCESS) {
3406 hal->firmware_version = fw_vesion.version;
3407 hal->firmware_sub_version = fw_vesion.sub_version;
3408 hal->firmware_size = fwsize;
3409 }
3410
3411 resume_tx:
3412 /* 6. Driver resume TX if needed */
3413 /* ToDo */
3414
3415 if (err)
3416 goto exit;
3417
3418 if (re_dl) {
3419 enum halmac_trx_mode mode;
3420
3421 /* 7. Change reserved page size */
3422 err = _cfg_drv_rsvd_pg_num(d);
3423 if (err)
3424 return -1;
3425
3426 /* 8. Init TRX Configuration */
3427 mode = _choose_trx_mode(d);
3428 status = api->halmac_init_trx_cfg(mac, mode);
3429 if (HALMAC_RET_SUCCESS != status)
3430 return -1;
3431 _init_trx_cfg_drv(d);
3432
3433 /* 9. Config RX Aggregation */
3434 err = rtw_halmac_rx_agg_switch(d, _TRUE);
3435 if (err)
3436 return -1;
3437
3438 /* 10. Send General Info */
3439 err = _send_general_info(d);
3440 if (err)
3441 return -1;
3442 }
3443
3444 exit:
3445 return err;
3446 }
3447
init_mac_flow(struct dvobj_priv * d)3448 static int init_mac_flow(struct dvobj_priv *d)
3449 {
3450 PADAPTER p;
3451 struct hal_com_data *hal;
3452 struct halmac_adapter *halmac;
3453 struct halmac_api *api;
3454 enum halmac_drv_rsvd_pg_num rsvd_page_number;
3455 union halmac_wlan_addr hwa;
3456 enum halmac_trx_mode trx_mode;
3457 enum halmac_ret_status status;
3458 u8 drv_rsvd_num;
3459 u8 nettype;
3460 int err, err_ret = -1;
3461
3462
3463 p = dvobj_get_primary_adapter(d);
3464 hal = GET_HAL_DATA(p);
3465 halmac = dvobj_to_halmac(d);
3466 api = HALMAC_GET_API(halmac);
3467
3468 #ifdef CONFIG_SUPPORT_TRX_SHARED
3469 status = api->halmac_cfg_rxff_expand_mode(halmac,
3470 _rtw_get_trx_share_mode(p));
3471 if (status != HALMAC_RET_SUCCESS)
3472 goto out;
3473 #endif
3474
3475 #ifdef DBG_LA_MODE
3476 if (dvobj_to_regsty(d)->la_mode_en) {
3477 status = api->halmac_cfg_la_mode(halmac, HALMAC_LA_MODE_PARTIAL);
3478 if (status != HALMAC_RET_SUCCESS) {
3479 RTW_ERR("%s: Fail to enable LA mode!\n", __FUNCTION__);
3480 goto out;
3481 }
3482 RTW_PRINT("%s: Enable LA mode OK.\n", __FUNCTION__);
3483 }
3484 #endif
3485
3486 err = _cfg_drv_rsvd_pg_num(d);
3487 if (err)
3488 goto out;
3489
3490 #ifdef CONFIG_USB_HCI
3491 status = api->halmac_set_bulkout_num(halmac, d->RtNumOutPipes);
3492 if (status != HALMAC_RET_SUCCESS)
3493 goto out;
3494 #endif /* CONFIG_USB_HCI */
3495
3496 trx_mode = _choose_trx_mode(d);
3497 status = api->halmac_init_mac_cfg(halmac, trx_mode);
3498 if (status != HALMAC_RET_SUCCESS)
3499 goto out;
3500
3501 /* Driver insert flow: Sync driver setting with register */
3502 /* Sync driver RCR cache with register setting */
3503 rtw_hal_get_hwreg(dvobj_get_primary_adapter(d), HW_VAR_RCR, NULL);
3504
3505 #ifdef CONFIG_RTS_FULL_BW
3506 err = rtw_halmac_set_rts_full_bw(d, _TRUE);
3507 if (err)
3508 RTW_WARN("%s: Fail to set RTS FULL BW mode\n", __FUNCTION__);
3509 #else
3510 err = rtw_halmac_set_rts_full_bw(d, _FALSE);
3511 if (err)
3512 RTW_WARN("%s: Fail to disable RTS FULL BW mode\n", __FUNCTION__);
3513 #endif /* CONFIG_RTS_FULL_BW */
3514
3515 _init_trx_cfg_drv(d);
3516 /* Driver inser flow end */
3517
3518 err = rtw_halmac_rx_agg_switch(d, _TRUE);
3519 if (err)
3520 goto out;
3521
3522 nettype = dvobj_to_regsty(d)->wireless_mode;
3523 if (is_supported_vht(nettype) == _TRUE)
3524 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_AC);
3525 else if (is_supported_ht(nettype) == _TRUE)
3526 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_N);
3527 else if (IsSupportedTxOFDM(nettype) == _TRUE)
3528 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_G);
3529 else
3530 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_B);
3531 if (status != HALMAC_RET_SUCCESS)
3532 goto out;
3533
3534 err_ret = 0;
3535 out:
3536 return err_ret;
3537 }
3538
_drv_enable_trx(struct dvobj_priv * d)3539 static int _drv_enable_trx(struct dvobj_priv *d)
3540 {
3541 struct _ADAPTER *adapter;
3542 u32 status;
3543
3544
3545 adapter = dvobj_get_primary_adapter(d);
3546 if (adapter->bup == _FALSE) {
3547 #ifdef CONFIG_NEW_NETDEV_HDL
3548 status = rtw_mi_start_drv_threads(adapter);
3549 #else
3550 status = rtw_start_drv_threads(adapter);
3551 #endif
3552 if (status == _FAIL) {
3553 RTW_ERR("%s: Start threads Failed!\n", __FUNCTION__);
3554 return -1;
3555 }
3556 }
3557
3558 rtw_intf_start(adapter);
3559
3560 return 0;
3561 }
3562
3563 /*
3564 * Notices:
3565 * Make sure following information
3566 * 1. GET_HAL_RFPATH
3567 * 2. GET_HAL_DATA(dvobj_get_primary_adapter(d))->rfe_type
3568 * 3. GET_HAL_DATA(dvobj_get_primary_adapter(d))->PackageType
3569 * 4. dvobj_get_primary_adapter(d)->registrypriv.mp_mode
3570 * are all ready before calling this function.
3571 */
_halmac_init_hal(struct dvobj_priv * d,u8 * fw,u32 fwsize)3572 static int _halmac_init_hal(struct dvobj_priv *d, u8 *fw, u32 fwsize)
3573 {
3574 PADAPTER adapter;
3575 struct halmac_adapter *halmac;
3576 struct halmac_api *api;
3577 enum halmac_ret_status status;
3578 u32 ok;
3579 u8 fw_ok = _FALSE;
3580 int err, err_ret = -1;
3581
3582
3583 adapter = dvobj_get_primary_adapter(d);
3584 halmac = dvobj_to_halmac(d);
3585 if (!halmac)
3586 goto out;
3587 api = HALMAC_GET_API(halmac);
3588
3589 /* StatePowerOff */
3590
3591 /* SKIP: halmac_init_adapter (Already done before) */
3592
3593 /* halmac_pre_Init_system_cfg */
3594 /* halmac_mac_power_switch(on) */
3595 /* halmac_Init_system_cfg */
3596 ok = rtw_hal_power_on(adapter);
3597 if (_FAIL == ok)
3598 goto out;
3599
3600 /* StatePowerOn */
3601
3602 /* DownloadFW */
3603 if (fw && fwsize) {
3604 err = download_fw(d, fw, fwsize, 0);
3605 if (err)
3606 goto out;
3607 fw_ok = _TRUE;
3608 }
3609
3610 /* InitMACFlow */
3611 err = init_mac_flow(d);
3612 if (err)
3613 goto out;
3614
3615 /* Driver insert flow: Enable TR/RX */
3616 err = _drv_enable_trx(d);
3617 if (err)
3618 goto out;
3619
3620 /* halmac_send_general_info */
3621 if (_TRUE == fw_ok) {
3622 err = _send_general_info(d);
3623 if (err)
3624 goto out;
3625 }
3626
3627 /* Init Phy parameter-MAC */
3628 ok = rtw_hal_init_mac_register(adapter);
3629 if (_FALSE == ok)
3630 goto out;
3631
3632 /* StateMacInitialized */
3633
3634 /* halmac_cfg_drv_info */
3635 err = rtw_halmac_config_rx_info(d, HALMAC_DRV_INFO_PHY_STATUS);
3636 if (err)
3637 goto out;
3638
3639 /* halmac_set_hw_value(HALMAC_HW_EN_BB_RF) */
3640 /* Init BB, RF */
3641 ok = rtw_hal_init_phy(adapter);
3642 if (_FALSE == ok)
3643 goto out;
3644
3645 status = api->halmac_init_interface_cfg(halmac);
3646 if (status != HALMAC_RET_SUCCESS)
3647 goto out;
3648
3649 /* SKIP: halmac_verify_platform_api */
3650 /* SKIP: halmac_h2c_lb */
3651
3652 /* StateRxIdle */
3653
3654 err_ret = 0;
3655 out:
3656 return err_ret;
3657 }
3658
rtw_halmac_init_hal(struct dvobj_priv * d)3659 int rtw_halmac_init_hal(struct dvobj_priv *d)
3660 {
3661 return _halmac_init_hal(d, NULL, 0);
3662 }
3663
3664 /*
3665 * Notices:
3666 * Make sure following information
3667 * 1. GET_HAL_RFPATH
3668 * 2. GET_HAL_DATA(dvobj_get_primary_adapter(d))->rfe_type
3669 * 3. GET_HAL_DATA(dvobj_get_primary_adapter(d))->PackageType
3670 * 4. dvobj_get_primary_adapter(d)->registrypriv.mp_mode
3671 * are all ready before calling this function.
3672 */
rtw_halmac_init_hal_fw(struct dvobj_priv * d,u8 * fw,u32 fwsize)3673 int rtw_halmac_init_hal_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
3674 {
3675 return _halmac_init_hal(d, fw, fwsize);
3676 }
3677
3678 /*
3679 * Notices:
3680 * Make sure following information
3681 * 1. GET_HAL_RFPATH
3682 * 2. GET_HAL_DATA(dvobj_get_primary_adapter(d))->rfe_type
3683 * 3. GET_HAL_DATA(dvobj_get_primary_adapter(d))->PackageType
3684 * 4. dvobj_get_primary_adapter(d)->registrypriv.mp_mode
3685 * are all ready before calling this function.
3686 */
rtw_halmac_init_hal_fw_file(struct dvobj_priv * d,u8 * fwpath)3687 int rtw_halmac_init_hal_fw_file(struct dvobj_priv *d, u8 *fwpath)
3688 {
3689 u8 *fw = NULL;
3690 u32 fwmaxsize = 0, size = 0;
3691 int err = 0;
3692
3693
3694 err = rtw_halmac_get_fw_max_size(d, &fwmaxsize);
3695 if (err) {
3696 RTW_ERR("%s: Fail to get Firmware MAX size(err=%d)\n", __FUNCTION__, err);
3697 return -1;
3698 }
3699
3700 fw = rtw_zmalloc(fwmaxsize);
3701 if (!fw)
3702 return -1;
3703
3704 size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
3705 if (!size) {
3706 err = -1;
3707 goto exit;
3708 }
3709
3710 err = _halmac_init_hal(d, fw, size);
3711
3712 exit:
3713 rtw_mfree(fw, fwmaxsize);
3714 /*fw = NULL;*/
3715
3716 return err;
3717 }
3718
rtw_halmac_deinit_hal(struct dvobj_priv * d)3719 int rtw_halmac_deinit_hal(struct dvobj_priv *d)
3720 {
3721 PADAPTER adapter;
3722 struct halmac_adapter *halmac;
3723 struct halmac_api *api;
3724 enum halmac_ret_status status;
3725 int err = -1;
3726
3727
3728 adapter = dvobj_get_primary_adapter(d);
3729 halmac = dvobj_to_halmac(d);
3730 if (!halmac)
3731 goto out;
3732 api = HALMAC_GET_API(halmac);
3733
3734 status = api->halmac_deinit_interface_cfg(halmac);
3735 if (status != HALMAC_RET_SUCCESS)
3736 goto out;
3737
3738 rtw_hal_power_off(adapter);
3739
3740 err = 0;
3741 out:
3742 return err;
3743 }
3744
rtw_halmac_self_verify(struct dvobj_priv * d)3745 int rtw_halmac_self_verify(struct dvobj_priv *d)
3746 {
3747 struct halmac_adapter *mac;
3748 struct halmac_api *api;
3749 enum halmac_ret_status status;
3750 int err = -1;
3751
3752
3753 mac = dvobj_to_halmac(d);
3754 api = HALMAC_GET_API(mac);
3755
3756 status = api->halmac_verify_platform_api(mac);
3757 if (status != HALMAC_RET_SUCCESS)
3758 goto out;
3759
3760 status = api->halmac_h2c_lb(mac);
3761 if (status != HALMAC_RET_SUCCESS)
3762 goto out;
3763
3764 err = 0;
3765 out:
3766 return err;
3767 }
3768
rtw_halmac_txfifo_is_empty(struct dvobj_priv * d)3769 static u8 rtw_halmac_txfifo_is_empty(struct dvobj_priv *d)
3770 {
3771 struct halmac_adapter *mac;
3772 struct halmac_api *api;
3773 enum halmac_ret_status status;
3774 u32 chk_num = 10;
3775 u8 rst = _FALSE;
3776
3777
3778 mac = dvobj_to_halmac(d);
3779 api = HALMAC_GET_API(mac);
3780
3781 status = api->halmac_txfifo_is_empty(mac, chk_num);
3782 if (status == HALMAC_RET_SUCCESS)
3783 rst = _TRUE;
3784
3785 return rst;
3786 }
3787
3788 /**
3789 * rtw_halmac_txfifo_wait_empty() - Wait TX FIFO to be emtpy
3790 * @d: struct dvobj_priv*
3791 * @timeout: time limit of wait, unit is ms
3792 * 0 for no limit
3793 *
3794 * Wait TX FIFO to be emtpy.
3795 *
3796 * Return 0 for TX FIFO is empty, otherwise not empty.
3797 */
rtw_halmac_txfifo_wait_empty(struct dvobj_priv * d,u32 timeout)3798 int rtw_halmac_txfifo_wait_empty(struct dvobj_priv *d, u32 timeout)
3799 {
3800 struct _ADAPTER *a;
3801 u8 empty = _FALSE;
3802 u32 cnt = 0;
3803 systime start_time = 0;
3804 u32 pass_time; /* ms */
3805
3806
3807 a = dvobj_get_primary_adapter(d);
3808 start_time = rtw_get_current_time();
3809
3810 do {
3811 cnt++;
3812 empty = rtw_halmac_txfifo_is_empty(d);
3813 if (empty == _TRUE)
3814 break;
3815
3816 if (timeout) {
3817 pass_time = rtw_get_passing_time_ms(start_time);
3818 if (pass_time > timeout)
3819 break;
3820 }
3821 if (RTW_CANNOT_IO(a)) {
3822 RTW_WARN("%s: Interrupted by I/O forbiden!\n", __FUNCTION__);
3823 break;
3824 }
3825
3826 rtw_msleep_os(2);
3827 } while (1);
3828
3829 if (empty == _FALSE) {
3830 #ifdef CONFIG_RTW_DEBUG
3831 u16 dbg_reg[] = {0x210, 0x230, 0x234, 0x238, 0x23C, 0x240,
3832 0x418, 0x10FC, 0x10F8, 0x11F4, 0x11F8};
3833 u8 i;
3834 u32 val;
3835
3836 if (!RTW_CANNOT_IO(a)) {
3837 for (i = 0; i < ARRAY_SIZE(dbg_reg); i++) {
3838 val = rtw_read32(a, dbg_reg[i]);
3839 RTW_ERR("REG_%X:0x%08x\n", dbg_reg[i], val);
3840 }
3841 }
3842 #endif /* CONFIG_RTW_DEBUG */
3843
3844 RTW_ERR("%s: Fail to wait txfifo empty!(cnt=%d)\n",
3845 __FUNCTION__, cnt);
3846 return -1;
3847 }
3848
3849 return 0;
3850 }
3851
_fw_mem_drv2halmac(enum fw_mem mem,u8 tx_stop)3852 static enum halmac_dlfw_mem _fw_mem_drv2halmac(enum fw_mem mem, u8 tx_stop)
3853 {
3854 enum halmac_dlfw_mem mem_halmac = HALMAC_DLFW_MEM_UNDEFINE;
3855
3856
3857 switch (mem) {
3858 case FW_EMEM:
3859 if (tx_stop == _FALSE)
3860 mem_halmac = HALMAC_DLFW_MEM_EMEM_RSVD_PG;
3861 else
3862 mem_halmac = HALMAC_DLFW_MEM_EMEM;
3863 break;
3864
3865 case FW_IMEM:
3866 case FW_DMEM:
3867 mem_halmac = HALMAC_DLFW_MEM_UNDEFINE;
3868 break;
3869 }
3870
3871 return mem_halmac;
3872 }
3873
rtw_halmac_dlfw_mem(struct dvobj_priv * d,u8 * fw,u32 fwsize,enum fw_mem mem)3874 int rtw_halmac_dlfw_mem(struct dvobj_priv *d, u8 *fw, u32 fwsize, enum fw_mem mem)
3875 {
3876 struct halmac_adapter *mac;
3877 struct halmac_api *api;
3878 enum halmac_ret_status status;
3879 enum halmac_dlfw_mem dlfw_mem;
3880 u8 tx_stop = _FALSE;
3881 u32 chk_timeout = 2000; /* unit: ms */
3882 int err = 0;
3883
3884
3885 mac = dvobj_to_halmac(d);
3886 api = HALMAC_GET_API(mac);
3887
3888 if ((!fw) || (!fwsize))
3889 return -1;
3890
3891 #ifndef RTW_HALMAC_DLFW_MEM_NO_STOP_TX
3892 /* 1. Driver Stop Tx */
3893 /* ToDo */
3894
3895 /* 2. Driver Check Tx FIFO is empty */
3896 err = rtw_halmac_txfifo_wait_empty(d, chk_timeout);
3897 if (err)
3898 tx_stop = _FALSE;
3899 else
3900 tx_stop = _TRUE;
3901 #endif /* !RTW_HALMAC_DLFW_MEM_NO_STOP_TX */
3902
3903 /* 3. Download Firmware MEM */
3904 dlfw_mem = _fw_mem_drv2halmac(mem, tx_stop);
3905 if (dlfw_mem == HALMAC_DLFW_MEM_UNDEFINE) {
3906 err = -1;
3907 goto resume_tx;
3908 }
3909 status = api->halmac_free_download_firmware(mac, dlfw_mem, fw, fwsize);
3910 if (status != HALMAC_RET_SUCCESS) {
3911 RTW_ERR("%s: halmac_free_download_firmware fail(err=0x%x)\n",
3912 __FUNCTION__, status);
3913 err = -1;
3914 goto resume_tx;
3915 }
3916
3917 resume_tx:
3918 #ifndef RTW_HALMAC_DLFW_MEM_NO_STOP_TX
3919 /* 4. Driver resume TX if needed */
3920 /* ToDo */
3921 #endif /* !RTW_HALMAC_DLFW_MEM_NO_STOP_TX */
3922
3923 return err;
3924 }
3925
rtw_halmac_dlfw_mem_from_file(struct dvobj_priv * d,u8 * fwpath,enum fw_mem mem)3926 int rtw_halmac_dlfw_mem_from_file(struct dvobj_priv *d, u8 *fwpath, enum fw_mem mem)
3927 {
3928 u8 *fw = NULL;
3929 u32 fwmaxsize = 0, size = 0;
3930 int err = 0;
3931
3932
3933 err = rtw_halmac_get_fw_max_size(d, &fwmaxsize);
3934 if (err) {
3935 RTW_ERR("%s: Fail to get Firmware MAX size(err=%d)\n", __FUNCTION__, err);
3936 return -1;
3937 }
3938
3939 fw = rtw_zmalloc(fwmaxsize);
3940 if (!fw)
3941 return -1;
3942
3943 size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
3944 if (size)
3945 err = rtw_halmac_dlfw_mem(d, fw, size, mem);
3946 else
3947 err = -1;
3948
3949 rtw_mfree(fw, fwmaxsize);
3950 /*fw = NULL;*/
3951
3952 return err;
3953 }
3954
3955 /*
3956 * Return:
3957 * 0 Success
3958 * -22 Invalid arguemnt
3959 */
rtw_halmac_dlfw(struct dvobj_priv * d,u8 * fw,u32 fwsize)3960 int rtw_halmac_dlfw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
3961 {
3962 PADAPTER adapter;
3963 enum halmac_ret_status status;
3964 u32 ok;
3965 int err, err_ret = -1;
3966
3967
3968 if (!fw || !fwsize)
3969 return -22;
3970
3971 adapter = dvobj_get_primary_adapter(d);
3972
3973 /* re-download firmware */
3974 if (rtw_is_hw_init_completed(adapter))
3975 return download_fw(d, fw, fwsize, 1);
3976
3977 /* Download firmware before hal init */
3978 /* Power on, download firmware and init mac */
3979 ok = rtw_hal_power_on(adapter);
3980 if (_FAIL == ok)
3981 goto out;
3982
3983 err = download_fw(d, fw, fwsize, 0);
3984 if (err) {
3985 err_ret = err;
3986 goto out;
3987 }
3988
3989 err = init_mac_flow(d);
3990 if (err)
3991 goto out;
3992
3993 err = _send_general_info(d);
3994 if (err)
3995 goto out;
3996
3997 err_ret = 0;
3998
3999 out:
4000 return err_ret;
4001 }
4002
rtw_halmac_dlfw_from_file(struct dvobj_priv * d,u8 * fwpath)4003 int rtw_halmac_dlfw_from_file(struct dvobj_priv *d, u8 *fwpath)
4004 {
4005 u8 *fw = NULL;
4006 u32 fwmaxsize = 0, size = 0;
4007 int err = 0;
4008
4009
4010 err = rtw_halmac_get_fw_max_size(d, &fwmaxsize);
4011 if (err) {
4012 RTW_ERR("%s: Fail to get Firmware MAX size(err=%d)\n", __FUNCTION__, err);
4013 return -1;
4014 }
4015
4016 fw = rtw_zmalloc(fwmaxsize);
4017 if (!fw)
4018 return -1;
4019
4020 size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
4021 if (size)
4022 err = rtw_halmac_dlfw(d, fw, size);
4023 else
4024 err = -1;
4025
4026 rtw_mfree(fw, fwmaxsize);
4027 /*fw = NULL;*/
4028
4029 return err;
4030 }
4031
4032 /*
4033 * Description:
4034 * Power on/off BB/RF domain.
4035 *
4036 * Parameters:
4037 * enable _TRUE/_FALSE for power on/off
4038 *
4039 * Return:
4040 * 0 Success
4041 * others Fail
4042 */
rtw_halmac_phy_power_switch(struct dvobj_priv * d,u8 enable)4043 int rtw_halmac_phy_power_switch(struct dvobj_priv *d, u8 enable)
4044 {
4045 PADAPTER adapter;
4046 struct halmac_adapter *halmac;
4047 struct halmac_api *api;
4048 enum halmac_ret_status status;
4049 u8 on;
4050
4051
4052 adapter = dvobj_get_primary_adapter(d);
4053 halmac = dvobj_to_halmac(d);
4054 if (!halmac)
4055 return -1;
4056 api = HALMAC_GET_API(halmac);
4057 on = (enable == _TRUE) ? 1 : 0;
4058
4059 status = api->halmac_set_hw_value(halmac, HALMAC_HW_EN_BB_RF, &on);
4060 if (status != HALMAC_RET_SUCCESS)
4061 return -1;
4062
4063 return 0;
4064 }
4065
_is_fw_read_cmd_down(PADAPTER adapter,u8 msgbox_num)4066 static u8 _is_fw_read_cmd_down(PADAPTER adapter, u8 msgbox_num)
4067 {
4068 u8 read_down = _FALSE;
4069 int retry_cnts = 100;
4070 u8 valid;
4071
4072 do {
4073 valid = rtw_read8(adapter, REG_HMETFR) & BIT(msgbox_num);
4074 if (0 == valid)
4075 read_down = _TRUE;
4076 else
4077 rtw_msleep_os(1);
4078 } while ((!read_down) && (retry_cnts--));
4079
4080 if (_FALSE == read_down)
4081 RTW_WARN("%s, reg_1cc(%x), msg_box(%d)...\n", __func__, rtw_read8(adapter, REG_HMETFR), msgbox_num);
4082
4083 return read_down;
4084 }
4085
4086 /**
4087 * rtw_halmac_send_h2c() - Send H2C to firmware
4088 * @d: struct dvobj_priv*
4089 * @h2c: H2C data buffer, suppose to be 8 bytes
4090 *
4091 * Send H2C to firmware by message box register(0x1D0~0x1D3 & 0x1F0~0x1F3).
4092 *
4093 * Assume firmware be ready to accept H2C here, please check
4094 * (hal->bFWReady == _TRUE) before call this function or make sure firmware is
4095 * ready.
4096 *
4097 * Return: 0 if process OK, otherwise fail to send this H2C.
4098 */
rtw_halmac_send_h2c(struct dvobj_priv * d,u8 * h2c)4099 int rtw_halmac_send_h2c(struct dvobj_priv *d, u8 *h2c)
4100 {
4101 PADAPTER adapter = dvobj_get_primary_adapter(d);
4102 PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
4103 u8 h2c_box_num = 0;
4104 u32 msgbox_addr = 0;
4105 u32 msgbox_ex_addr = 0;
4106 u32 h2c_cmd = 0;
4107 u32 h2c_cmd_ex = 0;
4108 int err = -1;
4109
4110
4111 if (!h2c) {
4112 RTW_WARN("%s: pbuf is NULL\n", __FUNCTION__);
4113 return err;
4114 }
4115
4116 if (rtw_is_surprise_removed(adapter)) {
4117 RTW_WARN("%s: surprise removed\n", __FUNCTION__);
4118 return err;
4119 }
4120
4121 _enter_critical_mutex(&d->h2c_fwcmd_mutex, NULL);
4122
4123 /* pay attention to if race condition happened in H2C cmd setting */
4124 h2c_box_num = hal->LastHMEBoxNum;
4125
4126 if (!_is_fw_read_cmd_down(adapter, h2c_box_num)) {
4127 RTW_WARN(" fw read cmd failed...\n");
4128 #ifdef DBG_CONFIG_ERROR_DETECT
4129 hal->srestpriv.self_dect_fw = _TRUE;
4130 hal->srestpriv.self_dect_fw_cnt++;
4131 #endif /* DBG_CONFIG_ERROR_DETECT */
4132 goto exit;
4133 }
4134
4135 /* Write Ext command (byte 4~7) */
4136 msgbox_ex_addr = REG_HMEBOX_E0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
4137 _rtw_memcpy((u8 *)(&h2c_cmd_ex), h2c + 4, EX_MESSAGE_BOX_SIZE);
4138 h2c_cmd_ex = le32_to_cpu(h2c_cmd_ex);
4139 rtw_write32(adapter, msgbox_ex_addr, h2c_cmd_ex);
4140
4141 /* Write command (byte 0~3) */
4142 msgbox_addr = REG_HMEBOX0 + (h2c_box_num * MESSAGE_BOX_SIZE);
4143 _rtw_memcpy((u8 *)(&h2c_cmd), h2c, 4);
4144 h2c_cmd = le32_to_cpu(h2c_cmd);
4145 rtw_write32(adapter, msgbox_addr, h2c_cmd);
4146
4147 /* update last msg box number */
4148 hal->LastHMEBoxNum = (h2c_box_num + 1) % MAX_H2C_BOX_NUMS;
4149 err = 0;
4150
4151 #ifdef DBG_H2C_CONTENT
4152 RTW_INFO_DUMP("[H2C] - ", h2c, RTW_HALMAC_H2C_MAX_SIZE);
4153 #endif
4154 exit:
4155 _exit_critical_mutex(&d->h2c_fwcmd_mutex, NULL);
4156 return err;
4157 }
4158
4159 /**
4160 * rtw_halmac_c2h_handle() - Handle C2H for HALMAC
4161 * @d: struct dvobj_priv*
4162 * @c2h: Full C2H packet, including RX description and payload
4163 * @size: Size(byte) of c2h
4164 *
4165 * Send C2H packet to HALMAC to process C2H packets, and the expected C2H ID is
4166 * 0xFF. This function won't have any I/O, so caller doesn't have to call it in
4167 * I/O safe place(ex. command thread).
4168 *
4169 * Please sure doesn't call this function in the same thread as someone is
4170 * waiting HALMAC C2H ack, otherwise there is a deadlock happen.
4171 *
4172 * Return: 0 if process OK, otherwise no action for this C2H.
4173 */
rtw_halmac_c2h_handle(struct dvobj_priv * d,u8 * c2h,u32 size)4174 int rtw_halmac_c2h_handle(struct dvobj_priv *d, u8 *c2h, u32 size)
4175 {
4176 struct halmac_adapter *mac;
4177 struct halmac_api *api;
4178 enum halmac_ret_status status;
4179 #ifdef RTW_HALMAC_FILTER_DRV_C2H
4180 u32 desc_size = 0;
4181 u8 *c2h_data;
4182 u8 sub;
4183 #endif /* RTW_HALMAC_FILTER_DRV_C2H */
4184
4185
4186 mac = dvobj_to_halmac(d);
4187 api = HALMAC_GET_API(mac);
4188
4189 #ifdef RTW_HALMAC_FILTER_DRV_C2H
4190 status = api->halmac_get_hw_value(mac, HALMAC_HW_RX_DESC_SIZE,
4191 &desc_size);
4192 if (status != HALMAC_RET_SUCCESS) {
4193 RTW_ERR("%s: fail to get rx desc size!\n", __FUNCTION__);
4194 goto skip_filter;
4195 }
4196
4197 c2h_data = c2h + desc_size;
4198 sub = C2H_HDR_GET_C2H_SUB_CMD_ID(c2h_data);
4199 switch (sub) {
4200 case C2H_SUB_CMD_ID_C2H_PKT_FTM_DBG:
4201 case C2H_SUB_CMD_ID_C2H_PKT_FTM_2_DBG:
4202 case C2H_SUB_CMD_ID_C2H_PKT_FTM_3_DBG:
4203 case C2H_SUB_CMD_ID_C2H_PKT_FTM_4_DBG:
4204 case C2H_SUB_CMD_ID_FTMACKRPT_HDL_DBG:
4205 case C2H_SUB_CMD_ID_FTMC2H_RPT:
4206 case C2H_SUB_CMD_ID_DRVFTMC2H_RPT:
4207 case C2H_SUB_CMD_ID_C2H_PKT_FTM_5_DBG:
4208 case C2H_SUB_CMD_ID_CCX_RPT:
4209 case C2H_SUB_CMD_ID_C2H_PKT_NAN_RPT:
4210 case C2H_SUB_CMD_ID_C2H_PKT_ATM_RPT:
4211 case C2H_SUB_CMD_ID_C2H_PKT_SCC_CSA_RPT:
4212 case C2H_SUB_CMD_ID_C2H_PKT_FW_STATUS_NOTIFY:
4213 case C2H_SUB_CMD_ID_C2H_PKT_FTMSESSION_END:
4214 case C2H_SUB_CMD_ID_C2H_PKT_DETECT_THERMAL:
4215 case C2H_SUB_CMD_ID_FW_FWCTRL_RPT:
4216 case C2H_SUB_CMD_ID_SCAN_CH_NOTIFY:
4217 case C2H_SUB_CMD_ID_FW_TBTT_RPT:
4218 case C2H_SUB_CMD_ID_BCN_OFFLOAD:
4219 case C2H_SUB_CMD_ID_FW_DBG_MSG:
4220 RTW_PRINT("%s: unhandled C2H, id=0xFF subid=0x%x len=%u\n",
4221 __FUNCTION__, sub, C2H_HDR_GET_LEN(c2h_data));
4222 RTW_PRINT_DUMP("C2H: ", c2h_data, size - desc_size);
4223 return 0;
4224 }
4225
4226 skip_filter:
4227 #endif /* RTW_HALMAC_FILTER_DRV_C2H */
4228
4229 status = api->halmac_get_c2h_info(mac, c2h, size);
4230 if (HALMAC_RET_SUCCESS != status)
4231 return -1;
4232
4233 return 0;
4234 }
4235
rtw_halmac_get_available_efuse_size(struct dvobj_priv * d,u32 * size)4236 int rtw_halmac_get_available_efuse_size(struct dvobj_priv *d, u32 *size)
4237 {
4238 struct halmac_adapter *mac;
4239 struct halmac_api *api;
4240 enum halmac_ret_status status;
4241 u32 val;
4242
4243
4244 mac = dvobj_to_halmac(d);
4245 api = HALMAC_GET_API(mac);
4246
4247 status = api->halmac_get_efuse_available_size(mac, &val);
4248 if (HALMAC_RET_SUCCESS != status)
4249 return -1;
4250
4251 *size = val;
4252 return 0;
4253 }
4254
rtw_halmac_get_physical_efuse_size(struct dvobj_priv * d,u32 * size)4255 int rtw_halmac_get_physical_efuse_size(struct dvobj_priv *d, u32 *size)
4256 {
4257 struct halmac_adapter *mac;
4258 struct halmac_api *api;
4259 enum halmac_ret_status status;
4260 u32 val;
4261
4262
4263 mac = dvobj_to_halmac(d);
4264 api = HALMAC_GET_API(mac);
4265
4266 status = api->halmac_get_efuse_size(mac, &val);
4267 if (HALMAC_RET_SUCCESS != status)
4268 return -1;
4269
4270 *size = val;
4271 return 0;
4272 }
4273
rtw_halmac_read_physical_efuse_map(struct dvobj_priv * d,u8 * map,u32 size)4274 int rtw_halmac_read_physical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
4275 {
4276 struct halmac_adapter *mac;
4277 struct halmac_api *api;
4278 enum halmac_ret_status status;
4279 enum halmac_feature_id id;
4280 int ret;
4281
4282
4283 mac = dvobj_to_halmac(d);
4284 api = HALMAC_GET_API(mac);
4285 id = HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE;
4286
4287 ret = init_halmac_event(d, id, map, size);
4288 if (ret)
4289 return -1;
4290
4291 status = api->halmac_dump_efuse_map(mac, HALMAC_EFUSE_R_DRV);
4292 if (HALMAC_RET_SUCCESS != status) {
4293 free_halmac_event(d, id);
4294 return -1;
4295 }
4296
4297 ret = wait_halmac_event(d, id);
4298 if (ret)
4299 return -1;
4300
4301 return 0;
4302 }
4303
rtw_halmac_read_physical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4304 int rtw_halmac_read_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4305 {
4306 struct halmac_adapter *mac;
4307 struct halmac_api *api;
4308 enum halmac_ret_status status;
4309 u8 v;
4310 u32 i;
4311 u8 *efuse = NULL;
4312 u32 size = 0;
4313 int err = 0;
4314
4315
4316 mac = dvobj_to_halmac(d);
4317 api = HALMAC_GET_API(mac);
4318
4319 if (api->halmac_read_efuse) {
4320 for (i = 0; i < cnt; i++) {
4321 status = api->halmac_read_efuse(mac, offset + i, &v);
4322 if (HALMAC_RET_SUCCESS != status)
4323 return -1;
4324 data[i] = v;
4325 }
4326 } else {
4327 err = rtw_halmac_get_physical_efuse_size(d, &size);
4328 if (err)
4329 return -1;
4330
4331 efuse = rtw_zmalloc(size);
4332 if (!efuse)
4333 return -1;
4334
4335 err = rtw_halmac_read_physical_efuse_map(d, efuse, size);
4336 if (err)
4337 err = -1;
4338 else
4339 _rtw_memcpy(data, efuse + offset, cnt);
4340
4341 rtw_mfree(efuse, size);
4342 }
4343
4344 return err;
4345 }
4346
rtw_halmac_write_physical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4347 int rtw_halmac_write_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4348 {
4349 struct halmac_adapter *mac;
4350 struct halmac_api *api;
4351 enum halmac_ret_status status;
4352 u32 i;
4353
4354
4355 mac = dvobj_to_halmac(d);
4356 api = HALMAC_GET_API(mac);
4357
4358 if (api->halmac_write_efuse == NULL)
4359 return -1;
4360
4361 for (i = 0; i < cnt; i++) {
4362 status = api->halmac_write_efuse(mac, offset + i, data[i]);
4363 if (HALMAC_RET_SUCCESS != status)
4364 return -1;
4365 }
4366
4367 return 0;
4368 }
4369
rtw_halmac_get_logical_efuse_size(struct dvobj_priv * d,u32 * size)4370 int rtw_halmac_get_logical_efuse_size(struct dvobj_priv *d, u32 *size)
4371 {
4372 struct halmac_adapter *mac;
4373 struct halmac_api *api;
4374 enum halmac_ret_status status;
4375 u32 val;
4376
4377
4378 mac = dvobj_to_halmac(d);
4379 api = HALMAC_GET_API(mac);
4380
4381 status = api->halmac_get_logical_efuse_size(mac, &val);
4382 if (HALMAC_RET_SUCCESS != status)
4383 return -1;
4384
4385 *size = val;
4386 return 0;
4387 }
4388
rtw_halmac_read_logical_efuse_map(struct dvobj_priv * d,u8 * map,u32 size,u8 * maskmap,u32 masksize)4389 int rtw_halmac_read_logical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size, u8 *maskmap, u32 masksize)
4390 {
4391 struct halmac_adapter *mac;
4392 struct halmac_api *api;
4393 enum halmac_ret_status status;
4394 enum halmac_feature_id id;
4395 int ret;
4396
4397
4398 mac = dvobj_to_halmac(d);
4399 api = HALMAC_GET_API(mac);
4400 id = HALMAC_FEATURE_DUMP_LOGICAL_EFUSE;
4401
4402 ret = init_halmac_event(d, id, map, size);
4403 if (ret)
4404 return -1;
4405
4406 status = api->halmac_dump_logical_efuse_map(mac, HALMAC_EFUSE_R_DRV);
4407 if (HALMAC_RET_SUCCESS != status) {
4408 free_halmac_event(d, id);
4409 return -1;
4410 }
4411
4412 ret = wait_halmac_event(d, id);
4413 if (ret)
4414 return -1;
4415
4416 if (maskmap && masksize) {
4417 struct halmac_pg_efuse_info pginfo;
4418
4419 pginfo.efuse_map = map;
4420 pginfo.efuse_map_size = size;
4421 pginfo.efuse_mask = maskmap;
4422 pginfo.efuse_mask_size = masksize;
4423
4424 status = api->halmac_mask_logical_efuse(mac, &pginfo);
4425 if (status != HALMAC_RET_SUCCESS)
4426 RTW_WARN("%s: mask logical efuse FAIL!\n", __FUNCTION__);
4427 }
4428
4429 return 0;
4430 }
4431
rtw_halmac_write_logical_efuse_map(struct dvobj_priv * d,u8 * map,u32 size,u8 * maskmap,u32 masksize)4432 int rtw_halmac_write_logical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size, u8 *maskmap, u32 masksize)
4433 {
4434 struct halmac_adapter *mac;
4435 struct halmac_api *api;
4436 struct halmac_pg_efuse_info pginfo;
4437 enum halmac_ret_status status;
4438
4439
4440 mac = dvobj_to_halmac(d);
4441 api = HALMAC_GET_API(mac);
4442
4443 pginfo.efuse_map = map;
4444 pginfo.efuse_map_size = size;
4445 pginfo.efuse_mask = maskmap;
4446 pginfo.efuse_mask_size = masksize;
4447
4448 status = api->halmac_pg_efuse_by_map(mac, &pginfo, HALMAC_EFUSE_R_AUTO);
4449 if (HALMAC_RET_SUCCESS != status)
4450 return -1;
4451
4452 return 0;
4453 }
4454
rtw_halmac_read_logical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4455 int rtw_halmac_read_logical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4456 {
4457 struct halmac_adapter *mac;
4458 struct halmac_api *api;
4459 enum halmac_ret_status status;
4460 u8 v;
4461 u32 i;
4462
4463
4464 mac = dvobj_to_halmac(d);
4465 api = HALMAC_GET_API(mac);
4466
4467 for (i = 0; i < cnt; i++) {
4468 status = api->halmac_read_logical_efuse(mac, offset + i, &v);
4469 if (HALMAC_RET_SUCCESS != status)
4470 return -1;
4471 data[i] = v;
4472 }
4473
4474 return 0;
4475 }
4476
rtw_halmac_write_logical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4477 int rtw_halmac_write_logical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4478 {
4479 struct halmac_adapter *mac;
4480 struct halmac_api *api;
4481 enum halmac_ret_status status;
4482 u32 i;
4483
4484
4485 mac = dvobj_to_halmac(d);
4486 api = HALMAC_GET_API(mac);
4487
4488 for (i = 0; i < cnt; i++) {
4489 status = api->halmac_write_logical_efuse(mac, offset + i, data[i]);
4490 if (HALMAC_RET_SUCCESS != status)
4491 return -1;
4492 }
4493
4494 return 0;
4495 }
4496
rtw_halmac_write_bt_physical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4497 int rtw_halmac_write_bt_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4498 {
4499 struct halmac_adapter *mac;
4500 struct halmac_api *api;
4501 enum halmac_ret_status status;
4502 u32 i;
4503 u8 bank = 1;
4504
4505
4506 mac = dvobj_to_halmac(d);
4507 api = HALMAC_GET_API(mac);
4508
4509 for (i = 0; i < cnt; i++) {
4510 status = api->halmac_write_efuse_bt(mac, offset + i, data[i], bank);
4511 if (HALMAC_RET_SUCCESS != status) {
4512 printk("%s: halmac_write_efuse_bt status = %d\n", __FUNCTION__, status);
4513 return -1;
4514 }
4515 }
4516 printk("%s: halmac_write_efuse_bt status = HALMAC_RET_SUCCESS %d\n", __FUNCTION__, status);
4517 return 0;
4518 }
4519
4520
rtw_halmac_read_bt_physical_efuse_map(struct dvobj_priv * d,u8 * map,u32 size)4521 int rtw_halmac_read_bt_physical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
4522 {
4523 struct halmac_adapter *mac;
4524 struct halmac_api *api;
4525 enum halmac_ret_status status;
4526 int bank = 1;
4527
4528
4529 mac = dvobj_to_halmac(d);
4530 api = HALMAC_GET_API(mac);
4531
4532 status = api->halmac_dump_efuse_map_bt(mac, bank, size, map);
4533 if (HALMAC_RET_SUCCESS != status) {
4534 printk("%s: halmac_dump_efuse_map_bt fail!\n", __FUNCTION__);
4535 return -1;
4536 }
4537
4538 printk("%s: OK!\n", __FUNCTION__);
4539
4540 return 0;
4541 }
4542
_fifo_sel_drv2halmac(u8 fifo_sel)4543 static enum hal_fifo_sel _fifo_sel_drv2halmac(u8 fifo_sel)
4544 {
4545 switch (fifo_sel) {
4546 case 0:
4547 return HAL_FIFO_SEL_TX;
4548 case 1:
4549 return HAL_FIFO_SEL_RX;
4550 case 2:
4551 return HAL_FIFO_SEL_RSVD_PAGE;
4552 case 3:
4553 return HAL_FIFO_SEL_REPORT;
4554 case 4:
4555 return HAL_FIFO_SEL_LLT;
4556 case 5:
4557 return HAL_FIFO_SEL_RXBUF_FW;
4558 }
4559
4560 return HAL_FIFO_SEL_RSVD_PAGE;
4561 }
4562
4563 /*#define CONFIG_HALMAC_FIFO_DUMP*/
rtw_halmac_dump_fifo(struct dvobj_priv * d,u8 fifo_sel,u32 addr,u32 size,u8 * buffer)4564 int rtw_halmac_dump_fifo(struct dvobj_priv *d, u8 fifo_sel, u32 addr, u32 size, u8 *buffer)
4565 {
4566 struct halmac_adapter *mac;
4567 struct halmac_api *api;
4568 enum hal_fifo_sel halmac_fifo_sel;
4569 enum halmac_ret_status status;
4570 u8 *pfifo_map = NULL;
4571 u32 fifo_size = 0;
4572 s8 ret = 0;/* 0:success, -1:error */
4573 u8 mem_created = _FALSE;
4574
4575
4576 mac = dvobj_to_halmac(d);
4577 api = HALMAC_GET_API(mac);
4578
4579 if ((size != 0) && (buffer == NULL))
4580 return -1;
4581
4582 halmac_fifo_sel = _fifo_sel_drv2halmac(fifo_sel);
4583
4584 if ((size) && (buffer)) {
4585 pfifo_map = buffer;
4586 fifo_size = size;
4587 } else {
4588 fifo_size = api->halmac_get_fifo_size(mac, halmac_fifo_sel);
4589
4590 if (fifo_size)
4591 pfifo_map = rtw_zvmalloc(fifo_size);
4592 if (pfifo_map == NULL)
4593 return -1;
4594 mem_created = _TRUE;
4595 }
4596
4597 status = api->halmac_dump_fifo(mac, halmac_fifo_sel, addr, fifo_size, pfifo_map);
4598 if (HALMAC_RET_SUCCESS != status) {
4599 ret = -1;
4600 goto _exit;
4601 }
4602
4603 #ifdef CONFIG_HALMAC_FIFO_DUMP
4604 {
4605 static const char * const fifo_sel_str[] = {
4606 "TX", "RX", "RSVD_PAGE", "REPORT", "LLT", "RXBUF_FW"
4607 };
4608
4609 RTW_INFO("%s FIFO DUMP [start_addr:0x%04x , size:%d]\n", fifo_sel_str[halmac_fifo_sel], addr, fifo_size);
4610 RTW_INFO_DUMP("\n", pfifo_map, fifo_size);
4611 RTW_INFO(" ==================================================\n");
4612 }
4613 #endif /* CONFIG_HALMAC_FIFO_DUMP */
4614
4615 _exit:
4616 if ((mem_created == _TRUE) && pfifo_map)
4617 rtw_vmfree(pfifo_map, fifo_size);
4618
4619 return ret;
4620 }
4621
4622 /*
4623 * rtw_halmac_rx_agg_switch() - Switch RX aggregation function and setting
4624 * @d struct dvobj_priv *
4625 * @enable _FALSE/_TRUE for disable/enable RX aggregation function
4626 *
4627 * This function could help to on/off bus RX aggregation function, and is only
4628 * useful for SDIO and USB interface. Although only "enable" flag is brough in,
4629 * some setting would be taken from other places, and they are from:
4630 * [DMA aggregation]
4631 * struct hal_com_data.rxagg_dma_size
4632 * struct hal_com_data.rxagg_dma_timeout
4633 * [USB aggregation] (only use for USB interface)
4634 * struct hal_com_data.rxagg_usb_size
4635 * struct hal_com_data.rxagg_usb_timeout
4636 * If above values of size and timeout are both 0 means driver would not
4637 * control the threshold setting and leave it to HALMAC handle.
4638 *
4639 * From HALMAC V1_04_04, driver force the size threshold be hard limit, and the
4640 * rx size can not exceed the setting.
4641 *
4642 * Return 0 for success, otherwise fail.
4643 */
rtw_halmac_rx_agg_switch(struct dvobj_priv * d,u8 enable)4644 int rtw_halmac_rx_agg_switch(struct dvobj_priv *d, u8 enable)
4645 {
4646 struct _ADAPTER *adapter;
4647 struct hal_com_data *hal;
4648 struct halmac_adapter *halmac;
4649 struct halmac_api *api;
4650 struct halmac_rxagg_cfg rxaggcfg;
4651 enum halmac_ret_status status;
4652
4653
4654 adapter = dvobj_get_primary_adapter(d);
4655 hal = GET_HAL_DATA(adapter);
4656 halmac = dvobj_to_halmac(d);
4657 api = HALMAC_GET_API(halmac);
4658 _rtw_memset((void *)&rxaggcfg, 0, sizeof(rxaggcfg));
4659 rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
4660 /*
4661 * Always enable size limit to avoid rx size exceed
4662 * driver defined size.
4663 */
4664 rxaggcfg.threshold.size_limit_en = 1;
4665
4666 #ifdef RTW_RX_AGGREGATION
4667 if (_TRUE == enable) {
4668 #ifdef CONFIG_SDIO_HCI
4669 rxaggcfg.mode = HALMAC_RX_AGG_MODE_DMA;
4670 rxaggcfg.threshold.drv_define = 0;
4671 if (hal->rxagg_dma_size || hal->rxagg_dma_timeout) {
4672 rxaggcfg.threshold.drv_define = 1;
4673 rxaggcfg.threshold.timeout = hal->rxagg_dma_timeout;
4674 rxaggcfg.threshold.size = hal->rxagg_dma_size;
4675 RTW_INFO("%s: RX aggregation threshold: "
4676 "timeout=%u size=%u\n",
4677 __FUNCTION__,
4678 hal->rxagg_dma_timeout,
4679 hal->rxagg_dma_size);
4680 }
4681 #elif defined(CONFIG_USB_HCI)
4682 switch (hal->rxagg_mode) {
4683 case RX_AGG_DISABLE:
4684 rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
4685 break;
4686
4687 case RX_AGG_DMA:
4688 rxaggcfg.mode = HALMAC_RX_AGG_MODE_DMA;
4689 if (hal->rxagg_dma_size || hal->rxagg_dma_timeout) {
4690 rxaggcfg.threshold.drv_define = 1;
4691 rxaggcfg.threshold.timeout = hal->rxagg_dma_timeout;
4692 rxaggcfg.threshold.size = hal->rxagg_dma_size;
4693 }
4694 break;
4695
4696 case RX_AGG_USB:
4697 case RX_AGG_MIX:
4698 rxaggcfg.mode = HALMAC_RX_AGG_MODE_USB;
4699 if (hal->rxagg_usb_size || hal->rxagg_usb_timeout) {
4700 rxaggcfg.threshold.drv_define = 1;
4701 rxaggcfg.threshold.timeout = hal->rxagg_usb_timeout;
4702 rxaggcfg.threshold.size = hal->rxagg_usb_size;
4703 }
4704 break;
4705 }
4706 #endif /* CONFIG_USB_HCI */
4707 }
4708 #endif /* RTW_RX_AGGREGATION */
4709
4710 status = api->halmac_cfg_rx_aggregation(halmac, &rxaggcfg);
4711 if (status != HALMAC_RET_SUCCESS)
4712 return -1;
4713
4714 return 0;
4715 }
4716
rtw_halmac_download_rsvd_page(struct dvobj_priv * dvobj,u8 pg_offset,u8 * pbuf,u32 size)4717 int rtw_halmac_download_rsvd_page(struct dvobj_priv *dvobj, u8 pg_offset, u8 *pbuf, u32 size)
4718 {
4719 enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4720 struct halmac_adapter *halmac = dvobj_to_halmac(dvobj);
4721 struct halmac_api *api = HALMAC_GET_API(halmac);
4722
4723 status = api->halmac_dl_drv_rsvd_page(halmac, pg_offset, pbuf, size);
4724 if (status != HALMAC_RET_SUCCESS)
4725 return -1;
4726
4727 return 0;
4728 }
4729
4730 /*
4731 * Description
4732 * Fill following spec info from HALMAC API:
4733 * sec_cam_ent_num
4734 *
4735 * Return
4736 * 0 Success
4737 * others Fail
4738 */
rtw_halmac_fill_hal_spec(struct dvobj_priv * dvobj,struct hal_spec_t * spec)4739 int rtw_halmac_fill_hal_spec(struct dvobj_priv *dvobj, struct hal_spec_t *spec)
4740 {
4741 enum halmac_ret_status status;
4742 struct halmac_adapter *halmac;
4743 struct halmac_api *api;
4744 u8 cam = 0; /* Security Cam Entry Number */
4745
4746
4747 halmac = dvobj_to_halmac(dvobj);
4748 api = HALMAC_GET_API(halmac);
4749
4750 /* Prepare data from HALMAC */
4751 status = api->halmac_get_hw_value(halmac, HALMAC_HW_CAM_ENTRY_NUM, &cam);
4752 if (status != HALMAC_RET_SUCCESS)
4753 return -1;
4754
4755 /* Fill data to hal_spec_t */
4756 spec->sec_cam_ent_num = cam;
4757
4758 return 0;
4759 }
4760
rtw_halmac_p2pps(struct dvobj_priv * dvobj,struct hal_p2p_ps_para * pp2p_ps_para)4761 int rtw_halmac_p2pps(struct dvobj_priv *dvobj, struct hal_p2p_ps_para *pp2p_ps_para)
4762 {
4763 enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4764 struct halmac_adapter *halmac = dvobj_to_halmac(dvobj);
4765 struct halmac_api *api = HALMAC_GET_API(halmac);
4766 struct halmac_p2pps halmac_p2p_ps;
4767
4768 (&halmac_p2p_ps)->offload_en = pp2p_ps_para->offload_en;
4769 (&halmac_p2p_ps)->role = pp2p_ps_para->role;
4770 (&halmac_p2p_ps)->ctwindow_en = pp2p_ps_para->ctwindow_en;
4771 (&halmac_p2p_ps)->noa_en = pp2p_ps_para->noa_en;
4772 (&halmac_p2p_ps)->noa_sel = pp2p_ps_para->noa_sel;
4773 (&halmac_p2p_ps)->all_sta_sleep = pp2p_ps_para->all_sta_sleep;
4774 (&halmac_p2p_ps)->discovery = pp2p_ps_para->discovery;
4775 (&halmac_p2p_ps)->disable_close_rf = pp2p_ps_para->disable_close_rf;
4776 (&halmac_p2p_ps)->p2p_port_id = _hw_port_drv2halmac(pp2p_ps_para->p2p_port_id);
4777 (&halmac_p2p_ps)->p2p_group = pp2p_ps_para->p2p_group;
4778 (&halmac_p2p_ps)->p2p_macid = pp2p_ps_para->p2p_macid;
4779 (&halmac_p2p_ps)->ctwindow_length = pp2p_ps_para->ctwindow_length;
4780 (&halmac_p2p_ps)->noa_duration_para = pp2p_ps_para->noa_duration_para;
4781 (&halmac_p2p_ps)->noa_interval_para = pp2p_ps_para->noa_interval_para;
4782 (&halmac_p2p_ps)->noa_start_time_para = pp2p_ps_para->noa_start_time_para;
4783 (&halmac_p2p_ps)->noa_count_para = pp2p_ps_para->noa_count_para;
4784
4785 status = api->halmac_p2pps(halmac, (&halmac_p2p_ps));
4786 if (status != HALMAC_RET_SUCCESS)
4787 return -1;
4788
4789 return 0;
4790
4791 }
4792
4793 /**
4794 * rtw_halmac_iqk() - Run IQ Calibration
4795 * @d: struct dvobj_priv*
4796 * @clear: IQK parameters
4797 * @segment: IQK parameters
4798 *
4799 * Process IQ Calibration(IQK).
4800 *
4801 * Return 0 for OK, otherwise fail.
4802 */
rtw_halmac_iqk(struct dvobj_priv * d,u8 clear,u8 segment)4803 int rtw_halmac_iqk(struct dvobj_priv *d, u8 clear, u8 segment)
4804 {
4805 struct halmac_adapter *mac;
4806 struct halmac_api *api;
4807 enum halmac_ret_status status;
4808 enum halmac_feature_id id;
4809 struct halmac_iqk_para para;
4810 int ret;
4811 u8 retry = 3;
4812 u8 delay = 1; /* ms */
4813
4814
4815 mac = dvobj_to_halmac(d);
4816 api = HALMAC_GET_API(mac);
4817 id = HALMAC_FEATURE_IQK;
4818
4819 ret = init_halmac_event(d, id, NULL, 0);
4820 if (ret)
4821 return -1;
4822
4823 para.clear = clear;
4824 para.segment_iqk = segment;
4825
4826 do {
4827 status = api->halmac_start_iqk(mac, ¶);
4828 if (status != HALMAC_RET_BUSY_STATE)
4829 break;
4830 RTW_WARN("%s: Fail to start IQK, status is BUSY! retry=%d\n", __FUNCTION__, retry);
4831 if (!retry)
4832 break;
4833 retry--;
4834 rtw_msleep_os(delay);
4835 } while (1);
4836 if (status != HALMAC_RET_SUCCESS) {
4837 free_halmac_event(d, id);
4838 return -1;
4839 }
4840
4841 ret = wait_halmac_event(d, id);
4842 if (ret)
4843 return -1;
4844
4845 return 0;
4846 }
4847
4848 /**
4849 * rtw_halmac_dpk() - Run DP Calibration
4850 * @d: struct dvobj_priv*
4851 * @buf: buffer for store return value
4852 * @bufsz: size of buffer
4853 *
4854 * Process DP Calibration(DPK).
4855 *
4856 * Return 0 for OK, otherwise fail.
4857 */
rtw_halmac_dpk(struct dvobj_priv * d,u8 * buf,u32 bufsz)4858 int rtw_halmac_dpk(struct dvobj_priv *d, u8 *buf, u32 bufsz)
4859 {
4860 struct halmac_adapter *mac;
4861 struct halmac_api *api;
4862 enum halmac_ret_status status;
4863 enum halmac_feature_id id;
4864 int ret;
4865
4866
4867 mac = dvobj_to_halmac(d);
4868 api = HALMAC_GET_API(mac);
4869 id = HALMAC_FEATURE_DPK;
4870
4871 ret = init_halmac_event(d, id, buf, bufsz);
4872 if (ret)
4873 return -1;
4874
4875 status = api->halmac_start_dpk(mac);
4876 if (status != HALMAC_RET_SUCCESS) {
4877 free_halmac_event(d, id);
4878 RTW_ERR("%s: Fail to start DPK (0x%x)!\n",
4879 __FUNCTION__, status);
4880 return -1;
4881 }
4882
4883 ret = wait_halmac_event(d, id);
4884 if (ret)
4885 return -1;
4886
4887 return 0;
4888 }
4889
_phy_parameter_val_drv2halmac(u32 val,u8 msk_en,u32 msk)4890 static inline u32 _phy_parameter_val_drv2halmac(u32 val, u8 msk_en, u32 msk)
4891 {
4892 if (!msk_en)
4893 return val;
4894
4895 return (val << bitshift(msk));
4896 }
4897
_phy_parameter_drv2halmac(struct rtw_phy_parameter * para,struct halmac_phy_parameter_info * info)4898 static int _phy_parameter_drv2halmac(struct rtw_phy_parameter *para, struct halmac_phy_parameter_info *info)
4899 {
4900 if (!para || !info)
4901 return -1;
4902
4903 _rtw_memset(info, 0, sizeof(*info));
4904
4905 switch (para->cmd) {
4906 case 0:
4907 /* MAC register */
4908 switch (para->data.mac.size) {
4909 case 1:
4910 info->cmd_id = HALMAC_PARAMETER_CMD_MAC_W8;
4911 break;
4912 case 2:
4913 info->cmd_id = HALMAC_PARAMETER_CMD_MAC_W16;
4914 break;
4915 default:
4916 info->cmd_id = HALMAC_PARAMETER_CMD_MAC_W32;
4917 break;
4918 }
4919 info->content.MAC_REG_W.value = _phy_parameter_val_drv2halmac(
4920 para->data.mac.value,
4921 para->data.mac.msk_en,
4922 para->data.mac.msk);
4923 info->content.MAC_REG_W.msk = para->data.mac.msk;
4924 info->content.MAC_REG_W.offset = para->data.mac.offset;
4925 info->content.MAC_REG_W.msk_en = para->data.mac.msk_en;
4926 break;
4927
4928 case 1:
4929 /* BB register */
4930 switch (para->data.bb.size) {
4931 case 1:
4932 info->cmd_id = HALMAC_PARAMETER_CMD_BB_W8;
4933 break;
4934 case 2:
4935 info->cmd_id = HALMAC_PARAMETER_CMD_BB_W16;
4936 break;
4937 default:
4938 info->cmd_id = HALMAC_PARAMETER_CMD_BB_W32;
4939 break;
4940 }
4941 info->content.BB_REG_W.value = _phy_parameter_val_drv2halmac(
4942 para->data.bb.value,
4943 para->data.bb.msk_en,
4944 para->data.bb.msk);
4945 info->content.BB_REG_W.msk = para->data.bb.msk;
4946 info->content.BB_REG_W.offset = para->data.bb.offset;
4947 info->content.BB_REG_W.msk_en = para->data.bb.msk_en;
4948 break;
4949
4950 case 2:
4951 /* RF register */
4952 info->cmd_id = HALMAC_PARAMETER_CMD_RF_W;
4953 info->content.RF_REG_W.value = _phy_parameter_val_drv2halmac(
4954 para->data.rf.value,
4955 para->data.rf.msk_en,
4956 para->data.rf.msk);
4957 info->content.RF_REG_W.msk = para->data.rf.msk;
4958 info->content.RF_REG_W.offset = para->data.rf.offset;
4959 info->content.RF_REG_W.msk_en = para->data.rf.msk_en;
4960 info->content.RF_REG_W.rf_path = para->data.rf.path;
4961 break;
4962
4963 case 3:
4964 /* Delay register */
4965 if (para->data.delay.unit == 0)
4966 info->cmd_id = HALMAC_PARAMETER_CMD_DELAY_US;
4967 else
4968 info->cmd_id = HALMAC_PARAMETER_CMD_DELAY_MS;
4969 info->content.DELAY_TIME.delay_time = para->data.delay.value;
4970 break;
4971
4972 case 0xFF:
4973 /* Latest(End) command */
4974 info->cmd_id = HALMAC_PARAMETER_CMD_END;
4975 break;
4976
4977 default:
4978 return -1;
4979 }
4980
4981 return 0;
4982 }
4983
4984 /**
4985 * rtw_halmac_cfg_phy_para() - Register(Phy parameter) configuration
4986 * @d: struct dvobj_priv*
4987 * @para: phy parameter
4988 *
4989 * Configure registers by firmware using H2C/C2H mechanism.
4990 * The latest command should be para->cmd==0xFF(End command) to finish all
4991 * processes.
4992 *
4993 * Return: 0 for OK, otherwise fail.
4994 */
rtw_halmac_cfg_phy_para(struct dvobj_priv * d,struct rtw_phy_parameter * para)4995 int rtw_halmac_cfg_phy_para(struct dvobj_priv *d, struct rtw_phy_parameter *para)
4996 {
4997 struct halmac_adapter *mac;
4998 struct halmac_api *api;
4999 enum halmac_ret_status status;
5000 enum halmac_feature_id id;
5001 struct halmac_phy_parameter_info info;
5002 u8 full_fifo;
5003 int err, ret;
5004
5005
5006 mac = dvobj_to_halmac(d);
5007 api = HALMAC_GET_API(mac);
5008 id = HALMAC_FEATURE_CFG_PARA;
5009 full_fifo = 1; /* ToDo: How to deciede? */
5010 ret = 0;
5011
5012 err = _phy_parameter_drv2halmac(para, &info);
5013 if (err)
5014 return -1;
5015
5016 err = init_halmac_event(d, id, NULL, 0);
5017 if (err)
5018 return -1;
5019
5020 status = api->halmac_cfg_parameter(mac, &info, full_fifo);
5021 if (info.cmd_id == HALMAC_PARAMETER_CMD_END) {
5022 if (status == HALMAC_RET_SUCCESS) {
5023 err = wait_halmac_event(d, id);
5024 if (err)
5025 ret = -1;
5026 } else {
5027 free_halmac_event(d, id);
5028 ret = -1;
5029 RTW_ERR("%s: Fail to send END of cfg parameter, status is 0x%x!\n", __FUNCTION__, status);
5030 }
5031 } else {
5032 if (status == HALMAC_RET_PARA_SENDING) {
5033 err = wait_halmac_event(d, id);
5034 if (err)
5035 ret = -1;
5036 } else {
5037 free_halmac_event(d, id);
5038 if (status != HALMAC_RET_SUCCESS) {
5039 ret = -1;
5040 RTW_ERR("%s: Fail to cfg parameter, status is 0x%x!\n", __FUNCTION__, status);
5041 }
5042 }
5043 }
5044
5045 return ret;
5046 }
5047
_led_mode_drv2halmac(u8 drv_mode)5048 static enum halmac_wlled_mode _led_mode_drv2halmac(u8 drv_mode)
5049 {
5050 enum halmac_wlled_mode halmac_mode;
5051
5052
5053 switch (drv_mode) {
5054 case 1:
5055 halmac_mode = HALMAC_WLLED_MODE_TX;
5056 break;
5057 case 2:
5058 halmac_mode = HALMAC_WLLED_MODE_RX;
5059 break;
5060 case 3:
5061 halmac_mode = HALMAC_WLLED_MODE_SW_CTRL;
5062 break;
5063 case 0:
5064 default:
5065 halmac_mode = HALMAC_WLLED_MODE_TRX;
5066 break;
5067 }
5068
5069 return halmac_mode;
5070 }
5071
5072 /**
5073 * rtw_halmac_led_cfg() - Configure Hardware LED Mode
5074 * @d: struct dvobj_priv*
5075 * @enable: enable or disable LED function
5076 * 0: disable
5077 * 1: enable
5078 * @mode: WLan LED mode (valid when enable==1)
5079 * 0: Blink when TX(transmit packet) and RX(receive packet)
5080 * 1: Blink when TX only
5081 * 2: Blink when RX only
5082 * 3: Software control
5083 *
5084 * Configure hardware WLan LED mode.
5085 * If want to change LED mode after enabled, need to disable LED first and
5086 * enable again to set new mode.
5087 *
5088 * Return 0 for OK, otherwise fail.
5089 */
rtw_halmac_led_cfg(struct dvobj_priv * d,u8 enable,u8 mode)5090 int rtw_halmac_led_cfg(struct dvobj_priv *d, u8 enable, u8 mode)
5091 {
5092 struct halmac_adapter *halmac;
5093 struct halmac_api *api;
5094 enum halmac_wlled_mode led_mode;
5095 enum halmac_ret_status status;
5096
5097
5098 halmac = dvobj_to_halmac(d);
5099 api = HALMAC_GET_API(halmac);
5100
5101 if (enable) {
5102 status = api->halmac_pinmux_set_func(halmac,
5103 HALMAC_GPIO_FUNC_WL_LED);
5104 if (status != HALMAC_RET_SUCCESS) {
5105 RTW_ERR("%s: pinmux set fail!(0x%x)\n",
5106 __FUNCTION__, status);
5107 return -1;
5108 }
5109
5110 led_mode = _led_mode_drv2halmac(mode);
5111 status = api->halmac_pinmux_wl_led_mode(halmac, led_mode);
5112 if (status != HALMAC_RET_SUCCESS) {
5113 RTW_ERR("%s: mode set fail!(0x%x)\n",
5114 __FUNCTION__, status);
5115 return -1;
5116 }
5117 } else {
5118 /* Change LED to software control and turn off */
5119 api->halmac_pinmux_wl_led_mode(halmac,
5120 HALMAC_WLLED_MODE_SW_CTRL);
5121 api->halmac_pinmux_wl_led_sw_ctrl(halmac, 0);
5122
5123 status = api->halmac_pinmux_free_func(halmac,
5124 HALMAC_GPIO_FUNC_WL_LED);
5125 if (status != HALMAC_RET_SUCCESS) {
5126 RTW_ERR("%s: pinmux free fail!(0x%x)\n",
5127 __FUNCTION__, status);
5128 return -1;
5129 }
5130 }
5131
5132 return 0;
5133 }
5134
5135 /**
5136 * rtw_halmac_led_switch() - Turn Hardware LED on/off
5137 * @d: struct dvobj_priv*
5138 * @on: LED light or not
5139 * 0: Off
5140 * 1: On(Light)
5141 *
5142 * Turn Hardware WLan LED On/Off.
5143 * Before use this function, user should call rtw_halmac_led_ctrl() to switch
5144 * mode to "software control(3)" first, otherwise control would fail.
5145 * The interval between on and off must be longer than 1 ms, or the LED would
5146 * keep light or dark only.
5147 * Ex. Turn off LED at first, turn on after 0.5ms and turn off again after
5148 * 0.5ms. The LED during this flow will only keep dark, and miss the turn on
5149 * operation between two turn off operations.
5150 */
rtw_halmac_led_switch(struct dvobj_priv * d,u8 on)5151 void rtw_halmac_led_switch(struct dvobj_priv *d, u8 on)
5152 {
5153 struct halmac_adapter *halmac;
5154 struct halmac_api *api;
5155
5156
5157 halmac = dvobj_to_halmac(d);
5158 api = HALMAC_GET_API(halmac);
5159
5160 api->halmac_pinmux_wl_led_sw_ctrl(halmac, on);
5161 }
5162
5163 /**
5164 * rtw_halmac_bt_wake_cfg() - Configure BT wake host function
5165 * @d: struct dvobj_priv*
5166 * @enable: enable or disable BT wake host function
5167 * 0: disable
5168 * 1: enable
5169 *
5170 * Configure pinmux to allow BT to control BT wake host pin.
5171 *
5172 * Return 0 for OK, otherwise fail.
5173 */
rtw_halmac_bt_wake_cfg(struct dvobj_priv * d,u8 enable)5174 int rtw_halmac_bt_wake_cfg(struct dvobj_priv *d, u8 enable)
5175 {
5176 struct halmac_adapter *halmac;
5177 struct halmac_api *api;
5178 enum halmac_ret_status status;
5179
5180
5181 halmac = dvobj_to_halmac(d);
5182 api = HALMAC_GET_API(halmac);
5183
5184 if (enable) {
5185 status = api->halmac_pinmux_set_func(halmac,
5186 HALMAC_GPIO_FUNC_BT_HOST_WAKE1);
5187 if (status != HALMAC_RET_SUCCESS) {
5188 RTW_ERR("%s: pinmux set BT_HOST_WAKE1 fail!(0x%x)\n",
5189 __FUNCTION__, status);
5190 return -1;
5191 }
5192 } else {
5193 status = api->halmac_pinmux_free_func(halmac,
5194 HALMAC_GPIO_FUNC_BT_HOST_WAKE1);
5195 if (status != HALMAC_RET_SUCCESS) {
5196 RTW_ERR("%s: pinmux free BT_HOST_WAKE1 fail!(0x%x)\n",
5197 __FUNCTION__, status);
5198 return -1;
5199 }
5200 }
5201
5202 return 0;
5203 }
5204
5205 #ifdef CONFIG_PNO_SUPPORT
5206 /**
5207 * _halmac_scanoffload() - Switch channel by firmware during scanning
5208 * @d: struct dvobj_priv*
5209 * @enable: 1: enable, 0: disable
5210 * @nlo: 1: nlo mode (no c2h event), 0: normal mode
5211 * @ssid: ssid of probe request
5212 * @ssid_len: ssid length
5213 *
5214 * Switch Channel and Send Porbe Request Offloaded by FW
5215 *
5216 * Return 0 for OK, otherwise fail.
5217 */
_halmac_scanoffload(struct dvobj_priv * d,u32 enable,u8 nlo,u8 * ssid,u8 ssid_len)5218 static int _halmac_scanoffload(struct dvobj_priv *d, u32 enable, u8 nlo,
5219 u8 *ssid, u8 ssid_len)
5220 {
5221 struct _ADAPTER *adapter;
5222 struct halmac_adapter *mac;
5223 struct halmac_api *api;
5224 enum halmac_ret_status status;
5225 struct halmac_ch_info ch_info;
5226 struct halmac_ch_switch_option cs_option;
5227 struct mlme_ext_priv *pmlmeext;
5228 enum halmac_feature_id id_update, id_ch_sw;
5229 struct halmac_indicator *indicator, *tbl;
5230
5231 int err = 0;
5232 u8 probereq[64];
5233 u32 len = 0;
5234 int i = 0;
5235 struct pno_ssid pnossid;
5236 struct rf_ctl_t *rfctl = NULL;
5237 struct _RT_CHANNEL_INFO *ch_set;
5238
5239
5240 tbl = d->hmpriv.indicator;
5241 adapter = dvobj_get_primary_adapter(d);
5242 mac = dvobj_to_halmac(d);
5243 if (!mac)
5244 return -1;
5245 api = HALMAC_GET_API(mac);
5246 id_update = HALMAC_FEATURE_UPDATE_PACKET;
5247 id_ch_sw = HALMAC_FEATURE_CHANNEL_SWITCH;
5248 pmlmeext = &(adapter->mlmeextpriv);
5249 rfctl = adapter_to_rfctl(adapter);
5250 ch_set = rfctl->channel_set;
5251
5252 RTW_INFO("%s: %s scanoffload, mode: %s\n",
5253 __FUNCTION__, enable?"Enable":"Disable",
5254 nlo?"PNO/NLO":"Normal");
5255
5256 if (enable) {
5257 _rtw_memset(probereq, 0, sizeof(probereq));
5258
5259 _rtw_memset(&pnossid, 0, sizeof(pnossid));
5260 if (ssid) {
5261 if (ssid_len > sizeof(pnossid.SSID)) {
5262 RTW_ERR("%s: SSID length(%d) is too long(>%d)!!\n",
5263 __FUNCTION__, ssid_len, sizeof(pnossid.SSID));
5264 return -1;
5265 }
5266
5267 pnossid.SSID_len = ssid_len;
5268 _rtw_memcpy(pnossid.SSID, ssid, ssid_len);
5269 }
5270
5271 rtw_hal_construct_ProbeReq(adapter, probereq, &len, &pnossid);
5272
5273 if (!nlo) {
5274 err = init_halmac_event(d, id_update, NULL, 0);
5275 if (err)
5276 return -1;
5277 }
5278
5279 status = api->halmac_update_packet(mac, HALMAC_PACKET_PROBE_REQ,
5280 probereq, len);
5281 if (status != HALMAC_RET_SUCCESS) {
5282 if (!nlo)
5283 free_halmac_event(d, id_update);
5284 RTW_ERR("%s: halmac_update_packet FAIL(%d)!!\n",
5285 __FUNCTION__, status);
5286 return -1;
5287 }
5288
5289 if (!nlo) {
5290 err = wait_halmac_event(d, id_update);
5291 if (err)
5292 RTW_ERR("%s: wait update packet FAIL(%d)!!\n",
5293 __FUNCTION__, err);
5294 }
5295
5296 api->halmac_clear_ch_info(mac);
5297
5298 for (i = 0; i < rfctl->max_chan_nums && ch_set[i].ChannelNum != 0; i++) {
5299 _rtw_memset(&ch_info, 0, sizeof(ch_info));
5300 ch_info.extra_info = 0;
5301 ch_info.channel = ch_set[i].ChannelNum;
5302 ch_info.bw = HALMAC_BW_20;
5303 ch_info.pri_ch_idx = HALMAC_CH_IDX_1;
5304 ch_info.action_id = HALMAC_CS_ACTIVE_SCAN;
5305 ch_info.timeout = 1;
5306 status = api->halmac_add_ch_info(mac, &ch_info);
5307 if (status != HALMAC_RET_SUCCESS) {
5308 RTW_ERR("%s: add_ch_info FAIL(%d)!!\n",
5309 __FUNCTION__, status);
5310 return -1;
5311 }
5312 }
5313
5314 /* set channel switch option */
5315 _rtw_memset(&cs_option, 0, sizeof(cs_option));
5316 cs_option.dest_bw = HALMAC_BW_20;
5317 cs_option.periodic_option = HALMAC_CS_PERIODIC_2_PHASE;
5318 cs_option.dest_pri_ch_idx = HALMAC_CH_IDX_UNDEFINE;
5319 cs_option.tsf_low = 0;
5320 cs_option.switch_en = 1;
5321 cs_option.dest_ch_en = 1;
5322 cs_option.absolute_time_en = 0;
5323 cs_option.dest_ch = 1;
5324
5325 cs_option.normal_period = 5;
5326 cs_option.normal_period_sel = 0;
5327 cs_option.normal_cycle = 10;
5328
5329 cs_option.phase_2_period = 1;
5330 cs_option.phase_2_period_sel = 1;
5331
5332 /* nlo is for wow fw, 1: no c2h response */
5333 cs_option.nlo_en = nlo;
5334
5335 if (!nlo) {
5336 err = init_halmac_event(d, id_ch_sw, NULL, 0);
5337 if (err)
5338 return -1;
5339 }
5340
5341 status = api->halmac_ctrl_ch_switch(mac, &cs_option);
5342 if (status != HALMAC_RET_SUCCESS) {
5343 if (!nlo)
5344 free_halmac_event(d, id_ch_sw);
5345 RTW_ERR("%s: halmac_ctrl_ch_switch FAIL(%d)!!\n",
5346 __FUNCTION__, status);
5347 return -1;
5348 }
5349
5350 if (!nlo) {
5351 err = wait_halmac_event(d, id_ch_sw);
5352 if (err)
5353 RTW_ERR("%s: wait ctrl_ch_switch FAIL(%d)!!\n",
5354 __FUNCTION__, err);
5355 }
5356 } else {
5357 api->halmac_clear_ch_info(mac);
5358
5359 _rtw_memset(&cs_option, 0, sizeof(cs_option));
5360 cs_option.switch_en = 0;
5361
5362 if (!nlo) {
5363 err = init_halmac_event(d, id_ch_sw, NULL, 0);
5364 if (err)
5365 return -1;
5366 }
5367
5368 status = api->halmac_ctrl_ch_switch(mac, &cs_option);
5369 if (status != HALMAC_RET_SUCCESS) {
5370 if (!nlo)
5371 free_halmac_event(d, id_ch_sw);
5372 RTW_ERR("%s: halmac_ctrl_ch_switch FAIL(%d)!!\n",
5373 __FUNCTION__, status);
5374 return -1;
5375 }
5376
5377 if (!nlo) {
5378 err = wait_halmac_event(d, id_ch_sw);
5379 if (err)
5380 RTW_ERR("%s: wait ctrl_ch_switch FAIL(%d)!!\n",
5381 __FUNCTION__, err);
5382 }
5383 }
5384
5385 return 0;
5386 }
5387
5388 /**
5389 * rtw_halmac_pno_scanoffload() - Control firmware scan AP function for PNO
5390 * @d: struct dvobj_priv*
5391 * @enable: 1: enable, 0: disable
5392 *
5393 * Switch firmware scan AP function for PNO(prefer network offload) or
5394 * NLO(network list offload).
5395 *
5396 * Return 0 for OK, otherwise fail.
5397 */
rtw_halmac_pno_scanoffload(struct dvobj_priv * d,u32 enable)5398 int rtw_halmac_pno_scanoffload(struct dvobj_priv *d, u32 enable)
5399 {
5400 return _halmac_scanoffload(d, enable, 1, NULL, 0);
5401 }
5402 #endif /* CONFIG_PNO_SUPPORT */
5403
5404 #ifdef CONFIG_SDIO_HCI
5405
5406 /**
5407 * rtw_halmac_preinit_sdio_io_indirect() - Enable indirect I/O or not
5408 * @d: struct dvobj_priv*
5409 * @enable: true: enable, false: disable
5410 *
5411 * Enable register access using direct I/O or indirect. This function should be
5412 * called before rtw_halmac_init_adapter(), and the life cycle is the same as
5413 * driver until removing driver.
5414 *
5415 * Return 0 for OK, otherwise fail.
5416 */
rtw_halmac_preinit_sdio_io_indirect(struct dvobj_priv * d,bool enable)5417 int rtw_halmac_preinit_sdio_io_indirect(struct dvobj_priv *d, bool enable)
5418 {
5419 struct halmac_adapter *halmac;
5420 struct halmacpriv *priv;
5421
5422
5423 halmac = dvobj_to_halmac(d);
5424 if (halmac) {
5425 RTW_WARN("%s: illegal operation! "
5426 "preinit function only could be called before init!\n",
5427 __FUNCTION__);
5428 return -1;
5429 }
5430
5431 priv = &d->hmpriv;
5432 priv->sdio_io_indir = (enable ? 1 : 2);
5433
5434 return 0;
5435 }
5436
5437 /*
5438 * Description:
5439 * Update queue allocated page number to driver
5440 *
5441 * Parameter:
5442 * d pointer to struct dvobj_priv of driver
5443 *
5444 * Return:
5445 * 0 Success, "page" is valid.
5446 * others Fail, "page" is invalid.
5447 */
rtw_halmac_query_tx_page_num(struct dvobj_priv * d)5448 int rtw_halmac_query_tx_page_num(struct dvobj_priv *d)
5449 {
5450 PADAPTER adapter;
5451 struct halmacpriv *hmpriv;
5452 struct halmac_adapter *halmac;
5453 struct halmac_api *api;
5454 struct halmac_rqpn_map rqpn;
5455 enum halmac_dma_mapping dmaqueue;
5456 struct halmac_txff_allocation fifosize;
5457 enum halmac_ret_status status;
5458 u8 i;
5459
5460
5461 adapter = dvobj_get_primary_adapter(d);
5462 hmpriv = &d->hmpriv;
5463 halmac = dvobj_to_halmac(d);
5464 api = HALMAC_GET_API(halmac);
5465 _rtw_memset((void *)&rqpn, 0, sizeof(rqpn));
5466 _rtw_memset((void *)&fifosize, 0, sizeof(fifosize));
5467
5468 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RQPN_MAPPING, &rqpn);
5469 if (status != HALMAC_RET_SUCCESS)
5470 return -1;
5471 status = api->halmac_get_hw_value(halmac, HALMAC_HW_TXFF_ALLOCATION, &fifosize);
5472 if (status != HALMAC_RET_SUCCESS)
5473 return -1;
5474
5475 for (i = 0; i < HW_QUEUE_ENTRY; i++) {
5476 hmpriv->txpage[i] = 0;
5477
5478 /* Driver index mapping to HALMAC DMA queue */
5479 dmaqueue = HALMAC_DMA_MAPPING_UNDEFINE;
5480 switch (i) {
5481 case VO_QUEUE_INX:
5482 dmaqueue = rqpn.dma_map_vo;
5483 break;
5484 case VI_QUEUE_INX:
5485 dmaqueue = rqpn.dma_map_vi;
5486 break;
5487 case BE_QUEUE_INX:
5488 dmaqueue = rqpn.dma_map_be;
5489 break;
5490 case BK_QUEUE_INX:
5491 dmaqueue = rqpn.dma_map_bk;
5492 break;
5493 case MGT_QUEUE_INX:
5494 dmaqueue = rqpn.dma_map_mg;
5495 break;
5496 case HIGH_QUEUE_INX:
5497 dmaqueue = rqpn.dma_map_hi;
5498 break;
5499 case BCN_QUEUE_INX:
5500 case TXCMD_QUEUE_INX:
5501 /* Unlimited */
5502 hmpriv->txpage[i] = 0xFFFF;
5503 continue;
5504 }
5505
5506 switch (dmaqueue) {
5507 case HALMAC_DMA_MAPPING_EXTRA:
5508 hmpriv->txpage[i] = fifosize.extra_queue_pg_num;
5509 break;
5510 case HALMAC_DMA_MAPPING_LOW:
5511 hmpriv->txpage[i] = fifosize.low_queue_pg_num;
5512 break;
5513 case HALMAC_DMA_MAPPING_NORMAL:
5514 hmpriv->txpage[i] = fifosize.normal_queue_pg_num;
5515 break;
5516 case HALMAC_DMA_MAPPING_HIGH:
5517 hmpriv->txpage[i] = fifosize.high_queue_pg_num;
5518 break;
5519 case HALMAC_DMA_MAPPING_UNDEFINE:
5520 break;
5521 }
5522 hmpriv->txpage[i] += fifosize.pub_queue_pg_num;
5523 }
5524
5525 return 0;
5526 }
5527
5528 /*
5529 * Description:
5530 * Get specific queue allocated page number
5531 *
5532 * Parameter:
5533 * d pointer to struct dvobj_priv of driver
5534 * queue target queue to query, VO/VI/BE/BK/.../TXCMD_QUEUE_INX
5535 * page return allocated page number
5536 *
5537 * Return:
5538 * 0 Success, "page" is valid.
5539 * others Fail, "page" is invalid.
5540 */
rtw_halmac_get_tx_queue_page_num(struct dvobj_priv * d,u8 queue,u32 * page)5541 int rtw_halmac_get_tx_queue_page_num(struct dvobj_priv *d, u8 queue, u32 *page)
5542 {
5543 *page = 0;
5544 if (queue < HW_QUEUE_ENTRY)
5545 *page = d->hmpriv.txpage[queue];
5546
5547 return 0;
5548 }
5549
5550 /*
5551 * Return:
5552 * address for SDIO command
5553 */
rtw_halmac_sdio_get_tx_addr(struct dvobj_priv * d,u8 * desc,u32 size)5554 u32 rtw_halmac_sdio_get_tx_addr(struct dvobj_priv *d, u8 *desc, u32 size)
5555 {
5556 struct halmac_adapter *mac;
5557 struct halmac_api *api;
5558 enum halmac_ret_status status;
5559 u32 addr;
5560
5561
5562 mac = dvobj_to_halmac(d);
5563 api = HALMAC_GET_API(mac);
5564
5565 status = api->halmac_get_sdio_tx_addr(mac, desc, size, &addr);
5566 if (HALMAC_RET_SUCCESS != status)
5567 return 0;
5568
5569 return addr;
5570 }
5571
rtw_halmac_sdio_tx_allowed(struct dvobj_priv * d,u8 * buf,u32 size)5572 int rtw_halmac_sdio_tx_allowed(struct dvobj_priv *d, u8 *buf, u32 size)
5573 {
5574 struct halmac_adapter *mac;
5575 struct halmac_api *api;
5576 enum halmac_ret_status status;
5577
5578
5579 mac = dvobj_to_halmac(d);
5580 api = HALMAC_GET_API(mac);
5581
5582 status = api->halmac_tx_allowed_sdio(mac, buf, size);
5583 if (HALMAC_RET_SUCCESS != status)
5584 return -1;
5585
5586 return 0;
5587 }
5588
rtw_halmac_sdio_get_rx_addr(struct dvobj_priv * d,u8 * seq)5589 u32 rtw_halmac_sdio_get_rx_addr(struct dvobj_priv *d, u8 *seq)
5590 {
5591 u8 id;
5592
5593 #define RTW_SDIO_ADDR_RX_RX0FF_PRFIX 0x0E000
5594 #define RTW_SDIO_ADDR_RX_RX0FF_GEN(a) (RTW_SDIO_ADDR_RX_RX0FF_PRFIX|(a&0x3))
5595
5596 id = *seq;
5597 (*seq)++;
5598 return RTW_SDIO_ADDR_RX_RX0FF_GEN(id);
5599 }
5600
rtw_halmac_sdio_set_tx_format(struct dvobj_priv * d,enum halmac_sdio_tx_format format)5601 int rtw_halmac_sdio_set_tx_format(struct dvobj_priv *d, enum halmac_sdio_tx_format format)
5602 {
5603 struct halmac_adapter *mac;
5604 struct halmac_api *api;
5605 enum halmac_ret_status status;
5606
5607 mac = dvobj_to_halmac(d);
5608 api = HALMAC_GET_API(mac);
5609
5610 status = api->halmac_set_hw_value(mac, HALMAC_HW_SDIO_TX_FORMAT, &format);
5611 if (HALMAC_RET_SUCCESS != status)
5612 return -1;
5613
5614 return 0;
5615 }
5616 #endif /* CONFIG_SDIO_HCI */
5617
5618 #ifdef CONFIG_USB_HCI
rtw_halmac_usb_get_bulkout_id(struct dvobj_priv * d,u8 * buf,u32 size)5619 u8 rtw_halmac_usb_get_bulkout_id(struct dvobj_priv *d, u8 *buf, u32 size)
5620 {
5621 struct halmac_adapter *mac;
5622 struct halmac_api *api;
5623 enum halmac_ret_status status;
5624 u8 bulkout_id;
5625
5626
5627 mac = dvobj_to_halmac(d);
5628 api = HALMAC_GET_API(mac);
5629
5630 status = api->halmac_get_usb_bulkout_id(mac, buf, size, &bulkout_id);
5631 if (HALMAC_RET_SUCCESS != status)
5632 return 0;
5633
5634 return bulkout_id;
5635 }
5636
5637 /**
5638 * rtw_halmac_usb_get_txagg_desc_num() - MAX descriptor number in one bulk for TX
5639 * @d: struct dvobj_priv*
5640 * @size: TX FIFO size, unit is byte.
5641 *
5642 * Get MAX descriptor number in one bulk out from HALMAC.
5643 *
5644 * Return 0 for OK, otherwise fail.
5645 */
rtw_halmac_usb_get_txagg_desc_num(struct dvobj_priv * d,u8 * num)5646 int rtw_halmac_usb_get_txagg_desc_num(struct dvobj_priv *d, u8 *num)
5647 {
5648 struct halmac_adapter *halmac;
5649 struct halmac_api *api;
5650 enum halmac_ret_status status;
5651 u8 val = 0;
5652
5653
5654 halmac = dvobj_to_halmac(d);
5655 api = HALMAC_GET_API(halmac);
5656
5657 status = api->halmac_get_hw_value(halmac, HALMAC_HW_USB_TXAGG_DESC_NUM, &val);
5658 if (status != HALMAC_RET_SUCCESS)
5659 return -1;
5660
5661 *num = val;
5662
5663 return 0;
5664 }
5665
_usb_mode_drv2halmac(enum RTW_USB_SPEED usb_mode)5666 static inline enum halmac_usb_mode _usb_mode_drv2halmac(enum RTW_USB_SPEED usb_mode)
5667 {
5668 enum halmac_usb_mode halmac_usb_mode = HALMAC_USB_MODE_U2;
5669
5670 switch (usb_mode) {
5671 case RTW_USB_SPEED_2:
5672 halmac_usb_mode = HALMAC_USB_MODE_U2;
5673 break;
5674 case RTW_USB_SPEED_3:
5675 halmac_usb_mode = HALMAC_USB_MODE_U3;
5676 break;
5677 default:
5678 halmac_usb_mode = HALMAC_USB_MODE_U2;
5679 break;
5680 }
5681
5682 return halmac_usb_mode;
5683 }
5684
rtw_halmac_switch_usb_mode(struct dvobj_priv * d,enum RTW_USB_SPEED usb_mode)5685 u8 rtw_halmac_switch_usb_mode(struct dvobj_priv *d, enum RTW_USB_SPEED usb_mode)
5686 {
5687 PADAPTER adapter;
5688 struct halmac_adapter *mac;
5689 struct halmac_api *api;
5690 enum halmac_ret_status status;
5691 enum halmac_usb_mode halmac_usb_mode;
5692
5693 adapter = dvobj_get_primary_adapter(d);
5694 mac = dvobj_to_halmac(d);
5695 api = HALMAC_GET_API(mac);
5696 halmac_usb_mode = _usb_mode_drv2halmac(usb_mode);
5697 status = api->halmac_set_hw_value(mac, HALMAC_HW_USB_MODE, (void *)&halmac_usb_mode);
5698
5699 if (HALMAC_RET_SUCCESS != status)
5700 return _FAIL;
5701
5702 return _SUCCESS;
5703 }
5704 #endif /* CONFIG_USB_HCI */
5705
5706 #ifdef CONFIG_BEAMFORMING
5707 #ifdef RTW_BEAMFORMING_VERSION_2
rtw_halmac_bf_add_mu_bfer(struct dvobj_priv * d,u16 paid,u16 csi_para,u16 my_aid,enum halmac_csi_seg_len sel,u8 * addr)5708 int rtw_halmac_bf_add_mu_bfer(struct dvobj_priv *d, u16 paid, u16 csi_para,
5709 u16 my_aid, enum halmac_csi_seg_len sel, u8 *addr)
5710 {
5711 struct halmac_adapter *mac;
5712 struct halmac_api *api;
5713 enum halmac_ret_status status;
5714 struct halmac_mu_bfer_init_para param;
5715
5716
5717 mac = dvobj_to_halmac(d);
5718 api = HALMAC_GET_API(mac);
5719
5720 _rtw_memset(¶m, 0, sizeof(param));
5721 param.paid = paid;
5722 param.csi_para = csi_para;
5723 param.my_aid = my_aid;
5724 param.csi_length_sel = sel;
5725 _rtw_memcpy(param.bfer_address.addr, addr, 6);
5726
5727 status = api->halmac_mu_bfer_entry_init(mac, ¶m);
5728 if (status != HALMAC_RET_SUCCESS)
5729 return -1;
5730
5731 return 0;
5732 }
5733
rtw_halmac_bf_del_mu_bfer(struct dvobj_priv * d)5734 int rtw_halmac_bf_del_mu_bfer(struct dvobj_priv *d)
5735 {
5736 struct halmac_adapter *mac;
5737 struct halmac_api *api;
5738 enum halmac_ret_status status;
5739
5740
5741 mac = dvobj_to_halmac(d);
5742 api = HALMAC_GET_API(mac);
5743
5744 status = api->halmac_mu_bfer_entry_del(mac);
5745 if (status != HALMAC_RET_SUCCESS)
5746 return -1;
5747
5748 return 0;
5749 }
5750
5751
rtw_halmac_bf_cfg_sounding(struct dvobj_priv * d,enum halmac_snd_role role,enum halmac_data_rate rate)5752 int rtw_halmac_bf_cfg_sounding(struct dvobj_priv *d,
5753 enum halmac_snd_role role, enum halmac_data_rate rate)
5754 {
5755 struct halmac_adapter *mac;
5756 struct halmac_api *api;
5757 enum halmac_ret_status status;
5758
5759
5760 mac = dvobj_to_halmac(d);
5761 api = HALMAC_GET_API(mac);
5762
5763 status = api->halmac_cfg_sounding(mac, role, rate);
5764 if (status != HALMAC_RET_SUCCESS)
5765 return -1;
5766
5767 return 0;
5768 }
5769
rtw_halmac_bf_del_sounding(struct dvobj_priv * d,enum halmac_snd_role role)5770 int rtw_halmac_bf_del_sounding(struct dvobj_priv *d,
5771 enum halmac_snd_role role)
5772 {
5773 struct halmac_adapter *mac;
5774 struct halmac_api *api;
5775 enum halmac_ret_status status;
5776
5777
5778 mac = dvobj_to_halmac(d);
5779 api = HALMAC_GET_API(mac);
5780
5781 status = api->halmac_del_sounding(mac, role);
5782 if (status != HALMAC_RET_SUCCESS)
5783 return -1;
5784
5785 return 0;
5786 }
5787
5788 /**
5789 * rtw_halmac_bf_cfg_csi_rate() - Config data rate for CSI report frame by RSSI
5790 * @d: struct dvobj_priv*
5791 * @rssi: RSSI vlaue, unit is percentage (0~100).
5792 * @current_rate: Current CSI frame rate
5793 * Valid value example
5794 * 0 CCK 1M
5795 * 3 CCK 11M
5796 * 4 OFDM 6M
5797 * and so on
5798 * @fixrate_en: Enable to fix CSI frame in VHT rate, otherwise legacy OFDM rate.
5799 * The value "0" for disable, otheriwse enable.
5800 * @new_rate: Return new data rate, and value range is the same as
5801 * current_rate
5802 * @bmp_ofdm54: Return to suggest enabling OFDM 54M for CSI report frame or not,
5803 * The valid values and meanings are:
5804 * 0x00 disable
5805 * 0x01 enable
5806 * 0xFF Keep current setting
5807 *
5808 * According RSSI to config data rate for CSI report frame of Beamforming.
5809 *
5810 * Return 0 for OK, otherwise fail.
5811 */
rtw_halmac_bf_cfg_csi_rate(struct dvobj_priv * d,u8 rssi,u8 current_rate,u8 fixrate_en,u8 * new_rate,u8 * bmp_ofdm54)5812 int rtw_halmac_bf_cfg_csi_rate(struct dvobj_priv *d, u8 rssi,
5813 u8 current_rate, u8 fixrate_en, u8 *new_rate,
5814 u8 *bmp_ofdm54)
5815 {
5816 struct halmac_adapter *mac;
5817 struct halmac_api *api;
5818 enum halmac_ret_status status;
5819
5820
5821 mac = dvobj_to_halmac(d);
5822 api = HALMAC_GET_API(mac);
5823
5824 status = api->halmac_cfg_csi_rate(mac,
5825 rssi, current_rate, fixrate_en, new_rate,
5826 bmp_ofdm54);
5827 if (status != HALMAC_RET_SUCCESS)
5828 return -1;
5829
5830 return 0;
5831 }
5832
rtw_halmac_bf_cfg_mu_mimo(struct dvobj_priv * d,enum halmac_snd_role role,u8 * sounding_sts,u16 grouping_bitmap,u8 mu_tx_en,u32 * given_gid_tab,u32 * given_user_pos)5833 int rtw_halmac_bf_cfg_mu_mimo(struct dvobj_priv *d, enum halmac_snd_role role,
5834 u8 *sounding_sts, u16 grouping_bitmap, u8 mu_tx_en,
5835 u32 *given_gid_tab, u32 *given_user_pos)
5836 {
5837 struct halmac_adapter *mac;
5838 struct halmac_api *api;
5839 enum halmac_ret_status status;
5840 struct halmac_cfg_mumimo_para param;
5841
5842
5843 mac = dvobj_to_halmac(d);
5844 api = HALMAC_GET_API(mac);
5845
5846 _rtw_memset(¶m, 0, sizeof(param));
5847
5848 param.role = role;
5849 param.grouping_bitmap = grouping_bitmap;
5850 param.mu_tx_en = mu_tx_en;
5851
5852 if (sounding_sts)
5853 _rtw_memcpy(param.sounding_sts, sounding_sts, 6);
5854
5855 if (given_gid_tab)
5856 _rtw_memcpy(param.given_gid_tab, given_gid_tab, 8);
5857
5858 if (given_user_pos)
5859 _rtw_memcpy(param.given_user_pos, given_user_pos, 16);
5860
5861 status = api->halmac_cfg_mumimo(mac, ¶m);
5862 if (status != HALMAC_RET_SUCCESS)
5863 return -1;
5864
5865 return 0;
5866 }
5867
5868 #endif /* RTW_BEAMFORMING_VERSION_2 */
5869 #endif /* CONFIG_BEAMFORMING */
5870