NCSI specification defines 4 VLAN modes, currently kernel NCSI driver only supports the "VLAN + non-VLAN" mode (Mode #2), and there is no way to detect which modes are supported by the device. This patch adds support for configuring VLAN mode via the "ncsi,vlan-mode" devicetree node. Signed-off-by: Jiaqing Zhao <jiaqing.zhao@xxxxxxxxxxxxxxx> --- net/ncsi/internal.h | 1 + net/ncsi/ncsi-manage.c | 41 ++++++++++++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h index 7f384f841019..b868e07f7ffd 100644 --- a/net/ncsi/internal.h +++ b/net/ncsi/internal.h @@ -334,6 +334,7 @@ struct ncsi_dev_priv { struct work_struct work; /* For channel management */ struct packet_type ptype; /* NCSI packet Rx handler */ struct list_head node; /* Form NCSI device list */ + u32 vlan_mode; /* VLAN mode */ #define NCSI_MAX_VLAN_VIDS 15 struct list_head vlan_vids; /* List of active VLAN IDs */ diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c index 3fb95f29e3e2..a398b0eb72b2 100644 --- a/net/ncsi/ncsi-manage.c +++ b/net/ncsi/ncsi-manage.c @@ -10,6 +10,7 @@ #include <linux/skbuff.h> #include <linux/of.h> #include <linux/platform_device.h> +#include <dt-bindings/net/ncsi.h> #include <net/ncsi.h> #include <net/net_namespace.h> @@ -1042,7 +1043,11 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp) nd->state = ncsi_dev_state_config_oem_gma; break; case ncsi_dev_state_config_oem_gma: - nd->state = ncsi_dev_state_config_clear_vids; + /* Only set up hardware VLAN filters in filtered mode */ + if (ndp->vlan_mode == NCSI_VLAN_MODE_FILTERED) + nd->state = ncsi_dev_state_config_clear_vids; + else + nd->state = ncsi_dev_state_config_ev; ret = -1; #if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC) @@ -1094,11 +1099,15 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp) nd->state = ncsi_dev_state_config_svf; /* Enable/Disable the VLAN filter */ } else if (nd->state == ncsi_dev_state_config_ev) { - if (list_empty(&ndp->vlan_vids)) { - nca.type = NCSI_PKT_CMD_DV; - } else { + if (ndp->vlan_mode == NCSI_VLAN_MODE_FILTERED && + !list_empty(&ndp->vlan_vids)) { nca.type = NCSI_PKT_CMD_EV; nca.bytes[3] = NCSI_CAP_VLAN_FILTERED; + } else if (ndp->vlan_mode == NCSI_VLAN_MODE_ANY) { + nca.type = NCSI_PKT_CMD_EV; + nca.bytes[3] = NCSI_CAP_VLAN_ANY; + } else { + nca.type = NCSI_PKT_CMD_DV; } nd->state = ncsi_dev_state_config_sma; } else if (nd->state == ncsi_dev_state_config_sma) { @@ -1800,15 +1809,33 @@ struct ncsi_dev *ncsi_register_dev(struct net_device *dev, ndp->ptype.dev = dev; dev_add_pack(&ndp->ptype); + /* Set default VLAN mode (filtered) */ + ndp->vlan_mode = NCSI_VLAN_MODE_FILTERED; + pdev = to_platform_device(dev->dev.parent); if (pdev) { np = pdev->dev.of_node; - if (np && of_get_property(np, "mlx,multi-host", NULL)) - ndp->mlx_multi_host = true; + if (np) { + u32 vlan_mode; + + if (!of_property_read_u32(np, "ncsi,vlan-mode", &vlan_mode)) { + if (vlan_mode > NCSI_VLAN_MODE_ANY || + vlan_mode == NCSI_VLAN_MODE_ONLY) + dev_warn(&pdev->dev, "NCSI: Unsupported VLAN mode %u", + vlan_mode); + else + ndp->vlan_mode = vlan_mode; + dev_info(&pdev->dev, "NCSI: Configured VLAN mode %u", + ndp->vlan_mode); + } + if (of_get_property(np, "mlx,multi-host", NULL)) + ndp->mlx_multi_host = true; + } } /* Enable hardware VLAN filtering */ - if (dev->netdev_ops->ndo_vlan_rx_add_vid == ncsi_vlan_rx_add_vid && + if (ndp->vlan_mode == NCSI_VLAN_MODE_FILTERED && + dev->netdev_ops->ndo_vlan_rx_add_vid == ncsi_vlan_rx_add_vid && dev->netdev_ops->ndo_vlan_rx_kill_vid == ncsi_vlan_rx_kill_vid) dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER; -- 2.34.1