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