diff options
Diffstat (limited to 'drivers/net/ethernet/socionext/netsec.c')
-rw-r--r-- | drivers/net/ethernet/socionext/netsec.c | 96 |
1 files changed, 42 insertions, 54 deletions
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c index 1502fe8b0456..e8224b543dfc 100644 --- a/drivers/net/ethernet/socionext/netsec.c +++ b/drivers/net/ethernet/socionext/netsec.c @@ -243,6 +243,7 @@ NET_IP_ALIGN) #define NETSEC_RX_BUF_NON_DATA (NETSEC_RXBUF_HEADROOM + \ SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) +#define NETSEC_RX_BUF_SIZE (PAGE_SIZE - NETSEC_RX_BUF_NON_DATA) #define DESC_SZ sizeof(struct netsec_de) @@ -252,7 +253,6 @@ #define NETSEC_XDP_CONSUMED BIT(0) #define NETSEC_XDP_TX BIT(1) #define NETSEC_XDP_REDIR BIT(2) -#define NETSEC_XDP_RX_OK (NETSEC_XDP_PASS | NETSEC_XDP_TX | NETSEC_XDP_REDIR) enum ring_id { NETSEC_RING_TX = 0, @@ -282,7 +282,6 @@ struct netsec_desc_ring { void *vaddr; u16 head, tail; u16 xdp_xmit; /* netsec_xdp_xmit packets */ - bool is_xdp; struct page_pool *page_pool; struct xdp_rxq_info xdp_rxq; spinlock_t lock; /* XDP tx queue locking */ @@ -634,8 +633,7 @@ static bool netsec_clean_tx_dring(struct netsec_priv *priv) unsigned int bytes; int cnt = 0; - if (dring->is_xdp) - spin_lock(&dring->lock); + spin_lock(&dring->lock); bytes = 0; entry = dring->vaddr + DESC_SZ * tail; @@ -663,6 +661,7 @@ static bool netsec_clean_tx_dring(struct netsec_priv *priv) bytes += desc->skb->len; dev_kfree_skb(desc->skb); } else { + bytes += desc->xdpf->len; xdp_return_frame(desc->xdpf); } next: @@ -682,8 +681,8 @@ next: entry = dring->vaddr + DESC_SZ * tail; cnt++; } - if (dring->is_xdp) - spin_unlock(&dring->lock); + + spin_unlock(&dring->lock); if (!cnt) return false; @@ -721,7 +720,6 @@ static void *netsec_alloc_rx_data(struct netsec_priv *priv, { struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_RX]; - enum dma_data_direction dma_dir; struct page *page; page = page_pool_dev_alloc_pages(dring->page_pool); @@ -736,9 +734,7 @@ static void *netsec_alloc_rx_data(struct netsec_priv *priv, /* Make sure the incoming payload fits in the page for XDP and non-XDP * cases and reserve enough space for headroom + skb_shared_info */ - *desc_len = PAGE_SIZE - NETSEC_RX_BUF_NON_DATA; - dma_dir = page_pool_get_dma_dir(dring->page_pool); - dma_sync_single_for_device(priv->dev, *dma_handle, *desc_len, dma_dir); + *desc_len = NETSEC_RX_BUF_SIZE; return page_address(page); } @@ -799,9 +795,6 @@ static void netsec_set_tx_de(struct netsec_priv *priv, de->data_buf_addr_lw = lower_32_bits(desc->dma_addr); de->buf_len_info = (tx_ctrl->tcp_seg_len << 16) | desc->len; de->attr = attr; - /* under spin_lock if using XDP */ - if (!dring->is_xdp) - dma_wmb(); dring->desc[idx] = *desc; if (desc->buf_type == TYPE_NETSEC_SKB) @@ -852,8 +845,8 @@ static u32 netsec_xdp_queue_one(struct netsec_priv *priv, enum dma_data_direction dma_dir = page_pool_get_dma_dir(rx_ring->page_pool); - dma_handle = page_pool_get_dma_addr(page) + - NETSEC_RXBUF_HEADROOM; + dma_handle = page_pool_get_dma_addr(page) + xdpf->headroom + + sizeof(*xdpf); dma_sync_single_for_device(priv->dev, dma_handle, xdpf->len, dma_dir); tx_desc.buf_type = TYPE_NETSEC_XDP_TX; @@ -863,6 +856,7 @@ static u32 netsec_xdp_queue_one(struct netsec_priv *priv, tx_desc.addr = xdpf->data; tx_desc.len = xdpf->len; + netdev_sent_queue(priv->ndev, xdpf->len); netsec_set_tx_de(priv, tx_ring, &tx_ctrl, &tx_desc, xdpf); return NETSEC_XDP_TX; @@ -887,6 +881,8 @@ static u32 netsec_xdp_xmit_back(struct netsec_priv *priv, struct xdp_buff *xdp) static u32 netsec_run_xdp(struct netsec_priv *priv, struct bpf_prog *prog, struct xdp_buff *xdp) { + struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_RX]; + unsigned int len = xdp->data_end - xdp->data; u32 ret = NETSEC_XDP_PASS; int err; u32 act; @@ -900,7 +896,9 @@ static u32 netsec_run_xdp(struct netsec_priv *priv, struct bpf_prog *prog, case XDP_TX: ret = netsec_xdp_xmit_back(priv, xdp); if (ret != NETSEC_XDP_TX) - xdp_return_buff(xdp); + __page_pool_put_page(dring->page_pool, + virt_to_head_page(xdp->data), + len, true); break; case XDP_REDIRECT: err = xdp_do_redirect(priv->ndev, xdp, prog); @@ -908,7 +906,9 @@ static u32 netsec_run_xdp(struct netsec_priv *priv, struct bpf_prog *prog, ret = NETSEC_XDP_REDIR; } else { ret = NETSEC_XDP_CONSUMED; - xdp_return_buff(xdp); + __page_pool_put_page(dring->page_pool, + virt_to_head_page(xdp->data), + len, true); } break; default: @@ -919,7 +919,9 @@ static u32 netsec_run_xdp(struct netsec_priv *priv, struct bpf_prog *prog, /* fall through -- handle aborts by dropping packet */ case XDP_DROP: ret = NETSEC_XDP_CONSUMED; - xdp_return_buff(xdp); + __page_pool_put_page(dring->page_pool, + virt_to_head_page(xdp->data), + len, true); break; } @@ -933,7 +935,6 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget) struct netsec_rx_pkt_info rx_info; enum dma_data_direction dma_dir; struct bpf_prog *xdp_prog; - struct sk_buff *skb = NULL; u16 xdp_xmit = 0; u32 xdp_act = 0; int done = 0; @@ -947,7 +948,8 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget) struct netsec_de *de = dring->vaddr + (DESC_SZ * idx); struct netsec_desc *desc = &dring->desc[idx]; struct page *page = virt_to_page(desc->addr); - u32 xdp_result = XDP_PASS; + u32 xdp_result = NETSEC_XDP_PASS; + struct sk_buff *skb = NULL; u16 pkt_len, desc_len; dma_addr_t dma_handle; struct xdp_buff xdp; @@ -1018,7 +1020,8 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget) * cache state. Since we paid the allocation cost if * building an skb fails try to put the page into cache */ - page_pool_recycle_direct(dring->page_pool, page); + __page_pool_put_page(dring->page_pool, page, + pkt_len, true); netif_err(priv, drv, priv->ndev, "rx failed to build skb\n"); break; @@ -1035,7 +1038,7 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget) next: if ((skb && napi_gro_receive(&priv->napi, skb) != GRO_DROP) || - xdp_result & NETSEC_XDP_RX_OK) { + xdp_result) { ndev->stats.rx_packets++; ndev->stats.rx_bytes += xdp.data_end - xdp.data; } @@ -1123,12 +1126,10 @@ static netdev_tx_t netsec_netdev_start_xmit(struct sk_buff *skb, u16 tso_seg_len = 0; int filled; - if (dring->is_xdp) - spin_lock_bh(&dring->lock); + spin_lock_bh(&dring->lock); filled = netsec_desc_used(dring); if (netsec_check_stop_tx(priv, filled)) { - if (dring->is_xdp) - spin_unlock_bh(&dring->lock); + spin_unlock_bh(&dring->lock); net_warn_ratelimited("%s %s Tx queue full\n", dev_name(priv->dev), ndev->name); return NETDEV_TX_BUSY; @@ -1161,8 +1162,7 @@ static netdev_tx_t netsec_netdev_start_xmit(struct sk_buff *skb, tx_desc.dma_addr = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); if (dma_mapping_error(priv->dev, tx_desc.dma_addr)) { - if (dring->is_xdp) - spin_unlock_bh(&dring->lock); + spin_unlock_bh(&dring->lock); netif_err(priv, drv, priv->ndev, "%s: DMA mapping failed\n", __func__); ndev->stats.tx_dropped++; @@ -1177,8 +1177,7 @@ static netdev_tx_t netsec_netdev_start_xmit(struct sk_buff *skb, netdev_sent_queue(priv->ndev, skb->len); netsec_set_tx_de(priv, dring, &tx_ctrl, &tx_desc, skb); - if (dring->is_xdp) - spin_unlock_bh(&dring->lock); + spin_unlock_bh(&dring->lock); netsec_write(priv, NETSEC_REG_NRM_TX_PKTCNT, 1); /* submit another tx */ return NETDEV_TX_OK; @@ -1262,7 +1261,6 @@ err: static void netsec_setup_tx_dring(struct netsec_priv *priv) { struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_TX]; - struct bpf_prog *xdp_prog = READ_ONCE(priv->xdp_prog); int i; for (i = 0; i < DESC_NUM; i++) { @@ -1275,29 +1273,25 @@ static void netsec_setup_tx_dring(struct netsec_priv *priv) */ de->attr = 1U << NETSEC_TX_SHIFT_OWN_FIELD; } - - if (xdp_prog) - dring->is_xdp = true; - else - dring->is_xdp = false; - } static int netsec_setup_rx_dring(struct netsec_priv *priv) { struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_RX]; struct bpf_prog *xdp_prog = READ_ONCE(priv->xdp_prog); - struct page_pool_params pp_params = { 0 }; + struct page_pool_params pp_params = { + .order = 0, + /* internal DMA mapping in page_pool */ + .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, + .pool_size = DESC_NUM, + .nid = NUMA_NO_NODE, + .dev = priv->dev, + .dma_dir = xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE, + .offset = NETSEC_RXBUF_HEADROOM, + .max_len = NETSEC_RX_BUF_SIZE, + }; int i, err; - pp_params.order = 0; - /* internal DMA mapping in page_pool */ - pp_params.flags = PP_FLAG_DMA_MAP; - pp_params.pool_size = DESC_NUM; - pp_params.nid = cpu_to_node(0); - pp_params.dev = priv->dev; - pp_params.dma_dir = xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE; - dring->page_pool = page_pool_create(&pp_params); if (IS_ERR(dring->page_pool)) { err = PTR_ERR(dring->page_pool); @@ -1746,12 +1740,6 @@ static int netsec_netdev_set_features(struct net_device *ndev, return 0; } -static int netsec_netdev_ioctl(struct net_device *ndev, struct ifreq *ifr, - int cmd) -{ - return phy_mii_ioctl(ndev->phydev, ifr, cmd); -} - static int netsec_xdp_xmit(struct net_device *ndev, int n, struct xdp_frame **frames, u32 flags) { @@ -1836,7 +1824,7 @@ static const struct net_device_ops netsec_netdev_ops = { .ndo_set_features = netsec_netdev_set_features, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, - .ndo_do_ioctl = netsec_netdev_ioctl, + .ndo_do_ioctl = phy_do_ioctl, .ndo_xdp_xmit = netsec_xdp_xmit, .ndo_bpf = netsec_xdp, }; @@ -2007,7 +1995,7 @@ static int netsec_probe(struct platform_device *pdev) NETIF_MSG_LINK | NETIF_MSG_PROBE; priv->phy_interface = device_get_phy_mode(&pdev->dev); - if (priv->phy_interface < 0) { + if ((int)priv->phy_interface < 0) { dev_err(&pdev->dev, "missing required property 'phy-mode'\n"); ret = -ENODEV; goto free_ndev; |