Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / drivers / staging / bcm / HandleControlPacket.c
1 /**
2 @file HandleControlPacket.c
3 This file contains the routines to deal with
4 sending and receiving of control packets.
5 */
6 #include "headers.h"
7
8 /**
9 When a control packet is received, analyze the
10 "status" and call appropriate response function.
11 Enqueue the control packet for Application.
12 @return None
13 */
14 VOID handle_rx_control_packet(PMINI_ADAPTER Adapter,    /**<Pointer to the Adapter structure*/
15                                                                 struct sk_buff *skb)                            /**<Pointer to the socket buffer*/
16 {
17         PPER_TARANG_DATA        pTarang = NULL;
18         BOOLEAN HighPriorityMessage = FALSE;
19         struct sk_buff * newPacket = NULL;
20         CHAR cntrl_msg_mask_bit = 0;
21         BOOLEAN drop_pkt_flag = TRUE ;
22         USHORT usStatus = *(PUSHORT)(skb->data);
23         BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "=====>");
24         /* Get the Leader field */
25
26         switch(usStatus)
27         {
28                 case CM_RESPONSES:               // 0xA0
29                         BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "MAC Version Seems to be Non Multi-Classifier, rejected by Driver");
30                         HighPriorityMessage = TRUE ;
31                         break;
32                 case CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP:
33                         HighPriorityMessage = TRUE ;
34                         if(Adapter->LinkStatus==LINKUP_DONE)
35                         {
36                                 CmControlResponseMessage(Adapter,(skb->data +sizeof(USHORT)));
37                         }
38                         break;
39                 case LINK_CONTROL_RESP:          //0xA2
40                 case STATUS_RSP:          //0xA1
41                         BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,"LINK_CONTROL_RESP");
42                         HighPriorityMessage = TRUE ;
43                         LinkControlResponseMessage(Adapter,(skb->data + sizeof(USHORT)));
44                         break;
45                 case STATS_POINTER_RESP:       //0xA6
46                         HighPriorityMessage = TRUE ;
47                         StatisticsResponse(Adapter, (skb->data + sizeof(USHORT)));
48                         break;
49                 case IDLE_MODE_STATUS:                  //0xA3
50                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,"IDLE_MODE_STATUS Type Message Got from F/W");
51                         InterfaceIdleModeRespond(Adapter, (PUINT)(skb->data +
52                                                 sizeof(USHORT)));
53                         HighPriorityMessage = TRUE ;
54                         break;
55
56                 case AUTH_SS_HOST_MSG:
57                         HighPriorityMessage = TRUE ;
58                         break;
59
60                 default:
61                         BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,"Got Default Response");
62                         /* Let the Application Deal with This Packet */
63                         break;
64         }
65
66         //Queue The Control Packet to The Application Queues
67         down(&Adapter->RxAppControlQueuelock);
68
69         for (pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next)
70     {
71         if(Adapter->device_removed)
72                 {
73                         break;
74                 }
75
76                 drop_pkt_flag = TRUE ;
77                 /*
78                         There are cntrl msg from A0 to AC. It has been mapped to 0 to C bit in the cntrl mask.
79                         Also, by default AD to BF has been masked to the rest of the bits... which wil be ON by default.
80                         if mask bit is enable to particular pkt status, send it out to app else stop it.
81                 */
82                 cntrl_msg_mask_bit = (usStatus & 0x1F);
83                 //printk("\ninew  msg  mask bit which is disable in mask:%X", cntrl_msg_mask_bit);
84                 if(pTarang->RxCntrlMsgBitMask & (1<<cntrl_msg_mask_bit))
85                                 drop_pkt_flag = FALSE;
86
87                 if ((drop_pkt_flag == TRUE)  || (pTarang->AppCtrlQueueLen > MAX_APP_QUEUE_LEN) ||
88                                         ((pTarang->AppCtrlQueueLen > MAX_APP_QUEUE_LEN/2) && (HighPriorityMessage == FALSE)))
89                 {
90                         /*
91                                 Assumption:-
92                                 1. every tarang manages it own dropped pkt statitistics
93                                 2. Total packet dropped per tarang will be equal to the sum of all types of dropped
94                                         pkt by that tarang only.
95
96                         */
97                         switch(*(PUSHORT)skb->data)
98                         {
99                                 case CM_RESPONSES:
100                                         pTarang->stDroppedAppCntrlMsgs.cm_responses++;
101                                         break;
102                                 case CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP:
103                                  pTarang->stDroppedAppCntrlMsgs.cm_control_newdsx_multiclassifier_resp++;
104                                          break;
105                                 case LINK_CONTROL_RESP:
106                                         pTarang->stDroppedAppCntrlMsgs.link_control_resp++;
107                                         break;
108                                 case STATUS_RSP:
109                                         pTarang->stDroppedAppCntrlMsgs.status_rsp++;
110                                         break;
111                                 case STATS_POINTER_RESP:
112                                         pTarang->stDroppedAppCntrlMsgs.stats_pointer_resp++;
113                                         break;
114                                 case IDLE_MODE_STATUS:
115                                         pTarang->stDroppedAppCntrlMsgs.idle_mode_status++ ;
116                                         break;
117                                 case AUTH_SS_HOST_MSG:
118                                         pTarang->stDroppedAppCntrlMsgs.auth_ss_host_msg++ ;
119                                         break;
120                         default:
121                                         pTarang->stDroppedAppCntrlMsgs.low_priority_message++ ;
122                                         break;
123                         }
124
125                         continue;
126                 }
127
128         newPacket = skb_clone(skb, GFP_KERNEL);
129         if (!newPacket)
130            break;
131         ENQUEUEPACKET(pTarang->RxAppControlHead,pTarang->RxAppControlTail,
132                                 newPacket);
133         pTarang->AppCtrlQueueLen++;
134     }
135         up(&Adapter->RxAppControlQueuelock);
136     wake_up(&Adapter->process_read_wait_queue);
137     bcm_kfree_skb(skb);
138         BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "After wake_up_interruptible");
139 }
140
141 /**
142 @ingroup ctrl_pkt_functions
143 Thread to handle control pkt reception
144 */
145 int control_packet_handler  (PMINI_ADAPTER Adapter  /**< pointer to adapter object*/
146                                                 )
147 {
148         struct sk_buff *ctrl_packet= NULL;
149         unsigned long flags = 0;
150         //struct timeval tv ;
151         //int *puiBuffer = NULL ;
152         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "Entering to make thread wait on control packet event!");
153         while(1)
154         {
155                 wait_event_interruptible(Adapter->process_rx_cntrlpkt,
156                                                                  atomic_read(&Adapter->cntrlpktCnt) ||
157                                                                  Adapter->bWakeUpDevice ||
158                                                                  kthread_should_stop()
159                                                                 );
160
161
162                 if(kthread_should_stop())
163                 {
164                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "Exiting \n");
165                         return 0;
166                 }
167                 if(TRUE == Adapter->bWakeUpDevice)
168                 {
169                         Adapter->bWakeUpDevice = FALSE;
170                         if((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) &&
171                                 ((TRUE == Adapter->IdleMode)|| (TRUE == Adapter->bShutStatus)))
172                         {
173                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "Calling InterfaceAbortIdlemode\n");
174         //                      Adapter->bTriedToWakeUpFromlowPowerMode = TRUE;
175                                 InterfaceIdleModeWakeup (Adapter);
176                         }
177                         continue;
178                 }
179
180                 while(atomic_read(&Adapter->cntrlpktCnt))
181                 {
182                         spin_lock_irqsave(&Adapter->control_queue_lock, flags);
183                         ctrl_packet = Adapter->RxControlHead;
184                         if(ctrl_packet)
185                         {
186                                 DEQUEUEPACKET(Adapter->RxControlHead,Adapter->RxControlTail);
187 //                              Adapter->RxControlHead=ctrl_packet->next;
188                                 ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.rx_packets++;
189                                 ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.rx_bytes+=
190                                 ((PLEADER)ctrl_packet->data)->PLength;
191                         }
192                         #if 0  //Idle mode debug profiling...
193                         if(*(PUSHORT)ctrl_packet->data == IDLE_MODE_STATUS)
194                         {
195                                 puiBuffer = (PUINT)(ctrl_packet->data +sizeof(USHORT));
196                                 if((ntohl(*puiBuffer) == GO_TO_IDLE_MODE_PAYLOAD))
197                                 {
198                                         memset(&tv, 0, sizeof(tv));
199                                         do_gettimeofday(&tv);
200                                         if((ntohl(*(puiBuffer+1)) == 0))
201                                         {
202                                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "IdleMode Wake-up Msg from f/w at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000);
203                                         }
204                                         else
205                                         {
206                                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "IdleMode req Msg from f/w at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000);
207                                         }
208                                 }
209                                 else if((ntohl(*puiBuffer) == IDLE_MODE_SF_UPDATE_MSG))
210                                 {
211                                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "GOT IDLE_MODE_SF_UPDATE MSG at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000);
212                                 }
213                         }
214                         #endif
215
216                         spin_unlock_irqrestore (&Adapter->control_queue_lock, flags);
217                         handle_rx_control_packet(Adapter, ctrl_packet);
218                         atomic_dec(&Adapter->cntrlpktCnt);
219                 }
220
221                 SetUpTargetDsxBuffers(Adapter);
222         }
223         return STATUS_SUCCESS;
224 }
225
226 INT flushAllAppQ(void)
227 {
228         PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
229         PPER_TARANG_DATA        pTarang = NULL;
230         struct sk_buff *PacketToDrop = NULL;
231         for(pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next)
232         {
233                 while(pTarang->RxAppControlHead != NULL)
234                 {
235                         PacketToDrop=pTarang->RxAppControlHead;
236                         DEQUEUEPACKET(pTarang->RxAppControlHead,pTarang->RxAppControlTail);
237                         bcm_kfree_skb(PacketToDrop);
238                 }
239                 pTarang->AppCtrlQueueLen = 0;
240                 //dropped contrl packet statistics also should be reset.
241                 memset((PVOID)&pTarang->stDroppedAppCntrlMsgs, 0, sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES));
242
243         }
244         return STATUS_SUCCESS ;
245 }
246
247