Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.9.4.
   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 output %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 output %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}