📄 rtl865x_fast.c
字号:
#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 + -