Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1#include "headers.h"
2
3static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid, B_UINT16 uiClsId, struct bcm_phs_table *psServiceFlowTable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
4
5static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid, B_UINT16 uiClsId, struct bcm_phs_entry *pstServiceFlowEntry, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
6
7static 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
9static 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
11static bool ValidatePHSRuleComplete(struct bcm_phs_rule *psPhsRule);
12
13static bool DerefPhsRule(B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule);
14
15static UINT GetClassifierEntry(struct bcm_phs_classifier_table *pstClassifierTable, B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_classifier_entry **ppstClassifierEntry);
16
17static UINT GetPhsRuleEntry(struct bcm_phs_classifier_table *pstClassifierTable, B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_rule **ppstPhsRule);
18
19static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable);
20
21static 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
24static 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
27static int phs_decompress(unsigned char *in_buf, unsigned char *out_buf,
28 struct bcm_phs_rule *phs_rules, UINT *header_size);
29
30static 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
38static 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
66int 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
192int 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
249void 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 */
270int 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
320int 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 */
354ULONG 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 */
410ULONG 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 */
467ULONG 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 */
523ULONG 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 */
596static 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 */
677static 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 */
742static 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
788static 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
810UINT 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
829static 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
855static 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
880static 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
913static 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
1002static 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
1094static 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
1150static 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
1169void 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 */
1239static 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 */
1324static 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 */
1381static 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}