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  */
handle_rx_control_packet(PMINI_ADAPTER Adapter,struct sk_buff * skb)14 static VOID handle_rx_control_packet(PMINI_ADAPTER Adapter, struct sk_buff *skb)
15 {
16 	PPER_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  */
control_packet_handler(PMINI_ADAPTER Adapter)157 int control_packet_handler(PMINI_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 
flushAllAppQ(void)214 INT flushAllAppQ(void)
215 {
216 	PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
217 	PPER_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 
236