2020-05-28 02:09:22

by Ronak Doshi

[permalink] [raw]
Subject: [PATCH net-next 2/4] vmxnet3: add support to get/set rx flow hash

With vmxnet3 version 4, the emulation supports multiqueue(RSS) for
UDP and ESP traffic. A guest can enable/disable RSS for UDP/ESP over
IPv4/IPv6 by issuing commands introduced in this patch. ESP ipv6 is
not yet supported in this patch.

This patch implements get_rss_hash_opts and set_rss_hash_opts
methods to allow querying and configuring different Rx flow hash
configurations.

Signed-off-by: Ronak Doshi <[email protected]>
---
drivers/net/vmxnet3/vmxnet3_defs.h | 12 ++
drivers/net/vmxnet3/vmxnet3_drv.c | 39 ++++++
drivers/net/vmxnet3/vmxnet3_ethtool.c | 223 +++++++++++++++++++++++++++++++++-
drivers/net/vmxnet3/vmxnet3_int.h | 4 +
4 files changed, 276 insertions(+), 2 deletions(-)

diff --git a/drivers/net/vmxnet3/vmxnet3_defs.h b/drivers/net/vmxnet3/vmxnet3_defs.h
index c77274228a3e..aac97fac1186 100644
--- a/drivers/net/vmxnet3/vmxnet3_defs.h
+++ b/drivers/net/vmxnet3/vmxnet3_defs.h
@@ -82,6 +82,7 @@ enum {
VMXNET3_CMD_RESERVED3,
VMXNET3_CMD_SET_COALESCE,
VMXNET3_CMD_REGISTER_MEMREGS,
+ VMXNET3_CMD_SET_RSS_FIELDS,

VMXNET3_CMD_FIRST_GET = 0xF00D0000,
VMXNET3_CMD_GET_QUEUE_STATUS = VMXNET3_CMD_FIRST_GET,
@@ -96,6 +97,7 @@ enum {
VMXNET3_CMD_GET_RESERVED1,
VMXNET3_CMD_GET_TXDATA_DESC_SIZE,
VMXNET3_CMD_GET_COALESCE,
+ VMXNET3_CMD_GET_RSS_FIELDS,
};

/*
@@ -685,12 +687,22 @@ struct Vmxnet3_MemRegs {
struct Vmxnet3_MemoryRegion memRegs[1];
};

+enum Vmxnet3_RSSField {
+ VMXNET3_RSS_FIELDS_TCPIP4 = 0x0001,
+ VMXNET3_RSS_FIELDS_TCPIP6 = 0x0002,
+ VMXNET3_RSS_FIELDS_UDPIP4 = 0x0004,
+ VMXNET3_RSS_FIELDS_UDPIP6 = 0x0008,
+ VMXNET3_RSS_FIELDS_ESPIP4 = 0x0010,
+ VMXNET3_RSS_FIELDS_ESPIP6 = 0x0020,
+};
+
/* If the command data <= 16 bytes, use the shared memory directly.
* otherwise, use variable length configuration descriptor.
*/
union Vmxnet3_CmdInfo {
struct Vmxnet3_VariableLenConfDesc varConf;
struct Vmxnet3_SetPolling setPolling;
+ enum Vmxnet3_RSSField setRssFields;
__le64 data[2];
};

diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index ec2878f8c1f6..4ea7a40ada88 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -2554,6 +2554,39 @@ vmxnet3_init_coalesce(struct vmxnet3_adapter *adapter)
spin_unlock_irqrestore(&adapter->cmd_lock, flags);
}

+static void
+vmxnet3_init_rssfields(struct vmxnet3_adapter *adapter)
+{
+ struct Vmxnet3_DriverShared *shared = adapter->shared;
+ union Vmxnet3_CmdInfo *cmdInfo = &shared->cu.cmdInfo;
+ unsigned long flags;
+
+ if (!VMXNET3_VERSION_GE_4(adapter))
+ return;
+
+ spin_lock_irqsave(&adapter->cmd_lock, flags);
+
+ if (adapter->default_rss_fields) {
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_GET_RSS_FIELDS);
+ adapter->rss_fields =
+ VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+ } else {
+ cmdInfo->setRssFields = adapter->rss_fields;
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_SET_RSS_FIELDS);
+ /* Not all requested RSS may get applied, so get and
+ * cache what was actually applied.
+ */
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_GET_RSS_FIELDS);
+ adapter->rss_fields =
+ VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+ }
+
+ spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+}
+
int
vmxnet3_activate_dev(struct vmxnet3_adapter *adapter)
{
@@ -2603,6 +2636,7 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter)
}

vmxnet3_init_coalesce(adapter);
+ vmxnet3_init_rssfields(adapter);

for (i = 0; i < adapter->num_rx_queues; i++) {
VMXNET3_WRITE_BAR0_REG(adapter,
@@ -3430,6 +3464,11 @@ vmxnet3_probe_device(struct pci_dev *pdev,
adapter->default_coal_mode = true;
}

+ if (VMXNET3_VERSION_GE_4(adapter)) {
+ adapter->default_rss_fields = true;
+ adapter->rss_fields = VMXNET3_RSS_FIELDS_DEFAULT;
+ }
+
SET_NETDEV_DEV(netdev, &pdev->dev);
vmxnet3_declare_features(adapter, dma64);

diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index 1163eca7aba5..ceedf63020cb 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -665,18 +665,236 @@ vmxnet3_set_ringparam(struct net_device *netdev,
return err;
}

+static int
+vmxnet3_get_rss_hash_opts(struct vmxnet3_adapter *adapter,
+ struct ethtool_rxnfc *info)
+{
+ enum Vmxnet3_RSSField rss_fields;
+
+ if (netif_running(adapter->netdev)) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->cmd_lock, flags);
+
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_GET_RSS_FIELDS);
+ rss_fields = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+ spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+ } else {
+ rss_fields = adapter->rss_fields;
+ }
+
+ info->data = 0;
+
+ /* Report default options for RSS on vmxnet3 */
+ switch (info->flow_type) {
+ case TCP_V4_FLOW:
+ if (rss_fields & VMXNET3_RSS_FIELDS_TCPIP4)
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
+ RXH_IP_SRC | RXH_IP_DST;
+ break;
+ case UDP_V4_FLOW:
+ if (rss_fields & VMXNET3_RSS_FIELDS_UDPIP4)
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
+ RXH_IP_SRC | RXH_IP_DST;
+ break;
+ case AH_ESP_V4_FLOW:
+ case AH_V4_FLOW:
+ case ESP_V4_FLOW:
+ if (rss_fields & VMXNET3_RSS_FIELDS_ESPIP4)
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ case SCTP_V4_FLOW:
+ case IPV4_FLOW:
+ info->data |= RXH_IP_SRC | RXH_IP_DST;
+ break;
+ case TCP_V6_FLOW:
+ if (rss_fields & VMXNET3_RSS_FIELDS_TCPIP6)
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
+ RXH_IP_SRC | RXH_IP_DST;
+ break;
+ case UDP_V6_FLOW:
+ if (rss_fields & VMXNET3_RSS_FIELDS_UDPIP6)
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
+ RXH_IP_SRC | RXH_IP_DST;
+ break;
+ case AH_ESP_V6_FLOW:
+ case AH_V6_FLOW:
+ case ESP_V6_FLOW:
+ case SCTP_V6_FLOW:
+ case IPV6_FLOW:
+ info->data |= RXH_IP_SRC | RXH_IP_DST;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+vmxnet3_set_rss_hash_opt(struct net_device *netdev,
+ struct vmxnet3_adapter *adapter,
+ struct ethtool_rxnfc *nfc)
+{
+ enum Vmxnet3_RSSField rss_fields = adapter->rss_fields;
+
+ /* RSS does not support anything other than hashing
+ * to queues on src and dst IPs and ports
+ */
+ if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
+ RXH_L4_B_0_1 | RXH_L4_B_2_3))
+ return -EINVAL;
+
+ switch (nfc->flow_type) {
+ case TCP_V4_FLOW:
+ case TCP_V6_FLOW:
+ if (!(nfc->data & RXH_IP_SRC) ||
+ !(nfc->data & RXH_IP_DST) ||
+ !(nfc->data & RXH_L4_B_0_1) ||
+ !(nfc->data & RXH_L4_B_2_3))
+ return -EINVAL;
+ break;
+ case UDP_V4_FLOW:
+ if (!(nfc->data & RXH_IP_SRC) ||
+ !(nfc->data & RXH_IP_DST))
+ return -EINVAL;
+ switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
+ case 0:
+ rss_fields &= ~VMXNET3_RSS_FIELDS_UDPIP4;
+ break;
+ case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+ rss_fields |= VMXNET3_RSS_FIELDS_UDPIP4;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case UDP_V6_FLOW:
+ if (!(nfc->data & RXH_IP_SRC) ||
+ !(nfc->data & RXH_IP_DST))
+ return -EINVAL;
+ switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
+ case 0:
+ rss_fields &= ~VMXNET3_RSS_FIELDS_UDPIP6;
+ break;
+ case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+ rss_fields |= VMXNET3_RSS_FIELDS_UDPIP6;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case ESP_V4_FLOW:
+ case AH_V4_FLOW:
+ case AH_ESP_V4_FLOW:
+ if (!(nfc->data & RXH_IP_SRC) ||
+ !(nfc->data & RXH_IP_DST))
+ return -EINVAL;
+ switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
+ case 0:
+ rss_fields &= ~VMXNET3_RSS_FIELDS_ESPIP4;
+ break;
+ case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+ rss_fields |= VMXNET3_RSS_FIELDS_ESPIP4;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case ESP_V6_FLOW:
+ case AH_V6_FLOW:
+ case AH_ESP_V6_FLOW:
+ case SCTP_V4_FLOW:
+ case SCTP_V6_FLOW:
+ if (!(nfc->data & RXH_IP_SRC) ||
+ !(nfc->data & RXH_IP_DST) ||
+ (nfc->data & RXH_L4_B_0_1) ||
+ (nfc->data & RXH_L4_B_2_3))
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* if we changed something we need to update flags */
+ if (rss_fields != adapter->rss_fields) {
+ adapter->default_rss_fields = false;
+ if (netif_running(netdev)) {
+ struct Vmxnet3_DriverShared *shared = adapter->shared;
+ union Vmxnet3_CmdInfo *cmdInfo = &shared->cu.cmdInfo;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->cmd_lock, flags);
+ cmdInfo->setRssFields = rss_fields;
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_SET_RSS_FIELDS);
+
+ /* Not all requested RSS may get applied, so get and
+ * cache what was actually applied.
+ */
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_GET_RSS_FIELDS);
+ adapter->rss_fields =
+ VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
+ spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+ } else {
+ /* When the device is activated, we will try to apply
+ * these rules and cache the applied value later.
+ */
+ adapter->rss_fields = rss_fields;
+ }
+ }
+ return 0;
+}

static int
vmxnet3_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info,
u32 *rules)
{
struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+ int err = 0;
+
switch (info->cmd) {
case ETHTOOL_GRXRINGS:
info->data = adapter->num_rx_queues;
- return 0;
+ break;
+ case ETHTOOL_GRXFH:
+ if (!VMXNET3_VERSION_GE_4(adapter)) {
+ err = -EOPNOTSUPP;
+ break;
+ }
+ err = vmxnet3_get_rss_hash_opts(adapter, info);
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
}
- return -EOPNOTSUPP;
+
+ return err;
+}
+
+static int
+vmxnet3_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info)
+{
+ struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+ int err = 0;
+
+ if (!VMXNET3_VERSION_GE_4(adapter)) {
+ err = -EOPNOTSUPP;
+ goto done;
+ }
+
+ switch (info->cmd) {
+ case ETHTOOL_SRXFH:
+ err = vmxnet3_set_rss_hash_opt(netdev, adapter, info);
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+done:
+ return err;
}

#ifdef VMXNET3_RSS
@@ -887,6 +1105,7 @@ static const struct ethtool_ops vmxnet3_ethtool_ops = {
.get_ringparam = vmxnet3_get_ringparam,
.set_ringparam = vmxnet3_set_ringparam,
.get_rxnfc = vmxnet3_get_rxnfc,
+ .set_rxnfc = vmxnet3_set_rxnfc,
#ifdef VMXNET3_RSS
.get_rxfh_indir_size = vmxnet3_get_rss_indir_size,
.get_rxfh = vmxnet3_get_rss,
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index e803ffad75d6..d52ccc3eeba2 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -377,6 +377,8 @@ struct vmxnet3_adapter {
u16 rxdata_desc_size;

bool rxdataring_enabled;
+ bool default_rss_fields;
+ enum Vmxnet3_RSSField rss_fields;

struct work_struct work;

@@ -438,6 +440,8 @@ struct vmxnet3_adapter {

#define VMXNET3_COAL_RBC_RATE(usecs) (1000000 / usecs)
#define VMXNET3_COAL_RBC_USECS(rbc_rate) (1000000 / rbc_rate)
+#define VMXNET3_RSS_FIELDS_DEFAULT (VMXNET3_RSS_FIELDS_TCPIP4 | \
+ VMXNET3_RSS_FIELDS_TCPIP6)

int
vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter);
--
2.11.0


2020-05-28 05:54:46

by Michal Kubecek

[permalink] [raw]
Subject: Re: [PATCH net-next 2/4] vmxnet3: add support to get/set rx flow hash

On Wed, May 27, 2020 at 07:07:04PM -0700, Ronak Doshi wrote:
> With vmxnet3 version 4, the emulation supports multiqueue(RSS) for
> UDP and ESP traffic. A guest can enable/disable RSS for UDP/ESP over
> IPv4/IPv6 by issuing commands introduced in this patch. ESP ipv6 is
> not yet supported in this patch.
>
> This patch implements get_rss_hash_opts and set_rss_hash_opts
> methods to allow querying and configuring different Rx flow hash
> configurations.
>
> Signed-off-by: Ronak Doshi <[email protected]>
> ---
[...]
> diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
> index 1163eca7aba5..ceedf63020cb 100644
> --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
> +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
> @@ -665,18 +665,236 @@ vmxnet3_set_ringparam(struct net_device *netdev,
> return err;
> }
>
> +static int
> +vmxnet3_get_rss_hash_opts(struct vmxnet3_adapter *adapter,
> + struct ethtool_rxnfc *info)
> +{
> + enum Vmxnet3_RSSField rss_fields;
> +
> + if (netif_running(adapter->netdev)) {
> + unsigned long flags;
> +
> + spin_lock_irqsave(&adapter->cmd_lock, flags);
> +
> + VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
> + VMXNET3_CMD_GET_RSS_FIELDS);
> + rss_fields = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
> + spin_unlock_irqrestore(&adapter->cmd_lock, flags);
> + } else {
> + rss_fields = adapter->rss_fields;
> + }
> +
> + info->data = 0;
> +
> + /* Report default options for RSS on vmxnet3 */
> + switch (info->flow_type) {
> + case TCP_V4_FLOW:
> + if (rss_fields & VMXNET3_RSS_FIELDS_TCPIP4)
> + info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
> + RXH_IP_SRC | RXH_IP_DST;
> + break;
> + case UDP_V4_FLOW:
> + if (rss_fields & VMXNET3_RSS_FIELDS_UDPIP4)
> + info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
> + RXH_IP_SRC | RXH_IP_DST;
> + break;

In both cases above (and also in the two for IPv6 below) you set
info->data to either 0 or all four bits, depending on the value of
corresponding flag in rss_fields. But in vmxnet3_set_rss_hash_opt()
you have different mapping:

- for TCP, you only accept all four bits (no other value) and don't
touch rss_fields at all
- for UDP, you allow either all four bits (and set the flag) or the
two IP related bits (and clear the flag)

The UDPv4/UDPv6 behaviour of vmxnet3_set_rss_hash_opt() seems to be the
correct one but you should be consistent between get and set handlers.

> + case AH_ESP_V4_FLOW:
> + case AH_V4_FLOW:
> + case ESP_V4_FLOW:
> + if (rss_fields & VMXNET3_RSS_FIELDS_ESPIP4)
> + info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;

If this fallthrough is intentional (it seems to be), it should be
marked.

Michal

> + case SCTP_V4_FLOW:
> + case IPV4_FLOW:
> + info->data |= RXH_IP_SRC | RXH_IP_DST;
> + break;
> + case TCP_V6_FLOW:
> + if (rss_fields & VMXNET3_RSS_FIELDS_TCPIP6)
> + info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
> + RXH_IP_SRC | RXH_IP_DST;
> + break;
> + case UDP_V6_FLOW:
> + if (rss_fields & VMXNET3_RSS_FIELDS_UDPIP6)
> + info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
> + RXH_IP_SRC | RXH_IP_DST;
> + break;
> + case AH_ESP_V6_FLOW:
> + case AH_V6_FLOW:
> + case ESP_V6_FLOW:
> + case SCTP_V6_FLOW:
> + case IPV6_FLOW:
> + info->data |= RXH_IP_SRC | RXH_IP_DST;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int
> +vmxnet3_set_rss_hash_opt(struct net_device *netdev,
> + struct vmxnet3_adapter *adapter,
> + struct ethtool_rxnfc *nfc)
> +{
> + enum Vmxnet3_RSSField rss_fields = adapter->rss_fields;
> +
> + /* RSS does not support anything other than hashing
> + * to queues on src and dst IPs and ports
> + */
> + if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
> + RXH_L4_B_0_1 | RXH_L4_B_2_3))
> + return -EINVAL;
> +
> + switch (nfc->flow_type) {
> + case TCP_V4_FLOW:
> + case TCP_V6_FLOW:
> + if (!(nfc->data & RXH_IP_SRC) ||
> + !(nfc->data & RXH_IP_DST) ||
> + !(nfc->data & RXH_L4_B_0_1) ||
> + !(nfc->data & RXH_L4_B_2_3))
> + return -EINVAL;
> + break;
> + case UDP_V4_FLOW:
> + if (!(nfc->data & RXH_IP_SRC) ||
> + !(nfc->data & RXH_IP_DST))
> + return -EINVAL;
> + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
> + case 0:
> + rss_fields &= ~VMXNET3_RSS_FIELDS_UDPIP4;
> + break;
> + case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
> + rss_fields |= VMXNET3_RSS_FIELDS_UDPIP4;
> + break;
> + default:
> + return -EINVAL;
> + }
> + break;
> + case UDP_V6_FLOW:
> + if (!(nfc->data & RXH_IP_SRC) ||
> + !(nfc->data & RXH_IP_DST))
> + return -EINVAL;
> + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
> + case 0:
> + rss_fields &= ~VMXNET3_RSS_FIELDS_UDPIP6;
> + break;
> + case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
> + rss_fields |= VMXNET3_RSS_FIELDS_UDPIP6;
> + break;
> + default:
> + return -EINVAL;
> + }
> + break;
> + case ESP_V4_FLOW:
> + case AH_V4_FLOW:
> + case AH_ESP_V4_FLOW:
> + if (!(nfc->data & RXH_IP_SRC) ||
> + !(nfc->data & RXH_IP_DST))
> + return -EINVAL;
> + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
> + case 0:
> + rss_fields &= ~VMXNET3_RSS_FIELDS_ESPIP4;
> + break;
> + case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
> + rss_fields |= VMXNET3_RSS_FIELDS_ESPIP4;
> + break;
> + default:
> + return -EINVAL;
> + }
> + break;
> + case ESP_V6_FLOW:
> + case AH_V6_FLOW:
> + case AH_ESP_V6_FLOW:
> + case SCTP_V4_FLOW:
> + case SCTP_V6_FLOW:
> + if (!(nfc->data & RXH_IP_SRC) ||
> + !(nfc->data & RXH_IP_DST) ||
> + (nfc->data & RXH_L4_B_0_1) ||
> + (nfc->data & RXH_L4_B_2_3))
> + return -EINVAL;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + /* if we changed something we need to update flags */
> + if (rss_fields != adapter->rss_fields) {
> + adapter->default_rss_fields = false;
> + if (netif_running(netdev)) {
> + struct Vmxnet3_DriverShared *shared = adapter->shared;
> + union Vmxnet3_CmdInfo *cmdInfo = &shared->cu.cmdInfo;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&adapter->cmd_lock, flags);
> + cmdInfo->setRssFields = rss_fields;
> + VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
> + VMXNET3_CMD_SET_RSS_FIELDS);
> +
> + /* Not all requested RSS may get applied, so get and
> + * cache what was actually applied.
> + */
> + VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
> + VMXNET3_CMD_GET_RSS_FIELDS);
> + adapter->rss_fields =
> + VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
> + spin_unlock_irqrestore(&adapter->cmd_lock, flags);
> + } else {
> + /* When the device is activated, we will try to apply
> + * these rules and cache the applied value later.
> + */
> + adapter->rss_fields = rss_fields;
> + }
> + }
> + return 0;
> +}
>
> static int
> vmxnet3_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info,
> u32 *rules)
> {
> struct vmxnet3_adapter *adapter = netdev_priv(netdev);
> + int err = 0;
> +
> switch (info->cmd) {
> case ETHTOOL_GRXRINGS:
> info->data = adapter->num_rx_queues;
> - return 0;
> + break;
> + case ETHTOOL_GRXFH:
> + if (!VMXNET3_VERSION_GE_4(adapter)) {
> + err = -EOPNOTSUPP;
> + break;
> + }
> + err = vmxnet3_get_rss_hash_opts(adapter, info);
> + break;
> + default:
> + err = -EOPNOTSUPP;
> + break;
> }
> - return -EOPNOTSUPP;
> +
> + return err;
> +}
> +
> +static int
> +vmxnet3_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info)
> +{
> + struct vmxnet3_adapter *adapter = netdev_priv(netdev);
> + int err = 0;
> +
> + if (!VMXNET3_VERSION_GE_4(adapter)) {
> + err = -EOPNOTSUPP;
> + goto done;
> + }
> +
> + switch (info->cmd) {
> + case ETHTOOL_SRXFH:
> + err = vmxnet3_set_rss_hash_opt(netdev, adapter, info);
> + break;
> + default:
> + err = -EOPNOTSUPP;
> + break;
> + }
> +
> +done:
> + return err;
> }
>
> #ifdef VMXNET3_RSS
> @@ -887,6 +1105,7 @@ static const struct ethtool_ops vmxnet3_ethtool_ops = {
> .get_ringparam = vmxnet3_get_ringparam,
> .set_ringparam = vmxnet3_set_ringparam,
> .get_rxnfc = vmxnet3_get_rxnfc,
> + .set_rxnfc = vmxnet3_set_rxnfc,
> #ifdef VMXNET3_RSS
> .get_rxfh_indir_size = vmxnet3_get_rss_indir_size,
> .get_rxfh = vmxnet3_get_rss,
> diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
> index e803ffad75d6..d52ccc3eeba2 100644
> --- a/drivers/net/vmxnet3/vmxnet3_int.h
> +++ b/drivers/net/vmxnet3/vmxnet3_int.h
> @@ -377,6 +377,8 @@ struct vmxnet3_adapter {
> u16 rxdata_desc_size;
>
> bool rxdataring_enabled;
> + bool default_rss_fields;
> + enum Vmxnet3_RSSField rss_fields;
>
> struct work_struct work;
>
> @@ -438,6 +440,8 @@ struct vmxnet3_adapter {
>
> #define VMXNET3_COAL_RBC_RATE(usecs) (1000000 / usecs)
> #define VMXNET3_COAL_RBC_USECS(rbc_rate) (1000000 / rbc_rate)
> +#define VMXNET3_RSS_FIELDS_DEFAULT (VMXNET3_RSS_FIELDS_TCPIP4 | \
> + VMXNET3_RSS_FIELDS_TCPIP6)
>
> int
> vmxnet3_quiesce_dev(struct vmxnet3_adapter *adapter);
> --
> 2.11.0
>

2020-05-28 10:45:53

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH net-next 2/4] vmxnet3: add support to get/set rx flow hash

Hi Ronak,

I love your patch! Perhaps something to improve:

[auto build test WARNING on net-next/master]
[also build test WARNING on sparc-next/master linus/master ipvs/master v5.7-rc7 next-20200526]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url: https://github.com/0day-ci/linux/commits/Ronak-Doshi/vmxnet3-upgrade-to-version-4/20200528-112935
base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 50ce4c099bebf56be86c9448f7f4bcd34f33663c
config: alpha-allyesconfig (attached as .config)
compiler: alpha-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=alpha

If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <[email protected]>

All warnings (new ones prefixed by >>, old ones prefixed by <<):

drivers/net/vmxnet3/vmxnet3_ethtool.c: In function 'vmxnet3_get_rss_hash_opts':
>> drivers/net/vmxnet3/vmxnet3_ethtool.c:704:6: warning: this statement may fall through [-Wimplicit-fallthrough=]
704 | if (rss_fields & VMXNET3_RSS_FIELDS_ESPIP4)
| ^
drivers/net/vmxnet3/vmxnet3_ethtool.c:706:2: note: here
706 | case SCTP_V4_FLOW:
| ^~~~

vim +704 drivers/net/vmxnet3/vmxnet3_ethtool.c

667
668 static int
669 vmxnet3_get_rss_hash_opts(struct vmxnet3_adapter *adapter,
670 struct ethtool_rxnfc *info)
671 {
672 enum Vmxnet3_RSSField rss_fields;
673
674 if (netif_running(adapter->netdev)) {
675 unsigned long flags;
676
677 spin_lock_irqsave(&adapter->cmd_lock, flags);
678
679 VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
680 VMXNET3_CMD_GET_RSS_FIELDS);
681 rss_fields = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
682 spin_unlock_irqrestore(&adapter->cmd_lock, flags);
683 } else {
684 rss_fields = adapter->rss_fields;
685 }
686
687 info->data = 0;
688
689 /* Report default options for RSS on vmxnet3 */
690 switch (info->flow_type) {
691 case TCP_V4_FLOW:
692 if (rss_fields & VMXNET3_RSS_FIELDS_TCPIP4)
693 info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
694 RXH_IP_SRC | RXH_IP_DST;
695 break;
696 case UDP_V4_FLOW:
697 if (rss_fields & VMXNET3_RSS_FIELDS_UDPIP4)
698 info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
699 RXH_IP_SRC | RXH_IP_DST;
700 break;
701 case AH_ESP_V4_FLOW:
702 case AH_V4_FLOW:
703 case ESP_V4_FLOW:
> 704 if (rss_fields & VMXNET3_RSS_FIELDS_ESPIP4)
705 info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
706 case SCTP_V4_FLOW:
707 case IPV4_FLOW:
708 info->data |= RXH_IP_SRC | RXH_IP_DST;
709 break;
710 case TCP_V6_FLOW:
711 if (rss_fields & VMXNET3_RSS_FIELDS_TCPIP6)
712 info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
713 RXH_IP_SRC | RXH_IP_DST;
714 break;
715 case UDP_V6_FLOW:
716 if (rss_fields & VMXNET3_RSS_FIELDS_UDPIP6)
717 info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
718 RXH_IP_SRC | RXH_IP_DST;
719 break;
720 case AH_ESP_V6_FLOW:
721 case AH_V6_FLOW:
722 case ESP_V6_FLOW:
723 case SCTP_V6_FLOW:
724 case IPV6_FLOW:
725 info->data |= RXH_IP_SRC | RXH_IP_DST;
726 break;
727 default:
728 return -EINVAL;
729 }
730
731 return 0;
732 }
733

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (3.89 kB)
.config.gz (60.00 kB)
Download all attachments