Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Shrikrishna Khare and committed by
David S. Miller
4edef40e 50a5ce3e

+253 -1
+32 -1
drivers/net/vmxnet3/vmxnet3_defs.h
··· 80 80 VMXNET3_CMD_LOAD_PLUGIN, 81 81 VMXNET3_CMD_RESERVED2, 82 82 VMXNET3_CMD_RESERVED3, 83 + VMXNET3_CMD_SET_COALESCE, 83 84 84 85 VMXNET3_CMD_FIRST_GET = 0xF00D0000, 85 86 VMXNET3_CMD_GET_QUEUE_STATUS = VMXNET3_CMD_FIRST_GET, ··· 93 92 VMXNET3_CMD_GET_DEV_EXTRA_INFO, 94 93 VMXNET3_CMD_GET_CONF_INTR, 95 94 VMXNET3_CMD_GET_RESERVED1, 96 - VMXNET3_CMD_GET_TXDATA_DESC_SIZE 95 + VMXNET3_CMD_GET_TXDATA_DESC_SIZE, 96 + VMXNET3_CMD_GET_COALESCE, 97 97 }; 98 98 99 99 /* ··· 637 635 638 636 struct Vmxnet3_SetPolling { 639 637 u8 enablePolling; 638 + }; 639 + 640 + #define VMXNET3_COAL_STATIC_MAX_DEPTH 128 641 + #define VMXNET3_COAL_RBC_MIN_RATE 100 642 + #define VMXNET3_COAL_RBC_MAX_RATE 100000 643 + 644 + enum Vmxnet3_CoalesceMode { 645 + VMXNET3_COALESCE_DISABLED = 0, 646 + VMXNET3_COALESCE_ADAPT = 1, 647 + VMXNET3_COALESCE_STATIC = 2, 648 + VMXNET3_COALESCE_RBC = 3 649 + }; 650 + 651 + struct Vmxnet3_CoalesceRbc { 652 + u32 rbc_rate; 653 + }; 654 + 655 + struct Vmxnet3_CoalesceStatic { 656 + u32 tx_depth; 657 + u32 tx_comp_depth; 658 + u32 rx_depth; 659 + }; 660 + 661 + struct Vmxnet3_CoalesceScheme { 662 + enum Vmxnet3_CoalesceMode coalMode; 663 + union { 664 + struct Vmxnet3_CoalesceRbc coalRbc; 665 + struct Vmxnet3_CoalesceStatic coalStatic; 666 + } coalPara; 640 667 }; 641 668 642 669 /* If the command data <= 16 bytes, use the shared memory directly.
+54
drivers/net/vmxnet3/vmxnet3_drv.c
··· 2491 2491 /* the rest are already zeroed */ 2492 2492 } 2493 2493 2494 + static void 2495 + vmxnet3_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 2495 2521 int 2496 2522 vmxnet3_activate_dev(struct vmxnet3_adapter *adapter) ··· 2565 2539 err = -EINVAL; 2566 2540 goto activate_err; 2567 2541 } 2542 + 2543 + vmxnet3_init_coalesce(adapter); 2568 2544 2569 2545 for (i = 0; i < adapter->num_rx_queues; i++) { 2570 2546 VMXNET3_WRITE_BAR0_REG(adapter, ··· 3373 3345 goto err_ver; 3374 3346 } 3375 3347 3348 + if (VMXNET3_VERSION_GE_3(adapter)) { 3349 + adapter->coal_conf = 3350 + dma_alloc_coherent(&adapter->pdev->dev, 3351 + sizeof(struct Vmxnet3_CoalesceScheme) 3352 + , 3353 + &adapter->coal_conf_pa, 3354 + GFP_KERNEL); 3355 + if (!adapter->coal_conf) { 3356 + err = -ENOMEM; 3357 + goto err_ver; 3358 + } 3359 + memset(adapter->coal_conf, 0, sizeof(*adapter->coal_conf)); 3360 + adapter->coal_conf->coalMode = VMXNET3_COALESCE_DISABLED; 3361 + adapter->default_coal_mode = true; 3362 + } 3363 + 3376 3364 SET_NETDEV_DEV(netdev, &pdev->dev); 3377 3365 vmxnet3_declare_features(adapter, dma64); 3378 3366 ··· 3451 3407 return 0; 3452 3408 3453 3409 err_register: 3410 + if (VMXNET3_VERSION_GE_3(adapter)) { 3411 + dma_free_coherent(&adapter->pdev->dev, 3412 + sizeof(struct Vmxnet3_CoalesceScheme), 3413 + adapter->coal_conf, adapter->coal_conf_pa); 3414 + } 3454 3415 vmxnet3_free_intr_resources(adapter); 3455 3416 err_ver: 3456 3417 vmxnet3_free_pci_resources(adapter); ··· 3506 3457 3507 3458 vmxnet3_free_intr_resources(adapter); 3508 3459 vmxnet3_free_pci_resources(adapter); 3460 + if (VMXNET3_VERSION_GE_3(adapter)) { 3461 + dma_free_coherent(&adapter->pdev->dev, 3462 + sizeof(struct Vmxnet3_CoalesceScheme), 3463 + adapter->coal_conf, adapter->coal_conf_pa); 3464 + } 3509 3465 #ifdef VMXNET3_RSS 3510 3466 dma_free_coherent(&adapter->pdev->dev, sizeof(struct UPT1_RSSConf), 3511 3467 adapter->rss_conf, adapter->rss_conf_pa);
+158
drivers/net/vmxnet3/vmxnet3_ethtool.c
··· 725 725 } 726 726 #endif 727 727 728 + static int 729 + vmxnet3_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 + 763 + static int 764 + vmxnet3_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 + 868 + done: 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 + 728 884 static const struct ethtool_ops vmxnet3_ethtool_ops = { 729 885 .get_settings = vmxnet3_get_settings, 730 886 .get_drvinfo = vmxnet3_get_drvinfo, ··· 889 733 .get_wol = vmxnet3_get_wol, 890 734 .set_wol = vmxnet3_set_wol, 891 735 .get_link = ethtool_op_get_link, 736 + .get_coalesce = vmxnet3_get_coalesce, 737 + .set_coalesce = vmxnet3_set_coalesce, 892 738 .get_strings = vmxnet3_get_strings, 893 739 .get_sset_count = vmxnet3_get_sset_count, 894 740 .get_ethtool_stats = vmxnet3_get_ethtool_stats,
+9
drivers/net/vmxnet3/vmxnet3_int.h
··· 358 358 int rx_buf_per_pkt; /* only apply to the 1st ring */ 359 359 dma_addr_t shared_pa; 360 360 dma_addr_t queue_desc_pa; 361 + dma_addr_t coal_conf_pa; 361 362 362 363 /* Wake-on-LAN */ 363 364 u32 wol; ··· 384 383 unsigned long state; /* VMXNET3_STATE_BIT_xxx */ 385 384 386 385 int share_intr; 386 + 387 + struct Vmxnet3_CoalesceScheme *coal_conf; 388 + bool default_coal_mode; 387 389 388 390 dma_addr_t adapter_pa; 389 391 dma_addr_t pm_conf_pa; ··· 432 428 #define VMXNET3_RX_DATA_RING(adapter, rqID) \ 433 429 (rqID >= 2 * adapter->num_rx_queues && \ 434 430 rqID < 3 * adapter->num_rx_queues) \ 431 + 432 + #define VMXNET3_COAL_STATIC_DEFAULT_DEPTH 64 433 + 434 + #define VMXNET3_COAL_RBC_RATE(usecs) (1000000 / usecs) 435 + #define VMXNET3_COAL_RBC_USECS(rbc_rate) (1000000 / rbc_rate) 435 436 436 437 int 437 438 vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter);