cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rings.c (7071B)


      1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
      2/* Copyright (C) 2015-2019 Netronome Systems, Inc. */
      3
      4#include <linux/seq_file.h>
      5
      6#include "../nfp_net.h"
      7#include "../nfp_net_dp.h"
      8#include "../nfp_net_xsk.h"
      9#include "nfd3.h"
     10
     11static void nfp_nfd3_xsk_tx_bufs_free(struct nfp_net_tx_ring *tx_ring)
     12{
     13	struct nfp_nfd3_tx_buf *txbuf;
     14	unsigned int idx;
     15
     16	while (tx_ring->rd_p != tx_ring->wr_p) {
     17		idx = D_IDX(tx_ring, tx_ring->rd_p);
     18		txbuf = &tx_ring->txbufs[idx];
     19
     20		txbuf->real_len = 0;
     21
     22		tx_ring->qcp_rd_p++;
     23		tx_ring->rd_p++;
     24
     25		if (tx_ring->r_vec->xsk_pool) {
     26			if (txbuf->is_xsk_tx)
     27				nfp_nfd3_xsk_tx_free(txbuf);
     28
     29			xsk_tx_completed(tx_ring->r_vec->xsk_pool, 1);
     30		}
     31	}
     32}
     33
     34/**
     35 * nfp_nfd3_tx_ring_reset() - Free any untransmitted buffers and reset pointers
     36 * @dp:		NFP Net data path struct
     37 * @tx_ring:	TX ring structure
     38 *
     39 * Assumes that the device is stopped, must be idempotent.
     40 */
     41static void
     42nfp_nfd3_tx_ring_reset(struct nfp_net_dp *dp, struct nfp_net_tx_ring *tx_ring)
     43{
     44	struct netdev_queue *nd_q;
     45	const skb_frag_t *frag;
     46
     47	while (!tx_ring->is_xdp && tx_ring->rd_p != tx_ring->wr_p) {
     48		struct nfp_nfd3_tx_buf *tx_buf;
     49		struct sk_buff *skb;
     50		int idx, nr_frags;
     51
     52		idx = D_IDX(tx_ring, tx_ring->rd_p);
     53		tx_buf = &tx_ring->txbufs[idx];
     54
     55		skb = tx_ring->txbufs[idx].skb;
     56		nr_frags = skb_shinfo(skb)->nr_frags;
     57
     58		if (tx_buf->fidx == -1) {
     59			/* unmap head */
     60			dma_unmap_single(dp->dev, tx_buf->dma_addr,
     61					 skb_headlen(skb), DMA_TO_DEVICE);
     62		} else {
     63			/* unmap fragment */
     64			frag = &skb_shinfo(skb)->frags[tx_buf->fidx];
     65			dma_unmap_page(dp->dev, tx_buf->dma_addr,
     66				       skb_frag_size(frag), DMA_TO_DEVICE);
     67		}
     68
     69		/* check for last gather fragment */
     70		if (tx_buf->fidx == nr_frags - 1)
     71			dev_kfree_skb_any(skb);
     72
     73		tx_buf->dma_addr = 0;
     74		tx_buf->skb = NULL;
     75		tx_buf->fidx = -2;
     76
     77		tx_ring->qcp_rd_p++;
     78		tx_ring->rd_p++;
     79	}
     80
     81	if (tx_ring->is_xdp)
     82		nfp_nfd3_xsk_tx_bufs_free(tx_ring);
     83
     84	memset(tx_ring->txds, 0, tx_ring->size);
     85	tx_ring->wr_p = 0;
     86	tx_ring->rd_p = 0;
     87	tx_ring->qcp_rd_p = 0;
     88	tx_ring->wr_ptr_add = 0;
     89
     90	if (tx_ring->is_xdp || !dp->netdev)
     91		return;
     92
     93	nd_q = netdev_get_tx_queue(dp->netdev, tx_ring->idx);
     94	netdev_tx_reset_queue(nd_q);
     95}
     96
     97/**
     98 * nfp_nfd3_tx_ring_free() - Free resources allocated to a TX ring
     99 * @tx_ring:   TX ring to free
    100 */
    101static void nfp_nfd3_tx_ring_free(struct nfp_net_tx_ring *tx_ring)
    102{
    103	struct nfp_net_r_vector *r_vec = tx_ring->r_vec;
    104	struct nfp_net_dp *dp = &r_vec->nfp_net->dp;
    105
    106	kvfree(tx_ring->txbufs);
    107
    108	if (tx_ring->txds)
    109		dma_free_coherent(dp->dev, tx_ring->size,
    110				  tx_ring->txds, tx_ring->dma);
    111
    112	tx_ring->cnt = 0;
    113	tx_ring->txbufs = NULL;
    114	tx_ring->txds = NULL;
    115	tx_ring->dma = 0;
    116	tx_ring->size = 0;
    117}
    118
    119/**
    120 * nfp_nfd3_tx_ring_alloc() - Allocate resource for a TX ring
    121 * @dp:        NFP Net data path struct
    122 * @tx_ring:   TX Ring structure to allocate
    123 *
    124 * Return: 0 on success, negative errno otherwise.
    125 */
    126static int
    127nfp_nfd3_tx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_tx_ring *tx_ring)
    128{
    129	struct nfp_net_r_vector *r_vec = tx_ring->r_vec;
    130
    131	tx_ring->cnt = dp->txd_cnt;
    132
    133	tx_ring->size = array_size(tx_ring->cnt, sizeof(*tx_ring->txds));
    134	tx_ring->txds = dma_alloc_coherent(dp->dev, tx_ring->size,
    135					   &tx_ring->dma,
    136					   GFP_KERNEL | __GFP_NOWARN);
    137	if (!tx_ring->txds) {
    138		netdev_warn(dp->netdev, "failed to allocate TX descriptor ring memory, requested descriptor count: %d, consider lowering descriptor count\n",
    139			    tx_ring->cnt);
    140		goto err_alloc;
    141	}
    142
    143	tx_ring->txbufs = kvcalloc(tx_ring->cnt, sizeof(*tx_ring->txbufs),
    144				   GFP_KERNEL);
    145	if (!tx_ring->txbufs)
    146		goto err_alloc;
    147
    148	if (!tx_ring->is_xdp && dp->netdev)
    149		netif_set_xps_queue(dp->netdev, &r_vec->affinity_mask,
    150				    tx_ring->idx);
    151
    152	return 0;
    153
    154err_alloc:
    155	nfp_nfd3_tx_ring_free(tx_ring);
    156	return -ENOMEM;
    157}
    158
    159static void
    160nfp_nfd3_tx_ring_bufs_free(struct nfp_net_dp *dp,
    161			   struct nfp_net_tx_ring *tx_ring)
    162{
    163	unsigned int i;
    164
    165	if (!tx_ring->is_xdp)
    166		return;
    167
    168	for (i = 0; i < tx_ring->cnt; i++) {
    169		if (!tx_ring->txbufs[i].frag)
    170			return;
    171
    172		nfp_net_dma_unmap_rx(dp, tx_ring->txbufs[i].dma_addr);
    173		__free_page(virt_to_page(tx_ring->txbufs[i].frag));
    174	}
    175}
    176
    177static int
    178nfp_nfd3_tx_ring_bufs_alloc(struct nfp_net_dp *dp,
    179			    struct nfp_net_tx_ring *tx_ring)
    180{
    181	struct nfp_nfd3_tx_buf *txbufs = tx_ring->txbufs;
    182	unsigned int i;
    183
    184	if (!tx_ring->is_xdp)
    185		return 0;
    186
    187	for (i = 0; i < tx_ring->cnt; i++) {
    188		txbufs[i].frag = nfp_net_rx_alloc_one(dp, &txbufs[i].dma_addr);
    189		if (!txbufs[i].frag) {
    190			nfp_nfd3_tx_ring_bufs_free(dp, tx_ring);
    191			return -ENOMEM;
    192		}
    193	}
    194
    195	return 0;
    196}
    197
    198static void
    199nfp_nfd3_print_tx_descs(struct seq_file *file,
    200			struct nfp_net_r_vector *r_vec,
    201			struct nfp_net_tx_ring *tx_ring,
    202			u32 d_rd_p, u32 d_wr_p)
    203{
    204	struct nfp_nfd3_tx_desc *txd;
    205	u32 txd_cnt = tx_ring->cnt;
    206	int i;
    207
    208	for (i = 0; i < txd_cnt; i++) {
    209		struct xdp_buff *xdp;
    210		struct sk_buff *skb;
    211
    212		txd = &tx_ring->txds[i];
    213		seq_printf(file, "%04d: 0x%08x 0x%08x 0x%08x 0x%08x", i,
    214			   txd->vals[0], txd->vals[1],
    215			   txd->vals[2], txd->vals[3]);
    216
    217		if (!tx_ring->is_xdp) {
    218			skb = READ_ONCE(tx_ring->txbufs[i].skb);
    219			if (skb)
    220				seq_printf(file, " skb->head=%p skb->data=%p",
    221					   skb->head, skb->data);
    222		} else {
    223			xdp = READ_ONCE(tx_ring->txbufs[i].xdp);
    224			if (xdp)
    225				seq_printf(file, " xdp->data=%p", xdp->data);
    226		}
    227
    228		if (tx_ring->txbufs[i].dma_addr)
    229			seq_printf(file, " dma_addr=%pad",
    230				   &tx_ring->txbufs[i].dma_addr);
    231
    232		if (i == tx_ring->rd_p % txd_cnt)
    233			seq_puts(file, " H_RD");
    234		if (i == tx_ring->wr_p % txd_cnt)
    235			seq_puts(file, " H_WR");
    236		if (i == d_rd_p % txd_cnt)
    237			seq_puts(file, " D_RD");
    238		if (i == d_wr_p % txd_cnt)
    239			seq_puts(file, " D_WR");
    240
    241		seq_putc(file, '\n');
    242	}
    243}
    244
    245#define NFP_NFD3_CFG_CTRL_SUPPORTED					\
    246	(NFP_NET_CFG_CTRL_ENABLE | NFP_NET_CFG_CTRL_PROMISC |		\
    247	 NFP_NET_CFG_CTRL_L2BC | NFP_NET_CFG_CTRL_L2MC |		\
    248	 NFP_NET_CFG_CTRL_RXCSUM | NFP_NET_CFG_CTRL_TXCSUM |		\
    249	 NFP_NET_CFG_CTRL_RXVLAN | NFP_NET_CFG_CTRL_TXVLAN |		\
    250	 NFP_NET_CFG_CTRL_GATHER | NFP_NET_CFG_CTRL_LSO |		\
    251	 NFP_NET_CFG_CTRL_CTAG_FILTER | NFP_NET_CFG_CTRL_CMSG_DATA |	\
    252	 NFP_NET_CFG_CTRL_RINGCFG | NFP_NET_CFG_CTRL_RSS |		\
    253	 NFP_NET_CFG_CTRL_IRQMOD | NFP_NET_CFG_CTRL_TXRWB |		\
    254	 NFP_NET_CFG_CTRL_VXLAN | NFP_NET_CFG_CTRL_NVGRE |		\
    255	 NFP_NET_CFG_CTRL_BPF | NFP_NET_CFG_CTRL_LSO2 |			\
    256	 NFP_NET_CFG_CTRL_RSS2 | NFP_NET_CFG_CTRL_CSUM_COMPLETE |	\
    257	 NFP_NET_CFG_CTRL_LIVE_ADDR)
    258
    259const struct nfp_dp_ops nfp_nfd3_ops = {
    260	.version		= NFP_NFD_VER_NFD3,
    261	.tx_min_desc_per_pkt	= 1,
    262	.cap_mask		= NFP_NFD3_CFG_CTRL_SUPPORTED,
    263	.poll			= nfp_nfd3_poll,
    264	.xsk_poll		= nfp_nfd3_xsk_poll,
    265	.ctrl_poll		= nfp_nfd3_ctrl_poll,
    266	.xmit			= nfp_nfd3_tx,
    267	.ctrl_tx_one		= nfp_nfd3_ctrl_tx_one,
    268	.rx_ring_fill_freelist	= nfp_nfd3_rx_ring_fill_freelist,
    269	.tx_ring_alloc		= nfp_nfd3_tx_ring_alloc,
    270	.tx_ring_reset		= nfp_nfd3_tx_ring_reset,
    271	.tx_ring_free		= nfp_nfd3_tx_ring_free,
    272	.tx_ring_bufs_alloc	= nfp_nfd3_tx_ring_bufs_alloc,
    273	.tx_ring_bufs_free	= nfp_nfd3_tx_ring_bufs_free,
    274	.print_tx_descs		= nfp_nfd3_print_tx_descs
    275};