1 /****************************************************************************** 2 * 3 * Copyright(c) 2009-2014 Realtek Corporation. 4 * 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. 8 * 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 12 * more details. 13 * 14 * The full GNU General Public License is included in this distribution in the 15 * file called LICENSE. 16 * 17 * Contact Information: 18 * wlanfae <wlanfae@realtek.com> 19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, 20 * Hsinchu 300, Taiwan. 21 * 22 * Larry Finger <Larry.Finger@lwfinger.net> 23 * 24 *****************************************************************************/ 25 26 #include "../wifi.h" 27 #include "../pci.h" 28 #include "../base.h" 29 #include "../core.h" 30 #include "reg.h" 31 #include "def.h" 32 #include "fw.h" 33 #include "../rtl8723com/fw_common.h" 34 35 static bool _rtl8723be_check_fw_read_last_h2c(struct ieee80211_hw *hw, 36 u8 boxnum) 37 { 38 struct rtl_priv *rtlpriv = rtl_priv(hw); 39 u8 val_hmetfr; 40 bool result = false; 41 42 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); 43 if (((val_hmetfr >> boxnum) & BIT(0)) == 0) 44 result = true; 45 return result; 46 } 47 48 static void _rtl8723be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id, 49 u32 cmd_len, u8 *p_cmdbuffer) 50 { 51 struct rtl_priv *rtlpriv = rtl_priv(hw); 52 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 53 u8 boxnum; 54 u16 box_reg = 0, box_extreg = 0; 55 u8 u1b_tmp; 56 bool isfw_read = false; 57 u8 buf_index = 0; 58 bool bwrite_sucess = false; 59 u8 wait_h2c_limmit = 100; 60 u8 wait_writeh2c_limmit = 100; 61 u8 boxcontent[4], boxextcontent[4]; 62 u32 h2c_waitcounter = 0; 63 unsigned long flag; 64 u8 idx; 65 66 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); 67 68 while (true) { 69 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 70 if (rtlhal->h2c_setinprogress) { 71 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 72 "H2C set in progress! Wait to set..element_id(%d).\n", 73 element_id); 74 75 while (rtlhal->h2c_setinprogress) { 76 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, 77 flag); 78 h2c_waitcounter++; 79 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 80 "Wait 100 us (%d times)...\n", 81 h2c_waitcounter); 82 udelay(100); 83 84 if (h2c_waitcounter > 1000) 85 return; 86 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, 87 flag); 88 } 89 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 90 } else { 91 rtlhal->h2c_setinprogress = true; 92 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 93 break; 94 } 95 } 96 97 while (!bwrite_sucess) { 98 wait_writeh2c_limmit--; 99 if (wait_writeh2c_limmit == 0) { 100 pr_err("Write H2C fail because no trigger for FW INT!\n"); 101 break; 102 } 103 104 boxnum = rtlhal->last_hmeboxnum; 105 switch (boxnum) { 106 case 0: 107 box_reg = REG_HMEBOX_0; 108 box_extreg = REG_HMEBOX_EXT_0; 109 break; 110 case 1: 111 box_reg = REG_HMEBOX_1; 112 box_extreg = REG_HMEBOX_EXT_1; 113 break; 114 case 2: 115 box_reg = REG_HMEBOX_2; 116 box_extreg = REG_HMEBOX_EXT_2; 117 break; 118 case 3: 119 box_reg = REG_HMEBOX_3; 120 box_extreg = REG_HMEBOX_EXT_3; 121 break; 122 default: 123 pr_err("switch case %#x not processed\n", 124 boxnum); 125 break; 126 } 127 128 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, boxnum); 129 while (!isfw_read) { 130 wait_h2c_limmit--; 131 if (wait_h2c_limmit == 0) { 132 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 133 "Waiting too long for FW read clear HMEBox(%d)!\n", 134 boxnum); 135 break; 136 } 137 138 udelay(10); 139 140 isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, 141 boxnum); 142 u1b_tmp = rtl_read_byte(rtlpriv, 0x130); 143 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 144 "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", 145 boxnum, u1b_tmp); 146 } 147 148 if (!isfw_read) { 149 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 150 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", 151 boxnum); 152 break; 153 } 154 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", 160 box_reg, element_id); 161 162 switch (cmd_len) { 163 case 1: 164 case 2: 165 case 3: 166 /*boxcontent[0] &= ~(BIT(7));*/ 167 memcpy((u8 *)(boxcontent) + 1, 168 p_cmdbuffer + buf_index, cmd_len); 169 170 for (idx = 0; idx < 4; idx++) { 171 rtl_write_byte(rtlpriv, box_reg + idx, 172 boxcontent[idx]); 173 } 174 break; 175 case 4: 176 case 5: 177 case 6: 178 case 7: 179 /*boxcontent[0] |= (BIT(7));*/ 180 memcpy((u8 *)(boxextcontent), 181 p_cmdbuffer + buf_index+3, cmd_len-3); 182 memcpy((u8 *)(boxcontent) + 1, 183 p_cmdbuffer + buf_index, 3); 184 185 for (idx = 0; idx < 4; idx++) { 186 rtl_write_byte(rtlpriv, box_extreg + idx, 187 boxextcontent[idx]); 188 } 189 190 for (idx = 0; idx < 4; idx++) { 191 rtl_write_byte(rtlpriv, box_reg + idx, 192 boxcontent[idx]); 193 } 194 break; 195 default: 196 pr_err("switch case %#x not processed\n", 197 cmd_len); 198 break; 199 } 200 201 bwrite_sucess = true; 202 203 rtlhal->last_hmeboxnum = boxnum + 1; 204 if (rtlhal->last_hmeboxnum == 4) 205 rtlhal->last_hmeboxnum = 0; 206 207 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 208 "pHalData->last_hmeboxnum = %d\n", 209 rtlhal->last_hmeboxnum); 210 } 211 212 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 213 rtlhal->h2c_setinprogress = false; 214 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 215 216 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); 217 } 218 219 void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, 220 u32 cmd_len, u8 *p_cmdbuffer) 221 { 222 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 223 u32 tmp_cmdbuf[2]; 224 225 if (!rtlhal->fw_ready) { 226 WARN_ONCE(true, 227 "rtl8723be: error H2C cmd because of Fw download fail!!!\n"); 228 return; 229 } 230 231 memset(tmp_cmdbuf, 0, 8); 232 memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len); 233 _rtl8723be_fill_h2c_command(hw, element_id, cmd_len, 234 (u8 *)&tmp_cmdbuf); 235 return; 236 } 237 238 void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) 239 { 240 struct rtl_priv *rtlpriv = rtl_priv(hw); 241 u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 }; 242 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 243 u8 rlbm, power_state = 0; 244 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); 245 246 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); 247 rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/ 248 SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); 249 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 250 (rtlpriv->mac80211.p2p) ? 251 ppsc->smart_ps : 1); 252 SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, 253 ppsc->reg_max_lps_awakeintvl); 254 SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); 255 if (mode == FW_PS_ACTIVE_MODE) 256 power_state |= FW_PWR_STATE_ACTIVE; 257 else 258 power_state |= FW_PWR_STATE_RF_OFF; 259 SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); 260 261 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 262 "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", 263 u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH); 264 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH, 265 u1_h2c_set_pwrmode); 266 } 267 268 void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus) 269 { 270 u8 parm[3] = { 0, 0, 0 }; 271 /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect 272 * bit1=0-->update Media Status to MACID 273 * bit1=1-->update Media Status from MACID to MACID_End 274 * parm[1]: MACID, if this is INFRA_STA, MacID = 0 275 * parm[2]: MACID_End 276 */ 277 SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus); 278 SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); 279 280 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_MSRRPT, 3, parm); 281 } 282 283 #define BEACON_PG 0 /* ->1 */ 284 #define PSPOLL_PG 2 285 #define NULL_PG 3 286 #define PROBERSP_PG 4 /* ->5 */ 287 288 #define TOTAL_RESERVED_PKT_LEN 768 289 290 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 291 /* page 0 beacon */ 292 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 293 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 294 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00, 295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 296 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65, 297 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B, 298 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06, 299 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, 300 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 301 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 304 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, 305 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50, 306 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 307 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00, 308 309 /* page 1 beacon */ 310 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00, 311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 321 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 322 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 326 327 /* page 2 ps-poll */ 328 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B, 329 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 339 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 340 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 343 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 344 345 /* page 3 null */ 346 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B, 347 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, 348 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00, 349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 357 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, 358 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 361 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 362 363 /* page 4 probe_resp */ 364 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 365 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 366 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 367 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, 368 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 369 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 370 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 371 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 372 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 373 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 374 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 377 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 378 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 380 381 /* page 5 probe_resp */ 382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 387 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 398 }; 399 400 void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, 401 bool b_dl_finished) 402 { 403 struct rtl_priv *rtlpriv = rtl_priv(hw); 404 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 405 struct sk_buff *skb = NULL; 406 407 u32 totalpacketlen; 408 bool rtstatus; 409 u8 u1rsvdpageloc[5] = { 0 }; 410 bool b_dlok = false; 411 412 u8 *beacon; 413 u8 *p_pspoll; 414 u8 *nullfunc; 415 u8 *p_probersp; 416 /*--------------------------------------------------------- 417 * (1) beacon 418 *--------------------------------------------------------- 419 */ 420 beacon = &reserved_page_packet[BEACON_PG * 128]; 421 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); 422 SET_80211_HDR_ADDRESS3(beacon, mac->bssid); 423 424 /*------------------------------------------------------- 425 * (2) ps-poll 426 *------------------------------------------------------- 427 */ 428 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; 429 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); 430 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); 431 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); 432 433 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); 434 435 /*-------------------------------------------------------- 436 * (3) null data 437 *-------------------------------------------------------- 438 */ 439 nullfunc = &reserved_page_packet[NULL_PG * 128]; 440 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); 441 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); 442 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); 443 444 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); 445 446 /*--------------------------------------------------------- 447 * (4) probe response 448 *--------------------------------------------------------- 449 */ 450 p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; 451 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); 452 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); 453 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); 454 455 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); 456 457 totalpacketlen = TOTAL_RESERVED_PKT_LEN; 458 459 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, 460 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 461 &reserved_page_packet[0], totalpacketlen); 462 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 463 "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 464 u1rsvdpageloc, 3); 465 466 skb = dev_alloc_skb(totalpacketlen); 467 memcpy((u8 *)skb_put(skb, totalpacketlen), 468 &reserved_page_packet, totalpacketlen); 469 470 rtstatus = rtl_cmd_send_packet(hw, skb); 471 472 if (rtstatus) 473 b_dlok = true; 474 475 if (b_dlok) { 476 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, 477 "Set RSVD page location to Fw.\n"); 478 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n", 479 u1rsvdpageloc, 3); 480 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RSVDPAGE, 481 sizeof(u1rsvdpageloc), u1rsvdpageloc); 482 } else 483 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 484 "Set RSVD page location to Fw FAIL!!!!!!.\n"); 485 } 486 487 /*Should check FW support p2p or not.*/ 488 static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, 489 u8 ctwindow) 490 { 491 u8 u1_ctwindow_period[1] = { ctwindow}; 492 493 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_CTW_CMD, 1, 494 u1_ctwindow_period); 495 } 496 497 void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, 498 u8 p2p_ps_state) 499 { 500 struct rtl_priv *rtlpriv = rtl_priv(hw); 501 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); 502 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 503 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); 504 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; 505 u8 i; 506 u16 ctwindow; 507 u32 start_time, tsf_low; 508 509 switch (p2p_ps_state) { 510 case P2P_PS_DISABLE: 511 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); 512 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); 513 break; 514 case P2P_PS_ENABLE: 515 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); 516 /* update CTWindow value. */ 517 if (p2pinfo->ctwindow > 0) { 518 p2p_ps_offload->ctwindow_en = 1; 519 ctwindow = p2pinfo->ctwindow; 520 rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow); 521 } 522 /* hw only support 2 set of NoA */ 523 for (i = 0 ; i < p2pinfo->noa_num ; i++) { 524 /* To control the register setting 525 * for which NOA 526 */ 527 rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); 528 if (i == 0) 529 p2p_ps_offload->noa0_en = 1; 530 else 531 p2p_ps_offload->noa1_en = 1; 532 533 /* config P2P NoA Descriptor Register */ 534 rtl_write_dword(rtlpriv, 0x5E0, 535 p2pinfo->noa_duration[i]); 536 rtl_write_dword(rtlpriv, 0x5E4, 537 p2pinfo->noa_interval[i]); 538 539 /*Get Current TSF value */ 540 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); 541 542 start_time = p2pinfo->noa_start_time[i]; 543 if (p2pinfo->noa_count_type[i] != 1) { 544 while (start_time <= (tsf_low + (50 * 1024))) { 545 start_time += p2pinfo->noa_interval[i]; 546 if (p2pinfo->noa_count_type[i] != 255) 547 p2pinfo->noa_count_type[i]--; 548 } 549 } 550 rtl_write_dword(rtlpriv, 0x5E8, start_time); 551 rtl_write_dword(rtlpriv, 0x5EC, 552 p2pinfo->noa_count_type[i]); 553 } 554 555 if ((p2pinfo->opp_ps == 1) || 556 (p2pinfo->noa_num > 0)) { 557 /* rst p2p circuit */ 558 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); 559 560 p2p_ps_offload->offload_en = 1; 561 562 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { 563 p2p_ps_offload->role = 1; 564 p2p_ps_offload->allstasleep = 0; 565 } else { 566 p2p_ps_offload->role = 0; 567 } 568 p2p_ps_offload->discovery = 0; 569 } 570 break; 571 case P2P_PS_SCAN: 572 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); 573 p2p_ps_offload->discovery = 1; 574 break; 575 case P2P_PS_SCAN_DONE: 576 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); 577 p2p_ps_offload->discovery = 0; 578 p2pinfo->p2p_ps_state = P2P_PS_ENABLE; 579 break; 580 default: 581 break; 582 } 583 584 rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_OFFLOAD, 1, 585 (u8 *)p2p_ps_offload); 586 } 587 588 void rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw, 589 u8 c2h_cmd_id, 590 u8 c2h_cmd_len, u8 *tmp_buf) 591 { 592 struct rtl_priv *rtlpriv = rtl_priv(hw); 593 594 switch (c2h_cmd_id) { 595 case C2H_8723B_DBG: 596 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 597 "[C2H], C2H_8723BE_DBG!!\n"); 598 break; 599 case C2H_8723B_TX_REPORT: 600 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 601 "[C2H], C2H_8723BE_TX_REPORT!\n"); 602 break; 603 case C2H_8723B_BT_INFO: 604 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 605 "[C2H], C2H_8723BE_BT_INFO!!\n"); 606 rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf, 607 c2h_cmd_len); 608 break; 609 case C2H_8723B_BT_MP: 610 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 611 "[C2H], C2H_8723BE_BT_MP!!\n"); 612 break; 613 default: 614 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 615 "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id); 616 break; 617 } 618 } 619 620 void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len) 621 { 622 struct rtl_priv *rtlpriv = rtl_priv(hw); 623 u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0; 624 u8 *tmp_buf = NULL; 625 626 c2h_cmd_id = buffer[0]; 627 c2h_cmd_seq = buffer[1]; 628 c2h_cmd_len = len - 2; 629 tmp_buf = buffer + 2; 630 631 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 632 "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n", 633 c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len); 634 635 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE, 636 "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len); 637 638 switch (c2h_cmd_id) { 639 case C2H_8723B_BT_INFO: 640 case C2H_8723B_BT_MP: 641 rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf); 642 break; 643 644 default: 645 rtl8723be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, 646 tmp_buf); 647 break; 648 } 649 } 650