Merge branch 'dpaa2-eth-Driver-updates'
Ioana Ciocoi Radulescu says: ==================== dpaa2-eth: Driver updates First patch moves the driver to a page-per-frame memory model. The others are minor tweaks and optimizations. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
8ce5cd5ed4
@ -86,16 +86,16 @@ static void free_rx_fd(struct dpaa2_eth_priv *priv,
|
||||
for (i = 1; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
|
||||
addr = dpaa2_sg_get_addr(&sgt[i]);
|
||||
sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
|
||||
dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
skb_free_frag(sg_vaddr);
|
||||
free_pages((unsigned long)sg_vaddr, 0);
|
||||
if (dpaa2_sg_is_final(&sgt[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
free_buf:
|
||||
skb_free_frag(vaddr);
|
||||
free_pages((unsigned long)vaddr, 0);
|
||||
}
|
||||
|
||||
/* Build a linear skb based on a single-buffer frame descriptor */
|
||||
@ -109,7 +109,7 @@ static struct sk_buff *build_linear_skb(struct dpaa2_eth_channel *ch,
|
||||
|
||||
ch->buf_count--;
|
||||
|
||||
skb = build_skb(fd_vaddr, DPAA2_ETH_SKB_SIZE);
|
||||
skb = build_skb(fd_vaddr, DPAA2_ETH_RX_BUF_RAW_SIZE);
|
||||
if (unlikely(!skb))
|
||||
return NULL;
|
||||
|
||||
@ -144,19 +144,19 @@ static struct sk_buff *build_frag_skb(struct dpaa2_eth_priv *priv,
|
||||
/* Get the address and length from the S/G entry */
|
||||
sg_addr = dpaa2_sg_get_addr(sge);
|
||||
sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, sg_addr);
|
||||
dma_unmap_single(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
dma_unmap_page(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
sg_length = dpaa2_sg_get_len(sge);
|
||||
|
||||
if (i == 0) {
|
||||
/* We build the skb around the first data buffer */
|
||||
skb = build_skb(sg_vaddr, DPAA2_ETH_SKB_SIZE);
|
||||
skb = build_skb(sg_vaddr, DPAA2_ETH_RX_BUF_RAW_SIZE);
|
||||
if (unlikely(!skb)) {
|
||||
/* Free the first SG entry now, since we already
|
||||
* unmapped it and obtained the virtual address
|
||||
*/
|
||||
skb_free_frag(sg_vaddr);
|
||||
free_pages((unsigned long)sg_vaddr, 0);
|
||||
|
||||
/* We still need to subtract the buffers used
|
||||
* by this FD from our software counter
|
||||
@ -211,9 +211,9 @@ static void free_bufs(struct dpaa2_eth_priv *priv, u64 *buf_array, int count)
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
vaddr = dpaa2_iova_to_virt(priv->iommu_domain, buf_array[i]);
|
||||
dma_unmap_single(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
skb_free_frag(vaddr);
|
||||
dma_unmap_page(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
free_pages((unsigned long)vaddr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,9 +264,7 @@ static int xdp_enqueue(struct dpaa2_eth_priv *priv, struct dpaa2_fd *fd,
|
||||
|
||||
fq = &priv->fq[queue_id];
|
||||
for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) {
|
||||
err = dpaa2_io_service_enqueue_qd(fq->channel->dpio,
|
||||
priv->tx_qdid, 0,
|
||||
fq->tx_qdbin, fd);
|
||||
err = priv->enqueue(priv, fq, fd, 0);
|
||||
if (err != -EBUSY)
|
||||
break;
|
||||
}
|
||||
@ -378,16 +376,16 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
|
||||
return;
|
||||
}
|
||||
|
||||
dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
skb = build_linear_skb(ch, fd, vaddr);
|
||||
} else if (fd_format == dpaa2_fd_sg) {
|
||||
WARN_ON(priv->xdp_prog);
|
||||
|
||||
dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
skb = build_frag_skb(priv, ch, buf_data);
|
||||
skb_free_frag(vaddr);
|
||||
free_pages((unsigned long)vaddr, 0);
|
||||
percpu_extras->rx_sg_frames++;
|
||||
percpu_extras->rx_sg_bytes += dpaa2_fd_get_len(fd);
|
||||
} else {
|
||||
@ -657,7 +655,7 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
|
||||
* dpaa2_eth_tx().
|
||||
*/
|
||||
static void free_tx_fd(const struct dpaa2_eth_priv *priv,
|
||||
const struct dpaa2_fd *fd)
|
||||
const struct dpaa2_fd *fd, bool in_napi)
|
||||
{
|
||||
struct device *dev = priv->net_dev->dev.parent;
|
||||
dma_addr_t fd_addr;
|
||||
@ -712,7 +710,7 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
|
||||
skb_free_frag(skbh);
|
||||
|
||||
/* Move on with skb release */
|
||||
dev_kfree_skb(skb);
|
||||
napi_consume_skb(skb, in_napi);
|
||||
}
|
||||
|
||||
static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
|
||||
@ -785,9 +783,7 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
|
||||
queue_mapping = skb_get_queue_mapping(skb);
|
||||
fq = &priv->fq[queue_mapping];
|
||||
for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) {
|
||||
err = dpaa2_io_service_enqueue_qd(fq->channel->dpio,
|
||||
priv->tx_qdid, 0,
|
||||
fq->tx_qdbin, &fd);
|
||||
err = priv->enqueue(priv, fq, &fd, 0);
|
||||
if (err != -EBUSY)
|
||||
break;
|
||||
}
|
||||
@ -795,7 +791,7 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
|
||||
if (unlikely(err < 0)) {
|
||||
percpu_stats->tx_errors++;
|
||||
/* Clean up everything, including freeing the skb */
|
||||
free_tx_fd(priv, &fd);
|
||||
free_tx_fd(priv, &fd, false);
|
||||
} else {
|
||||
fd_len = dpaa2_fd_get_len(&fd);
|
||||
percpu_stats->tx_packets++;
|
||||
@ -837,7 +833,7 @@ static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
|
||||
|
||||
/* Check frame errors in the FD field */
|
||||
fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_TX_ERR_MASK;
|
||||
free_tx_fd(priv, fd);
|
||||
free_tx_fd(priv, fd, true);
|
||||
|
||||
if (likely(!fd_errors))
|
||||
return;
|
||||
@ -903,7 +899,7 @@ static int add_bufs(struct dpaa2_eth_priv *priv,
|
||||
{
|
||||
struct device *dev = priv->net_dev->dev.parent;
|
||||
u64 buf_array[DPAA2_ETH_BUFS_PER_CMD];
|
||||
void *buf;
|
||||
struct page *page;
|
||||
dma_addr_t addr;
|
||||
int i, err;
|
||||
|
||||
@ -911,14 +907,16 @@ static int add_bufs(struct dpaa2_eth_priv *priv,
|
||||
/* Allocate buffer visible to WRIOP + skb shared info +
|
||||
* alignment padding
|
||||
*/
|
||||
buf = napi_alloc_frag(dpaa2_eth_buf_raw_size(priv));
|
||||
if (unlikely(!buf))
|
||||
/* allocate one page for each Rx buffer. WRIOP sees
|
||||
* the entire page except for a tailroom reserved for
|
||||
* skb shared info
|
||||
*/
|
||||
page = dev_alloc_pages(0);
|
||||
if (!page)
|
||||
goto err_alloc;
|
||||
|
||||
buf = PTR_ALIGN(buf, priv->rx_buf_align);
|
||||
|
||||
addr = dma_map_single(dev, buf, DPAA2_ETH_RX_BUF_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
addr = dma_map_page(dev, page, 0, DPAA2_ETH_RX_BUF_SIZE,
|
||||
DMA_BIDIRECTIONAL);
|
||||
if (unlikely(dma_mapping_error(dev, addr)))
|
||||
goto err_map;
|
||||
|
||||
@ -926,7 +924,7 @@ static int add_bufs(struct dpaa2_eth_priv *priv,
|
||||
|
||||
/* tracing point */
|
||||
trace_dpaa2_eth_buf_seed(priv->net_dev,
|
||||
buf, dpaa2_eth_buf_raw_size(priv),
|
||||
page, DPAA2_ETH_RX_BUF_RAW_SIZE,
|
||||
addr, DPAA2_ETH_RX_BUF_SIZE,
|
||||
bpid);
|
||||
}
|
||||
@ -948,7 +946,7 @@ release_bufs:
|
||||
return i;
|
||||
|
||||
err_map:
|
||||
skb_free_frag(buf);
|
||||
__free_pages(page, 0);
|
||||
err_alloc:
|
||||
/* If we managed to allocate at least some buffers,
|
||||
* release them to hardware
|
||||
@ -2134,6 +2132,7 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv)
|
||||
{
|
||||
struct device *dev = priv->net_dev->dev.parent;
|
||||
struct dpni_buffer_layout buf_layout = {0};
|
||||
u16 rx_buf_align;
|
||||
int err;
|
||||
|
||||
/* We need to check for WRIOP version 1.0.0, but depending on the MC
|
||||
@ -2142,9 +2141,9 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv)
|
||||
*/
|
||||
if (priv->dpni_attrs.wriop_version == DPAA2_WRIOP_VERSION(0, 0, 0) ||
|
||||
priv->dpni_attrs.wriop_version == DPAA2_WRIOP_VERSION(1, 0, 0))
|
||||
priv->rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN_REV1;
|
||||
rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN_REV1;
|
||||
else
|
||||
priv->rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN;
|
||||
rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN;
|
||||
|
||||
/* tx buffer */
|
||||
buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE;
|
||||
@ -2184,7 +2183,7 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv)
|
||||
/* rx buffer */
|
||||
buf_layout.pass_frame_status = true;
|
||||
buf_layout.pass_parser_result = true;
|
||||
buf_layout.data_align = priv->rx_buf_align;
|
||||
buf_layout.data_align = rx_buf_align;
|
||||
buf_layout.data_head_room = dpaa2_eth_rx_head_room(priv);
|
||||
buf_layout.private_data_size = 0;
|
||||
buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
|
||||
@ -2202,6 +2201,36 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DPNI_ENQUEUE_FQID_VER_MAJOR 7
|
||||
#define DPNI_ENQUEUE_FQID_VER_MINOR 9
|
||||
|
||||
static inline int dpaa2_eth_enqueue_qd(struct dpaa2_eth_priv *priv,
|
||||
struct dpaa2_eth_fq *fq,
|
||||
struct dpaa2_fd *fd, u8 prio)
|
||||
{
|
||||
return dpaa2_io_service_enqueue_qd(fq->channel->dpio,
|
||||
priv->tx_qdid, prio,
|
||||
fq->tx_qdbin, fd);
|
||||
}
|
||||
|
||||
static inline int dpaa2_eth_enqueue_fq(struct dpaa2_eth_priv *priv,
|
||||
struct dpaa2_eth_fq *fq,
|
||||
struct dpaa2_fd *fd,
|
||||
u8 prio __always_unused)
|
||||
{
|
||||
return dpaa2_io_service_enqueue_fq(fq->channel->dpio,
|
||||
fq->tx_fqid, fd);
|
||||
}
|
||||
|
||||
static void set_enqueue_mode(struct dpaa2_eth_priv *priv)
|
||||
{
|
||||
if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_ENQUEUE_FQID_VER_MAJOR,
|
||||
DPNI_ENQUEUE_FQID_VER_MINOR) < 0)
|
||||
priv->enqueue = dpaa2_eth_enqueue_qd;
|
||||
else
|
||||
priv->enqueue = dpaa2_eth_enqueue_fq;
|
||||
}
|
||||
|
||||
/* Configure the DPNI object this interface is associated with */
|
||||
static int setup_dpni(struct fsl_mc_device *ls_dev)
|
||||
{
|
||||
@ -2255,6 +2284,8 @@ static int setup_dpni(struct fsl_mc_device *ls_dev)
|
||||
if (err)
|
||||
goto close;
|
||||
|
||||
set_enqueue_mode(priv);
|
||||
|
||||
priv->cls_rules = devm_kzalloc(dev, sizeof(struct dpaa2_eth_cls_rule) *
|
||||
dpaa2_eth_fs_count(priv), GFP_KERNEL);
|
||||
if (!priv->cls_rules)
|
||||
@ -2339,6 +2370,7 @@ static int setup_tx_flow(struct dpaa2_eth_priv *priv,
|
||||
}
|
||||
|
||||
fq->tx_qdbin = qid.qdbin;
|
||||
fq->tx_fqid = qid.fqid;
|
||||
|
||||
err = dpni_get_queue(priv->mc_io, 0, priv->mc_token,
|
||||
DPNI_QUEUE_TX_CONFIRM, 0, fq->flowid,
|
||||
|
@ -53,7 +53,8 @@
|
||||
*/
|
||||
#define DPAA2_ETH_MAX_FRAMES_PER_QUEUE (DPAA2_ETH_TAILDROP_THRESH / 64)
|
||||
#define DPAA2_ETH_NUM_BUFS (DPAA2_ETH_MAX_FRAMES_PER_QUEUE + 256)
|
||||
#define DPAA2_ETH_REFILL_THRESH DPAA2_ETH_MAX_FRAMES_PER_QUEUE
|
||||
#define DPAA2_ETH_REFILL_THRESH \
|
||||
(DPAA2_ETH_NUM_BUFS - DPAA2_ETH_BUFS_PER_CMD)
|
||||
|
||||
/* Maximum number of buffers that can be acquired/released through a single
|
||||
* QBMan command
|
||||
@ -63,9 +64,11 @@
|
||||
/* Hardware requires alignment for ingress/egress buffer addresses */
|
||||
#define DPAA2_ETH_TX_BUF_ALIGN 64
|
||||
|
||||
#define DPAA2_ETH_RX_BUF_SIZE 2048
|
||||
#define DPAA2_ETH_SKB_SIZE \
|
||||
(DPAA2_ETH_RX_BUF_SIZE + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
|
||||
#define DPAA2_ETH_RX_BUF_RAW_SIZE PAGE_SIZE
|
||||
#define DPAA2_ETH_RX_BUF_TAILROOM \
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
|
||||
#define DPAA2_ETH_RX_BUF_SIZE \
|
||||
(DPAA2_ETH_RX_BUF_RAW_SIZE - DPAA2_ETH_RX_BUF_TAILROOM)
|
||||
|
||||
/* Hardware annotation area in RX/TX buffers */
|
||||
#define DPAA2_ETH_RX_HWA_SIZE 64
|
||||
@ -274,6 +277,7 @@ struct dpaa2_eth_priv;
|
||||
struct dpaa2_eth_fq {
|
||||
u32 fqid;
|
||||
u32 tx_qdbin;
|
||||
u32 tx_fqid;
|
||||
u16 flowid;
|
||||
int target_cpu;
|
||||
u32 dq_frames;
|
||||
@ -326,6 +330,9 @@ struct dpaa2_eth_priv {
|
||||
|
||||
u8 num_fqs;
|
||||
struct dpaa2_eth_fq fq[DPAA2_ETH_MAX_QUEUES];
|
||||
int (*enqueue)(struct dpaa2_eth_priv *priv,
|
||||
struct dpaa2_eth_fq *fq,
|
||||
struct dpaa2_fd *fd, u8 prio);
|
||||
|
||||
u8 num_channels;
|
||||
struct dpaa2_eth_channel *channel[DPAA2_ETH_MAX_DPCONS];
|
||||
@ -343,7 +350,6 @@ struct dpaa2_eth_priv {
|
||||
bool rx_tstamp; /* Rx timestamping enabled */
|
||||
|
||||
u16 tx_qdid;
|
||||
u16 rx_buf_align;
|
||||
struct fsl_mc_io *mc_io;
|
||||
/* Cores which have an affine DPIO/DPCON.
|
||||
* This is the cpu set on which Rx and Tx conf frames are processed
|
||||
@ -418,15 +424,6 @@ enum dpaa2_eth_rx_dist {
|
||||
DPAA2_ETH_RX_DIST_CLS
|
||||
};
|
||||
|
||||
/* Hardware only sees DPAA2_ETH_RX_BUF_SIZE, but the skb built around
|
||||
* the buffer also needs space for its shared info struct, and we need
|
||||
* to allocate enough to accommodate hardware alignment restrictions
|
||||
*/
|
||||
static inline unsigned int dpaa2_eth_buf_raw_size(struct dpaa2_eth_priv *priv)
|
||||
{
|
||||
return DPAA2_ETH_SKB_SIZE + priv->rx_buf_align;
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned int dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv,
|
||||
struct sk_buff *skb)
|
||||
@ -451,8 +448,7 @@ unsigned int dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv,
|
||||
*/
|
||||
static inline unsigned int dpaa2_eth_rx_head_room(struct dpaa2_eth_priv *priv)
|
||||
{
|
||||
return priv->tx_data_offset + DPAA2_ETH_TX_BUF_ALIGN -
|
||||
DPAA2_ETH_RX_HWA_SIZE;
|
||||
return priv->tx_data_offset - DPAA2_ETH_RX_HWA_SIZE;
|
||||
}
|
||||
|
||||
int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags);
|
||||
|
Loading…
x
Reference in New Issue
Block a user