1 /****************************************************************************** 2 * 3 * Copyright(c) 2009-2012 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 _rtl8723e_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, val_mcutst_1; 40 bool result = false; 41 42 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); 43 val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum)); 44 45 if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0) 46 result = true; 47 return result; 48 } 49 50 static void _rtl8723e_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id, 51 u32 cmd_len, u8 *cmdbuffer) 52 { 53 struct rtl_priv *rtlpriv = rtl_priv(hw); 54 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 55 u8 boxnum; 56 u16 box_reg = 0, box_extreg = 0; 57 u8 u1b_tmp; 58 bool isfw_read = false; 59 u8 buf_index = 0; 60 bool bwrite_sucess = false; 61 u8 wait_h2c_limmit = 100; 62 u8 wait_writeh2c_limmit = 100; 63 u8 boxcontent[4], boxextcontent[2]; 64 u32 h2c_waitcounter = 0; 65 unsigned long flag; 66 u8 idx; 67 68 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); 69 70 while (true) { 71 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 72 if (rtlhal->h2c_setinprogress) { 73 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 74 "H2C set in progress! Wait to set..element_id(%d).\n", 75 element_id); 76 77 while (rtlhal->h2c_setinprogress) { 78 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, 79 flag); 80 h2c_waitcounter++; 81 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 82 "Wait 100 us (%d times)...\n", 83 h2c_waitcounter); 84 udelay(100); 85 86 if (h2c_waitcounter > 1000) 87 return; 88 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, 89 flag); 90 } 91 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 92 } else { 93 rtlhal->h2c_setinprogress = true; 94 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 95 break; 96 } 97 } 98 99 while (!bwrite_sucess) { 100 wait_writeh2c_limmit--; 101 if (wait_writeh2c_limmit == 0) { 102 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 103 "Write H2C fail because no trigger for FW INT!\n"); 104 break; 105 } 106 107 boxnum = rtlhal->last_hmeboxnum; 108 switch (boxnum) { 109 case 0: 110 box_reg = REG_HMEBOX_0; 111 box_extreg = REG_HMEBOX_EXT_0; 112 break; 113 case 1: 114 box_reg = REG_HMEBOX_1; 115 box_extreg = REG_HMEBOX_EXT_1; 116 break; 117 case 2: 118 box_reg = REG_HMEBOX_2; 119 box_extreg = REG_HMEBOX_EXT_2; 120 break; 121 case 3: 122 box_reg = REG_HMEBOX_3; 123 box_extreg = REG_HMEBOX_EXT_3; 124 break; 125 default: 126 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 127 "switch case not process\n"); 128 break; 129 } 130 131 isfw_read = _rtl8723e_check_fw_read_last_h2c(hw, boxnum); 132 while (!isfw_read) { 133 134 wait_h2c_limmit--; 135 if (wait_h2c_limmit == 0) { 136 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 137 "Wating too long for FW read clear HMEBox(%d)!\n", 138 boxnum); 139 break; 140 } 141 142 udelay(10); 143 144 isfw_read = _rtl8723e_check_fw_read_last_h2c(hw, 145 boxnum); 146 u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF); 147 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 148 "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n", 149 boxnum, u1b_tmp); 150 } 151 152 if (!isfw_read) { 153 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 154 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", 155 boxnum); 156 break; 157 } 158 159 memset(boxcontent, 0, sizeof(boxcontent)); 160 memset(boxextcontent, 0, sizeof(boxextcontent)); 161 boxcontent[0] = element_id; 162 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 163 "Write element_id box_reg(%4x) = %2x\n", 164 box_reg, element_id); 165 166 switch (cmd_len) { 167 case 1: 168 boxcontent[0] &= ~(BIT(7)); 169 memcpy((u8 *)(boxcontent) + 1, 170 cmdbuffer + buf_index, 1); 171 172 for (idx = 0; idx < 4; idx++) { 173 rtl_write_byte(rtlpriv, box_reg + idx, 174 boxcontent[idx]); 175 } 176 break; 177 case 2: 178 boxcontent[0] &= ~(BIT(7)); 179 memcpy((u8 *)(boxcontent) + 1, 180 cmdbuffer + buf_index, 2); 181 182 for (idx = 0; idx < 4; idx++) { 183 rtl_write_byte(rtlpriv, box_reg + idx, 184 boxcontent[idx]); 185 } 186 break; 187 case 3: 188 boxcontent[0] &= ~(BIT(7)); 189 memcpy((u8 *)(boxcontent) + 1, 190 cmdbuffer + buf_index, 3); 191 192 for (idx = 0; idx < 4; idx++) { 193 rtl_write_byte(rtlpriv, box_reg + idx, 194 boxcontent[idx]); 195 } 196 break; 197 case 4: 198 boxcontent[0] |= (BIT(7)); 199 memcpy((u8 *)(boxextcontent), 200 cmdbuffer + buf_index, 2); 201 memcpy((u8 *)(boxcontent) + 1, 202 cmdbuffer + buf_index + 2, 2); 203 204 for (idx = 0; idx < 2; idx++) { 205 rtl_write_byte(rtlpriv, box_extreg + idx, 206 boxextcontent[idx]); 207 } 208 209 for (idx = 0; idx < 4; idx++) { 210 rtl_write_byte(rtlpriv, box_reg + idx, 211 boxcontent[idx]); 212 } 213 break; 214 case 5: 215 boxcontent[0] |= (BIT(7)); 216 memcpy((u8 *)(boxextcontent), 217 cmdbuffer + buf_index, 2); 218 memcpy((u8 *)(boxcontent) + 1, 219 cmdbuffer + buf_index + 2, 3); 220 221 for (idx = 0; idx < 2; idx++) { 222 rtl_write_byte(rtlpriv, box_extreg + idx, 223 boxextcontent[idx]); 224 } 225 226 for (idx = 0; idx < 4; idx++) { 227 rtl_write_byte(rtlpriv, box_reg + idx, 228 boxcontent[idx]); 229 } 230 break; 231 default: 232 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 233 "switch case not process\n"); 234 break; 235 } 236 237 bwrite_sucess = true; 238 239 rtlhal->last_hmeboxnum = boxnum + 1; 240 if (rtlhal->last_hmeboxnum == 4) 241 rtlhal->last_hmeboxnum = 0; 242 243 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, 244 "pHalData->last_hmeboxnum = %d\n", 245 rtlhal->last_hmeboxnum); 246 } 247 248 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); 249 rtlhal->h2c_setinprogress = false; 250 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); 251 252 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); 253 } 254 255 void rtl8723e_fill_h2c_cmd(struct ieee80211_hw *hw, 256 u8 element_id, u32 cmd_len, u8 *cmdbuffer) 257 { 258 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 259 u32 tmp_cmdbuf[2]; 260 261 if (!rtlhal->fw_ready) { 262 RT_ASSERT(false, 263 "return H2C cmd because of Fw download fail!!!\n"); 264 return; 265 } 266 memset(tmp_cmdbuf, 0, 8); 267 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); 268 _rtl8723e_fill_h2c_command(hw, element_id, cmd_len, 269 (u8 *)&tmp_cmdbuf); 270 } 271 272 void rtl8723e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) 273 { 274 struct rtl_priv *rtlpriv = rtl_priv(hw); 275 u8 u1_h2c_set_pwrmode[3] = { 0 }; 276 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 277 278 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); 279 280 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); 281 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 282 (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1); 283 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, 284 ppsc->reg_max_lps_awakeintvl); 285 286 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 287 "rtl8723e_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n", 288 u1_h2c_set_pwrmode, 3); 289 rtl8723e_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode); 290 } 291 292 #define BEACON_PG 0 /* ->1 */ 293 #define PSPOLL_PG 2 294 #define NULL_PG 3 295 #define PROBERSP_PG 4 /* ->5 */ 296 297 #define TOTAL_RESERVED_PKT_LEN 768 298 299 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { 300 /* page 0 beacon */ 301 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 302 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 303 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, 304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 305 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 306 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 307 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 308 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 309 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 310 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 311 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 315 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 317 318 /* page 1 beacon */ 319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 328 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 331 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, 332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 333 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 335 336 /* page 2 ps-poll */ 337 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, 338 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 349 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, 350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 351 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 353 354 /* page 3 null */ 355 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 356 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 357 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 367 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, 368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 369 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 371 372 /* page 4 probe_resp */ 373 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, 374 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, 375 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 376 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, 377 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, 378 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, 379 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, 380 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, 381 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, 382 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, 383 0x03, 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 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, 387 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 389 390 /* page 5 probe_resp */ 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 399 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 407 }; 408 409 void rtl8723e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) 410 { 411 struct rtl_priv *rtlpriv = rtl_priv(hw); 412 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 413 struct sk_buff *skb = NULL; 414 u32 totalpacketlen; 415 bool rtstatus; 416 u8 u1rsvdpageloc[3] = { 0 }; 417 bool b_dlok = false; 418 u8 *beacon; 419 u8 *p_pspoll; 420 u8 *nullfunc; 421 u8 *p_probersp; 422 423 /*--------------------------------------------------------- 424 * (1) beacon 425 *--------------------------------------------------------- 426 */ 427 beacon = &reserved_page_packet[BEACON_PG * 128]; 428 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); 429 SET_80211_HDR_ADDRESS3(beacon, mac->bssid); 430 431 /*------------------------------------------------------- 432 * (2) ps-poll 433 *-------------------------------------------------------- 434 */ 435 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; 436 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); 437 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); 438 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); 439 440 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); 441 442 /*-------------------------------------------------------- 443 * (3) null data 444 *--------------------------------------------------------- 445 */ 446 nullfunc = &reserved_page_packet[NULL_PG * 128]; 447 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); 448 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); 449 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); 450 451 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); 452 453 /*--------------------------------------------------------- 454 * (4) probe response 455 *---------------------------------------------------------- 456 */ 457 p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; 458 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); 459 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); 460 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); 461 462 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); 463 464 totalpacketlen = TOTAL_RESERVED_PKT_LEN; 465 466 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, 467 "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 468 &reserved_page_packet[0], totalpacketlen); 469 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 470 "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", 471 u1rsvdpageloc, 3); 472 473 skb = dev_alloc_skb(totalpacketlen); 474 memcpy((u8 *)skb_put(skb, totalpacketlen), 475 &reserved_page_packet, totalpacketlen); 476 477 rtstatus = rtl_cmd_send_packet(hw, skb); 478 479 if (rtstatus) 480 b_dlok = true; 481 482 if (b_dlok) { 483 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, 484 "Set RSVD page location to Fw.\n"); 485 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, 486 "H2C_RSVDPAGE:\n", 487 u1rsvdpageloc, 3); 488 rtl8723e_fill_h2c_cmd(hw, H2C_RSVDPAGE, 489 sizeof(u1rsvdpageloc), u1rsvdpageloc); 490 } else 491 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 492 "Set RSVD page location to Fw FAIL!!!!!!.\n"); 493 } 494 495 void rtl8723e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) 496 { 497 u8 u1_joinbssrpt_parm[1] = { 0 }; 498 499 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); 500 501 rtl8723e_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); 502 } 503 504 static void rtl8723e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, 505 u8 ctwindow) 506 { 507 u8 u1_ctwindow_period[1] = { ctwindow}; 508 509 rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); 510 511 } 512 513 void rtl8723e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) 514 { 515 struct rtl_priv *rtlpriv = rtl_priv(hw); 516 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); 517 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 518 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); 519 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; 520 u8 i; 521 u16 ctwindow; 522 u32 start_time, tsf_low; 523 524 switch (p2p_ps_state) { 525 case P2P_PS_DISABLE: 526 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); 527 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); 528 break; 529 case P2P_PS_ENABLE: 530 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); 531 /* update CTWindow value. */ 532 if (p2pinfo->ctwindow > 0) { 533 p2p_ps_offload->ctwindow_en = 1; 534 ctwindow = p2pinfo->ctwindow; 535 rtl8723e_set_p2p_ctw_period_cmd(hw, ctwindow); 536 } 537 538 /* hw only support 2 set of NoA */ 539 for (i = 0 ; i < p2pinfo->noa_num ; i++) { 540 /* To control the register setting for which NOA*/ 541 rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); 542 if (i == 0) 543 p2p_ps_offload->noa0_en = 1; 544 else 545 p2p_ps_offload->noa1_en = 1; 546 547 /* config P2P NoA Descriptor Register */ 548 rtl_write_dword(rtlpriv, 0x5E0, 549 p2pinfo->noa_duration[i]); 550 rtl_write_dword(rtlpriv, 0x5E4, 551 p2pinfo->noa_interval[i]); 552 553 /*Get Current TSF value */ 554 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); 555 556 start_time = p2pinfo->noa_start_time[i]; 557 if (p2pinfo->noa_count_type[i] != 1) { 558 while (start_time <= 559 (tsf_low+(50*1024))) { 560 start_time += 561 p2pinfo->noa_interval[i]; 562 if (p2pinfo->noa_count_type[i] != 255) 563 p2pinfo->noa_count_type[i]--; 564 } 565 } 566 rtl_write_dword(rtlpriv, 0x5E8, start_time); 567 rtl_write_dword(rtlpriv, 0x5EC, 568 p2pinfo->noa_count_type[i]); 569 570 } 571 572 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { 573 /* rst p2p circuit */ 574 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); 575 576 p2p_ps_offload->offload_en = 1; 577 578 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { 579 p2p_ps_offload->role = 1; 580 p2p_ps_offload->allstasleep = 0; 581 } else { 582 p2p_ps_offload->role = 0; 583 } 584 585 p2p_ps_offload->discovery = 0; 586 } 587 break; 588 case P2P_PS_SCAN: 589 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); 590 p2p_ps_offload->discovery = 1; 591 break; 592 case P2P_PS_SCAN_DONE: 593 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); 594 p2p_ps_offload->discovery = 0; 595 p2pinfo->p2p_ps_state = P2P_PS_ENABLE; 596 break; 597 default: 598 break; 599 } 600 601 rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload); 602 603 } 604