aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-05-02 15:41:23 -0400
committerDavid S. Miller <davem@davemloft.net>2017-05-02 15:41:23 -0400
commitb0e92279d3ec3656152c4dfa1c8b28fa40ca66d7 (patch)
tree5a75ad322f5011b324bf620aa0d69ae06caa90fd
parentee0d8d8482345ff97a75a7d747efc309f13b0d80 (diff)
parent773225388dae15e72790d6f573e2e70e96292b6b (diff)
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: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic.h10
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c29
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_main.c313
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_queues.c387
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_queues.h32
-rw-r--r--drivers/net/ethernet/cavium/thunder/q_struct.h10
6 files changed, 657 insertions, 124 deletions
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index 6fb44218bf55..4a02e618e318 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -252,12 +252,14 @@ struct nicvf_drv_stats {
252 u64 tx_csum_overflow; 252 u64 tx_csum_overflow;
253 253
254 /* driver debug stats */ 254 /* driver debug stats */
255 u64 rcv_buffer_alloc_failures;
256 u64 tx_tso; 255 u64 tx_tso;
257 u64 tx_timeout; 256 u64 tx_timeout;
258 u64 txq_stop; 257 u64 txq_stop;
259 u64 txq_wake; 258 u64 txq_wake;
260 259
260 u64 rcv_buffer_alloc_failures;
261 u64 page_alloc;
262
261 struct u64_stats_sync syncp; 263 struct u64_stats_sync syncp;
262}; 264};
263 265
@@ -266,9 +268,9 @@ struct nicvf {
266 struct net_device *netdev; 268 struct net_device *netdev;
267 struct pci_dev *pdev; 269 struct pci_dev *pdev;
268 void __iomem *reg_base; 270 void __iomem *reg_base;
271 struct bpf_prog *xdp_prog;
269#define MAX_QUEUES_PER_QSET 8 272#define MAX_QUEUES_PER_QSET 8
270 struct queue_set *qs; 273 struct queue_set *qs;
271 struct nicvf_cq_poll *napi[8];
272 void *iommu_domain; 274 void *iommu_domain;
273 u8 vf_id; 275 u8 vf_id;
274 u8 sqs_id; 276 u8 sqs_id;
@@ -294,6 +296,7 @@ struct nicvf {
294 /* Queue count */ 296 /* Queue count */
295 u8 rx_queues; 297 u8 rx_queues;
296 u8 tx_queues; 298 u8 tx_queues;
299 u8 xdp_tx_queues;
297 u8 max_queues; 300 u8 max_queues;
298 301
299 u8 node; 302 u8 node;
@@ -318,6 +321,9 @@ struct nicvf {
318 struct nicvf_drv_stats __percpu *drv_stats; 321 struct nicvf_drv_stats __percpu *drv_stats;
319 struct bgx_stats bgx_stats; 322 struct bgx_stats bgx_stats;
320 323
324 /* Napi */
325 struct nicvf_cq_poll *napi[8];
326
321 /* MSI-X */ 327 /* MSI-X */
322 u8 num_vec; 328 u8 num_vec;
323 char irq_name[NIC_VF_MSIX_VECTORS][IFNAMSIZ + 15]; 329 char irq_name[NIC_VF_MSIX_VECTORS][IFNAMSIZ + 15];
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
index 02a986cdbb39..b9ece9cbf98b 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
@@ -100,11 +100,12 @@ static const struct nicvf_stat nicvf_drv_stats[] = {
100 NICVF_DRV_STAT(tx_csum_overlap), 100 NICVF_DRV_STAT(tx_csum_overlap),
101 NICVF_DRV_STAT(tx_csum_overflow), 101 NICVF_DRV_STAT(tx_csum_overflow),
102 102
103 NICVF_DRV_STAT(rcv_buffer_alloc_failures),
104 NICVF_DRV_STAT(tx_tso), 103 NICVF_DRV_STAT(tx_tso),
105 NICVF_DRV_STAT(tx_timeout), 104 NICVF_DRV_STAT(tx_timeout),
106 NICVF_DRV_STAT(txq_stop), 105 NICVF_DRV_STAT(txq_stop),
107 NICVF_DRV_STAT(txq_wake), 106 NICVF_DRV_STAT(txq_wake),
107 NICVF_DRV_STAT(rcv_buffer_alloc_failures),
108 NICVF_DRV_STAT(page_alloc),
108}; 109};
109 110
110static const struct nicvf_stat nicvf_queue_stats[] = { 111static const struct nicvf_stat nicvf_queue_stats[] = {
@@ -720,7 +721,7 @@ static int nicvf_set_channels(struct net_device *dev,
720 struct nicvf *nic = netdev_priv(dev); 721 struct nicvf *nic = netdev_priv(dev);
721 int err = 0; 722 int err = 0;
722 bool if_up = netif_running(dev); 723 bool if_up = netif_running(dev);
723 int cqcount; 724 u8 cqcount, txq_count;
724 725
725 if (!channel->rx_count || !channel->tx_count) 726 if (!channel->rx_count || !channel->tx_count)
726 return -EINVAL; 727 return -EINVAL;
@@ -729,10 +730,26 @@ static int nicvf_set_channels(struct net_device *dev,
729 if (channel->tx_count > nic->max_queues) 730 if (channel->tx_count > nic->max_queues)
730 return -EINVAL; 731 return -EINVAL;
731 732
733 if (nic->xdp_prog &&
734 ((channel->tx_count + channel->rx_count) > nic->max_queues)) {
735 netdev_err(nic->netdev,
736 "XDP mode, RXQs + TXQs > Max %d\n",
737 nic->max_queues);
738 return -EINVAL;
739 }
740
732 if (if_up) 741 if (if_up)
733 nicvf_stop(dev); 742 nicvf_stop(dev);
734 743
735 cqcount = max(channel->rx_count, channel->tx_count); 744 nic->rx_queues = channel->rx_count;
745 nic->tx_queues = channel->tx_count;
746 if (!nic->xdp_prog)
747 nic->xdp_tx_queues = 0;
748 else
749 nic->xdp_tx_queues = channel->rx_count;
750
751 txq_count = nic->xdp_tx_queues + nic->tx_queues;
752 cqcount = max(nic->rx_queues, txq_count);
736 753
737 if (cqcount > MAX_CMP_QUEUES_PER_QS) { 754 if (cqcount > MAX_CMP_QUEUES_PER_QS) {
738 nic->sqs_count = roundup(cqcount, MAX_CMP_QUEUES_PER_QS); 755 nic->sqs_count = roundup(cqcount, MAX_CMP_QUEUES_PER_QS);
@@ -741,12 +758,10 @@ static int nicvf_set_channels(struct net_device *dev,
741 nic->sqs_count = 0; 758 nic->sqs_count = 0;
742 } 759 }
743 760
744 nic->qs->rq_cnt = min_t(u32, channel->rx_count, MAX_RCV_QUEUES_PER_QS); 761 nic->qs->rq_cnt = min_t(u8, nic->rx_queues, MAX_RCV_QUEUES_PER_QS);
745 nic->qs->sq_cnt = min_t(u32, channel->tx_count, MAX_SND_QUEUES_PER_QS); 762 nic->qs->sq_cnt = min_t(u8, txq_count, MAX_SND_QUEUES_PER_QS);
746 nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt); 763 nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt);
747 764
748 nic->rx_queues = channel->rx_count;
749 nic->tx_queues = channel->tx_count;
750 err = nicvf_set_real_num_queues(dev, nic->tx_queues, nic->rx_queues); 765 err = nicvf_set_real_num_queues(dev, nic->tx_queues, nic->rx_queues);
751 if (err) 766 if (err)
752 return err; 767 return err;
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 81a2fcb3cb1b..d6477af88085 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -17,6 +17,9 @@
17#include <linux/prefetch.h> 17#include <linux/prefetch.h>
18#include <linux/irq.h> 18#include <linux/irq.h>
19#include <linux/iommu.h> 19#include <linux/iommu.h>
20#include <linux/bpf.h>
21#include <linux/bpf_trace.h>
22#include <linux/filter.h>
20 23
21#include "nic_reg.h" 24#include "nic_reg.h"
22#include "nic.h" 25#include "nic.h"
@@ -397,8 +400,10 @@ static void nicvf_request_sqs(struct nicvf *nic)
397 400
398 if (nic->rx_queues > MAX_RCV_QUEUES_PER_QS) 401 if (nic->rx_queues > MAX_RCV_QUEUES_PER_QS)
399 rx_queues = nic->rx_queues - MAX_RCV_QUEUES_PER_QS; 402 rx_queues = nic->rx_queues - MAX_RCV_QUEUES_PER_QS;
400 if (nic->tx_queues > MAX_SND_QUEUES_PER_QS) 403
401 tx_queues = nic->tx_queues - MAX_SND_QUEUES_PER_QS; 404 tx_queues = nic->tx_queues + nic->xdp_tx_queues;
405 if (tx_queues > MAX_SND_QUEUES_PER_QS)
406 tx_queues = tx_queues - MAX_SND_QUEUES_PER_QS;
402 407
403 /* Set no of Rx/Tx queues in each of the SQsets */ 408 /* Set no of Rx/Tx queues in each of the SQsets */
404 for (sqs = 0; sqs < nic->sqs_count; sqs++) { 409 for (sqs = 0; sqs < nic->sqs_count; sqs++) {
@@ -496,12 +501,99 @@ static int nicvf_init_resources(struct nicvf *nic)
496 return 0; 501 return 0;
497} 502}
498 503
504static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog,
505