aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/bcm/HandleControlPacket.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/bcm/HandleControlPacket.c')
-rw-r--r--drivers/staging/bcm/HandleControlPacket.c247
1 files changed, 247 insertions, 0 deletions
diff --git a/drivers/staging/bcm/HandleControlPacket.c b/drivers/staging/bcm/HandleControlPacket.c
new file mode 100644
index 000000000000..7b2ec28a4bc1
--- /dev/null
+++ b/drivers/staging/bcm/HandleControlPacket.c
@@ -0,0 +1,247 @@
+/**
+@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 ;
+}
+
+