Commit b0e92279 authored by David S. Miller's avatar David S. Miller

Merge branch 'thunderx-xdp'

Sunil Goutham says:

====================
net: thunderx: Adds XDP support

This patch series adds support for XDP to ThunderX NIC driver
which is used on CN88xx, CN81xx and CN83xx platforms.

Patches 1-4 are performance improvement and cleanup patches
which are done keeping XDP performance bottlenecks in view.
Rest of the patches adds actual XDP support.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ee0d8d84 77322538
...@@ -252,12 +252,14 @@ struct nicvf_drv_stats { ...@@ -252,12 +252,14 @@ struct nicvf_drv_stats {
u64 tx_csum_overflow; u64 tx_csum_overflow;
/* driver debug stats */ /* driver debug stats */
u64 rcv_buffer_alloc_failures;
u64 tx_tso; u64 tx_tso;
u64 tx_timeout; u64 tx_timeout;
u64 txq_stop; u64 txq_stop;
u64 txq_wake; u64 txq_wake;
u64 rcv_buffer_alloc_failures;
u64 page_alloc;
struct u64_stats_sync syncp; struct u64_stats_sync syncp;
}; };
...@@ -266,9 +268,9 @@ struct nicvf { ...@@ -266,9 +268,9 @@ struct nicvf {
struct net_device *netdev; struct net_device *netdev;
struct pci_dev *pdev; struct pci_dev *pdev;
void __iomem *reg_base; void __iomem *reg_base;
struct bpf_prog *xdp_prog;
#define MAX_QUEUES_PER_QSET 8 #define MAX_QUEUES_PER_QSET 8
struct queue_set *qs; struct queue_set *qs;
struct nicvf_cq_poll *napi[8];
void *iommu_domain; void *iommu_domain;
u8 vf_id; u8 vf_id;
u8 sqs_id; u8 sqs_id;
...@@ -294,6 +296,7 @@ struct nicvf { ...@@ -294,6 +296,7 @@ struct nicvf {
/* Queue count */ /* Queue count */
u8 rx_queues; u8 rx_queues;
u8 tx_queues; u8 tx_queues;
u8 xdp_tx_queues;
u8 max_queues; u8 max_queues;
u8 node; u8 node;
...@@ -318,6 +321,9 @@ struct nicvf { ...@@ -318,6 +321,9 @@ struct nicvf {
struct nicvf_drv_stats __percpu *drv_stats; struct nicvf_drv_stats __percpu *drv_stats;
struct bgx_stats bgx_stats; struct bgx_stats bgx_stats;
/* Napi */
struct nicvf_cq_poll *napi[8];
/* MSI-X */ /* MSI-X */
u8 num_vec; u8 num_vec;
char irq_name[NIC_VF_MSIX_VECTORS][IFNAMSIZ + 15]; char irq_name[NIC_VF_MSIX_VECTORS][IFNAMSIZ + 15];
......
...@@ -100,11 +100,12 @@ static const struct nicvf_stat nicvf_drv_stats[] = { ...@@ -100,11 +100,12 @@ static const struct nicvf_stat nicvf_drv_stats[] = {
NICVF_DRV_STAT(tx_csum_overlap), NICVF_DRV_STAT(tx_csum_overlap),
NICVF_DRV_STAT(tx_csum_overflow), NICVF_DRV_STAT(tx_csum_overflow),
NICVF_DRV_STAT(rcv_buffer_alloc_failures),
NICVF_DRV_STAT(tx_tso), NICVF_DRV_STAT(tx_tso),
NICVF_DRV_STAT(tx_timeout), NICVF_DRV_STAT(tx_timeout),
NICVF_DRV_STAT(txq_stop), NICVF_DRV_STAT(txq_stop),
NICVF_DRV_STAT(txq_wake), NICVF_DRV_STAT(txq_wake),
NICVF_DRV_STAT(rcv_buffer_alloc_failures),
NICVF_DRV_STAT(page_alloc),
}; };
static const struct nicvf_stat nicvf_queue_stats[] = { static const struct nicvf_stat nicvf_queue_stats[] = {
...@@ -720,7 +721,7 @@ static int nicvf_set_channels(struct net_device *dev, ...@@ -720,7 +721,7 @@ static int nicvf_set_channels(struct net_device *dev,
struct nicvf *nic = netdev_priv(dev); struct nicvf *nic = netdev_priv(dev);
int err = 0; int err = 0;
bool if_up = netif_running(dev); bool if_up = netif_running(dev);
int cqcount; u8 cqcount, txq_count;
if (!channel->rx_count || !channel->tx_count) if (!channel->rx_count || !channel->tx_count)
return -EINVAL; return -EINVAL;
...@@ -729,10 +730,26 @@ static int nicvf_set_channels(struct net_device *dev, ...@@ -729,10 +730,26 @@ static int nicvf_set_channels(struct net_device *dev,
if (channel->tx_count > nic->max_queues) if (channel->tx_count > nic->max_queues)
return -EINVAL; return -EINVAL;
if (nic->xdp_prog &&
((channel->tx_count + channel->rx_count) > nic->max_queues)) {
netdev_err(nic->netdev,
"XDP mode, RXQs + TXQs > Max %d\n",
nic->max_queues);
return -EINVAL;
}
if (if_up) if (if_up)
nicvf_stop(dev); nicvf_stop(dev);
cqcount = max(channel->rx_count, channel->tx_count); nic->rx_queues = channel->rx_count;
nic->tx_queues = channel->tx_count;
if (!nic->xdp_prog)
nic->xdp_tx_queues = 0;
else
nic->xdp_tx_queues = channel->rx_count;
txq_count = nic->xdp_tx_queues + nic->tx_queues;
cqcount = max(nic->rx_queues, txq_count);
if (cqcount > MAX_CMP_QUEUES_PER_QS) { if (cqcount > MAX_CMP_QUEUES_PER_QS) {
nic->sqs_count = roundup(cqcount, MAX_CMP_QUEUES_PER_QS); nic->sqs_count = roundup(cqcount, MAX_CMP_QUEUES_PER_QS);
...@@ -741,12 +758,10 @@ static int nicvf_set_channels(struct net_device *dev, ...@@ -741,12 +758,10 @@ static int nicvf_set_channels(struct net_device *dev,
nic->sqs_count = 0; nic->sqs_count = 0;
} }
nic->qs->rq_cnt = min_t(u32, channel->rx_count, MAX_RCV_QUEUES_PER_QS); nic->qs->rq_cnt = min_t(u8, nic->rx_queues, MAX_RCV_QUEUES_PER_QS);
nic->qs->sq_cnt = min_t(u32, channel->tx_count, MAX_SND_QUEUES_PER_QS); nic->qs->sq_cnt = min_t(u8, txq_count, MAX_SND_QUEUES_PER_QS);
nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt); nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt);
nic->rx_queues = channel->rx_count;
nic->tx_queues = channel->tx_count;
err = nicvf_set_real_num_queues(dev, nic->tx_queues, nic->rx_queues); err = nicvf_set_real_num_queues(dev, nic->tx_queues, nic->rx_queues);
if (err) if (err)
return err; return err;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define NICVF_QUEUES_H #define NICVF_QUEUES_H
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/iommu.h>
#include "q_struct.h" #include "q_struct.h"
#define MAX_QUEUE_SET 128 #define MAX_QUEUE_SET 128
...@@ -213,6 +214,12 @@ struct q_desc_mem { ...@@ -213,6 +214,12 @@ struct q_desc_mem {
void *unalign_base; void *unalign_base;
}; };
struct pgcache {
struct page *page;
int ref_count;
u64 dma_addr;
};
struct rbdr { struct rbdr {
bool enable; bool enable;
u32 dma_size; u32 dma_size;
...@@ -222,6 +229,13 @@ struct rbdr { ...@@ -222,6 +229,13 @@ struct rbdr {
u32 head; u32 head;
u32 tail; u32 tail;
struct q_desc_mem dmem; struct q_desc_mem dmem;
bool is_xdp;
/* For page recycling */
int pgidx;
int pgcnt;
int pgalloc;
struct pgcache *pgcache;
} ____cacheline_aligned_in_smp; } ____cacheline_aligned_in_smp;
struct rcv_queue { struct rcv_queue {
...@@ -258,6 +272,10 @@ struct snd_queue { ...@@ -258,6 +272,10 @@ struct snd_queue {
u32 tail; u32 tail;
u64 *skbuff; u64 *skbuff;
void *desc; void *desc;
u64 *xdp_page;
u16 xdp_desc_cnt;
u16 xdp_free_cnt;
bool is_xdp;
#define TSO_HEADER_SIZE 128 #define TSO_HEADER_SIZE 128
/* For TSO segment's header */ /* For TSO segment's header */
...@@ -301,6 +319,14 @@ struct queue_set { ...@@ -301,6 +319,14 @@ struct queue_set {
#define CQ_ERR_MASK (CQ_WR_FULL | CQ_WR_DISABLE | CQ_WR_FAULT) #define CQ_ERR_MASK (CQ_WR_FULL | CQ_WR_DISABLE | CQ_WR_FAULT)
static inline u64 nicvf_iova_to_phys(struct nicvf *nic, dma_addr_t dma_addr)
{
/* Translation is installed only when IOMMU is present */
if (nic->iommu_domain)
return iommu_iova_to_phys(nic->iommu_domain, dma_addr);
return dma_addr;
}
void nicvf_unmap_sndq_buffers(struct nicvf *nic, struct snd_queue *sq, void nicvf_unmap_sndq_buffers(struct nicvf *nic, struct snd_queue *sq,
int hdr_sqe, u8 subdesc_cnt); int hdr_sqe, u8 subdesc_cnt);
void nicvf_config_vlan_stripping(struct nicvf *nic, void nicvf_config_vlan_stripping(struct nicvf *nic,
...@@ -318,8 +344,12 @@ void nicvf_sq_free_used_descs(struct net_device *netdev, ...@@ -318,8 +344,12 @@ void nicvf_sq_free_used_descs(struct net_device *netdev,
struct snd_queue *sq, int qidx); struct snd_queue *sq, int qidx);
int nicvf_sq_append_skb(struct nicvf *nic, struct snd_queue *sq, int nicvf_sq_append_skb(struct nicvf *nic, struct snd_queue *sq,
struct sk_buff *skb, u8 sq_num); struct sk_buff *skb, u8 sq_num);
int nicvf_xdp_sq_append_pkt(struct nicvf *nic, struct snd_queue *sq,
u64 bufaddr, u64 dma_addr, u16 len);
void nicvf_xdp_sq_doorbell(struct nicvf *nic, struct snd_queue *sq, int sq_num);
struct sk_buff *nicvf_get_rcv_skb(struct nicvf *nic, struct cqe_rx_t *cqe_rx); struct sk_buff *nicvf_get_rcv_skb(struct nicvf *nic,
struct cqe_rx_t *cqe_rx, bool xdp);
void nicvf_rbdr_task(unsigned long data); void nicvf_rbdr_task(unsigned long data);
void nicvf_rbdr_work(struct work_struct *work); void nicvf_rbdr_work(struct work_struct *work);
......
...@@ -359,15 +359,7 @@ union cq_desc_t { ...@@ -359,15 +359,7 @@ union cq_desc_t {
}; };
struct rbdr_entry_t { struct rbdr_entry_t {
#if defined(__BIG_ENDIAN_BITFIELD) u64 buf_addr;
u64 rsvd0:15;
u64 buf_addr:42;
u64 cache_align:7;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
u64 cache_align:7;
u64 buf_addr:42;
u64 rsvd0:15;
#endif
}; };
/* TCP reassembly context */ /* TCP reassembly context */
......
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