1 /******************************************************************************
3 * Copyright(c) 2016 Realtek Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
22 * Larry Finger <Larry.Finger@lwfinger.net>
24 *****************************************************************************/
33 static bool _rtl8822be_check_fw_read_last_h2c(struct ieee80211_hw *hw,
36 struct rtl_priv *rtlpriv = rtl_priv(hw);
40 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR_8822B);
41 if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
46 static void _rtl8822be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
47 u32 cmd_len, u8 *cmdbuffer)
49 struct rtl_priv *rtlpriv = rtl_priv(hw);
50 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
52 u16 box_reg = 0, box_extreg = 0;
56 bool bwrite_success = false;
57 u8 wait_h2c_limmit = 100;
58 u8 boxcontent[4], boxextcontent[4];
59 u32 h2c_waitcounter = 0;
63 /* 1. Prevent race condition in setting H2C cmd.
64 * (copy from MgntActSet_RF_State().)
67 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
68 if (rtlhal->h2c_setinprogress) {
69 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
70 "H2C set in progress! wait..H2C_ID=%d.\n",
73 while (rtlhal->h2c_setinprogress) {
74 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
77 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
78 "Wait 100 us (%d times)...\n",
82 if (h2c_waitcounter > 1000)
84 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
87 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
89 rtlhal->h2c_setinprogress = true;
90 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
95 while (!bwrite_success) {
96 /* 2. Find the last BOX number which has been writen. */
97 boxnum = rtlhal->last_hmeboxnum;
100 box_reg = REG_HMEBOX0_8822B;
101 box_extreg = REG_HMEBOX_E0_8822B;
104 box_reg = REG_HMEBOX1_8822B;
105 box_extreg = REG_HMEBOX_E1_8822B;
108 box_reg = REG_HMEBOX2_8822B;
109 box_extreg = REG_HMEBOX_E2_8822B;
112 box_reg = REG_HMEBOX3_8822B;
113 box_extreg = REG_HMEBOX_E3_8822B;
116 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
117 "switch case not process\n");
121 /* 3. Check if the box content is empty. */
122 u1b_tmp = rtl_read_byte(rtlpriv, REG_CR_8822B);
124 if (u1b_tmp == 0xea) {
125 if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS_8822B) ==
127 rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY_8822B) ==
129 rtl_write_byte(rtlpriv, REG_SYS_CFG1_8822B + 3,
132 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
133 "REG_CR is unavaliable\n");
137 wait_h2c_limmit = 100;
138 isfw_read = _rtl8822be_check_fw_read_last_h2c(hw, boxnum);
141 if (wait_h2c_limmit == 0) {
142 RT_TRACE(rtlpriv, COMP_CMD, DBG_WARNING,
143 "Wait too long for FW clear MB%d!!!\n",
149 _rtl8822be_check_fw_read_last_h2c(hw, boxnum);
150 u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
151 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
152 "Waiting for FW clear MB%d!!! 0x130 = %2x\n",
156 /* If Fw has not read the last H2C cmd,
157 * break and give up this H2C.
160 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
161 "Write H2C reg BOX[%d] fail,Fw don't read.\n",
165 /* 4. Fill the H2C cmd into box */
166 memset(boxcontent, 0, sizeof(boxcontent));
167 memset(boxextcontent, 0, sizeof(boxextcontent));
168 boxcontent[0] = element_id;
169 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
170 "Write element_id box_reg(%4x) = %2x\n", box_reg,
177 /*boxcontent[0] &= ~(BIT(7));*/
178 memcpy((u8 *)(boxcontent) + 1, cmdbuffer + buf_index,
181 for (idx = 0; idx < 4; idx++) {
182 rtl_write_byte(rtlpriv, box_reg + idx,
190 /*boxcontent[0] |= (BIT(7));*/
191 memcpy((u8 *)(boxextcontent), cmdbuffer + buf_index + 3,
193 memcpy((u8 *)(boxcontent) + 1, cmdbuffer + buf_index,
196 for (idx = 0; idx < 4; idx++) {
197 rtl_write_byte(rtlpriv, box_extreg + idx,
201 for (idx = 0; idx < 4; idx++) {
202 rtl_write_byte(rtlpriv, box_reg + idx,
207 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
208 "switch case not process\n");
212 bwrite_success = true;
214 rtlhal->last_hmeboxnum = boxnum + 1;
215 if (rtlhal->last_hmeboxnum == 4)
216 rtlhal->last_hmeboxnum = 0;
218 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
219 "pHalData->last_hmeboxnum = %d\n",
220 rtlhal->last_hmeboxnum);
223 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
224 rtlhal->h2c_setinprogress = false;
225 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
227 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
230 void rtl8822be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, u32 cmd_len,
233 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
234 struct rtl_priv *rtlpriv = rtl_priv(hw);
237 if (!rtlhal->fw_ready) {
239 "return H2C cmd because of Fw download fail!!!\n");
243 memset(tmp_cmdbuf, 0, 8);
244 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
246 RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG,
247 "h2c cmd: len=%d %02X%02X%02X%02X %02X%02X%02X%02X\n", cmd_len,
248 tmp_cmdbuf[2], tmp_cmdbuf[1], tmp_cmdbuf[0], element_id,
249 tmp_cmdbuf[6], tmp_cmdbuf[5], tmp_cmdbuf[4], tmp_cmdbuf[3]);
251 _rtl8822be_fill_h2c_command(hw, element_id, cmd_len, tmp_cmdbuf);
254 void rtl8822be_set_default_port_id_cmd(struct ieee80211_hw *hw)
256 u8 h2c_set_default_port_id[H2C_DEFAULT_PORT_ID_LEN];
258 SET_H2CCMD_DFTPID_PORT_ID(h2c_set_default_port_id, 0);
259 SET_H2CCMD_DFTPID_MAC_ID(h2c_set_default_port_id, 0);
261 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_DEFAULT_PORT_ID,
262 H2C_DEFAULT_PORT_ID_LEN,
263 h2c_set_default_port_id);
266 void rtl8822be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
268 struct rtl_priv *rtlpriv = rtl_priv(hw);
269 u8 u1_h2c_set_pwrmode[H2C_8822B_PWEMODE_LENGTH] = {0};
270 static u8 prev_h2c[H2C_8822B_PWEMODE_LENGTH] = {0};
271 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
272 u8 rlbm, power_state = 0, byte5 = 0;
273 u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
275 struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
276 bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
277 btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
278 bool bt_lps_on = (rtlpriv->cfg->ops->get_btc_status() ?
279 btc_ops->btc_is_bt_lps_on(rtlpriv) : false);
281 memset(u1_h2c_set_pwrmode, 0, H2C_8822B_PWEMODE_LENGTH);
284 mode = (bt_lps_on ? FW_PS_MIN_MODE : FW_PS_ACTIVE_MODE);
286 RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
293 smart_ps = ppsc->smart_ps;
298 smart_ps = ppsc->smart_ps;
300 case FW_PS_DTIM_MODE:
302 awake_intvl = ppsc->reg_max_lps_awakeintvl;
304 * hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
305 * is only used in swlps.
307 smart_ps = ppsc->smart_ps;
309 case FW_PS_ACTIVE_MODE:
316 smart_ps = ppsc->smart_ps;
320 if (rtlpriv->mac80211.p2p) {
325 if (mode == FW_PS_ACTIVE_MODE) {
327 power_state = FW_PWR_STATE_ACTIVE;
330 byte5 = btc_ops->btc_get_lps_val(rtlpriv);
331 power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
333 if ((rlbm == 2) && (byte5 & BIT(4))) {
334 /* Keep awake interval to 1 to prevent from
335 * decreasing coex performance
343 power_state = FW_PWR_STATE_RF_OFF;
347 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
348 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
349 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, smart_ps);
350 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, awake_intvl);
351 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
352 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
353 SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
355 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
356 "rtl8822be_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
357 u1_h2c_set_pwrmode, H2C_8822B_PWEMODE_LENGTH);
358 if (rtlpriv->cfg->ops->get_btc_status())
359 btc_ops->btc_record_pwr_mode(rtlpriv, u1_h2c_set_pwrmode,
360 H2C_8822B_PWEMODE_LENGTH);
362 if (!memcmp(prev_h2c, u1_h2c_set_pwrmode, H2C_8822B_PWEMODE_LENGTH))
364 memcpy(prev_h2c, u1_h2c_set_pwrmode, H2C_8822B_PWEMODE_LENGTH);
366 rtl8822be_set_default_port_id_cmd(hw);
367 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_SETPWRMODE,
368 H2C_8822B_PWEMODE_LENGTH, u1_h2c_set_pwrmode);
371 void rtl8822be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
373 u8 parm[4] = {0, 0, 0, 0};
374 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
375 * bit1=0-->update Media Status to MACID
376 * bit1=1-->update Media Status from MACID to MACID_End
377 * parm[1]: MACID, if this is INFRA_STA, MacID = 0
379 * parm[3]: bit2-0: port ID
382 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
383 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
385 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_MSRRPT, 4, parm);
388 static bool _rtl8822be_send_bcn_or_cmd_packet(struct ieee80211_hw *hw,
389 struct sk_buff *skb, u8 hw_queue)
391 struct rtl_priv *rtlpriv = rtl_priv(hw);
392 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
393 struct rtl8192_tx_ring *ring;
394 struct rtl_tx_desc *pdesc;
395 struct rtl_tx_buffer_desc *pbd_desc;
397 struct sk_buff *pskb = NULL;
401 if (hw_queue != BEACON_QUEUE && hw_queue != H2C_QUEUE)
404 ring = &rtlpci->tx_ring[hw_queue];
406 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
408 if (hw_queue == BEACON_QUEUE) {
409 pdesc = &ring->desc[0];
410 pbd_desc = &ring->buffer_desc[0];
411 pdesc_or_bddesc = (u8 *)pbd_desc;
413 /* free previous beacon queue */
414 pskb = __skb_dequeue(&ring->queue);
417 goto free_prev_skb_done;
419 dma_addr = rtlpriv->cfg->ops->get_desc(
420 hw, (u8 *)pbd_desc, true, HW_DESC_TXBUFF_ADDR);
422 pci_unmap_single(rtlpci->pdev, dma_addr, pskb->len,
429 } else { /* hw_queue == TXCMD_QUEUE */
430 if (rtlpriv->cfg->ops->get_available_desc(hw, hw_queue) == 0) {
431 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
432 "get_available_desc fail hw_queue=%d\n",
434 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock,
439 pdesc = &ring->desc[ring->cur_tx_wp];
440 pbd_desc = &ring->buffer_desc[ring->cur_tx_wp];
441 pdesc_or_bddesc = (u8 *)pdesc;
444 rtlpriv->cfg->ops->fill_tx_special_desc(hw, (u8 *)pdesc, (u8 *)pbd_desc,
447 __skb_queue_tail(&ring->queue, skb);
449 rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc_or_bddesc, true,
450 HW_DESC_OWN, (u8 *)&hw_queue);
452 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
454 rtlpriv->cfg->ops->tx_polling(hw, hw_queue);
459 bool rtl8822b_halmac_cb_write_data_rsvd_page(struct rtl_priv *rtlpriv, u8 *buf,
462 struct sk_buff *skb = NULL;
466 skb = dev_alloc_skb(size);
469 memcpy((u8 *)skb_put(skb, size), buf, size);
471 if (!_rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, BEACON_QUEUE))
474 /* These code isn't actually need, because halmac will check
478 /* Polling Beacon Queue to send Beacon */
479 u1b_tmp = rtl_read_byte(rtlpriv, REG_RX_RXBD_NUM_8822B + 1);
481 while ((count < 20) && (u1b_tmp & BIT(4))) {
484 u1b_tmp = rtl_read_byte(rtlpriv, REG_RX_RXBD_NUM_8822B + 1);
488 pr_err("%s polling beacon fail\n", __func__);
493 bool rtl8822b_halmac_cb_write_data_h2c(struct rtl_priv *rtlpriv, u8 *buf,
496 struct sk_buff *skb = NULL;
498 /* without GFP_DMA, pci_map_single() may not work */
499 skb = __netdev_alloc_skb(NULL, size, GFP_ATOMIC | GFP_DMA);
500 memcpy((u8 *)skb_put(skb, size), buf, size);
502 return _rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, H2C_QUEUE);
505 /* Rsvd page HALMAC_RSVD_DRV_PGNUM_8822B occupies 16 page (2048 byte) */
506 #define BEACON_PG 0 /* ->1 */
509 #define PROBERSP_PG 4 /* ->5 */
510 #define QOS_NULL_PG 6
511 #define BT_QOS_NULL_PG 7
513 #define TOTAL_RESERVED_PKT_LEN 1024
515 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {/* page size = 128 */
517 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
518 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
519 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
522 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
523 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
524 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
525 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
526 0x09, 0x03, 0xFF, 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, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
530 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
531 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
532 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
535 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 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,
540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x10, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 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,
553 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
554 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x18, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
572 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
573 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x72, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 /* page 4 probe_resp */
589 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
590 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
591 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
592 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
593 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
594 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
595 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
596 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
597 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
598 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
599 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
603 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 /* page 5 probe_resp */
607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 /* page 6 qos null data */
625 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
626 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
627 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
636 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 /* page 7 BT-qos null data */
643 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
644 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
645 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 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,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 void rtl8822be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
663 struct rtl_priv *rtlpriv = rtl_priv(hw);
664 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
665 struct sk_buff *skb = NULL;
669 u8 u1_rsvd_page_loc[7] = {0};
679 memset(u1_rsvd_page_loc, 0, sizeof(u1_rsvd_page_loc));
681 /*---------------------------------------------------------
683 *---------------------------------------------------------
685 beacon = &reserved_page_packet[BEACON_PG * 128];
686 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
687 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
689 /*-------------------------------------------------------
691 *--------------------------------------------------------
693 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
694 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
695 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
696 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
698 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1_rsvd_page_loc, PSPOLL_PG);
700 /*--------------------------------------------------------
702 *---------------------------------------------------------
704 nullfunc = &reserved_page_packet[NULL_PG * 128];
705 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
706 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
707 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
709 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1_rsvd_page_loc, NULL_PG);
711 /*---------------------------------------------------------
713 *----------------------------------------------------------
715 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
716 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
717 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
718 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
720 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1_rsvd_page_loc, PROBERSP_PG);
722 /*---------------------------------------------------------
724 *----------------------------------------------------------
726 qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
727 SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
728 SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
729 SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
731 SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1_rsvd_page_loc, QOS_NULL_PG);
733 /*---------------------------------------------------------
734 * (6) BT QoS null data
735 *----------------------------------------------------------
737 btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
738 SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
739 SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
740 SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
742 SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1_rsvd_page_loc,
745 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
747 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
748 "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
749 &reserved_page_packet[0], totalpacketlen);
750 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
751 "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
752 u1_rsvd_page_loc, 3);
754 skb = dev_alloc_skb(totalpacketlen);
757 memcpy((u8 *)skb_put(skb, totalpacketlen), &reserved_page_packet,
760 rtstatus = _rtl8822be_send_bcn_or_cmd_packet(hw, skb, BEACON_QUEUE);
766 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
767 "Set RSVD page location to Fw.\n");
768 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C_RSVDPAGE:\n",
769 u1_rsvd_page_loc, 3);
770 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_RSVDPAGE,
771 sizeof(u1_rsvd_page_loc),
774 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
775 "Set RSVD page location to Fw FAIL!!!!!!.\n");
778 /* Should check FW support p2p or not. */
779 static void rtl8822be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
782 u8 u1_ctwindow_period[1] = {ctwindow};
784 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_CTW_CMD, 1,
788 void rtl8822be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
790 struct rtl_priv *rtlpriv = rtl_priv(hw);
791 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
792 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
793 struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
794 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
797 u32 start_time, tsf_low;
799 switch (p2p_ps_state) {
801 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
802 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
805 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
806 /* update CTWindow value. */
807 if (p2pinfo->ctwindow > 0) {
808 p2p_ps_offload->ctwindow_en = 1;
809 ctwindow = p2pinfo->ctwindow;
810 rtl8822be_set_p2p_ctw_period_cmd(hw, ctwindow);
812 /* hw only support 2 set of NoA */
813 for (i = 0; i < p2pinfo->noa_num; i++) {
814 /* To control the register setting for which NOA*/
815 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
817 p2p_ps_offload->noa0_en = 1;
819 p2p_ps_offload->noa1_en = 1;
820 /* config P2P NoA Descriptor Register */
821 rtl_write_dword(rtlpriv, 0x5E0,
822 p2pinfo->noa_duration[i]);
823 rtl_write_dword(rtlpriv, 0x5E4,
824 p2pinfo->noa_interval[i]);
826 /*Get Current TSF value */
827 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR_8822B);
829 start_time = p2pinfo->noa_start_time[i];
830 if (p2pinfo->noa_count_type[i] != 1) {
831 while (start_time <= (tsf_low + (50 * 1024))) {
832 start_time += p2pinfo->noa_interval[i];
833 if (p2pinfo->noa_count_type[i] != 255)
834 p2pinfo->noa_count_type[i]--;
837 rtl_write_dword(rtlpriv, 0x5E8, start_time);
838 rtl_write_dword(rtlpriv, 0x5EC,
839 p2pinfo->noa_count_type[i]);
841 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
842 /* rst p2p circuit */
843 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST_8822B, BIT(4));
844 p2p_ps_offload->offload_en = 1;
846 if (rtlpriv->mac80211.p2p == P2P_ROLE_GO) {
847 p2p_ps_offload->role = 1;
848 p2p_ps_offload->allstasleep = 0;
850 p2p_ps_offload->role = 0;
852 p2p_ps_offload->discovery = 0;
856 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
857 p2p_ps_offload->discovery = 1;
859 case P2P_PS_SCAN_DONE:
860 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
861 p2p_ps_offload->discovery = 0;
862 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
868 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_OFFLOAD, 1,
869 (u8 *)p2p_ps_offload);
873 void rtl8822be_c2h_content_parsing_ext(struct ieee80211_hw *hw,
878 struct rtl_priv *rtlpriv = rtl_priv(hw);
879 struct rtl_halmac_ops *halmac_ops;
881 switch (c2h_sub_cmd_id) {
883 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
884 "[C2H], C2H_8822BE_TX_REPORT!\n");
885 rtl_tx_report_handler(hw, c2h_content_buf, c2h_cmd_len);
888 /* indicate c2h pkt + rx desc to halmac */
889 halmac_ops = rtlpriv->halmac.ops;
890 halmac_ops->halmac_c2h_handle(rtlpriv,
891 c2h_content_buf - 24 - 2 - 2,
892 c2h_cmd_len + 24 + 2 + 2);
897 void rtl8822be_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
898 u8 c2h_cmd_len, u8 *tmp_buf)
900 struct rtl_priv *rtlpriv = rtl_priv(hw);
901 struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
903 if (c2h_cmd_id == 0xFF) {
904 rtl8822be_c2h_content_parsing_ext(hw, tmp_buf[0],
910 switch (c2h_cmd_id) {
912 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
913 "[C2H], C2H_8822BE_DBG!!\n");
916 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
917 "[C2H], C2H_8822B_TXBF!!\n");
919 case C2H_8822B_BT_INFO:
920 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
921 "[C2H], C2H_8822BE_BT_INFO!!\n");
922 if (rtlpriv->cfg->ops->get_btc_status())
923 btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
926 case C2H_8822B_BT_MP:
927 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
928 "[C2H], C2H_8822BE_BT_MP!!\n");
929 if (rtlpriv->cfg->ops->get_btc_status())
930 btc_ops->btc_btmpinfo_notify(rtlpriv, tmp_buf,
934 if (!rtlpriv->phydm.ops->phydm_c2h_content_parsing(
935 rtlpriv, c2h_cmd_id, c2h_cmd_len, tmp_buf))
938 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
939 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
944 void rtl8822be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
946 struct rtl_priv *rtlpriv = rtl_priv(hw);
947 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
950 c2h_cmd_id = buffer[0];
951 c2h_cmd_seq = buffer[1];
952 c2h_cmd_len = len - 2;
953 tmp_buf = buffer + 2;
955 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
956 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
957 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
959 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
960 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
962 switch (c2h_cmd_id) {
963 case C2H_8822B_BT_INFO:
964 case C2H_8822B_BT_MP:
965 rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
968 rtl8822be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,