/** * @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 */ static VOID handle_rx_control_packet(PMINI_ADAPTER Adapter, struct sk_buff *skb) { 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); if (netif_msg_pktdata(Adapter)) print_hex_dump(KERN_DEBUG, PFX "rx control: ", DUMP_PREFIX_NONE, 16, 1, skb->data, skb->len, 0); 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); dev_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; */ } 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); dev_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; }