at v3.16 1448 lines 50 kB view raw
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}