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