|
@@ -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,
|
|
@@ -93,18 +93,29 @@ static int fm10k_hw_ready(struct fm10k_intfc *interface)
|
|
|
|
|
|
void fm10k_service_event_schedule(struct fm10k_intfc *interface)
|
|
|
{
|
|
|
- if (!test_bit(__FM10K_SERVICE_DISABLE, &interface->state) &&
|
|
|
- !test_and_set_bit(__FM10K_SERVICE_SCHED, &interface->state))
|
|
|
+ if (!test_bit(__FM10K_SERVICE_DISABLE, 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);
|
|
|
+ } else {
|
|
|
+ set_bit(__FM10K_SERVICE_REQUEST, interface->state);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
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 */
|
|
|
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)
|
|
|
if (~value) {
|
|
|
interface->hw.hw_addr = interface->uc_addr;
|
|
|
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");
|
|
|
return;
|
|
|
}
|
|
@@ -159,7 +170,7 @@ static void fm10k_prepare_for_reset(struct fm10k_intfc *interface)
|
|
|
/* put off any impending NetWatchDogTimeout */
|
|
|
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);
|
|
|
|
|
|
rtnl_lock();
|
|
@@ -242,7 +253,7 @@ static int fm10k_handle_reset(struct fm10k_intfc *interface)
|
|
|
|
|
|
rtnl_unlock();
|
|
|
|
|
|
- clear_bit(__FM10K_RESETTING, &interface->state);
|
|
|
+ clear_bit(__FM10K_RESETTING, interface->state);
|
|
|
|
|
|
return err;
|
|
|
err_open:
|
|
@@ -254,7 +265,7 @@ reinit_err:
|
|
|
|
|
|
rtnl_unlock();
|
|
|
|
|
|
- clear_bit(__FM10K_RESETTING, &interface->state);
|
|
|
+ clear_bit(__FM10K_RESETTING, interface->state);
|
|
|
|
|
|
return err;
|
|
|
}
|
|
@@ -273,11 +284,10 @@ static void fm10k_reinit(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;
|
|
|
|
|
|
- interface->flags &= ~FM10K_FLAG_RESET_REQUESTED;
|
|
|
-
|
|
|
netdev_err(interface->netdev, "Reset interface\n");
|
|
|
|
|
|
fm10k_reinit(interface);
|
|
@@ -296,7 +306,7 @@ static void fm10k_configure_swpri_map(struct fm10k_intfc *interface)
|
|
|
int i;
|
|
|
|
|
|
/* 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 */
|
|
|
if (hw->mac.type != fm10k_mac_pf)
|
|
@@ -317,14 +327,14 @@ static void fm10k_watchdog_update_host_state(struct fm10k_intfc *interface)
|
|
|
struct fm10k_hw *hw = &interface->hw;
|
|
|
s32 err;
|
|
|
|
|
|
- if (test_bit(__FM10K_LINK_DOWN, &interface->state)) {
|
|
|
+ if (test_bit(__FM10K_LINK_DOWN, interface->state)) {
|
|
|
interface->host_ready = false;
|
|
|
if (time_is_after_jiffies(interface->link_down_event))
|
|
|
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()) {
|
|
|
fm10k_configure_swpri_map(interface);
|
|
|
rtnl_unlock();
|
|
@@ -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);
|
|
|
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 */
|
|
|
fm10k_mbx_unlock(interface);
|
|
@@ -412,7 +422,7 @@ void fm10k_update_stats(struct fm10k_intfc *interface)
|
|
|
int i;
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
/* do not allow stats update via service task for next second */
|
|
@@ -493,7 +503,7 @@ void fm10k_update_stats(struct fm10k_intfc *interface)
|
|
|
net_stats->rx_errors = rx_errors;
|
|
|
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)
|
|
|
* controller to flush Tx.
|
|
|
*/
|
|
|
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)
|
|
|
static void fm10k_watchdog_subtask(struct fm10k_intfc *interface)
|
|
|
{
|
|
|
/* if interface is down do nothing */
|
|
|
- if (test_bit(__FM10K_DOWN, &interface->state) ||
|
|
|
- test_bit(__FM10K_RESETTING, &interface->state))
|
|
|
+ if (test_bit(__FM10K_DOWN, interface->state) ||
|
|
|
+ test_bit(__FM10K_RESETTING, interface->state))
|
|
|
return;
|
|
|
|
|
|
if (interface->host_ready)
|
|
@@ -564,8 +574,8 @@ static void fm10k_check_hang_subtask(struct fm10k_intfc *interface)
|
|
|
int i;
|
|
|
|
|
|
/* If we're down or resetting, just bail */
|
|
|
- if (test_bit(__FM10K_DOWN, &interface->state) ||
|
|
|
- test_bit(__FM10K_RESETTING, &interface->state))
|
|
|
+ if (test_bit(__FM10K_DOWN, interface->state) ||
|
|
|
+ test_bit(__FM10K_RESETTING, interface->state))
|
|
|
return;
|
|
|
|
|
|
/* 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,
|
|
|
FM10K_PFVTCTL_FTAG_DESC_ENABLE);
|
|
|
|
|
|
/* 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)
|
|
|
netif_set_xps_queue(ring->netdev,
|
|
|
&ring->q_vector->affinity_mask,
|
|
@@ -744,6 +754,7 @@ static void fm10k_configure_rx_ring(struct fm10k_intfc *interface,
|
|
|
/* disable queue to avoid issues while updating state */
|
|
|
rxqctl = fm10k_read_reg(hw, FM10K_RXQCTL(reg_idx));
|
|
|
rxqctl &= ~FM10K_RXQCTL_ENABLE;
|
|
|
+ fm10k_write_reg(hw, FM10K_RXQCTL(reg_idx), rxqctl);
|
|
|
fm10k_write_flush(hw);
|
|
|
|
|
|
/* possible poll here to verify ring resources have been cleaned */
|
|
@@ -864,9 +875,9 @@ static void fm10k_configure_dglort(struct fm10k_intfc *interface)
|
|
|
FM10K_MRQC_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;
|
|
|
- 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;
|
|
|
|
|
|
fm10k_write_reg(hw, FM10K_MRQC(0), mrqc);
|
|
@@ -981,7 +992,7 @@ void fm10k_netpoll(struct net_device *netdev)
|
|
|
int i;
|
|
|
|
|
|
/* if interface is down do nothing */
|
|
|
- if (test_bit(__FM10K_DOWN, &interface->state))
|
|
|
+ if (test_bit(__FM10K_DOWN, interface->state))
|
|
|
return;
|
|
|
|
|
|
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)
|
|
|
}
|
|
|
|
|
|
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 (eicr & FM10K_EICR_SWITCHNOTREADY) {
|
|
|
/* force link down for at least 4 seconds */
|
|
|
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 */
|
|
|
hw->mac.dglort_map = FM10K_DGLORTMAP_NONE;
|
|
@@ -1247,12 +1258,12 @@ static s32 fm10k_mbx_mac_addr(struct fm10k_hw *hw, u32 **results,
|
|
|
/* MAC was changed so we need reset */
|
|
|
if (is_valid_ether_addr(hw->mac.perm_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 */
|
|
|
if ((vlan_override != hw->mac.vlan_override) ||
|
|
|
(default_vid != hw->mac.default_vid))
|
|
|
- interface->flags |= FM10K_FLAG_RESET_REQUESTED;
|
|
|
+ set_bit(FM10K_FLAG_RESET_REQUESTED, interface->flags);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -1326,7 +1337,7 @@ static s32 fm10k_lport_map(struct fm10k_hw *hw, u32 **results,
|
|
|
if (!err && hw->swapi.status) {
|
|
|
/* force link down for a reasonable delay */
|
|
|
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 */
|
|
|
hw->mac.dglort_map = FM10K_DGLORTMAP_NONE;
|
|
@@ -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 */
|
|
|
if (dglort_map != hw->mac.dglort_map)
|
|
|
- interface->flags |= FM10K_FLAG_RESET_REQUESTED;
|
|
|
+ set_bit(FM10K_FLAG_RESET_REQUESTED, interface->flags);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -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 */
|
|
|
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;
|
|
|
|
|
@@ -1624,10 +1635,10 @@ void fm10k_up(struct fm10k_intfc *interface)
|
|
|
hw->mac.ops.update_int_moderator(hw);
|
|
|
|
|
|
/* 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_bit(__FM10K_DOWN, &interface->state);
|
|
|
+ clear_bit(__FM10K_DOWN, interface->state);
|
|
|
|
|
|
/* enable polling cleanups */
|
|
|
fm10k_napi_enable_all(interface);
|
|
@@ -1661,7 +1672,7 @@ void fm10k_down(struct fm10k_intfc *interface)
|
|
|
int err, i = 0, count = 0;
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
/* call carrier off first to avoid false dev_watchdog timeouts */
|
|
@@ -1681,7 +1692,7 @@ void fm10k_down(struct fm10k_intfc *interface)
|
|
|
fm10k_update_stats(interface);
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
/* skip waiting for TX DMA if we lost PCIe link */
|
|
@@ -1850,8 +1861,8 @@ static int fm10k_sw_init(struct fm10k_intfc *interface,
|
|
|
memcpy(interface->rssrk, rss_key, sizeof(rss_key));
|
|
|
|
|
|
/* Start off interface as being down */
|
|
|
- set_bit(__FM10K_DOWN, &interface->state);
|
|
|
- set_bit(__FM10K_UPDATING_STATS, &interface->state);
|
|
|
+ set_bit(__FM10K_DOWN, interface->state);
|
|
|
+ set_bit(__FM10K_UPDATING_STATS, interface->state);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -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
|
|
|
* or work item.
|
|
|
*/
|
|
|
- set_bit(__FM10K_SERVICE_DISABLE, &interface->state);
|
|
|
+ set_bit(__FM10K_SERVICE_DISABLE, interface->state);
|
|
|
|
|
|
err = fm10k_mbx_request_irq(interface);
|
|
|
if (err)
|
|
@@ -2069,7 +2080,7 @@ static int fm10k_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
fm10k_iov_configure(pdev, 0);
|
|
|
|
|
|
/* 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;
|
|
|
|
|
@@ -2107,7 +2118,7 @@ static void fm10k_remove(struct pci_dev *pdev)
|
|
|
|
|
|
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);
|
|
|
|
|
|
/* free netdev, this may bounce the interrupts due to setup_tc */
|
|
@@ -2146,7 +2157,7 @@ static void fm10k_prepare_suspend(struct fm10k_intfc *interface)
|
|
|
* stopped. We stop the watchdog task until after we resume software
|
|
|
* activity.
|
|
|
*/
|
|
|
- set_bit(__FM10K_SERVICE_DISABLE, &interface->state);
|
|
|
+ set_bit(__FM10K_SERVICE_DISABLE, interface->state);
|
|
|
cancel_work_sync(&interface->service_task);
|
|
|
|
|
|
fm10k_prepare_for_reset(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 */
|
|
|
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_bit(__FM10K_SERVICE_DISABLE, &interface->state);
|
|
|
+ clear_bit(__FM10K_SERVICE_DISABLE, interface->state);
|
|
|
fm10k_service_event_schedule(interface);
|
|
|
|
|
|
return err;
|