diff options
Diffstat (limited to 'drivers/net/ethernet/intel/fm10k/fm10k_netdev.c')
-rw-r--r-- | drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 119 |
1 files changed, 88 insertions, 31 deletions
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 01db688cf539..24f2f6f86f5a 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -1,5 +1,5 @@ /* Intel(R) Ethernet Switch Host Interface Driver - * Copyright(c) 2013 - 2016 Intel Corporation. + * Copyright(c) 2013 - 2017 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, @@ -737,6 +737,23 @@ static void fm10k_tx_timeout(struct net_device *netdev) } } +/** + * fm10k_host_mbx_ready - Check PF interface's mailbox readiness + * @interface: board private structure + * + * This function checks if the PF interface's mailbox is ready before queueing + * mailbox messages for transmission. This will prevent filling the TX mailbox + * queue when the receiver is not ready. VF interfaces are exempt from this + * check since it will block all PF-VF mailbox messages from being sent from + * the VF to the PF at initialization. + **/ +static bool fm10k_host_mbx_ready(struct fm10k_intfc *interface) +{ + struct fm10k_hw *hw = &interface->hw; + + return (hw->mac.type == fm10k_mac_vf || interface->host_ready); +} + static int fm10k_uc_vlan_unsync(struct net_device *netdev, const unsigned char *uc_addr) { @@ -745,12 +762,15 @@ static int fm10k_uc_vlan_unsync(struct net_device *netdev, u16 glort = interface->glort; u16 vid = interface->vid; bool set = !!(vid / VLAN_N_VID); - int err; + int err = -EHOSTDOWN; /* drop any leading bits on the VLAN ID */ vid &= VLAN_N_VID - 1; - err = hw->mac.ops.update_uc_addr(hw, glort, uc_addr, vid, set, 0); + if (fm10k_host_mbx_ready(interface)) + err = hw->mac.ops.update_uc_addr(hw, glort, uc_addr, + vid, set, 0); + if (err) return err; @@ -766,12 +786,14 @@ static int fm10k_mc_vlan_unsync(struct net_device *netdev, u16 glort = interface->glort; u16 vid = interface->vid; bool set = !!(vid / VLAN_N_VID); - int err; + int err = -EHOSTDOWN; /* drop any leading bits on the VLAN ID */ vid &= VLAN_N_VID - 1; - err = hw->mac.ops.update_mc_addr(hw, glort, mc_addr, vid, set); + if (fm10k_host_mbx_ready(interface)) + err = hw->mac.ops.update_mc_addr(hw, glort, mc_addr, vid, set); + if (err) return err; @@ -822,7 +844,7 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) /* Do not throw an error if the interface is down. We will sync once * we come up */ - if (test_bit(__FM10K_DOWN, &interface->state)) + if (test_bit(__FM10K_DOWN, interface->state)) return 0; fm10k_mbx_lock(interface); @@ -834,9 +856,13 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) goto err_out; } - /* update our base MAC address */ - err = hw->mac.ops.update_uc_addr(hw, interface->glort, hw->mac.addr, - vid, set, 0); + /* update our base MAC address if host's mailbox is ready */ + if (fm10k_host_mbx_ready(interface)) + err = hw->mac.ops.update_uc_addr(hw, interface->glort, + hw->mac.addr, vid, set, 0); + else + err = -EHOSTDOWN; + if (err) goto err_out; @@ -907,12 +933,15 @@ static int __fm10k_uc_sync(struct net_device *dev, if (!is_valid_ether_addr(addr)) return -EADDRNOTAVAIL; - /* update table with current entries */ + /* update table with current entries if host's mailbox is ready */ + if (!fm10k_host_mbx_ready(interface)) + return -EHOSTDOWN; + for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 1; vid < VLAN_N_VID; vid = fm10k_find_next_vlan(interface, vid)) { err = hw->mac.ops.update_uc_addr(hw, glort, addr, - vid, sync, 0); + vid, sync, 0); if (err) return err; } @@ -970,7 +999,10 @@ static int __fm10k_mc_sync(struct net_device *dev, struct fm10k_hw *hw = &interface->hw; u16 vid, glort = interface->glort; - /* update table with current entries */ + /* update table with current entries if host's mailbox is ready */ + if (!fm10k_host_mbx_ready(interface)) + return 0; + for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 1; vid < VLAN_N_VID; vid = fm10k_find_next_vlan(interface, vid)) { @@ -1018,8 +1050,10 @@ static void fm10k_set_rx_mode(struct net_device *dev) if (interface->xcast_mode == FM10K_XCAST_MODE_PROMISC) fm10k_clear_unused_vlans(interface); - /* update xcast mode */ - hw->mac.ops.update_xcast_mode(hw, interface->glort, xcast_mode); + /* update xcast mode if host's mailbox is ready */ + if (fm10k_host_mbx_ready(interface)) + hw->mac.ops.update_xcast_mode(hw, interface->glort, + xcast_mode); /* record updated xcast mode state */ interface->xcast_mode = xcast_mode; @@ -1054,8 +1088,10 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) fm10k_mbx_lock(interface); - /* Enable logical port */ - hw->mac.ops.update_lport_state(hw, glort, interface->glort_count, true); + /* Enable logical port if host's mailbox is ready */ + if (fm10k_host_mbx_ready(interface)) + hw->mac.ops.update_lport_state(hw, glort, + interface->glort_count, true); /* update VLAN table */ hw->mac.ops.update_vlan(hw, FM10K_VLAN_ALL, 0, @@ -1069,12 +1105,18 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) vid < VLAN_N_VID; vid = fm10k_find_next_vlan(interface, vid)) { hw->mac.ops.update_vlan(hw, vid, 0, true); - hw->mac.ops.update_uc_addr(hw, glort, hw->mac.addr, - vid, true, 0); + + /* Update unicast entries if host's mailbox is ready */ + if (fm10k_host_mbx_ready(interface)) + hw->mac.ops.update_uc_addr(hw, glort, hw->mac.addr, + vid, true, 0); } - /* update xcast mode before synchronizing addresses */ - hw->mac.ops.update_xcast_mode(hw, glort, xcast_mode); + /* update xcast mode before synchronizing addresses if host's mailbox + * is ready + */ + if (fm10k_host_mbx_ready(interface)) + hw->mac.ops.update_xcast_mode(hw, glort, xcast_mode); /* synchronize all of the addresses */ __dev_uc_sync(netdev, fm10k_uc_sync, fm10k_uc_unsync); @@ -1096,9 +1138,12 @@ void fm10k_reset_rx_state(struct fm10k_intfc *interface) fm10k_mbx_lock(interface); - /* clear the logical port state on lower device */ - hw->mac.ops.update_lport_state(hw, interface->glort, - interface->glort_count, false); + /* clear the logical port state on lower device if host's mailbox is + * ready + */ + if (fm10k_host_mbx_ready(interface)) + hw->mac.ops.update_lport_state(hw, interface->glort, + interface->glort_count, false); fm10k_mbx_unlock(interface); @@ -1115,8 +1160,8 @@ void fm10k_reset_rx_state(struct fm10k_intfc *interface) * @netdev: network interface device structure * @stats: storage space for 64bit statistics * - * Returns 64bit statistics, for use in the ndo_get_stats64 callback. This - * function replaces fm10k_get_stats for kernels which support it. + * Obtain 64bit statistics in a way that is safe for both 32bit and 64bit + * architectures. */ static void fm10k_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) @@ -1207,7 +1252,7 @@ int fm10k_setup_tc(struct net_device *dev, u8 tc) goto err_open; /* flag to indicate SWPRI has yet to be updated */ - interface->flags |= FM10K_FLAG_SWPRI_CONFIG; + set_bit(FM10K_FLAG_SWPRI_CONFIG, interface->flags); return 0; err_open: @@ -1226,7 +1271,9 @@ static int __fm10k_setup_tc(struct net_device *dev, u32 handle, __be16 proto, if (tc->type != TC_SETUP_MQPRIO) return -EINVAL; - return fm10k_setup_tc(dev, tc->tc); + tc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS; + + return fm10k_setup_tc(dev, tc->mqprio->num_tc); } static void fm10k_assign_l2_accel(struct fm10k_intfc *interface, @@ -1317,8 +1364,13 @@ static void *fm10k_dfwd_add_station(struct net_device *dev, fm10k_mbx_lock(interface); glort = l2_accel->dglort + 1 + i; - hw->mac.ops.update_xcast_mode(hw, glort, FM10K_XCAST_MODE_MULTI); - hw->mac.ops.update_uc_addr(hw, glort, sdev->dev_addr, 0, true, 0); + + if (fm10k_host_mbx_ready(interface)) { + hw->mac.ops.update_xcast_mode(hw, glort, + FM10K_XCAST_MODE_MULTI); + hw->mac.ops.update_uc_addr(hw, glort, sdev->dev_addr, + 0, true, 0); + } fm10k_mbx_unlock(interface); @@ -1352,8 +1404,13 @@ static void fm10k_dfwd_del_station(struct net_device *dev, void *priv) fm10k_mbx_lock(interface); glort = l2_accel->dglort + 1 + i; - hw->mac.ops.update_xcast_mode(hw, glort, FM10K_XCAST_MODE_NONE); - hw->mac.ops.update_uc_addr(hw, glort, sdev->dev_addr, 0, false, 0); + + if (fm10k_host_mbx_ready(interface)) { + hw->mac.ops.update_xcast_mode(hw, glort, + FM10K_XCAST_MODE_NONE); + hw->mac.ops.update_uc_addr(hw, glort, sdev->dev_addr, + 0, false, 0); + } fm10k_mbx_unlock(interface); |