180f6ccf9SSriram Yagnaraman // SPDX-License-Identifier: GPL-2.0 280f6ccf9SSriram Yagnaraman /* Copyright(c) 2018 Intel Corporation. */ 380f6ccf9SSriram Yagnaraman 480f6ccf9SSriram Yagnaraman #include <linux/bpf_trace.h> 580f6ccf9SSriram Yagnaraman #include <net/xdp_sock_drv.h> 680f6ccf9SSriram Yagnaraman #include <net/xdp.h> 780f6ccf9SSriram Yagnaraman 880f6ccf9SSriram Yagnaraman #include "e1000_hw.h" 980f6ccf9SSriram Yagnaraman #include "igb.h" 1080f6ccf9SSriram Yagnaraman 1180f6ccf9SSriram Yagnaraman static int igb_realloc_rx_buffer_info(struct igb_ring *ring, bool pool_present) 1280f6ccf9SSriram Yagnaraman { 1380f6ccf9SSriram Yagnaraman int size = pool_present ? 1480f6ccf9SSriram Yagnaraman sizeof(*ring->rx_buffer_info_zc) * ring->count : 1580f6ccf9SSriram Yagnaraman sizeof(*ring->rx_buffer_info) * ring->count; 1680f6ccf9SSriram Yagnaraman void *buff_info = vmalloc(size); 1780f6ccf9SSriram Yagnaraman 1880f6ccf9SSriram Yagnaraman if (!buff_info) 1980f6ccf9SSriram Yagnaraman return -ENOMEM; 2080f6ccf9SSriram Yagnaraman 2180f6ccf9SSriram Yagnaraman if (pool_present) { 2280f6ccf9SSriram Yagnaraman vfree(ring->rx_buffer_info); 2380f6ccf9SSriram Yagnaraman ring->rx_buffer_info = NULL; 2480f6ccf9SSriram Yagnaraman ring->rx_buffer_info_zc = buff_info; 2580f6ccf9SSriram Yagnaraman } else { 2680f6ccf9SSriram Yagnaraman vfree(ring->rx_buffer_info_zc); 2780f6ccf9SSriram Yagnaraman ring->rx_buffer_info_zc = NULL; 2880f6ccf9SSriram Yagnaraman ring->rx_buffer_info = buff_info; 2980f6ccf9SSriram Yagnaraman } 3080f6ccf9SSriram Yagnaraman 3180f6ccf9SSriram Yagnaraman return 0; 3280f6ccf9SSriram Yagnaraman } 3380f6ccf9SSriram Yagnaraman 3480f6ccf9SSriram Yagnaraman static void igb_txrx_ring_disable(struct igb_adapter *adapter, u16 qid) 3580f6ccf9SSriram Yagnaraman { 3680f6ccf9SSriram Yagnaraman struct igb_ring *tx_ring = adapter->tx_ring[qid]; 3780f6ccf9SSriram Yagnaraman struct igb_ring *rx_ring = adapter->rx_ring[qid]; 3880f6ccf9SSriram Yagnaraman struct e1000_hw *hw = &adapter->hw; 3980f6ccf9SSriram Yagnaraman 4080f6ccf9SSriram Yagnaraman set_bit(IGB_RING_FLAG_TX_DISABLED, &tx_ring->flags); 4180f6ccf9SSriram Yagnaraman 4280f6ccf9SSriram Yagnaraman wr32(E1000_TXDCTL(tx_ring->reg_idx), 0); 4380f6ccf9SSriram Yagnaraman wr32(E1000_RXDCTL(rx_ring->reg_idx), 0); 4480f6ccf9SSriram Yagnaraman 4580f6ccf9SSriram Yagnaraman synchronize_net(); 4680f6ccf9SSriram Yagnaraman 4780f6ccf9SSriram Yagnaraman /* Rx/Tx share the same napi context. */ 4880f6ccf9SSriram Yagnaraman napi_disable(&rx_ring->q_vector->napi); 4980f6ccf9SSriram Yagnaraman 5080f6ccf9SSriram Yagnaraman igb_clean_tx_ring(tx_ring); 5180f6ccf9SSriram Yagnaraman igb_clean_rx_ring(rx_ring); 5280f6ccf9SSriram Yagnaraman 5380f6ccf9SSriram Yagnaraman memset(&rx_ring->rx_stats, 0, sizeof(rx_ring->rx_stats)); 5480f6ccf9SSriram Yagnaraman memset(&tx_ring->tx_stats, 0, sizeof(tx_ring->tx_stats)); 5580f6ccf9SSriram Yagnaraman } 5680f6ccf9SSriram Yagnaraman 5780f6ccf9SSriram Yagnaraman static void igb_txrx_ring_enable(struct igb_adapter *adapter, u16 qid) 5880f6ccf9SSriram Yagnaraman { 5980f6ccf9SSriram Yagnaraman struct igb_ring *tx_ring = adapter->tx_ring[qid]; 6080f6ccf9SSriram Yagnaraman struct igb_ring *rx_ring = adapter->rx_ring[qid]; 6180f6ccf9SSriram Yagnaraman 6280f6ccf9SSriram Yagnaraman igb_configure_tx_ring(adapter, tx_ring); 6380f6ccf9SSriram Yagnaraman igb_configure_rx_ring(adapter, rx_ring); 6480f6ccf9SSriram Yagnaraman 6580f6ccf9SSriram Yagnaraman synchronize_net(); 6680f6ccf9SSriram Yagnaraman 6780f6ccf9SSriram Yagnaraman clear_bit(IGB_RING_FLAG_TX_DISABLED, &tx_ring->flags); 6880f6ccf9SSriram Yagnaraman 6980f6ccf9SSriram Yagnaraman /* call igb_desc_unused which always leaves 7080f6ccf9SSriram Yagnaraman * at least 1 descriptor unused to make sure 7180f6ccf9SSriram Yagnaraman * next_to_use != next_to_clean 7280f6ccf9SSriram Yagnaraman */ 732c619601SSriram Yagnaraman if (rx_ring->xsk_pool) 742c619601SSriram Yagnaraman igb_alloc_rx_buffers_zc(rx_ring, rx_ring->xsk_pool, 752c619601SSriram Yagnaraman igb_desc_unused(rx_ring)); 762c619601SSriram Yagnaraman else 7780f6ccf9SSriram Yagnaraman igb_alloc_rx_buffers(rx_ring, igb_desc_unused(rx_ring)); 7880f6ccf9SSriram Yagnaraman 7980f6ccf9SSriram Yagnaraman /* Rx/Tx share the same napi context. */ 8080f6ccf9SSriram Yagnaraman napi_enable(&rx_ring->q_vector->napi); 8180f6ccf9SSriram Yagnaraman } 8280f6ccf9SSriram Yagnaraman 8380f6ccf9SSriram Yagnaraman struct xsk_buff_pool *igb_xsk_pool(struct igb_adapter *adapter, 8480f6ccf9SSriram Yagnaraman struct igb_ring *ring) 8580f6ccf9SSriram Yagnaraman { 8680f6ccf9SSriram Yagnaraman int qid = ring->queue_index; 8780f6ccf9SSriram Yagnaraman struct xsk_buff_pool *pool; 8880f6ccf9SSriram Yagnaraman 8980f6ccf9SSriram Yagnaraman pool = xsk_get_pool_from_qid(adapter->netdev, qid); 9080f6ccf9SSriram Yagnaraman 9180f6ccf9SSriram Yagnaraman if (!igb_xdp_is_enabled(adapter)) 9280f6ccf9SSriram Yagnaraman return NULL; 9380f6ccf9SSriram Yagnaraman 9480f6ccf9SSriram Yagnaraman return (pool && pool->dev) ? pool : NULL; 9580f6ccf9SSriram Yagnaraman } 9680f6ccf9SSriram Yagnaraman 9780f6ccf9SSriram Yagnaraman static int igb_xsk_pool_enable(struct igb_adapter *adapter, 9880f6ccf9SSriram Yagnaraman struct xsk_buff_pool *pool, 9980f6ccf9SSriram Yagnaraman u16 qid) 10080f6ccf9SSriram Yagnaraman { 10180f6ccf9SSriram Yagnaraman struct net_device *netdev = adapter->netdev; 10280f6ccf9SSriram Yagnaraman struct igb_ring *rx_ring; 10380f6ccf9SSriram Yagnaraman bool if_running; 10480f6ccf9SSriram Yagnaraman int err; 10580f6ccf9SSriram Yagnaraman 10680f6ccf9SSriram Yagnaraman if (qid >= adapter->num_rx_queues) 10780f6ccf9SSriram Yagnaraman return -EINVAL; 10880f6ccf9SSriram Yagnaraman 10980f6ccf9SSriram Yagnaraman if (qid >= netdev->real_num_rx_queues || 11080f6ccf9SSriram Yagnaraman qid >= netdev->real_num_tx_queues) 11180f6ccf9SSriram Yagnaraman return -EINVAL; 11280f6ccf9SSriram Yagnaraman 11380f6ccf9SSriram Yagnaraman err = xsk_pool_dma_map(pool, &adapter->pdev->dev, IGB_RX_DMA_ATTR); 11480f6ccf9SSriram Yagnaraman if (err) 11580f6ccf9SSriram Yagnaraman return err; 11680f6ccf9SSriram Yagnaraman 11780f6ccf9SSriram Yagnaraman rx_ring = adapter->rx_ring[qid]; 11880f6ccf9SSriram Yagnaraman if_running = netif_running(adapter->netdev) && igb_xdp_is_enabled(adapter); 11980f6ccf9SSriram Yagnaraman if (if_running) 12080f6ccf9SSriram Yagnaraman igb_txrx_ring_disable(adapter, qid); 12180f6ccf9SSriram Yagnaraman 12280f6ccf9SSriram Yagnaraman if (if_running) { 12380f6ccf9SSriram Yagnaraman err = igb_realloc_rx_buffer_info(rx_ring, true); 12480f6ccf9SSriram Yagnaraman if (!err) { 12580f6ccf9SSriram Yagnaraman igb_txrx_ring_enable(adapter, qid); 12680f6ccf9SSriram Yagnaraman /* Kick start the NAPI context so that receiving will start */ 12780f6ccf9SSriram Yagnaraman err = igb_xsk_wakeup(adapter->netdev, qid, XDP_WAKEUP_RX); 12880f6ccf9SSriram Yagnaraman } 12980f6ccf9SSriram Yagnaraman 13080f6ccf9SSriram Yagnaraman if (err) { 13180f6ccf9SSriram Yagnaraman xsk_pool_dma_unmap(pool, IGB_RX_DMA_ATTR); 13280f6ccf9SSriram Yagnaraman return err; 13380f6ccf9SSriram Yagnaraman } 13480f6ccf9SSriram Yagnaraman } 13580f6ccf9SSriram Yagnaraman 13680f6ccf9SSriram Yagnaraman return 0; 13780f6ccf9SSriram Yagnaraman } 13880f6ccf9SSriram Yagnaraman 13980f6ccf9SSriram Yagnaraman static int igb_xsk_pool_disable(struct igb_adapter *adapter, u16 qid) 14080f6ccf9SSriram Yagnaraman { 14180f6ccf9SSriram Yagnaraman struct xsk_buff_pool *pool; 14280f6ccf9SSriram Yagnaraman struct igb_ring *rx_ring; 14380f6ccf9SSriram Yagnaraman bool if_running; 14480f6ccf9SSriram Yagnaraman int err; 14580f6ccf9SSriram Yagnaraman 14680f6ccf9SSriram Yagnaraman pool = xsk_get_pool_from_qid(adapter->netdev, qid); 14780f6ccf9SSriram Yagnaraman if (!pool) 14880f6ccf9SSriram Yagnaraman return -EINVAL; 14980f6ccf9SSriram Yagnaraman 15080f6ccf9SSriram Yagnaraman rx_ring = adapter->rx_ring[qid]; 15180f6ccf9SSriram Yagnaraman if_running = netif_running(adapter->netdev) && igb_xdp_is_enabled(adapter); 15280f6ccf9SSriram Yagnaraman if (if_running) 15380f6ccf9SSriram Yagnaraman igb_txrx_ring_disable(adapter, qid); 15480f6ccf9SSriram Yagnaraman 15580f6ccf9SSriram Yagnaraman xsk_pool_dma_unmap(pool, IGB_RX_DMA_ATTR); 15680f6ccf9SSriram Yagnaraman 15780f6ccf9SSriram Yagnaraman if (if_running) { 15880f6ccf9SSriram Yagnaraman err = igb_realloc_rx_buffer_info(rx_ring, false); 15980f6ccf9SSriram Yagnaraman if (err) 16080f6ccf9SSriram Yagnaraman return err; 16180f6ccf9SSriram Yagnaraman 16280f6ccf9SSriram Yagnaraman igb_txrx_ring_enable(adapter, qid); 16380f6ccf9SSriram Yagnaraman } 16480f6ccf9SSriram Yagnaraman 16580f6ccf9SSriram Yagnaraman return 0; 16680f6ccf9SSriram Yagnaraman } 16780f6ccf9SSriram Yagnaraman 16880f6ccf9SSriram Yagnaraman int igb_xsk_pool_setup(struct igb_adapter *adapter, 16980f6ccf9SSriram Yagnaraman struct xsk_buff_pool *pool, 17080f6ccf9SSriram Yagnaraman u16 qid) 17180f6ccf9SSriram Yagnaraman { 17280f6ccf9SSriram Yagnaraman return pool ? igb_xsk_pool_enable(adapter, pool, qid) : 17380f6ccf9SSriram Yagnaraman igb_xsk_pool_disable(adapter, qid); 17480f6ccf9SSriram Yagnaraman } 17580f6ccf9SSriram Yagnaraman 1762c619601SSriram Yagnaraman static u16 igb_fill_rx_descs(struct xsk_buff_pool *pool, struct xdp_buff **xdp, 1772c619601SSriram Yagnaraman union e1000_adv_rx_desc *rx_desc, u16 count) 1782c619601SSriram Yagnaraman { 1792c619601SSriram Yagnaraman dma_addr_t dma; 1802c619601SSriram Yagnaraman u16 buffs; 1812c619601SSriram Yagnaraman int i; 1822c619601SSriram Yagnaraman 1832c619601SSriram Yagnaraman /* nothing to do */ 1842c619601SSriram Yagnaraman if (!count) 1852c619601SSriram Yagnaraman return 0; 1862c619601SSriram Yagnaraman 1872c619601SSriram Yagnaraman buffs = xsk_buff_alloc_batch(pool, xdp, count); 1882c619601SSriram Yagnaraman for (i = 0; i < buffs; i++) { 1892c619601SSriram Yagnaraman dma = xsk_buff_xdp_get_dma(*xdp); 1902c619601SSriram Yagnaraman rx_desc->read.pkt_addr = cpu_to_le64(dma); 1912c619601SSriram Yagnaraman rx_desc->wb.upper.length = 0; 1922c619601SSriram Yagnaraman 1932c619601SSriram Yagnaraman rx_desc++; 1942c619601SSriram Yagnaraman xdp++; 1952c619601SSriram Yagnaraman } 1962c619601SSriram Yagnaraman 1972c619601SSriram Yagnaraman return buffs; 1982c619601SSriram Yagnaraman } 1992c619601SSriram Yagnaraman 2002c619601SSriram Yagnaraman bool igb_alloc_rx_buffers_zc(struct igb_ring *rx_ring, 2012c619601SSriram Yagnaraman struct xsk_buff_pool *xsk_pool, u16 count) 2022c619601SSriram Yagnaraman { 2032c619601SSriram Yagnaraman u32 nb_buffs_extra = 0, nb_buffs = 0; 2042c619601SSriram Yagnaraman union e1000_adv_rx_desc *rx_desc; 2052c619601SSriram Yagnaraman u16 ntu = rx_ring->next_to_use; 2062c619601SSriram Yagnaraman u16 total_count = count; 2072c619601SSriram Yagnaraman struct xdp_buff **xdp; 2082c619601SSriram Yagnaraman 2092c619601SSriram Yagnaraman rx_desc = IGB_RX_DESC(rx_ring, ntu); 2102c619601SSriram Yagnaraman xdp = &rx_ring->rx_buffer_info_zc[ntu]; 2112c619601SSriram Yagnaraman 2122c619601SSriram Yagnaraman if (ntu + count >= rx_ring->count) { 2132c619601SSriram Yagnaraman nb_buffs_extra = igb_fill_rx_descs(xsk_pool, xdp, rx_desc, 2142c619601SSriram Yagnaraman rx_ring->count - ntu); 2152c619601SSriram Yagnaraman if (nb_buffs_extra != rx_ring->count - ntu) { 2162c619601SSriram Yagnaraman ntu += nb_buffs_extra; 2172c619601SSriram Yagnaraman goto exit; 2182c619601SSriram Yagnaraman } 2192c619601SSriram Yagnaraman rx_desc = IGB_RX_DESC(rx_ring, 0); 2202c619601SSriram Yagnaraman xdp = rx_ring->rx_buffer_info_zc; 2212c619601SSriram Yagnaraman ntu = 0; 2222c619601SSriram Yagnaraman count -= nb_buffs_extra; 2232c619601SSriram Yagnaraman } 2242c619601SSriram Yagnaraman 2252c619601SSriram Yagnaraman nb_buffs = igb_fill_rx_descs(xsk_pool, xdp, rx_desc, count); 2262c619601SSriram Yagnaraman ntu += nb_buffs; 2272c619601SSriram Yagnaraman if (ntu == rx_ring->count) 2282c619601SSriram Yagnaraman ntu = 0; 2292c619601SSriram Yagnaraman 2302c619601SSriram Yagnaraman /* clear the length for the next_to_use descriptor */ 2312c619601SSriram Yagnaraman rx_desc = IGB_RX_DESC(rx_ring, ntu); 2322c619601SSriram Yagnaraman rx_desc->wb.upper.length = 0; 2332c619601SSriram Yagnaraman 2342c619601SSriram Yagnaraman exit: 2352c619601SSriram Yagnaraman if (rx_ring->next_to_use != ntu) { 2362c619601SSriram Yagnaraman rx_ring->next_to_use = ntu; 2372c619601SSriram Yagnaraman 2382c619601SSriram Yagnaraman /* Force memory writes to complete before letting h/w 2392c619601SSriram Yagnaraman * know there are new descriptors to fetch. (Only 2402c619601SSriram Yagnaraman * applicable for weak-ordered memory model archs, 2412c619601SSriram Yagnaraman * such as IA-64). 2422c619601SSriram Yagnaraman */ 2432c619601SSriram Yagnaraman wmb(); 2442c619601SSriram Yagnaraman writel(ntu, rx_ring->tail); 2452c619601SSriram Yagnaraman } 2462c619601SSriram Yagnaraman 2472c619601SSriram Yagnaraman return total_count == (nb_buffs + nb_buffs_extra); 2482c619601SSriram Yagnaraman } 2492c619601SSriram Yagnaraman 2502c619601SSriram Yagnaraman void igb_clean_rx_ring_zc(struct igb_ring *rx_ring) 2512c619601SSriram Yagnaraman { 2522c619601SSriram Yagnaraman u16 ntc = rx_ring->next_to_clean; 2532c619601SSriram Yagnaraman u16 ntu = rx_ring->next_to_use; 2542c619601SSriram Yagnaraman 2552c619601SSriram Yagnaraman while (ntc != ntu) { 2562c619601SSriram Yagnaraman struct xdp_buff *xdp = rx_ring->rx_buffer_info_zc[ntc]; 2572c619601SSriram Yagnaraman 2582c619601SSriram Yagnaraman xsk_buff_free(xdp); 2592c619601SSriram Yagnaraman ntc++; 2602c619601SSriram Yagnaraman if (ntc >= rx_ring->count) 2612c619601SSriram Yagnaraman ntc = 0; 2622c619601SSriram Yagnaraman } 2632c619601SSriram Yagnaraman } 2642c619601SSriram Yagnaraman 2652c619601SSriram Yagnaraman static struct sk_buff *igb_construct_skb_zc(struct igb_ring *rx_ring, 2662c619601SSriram Yagnaraman struct xdp_buff *xdp, 2672c619601SSriram Yagnaraman ktime_t timestamp) 2682c619601SSriram Yagnaraman { 2692c619601SSriram Yagnaraman unsigned int totalsize = xdp->data_end - xdp->data_meta; 2702c619601SSriram Yagnaraman unsigned int metasize = xdp->data - xdp->data_meta; 2712c619601SSriram Yagnaraman struct sk_buff *skb; 2722c619601SSriram Yagnaraman 2732c619601SSriram Yagnaraman net_prefetch(xdp->data_meta); 2742c619601SSriram Yagnaraman 2752c619601SSriram Yagnaraman /* allocate a skb to store the frags */ 2762c619601SSriram Yagnaraman skb = napi_alloc_skb(&rx_ring->q_vector->napi, totalsize); 2772c619601SSriram Yagnaraman if (unlikely(!skb)) 2782c619601SSriram Yagnaraman return NULL; 2792c619601SSriram Yagnaraman 2802c619601SSriram Yagnaraman if (timestamp) 2812c619601SSriram Yagnaraman skb_hwtstamps(skb)->hwtstamp = timestamp; 2822c619601SSriram Yagnaraman 2832c619601SSriram Yagnaraman memcpy(__skb_put(skb, totalsize), xdp->data_meta, 2842c619601SSriram Yagnaraman ALIGN(totalsize, sizeof(long))); 2852c619601SSriram Yagnaraman 2862c619601SSriram Yagnaraman if (metasize) { 2872c619601SSriram Yagnaraman skb_metadata_set(skb, metasize); 2882c619601SSriram Yagnaraman __skb_pull(skb, metasize); 2892c619601SSriram Yagnaraman } 2902c619601SSriram Yagnaraman 2912c619601SSriram Yagnaraman return skb; 2922c619601SSriram Yagnaraman } 2932c619601SSriram Yagnaraman 2942c619601SSriram Yagnaraman static int igb_run_xdp_zc(struct igb_adapter *adapter, struct igb_ring *rx_ring, 2952c619601SSriram Yagnaraman struct xdp_buff *xdp, struct xsk_buff_pool *xsk_pool, 2962c619601SSriram Yagnaraman struct bpf_prog *xdp_prog) 2972c619601SSriram Yagnaraman { 2982c619601SSriram Yagnaraman int err, result = IGB_XDP_PASS; 2992c619601SSriram Yagnaraman u32 act; 3002c619601SSriram Yagnaraman 3012c619601SSriram Yagnaraman prefetchw(xdp->data_hard_start); /* xdp_frame write */ 3022c619601SSriram Yagnaraman 3032c619601SSriram Yagnaraman act = bpf_prog_run_xdp(xdp_prog, xdp); 3042c619601SSriram Yagnaraman 3052c619601SSriram Yagnaraman if (likely(act == XDP_REDIRECT)) { 3062c619601SSriram Yagnaraman err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog); 3072c619601SSriram Yagnaraman if (!err) 3082c619601SSriram Yagnaraman return IGB_XDP_REDIR; 3092c619601SSriram Yagnaraman 3102c619601SSriram Yagnaraman if (xsk_uses_need_wakeup(xsk_pool) && 3112c619601SSriram Yagnaraman err == -ENOBUFS) 3122c619601SSriram Yagnaraman result = IGB_XDP_EXIT; 3132c619601SSriram Yagnaraman else 3142c619601SSriram Yagnaraman result = IGB_XDP_CONSUMED; 3152c619601SSriram Yagnaraman goto out_failure; 3162c619601SSriram Yagnaraman } 3172c619601SSriram Yagnaraman 3182c619601SSriram Yagnaraman switch (act) { 3192c619601SSriram Yagnaraman case XDP_PASS: 3202c619601SSriram Yagnaraman break; 3212c619601SSriram Yagnaraman case XDP_TX: 3222c619601SSriram Yagnaraman result = igb_xdp_xmit_back(adapter, xdp); 3232c619601SSriram Yagnaraman if (result == IGB_XDP_CONSUMED) 3242c619601SSriram Yagnaraman goto out_failure; 3252c619601SSriram Yagnaraman break; 3262c619601SSriram Yagnaraman default: 3272c619601SSriram Yagnaraman bpf_warn_invalid_xdp_action(adapter->netdev, xdp_prog, act); 3282c619601SSriram Yagnaraman fallthrough; 3292c619601SSriram Yagnaraman case XDP_ABORTED: 3302c619601SSriram Yagnaraman out_failure: 3312c619601SSriram Yagnaraman trace_xdp_exception(rx_ring->netdev, xdp_prog, act); 3322c619601SSriram Yagnaraman fallthrough; 3332c619601SSriram Yagnaraman case XDP_DROP: 3342c619601SSriram Yagnaraman result = IGB_XDP_CONSUMED; 3352c619601SSriram Yagnaraman break; 3362c619601SSriram Yagnaraman } 3372c619601SSriram Yagnaraman 3382c619601SSriram Yagnaraman return result; 3392c619601SSriram Yagnaraman } 3402c619601SSriram Yagnaraman 3412c619601SSriram Yagnaraman int igb_clean_rx_irq_zc(struct igb_q_vector *q_vector, 3422c619601SSriram Yagnaraman struct xsk_buff_pool *xsk_pool, const int budget) 3432c619601SSriram Yagnaraman { 3442c619601SSriram Yagnaraman struct igb_adapter *adapter = q_vector->adapter; 3452c619601SSriram Yagnaraman unsigned int total_bytes = 0, total_packets = 0; 3462c619601SSriram Yagnaraman struct igb_ring *rx_ring = q_vector->rx.ring; 3472c619601SSriram Yagnaraman u32 ntc = rx_ring->next_to_clean; 3482c619601SSriram Yagnaraman struct bpf_prog *xdp_prog; 3492c619601SSriram Yagnaraman unsigned int xdp_xmit = 0; 3502c619601SSriram Yagnaraman bool failure = false; 3512c619601SSriram Yagnaraman u16 entries_to_alloc; 3522c619601SSriram Yagnaraman struct sk_buff *skb; 3532c619601SSriram Yagnaraman 3542c619601SSriram Yagnaraman /* xdp_prog cannot be NULL in the ZC path */ 3552c619601SSriram Yagnaraman xdp_prog = READ_ONCE(rx_ring->xdp_prog); 3562c619601SSriram Yagnaraman 3572c619601SSriram Yagnaraman while (likely(total_packets < budget)) { 3582c619601SSriram Yagnaraman union e1000_adv_rx_desc *rx_desc; 3592c619601SSriram Yagnaraman ktime_t timestamp = 0; 3602c619601SSriram Yagnaraman struct xdp_buff *xdp; 3612c619601SSriram Yagnaraman unsigned int size; 3622c619601SSriram Yagnaraman int xdp_res = 0; 3632c619601SSriram Yagnaraman 3642c619601SSriram Yagnaraman rx_desc = IGB_RX_DESC(rx_ring, ntc); 3652c619601SSriram Yagnaraman size = le16_to_cpu(rx_desc->wb.upper.length); 3662c619601SSriram Yagnaraman if (!size) 3672c619601SSriram Yagnaraman break; 3682c619601SSriram Yagnaraman 3692c619601SSriram Yagnaraman /* This memory barrier is needed to keep us from reading 3702c619601SSriram Yagnaraman * any other fields out of the rx_desc until we know the 3712c619601SSriram Yagnaraman * descriptor has been written back 3722c619601SSriram Yagnaraman */ 3732c619601SSriram Yagnaraman dma_rmb(); 3742c619601SSriram Yagnaraman 3752c619601SSriram Yagnaraman xdp = rx_ring->rx_buffer_info_zc[ntc]; 3762c619601SSriram Yagnaraman xsk_buff_set_size(xdp, size); 3772c619601SSriram Yagnaraman xsk_buff_dma_sync_for_cpu(xdp); 3782c619601SSriram Yagnaraman 3792c619601SSriram Yagnaraman /* pull rx packet timestamp if available and valid */ 3802c619601SSriram Yagnaraman if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { 3812c619601SSriram Yagnaraman int ts_hdr_len; 3822c619601SSriram Yagnaraman 3832c619601SSriram Yagnaraman ts_hdr_len = igb_ptp_rx_pktstamp(rx_ring->q_vector, 3842c619601SSriram Yagnaraman xdp->data, 3852c619601SSriram Yagnaraman ×tamp); 3862c619601SSriram Yagnaraman 3872c619601SSriram Yagnaraman xdp->data += ts_hdr_len; 3882c619601SSriram Yagnaraman xdp->data_meta += ts_hdr_len; 3892c619601SSriram Yagnaraman size -= ts_hdr_len; 3902c619601SSriram Yagnaraman } 3912c619601SSriram Yagnaraman 3922c619601SSriram Yagnaraman xdp_res = igb_run_xdp_zc(adapter, rx_ring, xdp, xsk_pool, 3932c619601SSriram Yagnaraman xdp_prog); 3942c619601SSriram Yagnaraman 3952c619601SSriram Yagnaraman if (xdp_res) { 3962c619601SSriram Yagnaraman if (likely(xdp_res & (IGB_XDP_TX | IGB_XDP_REDIR))) { 3972c619601SSriram Yagnaraman xdp_xmit |= xdp_res; 3982c619601SSriram Yagnaraman } else if (xdp_res == IGB_XDP_EXIT) { 3992c619601SSriram Yagnaraman failure = true; 4002c619601SSriram Yagnaraman break; 4012c619601SSriram Yagnaraman } else if (xdp_res == IGB_XDP_CONSUMED) { 4022c619601SSriram Yagnaraman xsk_buff_free(xdp); 4032c619601SSriram Yagnaraman } 4042c619601SSriram Yagnaraman 4052c619601SSriram Yagnaraman total_packets++; 4062c619601SSriram Yagnaraman total_bytes += size; 4072c619601SSriram Yagnaraman ntc++; 4082c619601SSriram Yagnaraman if (ntc == rx_ring->count) 4092c619601SSriram Yagnaraman ntc = 0; 4102c619601SSriram Yagnaraman continue; 4112c619601SSriram Yagnaraman } 4122c619601SSriram Yagnaraman 4132c619601SSriram Yagnaraman skb = igb_construct_skb_zc(rx_ring, xdp, timestamp); 4142c619601SSriram Yagnaraman 4152c619601SSriram Yagnaraman /* exit if we failed to retrieve a buffer */ 4162c619601SSriram Yagnaraman if (!skb) { 4172c619601SSriram Yagnaraman rx_ring->rx_stats.alloc_failed++; 4182c619601SSriram Yagnaraman break; 4192c619601SSriram Yagnaraman } 4202c619601SSriram Yagnaraman 4212c619601SSriram Yagnaraman xsk_buff_free(xdp); 4222c619601SSriram Yagnaraman ntc++; 4232c619601SSriram Yagnaraman if (ntc == rx_ring->count) 4242c619601SSriram Yagnaraman ntc = 0; 4252c619601SSriram Yagnaraman 4262c619601SSriram Yagnaraman if (eth_skb_pad(skb)) 4272c619601SSriram Yagnaraman continue; 4282c619601SSriram Yagnaraman 4292c619601SSriram Yagnaraman /* probably a little skewed due to removing CRC */ 4302c619601SSriram Yagnaraman total_bytes += skb->len; 4312c619601SSriram Yagnaraman 4322c619601SSriram Yagnaraman /* populate checksum, timestamp, VLAN, and protocol */ 4332c619601SSriram Yagnaraman igb_process_skb_fields(rx_ring, rx_desc, skb); 4342c619601SSriram Yagnaraman 4352c619601SSriram Yagnaraman napi_gro_receive(&q_vector->napi, skb); 4362c619601SSriram Yagnaraman 4372c619601SSriram Yagnaraman /* update budget accounting */ 4382c619601SSriram Yagnaraman total_packets++; 4392c619601SSriram Yagnaraman } 4402c619601SSriram Yagnaraman 4412c619601SSriram Yagnaraman rx_ring->next_to_clean = ntc; 4422c619601SSriram Yagnaraman 4432c619601SSriram Yagnaraman if (xdp_xmit) 4442c619601SSriram Yagnaraman igb_finalize_xdp(adapter, xdp_xmit); 4452c619601SSriram Yagnaraman 4462c619601SSriram Yagnaraman igb_update_rx_stats(q_vector, total_packets, total_bytes); 4472c619601SSriram Yagnaraman 4482c619601SSriram Yagnaraman entries_to_alloc = igb_desc_unused(rx_ring); 4492c619601SSriram Yagnaraman if (entries_to_alloc >= IGB_RX_BUFFER_WRITE) 4502c619601SSriram Yagnaraman failure |= !igb_alloc_rx_buffers_zc(rx_ring, xsk_pool, 4512c619601SSriram Yagnaraman entries_to_alloc); 4522c619601SSriram Yagnaraman 4532c619601SSriram Yagnaraman if (xsk_uses_need_wakeup(xsk_pool)) { 4542c619601SSriram Yagnaraman if (failure || rx_ring->next_to_clean == rx_ring->next_to_use) 4552c619601SSriram Yagnaraman xsk_set_rx_need_wakeup(xsk_pool); 4562c619601SSriram Yagnaraman else 4572c619601SSriram Yagnaraman xsk_clear_rx_need_wakeup(xsk_pool); 4582c619601SSriram Yagnaraman 4592c619601SSriram Yagnaraman return (int)total_packets; 4602c619601SSriram Yagnaraman } 4612c619601SSriram Yagnaraman return failure ? budget : (int)total_packets; 4622c619601SSriram Yagnaraman } 4632c619601SSriram Yagnaraman 464*f8e284a0SSriram Yagnaraman bool igb_xmit_zc(struct igb_ring *tx_ring, struct xsk_buff_pool *xsk_pool) 465*f8e284a0SSriram Yagnaraman { 466*f8e284a0SSriram Yagnaraman unsigned int budget = igb_desc_unused(tx_ring); 467*f8e284a0SSriram Yagnaraman u32 cmd_type, olinfo_status, nb_pkts, i = 0; 468*f8e284a0SSriram Yagnaraman struct xdp_desc *descs = xsk_pool->tx_descs; 469*f8e284a0SSriram Yagnaraman union e1000_adv_tx_desc *tx_desc = NULL; 470*f8e284a0SSriram Yagnaraman struct igb_tx_buffer *tx_buffer_info; 471*f8e284a0SSriram Yagnaraman unsigned int total_bytes = 0; 472*f8e284a0SSriram Yagnaraman dma_addr_t dma; 473*f8e284a0SSriram Yagnaraman 474*f8e284a0SSriram Yagnaraman if (!netif_carrier_ok(tx_ring->netdev)) 475*f8e284a0SSriram Yagnaraman return true; 476*f8e284a0SSriram Yagnaraman 477*f8e284a0SSriram Yagnaraman if (test_bit(IGB_RING_FLAG_TX_DISABLED, &tx_ring->flags)) 478*f8e284a0SSriram Yagnaraman return true; 479*f8e284a0SSriram Yagnaraman 480*f8e284a0SSriram Yagnaraman nb_pkts = xsk_tx_peek_release_desc_batch(xsk_pool, budget); 481*f8e284a0SSriram Yagnaraman if (!nb_pkts) 482*f8e284a0SSriram Yagnaraman return true; 483*f8e284a0SSriram Yagnaraman 484*f8e284a0SSriram Yagnaraman while (nb_pkts-- > 0) { 485*f8e284a0SSriram Yagnaraman dma = xsk_buff_raw_get_dma(xsk_pool, descs[i].addr); 486*f8e284a0SSriram Yagnaraman xsk_buff_raw_dma_sync_for_device(xsk_pool, dma, descs[i].len); 487*f8e284a0SSriram Yagnaraman 488*f8e284a0SSriram Yagnaraman tx_buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; 489*f8e284a0SSriram Yagnaraman tx_buffer_info->bytecount = descs[i].len; 490*f8e284a0SSriram Yagnaraman tx_buffer_info->type = IGB_TYPE_XSK; 491*f8e284a0SSriram Yagnaraman tx_buffer_info->xdpf = NULL; 492*f8e284a0SSriram Yagnaraman tx_buffer_info->gso_segs = 1; 493*f8e284a0SSriram Yagnaraman tx_buffer_info->time_stamp = jiffies; 494*f8e284a0SSriram Yagnaraman 495*f8e284a0SSriram Yagnaraman tx_desc = IGB_TX_DESC(tx_ring, tx_ring->next_to_use); 496*f8e284a0SSriram Yagnaraman tx_desc->read.buffer_addr = cpu_to_le64(dma); 497*f8e284a0SSriram Yagnaraman 498*f8e284a0SSriram Yagnaraman /* put descriptor type bits */ 499*f8e284a0SSriram Yagnaraman cmd_type = E1000_ADVTXD_DTYP_DATA | E1000_ADVTXD_DCMD_DEXT | 500*f8e284a0SSriram Yagnaraman E1000_ADVTXD_DCMD_IFCS; 501*f8e284a0SSriram Yagnaraman olinfo_status = descs[i].len << E1000_ADVTXD_PAYLEN_SHIFT; 502*f8e284a0SSriram Yagnaraman 503*f8e284a0SSriram Yagnaraman /* FIXME: This sets the Report Status (RS) bit for every 504*f8e284a0SSriram Yagnaraman * descriptor. One nice to have optimization would be to set it 505*f8e284a0SSriram Yagnaraman * only for the last descriptor in the whole batch. See Intel 506*f8e284a0SSriram Yagnaraman * ice driver for an example on how to do it. 507*f8e284a0SSriram Yagnaraman */ 508*f8e284a0SSriram Yagnaraman cmd_type |= descs[i].len | IGB_TXD_DCMD; 509*f8e284a0SSriram Yagnaraman tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); 510*f8e284a0SSriram Yagnaraman tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); 511*f8e284a0SSriram Yagnaraman 512*f8e284a0SSriram Yagnaraman total_bytes += descs[i].len; 513*f8e284a0SSriram Yagnaraman 514*f8e284a0SSriram Yagnaraman i++; 515*f8e284a0SSriram Yagnaraman tx_ring->next_to_use++; 516*f8e284a0SSriram Yagnaraman tx_buffer_info->next_to_watch = tx_desc; 517*f8e284a0SSriram Yagnaraman if (tx_ring->next_to_use == tx_ring->count) 518*f8e284a0SSriram Yagnaraman tx_ring->next_to_use = 0; 519*f8e284a0SSriram Yagnaraman } 520*f8e284a0SSriram Yagnaraman 521*f8e284a0SSriram Yagnaraman netdev_tx_sent_queue(txring_txq(tx_ring), total_bytes); 522*f8e284a0SSriram Yagnaraman igb_xdp_ring_update_tail(tx_ring); 523*f8e284a0SSriram Yagnaraman 524*f8e284a0SSriram Yagnaraman return nb_pkts < budget; 525*f8e284a0SSriram Yagnaraman } 526*f8e284a0SSriram Yagnaraman 52780f6ccf9SSriram Yagnaraman int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags) 52880f6ccf9SSriram Yagnaraman { 52980f6ccf9SSriram Yagnaraman struct igb_adapter *adapter = netdev_priv(dev); 53080f6ccf9SSriram Yagnaraman struct e1000_hw *hw = &adapter->hw; 53180f6ccf9SSriram Yagnaraman struct igb_ring *ring; 53280f6ccf9SSriram Yagnaraman u32 eics = 0; 53380f6ccf9SSriram Yagnaraman 53480f6ccf9SSriram Yagnaraman if (test_bit(__IGB_DOWN, &adapter->state)) 53580f6ccf9SSriram Yagnaraman return -ENETDOWN; 53680f6ccf9SSriram Yagnaraman 53780f6ccf9SSriram Yagnaraman if (!igb_xdp_is_enabled(adapter)) 53880f6ccf9SSriram Yagnaraman return -EINVAL; 53980f6ccf9SSriram Yagnaraman 54080f6ccf9SSriram Yagnaraman if (qid >= adapter->num_tx_queues) 54180f6ccf9SSriram Yagnaraman return -EINVAL; 54280f6ccf9SSriram Yagnaraman 54380f6ccf9SSriram Yagnaraman ring = adapter->tx_ring[qid]; 54480f6ccf9SSriram Yagnaraman 54580f6ccf9SSriram Yagnaraman if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags)) 54680f6ccf9SSriram Yagnaraman return -ENETDOWN; 54780f6ccf9SSriram Yagnaraman 54880f6ccf9SSriram Yagnaraman if (!READ_ONCE(ring->xsk_pool)) 54980f6ccf9SSriram Yagnaraman return -EINVAL; 55080f6ccf9SSriram Yagnaraman 55180f6ccf9SSriram Yagnaraman if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) { 55280f6ccf9SSriram Yagnaraman /* Cause software interrupt */ 55380f6ccf9SSriram Yagnaraman if (adapter->flags & IGB_FLAG_HAS_MSIX) { 55480f6ccf9SSriram Yagnaraman eics |= ring->q_vector->eims_value; 55580f6ccf9SSriram Yagnaraman wr32(E1000_EICS, eics); 55680f6ccf9SSriram Yagnaraman } else { 55780f6ccf9SSriram Yagnaraman wr32(E1000_ICS, E1000_ICS_RXDMT0); 55880f6ccf9SSriram Yagnaraman } 55980f6ccf9SSriram Yagnaraman } 56080f6ccf9SSriram Yagnaraman 56180f6ccf9SSriram Yagnaraman return 0; 56280f6ccf9SSriram Yagnaraman } 563