Commit bea4b309 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'enetc-Migrate-to-PHYLINK-and-PCS_LYNX'

Claudiu Manoil says:

====================
enetc: Migrate to PHYLINK and PCS_LYNX

Transitioning the enetc driver from phylib to phylink.
Offloading the serdes configuration to the PCS_LYNX
module is a mandatory part of this transition. Aiming
for a cleaner, more maintainable design, and better
code reuse.
The first 2 patches are clean up prerequisites.

Tested on a p1028rdb board.

v2: validate() explicitly rejects now all interface modes not
supported by the driver instead of relying on the device tree
to provide only supported interfaces, and dropped redundant
activation of pcs_poll (addressing Ioana's findings)
====================
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents df41c19a 71b77a7a
...@@ -199,6 +199,7 @@ qsgmii_phy3: ethernet-phy@13 { ...@@ -199,6 +199,7 @@ qsgmii_phy3: ethernet-phy@13 {
&enetc_port0 { &enetc_port0 {
phy-handle = <&sgmii_phy0>; phy-handle = <&sgmii_phy0>;
phy-connection-type = "sgmii"; phy-connection-type = "sgmii";
managed = "in-band-status";
status = "okay"; status = "okay";
mdio { mdio {
......
...@@ -3,7 +3,8 @@ config FSL_ENETC ...@@ -3,7 +3,8 @@ config FSL_ENETC
tristate "ENETC PF driver" tristate "ENETC PF driver"
depends on PCI && PCI_MSI depends on PCI && PCI_MSI
select FSL_ENETC_MDIO select FSL_ENETC_MDIO
select PHYLIB select PHYLINK
select PCS_LYNX
select DIMLIB select DIMLIB
help help
This driver supports NXP ENETC gigabit ethernet controller PCIe This driver supports NXP ENETC gigabit ethernet controller PCIe
...@@ -15,7 +16,7 @@ config FSL_ENETC ...@@ -15,7 +16,7 @@ config FSL_ENETC
config FSL_ENETC_VF config FSL_ENETC_VF
tristate "ENETC VF driver" tristate "ENETC VF driver"
depends on PCI && PCI_MSI depends on PCI && PCI_MSI
select PHYLIB select PHYLINK
select DIMLIB select DIMLIB
help help
This driver supports NXP ENETC gigabit ethernet controller PCIe This driver supports NXP ENETC gigabit ethernet controller PCIe
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include "enetc.h" #include "enetc.h"
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/udp.h> #include <linux/udp.h>
#include <linux/of_mdio.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
/* ENETC overhead: optional extension BD + 1 BD gap */ /* ENETC overhead: optional extension BD + 1 BD gap */
...@@ -1392,38 +1391,24 @@ static void enetc_clear_interrupts(struct enetc_ndev_priv *priv) ...@@ -1392,38 +1391,24 @@ static void enetc_clear_interrupts(struct enetc_ndev_priv *priv)
enetc_rxbdr_wr(&priv->si->hw, i, ENETC_RBIER, 0); enetc_rxbdr_wr(&priv->si->hw, i, ENETC_RBIER, 0);
} }
static void adjust_link(struct net_device *ndev) static int enetc_phylink_connect(struct net_device *ndev)
{ {
struct enetc_ndev_priv *priv = netdev_priv(ndev); struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct phy_device *phydev = ndev->phydev;
if (priv->active_offloads & ENETC_F_QBV)
enetc_sched_speed_set(ndev);
phy_print_status(phydev);
}
static int enetc_phy_connect(struct net_device *ndev)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct phy_device *phydev;
struct ethtool_eee edata; struct ethtool_eee edata;
int err;
if (!priv->phy_node) if (!priv->phylink)
return 0; /* phy-less mode */ return 0; /* phy-less mode */
phydev = of_phy_connect(ndev, priv->phy_node, &adjust_link, err = phylink_of_phy_connect(priv->phylink, priv->dev->of_node, 0);
0, priv->if_mode); if (err) {
if (!phydev) {
dev_err(&ndev->dev, "could not attach to PHY\n"); dev_err(&ndev->dev, "could not attach to PHY\n");
return -ENODEV; return err;
} }
phy_attached_info(phydev);
/* disable EEE autoneg, until ENETC driver supports it */ /* disable EEE autoneg, until ENETC driver supports it */
memset(&edata, 0, sizeof(struct ethtool_eee)); memset(&edata, 0, sizeof(struct ethtool_eee));
phy_ethtool_set_eee(phydev, &edata); phylink_ethtool_set_eee(priv->phylink, &edata);
return 0; return 0;
} }
...@@ -1443,8 +1428,8 @@ void enetc_start(struct net_device *ndev) ...@@ -1443,8 +1428,8 @@ void enetc_start(struct net_device *ndev)
enable_irq(irq); enable_irq(irq);
} }
if (ndev->phydev) if (priv->phylink)
phy_start(ndev->phydev); phylink_start(priv->phylink);
else else
netif_carrier_on(ndev); netif_carrier_on(ndev);
...@@ -1460,7 +1445,7 @@ int enetc_open(struct net_device *ndev) ...@@ -1460,7 +1445,7 @@ int enetc_open(struct net_device *ndev)
if (err) if (err)
return err; return err;
err = enetc_phy_connect(ndev); err = enetc_phylink_connect(ndev);
if (err) if (err)
goto err_phy_connect; goto err_phy_connect;
...@@ -1490,8 +1475,8 @@ int enetc_open(struct net_device *ndev) ...@@ -1490,8 +1475,8 @@ int enetc_open(struct net_device *ndev)
err_alloc_rx: err_alloc_rx:
enetc_free_tx_resources(priv); enetc_free_tx_resources(priv);
err_alloc_tx: err_alloc_tx:
if (ndev->phydev) if (priv->phylink)
phy_disconnect(ndev->phydev); phylink_disconnect_phy(priv->phylink);
err_phy_connect: err_phy_connect:
enetc_free_irqs(priv); enetc_free_irqs(priv);
...@@ -1514,8 +1499,8 @@ void enetc_stop(struct net_device *ndev) ...@@ -1514,8 +1499,8 @@ void enetc_stop(struct net_device *ndev)
napi_disable(&priv->int_vector[i]->napi); napi_disable(&priv->int_vector[i]->napi);
} }
if (ndev->phydev) if (priv->phylink)
phy_stop(ndev->phydev); phylink_stop(priv->phylink);
else else
netif_carrier_off(ndev); netif_carrier_off(ndev);
...@@ -1529,8 +1514,8 @@ int enetc_close(struct net_device *ndev) ...@@ -1529,8 +1514,8 @@ int enetc_close(struct net_device *ndev)
enetc_stop(ndev); enetc_stop(ndev);
enetc_clear_bdrs(priv); enetc_clear_bdrs(priv);
if (ndev->phydev) if (priv->phylink)
phy_disconnect(ndev->phydev); phylink_disconnect_phy(priv->phylink);
enetc_free_rxtx_rings(priv); enetc_free_rxtx_rings(priv);
enetc_free_rx_resources(priv); enetc_free_rx_resources(priv);
enetc_free_tx_resources(priv); enetc_free_tx_resources(priv);
...@@ -1780,6 +1765,7 @@ static int enetc_hwtstamp_get(struct net_device *ndev, struct ifreq *ifr) ...@@ -1780,6 +1765,7 @@ static int enetc_hwtstamp_get(struct net_device *ndev, struct ifreq *ifr)
int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
{ {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
#ifdef CONFIG_FSL_ENETC_PTP_CLOCK #ifdef CONFIG_FSL_ENETC_PTP_CLOCK
if (cmd == SIOCSHWTSTAMP) if (cmd == SIOCSHWTSTAMP)
return enetc_hwtstamp_set(ndev, rq); return enetc_hwtstamp_set(ndev, rq);
...@@ -1787,9 +1773,10 @@ int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) ...@@ -1787,9 +1773,10 @@ int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
return enetc_hwtstamp_get(ndev, rq); return enetc_hwtstamp_get(ndev, rq);
#endif #endif
if (!ndev->phydev) if (!priv->phylink)
return -EOPNOTSUPP; return -EOPNOTSUPP;
return phy_mii_ioctl(ndev->phydev, rq, cmd);
return phylink_mii_ioctl(priv->phylink, rq, cmd);
} }
int enetc_alloc_msix(struct enetc_ndev_priv *priv) int enetc_alloc_msix(struct enetc_ndev_priv *priv)
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/phy.h> #include <linux/phylink.h>
#include <linux/dim.h> #include <linux/dim.h>
#include "enetc_hw.h" #include "enetc_hw.h"
...@@ -264,8 +264,7 @@ struct enetc_ndev_priv { ...@@ -264,8 +264,7 @@ struct enetc_ndev_priv {
struct psfp_cap psfp_cap; struct psfp_cap psfp_cap;
struct device_node *phy_node; struct phylink *phylink;
phy_interface_t if_mode;
int ic_mode; int ic_mode;
u32 tx_ictt; u32 tx_ictt;
}; };
...@@ -323,7 +322,7 @@ int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd); ...@@ -323,7 +322,7 @@ int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
#ifdef CONFIG_FSL_ENETC_QOS #ifdef CONFIG_FSL_ENETC_QOS
int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data); int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data);
void enetc_sched_speed_set(struct net_device *ndev); void enetc_sched_speed_set(struct enetc_ndev_priv *priv, int speed);
int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data); int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data);
int enetc_setup_tc_txtime(struct net_device *ndev, void *type_data); int enetc_setup_tc_txtime(struct net_device *ndev, void *type_data);
int enetc_setup_tc_block_cb(enum tc_setup_type type, void *type_data, int enetc_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
...@@ -388,7 +387,7 @@ static inline int enetc_psfp_disable(struct enetc_ndev_priv *priv) ...@@ -388,7 +387,7 @@ static inline int enetc_psfp_disable(struct enetc_ndev_priv *priv)
#else #else
#define enetc_setup_tc_taprio(ndev, type_data) -EOPNOTSUPP #define enetc_setup_tc_taprio(ndev, type_data) -EOPNOTSUPP
#define enetc_sched_speed_set(ndev) (void)0 #define enetc_sched_speed_set(priv, speed) (void)0
#define enetc_setup_tc_cbs(ndev, type_data) -EOPNOTSUPP #define enetc_setup_tc_cbs(ndev, type_data) -EOPNOTSUPP
#define enetc_setup_tc_txtime(ndev, type_data) -EOPNOTSUPP #define enetc_setup_tc_txtime(ndev, type_data) -EOPNOTSUPP
#define enetc_setup_tc_psfp(ndev, type_data) -EOPNOTSUPP #define enetc_setup_tc_psfp(ndev, type_data) -EOPNOTSUPP
......
...@@ -686,6 +686,28 @@ static int enetc_set_wol(struct net_device *dev, ...@@ -686,6 +686,28 @@ static int enetc_set_wol(struct net_device *dev,
return ret; return ret;
} }
static int enetc_get_link_ksettings(struct net_device *dev,
struct ethtool_link_ksettings *cmd)
{
struct enetc_ndev_priv *priv = netdev_priv(dev);
if (!priv->phylink)
return -EOPNOTSUPP;
return phylink_ethtool_ksettings_get(priv->phylink, cmd);
}
static int enetc_set_link_ksettings(struct net_device *dev,
const struct ethtool_link_ksettings *cmd)
{
struct enetc_ndev_priv *priv = netdev_priv(dev);
if (!priv->phylink)
return -EOPNOTSUPP;
return phylink_ethtool_ksettings_set(priv->phylink, cmd);
}
static const struct ethtool_ops enetc_pf_ethtool_ops = { static const struct ethtool_ops enetc_pf_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS | .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES | ETHTOOL_COALESCE_MAX_FRAMES |
...@@ -704,8 +726,8 @@ static const struct ethtool_ops enetc_pf_ethtool_ops = { ...@@ -704,8 +726,8 @@ static const struct ethtool_ops enetc_pf_ethtool_ops = {
.get_ringparam = enetc_get_ringparam, .get_ringparam = enetc_get_ringparam,
.get_coalesce = enetc_get_coalesce, .get_coalesce = enetc_get_coalesce,
.set_coalesce = enetc_set_coalesce, .set_coalesce = enetc_set_coalesce,
.get_link_ksettings = phy_ethtool_get_link_ksettings, .get_link_ksettings = enetc_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings, .set_link_ksettings = enetc_set_link_ksettings,
.get_link = ethtool_op_get_link, .get_link = ethtool_op_get_link,
.get_ts_info = enetc_get_ts_info, .get_ts_info = enetc_get_ts_info,
.get_wol = enetc_get_wol, .get_wol = enetc_get_wol,
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* Copyright 2017-2019 NXP */ /* Copyright 2017-2019 NXP */
#include "enetc.h" #include "enetc.h"
#include <linux/pcs-lynx.h>
#define ENETC_PF_NUM_RINGS 8 #define ENETC_PF_NUM_RINGS 8
...@@ -45,12 +46,15 @@ struct enetc_pf { ...@@ -45,12 +46,15 @@ struct enetc_pf {
struct mii_bus *mdio; /* saved for cleanup */ struct mii_bus *mdio; /* saved for cleanup */
struct mii_bus *imdio; struct mii_bus *imdio;
struct phy_device *pcs; struct lynx_pcs *pcs;
struct device_node *phy_node;
phy_interface_t if_mode; phy_interface_t if_mode;
struct phylink_config phylink_config;
}; };
#define phylink_to_enetc_pf(config) \
container_of((config), struct enetc_pf, phylink_config)
int enetc_msg_psi_init(struct enetc_pf *pf); int enetc_msg_psi_init(struct enetc_pf *pf);
void enetc_msg_psi_free(struct enetc_pf *pf); void enetc_msg_psi_free(struct enetc_pf *pf);
void enetc_msg_handle_rxmsg(struct enetc_pf *pf, int mbox_id, u16 *status); void enetc_msg_handle_rxmsg(struct enetc_pf *pf, int mbox_id, u16 *status);
...@@ -15,17 +15,14 @@ static u16 enetc_get_max_gcl_len(struct enetc_hw *hw) ...@@ -15,17 +15,14 @@ static u16 enetc_get_max_gcl_len(struct enetc_hw *hw)
& ENETC_QBV_MAX_GCL_LEN_MASK; & ENETC_QBV_MAX_GCL_LEN_MASK;
} }
void enetc_sched_speed_set(struct net_device *ndev) void enetc_sched_speed_set(struct enetc_ndev_priv *priv, int speed)
{ {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct phy_device *phydev = ndev->phydev;
u32 old_speed = priv->speed; u32 old_speed = priv->speed;
u32 speed, pspeed; u32 pspeed;
if (phydev->speed == old_speed) if (speed == old_speed)
return; return;
speed = phydev->speed;
switch (speed) { switch (speed) {
case SPEED_1000: case SPEED_1000:
pspeed = ENETC_PMR_PSPEED_1000M; pspeed = ENETC_PMR_PSPEED_1000M;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment