/**
@file HandleControlPacket.c
This file contains the routines to deal with
sending and receiving of control packets.
*/
#include "headers.h"

/**
When a control packet is received, analyze the
"status" and call appropriate response function.
Enqueue the control packet for Application.
@return None
*/
VOID handle_rx_control_packet(PMINI_ADAPTER Adapter, 	/**<Pointer to the Adapter structure*/
								struct sk_buff *skb)				/**<Pointer to the socket buffer*/
{
	PPER_TARANG_DATA	pTarang = NULL;
	BOOLEAN HighPriorityMessage = FALSE;
	struct sk_buff * newPacket = NULL;
	CHAR cntrl_msg_mask_bit = 0;
	BOOLEAN drop_pkt_flag = TRUE ;
	USHORT usStatus = *(PUSHORT)(skb->data);
	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "=====>");
	/* Get the Leader field */

	switch(usStatus)
	{
		case CM_RESPONSES:               // 0xA0
			BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "MAC Version Seems to be Non Multi-Classifier, rejected by Driver");
			HighPriorityMessage = TRUE ;
			break;
		case CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP:
			HighPriorityMessage = TRUE ;
			if(Adapter->LinkStatus==LINKUP_DONE)
			{
				CmControlResponseMessage(Adapter,(skb->data +sizeof(USHORT)));
			}
			break;
		case LINK_CONTROL_RESP:          //0xA2
		case STATUS_RSP:          //0xA1
			BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,"LINK_CONTROL_RESP");
			HighPriorityMessage = TRUE ;
			LinkControlResponseMessage(Adapter,(skb->data + sizeof(USHORT)));
			break;
		case STATS_POINTER_RESP:       //0xA6
			HighPriorityMessage = TRUE ;
			StatisticsResponse(Adapter, (skb->data + sizeof(USHORT)));
			break;
		case IDLE_MODE_STATUS:			//0xA3
			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,"IDLE_MODE_STATUS Type Message Got from F/W");
			InterfaceIdleModeRespond(Adapter, (PUINT)(skb->data +
						sizeof(USHORT)));
			HighPriorityMessage = TRUE ;
			break;

		case AUTH_SS_HOST_MSG:
			HighPriorityMessage = TRUE ;
			break;

	 	default:
			BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,"Got Default Response");
			/* Let the Application Deal with This Packet */
			break;
	}

	//Queue The Control Packet to The Application Queues
	down(&Adapter->RxAppControlQueuelock);

	for (pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next)
    {
       	if(Adapter->device_removed)
		{
			break;
		}

		drop_pkt_flag = TRUE ;
		/*
			There are cntrl msg from A0 to AC. It has been mapped to 0 to C bit in the cntrl mask.
			Also, by default AD to BF has been masked to the rest of the bits... which wil be ON by default.
			if mask bit is enable to particular pkt status, send it out to app else stop it.
		*/
		cntrl_msg_mask_bit = (usStatus & 0x1F);
		//printk("\ninew  msg  mask bit which is disable in mask:%X", cntrl_msg_mask_bit);
		if(pTarang->RxCntrlMsgBitMask & (1<<cntrl_msg_mask_bit))
				drop_pkt_flag = FALSE;

		if ((drop_pkt_flag == TRUE)  || (pTarang->AppCtrlQueueLen > MAX_APP_QUEUE_LEN) ||
					((pTarang->AppCtrlQueueLen > MAX_APP_QUEUE_LEN/2) && (HighPriorityMessage == FALSE)))
		{
			/*
				Assumption:-
				1. every tarang manages it own dropped pkt statitistics
				2. Total packet dropped per tarang will be equal to the sum of all types of dropped
					pkt by that tarang only.

			*/
			switch(*(PUSHORT)skb->data)
			{
				case CM_RESPONSES:
					pTarang->stDroppedAppCntrlMsgs.cm_responses++;
					break;
				case CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP:
				 pTarang->stDroppedAppCntrlMsgs.cm_control_newdsx_multiclassifier_resp++;
					 break;
				case LINK_CONTROL_RESP:
					pTarang->stDroppedAppCntrlMsgs.link_control_resp++;
					break;
				case STATUS_RSP:
					pTarang->stDroppedAppCntrlMsgs.status_rsp++;
					break;
				case STATS_POINTER_RESP:
					pTarang->stDroppedAppCntrlMsgs.stats_pointer_resp++;
					break;
				case IDLE_MODE_STATUS:
					pTarang->stDroppedAppCntrlMsgs.idle_mode_status++ ;
					break;
				case AUTH_SS_HOST_MSG:
					pTarang->stDroppedAppCntrlMsgs.auth_ss_host_msg++ ;
					break;
			default:
					pTarang->stDroppedAppCntrlMsgs.low_priority_message++ ;
					break;
			}

			continue;
		}

        newPacket = skb_clone(skb, GFP_KERNEL);
        if (!newPacket)
           break;
        ENQUEUEPACKET(pTarang->RxAppControlHead,pTarang->RxAppControlTail,
				newPacket);
        pTarang->AppCtrlQueueLen++;
    }
	up(&Adapter->RxAppControlQueuelock);
    wake_up(&Adapter->process_read_wait_queue);
    bcm_kfree_skb(skb);
	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "After wake_up_interruptible");
}

/**
@ingroup ctrl_pkt_functions
Thread to handle control pkt reception
*/
int control_packet_handler  (PMINI_ADAPTER Adapter  /**< pointer to adapter object*/
						)
{
	struct sk_buff *ctrl_packet= NULL;
	unsigned long flags = 0;
	//struct timeval tv ;
	//int *puiBuffer = NULL ;
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "Entering to make thread wait on control packet event!");
	while(1)
	{
		wait_event_interruptible(Adapter->process_rx_cntrlpkt,
								 atomic_read(&Adapter->cntrlpktCnt) ||
								 Adapter->bWakeUpDevice ||
								 kthread_should_stop()
								);


		if(kthread_should_stop())
		{
			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "Exiting \n");
			return 0;
		}
		if(TRUE == Adapter->bWakeUpDevice)
		{
			Adapter->bWakeUpDevice = FALSE;
			if((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) &&
				((TRUE == Adapter->IdleMode)|| (TRUE == Adapter->bShutStatus)))
			{
				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "Calling InterfaceAbortIdlemode\n");
	//			Adapter->bTriedToWakeUpFromlowPowerMode = TRUE;
				InterfaceIdleModeWakeup (Adapter);
			}
			continue;
		}

		while(atomic_read(&Adapter->cntrlpktCnt))
		{
			spin_lock_irqsave(&Adapter->control_queue_lock, flags);
			ctrl_packet = Adapter->RxControlHead;
			if(ctrl_packet)
			{
				DEQUEUEPACKET(Adapter->RxControlHead,Adapter->RxControlTail);
//				Adapter->RxControlHead=ctrl_packet->next;
				((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.rx_packets++;
				((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.rx_bytes+=
				((PLEADER)ctrl_packet->data)->PLength;
			}
			#if 0  //Idle mode debug profiling...
			if(*(PUSHORT)ctrl_packet->data == IDLE_MODE_STATUS)
			{
				puiBuffer = (PUINT)(ctrl_packet->data +sizeof(USHORT));
				if((ntohl(*puiBuffer) == GO_TO_IDLE_MODE_PAYLOAD))
				{
					memset(&tv, 0, sizeof(tv));
					do_gettimeofday(&tv);
					if((ntohl(*(puiBuffer+1)) == 0))
					{
						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "IdleMode Wake-up Msg from f/w at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000);
					}
					else
					{
					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "IdleMode req Msg from f/w at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000);
					}
				}
				else if((ntohl(*puiBuffer) == IDLE_MODE_SF_UPDATE_MSG))
				{
					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "GOT IDLE_MODE_SF_UPDATE MSG at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000);
				}
			}
			#endif

			spin_unlock_irqrestore (&Adapter->control_queue_lock, flags);
		 	handle_rx_control_packet(Adapter, ctrl_packet);
			atomic_dec(&Adapter->cntrlpktCnt);
		}

		SetUpTargetDsxBuffers(Adapter);
	}
	return STATUS_SUCCESS;
}

INT flushAllAppQ(void)
{
	PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
	PPER_TARANG_DATA	pTarang = NULL;
	struct sk_buff *PacketToDrop = NULL;
	for(pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next)
	{
		while(pTarang->RxAppControlHead != NULL)
		{
			PacketToDrop=pTarang->RxAppControlHead;
			DEQUEUEPACKET(pTarang->RxAppControlHead,pTarang->RxAppControlTail);
			bcm_kfree_skb(PacketToDrop);
		}
		pTarang->AppCtrlQueueLen = 0;
		//dropped contrl packet statistics also should be reset.
		memset((PVOID)&pTarang->stDroppedAppCntrlMsgs, 0, sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES));

	}
	return STATUS_SUCCESS ;
}


