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

net: atlantic: implement wake_phy feature



Wake on PHY allows to configure device to wakeup host
as soon as PHY link status is changed to active.

Signed-off-by: default avatarNikita Danilov <ndanilov@marvell.com>
Signed-off-by: default avatarIgor Russkikh <irusskikh@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d993e14b
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -78,6 +78,9 @@

#define AQ_CFG_FC_MODE AQ_NIC_FC_FULL

/* Default WOL modes used on initialization */
#define AQ_CFG_WOL_MODES WAKE_MAGIC

#define AQ_CFG_SPEED_MSK  0xFFFFU	/* 0xFFFFU==auto_neg */

#define AQ_CFG_IS_AUTONEG_DEF       1U
+8 −10
Original line number Diff line number Diff line
@@ -356,11 +356,8 @@ static void aq_ethtool_get_wol(struct net_device *ndev,
	struct aq_nic_s *aq_nic = netdev_priv(ndev);
	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);

	wol->supported = WAKE_MAGIC;
	wol->wolopts = 0;

	if (cfg->wol)
		wol->wolopts |= WAKE_MAGIC;
	wol->supported = AQ_NIC_WOL_MODES;
	wol->wolopts = cfg->wol;
}

static int aq_ethtool_set_wol(struct net_device *ndev,
@@ -371,11 +368,12 @@ static int aq_ethtool_set_wol(struct net_device *ndev,
	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
	int err = 0;

	if (wol->wolopts & WAKE_MAGIC)
		cfg->wol |= AQ_NIC_WOL_ENABLED;
	else
		cfg->wol &= ~AQ_NIC_WOL_ENABLED;
	err = device_set_wakeup_enable(&pdev->dev, wol->wolopts);
	if (wol->wolopts & ~AQ_NIC_WOL_MODES)
		return -EOPNOTSUPP;

	cfg->wol = wol->wolopts;

	err = device_set_wakeup_enable(&pdev->dev, !!cfg->wol);

	return err;
}
+2 −2
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ static int aq_ndev_open(struct net_device *ndev)

err_exit:
	if (err < 0)
		aq_nic_deinit(aq_nic);
		aq_nic_deinit(aq_nic, true);
	return err;
}

@@ -86,7 +86,7 @@ static int aq_ndev_close(struct net_device *ndev)
	err = aq_nic_stop(aq_nic);
	if (err < 0)
		goto err_exit;
	aq_nic_deinit(aq_nic);
	aq_nic_deinit(aq_nic, true);

err_exit:
	return err;
+19 −15
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ void aq_nic_cfg_start(struct aq_nic_s *self)
	cfg->num_rss_queues = AQ_CFG_NUM_RSS_QUEUES_DEF;
	cfg->aq_rss.base_cpu_number = AQ_CFG_RSS_BASE_CPU_NUM_DEF;
	cfg->flow_control = AQ_CFG_FC_MODE;
	cfg->wol = AQ_CFG_WOL_MODES;

	cfg->mtu = AQ_CFG_MTU_DEF;
	cfg->link_speed_msk = AQ_CFG_SPEED_MSK;
@@ -1000,7 +1001,20 @@ int aq_nic_stop(struct aq_nic_s *self)
	return self->aq_hw_ops->hw_stop(self->aq_hw);
}

void aq_nic_deinit(struct aq_nic_s *self)
void aq_nic_set_power(struct aq_nic_s *self)
{
	if (self->power_state != AQ_HW_POWER_STATE_D0 ||
	    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);
		}
}

void aq_nic_deinit(struct aq_nic_s *self, bool link_down)
{
	struct aq_vec_s *aq_vec = NULL;
	unsigned int i = 0U;
@@ -1017,23 +1031,12 @@ void aq_nic_deinit(struct aq_nic_s *self)
	aq_ptp_ring_free(self);
	aq_ptp_free(self);

	if (likely(self->aq_fw_ops->deinit)) {
	if (likely(self->aq_fw_ops->deinit) && link_down) {
		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)
		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:;
}

@@ -1072,7 +1075,7 @@ int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg)
		if (err < 0)
			goto err_exit;

		aq_nic_deinit(self);
		aq_nic_deinit(self, !self->aq_hw->aq_nic_cfg->wol);
	} else {
		err = aq_nic_init(self);
		if (err < 0)
@@ -1108,7 +1111,8 @@ void aq_nic_shutdown(struct aq_nic_s *self)
		if (err < 0)
			goto err_exit;
	}
	aq_nic_deinit(self);
	aq_nic_deinit(self, !self->aq_hw->aq_nic_cfg->wol);
	aq_nic_set_power(self);

err_exit:
	rtnl_unlock();
+4 −2
Original line number Diff line number Diff line
@@ -60,7 +60,8 @@ struct aq_nic_cfg_s {
#define AQ_NIC_FLAG_ERR_UNPLUG  0x40000000U
#define AQ_NIC_FLAG_ERR_HW      0x80000000U

#define AQ_NIC_WOL_ENABLED	BIT(0)
#define AQ_NIC_WOL_MODES        (WAKE_MAGIC |\
				 WAKE_PHY)

#define AQ_NIC_TCVEC2RING(_NIC_, _TC_, _VEC_) \
	((_TC_) * AQ_CFG_TCS_MAX + (_VEC_))
@@ -141,7 +142,8 @@ int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p);
int aq_nic_get_regs_count(struct aq_nic_s *self);
void aq_nic_get_stats(struct aq_nic_s *self, u64 *data);
int aq_nic_stop(struct aq_nic_s *self);
void aq_nic_deinit(struct aq_nic_s *self);
void aq_nic_deinit(struct aq_nic_s *self, bool link_down);
void aq_nic_set_power(struct aq_nic_s *self);
void aq_nic_free_hot_resources(struct aq_nic_s *self);
void aq_nic_free_vectors(struct aq_nic_s *self);
int aq_nic_set_mtu(struct aq_nic_s *self, int new_mtu);
Loading