236 lines
6.8 KiB
C
236 lines
6.8 KiB
C
/**
|
|
* @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;
|
|
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(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(S_MIBS_DROPPED_APP_CNTRL_MESSAGES));
|
|
|
|
}
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|