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 @@
/* Default size for MTU and freelist buffer sizes */
#define NFP_NET_DEFAULT_MTU 1500
#define NFP_NET_DEFAULT_RX_BUFSZ 2048
/* Maximum number of bytes prepended to a packet */
#define NFP_NET_MAX_PREPEND 64
......@@ -88,6 +87,9 @@
/* Queue/Ring definitions */
#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_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_RX_DESCS 256 /* Min. # of Rx descs per ring */
......@@ -102,6 +104,10 @@
/* Offload definitions */
#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 */
struct nfp_net;
struct nfp_net_r_vector;
......@@ -278,11 +284,11 @@ struct nfp_net_rx_hash {
/**
* 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
*/
struct nfp_net_rx_buf {
struct sk_buff *skb;
void *frag;
dma_addr_t dma_addr;
};
......@@ -421,7 +427,6 @@ struct nfp_stat_pair {
* @netdev: Backpointer to net_device structure
* @nfp_fallback: Is the driver used in fallback mode?
* @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?
* @bpf_offload_skip_sw: Offloaded BPF program will not be rerun by cls_bpf
* @ctrl: Local copy of the control register/word.
......@@ -451,7 +456,7 @@ struct nfp_stat_pair {
* @rxd_cnt: Size of the RX ring in number of descriptors
* @tx_rings: Array of pre-allocated TX 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
* @r_vecs: Pre-allocated array of ring vectors
* @irq_entries: Pre-allocated array of MSI-X entries
......@@ -487,7 +492,6 @@ struct nfp_net {
unsigned nfp_fallback:1;
unsigned is_vf:1;
unsigned is_nfp3200:1;
unsigned fw_loaded:1;
unsigned bpf_offload_skip_sw:1;
......@@ -524,11 +528,11 @@ struct nfp_net {
struct timer_list rx_filter_stats_timer;
spinlock_t rx_filter_lock;
int max_tx_rings;
int max_rx_rings;
unsigned int max_tx_rings;
unsigned int max_rx_rings;
int num_tx_rings;
int num_rx_rings;
unsigned int num_tx_rings;
unsigned int num_rx_rings;
int stride_tx;
int stride_rx;
......@@ -536,11 +540,10 @@ struct nfp_net {
int txd_cnt;
int rxd_cnt;
u8 num_irqs;
u8 num_r_vecs;
struct nfp_net_r_vector r_vecs[NFP_NET_MAX_TX_RINGS];
struct msix_entry irq_entries[NFP_NET_NON_Q_VECTORS +
NFP_NET_MAX_TX_RINGS];
unsigned int max_r_vecs;
unsigned int num_r_vecs;
struct nfp_net_r_vector r_vecs[NFP_NET_MAX_R_VECS];
struct msix_entry irq_entries[NFP_NET_MAX_IRQS];
irq_handler_t lsc_handler;
char lsc_name[IFNAMSIZ + 8];
......@@ -593,16 +596,13 @@ static inline void nn_writeb(struct nfp_net *nn, int off, u8 val)
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)
{
WARN_ON_ONCE(nn->is_nfp3200);
return readw(nn->ctrl_bar + off);
}
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);
}
......@@ -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_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)))
/* nfp_qcp_ptr - Read or Write Pointer of a queue */
......@@ -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 __iomem *ctrl_bar);
struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev,
int max_tx_rings, int max_rx_rings);
struct nfp_net *
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);
int nfp_net_netdev_init(struct net_device *netdev);
void nfp_net_netdev_clean(struct net_device *netdev);
......
......@@ -50,6 +50,7 @@
#include <linux/interrupt.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/page_ref.h>
#include <linux/pci.h>
#include <linux/pci_regs.h>
#include <linux/msi.h>
......@@ -80,6 +81,22 @@ void nfp_net_get_fw_version(struct nfp_net_fw_version *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 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)
/* 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
* @nn: NFP Network structure
* @entry_nr: MSI-X table entry
*
* If MSI-X auto-masking is enabled clear the mask bit, otherwise
* clear the ICR for the entry.
* Clear the ICR for the IRQ entry.
*/
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_pci_flush(nn);
}
......@@ -319,28 +307,6 @@ static int nfp_net_msix_alloc(struct nfp_net *nn, int nr_vecs)
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
* @nn: NFP Network structure
......@@ -350,22 +316,24 @@ static int nfp_net_irqs_wanted(struct nfp_net *nn)
int nfp_net_irqs_alloc(struct nfp_net *nn)
{
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);
if (nn->num_irqs == 0) {
n = nfp_net_msix_alloc(nn, wanted_irqs);
if (n == 0) {
nn_err(nn, "Failed to allocate MSI-X IRQs\n");
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",
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)
struct nfp_net_r_vector *r_vec;
int r;
/* Assumes nn->num_tx_rings == nn->num_rx_rings */
if (nn->num_tx_rings > nn->num_r_vecs) {
nn_warn(nn, "More rings (%d) than vectors (%d).\n",
nn->num_tx_rings, nn->num_r_vecs);
nn->num_tx_rings = nn->num_r_vecs;
nn->num_rx_rings = nn->num_r_vecs;
}
if (nn->num_rx_rings > nn->num_r_vecs ||
nn->num_tx_rings > nn->num_r_vecs)
nn_warn(nn, "More rings (%d,%d) than vectors (%d).\n",
nn->num_rx_rings, nn->num_tx_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->exn_handler = nfp_net_irq_exn;
......@@ -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.
*/
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);
}
......@@ -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))
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 */
txbuf = &tx_ring->txbufs[wr_idx];
......@@ -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))
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].dma_addr = dma_addr;
tx_ring->txbufs[wr_idx].fidx = f;
......@@ -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;
while (todo--) {
idx = tx_ring->rd_p % tx_ring->cnt;
idx = tx_ring->rd_p & (tx_ring->cnt - 1);
tx_ring->rd_p++;
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)
int nr_frags, fidx, idx;
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;
nr_frags = skb_shinfo(skb)->nr_frags;
fidx = tx_ring->txbufs[idx].fidx;
......@@ -1059,69 +1027,92 @@ static void nfp_net_tx_timeout(struct net_device *netdev)
/* Receive processing
*/
/**
* 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)
static unsigned int
nfp_net_calc_fl_bufsz(struct nfp_net *nn, unsigned int mtu)
{
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
* @dma_addr: Pointer to storage for DMA address (output param)
* @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,
unsigned int fl_bufsz)
{
struct nfp_net *nn = rx_ring->r_vec->nfp_net;
struct sk_buff *skb;
void *frag;
skb = netdev_alloc_skb(nn->netdev, fl_bufsz);
if (!skb) {
nn_warn_ratelimit(nn, "Failed to alloc receive SKB\n");
frag = netdev_alloc_frag(fl_bufsz);
if (!frag) {
nn_warn_ratelimit(nn, "Failed to alloc receive page frag\n");
return NULL;
}
*dma_addr = dma_map_single(&nn->pdev->dev, skb->data,
fl_bufsz, DMA_FROM_DEVICE);
*dma_addr = nfp_net_dma_map_rx(nn, frag, fl_bufsz, DMA_FROM_DEVICE);
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");
return NULL;
}
return skb;
return frag;
}
/**
* nfp_net_rx_give_one() - Put mapped skb on the software and hardware rings
* @rx_ring: RX ring structure
* @skb: Skb to put on rings
* @frag: page fragment buffer
* @dma_addr: DMA address of skb mapping
*/
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;
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 */
rx_ring->rxbufs[wr_idx].skb = skb;
rx_ring->rxbufs[wr_idx].frag = frag;
rx_ring->rxbufs[wr_idx].dma_addr = dma_addr;
/* Fill freelist descriptor */
......@@ -1153,12 +1144,12 @@ static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring)
unsigned int wr_idx, last_idx;
/* 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;
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].skb = NULL;
rx_ring->rxbufs[last_idx].frag = NULL;
memset(rx_ring->rxds, 0, sizeof(*rx_ring->rxds) * rx_ring->cnt);
rx_ring->wr_p = 0;
......@@ -1178,7 +1169,6 @@ static void nfp_net_rx_ring_reset(struct nfp_net_rx_ring *rx_ring)
static void
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;
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)
* fails to allocate enough buffers and calls here to free
* already allocated ones.
*/
if (!rx_ring->rxbufs[i].skb)
if (!rx_ring->rxbufs[i].frag)
continue;
dma_unmap_single(&pdev->dev, rx_ring->rxbufs[i].dma_addr,
rx_ring->bufsz, DMA_FROM_DEVICE);
dev_kfree_skb_any(rx_ring->rxbufs[i].skb);
nfp_net_dma_unmap_rx(nn, rx_ring->rxbufs[i].dma_addr,
rx_ring->bufsz, DMA_FROM_DEVICE);
skb_free_frag(rx_ring->rxbufs[i].frag);
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)
rxbufs = rx_ring->rxbufs;
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,
rx_ring->bufsz);
if (!rxbufs[i].skb) {
if (!rxbufs[i].frag) {
nfp_net_rx_ring_bufs_free(nn, rx_ring);
return -ENOMEM;
}
......@@ -1232,7 +1222,7 @@ static void nfp_net_rx_ring_fill_freelist(struct nfp_net_rx_ring *rx_ring)
unsigned int 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);
}
......@@ -1359,6 +1349,25 @@ nfp_net_parse_meta(struct net_device *netdev, struct sk_buff *skb,
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
* @rx_ring: RX ring to receive from
......@@ -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
* 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.
*/
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 *nn = r_vec->nfp_net;
unsigned int data_len, meta_len;
int avail = 0, pkts_polled = 0;
struct sk_buff *skb, *new_skb;
struct nfp_net_rx_buf *rxbuf;
struct nfp_net_rx_desc *rxd;
dma_addr_t new_dma_addr;
u32 qcp_wr_p;
struct sk_buff *skb;
int pkts_polled = 0;
void *new_frag;
int idx;
if (nn->is_nfp3200) {
/* Work out how many packets arrived */
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;
while (pkts_polled < budget) {
idx = rx_ring->rd_p & (rx_ring->cnt - 1);
rxd = &rx_ring->rxds[idx];
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]);
if (!(rxd->rxd.meta_len_dd & PCIE_DESC_RX_DD))
break;
}
/* Memory barrier to ensure that we won't do other reads
* before the DD bit.
*/
......@@ -1431,26 +1406,23 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
rx_ring->rd_p++;
pkts_polled++;
avail--;
skb = rx_ring->rxbufs[idx].skb;
new_skb = nfp_net_rx_alloc_one(rx_ring, &new_dma_addr,
nn->fl_bufsz);
if (!new_skb) {
nfp_net_rx_give_one(rx_ring, rx_ring->rxbufs[idx].skb,
rx_ring->rxbufs[idx].dma_addr);
u64_stats_update_begin(&r_vec->rx_sync);
r_vec->rx_drops++;
u64_stats_update_end(&r_vec->rx_sync);
rxbuf = &rx_ring->rxbufs[idx];
skb = build_skb(rxbuf->frag, nn->fl_bufsz);
if (unlikely(!skb)) {
nfp_net_rx_drop(r_vec, rx_ring, rxbuf, NULL);
continue;
}
new_frag = nfp_net_napi_alloc_one(nn, &new_dma_addr);
if (unlikely(!new_frag)) {
nfp_net_rx_drop(r_vec, rx_ring, rxbuf, skb);
continue;
}
dma_unmap_single(&nn->pdev->dev,
rx_ring->rxbufs[idx].dma_addr,
nn->fl_bufsz, DMA_FROM_DEVICE);
nfp_net_dma_unmap_rx(nn, rx_ring->rxbufs[idx].dma_addr,
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 >
* <-- [rx_offset] -->
......@@ -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);
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
skb_reserve(skb, nn->rx_offset);
skb_reserve(skb,
NFP_NET_RX_BUF_HEADROOM + nn->rx_offset);
skb_put(skb, data_len - meta_len);
/* Stats update */
......@@ -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);
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");
nfp_net_rx_drop(r_vec, rx_ring, NULL, skb);
continue;
}
}
......@@ -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);
}
if (nn->is_nfp3200)
nfp_qcp_rd_ptr_add(rx_ring->qcp_rx, pkts_polled);
return pkts_polled;
}
......@@ -1525,21 +1491,16 @@ static int nfp_net_poll(struct napi_struct *napi, int budget)
{
struct nfp_net_r_vector *r_vec =
container_of(napi, struct nfp_net_r_vector, napi);
struct nfp_net_rx_ring *rx_ring = r_vec->rx_ring;
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;
unsigned int pkts_polled = 0;
tx_ring = &nn->tx_rings[rx_ring->idx];
txq = netdev_get_tx_queue(nn->netdev, tx_ring->idx);
nfp_net_tx_complete(tx_ring);
pkts_polled = nfp_net_rx(rx_ring, budget);
if (r_vec->tx_ring)
nfp_net_tx_complete(r_vec->tx_ring);
if (r_vec->rx_ring)
pkts_polled = nfp_net_rx(r_vec->rx_ring, budget);
if (pkts_polled < budget) {
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;
......@@ -1783,7 +1744,7 @@ nfp_net_shadow_rx_rings_free(struct nfp_net *nn, struct nfp_net_rx_ring *rings)
if (!rings)
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_free(&rings[r]);
}
......@@ -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];
int err;
r_vec->tx_ring = &nn->tx_rings[idx];
nfp_net_tx_ring_init(r_vec->tx_ring, r_vec, idx);
if (idx < nn->num_tx_rings) {
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];
nfp_net_rx_ring_init(r_vec->rx_ring, r_vec, idx);
if (idx < nn->num_rx_rings) {
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),
"%s-rxtx-%d", nn->netdev->name, idx);
......@@ -1879,13 +1848,13 @@ void nfp_net_coalesce_write_cfg(struct nfp_net *nn)
/* copy RX interrupt coalesce parameters */
value = (nn->rx_coalesce_max_frames << 16) |
(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);
/* copy TX interrupt coalesce parameters */
value = (nn->tx_coalesce_max_frames << 16) |
(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);
}
......@@ -1901,9 +1870,8 @@ static void nfp_net_write_mac_addr(struct nfp_net *nn)
{
nn_writel(nn, NFP_NET_CFG_MACADDR + 0,
get_unaligned_be32(nn->netdev->dev_addr));
/* We can't do writew for NFP-3200 compatibility */
nn_writel(nn, NFP_NET_CFG_MACADDR + 4,
get_unaligned_be16(nn->netdev->dev_addr + 4) << 16);
nn_writew(nn, NFP_NET_CFG_MACADDR + 6,
get_unaligned_be16(nn->netdev->dev_addr + 4));
}
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)
if (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);
for (r = 0; r < nn->num_tx_rings; r++)
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);
}
nn->ctrl = new_ctrl;
}
static void
nfp_net_vec_write_ring_data(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
unsigned int idx)
nfp_net_rx_ring_hw_cfg_write(struct nfp_net *nn,
struct nfp_net_rx_ring *rx_ring, unsigned int idx)
{
/* 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_writeb(nn, NFP_NET_CFG_RXR_SZ(idx), ilog2(r_vec->rx_ring->cnt));
nn_writeb(nn, NFP_NET_CFG_RXR_VEC(idx), r_vec->irq_idx);
nn_writeq(nn, NFP_NET_CFG_RXR_ADDR(idx), rx_ring->dma);
nn_writeb(nn, NFP_NET_CFG_RXR_SZ(idx), ilog2(rx_ring->cnt));
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);
nn_writeb(nn, NFP_NET_CFG_TXR_SZ(idx), ilog2(r_vec->tx_ring->cnt));
nn_writeb(nn, NFP_NET_CFG_TXR_VEC(idx), r_vec->irq_idx);
static void
nfp_net_tx_ring_hw_cfg_write(struct nfp_net *nn,
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)
......@@ -1989,8 +1963,10 @@ static int __nfp_net_set_config_and_enable(struct nfp_net *nn)
update |= NFP_NET_CFG_UPDATE_IRQMOD;
}
for (r = 0; r < nn->num_r_vecs; r++)
nfp_net_vec_write_ring_data(nn, &nn->r_vecs[r], r);
for (r = 0; r < nn->num_tx_rings; 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 ?
0xffffffffffffffffULL : ((u64)1 << nn->num_tx_rings) - 1);
......@@ -2016,7 +1992,7 @@ static int __nfp_net_set_config_and_enable(struct nfp_net *nn)
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);
/* Since reconfiguration requests while NFP is down are ignored we
......@@ -2108,20 +2084,22 @@ static int nfp_net_netdev_open(struct net_device *netdev)
for (r = 0; r < nn->num_r_vecs; r++) {
err = nfp_net_prepare_vector(nn, &nn->r_vecs[r], r);
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);
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,
nn->fl_bufsz, nn->rxd_cnt);
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);
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);
......@@ -2154,17 +2132,21 @@ static int nfp_net_netdev_open(struct net_device *netdev)
return 0;
err_free_rings:
r = nn->num_r_vecs;
err_free_prev_vecs:
r = nn->num_rx_rings;
err_flush_free_rx_ring_p:
while (r--) {
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);
}
r = nn->num_tx_rings;
err_free_tx_ring_p:
while (r--)
nfp_net_tx_ring_free(nn->r_vecs[r].tx_ring);
r = nn->num_r_vecs;
err_cleanup_vec_p:
while (r--)
nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
}
kfree(nn->tx_rings);
err_free_rx_rings:
kfree(nn->rx_rings);
......@@ -2203,12 +2185,14 @@ static void nfp_net_close_free_all(struct nfp_net *nn)
{
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_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);
for (r = 0; r < nn->num_r_vecs; r++)
nfp_net_cleanup_vector(nn, &nn->r_vecs[r]);
}
kfree(nn->rx_rings);
kfree(nn->tx_rings);
......@@ -2280,7 +2264,7 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu)
old_mtu = netdev->mtu;
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)) {
netdev->mtu = new_mtu;
......@@ -2681,8 +2665,7 @@ static const struct net_device_ops nfp_net_netdev_ops = {
*/
void nfp_net_info(struct nfp_net *nn)
{
nn_info(nn, "Netronome %s %sNetdev: TxQs=%d/%d RxQs=%d/%d\n",
nn->is_nfp3200 ? "NFP-32xx" : "NFP-6xxx",
nn_info(nn, "Netronome NFP-6xxx %sNetdev: TxQs=%d/%d RxQs=%d/%d\n",
nn->is_vf ? "VF " : "",
nn->num_tx_rings, nn->max_tx_rings,
nn->num_rx_rings, nn->max_rx_rings);
......@@ -2723,11 +2706,11 @@ void nfp_net_info(struct nfp_net *nn)
* Return: NFP Net device structure, or ERR_PTR on error.
*/
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 nfp_net *nn;
int nqs;
netdev = alloc_etherdev_mqs(sizeof(struct nfp_net),
max_tx_rings, max_rx_rings);
......@@ -2743,9 +2726,12 @@ struct nfp_net *nfp_net_netdev_alloc(struct pci_dev *pdev,
nn->max_tx_rings = max_tx_rings;
nn->max_rx_rings = max_rx_rings;
nqs = netif_get_num_default_rss_queues();
nn->num_tx_rings = min_t(int, nqs, max_tx_rings);
nn->num_rx_rings = min_t(int, nqs, max_rx_rings);
nn->num_tx_rings = min_t(unsigned int, max_tx_rings, num_online_cpus());
nn->num_rx_rings = min_t(unsigned int, 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->rxd_cnt = NFP_NET_RX_DESCS_DEFAULT;
......@@ -2821,12 +2807,18 @@ int nfp_net_netdev_init(struct net_device *netdev)
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 */
if (nn->max_mtu < NFP_NET_DEFAULT_MTU)
netdev->mtu = nn->max_mtu;
else
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
*
......@@ -2897,18 +2889,6 @@ int nfp_net_netdev_init(struct net_device *netdev)
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 */
nn->qcp_cfg = nn->tx_bar + NFP_QCP_QUEUE_ADDR_SZ;
......@@ -2922,7 +2902,6 @@ int nfp_net_netdev_init(struct net_device *netdev)
return err;
/* Finalise the netdev setup */
ether_setup(netdev);
netdev->netdev_ops = &nfp_net_netdev_ops;
netdev->watchdog_timeo = msecs_to_jiffies(5 * 1000);
......
......@@ -50,7 +50,7 @@
/**
* 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.
*/
#define NFP_NET_CFG_BAR_SZ (32 * 1024)
......@@ -186,18 +186,13 @@
#define NFP_NET_CFG_START_RXQ 0x004c
/**
* NFP-3200 workaround (0x0050 - 0x0058)
* @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
* Prepend configuration
*/
#define NFP_NET_CFG_RX_OFFSET 0x0050
#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_SZ: Size of the UDP port table in bytes
*/
......@@ -205,7 +200,7 @@
#define NFP_NET_CFG_VXLAN_SZ 0x0008
/**
* NFP6000 - BPF section
* BPF section
* @NFP_NET_CFG_BPF_ABI: BPF ABI version
* @NFP_NET_CFG_BPF_CAP: BPF capabilities
* @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)
struct nfp_net_r_vector *r_vec = file->private;
struct nfp_net_rx_ring *rx_ring;
struct nfp_net_rx_desc *rxd;
struct sk_buff *skb;
struct nfp_net *nn;
void *frag;
int i;
rtnl_lock();
......@@ -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,
rxd->vals[0], rxd->vals[1]);
skb = READ_ONCE(rx_ring->rxbufs[i].skb);
if (skb)
seq_printf(file, " skb->head=%p skb->data=%p",
skb->head, skb->data);
frag = READ_ONCE(rx_ring->rxbufs[i].frag);
if (frag)
seq_printf(file, " frag=%p", frag);
if (rx_ring->rxbufs[i].dma_addr)
seq_printf(file, " dma_addr=%pad",
......
......@@ -63,9 +63,7 @@ static void nfp_netvf_get_mac_addr(struct nfp_net *nn)
u8 mac_addr[ETH_ALEN];
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_readl(nn, NFP_NET_CFG_MACADDR + 4) >> 16,
&mac_addr[4]);
put_unaligned_be16(nn_readw(nn, NFP_NET_CFG_MACADDR + 6), &mac_addr[4]);
if (!is_valid_ether_addr(mac_addr)) {
eth_hw_addr_random(nn->netdev);
......@@ -86,7 +84,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
int tx_bar_no, rx_bar_no;
u8 __iomem *ctrl_bar;
struct nfp_net *nn;
int is_nfp3200;
u32 startq;
int stride;
int err;
......@@ -101,15 +98,6 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
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);
err = dma_set_mask_and_coherent(&pdev->dev,
......@@ -149,15 +137,9 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev,
} else {
switch (fw_ver.major) {
case 1 ... 4:
if (is_nfp3200) {
stride = 2;
tx_bar_no = NFP_NET_Q0_BAR;
rx_bar_no = NFP_NET_Q1_BAR;
} else {
stride = 4;
tx_bar_no = NFP_NET_Q0_BAR;
rx_bar_no = tx_bar_no;
}
stride = 4;
tx_bar_no = NFP_NET_Q0_BAR;
rx_bar_no = tx_bar_no;
break;
default:
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,
max_rx_rings = (rx_bar_sz / NFP_QCP_QUEUE_ADDR_SZ) / 2;
}
/* XXX Implement a workaround for THB-350 here. Ideally, we
* have a different PCI ID for A rev VFs.
*/
switch (pdev->device) {
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;
}
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);
/* Allocate and initialise the netdev */
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,
nn->fw_ver = fw_ver;
nn->ctrl_bar = ctrl_bar;
nn->is_vf = 1;
nn->is_nfp3200 = is_nfp3200;
nn->stride_tx = 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