diff options
Diffstat (limited to 'drivers/net/ethernet/intel/fm10k/fm10k_netdev.c')
-rw-r--r-- | drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 94 |
1 files changed, 65 insertions, 29 deletions
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 45793491d4ba..929f538d28bc 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -1,27 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 -/* Intel(R) Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2018 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ +/* Copyright(c) 2013 - 2018 Intel Corporation. */ #include "fm10k.h" #include <linux/vmalloc.h> #include <net/udp_tunnel.h> +#include <linux/if_macvlan.h> /** * fm10k_setup_tx_resources - allocate Tx resources (Descriptors) @@ -924,7 +907,9 @@ static int fm10k_mc_vlan_unsync(struct net_device *netdev, static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) { struct fm10k_intfc *interface = netdev_priv(netdev); + struct fm10k_l2_accel *l2_accel = interface->l2_accel; struct fm10k_hw *hw = &interface->hw; + u16 glort; s32 err; int i; @@ -992,6 +977,22 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) if (err) goto err_out; + /* Update L2 accelerated macvlan addresses */ + if (l2_accel) { + for (i = 0; i < l2_accel->size; i++) { + struct net_device *sdev = l2_accel->macvlan[i]; + + if (!sdev) + continue; + + glort = l2_accel->dglort + 1 + i; + + fm10k_queue_mac_request(interface, glort, + sdev->dev_addr, + vid, set); + } + } + /* set VLAN ID prior to syncing/unsyncing the VLAN */ interface->vid = vid + (set ? VLAN_N_VID : 0); @@ -1231,6 +1232,22 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) fm10k_queue_mac_request(interface, glort, hw->mac.addr, vid, true); + + /* synchronize macvlan addresses */ + if (l2_accel) { + for (i = 0; i < l2_accel->size; i++) { + struct net_device *sdev = l2_accel->macvlan[i]; + + if (!sdev) + continue; + + glort = l2_accel->dglort + 1 + i; + + fm10k_queue_mac_request(interface, glort, + sdev->dev_addr, + vid, true); + } + } } /* update xcast mode before synchronizing addresses if host's mailbox @@ -1254,7 +1271,7 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) glort = l2_accel->dglort + 1 + i; hw->mac.ops.update_xcast_mode(hw, glort, - FM10K_XCAST_MODE_MULTI); + FM10K_XCAST_MODE_NONE); fm10k_queue_mac_request(interface, glort, sdev->dev_addr, hw->mac.default_vid, true); @@ -1447,7 +1464,14 @@ static void *fm10k_dfwd_add_station(struct net_device *dev, struct fm10k_dglort_cfg dglort = { 0 }; struct fm10k_hw *hw = &interface->hw; int size = 0, i; - u16 glort; + u16 vid, glort; + + /* The hardware supported by fm10k only filters on the destination MAC + * address. In order to avoid issues we only support offloading modes + * where the hardware can actually provide the functionality. + */ + if (!macvlan_supports_dest_filter(sdev)) + return ERR_PTR(-EMEDIUMTYPE); /* allocate l2 accel structure if it is not available */ if (!l2_accel) { @@ -1513,12 +1537,18 @@ static void *fm10k_dfwd_add_station(struct net_device *dev, glort = l2_accel->dglort + 1 + i; - if (fm10k_host_mbx_ready(interface)) { + if (fm10k_host_mbx_ready(interface)) hw->mac.ops.update_xcast_mode(hw, glort, - FM10K_XCAST_MODE_MULTI); + FM10K_XCAST_MODE_NONE); + + fm10k_queue_mac_request(interface, glort, sdev->dev_addr, + hw->mac.default_vid, true); + + for (vid = fm10k_find_next_vlan(interface, 0); + vid < VLAN_N_VID; + vid = fm10k_find_next_vlan(interface, vid)) fm10k_queue_mac_request(interface, glort, sdev->dev_addr, - hw->mac.default_vid, true); - } + vid, true); fm10k_mbx_unlock(interface); @@ -1532,8 +1562,8 @@ static void fm10k_dfwd_del_station(struct net_device *dev, void *priv) struct fm10k_dglort_cfg dglort = { 0 }; struct fm10k_hw *hw = &interface->hw; struct net_device *sdev = priv; + u16 vid, glort; int i; - u16 glort; if (!l2_accel) return; @@ -1553,12 +1583,18 @@ static void fm10k_dfwd_del_station(struct net_device *dev, void *priv) glort = l2_accel->dglort + 1 + i; - if (fm10k_host_mbx_ready(interface)) { + if (fm10k_host_mbx_ready(interface)) hw->mac.ops.update_xcast_mode(hw, glort, FM10K_XCAST_MODE_NONE); + + fm10k_queue_mac_request(interface, glort, sdev->dev_addr, + hw->mac.default_vid, false); + + for (vid = fm10k_find_next_vlan(interface, 0); + vid < VLAN_N_VID; + vid = fm10k_find_next_vlan(interface, vid)) fm10k_queue_mac_request(interface, glort, sdev->dev_addr, - hw->mac.default_vid, false); - } + vid, false); fm10k_mbx_unlock(interface); |