235 lines · 6.8 KB · C
RawDownload
/** * @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;}