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