]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
networking: make skb_put & friends return void pointers
[mirror_ubuntu-artful-kernel.git] / drivers / net / wireless / realtek / rtlwifi / rtl8192se / fw.c
CommitLineData
701307a8
CL
1/******************************************************************************
2 *
ca742cd9 3 * Copyright(c) 2009-2012 Realtek Corporation.
701307a8
CL
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 *
701307a8
CL
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 "reg.h"
30#include "def.h"
31#include "fw.h"
32
33static void _rtl92s_fw_set_rqpn(struct ieee80211_hw *hw)
34{
35 struct rtl_priv *rtlpriv = rtl_priv(hw);
36
37 rtl_write_dword(rtlpriv, RQPN, 0xffffffff);
38 rtl_write_dword(rtlpriv, RQPN + 4, 0xffffffff);
39 rtl_write_byte(rtlpriv, RQPN + 8, 0xff);
40 rtl_write_byte(rtlpriv, RQPN + 0xB, 0x80);
41}
42
43static bool _rtl92s_firmware_enable_cpu(struct ieee80211_hw *hw)
44{
45 struct rtl_priv *rtlpriv = rtl_priv(hw);
46 u32 ichecktime = 200;
47 u16 tmpu2b;
48 u8 tmpu1b, cpustatus = 0;
49
50 _rtl92s_fw_set_rqpn(hw);
51
52 /* Enable CPU. */
53 tmpu1b = rtl_read_byte(rtlpriv, SYS_CLKR);
54 /* AFE source */
55 rtl_write_byte(rtlpriv, SYS_CLKR, (tmpu1b | SYS_CPU_CLKSEL));
56
57 tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
58 rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | FEN_CPUEN));
59
60 /* Polling IMEM Ready after CPU has refilled. */
61 do {
62 cpustatus = rtl_read_byte(rtlpriv, TCR);
63 if (cpustatus & IMEM_RDY) {
64 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
f30d7507 65 "IMEM Ready after CPU has refilled\n");
701307a8
CL
66 break;
67 }
68
69 udelay(100);
70 } while (ichecktime--);
71
72 if (!(cpustatus & IMEM_RDY))
73 return false;
74
75 return true;
76}
77
78static enum fw_status _rtl92s_firmware_get_nextstatus(
79 enum fw_status fw_currentstatus)
80{
81 enum fw_status next_fwstatus = 0;
82
83 switch (fw_currentstatus) {
84 case FW_STATUS_INIT:
85 next_fwstatus = FW_STATUS_LOAD_IMEM;
86 break;
87 case FW_STATUS_LOAD_IMEM:
88 next_fwstatus = FW_STATUS_LOAD_EMEM;
89 break;
90 case FW_STATUS_LOAD_EMEM:
91 next_fwstatus = FW_STATUS_LOAD_DMEM;
92 break;
93 case FW_STATUS_LOAD_DMEM:
94 next_fwstatus = FW_STATUS_READY;
95 break;
96 default:
97 break;
98 }
99
100 return next_fwstatus;
101}
102
103static u8 _rtl92s_firmware_header_map_rftype(struct ieee80211_hw *hw)
104{
105 struct rtl_priv *rtlpriv = rtl_priv(hw);
106 struct rtl_phy *rtlphy = &(rtlpriv->phy);
107
108 switch (rtlphy->rf_type) {
109 case RF_1T1R:
110 return 0x11;
701307a8
CL
111 case RF_1T2R:
112 return 0x12;
701307a8
CL
113 case RF_2T2R:
114 return 0x22;
701307a8 115 default:
2d15acac 116 pr_err("Unknown RF type(%x)\n", rtlphy->rf_type);
701307a8
CL
117 break;
118 }
119 return 0x22;
120}
121
122static void _rtl92s_firmwareheader_priveupdate(struct ieee80211_hw *hw,
123 struct fw_priv *pfw_priv)
124{
125 /* Update RF types for RATR settings. */
126 pfw_priv->rf_config = _rtl92s_firmware_header_map_rftype(hw);
127}
128
129
130
131static bool _rtl92s_cmd_send_packet(struct ieee80211_hw *hw,
132 struct sk_buff *skb, u8 last)
133{
134 struct rtl_priv *rtlpriv = rtl_priv(hw);
135 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
136 struct rtl8192_tx_ring *ring;
137 struct rtl_tx_desc *pdesc;
138 unsigned long flags;
139 u8 idx = 0;
140
141 ring = &rtlpci->tx_ring[TXCMD_QUEUE];
142
143 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
144
145 idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries;
146 pdesc = &ring->desc[idx];
147 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb);
148 __skb_queue_tail(&ring->queue, skb);
149
150 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
151
152 return true;
153}
154
155static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw,
156 u8 *code_virtual_address, u32 buffer_len)
157{
158 struct rtl_priv *rtlpriv = rtl_priv(hw);
159 struct sk_buff *skb;
160 struct rtl_tcb_desc *tcb_desc;
161 unsigned char *seg_ptr;
162 u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE;
163 u16 frag_length, frag_offset = 0;
164 u16 extra_descoffset = 0;
165 u8 last_inipkt = 0;
166
167 _rtl92s_fw_set_rqpn(hw);
168
169 if (buffer_len >= MAX_FIRMWARE_CODE_SIZE) {
2d15acac 170 pr_err("Size over FIRMWARE_CODE_SIZE!\n");
701307a8
CL
171 return false;
172 }
173
174 extra_descoffset = 0;
175
176 do {
177 if ((buffer_len - frag_offset) > frag_threshold) {
178 frag_length = frag_threshold + extra_descoffset;
179 } else {
180 frag_length = (u16)(buffer_len - frag_offset +
181 extra_descoffset);
182 last_inipkt = 1;
183 }
184
185 /* Allocate skb buffer to contain firmware */
186 /* info and tx descriptor info. */
187 skb = dev_alloc_skb(frag_length);
d90db4b1
LF
188 if (!skb)
189 return false;
701307a8 190 skb_reserve(skb, extra_descoffset);
59ae1d12
JB
191 seg_ptr = skb_put_data(skb,
192 code_virtual_address + frag_offset,
193 (u32)(frag_length - extra_descoffset));
701307a8
CL
194
195 tcb_desc = (struct rtl_tcb_desc *)(skb->cb);
196 tcb_desc->queue_index = TXCMD_QUEUE;
197 tcb_desc->cmd_or_init = DESC_PACKET_TYPE_INIT;
198 tcb_desc->last_inipkt = last_inipkt;
199
200 _rtl92s_cmd_send_packet(hw, skb, last_inipkt);
201
202 frag_offset += (frag_length - extra_descoffset);
203
204 } while (frag_offset < buffer_len);
205
206 rtl_write_byte(rtlpriv, TP_POLL, TPPOLL_CQ);
207
208 return true ;
209}
210
211static bool _rtl92s_firmware_checkready(struct ieee80211_hw *hw,
212 u8 loadfw_status)
213{
214 struct rtl_priv *rtlpriv = rtl_priv(hw);
215 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
216 struct rt_firmware *firmware = (struct rt_firmware *)rtlhal->pfirmware;
217 u32 tmpu4b;
218 u8 cpustatus = 0;
219 short pollingcnt = 1000;
220 bool rtstatus = true;
221
f30d7507
JP
222 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
223 "LoadStaus(%d)\n", loadfw_status);
701307a8
CL
224
225 firmware->fwstatus = (enum fw_status)loadfw_status;
226
227 switch (loadfw_status) {
228 case FW_STATUS_LOAD_IMEM:
229 /* Polling IMEM code done. */
230 do {
231 cpustatus = rtl_read_byte(rtlpriv, TCR);
232 if (cpustatus & IMEM_CODE_DONE)
233 break;
234 udelay(5);
235 } while (pollingcnt--);
236
237 if (!(cpustatus & IMEM_CHK_RPT) || (pollingcnt <= 0)) {
2d15acac
LF
238 pr_err("FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\n",
239 cpustatus);
701307a8
CL
240 goto status_check_fail;
241 }
242 break;
243
244 case FW_STATUS_LOAD_EMEM:
245 /* Check Put Code OK and Turn On CPU */
246 /* Polling EMEM code done. */
247 do {
248 cpustatus = rtl_read_byte(rtlpriv, TCR);
249 if (cpustatus & EMEM_CODE_DONE)
250 break;
251 udelay(5);
252 } while (pollingcnt--);
253
254 if (!(cpustatus & EMEM_CHK_RPT) || (pollingcnt <= 0)) {
2d15acac
LF
255 pr_err("FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\n",
256 cpustatus);
701307a8
CL
257 goto status_check_fail;
258 }
259
260 /* Turn On CPU */
261 rtstatus = _rtl92s_firmware_enable_cpu(hw);
23677ce3 262 if (!rtstatus) {
2d15acac 263 pr_err("Enable CPU fail!\n");
701307a8
CL
264 goto status_check_fail;
265 }
266 break;
267
268 case FW_STATUS_LOAD_DMEM:
269 /* Polling DMEM code done */
270 do {
271 cpustatus = rtl_read_byte(rtlpriv, TCR);
272 if (cpustatus & DMEM_CODE_DONE)
273 break;
274 udelay(5);
275 } while (pollingcnt--);
276
277 if (!(cpustatus & DMEM_CODE_DONE) || (pollingcnt <= 0)) {
2d15acac
LF
278 pr_err("Polling DMEM code done fail ! cpustatus(%#x)\n",
279 cpustatus);
701307a8
CL
280 goto status_check_fail;
281 }
282
283 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
f30d7507
JP
284 "DMEM code download success, cpustatus(%#x)\n",
285 cpustatus);
701307a8
CL
286
287 /* Prevent Delay too much and being scheduled out */
288 /* Polling Load Firmware ready */
289 pollingcnt = 2000;
290 do {
291 cpustatus = rtl_read_byte(rtlpriv, TCR);
292 if (cpustatus & FWRDY)
293 break;
294 udelay(40);
295 } while (pollingcnt--);
296
297 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
f30d7507
JP
298 "Polling Load Firmware ready, cpustatus(%x)\n",
299 cpustatus);
701307a8
CL
300
301 if (((cpustatus & LOAD_FW_READY) != LOAD_FW_READY) ||
302 (pollingcnt <= 0)) {
2d15acac
LF
303 pr_err("Polling Load Firmware ready fail ! cpustatus(%x)\n",
304 cpustatus);
701307a8
CL
305 goto status_check_fail;
306 }
307
308 /* If right here, we can set TCR/RCR to desired value */
309 /* and config MAC lookback mode to normal mode */
310 tmpu4b = rtl_read_dword(rtlpriv, TCR);
311 rtl_write_dword(rtlpriv, TCR, (tmpu4b & (~TCR_ICV)));
312
313 tmpu4b = rtl_read_dword(rtlpriv, RCR);
314 rtl_write_dword(rtlpriv, RCR, (tmpu4b | RCR_APPFCS |
315 RCR_APP_ICV | RCR_APP_MIC));
316
317 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
f30d7507 318 "Current RCR settings(%#x)\n", tmpu4b);
701307a8
CL
319
320 /* Set to normal mode. */
321 rtl_write_byte(rtlpriv, LBKMD_SEL, LBK_NORMAL);
322 break;
323
324 default:
2d15acac 325 pr_err("Unknown status check!\n");
701307a8
CL
326 rtstatus = false;
327 break;
328 }
329
330status_check_fail:
f30d7507
JP
331 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
332 "loadfw_status(%d), rtstatus(%x)\n",
333 loadfw_status, rtstatus);
701307a8
CL
334 return rtstatus;
335}
336
337int rtl92s_download_fw(struct ieee80211_hw *hw)
338{
339 struct rtl_priv *rtlpriv = rtl_priv(hw);
340 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
341 struct rt_firmware *firmware = NULL;
342 struct fw_hdr *pfwheader;
343 struct fw_priv *pfw_priv = NULL;
344 u8 *puc_mappedfile = NULL;
345 u32 ul_filelength = 0;
701307a8
CL
346 u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE;
347 u8 fwstatus = FW_STATUS_INIT;
348 bool rtstatus = true;
349
b0302aba 350 if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
701307a8
CL
351 return 1;
352
353 firmware = (struct rt_firmware *)rtlhal->pfirmware;
354 firmware->fwstatus = FW_STATUS_INIT;
355
356 puc_mappedfile = firmware->sz_fw_tmpbuffer;
701307a8
CL
357
358 /* 1. Retrieve FW header. */
359 firmware->pfwheader = (struct fw_hdr *) puc_mappedfile;
360 pfwheader = firmware->pfwheader;
361 firmware->firmwareversion = byte(pfwheader->version, 0);
362 firmware->pfwheader->fwpriv.hci_sel = 1;/* pcie */
363
f30d7507
JP
364 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
365 "signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n",
366 pfwheader->signature,
701307a8 367 pfwheader->version, pfwheader->dmem_size,
f30d7507 368 pfwheader->img_imem_size, pfwheader->img_sram_size);
701307a8
CL
369
370 /* 2. Retrieve IMEM image. */
371 if ((pfwheader->img_imem_size == 0) || (pfwheader->img_imem_size >
372 sizeof(firmware->fw_imem))) {
2d15acac 373 pr_err("memory for data image is less than IMEM required\n");
701307a8
CL
374 goto fail;
375 } else {
376 puc_mappedfile += fwhdr_size;
377
378 memcpy(firmware->fw_imem, puc_mappedfile,
379 pfwheader->img_imem_size);
380 firmware->fw_imem_len = pfwheader->img_imem_size;
381 }
382
383 /* 3. Retriecve EMEM image. */
384 if (pfwheader->img_sram_size > sizeof(firmware->fw_emem)) {
2d15acac 385 pr_err("memory for data image is less than EMEM required\n");
701307a8
CL
386 goto fail;
387 } else {
388 puc_mappedfile += firmware->fw_imem_len;
389
390 memcpy(firmware->fw_emem, puc_mappedfile,
391 pfwheader->img_sram_size);
392 firmware->fw_emem_len = pfwheader->img_sram_size;
393 }
394
395 /* 4. download fw now */
396 fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus);
397 while (fwstatus != FW_STATUS_READY) {
398 /* Image buffer redirection. */
399 switch (fwstatus) {
400 case FW_STATUS_LOAD_IMEM:
401 puc_mappedfile = firmware->fw_imem;
402 ul_filelength = firmware->fw_imem_len;
403 break;
404 case FW_STATUS_LOAD_EMEM:
405 puc_mappedfile = firmware->fw_emem;
406 ul_filelength = firmware->fw_emem_len;
407 break;
408 case FW_STATUS_LOAD_DMEM:
409 /* Partial update the content of header private. */
410 pfwheader = firmware->pfwheader;
411 pfw_priv = &pfwheader->fwpriv;
412 _rtl92s_firmwareheader_priveupdate(hw, pfw_priv);
413 puc_mappedfile = (u8 *)(firmware->pfwheader) +
414 RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
415 ul_filelength = fwhdr_size -
416 RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
417 break;
418 default:
2d15acac 419 pr_err("Unexpected Download step!!\n");
701307a8 420 goto fail;
701307a8
CL
421 }
422
423 /* <2> Download image file */
424 rtstatus = _rtl92s_firmware_downloadcode(hw, puc_mappedfile,
425 ul_filelength);
426
23677ce3 427 if (!rtstatus) {
2d15acac 428 pr_err("fail!\n");
701307a8
CL
429 goto fail;
430 }
431
432 /* <3> Check whether load FW process is ready */
433 rtstatus = _rtl92s_firmware_checkready(hw, fwstatus);
23677ce3 434 if (!rtstatus) {
2d15acac 435 pr_err("rtl8192se: firmware fail!\n");
701307a8
CL
436 goto fail;
437 }
438
439 fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus);
440 }
441
442 return rtstatus;
443fail:
444 return 0;
445}
446
447static u32 _rtl92s_fill_h2c_cmd(struct sk_buff *skb, u32 h2cbufferlen,
448 u32 cmd_num, u32 *pelement_id, u32 *pcmd_len,
449 u8 **pcmb_buffer, u8 *cmd_start_seq)
450{
451 u32 totallen = 0, len = 0, tx_desclen = 0;
452 u32 pre_continueoffset = 0;
453 u8 *ph2c_buffer;
454 u8 i = 0;
455
456 do {
550116d2 457 /* 8 - Byte alignment */
701307a8
CL
458 len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8);
459
460 /* Buffer length is not enough */
461 if (h2cbufferlen < totallen + len + tx_desclen)
462 break;
463
464 /* Clear content */
4df864c1 465 ph2c_buffer = skb_put(skb, (u32)len);
701307a8
CL
466 memset((ph2c_buffer + totallen + tx_desclen), 0, len);
467
468 /* CMD len */
469 SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen),
470 0, 16, pcmd_len[i]);
471
472 /* CMD ID */
473 SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen),
474 16, 8, pelement_id[i]);
475
476 /* CMD Sequence */
477 *cmd_start_seq = *cmd_start_seq % 0x80;
478 SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen),
479 24, 7, *cmd_start_seq);
480 ++*cmd_start_seq;
481
482 /* Copy memory */
483 memcpy((ph2c_buffer + totallen + tx_desclen +
484 H2C_TX_CMD_HDR_LEN), pcmb_buffer[i], pcmd_len[i]);
485
486 /* CMD continue */
487 /* set the continue in prevoius cmd. */
488 if (i < cmd_num - 1)
489 SET_BITS_TO_LE_4BYTE((ph2c_buffer + pre_continueoffset),
490 31, 1, 1);
491
492 pre_continueoffset = totallen;
493
494 totallen += len;
495 } while (++i < cmd_num);
496
497 return totallen;
498}
499
500static u32 _rtl92s_get_h2c_cmdlen(u32 h2cbufferlen, u32 cmd_num, u32 *pcmd_len)
501{
502 u32 totallen = 0, len = 0, tx_desclen = 0;
503 u8 i = 0;
504
505 do {
550116d2 506 /* 8 - Byte alignment */
701307a8
CL
507 len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8);
508
509 /* Buffer length is not enough */
510 if (h2cbufferlen < totallen + len + tx_desclen)
511 break;
512
513 totallen += len;
514 } while (++i < cmd_num);
515
516 return totallen + tx_desclen;
517}
518
519static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd,
520 u8 *pcmd_buffer)
521{
522 struct rtl_priv *rtlpriv = rtl_priv(hw);
523 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
524 struct rtl_tcb_desc *cb_desc;
525 struct sk_buff *skb;
526 u32 element_id = 0;
527 u32 cmd_len = 0;
528 u32 len;
529
530 switch (h2c_cmd) {
531 case FW_H2C_SETPWRMODE:
532 element_id = H2C_SETPWRMODE_CMD ;
533 cmd_len = sizeof(struct h2c_set_pwrmode_parm);
534 break;
535 case FW_H2C_JOINBSSRPT:
536 element_id = H2C_JOINBSSRPT_CMD;
537 cmd_len = sizeof(struct h2c_joinbss_rpt_parm);
538 break;
539 case FW_H2C_WOWLAN_UPDATE_GTK:
540 element_id = H2C_WOWLAN_UPDATE_GTK_CMD;
541 cmd_len = sizeof(struct h2c_wpa_two_way_parm);
542 break;
543 case FW_H2C_WOWLAN_UPDATE_IV:
544 element_id = H2C_WOWLAN_UPDATE_IV_CMD;
545 cmd_len = sizeof(unsigned long long);
546 break;
547 case FW_H2C_WOWLAN_OFFLOAD:
548 element_id = H2C_WOWLAN_FW_OFFLOAD;
549 cmd_len = sizeof(u8);
550 break;
551 default:
552 break;
553 }
554
555 len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len);
556 skb = dev_alloc_skb(len);
d90db4b1
LF
557 if (!skb)
558 return false;
701307a8
CL
559 cb_desc = (struct rtl_tcb_desc *)(skb->cb);
560 cb_desc->queue_index = TXCMD_QUEUE;
561 cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL;
562 cb_desc->last_inipkt = false;
563
564 _rtl92s_fill_h2c_cmd(skb, MAX_TRANSMIT_BUFFER_SIZE, 1, &element_id,
565 &cmd_len, &pcmd_buffer, &rtlhal->h2c_txcmd_seq);
566 _rtl92s_cmd_send_packet(hw, skb, false);
567 rtlpriv->cfg->ops->tx_polling(hw, TXCMD_QUEUE);
568
569 return true;
570}
571
572void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 Mode)
573{
574 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
575 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
576 struct h2c_set_pwrmode_parm pwrmode;
577 u16 max_wakeup_period = 0;
578
579 pwrmode.mode = Mode;
580 pwrmode.flag_low_traffic_en = 0;
581 pwrmode.flag_lpnav_en = 0;
582 pwrmode.flag_rf_low_snr_en = 0;
583 pwrmode.flag_dps_en = 0;
584 pwrmode.bcn_rx_en = 0;
585 pwrmode.bcn_to = 0;
586 SET_BITS_TO_LE_2BYTE((u8 *)(&pwrmode) + 8, 0, 16,
587 mac->vif->bss_conf.beacon_int);
588 pwrmode.app_itv = 0;
589 pwrmode.awake_bcn_itvl = ppsc->reg_max_lps_awakeintvl;
590 pwrmode.smart_ps = 1;
591 pwrmode.bcn_pass_period = 10;
592
593 /* Set beacon pass count */
594 if (pwrmode.mode == FW_PS_MIN_MODE)
595 max_wakeup_period = mac->vif->bss_conf.beacon_int;
596 else if (pwrmode.mode == FW_PS_MAX_MODE)
597 max_wakeup_period = mac->vif->bss_conf.beacon_int *
598 mac->vif->bss_conf.dtim_period;
599
600 if (max_wakeup_period >= 500)
601 pwrmode.bcn_pass_cnt = 1;
602 else if ((max_wakeup_period >= 300) && (max_wakeup_period < 500))
603 pwrmode.bcn_pass_cnt = 2;
604 else if ((max_wakeup_period >= 200) && (max_wakeup_period < 300))
605 pwrmode.bcn_pass_cnt = 3;
606 else if ((max_wakeup_period >= 20) && (max_wakeup_period < 200))
607 pwrmode.bcn_pass_cnt = 5;
608 else
609 pwrmode.bcn_pass_cnt = 1;
610
611 _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_SETPWRMODE, (u8 *)&pwrmode);
612
613}
614
615void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw,
616 u8 mstatus, u8 ps_qosinfo)
617{
618 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
619 struct h2c_joinbss_rpt_parm joinbss_rpt;
620
621 joinbss_rpt.opmode = mstatus;
622 joinbss_rpt.ps_qos_info = ps_qosinfo;
623 joinbss_rpt.bssid[0] = mac->bssid[0];
624 joinbss_rpt.bssid[1] = mac->bssid[1];
625 joinbss_rpt.bssid[2] = mac->bssid[2];
626 joinbss_rpt.bssid[3] = mac->bssid[3];
627 joinbss_rpt.bssid[4] = mac->bssid[4];
628 joinbss_rpt.bssid[5] = mac->bssid[5];
629 SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 8, 0, 16,
630 mac->vif->bss_conf.beacon_int);
631 SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 10, 0, 16, mac->assoc_id);
632
633 _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_JOINBSSRPT, (u8 *)&joinbss_rpt);
634}
635