Beispiel #1
0
VOID MeshClonePacket(
	IN PRTMP_ADAPTER pAd,
	IN PNDIS_PACKET pPacket,
	IN UINT8 MeshSrc,
	IN UINT8 MeshLinkIdx)
{
	INT idx;
	PUCHAR pSA = NULL;
	PUCHAR pDA = NULL;

	for (idx = 0; idx < MAX_MESH_LINKS; idx++)
	{
		if ((MeshSrc == MESH_FORWARD)
			&& (MeshLinkIdx == idx))
			continue;

		pSA = GET_OS_PKT_DATAPTR(pPacket) + MAC_ADDR_LEN;
		if (MAC_ADDR_EQUAL(pAd->MeshTab.MeshLink[idx].Entry.PeerMacAddr, pSA))
			continue;

		pDA = GET_OS_PKT_DATAPTR(pPacket);
		if (IS_MULTICAST_MAC_ADDR(pDA)
			&& (MultipathEntryLookUp(pAd, idx, pSA) != NULL))
			continue;

		if (PeerLinkValidCheck(pAd, idx) == TRUE)
		{
			PNDIS_PACKET pPacketClone;

/*			pPacketClone = skb_clone(RTPKT_TO_OSPKT(pPacket), GFP_ATOMIC); */
			OS_PKT_CLONE(pAd, pPacket, pPacketClone, GFP_ATOMIC);
			if (pPacketClone == NULL)
				continue;

			RTMP_SET_PACKET_NET_DEVICE_MESH(pPacketClone, 0);
			RTMP_SET_PACKET_SOURCE(pPacketClone, PKTSRC_NDIS);
			RTMP_SET_PACKET_MOREDATA(pPacketClone, FALSE);
			RTMP_SET_PACKET_WCID(pPacketClone, pAd->MeshTab.MeshLink[idx].Entry.MacTabMatchWCID);
			RTMP_SET_MESH_ROUTE_ID(pPacketClone, BMCAST_ROUTE_ID);
			RTMP_SET_MESH_SOURCE(pPacketClone, MeshSrc);
#ifdef CONFIG_AP_SUPPORT
			APSendPacket(pAd, pPacketClone);
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
			STASendPacket(pAd, pPacketClone);
#endif /* CONFIG_STA_SUPPORT */
		}
	}

	return;
}
/*
========================================================================
Routine Description:
    Send a packet to WLAN.

Arguments:
    skb_p           points to our adapter
    dev_p           which WLAN network interface

Return Value:
    0: transmit successfully
    otherwise: transmit fail

Note:
========================================================================
*/
INT ApCli_VirtualIF_PacketSend(
	IN PNDIS_PACKET 	skb_p, 
	IN PNET_DEV			dev_p)
{
	RTMP_ADAPTER *ad_p;
	PAPCLI_STRUCT pApCli;
	INT apcliIndex;



	ad_p = RTMP_OS_NETDEV_GET_PRIV(dev_p);
	ASSERT(ad_p);

#ifdef RALINK_ATE
	if (ATE_ON(ad_p))
	{
		RELEASE_NDIS_PACKET(ad_p, skb_p, NDIS_STATUS_FAILURE);
		return 0;
	}
#endif // RALINK_ATE //

	if ((RTMP_TEST_FLAG(ad_p, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
		(RTMP_TEST_FLAG(ad_p, fRTMP_ADAPTER_RADIO_OFF))          ||
		(RTMP_TEST_FLAG(ad_p, fRTMP_ADAPTER_RESET_IN_PROGRESS)))
	{
		/* wlan is scanning/disabled/reset */
		RELEASE_NDIS_PACKET(ad_p, skb_p, NDIS_STATUS_FAILURE);
		return 0;
	}

	if (!(RTMP_OS_NETDEV_STATE_RUNNING(dev_p)))
	{
		/* the interface is down */
		RELEASE_NDIS_PACKET(ad_p, skb_p, NDIS_STATUS_FAILURE);
		return 0;
	}


	pApCli = (PAPCLI_STRUCT)&ad_p->ApCfg.ApCliTab;

	for(apcliIndex = 0; apcliIndex < MAX_APCLI_NUM; apcliIndex++)
	{
		if (pApCli[apcliIndex].Valid != TRUE)
			continue;

		/* find the device in our ApCli list */
		if (pApCli[apcliIndex].dev == dev_p)
		{
			/* ya! find it */
			ad_p->RalinkCounters.PendingNdisPacketCount ++;
			RTMP_SET_PACKET_MOREDATA(skb_p, FALSE);
			RTMP_SET_PACKET_NET_DEVICE_APCLI(skb_p, apcliIndex);
			SET_OS_PKT_NETDEV(skb_p, ad_p->net_dev);


			/* transmit the packet */
			return rt28xx_packet_xmit(RTPKT_TO_OSPKT(skb_p));
		}
    }

	RELEASE_NDIS_PACKET(ad_p, skb_p, NDIS_STATUS_FAILURE);

	return 0;
} /* End of ApCli_VirtualIF_PacketSend */
Beispiel #3
0
/*
  ========================================================================
  Description:
	This routine frees all packets in PSQ that's destined to a specific DA.
	BCAST/MCAST in DTIMCount=0 case is also handled here, just like a PS-POLL 
	is received from a WSTA which has MAC address FF:FF:FF:FF:FF:FF
  ========================================================================
*/
VOID RtmpHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT wcid, BOOLEAN isActive)
{ 
	QUEUE_ENTRY *pQEntry;
	MAC_TABLE_ENTRY *pMacEntry;
	unsigned long IrqFlags;

	/*
	DBGPRINT(RT_DEBUG_TRACE, ("rcv PS-POLL (AID=%d) from %02x:%02x:%02x:%02x:%02x:%02x\n",
				Aid, PRINT_MAC(pAddr)));
	*/

	pMacEntry = &pAd->MacTab.Content[wcid];
	if (RTMPEqualMemory(pMacEntry->Addr, pAddr, MAC_ADDR_LEN))
	{
#ifdef DROP_MASK_SUPPORT
		/* Disable Drop Mask */
		set_drop_mask_per_client(pAd, pMacEntry, 2, 0);
#endif /* DROP_MASK_SUPPORT */

#ifdef PS_ENTRY_MAITENANCE
		pMacEntry->continuous_ps_count = 0;
#endif /* PS_ENTRY_MAITENANCE */

		/* Sta is change to Power Active stat. Reset ContinueTxFailCnt */
		pMacEntry->ContinueTxFailCnt = 0;

#ifdef UAPSD_SUPPORT
		if (UAPSD_MR_IS_ALL_AC_UAPSD(isActive, pMacEntry))
		{
			/*
				IEEE802.11e spec.
				11.2.1.7 Receive operation for STAs in PS mode during the CP
				When a non-AP QSTA that is using U-APSD and has all ACs
				delivery-enabled detects that the bit corresponding to its AID
				is set in the TIM, the non-AP QSTA shall issue a trigger frame
				or a PS-Poll frame to retrieve the buffered MSDU or management
				frames.

				WMM Spec. v1.1a 070601
				3.6.2	U-APSD STA Operation
				3.6.2.3	In case one or more ACs are not
				delivery-enabled ACs, the WMM STA may retrieve MSDUs and
				MMPDUs belonging to those ACs by sending PS-Polls to the WMM AP.
				In case all ACs are delivery enabled ACs, WMM STA should only
				use trigger frames to retrieve MSDUs and MMPDUs belonging to
				those ACs, and it should not send PS-Poll frames.

				Different definitions in IEEE802.11e and WMM spec.
				But we follow the WiFi WMM Spec.
			*/

			DBGPRINT(RT_DEBUG_TRACE, ("All AC are UAPSD, can not use PS-Poll\n"));
			return; /* all AC are U-APSD, can not use PS-Poll */
		}
#endif /* UAPSD_SUPPORT */

		RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
		if (isActive == FALSE)
		{
			if (pMacEntry->PsQueue.Head)
			{
#ifdef UAPSD_SUPPORT
				UINT32 NumOfOldPsPkt;
				NumOfOldPsPkt = pAd->TxSwQueue[QID_AC_BE].Number;
#endif /* UAPSD_SUPPORT */

				pQEntry = RemoveHeadQueue(&pMacEntry->PsQueue);
				if ( pMacEntry->PsQueue.Number >=1 )
					RTMP_SET_PACKET_MOREDATA(RTPKT_TO_OSPKT(pQEntry), TRUE);
				InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pQEntry);

#ifdef UAPSD_SUPPORT
				/* we need to call RTMPDeQueuePacket() immediately as below */
				if (NumOfOldPsPkt != pAd->TxSwQueue[QID_AC_BE].Number)
				{
					if (RTMP_GET_PACKET_DHCP(RTPKT_TO_OSPKT(pQEntry)) ||
						RTMP_GET_PACKET_EAPOL(RTPKT_TO_OSPKT(pQEntry)) ||
						RTMP_GET_PACKET_WAI(RTPKT_TO_OSPKT(pQEntry)))
					{
						/*
							These packets will use 1M/6M rate to send.
							If you use 1M(2.4G)/6M(5G) to send, no statistics
							count in NICUpdateFifoStaCounters().

							So we can not count it for UAPSD; Or the SP will
							not closed until timeout.
						*/
					}
					else
						UAPSD_MR_MIX_PS_POLL_RCV(pAd, pMacEntry);
				}
#endif /* UAPSD_SUPPORT */
			}
			else
			{
				/*
					or transmit a (QoS) Null Frame;

					In addtion, in Station Keep Alive mechanism, we need to
					send a QoS Null frame to detect the station live status.
				*/
				BOOLEAN bQosNull = FALSE;

				if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
					bQosNull = TRUE;

				RtmpEnqueueNullFrame(pAd, pMacEntry->Addr, pMacEntry->CurrTxRate,
										pMacEntry->Aid, pMacEntry->apidx,
										bQosNull, TRUE, 0);
			}
		}
		else
		{
#ifdef UAPSD_SUPPORT
			/* deliver all queued UAPSD packets */
			UAPSD_AllPacketDeliver(pAd, pMacEntry);

			/* end the SP if exists */
			UAPSD_MR_ENTRY_RESET(pAd, pMacEntry);
#endif /* UAPSD_SUPPORT */

			while(pMacEntry->PsQueue.Head)
			{
				pQEntry = RemoveHeadQueue(&pMacEntry->PsQueue);
				InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pQEntry);
			}
		}

		if ((pMacEntry->Aid > 0) && (pMacEntry->Aid < MAX_LEN_OF_MAC_TABLE) &&
			(pMacEntry->PsQueue.Number == 0))
		{
			/* clear corresponding TIM bit because no any PS packet */
#ifdef CONFIG_AP_SUPPORT
			if(pMacEntry->wdev->wdev_type == WDEV_TYPE_AP)
			{
				WLAN_MR_TIM_BIT_CLEAR(pAd, pMacEntry->apidx, pMacEntry->Aid);
			}
#endif /* CONFIG_AP_SUPPORT */
			pMacEntry->PsQIdleCount = 0;
		}

		RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);

		/*
			Dequeue outgoing frames from TxSwQueue0..3 queue and process it
			TODO: 2004-12-27 it's not a good idea to handle "More Data" bit here. 
				because the RTMPDeQueue process doesn't guarantee to de-queue the 
				desired MSDU from the corresponding TxSwQueue/PsQueue when QOS 
				in-used. We should consider "HardTransmt" this MPDU using MGMT 
				queue or things like that.
		*/
		RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
	}
	else
	{
		DBGPRINT(RT_DEBUG_ERROR,("rcv PS-POLL (AID=%d not match) from %02x:%02x:%02x:%02x:%02x:%02x\n", 
			  pMacEntry->Aid, PRINT_MAC(pAddr)));

	}
}
Beispiel #4
0
/*
  ========================================================================
  Description:
	This routine frees all packets in PSQ that's destined to a specific DA.
	BCAST/MCAST in DTIMCount=0 case is also handled here, just like a PS-POLL 
	is received from a WSTA which has MAC address FF:FF:FF:FF:FF:FF
  ========================================================================
*/
VOID MtHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT wcid, BOOLEAN isActive)
{
#ifdef CONFIG_AP_SUPPORT
#if defined(MT_PS) || defined(UAPSD_SUPPORT)
	MAC_TABLE_ENTRY *pMacEntry;
#endif
	STA_TR_ENTRY *tr_entry;
	BOOLEAN       IsDequeu= FALSE;
	INT           DequeuAC = QID_AC_BE;
	INT           DequeuCOUNT;
#ifdef MT_PS
	INT i, Total_Packet_Number = 0;
#endif /* MT_PS */
	//struct tx_swq_fifo *fifo_swq;

	ASSERT(wcid < MAX_LEN_OF_MAC_TABLE);
#if defined(MT_PS) || defined(UAPSD_SUPPORT)
	pMacEntry = &pAd->MacTab.Content[wcid];
#endif
	tr_entry = &pAd->MacTab.tr_entry[wcid];
	
	if (isActive == FALSE) /* ps poll */
	{
#ifdef MT_PS
		if (tr_entry->ps_state == APPS_RETRIEVE_DONE) /*state is finish(sleep)*/
		{				
			if (pMacEntry->i_psm == I_PSM_DISABLE)
			{
				MT_SET_IGNORE_PSM(pAd, pMacEntry, I_PSM_ENABLE);
			}
		}

		if(tr_entry->ps_state == APPS_RETRIEVE_DONE || tr_entry->ps_state == APPS_RETRIEVE_IDLE)
		{
			for (i = 0; i < WMM_QUE_NUM; i++)
				Total_Packet_Number = Total_Packet_Number + tr_entry->tx_queue[i].Number;

			if (Total_Packet_Number > 0)
			{
				{
					DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_PS, ("RtmpHandleRxPsPoll fetch tx queue tr_entry->ps_queue.Number= %x tr_entry->tx_queue[0].Number=%x Total_Packet_Number=%x\n",
						tr_entry->ps_queue.Number, tr_entry->tx_queue[QID_AC_BE].Number, Total_Packet_Number));

					for (i = (WMM_QUE_NUM - 1); i >=0; i--)
					{
						if (tr_entry->tx_queue[i].Head)
						{
							if (Total_Packet_Number > 1)
							{
								RTMP_SET_PACKET_MOREDATA(RTPKT_TO_OSPKT(tr_entry->tx_queue[i].Head), TRUE);
							}
							RTMP_SET_PACKET_TXTYPE(RTPKT_TO_OSPKT(tr_entry->tx_queue[i].Head), TX_LEGACY_FRAME);

							DequeuAC = i;
							IsDequeu = TRUE;
							DequeuCOUNT = 1;
							tr_entry->PsQIdleCount = 0;
							break;
						}
					}               
				}
			}
			else /* Recieve ps_poll but no packet==>send NULL Packet */
			{ 
				BOOLEAN bQosNull = FALSE;
				DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("RtmpHandleRxPsPoll no packet tr_entry->ps_queue.Number= %x tr_entry->tx_queue[0].Number=%x Total_Packet_Number=%x\n" 
					,tr_entry->ps_queue.Number, tr_entry->tx_queue[QID_AC_BE].Number, Total_Packet_Number));
				if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
					bQosNull = TRUE;

				RtmpEnqueueNullFrame(pAd, pMacEntry->Addr, tr_entry->CurrTxRate,
				pMacEntry->Aid, pMacEntry->func_tb_idx,
				bQosNull, TRUE, 0);
			} 
			if (Total_Packet_Number >1)
			{
				WLAN_MR_TIM_BIT_SET(pAd, tr_entry->func_tb_idx, tr_entry->wcid);
			} 
			else 
			{
				WLAN_MR_TIM_BIT_CLEAR(pAd, tr_entry->func_tb_idx, tr_entry->wcid);
			}
		} else
			tr_entry->PsDeQWaitCnt = 0;
#else
		/*
			Need to check !! @20140212
			New architecture has per AC sw-Q for per entry.
			We should check packets by ACs priority --> 1. VO, 2. VI, 3. BE, 4. BK
		*/
		DequeuAC = QID_AC_BE;
		IsDequeu = TRUE;
		DequeuCOUNT = 1;
		tr_entry->PsQIdleCount = 0;
#endif /* Ps_poll and ifndef MT_PS */

	}        
	else /* Receive Power bit 0 frame */ 
	{
		WLAN_MR_TIM_BIT_CLEAR(pAd, tr_entry->func_tb_idx, tr_entry->wcid);
#ifdef MT_PS
		if (pMacEntry->i_psm == I_PSM_ENABLE)
		{
			MT_SET_IGNORE_PSM(pAd, pMacEntry, I_PSM_DISABLE);
		}
#endif /*Power bit is 1 and ifndef MT_PS */

		DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("RtmpHandleRxPsPoll null0/1 wcid = %x mt_ps_queue.Number = %d\n",
			tr_entry->wcid,
			tr_entry->ps_queue.Number));

		DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s(%d) tx_queue.Number = BE:%d, BK:%d, VI:%d, VO:%d, ps_state:%x,  tx_queue.TokenCount = BE:%d, BK:%d, VI:%d, VO:%d\n",
			__FUNCTION__, __LINE__,
			tr_entry->tx_queue[QID_AC_BE].Number,
			tr_entry->tx_queue[QID_AC_BK].Number,
			tr_entry->tx_queue[QID_AC_VI].Number,
			tr_entry->tx_queue[QID_AC_VO].Number,
			tr_entry->ps_state,
			tr_entry->TokenCount[QID_AC_BE],
			tr_entry->TokenCount[QID_AC_BK],
			tr_entry->TokenCount[QID_AC_VI],
			tr_entry->TokenCount[QID_AC_VO]));

#ifdef UAPSD_SUPPORT
		if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_APSD_CAPABLE))
		{
			/* deliver all queued UAPSD packets */
			UAPSD_AllPacketDeliver(pAd, pMacEntry);

			/* end the SP if exists */
			UAPSD_MR_ENTRY_RESET(pAd, pMacEntry);
		}
#endif /* UAPSD_SUPPORT */

		if (tr_entry->enqCount > 0) 
		{
			IsDequeu = TRUE;
			DequeuAC = NUM_OF_TX_RING;
			if (tr_entry->enqCount > MAX_TX_PROCESS)
			{
				DequeuCOUNT = MAX_TX_PROCESS;
				rtmp_ps_enq(pAd,tr_entry);
			}
			else
			{
				DequeuCOUNT = tr_entry->enqCount;
			}
		}
	}   

	if (IsDequeu == TRUE)
	{
		RTMPDeQueuePacket(pAd, FALSE, DequeuAC, tr_entry->wcid, DequeuCOUNT);
		DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("RtmpHandleRxPsPoll IsDequeu == TRUE tr_entry->wcid=%x DequeuCOUNT=%d, ps_state=%d\n",tr_entry->wcid, DequeuCOUNT, tr_entry->ps_state));
	}    
	return;
	
#endif /* CONFIG_AP_SUPPORT */
}
void tbtt_tasklet(unsigned long data)
{
//#define MAX_TX_IN_TBTT		(16)

#ifdef CONFIG_AP_SUPPORT
		PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;

#ifdef RTMP_MAC_PCI
	if (pAd->OpMode == OPMODE_AP)
	{
#ifdef AP_QLOAD_SUPPORT
		/* update channel utilization */
		QBSS_LoadUpdate(pAd, 0);
#endif // AP_QLOAD_SUPPORT //

	}
#endif // RTMP_MAC_PCI //

	if (pAd->OpMode == OPMODE_AP)
	{
		//
		// step 7 - if DTIM, then move backlogged bcast/mcast frames from PSQ to TXQ whenever DtimCount==0
#ifdef RTMP_MAC_PCI
		// NOTE: This updated BEACON frame will be sent at "next" TBTT instead of at cureent TBTT. The reason is
		//       because ASIC already fetch the BEACON content down to TX FIFO before driver can make any
		//       modification. To compenstate this effect, the actual time to deilver PSQ frames will be
		//       at the time that we wrapping around DtimCount from 0 to DtimPeriod-1
		if (pAd->ApCfg.DtimCount == 0)
#endif // RTMP_MAC_PCI //
		{
			PQUEUE_ENTRY    pEntry;
			BOOLEAN			bPS = FALSE;
			UINT 			count = 0;
			unsigned long 		IrqFlags;

//			NdisAcquireSpinLock(&pAd->MacTabLock);
//			NdisAcquireSpinLock(&pAd->TxSwQueueLock);
			
			RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
			while (pAd->MacTab.McastPsQueue.Head)
			{
				bPS = TRUE;
				if (pAd->TxSwQueue[QID_AC_BE].Number <= (MAX_PACKETS_IN_QUEUE + MAX_PACKETS_IN_MCAST_PS_QUEUE))
				{
					pEntry = RemoveHeadQueue(&pAd->MacTab.McastPsQueue);
					//if(pAd->MacTab.McastPsQueue.Number)
					if (count)
					{
						RTMP_SET_PACKET_MOREDATA(pEntry, TRUE);
					}
					InsertHeadQueue(&pAd->TxSwQueue[QID_AC_BE], pEntry);
					count++;
				}
				else
				{
					break;
				}
			}
			RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
			
			
//			NdisReleaseSpinLock(&pAd->TxSwQueueLock);
//			NdisReleaseSpinLock(&pAd->MacTabLock);
			if (pAd->MacTab.McastPsQueue.Number == 0)
			{			
                UINT bss_index;

                /* clear MCAST/BCAST backlog bit for all BSS */
                for(bss_index=BSS0; bss_index<pAd->ApCfg.BssidNum; bss_index++)
					WLAN_MR_TIM_BCMC_CLEAR(bss_index);
                /* End of for */
			}
			pAd->MacTab.PsQIdleCount = 0;

			// Dequeue outgoing framea from TxSwQueue0..3 queue and process it
            if (bPS == TRUE) 
			{
				RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, /*MAX_TX_IN_TBTT*/MAX_PACKETS_IN_MCAST_PS_QUEUE);
			}
		}
	}
#endif // CONFIG_AP_SUPPORT //
}