⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtl865x_fast.c

📁 Ralink RT61 SoftAP Driver source code. RT61:MiniPCI
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifdef RTL865X_FAST_PATH 

#include "rt_config.h"
#include "re865x/rtl865x/mbuf.h" 
#include "re865x/rtl865x/rtl8651_tblDrvFwd.h"
#include "re865x/rtl865x/rtl8651_tblAsicDrv.h"
#include "re865x/rtl865x/rtl8651_tblDrv.h"

/* ============================ Declaration ============================ */
static inline void rtl865x_extDev_set_skb_property(	u16 pktType,
													struct sk_buff *skb,
													struct net_device *dev,
													struct rtl_pktHdr *pktHdr,
													u16 rxIdx);
static inline void rtl865x_extDev_clr_skb_property(	struct sk_buff *skb);
static struct sk_buff *rtl865x_extDev_alloc_skb (	u32 length,
												u32 headroom,
												u16 rxIdx,
												struct net_device *dev);
static void rtl865x_extDev_actualFreeRxRingSkb(struct sk_buff *skb);

static int rtl865x_extDev_mbuf2Skb(struct net_device *dev, struct sk_buff *skb);
static void rtl865x_extDev_rx_skb(struct net_device *dev, struct sk_buff *skb);


int rtl865x_extDev_addHost (	u8 *hostMac,
								u16 vid,
								unsigned int linkid);
int rtl865x_extDev_removeHost (	u8 *hostMac,
								u16 vid);

int rtl865x_extDev_unicastFastRecv (	struct sk_buff *skb,
												u16 vid,
												struct net_device *dev);
static int rtl865x_extDev_rxRunoutTxPending(	struct sk_buff *skb,
												struct net_device *dev);
static int rtl865x_extDev_pktUcastTx(struct rtl_pktHdr *pkt);
static void rtl865x_extDev_pktFree(struct rtl_pktHdr *pkt);
/*
	design note:

	[chenyl] In order to simplify the flow, we only speed up single 8139CP.
*/
static struct net_device *rt61_txDev = NULL;
static int rt61_activeCnt = 0;
static int rt61_firstPkt = 0;

/* ============================ Implementation ============================ */

/* ======================================================
						Library
     ====================================================== */

static inline void rtl865x_extDev_set_skb_property(	u16 pktType,
													struct sk_buff *skb,
													struct net_device *dev,
													struct rtl_pktHdr *pktHdr,
													u16 rxIdx)
{
	struct rtl_mBuf *mbuf;

	/*
		1) Link socket buffer and mbuf/packet header.
		2) Set property of this socket buffer.
		3) Set rx-descriptor ring index for this packet
		4) Set cp pointer for this packet
		5) Set proprietary magic number for Rome Driver process.
	*/

	mbuf = pktHdr->ph_mbuf;

	RTL865X_SET_PKTHDR(skb, pktHdr);
	RTL865X_SET_DEVPTR(skb, dev);
	RTL865X_SET_PKTTYPE(skb, pktType);

	if (	(pktType == RTL865X_TYPE_RXRING) ||
		(pktType == RTL865X_TYPE_RUNOUTRX))
	{
		mbuf->m_unused1 = RTL865X_MBUF_MAGIC_EXTDEV;
		skb->pkt_type = PACKET_AIRGO;
		RTL865X_SET_RXDESC(skb, rxIdx);
	} else
	{
		RTL865X_SET_RXDESC(skb, RTL865X_MBUF_MAX_RXDESC);
	}
}

static inline void rtl865x_extDev_clr_skb_property(	struct sk_buff *skb)
{
	u16 type;

	type = RTL865X_GET_PKTTYPE(skb);

	if (	(type == RTL865X_TYPE_RXRING) ||
		(type == RTL865X_TYPE_RUNOUTRX))
	{
		struct rtl_pktHdr *pktHdr;
		struct rtl_mBuf *mbuf;

		pktHdr = RTL865X_GET_PKTHDR(skb);

		if (pktHdr)
		{
			mbuf = pktHdr->ph_mbuf;
			mbuf->m_unused1 = RTL865X_MBUF_MAGIC_NONE;
		}
	}

	RTL865X_SET_RXDESC(skb, 0);
	RTL865X_SET_DEVPTR(skb, NULL);
	RTL865X_SET_SKBOWNER(skb, 0);
	RTL865X_SET_PKTHDR(skb, NULL);
	RTL865X_SET_PKTTYPE(skb, RTL865X_TYPE_NONE);
	skb->pkt_type = PACKET_HOST;	/* default type */
}

/* ======================================================
						sock-buffer interface
     ====================================================== */
/*
	This function must be called when Rx Ring init. => Only allocate packet in Rx Ring.

	- This function do the following thing to allocate mbuf structure:

		1. Allocate socket buffer.
		2. Attach mbuf & packet header gotten from mbuf system of Rome Driver.
		3. Set related parameter to link mbuf, packet header and socket buffer.
*/
struct sk_buff *rtl865x_extDev_alloc_skb (	u32 length,
												u32 headroom,
												u16 rxIdx,
												struct net_device *dev)
{
	struct sk_buff *skb = NULL;
	struct rtl_mBuf *mbuf = NULL;
	struct rtl_pktHdr *pktHdr = NULL;

#ifdef DEBUG
	printk (	"%s -- (%s [%d]) Allocate Socket buffer for Rx Ring (len %d headroom %d rxIdx %d).\n",
			dev->name,
			__FUNCTION__,
			__LINE__,
			length,
			headroom,
			rxIdx);
#endif

	/* 1 & 2. allocate skbuff / mbuf / packet header and reserve headroom */
	skb = dev_alloc_skb(length + headroom);

	if (skb == NULL)
	{
		goto out;
	}

	skb_reserve(skb, headroom);

	mbuf = mBuf_attachHeader(	(void*)(UNCACHE((u32)(skb->head))),
								(u32)(skb),
								length,
								0,
								skb_headroom(skb));

	if (mbuf == NULL)
	{
		dev_kfree_skb(skb);
		skb = NULL;
		goto out;
	}

	pktHdr = mbuf->m_pkthdr;

#ifdef DEBUG
	printk (	"\t=>mbuf (%p) pktHdr (%p) m_data(%p) leadingSpace(%d) skb-head(%p) skb-data(%p).\n",
			mbuf,
			pktHdr,
			mbuf->m_data,
			mBuf_leadingSpace(mbuf),
			skb->head,
			skb->data);
#endif

	/*	3. Set relative fields */
	skb->dev = dev;
	rtl865x_extDev_set_skb_property(	RTL865X_TYPE_RXRING,
										skb,
										dev,
										pktHdr,
										rxIdx);

	RTL865X_SET_SKBOWNER(skb, RTL865X_RXRING_OWN);

out:
	return skb;
}

/*
	Actually free socket buffer of RxRing or Runout
*/
static void rtl865x_extDev_actualFreeRxRingSkb(struct sk_buff *skb)
{
	struct rtl_pktHdr *pktHdr;
	u16 headroom;

	pktHdr = RTL865X_GET_PKTHDR(skb);

	rtl865x_extDev_clr_skb_property(skb);

	headroom = mBuf_leadingSpace(pktHdr->ph_mbuf);
	mBuf_freeOneMbufPkthdr(	pktHdr->ph_mbuf,
								NULL,
								NULL,
								NULL);

#ifdef DEBUG
	printk (	"(%s [%d]) Free Rx Ring packet (pkt %p rxIdx %d).\n",
			__FUNCTION__,
			__LINE__,
			RTL865X_GET_PKTHDR(skb),
			RTL865X_GET_RXDESC(skb));
#endif

	/*
		clear this socket buffer.
	*/
	skb->data = skb->tail = skb->head;
	skb->len  = skb->data_len = 0;
	skb_reserve(skb, headroom);

	dev_kfree_skb(skb);
}

/*
	3 processes for socket buffer free module:

		1. This packet is from RX ring.
			A. bridge between 8139cp devices.
			B. RX failed.
				- packet type == RTL865X_TYPE_RXRING
				- put it back to corresponding RX ring if "actualFree" == FALSE.
				- actually free scoket buffer / mbuf / packet header if "actualFree" == TRUE.

		2. This packet is from Rome Driver.
			A. Rx frome Rome Driver and Tx to 8139cp.
				- packet type != RTL865X_TYPE_RXRING && packet type != RTL865X_TYPE_PS
				- use Rome Driver's MBUF API to free this packet.

		3. This packet is from other position.
			A. Direct TX from protocol stack.
				- packet type == RTL865X_TYPE_PS
				- free socket buffer directly.
*/
__IRAM_AIRGO  void rtl865x_extDev_kfree_skb(struct sk_buff *skb, u32 actualFree)
{
	u16 pktType = RTL865X_GET_PKTTYPE(skb);

#ifdef DEBUG
	printk("free socket buffer : %p (type %d), actualFree (%d)\n", skb, pktType, actualFree);
#endif

	switch (pktType)
	{
		case RTL865X_TYPE_RT61:
	        RTMPFreeSkbBuffer(skb);
			break;
		case RTL865X_TYPE_ROMEDRV:
		/* packet from Rome Driver */
		{
			struct rtl_pktHdr *pktHdr;
			struct rtl_mBuf *mbuf;

			pktHdr = RTL865X_GET_PKTHDR(skb);
			mbuf = pktHdr->ph_mbuf;

			/*	we just modify some socket buffer's fields in rtl865x_extDev_pktUcastTx(),
				so we MUST restore them before free it back to Rome Driver				*/
			skb->data = RTL865X_GET_ROMEDRV_SKBINFO(skb, data);
			skb->tail = RTL865X_GET_ROMEDRV_SKBINFO(skb, tail);
			skb->len = RTL865X_GET_ROMEDRV_SKBINFO(skb, len);
			skb->data_len = 0;

			RTL865X_SET_ROMEDRV_SKBINFO(skb, 0, data);
			RTL865X_SET_ROMEDRV_SKBINFO(skb, 0, tail);
			RTL865X_SET_ROMEDRV_SKBINFO(skb, 0, len);
			RTL865X_SET_PKTHDR(skb, NULL);
			RTL865X_SET_PKTTYPE(skb, RTL865X_TYPE_NONE);

			mBuf_freeMbufChain(mbuf);
		}
		break;

		case RTL865X_TYPE_RXRING:
		/* packet from RX Ring */
		{
//			printk("RTL865X_TYPE_RXRING\n");
#if 0
			u16 rxIdx;
			struct net_device *dev;
			struct cp_private *cp;
			struct rtl_pktHdr *pktHdr;
			struct rtl_mBuf *mbuf;

			if (actualFree == FALSE)
			{
				rxIdx = RTL865X_GET_RXDESC(skb);
				dev = RTL865X_GET_DEVPTR(skb);
				pktHdr = RTL865X_GET_PKTHDR(skb);
				cp = dev->priv;
				mbuf = pktHdr->ph_mbuf;

				/*
					clear this socket buffer.
				*/
				skb->data = skb->tail = skb->head;
				skb->len  = skb->data_len = 0;
				skb_reserve(skb, mBuf_leadingSpace(mbuf));
				skb->dev = cp->dev;

#ifdef DEBUG
				printk("\t=> Reclaim socket buff (0x%p) into RxRing Idx (%d)\n\t\t(data(0x%p) tail(0x%p) head(0x%p) len(%d) trueSize(%d)) - dev (%s).\n\t\tmbuf(0x%p) pktHdr(0x%p) mbufLead(%d)\n",
						skb,
						rxIdx,
						skb->data,
						skb->tail,
						skb->head,
						skb->len,
						skb->truesize,
						skb->dev->name,
						RTL865X_GET_PKTHDR(skb),
						((struct rtl_pktHdr*)(RTL865X_GET_PKTHDR(skb)))->ph_mbuf,
						mBuf_leadingSpace(((struct rtl_pktHdr*)(RTL865X_GET_PKTHDR(skb)))->ph_mbuf));
#endif

				rtlglue_drvMutexLock();
				/* ================================================================== */
				/* put this socket buffer back to Rx Ring */
				cp->rx_skb[rxIdx].mapping = pci_map_single(	cp->pdev,
															skb->tail,
															cp->rx_buf_sz,
															PCI_DMA_FROMDEVICE);
				cp->rx_skb[rxIdx].skb = skb;
				cp->rx_skb[rxIdx].frag = 0;

				if (rxIdx == (CP_RX_RING_SIZE - 1))
				{
					cp->rx_ring[rxIdx].opts1 = cpu_to_le32( DescOwn | RingEnd | cp->rx_buf_sz );
				} else
				{
					cp->rx_ring[rxIdx].opts1 = cpu_to_le32( DescOwn | cp->rx_buf_sz );
				}

				cp->rx_ring[rxIdx].opts2 = 0;
				cp->rx_ring[rxIdx].addr_lo = cpu_to_le32(cp->rx_skb[rxIdx].mapping);
				cp->rx_ring[rxIdx].addr_hi = 0;

				RTL865X_SET_SKBOWNER(skb, RTL865X_RXRING_OWN);

				/* ================================================================== */
				rtlglue_drvMutexUnlock();

			}else
#endif
			{
				/* actualFree == TRUE: actually free Rx Ring Socket buffer */
				rtl865x_extDev_actualFreeRxRingSkb(skb);
			}
		}
		break;

		case RTL865X_TYPE_PS:
		/* packet from Protocol Stack */
		{
			rtl865x_extDev_clr_skb_property(skb);
			dev_kfree_skb(skb);
		}
		break;

		case RTL865X_TYPE_RUNOUTRX:
		{
			/* the position of this packet in RX Ring is replaced : actually free it */
			rtl865x_extDev_actualFreeRxRingSkb(skb);
		}
		break;

		default:
			printk("Packet type : %d -- free socket buffer only\n", pktType);
			dev_kfree_skb(skb);
	}
}

/* ======================================================
						protocol stack interface
     ====================================================== */
static int rtl865x_extDev_mbuf2Skb(struct net_device *dev, struct sk_buff *skb)
{
	struct sk_buff *newSkb = NULL;
	struct rtl_pktHdr *pktHdr = NULL;
	struct rtl_mBuf *mbuf = NULL;
	unsigned int pktLen = 0;
	unsigned int pktTotalLen = 0;
	u16 rxIdx;
	u16 pktType;
	u16 headroom;

#ifdef DEBUG
	printk("%s -- for socket buffer (%p) -- head %p data %p headroom %d len %d mbuf_head %d\n",
		__FUNCTION__,
		skb,
		skb->head,
		skb->data,
		(u32)skb->data - (u32)skb->head,
		skb->len,
		mBuf_leadingSpace(((struct rtl_pktHdr*)RTL865X_GET_PKTHDR(skb))->ph_mbuf)
		);
#endif

	pktHdr = RTL865X_GET_PKTHDR(skb);
	mbuf = pktHdr->ph_mbuf;
	pktLen = pktHdr->ph_len;
	pktTotalLen = mbuf->m_extsize;
	rxIdx = RTL865X_GET_RXDESC(skb);
	pktType = RTL865X_GET_PKTTYPE(skb);
	headroom = mBuf_leadingSpace(mbuf);

	if (pktType != RTL865X_TYPE_RXRING)
	{
		printk("BUG ! socket buffer which put into %s is not from Rx Ring!!\n", __FUNCTION__);
		goto err_out;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -