From: Nikita Danilov <ndani...@aquantia.com>

Since fw ops may be invoked from different threads all its invocation
must be wrapped by mutex.

Signed-off-by: Nikita Danilov <ndani...@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russk...@aquantia.com>
---
 .../ethernet/aquantia/atlantic/aq_ethtool.c   | 22 +++++++++++++---
 .../net/ethernet/aquantia/atlantic/aq_nic.c   | 26 ++++++++++++++-----
 2 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c 
b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
index a718d7a1f76c..79da48094770 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
@@ -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;
 }
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c 
b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index b8f6f4129f44..454a44bb148e 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -243,8 +243,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;
 
@@ -313,7 +315,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;
 
@@ -883,7 +887,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;
 
@@ -944,14 +950,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:;
 }
-- 
2.17.1

Reply via email to