1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
4 * Copyright(c) 2016 Realtek Corporation.
7 * wlanfae <wlanfae@realtek.com>
8 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
11 * Larry Finger <Larry.Finger@lwfinger.net>
13 *****************************************************************************/
22 static bool _rtl8822be_check_fw_read_last_h2c(struct ieee80211_hw *hw,
25 struct rtl_priv *rtlpriv = rtl_priv(hw);
29 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR_8822B);
30 if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
35 static void _rtl8822be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
36 u32 cmd_len, u8 *cmdbuffer)
38 struct rtl_priv *rtlpriv = rtl_priv(hw);
39 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
41 u16 box_reg = 0, box_extreg = 0;
45 bool bwrite_success = false;
46 u8 wait_h2c_limmit = 100;
47 u8 boxcontent[4], boxextcontent[4];
48 u32 h2c_waitcounter = 0;
52 /* 1. Prevent race condition in setting H2C cmd.
53 * (copy from MgntActSet_RF_State().)
56 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
57 if (rtlhal->h2c_setinprogress) {
58 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
59 "H2C set in progress! wait..H2C_ID=%d.\n",
62 while (rtlhal->h2c_setinprogress) {
63 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
66 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
67 "Wait 100 us (%d times)...\n",
71 if (h2c_waitcounter > 1000)
73 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
76 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
78 rtlhal->h2c_setinprogress = true;
79 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
84 while (!bwrite_success) {
85 /* 2. Find the last BOX number which has been written. */
86 boxnum = rtlhal->last_hmeboxnum;
89 box_reg = REG_HMEBOX0_8822B;
90 box_extreg = REG_HMEBOX_E0_8822B;
93 box_reg = REG_HMEBOX1_8822B;
94 box_extreg = REG_HMEBOX_E1_8822B;
97 box_reg = REG_HMEBOX2_8822B;
98 box_extreg = REG_HMEBOX_E2_8822B;
101 box_reg = REG_HMEBOX3_8822B;
102 box_extreg = REG_HMEBOX_E3_8822B;
105 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
106 "switch case not process\n");
110 /* 3. Check if the box content is empty. */
111 u1b_tmp = rtl_read_byte(rtlpriv, REG_CR_8822B);
113 if (u1b_tmp == 0xea) {
114 if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS_8822B) ==
116 rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY_8822B) ==
118 rtl_write_byte(rtlpriv, REG_SYS_CFG1_8822B + 3,
121 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
122 "REG_CR is unavaliable\n");
126 wait_h2c_limmit = 100;
127 isfw_read = _rtl8822be_check_fw_read_last_h2c(hw, boxnum);
130 if (wait_h2c_limmit == 0) {
131 RT_TRACE(rtlpriv, COMP_CMD, DBG_WARNING,
132 "Wait too long for FW clear MB%d!!!\n",
138 _rtl8822be_check_fw_read_last_h2c(hw, boxnum);
139 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
140 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
141 "Waiting for FW clear MB%d!!! 0x130 = %2x\n",
145 /* If Fw has not read the last H2C cmd,
146 * break and give up this H2C.
149 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
150 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
154 /* 4. Fill the H2C cmd into box */
155 memset(boxcontent, 0, sizeof(boxcontent));
156 memset(boxextcontent, 0, sizeof(boxextcontent));
157 boxcontent[0] = element_id;
158 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
159 "Write element_id box_reg(%4x) = %2x\n", box_reg,
166 /*boxcontent[0] &= ~(BIT(7));*/
167 memcpy((u8 *)(boxcontent) + 1, cmdbuffer + buf_index,
170 for (idx = 0; idx < 4; idx++) {
171 rtl_write_byte(rtlpriv, box_reg + idx,
179 /*boxcontent[0] |= (BIT(7));*/
180 memcpy((u8 *)(boxextcontent), cmdbuffer + buf_index + 3,
182 memcpy((u8 *)(boxcontent) + 1, cmdbuffer + buf_index,
185 for (idx = 0; idx < 4; idx++) {
186 rtl_write_byte(rtlpriv, box_extreg + idx,
190 for (idx = 0; idx < 4; idx++) {
191 rtl_write_byte(rtlpriv, box_reg + idx,
196 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
197 "switch case not process\n");
201 bwrite_success = true;
203 rtlhal->last_hmeboxnum = boxnum + 1;
204 if (rtlhal->last_hmeboxnum == 4)
205 rtlhal->last_hmeboxnum = 0;
207 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
208 "pHalData->last_hmeboxnum = %d\n",
209 rtlhal->last_hmeboxnum);
212 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
213 rtlhal->h2c_setinprogress = false;
214 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
216 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
219 void rtl8822be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, u32 cmd_len,
222 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
223 struct rtl_priv *rtlpriv = rtl_priv(hw);
226 if (!rtlhal->fw_ready) {
228 "return H2C cmd because of Fw download fail!!!\n");
232 memset(tmp_cmdbuf, 0, 8);
233 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
235 RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG,
236 "h2c cmd: len=%d %02X%02X%02X%02X %02X%02X%02X%02X\n", cmd_len,
237 tmp_cmdbuf[2], tmp_cmdbuf[1], tmp_cmdbuf[0], element_id,
238 tmp_cmdbuf[6], tmp_cmdbuf[5], tmp_cmdbuf[4], tmp_cmdbuf[3]);
240 _rtl8822be_fill_h2c_command(hw, element_id, cmd_len, tmp_cmdbuf);
243 void rtl8822be_set_default_port_id_cmd(struct ieee80211_hw *hw)
245 u8 h2c_set_default_port_id[H2C_DEFAULT_PORT_ID_LEN];
247 SET_H2CCMD_DFTPID_PORT_ID(h2c_set_default_port_id, 0);
248 SET_H2CCMD_DFTPID_MAC_ID(h2c_set_default_port_id, 0);
250 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_DEFAULT_PORT_ID,
251 H2C_DEFAULT_PORT_ID_LEN,
252 h2c_set_default_port_id);
255 void rtl8822be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
257 struct rtl_priv *rtlpriv = rtl_priv(hw);
258 u8 u1_h2c_set_pwrmode[H2C_8822B_PWEMODE_LENGTH] = {0};
259 static u8 prev_h2c[H2C_8822B_PWEMODE_LENGTH] = {0};
260 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
261 u8 rlbm, power_state = 0, byte5 = 0;
262 u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
264 struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
265 bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
266 btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
267 bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
268 btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
270 memset(u1_h2c_set_pwrmode, 0, H2C_8822B_PWEMODE_LENGTH);
273 mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
275 RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
282 smart_ps = ppsc->smart_ps;
287 smart_ps = ppsc->smart_ps;
289 case FW_PS_DTIM_MODE:
291 awake_intvl = ppsc->reg_max_lps_awakeintvl;
293 * hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
294 * is only used in swlps.
296 smart_ps = ppsc->smart_ps;
298 case FW_PS_ACTIVE_MODE:
305 smart_ps = ppsc->smart_ps;
309 if (rtlpriv->mac80211.p2p) {
314 if (mode == FW_PS_ACTIVE_MODE) {
316 power_state = FW_PWR_STATE_ACTIVE;
319 byte5 = btc_ops->btc_get_lps_val(rtlpriv);
320 power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
322 if (rlbm == 2 && (byte5 & BIT(4))) {
323 /* Keep awake interval to 1 to prevent from
324 * decreasing coex performance
332 power_state = FW_PWR_STATE_RF_OFF;
336 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
337 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
338 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, smart_ps);
339 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, awake_intvl);
340 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
341 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
342 SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
344 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
345 "rtl8822be_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
346 u1_h2c_set_pwrmode, H2C_8822B_PWEMODE_LENGTH);
347 if (rtlpriv->cfg->ops->get_btc_status())
348 btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
349 H2C_8822B_PWEMODE_LENGTH);
351 if (!memcmp(prev_h2c, u1_h2c_set_pwrmode, H2C_8822B_PWEMODE_LENGTH))
353 memcpy(prev_h2c, u1_h2c_set_pwrmode, H2C_8822B_PWEMODE_LENGTH);
355 rtl8822be_set_default_port_id_cmd(hw);
356 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_SETPWRMODE,
357 H2C_8822B_PWEMODE_LENGTH, u1_h2c_set_pwrmode);
360 void rtl8822be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
362 u8 parm[4] = {0, 0, 0, 0};
363 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
364 * bit1=0-->update Media Status to MACID
365 * bit1=1-->update Media Status from MACID to MACID_End
366 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
368 * parm[3]: bit2-0: port ID
371 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
372 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
374 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_MSRRPT, 4, parm);
377 static bool _rtl8822be_send_bcn_or_cmd_packet(struct ieee80211_hw *hw,
378 struct sk_buff *skb, u8 hw_queue)
380 struct rtl_priv *rtlpriv = rtl_priv(hw);
381 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
382 struct rtl8192_tx_ring *ring;
383 struct rtl_tx_desc *pdesc;
384 struct rtl_tx_buffer_desc *pbd_desc;
386 struct sk_buff *pskb = NULL;
390 if (hw_queue != BEACON_QUEUE && hw_queue != H2C_QUEUE)
393 ring = &rtlpci->tx_ring[hw_queue];
395 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
397 if (hw_queue == BEACON_QUEUE) {
398 pdesc = &ring->desc[0];
399 pbd_desc = &ring->buffer_desc[0];
400 pdesc_or_bddesc = (u8 *)pbd_desc;
402 /* free previous beacon queue */
403 pskb = __skb_dequeue(&ring->queue);
406 goto free_prev_skb_done;
408 dma_addr = rtlpriv->cfg->ops->get_desc(
409 hw, (u8 *)pbd_desc, true, HW_DESC_TXBUFF_ADDR);
411 pci_unmap_single(rtlpci->pdev, dma_addr, pskb->len,
418 } else { /* hw_queue == TXCMD_QUEUE */
419 if (rtlpriv->cfg->ops->get_available_desc(hw, hw_queue) == 0) {
420 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
421 "get_available_desc fail hw_queue=%d\n",
423 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock,
428 pdesc = &ring->desc[ring->cur_tx_wp];
429 pbd_desc = &ring->buffer_desc[ring->cur_tx_wp];
430 pdesc_or_bddesc = (u8 *)pdesc;
433 rtlpriv->cfg->ops->fill_tx_special_desc(hw, (u8 *)pdesc, (u8 *)pbd_desc,
436 __skb_queue_tail(&ring->queue, skb);
438 rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc_or_bddesc, true,
439 HW_DESC_OWN, (u8 *)&hw_queue);
441 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
443 rtlpriv->cfg->ops->tx_polling(hw, hw_queue);
448 bool rtl8822b_halmac_cb_write_data_rsvd_page(struct rtl_priv *rtlpriv, u8 *buf,
451 struct sk_buff *skb = NULL;
455 skb = dev_alloc_skb(size);
458 memcpy((u8 *)skb_put(skb, size), buf, size);
460 if (!_rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, BEACON_QUEUE))
463 /* These code isn't actually need, because halmac will check
467 /* Polling Beacon Queue to send Beacon */
468 u1b_tmp = rtl_read_byte(rtlpriv, REG_RX_RXBD_NUM_8822B + 1);
470 while ((count < 20) && (u1b_tmp & BIT(4))) {
473 u1b_tmp = rtl_read_byte(rtlpriv, REG_RX_RXBD_NUM_8822B + 1);
477 pr_err("%s polling beacon fail\n", __func__);
482 bool rtl8822b_halmac_cb_write_data_h2c(struct rtl_priv *rtlpriv, u8 *buf,
485 struct sk_buff *skb = NULL;
487 /* without GFP_DMA, pci_map_single() may not work */
488 skb = __netdev_alloc_skb(NULL, size, GFP_ATOMIC | GFP_DMA);
489 memcpy((u8 *)skb_put(skb, size), buf, size);
491 return _rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, H2C_QUEUE);
494 /* Rsvd page HALMAC_RSVD_DRV_PGNUM_8822B occupies 16 page (2048 byte) */
495 #define BEACON_PG 0 /* ->1 */
498 #define PROBERSP_PG 4 /* ->5 */
499 #define QOS_NULL_PG 6
500 #define BT_QOS_NULL_PG 7
502 #define TOTAL_RESERVED_PKT_LEN 1024
504 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {/* page size = 128 */
506 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
507 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
508 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
511 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
512 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
513 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
514 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
515 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
519 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
520 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
521 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
524 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534 0x10, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
535 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
543 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
552 0x18, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
561 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
562 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570 0x72, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 /* page 4 probe_resp */
578 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
579 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
580 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
581 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
582 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
583 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
584 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
585 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
586 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
587 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
588 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
592 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 /* page 5 probe_resp */
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
607 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 /* page 6 qos null data */
614 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
615 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
616 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
625 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 /* page 7 BT-qos null data */
632 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
633 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
634 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 void rtl8822be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
652 struct rtl_priv *rtlpriv = rtl_priv(hw);
653 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
654 struct sk_buff *skb = NULL;
658 u8 u1_rsvd_page_loc[7] = {0};
668 memset(u1_rsvd_page_loc, 0, sizeof(u1_rsvd_page_loc));
670 /*---------------------------------------------------------
672 *---------------------------------------------------------
674 beacon = &reserved_page_packet[BEACON_PG * 128];
675 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
676 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
678 /*-------------------------------------------------------
680 *--------------------------------------------------------
682 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
683 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
684 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
685 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
687 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1_rsvd_page_loc, PSPOLL_PG);
689 /*--------------------------------------------------------
691 *---------------------------------------------------------
693 nullfunc = &reserved_page_packet[NULL_PG * 128];
694 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
695 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
696 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
698 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1_rsvd_page_loc, NULL_PG);
700 /*---------------------------------------------------------
702 *----------------------------------------------------------
704 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
705 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
706 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
707 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
709 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1_rsvd_page_loc, PROBERSP_PG);
711 /*---------------------------------------------------------
713 *----------------------------------------------------------
715 qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
716 SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
717 SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
718 SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
720 SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1_rsvd_page_loc, QOS_NULL_PG);
722 /*---------------------------------------------------------
723 * (6) BT QoS null data
724 *----------------------------------------------------------
726 btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
727 SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
728 SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
729 SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
731 SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1_rsvd_page_loc,
734 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
736 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
737 "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
738 &reserved_page_packet[0], totalpacketlen);
739 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
740 "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
741 u1_rsvd_page_loc, 3);
743 skb = dev_alloc_skb(totalpacketlen);
746 memcpy((u8 *)skb_put(skb, totalpacketlen), &reserved_page_packet,
749 rtstatus = _rtl8822be_send_bcn_or_cmd_packet(hw, skb, BEACON_QUEUE);
755 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
756 "Set RSVD page location to Fw.\n");
757 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C_RSVDPAGE:\n",
758 u1_rsvd_page_loc, 3);
759 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_RSVDPAGE,
760 sizeof(u1_rsvd_page_loc),
763 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
764 "Set RSVD page location to Fw FAIL!!!!!!.\n");
768 /* Should check FW support p2p or not. */
769 static void rtl8822be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
772 u8 u1_ctwindow_period[1] = {ctwindow};
774 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_CTW_CMD, 1,
778 void rtl8822be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
780 struct rtl_priv *rtlpriv = rtl_priv(hw);
781 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
782 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
783 struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
784 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
787 u32 start_time, tsf_low;
789 switch (p2p_ps_state) {
791 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
792 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
795 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
796 /* update CTWindow value. */
797 if (p2pinfo->ctwindow > 0) {
798 p2p_ps_offload->ctwindow_en = 1;
799 ctwindow = p2pinfo->ctwindow;
800 rtl8822be_set_p2p_ctw_period_cmd(hw, ctwindow);
802 /* hw only support 2 set of NoA */
803 for (i = 0; i < p2pinfo->noa_num; i++) {
804 /* To control the register setting for which NOA*/
805 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
807 p2p_ps_offload->noa0_en = 1;
809 p2p_ps_offload->noa1_en = 1;
810 /* config P2P NoA Descriptor Register */
811 rtl_write_dword(rtlpriv, 0x5E0,
812 p2pinfo->noa_duration[i]);
813 rtl_write_dword(rtlpriv, 0x5E4,
814 p2pinfo->noa_interval[i]);
816 /*Get Current TSF value */
817 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR_8822B);
819 start_time = p2pinfo->noa_start_time[i];
820 if (p2pinfo->noa_count_type[i] != 1) {
821 while (start_time <= (tsf_low + (50 * 1024))) {
822 start_time += p2pinfo->noa_interval[i];
823 if (p2pinfo->noa_count_type[i] != 255)
824 p2pinfo->noa_count_type[i]--;
827 rtl_write_dword(rtlpriv, 0x5E8, start_time);
828 rtl_write_dword(rtlpriv, 0x5EC,
829 p2pinfo->noa_count_type[i]);
831 if (p2pinfo->opp_ps == 1 || p2pinfo->noa_num > 0) {
832 /* rst p2p circuit */
833 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST_8822B, BIT(4));
834 p2p_ps_offload->offload_en = 1;
836 if (rtlpriv->mac80211.p2p == P2P_ROLE_GO) {
837 p2p_ps_offload->role = 1;
838 p2p_ps_offload->allstasleep = 0;
840 p2p_ps_offload->role = 0;
842 p2p_ps_offload->discovery = 0;
846 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
847 p2p_ps_offload->discovery = 1;
849 case P2P_PS_SCAN_DONE:
850 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
851 p2p_ps_offload->discovery = 0;
852 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
858 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_OFFLOAD, 1,
859 (u8 *)p2p_ps_offload);
863 void rtl8822be_c2h_content_parsing_ext(struct ieee80211_hw *hw,
868 struct rtl_priv *rtlpriv = rtl_priv(hw);
869 struct rtl_halmac_ops *halmac_ops;
871 switch (c2h_sub_cmd_id) {
873 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
874 "[C2H], C2H_8822BE_TX_REPORT!\n");
875 rtl_tx_report_handler(hw, c2h_content_buf, c2h_cmd_len);
878 /* indicate c2h pkt + rx desc to halmac */
879 halmac_ops = rtlpriv->halmac.ops;
880 halmac_ops->halmac_c2h_handle(rtlpriv,
881 c2h_content_buf - 24 - 2 - 2,
882 c2h_cmd_len + 24 + 2 + 2);
887 void rtl8822be_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
888 u8 c2h_cmd_len, u8 *tmp_buf)
890 struct rtl_priv *rtlpriv = rtl_priv(hw);
891 struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
893 if (c2h_cmd_id == 0xFF) {
894 rtl8822be_c2h_content_parsing_ext(hw, tmp_buf[0],
900 switch (c2h_cmd_id) {
902 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
903 "[C2H], C2H_8822BE_DBG!!\n");
906 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
907 "[C2H], C2H_8822B_TXBF!!\n");
909 case C2H_8822B_BT_INFO:
910 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
911 "[C2H], C2H_8822BE_BT_INFO!!\n");
912 if (rtlpriv->cfg->ops->get_btc_status())
913 btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
916 case C2H_8822B_BT_MP:
917 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
918 "[C2H], C2H_8822BE_BT_MP!!\n");
919 if (rtlpriv->cfg->ops->get_btc_status())
920 btc_ops->btc_btmpinfo_notify(rtlpriv, tmp_buf,
924 if (!rtlpriv->phydm.ops->phydm_c2h_content_parsing(
925 rtlpriv, c2h_cmd_id, c2h_cmd_len, tmp_buf))
928 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
929 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
934 void rtl8822be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
936 struct rtl_priv *rtlpriv = rtl_priv(hw);
937 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
940 c2h_cmd_id = buffer[0];
941 c2h_cmd_seq = buffer[1];
942 c2h_cmd_len = len - 2;
943 tmp_buf = buffer + 2;
945 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
946 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
947 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
949 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
950 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
952 switch (c2h_cmd_id) {
953 case C2H_8822B_BT_INFO:
954 case C2H_8822B_BT_MP:
955 rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
958 rtl8822be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,