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);
491 memcpy((u8 *)skb_put(skb, size), buf, size);
493 return _rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, H2C_QUEUE);
496 /* Rsvd page HALMAC_RSVD_DRV_PGNUM_8822B occupies 16 page (2048 byte) */
497 #define BEACON_PG 0 /* ->1 */
500 #define PROBERSP_PG 4 /* ->5 */
501 #define QOS_NULL_PG 6
502 #define BT_QOS_NULL_PG 7
504 #define TOTAL_RESERVED_PKT_LEN 1024
506 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {/* page size = 128 */
508 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
509 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
510 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
512 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
513 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
514 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
515 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
516 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
517 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
521 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
522 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
523 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
526 0x00, 0x50, 0xF2, 0x02, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536 0x10, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
537 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
545 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x18, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
563 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
564 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x72, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 /* page 4 probe_resp */
580 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
581 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
582 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
583 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
584 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
585 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
586 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
587 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
588 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
589 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
590 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
594 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 /* page 5 probe_resp */
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 /* page 6 qos null data */
616 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
617 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
618 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
627 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 /* page 7 BT-qos null data */
634 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
635 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
636 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 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,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 void rtl8822be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
654 struct rtl_priv *rtlpriv = rtl_priv(hw);
655 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
656 struct sk_buff *skb = NULL;
660 u8 u1_rsvd_page_loc[7] = {0};
670 memset(u1_rsvd_page_loc, 0, sizeof(u1_rsvd_page_loc));
672 /*---------------------------------------------------------
674 *---------------------------------------------------------
676 beacon = &reserved_page_packet[BEACON_PG * 128];
677 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
678 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
680 /*-------------------------------------------------------
682 *--------------------------------------------------------
684 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
685 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
686 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
687 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
689 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1_rsvd_page_loc, PSPOLL_PG);
691 /*--------------------------------------------------------
693 *---------------------------------------------------------
695 nullfunc = &reserved_page_packet[NULL_PG * 128];
696 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
697 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
698 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
700 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1_rsvd_page_loc, NULL_PG);
702 /*---------------------------------------------------------
704 *----------------------------------------------------------
706 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
707 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
708 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
709 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
711 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1_rsvd_page_loc, PROBERSP_PG);
713 /*---------------------------------------------------------
715 *----------------------------------------------------------
717 qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
718 SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
719 SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
720 SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
722 SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1_rsvd_page_loc, QOS_NULL_PG);
724 /*---------------------------------------------------------
725 * (6) BT QoS null data
726 *----------------------------------------------------------
728 btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
729 SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
730 SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
731 SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
733 SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1_rsvd_page_loc,
736 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
738 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
739 "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
740 &reserved_page_packet[0], totalpacketlen);
741 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
742 "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
743 u1_rsvd_page_loc, 3);
745 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,