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