at v3.13 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 ULONG lStatus = 0; 413 UINT nSFIndex = 0, nClsidIndex = 0; 414 struct bcm_phs_entry *pstServiceFlowEntry = NULL; 415 struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL; 416 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 417 struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext; 418 419 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "======>\n"); 420 421 if (pDeviceExtension) { 422 /* Retrieve the SFID Entry Index for requested Service Flow */ 423 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry); 424 425 if (nSFIndex == PHS_INVALID_TABLE_INDEX) { 426 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n"); 427 return ERR_SF_MATCH_FAIL; 428 } 429 430 pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable; 431 if (pstClassifierRulesTable) { 432 for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) { 433 if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].bUsed && pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule) { 434 if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8PHSI == u8PHSI) { 435 436 if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt) 437 pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--; 438 439 if (0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt) 440 kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule); 441 442 memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0, 443 sizeof(struct bcm_phs_classifier_entry)); 444 } 445 } 446 } 447 } 448 } 449 return lStatus; 450} 451 452/* 453 * PhsDeleteClassifierRule 454 * 455 * Routine Description: 456 * Exported function to Delete a PHS Rule for the SFID,CLSID Pair. 457 * 458 * Arguments: 459 * IN void* pvContext - PHS Driver Specific Context 460 * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies 461 * IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies. 462 * 463 * Return Value: 464 * 465 * 0 if successful, 466 * >0 Error. 467 */ 468ULONG PhsDeleteClassifierRule(IN void *pvContext, IN B_UINT16 uiVcid, IN B_UINT16 uiClsId) 469{ 470 ULONG lStatus = 0; 471 UINT nSFIndex = 0, nClsidIndex = 0; 472 struct bcm_phs_entry *pstServiceFlowEntry = NULL; 473 struct bcm_phs_classifier_entry *pstClassifierEntry = NULL; 474 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 475 struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext; 476 477 if (pDeviceExtension) { 478 /* Retrieve the SFID Entry Index for requested Service Flow */ 479 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry); 480 if (nSFIndex == PHS_INVALID_TABLE_INDEX) { 481 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n"); 482 return ERR_SF_MATCH_FAIL; 483 } 484 485 nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable, 486 uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry); 487 488 if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) { 489 if (pstClassifierEntry->pstPhsRule) { 490 if (pstClassifierEntry->pstPhsRule->u8RefCnt) 491 pstClassifierEntry->pstPhsRule->u8RefCnt--; 492 493 if (0 == pstClassifierEntry->pstPhsRule->u8RefCnt) 494 kfree(pstClassifierEntry->pstPhsRule); 495 } 496 memset(pstClassifierEntry, 0, sizeof(struct bcm_phs_classifier_entry)); 497 } 498 499 nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable, 500 uiClsId, eOldClassifierRuleContext, &pstClassifierEntry); 501 502 if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) { 503 kfree(pstClassifierEntry->pstPhsRule); 504 memset(pstClassifierEntry, 0, sizeof(struct bcm_phs_classifier_entry)); 505 } 506 } 507 return lStatus; 508} 509 510/* 511 * PhsDeleteSFRules 512 * 513 * Routine Description: 514 * Exported function to Delete a all PHS Rules for the SFID. 515 * 516 * Arguments: 517 * IN void* pvContext - PHS Driver Specific Context 518 * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rules need to be deleted 519 * 520 * Return Value: 521 * 522 * 0 if successful, 523 * >0 Error. 524 */ 525ULONG PhsDeleteSFRules(IN void *pvContext, IN B_UINT16 uiVcid) 526{ 527 ULONG lStatus = 0; 528 UINT nSFIndex = 0, nClsidIndex = 0; 529 struct bcm_phs_entry *pstServiceFlowEntry = NULL; 530 struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL; 531 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 532 struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext; 533 534 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "====>\n"); 535 536 if (pDeviceExtension) { 537 /* Retrieve the SFID Entry Index for requested Service Flow */ 538 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, 539 uiVcid, &pstServiceFlowEntry); 540 if (nSFIndex == PHS_INVALID_TABLE_INDEX) { 541 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n"); 542 return ERR_SF_MATCH_FAIL; 543 } 544 545 pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable; 546 if (pstClassifierRulesTable) { 547 for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) { 548 if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule) { 549 550 if (pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt) 551 pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--; 552 553 if (0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt) 554 kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule); 555 556 pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule = NULL; 557 } 558 memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0, sizeof(struct bcm_phs_classifier_entry)); 559 if (pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule) { 560 561 if (pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt) 562 pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--; 563 564 if (0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt) 565 kfree(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule); 566 567 pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule = NULL; 568 } 569 memset(&pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex], 0, sizeof(struct bcm_phs_classifier_entry)); 570 } 571 } 572 pstServiceFlowEntry->bUsed = false; 573 pstServiceFlowEntry->uiVcid = 0; 574 } 575 576 return lStatus; 577} 578 579/* 580 * PhsCompress 581 * 582 * Routine Description: 583 * Exported function to compress the data using PHS. 584 * 585 * Arguments: 586 * IN void* pvContext - PHS Driver Specific Context. 587 * IN B_UINT16 uiVcid - The Service Flow ID to which current packet header compression applies. 588 * IN UINT uiClsId - The Classifier ID to which current packet header compression applies. 589 * IN void *pvInputBuffer - The Input buffer containg packet header data 590 * IN void *pvOutputBuffer - The output buffer returned by this function after PHS 591 * IN UINT *pOldHeaderSize - The actual size of the header before PHS 592 * IN UINT *pNewHeaderSize - The new size of the header after applying PHS 593 * 594 * Return Value: 595 * 596 * 0 if successful, 597 * >0 Error. 598 */ 599static ULONG PhsCompress(IN void *pvContext, 600 IN B_UINT16 uiVcid, 601 IN B_UINT16 uiClsId, 602 IN void *pvInputBuffer, 603 OUT void *pvOutputBuffer, 604 OUT UINT *pOldHeaderSize, 605 OUT UINT *pNewHeaderSize) 606{ 607 UINT nSFIndex = 0, nClsidIndex = 0; 608 struct bcm_phs_entry *pstServiceFlowEntry = NULL; 609 struct bcm_phs_classifier_entry *pstClassifierEntry = NULL; 610 struct bcm_phs_rule *pstPhsRule = NULL; 611 ULONG lStatus = 0; 612 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 613 struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext; 614 615 if (pDeviceExtension == NULL) { 616 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "Invalid Device Extension\n"); 617 lStatus = STATUS_PHS_NOCOMPRESSION; 618 return lStatus; 619 } 620 621 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "Suppressing header\n"); 622 623 /* Retrieve the SFID Entry Index for requested Service Flow */ 624 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, 625 uiVcid, &pstServiceFlowEntry); 626 if (nSFIndex == PHS_INVALID_TABLE_INDEX) { 627 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "SFID Match Failed\n"); 628 lStatus = STATUS_PHS_NOCOMPRESSION; 629 return lStatus; 630 } 631 632 nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable, 633 uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry); 634 635 if (nClsidIndex == PHS_INVALID_TABLE_INDEX) { 636 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "No PHS Rule Defined For Classifier\n"); 637 lStatus = STATUS_PHS_NOCOMPRESSION; 638 return lStatus; 639 } 640 641 /* get rule from SF id,Cls ID pair and proceed */ 642 pstPhsRule = pstClassifierEntry->pstPhsRule; 643 if (!ValidatePHSRuleComplete(pstPhsRule)) { 644 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "PHS Rule Defined For Classifier But Not Complete\n"); 645 lStatus = STATUS_PHS_NOCOMPRESSION; 646 return lStatus; 647 } 648 649 /* Compress Packet */ 650 lStatus = phs_compress(pstPhsRule, (PUCHAR)pvInputBuffer, 651 (PUCHAR)pvOutputBuffer, pOldHeaderSize, pNewHeaderSize); 652 653 if (lStatus == STATUS_PHS_COMPRESSED) { 654 pstPhsRule->PHSModifiedBytes += *pOldHeaderSize - *pNewHeaderSize - 1; 655 pstPhsRule->PHSModifiedNumPackets++; 656 } else 657 pstPhsRule->PHSErrorNumPackets++; 658 659 return lStatus; 660} 661 662/* 663 * PhsDeCompress 664 * 665 * Routine Description: 666 * Exported function to restore the packet header in Rx path. 667 * 668 * Arguments: 669 * IN void* pvContext - PHS Driver Specific Context. 670 * IN B_UINT16 uiVcid - The Service Flow ID to which current packet header restoration applies. 671 * IN void *pvInputBuffer - The Input buffer containg suppressed packet header data 672 * OUT void *pvOutputBuffer - The output buffer returned by this function after restoration 673 * OUT UINT *pHeaderSize - The packet header size after restoration is returned in this parameter. 674 * 675 * Return Value: 676 * 677 * 0 if successful, 678 * >0 Error. 679 */ 680static ULONG PhsDeCompress(IN void *pvContext, 681 IN B_UINT16 uiVcid, 682 IN void *pvInputBuffer, 683 OUT void *pvOutputBuffer, 684 OUT UINT *pInHeaderSize, 685 OUT UINT *pOutHeaderSize) 686{ 687 UINT nSFIndex = 0, nPhsRuleIndex = 0; 688 struct bcm_phs_entry *pstServiceFlowEntry = NULL; 689 struct bcm_phs_rule *pstPhsRule = NULL; 690 UINT phsi; 691 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 692 struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext; 693 694 *pInHeaderSize = 0; 695 if (pDeviceExtension == NULL) { 696 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "Invalid Device Extension\n"); 697 return ERR_PHS_INVALID_DEVICE_EXETENSION; 698 } 699 700 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "Restoring header\n"); 701 702 phsi = *((unsigned char *)(pvInputBuffer)); 703 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "PHSI To Be Used For restore : %x\n", phsi); 704 if (phsi == UNCOMPRESSED_PACKET) 705 return STATUS_PHS_NOCOMPRESSION; 706 707 /* Retrieve the SFID Entry Index for requested Service Flow */ 708 nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, 709 uiVcid, &pstServiceFlowEntry); 710 if (nSFIndex == PHS_INVALID_TABLE_INDEX) { 711 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "SFID Match Failed During Lookup\n"); 712 return ERR_SF_MATCH_FAIL; 713 } 714 715 nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable, phsi, 716 eActiveClassifierRuleContext, &pstPhsRule); 717 if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX) { 718 /* Phs Rule does not exist in active rules table. Lets try in the old rules table. */ 719 nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable, 720 phsi, eOldClassifierRuleContext, &pstPhsRule); 721 if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX) 722 return ERR_PHSRULE_MATCH_FAIL; 723 } 724 725 *pInHeaderSize = phs_decompress((PUCHAR)pvInputBuffer, 726 (PUCHAR)pvOutputBuffer, pstPhsRule, pOutHeaderSize); 727 728 pstPhsRule->PHSModifiedBytes += *pOutHeaderSize - *pInHeaderSize - 1; 729 730 pstPhsRule->PHSModifiedNumPackets++; 731 return STATUS_PHS_COMPRESSED; 732} 733 734/* 735 * Procedure: free_phs_serviceflow_rules 736 * 737 * Description: This routine is responsible for freeing memory allocated for PHS rules. 738 * 739 * Arguments: 740 * rules - ptr to S_SERVICEFLOW_TABLE structure. 741 * 742 * Returns: 743 * Does not return any value. 744 */ 745static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable) 746{ 747 int i, j; 748 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 749 750 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "=======>\n"); 751 752 if (psServiceFlowRulesTable) { 753 for (i = 0; i < MAX_SERVICEFLOWS; i++) { 754 struct bcm_phs_entry stServiceFlowEntry = psServiceFlowRulesTable->stSFList[i]; 755 struct bcm_phs_classifier_table *pstClassifierRulesTable = stServiceFlowEntry.pstClassifierTable; 756 757 if (pstClassifierRulesTable) { 758 for (j = 0; j < MAX_PHSRULE_PER_SF; j++) { 759 if (pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule) { 760 761 if (pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt) 762 pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt--; 763 764 if (0 == pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule->u8RefCnt) 765 kfree(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule); 766 767 pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule = NULL; 768 } 769 770 if (pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule) { 771 772 if (pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt) 773 pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt--; 774 775 if (0 == pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule->u8RefCnt) 776 kfree(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule); 777 778 pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule = NULL; 779 } 780 } 781 kfree(pstClassifierRulesTable); 782 stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL; 783 } 784 } 785 } 786 787 kfree(psServiceFlowRulesTable); 788 psServiceFlowRulesTable = NULL; 789} 790 791static bool ValidatePHSRuleComplete(IN struct bcm_phs_rule *psPhsRule) 792{ 793 if (psPhsRule) { 794 if (!psPhsRule->u8PHSI) { 795 /* PHSI is not valid */ 796 return false; 797 } 798 799 if (!psPhsRule->u8PHSS) { 800 /* PHSS Is Undefined */ 801 return false; 802 } 803 804 /* Check if PHSF is defines for the PHS Rule */ 805 if (!psPhsRule->u8PHSFLength) /* If any part of PHSF is valid then Rule contains valid PHSF */ 806 return false; 807 808 return TRUE; 809 } else 810 return false; 811} 812 813UINT GetServiceFlowEntry(IN struct bcm_phs_table *psServiceFlowTable, 814 IN B_UINT16 uiVcid, 815 struct bcm_phs_entry **ppstServiceFlowEntry) 816{ 817 int i; 818 819 for (i = 0; i < MAX_SERVICEFLOWS; i++) { 820 if (psServiceFlowTable->stSFList[i].bUsed) { 821 if (psServiceFlowTable->stSFList[i].uiVcid == uiVcid) { 822 *ppstServiceFlowEntry = &psServiceFlowTable->stSFList[i]; 823 return i; 824 } 825 } 826 } 827 828 *ppstServiceFlowEntry = NULL; 829 return PHS_INVALID_TABLE_INDEX; 830} 831 832static UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable, 833 IN B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext, 834 OUT struct bcm_phs_classifier_entry **ppstClassifierEntry) 835{ 836 int i; 837 struct bcm_phs_classifier_entry *psClassifierRules = NULL; 838 839 for (i = 0; i < MAX_PHSRULE_PER_SF; i++) { 840 841 if (eClsContext == eActiveClassifierRuleContext) 842 psClassifierRules = &pstClassifierTable->stActivePhsRulesList[i]; 843 else 844 psClassifierRules = &pstClassifierTable->stOldPhsRulesList[i]; 845 846 if (psClassifierRules->bUsed) { 847 if (psClassifierRules->uiClassifierRuleId == uiClsid) { 848 *ppstClassifierEntry = psClassifierRules; 849 return i; 850 } 851 } 852 } 853 854 *ppstClassifierEntry = NULL; 855 return PHS_INVALID_TABLE_INDEX; 856} 857 858static UINT GetPhsRuleEntry(IN struct bcm_phs_classifier_table *pstClassifierTable, 859 IN B_UINT32 uiPHSI, enum bcm_phs_classifier_context eClsContext, 860 OUT struct bcm_phs_rule **ppstPhsRule) 861{ 862 int i; 863 struct bcm_phs_classifier_entry *pstClassifierRule = NULL; 864 865 for (i = 0; i < MAX_PHSRULE_PER_SF; i++) { 866 if (eClsContext == eActiveClassifierRuleContext) 867 pstClassifierRule = &pstClassifierTable->stActivePhsRulesList[i]; 868 else 869 pstClassifierRule = &pstClassifierTable->stOldPhsRulesList[i]; 870 871 if (pstClassifierRule->bUsed) { 872 if (pstClassifierRule->u8PHSI == uiPHSI) { 873 *ppstPhsRule = pstClassifierRule->pstPhsRule; 874 return i; 875 } 876 } 877 } 878 879 *ppstPhsRule = NULL; 880 return PHS_INVALID_TABLE_INDEX; 881} 882 883static UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid, IN B_UINT16 uiClsId, 884 IN struct bcm_phs_table *psServiceFlowTable, 885 struct bcm_phs_rule *psPhsRule, 886 B_UINT8 u8AssociatedPHSI) 887{ 888 struct bcm_phs_classifier_table *psaClassifiertable = NULL; 889 UINT uiStatus = 0; 890 int iSfIndex; 891 bool bFreeEntryFound = false; 892 893 /* Check for a free entry in SFID table */ 894 for (iSfIndex = 0; iSfIndex < MAX_SERVICEFLOWS; iSfIndex++) { 895 if (!psServiceFlowTable->stSFList[iSfIndex].bUsed) { 896 bFreeEntryFound = TRUE; 897 break; 898 } 899 } 900 901 if (!bFreeEntryFound) 902 return ERR_SFTABLE_FULL; 903 904 psaClassifiertable = psServiceFlowTable->stSFList[iSfIndex].pstClassifierTable; 905 uiStatus = CreateClassifierPHSRule(uiClsId, psaClassifiertable, psPhsRule, 906 eActiveClassifierRuleContext, u8AssociatedPHSI); 907 if (uiStatus == PHS_SUCCESS) { 908 /* Add entry at free index to the SF */ 909 psServiceFlowTable->stSFList[iSfIndex].bUsed = TRUE; 910 psServiceFlowTable->stSFList[iSfIndex].uiVcid = uiVcid; 911 } 912 913 return uiStatus; 914} 915 916static UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid, 917 IN B_UINT16 uiClsId, 918 IN struct bcm_phs_entry *pstServiceFlowEntry, 919 struct bcm_phs_rule *psPhsRule, 920 B_UINT8 u8AssociatedPHSI) 921{ 922 struct bcm_phs_classifier_entry *pstClassifierEntry = NULL; 923 UINT uiStatus = PHS_SUCCESS; 924 UINT nClassifierIndex = 0; 925 struct bcm_phs_classifier_table *psaClassifiertable = NULL; 926 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 927 928 psaClassifiertable = pstServiceFlowEntry->pstClassifierTable; 929 930 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "==>"); 931 932 /* Check if the supplied Classifier already exists */ 933 nClassifierIndex = GetClassifierEntry( 934 pstServiceFlowEntry->pstClassifierTable, 935 uiClsId, 936 eActiveClassifierRuleContext, 937 &pstClassifierEntry); 938 939 if (nClassifierIndex == PHS_INVALID_TABLE_INDEX) { 940 /* 941 * The Classifier doesn't exist. So its a new classifier being added. 942 * Add new entry to associate PHS Rule to the Classifier 943 */ 944 945 uiStatus = CreateClassifierPHSRule(uiClsId, psaClassifiertable, 946 psPhsRule, 947 eActiveClassifierRuleContext, 948 u8AssociatedPHSI); 949 return uiStatus; 950 } 951 952 /* 953 * The Classifier exists.The PHS Rule for this classifier 954 * is being modified 955 */ 956 957 if (pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI) { 958 if (pstClassifierEntry->pstPhsRule == NULL) 959 return ERR_PHS_INVALID_PHS_RULE; 960 961 /* 962 * This rule already exists if any fields are changed for this PHS 963 * rule update them. 964 */ 965 /* If any part of PHSF is valid then we update PHSF */ 966 if (psPhsRule->u8PHSFLength) { 967 /* update PHSF */ 968 memcpy(pstClassifierEntry->pstPhsRule->u8PHSF, 969 psPhsRule->u8PHSF, MAX_PHS_LENGTHS); 970 } 971 972 if (psPhsRule->u8PHSFLength) { 973 /* update PHSFLen */ 974 pstClassifierEntry->pstPhsRule->u8PHSFLength = psPhsRule->u8PHSFLength; 975 } 976 977 if (psPhsRule->u8PHSMLength) { 978 /* update PHSM */ 979 memcpy(pstClassifierEntry->pstPhsRule->u8PHSM, 980 psPhsRule->u8PHSM, MAX_PHS_LENGTHS); 981 } 982 983 if (psPhsRule->u8PHSMLength) { 984 /* update PHSM Len */ 985 pstClassifierEntry->pstPhsRule->u8PHSMLength = 986 psPhsRule->u8PHSMLength; 987 } 988 989 if (psPhsRule->u8PHSS) { 990 /* update PHSS */ 991 pstClassifierEntry->pstPhsRule->u8PHSS = psPhsRule->u8PHSS; 992 } 993 994 /* update PHSV */ 995 pstClassifierEntry->pstPhsRule->u8PHSV = psPhsRule->u8PHSV; 996 } else { 997 /* A new rule is being set for this classifier. */ 998 uiStatus = UpdateClassifierPHSRule(uiClsId, pstClassifierEntry, 999 psaClassifiertable, psPhsRule, u8AssociatedPHSI); 1000 } 1001 1002 return uiStatus; 1003} 1004 1005static UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId, 1006 struct bcm_phs_classifier_table *psaClassifiertable, 1007 struct bcm_phs_rule *psPhsRule, 1008 enum bcm_phs_classifier_context eClsContext, 1009 B_UINT8 u8AssociatedPHSI) 1010{ 1011 UINT iClassifierIndex = 0; 1012 bool bFreeEntryFound = false; 1013 struct bcm_phs_classifier_entry *psClassifierRules = NULL; 1014 UINT nStatus = PHS_SUCCESS; 1015 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 1016 1017 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "Inside CreateClassifierPHSRule"); 1018 1019 if (psaClassifiertable == NULL) 1020 return ERR_INVALID_CLASSIFIERTABLE_FOR_SF; 1021 1022 if (eClsContext == eOldClassifierRuleContext) { 1023 /* 1024 * If An Old Entry for this classifier ID already exists in the 1025 * old rules table replace it. 1026 */ 1027 1028 iClassifierIndex = 1029 GetClassifierEntry(psaClassifiertable, uiClsId, 1030 eClsContext, &psClassifierRules); 1031 1032 if (iClassifierIndex != PHS_INVALID_TABLE_INDEX) { 1033 /* 1034 * The Classifier already exists in the old rules table 1035 * Lets replace the old classifier with the new one. 1036 */ 1037 bFreeEntryFound = TRUE; 1038 } 1039 } 1040 1041 if (!bFreeEntryFound) { 1042 /* Continue to search for a free location to add the rule */ 1043 for (iClassifierIndex = 0; iClassifierIndex < 1044 MAX_PHSRULE_PER_SF; iClassifierIndex++) { 1045 if (eClsContext == eActiveClassifierRuleContext) 1046 psClassifierRules = &psaClassifiertable->stActivePhsRulesList[iClassifierIndex]; 1047 else 1048 psClassifierRules = &psaClassifiertable->stOldPhsRulesList[iClassifierIndex]; 1049 1050 if (!psClassifierRules->bUsed) { 1051 bFreeEntryFound = TRUE; 1052 break; 1053 } 1054 } 1055 } 1056 1057 if (!bFreeEntryFound) { 1058 1059 if (eClsContext == eActiveClassifierRuleContext) 1060 return ERR_CLSASSIFIER_TABLE_FULL; 1061 else { 1062 /* Lets replace the oldest rule if we are looking in old Rule table */ 1063 if (psaClassifiertable->uiOldestPhsRuleIndex >= MAX_PHSRULE_PER_SF) 1064 psaClassifiertable->uiOldestPhsRuleIndex = 0; 1065 1066 iClassifierIndex = psaClassifiertable->uiOldestPhsRuleIndex; 1067 psClassifierRules = &psaClassifiertable->stOldPhsRulesList[iClassifierIndex]; 1068 1069 (psaClassifiertable->uiOldestPhsRuleIndex)++; 1070 } 1071 } 1072 1073 if (eClsContext == eOldClassifierRuleContext) { 1074 1075 if (psClassifierRules->pstPhsRule == NULL) { 1076 1077 psClassifierRules->pstPhsRule = kmalloc(sizeof(struct bcm_phs_rule), GFP_KERNEL); 1078 1079 if (NULL == psClassifierRules->pstPhsRule) 1080 return ERR_PHSRULE_MEMALLOC_FAIL; 1081 } 1082 1083 psClassifierRules->bUsed = TRUE; 1084 psClassifierRules->uiClassifierRuleId = uiClsId; 1085 psClassifierRules->u8PHSI = psPhsRule->u8PHSI; 1086 psClassifierRules->bUnclassifiedPHSRule = psPhsRule->bUnclassifiedPHSRule; 1087 1088 /* Update The PHS rule */ 1089 memcpy(psClassifierRules->pstPhsRule, psPhsRule, sizeof(struct bcm_phs_rule)); 1090 } else 1091 nStatus = UpdateClassifierPHSRule(uiClsId, psClassifierRules, 1092 psaClassifiertable, psPhsRule, u8AssociatedPHSI); 1093 1094 return nStatus; 1095} 1096 1097static UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId, 1098 IN struct bcm_phs_classifier_entry *pstClassifierEntry, 1099 struct bcm_phs_classifier_table *psaClassifiertable, 1100 struct bcm_phs_rule *psPhsRule, 1101 B_UINT8 u8AssociatedPHSI) 1102{ 1103 struct bcm_phs_rule *pstAddPhsRule = NULL; 1104 UINT nPhsRuleIndex = 0; 1105 bool bPHSRuleOrphaned = false; 1106 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 1107 1108 psPhsRule->u8RefCnt = 0; 1109 1110 /* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry */ 1111 bPHSRuleOrphaned = DerefPhsRule(uiClsId, psaClassifiertable, 1112 pstClassifierEntry->pstPhsRule); 1113 1114 /* Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in Classifier table for this SF */ 1115 nPhsRuleIndex = GetPhsRuleEntry(psaClassifiertable, u8AssociatedPHSI, 1116 eActiveClassifierRuleContext, &pstAddPhsRule); 1117 if (PHS_INVALID_TABLE_INDEX == nPhsRuleIndex) { 1118 1119 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAdding New PHSRuleEntry For Classifier"); 1120 1121 if (psPhsRule->u8PHSI == 0) { 1122 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nError PHSI is Zero\n"); 1123 return ERR_PHS_INVALID_PHS_RULE; 1124 } 1125 1126 /* Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId */ 1127 if (false == bPHSRuleOrphaned) { 1128 1129 pstClassifierEntry->pstPhsRule = kmalloc(sizeof(struct bcm_phs_rule), GFP_KERNEL); 1130 if (NULL == pstClassifierEntry->pstPhsRule) 1131 return ERR_PHSRULE_MEMALLOC_FAIL; 1132 } 1133 memcpy(pstClassifierEntry->pstPhsRule, psPhsRule, sizeof(struct bcm_phs_rule)); 1134 } else { 1135 /* Step 2.b PHS Rule Exists Tie uiClsId with the existing PHS Rule */ 1136 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nTying Classifier to Existing PHS Rule"); 1137 if (bPHSRuleOrphaned) { 1138 kfree(pstClassifierEntry->pstPhsRule); 1139 pstClassifierEntry->pstPhsRule = NULL; 1140 } 1141 pstClassifierEntry->pstPhsRule = pstAddPhsRule; 1142 } 1143 1144 pstClassifierEntry->bUsed = TRUE; 1145 pstClassifierEntry->u8PHSI = pstClassifierEntry->pstPhsRule->u8PHSI; 1146 pstClassifierEntry->uiClassifierRuleId = uiClsId; 1147 pstClassifierEntry->pstPhsRule->u8RefCnt++; 1148 pstClassifierEntry->bUnclassifiedPHSRule = pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule; 1149 1150 return PHS_SUCCESS; 1151} 1152 1153static bool DerefPhsRule(IN B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule) 1154{ 1155 if (pstPhsRule == NULL) 1156 return false; 1157 1158 if (pstPhsRule->u8RefCnt) 1159 pstPhsRule->u8RefCnt--; 1160 1161 if (0 == pstPhsRule->u8RefCnt) { 1162 /* 1163 * if(pstPhsRule->u8PHSI) 1164 * Store the currently active rule into the old rules list 1165 * CreateClassifierPHSRule(uiClsId,psaClassifiertable,pstPhsRule,eOldClassifierRuleContext,pstPhsRule->u8PHSI); 1166 */ 1167 return TRUE; 1168 } else 1169 return false; 1170} 1171 1172void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension) 1173{ 1174 int i, j, k, l; 1175 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 1176 1177 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n Dumping PHS Rules :\n"); 1178 1179 for (i = 0; i < MAX_SERVICEFLOWS; i++) { 1180 1181 struct bcm_phs_entry stServFlowEntry = 1182 pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i]; 1183 if (stServFlowEntry.bUsed) { 1184 1185 for (j = 0; j < MAX_PHSRULE_PER_SF; j++) { 1186 1187 for (l = 0; l < 2; l++) { 1188 struct bcm_phs_classifier_entry stClsEntry; 1189 1190 if (l == 0) { 1191 stClsEntry = stServFlowEntry.pstClassifierTable->stActivePhsRulesList[j]; 1192 if (stClsEntry.bUsed) 1193 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Active PHS Rule :\n"); 1194 } else { 1195 stClsEntry = stServFlowEntry.pstClassifierTable->stOldPhsRulesList[j]; 1196 if (stClsEntry.bUsed) 1197 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Old PHS Rule :\n"); 1198 } 1199 1200 if (stClsEntry.bUsed) { 1201 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID : %#X", stServFlowEntry.uiVcid); 1202 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID : %#X", stClsEntry.uiClassifierRuleId); 1203 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID : %#X", stClsEntry.u8PHSI); 1204 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n"); 1205 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI : %#X", stClsEntry.pstPhsRule->u8PHSI); 1206 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ", stClsEntry.pstPhsRule->u8PHSFLength); 1207 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : "); 1208 1209 for (k = 0 ; k < stClsEntry.pstPhsRule->u8PHSFLength; k++) 1210 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ", stClsEntry.pstPhsRule->u8PHSF[k]); 1211 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength : %#X", stClsEntry.pstPhsRule->u8PHSMLength); 1212 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :"); 1213 1214 for (k = 0; k < stClsEntry.pstPhsRule->u8PHSMLength; k++) 1215 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ", stClsEntry.pstPhsRule->u8PHSM[k]); 1216 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ", stClsEntry.pstPhsRule->u8PHSS); 1217 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV : %#X", stClsEntry.pstPhsRule->u8PHSV); 1218 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n"); 1219 } 1220 } 1221 } 1222 } 1223 } 1224} 1225 1226/* 1227 * Procedure: phs_decompress 1228 * 1229 * Description: This routine restores the static fields within the packet. 1230 * 1231 * Arguments: 1232 * in_buf - ptr to incoming packet buffer. 1233 * out_buf - ptr to output buffer where the suppressed header is copied. 1234 * decomp_phs_rules - ptr to PHS rule. 1235 * header_size - ptr to field which holds the phss or phsf_length. 1236 * 1237 * Returns: 1238 * size -The number of bytes of dynamic fields present with in the incoming packet 1239 * header. 1240 * 0 -If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed. 1241 */ 1242static int phs_decompress(unsigned char *in_buf, 1243 unsigned char *out_buf, 1244 struct bcm_phs_rule *decomp_phs_rules, 1245 UINT *header_size) 1246{ 1247 int phss, size = 0; 1248 struct bcm_phs_rule *tmp_memb; 1249 int bit, i = 0; 1250 unsigned char *phsf, *phsm; 1251 int in_buf_len = *header_size - 1; 1252 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 1253 1254 in_buf++; 1255 1256 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "====>\n"); 1257 *header_size = 0; 1258 1259 if ((decomp_phs_rules == NULL)) 1260 return 0; 1261 1262 tmp_memb = decomp_phs_rules; 1263 /* 1264 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1 %d",phsi)); 1265 * header_size = tmp_memb->u8PHSFLength; 1266 */ 1267 phss = tmp_memb->u8PHSS; 1268 phsf = tmp_memb->u8PHSF; 1269 phsm = tmp_memb->u8PHSM; 1270 1271 if (phss > MAX_PHS_LENGTHS) 1272 phss = MAX_PHS_LENGTHS; 1273 1274 /* 1275 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,"\nDECOMP: 1276 * In phs_decompress PHSI %d phss %d index %d",phsi,phss,index)); 1277 */ 1278 while ((phss > 0) && (size < in_buf_len)) { 1279 bit = ((*phsm << i) & SUPPRESS); 1280 1281 if (bit == SUPPRESS) { 1282 *out_buf = *phsf; 1283 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nDECOMP:In phss %d phsf %d ouput %d", 1284 phss, *phsf, *out_buf); 1285 } else { 1286 *out_buf = *in_buf; 1287 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL, "\nDECOMP:In phss %d input %d ouput %d", 1288 phss, *in_buf, *out_buf); 1289 in_buf++; 1290 size++; 1291 } 1292 out_buf++; 1293 phsf++; 1294 phss--; 1295 i++; 1296 *header_size = *header_size + 1; 1297 1298 if (i > MAX_NO_BIT) { 1299 i = 0; 1300 phsm++; 1301 } 1302 } 1303 1304 return size; 1305} 1306 1307/* 1308 * Procedure: phs_compress 1309 * 1310 * Description: This routine suppresses the static fields within the packet.Before 1311 * that it will verify the fields to be suppressed with the corresponding fields in the 1312 * phsf. For verification it checks the phsv field of PHS rule. If set and verification 1313 * succeeds it suppresses the field.If any one static field is found different none of 1314 * the static fields are suppressed then the packet is sent as uncompressed packet with 1315 * phsi=0. 1316 * 1317 * Arguments: 1318 * phs_rule - ptr to PHS rule. 1319 * in_buf - ptr to incoming packet buffer. 1320 * out_buf - ptr to output buffer where the suppressed header is copied. 1321 * header_size - ptr to field which holds the phss. 1322 * 1323 * Returns: 1324 * size-The number of bytes copied into the output buffer i.e dynamic fields 1325 * 0 -If PHS rule is NULL.If PHSV field is not set.If the verification fails. 1326 */ 1327static int phs_compress(struct bcm_phs_rule *phs_rule, 1328 unsigned char *in_buf, 1329 unsigned char *out_buf, 1330 UINT *header_size, 1331 UINT *new_header_size) 1332{ 1333 unsigned char *old_addr = out_buf; 1334 int suppress = 0; 1335 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 1336 1337 if (phs_rule == NULL) { 1338 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nphs_compress(): phs_rule null!"); 1339 *out_buf = ZERO_PHSI; 1340 return STATUS_PHS_NOCOMPRESSION; 1341 } 1342 1343 if (phs_rule->u8PHSS <= *new_header_size) 1344 *header_size = phs_rule->u8PHSS; 1345 else 1346 *header_size = *new_header_size; 1347 1348 /* To copy PHSI */ 1349 out_buf++; 1350 suppress = verify_suppress_phsf(in_buf, out_buf, phs_rule->u8PHSF, 1351 phs_rule->u8PHSM, phs_rule->u8PHSS, 1352 phs_rule->u8PHSV, new_header_size); 1353 1354 if (suppress == STATUS_PHS_COMPRESSED) { 1355 *old_addr = (unsigned char)phs_rule->u8PHSI; 1356 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In phs_compress phsi %d", phs_rule->u8PHSI); 1357 } else { 1358 *old_addr = ZERO_PHSI; 1359 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In phs_compress PHSV Verification failed"); 1360 } 1361 1362 return suppress; 1363} 1364 1365/* 1366 * Procedure: verify_suppress_phsf 1367 * 1368 * Description: This routine verifies the fields of the packet and if all the 1369 * static fields are equal it adds the phsi of that PHS rule.If any static 1370 * field differs it woun't suppress any field. 1371 * 1372 * Arguments: 1373 * rules_set - ptr to classifier_rules. 1374 * in_buffer - ptr to incoming packet buffer. 1375 * out_buffer - ptr to output buffer where the suppressed header is copied. 1376 * phsf - ptr to phsf. 1377 * phsm - ptr to phsm. 1378 * phss - variable holding phss. 1379 * 1380 * Returns: 1381 * size-The number of bytes copied into the output buffer i.e dynamic fields. 1382 * 0 -Packet has failed the verification. 1383 */ 1384static int verify_suppress_phsf(unsigned char *in_buffer, 1385 unsigned char *out_buffer, 1386 unsigned char *phsf, 1387 unsigned char *phsm, 1388 unsigned int phss, 1389 unsigned int phsv, 1390 UINT *new_header_size) 1391{ 1392 unsigned int size = 0; 1393 int bit, i = 0; 1394 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 1395 1396 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In verify_phsf PHSM - 0x%X", *phsm); 1397 1398 if (phss > (*new_header_size)) 1399 phss = *new_header_size; 1400 1401 while (phss > 0) { 1402 bit = ((*phsm << i) & SUPPRESS); 1403 if (bit == SUPPRESS) { 1404 if (*in_buffer != *phsf) { 1405 if (phsv == VERIFY) { 1406 BCM_DEBUG_PRINT(Adapter, 1407 DBG_TYPE_OTHERS, 1408 PHS_SEND, 1409 DBG_LVL_ALL, 1410 "\nCOMP:In verify_phsf failed for field %d buf %d phsf %d", 1411 phss, 1412 *in_buffer, 1413 *phsf); 1414 return STATUS_PHS_NOCOMPRESSION; 1415 } 1416 } else 1417 BCM_DEBUG_PRINT(Adapter, 1418 DBG_TYPE_OTHERS, 1419 PHS_SEND, 1420 DBG_LVL_ALL, 1421 "\nCOMP:In verify_phsf success for field %d buf %d phsf %d", 1422 phss, 1423 *in_buffer, 1424 *phsf); 1425 } else { 1426 *out_buffer = *in_buffer; 1427 BCM_DEBUG_PRINT(Adapter, 1428 DBG_TYPE_OTHERS, 1429 PHS_SEND, 1430 DBG_LVL_ALL, 1431 "\nCOMP:In copying_header input %d out %d", 1432 *in_buffer, 1433 *out_buffer); 1434 out_buffer++; 1435 size++; 1436 } 1437 1438 in_buffer++; 1439 phsf++; 1440 phss--; 1441 i++; 1442 1443 if (i > MAX_NO_BIT) { 1444 i = 0; 1445 phsm++; 1446 } 1447 } 1448 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "\nCOMP:In verify_phsf success"); 1449 *new_header_size = size; 1450 return STATUS_PHS_COMPRESSED; 1451}