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