diff options
| author | David S. Miller <davem@davemloft.net> | 2017-05-02 15:41:23 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-05-02 15:41:23 -0400 |
| commit | b0e92279d3ec3656152c4dfa1c8b28fa40ca66d7 (patch) | |
| tree | 5a75ad322f5011b324bf620aa0d69ae06caa90fd | |
| parent | ee0d8d8482345ff97a75a7d747efc309f13b0d80 (diff) | |
| parent | 773225388dae15e72790d6f573e2e70e96292b6b (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.h | 10 | ||||
| -rw-r--r-- | drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c | 29 | ||||
| -rw-r--r-- | drivers/net/ethernet/cavium/thunder/nicvf_main.c | 313 | ||||
| -rw-r--r-- | drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 387 | ||||
| -rw-r--r-- | drivers/net/ethernet/cavium/thunder/nicvf_queues.h | 32 | ||||
| -rw-r--r-- | drivers/net/ethernet/cavium/thunder/q_struct.h | 10 |
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 | ||
| 110 | static const struct nicvf_stat nicvf_queue_stats[] = { | 111 | static 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 | ||
| 504 | static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog, | ||
| 505 | |||
