net: aquantia: introduce fwreq mutex
Some of FW operations could be invoked simultaneously, from f.e. ethtool context and from service service activity work. Here we introduce a fw mutex to secure and serialize access to FW logic. Signed-off-by: Nikita Danilov <ndanilov@aquantia.com> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
18eac376ed
Коммит
f5dce08ab1
|
@ -405,8 +405,10 @@ static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee)
|
|||
if (!aq_nic->aq_fw_ops->get_eee_rate)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&aq_nic->fwreq_mutex);
|
||||
err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
|
||||
&supported_rates);
|
||||
mutex_unlock(&aq_nic->fwreq_mutex);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -439,8 +441,10 @@ static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
|
|||
!aq_nic->aq_fw_ops->set_eee_rate))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&aq_nic->fwreq_mutex);
|
||||
err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
|
||||
&supported_rates);
|
||||
mutex_unlock(&aq_nic->fwreq_mutex);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -452,20 +456,28 @@ static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
|
|||
cfg->eee_speeds = 0;
|
||||
}
|
||||
|
||||
return aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
|
||||
mutex_lock(&aq_nic->fwreq_mutex);
|
||||
err = aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
|
||||
mutex_unlock(&aq_nic->fwreq_mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int aq_ethtool_nway_reset(struct net_device *ndev)
|
||||
{
|
||||
struct aq_nic_s *aq_nic = netdev_priv(ndev);
|
||||
int err = 0;
|
||||
|
||||
if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (netif_running(ndev))
|
||||
return aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
|
||||
if (netif_running(ndev)) {
|
||||
mutex_lock(&aq_nic->fwreq_mutex);
|
||||
err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
|
||||
mutex_unlock(&aq_nic->fwreq_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static void aq_ethtool_get_pauseparam(struct net_device *ndev,
|
||||
|
@ -503,7 +515,9 @@ static int aq_ethtool_set_pauseparam(struct net_device *ndev,
|
|||
else
|
||||
aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_TX;
|
||||
|
||||
mutex_lock(&aq_nic->fwreq_mutex);
|
||||
err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
|
||||
mutex_unlock(&aq_nic->fwreq_mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -234,8 +234,10 @@ int aq_nic_ndev_register(struct aq_nic_s *self)
|
|||
if (err)
|
||||
goto err_exit;
|
||||
|
||||
mutex_lock(&self->fwreq_mutex);
|
||||
err = self->aq_fw_ops->get_mac_permanent(self->aq_hw,
|
||||
self->ndev->dev_addr);
|
||||
mutex_unlock(&self->fwreq_mutex);
|
||||
if (err)
|
||||
goto err_exit;
|
||||
|
||||
|
@ -304,7 +306,9 @@ int aq_nic_init(struct aq_nic_s *self)
|
|||
unsigned int i = 0U;
|
||||
|
||||
self->power_state = AQ_HW_POWER_STATE_D0;
|
||||
mutex_lock(&self->fwreq_mutex);
|
||||
err = self->aq_hw_ops->hw_reset(self->aq_hw);
|
||||
mutex_unlock(&self->fwreq_mutex);
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
|
||||
|
@ -871,7 +875,9 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self,
|
|||
self->aq_nic_cfg.is_autoneg = false;
|
||||
}
|
||||
|
||||
mutex_lock(&self->fwreq_mutex);
|
||||
err = self->aq_fw_ops->set_link_speed(self->aq_hw, rate);
|
||||
mutex_unlock(&self->fwreq_mutex);
|
||||
if (err < 0)
|
||||
goto err_exit;
|
||||
|
||||
|
@ -931,14 +937,22 @@ void aq_nic_deinit(struct aq_nic_s *self)
|
|||
self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i])
|
||||
aq_vec_deinit(aq_vec);
|
||||
|
||||
self->aq_fw_ops->deinit(self->aq_hw);
|
||||
if (likely(self->aq_fw_ops->deinit)) {
|
||||
mutex_lock(&self->fwreq_mutex);
|
||||
self->aq_fw_ops->deinit(self->aq_hw);
|
||||
mutex_unlock(&self->fwreq_mutex);
|
||||
}
|
||||
|
||||
if (self->power_state != AQ_HW_POWER_STATE_D0 ||
|
||||
self->aq_hw->aq_nic_cfg->wol) {
|
||||
self->aq_fw_ops->set_power(self->aq_hw,
|
||||
self->power_state,
|
||||
self->ndev->dev_addr);
|
||||
}
|
||||
self->aq_hw->aq_nic_cfg->wol)
|
||||
if (likely(self->aq_fw_ops->set_power)) {
|
||||
mutex_lock(&self->fwreq_mutex);
|
||||
self->aq_fw_ops->set_power(self->aq_hw,
|
||||
self->power_state,
|
||||
self->ndev->dev_addr);
|
||||
mutex_unlock(&self->fwreq_mutex);
|
||||
}
|
||||
|
||||
|
||||
err_exit:;
|
||||
}
|
||||
|
|
|
@ -105,6 +105,8 @@ struct aq_nic_s {
|
|||
struct pci_dev *pdev;
|
||||
unsigned int msix_entry_mask;
|
||||
u32 irqvecs;
|
||||
/* mutex to serialize FW interface access operations */
|
||||
struct mutex fwreq_mutex;
|
||||
struct aq_hw_rx_fltrs_s aq_hw_rx_fltrs;
|
||||
};
|
||||
|
||||
|
|
|
@ -231,6 +231,8 @@ static int aq_pci_probe(struct pci_dev *pdev,
|
|||
SET_NETDEV_DEV(ndev, &pdev->dev);
|
||||
pci_set_drvdata(pdev, self);
|
||||
|
||||
mutex_init(&self->fwreq_mutex);
|
||||
|
||||
err = aq_pci_probe_get_hw_by_id(pdev, &self->aq_hw_ops,
|
||||
&aq_nic_get_cfg(self)->aq_hw_caps);
|
||||
if (err)
|
||||
|
|
Загрузка…
Ссылка в новой задаче