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