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