xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/ssv6xxx/smac/ap.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (c) 2015 South Silicon Valley Microelectronics Inc.
3  * Copyright (c) 2015 iComm Corporation
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  * See the GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #include <ssv6200.h>
18 #include <linux/nl80211.h>
19 #include <linux/etherdevice.h>
20 #include <linux/delay.h>
21 #include <linux/version.h>
22 #include <linux/time.h>
23 #include <linux/sched.h>
24 #include <net/mac80211.h>
25 #include <ssv6200.h>
26 #include "lib.h"
27 #include "dev.h"
28 #include "ap.h"
29 #include "ssv_rc_common.h"
30 #include "ssv_rc.h"
31 int ssv6200_bcast_queue_len(struct ssv6xxx_bcast_txq *bcast_txq);
32 #define IS_EQUAL(a,b) ( (a) == (b) )
33 #define SET_BIT(v,b) ( (v) |= (0x01<<b) )
34 #define CLEAR_BIT(v,b) ( (v) &= ~(0x01<<b) )
35 #define IS_BIT_SET(v,b) ( (v) & (0x01<<(b) ) )
36 #define PBUF_BASE_ADDR 0x80000000
37 #define PBUF_ADDR_SHIFT 16
38 #define PBUF_MapPkttoID(_PKT) (((u32)_PKT&0x0FFF0000)>>PBUF_ADDR_SHIFT)
39 #define PBUF_MapIDtoPkt(_ID) (PBUF_BASE_ADDR|((_ID)<<PBUF_ADDR_SHIFT))
40 #define SSV6xxx_BEACON_MAX_ALLOCATE_CNT 10
41 #define MTX_BCN_PKTID_CH_LOCK_SHIFT MTX_BCN_PKTID_CH_LOCK_SFT
42 #define MTX_BCN_CFG_VLD_SHIFT MTX_BCN_CFG_VLD_SFT
43 #define MTX_BCN_CFG_VLD_MASK MTX_BCN_CFG_VLD_MSK
44 #define AUTO_BCN_ONGOING_MASK MTX_AUTO_BCN_ONGOING_MSK
45 #define AUTO_BCN_ONGOING_SHIFT MTX_AUTO_BCN_ONGOING_SFT
46 #define MTX_BCN_TIMER_EN_SHIFT MTX_BCN_TIMER_EN_SFT
47 #define MTX_TSF_TIMER_EN_SHIFT MTX_TSF_TIMER_EN_SFT
48 #define MTX_HALT_MNG_UNTIL_DTIM_SHIFT MTX_HALT_MNG_UNTIL_DTIM_SFT
49 #define MTX_BCN_ENABLE_MASK (MTX_BCN_TIMER_EN_I_MSK)
50 #define MTX_BCN_PERIOD_SHIFT MTX_BCN_PERIOD_SFT
51 #define MTX_DTIM_NUM_SHIFT MTX_DTIM_NUM_SFT
52 #define MTX_DTIM_OFST0 MTX_DTIM_OFST0_SFT
53 enum ssv6xxx_beacon_type{
54  SSV6xxx_BEACON_0,
55  SSV6xxx_BEACON_1,
56 };
57 static const u32 ssv6xxx_beacon_adr[] =
58 {
59  ADR_MTX_BCN_CFG0,
60     ADR_MTX_BCN_CFG1,
61 };
ssv6xxx_beacon_reg_lock(struct ssv_softc * sc,bool block)62 void ssv6xxx_beacon_reg_lock(struct ssv_softc *sc, bool block)
63 {
64  u32 val;
65  val = block<<MTX_BCN_PKTID_CH_LOCK_SHIFT;
66 #ifdef BEACON_DEBUG
67  printk("ssv6xxx_beacon_reg_lock   val[0x:%08x]\n ", val);
68 #endif
69  SMAC_REG_WRITE(sc->sh, ADR_MTX_BCN_MISC, val);
70 }
ssv6xxx_beacon_set_info(struct ssv_softc * sc,u8 beacon_interval,u8 dtim_cnt)71 void ssv6xxx_beacon_set_info(struct ssv_softc *sc, u8 beacon_interval, u8 dtim_cnt)
72 {
73  u32 val;
74  if(beacon_interval==0)
75   beacon_interval = 100;
76 #ifdef BEACON_DEBUG
77  printk("[A] BSS_CHANGED_BEACON_INT beacon_int[%d] dtim_cnt[%d]\n",beacon_interval, (dtim_cnt));
78 #endif
79  val = (beacon_interval<<MTX_BCN_PERIOD_SHIFT)| (dtim_cnt<<MTX_DTIM_NUM_SHIFT);
80  SMAC_REG_WRITE(sc->sh, ADR_MTX_BCN_PRD, val);
81 }
ssv6xxx_beacon_enable(struct ssv_softc * sc,bool bEnable)82 bool ssv6xxx_beacon_enable(struct ssv_softc *sc, bool bEnable)
83 {
84  u32 regval=0;
85  int ret = 0;
86  if(bEnable && !sc->beacon_usage)
87  {
88   printk("[A] Reject to set beacon!!!.        ssv6xxx_beacon_enable bEnable[%d] sc->beacon_usage[%d]\n",bEnable ,sc->beacon_usage);
89         sc->enable_beacon = BEACON_WAITING_ENABLED;
90   return 0;
91  }
92  if((bEnable && (BEACON_ENABLED & sc->enable_beacon))||
93         (!bEnable && !sc->enable_beacon))
94  {
95   printk("[A] ssv6xxx_beacon_enable bEnable[%d] and sc->enable_beacon[%d] are the same. no need to execute.\n",bEnable ,sc->enable_beacon);
96         if(bEnable){
97             printk("        Ignore enable beacon cmd!!!!\n");
98             return 0;
99         }
100  }
101  SMAC_REG_READ(sc->sh, ADR_MTX_BCN_EN_MISC, &regval);
102 #ifdef BEACON_DEBUG
103  printk("[A] ssv6xxx_beacon_enable read misc reg val [%08x]\n", regval);
104 #endif
105  regval &= MTX_BCN_ENABLE_MASK;
106 #ifdef BEACON_DEBUG
107  printk("[A] ssv6xxx_beacon_enable read misc reg val [%08x]\n", regval);
108 #endif
109  regval |= (bEnable<<MTX_BCN_TIMER_EN_SHIFT);
110  ret = SMAC_REG_WRITE(sc->sh, ADR_MTX_BCN_EN_MISC, regval);
111 #ifdef BEACON_DEBUG
112  printk("[A] ssv6xxx_beacon_enable read misc reg val [%08x]\n", regval);
113 #endif
114     sc->enable_beacon = (bEnable==true)?BEACON_ENABLED:0;
115  return ret;
116 }
ssv6xxx_beacon_fill_content(struct ssv_softc * sc,u32 regaddr,u8 * beacon,int size)117 int ssv6xxx_beacon_fill_content(struct ssv_softc *sc, u32 regaddr, u8 *beacon, int size)
118 {
119  u32 i, val;
120  u32 *ptr = (u32*)beacon;
121  size = size/4;
122  for(i=0; i<size; i++)
123  {
124   val = (u32)(*(ptr+i));
125 #ifdef BEACON_DEBUG
126   printk("[%08x] ", val );
127 #endif
128   SMAC_REG_WRITE(sc->sh, regaddr+i*4, val);
129  }
130 #ifdef BEACON_DEBUG
131   printk("\n");
132 #endif
133     return 0;
134 }
ssv6xxx_beacon_fill_tx_desc(struct ssv_softc * sc,struct sk_buff * beacon_skb)135 void ssv6xxx_beacon_fill_tx_desc(struct ssv_softc *sc, struct sk_buff* beacon_skb)
136 {
137  struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(beacon_skb);
138  struct ssv6200_tx_desc *tx_desc;
139  u16 pb_offset = TXPB_OFFSET;
140  struct ssv_rate_info ssv_rate;
141  skb_push(beacon_skb, pb_offset);
142  tx_desc = (struct ssv6200_tx_desc *)beacon_skb->data;
143  memset(tx_desc,0, pb_offset);
144  ssv6xxx_rc_hw_rate_idx(sc, tx_info, &ssv_rate);
145     tx_desc->len = beacon_skb->len-pb_offset;
146  tx_desc->c_type = M2_TXREQ;
147     tx_desc->f80211 = 1;
148  tx_desc->ack_policy = 1;
149     tx_desc->hdr_offset = pb_offset;
150     tx_desc->hdr_len = 24;
151     tx_desc->payload_offset = tx_desc->hdr_offset + tx_desc->hdr_len;
152  tx_desc->crate_idx = ssv_rate.crate_hw_idx;
153  tx_desc->drate_idx = ssv_rate.drate_hw_idx;
154     skb_put(beacon_skb, 4);
155 }
ssv6xxx_beacon_get_valid_reg(struct ssv_softc * sc)156 inline enum ssv6xxx_beacon_type ssv6xxx_beacon_get_valid_reg(struct ssv_softc *sc)
157 {
158  u32 regval =0;
159  SMAC_REG_READ(sc->sh, ADR_MTX_BCN_MISC, &regval);
160  regval &= MTX_BCN_CFG_VLD_MASK;
161  regval = regval >>MTX_BCN_CFG_VLD_SHIFT;
162  if(regval==0x2 || regval == 0x0)
163   return SSV6xxx_BEACON_0;
164  else if(regval==0x1)
165   return SSV6xxx_BEACON_1;
166  else
167   printk("=============>ERROR!!drv_bcn_reg_available\n");
168  return SSV6xxx_BEACON_0;
169 }
ssv6xxx_beacon_set(struct ssv_softc * sc,struct sk_buff * beacon_skb,int dtim_offset)170 bool ssv6xxx_beacon_set(struct ssv_softc *sc, struct sk_buff *beacon_skb, int dtim_offset)
171 {
172  u32 reg_tx_beacon_adr = ADR_MTX_BCN_CFG0;
173  enum ssv6xxx_beacon_type avl_bcn_type = SSV6xxx_BEACON_0;
174  bool ret = true;
175  int val;
176  ssv6xxx_beacon_reg_lock(sc, 1);
177  avl_bcn_type = ssv6xxx_beacon_get_valid_reg(sc);
178  if(avl_bcn_type == SSV6xxx_BEACON_1)
179   reg_tx_beacon_adr = ADR_MTX_BCN_CFG1;
180 #ifdef BEACON_DEBUG
181  printk("[A] ssv6xxx_beacon_set avl_bcn_type[%d]\n", avl_bcn_type);
182 #endif
183  do{
184   if(IS_BIT_SET(sc->beacon_usage, avl_bcn_type))
185   {
186 #ifdef BEACON_DEBUG
187    printk("[A] beacon has already been set old len[%d] new len[%d]\n", sc->beacon_info[avl_bcn_type].len, beacon_skb->len);
188 #endif
189    if (sc->beacon_info[avl_bcn_type].len >= beacon_skb->len)
190    {
191     break;
192    }
193    else
194    {
195     if(false == ssv6xxx_pbuf_free(sc, sc->beacon_info[avl_bcn_type].pubf_addr))
196     {
197 #ifdef BEACON_DEBUG
198      printk("=============>ERROR!!Intend to allcoate beacon from ASIC fail.\n");
199 #endif
200      ret = false;
201      goto out;
202     }
203     CLEAR_BIT(sc->beacon_usage, avl_bcn_type);
204    }
205   }
206   sc->beacon_info[avl_bcn_type].pubf_addr = ssv6xxx_pbuf_alloc(sc, beacon_skb->len, TX_BUF);
207   sc->beacon_info[avl_bcn_type].len = beacon_skb->len;
208   if(sc->beacon_info[avl_bcn_type].pubf_addr == 0)
209   {
210    ret = false;
211    goto out;
212   }
213   SET_BIT(sc->beacon_usage, avl_bcn_type);
214 #ifdef BEACON_DEBUG
215   printk("[A] beacon type[%d] usage[%d] allocate new beacon addr[%08x] \n", avl_bcn_type, sc->beacon_usage, sc->beacon_info[avl_bcn_type].pubf_addr);
216 #endif
217  }while(0);
218  ssv6xxx_beacon_fill_content(sc, sc->beacon_info[avl_bcn_type].pubf_addr, beacon_skb->data, beacon_skb->len);
219  val = (PBUF_MapPkttoID(sc->beacon_info[avl_bcn_type].pubf_addr))|(dtim_offset<<MTX_DTIM_OFST0);
220  SMAC_REG_WRITE(sc->sh, reg_tx_beacon_adr, val);
221 #ifdef BEACON_DEBUG
222  printk("[A] update to register reg_tx_beacon_adr[%08x] val[%08x]\n", reg_tx_beacon_adr, val);
223 #endif
224 out:
225  ssv6xxx_beacon_reg_lock(sc, 0);
226     if(sc->beacon_usage && (sc->enable_beacon&BEACON_WAITING_ENABLED)){
227         printk("[A] enable beacon for BEACON_WAITING_ENABLED flags\n");
228         ssv6xxx_beacon_enable(sc, true);
229     }
230  return ret;
231 }
ssv6xxx_auto_bcn_ongoing(struct ssv_softc * sc)232 inline bool ssv6xxx_auto_bcn_ongoing(struct ssv_softc *sc)
233 {
234  u32 regval;
235  SMAC_REG_READ(sc->sh, ADR_MTX_BCN_MISC, &regval);
236  return ((AUTO_BCN_ONGOING_MASK&regval)>>AUTO_BCN_ONGOING_SHIFT);
237 }
ssv6xxx_beacon_release(struct ssv_softc * sc)238 void ssv6xxx_beacon_release(struct ssv_softc *sc)
239 {
240  int cnt=10;
241  printk("[A] ssv6xxx_beacon_release Enter\n");
242     cancel_work_sync(&sc->set_tim_work);
243  do {
244   if(ssv6xxx_auto_bcn_ongoing(sc))
245    ssv6xxx_beacon_enable(sc, false);
246   else
247    break;
248   cnt--;
249   if(cnt<=0)
250    break;
251  } while(1);
252  if(IS_BIT_SET(sc->beacon_usage, SSV6xxx_BEACON_0))
253  {
254   ssv6xxx_pbuf_free(sc, sc->beacon_info[SSV6xxx_BEACON_0].pubf_addr);
255   CLEAR_BIT(sc->beacon_usage, SSV6xxx_BEACON_0);
256  }
257  if(IS_BIT_SET(sc->beacon_usage, SSV6xxx_BEACON_1))
258  {
259   ssv6xxx_pbuf_free(sc, sc->beacon_info[SSV6xxx_BEACON_1].pubf_addr);
260   CLEAR_BIT(sc->beacon_usage, SSV6xxx_BEACON_1);
261  }
262  sc->enable_beacon = 0;
263     if(sc->beacon_buf){
264         dev_kfree_skb_any(sc->beacon_buf);
265         sc->beacon_buf = NULL;
266     }
267 #ifdef BEACON_DEBUG
268  printk("[A] ssv6xxx_beacon_release leave\n");
269 #endif
270 }
ssv6xxx_beacon_change(struct ssv_softc * sc,struct ieee80211_hw * hw,struct ieee80211_vif * vif,bool aid0_bit_set)271 void ssv6xxx_beacon_change(struct ssv_softc *sc, struct ieee80211_hw *hw, struct ieee80211_vif *vif, bool aid0_bit_set)
272 {
273  struct sk_buff *skb;
274     struct sk_buff *old_skb = NULL;
275  u16 tim_offset, tim_length;
276     if(sc == NULL || hw == NULL || vif == NULL ){
277         printk("[Error]........ssv6xxx_beacon_change input error\n");
278   return;
279     }
280     do{
281      skb = ieee80211_beacon_get_tim(hw, vif,
282        &tim_offset, &tim_length);
283         if(skb == NULL){
284             printk("[Error]........skb is NULL\n");
285             break;
286         }
287      if (tim_offset && tim_length >= 6) {
288       skb->data[tim_offset + 2] = 0;
289       if (aid0_bit_set)
290        skb->data[tim_offset + 4] |= 1;
291       else
292        skb->data[tim_offset + 4] &= ~1;
293      }
294 #ifdef BEACON_DEBUG
295      printk("[A] beacon len [%d] tim_offset[%d]\n", skb->len, tim_offset);
296 #endif
297      ssv6xxx_beacon_fill_tx_desc(sc, skb);
298 #ifdef BEACON_DEBUG
299      printk("[A] beacon len [%d] tim_offset[%d]\n", skb->len, tim_offset);
300 #endif
301         if(sc->beacon_buf)
302         {
303             if(memcmp(sc->beacon_buf->data, skb->data, (skb->len-FCS_LEN)) == 0){
304                 old_skb = skb;
305                 break;
306             }
307             else{
308                  old_skb = sc->beacon_buf;
309                  sc->beacon_buf = skb;
310             }
311         }
312         else{
313             sc->beacon_buf = skb;
314         }
315      tim_offset+=2;
316      if(ssv6xxx_beacon_set(sc, skb, tim_offset))
317      {
318       u8 dtim_cnt = vif->bss_conf.dtim_period-1;
319       if(sc->beacon_dtim_cnt != dtim_cnt)
320       {
321        sc->beacon_dtim_cnt = dtim_cnt;
322 #ifdef BEACON_DEBUG
323                 printk("[A] beacon_dtim_cnt [%d]\n", sc->beacon_dtim_cnt);
324 #endif
325                 ssv6xxx_beacon_set_info(sc, sc->beacon_interval,
326                                                         sc->beacon_dtim_cnt);
327       }
328      }
329     }while(0);
330     if(old_skb)
331      dev_kfree_skb_any(old_skb);
332 }
ssv6200_set_tim_work(struct work_struct * work)333 void ssv6200_set_tim_work(struct work_struct *work)
334 {
335     struct ssv_softc *sc =
336             container_of(work, struct ssv_softc, set_tim_work);
337 #ifdef BROADCAST_DEBUG
338  printk("%s() enter\n", __FUNCTION__);
339 #endif
340  ssv6xxx_beacon_change(sc, sc->hw, sc->ap_vif, sc->aid0_bit_set);
341 #ifdef BROADCAST_DEBUG
342     printk("%s() leave\n", __FUNCTION__);
343 #endif
344 }
ssv6200_bcast_queue_len(struct ssv6xxx_bcast_txq * bcast_txq)345 int ssv6200_bcast_queue_len(struct ssv6xxx_bcast_txq *bcast_txq)
346 {
347  u32 len;
348     unsigned long flags;
349     spin_lock_irqsave(&bcast_txq->txq_lock, flags);
350     len = bcast_txq->cur_qsize;
351     spin_unlock_irqrestore(&bcast_txq->txq_lock, flags);
352     return len;
353 }
ssv6200_bcast_dequeue(struct ssv6xxx_bcast_txq * bcast_txq,u8 * remain_len)354 struct sk_buff* ssv6200_bcast_dequeue(struct ssv6xxx_bcast_txq *bcast_txq, u8 *remain_len)
355 {
356     struct sk_buff *skb = NULL;
357     unsigned long flags;
358     spin_lock_irqsave(&bcast_txq->txq_lock, flags);
359     if(bcast_txq->cur_qsize){
360         bcast_txq->cur_qsize --;
361         if(remain_len)
362             *remain_len = bcast_txq->cur_qsize;
363         skb = __skb_dequeue(&bcast_txq->qhead);
364     }
365     spin_unlock_irqrestore(&bcast_txq->txq_lock, flags);
366     return skb;
367 }
ssv6200_bcast_enqueue(struct ssv_softc * sc,struct ssv6xxx_bcast_txq * bcast_txq,struct sk_buff * skb)368 int ssv6200_bcast_enqueue(struct ssv_softc *sc, struct ssv6xxx_bcast_txq *bcast_txq,
369                                                         struct sk_buff *skb)
370 {
371     unsigned long flags;
372     spin_lock_irqsave(&bcast_txq->txq_lock, flags);
373     if (bcast_txq->cur_qsize >=
374                     SSV6200_MAX_BCAST_QUEUE_LEN){
375         struct sk_buff *old_skb;
376   old_skb = __skb_dequeue(&bcast_txq->qhead);
377         bcast_txq->cur_qsize --;
378         ssv6xxx_txbuf_free_skb(old_skb, (void*)sc);
379         printk("[B] ssv6200_bcast_enqueue - remove oldest queue\n");
380     }
381     __skb_queue_tail(&bcast_txq->qhead, skb);
382     bcast_txq->cur_qsize ++;
383     spin_unlock_irqrestore(&bcast_txq->txq_lock, flags);
384     return bcast_txq->cur_qsize;
385 }
ssv6200_bcast_flush(struct ssv_softc * sc,struct ssv6xxx_bcast_txq * bcast_txq)386 void ssv6200_bcast_flush(struct ssv_softc *sc, struct ssv6xxx_bcast_txq *bcast_txq)
387 {
388     struct sk_buff *skb;
389     unsigned long flags;
390 #ifdef BCAST_DEBUG
391     printk("ssv6200_bcast_flush\n");
392 #endif
393     spin_lock_irqsave(&bcast_txq->txq_lock, flags);
394     while(bcast_txq->cur_qsize > 0) {
395         skb = __skb_dequeue(&bcast_txq->qhead);
396         bcast_txq->cur_qsize --;
397         ssv6xxx_txbuf_free_skb(skb, (void*)sc);
398     }
399     spin_unlock_irqrestore(&bcast_txq->txq_lock, flags);
400 }
401 static int queue_block_cnt = 0;
ssv6200_bcast_tx_work(struct work_struct * work)402 void ssv6200_bcast_tx_work(struct work_struct *work)
403 {
404     struct ssv_softc *sc =
405             container_of(work, struct ssv_softc, bcast_tx_work.work);
406 #if 1
407     struct sk_buff* skb;
408     int i;
409     u8 remain_size;
410 #endif
411     unsigned long flags;
412     bool needtimer = true;
413     long tmo = sc->bcast_interval;
414     spin_lock_irqsave(&sc->ps_state_lock, flags);
415     do{
416 #ifdef BCAST_DEBUG
417         printk("[B] bcast_timer: hw_mng_used[%d] HCI_TXQ_EMPTY[%d] bcast_queue_len[%d].....................\n",
418                sc->hw_mng_used, HCI_TXQ_EMPTY(sc->sh, 4), ssv6200_bcast_queue_len(&sc->bcast_txq));
419 #endif
420         if(sc->hw_mng_used != 0 ||
421             false == HCI_TXQ_EMPTY(sc->sh, 4)){
422 #ifdef BCAST_DEBUG
423             printk("HW queue still have frames insdide. skip this one hw_mng_used[%d] bEmptyTXQ4[%d]\n",
424                 sc->hw_mng_used, HCI_TXQ_EMPTY(sc->sh, 4));
425 #endif
426             queue_block_cnt++;
427             if(queue_block_cnt>5){
428                 queue_block_cnt = 0;
429                 ssv6200_bcast_flush(sc, &sc->bcast_txq);
430                 needtimer = false;
431             }
432             break;
433         }
434         queue_block_cnt = 0;
435         for(i=0;i<SSV6200_ID_MANAGER_QUEUE;i++){
436             skb = ssv6200_bcast_dequeue(&sc->bcast_txq, &remain_size);
437             if(!skb){
438                 needtimer = false;
439                 break;
440             }
441             if( (0 != remain_size) &&
442                 (SSV6200_ID_MANAGER_QUEUE-1) != i ){
443                 struct ieee80211_hdr *hdr;
444                 struct ssv6200_tx_desc *tx_desc = (struct ssv6200_tx_desc *)skb->data;
445                 hdr = (struct ieee80211_hdr *) ((u8*)tx_desc+tx_desc->hdr_offset);
446                 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
447             }
448 #ifdef BCAST_DEBUG
449             printk("[B] bcast_timer:tx remain_size[%d] i[%d]\n", remain_size, i);
450 #endif
451    spin_unlock_irqrestore(&sc->ps_state_lock, flags);
452             if(HCI_SEND(sc->sh, skb, 4)<0){
453                 printk("bcast_timer send fail!!!!!!! \n");
454                 ssv6xxx_txbuf_free_skb(skb, (void*)sc);
455                 BUG_ON(1);
456             }
457    spin_lock_irqsave(&sc->ps_state_lock, flags);
458         }
459     }while(0);
460     if(needtimer){
461 #ifdef BCAST_DEBUG
462         printk("[B] bcast_timer:need more timer to tx bcast frame time[%d]\n", sc->bcast_interval);
463 #endif
464         queue_delayed_work(sc->config_wq,
465        &sc->bcast_tx_work,
466        tmo);
467     }
468     else{
469 #ifdef BCAST_DEBUG
470        printk("[B] bcast_timer: ssv6200_bcast_stop\n");
471 #endif
472        ssv6200_bcast_stop(sc);
473     }
474     spin_unlock_irqrestore(&sc->ps_state_lock, flags);
475 #ifdef BCAST_DEBUG
476     printk("[B] bcast_timer: leave.....................\n");
477 #endif
478 }
ssv6200_bcast_start_work(struct work_struct * work)479 void ssv6200_bcast_start_work(struct work_struct *work)
480 {
481  struct ssv_softc *sc =
482   container_of(work, struct ssv_softc, bcast_start_work);
483 #ifdef BCAST_DEBUG
484     printk("[B] ssv6200_bcast_start_work==\n");
485 #endif
486     sc->bcast_interval = (sc->beacon_dtim_cnt+1) *
487    (sc->beacon_interval + 20) * HZ / 1000;
488  if (!sc->aid0_bit_set) {
489   sc->aid0_bit_set = true;
490   ssv6xxx_beacon_change(sc, sc->hw,
491                         sc->ap_vif, sc->aid0_bit_set);
492         queue_delayed_work(sc->config_wq,
493        &sc->bcast_tx_work,
494        sc->bcast_interval);
495 #ifdef BCAST_DEBUG
496         printk("[B] bcast_start_work: Modify timer to DTIM[%d]ms==\n",
497                (sc->beacon_dtim_cnt+1)*(sc->beacon_interval + 20));
498 #endif
499  }
500 }
ssv6200_bcast_stop_work(struct work_struct * work)501 void ssv6200_bcast_stop_work(struct work_struct *work)
502 {
503  struct ssv_softc *sc =
504   container_of(work, struct ssv_softc, bcast_stop_work.work);
505     long tmo = HZ / 100;
506 #ifdef BCAST_DEBUG
507     printk("[B] ssv6200_bcast_stop_work\n");
508 #endif
509  if (sc->aid0_bit_set) {
510         if(0== ssv6200_bcast_queue_len(&sc->bcast_txq)){
511             cancel_delayed_work_sync(&sc->bcast_tx_work);
512       sc->aid0_bit_set = false;
513       ssv6xxx_beacon_change(sc, sc->hw,
514                             sc->ap_vif, sc->aid0_bit_set);
515 #ifdef BCAST_DEBUG
516             printk("remove group bit in DTIM\n");
517 #endif
518         }
519         else{
520 #ifdef BCAST_DEBUG
521             printk("bcast_stop_work: bcast queue still have data. just modify timer to 10ms\n");
522 #endif
523             queue_delayed_work(sc->config_wq,
524        &sc->bcast_tx_work,
525        tmo);
526         }
527  }
528 }
ssv6200_bcast_stop(struct ssv_softc * sc)529 void ssv6200_bcast_stop(struct ssv_softc *sc)
530 {
531     queue_delayed_work(sc->config_wq,
532          &sc->bcast_stop_work, sc->beacon_interval*HZ/1024);
533 }
ssv6200_bcast_start(struct ssv_softc * sc)534 void ssv6200_bcast_start(struct ssv_softc *sc)
535 {
536     queue_work(sc->config_wq, &sc->bcast_start_work);
537 }
ssv6200_release_bcast_frame_res(struct ssv_softc * sc,struct ieee80211_vif * vif)538 void ssv6200_release_bcast_frame_res(struct ssv_softc *sc, struct ieee80211_vif *vif)
539 {
540     unsigned long flags;
541     struct ssv_vif_priv_data *priv_vif = (struct ssv_vif_priv_data *)vif->drv_priv;
542     spin_lock_irqsave(&sc->ps_state_lock, flags);
543     priv_vif->sta_asleep_mask = 0;
544     spin_unlock_irqrestore(&sc->ps_state_lock, flags);
545     cancel_work_sync(&sc->bcast_start_work);
546     cancel_delayed_work_sync(&sc->bcast_stop_work);
547     ssv6200_bcast_flush(sc, &sc->bcast_txq);
548     cancel_delayed_work_sync(&sc->bcast_tx_work);
549 }
550