Skip to content

Commit

Permalink
net: dpaa: Convert to phylink
Browse files Browse the repository at this point in the history
This converts DPAA to phylink. All macs are converted. This should work
with no device tree modifications (including those made in this series),
except for QSGMII (as noted previously).

The mEMAC configuration is one of the tricker areas. I have tried to
capture all the restrictions across the various models. Most of the time,
we assume that if the serdes supports a mode or the phy-interface-mode
specifies it, then we support it. The only place we can't do this is
(RG)MII, since there's no serdes. In that case, we rely on a (new)
devicetree property. There are also several cases where half-duplex is
broken. Unfortunately, only a single compatible is used for the MAC, so we
have to use the board compatible instead.

The 10GEC conversion is very straightforward, since it only supports XAUI.
There is generally nothing to configure.

The dTSEC conversion is broadly similar to mEMAC, but is simpler because we
don't support configuring the SerDes (though this can be easily added) and
we don't have multiple PCSs. From what I can tell, there's nothing
different in the driver or documentation between SGMII and 1000BASE-X
except for the advertising. Similarly, I couldn't find anything about
2500BASE-X. In both cases, I treat them like SGMII. These modes aren't used
by any in-tree boards. Similarly, despite being mentioned in the driver, I
couldn't find any documented SoCs which supported QSGMII.  I have left it
unimplemented for now.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Sean Anderson authored and David S. Miller committed Oct 19, 2022
1 parent a7c2a32 commit 5d93cfc
Show file tree
Hide file tree
Showing 10 changed files with 612 additions and 909 deletions.
4 changes: 2 additions & 2 deletions drivers/net/ethernet/freescale/dpaa/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
menuconfig FSL_DPAA_ETH
tristate "DPAA Ethernet"
depends on FSL_DPAA && FSL_FMAN
select PHYLIB
select FIXED_PHY
select PHYLINK
select PCS_LYNX
help
Data Path Acceleration Architecture Ethernet driver,
supporting the Freescale QorIQ chips.
Expand Down
89 changes: 26 additions & 63 deletions drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,15 +264,27 @@ static int dpaa_netdev_init(struct net_device *net_dev,
net_dev->needed_headroom = priv->tx_headroom;
net_dev->watchdog_timeo = msecs_to_jiffies(tx_timeout);

mac_dev->net_dev = net_dev;
/* The rest of the config is filled in by the mac device already */
mac_dev->phylink_config.dev = &net_dev->dev;
mac_dev->phylink_config.type = PHYLINK_NETDEV;
mac_dev->update_speed = dpaa_eth_cgr_set_speed;
mac_dev->phylink = phylink_create(&mac_dev->phylink_config,
dev_fwnode(mac_dev->dev),
mac_dev->phy_if,
mac_dev->phylink_ops);
if (IS_ERR(mac_dev->phylink)) {
err = PTR_ERR(mac_dev->phylink);
dev_err_probe(dev, err, "Could not create phylink\n");
return err;
}

/* start without the RUNNING flag, phylib controls it later */
netif_carrier_off(net_dev);

err = register_netdev(net_dev);
if (err < 0) {
dev_err(dev, "register_netdev() = %d\n", err);
phylink_destroy(mac_dev->phylink);
return err;
}

Expand All @@ -294,8 +306,7 @@ static int dpaa_stop(struct net_device *net_dev)
*/
msleep(200);

if (mac_dev->phy_dev)
phy_stop(mac_dev->phy_dev);
phylink_stop(mac_dev->phylink);
mac_dev->disable(mac_dev->fman_mac);

for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
Expand All @@ -304,8 +315,7 @@ static int dpaa_stop(struct net_device *net_dev)
err = error;
}

if (net_dev->phydev)
phy_disconnect(net_dev->phydev);
phylink_disconnect_phy(mac_dev->phylink);
net_dev->phydev = NULL;

msleep(200);
Expand Down Expand Up @@ -833,10 +843,10 @@ static int dpaa_eth_cgr_init(struct dpaa_priv *priv)

/* Set different thresholds based on the configured MAC speed.
* This may turn suboptimal if the MAC is reconfigured at another
* speed, so MACs must call dpaa_eth_cgr_set_speed in their adjust_link
* speed, so MACs must call dpaa_eth_cgr_set_speed in their link_up
* callback.
*/
if (priv->mac_dev->if_support & SUPPORTED_10000baseT_Full)
if (priv->mac_dev->phylink_config.mac_capabilities & MAC_10000FD)
cs_th = DPAA_CS_THRESHOLD_10G;
else
cs_th = DPAA_CS_THRESHOLD_1G;
Expand Down Expand Up @@ -865,7 +875,7 @@ static int dpaa_eth_cgr_init(struct dpaa_priv *priv)

static void dpaa_eth_cgr_set_speed(struct mac_device *mac_dev, int speed)
{
struct net_device *net_dev = mac_dev->net_dev;
struct net_device *net_dev = to_net_dev(mac_dev->phylink_config.dev);
struct dpaa_priv *priv = netdev_priv(net_dev);
struct qm_mcc_initcgr opts = { };
u32 cs_th;
Expand Down Expand Up @@ -2904,58 +2914,6 @@ static void dpaa_eth_napi_disable(struct dpaa_priv *priv)
}
}

static void dpaa_adjust_link(struct net_device *net_dev)
{
struct mac_device *mac_dev;
struct dpaa_priv *priv;

priv = netdev_priv(net_dev);
mac_dev = priv->mac_dev;
mac_dev->adjust_link(mac_dev);
}

/* The Aquantia PHYs are capable of performing rate adaptation */
#define PHY_VEND_AQUANTIA 0x03a1b400
#define PHY_VEND_AQUANTIA2 0x31c31c00

static int dpaa_phy_init(struct net_device *net_dev)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
struct mac_device *mac_dev;
struct phy_device *phy_dev;
struct dpaa_priv *priv;
u32 phy_vendor;

priv = netdev_priv(net_dev);
mac_dev = priv->mac_dev;

phy_dev = of_phy_connect(net_dev, mac_dev->phy_node,
&dpaa_adjust_link, 0,
mac_dev->phy_if);
if (!phy_dev) {
netif_err(priv, ifup, net_dev, "init_phy() failed\n");
return -ENODEV;
}

phy_vendor = phy_dev->drv->phy_id & GENMASK(31, 10);
/* Unless the PHY is capable of rate adaptation */
if (mac_dev->phy_if != PHY_INTERFACE_MODE_XGMII ||
(phy_vendor != PHY_VEND_AQUANTIA &&
phy_vendor != PHY_VEND_AQUANTIA2)) {
/* remove any features not supported by the controller */
ethtool_convert_legacy_u32_to_link_mode(mask,
mac_dev->if_support);
linkmode_and(phy_dev->supported, phy_dev->supported, mask);
}

phy_support_asym_pause(phy_dev);

mac_dev->phy_dev = phy_dev;
net_dev->phydev = phy_dev;

return 0;
}

static int dpaa_open(struct net_device *net_dev)
{
struct mac_device *mac_dev;
Expand All @@ -2966,7 +2924,8 @@ static int dpaa_open(struct net_device *net_dev)
mac_dev = priv->mac_dev;
dpaa_eth_napi_enable(priv);

err = dpaa_phy_init(net_dev);
err = phylink_of_phy_connect(mac_dev->phylink,
mac_dev->dev->of_node, 0);
if (err)
goto phy_init_failed;

Expand All @@ -2981,7 +2940,7 @@ static int dpaa_open(struct net_device *net_dev)
netif_err(priv, ifup, net_dev, "mac_dev->enable() = %d\n", err);
goto mac_start_failed;
}
phy_start(priv->mac_dev->phy_dev);
phylink_start(mac_dev->phylink);

netif_tx_start_all_queues(net_dev);

Expand All @@ -2990,6 +2949,7 @@ static int dpaa_open(struct net_device *net_dev)
mac_start_failed:
for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++)
fman_port_disable(mac_dev->port[i]);
phylink_disconnect_phy(mac_dev->phylink);

phy_init_failed:
dpaa_eth_napi_disable(priv);
Expand Down Expand Up @@ -3145,10 +3105,12 @@ static int dpaa_ts_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static int dpaa_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd)
{
int ret = -EINVAL;
struct dpaa_priv *priv = netdev_priv(net_dev);

if (cmd == SIOCGMIIREG) {
if (net_dev->phydev)
return phy_mii_ioctl(net_dev->phydev, rq, cmd);
return phylink_mii_ioctl(priv->mac_dev->phylink, rq,
cmd);
}

if (cmd == SIOCSHWTSTAMP)
Expand Down Expand Up @@ -3551,6 +3513,7 @@ static int dpaa_remove(struct platform_device *pdev)

dev_set_drvdata(dev, NULL);
unregister_netdev(net_dev);
phylink_destroy(priv->mac_dev->phylink);

err = dpaa_fq_free(dev, &priv->dpaa_fq_list);

Expand Down
90 changes: 15 additions & 75 deletions drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,19 @@ static char dpaa_stats_global[][ETH_GSTRING_LEN] = {
static int dpaa_get_link_ksettings(struct net_device *net_dev,
struct ethtool_link_ksettings *cmd)
{
if (!net_dev->phydev)
return 0;
struct dpaa_priv *priv = netdev_priv(net_dev);
struct mac_device *mac_dev = priv->mac_dev;

phy_ethtool_ksettings_get(net_dev->phydev, cmd);

return 0;
return phylink_ethtool_ksettings_get(mac_dev->phylink, cmd);
}

static int dpaa_set_link_ksettings(struct net_device *net_dev,
const struct ethtool_link_ksettings *cmd)
{
int err;

if (!net_dev->phydev)
return -ENODEV;

err = phy_ethtool_ksettings_set(net_dev->phydev, cmd);
if (err < 0)
netdev_err(net_dev, "phy_ethtool_ksettings_set() = %d\n", err);
struct dpaa_priv *priv = netdev_priv(net_dev);
struct mac_device *mac_dev = priv->mac_dev;

return err;
return phylink_ethtool_ksettings_set(mac_dev->phylink, cmd);
}

static void dpaa_get_drvinfo(struct net_device *net_dev,
Expand All @@ -99,80 +91,28 @@ static void dpaa_set_msglevel(struct net_device *net_dev,

static int dpaa_nway_reset(struct net_device *net_dev)
{
int err;

if (!net_dev->phydev)
return -ENODEV;

err = 0;
if (net_dev->phydev->autoneg) {
err = phy_start_aneg(net_dev->phydev);
if (err < 0)
netdev_err(net_dev, "phy_start_aneg() = %d\n",
err);
}
struct dpaa_priv *priv = netdev_priv(net_dev);
struct mac_device *mac_dev = priv->mac_dev;

return err;
return phylink_ethtool_nway_reset(mac_dev->phylink);
}

static void dpaa_get_pauseparam(struct net_device *net_dev,
struct ethtool_pauseparam *epause)
{
struct mac_device *mac_dev;
struct dpaa_priv *priv;

priv = netdev_priv(net_dev);
mac_dev = priv->mac_dev;

if (!net_dev->phydev)
return;
struct dpaa_priv *priv = netdev_priv(net_dev);
struct mac_device *mac_dev = priv->mac_dev;

epause->autoneg = mac_dev->autoneg_pause;
epause->rx_pause = mac_dev->rx_pause_active;
epause->tx_pause = mac_dev->tx_pause_active;
phylink_ethtool_get_pauseparam(mac_dev->phylink, epause);
}

static int dpaa_set_pauseparam(struct net_device *net_dev,
struct ethtool_pauseparam *epause)
{
struct mac_device *mac_dev;
struct phy_device *phydev;
bool rx_pause, tx_pause;
struct dpaa_priv *priv;
int err;

priv = netdev_priv(net_dev);
mac_dev = priv->mac_dev;

phydev = net_dev->phydev;
if (!phydev) {
netdev_err(net_dev, "phy device not initialized\n");
return -ENODEV;
}

if (!phy_validate_pause(phydev, epause))
return -EINVAL;

/* The MAC should know how to handle PAUSE frame autonegotiation before
* adjust_link is triggered by a forced renegotiation of sym/asym PAUSE
* settings.
*/
mac_dev->autoneg_pause = !!epause->autoneg;
mac_dev->rx_pause_req = !!epause->rx_pause;
mac_dev->tx_pause_req = !!epause->tx_pause;

/* Determine the sym/asym advertised PAUSE capabilities from the desired
* rx/tx pause settings.
*/

phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause);

fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
if (err < 0)
netdev_err(net_dev, "set_mac_active_pause() = %d\n", err);
struct dpaa_priv *priv = netdev_priv(net_dev);
struct mac_device *mac_dev = priv->mac_dev;

return err;
return phylink_ethtool_set_pauseparam(mac_dev->phylink, epause);
}

static int dpaa_get_sset_count(struct net_device *net_dev, int type)
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/freescale/fman/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ config FSL_FMAN
tristate "FMan support"
depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST
select GENERIC_ALLOCATOR
select PHYLIB
select PHYLINK
select PCS
select PCS_LYNX
Expand Down
Loading

0 comments on commit 5d93cfc

Please sign in to comment.