Commit 430cc484 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'dpaa2-mac-various-updates'

Ioana Ciornei says:

====================
dpaa2-mac: various updates

The first two patches of this series extends the MAC statistics support
to also work for network interfaces which have their link status handled
by firmware (TYPE_FIXED).

The next two patches are fixing a sporadic problem which happens when
the connected DPMAC object is not yet discovered by the fsl-mc bus, thus
the dpaa2-eth is not able to get a reference to it. A referred probe
will be requested in this case.

Finally, the last two patches make some cosmetic changes, mostly
removing comments and unnecessary checks.

Changes in v2:
 - replaced IS_ERR_OR_NULL() by IS_ERR() in patch 4/6
 - reworded the commit message of patch 6/6
====================

Link: https://lore.kernel.org/r/20210108090727.866283-1-ciorneiioana@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 38f7b449 14002089
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -840,6 +840,15 @@ struct fsl_mc_device *fsl_mc_get_endpoint(struct fsl_mc_device *mc_dev)
	endpoint_desc.id = endpoint2.id;
	endpoint = fsl_mc_device_lookup(&endpoint_desc, mc_bus_dev);

	/*
	 * We know that the device has an endpoint because we verified by
	 * interrogating the firmware. This is the case when the device was not
	 * yet discovered by the fsl-mc bus, thus the lookup returned NULL.
	 * Differentiate this case by returning EPROBE_DEFER.
	 */
	if (!endpoint)
		return ERR_PTR(-EPROBE_DEFER);

	return endpoint;
}
EXPORT_SYMBOL_GPL(fsl_mc_get_endpoint);
+33 −20
Original line number Diff line number Diff line
@@ -1691,7 +1691,7 @@ static int dpaa2_eth_link_state_update(struct dpaa2_eth_priv *priv)
	/* When we manage the MAC/PHY using phylink there is no need
	 * to manually update the netif_carrier.
	 */
	if (priv->mac)
	if (dpaa2_eth_is_type_phy(priv))
		goto out;

	/* Chech link state; speed / duplex changes are not treated yet */
@@ -1730,7 +1730,7 @@ static int dpaa2_eth_open(struct net_device *net_dev)
			   priv->dpbp_dev->obj_desc.id, priv->bpid);
	}

	if (!priv->mac) {
	if (!dpaa2_eth_is_type_phy(priv)) {
		/* We'll only start the txqs when the link is actually ready;
		 * make sure we don't race against the link up notification,
		 * which may come immediately after dpni_enable();
@@ -1752,7 +1752,7 @@ static int dpaa2_eth_open(struct net_device *net_dev)
		goto enable_err;
	}

	if (priv->mac)
	if (dpaa2_eth_is_type_phy(priv))
		phylink_start(priv->mac->phylink);

	return 0;
@@ -1826,11 +1826,11 @@ static int dpaa2_eth_stop(struct net_device *net_dev)
	int dpni_enabled = 0;
	int retries = 10;

	if (!priv->mac) {
	if (dpaa2_eth_is_type_phy(priv)) {
		phylink_stop(priv->mac->phylink);
	} else {
		netif_tx_stop_all_queues(net_dev);
		netif_carrier_off(net_dev);
	} else {
		phylink_stop(priv->mac->phylink);
	}

	/* On dpni_disable(), the MC firmware will:
@@ -2115,7 +2115,7 @@ static int dpaa2_eth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
	if (cmd == SIOCSHWTSTAMP)
		return dpaa2_eth_ts_ioctl(dev, rq, cmd);

	if (priv->mac)
	if (dpaa2_eth_is_type_phy(priv))
		return phylink_mii_ioctl(priv->mac->phylink, rq, cmd);

	return -EOPNOTSUPP;
@@ -4042,10 +4042,11 @@ static int dpaa2_eth_connect_mac(struct dpaa2_eth_priv *priv)

	dpni_dev = to_fsl_mc_device(priv->net_dev->dev.parent);
	dpmac_dev = fsl_mc_get_endpoint(dpni_dev);
	if (IS_ERR_OR_NULL(dpmac_dev) || dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type)
		return 0;

	if (dpaa2_mac_is_type_fixed(dpmac_dev, priv->mc_io))
	if (PTR_ERR(dpmac_dev) == -EPROBE_DEFER)
		return PTR_ERR(dpmac_dev);

	if (IS_ERR(dpmac_dev) || dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type)
		return 0;

	mac = kzalloc(sizeof(struct dpaa2_mac), GFP_KERNEL);
@@ -4056,23 +4057,35 @@ static int dpaa2_eth_connect_mac(struct dpaa2_eth_priv *priv)
	mac->mc_io = priv->mc_io;
	mac->net_dev = priv->net_dev;

	err = dpaa2_mac_open(mac);
	if (err)
		goto err_free_mac;
	priv->mac = mac;

	if (dpaa2_eth_is_type_phy(priv)) {
		err = dpaa2_mac_connect(mac);
		if (err) {
			netdev_err(priv->net_dev, "Error connecting to the MAC endpoint\n");
		kfree(mac);
		return err;
			goto err_close_mac;
		}
	}
	priv->mac = mac;

	return 0;

err_close_mac:
	dpaa2_mac_close(mac);
	priv->mac = NULL;
err_free_mac:
	kfree(mac);
	return err;
}

static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv)
{
	if (!priv->mac)
		return;

	if (dpaa2_eth_is_type_phy(priv))
		dpaa2_mac_disconnect(priv->mac);

	dpaa2_mac_close(priv->mac);
	kfree(priv->mac);
	priv->mac = NULL;
}
@@ -4101,7 +4114,7 @@ static irqreturn_t dpni_irq0_handler_thread(int irq_num, void *arg)
		dpaa2_eth_update_tx_fqids(priv);

		rtnl_lock();
		if (priv->mac)
		if (dpaa2_eth_has_mac(priv))
			dpaa2_eth_disconnect_mac(priv);
		else
			dpaa2_eth_connect_mac(priv);
+13 −0
Original line number Diff line number Diff line
@@ -693,6 +693,19 @@ static inline unsigned int dpaa2_eth_rx_head_room(struct dpaa2_eth_priv *priv)
	return priv->tx_data_offset - DPAA2_ETH_RX_HWA_SIZE;
}

static inline bool dpaa2_eth_is_type_phy(struct dpaa2_eth_priv *priv)
{
	if (priv->mac && priv->mac->attr.link_type == DPMAC_LINK_TYPE_PHY)
		return true;

	return false;
}

static inline bool dpaa2_eth_has_mac(struct dpaa2_eth_priv *priv)
{
	return priv->mac ? true : false;
}

int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags);
int dpaa2_eth_set_cls(struct net_device *net_dev, u64 key);
int dpaa2_eth_cls_key_size(u64 key);
+8 −8
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ static int dpaa2_eth_nway_reset(struct net_device *net_dev)
{
	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);

	if (priv->mac)
	if (dpaa2_eth_is_type_phy(priv))
		return phylink_ethtool_nway_reset(priv->mac->phylink);

	return -EOPNOTSUPP;
@@ -97,7 +97,7 @@ dpaa2_eth_get_link_ksettings(struct net_device *net_dev,
{
	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);

	if (priv->mac)
	if (dpaa2_eth_is_type_phy(priv))
		return phylink_ethtool_ksettings_get(priv->mac->phylink,
						     link_settings);

@@ -115,7 +115,7 @@ dpaa2_eth_set_link_ksettings(struct net_device *net_dev,
{
	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);

	if (!priv->mac)
	if (!dpaa2_eth_is_type_phy(priv))
		return -ENOTSUPP;

	return phylink_ethtool_ksettings_set(priv->mac->phylink, link_settings);
@@ -127,7 +127,7 @@ static void dpaa2_eth_get_pauseparam(struct net_device *net_dev,
	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
	u64 link_options = priv->link_state.options;

	if (priv->mac) {
	if (dpaa2_eth_is_type_phy(priv)) {
		phylink_ethtool_get_pauseparam(priv->mac->phylink, pause);
		return;
	}
@@ -150,7 +150,7 @@ static int dpaa2_eth_set_pauseparam(struct net_device *net_dev,
		return -EOPNOTSUPP;
	}

	if (priv->mac)
	if (dpaa2_eth_is_type_phy(priv))
		return phylink_ethtool_set_pauseparam(priv->mac->phylink,
						      pause);
	if (pause->autoneg)
@@ -198,7 +198,7 @@ static void dpaa2_eth_get_strings(struct net_device *netdev, u32 stringset,
			strlcpy(p, dpaa2_ethtool_extras[i], ETH_GSTRING_LEN);
			p += ETH_GSTRING_LEN;
		}
		if (priv->mac)
		if (dpaa2_eth_has_mac(priv))
			dpaa2_mac_get_strings(p);
		break;
	}
@@ -211,7 +211,7 @@ static int dpaa2_eth_get_sset_count(struct net_device *net_dev, int sset)

	switch (sset) {
	case ETH_SS_STATS: /* ethtool_get_stats(), ethtool_get_drvinfo() */
		if (priv->mac)
		if (dpaa2_eth_has_mac(priv))
			num_ss_stats += dpaa2_mac_get_sset_count();
		return num_ss_stats;
	default:
@@ -313,7 +313,7 @@ static void dpaa2_eth_get_ethtool_stats(struct net_device *net_dev,
	}
	*(data + i++) = buf_cnt;

	if (priv->mac)
	if (dpaa2_eth_has_mac(priv))
		dpaa2_mac_get_ethtool_stats(priv->mac, data + i);
}

+58 −77
Original line number Diff line number Diff line
@@ -174,10 +174,6 @@ static void dpaa2_mac_link_up(struct phylink_config *config,

	dpmac_state->up = 1;

	if (mac->if_link_type == DPMAC_LINK_TYPE_PHY) {
		/* If the DPMAC is configured for PHY mode, we need
		 * to pass the link parameters to the MC firmware.
		 */
	dpmac_state->rate = speed;

	if (duplex == DUPLEX_HALF)
@@ -185,9 +181,6 @@ static void dpaa2_mac_link_up(struct phylink_config *config,
	else if (duplex == DUPLEX_FULL)
		dpmac_state->options &= ~DPMAC_LINK_OPT_HALF_DUPLEX;

		/* This is lossy; the firmware really should take the pause
		 * enablement status rather than pause/asym pause status.
		 */
	if (rx_pause)
		dpmac_state->options |= DPMAC_LINK_OPT_PAUSE;
	else
@@ -197,7 +190,6 @@ static void dpaa2_mac_link_up(struct phylink_config *config,
		dpmac_state->options |= DPMAC_LINK_OPT_ASYM_PAUSE;
	else
		dpmac_state->options &= ~DPMAC_LINK_OPT_ASYM_PAUSE;
	}

	err = dpmac_set_link_state(mac->mc_io, 0,
				   mac->mc_dev->mc_handle, dpmac_state);
@@ -228,32 +220,6 @@ static const struct phylink_mac_ops dpaa2_mac_phylink_ops = {
	.mac_link_down = dpaa2_mac_link_down,
};

bool dpaa2_mac_is_type_fixed(struct fsl_mc_device *dpmac_dev,
			     struct fsl_mc_io *mc_io)
{
	struct dpmac_attr attr;
	bool fixed = false;
	u16 mc_handle = 0;
	int err;

	err = dpmac_open(mc_io, 0, dpmac_dev->obj_desc.id,
			 &mc_handle);
	if (err || !mc_handle)
		return false;

	err = dpmac_get_attributes(mc_io, 0, mc_handle, &attr);
	if (err)
		goto out;

	if (attr.link_type == DPMAC_LINK_TYPE_FIXED)
		fixed = true;

out:
	dpmac_close(mc_io, 0, mc_handle);

	return fixed;
}

static int dpaa2_pcs_create(struct dpaa2_mac *mac,
			    struct device_node *dpmac_node, int id)
{
@@ -302,36 +268,20 @@ static void dpaa2_pcs_destroy(struct dpaa2_mac *mac)

int dpaa2_mac_connect(struct dpaa2_mac *mac)
{
	struct fsl_mc_device *dpmac_dev = mac->mc_dev;
	struct net_device *net_dev = mac->net_dev;
	struct device_node *dpmac_node;
	struct phylink *phylink;
	struct dpmac_attr attr;
	int err;

	err = dpmac_open(mac->mc_io, 0, dpmac_dev->obj_desc.id,
			 &dpmac_dev->mc_handle);
	if (err || !dpmac_dev->mc_handle) {
		netdev_err(net_dev, "dpmac_open() = %d\n", err);
		return -ENODEV;
	}

	err = dpmac_get_attributes(mac->mc_io, 0, dpmac_dev->mc_handle, &attr);
	if (err) {
		netdev_err(net_dev, "dpmac_get_attributes() = %d\n", err);
		goto err_close_dpmac;
	}
	mac->if_link_type = mac->attr.link_type;

	mac->if_link_type = attr.link_type;

	dpmac_node = dpaa2_mac_get_node(attr.id);
	dpmac_node = dpaa2_mac_get_node(mac->attr.id);
	if (!dpmac_node) {
		netdev_err(net_dev, "No dpmac@%d node found.\n", attr.id);
		err = -ENODEV;
		goto err_close_dpmac;
		netdev_err(net_dev, "No dpmac@%d node found.\n", mac->attr.id);
		return -ENODEV;
	}

	err = dpaa2_mac_get_if_mode(dpmac_node, attr);
	err = dpaa2_mac_get_if_mode(dpmac_node, mac->attr);
	if (err < 0) {
		err = -EINVAL;
		goto err_put_node;
@@ -351,9 +301,9 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
		goto err_put_node;
	}

	if (attr.link_type == DPMAC_LINK_TYPE_PHY &&
	    attr.eth_if != DPMAC_ETH_IF_RGMII) {
		err = dpaa2_pcs_create(mac, dpmac_node, attr.id);
	if (mac->attr.link_type == DPMAC_LINK_TYPE_PHY &&
	    mac->attr.eth_if != DPMAC_ETH_IF_RGMII) {
		err = dpaa2_pcs_create(mac, dpmac_node, mac->attr.id);
		if (err)
			goto err_put_node;
	}
@@ -389,8 +339,7 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
	dpaa2_pcs_destroy(mac);
err_put_node:
	of_node_put(dpmac_node);
err_close_dpmac:
	dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle);

	return err;
}

@@ -402,8 +351,40 @@ void dpaa2_mac_disconnect(struct dpaa2_mac *mac)
	phylink_disconnect_phy(mac->phylink);
	phylink_destroy(mac->phylink);
	dpaa2_pcs_destroy(mac);
}

int dpaa2_mac_open(struct dpaa2_mac *mac)
{
	struct fsl_mc_device *dpmac_dev = mac->mc_dev;
	struct net_device *net_dev = mac->net_dev;
	int err;

	err = dpmac_open(mac->mc_io, 0, dpmac_dev->obj_desc.id,
			 &dpmac_dev->mc_handle);
	if (err || !dpmac_dev->mc_handle) {
		netdev_err(net_dev, "dpmac_open() = %d\n", err);
		return -ENODEV;
	}

	err = dpmac_get_attributes(mac->mc_io, 0, dpmac_dev->mc_handle,
				   &mac->attr);
	if (err) {
		netdev_err(net_dev, "dpmac_get_attributes() = %d\n", err);
		goto err_close_dpmac;
	}

	dpmac_close(mac->mc_io, 0, mac->mc_dev->mc_handle);
	return 0;

err_close_dpmac:
	dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle);
	return err;
}

void dpaa2_mac_close(struct dpaa2_mac *mac)
{
	struct fsl_mc_device *dpmac_dev = mac->mc_dev;

	dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle);
}

static char dpaa2_mac_ethtool_stats[][ETH_GSTRING_LEN] = {
Loading