diff options
Diffstat (limited to 'drivers/staging/bcm/HandleControlPacket.c')
| -rw-r--r-- | drivers/staging/bcm/HandleControlPacket.c | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/drivers/staging/bcm/HandleControlPacket.c b/drivers/staging/bcm/HandleControlPacket.c new file mode 100644 index 00000000000..495fe3dc514 --- /dev/null +++ b/drivers/staging/bcm/HandleControlPacket.c @@ -0,0 +1,235 @@ +/** + * @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(struct bcm_mini_adapter *Adapter, struct sk_buff *skb) +{ + struct bcm_tarang_data *pTarang = NULL; + bool HighPriorityMessage = false; + struct sk_buff *newPacket = NULL; + CHAR cntrl_msg_mask_bit = 0; + bool 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(struct bcm_mini_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) +{ + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_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(struct bcm_mibs_dropped_cntrl_msg)); + + } + return STATUS_SUCCESS; +} + + |
