• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "headers.h"
2 
3 static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,
4 					    B_UINT16 uiClsId,
5 					    struct bcm_phs_table *psServiceFlowTable,
6 					    struct bcm_phs_rule *psPhsRule,
7 					    B_UINT8 u8AssociatedPHSI);
8 
9 static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,
10 					    B_UINT16  uiClsId,
11 					    struct bcm_phs_entry *pstServiceFlowEntry,
12 					    struct bcm_phs_rule *psPhsRule,
13 					    B_UINT8 u8AssociatedPHSI);
14 
15 static UINT CreateClassifierPHSRule(B_UINT16  uiClsId,
16 				    struct bcm_phs_classifier_table *psaClassifiertable,
17 				    struct bcm_phs_rule *psPhsRule,
18 				    enum bcm_phs_classifier_context eClsContext,
19 				    B_UINT8 u8AssociatedPHSI);
20 
21 static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId,
22 				    struct bcm_phs_classifier_entry *pstClassifierEntry,
23 				    struct bcm_phs_classifier_table *psaClassifiertable,
24 				    struct bcm_phs_rule *psPhsRule,
25 				    B_UINT8 u8AssociatedPHSI);
26 
27 static bool ValidatePHSRuleComplete(const struct bcm_phs_rule *psPhsRule);
28 
29 static bool DerefPhsRule(B_UINT16 uiClsId,
30 			 struct bcm_phs_classifier_table *psaClassifiertable,
31 			 struct bcm_phs_rule *pstPhsRule);
32 
33 static UINT GetClassifierEntry(struct bcm_phs_classifier_table *pstClassifierTable,
34 			       B_UINT32 uiClsid,
35 			       enum bcm_phs_classifier_context eClsContext,
36 			       struct bcm_phs_classifier_entry **ppstClassifierEntry);
37 
38 static UINT GetPhsRuleEntry(struct bcm_phs_classifier_table *pstClassifierTable,
39 			    B_UINT32 uiPHSI,
40 			    enum bcm_phs_classifier_context eClsContext,
41 			    struct bcm_phs_rule **ppstPhsRule);
42 
43 static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable);
44 
45 static int phs_compress(struct bcm_phs_rule *phs_members,
46 			unsigned char *in_buf,
47 			unsigned char *out_buf,
48 			unsigned int *header_size,
49 			UINT *new_header_size);
50 
51 static int verify_suppress_phsf(unsigned char *in_buffer,
52 				unsigned char *out_buffer,
53 				unsigned char *phsf,
54 				unsigned char *phsm,
55 				unsigned int phss,
56 				unsigned int phsv,
57 				UINT *new_header_size);
58 
59 static int phs_decompress(unsigned char *in_buf,
60 			  unsigned char *out_buf,
61 			  struct bcm_phs_rule *phs_rules,
62 			  UINT *header_size);
63 
64 static ULONG PhsCompress(void *pvContext,
65 			 B_UINT16 uiVcid,
66 			 B_UINT16 uiClsId,
67 			 void *pvInputBuffer,
68 			 void *pvOutputBuffer,
69 			 UINT *pOldHeaderSize,
70 			 UINT *pNewHeaderSize);
71 
72 static ULONG PhsDeCompress(void *pvContext,
73 			   B_UINT16 uiVcid,
74 			   void *pvInputBuffer,
75 			   void *pvOutputBuffer,
76 			   UINT *pInHeaderSize,
77 			   UINT *pOutHeaderSize);
78 
79 #define IN
80 #define OUT
81 
82 /*
83  * Function: PHSTransmit
84  * Description:	This routine handle PHS(Payload Header Suppression for Tx path.
85  *	It extracts a fragment of the NDIS_PACKET containing the header
86  *	to be suppressed. It then suppresses the header by invoking PHS exported compress routine.
87  *	The header data after suppression is copied back to the NDIS_PACKET.
88  *
89  * Input parameters: IN struct bcm_mini_adapter *Adapter         - Miniport Adapter Context
90  *	IN Packet - NDIS packet containing data to be transmitted
91  *	IN USHORT Vcid - vcid pertaining to connection on which the packet is being sent.Used to
92  *		identify PHS rule to be applied.
93  *	B_UINT16 uiClassifierRuleID - Classifier Rule ID
94  *	BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF.
95  *
96  * Return:	STATUS_SUCCESS - If the send was successful.
97  *	Other  - If an error occurred.
98  */
99 
PHSTransmit(struct bcm_mini_adapter * Adapter,struct sk_buff ** pPacket,USHORT Vcid,B_UINT16 uiClassifierRuleID,bool bHeaderSuppressionEnabled,UINT * PacketLen,UCHAR bEthCSSupport)100 int PHSTransmit(struct bcm_mini_adapter *Adapter,
101 		struct sk_buff **pPacket,
102 		USHORT Vcid,
103 		B_UINT16 uiClassifierRuleID,
104 		bool bHeaderSuppressionEnabled,
105 		UINT *PacketLen,
106 		UCHAR bEthCSSupport)
107 {
108 	/* PHS Sepcific */
109 	UINT unPHSPktHdrBytesCopied = 0;
110 	UINT unPhsOldHdrSize = 0;
111 	UINT unPHSNewPktHeaderLen = 0;
112 	/* Pointer to PHS IN Hdr Buffer */
113 	PUCHAR pucPHSPktHdrInBuf =
114 		Adapter->stPhsTxContextInfo.ucaHdrSuppressionInBuf;
115 	/* Pointer to PHS OUT Hdr Buffer */
116 	PUCHAR pucPHSPktHdrOutBuf =
117 		Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf;
118 	UINT usPacketType;
119 	UINT BytesToRemove = 0;
120 	bool bPHSI = 0;
121 	LONG ulPhsStatus = 0;
122 	UINT numBytesCompressed = 0;
123 	struct sk_buff *newPacket = NULL;
124 	struct sk_buff *Packet = *pPacket;
125 
126 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
127 			"In PHSTransmit");
128 
129 	if (!bEthCSSupport)
130 		BytesToRemove = ETH_HLEN;
131 	/*
132 	 * Accumulate the header upto the size we support suppression
133 	 * from NDIS packet
134 	 */
135 
136 	usPacketType = ((struct ethhdr *)(Packet->data))->h_proto;
137 
138 	pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
139 	/* considering data after ethernet header */
140 	if ((*PacketLen - BytesToRemove) < MAX_PHS_LENGTHS)
141 		unPHSPktHdrBytesCopied = (*PacketLen - BytesToRemove);
142 	else
143 		unPHSPktHdrBytesCopied = MAX_PHS_LENGTHS;
144 
145 	if ((unPHSPktHdrBytesCopied > 0) &&
146 		(unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS)) {
147 
148 		/*
149 		 * Step 2 Suppress Header using PHS and fill into intermediate
150 		 * ucaPHSPktHdrOutBuf.
151 		 * Suppress only if IP Header and PHS Enabled For the
152 		 * Service Flow
153 		 */
154 		if (((usPacketType == ETHERNET_FRAMETYPE_IPV4) ||
155 				(usPacketType == ETHERNET_FRAMETYPE_IPV6)) &&
156 			(bHeaderSuppressionEnabled)) {
157 
158 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND,
159 					DBG_LVL_ALL,
160 					"\nTrying to PHS Compress Using Classifier rule 0x%X",
161 					uiClassifierRuleID);
162 			unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied;
163 			ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext,
164 						  Vcid,
165 						  uiClassifierRuleID,
166 						  pucPHSPktHdrInBuf,
167 						  pucPHSPktHdrOutBuf,
168 						  &unPhsOldHdrSize,
169 						  &unPHSNewPktHeaderLen);
170 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND,
171 					DBG_LVL_ALL,
172 					"\nPHS Old header Size : %d New Header Size  %d\n",
173 					unPhsOldHdrSize, unPHSNewPktHeaderLen);
174 
175 			if (unPHSNewPktHeaderLen == unPhsOldHdrSize) {
176 
177 				if (ulPhsStatus == STATUS_PHS_COMPRESSED)
178 					bPHSI = *pucPHSPktHdrOutBuf;
179 
180 				ulPhsStatus = STATUS_PHS_NOCOMPRESSION;
181 			}
182 
183 			if (ulPhsStatus == STATUS_PHS_COMPRESSED) {
184 
185 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
186 						PHS_SEND, DBG_LVL_ALL,
187 						"PHS Sending packet Compressed");
188 
189 				if (skb_cloned(Packet)) {
190 					newPacket =
191 						skb_copy(Packet, GFP_ATOMIC);
192 
193 					if (newPacket == NULL)
194 						return STATUS_FAILURE;
195 
196 					dev_kfree_skb(Packet);
197 					*pPacket = Packet = newPacket;
198 					pucPHSPktHdrInBuf =
199 						Packet->data + BytesToRemove;
200 				}
201 
202 				numBytesCompressed = unPhsOldHdrSize -
203 					(unPHSNewPktHeaderLen + PHSI_LEN);
204 
205 				memcpy(pucPHSPktHdrInBuf + numBytesCompressed,
206 				       pucPHSPktHdrOutBuf,
207 				       unPHSNewPktHeaderLen + PHSI_LEN);
208 				memcpy(Packet->data + numBytesCompressed,
209 				       Packet->data, BytesToRemove);
210 				skb_pull(Packet, numBytesCompressed);
211 
212 				return STATUS_SUCCESS;
213 			} else {
214 				/* if one byte headroom is not available,
215 				 * increase it through skb_cow
216 				 */
217 				if (!(skb_headroom(Packet) > 0)) {
218 
219 					if (skb_cow(Packet, 1)) {
220 						BCM_DEBUG_PRINT(Adapter,
221 								DBG_TYPE_PRINTK,
222 								0, 0,
223 								"SKB Cow Failed\n");
224 						return STATUS_FAILURE;
225 					}
226 				}
227 				skb_push(Packet, 1);
228 
229 				/*
230 				 * CAUTION: The MAC Header is getting corrupted
231 				 * here for IP CS - can be saved by copying 14
232 				 * Bytes.  not needed .... hence corrupting it.
233 				 */
234 				*(Packet->data + BytesToRemove) = bPHSI;
235 				return STATUS_SUCCESS;
236 			}
237 		} else {
238 
239 			if (!bHeaderSuppressionEnabled)
240 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
241 						PHS_SEND, DBG_LVL_ALL,
242 						"\nHeader Suppression Disabled For SF: No PHS\n");
243 
244 			return STATUS_SUCCESS;
245 		}
246 	}
247 
248 	/* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
249 	 * "PHSTransmit : Dumping data packet After PHS"); */
250 	return STATUS_SUCCESS;
251 }
252 
PHSReceive(struct bcm_mini_adapter * Adapter,USHORT usVcid,struct sk_buff * packet,UINT * punPacketLen,UCHAR * pucEthernetHdr,UINT bHeaderSuppressionEnabled)253 int PHSReceive(struct bcm_mini_adapter *Adapter,
254 	       USHORT usVcid,
255 	       struct sk_buff *packet,
256 	       UINT *punPacketLen,
257 	       UCHAR *pucEthernetHdr,
258 	       UINT bHeaderSuppressionEnabled)
259 {
260 	u32 nStandardPktHdrLen = 0;
261 	u32 nTotalsuppressedPktHdrBytes = 0;
262 	int ulPhsStatus	= 0;
263 	PUCHAR pucInBuff = NULL;
264 	UINT TotalBytesAdded = 0;
265 
266 	if (!bHeaderSuppressionEnabled) {
267 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
268 				DBG_LVL_ALL,
269 				"\nPhs Disabled for incoming packet");
270 		return ulPhsStatus;
271 	}
272 
273 	pucInBuff = packet->data;
274 
275 	/* Restore PHS suppressed header */
276 	nStandardPktHdrLen = packet->len;
277 	ulPhsStatus = PhsDeCompress(&Adapter->stBCMPhsContext,
278 				    usVcid,
279 				    pucInBuff,
280 				    Adapter->ucaPHSPktRestoreBuf,
281 				    &nTotalsuppressedPktHdrBytes,
282 				    &nStandardPktHdrLen);
283 
284 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
285 			"\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
286 			nTotalsuppressedPktHdrBytes, nStandardPktHdrLen);
287 
288 	if (ulPhsStatus != STATUS_PHS_COMPRESSED) {
289 		skb_pull(packet, 1);
290 		return STATUS_SUCCESS;
291 	} else {
292 		TotalBytesAdded = nStandardPktHdrLen -
293 			nTotalsuppressedPktHdrBytes - PHSI_LEN;
294 
295 		if (TotalBytesAdded) {
296 			if (skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded))
297 				skb_push(packet, TotalBytesAdded);
298 			else {
299 				if (skb_cow(packet, skb_headroom(packet) + TotalBytesAdded)) {
300 					BCM_DEBUG_PRINT(Adapter,
301 							DBG_TYPE_PRINTK, 0, 0,
302 							"cow failed in receive\n");
303 					return STATUS_FAILURE;
304 				}
305 
306 				skb_push(packet, TotalBytesAdded);
307 			}
308 		}
309 
310 		memcpy(packet->data, Adapter->ucaPHSPktRestoreBuf,
311 		       nStandardPktHdrLen);
312 	}
313 
314 	return STATUS_SUCCESS;
315 }
316 
DumpFullPacket(UCHAR * pBuf,UINT nPktLen)317 void DumpFullPacket(UCHAR *pBuf, UINT nPktLen)
318 {
319 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
320 
321 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,
322 			"Dumping Data Packet");
323 	BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,
324 			       pBuf, nPktLen);
325 }
326 
327 /*
328  * Procedure:   phs_init
329  *
330  * Description: This routine is responsible for allocating memory for classifier
331  * and PHS rules.
332  *
333  * Arguments:
334  * pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules
335  * and PHS Rules , RX, TX buffer etc
336  *
337  * Returns:
338  * TRUE(1)	-If allocation of memory was successful.
339  * FALSE	-If allocation of memory fails.
340  */
phs_init(struct bcm_phs_extension * pPhsdeviceExtension,struct bcm_mini_adapter * Adapter)341 int phs_init(struct bcm_phs_extension *pPhsdeviceExtension,
342 	     struct bcm_mini_adapter *Adapter)
343 {
344 	int i;
345 	struct bcm_phs_table *pstServiceFlowTable;
346 
347 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
348 			"\nPHS:phs_init function");
349 
350 	if (pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
351 		return -EINVAL;
352 
353 	pPhsdeviceExtension->pstServiceFlowPhsRulesTable =
354 		kzalloc(sizeof(struct bcm_phs_table), GFP_KERNEL);
355 
356 	if (!pPhsdeviceExtension->pstServiceFlowPhsRulesTable) {
357 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
358 				DBG_LVL_ALL,
359 				"\nAllocation ServiceFlowPhsRulesTable failed");
360 		return -ENOMEM;
361 	}
362 
363 	pstServiceFlowTable = pPhsdeviceExtension->pstServiceFlowPhsRulesTable;
364 	for (i = 0; i < MAX_SERVICEFLOWS; i++) {
365 		struct bcm_phs_entry sServiceFlow =
366 			pstServiceFlowTable->stSFList[i];
367 		sServiceFlow.pstClassifierTable =
368 			kzalloc(sizeof(struct bcm_phs_classifier_table),
369 				GFP_KERNEL);
370 		if (!sServiceFlow.pstClassifierTable) {
371 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
372 					DBG_LVL_ALL, "\nAllocation failed");
373 			free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
374 			pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
375 			return -ENOMEM;
376 		}
377 	}
378 
379 	pPhsdeviceExtension->CompressedTxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
380 	if (pPhsdeviceExtension->CompressedTxBuffer == NULL) {
381 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
382 				DBG_LVL_ALL, "\nAllocation failed");
383 		free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
384 		pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
385 		return -ENOMEM;
386 	}
387 
388 	pPhsdeviceExtension->UnCompressedRxBuffer =
389 		kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
390 	if (pPhsdeviceExtension->UnCompressedRxBuffer == NULL) {
391 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
392 				DBG_LVL_ALL, "\nAllocation failed");
393 		kfree(pPhsdeviceExtension->CompressedTxBuffer);
394 		free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
395 		pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
396 		return -ENOMEM;
397 	}
398 
399 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
400 			"\n phs_init Successful");
401 	return STATUS_SUCCESS;
402 }
403 
PhsCleanup(IN struct bcm_phs_extension * pPHSDeviceExt)404 int PhsCleanup(IN struct bcm_phs_extension *pPHSDeviceExt)
405 {
406 	if (pPHSDeviceExt->pstServiceFlowPhsRulesTable) {
407 		free_phs_serviceflow_rules(pPHSDeviceExt->pstServiceFlowPhsRulesTable);
408 		pPHSDeviceExt->pstServiceFlowPhsRulesTable = NULL;
409 	}
410 
411 	kfree(pPHSDeviceExt->CompressedTxBuffer);
412 	pPHSDeviceExt->CompressedTxBuffer = NULL;
413 
414 	kfree(pPHSDeviceExt->UnCompressedRxBuffer);
415 	pPHSDeviceExt->UnCompressedRxBuffer = NULL;
416 
417 	return 0;
418 }
419 
420 /*
421  * PHS functions
422  * PhsUpdateClassifierRule
423  *
424  * Routine Description:
425  *   Exported function to add or modify a PHS Rule.
426  *
427  * Arguments:
428  *	IN void* pvContext - PHS Driver Specific Context
429  *	IN B_UINT16 uiVcid    - The Service Flow ID for which the PHS rule applies
430  *	IN B_UINT16  uiClsId   - The Classifier ID within the Service Flow for which the PHS rule applies.
431  *	IN struct bcm_phs_rule *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table.
432  *
433  * Return Value:
434  *
435  * 0 if successful,
436  * >0 Error.
437  */
PhsUpdateClassifierRule(IN void * pvContext,IN B_UINT16 uiVcid,IN B_UINT16 uiClsId,IN struct bcm_phs_rule * psPhsRule,IN B_UINT8 u8AssociatedPHSI)438 ULONG PhsUpdateClassifierRule(IN void *pvContext,
439 			      IN B_UINT16 uiVcid ,
440 			      IN B_UINT16 uiClsId   ,
441 			      IN struct bcm_phs_rule *psPhsRule,
442 			      IN B_UINT8 u8AssociatedPHSI)
443 {
444 	ULONG lStatus = 0;
445 	UINT nSFIndex = 0;
446 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
447 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
448 	struct bcm_phs_extension *pDeviceExtension =
449 		(struct bcm_phs_extension *)pvContext;
450 
451 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
452 			"PHS With Corr2 Changes\n");
453 
454 	if (pDeviceExtension == NULL) {
455 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
456 				DBG_LVL_ALL, "Invalid Device Extension\n");
457 		return ERR_PHS_INVALID_DEVICE_EXETENSION;
458 	}
459 
460 	if (u8AssociatedPHSI == 0)
461 		return ERR_PHS_INVALID_PHS_RULE;
462 
463 	/* Retrieve the SFID Entry Index for requested Service Flow */
464 	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
465 				       uiVcid, &pstServiceFlowEntry);
466 
467 	if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
468 		/* This is a new SF. Create a mapping entry for this */
469 		lStatus = CreateSFToClassifierRuleMapping(uiVcid, uiClsId,
470 							  pDeviceExtension->pstServiceFlowPhsRulesTable,
471 							  psPhsRule,
472 							  u8AssociatedPHSI);
473 		return lStatus;
474 	}
475 
476 	/* SF already Exists Add PHS Rule to existing SF */
477 	lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId,
478 						  pstServiceFlowEntry,
479 						  psPhsRule,
480 						  u8AssociatedPHSI);
481 
482 	return lStatus;
483 }
484 
485 /*
486  * PhsDeletePHSRule
487  *
488  * Routine Description:
489  *   Deletes the specified phs Rule within Vcid
490  *
491  * Arguments:
492  *	IN void* pvContext - PHS Driver Specific Context
493  *	IN B_UINT16  uiVcid    - The Service Flow ID for which the PHS rule applies
494  *	IN B_UINT8  u8PHSI   - the PHS Index identifying PHS rule to be deleted.
495  *
496  * Return Value:
497  *
498  * 0 if successful,
499  * >0 Error.
500  */
PhsDeletePHSRule(IN void * pvContext,IN B_UINT16 uiVcid,IN B_UINT8 u8PHSI)501 ULONG PhsDeletePHSRule(IN void *pvContext,
502 		       IN B_UINT16 uiVcid,
503 		       IN B_UINT8 u8PHSI)
504 {
505 	UINT nSFIndex = 0, nClsidIndex = 0;
506 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
507 	struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
508 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
509 	struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
510 	struct bcm_phs_classifier_entry *curr_entry;
511 
512 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
513 			"======>\n");
514 
515 	if (pDeviceExtension) {
516 		/* Retrieve the SFID Entry Index for requested Service Flow */
517 		nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
518 					       uiVcid, &pstServiceFlowEntry);
519 
520 		if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
521 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
522 					DBG_LVL_ALL, "SFID Match Failed\n");
523 			return ERR_SF_MATCH_FAIL;
524 		}
525 
526 		pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
527 		if (pstClassifierRulesTable) {
528 			for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
529 				curr_entry = &pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex];
530 				if (curr_entry->bUsed &&
531 				    curr_entry->pstPhsRule &&
532 				    (curr_entry->pstPhsRule->u8PHSI == u8PHSI)) {
533 
534 					if (curr_entry->pstPhsRule->u8RefCnt)
535 						curr_entry->pstPhsRule->u8RefCnt--;
536 
537 					if (0 == curr_entry->pstPhsRule->u8RefCnt)
538 						kfree(curr_entry->pstPhsRule);
539 
540 					memset(curr_entry,
541 					       0,
542 					       sizeof(struct bcm_phs_classifier_entry));
543 				}
544 			}
545 		}
546 	}
547 	return 0;
548 }
549 
550 /*
551  * PhsDeleteClassifierRule
552  *
553  * Routine Description:
554  *    Exported function to Delete a PHS Rule for the SFID,CLSID Pair.
555  *
556  * Arguments:
557  *	IN void* pvContext - PHS Driver Specific Context
558  *	IN B_UINT16  uiVcid    - The Service Flow ID for which the PHS rule applies
559  *	IN B_UINT16  uiClsId   - The Classifier ID within the Service Flow for which the PHS rule applies.
560  *
561  * Return Value:
562  *
563  * 0 if successful,
564  * >0 Error.
565  */
PhsDeleteClassifierRule(IN void * pvContext,IN B_UINT16 uiVcid,IN B_UINT16 uiClsId)566 ULONG PhsDeleteClassifierRule(IN void *pvContext,
567 			      IN B_UINT16 uiVcid,
568 			      IN B_UINT16 uiClsId)
569 {
570 	UINT nSFIndex = 0, nClsidIndex = 0;
571 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
572 	struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
573 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
574 	struct bcm_phs_extension *pDeviceExtension =
575 		(struct bcm_phs_extension *)pvContext;
576 
577 	if (!pDeviceExtension)
578 		goto out;
579 
580 	/* Retrieve the SFID Entry Index for requested Service Flow */
581 	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
582 				       uiVcid, &pstServiceFlowEntry);
583 	if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
584 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
585 				DBG_LVL_ALL, "SFID Match Failed\n");
586 		return ERR_SF_MATCH_FAIL;
587 	}
588 
589 	nClsidIndex =
590 		GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
591 				   uiClsId,
592 				   eActiveClassifierRuleContext,
593 				   &pstClassifierEntry);
594 
595 	if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) &&
596 			(!pstClassifierEntry->bUnclassifiedPHSRule)) {
597 		if (pstClassifierEntry->pstPhsRule) {
598 			if (pstClassifierEntry->pstPhsRule->u8RefCnt)
599 				pstClassifierEntry->pstPhsRule->u8RefCnt--;
600 
601 			if (0 == pstClassifierEntry->pstPhsRule->u8RefCnt)
602 				kfree(pstClassifierEntry->pstPhsRule);
603 		}
604 		memset(pstClassifierEntry, 0,
605 		       sizeof(struct bcm_phs_classifier_entry));
606 	}
607 
608 	nClsidIndex =
609 		GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
610 				   uiClsId,
611 				   eOldClassifierRuleContext,
612 				   &pstClassifierEntry);
613 
614 	if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) &&
615 			(!pstClassifierEntry->bUnclassifiedPHSRule)) {
616 		kfree(pstClassifierEntry->pstPhsRule);
617 		memset(pstClassifierEntry, 0,
618 		       sizeof(struct bcm_phs_classifier_entry));
619 	}
620 
621 out:
622 	return 0;
623 }
624 
625 /*
626  * PhsDeleteSFRules
627  *
628  * Routine Description:
629  *    Exported function to Delete a all PHS Rules for the SFID.
630  *
631  * Arguments:
632  *	IN void* pvContext - PHS Driver Specific Context
633  *	IN B_UINT16 uiVcid   - The Service Flow ID for which the PHS rules need to be deleted
634  *
635  * Return Value:
636  *
637  * 0 if successful,
638  * >0 Error.
639  */
PhsDeleteSFRules(IN void * pvContext,IN B_UINT16 uiVcid)640 ULONG PhsDeleteSFRules(IN void *pvContext, IN B_UINT16 uiVcid)
641 {
642 	UINT nSFIndex = 0, nClsidIndex = 0;
643 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
644 	struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
645 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
646 	struct bcm_phs_extension *pDeviceExtension =
647 		(struct bcm_phs_extension *)pvContext;
648 	struct bcm_phs_classifier_entry *curr_clsf_entry;
649 	struct bcm_phs_classifier_entry *curr_rules_list;
650 
651 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
652 			"====>\n");
653 
654 	if (!pDeviceExtension)
655 		goto out;
656 
657 	/* Retrieve the SFID Entry Index for requested Service Flow */
658 	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
659 				       uiVcid, &pstServiceFlowEntry);
660 	if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
661 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
662 				DBG_LVL_ALL, "SFID Match Failed\n");
663 		return ERR_SF_MATCH_FAIL;
664 	}
665 
666 	pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
667 	if (pstClassifierRulesTable) {
668 		for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
669 			curr_clsf_entry =
670 				&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex];
671 
672 			curr_rules_list =
673 				&pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex];
674 
675 			if (curr_clsf_entry->pstPhsRule) {
676 
677 				if (curr_clsf_entry->pstPhsRule->u8RefCnt)
678 					curr_clsf_entry->pstPhsRule->u8RefCnt--;
679 
680 				if (0 == curr_clsf_entry->pstPhsRule->u8RefCnt)
681 					kfree(curr_clsf_entry->pstPhsRule);
682 
683 				curr_clsf_entry->pstPhsRule = NULL;
684 			}
685 			memset(curr_clsf_entry, 0,
686 			       sizeof(struct bcm_phs_classifier_entry));
687 			if (curr_rules_list->pstPhsRule) {
688 
689 				if (curr_rules_list->pstPhsRule->u8RefCnt)
690 					curr_rules_list->pstPhsRule->u8RefCnt--;
691 
692 				if (0 == curr_rules_list->pstPhsRule->u8RefCnt)
693 					kfree(curr_rules_list->pstPhsRule);
694 
695 				curr_rules_list->pstPhsRule = NULL;
696 			}
697 			memset(curr_rules_list, 0,
698 			       sizeof(struct bcm_phs_classifier_entry));
699 		}
700 	}
701 	pstServiceFlowEntry->bUsed = false;
702 	pstServiceFlowEntry->uiVcid = 0;
703 
704 out:
705 	return 0;
706 }
707 
708 /*
709  * PhsCompress
710  *
711  * Routine Description:
712  *    Exported function to compress the data using PHS.
713  *
714  * Arguments:
715  *	IN void* pvContext	    - PHS Driver Specific Context.
716  *	IN B_UINT16 uiVcid	    - The Service Flow ID to which current
717  *				      packet header compression applies.
718  *	IN UINT  uiClsId	    - The Classifier ID to which current packet
719  *				      header compression applies.
720  *	IN void *pvInputBuffer	    - The Input buffer containg packet header
721  *				      data
722  *	IN void *pvOutputBuffer     - The output buffer returned by this
723  *				      function after PHS
724  *	IN UINT *pOldHeaderSize	    - The actual size of the header before PHS
725  *	IN UINT *pNewHeaderSize	    - The new size of the header after applying
726  *				      PHS
727  *
728  * Return Value:
729  *
730  * 0 if successful,
731  * >0 Error.
732  */
PhsCompress(IN void * pvContext,IN B_UINT16 uiVcid,IN B_UINT16 uiClsId,IN void * pvInputBuffer,OUT void * pvOutputBuffer,OUT UINT * pOldHeaderSize,OUT UINT * pNewHeaderSize)733 static ULONG PhsCompress(IN void *pvContext,
734 			 IN B_UINT16 uiVcid,
735 			 IN B_UINT16 uiClsId,
736 			 IN void *pvInputBuffer,
737 			 OUT void *pvOutputBuffer,
738 			 OUT UINT *pOldHeaderSize,
739 			 OUT UINT *pNewHeaderSize)
740 {
741 	UINT nSFIndex = 0, nClsidIndex = 0;
742 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
743 	struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
744 	struct bcm_phs_rule *pstPhsRule = NULL;
745 	ULONG lStatus = 0;
746 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
747 	struct bcm_phs_extension *pDeviceExtension =
748 		(struct bcm_phs_extension *)pvContext;
749 
750 	if (pDeviceExtension == NULL) {
751 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
752 				"Invalid Device Extension\n");
753 		lStatus = STATUS_PHS_NOCOMPRESSION;
754 		return lStatus;
755 	}
756 
757 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
758 			"Suppressing header\n");
759 
760 	/* Retrieve the SFID Entry Index for requested Service Flow */
761 	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
762 				       uiVcid, &pstServiceFlowEntry);
763 	if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
764 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
765 				"SFID Match Failed\n");
766 		lStatus = STATUS_PHS_NOCOMPRESSION;
767 		return lStatus;
768 	}
769 
770 	nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
771 					 uiClsId, eActiveClassifierRuleContext,
772 					 &pstClassifierEntry);
773 
774 	if (nClsidIndex == PHS_INVALID_TABLE_INDEX) {
775 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
776 				"No PHS Rule Defined For Classifier\n");
777 		lStatus =  STATUS_PHS_NOCOMPRESSION;
778 		return lStatus;
779 	}
780 
781 	/* get rule from SF id,Cls ID pair and proceed */
782 	pstPhsRule = pstClassifierEntry->pstPhsRule;
783 	if (!ValidatePHSRuleComplete(pstPhsRule)) {
784 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
785 				"PHS Rule Defined For Classifier But Not Complete\n");
786 		lStatus = STATUS_PHS_NOCOMPRESSION;
787 		return lStatus;
788 	}
789 
790 	/* Compress Packet */
791 	lStatus = phs_compress(pstPhsRule,
792 			       (PUCHAR)pvInputBuffer,
793 			       (PUCHAR)pvOutputBuffer,
794 			       pOldHeaderSize,
795 			       pNewHeaderSize);
796 
797 	if (lStatus == STATUS_PHS_COMPRESSED) {
798 		pstPhsRule->PHSModifiedBytes +=
799 			*pOldHeaderSize - *pNewHeaderSize - 1;
800 		pstPhsRule->PHSModifiedNumPackets++;
801 	} else {
802 		pstPhsRule->PHSErrorNumPackets++;
803 	}
804 
805 	return lStatus;
806 }
807 
808 /*
809  * PhsDeCompress
810  *
811  * Routine Description:
812  *    Exported function to restore the packet header in Rx path.
813  *
814  * Arguments:
815  *	IN void* pvContext	    - PHS Driver Specific Context.
816  *	IN B_UINT16 uiVcid	    - The Service Flow ID to which current
817  *				      packet header restoration applies.
818  *	IN  void *pvInputBuffer	    - The Input buffer containg suppressed
819  *				      packet header data
820  *	OUT void *pvOutputBuffer    - The output buffer returned by this
821  *				      function after restoration
822  *	OUT UINT *pHeaderSize	    - The packet header size after restoration
823  *				      is returned in this parameter.
824  *
825  * Return Value:
826  *
827  * 0 if successful,
828  * >0 Error.
829  */
PhsDeCompress(IN void * pvContext,IN B_UINT16 uiVcid,IN void * pvInputBuffer,OUT void * pvOutputBuffer,OUT UINT * pInHeaderSize,OUT UINT * pOutHeaderSize)830 static ULONG PhsDeCompress(IN void *pvContext,
831 			   IN B_UINT16 uiVcid,
832 			   IN void *pvInputBuffer,
833 			   OUT void *pvOutputBuffer,
834 			   OUT UINT *pInHeaderSize,
835 			   OUT UINT *pOutHeaderSize)
836 {
837 	UINT nSFIndex = 0, nPhsRuleIndex = 0;
838 	struct bcm_phs_entry *pstServiceFlowEntry = NULL;
839 	struct bcm_phs_rule *pstPhsRule = NULL;
840 	UINT phsi;
841 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
842 	struct bcm_phs_extension *pDeviceExtension =
843 		(struct bcm_phs_extension *)pvContext;
844 
845 	*pInHeaderSize = 0;
846 	if (pDeviceExtension == NULL) {
847 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
848 				DBG_LVL_ALL, "Invalid Device Extension\n");
849 		return ERR_PHS_INVALID_DEVICE_EXETENSION;
850 	}
851 
852 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
853 			"Restoring header\n");
854 
855 	phsi = *((unsigned char *)(pvInputBuffer));
856 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
857 			"PHSI To Be Used For restore : %x\n", phsi);
858 	if (phsi == UNCOMPRESSED_PACKET)
859 		return STATUS_PHS_NOCOMPRESSION;
860 
861 	/* Retrieve the SFID Entry Index for requested Service Flow */
862 	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
863 				       uiVcid, &pstServiceFlowEntry);
864 	if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
865 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
866 				DBG_LVL_ALL,
867 				"SFID Match Failed During Lookup\n");
868 		return ERR_SF_MATCH_FAIL;
869 	}
870 
871 	nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
872 					phsi,
873 					eActiveClassifierRuleContext,
874 					&pstPhsRule);
875 	if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX) {
876 		/* Phs Rule does not exist in  active rules table. Lets try
877 		 * in the old rules table. */
878 		nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
879 						phsi,
880 						eOldClassifierRuleContext,
881 						&pstPhsRule);
882 		if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
883 			return ERR_PHSRULE_MATCH_FAIL;
884 	}
885 
886 	*pInHeaderSize = phs_decompress((PUCHAR)pvInputBuffer,
887 					(PUCHAR)pvOutputBuffer,
888 					pstPhsRule,
889 					pOutHeaderSize);
890 
891 	pstPhsRule->PHSModifiedBytes += *pOutHeaderSize - *pInHeaderSize - 1;
892 
893 	pstPhsRule->PHSModifiedNumPackets++;
894 	return STATUS_PHS_COMPRESSED;
895 }
896 
897 /*
898  * Procedure:   free_phs_serviceflow_rules
899  *
900  * Description: This routine is responsible for freeing memory allocated for
901  * PHS rules.
902  *
903  * Arguments:
904  * rules	- ptr to S_SERVICEFLOW_TABLE structure.
905  *
906  * Returns:
907  * Does not return any value.
908  */
free_phs_serviceflow_rules(struct bcm_phs_table * psServiceFlowRulesTable)909 static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable)
910 {
911 	int i, j;
912 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
913 	struct bcm_phs_classifier_entry *curr_act_rules_list;
914 	struct bcm_phs_classifier_entry *curr_old_rules_list;
915 
916 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
917 			"=======>\n");
918 
919 	if (!psServiceFlowRulesTable)
920 		goto out;
921 
922 	for (i = 0; i < MAX_SERVICEFLOWS; i++) {
923 		struct bcm_phs_entry stServiceFlowEntry =
924 			psServiceFlowRulesTable->stSFList[i];
925 		struct bcm_phs_classifier_table *pstClassifierRulesTable =
926 			stServiceFlowEntry.pstClassifierTable;
927 
928 		if (pstClassifierRulesTable) {
929 			for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
930 				curr_act_rules_list =
931 					&pstClassifierRulesTable->stActivePhsRulesList[j];
932 
933 				curr_old_rules_list =
934 					&pstClassifierRulesTable->stOldPhsRulesList[j];
935 
936 				if (curr_act_rules_list->pstPhsRule) {
937 
938 					if (curr_act_rules_list->pstPhsRule->u8RefCnt)
939 						curr_act_rules_list->pstPhsRule->u8RefCnt--;
940 
941 					if (0 == curr_act_rules_list->pstPhsRule->u8RefCnt)
942 						kfree(curr_act_rules_list->pstPhsRule);
943 
944 					curr_act_rules_list->pstPhsRule = NULL;
945 				}
946 
947 				if (curr_old_rules_list->pstPhsRule) {
948 
949 					if (curr_old_rules_list->pstPhsRule->u8RefCnt)
950 						curr_old_rules_list->pstPhsRule->u8RefCnt--;
951 
952 					if (0 == curr_old_rules_list->pstPhsRule->u8RefCnt)
953 						kfree(curr_old_rules_list->pstPhsRule);
954 
955 					curr_old_rules_list->pstPhsRule = NULL;
956 				}
957 			}
958 			kfree(pstClassifierRulesTable);
959 			stServiceFlowEntry.pstClassifierTable =
960 				pstClassifierRulesTable = NULL;
961 		}
962 	}
963 
964 out:
965 
966 	kfree(psServiceFlowRulesTable);
967 	psServiceFlowRulesTable = NULL;
968 }
969 
ValidatePHSRuleComplete(IN const struct bcm_phs_rule * psPhsRule)970 static bool ValidatePHSRuleComplete(IN const struct bcm_phs_rule *psPhsRule)
971 {
972 	return (psPhsRule &&
973 		psPhsRule->u8PHSI &&
974 		psPhsRule->u8PHSS &&
975 		psPhsRule->u8PHSFLength);
976 }
977 
GetServiceFlowEntry(IN struct bcm_phs_table * psServiceFlowTable,IN B_UINT16 uiVcid,struct bcm_phs_entry ** ppstServiceFlowEntry)978 UINT GetServiceFlowEntry(IN struct bcm_phs_table *psServiceFlowTable,
979 			 IN B_UINT16 uiVcid,
980 			 struct bcm_phs_entry **ppstServiceFlowEntry)
981 {
982 	int i;
983 	struct bcm_phs_entry *curr_sf_list;
984 
985 	for (i = 0; i < MAX_SERVICEFLOWS; i++) {
986 		curr_sf_list = &psServiceFlowTable->stSFList[i];
987 		if (curr_sf_list->bUsed && (curr_sf_list->uiVcid == uiVcid)) {
988 			*ppstServiceFlowEntry = curr_sf_list;
989 			return i;
990 		}
991 	}
992 
993 	*ppstServiceFlowEntry = NULL;
994 	return PHS_INVALID_TABLE_INDEX;
995 }
996 
GetClassifierEntry(IN struct bcm_phs_classifier_table * pstClassifierTable,IN B_UINT32 uiClsid,enum bcm_phs_classifier_context eClsContext,OUT struct bcm_phs_classifier_entry ** ppstClassifierEntry)997 static UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
998 			       IN B_UINT32 uiClsid,
999 			       enum bcm_phs_classifier_context eClsContext,
1000 			       OUT struct bcm_phs_classifier_entry **ppstClassifierEntry)
1001 {
1002 	int  i;
1003 	struct bcm_phs_classifier_entry *psClassifierRules = NULL;
1004 
1005 	for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
1006 
1007 		if (eClsContext == eActiveClassifierRuleContext)
1008 			psClassifierRules =
1009 				&pstClassifierTable->stActivePhsRulesList[i];
1010 		else
1011 			psClassifierRules =
1012 				&pstClassifierTable->stOldPhsRulesList[i];
1013 
1014 		if (psClassifierRules->bUsed &&
1015 		   (psClassifierRules->uiClassifierRuleId == uiClsid)) {
1016 			*ppstClassifierEntry = psClassifierRules;
1017 			return i;
1018 		}
1019 	}
1020 
1021 	*ppstClassifierEntry = NULL;
1022 	return PHS_INVALID_TABLE_INDEX;
1023 }
1024 
GetPhsRuleEntry(IN struct bcm_phs_classifier_table * pstClassifierTable,IN B_UINT32 uiPHSI,enum bcm_phs_classifier_context eClsContext,OUT struct bcm_phs_rule ** ppstPhsRule)1025 static UINT GetPhsRuleEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
1026 			    IN B_UINT32 uiPHSI,
1027 			    enum bcm_phs_classifier_context eClsContext,
1028 			    OUT struct bcm_phs_rule **ppstPhsRule)
1029 {
1030 	int  i;
1031 	struct bcm_phs_classifier_entry *pstClassifierRule = NULL;
1032 
1033 	for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
1034 		if (eClsContext == eActiveClassifierRuleContext)
1035 			pstClassifierRule =
1036 				&pstClassifierTable->stActivePhsRulesList[i];
1037 		else
1038 			pstClassifierRule =
1039 				&pstClassifierTable->stOldPhsRulesList[i];
1040 
1041 		if (pstClassifierRule->bUsed &&
1042 		   (pstClassifierRule->u8PHSI == uiPHSI)) {
1043 			*ppstPhsRule = pstClassifierRule->pstPhsRule;
1044 			return i;
1045 		}
1046 	}
1047 
1048 	*ppstPhsRule = NULL;
1049 	return PHS_INVALID_TABLE_INDEX;
1050 }
1051 
CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid,IN B_UINT16 uiClsId,IN struct bcm_phs_table * psServiceFlowTable,struct bcm_phs_rule * psPhsRule,B_UINT8 u8AssociatedPHSI)1052 static UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid,
1053 					    IN B_UINT16  uiClsId,
1054 					    IN struct bcm_phs_table *psServiceFlowTable,
1055 					    struct bcm_phs_rule *psPhsRule,
1056 					    B_UINT8 u8AssociatedPHSI)
1057 {
1058 	struct bcm_phs_classifier_table *psaClassifiertable = NULL;
1059 	UINT uiStatus = 0;
1060 	int iSfIndex;
1061 	bool bFreeEntryFound = false;
1062 	struct bcm_phs_entry *curr_list;
1063 
1064 	/* Check for a free entry in SFID table */
1065 	for (iSfIndex = 0; iSfIndex < MAX_SERVICEFLOWS; iSfIndex++) {
1066 		curr_list = &psServiceFlowTable->stSFList[iSfIndex];
1067 		if (!curr_list->bUsed) {
1068 			bFreeEntryFound = TRUE;
1069 			break;
1070 		}
1071 	}
1072 
1073 	if (!bFreeEntryFound)
1074 		return ERR_SFTABLE_FULL;
1075 
1076 	psaClassifiertable = curr_list->pstClassifierTable;
1077 	uiStatus = CreateClassifierPHSRule(uiClsId,
1078 					   psaClassifiertable,
1079 					   psPhsRule,
1080 					   eActiveClassifierRuleContext,
1081 					   u8AssociatedPHSI);
1082 	if (uiStatus == PHS_SUCCESS) {
1083 		/* Add entry at free index to the SF */
1084 		curr_list->bUsed = TRUE;
1085 		curr_list->uiVcid = uiVcid;
1086 	}
1087 
1088 	return uiStatus;
1089 }
1090 
CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,IN B_UINT16 uiClsId,IN struct bcm_phs_entry * pstServiceFlowEntry,struct bcm_phs_rule * psPhsRule,B_UINT8 u8AssociatedPHSI)1091 static UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
1092 					    IN B_UINT16 uiClsId,
1093 					    IN struct bcm_phs_entry *pstServiceFlowEntry,
1094 					    struct bcm_phs_rule *psPhsRule,
1095 					    B_UINT8 u8AssociatedPHSI)
1096 {
1097 	struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
1098 	UINT uiStatus = PHS_SUCCESS;
1099 	UINT nClassifierIndex = 0;
1100 	struct bcm_phs_classifier_table *psaClassifiertable = NULL;
1101 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1102 
1103 	psaClassifiertable = pstServiceFlowEntry->pstClassifierTable;
1104 
1105 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
1106 			"==>");
1107 
1108 	/* Check if the supplied Classifier already exists */
1109 	nClassifierIndex = GetClassifierEntry(
1110 		pstServiceFlowEntry->pstClassifierTable,
1111 		uiClsId,
1112 		eActiveClassifierRuleContext,
1113 		&pstClassifierEntry);
1114 
1115 	if (nClassifierIndex == PHS_INVALID_TABLE_INDEX) {
1116 		/*
1117 		 * The Classifier doesn't exist. So its a new classifier being
1118 		 * added.
1119 		 * Add new entry to associate PHS Rule to the Classifier
1120 		 */
1121 
1122 		uiStatus = CreateClassifierPHSRule(uiClsId, psaClassifiertable,
1123 						   psPhsRule,
1124 						   eActiveClassifierRuleContext,
1125 						   u8AssociatedPHSI);
1126 		return uiStatus;
1127 	}
1128 
1129 	/*
1130 	 * The Classifier exists.The PHS Rule for this classifier
1131 	 * is being modified
1132 	 */
1133 
1134 	if (pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI) {
1135 		if (pstClassifierEntry->pstPhsRule == NULL)
1136 			return ERR_PHS_INVALID_PHS_RULE;
1137 
1138 		/*
1139 		 * This rule already exists if any fields are changed for this
1140 		 * PHS rule update them.
1141 		 */
1142 		/* If any part of PHSF is valid then we update PHSF */
1143 		if (psPhsRule->u8PHSFLength) {
1144 			/* update PHSF */
1145 			memcpy(pstClassifierEntry->pstPhsRule->u8PHSF,
1146 			       psPhsRule->u8PHSF,
1147 			       MAX_PHS_LENGTHS);
1148 		}
1149 
1150 		if (psPhsRule->u8PHSFLength) {
1151 			/* update PHSFLen */
1152 			pstClassifierEntry->pstPhsRule->u8PHSFLength =
1153 				psPhsRule->u8PHSFLength;
1154 		}
1155 
1156 		if (psPhsRule->u8PHSMLength) {
1157 			/* update PHSM */
1158 			memcpy(pstClassifierEntry->pstPhsRule->u8PHSM,
1159 			       psPhsRule->u8PHSM,
1160 			       MAX_PHS_LENGTHS);
1161 		}
1162 
1163 		if (psPhsRule->u8PHSMLength) {
1164 			/* update PHSM Len */
1165 			pstClassifierEntry->pstPhsRule->u8PHSMLength =
1166 				psPhsRule->u8PHSMLength;
1167 		}
1168 
1169 		if (psPhsRule->u8PHSS) {
1170 			/* update PHSS */
1171 			pstClassifierEntry->pstPhsRule->u8PHSS =
1172 				psPhsRule->u8PHSS;
1173 		}
1174 
1175 		/* update PHSV */
1176 		pstClassifierEntry->pstPhsRule->u8PHSV = psPhsRule->u8PHSV;
1177 	} else {
1178 		/* A new rule is being set for this classifier. */
1179 		uiStatus = UpdateClassifierPHSRule(uiClsId,
1180 						   pstClassifierEntry,
1181 						   psaClassifiertable,
1182 						   psPhsRule,
1183 						   u8AssociatedPHSI);
1184 	}
1185 
1186 	return uiStatus;
1187 }
1188 
CreateClassifierPHSRule(IN B_UINT16 uiClsId,struct bcm_phs_classifier_table * psaClassifiertable,struct bcm_phs_rule * psPhsRule,enum bcm_phs_classifier_context eClsContext,B_UINT8 u8AssociatedPHSI)1189 static UINT CreateClassifierPHSRule(IN B_UINT16  uiClsId,
1190 				    struct bcm_phs_classifier_table *psaClassifiertable,
1191 				    struct bcm_phs_rule *psPhsRule,
1192 				    enum bcm_phs_classifier_context eClsContext,
1193 				    B_UINT8 u8AssociatedPHSI)
1194 {
1195 	UINT iClassifierIndex = 0;
1196 	bool bFreeEntryFound = false;
1197 	struct bcm_phs_classifier_entry *psClassifierRules = NULL;
1198 	UINT nStatus = PHS_SUCCESS;
1199 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1200 
1201 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
1202 			"Inside CreateClassifierPHSRule");
1203 
1204 	if (psaClassifiertable == NULL)
1205 		return ERR_INVALID_CLASSIFIERTABLE_FOR_SF;
1206 
1207 	if (eClsContext == eOldClassifierRuleContext) {
1208 		/*
1209 		 * If An Old Entry for this classifier ID already exists in the
1210 		 * old rules table replace it.
1211 		 */
1212 
1213 		iClassifierIndex = GetClassifierEntry(psaClassifiertable,
1214 						      uiClsId,
1215 						      eClsContext,
1216 						      &psClassifierRules);
1217 
1218 		if (iClassifierIndex != PHS_INVALID_TABLE_INDEX) {
1219 			/*
1220 			 * The Classifier already exists in the old rules table
1221 			 * Lets replace the old classifier with the new one.
1222 			 */
1223 			bFreeEntryFound = TRUE;
1224 		}
1225 	}
1226 
1227 	if (!bFreeEntryFound) {
1228 		/* Continue to search for a free location to add the rule */
1229 		for (iClassifierIndex = 0; iClassifierIndex <
1230 			     MAX_PHSRULE_PER_SF; iClassifierIndex++) {
1231 			if (eClsContext == eActiveClassifierRuleContext)
1232 				psClassifierRules = &psaClassifiertable->stActivePhsRulesList[iClassifierIndex];
1233 			else
1234 				psClassifierRules = &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
1235 
1236 			if (!psClassifierRules->bUsed) {
1237 				bFreeEntryFound = TRUE;
1238 				break;
1239 			}
1240 		}
1241 	}
1242 
1243 	if (!bFreeEntryFound) {
1244 
1245 		if (eClsContext == eActiveClassifierRuleContext)
1246 			return ERR_CLSASSIFIER_TABLE_FULL;
1247 		else {
1248 			/* Lets replace the oldest rule if we are looking in
1249 			 * old Rule table */
1250 			if (psaClassifiertable->uiOldestPhsRuleIndex >= MAX_PHSRULE_PER_SF)
1251 				psaClassifiertable->uiOldestPhsRuleIndex = 0;
1252 
1253 			iClassifierIndex =
1254 				psaClassifiertable->uiOldestPhsRuleIndex;
1255 			psClassifierRules =
1256 				&psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
1257 
1258 			(psaClassifiertable->uiOldestPhsRuleIndex)++;
1259 		}
1260 	}
1261 
1262 	if (eClsContext == eOldClassifierRuleContext) {
1263 
1264 		if (psClassifierRules->pstPhsRule == NULL) {
1265 
1266 			psClassifierRules->pstPhsRule =
1267 				kmalloc(sizeof(struct bcm_phs_rule),
1268 					GFP_KERNEL);
1269 
1270 			if (NULL == psClassifierRules->pstPhsRule)
1271 				return ERR_PHSRULE_MEMALLOC_FAIL;
1272 		}
1273 
1274 		psClassifierRules->bUsed = TRUE;
1275 		psClassifierRules->uiClassifierRuleId = uiClsId;
1276 		psClassifierRules->u8PHSI = psPhsRule->u8PHSI;
1277 		psClassifierRules->bUnclassifiedPHSRule =
1278 			psPhsRule->bUnclassifiedPHSRule;
1279 
1280 		/* Update The PHS rule */
1281 		memcpy(psClassifierRules->pstPhsRule, psPhsRule,
1282 		       sizeof(struct bcm_phs_rule));
1283 	} else
1284 		nStatus = UpdateClassifierPHSRule(uiClsId,
1285 						  psClassifierRules,
1286 						  psaClassifiertable,
1287 						  psPhsRule,
1288 						  u8AssociatedPHSI);
1289 
1290 	return nStatus;
1291 }
1292 
UpdateClassifierPHSRule(IN B_UINT16 uiClsId,IN struct bcm_phs_classifier_entry * pstClassifierEntry,struct bcm_phs_classifier_table * psaClassifiertable,struct bcm_phs_rule * psPhsRule,B_UINT8 u8AssociatedPHSI)1293 static UINT UpdateClassifierPHSRule(IN B_UINT16  uiClsId,
1294 				    IN struct bcm_phs_classifier_entry *pstClassifierEntry,
1295 				    struct bcm_phs_classifier_table *psaClassifiertable,
1296 				    struct bcm_phs_rule *psPhsRule,
1297 				    B_UINT8 u8AssociatedPHSI)
1298 {
1299 	struct bcm_phs_rule *pstAddPhsRule = NULL;
1300 	UINT nPhsRuleIndex = 0;
1301 	bool bPHSRuleOrphaned = false;
1302 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1303 
1304 	psPhsRule->u8RefCnt = 0;
1305 
1306 	/* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry */
1307 	bPHSRuleOrphaned = DerefPhsRule(uiClsId, psaClassifiertable,
1308 					pstClassifierEntry->pstPhsRule);
1309 
1310 	/* Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in
1311 	 * Classifier table for this SF */
1312 	nPhsRuleIndex = GetPhsRuleEntry(psaClassifiertable, u8AssociatedPHSI,
1313 					eActiveClassifierRuleContext,
1314 					&pstAddPhsRule);
1315 	if (PHS_INVALID_TABLE_INDEX == nPhsRuleIndex) {
1316 
1317 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
1318 				DBG_LVL_ALL,
1319 				"\nAdding New PHSRuleEntry For Classifier");
1320 
1321 		if (psPhsRule->u8PHSI == 0) {
1322 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
1323 					DBG_LVL_ALL, "\nError PHSI is Zero\n");
1324 			return ERR_PHS_INVALID_PHS_RULE;
1325 		}
1326 
1327 		/* Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for
1328 		 * uiClsId */
1329 		if (false == bPHSRuleOrphaned) {
1330 
1331 			pstClassifierEntry->pstPhsRule =
1332 				kmalloc(sizeof(struct bcm_phs_rule),
1333 					GFP_KERNEL);
1334 			if (NULL == pstClassifierEntry->pstPhsRule)
1335 				return ERR_PHSRULE_MEMALLOC_FAIL;
1336 		}
1337 		memcpy(pstClassifierEntry->pstPhsRule, psPhsRule,
1338 		       sizeof(struct bcm_phs_rule));
1339 	} else {
1340 		/* Step 2.b PHS Rule  Exists Tie uiClsId with the existing
1341 		 * PHS Rule */
1342 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
1343 				DBG_LVL_ALL,
1344 				"\nTying Classifier to Existing PHS Rule");
1345 		if (bPHSRuleOrphaned) {
1346 			kfree(pstClassifierEntry->pstPhsRule);
1347 			pstClassifierEntry->pstPhsRule = NULL;
1348 		}
1349 		pstClassifierEntry->pstPhsRule = pstAddPhsRule;
1350 	}
1351 
1352 	pstClassifierEntry->bUsed = TRUE;
1353 	pstClassifierEntry->u8PHSI = pstClassifierEntry->pstPhsRule->u8PHSI;
1354 	pstClassifierEntry->uiClassifierRuleId = uiClsId;
1355 	pstClassifierEntry->pstPhsRule->u8RefCnt++;
1356 	pstClassifierEntry->bUnclassifiedPHSRule =
1357 		pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule;
1358 
1359 	return PHS_SUCCESS;
1360 }
1361 
DerefPhsRule(IN B_UINT16 uiClsId,struct bcm_phs_classifier_table * psaClassifiertable,struct bcm_phs_rule * pstPhsRule)1362 static bool DerefPhsRule(IN B_UINT16  uiClsId,
1363 			 struct bcm_phs_classifier_table *psaClassifiertable,
1364 			 struct bcm_phs_rule *pstPhsRule)
1365 {
1366 	if (pstPhsRule == NULL)
1367 		return false;
1368 
1369 	if (pstPhsRule->u8RefCnt)
1370 		pstPhsRule->u8RefCnt--;
1371 
1372 	return (0 == pstPhsRule->u8RefCnt);
1373 }
1374 
dbg_print_st_cls_entry(struct bcm_mini_adapter * ad,struct bcm_phs_entry * st_serv_flow_entry,struct bcm_phs_classifier_entry * st_cls_entry)1375 static void dbg_print_st_cls_entry(struct bcm_mini_adapter *ad,
1376 				   struct bcm_phs_entry *st_serv_flow_entry,
1377 				   struct bcm_phs_classifier_entry *st_cls_entry)
1378 {
1379 	int k;
1380 
1381 	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID  : %#X", st_serv_flow_entry->uiVcid);
1382 	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID  : %#X", st_cls_entry->uiClassifierRuleId);
1383 	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID  : %#X", st_cls_entry->u8PHSI);
1384 	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n");
1385 	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI  : %#X", st_cls_entry->pstPhsRule->u8PHSI);
1386 	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ", st_cls_entry->pstPhsRule->u8PHSFLength);
1387 	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : ");
1388 
1389 	for (k = 0 ; k < st_cls_entry->pstPhsRule->u8PHSFLength; k++)
1390 		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ", st_cls_entry->pstPhsRule->u8PHSF[k]);
1391 	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength  : %#X", st_cls_entry->pstPhsRule->u8PHSMLength);
1392 	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :");
1393 
1394 	for (k = 0; k < st_cls_entry->pstPhsRule->u8PHSMLength; k++)
1395 		BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ", st_cls_entry->pstPhsRule->u8PHSM[k]);
1396 	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ", st_cls_entry->pstPhsRule->u8PHSS);
1397 	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV  : %#X", st_cls_entry->pstPhsRule->u8PHSV);
1398 	BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n");
1399 }
1400 
phsrules_per_sf_dbg_print(struct bcm_mini_adapter * ad,struct bcm_phs_entry * st_serv_flow_entry)1401 static void phsrules_per_sf_dbg_print(struct bcm_mini_adapter *ad,
1402 				      struct bcm_phs_entry *st_serv_flow_entry)
1403 {
1404 	int j, l;
1405 	struct bcm_phs_classifier_entry st_cls_entry;
1406 
1407 	for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
1408 
1409 		for (l = 0; l < 2; l++) {
1410 
1411 			if (l == 0) {
1412 				st_cls_entry = st_serv_flow_entry->pstClassifierTable->stActivePhsRulesList[j];
1413 				if (st_cls_entry.bUsed)
1414 					BCM_DEBUG_PRINT(ad,
1415 							DBG_TYPE_OTHERS,
1416 							DUMP_INFO,
1417 							(DBG_LVL_ALL | DBG_NO_FUNC_PRINT),
1418 							"\n Active PHS Rule :\n");
1419 			} else {
1420 				st_cls_entry = st_serv_flow_entry->pstClassifierTable->stOldPhsRulesList[j];
1421 				if (st_cls_entry.bUsed)
1422 					BCM_DEBUG_PRINT(ad,
1423 							DBG_TYPE_OTHERS,
1424 							DUMP_INFO,
1425 							(DBG_LVL_ALL | DBG_NO_FUNC_PRINT),
1426 							"\n Old PHS Rule :\n");
1427 			}
1428 
1429 			if (st_cls_entry.bUsed) {
1430 				dbg_print_st_cls_entry(ad,
1431 						       st_serv_flow_entry,
1432 						       &st_cls_entry);
1433 			}
1434 		}
1435 	}
1436 }
1437 
DumpPhsRules(struct bcm_phs_extension * pDeviceExtension)1438 void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension)
1439 {
1440 	int i;
1441 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1442 
1443 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,
1444 			"\n Dumping PHS Rules :\n");
1445 
1446 	for (i = 0; i < MAX_SERVICEFLOWS; i++) {
1447 
1448 		struct bcm_phs_entry stServFlowEntry =
1449 			pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i];
1450 
1451 		if (!stServFlowEntry.bUsed)
1452 			continue;
1453 
1454 		phsrules_per_sf_dbg_print(Adapter, &stServFlowEntry);
1455 	}
1456 }
1457 
1458 /*
1459  * Procedure:   phs_decompress
1460  *
1461  * Description: This routine restores the static fields within the packet.
1462  *
1463  * Arguments:
1464  *	in_buf			- ptr to incoming packet buffer.
1465  *	out_buf			- ptr to output buffer where the suppressed
1466  *				  header is copied.
1467  *	decomp_phs_rules	- ptr to PHS rule.
1468  *	header_size		- ptr to field which holds the phss or
1469  *				  phsf_length.
1470  *
1471  * Returns:
1472  *	size	- The number of bytes of dynamic fields present with in the
1473  *		  incoming packet header.
1474  *	0	- If PHS rule is NULL.If PHSI is 0 indicateing packet as
1475  *		  uncompressed.
1476  */
phs_decompress(unsigned char * in_buf,unsigned char * out_buf,struct bcm_phs_rule * decomp_phs_rules,UINT * header_size)1477 static int phs_decompress(unsigned char *in_buf,
1478 			  unsigned char *out_buf,
1479 			  struct bcm_phs_rule *decomp_phs_rules,
1480 			  UINT *header_size)
1481 {
1482 	int phss, size = 0;
1483 	struct bcm_phs_rule *tmp_memb;
1484 	int bit, i = 0;
1485 	unsigned char *phsf, *phsm;
1486 	int in_buf_len = *header_size - 1;
1487 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1488 
1489 	in_buf++;
1490 
1491 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
1492 			"====>\n");
1493 	*header_size = 0;
1494 
1495 	if (decomp_phs_rules == NULL)
1496 		return 0;
1497 
1498 	tmp_memb = decomp_phs_rules;
1499 	/*
1500 	 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,
1501 	 * "\nDECOMP:In phs_decompress PHSI 1  %d",phsi));
1502 	 * header_size = tmp_memb->u8PHSFLength;
1503 	 */
1504 	phss = tmp_memb->u8PHSS;
1505 	phsf = tmp_memb->u8PHSF;
1506 	phsm = tmp_memb->u8PHSM;
1507 
1508 	if (phss > MAX_PHS_LENGTHS)
1509 		phss = MAX_PHS_LENGTHS;
1510 
1511 	/*
1512 	 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,
1513 	 * "\nDECOMP:
1514 	 * In phs_decompress PHSI  %d phss %d index %d",phsi,phss,index));
1515 	 */
1516 	while ((phss > 0) && (size < in_buf_len)) {
1517 		bit = ((*phsm << i) & SUPPRESS);
1518 
1519 		if (bit == SUPPRESS) {
1520 			*out_buf = *phsf;
1521 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
1522 					DBG_LVL_ALL,
1523 					"\nDECOMP:In phss  %d phsf %d output %d",
1524 					phss, *phsf, *out_buf);
1525 		} else {
1526 			*out_buf = *in_buf;
1527 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
1528 					DBG_LVL_ALL,
1529 					"\nDECOMP:In phss  %d input %d output %d",
1530 					phss, *in_buf, *out_buf);
1531 			in_buf++;
1532 			size++;
1533 		}
1534 		out_buf++;
1535 		phsf++;
1536 		phss--;
1537 		i++;
1538 		*header_size = *header_size + 1;
1539 
1540 		if (i > MAX_NO_BIT) {
1541 			i = 0;
1542 			phsm++;
1543 		}
1544 	}
1545 
1546 	return size;
1547 }
1548 
1549 /*
1550  * Procedure:   phs_compress
1551  *
1552  * Description: This routine suppresses the static fields within the packet.
1553  * Before that it will verify the fields to be suppressed with the corresponding
1554  * fields in the phsf. For verification it checks the phsv field of PHS rule.
1555  * If set and verification succeeds it suppresses the field.If any one static
1556  * field is found different none of the static fields are suppressed then the
1557  * packet is sent as uncompressed packet with phsi=0.
1558  *
1559  * Arguments:
1560  *	phs_rule - ptr to PHS rule.
1561  *	in_buf		- ptr to incoming packet buffer.
1562  *	out_buf		- ptr to output buffer where the suppressed header is
1563  *			  copied.
1564  *	header_size	- ptr to field which holds the phss.
1565  *
1566  * Returns:
1567  *	size	- The number of bytes copied into the output buffer i.e
1568  *		  dynamic fields
1569  *	0	- If PHS rule is NULL.If PHSV field is not set. If the
1570  *		  verification fails.
1571  */
phs_compress(struct bcm_phs_rule * phs_rule,unsigned char * in_buf,unsigned char * out_buf,UINT * header_size,UINT * new_header_size)1572 static int phs_compress(struct bcm_phs_rule *phs_rule,
1573 			unsigned char *in_buf,
1574 			unsigned char *out_buf,
1575 			UINT *header_size,
1576 			UINT *new_header_size)
1577 {
1578 	unsigned char *old_addr = out_buf;
1579 	int suppress = 0;
1580 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1581 
1582 	if (phs_rule == NULL) {
1583 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
1584 				"\nphs_compress(): phs_rule null!");
1585 		*out_buf = ZERO_PHSI;
1586 		return STATUS_PHS_NOCOMPRESSION;
1587 	}
1588 
1589 	if (phs_rule->u8PHSS <= *new_header_size)
1590 		*header_size = phs_rule->u8PHSS;
1591 	else
1592 		*header_size = *new_header_size;
1593 
1594 	/* To copy PHSI */
1595 	out_buf++;
1596 	suppress = verify_suppress_phsf(in_buf, out_buf, phs_rule->u8PHSF,
1597 					phs_rule->u8PHSM, phs_rule->u8PHSS,
1598 					phs_rule->u8PHSV, new_header_size);
1599 
1600 	if (suppress == STATUS_PHS_COMPRESSED) {
1601 		*old_addr = (unsigned char)phs_rule->u8PHSI;
1602 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
1603 				"\nCOMP:In phs_compress phsi %d",
1604 				phs_rule->u8PHSI);
1605 	} else {
1606 		*old_addr = ZERO_PHSI;
1607 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
1608 				"\nCOMP:In phs_compress PHSV Verification failed");
1609 	}
1610 
1611 	return suppress;
1612 }
1613 
1614 /*
1615  * Procedure:	verify_suppress_phsf
1616  *
1617  * Description: This routine verifies the fields of the packet and if all the
1618  * static fields are equal it adds the phsi of that PHS rule.If any static
1619  * field differs it woun't suppress any field.
1620  *
1621  * Arguments:
1622  * rules_set	- ptr to classifier_rules.
1623  * in_buffer	- ptr to incoming packet buffer.
1624  * out_buffer	- ptr to output buffer where the suppressed header is copied.
1625  * phsf		- ptr to phsf.
1626  * phsm		- ptr to phsm.
1627  * phss		- variable holding phss.
1628  *
1629  * Returns:
1630  *	size    - The number of bytes copied into the output buffer i.e dynamic
1631  *		  fields.
1632  *	0	- Packet has failed the verification.
1633  */
verify_suppress_phsf(unsigned char * in_buffer,unsigned char * out_buffer,unsigned char * phsf,unsigned char * phsm,unsigned int phss,unsigned int phsv,UINT * new_header_size)1634 static int verify_suppress_phsf(unsigned char *in_buffer,
1635 				unsigned char *out_buffer,
1636 				unsigned char *phsf,
1637 				unsigned char *phsm,
1638 				unsigned int phss,
1639 				unsigned int phsv,
1640 				UINT *new_header_size)
1641 {
1642 	unsigned int size = 0;
1643 	int bit, i = 0;
1644 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
1645 
1646 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
1647 			"\nCOMP:In verify_phsf PHSM - 0x%X", *phsm);
1648 
1649 	if (phss > (*new_header_size))
1650 		phss = *new_header_size;
1651 
1652 	while (phss > 0) {
1653 		bit = ((*phsm << i) & SUPPRESS);
1654 		if (bit == SUPPRESS) {
1655 			if (*in_buffer != *phsf) {
1656 				if (phsv == VERIFY) {
1657 					BCM_DEBUG_PRINT(Adapter,
1658 							DBG_TYPE_OTHERS,
1659 							PHS_SEND,
1660 							DBG_LVL_ALL,
1661 							"\nCOMP:In verify_phsf failed for field  %d buf  %d phsf %d",
1662 							phss,
1663 							*in_buffer,
1664 							*phsf);
1665 					return STATUS_PHS_NOCOMPRESSION;
1666 				}
1667 			} else
1668 				BCM_DEBUG_PRINT(Adapter,
1669 						DBG_TYPE_OTHERS,
1670 						PHS_SEND,
1671 						DBG_LVL_ALL,
1672 						"\nCOMP:In verify_phsf success for field  %d buf  %d phsf %d",
1673 						phss,
1674 						*in_buffer,
1675 						*phsf);
1676 		} else {
1677 			*out_buffer = *in_buffer;
1678 			BCM_DEBUG_PRINT(Adapter,
1679 					DBG_TYPE_OTHERS,
1680 					PHS_SEND,
1681 					DBG_LVL_ALL,
1682 					"\nCOMP:In copying_header input %d  out %d",
1683 					*in_buffer,
1684 					*out_buffer);
1685 			out_buffer++;
1686 			size++;
1687 		}
1688 
1689 		in_buffer++;
1690 		phsf++;
1691 		phss--;
1692 		i++;
1693 
1694 		if (i > MAX_NO_BIT) {
1695 			i = 0;
1696 			phsm++;
1697 		}
1698 	}
1699 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
1700 			"\nCOMP:In verify_phsf success");
1701 	*new_header_size = size;
1702 	return STATUS_PHS_COMPRESSED;
1703 }
1704