aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShrikrishna Khare <skhare@vmware.com>2016-06-16 13:51:57 -0400
committerDavid S. Miller <davem@davemloft.net>2016-06-17 01:37:04 -0400
commit4edef40ef5f8d09a0b1ded4d1d9b0e988cd98e97 (patch)
tree5b2ebb62c8e7c7ec7fcf8ce514ed340d9365ef74
parent50a5ce3e7116a70edb7a1d1d209e3bc537752427 (diff)
vmxnet3: add support for get_coalesce, set_coalesce ethtool operations
The emulation supports a variety of coalescing modes viz. disabled (no coalescing), adaptive, static (number of packets to batch before raising an interrupt), rate based (number of interrupts per second). This patch implements get_coalesce and set_coalesce methods to allow querying and configuring different coalescing modes. Signed-off-by: Keyong Sun <sunk@vmware.com> Signed-off-by: Manoj Tammali <tammalim@vmware.com> Signed-off-by: Shrikrishna Khare <skhare@vmware.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/vmxnet3/vmxnet3_defs.h33
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c54
-rw-r--r--drivers/net/vmxnet3/vmxnet3_ethtool.c158
-rw-r--r--drivers/net/vmxnet3/vmxnet3_int.h9
4 files changed, 253 insertions, 1 deletions
diff --git a/drivers/net/vmxnet3/vmxnet3_defs.h b/drivers/net/vmxnet3/vmxnet3_defs.h
index f3b31c2d8abc..274e145ab72a 100644
--- a/drivers/net/vmxnet3/vmxnet3_defs.h
+++ b/drivers/net/vmxnet3/vmxnet3_defs.h
@@ -80,6 +80,7 @@ enum {
80 VMXNET3_CMD_LOAD_PLUGIN, 80 VMXNET3_CMD_LOAD_PLUGIN,
81 VMXNET3_CMD_RESERVED2, 81 VMXNET3_CMD_RESERVED2,
82 VMXNET3_CMD_RESERVED3, 82 VMXNET3_CMD_RESERVED3,
83 VMXNET3_CMD_SET_COALESCE,
83 84
84 VMXNET3_CMD_FIRST_GET = 0xF00D0000, 85 VMXNET3_CMD_FIRST_GET = 0xF00D0000,
85 VMXNET3_CMD_GET_QUEUE_STATUS = VMXNET3_CMD_FIRST_GET, 86 VMXNET3_CMD_GET_QUEUE_STATUS = VMXNET3_CMD_FIRST_GET,
@@ -92,7 +93,8 @@ enum {
92 VMXNET3_CMD_GET_DEV_EXTRA_INFO, 93 VMXNET3_CMD_GET_DEV_EXTRA_INFO,
93 VMXNET3_CMD_GET_CONF_INTR, 94 VMXNET3_CMD_GET_CONF_INTR,
94 VMXNET3_CMD_GET_RESERVED1, 95 VMXNET3_CMD_GET_RESERVED1,
95 VMXNET3_CMD_GET_TXDATA_DESC_SIZE 96 VMXNET3_CMD_GET_TXDATA_DESC_SIZE,
97 VMXNET3_CMD_GET_COALESCE,
96}; 98};
97 99
98/* 100/*
@@ -637,6 +639,35 @@ struct Vmxnet3_SetPolling {
637 u8 enablePolling; 639 u8 enablePolling;
638}; 640};
639 641
642#define VMXNET3_COAL_STATIC_MAX_DEPTH 128
643#define VMXNET3_COAL_RBC_MIN_RATE 100
644#define VMXNET3_COAL_RBC_MAX_RATE 100000
645
646enum Vmxnet3_CoalesceMode {
647 VMXNET3_COALESCE_DISABLED = 0,
648 VMXNET3_COALESCE_ADAPT = 1,
649 VMXNET3_COALESCE_STATIC = 2,
650 VMXNET3_COALESCE_RBC = 3
651};
652
653struct Vmxnet3_CoalesceRbc {
654 u32 rbc_rate;
655};
656
657struct Vmxnet3_CoalesceStatic {
658 u32 tx_depth;
659 u32 tx_comp_depth;
660 u32 rx_depth;
661};
662
663struct Vmxnet3_CoalesceScheme {
664 enum Vmxnet3_CoalesceMode coalMode;
665 union {
666 struct Vmxnet3_CoalesceRbc coalRbc;
667 struct Vmxnet3_CoalesceStatic coalStatic;
668 } coalPara;
669};
670
640/* If the command data <= 16 bytes, use the shared memory directly. 671/* If the command data <= 16 bytes, use the shared memory directly.
641 * otherwise, use variable length configuration descriptor. 672 * otherwise, use variable length configuration descriptor.
642 */ 673 */
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 6449d2e6d94f..d0bcc1d97e80 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -2491,6 +2491,32 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter)
2491 /* the rest are already zeroed */ 2491 /* the rest are already zeroed */
2492} 2492}
2493 2493
2494static void
2495vmxnet3_init_coalesce(struct vmxnet3_adapter *adapter)
2496{
2497 struct Vmxnet3_DriverShared *shared = adapter->shared;
2498 union Vmxnet3_CmdInfo *cmdInfo = &shared->cu.cmdInfo;
2499 unsigned long flags;
2500
2501 if (!VMXNET3_VERSION_GE_3(adapter))
2502 return;
2503
2504 spin_lock_irqsave(&adapter->cmd_lock, flags);
2505 cmdInfo->varConf.confVer = 1;
2506 cmdInfo->varConf.confLen =
2507 cpu_to_le32(sizeof(*adapter->coal_conf));
2508 cmdInfo->varConf.confPA = cpu_to_le64(adapter->coal_conf_pa);
2509
2510 if (adapter->default_coal_mode) {
2511 VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
2512 VMXNET3_CMD_GET_COALESCE);
2513 } else {
2514 VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
2515 VMXNET3_CMD_SET_COALESCE);
2516 }
2517
2518 spin_unlock_irqrestore(&adapter->cmd_lock, flags);
2519}
2494 2520
2495int 2521int
2496vmxnet3_activate_dev(struct vmxnet3_adapter *adapter) 2522vmxnet3_activate_dev(struct vmxnet3_adapter *adapter)
@@ -2540,6 +2566,8 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter)
2540 goto activate_err; 2566 goto activate_err;
2541 } 2567 }
2542 2568
2569 vmxnet3_init_coalesce(adapter);
2570
2543 for (i = 0; i < adapter->num_rx_queues; i++) { 2571 for (i = 0; i < adapter->num_rx_queues; i++) {
2544 VMXNET3_WRITE_BAR0_REG(adapter, 2572 VMXNET3_WRITE_BAR0_REG(adapter,
2545 VMXNET3_REG_RXPROD + i * VMXNET3_REG_ALIGN, 2573 VMXNET3_REG_RXPROD + i * VMXNET3_REG_ALIGN,
@@ -3345,6 +3373,22 @@ vmxnet3_probe_device(struct pci_dev *pdev,
3345 goto err_ver; 3373 goto err_ver;
3346 } 3374 }
3347 3375
3376 if (VMXNET3_VERSION_GE_3(adapter)) {
3377 adapter->coal_conf =
3378 dma_alloc_coherent(&adapter->pdev->dev,
3379 sizeof(struct Vmxnet3_CoalesceScheme)
3380 ,
3381 &adapter->coal_conf_pa,
3382 GFP_KERNEL);
3383 if (!adapter->coal_conf) {
3384 err = -ENOMEM;
3385 goto err_ver;
3386 }
3387 memset(adapter->coal_conf, 0, sizeof(*adapter->coal_conf));
3388 adapter->coal_conf->coalMode = VMXNET3_COALESCE_DISABLED;
3389 adapter->default_coal_mode = true;
3390 }
3391
3348 SET_NETDEV_DEV(netdev, &pdev->dev); 3392 SET_NETDEV_DEV(netdev, &pdev->dev);
3349 vmxnet3_declare_features(adapter, dma64); 3393 vmxnet3_declare_features(adapter, dma64);
3350 3394
@@ -3407,6 +3451,11 @@ vmxnet3_probe_device(struct pci_dev *pdev,
3407 return 0; 3451 return 0;
3408 3452
3409err_register: 3453err_register:
3454 if (VMXNET3_VERSION_GE_3(adapter)) {
3455 dma_free_coherent(&adapter->pdev->dev,
3456 sizeof(struct Vmxnet3_CoalesceScheme),
3457 adapter->coal_conf, adapter->coal_conf_pa);
3458 }
3410 vmxnet3_free_intr_resources(adapter); 3459 vmxnet3_free_intr_resources(adapter);
3411err_ver: 3460err_ver:
3412 vmxnet3_free_pci_resources(adapter); 3461 vmxnet3_free_pci_resources(adapter);
@@ -3457,6 +3506,11 @@ vmxnet3_remove_device(struct pci_dev *pdev)
3457 3506
3458 vmxnet3_free_intr_resources(adapter); 3507 vmxnet3_free_intr_resources(adapter);
3459 vmxnet3_free_pci_resources(adapter); 3508 vmxnet3_free_pci_resources(adapter);
3509 if (VMXNET3_VERSION_GE_3(adapter)) {
3510 dma_free_coherent(&adapter->pdev->dev,
3511 sizeof(struct Vmxnet3_CoalesceScheme),
3512 adapter->coal_conf, adapter->coal_conf_pa);
3513 }
3460#ifdef VMXNET3_RSS 3514#ifdef VMXNET3_RSS
3461 dma_free_coherent(&adapter->pdev->dev, sizeof(struct UPT1_RSSConf), 3515 dma_free_coherent(&adapter->pdev->dev, sizeof(struct UPT1_RSSConf),
3462 adapter->rss_conf, adapter->rss_conf_pa); 3516 adapter->rss_conf, adapter->rss_conf_pa);
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index 38f7c7975e1f..aabc6ef366b4 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -725,6 +725,162 @@ vmxnet3_set_rss(struct net_device *netdev, const u32 *p, const u8 *key,
725} 725}
726#endif 726#endif
727 727
728static int
729vmxnet3_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec)
730{
731 struct vmxnet3_adapter *adapter = netdev_priv(netdev);
732
733 if (!VMXNET3_VERSION_GE_3(adapter))
734 return -EOPNOTSUPP;
735
736 switch (adapter->coal_conf->coalMode) {
737 case VMXNET3_COALESCE_DISABLED:
738 /* struct ethtool_coalesce is already initialized to 0 */
739 break;
740 case VMXNET3_COALESCE_ADAPT:
741 ec->use_adaptive_rx_coalesce = true;
742 break;
743 case VMXNET3_COALESCE_STATIC:
744 ec->tx_max_coalesced_frames =
745 adapter->coal_conf->coalPara.coalStatic.tx_comp_depth;
746 ec->rx_max_coalesced_frames =
747 adapter->coal_conf->coalPara.coalStatic.rx_depth;
748 break;
749 case VMXNET3_COALESCE_RBC: {
750 u32 rbc_rate;
751
752 rbc_rate = adapter->coal_conf->coalPara.coalRbc.rbc_rate;
753 ec->rx_coalesce_usecs = VMXNET3_COAL_RBC_USECS(rbc_rate);
754 }
755 break;
756 default:
757 return -EOPNOTSUPP;
758 }
759
760 return 0;
761}
762
763static int
764vmxnet3_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec)
765{
766 struct vmxnet3_adapter *adapter = netdev_priv(netdev);
767 struct Vmxnet3_DriverShared *shared = adapter->shared;
768 union Vmxnet3_CmdInfo *cmdInfo = &shared->cu.cmdInfo;
769 unsigned long flags;
770
771 if (!VMXNET3_VERSION_GE_3(adapter))
772 return -EOPNOTSUPP;
773
774 if (ec->rx_coalesce_usecs_irq ||
775 ec->rx_max_coalesced_frames_irq ||
776 ec->tx_coalesce_usecs ||
777 ec->tx_coalesce_usecs_irq ||
778 ec->tx_max_coalesced_frames_irq ||
779 ec->stats_block_coalesce_usecs ||
780 ec->use_adaptive_tx_coalesce ||
781 ec->pkt_rate_low ||
782 ec->rx_coalesce_usecs_low ||
783 ec->rx_max_coalesced_frames_low ||
784 ec->tx_coalesce_usecs_low ||
785 ec->tx_max_coalesced_frames_low ||
786 ec->pkt_rate_high ||
787 ec->rx_coalesce_usecs_high ||
788 ec->rx_max_coalesced_frames_high ||
789 ec->tx_coalesce_usecs_high ||
790 ec->tx_max_coalesced_frames_high ||
791 ec->rate_sample_interval) {
792 return -EINVAL;
793 }
794
795 if ((ec->rx_coalesce_usecs == 0) &&
796 (ec->use_adaptive_rx_coalesce == 0) &&
797 (ec->tx_max_coalesced_frames == 0) &&
798 (ec->rx_max_coalesced_frames == 0)) {
799 memset(adapter->coal_conf, 0, sizeof(*adapter->coal_conf));
800 adapter->coal_conf->coalMode = VMXNET3_COALESCE_DISABLED;
801 goto done;
802 }
803
804 if (ec->rx_coalesce_usecs != 0) {
805 u32 rbc_rate;
806
807 if ((ec->use_adaptive_rx_coalesce != 0) ||
808 (ec->tx_max_coalesced_frames != 0) ||
809 (ec->rx_max_coalesced_frames != 0)) {
810 return -EINVAL;
811 }
812
813 rbc_rate = VMXNET3_COAL_RBC_RATE(ec->rx_coalesce_usecs);
814 if (rbc_rate < VMXNET3_COAL_RBC_MIN_RATE ||
815 rbc_rate > VMXNET3_COAL_RBC_MAX_RATE) {
816 return -EINVAL;
817 }
818
819 memset(adapter->coal_conf, 0, sizeof(*adapter->coal_conf));
820 adapter->coal_conf->coalMode = VMXNET3_COALESCE_RBC;
821 adapter->coal_conf->coalPara.coalRbc.rbc_rate = rbc_rate;
822 goto done;
823 }
824
825 if (ec->use_adaptive_rx_coalesce != 0) {
826 if ((ec->rx_coalesce_usecs != 0) ||
827 (ec->tx_max_coalesced_frames != 0) ||
828 (ec->rx_max_coalesced_frames != 0)) {
829 return -EINVAL;
830 }
831 memset(adapter->coal_conf, 0, sizeof(*adapter->coal_conf));
832 adapter->coal_conf->coalMode = VMXNET3_COALESCE_ADAPT;
833 goto done;
834 }
835
836 if ((ec->tx_max_coalesced_frames != 0) ||
837 (ec->rx_max_coalesced_frames != 0)) {
838 if ((ec->rx_coalesce_usecs != 0) ||
839 (ec->use_adaptive_rx_coalesce != 0)) {
840 return -EINVAL;
841 }
842
843 if ((ec->tx_max_coalesced_frames >
844 VMXNET3_COAL_STATIC_MAX_DEPTH) ||
845 (ec->rx_max_coalesced_frames >
846 VMXNET3_COAL_STATIC_MAX_DEPTH)) {
847 return -EINVAL;
848 }
849
850 memset(adapter->coal_conf, 0, sizeof(*adapter->coal_conf));
851 adapter->coal_conf->coalMode = VMXNET3_COALESCE_STATIC;
852
853 adapter->coal_conf->coalPara.coalStatic.tx_comp_depth =
854 (ec->tx_max_coalesced_frames ?
855 ec->tx_max_coalesced_frames :
856 VMXNET3_COAL_STATIC_DEFAULT_DEPTH);
857
858 adapter->coal_conf->coalPara.coalStatic.rx_depth =
859 (ec->rx_max_coalesced_frames ?
860 ec->rx_max_coalesced_frames :
861 VMXNET3_COAL_STATIC_DEFAULT_DEPTH);
862
863 adapter->coal_conf->coalPara.coalStatic.tx_depth =
864 VMXNET3_COAL_STATIC_DEFAULT_DEPTH;
865 goto done;
866 }
867
868done:
869 adapter->default_coal_mode = false;
870 if (netif_running(netdev)) {
871 spin_lock_irqsave(&adapter->cmd_lock, flags);
872 cmdInfo->varConf.confVer = 1;
873 cmdInfo->varConf.confLen =
874 cpu_to_le32(sizeof(*adapter->coal_conf));
875 cmdInfo->varConf.confPA = cpu_to_le64(adapter->coal_conf_pa);
876 VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
877 VMXNET3_CMD_SET_COALESCE);
878 spin_unlock_irqrestore(&adapter->cmd_lock, flags);
879 }
880
881 return 0;
882}
883
728static const struct ethtool_ops vmxnet3_ethtool_ops = { 884static const struct ethtool_ops vmxnet3_ethtool_ops = {
729 .get_settings = vmxnet3_get_settings, 885 .get_settings = vmxnet3_get_settings,
730 .get_drvinfo = vmxnet3_get_drvinfo, 886 .get_drvinfo = vmxnet3_get_drvinfo,
@@ -733,6 +889,8 @@ static const struct ethtool_ops vmxnet3_ethtool_ops = {
733 .get_wol = vmxnet3_get_wol, 889 .get_wol = vmxnet3_get_wol,
734 .set_wol = vmxnet3_set_wol, 890 .set_wol = vmxnet3_set_wol,
735 .get_link = ethtool_op_get_link, 891 .get_link = ethtool_op_get_link,
892 .get_coalesce = vmxnet3_get_coalesce,
893 .set_coalesce = vmxnet3_set_coalesce,
736 .get_strings = vmxnet3_get_strings, 894 .get_strings = vmxnet3_get_strings,
737 .get_sset_count = vmxnet3_get_sset_count, 895 .get_sset_count = vmxnet3_get_sset_count,
738 .get_ethtool_stats = vmxnet3_get_ethtool_stats, 896 .get_ethtool_stats = vmxnet3_get_ethtool_stats,
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index c46bf09ade5a..63df4f2a743d 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -358,6 +358,7 @@ struct vmxnet3_adapter {
358 int rx_buf_per_pkt; /* only apply to the 1st ring */ 358 int rx_buf_per_pkt; /* only apply to the 1st ring */
359 dma_addr_t shared_pa; 359 dma_addr_t shared_pa;
360 dma_addr_t queue_desc_pa; 360 dma_addr_t queue_desc_pa;
361 dma_addr_t coal_conf_pa;
361 362
362 /* Wake-on-LAN */ 363 /* Wake-on-LAN */
363 u32 wol; 364 u32 wol;
@@ -384,6 +385,9 @@ struct vmxnet3_adapter {
384 385
385 int share_intr; 386 int share_intr;
386 387
388 struct Vmxnet3_CoalesceScheme *coal_conf;
389 bool default_coal_mode;
390
387 dma_addr_t adapter_pa; 391 dma_addr_t adapter_pa;
388 dma_addr_t pm_conf_pa; 392 dma_addr_t pm_conf_pa;
389 dma_addr_t rss_conf_pa; 393 dma_addr_t rss_conf_pa;
@@ -429,6 +433,11 @@ struct vmxnet3_adapter {
429 (rqID >= 2 * adapter->num_rx_queues && \ 433 (rqID >= 2 * adapter->num_rx_queues && \
430 rqID < 3 * adapter->num_rx_queues) \ 434 rqID < 3 * adapter->num_rx_queues) \
431 435
436#define VMXNET3_COAL_STATIC_DEFAULT_DEPTH 64
437
438#define VMXNET3_COAL_RBC_RATE(usecs) (1000000 / usecs)
439#define VMXNET3_COAL_RBC_USECS(rbc_rate) (1000000 / rbc_rate)
440
432int 441int
433vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter); 442vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter);
434 443