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, skb->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);
467 memcpy((u8 *)skb_put(skb, size), buf, size);
469 if (!_rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, BEACON_QUEUE))
472 /* These code isn't actually need, because halmac will check
476 /* Polling Beacon Queue to send Beacon */
477 u1b_tmp = rtl_read_byte(rtlpriv, REG_RX_RXBD_NUM_8822B + 1);
479 while ((count < 20) && (u1b_tmp & BIT(4))) {
482 u1b_tmp = rtl_read_byte(rtlpriv, REG_RX_RXBD_NUM_8822B + 1);
486 pr_err("%s polling beacon fail\n", __func__);
491 bool rtl8822b_halmac_cb_write_data_h2c(struct rtl_priv *rtlpriv, u8 *buf,
494 struct sk_buff *skb = NULL;
496 /* without GFP_DMA, pci_map_single() may not work */
497 skb = __netdev_alloc_skb(NULL, size, GFP_ATOMIC | GFP_DMA);
498 memcpy((u8 *)skb_put(skb, size), buf, size);
500 return _rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, H2C_QUEUE);
503 /* Rsvd page HALMAC_RSVD_DRV_PGNUM_8822B occupies 16 page (2048 byte) */
504 #define BEACON_PG 0 /* ->1 */
507 #define PROBERSP_PG 4 /* ->5 */
508 #define QOS_NULL_PG 6
509 #define BT_QOS_NULL_PG 7
511 #define TOTAL_RESERVED_PKT_LEN 1024
513 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {/* page size = 128 */
515 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
516 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
517 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
520 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
521 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
522 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
523 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
524 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
528 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
529 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
530 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
533 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x00, 0x00, 0x00, 0x00, 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 0x10, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 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,
551 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
552 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 0x18, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
570 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
571 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x72, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 /* page 4 probe_resp */
587 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
588 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
589 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
590 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
591 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
592 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
593 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
594 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
595 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
596 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
597 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
601 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 /* page 5 probe_resp */
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 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 0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 /* page 6 qos null data */
623 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
624 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
625 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00,
626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x1A, 0x00, 0x30, 0x84, 0x00, 0x12, 0x00, 0x00,
634 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 /* page 7 BT-qos null data */
641 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7,
642 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02,
643 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 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,
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,
659 void rtl8822be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
661 struct rtl_priv *rtlpriv = rtl_priv(hw);
662 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
663 struct sk_buff *skb = NULL;
667 u8 u1_rsvd_page_loc[7] = {0};
677 memset(u1_rsvd_page_loc, 0, sizeof(u1_rsvd_page_loc));
679 /*---------------------------------------------------------
681 *---------------------------------------------------------
683 beacon = &reserved_page_packet[BEACON_PG * 128];
684 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
685 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
687 /*-------------------------------------------------------
689 *--------------------------------------------------------
691 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
692 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
693 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
694 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
696 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1_rsvd_page_loc, PSPOLL_PG);
698 /*--------------------------------------------------------
700 *---------------------------------------------------------
702 nullfunc = &reserved_page_packet[NULL_PG * 128];
703 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
704 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
705 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
707 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1_rsvd_page_loc, NULL_PG);
709 /*---------------------------------------------------------
711 *----------------------------------------------------------
713 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
714 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
715 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
716 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
718 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1_rsvd_page_loc, PROBERSP_PG);
720 /*---------------------------------------------------------
722 *----------------------------------------------------------
724 qosnull = &reserved_page_packet[QOS_NULL_PG * 128];
725 SET_80211_HDR_ADDRESS1(qosnull, mac->bssid);
726 SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr);
727 SET_80211_HDR_ADDRESS3(qosnull, mac->bssid);
729 SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1_rsvd_page_loc, QOS_NULL_PG);
731 /*---------------------------------------------------------
732 * (6) BT QoS null data
733 *----------------------------------------------------------
735 btqosnull = &reserved_page_packet[BT_QOS_NULL_PG * 128];
736 SET_80211_HDR_ADDRESS1(btqosnull, mac->bssid);
737 SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr);
738 SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid);
740 SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1_rsvd_page_loc,
743 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
745 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
746 "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
747 &reserved_page_packet[0], totalpacketlen);
748 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
749 "rtl8822be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
750 u1_rsvd_page_loc, 3);
752 skb = dev_alloc_skb(totalpacketlen);
753 memcpy((u8 *)skb_put(skb, totalpacketlen), &reserved_page_packet,
756 rtstatus = _rtl8822be_send_bcn_or_cmd_packet(hw, skb, BEACON_QUEUE);
762 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
763 "Set RSVD page location to Fw.\n");
764 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C_RSVDPAGE:\n",
765 u1_rsvd_page_loc, 3);
766 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_RSVDPAGE,
767 sizeof(u1_rsvd_page_loc),
770 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
771 "Set RSVD page location to Fw FAIL!!!!!!.\n");
774 /* Should check FW support p2p or not. */
775 static void rtl8822be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw,
778 u8 u1_ctwindow_period[1] = {ctwindow};
780 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_CTW_CMD, 1,
784 void rtl8822be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
786 struct rtl_priv *rtlpriv = rtl_priv(hw);
787 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
788 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
789 struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
790 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
793 u32 start_time, tsf_low;
795 switch (p2p_ps_state) {
797 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
798 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
801 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
802 /* update CTWindow value. */
803 if (p2pinfo->ctwindow > 0) {
804 p2p_ps_offload->ctwindow_en = 1;
805 ctwindow = p2pinfo->ctwindow;
806 rtl8822be_set_p2p_ctw_period_cmd(hw, ctwindow);
808 /* hw only support 2 set of NoA */
809 for (i = 0; i < p2pinfo->noa_num; i++) {
810 /* To control the register setting for which NOA*/
811 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
813 p2p_ps_offload->noa0_en = 1;
815 p2p_ps_offload->noa1_en = 1;
816 /* config P2P NoA Descriptor Register */
817 rtl_write_dword(rtlpriv, 0x5E0,
818 p2pinfo->noa_duration[i]);
819 rtl_write_dword(rtlpriv, 0x5E4,
820 p2pinfo->noa_interval[i]);
822 /*Get Current TSF value */
823 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR_8822B);
825 start_time = p2pinfo->noa_start_time[i];
826 if (p2pinfo->noa_count_type[i] != 1) {
827 while (start_time <= (tsf_low + (50 * 1024))) {
828 start_time += p2pinfo->noa_interval[i];
829 if (p2pinfo->noa_count_type[i] != 255)
830 p2pinfo->noa_count_type[i]--;
833 rtl_write_dword(rtlpriv, 0x5E8, start_time);
834 rtl_write_dword(rtlpriv, 0x5EC,
835 p2pinfo->noa_count_type[i]);
837 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
838 /* rst p2p circuit */
839 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST_8822B, BIT(4));
840 p2p_ps_offload->offload_en = 1;
842 if (rtlpriv->mac80211.p2p == P2P_ROLE_GO) {
843 p2p_ps_offload->role = 1;
844 p2p_ps_offload->allstasleep = 0;
846 p2p_ps_offload->role = 0;
848 p2p_ps_offload->discovery = 0;
852 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
853 p2p_ps_offload->discovery = 1;
855 case P2P_PS_SCAN_DONE:
856 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
857 p2p_ps_offload->discovery = 0;
858 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
864 rtl8822be_fill_h2c_cmd(hw, H2C_8822B_P2P_PS_OFFLOAD, 1,
865 (u8 *)p2p_ps_offload);
869 void rtl8822be_c2h_content_parsing_ext(struct ieee80211_hw *hw,
874 struct rtl_priv *rtlpriv = rtl_priv(hw);
875 struct rtl_halmac_ops *halmac_ops;
877 switch (c2h_sub_cmd_id) {
879 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
880 "[C2H], C2H_8822BE_TX_REPORT!\n");
881 rtl_tx_report_handler(hw, c2h_content_buf, c2h_cmd_len);
884 /* indicate c2h pkt + rx desc to halmac */
885 halmac_ops = rtlpriv->halmac.ops;
886 halmac_ops->halmac_c2h_handle(rtlpriv,
887 c2h_content_buf - 24 - 2 - 2,
888 c2h_cmd_len + 24 + 2 + 2);
893 void rtl8822be_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
894 u8 c2h_cmd_len, u8 *tmp_buf)
896 struct rtl_priv *rtlpriv = rtl_priv(hw);
897 struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
899 if (c2h_cmd_id == 0xFF) {
900 rtl8822be_c2h_content_parsing_ext(hw, tmp_buf[0],
906 switch (c2h_cmd_id) {
908 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
909 "[C2H], C2H_8822BE_DBG!!\n");
912 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
913 "[C2H], C2H_8822B_TXBF!!\n");
915 case C2H_8822B_BT_INFO:
916 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
917 "[C2H], C2H_8822BE_BT_INFO!!\n");
918 if (rtlpriv->cfg->ops->get_btc_status())
919 btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
922 case C2H_8822B_BT_MP:
923 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
924 "[C2H], C2H_8822BE_BT_MP!!\n");
925 if (rtlpriv->cfg->ops->get_btc_status())
926 btc_ops->btc_btmpinfo_notify(rtlpriv, tmp_buf,
930 if (!rtlpriv->phydm.ops->phydm_c2h_content_parsing(
931 rtlpriv, c2h_cmd_id, c2h_cmd_len, tmp_buf))
934 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
935 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
940 void rtl8822be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
942 struct rtl_priv *rtlpriv = rtl_priv(hw);
943 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
946 c2h_cmd_id = buffer[0];
947 c2h_cmd_seq = buffer[1];
948 c2h_cmd_len = len - 2;
949 tmp_buf = buffer + 2;
951 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
952 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
953 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
955 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
956 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
958 switch (c2h_cmd_id) {
959 case C2H_8822B_BT_INFO:
960 case C2H_8822B_BT_MP:
961 rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
964 rtl8822be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,