提交 b4041278 编写于 作者: D David S. Miller

Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue

Jeff Kirsher says:

====================
100GbE Intel Wired LAN Driver Updates 2017-04-05

This series contains updates to fm10k only.

Phil Turnbull from Oracle fixes an issue where the argument provided to
FM10K_REMOVED macro was not what was expecting.

Jake modifies the driver to replace the bitwise operators and defines with
a BITMAP and enumeration values to avoid race conditions.  Also future
proof the driver so that developers do not have to remember to re-size the
bitmaps when adding new values.  Fixed the wording of a code comment to
avoid stating that we return a value for a void function.

Ngai-Mint makes sure that when configuring the receive ring, we make sure
the receive queue is disabled.  Fixed an issue where interfaces were
resetting because the transmit mailbox FIFO was becoming full since the
host was not ready, so ensure the host is ready before queueing up
mailbox messages.
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
/* Intel(R) Ethernet Switch Host Interface Driver /* 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -65,14 +65,16 @@ enum fm10k_ring_state_t { ...@@ -65,14 +65,16 @@ enum fm10k_ring_state_t {
__FM10K_TX_DETECT_HANG, __FM10K_TX_DETECT_HANG,
__FM10K_HANG_CHECK_ARMED, __FM10K_HANG_CHECK_ARMED,
__FM10K_TX_XPS_INIT_DONE, __FM10K_TX_XPS_INIT_DONE,
/* This must be last and is used to calculate BITMAP size */
__FM10K_TX_STATE_SIZE__,
}; };
#define check_for_tx_hang(ring) \ #define check_for_tx_hang(ring) \
test_bit(__FM10K_TX_DETECT_HANG, &(ring)->state) test_bit(__FM10K_TX_DETECT_HANG, (ring)->state)
#define set_check_for_tx_hang(ring) \ #define set_check_for_tx_hang(ring) \
set_bit(__FM10K_TX_DETECT_HANG, &(ring)->state) set_bit(__FM10K_TX_DETECT_HANG, (ring)->state)
#define clear_check_for_tx_hang(ring) \ #define clear_check_for_tx_hang(ring) \
clear_bit(__FM10K_TX_DETECT_HANG, &(ring)->state) clear_bit(__FM10K_TX_DETECT_HANG, (ring)->state)
struct fm10k_tx_buffer { struct fm10k_tx_buffer {
struct fm10k_tx_desc *next_to_watch; struct fm10k_tx_desc *next_to_watch;
...@@ -126,7 +128,7 @@ struct fm10k_ring { ...@@ -126,7 +128,7 @@ struct fm10k_ring {
struct fm10k_rx_buffer *rx_buffer; struct fm10k_rx_buffer *rx_buffer;
}; };
u32 __iomem *tail; u32 __iomem *tail;
unsigned long state; DECLARE_BITMAP(state, __FM10K_TX_STATE_SIZE__);
dma_addr_t dma; /* phys. address of descriptor ring */ dma_addr_t dma; /* phys. address of descriptor ring */
unsigned int size; /* length in bytes */ unsigned int size; /* length in bytes */
...@@ -249,18 +251,46 @@ struct fm10k_udp_port { ...@@ -249,18 +251,46 @@ struct fm10k_udp_port {
/* one work queue for entire driver */ /* one work queue for entire driver */
extern struct workqueue_struct *fm10k_workqueue; extern struct workqueue_struct *fm10k_workqueue;
/* The following enumeration contains flags which indicate or enable modified
* driver behaviors. To avoid race conditions, the flags are stored in
* a BITMAP in the fm10k_intfc structure. The BITMAP should be accessed using
* atomic *_bit() operations.
*/
enum fm10k_flags_t {
FM10K_FLAG_RESET_REQUESTED,
FM10K_FLAG_RSS_FIELD_IPV4_UDP,
FM10K_FLAG_RSS_FIELD_IPV6_UDP,
FM10K_FLAG_SWPRI_CONFIG,
/* __FM10K_FLAGS_SIZE__ is used to calculate the size of
* interface->flags and must be the last value in this
* enumeration.
*/
__FM10K_FLAGS_SIZE__
};
enum fm10k_state_t {
__FM10K_RESETTING,
__FM10K_DOWN,
__FM10K_SERVICE_SCHED,
__FM10K_SERVICE_REQUEST,
__FM10K_SERVICE_DISABLE,
__FM10K_MBX_LOCK,
__FM10K_LINK_DOWN,
__FM10K_UPDATING_STATS,
/* This value must be last and determines the BITMAP size */
__FM10K_STATE_SIZE__,
};
struct fm10k_intfc { struct fm10k_intfc {
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct net_device *netdev; struct net_device *netdev;
struct fm10k_l2_accel *l2_accel; /* pointer to L2 acceleration list */ struct fm10k_l2_accel *l2_accel; /* pointer to L2 acceleration list */
struct pci_dev *pdev; struct pci_dev *pdev;
unsigned long state; DECLARE_BITMAP(state, __FM10K_STATE_SIZE__);
/* Access flag values using atomic *_bit() operations */
DECLARE_BITMAP(flags, __FM10K_FLAGS_SIZE__);
u32 flags;
#define FM10K_FLAG_RESET_REQUESTED (u32)(BIT(0))
#define FM10K_FLAG_RSS_FIELD_IPV4_UDP (u32)(BIT(1))
#define FM10K_FLAG_RSS_FIELD_IPV6_UDP (u32)(BIT(2))
#define FM10K_FLAG_SWPRI_CONFIG (u32)(BIT(3))
int xcast_mode; int xcast_mode;
/* Tx fast path data */ /* Tx fast path data */
...@@ -352,22 +382,12 @@ struct fm10k_intfc { ...@@ -352,22 +382,12 @@ struct fm10k_intfc {
u16 vid; u16 vid;
}; };
enum fm10k_state_t {
__FM10K_RESETTING,
__FM10K_DOWN,
__FM10K_SERVICE_SCHED,
__FM10K_SERVICE_DISABLE,
__FM10K_MBX_LOCK,
__FM10K_LINK_DOWN,
__FM10K_UPDATING_STATS,
};
static inline void fm10k_mbx_lock(struct fm10k_intfc *interface) static inline void fm10k_mbx_lock(struct fm10k_intfc *interface)
{ {
/* busy loop if we cannot obtain the lock as some calls /* busy loop if we cannot obtain the lock as some calls
* such as ndo_set_rx_mode may be made in atomic context * such as ndo_set_rx_mode may be made in atomic context
*/ */
while (test_and_set_bit(__FM10K_MBX_LOCK, &interface->state)) while (test_and_set_bit(__FM10K_MBX_LOCK, interface->state))
udelay(20); udelay(20);
} }
...@@ -375,12 +395,12 @@ static inline void fm10k_mbx_unlock(struct fm10k_intfc *interface) ...@@ -375,12 +395,12 @@ static inline void fm10k_mbx_unlock(struct fm10k_intfc *interface)
{ {
/* flush memory to make sure state is correct */ /* flush memory to make sure state is correct */
smp_mb__before_atomic(); smp_mb__before_atomic();
clear_bit(__FM10K_MBX_LOCK, &interface->state); clear_bit(__FM10K_MBX_LOCK, interface->state);
} }
static inline int fm10k_mbx_trylock(struct fm10k_intfc *interface) static inline int fm10k_mbx_trylock(struct fm10k_intfc *interface)
{ {
return !test_and_set_bit(__FM10K_MBX_LOCK, &interface->state); return !test_and_set_bit(__FM10K_MBX_LOCK, interface->state);
} }
/* fm10k_test_staterr - test bits in Rx descriptor status and error fields */ /* fm10k_test_staterr - test bits in Rx descriptor status and error fields */
......
/* Intel(R) Ethernet Switch Host Interface Driver /* 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -562,7 +562,7 @@ static int fm10k_set_ringparam(struct net_device *netdev, ...@@ -562,7 +562,7 @@ static int fm10k_set_ringparam(struct net_device *netdev,
return 0; return 0;
} }
while (test_and_set_bit(__FM10K_RESETTING, &interface->state)) while (test_and_set_bit(__FM10K_RESETTING, interface->state))
usleep_range(1000, 2000); usleep_range(1000, 2000);
if (!netif_running(interface->netdev)) { if (!netif_running(interface->netdev)) {
...@@ -648,7 +648,7 @@ static int fm10k_set_ringparam(struct net_device *netdev, ...@@ -648,7 +648,7 @@ static int fm10k_set_ringparam(struct net_device *netdev,
fm10k_up(interface); fm10k_up(interface);
vfree(temp_ring); vfree(temp_ring);
clear_reset: clear_reset:
clear_bit(__FM10K_RESETTING, &interface->state); clear_bit(__FM10K_RESETTING, interface->state);
return err; return err;
} }
...@@ -716,7 +716,8 @@ static int fm10k_get_rss_hash_opts(struct fm10k_intfc *interface, ...@@ -716,7 +716,8 @@ static int fm10k_get_rss_hash_opts(struct fm10k_intfc *interface,
cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
/* fall through */ /* fall through */
case UDP_V4_FLOW: case UDP_V4_FLOW:
if (interface->flags & FM10K_FLAG_RSS_FIELD_IPV4_UDP) if (test_bit(FM10K_FLAG_RSS_FIELD_IPV4_UDP,
interface->flags))
cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
/* fall through */ /* fall through */
case SCTP_V4_FLOW: case SCTP_V4_FLOW:
...@@ -732,7 +733,8 @@ static int fm10k_get_rss_hash_opts(struct fm10k_intfc *interface, ...@@ -732,7 +733,8 @@ static int fm10k_get_rss_hash_opts(struct fm10k_intfc *interface,
cmd->data |= RXH_IP_SRC | RXH_IP_DST; cmd->data |= RXH_IP_SRC | RXH_IP_DST;
break; break;
case UDP_V6_FLOW: case UDP_V6_FLOW:
if (interface->flags & FM10K_FLAG_RSS_FIELD_IPV6_UDP) if (test_bit(FM10K_FLAG_RSS_FIELD_IPV6_UDP,
interface->flags))
cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
cmd->data |= RXH_IP_SRC | RXH_IP_DST; cmd->data |= RXH_IP_SRC | RXH_IP_DST;
break; break;
...@@ -764,12 +766,13 @@ static int fm10k_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, ...@@ -764,12 +766,13 @@ static int fm10k_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
return ret; return ret;
} }
#define UDP_RSS_FLAGS (FM10K_FLAG_RSS_FIELD_IPV4_UDP | \
FM10K_FLAG_RSS_FIELD_IPV6_UDP)
static int fm10k_set_rss_hash_opt(struct fm10k_intfc *interface, static int fm10k_set_rss_hash_opt(struct fm10k_intfc *interface,
struct ethtool_rxnfc *nfc) struct ethtool_rxnfc *nfc)
{ {
u32 flags = interface->flags; int rss_ipv4_udp = test_bit(FM10K_FLAG_RSS_FIELD_IPV4_UDP,
interface->flags);
int rss_ipv6_udp = test_bit(FM10K_FLAG_RSS_FIELD_IPV6_UDP,
interface->flags);
/* RSS does not support anything other than hashing /* RSS does not support anything other than hashing
* to queues on src and dst IPs and ports * to queues on src and dst IPs and ports
...@@ -793,10 +796,12 @@ static int fm10k_set_rss_hash_opt(struct fm10k_intfc *interface, ...@@ -793,10 +796,12 @@ static int fm10k_set_rss_hash_opt(struct fm10k_intfc *interface,
return -EINVAL; return -EINVAL;
switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
case 0: case 0:
flags &= ~FM10K_FLAG_RSS_FIELD_IPV4_UDP; clear_bit(FM10K_FLAG_RSS_FIELD_IPV4_UDP,
interface->flags);
break; break;
case (RXH_L4_B_0_1 | RXH_L4_B_2_3): case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
flags |= FM10K_FLAG_RSS_FIELD_IPV4_UDP; set_bit(FM10K_FLAG_RSS_FIELD_IPV4_UDP,
interface->flags);
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -808,10 +813,12 @@ static int fm10k_set_rss_hash_opt(struct fm10k_intfc *interface, ...@@ -808,10 +813,12 @@ static int fm10k_set_rss_hash_opt(struct fm10k_intfc *interface,
return -EINVAL; return -EINVAL;
switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
case 0: case 0:
flags &= ~FM10K_FLAG_RSS_FIELD_IPV6_UDP; clear_bit(FM10K_FLAG_RSS_FIELD_IPV6_UDP,
interface->flags);
break; break;
case (RXH_L4_B_0_1 | RXH_L4_B_2_3): case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
flags |= FM10K_FLAG_RSS_FIELD_IPV6_UDP; set_bit(FM10K_FLAG_RSS_FIELD_IPV6_UDP,
interface->flags);
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -835,28 +842,41 @@ static int fm10k_set_rss_hash_opt(struct fm10k_intfc *interface, ...@@ -835,28 +842,41 @@ static int fm10k_set_rss_hash_opt(struct fm10k_intfc *interface,
return -EINVAL; return -EINVAL;
} }
/* if we changed something we need to update flags */ /* If something changed we need to update the MRQC register. Note that
if (flags != interface->flags) { * test_bit() is guaranteed to return strictly 0 or 1, so testing for
* equality is safe.
*/
if ((rss_ipv4_udp != test_bit(FM10K_FLAG_RSS_FIELD_IPV4_UDP,
interface->flags)) ||
(rss_ipv6_udp != test_bit(FM10K_FLAG_RSS_FIELD_IPV6_UDP,
interface->flags))) {
struct fm10k_hw *hw = &interface->hw; struct fm10k_hw *hw = &interface->hw;
bool warn = false;
u32 mrqc; u32 mrqc;
if ((flags & UDP_RSS_FLAGS) &&
!(interface->flags & UDP_RSS_FLAGS))
netif_warn(interface, drv, interface->netdev,
"enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n");
interface->flags = flags;
/* Perform hash on these packet types */ /* Perform hash on these packet types */
mrqc = FM10K_MRQC_IPV4 | mrqc = FM10K_MRQC_IPV4 |
FM10K_MRQC_TCP_IPV4 | FM10K_MRQC_TCP_IPV4 |
FM10K_MRQC_IPV6 | FM10K_MRQC_IPV6 |
FM10K_MRQC_TCP_IPV6; FM10K_MRQC_TCP_IPV6;
if (flags & FM10K_FLAG_RSS_FIELD_IPV4_UDP) if (test_bit(FM10K_FLAG_RSS_FIELD_IPV4_UDP,
interface->flags)) {
mrqc |= FM10K_MRQC_UDP_IPV4; mrqc |= FM10K_MRQC_UDP_IPV4;
if (flags & FM10K_FLAG_RSS_FIELD_IPV6_UDP) warn = true;
}
if (test_bit(FM10K_FLAG_RSS_FIELD_IPV6_UDP,
interface->flags)) {
mrqc |= FM10K_MRQC_UDP_IPV6; mrqc |= FM10K_MRQC_UDP_IPV6;
warn = true;
}
/* If we enable UDP RSS display a warning that this may cause
* fragmented UDP packets to arrive out of order.
*/
if (warn)
netif_warn(interface, drv, interface->netdev,
"enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n");
fm10k_write_reg(hw, FM10K_MRQC(0), mrqc); fm10k_write_reg(hw, FM10K_MRQC(0), mrqc);
} }
...@@ -939,7 +959,7 @@ static void fm10k_self_test(struct net_device *dev, ...@@ -939,7 +959,7 @@ static void fm10k_self_test(struct net_device *dev,
memset(data, 0, sizeof(*data) * FM10K_TEST_LEN); memset(data, 0, sizeof(*data) * FM10K_TEST_LEN);
if (FM10K_REMOVED(hw)) { if (FM10K_REMOVED(hw->hw_addr)) {
netif_err(interface, drv, dev, netif_err(interface, drv, dev,
"Interface removed - test blocked\n"); "Interface removed - test blocked\n");
eth_test->flags |= ETH_TEST_FL_FAILED; eth_test->flags |= ETH_TEST_FL_FAILED;
......
/* Intel(R) Ethernet Switch Host Interface Driver /* 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -34,7 +34,7 @@ const char fm10k_driver_version[] = DRV_VERSION; ...@@ -34,7 +34,7 @@ const char fm10k_driver_version[] = DRV_VERSION;
char fm10k_driver_name[] = "fm10k"; char fm10k_driver_name[] = "fm10k";
static const char fm10k_driver_string[] = DRV_SUMMARY; static const char fm10k_driver_string[] = DRV_SUMMARY;
static const char fm10k_copyright[] = static const char fm10k_copyright[] =
"Copyright (c) 2013 - 2016 Intel Corporation."; "Copyright(c) 2013 - 2017 Intel Corporation.";
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_DESCRIPTION(DRV_SUMMARY); MODULE_DESCRIPTION(DRV_SUMMARY);
...@@ -1175,13 +1175,13 @@ bool fm10k_check_tx_hang(struct fm10k_ring *tx_ring) ...@@ -1175,13 +1175,13 @@ bool fm10k_check_tx_hang(struct fm10k_ring *tx_ring)
/* update completed stats and continue */ /* update completed stats and continue */
tx_ring->tx_stats.tx_done_old = tx_done; tx_ring->tx_stats.tx_done_old = tx_done;
/* reset the countdown */ /* reset the countdown */
clear_bit(__FM10K_HANG_CHECK_ARMED, &tx_ring->state); clear_bit(__FM10K_HANG_CHECK_ARMED, tx_ring->state);
return false; return false;
} }
/* make sure it is true for two checks in a row */ /* make sure it is true for two checks in a row */
return test_and_set_bit(__FM10K_HANG_CHECK_ARMED, &tx_ring->state); return test_and_set_bit(__FM10K_HANG_CHECK_ARMED, tx_ring->state);
} }
/** /**
...@@ -1191,9 +1191,9 @@ bool fm10k_check_tx_hang(struct fm10k_ring *tx_ring) ...@@ -1191,9 +1191,9 @@ bool fm10k_check_tx_hang(struct fm10k_ring *tx_ring)
void fm10k_tx_timeout_reset(struct fm10k_intfc *interface) void fm10k_tx_timeout_reset(struct fm10k_intfc *interface)
{ {
/* Do the reset outside of interrupt context */ /* Do the reset outside of interrupt context */
if (!test_bit(__FM10K_DOWN, &interface->state)) { if (!test_bit(__FM10K_DOWN, interface->state)) {
interface->tx_timeout_count++; interface->tx_timeout_count++;
interface->flags |= FM10K_FLAG_RESET_REQUESTED; set_bit(FM10K_FLAG_RESET_REQUESTED, interface->flags);
fm10k_service_event_schedule(interface); fm10k_service_event_schedule(interface);
} }
} }
...@@ -1214,7 +1214,7 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector, ...@@ -1214,7 +1214,7 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector,
unsigned int budget = q_vector->tx.work_limit; unsigned int budget = q_vector->tx.work_limit;
unsigned int i = tx_ring->next_to_clean; unsigned int i = tx_ring->next_to_clean;
if (test_bit(__FM10K_DOWN, &interface->state)) if (test_bit(__FM10K_DOWN, interface->state))
return true; return true;
tx_buffer = &tx_ring->tx_buffer[i]; tx_buffer = &tx_ring->tx_buffer[i];
...@@ -1344,7 +1344,7 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector, ...@@ -1344,7 +1344,7 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector,
smp_mb(); smp_mb();
if (__netif_subqueue_stopped(tx_ring->netdev, if (__netif_subqueue_stopped(tx_ring->netdev,
tx_ring->queue_index) && tx_ring->queue_index) &&
!test_bit(__FM10K_DOWN, &interface->state)) { !test_bit(__FM10K_DOWN, interface->state)) {
netif_wake_subqueue(tx_ring->netdev, netif_wake_subqueue(tx_ring->netdev,
tx_ring->queue_index); tx_ring->queue_index);
++tx_ring->tx_stats.restart_queue; ++tx_ring->tx_stats.restart_queue;
......
/* Intel(R) Ethernet Switch Host Interface Driver /* 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -737,6 +737,23 @@ static void fm10k_tx_timeout(struct net_device *netdev) ...@@ -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, static int fm10k_uc_vlan_unsync(struct net_device *netdev,
const unsigned char *uc_addr) const unsigned char *uc_addr)
{ {
...@@ -745,12 +762,15 @@ static int fm10k_uc_vlan_unsync(struct net_device *netdev, ...@@ -745,12 +762,15 @@ static int fm10k_uc_vlan_unsync(struct net_device *netdev,
u16 glort = interface->glort; u16 glort = interface->glort;
u16 vid = interface->vid; u16 vid = interface->vid;
bool set = !!(vid / VLAN_N_VID); bool set = !!(vid / VLAN_N_VID);
int err; int err = -EHOSTDOWN;
/* drop any leading bits on the VLAN ID */ /* drop any leading bits on the VLAN ID */
vid &= VLAN_N_VID - 1; 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) if (err)
return err; return err;
...@@ -766,12 +786,14 @@ static int fm10k_mc_vlan_unsync(struct net_device *netdev, ...@@ -766,12 +786,14 @@ static int fm10k_mc_vlan_unsync(struct net_device *netdev,
u16 glort = interface->glort; u16 glort = interface->glort;
u16 vid = interface->vid; u16 vid = interface->vid;
bool set = !!(vid / VLAN_N_VID); bool set = !!(vid / VLAN_N_VID);
int err; int err = -EHOSTDOWN;
/* drop any leading bits on the VLAN ID */ /* drop any leading bits on the VLAN ID */
vid &= VLAN_N_VID - 1; 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) if (err)
return err; return err;
...@@ -822,7 +844,7 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) ...@@ -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 /* Do not throw an error if the interface is down. We will sync once
* we come up * we come up
*/ */
if (test_bit(__FM10K_DOWN, &interface->state)) if (test_bit(__FM10K_DOWN, interface->state))
return 0; return 0;
fm10k_mbx_lock(interface); fm10k_mbx_lock(interface);
...@@ -834,9 +856,13 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) ...@@ -834,9 +856,13 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set)
goto err_out; goto err_out;
} }
/* update our base MAC address */ /* update our base MAC address if host's mailbox is ready */
err = hw->mac.ops.update_uc_addr(hw, interface->glort, hw->mac.addr, if (fm10k_host_mbx_ready(interface))
vid, set, 0); err = hw->mac.ops.update_uc_addr(hw, interface->glort,
hw->mac.addr, vid, set, 0);
else
err = -EHOSTDOWN;
if (err) if (err)
goto err_out; goto err_out;
...@@ -907,12 +933,15 @@ static int __fm10k_uc_sync(struct net_device *dev, ...@@ -907,12 +933,15 @@ static int __fm10k_uc_sync(struct net_device *dev,
if (!is_valid_ether_addr(addr)) if (!is_valid_ether_addr(addr))
return -EADDRNOTAVAIL; 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; for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 1;
vid < VLAN_N_VID; vid < VLAN_N_VID;
vid = fm10k_find_next_vlan(interface, vid)) { vid = fm10k_find_next_vlan(interface, vid)) {
err = hw->mac.ops.update_uc_addr(hw, glort, addr, err = hw->mac.ops.update_uc_addr(hw, glort, addr,
vid, sync, 0); vid, sync, 0);
if (err) if (err)
return err; return err;
} }
...@@ -970,7 +999,10 @@ static int __fm10k_mc_sync(struct net_device *dev, ...@@ -970,7 +999,10 @@ static int __fm10k_mc_sync(struct net_device *dev,
struct fm10k_hw *hw = &interface->hw; struct fm10k_hw *hw = &interface->hw;
u16 vid, glort = interface->glort; 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; for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 1;
vid < VLAN_N_VID; vid < VLAN_N_VID;
vid = fm10k_find_next_vlan(interface, vid)) { vid = fm10k_find_next_vlan(interface, vid)) {
...@@ -1018,8 +1050,10 @@ static void fm10k_set_rx_mode(struct net_device *dev) ...@@ -1018,8 +1050,10 @@ static void fm10k_set_rx_mode(struct net_device *dev)
if (interface->xcast_mode == FM10K_XCAST_MODE_PROMISC) if (interface->xcast_mode == FM10K_XCAST_MODE_PROMISC)
fm10k_clear_unused_vlans(interface); fm10k_clear_unused_vlans(interface);
/* update xcast mode */ /* update xcast mode if host's mailbox is ready */
hw->mac.ops.update_xcast_mode(hw, interface->glort, xcast_mode); if (fm10k_host_mbx_ready(interface))
hw->mac.ops.update_xcast_mode(hw, interface->glort,
xcast_mode);
/* record updated xcast mode state */ /* record updated xcast mode state */
interface->xcast_mode = xcast_mode; interface->xcast_mode = xcast_mode;
...@@ -1054,8 +1088,10 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) ...@@ -1054,8 +1088,10 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface)
fm10k_mbx_lock(interface); fm10k_mbx_lock(interface);
/* Enable logical port */ /* Enable logical port if host's mailbox is ready */
hw->mac.ops.update_lport_state(hw, glort, interface->glort_count, true); if (fm10k_host_mbx_ready(interface))
hw->mac.ops.update_lport_state(hw, glort,
interface->glort_count, true);
/* update VLAN table */ /* update VLAN table */
hw->mac.ops.update_vlan(hw, FM10K_VLAN_ALL, 0, hw->mac.ops.update_vlan(hw, FM10K_VLAN_ALL, 0,
...@@ -1069,12 +1105,18 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) ...@@ -1069,12 +1105,18 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface)
vid < VLAN_N_VID; vid < VLAN_N_VID;
vid = fm10k_find_next_vlan(interface, vid)) { vid = fm10k_find_next_vlan(interface, vid)) {
hw->mac.ops.update_vlan(hw, vid, 0, true); 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 */ /* update xcast mode before synchronizing addresses if host's mailbox
hw->mac.ops.update_xcast_mode(hw, glort, xcast_mode); * is ready
*/
if (fm10k_host_mbx_ready(interface))
hw->mac.ops.update_xcast_mode(hw, glort, xcast_mode);
/* synchronize all of the addresses */ /* synchronize all of the addresses */
__dev_uc_sync(netdev, fm10k_uc_sync, fm10k_uc_unsync); __dev_uc_sync(netdev, fm10k_uc_sync, fm10k_uc_unsync);
...@@ -1096,9 +1138,12 @@ void fm10k_reset_rx_state(struct fm10k_intfc *interface) ...@@ -1096,9 +1138,12 @@ void fm10k_reset_rx_state(struct fm10k_intfc *interface)
fm10k_mbx_lock(interface); fm10k_mbx_lock(interface);
/* clear the logical port state on lower device */ /* clear the logical port state on lower device if host's mailbox is
hw->mac.ops.update_lport_state(hw, interface->glort, * ready
interface->glort_count, false); */
if (fm10k_host_mbx_ready(interface))
hw->mac.ops.update_lport_state(hw, interface->glort,
interface->glort_count, false);
fm10k_mbx_unlock(interface); fm10k_mbx_unlock(interface);
...@@ -1115,8 +1160,8 @@ void fm10k_reset_rx_state(struct fm10k_intfc *interface) ...@@ -1115,8 +1160,8 @@ void fm10k_reset_rx_state(struct fm10k_intfc *interface)
* @netdev: network interface device structure * @netdev: network interface device structure
* @stats: storage space for 64bit statistics * @stats: storage space for 64bit statistics
* *
* Returns 64bit statistics, for use in the ndo_get_stats64 callback. This * Obtain 64bit statistics in a way that is safe for both 32bit and 64bit
* function replaces fm10k_get_stats for kernels which support it. * architectures.
*/ */
static void fm10k_get_stats64(struct net_device *netdev, static void fm10k_get_stats64(struct net_device *netdev,
struct rtnl_link_stats64 *stats) struct rtnl_link_stats64 *stats)
...@@ -1207,7 +1252,7 @@ int fm10k_setup_tc(struct net_device *dev, u8 tc) ...@@ -1207,7 +1252,7 @@ int fm10k_setup_tc(struct net_device *dev, u8 tc)
goto err_open; goto err_open;
/* flag to indicate SWPRI has yet to be updated */ /* 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; return 0;
err_open: err_open:
...@@ -1319,8 +1364,13 @@ static void *fm10k_dfwd_add_station(struct net_device *dev, ...@@ -1319,8 +1364,13 @@ static void *fm10k_dfwd_add_station(struct net_device *dev,
fm10k_mbx_lock(interface); fm10k_mbx_lock(interface);
glort = l2_accel->dglort + 1 + i; 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); fm10k_mbx_unlock(interface);
...@@ -1354,8 +1404,13 @@ static void fm10k_dfwd_del_station(struct net_device *dev, void *priv) ...@@ -1354,8 +1404,13 @@ static void fm10k_dfwd_del_station(struct net_device *dev, void *priv)
fm10k_mbx_lock(interface); fm10k_mbx_lock(interface);
glort = l2_accel->dglort + 1 + i; 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); fm10k_mbx_unlock(interface);
......
/* Intel(R) Ethernet Switch Host Interface Driver /* 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -93,18 +93,29 @@ static int fm10k_hw_ready(struct fm10k_intfc *interface) ...@@ -93,18 +93,29 @@ static int fm10k_hw_ready(struct fm10k_intfc *interface)
void fm10k_service_event_schedule(struct fm10k_intfc *interface) void fm10k_service_event_schedule(struct fm10k_intfc *interface)
{ {
if (!test_bit(__FM10K_SERVICE_DISABLE, &interface->state) && if (!test_bit(__FM10K_SERVICE_DISABLE, interface->state) &&
!test_and_set_bit(__FM10K_SERVICE_SCHED, &interface->state)) !test_and_set_bit(__FM10K_SERVICE_SCHED, interface->state)) {
clear_bit(__FM10K_SERVICE_REQUEST, interface->state);
queue_work(fm10k_workqueue, &interface->service_task); queue_work(fm10k_workqueue, &interface->service_task);
} else {
set_bit(__FM10K_SERVICE_REQUEST, interface->state);
}
} }
static void fm10k_service_event_complete(struct fm10k_intfc *interface) static void fm10k_service_event_complete(struct fm10k_intfc *interface)
{ {
WARN_ON(!test_bit(__FM10K_SERVICE_SCHED, &interface->state)); WARN_ON(!test_bit(__FM10K_SERVICE_SCHED, interface->state));
/* flush memory to make sure state is correct before next watchog */ /* flush memory to make sure state is correct before next watchog */
smp_mb__before_atomic(); smp_mb__before_atomic();
clear_bit(__FM10K_SERVICE_SCHED, &interface->state); clear_bit(__FM10K_SERVICE_SCHED, interface->state);
/* If a service event was requested since we started, immediately
* re-schedule now. This ensures we don't drop a request until the
* next timer event.
*/
if (test_bit(__FM10K_SERVICE_REQUEST, interface->state))
fm10k_service_event_schedule(interface);
} }
/** /**
...@@ -137,7 +148,7 @@ static void fm10k_detach_subtask(struct fm10k_intfc *interface) ...@@ -137,7 +148,7 @@ static void fm10k_detach_subtask(struct fm10k_intfc *interface)
if (~value) { if (~value) {
interface->hw.hw_addr = interface->uc_addr; interface->hw.hw_addr = interface->uc_addr;
netif_device_attach(netdev); netif_device_attach(netdev);
interface->flags |= FM10K_FLAG_RESET_REQUESTED; set_bit(FM10K_FLAG_RESET_REQUESTED, interface->flags);
netdev_warn(netdev, "PCIe link restored, device now attached\n"); netdev_warn(netdev, "PCIe link restored, device now attached\n");
return; return;
} }
...@@ -159,7 +170,7 @@ static void fm10k_prepare_for_reset(struct fm10k_intfc *interface) ...@@ -159,7 +170,7 @@ static void fm10k_prepare_for_reset(struct fm10k_intfc *interface)
/* put off any impending NetWatchDogTimeout */ /* put off any impending NetWatchDogTimeout */
netif_trans_update(netdev); netif_trans_update(netdev);
while (test_and_set_bit(__FM10K_RESETTING, &interface->state)) while (test_and_set_bit(__FM10K_RESETTING, interface->state))
usleep_range(1000, 2000); usleep_range(1000, 2000);
rtnl_lock(); rtnl_lock();
...@@ -242,7 +253,7 @@ static int fm10k_handle_reset(struct fm10k_intfc *interface) ...@@ -242,7 +253,7 @@ static int fm10k_handle_reset(struct fm10k_intfc *interface)
rtnl_unlock(); rtnl_unlock();
clear_bit(__FM10K_RESETTING, &interface->state); clear_bit(__FM10K_RESETTING, interface->state);
return err; return err;
err_open: err_open:
...@@ -254,7 +265,7 @@ static int fm10k_handle_reset(struct fm10k_intfc *interface) ...@@ -254,7 +265,7 @@ static int fm10k_handle_reset(struct fm10k_intfc *interface)
rtnl_unlock(); rtnl_unlock();
clear_bit(__FM10K_RESETTING, &interface->state); clear_bit(__FM10K_RESETTING, interface->state);
return err; return err;
} }
...@@ -273,11 +284,10 @@ static void fm10k_reinit(struct fm10k_intfc *interface) ...@@ -273,11 +284,10 @@ static void fm10k_reinit(struct fm10k_intfc *interface)
static void fm10k_reset_subtask(struct fm10k_intfc *interface) static void fm10k_reset_subtask(struct fm10k_intfc *interface)
{ {
if (!(interface->flags & FM10K_FLAG_RESET_REQUESTED)) if (!test_and_clear_bit(FM10K_FLAG_RESET_REQUESTED,
interface->flags))
return; return;
interface->flags &= ~FM10K_FLAG_RESET_REQUESTED;
netdev_err(interface->netdev, "Reset interface\n"); netdev_err(interface->netdev, "Reset interface\n");
fm10k_reinit(interface); fm10k_reinit(interface);
...@@ -296,7 +306,7 @@ static void fm10k_configure_swpri_map(struct fm10k_intfc *interface) ...@@ -296,7 +306,7 @@ static void fm10k_configure_swpri_map(struct fm10k_intfc *interface)
int i; int i;
/* clear flag indicating update is needed */ /* clear flag indicating update is needed */
interface->flags &= ~FM10K_FLAG_SWPRI_CONFIG; clear_bit(FM10K_FLAG_SWPRI_CONFIG, interface->flags);
/* these registers are only available on the PF */ /* these registers are only available on the PF */
if (hw->mac.type != fm10k_mac_pf) if (hw->mac.type != fm10k_mac_pf)
...@@ -317,14 +327,14 @@ static void fm10k_watchdog_update_host_state(struct fm10k_intfc *interface) ...@@ -317,14 +327,14 @@ static void fm10k_watchdog_update_host_state(struct fm10k_intfc *interface)
struct fm10k_hw *hw = &interface->hw; struct fm10k_hw *hw = &interface->hw;
s32 err; s32 err;
if (test_bit(__FM10K_LINK_DOWN, &interface->state)) { if (test_bit(__FM10K_LINK_DOWN, interface->state)) {
interface->host_ready = false; interface->host_ready = false;
if (time_is_after_jiffies(interface->link_down_event)) if (time_is_after_jiffies(interface->link_down_event))
return; return;
clear_bit(__FM10K_LINK_DOWN, &interface->state); clear_bit(__FM10K_LINK_DOWN, interface->state);
} }
if (interface->flags & FM10K_FLAG_SWPRI_CONFIG) { if (test_bit(FM10K_FLAG_SWPRI_CONFIG, interface->flags)) {
if (rtnl_trylock()) { if (rtnl_trylock()) {
fm10k_configure_swpri_map(interface); fm10k_configure_swpri_map(interface);
rtnl_unlock(); rtnl_unlock();
...@@ -336,7 +346,7 @@ static void fm10k_watchdog_update_host_state(struct fm10k_intfc *interface) ...@@ -336,7 +346,7 @@ static void fm10k_watchdog_update_host_state(struct fm10k_intfc *interface)
err = hw->mac.ops.get_host_state(hw, &interface->host_ready); err = hw->mac.ops.get_host_state(hw, &interface->host_ready);
if (err && time_is_before_jiffies(interface->last_reset)) if (err && time_is_before_jiffies(interface->last_reset))
interface->flags |= FM10K_FLAG_RESET_REQUESTED; set_bit(FM10K_FLAG_RESET_REQUESTED, interface->flags);
/* free the lock */ /* free the lock */
fm10k_mbx_unlock(interface); fm10k_mbx_unlock(interface);
...@@ -412,7 +422,7 @@ void fm10k_update_stats(struct fm10k_intfc *interface) ...@@ -412,7 +422,7 @@ void fm10k_update_stats(struct fm10k_intfc *interface)
int i; int i;
/* ensure only one thread updates stats at a time */ /* ensure only one thread updates stats at a time */
if (test_and_set_bit(__FM10K_UPDATING_STATS, &interface->state)) if (test_and_set_bit(__FM10K_UPDATING_STATS, interface->state))
return; return;
/* do not allow stats update via service task for next second */ /* do not allow stats update via service task for next second */
...@@ -493,7 +503,7 @@ void fm10k_update_stats(struct fm10k_intfc *interface) ...@@ -493,7 +503,7 @@ void fm10k_update_stats(struct fm10k_intfc *interface)
net_stats->rx_errors = rx_errors; net_stats->rx_errors = rx_errors;
net_stats->rx_dropped = interface->stats.nodesc_drop.count; net_stats->rx_dropped = interface->stats.nodesc_drop.count;
clear_bit(__FM10K_UPDATING_STATS, &interface->state); clear_bit(__FM10K_UPDATING_STATS, interface->state);
} }
/** /**
...@@ -523,7 +533,7 @@ static void fm10k_watchdog_flush_tx(struct fm10k_intfc *interface) ...@@ -523,7 +533,7 @@ static void fm10k_watchdog_flush_tx(struct fm10k_intfc *interface)
* controller to flush Tx. * controller to flush Tx.
*/ */
if (some_tx_pending) if (some_tx_pending)
interface->flags |= FM10K_FLAG_RESET_REQUESTED; set_bit(FM10K_FLAG_RESET_REQUESTED, interface->flags);
} }
/** /**
...@@ -533,8 +543,8 @@ static void fm10k_watchdog_flush_tx(struct fm10k_intfc *interface) ...@@ -533,8 +543,8 @@ static void fm10k_watchdog_flush_tx(struct fm10k_intfc *interface)
static void fm10k_watchdog_subtask(struct fm10k_intfc *interface) static void fm10k_watchdog_subtask(struct fm10k_intfc *interface)
{ {
/* if interface is down do nothing */ /* if interface is down do nothing */
if (test_bit(__FM10K_DOWN, &interface->state) || if (test_bit(__FM10K_DOWN, interface->state) ||
test_bit(__FM10K_RESETTING, &interface->state)) test_bit(__FM10K_RESETTING, interface->state))
return; return;
if (interface->host_ready) if (interface->host_ready)
...@@ -564,8 +574,8 @@ static void fm10k_check_hang_subtask(struct fm10k_intfc *interface) ...@@ -564,8 +574,8 @@ static void fm10k_check_hang_subtask(struct fm10k_intfc *interface)
int i; int i;
/* If we're down or resetting, just bail */ /* If we're down or resetting, just bail */
if (test_bit(__FM10K_DOWN, &interface->state) || if (test_bit(__FM10K_DOWN, interface->state) ||
test_bit(__FM10K_RESETTING, &interface->state)) test_bit(__FM10K_RESETTING, interface->state))
return; return;
/* rate limit tx hang checks to only once every 2 seconds */ /* rate limit tx hang checks to only once every 2 seconds */
...@@ -664,7 +674,7 @@ static void fm10k_configure_tx_ring(struct fm10k_intfc *interface, ...@@ -664,7 +674,7 @@ static void fm10k_configure_tx_ring(struct fm10k_intfc *interface,
FM10K_PFVTCTL_FTAG_DESC_ENABLE); FM10K_PFVTCTL_FTAG_DESC_ENABLE);
/* Initialize XPS */ /* Initialize XPS */
if (!test_and_set_bit(__FM10K_TX_XPS_INIT_DONE, &ring->state) && if (!test_and_set_bit(__FM10K_TX_XPS_INIT_DONE, ring->state) &&
ring->q_vector) ring->q_vector)
netif_set_xps_queue(ring->netdev, netif_set_xps_queue(ring->netdev,
&ring->q_vector->affinity_mask, &ring->q_vector->affinity_mask,
...@@ -744,6 +754,7 @@ static void fm10k_configure_rx_ring(struct fm10k_intfc *interface, ...@@ -744,6 +754,7 @@ static void fm10k_configure_rx_ring(struct fm10k_intfc *interface,
/* disable queue to avoid issues while updating state */ /* disable queue to avoid issues while updating state */
rxqctl = fm10k_read_reg(hw, FM10K_RXQCTL(reg_idx)); rxqctl = fm10k_read_reg(hw, FM10K_RXQCTL(reg_idx));
rxqctl &= ~FM10K_RXQCTL_ENABLE; rxqctl &= ~FM10K_RXQCTL_ENABLE;
fm10k_write_reg(hw, FM10K_RXQCTL(reg_idx), rxqctl);
fm10k_write_flush(hw); fm10k_write_flush(hw);
/* possible poll here to verify ring resources have been cleaned */ /* possible poll here to verify ring resources have been cleaned */
...@@ -864,9 +875,9 @@ static void fm10k_configure_dglort(struct fm10k_intfc *interface) ...@@ -864,9 +875,9 @@ static void fm10k_configure_dglort(struct fm10k_intfc *interface)
FM10K_MRQC_IPV6 | FM10K_MRQC_IPV6 |
FM10K_MRQC_TCP_IPV6; FM10K_MRQC_TCP_IPV6;
if (interface->flags & FM10K_FLAG_RSS_FIELD_IPV4_UDP) if (test_bit(FM10K_FLAG_RSS_FIELD_IPV4_UDP, interface->flags))
mrqc |= FM10K_MRQC_UDP_IPV4; mrqc |= FM10K_MRQC_UDP_IPV4;
if (interface->flags & FM10K_FLAG_RSS_FIELD_IPV6_UDP) if (test_bit(FM10K_FLAG_RSS_FIELD_IPV6_UDP, interface->flags))
mrqc |= FM10K_MRQC_UDP_IPV6; mrqc |= FM10K_MRQC_UDP_IPV6;
fm10k_write_reg(hw, FM10K_MRQC(0), mrqc); fm10k_write_reg(hw, FM10K_MRQC(0), mrqc);
...@@ -981,7 +992,7 @@ void fm10k_netpoll(struct net_device *netdev) ...@@ -981,7 +992,7 @@ void fm10k_netpoll(struct net_device *netdev)
int i; int i;
/* if interface is down do nothing */ /* if interface is down do nothing */
if (test_bit(__FM10K_DOWN, &interface->state)) if (test_bit(__FM10K_DOWN, interface->state))
return; return;
for (i = 0; i < interface->num_q_vectors; i++) for (i = 0; i < interface->num_q_vectors; i++)
...@@ -1168,13 +1179,13 @@ static irqreturn_t fm10k_msix_mbx_pf(int __always_unused irq, void *data) ...@@ -1168,13 +1179,13 @@ static irqreturn_t fm10k_msix_mbx_pf(int __always_unused irq, void *data)
} }
if (err == FM10K_ERR_RESET_REQUESTED) if (err == FM10K_ERR_RESET_REQUESTED)
interface->flags |= FM10K_FLAG_RESET_REQUESTED; set_bit(FM10K_FLAG_RESET_REQUESTED, interface->flags);
/* if switch toggled state we should reset GLORTs */ /* if switch toggled state we should reset GLORTs */
if (eicr & FM10K_EICR_SWITCHNOTREADY) { if (eicr & FM10K_EICR_SWITCHNOTREADY) {
/* force link down for at least 4 seconds */ /* force link down for at least 4 seconds */
interface->link_down_event = jiffies + (4 * HZ); interface->link_down_event = jiffies + (4 * HZ);
set_bit(__FM10K_LINK_DOWN, &interface->state); set_bit(__FM10K_LINK_DOWN, interface->state);
/* reset dglort_map back to no config */ /* reset dglort_map back to no config */
hw->mac.dglort_map = FM10K_DGLORTMAP_NONE; hw->mac.dglort_map = FM10K_DGLORTMAP_NONE;
...@@ -1247,12 +1258,12 @@ static s32 fm10k_mbx_mac_addr(struct fm10k_hw *hw, u32 **results, ...@@ -1247,12 +1258,12 @@ static s32 fm10k_mbx_mac_addr(struct fm10k_hw *hw, u32 **results,
/* MAC was changed so we need reset */ /* MAC was changed so we need reset */
if (is_valid_ether_addr(hw->mac.perm_addr) && if (is_valid_ether_addr(hw->mac.perm_addr) &&
!ether_addr_equal(hw->mac.perm_addr, hw->mac.addr)) !ether_addr_equal(hw->mac.perm_addr, hw->mac.addr))
interface->flags |= FM10K_FLAG_RESET_REQUESTED; set_bit(FM10K_FLAG_RESET_REQUESTED, interface->flags);
/* VLAN override was changed, or default VLAN changed */ /* VLAN override was changed, or default VLAN changed */
if ((vlan_override != hw->mac.vlan_override) || if ((vlan_override != hw->mac.vlan_override) ||
(default_vid != hw->mac.default_vid)) (default_vid != hw->mac.default_vid))
interface->flags |= FM10K_FLAG_RESET_REQUESTED; set_bit(FM10K_FLAG_RESET_REQUESTED, interface->flags);
return 0; return 0;
} }
...@@ -1326,7 +1337,7 @@ static s32 fm10k_lport_map(struct fm10k_hw *hw, u32 **results, ...@@ -1326,7 +1337,7 @@ static s32 fm10k_lport_map(struct fm10k_hw *hw, u32 **results,
if (!err && hw->swapi.status) { if (!err && hw->swapi.status) {
/* force link down for a reasonable delay */ /* force link down for a reasonable delay */
interface->link_down_event = jiffies + (2 * HZ); interface->link_down_event = jiffies + (2 * HZ);
set_bit(__FM10K_LINK_DOWN, &interface->state); set_bit(__FM10K_LINK_DOWN, interface->state);
/* reset dglort_map back to no config */ /* reset dglort_map back to no config */
hw->mac.dglort_map = FM10K_DGLORTMAP_NONE; hw->mac.dglort_map = FM10K_DGLORTMAP_NONE;
...@@ -1357,7 +1368,7 @@ static s32 fm10k_lport_map(struct fm10k_hw *hw, u32 **results, ...@@ -1357,7 +1368,7 @@ static s32 fm10k_lport_map(struct fm10k_hw *hw, u32 **results,
/* we need to reset if port count was just updated */ /* we need to reset if port count was just updated */
if (dglort_map != hw->mac.dglort_map) if (dglort_map != hw->mac.dglort_map)
interface->flags |= FM10K_FLAG_RESET_REQUESTED; set_bit(FM10K_FLAG_RESET_REQUESTED, interface->flags);
return 0; return 0;
} }
...@@ -1396,7 +1407,7 @@ static s32 fm10k_update_pvid(struct fm10k_hw *hw, u32 **results, ...@@ -1396,7 +1407,7 @@ static s32 fm10k_update_pvid(struct fm10k_hw *hw, u32 **results,
/* we need to reset if default VLAN was just updated */ /* we need to reset if default VLAN was just updated */
if (pvid != hw->mac.default_vid) if (pvid != hw->mac.default_vid)
interface->flags |= FM10K_FLAG_RESET_REQUESTED; set_bit(FM10K_FLAG_RESET_REQUESTED, interface->flags);
hw->mac.default_vid = pvid; hw->mac.default_vid = pvid;
...@@ -1624,10 +1635,10 @@ void fm10k_up(struct fm10k_intfc *interface) ...@@ -1624,10 +1635,10 @@ void fm10k_up(struct fm10k_intfc *interface)
hw->mac.ops.update_int_moderator(hw); hw->mac.ops.update_int_moderator(hw);
/* enable statistics capture again */ /* enable statistics capture again */
clear_bit(__FM10K_UPDATING_STATS, &interface->state); clear_bit(__FM10K_UPDATING_STATS, interface->state);
/* clear down bit to indicate we are ready to go */ /* clear down bit to indicate we are ready to go */
clear_bit(__FM10K_DOWN, &interface->state); clear_bit(__FM10K_DOWN, interface->state);
/* enable polling cleanups */ /* enable polling cleanups */
fm10k_napi_enable_all(interface); fm10k_napi_enable_all(interface);
...@@ -1661,7 +1672,7 @@ void fm10k_down(struct fm10k_intfc *interface) ...@@ -1661,7 +1672,7 @@ void fm10k_down(struct fm10k_intfc *interface)
int err, i = 0, count = 0; int err, i = 0, count = 0;
/* signal that we are down to the interrupt handler and service task */ /* signal that we are down to the interrupt handler and service task */
if (test_and_set_bit(__FM10K_DOWN, &interface->state)) if (test_and_set_bit(__FM10K_DOWN, interface->state))
return; return;
/* call carrier off first to avoid false dev_watchdog timeouts */ /* call carrier off first to avoid false dev_watchdog timeouts */
...@@ -1681,7 +1692,7 @@ void fm10k_down(struct fm10k_intfc *interface) ...@@ -1681,7 +1692,7 @@ void fm10k_down(struct fm10k_intfc *interface)
fm10k_update_stats(interface); fm10k_update_stats(interface);
/* prevent updating statistics while we're down */ /* prevent updating statistics while we're down */
while (test_and_set_bit(__FM10K_UPDATING_STATS, &interface->state)) while (test_and_set_bit(__FM10K_UPDATING_STATS, interface->state))
usleep_range(1000, 2000); usleep_range(1000, 2000);
/* skip waiting for TX DMA if we lost PCIe link */ /* skip waiting for TX DMA if we lost PCIe link */
...@@ -1850,8 +1861,8 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, ...@@ -1850,8 +1861,8 @@ static int fm10k_sw_init(struct fm10k_intfc *interface,
memcpy(interface->rssrk, rss_key, sizeof(rss_key)); memcpy(interface->rssrk, rss_key, sizeof(rss_key));
/* Start off interface as being down */ /* Start off interface as being down */
set_bit(__FM10K_DOWN, &interface->state); set_bit(__FM10K_DOWN, interface->state);
set_bit(__FM10K_UPDATING_STATS, &interface->state); set_bit(__FM10K_UPDATING_STATS, interface->state);
return 0; return 0;
} }
...@@ -2028,7 +2039,7 @@ static int fm10k_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2028,7 +2039,7 @@ static int fm10k_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
* must ensure it is disabled since we haven't yet requested the timer * must ensure it is disabled since we haven't yet requested the timer
* or work item. * or work item.
*/ */
set_bit(__FM10K_SERVICE_DISABLE, &interface->state); set_bit(__FM10K_SERVICE_DISABLE, interface->state);
err = fm10k_mbx_request_irq(interface); err = fm10k_mbx_request_irq(interface);
if (err) if (err)
...@@ -2069,7 +2080,7 @@ static int fm10k_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2069,7 +2080,7 @@ static int fm10k_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
fm10k_iov_configure(pdev, 0); fm10k_iov_configure(pdev, 0);
/* clear the service task disable bit to allow service task to start */ /* clear the service task disable bit to allow service task to start */
clear_bit(__FM10K_SERVICE_DISABLE, &interface->state); clear_bit(__FM10K_SERVICE_DISABLE, interface->state);
return 0; return 0;
...@@ -2107,7 +2118,7 @@ static void fm10k_remove(struct pci_dev *pdev) ...@@ -2107,7 +2118,7 @@ static void fm10k_remove(struct pci_dev *pdev)
del_timer_sync(&interface->service_timer); del_timer_sync(&interface->service_timer);
set_bit(__FM10K_SERVICE_DISABLE, &interface->state); set_bit(__FM10K_SERVICE_DISABLE, interface->state);
cancel_work_sync(&interface->service_task); cancel_work_sync(&interface->service_task);
/* free netdev, this may bounce the interrupts due to setup_tc */ /* free netdev, this may bounce the interrupts due to setup_tc */
...@@ -2146,7 +2157,7 @@ static void fm10k_prepare_suspend(struct fm10k_intfc *interface) ...@@ -2146,7 +2157,7 @@ static void fm10k_prepare_suspend(struct fm10k_intfc *interface)
* stopped. We stop the watchdog task until after we resume software * stopped. We stop the watchdog task until after we resume software
* activity. * activity.
*/ */
set_bit(__FM10K_SERVICE_DISABLE, &interface->state); set_bit(__FM10K_SERVICE_DISABLE, interface->state);
cancel_work_sync(&interface->service_task); cancel_work_sync(&interface->service_task);
fm10k_prepare_for_reset(interface); fm10k_prepare_for_reset(interface);
...@@ -2172,10 +2183,10 @@ static int fm10k_handle_resume(struct fm10k_intfc *interface) ...@@ -2172,10 +2183,10 @@ static int fm10k_handle_resume(struct fm10k_intfc *interface)
/* force link to stay down for a second to prevent link flutter */ /* force link to stay down for a second to prevent link flutter */
interface->link_down_event = jiffies + (HZ); interface->link_down_event = jiffies + (HZ);
set_bit(__FM10K_LINK_DOWN, &interface->state); set_bit(__FM10K_LINK_DOWN, interface->state);
/* clear the service task disable bit to allow service task to start */ /* clear the service task disable bit to allow service task to start */
clear_bit(__FM10K_SERVICE_DISABLE, &interface->state); clear_bit(__FM10K_SERVICE_DISABLE, interface->state);
fm10k_service_event_schedule(interface); fm10k_service_event_schedule(interface);
return err; return err;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册