Commit f5dce08a authored by Nikita Danilov's avatar Nikita Danilov Committed by David S. Miller

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: default avatarNikita Danilov <ndanilov@aquantia.com>
Signed-off-by: default avatarIgor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 18eac376
...@@ -405,8 +405,10 @@ static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee) ...@@ -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) if (!aq_nic->aq_fw_ops->get_eee_rate)
return -EOPNOTSUPP; return -EOPNOTSUPP;
mutex_lock(&aq_nic->fwreq_mutex);
err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate, err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
&supported_rates); &supported_rates);
mutex_unlock(&aq_nic->fwreq_mutex);
if (err < 0) if (err < 0)
return err; return err;
...@@ -439,8 +441,10 @@ static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee) ...@@ -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)) !aq_nic->aq_fw_ops->set_eee_rate))
return -EOPNOTSUPP; return -EOPNOTSUPP;
mutex_lock(&aq_nic->fwreq_mutex);
err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate, err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
&supported_rates); &supported_rates);
mutex_unlock(&aq_nic->fwreq_mutex);
if (err < 0) if (err < 0)
return err; return err;
...@@ -452,20 +456,28 @@ static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee) ...@@ -452,20 +456,28 @@ static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
cfg->eee_speeds = 0; 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) static int aq_ethtool_nway_reset(struct net_device *ndev)
{ {
struct aq_nic_s *aq_nic = netdev_priv(ndev); struct aq_nic_s *aq_nic = netdev_priv(ndev);
int err = 0;
if (unlikely(!aq_nic->aq_fw_ops->renegotiate)) if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (netif_running(ndev)) if (netif_running(ndev)) {
return aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw); 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, static void aq_ethtool_get_pauseparam(struct net_device *ndev,
...@@ -503,7 +515,9 @@ static int aq_ethtool_set_pauseparam(struct net_device *ndev, ...@@ -503,7 +515,9 @@ static int aq_ethtool_set_pauseparam(struct net_device *ndev,
else else
aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_TX; 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); err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
mutex_unlock(&aq_nic->fwreq_mutex);
return err; return err;
} }
......
...@@ -234,8 +234,10 @@ int aq_nic_ndev_register(struct aq_nic_s *self) ...@@ -234,8 +234,10 @@ int aq_nic_ndev_register(struct aq_nic_s *self)
if (err) if (err)
goto err_exit; goto err_exit;
mutex_lock(&self->fwreq_mutex);
err = self->aq_fw_ops->get_mac_permanent(self->aq_hw, err = self->aq_fw_ops->get_mac_permanent(self->aq_hw,
self->ndev->dev_addr); self->ndev->dev_addr);
mutex_unlock(&self->fwreq_mutex);
if (err) if (err)
goto err_exit; goto err_exit;
...@@ -304,7 +306,9 @@ int aq_nic_init(struct aq_nic_s *self) ...@@ -304,7 +306,9 @@ int aq_nic_init(struct aq_nic_s *self)
unsigned int i = 0U; unsigned int i = 0U;
self->power_state = AQ_HW_POWER_STATE_D0; self->power_state = AQ_HW_POWER_STATE_D0;
mutex_lock(&self->fwreq_mutex);
err = self->aq_hw_ops->hw_reset(self->aq_hw); err = self->aq_hw_ops->hw_reset(self->aq_hw);
mutex_unlock(&self->fwreq_mutex);
if (err < 0) if (err < 0)
goto err_exit; goto err_exit;
...@@ -871,7 +875,9 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self, ...@@ -871,7 +875,9 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self,
self->aq_nic_cfg.is_autoneg = false; self->aq_nic_cfg.is_autoneg = false;
} }
mutex_lock(&self->fwreq_mutex);
err = self->aq_fw_ops->set_link_speed(self->aq_hw, rate); err = self->aq_fw_ops->set_link_speed(self->aq_hw, rate);
mutex_unlock(&self->fwreq_mutex);
if (err < 0) if (err < 0)
goto err_exit; goto err_exit;
...@@ -931,15 +937,23 @@ void aq_nic_deinit(struct aq_nic_s *self) ...@@ -931,15 +937,23 @@ void aq_nic_deinit(struct aq_nic_s *self)
self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i])
aq_vec_deinit(aq_vec); aq_vec_deinit(aq_vec);
if (likely(self->aq_fw_ops->deinit)) {
mutex_lock(&self->fwreq_mutex);
self->aq_fw_ops->deinit(self->aq_hw); self->aq_fw_ops->deinit(self->aq_hw);
mutex_unlock(&self->fwreq_mutex);
}
if (self->power_state != AQ_HW_POWER_STATE_D0 || if (self->power_state != AQ_HW_POWER_STATE_D0 ||
self->aq_hw->aq_nic_cfg->wol) { 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->aq_fw_ops->set_power(self->aq_hw,
self->power_state, self->power_state,
self->ndev->dev_addr); self->ndev->dev_addr);
mutex_unlock(&self->fwreq_mutex);
} }
err_exit:; err_exit:;
} }
......
...@@ -105,6 +105,8 @@ struct aq_nic_s { ...@@ -105,6 +105,8 @@ struct aq_nic_s {
struct pci_dev *pdev; struct pci_dev *pdev;
unsigned int msix_entry_mask; unsigned int msix_entry_mask;
u32 irqvecs; u32 irqvecs;
/* mutex to serialize FW interface access operations */
struct mutex fwreq_mutex;
struct aq_hw_rx_fltrs_s aq_hw_rx_fltrs; struct aq_hw_rx_fltrs_s aq_hw_rx_fltrs;
}; };
......
...@@ -231,6 +231,8 @@ static int aq_pci_probe(struct pci_dev *pdev, ...@@ -231,6 +231,8 @@ static int aq_pci_probe(struct pci_dev *pdev,
SET_NETDEV_DEV(ndev, &pdev->dev); SET_NETDEV_DEV(ndev, &pdev->dev);
pci_set_drvdata(pdev, self); pci_set_drvdata(pdev, self);
mutex_init(&self->fwreq_mutex);
err = aq_pci_probe_get_hw_by_id(pdev, &self->aq_hw_ops, err = aq_pci_probe_get_hw_by_id(pdev, &self->aq_hw_ops,
&aq_nic_get_cfg(self)->aq_hw_caps); &aq_nic_get_cfg(self)->aq_hw_caps);
if (err) if (err)
......
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