Commit 169650d3 authored by David S. Miller's avatar David S. Miller

Merge branch 'nfp-cleanups-and-RX-path-rewrite'

Jakub Kicinski says:

====================
nfp: cleanups and RX path rewrite

This series lays groundwork for upcoming XDP support by updating
the RX path not to pre-allocate sk_buffs.  I start with few
cleanups, removal of NFP3200-related code being the most significant.
Patch 7 moves to alloc_frag() and build_skb() APIs.  Again, a number
of small cleanups follow.  The set ends with adding support for
different number of RX and TX rings.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6d052e9a cbeaf7aa
...@@ -75,7 +75,6 @@ ...@@ -75,7 +75,6 @@
/* Default size for MTU and freelist buffer sizes */ /* Default size for MTU and freelist buffer sizes */
#define NFP_NET_DEFAULT_MTU 1500 #define NFP_NET_DEFAULT_MTU 1500
#define NFP_NET_DEFAULT_RX_BUFSZ 2048
/* Maximum number of bytes prepended to a packet */ /* Maximum number of bytes prepended to a packet */
#define NFP_NET_MAX_PREPEND 64 #define NFP_NET_MAX_PREPEND 64
...@@ -88,6 +87,9 @@ ...@@ -88,6 +87,9 @@
/* Queue/Ring definitions */ /* Queue/Ring definitions */
#define NFP_NET_MAX_TX_RINGS 64 /* Max. # of Tx rings per device */ #define NFP_NET_MAX_TX_RINGS 64 /* Max. # of Tx rings per device */
#define NFP_NET_MAX_RX_RINGS 64 /* Max. # of Rx rings per device */ #define NFP_NET_MAX_RX_RINGS 64 /* Max. # of Rx rings per device */
#define NFP_NET_MAX_R_VECS (NFP_NET_MAX_TX_RINGS > NFP_NET_MAX_RX_RINGS ? \
NFP_NET_MAX_TX_RINGS : NFP_NET_MAX_RX_RINGS)
#define NFP_NET_MAX_IRQS (NFP_NET_NON_Q_VECTORS + NFP_NET_MAX_R_VECS)
#define NFP_NET_MIN_TX_DESCS 256 /* Min. # of Tx descs per ring */ #define NFP_NET_MIN_TX_DESCS 256 /* Min. # of Tx descs per ring */
#define NFP_NET_MIN_RX_DESCS 256 /* Min. # of Rx descs per ring */ #define NFP_NET_MIN_RX_DESCS 256 /* Min. # of Rx descs per ring */
...@@ -102,6 +104,10 @@ ...@@ -102,6 +104,10 @@
/* Offload definitions */ /* Offload definitions */
#define NFP_NET_N_VXLAN_PORTS (NFP_NET_CFG_VXLAN_SZ / sizeof(__be16)) #define NFP_NET_N_VXLAN_PORTS (NFP_NET_CFG_VXLAN_SZ / sizeof(__be16))
#define NFP_NET_RX_BUF_HEADROOM (NET_SKB_PAD + NET_IP_ALIGN)
#define NFP_NET_RX_BUF_NON_DATA (NFP_NET_RX_BUF_HEADROOM + \
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
/* Forward declarations */ /* Forward declarations */
struct nfp_net; struct nfp_net;
struct nfp_net_r_vector; struct nfp_net_r_vector;
...@@ -278,11 +284,11 @@ struct nfp_net_rx_hash { ...@@ -278,11 +284,11 @@ struct nfp_net_rx_hash {
/** /**
* struct nfp_net_rx_buf - software RX buffer descriptor * struct nfp_net_rx_buf - software RX buffer descriptor
* @skb: sk_buff associated with this buffer * @frag: page fragment buffer
* @dma_addr: DMA mapping address of the buffer * @dma_addr: DMA mapping address of the buffer
*/ */
struct nfp_net_rx_buf { struct nfp_net_rx_buf {
struct sk_buff *skb; void *frag;
dma_addr_t dma_addr; dma_addr_t dma_addr;
}; };
...@@ -421,7 +427,6 @@ struct nfp_stat_pair { ...@@ -421,7 +427,6 @@ struct nfp_stat_pair {
* @netdev: Backpointer to net_device structure * @netdev: Backpointer to net_device structure
* @nfp_fallback: Is the driver used in fallback mode? * @nfp_fallback: Is the driver used in fallback mode?
* @is_vf: Is the driver attached to a VF? * @is_vf: Is the driver attached to a VF?
* @is_nfp3200: Is the driver for a NFP-3200 card?
* @fw_loaded: Is the firmware loaded? * @fw_loaded: Is the firmware loaded?
* @bpf_offload_skip_sw: Offloaded BPF program will not be rerun by cls_bpf * @bpf_offload_skip_sw: Offloaded BPF program will not be rerun by cls_bpf
* @ctrl: Local copy of the control register/word. * @ctrl: Local copy of the control register/word.
...@@ -451,7 +456,7 @@ struct nfp_stat_pair { ...@@ -451,7 +456,7 @@ struct nfp_stat_pair {
* @rxd_cnt: Size of the RX ring in number of descriptors * @rxd_cnt: Size of the RX ring in number of descriptors
* @tx_rings: Array of pre-allocated TX ring structures * @tx_rings: Array of pre-allocated TX ring structures
* @rx_rings: Array of pre-allocated RX ring structures * @rx_rings: Array of pre-allocated RX ring structures
* @num_irqs: Number of allocated interrupt vectors * @max_r_vecs: Number of allocated interrupt vectors for RX/TX
* @num_r_vecs: Number of used ring vectors * @num_r_vecs: Number of used ring vectors
* @r_vecs: Pre-allocated array of ring vectors * @r_vecs: Pre-allocated array of ring vectors
* @irq_entries: Pre-allocated array of MSI-X entries * @irq_entries: Pre-allocated array of MSI-X entries
...@@ -487,7 +492,6 @@ struct nfp_net { ...@@ -487,7 +492,6 @@ struct nfp_net {
unsigned nfp_fallback:1; unsigned nfp_fallback:1;
unsigned is_vf:1; unsigned is_vf:1;
unsigned is_nfp3200:1;
unsigned fw_loaded:1; unsigned fw_loaded:1;
unsigned bpf_offload_skip_sw:1; unsigned bpf_offload_skip_sw:1;
...@@ -524,11 +528,11 @@ struct nfp_net { ...@@ -524,11 +528,11 @@ struct nfp_net {
struct timer_list rx_filter_stats_timer; struct timer_list rx_filter_stats_timer;
spinlock_t rx_filter_lock; spinlock_t rx_filter_lock;
int max_tx_rings; unsigned int max_tx_rings;
int max_rx_rings; unsigned int max_rx_rings;
int num_tx_rings; unsigned int num_tx_rings;
int num_rx_rings; unsigned int num_rx_rings;
int stride_tx; int stride_tx;
int stride_rx; int stride_rx;
...@@ -536,11 +540,10 @@ struct nfp_net { ...@@ -536,11 +540,10 @@ struct nfp_net {
int txd_cnt; int txd_cnt;
int rxd_cnt; int rxd_cnt;
u8 num_irqs; unsigned int max_r_vecs;
u8 num_r_vecs; unsigned int num_r_vecs;
struct nfp_net_r_vector r_vecs[NFP_NET_MAX_TX_RINGS]; struct nfp_net_r_vector r_vecs[NFP_NET_MAX_R_VECS];
struct msix_entry irq_entries[NFP_NET_NON_Q_VECTORS + struct msix_entry irq_entries[NFP_NET_MAX_IRQS];
NFP_NET_MAX_TX_RINGS];
irq_handler_t lsc_handler; irq_handler_t lsc_handler;
char lsc_name[IFNAMSIZ + 8]; char lsc_name[IFNAMSIZ + 8];
...@@ -593,16 +596,13 @@ static inline void nn_writeb(struct nfp_net *nn, int off, u8 val) ...@@ -593,16 +596,13 @@ static inline void nn_writeb(struct nfp_net *nn, int off, u8 val)
writeb(val, nn->ctrl_bar + off); writeb(val, nn->ctrl_bar + off);
} }
/* NFP-3200 can't handle 16-bit accesses too well */
static inline u16 nn_readw(struct nfp_net *nn, int off) static inline u16 nn_readw(struct nfp_net *nn, int off)
{ {
WARN_ON_ONCE(nn->is_nfp3200);
return readw(nn->ctrl_bar + off); return readw(nn->ctrl_bar + off);
} }
static inline void nn_writew(struct nfp_net *nn, int off, u16 val) static inline void nn_writew(struct nfp_net *nn, int off, u16 val)
{ {
WARN_ON_ONCE(nn->is_nfp3200);
writew(val, nn->ctrl_bar + off); writew(val, nn->ctrl_bar + off);
} }
...@@ -650,7 +650,7 @@ static inline void nn_pci_flush(struct nfp_net *nn) ...@@ -650,7 +650,7 @@ static inline void nn_pci_flush(struct nfp_net *nn)
#define NFP_QCP_QUEUE_STS_HI 0x000c #define NFP_QCP_QUEUE_STS_HI 0x000c
#define NFP_QCP_QUEUE_STS_HI_WRITEPTR_mask 0x3ffff #define NFP_QCP_QUEUE_STS_HI_WRITEPTR_mask 0x3ffff
/* The offset of a QCP queues in the PCIe Target (same on NFP3200 and NFP6000 */ /* The offset of a QCP queues in the PCIe Target */
#define NFP_PCIE_QUEUE(_q) (0x80000 + (NFP_QCP_QUEUE_ADDR_SZ * ((_q) & 0xff))) #define NFP_PCIE_QUEUE(_q) (0x80000 + (NFP_QCP_QUEUE_ADDR_SZ * ((_q) & 0xff)))
/* nfp_qcp_ptr - Read or Write Pointer of a queue */ /* nfp_qcp_ptr - Read or Write Pointer of a queue */
...@@ -757,8 +757,9 @@ extern const char nfp_net_driver_version[]; ...@@ -757,8 +757,9 @@ extern const char nfp_net_driver_version[];
void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver, void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver,
void __iomem *ctrl_bar); void __iomem *ctrl_bar);
struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev, struct nfp_net *
int max_tx_rings, int max_rx_rings); nfp_net_netdev_alloc(struct pci_dev *pdev,
unsigned int max_tx_rings, unsigned int max_rx_rings);
void nfp_net_netdev_free(struct nfp_net *nn); void nfp_net_netdev_free(struct nfp_net *nn);
int nfp_net_netdev_init(struct net_device *netdev); int nfp_net_netdev_init(struct net_device *netdev);
void nfp_net_netdev_clean(struct net_device *netdev); void nfp_net_netdev_clean(struct net_device *netdev);
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include <linux/page_ref.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pci_regs.h> #include <linux/pci_regs.h>
#include <linux/msi.h> #include <linux/msi.h>
...@@ -80,6 +81,22 @@ void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver, ...@@ -80,6 +81,22 @@ void nfp_net_get_fw_version(struct nfp_net_fw_version *fw_ver,
put_unaligned_le32(reg, fw_ver); put_unaligned_le32(reg, fw_ver);
} }
static dma_addr_t
nfp_net_dma_map_rx(struct nfp_net *nn, void *frag, unsigned int bufsz,
int direction)
{
return dma_map_single(&nn->pdev->dev, frag + NFP_NET_RX_BUF_HEADROOM,
bufsz - NFP_NET_RX_BUF_NON_DATA, direction);
}
static void
nfp_net_dma_unmap_rx(struct nfp_net *nn, dma_addr_t dma_addr,
unsigned int bufsz, int direction)
{
dma_unmap_single(&nn->pdev->dev, dma_addr,
bufsz - NFP_NET_RX_BUF_NON_DATA, direction);
}
/* Firmware reconfig /* Firmware reconfig
* *
* Firmware reconfig may take a while so we have two versions of it - * Firmware reconfig may take a while so we have two versions of it -
...@@ -248,44 +265,15 @@ int nfp_net_reconfig(struct nfp_net *nn, u32 update) ...@@ -248,44 +265,15 @@ int nfp_net_reconfig(struct nfp_net *nn, u32 update)
/* Interrupt configuration and handling /* Interrupt configuration and handling
*/ */
/**
* nfp_net_irq_unmask_msix() - Unmask MSI-X after automasking
* @nn: NFP Network structure
* @entry_nr: MSI-X table entry
*
* Clear the MSI-X table mask bit for the given entry bypassing Linux irq
* handling subsystem. Use *only* to reenable automasked vectors.
*/
static void nfp_net_irq_unmask_msix(struct nfp_net *nn, unsigned int entry_nr)
{
struct list_head *msi_head = &nn->pdev->dev.msi_list;
struct msi_desc *entry;
u32 off;
/* All MSI-Xs have the same mask_base */
entry = list_first_entry(msi_head, struct msi_desc, list);
off = (PCI_MSIX_ENTRY_SIZE * entry_nr) +
PCI_MSIX_ENTRY_VECTOR_CTRL;
writel(0, entry->mask_base + off);
readl(entry->mask_base);
}
/** /**
* nfp_net_irq_unmask() - Unmask automasked interrupt * nfp_net_irq_unmask() - Unmask automasked interrupt
* @nn: NFP Network structure * @nn: NFP Network structure
* @entry_nr: MSI-X table entry * @entry_nr: MSI-X table entry
* *
* If MSI-X auto-masking is enabled clear the mask bit, otherwise * Clear the ICR for the IRQ entry.
* clear the ICR for the entry.
*/ */
static void nfp_net_irq_unmask(struct nfp_net *nn, unsigned int entry_nr) static void nfp_net_irq_unmask(struct nfp_net *nn, unsigned int entry_nr)
{ {
if (nn->ctrl & NFP_NET_CFG_CTRL_MSIXAUTO) {
nfp_net_irq_unmask_msix(nn, entry_nr);
return;
}
nn_writeb(nn, NFP_NET_CFG_ICR(entry_nr), NFP_NET_CFG_ICR_UNMASKED); nn_writeb(nn, NFP_NET_CFG_ICR(entry_nr), NFP_NET_CFG_ICR_UNMASKED);
nn_pci_flush(nn); nn_pci_flush(nn);
} }
...@@ -319,28 +307,6 @@ static int nfp_net_msix_alloc(struct nfp_net *nn, int nr_vecs) ...@@ -319,28 +307,6 @@ static int nfp_net_msix_alloc(struct nfp_net *nn, int nr_vecs)
return nvecs; return nvecs;
} }
/**
* nfp_net_irqs_wanted() - Work out how many interrupt vectors we want
* @nn: NFP Network structure
*
* We want a vector per CPU (or ring), whatever is smaller plus
* NFP_NET_NON_Q_VECTORS for LSC etc.
*
* Return: Number of interrupts wanted
*/
static int nfp_net_irqs_wanted(struct nfp_net *nn)
{
int ncpus;
int vecs;
ncpus = num_online_cpus();
vecs = max_t(int, nn->num_tx_rings, nn->num_rx_rings);
vecs = min_t(int, vecs, ncpus);
return vecs + NFP_NET_NON_Q_VECTORS;
}
/** /**
* nfp_net_irqs_alloc() - allocates MSI-X irqs * nfp_net_irqs_alloc() - allocates MSI-X irqs
* @nn: NFP Network structure * @nn: NFP Network structure
...@@ -350,22 +316,24 @@ static int nfp_net_irqs_wanted(struct nfp_net *nn) ...@@ -350,22 +316,24 @@ static int nfp_net_irqs_wanted(struct nfp_net *nn)
int nfp_net_irqs_alloc(struct nfp_net *nn) int nfp_net_irqs_alloc(struct nfp_net *nn)
{ {
int wanted_irqs; int wanted_irqs;
unsigned int n;
wanted_irqs = nfp_net_irqs_wanted(nn); wanted_irqs = nn->num_r_vecs + NFP_NET_NON_Q_VECTORS;
nn->num_irqs = nfp_net_msix_alloc(nn, wanted_irqs); n = nfp_net_msix_alloc(nn, wanted_irqs);
if (nn->num_irqs == 0) { if (n == 0) {
nn_err(nn, "Failed to allocate MSI-X IRQs\n"); nn_err(nn, "Failed to allocate MSI-X IRQs\n");
return 0; return 0;
} }
nn->num_r_vecs = nn->num_irqs - NFP_NET_NON_Q_VECTORS; nn->max_r_vecs = n - NFP_NET_NON_Q_VECTORS;
nn->num_r_vecs = nn->max_r_vecs;
if (nn->num_irqs < wanted_irqs) if (n < wanted_irqs)
nn_warn(nn, "Unable to allocate %d vectors. Got %d instead\n", nn_warn(nn, "Unable to allocate %d vectors. Got %d instead\n",
wanted_irqs, nn->num_irqs); wanted_irqs, n);
return nn->num_irqs; return n;
} }
/** /**
...@@ -515,13 +483,13 @@ static void nfp_net_irqs_assign(struct net_device *netdev) ...@@ -515,13 +483,13 @@ static void nfp_net_irqs_assign(struct net_device *netdev)
struct nfp_net_r_vector *r_vec; struct nfp_net_r_vector *r_vec;
int r; int r;
/* Assumes nn->num_tx_rings == nn->num_rx_rings */ if (nn->num_rx_rings > nn->num_r_vecs ||
if (nn->num_tx_rings > nn->num_r_vecs) { nn->num_tx_rings > nn->num_r_vecs)
nn_warn(nn, "More rings (%d) than vectors (%d).\n", nn_warn(nn, "More rings (%d,%d) than vectors (%d).\n",
nn->num_tx_rings, nn->num_r_vecs); nn->num_rx_rings, nn->num_tx_rings, nn->num_r_vecs);
nn->num_tx_rings = nn->num_r_vecs;
nn->num_rx_rings = nn->num_r_vecs; nn->num_rx_rings = min(nn->num_r_vecs, nn->num_rx_rings);
} nn->num_tx_rings = min(nn->num_r_vecs, nn->num_tx_rings);
nn->lsc_handler = nfp_net_irq_lsc; nn->lsc_handler = nfp_net_irq_lsc;
nn->exn_handler = nfp_net_irq_exn; nn->exn_handler = nfp_net_irq_exn;
...@@ -605,7 +573,7 @@ static void nfp_net_aux_irq_free(struct nfp_net *nn, u32 ctrl_offset, ...@@ -605,7 +573,7 @@ static void nfp_net_aux_irq_free(struct nfp_net *nn, u32 ctrl_offset,
* *
* Return: True if the ring is full. * Return: True if the ring is full.
*/ */
static inline int nfp_net_tx_full(struct nfp_net_tx_ring *tx_ring, int dcnt) static int nfp_net_tx_full(struct nfp_net_tx_ring *tx_ring, int dcnt)
{ {
return (tx_ring->wr_p - tx_ring->rd_p) >= (tx_ring->cnt - dcnt); return (tx_ring->wr_p - tx_ring->rd_p) >= (tx_ring->cnt - dcnt);
} }
...@@ -790,7 +758,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev) ...@@ -790,7 +758,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev)
if (dma_mapping_error(&nn->pdev->dev, dma_addr)) if (dma_mapping_error(&nn->pdev->dev, dma_addr))
goto err_free; goto err_free;
wr_idx = tx_ring->wr_p % tx_ring->cnt; wr_idx = tx_ring->wr_p & (tx_ring->cnt - 1);
/* Stash the soft descriptor of the head then initialize it */ /* Stash the soft descriptor of the head then initialize it */
txbuf = &tx_ring->txbufs[wr_idx]; txbuf = &tx_ring->txbufs[wr_idx];
...@@ -834,7 +802,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev) ...@@ -834,7 +802,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev)
if (dma_mapping_error(&nn->pdev->dev, dma_addr)) if (dma_mapping_error(&nn->pdev->dev, dma_addr))
goto err_unmap; goto err_unmap;
wr_idx = (wr_idx + 1) % tx_ring->cnt; wr_idx = (wr_idx + 1) & (tx_ring->cnt - 1);
tx_ring->txbufs[wr_idx].skb = skb; tx_ring->txbufs[wr_idx].skb = skb;
tx_ring->txbufs[wr_idx].dma_addr = dma_addr; tx_ring->txbufs[wr_idx].dma_addr = dma_addr;
tx_ring->txbufs[wr_idx].fidx = f; tx_ring->txbufs[wr_idx].fidx = f;
...@@ -929,7 +897,7 @@ static void nfp_net_tx_complete(struct nfp_net_tx_ring *tx_ring) ...@@ -929,7 +897,7 @@ static void nfp_net_tx_complete(struct nfp_net_tx_ring *tx_ring)
todo = qcp_rd_p + tx_ring->cnt - tx_ring->qcp_rd_p; todo = qcp_rd_p + tx_ring->cnt - tx_ring->qcp_rd_p;
while (todo--) { while (todo--) {
idx = tx_ring->rd_p % tx_ring->cnt; idx = tx_ring->rd_p & (tx_ring->cnt - 1);
tx_ring->rd_p++; tx_ring->rd_p++;
skb = tx_ring->txbufs[idx].skb; skb = tx_ring->txbufs[idx].skb;
...@@ -1004,7 +972,7 @@ nfp_net_tx_ring_reset(struct nfp_net *nn, struct nfp_net_tx_ring *tx_ring) ...@@ -1004,7 +972,7 @@ nfp_net_tx_ring_reset(struct nfp_net *nn, struct nfp_net_tx_ring *tx_ring)
int nr_frags, fidx, idx; int nr_frags, fidx, idx;
struct sk_buff *skb; struct sk_buff *skb;
idx = tx_ring->rd_p % tx_ring->cnt; idx = tx_ring->rd_p & (tx_ring->cnt - 1);
skb = tx_ring->txbufs[idx].skb; skb = tx_ring->txbufs[idx].skb;
nr_frags = skb_shinfo(skb)->nr_frags; nr_frags = skb_shinfo(skb)->nr_frags;
fidx = tx_ring->txbufs[idx].fidx; fidx = tx_ring->txbufs[idx].fidx;
...@@ -1059,69 +1027,92 @@ static void nfp_net_tx_timeout(struct net_device *netdev) ...@@ -1059,69 +1027,92 @@ static void nfp_net_tx_timeout(struct net_device *netdev)
/* Receive processing /* Receive processing
*/ */
static unsigned int
/** nfp_net_calc_fl_bufsz(struct nfp_net *nn, unsigned int mtu)
* nfp_net_rx_space() - return the number of free slots on the RX ring
* @rx_ring: RX ring structure
*
* Make sure we leave at least one slot free.
*
* Return: True if there is space on the RX ring
*/
static inline int nfp_net_rx_space(struct nfp_net_rx_ring *rx_ring)
{ {
return (rx_ring->cnt - 1) - (rx_ring->wr_p - rx_ring->rd_p); unsigned int fl_bufsz;
fl_bufsz = NFP_NET_RX_BUF_HEADROOM;
if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC)
fl_bufsz += NFP_NET_MAX_PREPEND;
else
fl_bufsz += nn->rx_offset;
fl_bufsz += ETH_HLEN + VLAN_HLEN * 2 + mtu;
fl_bufsz = SKB_DATA_ALIGN(fl_bufsz);
fl_bufsz += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
return fl_bufsz;
} }
/** /**
* nfp_net_rx_alloc_one() - Allocate and map skb for RX * nfp_net_rx_alloc_one() - Allocate and map page frag for RX
* @rx_ring: RX ring structure of the skb * @rx_ring: RX ring structure of the skb
* @dma_addr: Pointer to storage for DMA address (output param) * @dma_addr: Pointer to storage for DMA address (output param)
* @fl_bufsz: size of freelist buffers * @fl_bufsz: size of freelist buffers
* *
* This function will allcate a new skb, map it for DMA. * This function will allcate a new page frag, map it for DMA.
* *
* Return: allocated skb or NULL on failure. * Return: allocated page frag or NULL on failure.
*/ */
static struct sk_buff * static void *
nfp_net_rx_alloc_one(struct nfp_net_rx_ring *rx_ring, dma_addr_t *dma_addr, nfp_net_rx_alloc_one(struct nfp_net_rx_ring *rx_ring, dma_addr_t *dma_addr,
unsigned int fl_bufsz) unsigned int fl_bufsz)
{ {
struct nfp_net *nn = rx_ring->r_vec->nfp_net; struct nfp_net *nn = rx_ring->r_vec->nfp_net;
struct sk_buff *skb; void *frag;
skb = netdev_alloc_skb(nn->netdev, fl_bufsz); frag = netdev_alloc_frag(fl_bufsz);
if (!skb) { if (!frag) {
nn_warn_ratelimit(nn, "Failed to alloc receive SKB\n"); nn_warn_ratelimit(nn, "Failed to alloc receive page frag\n");
return NULL; return NULL;
} }
*dma_addr = dma_map_single(&nn->pdev->dev, skb->data, *dma_addr = nfp_net_dma_map_rx(nn, frag, fl_bufsz, DMA_FROM_DEVICE);
fl_bufsz, DMA_FROM_DEVICE);
if (dma_mapping_error(&nn->pdev->dev, *dma_addr)) { if (dma_mapping_error(&nn->pdev->dev, *dma_addr)) {
dev_kfree_skb_any(skb); skb_free_frag(frag);
nn_warn_ratelimit(nn, "Failed to map DMA RX buffer\n");
return NULL;
}
return frag;
}
static void *nfp_net_napi_alloc_one(struct nfp_net *nn, dma_addr_t *dma_addr)
{
void *frag;
frag = napi_alloc_frag(nn->fl_bufsz);
if (!frag) {
nn_warn_ratelimit(nn, "Failed to alloc receive page frag\n");
return NULL;
}
*dma_addr = nfp_net_dma_map_rx(nn, frag, nn->fl_bufsz, DMA_FROM_DEVICE);
if (dma_mapping_error(&nn->pdev->dev, *dma_addr)) {
skb_free_frag(frag);
nn_warn_ratelimit(nn, "Failed to map DMA RX buffer\n"); nn_warn_ratelimit(nn, "Failed to map DMA RX buffer\n");
return NULL; return NULL;
} }
return skb; return frag;
} }
/** /**
* nfp_net_rx_give_one() - Put mapped skb on the software and hardware rings * nfp_net_rx_give_one() - Put mapped skb on the software and hardware rings
* @rx_ring: RX ring structure * @rx_ring: RX ring structure
* @skb: Skb to put on rings * @frag: page fragment buffer
* @dma_addr: DMA address of skb mapping * @dma_addr: DMA address of skb mapping
*/ */
static void nfp_net_rx_give_one(struct nfp_net_rx_ring *rx_ring, static void nfp_net_rx_give_one(struct nfp_net_rx_ring *rx_ring,
struct sk_buff *skb, dma_addr_t dma_addr) void *frag, dma_addr_t dma_addr)
{ {
unsigned int wr_idx; unsigned int wr_idx;
wr_idx = rx_ring->wr_p % rx_ring->cnt; wr_idx = rx_ring->wr_p & (rx_ring->cnt - 1);
/* Stash SKB and DMA address away */ /* Stash SKB and DMA address away */
rx_ring->rxbufs[wr_idx].skb = skb; rx_ring->rxbufs[wr_idx].frag = frag;
rx_ring->rxbufs[wr_idx].dma_addr = dma_addr; rx_ring->rxbufs[wr_idx].dma_addr = dma_addr;
/* Fill freelist descriptor */ /* Fill freelist descriptor */
...@@ -1153,12 +1144,12 @@ static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring) ...@@ -1153,12 +1144,12 @@ static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring)
unsigned int wr_idx, last_idx; unsigned int wr_idx, last_idx;
/* Move the empty entry to the end of the list */ /* Move the empty entry to the end of the list */
wr_idx = rx_ring->wr_p % rx_ring->cnt; wr_idx = rx_ring->wr_p & (rx_ring->cnt - 1);
last_idx = rx_ring->cnt - 1; last_idx = rx_ring->cnt - 1;
rx_ring->rxbufs[wr_idx].dma_addr = rx_ring->rxbufs[last_idx].dma_addr; rx_ring->rxbufs[wr_idx].dma_addr = rx_ring->rxbufs[last_idx].dma_addr;
rx_ring->rxbufs[wr_idx].skb = rx_ring->rxbufs[last_idx].skb; rx_ring->rxbufs[wr_idx].frag = rx_ring->rxbufs[last_idx].frag;
rx_ring->rxbufs[last_idx].dma_addr = 0; rx_ring->rxbufs[last_idx].dma_addr = 0;
rx_ring->rxbufs[last_idx].skb = NULL; rx_ring->rxbufs[last_idx].frag = NULL;
memset(rx_ring->rxds, 0, sizeof(*rx_ring->rxds) * rx_ring->cnt); memset(rx_ring->rxds, 0, sizeof(*rx_ring->rxds) * rx_ring->cnt);
rx_ring->wr_p = 0; rx_ring->wr_p = 0;
...@@ -1178,7 +1169,6 @@ static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring) ...@@ -1178,7 +1169,6 @@ static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring)
static void static void
nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring)
{ {
struct pci_dev *pdev = nn->pdev;
unsigned int i; unsigned int i;
for (i = 0; i < rx_ring->cnt - 1; i++) { for (i = 0; i < rx_ring->cnt - 1; i++) {
...@@ -1186,14 +1176,14 @@ nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) ...@@ -1186,14 +1176,14 @@ nfp_net_rx_ring_bufs_free(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring)
* fails to allocate enough buffers and calls here to free * fails to allocate enough buffers and calls here to free
* already allocated ones. * already allocated ones.
*/ */
if (!rx_ring->rxbufs[i].skb) if (!rx_ring->rxbufs[i].frag)
continue; continue;
dma_unmap_single(&pdev->dev, rx_ring->rxbufs[i].dma_addr, nfp_net_dma_unmap_rx(nn, rx_ring->rxbufs[i].dma_addr,
rx_ring->bufsz, DMA_FROM_DEVICE); rx_ring->bufsz, DMA_FROM_DEVICE);
dev_kfree_skb_any(rx_ring->rxbufs[i].skb); skb_free_frag(rx_ring->rxbufs[i].frag);
rx_ring->rxbufs[i].dma_addr = 0; rx_ring->rxbufs[i].dma_addr = 0;
rx_ring->rxbufs[i].skb = NULL; rx_ring->rxbufs[i].frag = NULL;
} }
} }
...@@ -1211,10 +1201,10 @@ nfp_net_rx_ring_bufs_alloc(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring) ...@@ -1211,10 +1201,10 @@ nfp_net_rx_ring_bufs_alloc(struct nfp_net *nn, struct nfp_net_rx_ring *rx_ring)
rxbufs = rx_ring->rxbufs; rxbufs = rx_ring->rxbufs;
for (i = 0; i < rx_ring->cnt - 1; i++) { for (i = 0; i < rx_ring->cnt - 1; i++) {
rxbufs[i].skb = rxbufs[i].frag =
nfp_net_rx_alloc_one(rx_ring, &rxbufs[i].dma_addr, nfp_net_rx_alloc_one(rx_ring, &rxbufs[i].dma_addr,
rx_ring->bufsz); rx_ring->bufsz);
if (!rxbufs[i].skb) { if (!rxbufs[i].frag) {
nfp_net_rx_ring_bufs_free(nn, rx_ring); nfp_net_rx_ring_bufs_free(nn, rx_ring);
return -ENOMEM; return -ENOMEM;
} }
...@@ -1232,7 +1222,7 @@ static void nfp_net_rx_ring_fill_freelist(struct nfp_net_rx_ring *rx_ring) ...@@ -1232,7 +1222,7 @@ static void nfp_net_rx_ring_fill_freelist(struct nfp_net_rx_ring *rx_ring)
unsigned int i; unsigned int i;
for (i = 0; i < rx_ring->cnt - 1; i++) for (i = 0; i < rx_ring->cnt - 1; i++)
nfp_net_rx_give_one(rx_ring, rx_ring->rxbufs[i].skb, nfp_net_rx_give_one(rx_ring, rx_ring->rxbufs[i].frag,
rx_ring->rxbufs[i].dma_addr); rx_ring->rxbufs[i].dma_addr);
} }
...@@ -1359,6 +1349,25 @@ nfp_net_parse_meta(struct net_device *netdev, struct sk_buff *skb, ...@@ -1359,6 +1349,25 @@ nfp_net_parse_meta(struct net_device *netdev, struct sk_buff *skb,
return data; return data;
} }
static void
nfp_net_rx_drop(struct nfp_net_r_vector *r_vec, struct nfp_net_rx_ring *rx_ring,
struct nfp_net_rx_buf *rxbuf, struct sk_buff *skb)
{
u64_stats_update_begin(&r_vec->rx_sync);
r_vec->rx_drops++;
u64_stats_update_end(&r_vec->rx_sync);
/* skb is build based on the frag, free_skb() would free the frag
* so to be able to reuse it we need an extra ref.
*/
if (skb && rxbuf && skb->head == rxbuf->frag)
page_ref_inc(virt_to_head_page(rxbuf->frag));
if (rxbuf)
nfp_net_rx_give_one(rx_ring, rxbuf->frag, rxbuf->dma_addr);
if (skb)
dev_kfree_skb_any(skb);
}
/** /**
* nfp_net_rx() - receive up to @budget packets on @rx_ring * nfp_net_rx() - receive up to @budget packets on @rx_ring
* @rx_ring: RX ring to receive from * @rx_ring: RX ring to receive from
...@@ -1368,20 +1377,6 @@ nfp_net_parse_meta(struct net_device *netdev, struct sk_buff *skb, ...@@ -1368,20 +1377,6 @@ nfp_net_parse_meta(struct net_device *netdev, struct sk_buff *skb,
* more cleanly separate packet receive code from other bookkeeping * more cleanly separate packet receive code from other bookkeeping
* functions performed in the napi poll function. * functions performed in the napi poll function.
* *
* There are differences between the NFP-3200 firmware and the
* NFP-6000 firmware. The NFP-3200 firmware uses a dedicated RX queue
* to indicate that new packets have arrived. The NFP-6000 does not
* have this queue and uses the DD bit in the RX descriptor. This
* method cannot be used on the NFP-3200 as it causes a race
* condition: The RX ring write pointer on the NFP-3200 is updated
* after packets (and descriptors) have been DMAed. If the DD bit is
* used and subsequently the read pointer is updated this may lead to
* the RX queue to underflow (if the firmware has not yet update the
* write pointer). Therefore we use slightly ugly conditional code
* below to handle the differences. We may, in the future update the
* NFP-3200 firmware to behave the same as the firmware on the
* NFP-6000.
*
* Return: Number of packets received. * Return: Number of packets received.
*/ */
static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
...@@ -1389,41 +1384,21 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) ...@@ -1389,41 +1384,21 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
struct nfp_net_r_vector *r_vec = rx_ring->r_vec; struct nfp_net_r_vector *r_vec = rx_ring->r_vec;
struct nfp_net *nn = r_vec->nfp_net; struct nfp_net *nn = r_vec->nfp_net;
unsigned int data_len, meta_len; unsigned int data_len, meta_len;
int avail = 0, pkts_polled = 0; struct nfp_net_rx_buf *rxbuf;
struct sk_buff *skb, *new_skb;
struct nfp_net_rx_desc *rxd; struct nfp_net_rx_desc *rxd;
dma_addr_t new_dma_addr; dma_addr_t new_dma_addr;
u32 qcp_wr_p; struct sk_buff *skb;
int pkts_polled = 0;
void *new_frag;
int idx; int idx;
if (nn->is_nfp3200) { while (pkts_polled < budget) {
/* Work out how many packets arrived */ idx = rx_ring->rd_p & (rx_ring->cnt - 1);
qcp_wr_p = nfp_qcp_wr_ptr_read(rx_ring->qcp_rx);
idx = rx_ring->rd_p % rx_ring->cnt;
if (qcp_wr_p == idx)
/* No new packets */
return 0;
if (qcp_wr_p > idx)
avail = qcp_wr_p - idx;
else
avail = qcp_wr_p + rx_ring->cnt - idx;
} else {
avail = budget + 1;
}
while (avail > 0 && pkts_polled < budget) {
idx = rx_ring->rd_p % rx_ring->cnt;
rxd = &rx_ring->rxds[idx]; rxd = &rx_ring->rxds[idx];
if (!(rxd->rxd.meta_len_dd & PCIE_DESC_RX_DD)) { if (!(rxd->rxd.meta_len_dd & PCIE_DESC_RX_DD))
if (nn->is_nfp3200)
nn_dbg(nn, "RX descriptor not valid (DD)%d:%u rxd[0]=%#x rxd[1]=%#x\n",
rx_ring->idx, idx,
rxd->vals[0], rxd->vals[1]);
break; break;
}
/* Memory barrier to ensure that we won't do other reads /* Memory barrier to ensure that we won't do other reads
* before the DD bit. * before the DD bit.
*/ */
...@@ -1431,26 +1406,23 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) ...@@ -1431,26 +1406,23 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
rx_ring->rd_p++; rx_ring->rd_p++;
pkts_polled++; pkts_polled++;
avail--;
rxbuf = &rx_ring->rxbufs[idx];
skb = rx_ring->rxbufs[idx].skb; skb = build_skb(rxbuf->frag, nn->fl_bufsz);
if (unlikely(!skb)) {
new_skb = nfp_net_rx_alloc_one(rx_ring, &new_dma_addr, nfp_net_rx_drop(r_vec, rx_ring, rxbuf, NULL);
nn->fl_bufsz); continue;
if (!new_skb) { }
nfp_net_rx_give_one(rx_ring, rx_ring->rxbufs[idx].skb, new_frag = nfp_net_napi_alloc_one(nn, &new_dma_addr);
rx_ring->rxbufs[idx].dma_addr); if (unlikely(!new_frag)) {
u64_stats_update_begin(&r_vec->rx_sync); nfp_net_rx_drop(r_vec, rx_ring, rxbuf, skb);
r_vec->rx_drops++;
u64_stats_update_end(&r_vec->rx_sync);
continue; continue;
} }
dma_unmap_single(&nn->pdev->dev, nfp_net_dma_unmap_rx(nn, rx_ring->rxbufs[idx].dma_addr,
rx_ring->rxbufs[idx].dma_addr, nn->fl_bufsz, DMA_FROM_DEVICE);
nn->fl_bufsz, DMA_FROM_DEVICE);
nfp_net_rx_give_one(rx_ring, new_skb, new_dma_addr); nfp_net_rx_give_one(rx_ring, new_frag, new_dma_addr);
/* < meta_len > /* < meta_len >
* <-- [rx_offset] --> * <-- [rx_offset] -->
...@@ -1468,9 +1440,10 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) ...@@ -1468,9 +1440,10 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
data_len = le16_to_cpu(rxd->rxd.data_len); data_len = le16_to_cpu(rxd->rxd.data_len);
if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC) if (nn->rx_offset == NFP_NET_CFG_RX_OFFSET_DYNAMIC)
skb_reserve(skb, meta_len); skb_reserve(skb, NFP_NET_RX_BUF_HEADROOM + meta_len);
else else
skb_reserve(skb, nn->rx_offset); skb_reserve(skb,
NFP_NET_RX_BUF_HEADROOM + nn->rx_offset);
skb_put(skb, data_len - meta_len); skb_put(skb, data_len - meta_len);
/* Stats update */ /* Stats update */
...@@ -1486,12 +1459,8 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) ...@@ -1486,12 +1459,8 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
end = nfp_net_parse_meta(nn->netdev, skb, meta_len); end = nfp_net_parse_meta(nn->netdev, skb, meta_len);
if (unlikely(end != skb->data)) { if (unlikely(end != skb->data)) {
u64_stats_update_begin(&r_vec->rx_sync);
r_vec->rx_drops++;
u64_stats_update_end(&r_vec->rx_sync);
dev_kfree_skb_any(skb);
nn_warn_ratelimit(nn, "invalid RX packet metadata\n"); nn_warn_ratelimit(nn, "invalid RX packet metadata\n");
nfp_net_rx_drop(r_vec, rx_ring, NULL, skb);
continue; continue;
} }
} }
...@@ -1508,9 +1477,6 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) ...@@ -1508,9 +1477,6 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
napi_gro_receive(&rx_ring->r_vec->napi, skb); napi_gro_receive(&rx_ring->r_vec->napi, skb);
} }
if (nn->is_nfp3200)
nfp_qcp_rd_ptr_add(rx_ring->qcp_rx, pkts_polled);
return pkts_polled; return pkts_polled;
} }
...@@ -1525,21 +1491,16 @@ static int nfp_net_poll(struct napi_struct *napi, int budget) ...@@ -1525,21 +1491,16 @@ static int nfp_net_poll(struct napi_struct *napi, int budget)
{ {
struct nfp_net_r_vector *r_vec = struct nfp_net_r_vector *r_vec =
container_of(napi, struct nfp_net_r_vector, napi); container_of(napi, struct nfp_net_r_vector, napi);
struct nfp_net_rx_ring *rx_ring = r_vec->rx_ring; unsigned int pkts_polled = 0;
struct nfp_net_tx_ring *tx_ring = r_vec->tx_ring;
struct nfp_net *nn = r_vec->nfp_net;
struct netdev_queue *txq;
unsigned int pkts_polled;
tx_ring = &nn->tx_rings[rx_ring->idx]; if (r_vec->tx_ring)
txq = netdev_get_tx_queue(nn->netdev, tx_ring->idx); nfp_net_tx_complete(r_vec->tx_ring);
nfp_net_tx_complete(tx_ring); if (r_vec->rx_ring)
pkts_polled = nfp_net_rx(r_vec->rx_ring, budget);
pkts_polled = nfp_net_rx(rx_ring, budget);
if (pkts_polled < budget) { if (pkts_polled < budget) {
napi_complete_done(napi, pkts_polled); napi_complete_done(napi, pkts_polled);
nfp_net_irq_unmask(nn, r_vec->irq_idx); nfp_net_irq_unmask(r_vec->nfp_net, r_vec->irq_idx);
} }
return pkts_polled; return pkts_polled;
...@@ -1783,7 +1744,7 @@ nfp_net_shadow_rx_rings_free(struct nfp_net *nn, struct nfp_net_rx_ring *rings) ...@@ -1783,7 +1744,7 @@ nfp_net_shadow_rx_rings_free(struct nfp_net *nn, struct nfp_net_rx_ring *rings)
if (!rings) if (!rings)
return; return;
for (r = 0; r < nn->num_r_vecs; r++) { for (r = 0; r < nn->num_rx_rings; r++) {
nfp_net_rx_ring_bufs_free(nn, &rings[r]); nfp_net_rx_ring_bufs_free(nn, &rings[r]);
nfp_net_rx_ring_free(&rings[r]); nfp_net_rx_ring_free(&rings[r]);
} }
...@@ -1798,11 +1759,19 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, ...@@ -1798,11 +1759,19 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
struct msix_entry *entry = &nn->irq_entries[r_vec->irq_idx]; struct msix_entry *entry = &nn->irq_entries[r_vec->irq_idx];
int err; int err;
r_vec->tx_ring = &nn->tx_rings[idx]; if (idx < nn->num_tx_rings) {
nfp_net_tx_ring_init(r_vec->tx_ring, r_vec, idx); r_vec->tx_ring = &nn->tx_rings[idx];
nfp_net_tx_ring_init(r_vec->tx_ring, r_vec, idx);
} else {
r_vec->tx_ring = NULL;
}
r_vec->rx_ring = &nn->rx_rings[idx]; if (idx < nn->num_rx_rings) {
nfp_net_rx_ring_init(r_vec->rx_ring, r_vec, idx); r_vec->rx_ring = &nn->rx_rings[idx];
nfp_net_rx_ring_init(r_vec->rx_ring, r_vec, idx);
} else {
r_vec->rx_ring = NULL;
}
snprintf(r_vec->name, sizeof(r_vec->name), snprintf(r_vec->name, sizeof(r_vec->name),
"%s-rxtx-%d", nn->netdev->name, idx); "%s-rxtx-%d", nn->netdev->name, idx);
...@@ -1879,13 +1848,13 @@ void nfp_net_coalesce_write_cfg(struct nfp_net *nn) ...@@ -1879,13 +1848,13 @@ void nfp_net_coalesce_write_cfg(struct nfp_net *nn)
/* copy RX interrupt coalesce parameters */ /* copy RX interrupt coalesce parameters */
value = (nn->rx_coalesce_max_frames << 16) | value = (nn->rx_coalesce_max_frames << 16) |
(factor * nn->rx_coalesce_usecs); (factor * nn->rx_coalesce_usecs);
for (i = 0; i < nn->num_r_vecs; i++) for (i = 0; i < nn->num_rx_rings; i++)
nn_writel(nn, NFP_NET_CFG_RXR_IRQ_MOD(i), value); nn_writel(nn, NFP_NET_CFG_RXR_IRQ_MOD(i), value);
/* copy TX interrupt coalesce parameters */ /* copy TX interrupt coalesce parameters */
value = (nn->tx_coalesce_max_frames << 16) | value = (nn->tx_coalesce_max_frames << 16) |
(factor * nn->tx_coalesce_usecs); (factor * nn->tx_coalesce_usecs);
for (i = 0; i < nn->num_r_vecs; i++) for (i = 0; i < nn->num_tx_rings; i++)
nn_writel(nn, NFP_NET_CFG_TXR_IRQ_MOD(i), value); nn_writel(nn, NFP_NET_CFG_TXR_IRQ_MOD(i), value);
} }
...@@ -1901,9 +1870,8 @@ static void nfp_net_write_mac_addr(struct nfp_net *nn) ...@@ -1901,9 +1870,8 @@ static void nfp_net_write_mac_addr(struct nfp_net *nn)
{ {
nn_writel(nn, NFP_NET_CFG_MACADDR + 0, nn_writel(nn, NFP_NET_CFG_MACADDR + 0,
get_unaligned_be32(nn->netdev->dev_addr)); get_unaligned_be32(nn->netdev->dev_addr));
/* We can't do writew for NFP-3200 compatibility */ nn_writew(nn, NFP_NET_CFG_MACADDR + 6,
nn_writel(nn, NFP_NET_CFG_MACADDR + 4, get_unaligned_be16(nn->netdev->dev_addr + 4));
get_unaligned_be16(nn->netdev->dev_addr + 4) << 16);
} }
static void nfp_net_vec_clear_ring_data(struct nfp_net *nn, unsigned int idx) static void nfp_net_vec_clear_ring_data(struct nfp_net *nn, unsigned int idx)
...@@ -1944,27 +1912,33 @@ static void nfp_net_clear_config_and_disable(struct nfp_net *nn) ...@@ -1944,27 +1912,33 @@ static void nfp_net_clear_config_and_disable(struct nfp_net *nn)
if (err) if (err)
nn_err(nn, "Could not disable device: %d\n", err); nn_err(nn, "Could not disable device: %d\n", err);
for (r = 0; r < nn->num_r_vecs; r++) { for (r = 0; r < nn->num_rx_rings; r++)
nfp_net_rx_ring_reset(nn->r_vecs[r].rx_ring); nfp_net_rx_ring_reset(nn->r_vecs[r].rx_ring);
for (r = 0; r < nn->num_tx_rings; r++)
nfp_net_tx_ring_reset(nn, nn->r_vecs[r].tx_ring); nfp_net_tx_ring_reset(nn, nn->r_vecs[r].tx_ring);
for (r = 0; r < nn->num_r_vecs; r++)
nfp_net_vec_clear_ring_data(nn, r); nfp_net_vec_clear_ring_data(nn, r);
}
nn->ctrl = new_ctrl; nn->ctrl = new_ctrl;
} }
static void static void
nfp_net_vec_write_ring_data(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, nfp_net_rx_ring_hw_cfg_write(struct nfp_net *nn,
unsigned int idx) struct nfp_net_rx_ring *rx_ring, unsigned int idx)
{ {
/* Write the DMA address, size and MSI-X info to the device */ /* Write the DMA address, size and MSI-X info to the device */
nn_writeq(nn, NFP_NET_CFG_RXR_ADDR(idx), r_vec->rx_ring->dma); nn_writeq(nn, NFP_NET_CFG_RXR_ADDR(idx), rx_ring->dma);
nn_writeb(nn, NFP_NET_CFG_RXR_SZ(idx), ilog2(r_vec->rx_ring->cnt)); nn_writeb(nn, NFP_NET_CFG_RXR_SZ(idx), ilog2(rx_ring->cnt));
nn_writeb(nn, NFP_NET_CFG_RXR_VEC(idx), r_vec->irq_idx); nn_writeb(nn, NFP_NET_CFG_RXR_VEC(idx), rx_ring->r_vec->irq_idx);
}
nn_writeq(nn, NFP_NET_CFG_TXR_ADDR(idx), r_vec->tx_ring->dma); static void
nn_writeb(nn, NFP_NET_CFG_TXR_SZ(idx), ilog2(r_vec->tx_ring->cnt)); nfp_net_tx_ring_hw_cfg_write(struct nfp_net *nn,
nn_writeb(nn, NFP_NET_CFG_TXR_VEC(idx), r_vec->irq_idx); struct nfp_net_tx_ring *tx_ring, unsigned int idx)
{
nn_writeq(nn, NFP_NET_CFG_TXR_ADDR(idx), tx_ring->dma);
nn_writeb(nn, NFP_NET_CFG_TXR_SZ(idx), ilog2(tx_ring->cnt));
nn_writeb(nn, NFP_NET_CFG_TXR_VEC(idx), tx_ring->r_vec->irq_idx);
} }
static int __nfp_net_set_config_and_enable(struct nfp_net *nn) static int __nfp_net_set_config_and_enable(struct nfp_net *nn)
...@@ -1989,8 +1963,10 @@ static int __nfp_net_set_config_and_enable(struct nfp_net *nn) ...@@ -1989,8 +1963,10 @@ static int __nfp_net_set_config_and_enable(struct nfp_net *nn)
update |= NFP_NET_CFG_UPDATE_IRQMOD; update |= NFP_NET_CFG_UPDATE_IRQMOD;
} }
for (r = 0; r < nn->num_r_vecs; r++) for (r = 0; r < nn->num_tx_rings; r++)
nfp_net_vec_write_ring_data(nn, &nn->r_vecs[r], r); nfp_net_tx_ring_hw_cfg_write(nn, &nn->tx_rings[r], r);
for (r = 0; r < nn->num_rx_rings; r++)
nfp_net_rx_ring_hw_cfg_write(nn, &nn->rx_rings[r], r);
nn_writeq(nn, NFP_NET_CFG_TXRS_ENABLE, nn->num_tx_rings == 64 ? nn_writeq(nn, NFP_NET_CFG_TXRS_ENABLE, nn->num_tx_rings == 64 ?
0xffffffffffffffffULL : ((u64)1 << nn->num_tx_rings) - 1); 0xffffffffffffffffULL : ((u64)1 << nn->num_tx_rings) - 1);
...@@ -2016,7 +1992,7 @@ static int __nfp_net_set_config_and_enable(struct nfp_net *nn) ...@@ -2016,7 +1992,7 @@ static int __nfp_net_set_config_and_enable(struct nfp_net *nn)
nn->ctrl = new_ctrl; nn->ctrl = new_ctrl;
for (r = 0; r < nn->num_r_vecs; r++) for (r = 0; r < nn->num_rx_rings; r++)
nfp_net_rx_ring_fill_freelist(nn->r_vecs[r].rx_ring); nfp_net_rx_ring_fill_freelist(nn->r_vecs[r].rx_ring);
/* Since reconfiguration requests while NFP is down are ignored we /* Since reconfiguration requests while NFP is down are ignored we
...@@ -2108,20 +2084,22 @@ static int nfp_net_netdev_open(struct net_device *netdev) ...@@ -2108,20 +2084,22 @@ static int nfp_net_netdev_open(struct net_device *netdev)
for (r = 0; r < nn->num_r_vecs; r++) { for (r = 0; r < nn->num_r_vecs; r++) {
err = nfp_net_prepare_vector(nn, &nn->r_vecs[r], r); err = nfp_net_prepare_vector(nn, &nn->r_vecs[r], r);
if (err) if (err)
goto err_free_prev_vecs; goto err_cleanup_vec_p;
}
for (r = 0; r < nn->num_tx_rings; r++) {
err = nfp_net_tx_ring_alloc(nn->r_vecs[r].tx_ring, nn->txd_cnt); err = nfp_net_tx_ring_alloc(nn->r_vecs[r].tx_ring, nn->txd_cnt);
if (err) if (err)
goto err_cleanup_vec_p; goto err_free_tx_ring_p;
}
for (r = 0; r < nn->num_rx_rings; r++) {
err = nfp_net_rx_ring_alloc(nn->r_vecs[r].rx_ring, err = nfp_net_rx_ring_alloc(nn->r_vecs[r].rx_ring,
nn->fl_bufsz, nn->rxd_cnt); nn->fl_bufsz, nn->rxd_cnt);
if (err) if (err)
goto err_free_tx_ring_p; goto err_flush_free_rx_ring_p;
err = nfp_net_rx_ring_bufs_alloc(nn, nn->r_vecs[r].rx_ring); err = nfp_net_rx_ring_bufs_alloc(nn, nn->r_vecs[r].rx_ring);
if (err) if (err)
goto err_flush_rx_ring_p; goto err_free_rx_ring_p;
} }
err = netif_set_real_num_tx_queues(netdev, nn->num_tx_rings); err = netif_set_real_num_tx_queues(netdev, nn->num_tx_rings);
...@@ -2154,17 +2132,21 @@ static int nfp_net_netdev_open(struct net_device *netdev) ...@@ -2154,17 +2132,21 @@ static int nfp_net_netdev_open(struct net_device *netdev)
return 0; return 0;
err_free_rings: err_free_rings:
r = nn->num_r_vecs; r = nn->num_rx_rings;
err_free_prev_vecs: err_flush_free_rx_ring_p:
while (r--) { while (r--) {
nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring); nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring);
err_flush_rx_ring_p: err_free_rx_ring_p:
nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring); nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring);
}
r = nn->num_tx_rings;
err_free_tx_ring_p: err_free_tx_ring_p:
while (r--)
nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring); nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring);
r = nn->num_r_vecs;
err_cleanup_vec_p: err_cleanup_vec_p:
while (r--)
nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
}
kfree(nn->tx_rings); kfree(nn->tx_rings);
err_free_rx_rings: err_free_rx_rings:
kfree(nn->rx_rings); kfree(nn->rx_rings);
...@@ -2203,12 +2185,14 @@ static void nfp_net_close_free_all(struct nfp_net *nn) ...@@ -2203,12 +2185,14 @@ static void nfp_net_close_free_all(struct nfp_net *nn)
{ {
unsigned int r; unsigned int r;
for (r = 0; r < nn->num_r_vecs; r++) { for (r = 0; r < nn->num_rx_rings; r++) {
nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring); nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring);
nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring); nfp_net_rx_ring_free(nn->r_vecs[r].rx_ring);
}
for (r = 0; r < nn->num_tx_rings; r++)
nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring); nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring);
for (r = 0; r < nn->num_r_vecs; r++)
nfp_net_cleanup_vector(nn, &nn->r_vecs[r]); nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
}
kfree(nn->rx_rings); kfree(nn->rx_rings);
kfree(nn->tx_rings); kfree(nn->tx_rings);
...@@ -2280,7 +2264,7 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu) ...@@ -2280,7 +2264,7 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu)
old_mtu = netdev->mtu; old_mtu = netdev->mtu;
old_fl_bufsz = nn->fl_bufsz; old_fl_bufsz = nn->fl_bufsz;
new_fl_bufsz = NFP_NET_MAX_PREPEND + ETH_HLEN + VLAN_HLEN * 2 + new_mtu; new_fl_bufsz = nfp_net_calc_fl_bufsz(nn, new_mtu);
if (!netif_running(netdev)) { if (!netif_running(netdev)) {
netdev->mtu = new_mtu; netdev->mtu = new_mtu;
...@@ -2681,8 +2665,7 @@ static const struct net_device_ops nfp_net_netdev_ops = { ...@@ -2681,8 +2665,7 @@ static const struct net_device_ops nfp_net_netdev_ops = {
*/ */
void nfp_net_info(struct nfp_net *nn) void nfp_net_info(struct nfp_net *nn)
{ {
nn_info(nn, "Netronome %s %sNetdev: TxQs=%d/%d RxQs=%d/%d\n", nn_info(nn, "Netronome NFP-6xxx %sNetdev: TxQs=%d/%d RxQs=%d/%d\n",
nn->is_nfp3200 ? "NFP-32xx" : "NFP-6xxx",
nn->is_vf ? "VF " : "", nn->is_vf ? "VF " : "",
nn->num_tx_rings, nn->max_tx_rings, nn->num_tx_rings, nn->max_tx_rings,
nn->num_rx_rings, nn->max_rx_rings); nn->num_rx_rings, nn->max_rx_rings);
...@@ -2723,11 +2706,11 @@ void nfp_net_info(struct nfp_net *nn) ...@@ -2723,11 +2706,11 @@ void nfp_net_info(struct nfp_net *nn)
* Return: NFP Net device structure, or ERR_PTR on error. * Return: NFP Net device structure, or ERR_PTR on error.
*/ */
struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev, struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev,
int max_tx_rings, int max_rx_rings) unsigned int max_tx_rings,
unsigned int max_rx_rings)
{ {
struct net_device *netdev; struct net_device *netdev;
struct nfp_net *nn; struct nfp_net *nn;
int nqs;
netdev = alloc_etherdev_mqs(sizeof(struct nfp_net), netdev = alloc_etherdev_mqs(sizeof(struct nfp_net),
max_tx_rings, max_rx_rings); max_tx_rings, max_rx_rings);
...@@ -2743,9 +2726,12 @@ struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev, ...@@ -2743,9 +2726,12 @@ struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev,
nn->max_tx_rings = max_tx_rings; nn->max_tx_rings = max_tx_rings;
nn->max_rx_rings = max_rx_rings; nn->max_rx_rings = max_rx_rings;
nqs = netif_get_num_default_rss_queues(); nn->num_tx_rings = min_t(unsigned int, max_tx_rings, num_online_cpus());
nn->num_tx_rings = min_t(int, nqs, max_tx_rings); nn->num_rx_rings = min_t(unsigned int, max_rx_rings,
nn->num_rx_rings = min_t(int, nqs, max_rx_rings); netif_get_num_default_rss_queues());
nn->num_r_vecs = max(nn->num_tx_rings, nn->num_rx_rings);
nn->num_r_vecs = min_t(unsigned int, nn->num_r_vecs, num_online_cpus());
nn->txd_cnt = NFP_NET_TX_DESCS_DEFAULT; nn->txd_cnt = NFP_NET_TX_DESCS_DEFAULT;
nn->rxd_cnt = NFP_NET_RX_DESCS_DEFAULT; nn->rxd_cnt = NFP_NET_RX_DESCS_DEFAULT;
...@@ -2821,12 +2807,18 @@ int nfp_net_netdev_init(struct net_device *netdev) ...@@ -2821,12 +2807,18 @@ int nfp_net_netdev_init(struct net_device *netdev)
nfp_net_write_mac_addr(nn); nfp_net_write_mac_addr(nn);
/* Determine RX packet/metadata boundary offset */
if (nn->fw_ver.major >= 2)
nn->rx_offset = nn_readl(nn, NFP_NET_CFG_RX_OFFSET);
else
nn->rx_offset = NFP_NET_RX_OFFSET;
/* Set default MTU and Freelist buffer size */ /* Set default MTU and Freelist buffer size */
if (nn->max_mtu < NFP_NET_DEFAULT_MTU) if (nn->max_mtu < NFP_NET_DEFAULT_MTU)
netdev->mtu = nn->max_mtu; netdev->mtu = nn->max_mtu;
else else
netdev->mtu = NFP_NET_DEFAULT_MTU; netdev->mtu = NFP_NET_DEFAULT_MTU;
nn->fl_bufsz = NFP_NET_DEFAULT_RX_BUFSZ; nn->fl_bufsz = nfp_net_calc_fl_bufsz(nn, netdev->mtu);
/* Advertise/enable offloads based on capabilities /* Advertise/enable offloads based on capabilities
* *
...@@ -2897,18 +2889,6 @@ int nfp_net_netdev_init(struct net_device *netdev) ...@@ -2897,18 +2889,6 @@ int nfp_net_netdev_init(struct net_device *netdev)
nn->ctrl |= NFP_NET_CFG_CTRL_IRQMOD; nn->ctrl |= NFP_NET_CFG_CTRL_IRQMOD;
} }
/* On NFP-3200 enable MSI-X auto-masking, if supported and the
* interrupts are not shared.
*/
if (nn->is_nfp3200 && nn->cap & NFP_NET_CFG_CTRL_MSIXAUTO)
nn->ctrl |= NFP_NET_CFG_CTRL_MSIXAUTO;
/* On NFP4000/NFP6000, determine RX packet/metadata boundary offset */
if (nn->fw_ver.major >= 2)
nn->rx_offset = nn_readl(nn, NFP_NET_CFG_RX_OFFSET);
else
nn->rx_offset = NFP_NET_RX_OFFSET;
/* Stash the re-configuration queue away. First odd queue in TX Bar */ /* Stash the re-configuration queue away. First odd queue in TX Bar */
nn->qcp_cfg = nn->tx_bar + NFP_QCP_QUEUE_ADDR_SZ; nn->qcp_cfg = nn->tx_bar + NFP_QCP_QUEUE_ADDR_SZ;
...@@ -2922,7 +2902,6 @@ int nfp_net_netdev_init(struct net_device *netdev) ...@@ -2922,7 +2902,6 @@ int nfp_net_netdev_init(struct net_device *netdev)
return err; return err;
/* Finalise the netdev setup */ /* Finalise the netdev setup */
ether_setup(netdev);
netdev->netdev_ops = &nfp_net_netdev_ops; netdev->netdev_ops = &nfp_net_netdev_ops;
netdev->watchdog_timeo = msecs_to_jiffies(5 * 1000); netdev->watchdog_timeo = msecs_to_jiffies(5 * 1000);
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
/** /**
* Configuration BAR size. * Configuration BAR size.
* *
* The configuration BAR is 8K in size, but on the NFP6000, due to * The configuration BAR is 8K in size, but due to
* THB-350, 32k needs to be reserved. * THB-350, 32k needs to be reserved.
*/ */
#define NFP_NET_CFG_BAR_SZ (32 * 1024) #define NFP_NET_CFG_BAR_SZ (32 * 1024)
...@@ -186,18 +186,13 @@ ...@@ -186,18 +186,13 @@
#define NFP_NET_CFG_START_RXQ 0x004c #define NFP_NET_CFG_START_RXQ 0x004c
/** /**
* NFP-3200 workaround (0x0050 - 0x0058) * Prepend configuration
* @NFP_NET_CFG_SPARE_ADDR: DMA address for ME code to use (e.g. YDS-155 fix)
*/
#define NFP_NET_CFG_SPARE_ADDR 0x0050
/**
* NFP6000/NFP4000 - Prepend configuration
*/ */
#define NFP_NET_CFG_RX_OFFSET 0x0050 #define NFP_NET_CFG_RX_OFFSET 0x0050
#define NFP_NET_CFG_RX_OFFSET_DYNAMIC 0 /* Prepend mode */ #define NFP_NET_CFG_RX_OFFSET_DYNAMIC 0 /* Prepend mode */
/** /**
* NFP6000/NFP4000 - VXLAN/UDP encap configuration * VXLAN/UDP encap configuration
* @NFP_NET_CFG_VXLAN_PORT: Base address of table of tunnels' UDP dst ports * @NFP_NET_CFG_VXLAN_PORT: Base address of table of tunnels' UDP dst ports
* @NFP_NET_CFG_VXLAN_SZ: Size of the UDP port table in bytes * @NFP_NET_CFG_VXLAN_SZ: Size of the UDP port table in bytes
*/ */
...@@ -205,7 +200,7 @@ ...@@ -205,7 +200,7 @@
#define NFP_NET_CFG_VXLAN_SZ 0x0008 #define NFP_NET_CFG_VXLAN_SZ 0x0008
/** /**
* NFP6000 - BPF section * BPF section
* @NFP_NET_CFG_BPF_ABI: BPF ABI version * @NFP_NET_CFG_BPF_ABI: BPF ABI version
* @NFP_NET_CFG_BPF_CAP: BPF capabilities * @NFP_NET_CFG_BPF_CAP: BPF capabilities
* @NFP_NET_CFG_BPF_MAX_LEN: Maximum size of JITed BPF code in bytes * @NFP_NET_CFG_BPF_MAX_LEN: Maximum size of JITed BPF code in bytes
......
...@@ -44,8 +44,8 @@ static int nfp_net_debugfs_rx_q_read(struct seq_file *file, void *data) ...@@ -44,8 +44,8 @@ static int nfp_net_debugfs_rx_q_read(struct seq_file *file, void *data)
struct nfp_net_r_vector *r_vec = file->private; struct nfp_net_r_vector *r_vec = file->private;
struct nfp_net_rx_ring *rx_ring; struct nfp_net_rx_ring *rx_ring;
struct nfp_net_rx_desc *rxd; struct nfp_net_rx_desc *rxd;
struct sk_buff *skb;
struct nfp_net *nn; struct nfp_net *nn;
void *frag;
int i; int i;
rtnl_lock(); rtnl_lock();
...@@ -73,10 +73,9 @@ static int nfp_net_debugfs_rx_q_read(struct seq_file *file, void *data) ...@@ -73,10 +73,9 @@ static int nfp_net_debugfs_rx_q_read(struct seq_file *file, void *data)
seq_printf(file, "%04d: 0x%08x 0x%08x", i, seq_printf(file, "%04d: 0x%08x 0x%08x", i,
rxd->vals[0], rxd->vals[1]); rxd->vals[0], rxd->vals[1]);
skb = READ_ONCE(rx_ring->rxbufs[i].skb); frag = READ_ONCE(rx_ring->rxbufs[i].frag);
if (skb) if (frag)
seq_printf(file, " skb->head=%p skb->data=%p", seq_printf(file, " frag=%p", frag);
skb->head, skb->data);
if (rx_ring->rxbufs[i].dma_addr) if (rx_ring->rxbufs[i].dma_addr)
seq_printf(file, " dma_addr=%pad", seq_printf(file, " dma_addr=%pad",
......
...@@ -63,9 +63,7 @@ static void nfp_netvf_get_mac_addr(struct nfp_net *nn) ...@@ -63,9 +63,7 @@ static void nfp_netvf_get_mac_addr(struct nfp_net *nn)
u8 mac_addr[ETH_ALEN]; u8 mac_addr[ETH_ALEN];
put_unaligned_be32(nn_readl(nn, NFP_NET_CFG_MACADDR + 0), &mac_addr[0]); put_unaligned_be32(nn_readl(nn, NFP_NET_CFG_MACADDR + 0), &mac_addr[0]);
/* We can't do readw for NFP-3200 compatibility */ put_unaligned_be16(nn_readw(nn, NFP_NET_CFG_MACADDR + 6), &mac_addr[4]);
put_unaligned_be16(nn_readl(nn, NFP_NET_CFG_MACADDR + 4) >> 16,
&mac_addr[4]);
if (!is_valid_ether_addr(mac_addr)) { if (!is_valid_ether_addr(mac_addr)) {
eth_hw_addr_random(nn->netdev); eth_hw_addr_random(nn->netdev);
...@@ -86,7 +84,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, ...@@ -86,7 +84,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
int tx_bar_no, rx_bar_no; int tx_bar_no, rx_bar_no;
u8 __iomem *ctrl_bar; u8 __iomem *ctrl_bar;
struct nfp_net *nn; struct nfp_net *nn;
int is_nfp3200;
u32 startq; u32 startq;
int stride; int stride;
int err; int err;
...@@ -101,15 +98,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, ...@@ -101,15 +98,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
goto err_pci_disable; goto err_pci_disable;
} }
switch (pdev->device) {
case PCI_DEVICE_NFP6000VF:
is_nfp3200 = 0;
break;
default:
err = -ENODEV;
goto err_pci_regions;
}
pci_set_master(pdev); pci_set_master(pdev);
err = dma_set_mask_and_coherent(&pdev->dev, err = dma_set_mask_and_coherent(&pdev->dev,
...@@ -149,15 +137,9 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, ...@@ -149,15 +137,9 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
} else { } else {
switch (fw_ver.major) { switch (fw_ver.major) {
case 1 ... 4: case 1 ... 4:
if (is_nfp3200) { stride = 4;
stride = 2; tx_bar_no = NFP_NET_Q0_BAR;
tx_bar_no = NFP_NET_Q0_BAR; rx_bar_no = tx_bar_no;
rx_bar_no = NFP_NET_Q1_BAR;
} else {
stride = 4;
tx_bar_no = NFP_NET_Q0_BAR;
rx_bar_no = tx_bar_no;
}
break; break;
default: default:
dev_err(&pdev->dev, "Unsupported Firmware ABI %d.%d.%d.%d\n", dev_err(&pdev->dev, "Unsupported Firmware ABI %d.%d.%d.%d\n",
...@@ -189,20 +171,10 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, ...@@ -189,20 +171,10 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
max_rx_rings = (rx_bar_sz / NFP_QCP_QUEUE_ADDR_SZ) / 2; max_rx_rings = (rx_bar_sz / NFP_QCP_QUEUE_ADDR_SZ) / 2;
} }
/* XXX Implement a workaround for THB-350 here. Ideally, we startq = readl(ctrl_bar + NFP_NET_CFG_START_TXQ);
* have a different PCI ID for A rev VFs. tx_bar_off = NFP_PCIE_QUEUE(startq);
*/ startq = readl(ctrl_bar + NFP_NET_CFG_START_RXQ);
switch (pdev->device) { rx_bar_off = NFP_PCIE_QUEUE(startq);
case PCI_DEVICE_NFP6000VF:
startq = readl(ctrl_bar + NFP_NET_CFG_START_TXQ);
tx_bar_off = NFP_PCIE_QUEUE(startq);
startq = readl(ctrl_bar + NFP_NET_CFG_START_RXQ);
rx_bar_off = NFP_PCIE_QUEUE(startq);
break;
default:
err = -ENODEV;
goto err_ctrl_unmap;
}
/* Allocate and initialise the netdev */ /* Allocate and initialise the netdev */
nn = nfp_net_netdev_alloc(pdev, max_tx_rings, max_rx_rings); nn = nfp_net_netdev_alloc(pdev, max_tx_rings, max_rx_rings);
...@@ -214,7 +186,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, ...@@ -214,7 +186,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
nn->fw_ver = fw_ver; nn->fw_ver = fw_ver;
nn->ctrl_bar = ctrl_bar; nn->ctrl_bar = ctrl_bar;
nn->is_vf = 1; nn->is_vf = 1;
nn->is_nfp3200 = is_nfp3200;
nn->stride_tx = stride; nn->stride_tx = stride;
nn->stride_rx = stride; nn->stride_rx = stride;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment