]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/staging/bcm/HandleControlPacket.c
Merge branch 'master' into csb1725
[mv-sheeva.git] / drivers / staging / bcm / HandleControlPacket.c
diff --git a/drivers/staging/bcm/HandleControlPacket.c b/drivers/staging/bcm/HandleControlPacket.c
new file mode 100644 (file)
index 0000000..7b2ec28
--- /dev/null
@@ -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 ;
+}
+
+