PM / sleep: Asynchronous threads for suspend_noirq
[linux/fpc-iii.git] / drivers / staging / bcm / HandleControlPacket.c
blob495fe3dc514874b5b57f2773f2516a62d3046bff
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"
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
14 static VOID handle_rx_control_packet(struct bcm_mini_adapter *Adapter, struct sk_buff *skb)
16 struct bcm_tarang_data *pTarang = NULL;
17 bool HighPriorityMessage = false;
18 struct sk_buff *newPacket = NULL;
19 CHAR cntrl_msg_mask_bit = 0;
20 bool drop_pkt_flag = TRUE;
21 USHORT usStatus = *(PUSHORT)(skb->data);
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);
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;
61 case AUTH_SS_HOST_MSG:
62 HighPriorityMessage = TRUE;
63 break;
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;
72 /* Queue The Control Packet to The Application Queues */
73 down(&Adapter->RxAppControlQueuelock);
75 for (pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next) {
76 if (Adapter->device_removed)
77 break;
79 drop_pkt_flag = TRUE;
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.
88 cntrl_msg_mask_bit = (usStatus & 0x1F);
90 * printk("\ninew msg mask bit which is disable in mask:%X",
91 * cntrl_msg_mask_bit);
93 if (pTarang->RxCntrlMsgBitMask & (1 << cntrl_msg_mask_bit))
94 drop_pkt_flag = false;
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))) {
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.
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;
136 continue;
139 newPacket = skb_clone(skb, GFP_KERNEL);
140 if (!newPacket)
141 break;
142 ENQUEUEPACKET(pTarang->RxAppControlHead,
143 pTarang->RxAppControlTail, newPacket);
144 pTarang->AppCtrlQueueLen++;
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");
154 * @ingroup ctrl_pkt_functions
155 * Thread to handle control pkt reception
157 int control_packet_handler(struct bcm_mini_adapter *Adapter /* pointer to adapter object*/)
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());
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;
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");
186 * Adapter->bTriedToWakeUpFromlowPowerMode
187 * = TRUE;
189 InterfaceIdleModeWakeup(Adapter);
191 continue;
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; */
203 spin_unlock_irqrestore(&Adapter->control_queue_lock,
204 flags);
205 handle_rx_control_packet(Adapter, ctrl_packet);
206 atomic_dec(&Adapter->cntrlpktCnt);
209 SetUpTargetDsxBuffers(Adapter);
211 return STATUS_SUCCESS;
214 INT flushAllAppQ(void)
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);
226 pTarang->AppCtrlQueueLen = 0;
227 /* dropped contrl packet statistics also should be reset. */
228 memset((PVOID)&pTarang->stDroppedAppCntrlMsgs, 0,
229 sizeof(struct bcm_mibs_dropped_cntrl_msg));
232 return STATUS_SUCCESS;