root/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _rtl88e_enable_fw_download
  2. _rtl88e_write_fw
  3. _rtl88e_fw_free_to_go
  4. rtl88e_download_fw
  5. _rtl88e_check_fw_read_last_h2c
  6. _rtl88e_fill_h2c_command
  7. rtl88e_fill_h2c_cmd
  8. rtl88e_firmware_selfreset
  9. rtl88e_set_fw_pwrmode_cmd
  10. rtl88e_set_fw_joinbss_report_cmd
  11. rtl88e_set_fw_ap_off_load_cmd
  12. rtl88e_set_fw_rsvdpagepkt
  13. rtl88e_set_p2p_ctw_period_cmd
  14. rtl88e_set_p2p_ps_offload_cmd

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* Copyright(c) 2009-2013  Realtek Corporation.*/
   3 
   4 #include "../wifi.h"
   5 #include "../pci.h"
   6 #include "../base.h"
   7 #include "../core.h"
   8 #include "../efuse.h"
   9 #include "reg.h"
  10 #include "def.h"
  11 #include "fw.h"
  12 
  13 static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable)
  14 {
  15         struct rtl_priv *rtlpriv = rtl_priv(hw);
  16         u8 tmp;
  17 
  18         if (enable) {
  19                 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
  20                 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
  21 
  22                 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
  23                 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
  24 
  25                 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
  26                 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
  27         } else {
  28                 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
  29                 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
  30 
  31                 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
  32         }
  33 }
  34 
  35 static void _rtl88e_write_fw(struct ieee80211_hw *hw,
  36                              enum version_8188e version, u8 *buffer, u32 size)
  37 {
  38         struct rtl_priv *rtlpriv = rtl_priv(hw);
  39         u8 *bufferptr = (u8 *)buffer;
  40         u32 pagenums, remainsize;
  41         u32 page, offset;
  42 
  43         RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size);
  44 
  45         rtl_fill_dummy(bufferptr, &size);
  46 
  47         pagenums = size / FW_8192C_PAGE_SIZE;
  48         remainsize = size % FW_8192C_PAGE_SIZE;
  49 
  50         if (pagenums > 8)
  51                 pr_err("Page numbers should not greater then 8\n");
  52 
  53         for (page = 0; page < pagenums; page++) {
  54                 offset = page * FW_8192C_PAGE_SIZE;
  55                 rtl_fw_page_write(hw, page, (bufferptr + offset),
  56                                   FW_8192C_PAGE_SIZE);
  57         }
  58 
  59         if (remainsize) {
  60                 offset = pagenums * FW_8192C_PAGE_SIZE;
  61                 page = pagenums;
  62                 rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
  63         }
  64 }
  65 
  66 static int _rtl88e_fw_free_to_go(struct ieee80211_hw *hw)
  67 {
  68         struct rtl_priv *rtlpriv = rtl_priv(hw);
  69         int err = -EIO;
  70         u32 counter = 0;
  71         u32 value32;
  72 
  73         do {
  74                 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  75         } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
  76                  (!(value32 & FWDL_CHKSUM_RPT)));
  77 
  78         if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
  79                 pr_err("chksum report fail! REG_MCUFWDL:0x%08x .\n",
  80                        value32);
  81                 goto exit;
  82         }
  83         value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  84         value32 |= MCUFWDL_RDY;
  85         value32 &= ~WINTINI_RDY;
  86         rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
  87 
  88         rtl88e_firmware_selfreset(hw);
  89         counter = 0;
  90 
  91         do {
  92                 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  93                 if (value32 & WINTINI_RDY)
  94                         return 0;
  95 
  96                 udelay(FW_8192C_POLLING_DELAY);
  97 
  98         } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
  99 
 100         pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n",
 101                value32);
 102 
 103 exit:
 104         return err;
 105 }
 106 
 107 int rtl88e_download_fw(struct ieee80211_hw *hw,
 108                        bool buse_wake_on_wlan_fw)
 109 {
 110         struct rtl_priv *rtlpriv = rtl_priv(hw);
 111         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 112         struct rtlwifi_firmware_header *pfwheader;
 113         u8 *pfwdata;
 114         u32 fwsize;
 115         int err;
 116         enum version_8188e version = rtlhal->version;
 117 
 118         if (!rtlhal->pfirmware)
 119                 return 1;
 120 
 121         pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
 122         rtlhal->fw_version = le16_to_cpu(pfwheader->version);
 123         rtlhal->fw_subversion = pfwheader->subversion;
 124         pfwdata = rtlhal->pfirmware;
 125         fwsize = rtlhal->fwsize;
 126         RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
 127                  "normal Firmware SIZE %d\n", fwsize);
 128 
 129         if (IS_FW_HEADER_EXIST(pfwheader)) {
 130                 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
 131                          "Firmware Version(%d), Signature(%#x), Size(%d)\n",
 132                           pfwheader->version, pfwheader->signature,
 133                           (int)sizeof(struct rtlwifi_firmware_header));
 134 
 135                 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
 136                 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
 137         }
 138 
 139         if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
 140                 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
 141                 rtl88e_firmware_selfreset(hw);
 142         }
 143         _rtl88e_enable_fw_download(hw, true);
 144         _rtl88e_write_fw(hw, version, pfwdata, fwsize);
 145         _rtl88e_enable_fw_download(hw, false);
 146 
 147         err = _rtl88e_fw_free_to_go(hw);
 148         if (err)
 149                 pr_err("Firmware is not ready to run!\n");
 150 
 151         return 0;
 152 }
 153 
 154 static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
 155 {
 156         struct rtl_priv *rtlpriv = rtl_priv(hw);
 157         u8 val_hmetfr;
 158 
 159         val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
 160         if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
 161                 return true;
 162         return false;
 163 }
 164 
 165 static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw,
 166                                      u8 element_id, u32 cmd_len,
 167                                      u8 *cmd_b)
 168 {
 169         struct rtl_priv *rtlpriv = rtl_priv(hw);
 170         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 171         u8 boxnum;
 172         u16 box_reg = 0, box_extreg = 0;
 173         u8 u1b_tmp;
 174         bool isfw_read = false;
 175         u8 buf_index = 0;
 176         bool write_sucess = false;
 177         u8 wait_h2c_limmit = 100;
 178         u8 wait_writeh2c_limit = 100;
 179         u8 boxcontent[4], boxextcontent[4];
 180         u32 h2c_waitcounter = 0;
 181         unsigned long flag;
 182         u8 idx;
 183 
 184         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
 185 
 186         while (true) {
 187                 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 188                 if (rtlhal->h2c_setinprogress) {
 189                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 190                                  "H2C set in progress! Wait to set..element_id(%d).\n",
 191                                  element_id);
 192 
 193                         while (rtlhal->h2c_setinprogress) {
 194                                 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
 195                                                        flag);
 196                                 h2c_waitcounter++;
 197                                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 198                                          "Wait 100 us (%d times)...\n",
 199                                          h2c_waitcounter);
 200                                 udelay(100);
 201 
 202                                 if (h2c_waitcounter > 1000)
 203                                         return;
 204                                 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
 205                                                   flag);
 206                         }
 207                         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 208                 } else {
 209                         rtlhal->h2c_setinprogress = true;
 210                         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 211                         break;
 212                 }
 213         }
 214 
 215         while (!write_sucess) {
 216                 wait_writeh2c_limit--;
 217                 if (wait_writeh2c_limit == 0) {
 218                         pr_err("Write H2C fail because no trigger for FW INT!\n");
 219                         break;
 220                 }
 221 
 222                 boxnum = rtlhal->last_hmeboxnum;
 223                 switch (boxnum) {
 224                 case 0:
 225                         box_reg = REG_HMEBOX_0;
 226                         box_extreg = REG_HMEBOX_EXT_0;
 227                         break;
 228                 case 1:
 229                         box_reg = REG_HMEBOX_1;
 230                         box_extreg = REG_HMEBOX_EXT_1;
 231                         break;
 232                 case 2:
 233                         box_reg = REG_HMEBOX_2;
 234                         box_extreg = REG_HMEBOX_EXT_2;
 235                         break;
 236                 case 3:
 237                         box_reg = REG_HMEBOX_3;
 238                         box_extreg = REG_HMEBOX_EXT_3;
 239                         break;
 240                 default:
 241                         RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
 242                                  "switch case %#x not processed\n", boxnum);
 243                         break;
 244                 }
 245                 isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
 246                 while (!isfw_read) {
 247                         wait_h2c_limmit--;
 248                         if (wait_h2c_limmit == 0) {
 249                                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 250                                          "Waiting too long for FW read clear HMEBox(%d)!\n",
 251                                          boxnum);
 252                                 break;
 253                         }
 254 
 255                         udelay(10);
 256 
 257                         isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
 258                         u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
 259                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 260                                  "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
 261                                  boxnum, u1b_tmp);
 262                 }
 263 
 264                 if (!isfw_read) {
 265                         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 266                                  "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
 267                                  boxnum);
 268                         break;
 269                 }
 270 
 271                 memset(boxcontent, 0, sizeof(boxcontent));
 272                 memset(boxextcontent, 0, sizeof(boxextcontent));
 273                 boxcontent[0] = element_id;
 274                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 275                          "Write element_id box_reg(%4x) = %2x\n",
 276                          box_reg, element_id);
 277 
 278                 switch (cmd_len) {
 279                 case 1:
 280                 case 2:
 281                 case 3:
 282                         /*boxcontent[0] &= ~(BIT(7));*/
 283                         memcpy((u8 *)(boxcontent) + 1,
 284                                cmd_b + buf_index, cmd_len);
 285 
 286                         for (idx = 0; idx < 4; idx++) {
 287                                 rtl_write_byte(rtlpriv, box_reg + idx,
 288                                                boxcontent[idx]);
 289                         }
 290                         break;
 291                 case 4:
 292                 case 5:
 293                 case 6:
 294                 case 7:
 295                         /*boxcontent[0] |= (BIT(7));*/
 296                         memcpy((u8 *)(boxextcontent),
 297                                cmd_b + buf_index+3, cmd_len-3);
 298                         memcpy((u8 *)(boxcontent) + 1,
 299                                cmd_b + buf_index, 3);
 300 
 301                         for (idx = 0; idx < 2; idx++) {
 302                                 rtl_write_byte(rtlpriv, box_extreg + idx,
 303                                                boxextcontent[idx]);
 304                         }
 305 
 306                         for (idx = 0; idx < 4; idx++) {
 307                                 rtl_write_byte(rtlpriv, box_reg + idx,
 308                                                boxcontent[idx]);
 309                         }
 310                         break;
 311                 default:
 312                         RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
 313                                  "switch case %#x not processed\n", cmd_len);
 314                         break;
 315                 }
 316 
 317                 write_sucess = true;
 318 
 319                 rtlhal->last_hmeboxnum = boxnum + 1;
 320                 if (rtlhal->last_hmeboxnum == 4)
 321                         rtlhal->last_hmeboxnum = 0;
 322 
 323                 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
 324                          "pHalData->last_hmeboxnum  = %d\n",
 325                           rtlhal->last_hmeboxnum);
 326         }
 327 
 328         spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
 329         rtlhal->h2c_setinprogress = false;
 330         spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
 331 
 332         RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
 333 }
 334 
 335 void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw,
 336                          u8 element_id, u32 cmd_len, u8 *cmdbuffer)
 337 {
 338         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 339         u32 tmp_cmdbuf[2];
 340 
 341         if (!rtlhal->fw_ready) {
 342                 WARN_ONCE(true,
 343                           "rtl8188ee: error H2C cmd because of Fw download fail!!!\n");
 344                 return;
 345         }
 346 
 347         memset(tmp_cmdbuf, 0, 8);
 348         memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
 349         _rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
 350 
 351         return;
 352 }
 353 
 354 void rtl88e_firmware_selfreset(struct ieee80211_hw *hw)
 355 {
 356         u8 u1b_tmp;
 357         struct rtl_priv *rtlpriv = rtl_priv(hw);
 358 
 359         u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1);
 360         rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2))));
 361         rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2)));
 362         RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
 363                  "8051Reset88E(): 8051 reset success\n");
 364 
 365 }
 366 
 367 void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
 368 {
 369         struct rtl_priv *rtlpriv = rtl_priv(hw);
 370         u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 };
 371         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 372         u8 rlbm, power_state = 0;
 373         RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
 374 
 375         SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
 376         rlbm = 0;/*YJ, temp, 120316. FW now not support RLBM=2.*/
 377         SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
 378         SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
 379                 (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
 380         SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
 381                 ppsc->reg_max_lps_awakeintvl);
 382         SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
 383         if (mode == FW_PS_ACTIVE_MODE)
 384                 power_state |= FW_PWR_STATE_ACTIVE;
 385         else
 386                 power_state |= FW_PWR_STATE_RF_OFF;
 387 
 388         SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
 389 
 390         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 391                       "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
 392                       u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH);
 393         rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE,
 394                             H2C_88E_PWEMODE_LENGTH, u1_h2c_set_pwrmode);
 395 }
 396 
 397 void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
 398 {
 399         u8 u1_joinbssrpt_parm[1] = { 0 };
 400 
 401         SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
 402 
 403         rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm);
 404 }
 405 
 406 void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw,
 407                                    u8 ap_offload_enable)
 408 {
 409         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 410         u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 };
 411 
 412         SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable);
 413         SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid);
 414         SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0);
 415 
 416         rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD,
 417                             H2C_88E_AP_OFFLOAD_LENGTH, u1_apoffload_parm);
 418 
 419 }
 420 
 421 #define BEACON_PG               0 /* ->1 */
 422 #define PSPOLL_PG               2
 423 #define NULL_PG                 3
 424 #define PROBERSP_PG             4 /* ->5 */
 425 
 426 #define TOTAL_RESERVED_PKT_LEN  768
 427 
 428 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
 429         /* page 0 beacon */
 430         0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
 431         0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 432         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
 433         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 434         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 435         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 436         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 437         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 438         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 439         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 440         0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 441         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 442         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 443         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 444         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 445         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 446 
 447         /* page 1 beacon */
 448         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 449         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 450         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 451         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 452         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 453         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 454         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 455         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 456         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 457         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 458         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 459         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 460         0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
 461         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 462         0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 463         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 464 
 465         /* page 2  ps-poll */
 466         0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
 467         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 468         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 469         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 470         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 471         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 472         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 473         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 474         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 475         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 476         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 477         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 478         0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
 479         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
 480         0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 481         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 482 
 483         /* page 3  null */
 484         0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 485         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 486         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 487         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 488         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 489         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 490         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 491         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 492         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 493         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 494         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 495         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 496         0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
 497         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
 498         0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 499         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 500 
 501         /* page 4  probe_resp */
 502         0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
 503         0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
 504         0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
 505         0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
 506         0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
 507         0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
 508         0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
 509         0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
 510         0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
 511         0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
 512         0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 513         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 514         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 515         0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
 516         0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 517         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 518 
 519         /* page 5  probe_resp */
 520         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 521         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 522         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 523         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 524         0x00, 0x00, 0x00, 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, 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 };
 537 
 538 void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
 539 {
 540         struct rtl_priv *rtlpriv = rtl_priv(hw);
 541         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 542         struct sk_buff *skb = NULL;
 543         u32 totalpacketlen;
 544         bool rtstatus;
 545         u8 u1rsvdpageloc[5] = { 0 };
 546         bool b_dlok = false;
 547         u8 *beacon;
 548         u8 *p_pspoll;
 549         u8 *nullfunc;
 550         u8 *p_probersp;
 551 
 552         /*---------------------------------------------------------
 553          *                      (1) beacon
 554          *---------------------------------------------------------
 555          */
 556         beacon = &reserved_page_packet[BEACON_PG * 128];
 557         SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
 558         SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
 559 
 560         /*-------------------------------------------------------
 561          *                      (2) ps-poll
 562          *--------------------------------------------------------
 563          */
 564         p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
 565         SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
 566         SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
 567         SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
 568 
 569         SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
 570 
 571         /*--------------------------------------------------------
 572          *                      (3) null data
 573          *---------------------------------------------------------
 574          */
 575         nullfunc = &reserved_page_packet[NULL_PG * 128];
 576         SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
 577         SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
 578         SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
 579 
 580         SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
 581 
 582         /*---------------------------------------------------------
 583          *                      (4) probe response
 584          *----------------------------------------------------------
 585          */
 586         p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
 587         SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
 588         SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
 589         SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
 590 
 591         SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
 592 
 593         totalpacketlen = TOTAL_RESERVED_PKT_LEN;
 594 
 595         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
 596                       "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 597                       &reserved_page_packet[0], totalpacketlen);
 598         RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 599                       "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 600                       u1rsvdpageloc, 3);
 601 
 602         skb = dev_alloc_skb(totalpacketlen);
 603         if (!skb)
 604                 return;
 605         skb_put_data(skb, &reserved_page_packet, totalpacketlen);
 606 
 607         rtstatus = rtl_cmd_send_packet(hw, skb);
 608 
 609         if (rtstatus)
 610                 b_dlok = true;
 611 
 612         if (b_dlok) {
 613                 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 614                          "Set RSVD page location to Fw.\n");
 615                 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
 616                               "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
 617                 rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE,
 618                                     sizeof(u1rsvdpageloc), u1rsvdpageloc);
 619         } else
 620                 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 621                          "Set RSVD page location to Fw FAIL!!!!!!.\n");
 622 }
 623 
 624 /*Should check FW support p2p or not.*/
 625 static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
 626 {
 627         u8 u1_ctwindow_period[1] = { ctwindow};
 628 
 629         rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
 630 
 631 }
 632 
 633 void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
 634 {
 635         struct rtl_priv *rtlpriv = rtl_priv(hw);
 636         struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
 637         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 638         struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
 639         struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
 640         u8      i;
 641         u16     ctwindow;
 642         u32     start_time, tsf_low;
 643 
 644         switch (p2p_ps_state) {
 645         case P2P_PS_DISABLE:
 646                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
 647                 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
 648                 break;
 649         case P2P_PS_ENABLE:
 650                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
 651                 /* update CTWindow value. */
 652                 if (p2pinfo->ctwindow > 0) {
 653                         p2p_ps_offload->ctwindow_en = 1;
 654                         ctwindow = p2pinfo->ctwindow;
 655                         rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow);
 656                 }
 657 
 658                 /* hw only support 2 set of NoA */
 659                 for (i = 0 ; i < p2pinfo->noa_num; i++) {
 660                         /* To control the register setting for which NOA*/
 661                         rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
 662                         if (i == 0)
 663                                 p2p_ps_offload->noa0_en = 1;
 664                         else
 665                                 p2p_ps_offload->noa1_en = 1;
 666 
 667                         /* config P2P NoA Descriptor Register */
 668                         rtl_write_dword(rtlpriv, 0x5E0,
 669                                         p2pinfo->noa_duration[i]);
 670                         rtl_write_dword(rtlpriv, 0x5E4,
 671                                         p2pinfo->noa_interval[i]);
 672 
 673                         /*Get Current TSF value */
 674                         tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
 675 
 676                         start_time = p2pinfo->noa_start_time[i];
 677                         if (p2pinfo->noa_count_type[i] != 1) {
 678                                 while (start_time <= (tsf_low+(50*1024))) {
 679                                         start_time += p2pinfo->noa_interval[i];
 680                                         if (p2pinfo->noa_count_type[i] != 255)
 681                                                 p2pinfo->noa_count_type[i]--;
 682                                 }
 683                         }
 684                         rtl_write_dword(rtlpriv, 0x5E8, start_time);
 685                         rtl_write_dword(rtlpriv, 0x5EC,
 686                                         p2pinfo->noa_count_type[i]);
 687                 }
 688 
 689                 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
 690                         /* rst p2p circuit */
 691                         rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
 692 
 693                         p2p_ps_offload->offload_en = 1;
 694 
 695                         if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
 696                                 p2p_ps_offload->role = 1;
 697                                 p2p_ps_offload->allstasleep = -1;
 698                         } else {
 699                                 p2p_ps_offload->role = 0;
 700                         }
 701 
 702                         p2p_ps_offload->discovery = 0;
 703                 }
 704                 break;
 705         case P2P_PS_SCAN:
 706                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
 707                 p2p_ps_offload->discovery = 1;
 708                 break;
 709         case P2P_PS_SCAN_DONE:
 710                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
 711                 p2p_ps_offload->discovery = 0;
 712                 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
 713                 break;
 714         default:
 715                 break;
 716         }
 717 
 718         rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1,
 719                             (u8 *)p2p_ps_offload);
 720 
 721 }

/* [<][>][^][v][top][bottom][index][help] */