Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+18 −4
Original line number Original line Diff line number Diff line
@@ -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)
		     !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)
		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,
	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;
}
}
+20 −6
Original line number Original line Diff line number Diff line
@@ -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)
	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,
		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)
		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:;
}
}


+2 −0
Original line number Original line Diff line number Diff line
@@ -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;
};
};


+2 −0
Original line number Original line Diff line number Diff line
@@ -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)