Commit bc672d49 authored by David S. Miller's avatar David S. Miller

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

Tony Nguyen says:

====================
40GbE Intel Wired LAN Driver Updates 2021-07-19

This series contains updates to iavf and i40e drivers.

Stefan Assmann adds locking to a path that does not acquire a spinlock
where needed for i40e. He also adjusts locking of critical sections to
help avoid races and removes overriding of the adapter state during
pending reset for iavf driver.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e4b1dc43 226d5285
...@@ -1160,12 +1160,12 @@ static int i40e_quiesce_vf_pci(struct i40e_vf *vf) ...@@ -1160,12 +1160,12 @@ static int i40e_quiesce_vf_pci(struct i40e_vf *vf)
} }
/** /**
* i40e_getnum_vf_vsi_vlan_filters * __i40e_getnum_vf_vsi_vlan_filters
* @vsi: pointer to the vsi * @vsi: pointer to the vsi
* *
* called to get the number of VLANs offloaded on this VF * called to get the number of VLANs offloaded on this VF
**/ **/
static int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi) static int __i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi)
{ {
struct i40e_mac_filter *f; struct i40e_mac_filter *f;
u16 num_vlans = 0, bkt; u16 num_vlans = 0, bkt;
...@@ -1178,6 +1178,23 @@ static int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi) ...@@ -1178,6 +1178,23 @@ static int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi)
return num_vlans; return num_vlans;
} }
/**
* i40e_getnum_vf_vsi_vlan_filters
* @vsi: pointer to the vsi
*
* wrapper for __i40e_getnum_vf_vsi_vlan_filters() with spinlock held
**/
static int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi)
{
int num_vlans;
spin_lock_bh(&vsi->mac_filter_hash_lock);
num_vlans = __i40e_getnum_vf_vsi_vlan_filters(vsi);
spin_unlock_bh(&vsi->mac_filter_hash_lock);
return num_vlans;
}
/** /**
* i40e_get_vlan_list_sync * i40e_get_vlan_list_sync
* @vsi: pointer to the VSI * @vsi: pointer to the VSI
...@@ -1195,7 +1212,7 @@ static void i40e_get_vlan_list_sync(struct i40e_vsi *vsi, u16 *num_vlans, ...@@ -1195,7 +1212,7 @@ static void i40e_get_vlan_list_sync(struct i40e_vsi *vsi, u16 *num_vlans,
int bkt; int bkt;
spin_lock_bh(&vsi->mac_filter_hash_lock); spin_lock_bh(&vsi->mac_filter_hash_lock);
*num_vlans = i40e_getnum_vf_vsi_vlan_filters(vsi); *num_vlans = __i40e_getnum_vf_vsi_vlan_filters(vsi);
*vlan_list = kcalloc(*num_vlans, sizeof(**vlan_list), GFP_ATOMIC); *vlan_list = kcalloc(*num_vlans, sizeof(**vlan_list), GFP_ATOMIC);
if (!(*vlan_list)) if (!(*vlan_list))
goto err; goto err;
......
...@@ -131,6 +131,30 @@ enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw, ...@@ -131,6 +131,30 @@ enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw,
return 0; return 0;
} }
/**
* iavf_lock_timeout - try to set bit but give up after timeout
* @adapter: board private structure
* @bit: bit to set
* @msecs: timeout in msecs
*
* Returns 0 on success, negative on failure
**/
static int iavf_lock_timeout(struct iavf_adapter *adapter,
enum iavf_critical_section_t bit,
unsigned int msecs)
{
unsigned int wait, delay = 10;
for (wait = 0; wait < msecs; wait += delay) {
if (!test_and_set_bit(bit, &adapter->crit_section))
return 0;
msleep(delay);
}
return -1;
}
/** /**
* iavf_schedule_reset - Set the flags and schedule a reset event * iavf_schedule_reset - Set the flags and schedule a reset event
* @adapter: board private structure * @adapter: board private structure
...@@ -1988,7 +2012,6 @@ static void iavf_watchdog_task(struct work_struct *work) ...@@ -1988,7 +2012,6 @@ static void iavf_watchdog_task(struct work_struct *work)
/* check for hw reset */ /* check for hw reset */
reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK; reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK;
if (!reg_val) { if (!reg_val) {
adapter->state = __IAVF_RESETTING;
adapter->flags |= IAVF_FLAG_RESET_PENDING; adapter->flags |= IAVF_FLAG_RESET_PENDING;
adapter->aq_required = 0; adapter->aq_required = 0;
adapter->current_op = VIRTCHNL_OP_UNKNOWN; adapter->current_op = VIRTCHNL_OP_UNKNOWN;
...@@ -2102,6 +2125,10 @@ static void iavf_reset_task(struct work_struct *work) ...@@ -2102,6 +2125,10 @@ static void iavf_reset_task(struct work_struct *work)
if (test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section)) if (test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
return; return;
if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 200)) {
schedule_work(&adapter->reset_task);
return;
}
while (test_and_set_bit(__IAVF_IN_CLIENT_TASK, while (test_and_set_bit(__IAVF_IN_CLIENT_TASK,
&adapter->crit_section)) &adapter->crit_section))
usleep_range(500, 1000); usleep_range(500, 1000);
...@@ -2308,6 +2335,8 @@ static void iavf_adminq_task(struct work_struct *work) ...@@ -2308,6 +2335,8 @@ static void iavf_adminq_task(struct work_struct *work)
if (!event.msg_buf) if (!event.msg_buf)
goto out; goto out;
if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 200))
goto freedom;
do { do {
ret = iavf_clean_arq_element(hw, &event, &pending); ret = iavf_clean_arq_element(hw, &event, &pending);
v_op = (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high); v_op = (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);
...@@ -2321,6 +2350,7 @@ static void iavf_adminq_task(struct work_struct *work) ...@@ -2321,6 +2350,7 @@ static void iavf_adminq_task(struct work_struct *work)
if (pending != 0) if (pending != 0)
memset(event.msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE); memset(event.msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE);
} while (pending); } while (pending);
clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
if ((adapter->flags & if ((adapter->flags &
(IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) || (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) ||
...@@ -3625,6 +3655,10 @@ static void iavf_init_task(struct work_struct *work) ...@@ -3625,6 +3655,10 @@ static void iavf_init_task(struct work_struct *work)
init_task.work); init_task.work);
struct iavf_hw *hw = &adapter->hw; struct iavf_hw *hw = &adapter->hw;
if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 5000)) {
dev_warn(&adapter->pdev->dev, "failed to set __IAVF_IN_CRITICAL_TASK in %s\n", __FUNCTION__);
return;
}
switch (adapter->state) { switch (adapter->state) {
case __IAVF_STARTUP: case __IAVF_STARTUP:
if (iavf_startup(adapter) < 0) if (iavf_startup(adapter) < 0)
...@@ -3637,14 +3671,14 @@ static void iavf_init_task(struct work_struct *work) ...@@ -3637,14 +3671,14 @@ static void iavf_init_task(struct work_struct *work)
case __IAVF_INIT_GET_RESOURCES: case __IAVF_INIT_GET_RESOURCES:
if (iavf_init_get_resources(adapter) < 0) if (iavf_init_get_resources(adapter) < 0)
goto init_failed; goto init_failed;
return; goto out;
default: default:
goto init_failed; goto init_failed;
} }
queue_delayed_work(iavf_wq, &adapter->init_task, queue_delayed_work(iavf_wq, &adapter->init_task,
msecs_to_jiffies(30)); msecs_to_jiffies(30));
return; goto out;
init_failed: init_failed:
if (++adapter->aq_wait_count > IAVF_AQ_MAX_ERR) { if (++adapter->aq_wait_count > IAVF_AQ_MAX_ERR) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
...@@ -3653,9 +3687,11 @@ static void iavf_init_task(struct work_struct *work) ...@@ -3653,9 +3687,11 @@ static void iavf_init_task(struct work_struct *work)
iavf_shutdown_adminq(hw); iavf_shutdown_adminq(hw);
adapter->state = __IAVF_STARTUP; adapter->state = __IAVF_STARTUP;
queue_delayed_work(iavf_wq, &adapter->init_task, HZ * 5); queue_delayed_work(iavf_wq, &adapter->init_task, HZ * 5);
return; goto out;
} }
queue_delayed_work(iavf_wq, &adapter->init_task, HZ); queue_delayed_work(iavf_wq, &adapter->init_task, HZ);
out:
clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
} }
/** /**
...@@ -3672,9 +3708,12 @@ static void iavf_shutdown(struct pci_dev *pdev) ...@@ -3672,9 +3708,12 @@ static void iavf_shutdown(struct pci_dev *pdev)
if (netif_running(netdev)) if (netif_running(netdev))
iavf_close(netdev); iavf_close(netdev);
if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 5000))
dev_warn(&adapter->pdev->dev, "failed to set __IAVF_IN_CRITICAL_TASK in %s\n", __FUNCTION__);
/* Prevent the watchdog from running. */ /* Prevent the watchdog from running. */
adapter->state = __IAVF_REMOVE; adapter->state = __IAVF_REMOVE;
adapter->aq_required = 0; adapter->aq_required = 0;
clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
#ifdef CONFIG_PM #ifdef CONFIG_PM
pci_save_state(pdev); pci_save_state(pdev);
...@@ -3908,10 +3947,6 @@ static void iavf_remove(struct pci_dev *pdev) ...@@ -3908,10 +3947,6 @@ static void iavf_remove(struct pci_dev *pdev)
err); err);
} }
/* Shut down all the garbage mashers on the detention level */
adapter->state = __IAVF_REMOVE;
adapter->aq_required = 0;
adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
iavf_request_reset(adapter); iavf_request_reset(adapter);
msleep(50); msleep(50);
/* If the FW isn't responding, kick it once, but only once. */ /* If the FW isn't responding, kick it once, but only once. */
...@@ -3919,6 +3954,13 @@ static void iavf_remove(struct pci_dev *pdev) ...@@ -3919,6 +3954,13 @@ static void iavf_remove(struct pci_dev *pdev)
iavf_request_reset(adapter); iavf_request_reset(adapter);
msleep(50); msleep(50);
} }
if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 5000))
dev_warn(&adapter->pdev->dev, "failed to set __IAVF_IN_CRITICAL_TASK in %s\n", __FUNCTION__);
/* Shut down all the garbage mashers on the detention level */
adapter->state = __IAVF_REMOVE;
adapter->aq_required = 0;
adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
iavf_free_all_tx_resources(adapter); iavf_free_all_tx_resources(adapter);
iavf_free_all_rx_resources(adapter); iavf_free_all_rx_resources(adapter);
iavf_misc_irq_disable(adapter); iavf_misc_irq_disable(adapter);
......
...@@ -326,11 +326,9 @@ static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev) ...@@ -326,11 +326,9 @@ static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev)
static int dp8382x_disable_wol(struct phy_device *phydev) static int dp8382x_disable_wol(struct phy_device *phydev)
{ {
int value = DP83822_WOL_EN | DP83822_WOL_MAGIC_EN | return phy_clear_bits_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
DP83822_WOL_SECURE_ON; DP83822_WOL_EN | DP83822_WOL_MAGIC_EN |
DP83822_WOL_SECURE_ON);
return phy_clear_bits_mmd(phydev, DP83822_DEVADDR,
MII_DP83822_WOL_CFG, value);
} }
static int dp83822_read_status(struct phy_device *phydev) static int dp83822_read_status(struct phy_device *phydev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment