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