diff options
author | Pablo Cascón <pablo.cascon@netronome.com> | 2017-06-16 02:22:15 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-06-19 07:11:49 +0300 |
commit | b64052fc9bcb4fa3ca8701e74c1aac0e2847b724 (patch) | |
tree | 20f925dc0e009228bf58b0403a9bf5486eef1bb6 /drivers/net/ethernet/netronome/nfp/nfp_net_common.c | |
parent | d427caee5a3f04938f47bec6fdec97a52668ee53 (diff) | |
download | linux-b64052fc9bcb4fa3ca8701e74c1aac0e2847b724.tar.xz |
nfp: add VLAN filtering support
Add general use per-vNIC mailbox area and use it for VLAN filtering
support. Initially proto is hardcoded to 802.1q.
Signed-off-by: Pablo Cascón <pablo.cascon@netronome.com>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/netronome/nfp/nfp_net_common.c')
-rw-r--r-- | drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 378512dec80d..2bdddd1ae666 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -280,6 +280,30 @@ int nfp_net_reconfig(struct nfp_net *nn, u32 update) return ret; } +/** + * nfp_net_reconfig_mbox() - Reconfigure the firmware via the mailbox + * @nn: NFP Net device to reconfigure + * @mbox_cmd: The value for the mailbox command + * + * Helper function for mailbox updates + * + * Return: Negative errno on error, 0 on success + */ +static int nfp_net_reconfig_mbox(struct nfp_net *nn, u32 mbox_cmd) +{ + int ret; + + nn_writeq(nn, NFP_NET_CFG_MBOX_CMD, mbox_cmd); + + ret = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_MBOX); + if (ret) { + nn_err(nn, "Mailbox update error\n"); + return ret; + } + + return -nn_readl(nn, NFP_NET_CFG_MBOX_RET); +} + /* Interrupt configuration and handling */ @@ -2960,6 +2984,40 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu) return nfp_net_ring_reconfig(nn, dp, NULL); } +static int +nfp_net_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid) +{ + struct nfp_net *nn = netdev_priv(netdev); + + /* Priority tagged packets with vlan id 0 are processed by the + * NFP as untagged packets + */ + if (!vid) + return 0; + + nn_writew(nn, NFP_NET_CFG_VLAN_FILTER_VID, vid); + nn_writew(nn, NFP_NET_CFG_VLAN_FILTER_PROTO, ETH_P_8021Q); + + return nfp_net_reconfig_mbox(nn, NFP_NET_CFG_MBOX_CMD_CTAG_FILTER_ADD); +} + +static int +nfp_net_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid) +{ + struct nfp_net *nn = netdev_priv(netdev); + + /* Priority tagged packets with vlan id 0 are processed by the + * NFP as untagged packets + */ + if (!vid) + return 0; + + nn_writew(nn, NFP_NET_CFG_VLAN_FILTER_VID, vid); + nn_writew(nn, NFP_NET_CFG_VLAN_FILTER_PROTO, ETH_P_8021Q); + + return nfp_net_reconfig_mbox(nn, NFP_NET_CFG_MBOX_CMD_CTAG_FILTER_KILL); +} + static void nfp_net_stat64(struct net_device *netdev, struct rtnl_link_stats64 *stats) { @@ -3053,6 +3111,13 @@ static int nfp_net_set_features(struct net_device *netdev, new_ctrl &= ~NFP_NET_CFG_CTRL_TXVLAN; } + if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) { + if (features & NETIF_F_HW_VLAN_CTAG_FILTER) + new_ctrl |= NFP_NET_CFG_CTRL_CTAG_FILTER; + else + new_ctrl &= ~NFP_NET_CFG_CTRL_CTAG_FILTER; + } + if (changed & NETIF_F_SG) { if (features & NETIF_F_SG) new_ctrl |= NFP_NET_CFG_CTRL_GATHER; @@ -3289,6 +3354,8 @@ const struct net_device_ops nfp_net_netdev_ops = { .ndo_stop = nfp_net_netdev_close, .ndo_start_xmit = nfp_net_tx, .ndo_get_stats64 = nfp_net_stat64, + .ndo_vlan_rx_add_vid = nfp_net_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = nfp_net_vlan_rx_kill_vid, .ndo_setup_tc = nfp_net_setup_tc, .ndo_tx_timeout = nfp_net_tx_timeout, .ndo_set_rx_mode = nfp_net_set_rx_mode, @@ -3316,7 +3383,7 @@ void nfp_net_info(struct nfp_net *nn) nn->fw_ver.resv, nn->fw_ver.class, nn->fw_ver.major, nn->fw_ver.minor, nn->max_mtu); - nn_info(nn, "CAP: %#x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + nn_info(nn, "CAP: %#x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", nn->cap, nn->cap & NFP_NET_CFG_CTRL_PROMISC ? "PROMISC " : "", nn->cap & NFP_NET_CFG_CTRL_L2BC ? "L2BCFILT " : "", @@ -3331,6 +3398,7 @@ void nfp_net_info(struct nfp_net *nn) nn->cap & NFP_NET_CFG_CTRL_LSO2 ? "TSO2 " : "", nn->cap & NFP_NET_CFG_CTRL_RSS ? "RSS1 " : "", nn->cap & NFP_NET_CFG_CTRL_RSS2 ? "RSS2 " : "", + nn->cap & NFP_NET_CFG_CTRL_CTAG_FILTER ? "CTAG_FILTER " : "", nn->cap & NFP_NET_CFG_CTRL_L2SWITCH ? "L2SWITCH " : "", nn->cap & NFP_NET_CFG_CTRL_MSIXAUTO ? "AUTOMASK " : "", nn->cap & NFP_NET_CFG_CTRL_IRQMOD ? "IRQMOD " : "", @@ -3547,6 +3615,10 @@ static void nfp_net_netdev_init(struct nfp_net *nn) nn->dp.ctrl |= NFP_NET_CFG_CTRL_TXVLAN; } } + if (nn->cap & NFP_NET_CFG_CTRL_CTAG_FILTER) { + netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER; + nn->dp.ctrl |= NFP_NET_CFG_CTRL_CTAG_FILTER; + } netdev->features = netdev->hw_features; |