From 9dbb72b01cfa61fe31532c57a456d1e760fa517e Mon Sep 17 00:00:00 2001 From: Igor Pecovnik Date: Sun, 21 Nov 2021 17:58:03 +0100 Subject: [PATCH] Adjusting patches due to upstream changes to make mvbe family operational again @heisath --- config/kernel/linux-mvebu-current.config | 15 +- .../mvebu-5.10/09-pci-link-retraining.patch | 9 +- ...vebu-clearfog-pcie-updates.patch.disabled} | 0 .../mvebu-5.15/09-pci-link-retraining.patch | 9 +- ...vebu-clearfog-pcie-updates.patch.disabled} | 0 .../archive/mvebu-5.15/13-net-mvneta.patch | 10484 ---------------- ...tch => 21-pcie-bridge-emul.patch.disabled} | 0 7 files changed, 17 insertions(+), 10500 deletions(-) rename patch/kernel/archive/mvebu-5.10/{10-mvebu-clearfog-pcie-updates.patch => 10-mvebu-clearfog-pcie-updates.patch.disabled} (100%) rename patch/kernel/archive/mvebu-5.15/{10-mvebu-clearfog-pcie-updates.patch => 10-mvebu-clearfog-pcie-updates.patch.disabled} (100%) delete mode 100644 patch/kernel/archive/mvebu-5.15/13-net-mvneta.patch rename patch/kernel/archive/mvebu-5.15/{21-pcie-bridge-emul.patch => 21-pcie-bridge-emul.patch.disabled} (100%) diff --git a/config/kernel/linux-mvebu-current.config b/config/kernel/linux-mvebu-current.config index 698f09e596..eecb855a34 100644 --- a/config/kernel/linux-mvebu-current.config +++ b/config/kernel/linux-mvebu-current.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 5.10.48 Kernel Configuration +# Linux/arm 5.10.81 Kernel Configuration # CONFIG_CC_VERSION_TEXT="arm-linux-gnueabihf-gcc (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)) 8.3.0" CONFIG_CC_IS_GCC=y @@ -200,6 +200,7 @@ CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_FUTEX_PI=y +CONFIG_HAVE_FUTEX_CMPXCHG=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y @@ -483,7 +484,6 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_PARAVIRT is not set # CONFIG_PARAVIRT_TIME_ACCOUNTING is not set # CONFIG_XEN is not set -CONFIG_STACKPROTECTOR_PER_TASK=y # end of Kernel Features # @@ -693,10 +693,6 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y # end of GCOV-based kernel profiling CONFIG_HAVE_GCC_PLUGINS=y -CONFIG_GCC_PLUGINS=y -# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set -# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set -CONFIG_GCC_PLUGIN_ARM_SSP_PER_TASK=y # end of General architecture-dependent options CONFIG_RT_MUTEXES=y @@ -3031,6 +3027,7 @@ CONFIG_WLAN_VENDOR_TI=y CONFIG_RTL8822BS=m CONFIG_RTL8723DU=m CONFIG_RTL8723DS=m +CONFIG_RTL8822CS=m CONFIG_RTL8822BU=m CONFIG_RTL8188EU=m CONFIG_RTL8821CU=m @@ -3692,6 +3689,7 @@ CONFIG_CHARGER_BQ25890=m CONFIG_CHARGER_BQ25980=m CONFIG_CHARGER_SMB347=m CONFIG_BATTERY_GAUGE_LTC2941=m +CONFIG_BATTERY_RT5033=m CONFIG_CHARGER_RT9455=m CONFIG_CHARGER_UCS1002=m # CONFIG_CHARGER_BD99954 is not set @@ -5446,6 +5444,7 @@ CONFIG_AD9834=m # CONFIG_LTE_GDM724X is not set # CONFIG_GS_FPGABOOT is not set # CONFIG_UNISYSSPAR is not set +CONFIG_COMMON_CLK_XLNX_CLKWZRD=m # CONFIG_MOST_COMPONENTS is not set # CONFIG_KS7010 is not set # CONFIG_PI433 is not set @@ -6425,7 +6424,6 @@ CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" # CONFIG_PSTORE_CONSOLE is not set # CONFIG_PSTORE_PMSG is not set CONFIG_PSTORE_RAM=m -# CONFIG_PSTORE_BLK is not set CONFIG_SYSV_FS=m CONFIG_UFS_FS=m CONFIG_UFS_FS_WRITE=y @@ -6656,9 +6654,6 @@ CONFIG_LSM="lockdown,yama,integrity,apparmor" # Memory initialization # CONFIG_INIT_STACK_NONE=y -# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set -# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set -# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set # end of Memory initialization diff --git a/patch/kernel/archive/mvebu-5.10/09-pci-link-retraining.patch b/patch/kernel/archive/mvebu-5.10/09-pci-link-retraining.patch index 371bbce1e8..d3cf9df1cd 100644 --- a/patch/kernel/archive/mvebu-5.10/09-pci-link-retraining.patch +++ b/patch/kernel/archive/mvebu-5.10/09-pci-link-retraining.patch @@ -149,7 +149,7 @@ diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5d2acebc3..91d675e0d 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c -@@ -3572,18 +3572,44 @@ static void quirk_nvidia_no_bus_reset(struct pci_dev *dev) +@@ -3572,19 +3572,46 @@ static void quirk_nvidia_no_bus_reset(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, quirk_nvidia_no_bus_reset); @@ -181,6 +181,7 @@ index 5d2acebc3..91d675e0d 100644 -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034, quirk_no_bus_reset); +-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003e, quirk_no_bus_reset); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x002e, + quirk_no_bus_reset_and_no_retrain_link); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, @@ -191,6 +192,8 @@ index 5d2acebc3..91d675e0d 100644 + quirk_no_bus_reset_and_no_retrain_link); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034, + quirk_no_bus_reset_and_no_retrain_link); ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003e, ++ quirk_no_bus_reset_and_no_retrain_link); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, + quirk_no_bus_reset_and_no_retrain_link); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0042, @@ -204,9 +207,9 @@ index 86c799c97b77..fdbf7254e4ab 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -227,6 +227,8 @@ enum pci_dev_flags { - PCI_DEV_FLAGS_NO_FLR_RESET = (__force pci_dev_flags_t) (1 << 10), - /* Don't use Relaxed Ordering for TLPs directed at this device */ PCI_DEV_FLAGS_NO_RELAXED_ORDERING = (__force pci_dev_flags_t) (1 << 11), + /* Device does honor MSI masking despite saying otherwise */ + PCI_DEV_FLAGS_HAS_MSI_MASKING = (__force pci_dev_flags_t) (1 << 12), + /* Don't Retrain Link for device when bridge is not in GEN1 mode */ + PCI_DEV_FLAGS_NO_RETRAIN_LINK_WHEN_NOT_GEN1 = (__force pci_dev_flags_t) (1 << 12), }; diff --git a/patch/kernel/archive/mvebu-5.10/10-mvebu-clearfog-pcie-updates.patch b/patch/kernel/archive/mvebu-5.10/10-mvebu-clearfog-pcie-updates.patch.disabled similarity index 100% rename from patch/kernel/archive/mvebu-5.10/10-mvebu-clearfog-pcie-updates.patch rename to patch/kernel/archive/mvebu-5.10/10-mvebu-clearfog-pcie-updates.patch.disabled diff --git a/patch/kernel/archive/mvebu-5.15/09-pci-link-retraining.patch b/patch/kernel/archive/mvebu-5.15/09-pci-link-retraining.patch index 371bbce1e8..d3cf9df1cd 100644 --- a/patch/kernel/archive/mvebu-5.15/09-pci-link-retraining.patch +++ b/patch/kernel/archive/mvebu-5.15/09-pci-link-retraining.patch @@ -149,7 +149,7 @@ diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5d2acebc3..91d675e0d 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c -@@ -3572,18 +3572,44 @@ static void quirk_nvidia_no_bus_reset(struct pci_dev *dev) +@@ -3572,19 +3572,46 @@ static void quirk_nvidia_no_bus_reset(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, quirk_nvidia_no_bus_reset); @@ -181,6 +181,7 @@ index 5d2acebc3..91d675e0d 100644 -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034, quirk_no_bus_reset); +-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003e, quirk_no_bus_reset); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x002e, + quirk_no_bus_reset_and_no_retrain_link); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, @@ -191,6 +192,8 @@ index 5d2acebc3..91d675e0d 100644 + quirk_no_bus_reset_and_no_retrain_link); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034, + quirk_no_bus_reset_and_no_retrain_link); ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003e, ++ quirk_no_bus_reset_and_no_retrain_link); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, + quirk_no_bus_reset_and_no_retrain_link); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0042, @@ -204,9 +207,9 @@ index 86c799c97b77..fdbf7254e4ab 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -227,6 +227,8 @@ enum pci_dev_flags { - PCI_DEV_FLAGS_NO_FLR_RESET = (__force pci_dev_flags_t) (1 << 10), - /* Don't use Relaxed Ordering for TLPs directed at this device */ PCI_DEV_FLAGS_NO_RELAXED_ORDERING = (__force pci_dev_flags_t) (1 << 11), + /* Device does honor MSI masking despite saying otherwise */ + PCI_DEV_FLAGS_HAS_MSI_MASKING = (__force pci_dev_flags_t) (1 << 12), + /* Don't Retrain Link for device when bridge is not in GEN1 mode */ + PCI_DEV_FLAGS_NO_RETRAIN_LINK_WHEN_NOT_GEN1 = (__force pci_dev_flags_t) (1 << 12), }; diff --git a/patch/kernel/archive/mvebu-5.15/10-mvebu-clearfog-pcie-updates.patch b/patch/kernel/archive/mvebu-5.15/10-mvebu-clearfog-pcie-updates.patch.disabled similarity index 100% rename from patch/kernel/archive/mvebu-5.15/10-mvebu-clearfog-pcie-updates.patch rename to patch/kernel/archive/mvebu-5.15/10-mvebu-clearfog-pcie-updates.patch.disabled diff --git a/patch/kernel/archive/mvebu-5.15/13-net-mvneta.patch b/patch/kernel/archive/mvebu-5.15/13-net-mvneta.patch deleted file mode 100644 index 2b4091494b..0000000000 --- a/patch/kernel/archive/mvebu-5.15/13-net-mvneta.patch +++ /dev/null @@ -1,10484 +0,0 @@ -From 4b1e8972f805590d7f94b8e955dc2d792bbc0eb6 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 17 Sep 2021 10:40:04 +0100 -Subject: net: phylink: don't call netif_carrier_off() with NULL netdev - -Dan Carpenter points out that we have a code path that permits a NULL -netdev pointer to be passed to netif_carrier_off(), which will cause -a kernel oops. In any case, we need to set pl->old_link_state to false -to have the desired effect when there is no netdev present. - -Fixes: f97493657c63 ("net: phylink: add suspend/resume support") -Reported-by: Dan Carpenter -Signed-off-by: Russell King (Oracle) ---- - drivers/net/phy/phylink.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index 0a0abe8e4be0..5a58c77d0002 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -1333,7 +1333,10 @@ void phylink_suspend(struct phylink *pl, bool mac_wol) - * but one would hope all packets have been sent. This - * also means phylink_resolve() will do nothing. - */ -- netif_carrier_off(pl->netdev); -+ if (pl->netdev) -+ netif_carrier_off(pl->netdev); -+ else -+ pl->old_link_state = false; - - /* We do not call mac_link_down() here as we want the - * link to remain up to receive the WoL packets. --- -cgit v1.2.3 - - -From df6edf486b7558394d1591efe963fe5cf87c624d Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Thu, 30 Jan 2020 22:42:38 +0000 -Subject: net: dpaa2-mac: add support for more ethtool 10G link modes -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Phylink documentation says: - Note that the PHY may be able to transform from one connection - technology to another, so, eg, don't clear 1000BaseX just - because the MAC is unable to BaseX mode. This is more about - clearing unsupported speeds and duplex settings. The port modes - should not be cleared; phylink_set_port_modes() will help with this. - -So add the missing 10G modes. - -Signed-off-by: Russell King -Acked-by: Marek BehĂșn -Acked-by: Ioana Ciornei ---- - drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -index ae6d382d8735..a882f7e6639a 100644 ---- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -@@ -140,6 +140,12 @@ static void dpaa2_mac_validate(struct phylink_config *config, - case PHY_INTERFACE_MODE_10GBASER: - case PHY_INTERFACE_MODE_USXGMII: - phylink_set(mask, 10000baseT_Full); -+ phylink_set(mask, 10000baseKR_Full); -+ phylink_set(mask, 10000baseCR_Full); -+ phylink_set(mask, 10000baseSR_Full); -+ phylink_set(mask, 10000baseLR_Full); -+ phylink_set(mask, 10000baseLRM_Full); -+ phylink_set(mask, 10000baseER_Full); - if (state->interface == PHY_INTERFACE_MODE_10GBASER) - break; - phylink_set(mask, 5000baseT_Full); --- -cgit v1.2.3 - - -From 8ddb65e56fff39d44c0574091ebcd95dd3343d8e Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Fri, 29 Nov 2019 21:41:56 +0000 -Subject: net: phy: marvell10g: add downshift tunable support - -Add support for the downshift tunable for the Marvell 88x3310 PHY. -Downshift is only usable with firmware 0.3.5.0 and later. - -Signed-off-by: Russell King ---- - drivers/net/phy/marvell10g.c | 107 ++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 106 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c -index bd310e8d5e43..b6fea119fe13 100644 ---- a/drivers/net/phy/marvell10g.c -+++ b/drivers/net/phy/marvell10g.c -@@ -22,6 +22,7 @@ - * If both the fiber and copper ports are connected, the first to gain - * link takes priority and the other port is completely locked out. - */ -+#include - #include - #include - #include -@@ -33,6 +34,8 @@ - #define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe - #define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa) - -+#define MV_VERSION(a,b,c,d) ((a) << 24 | (b) << 16 | (c) << 8 | (d)) -+ - enum { - MV_PMA_FW_VER0 = 0xc011, - MV_PMA_FW_VER1 = 0xc012, -@@ -62,6 +65,15 @@ enum { - MV_PCS_CSCR1_MDIX_MDIX = 0x0020, - MV_PCS_CSCR1_MDIX_AUTO = 0x0060, - -+ MV_PCS_DSC1 = 0x8003, -+ MV_PCS_DSC1_ENABLE = BIT(9), -+ MV_PCS_DSC1_10GBT = 0x01c0, -+ MV_PCS_DSC1_1GBR = 0x0038, -+ MV_PCS_DSC1_100BTX = 0x0007, -+ MV_PCS_DSC2 = 0x8004, -+ MV_PCS_DSC2_2P5G = 0xf000, -+ MV_PCS_DSC2_5G = 0x0f00, -+ - MV_PCS_CSSR1 = 0x8008, - MV_PCS_CSSR1_SPD1_MASK = 0xc000, - MV_PCS_CSSR1_SPD1_SPD2 = 0xc000, -@@ -125,6 +137,7 @@ enum { - }; - - struct mv3310_chip { -+ bool (*has_downshift)(struct phy_device *phydev); - void (*init_supported_interfaces)(unsigned long *mask); - int (*get_mactype)(struct phy_device *phydev); - int (*init_interface)(struct phy_device *phydev, int mactype); -@@ -138,6 +151,7 @@ struct mv3310_priv { - DECLARE_BITMAP(supported_interfaces, PHY_INTERFACE_MODE_MAX); - - u32 firmware_ver; -+ bool has_downshift; - bool rate_match; - phy_interface_t const_interface; - -@@ -330,6 +344,71 @@ static int mv3310_reset(struct phy_device *phydev, u32 unit) - 5000, 100000, true); - } - -+static int mv3310_get_downshift(struct phy_device *phydev, u8 *ds) -+{ -+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); -+ int val; -+ -+ if (!priv->has_downshift) -+ return -EOPNOTSUPP; -+ -+ val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1); -+ if (val < 0) -+ return val; -+ -+ if (val & MV_PCS_DSC1_ENABLE) -+ /* assume that all fields are the same */ -+ *ds = 1 + FIELD_GET(MV_PCS_DSC1_10GBT, (u16)val); -+ else -+ *ds = DOWNSHIFT_DEV_DISABLE; -+ -+ return 0; -+} -+ -+static int mv3310_set_downshift(struct phy_device *phydev, u8 ds) -+{ -+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); -+ u16 val; -+ int err; -+ -+ if (!priv->has_downshift) -+ return -EOPNOTSUPP; -+ -+ if (ds == DOWNSHIFT_DEV_DISABLE) -+ return phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1, -+ MV_PCS_DSC1_ENABLE); -+ -+ /* DOWNSHIFT_DEV_DEFAULT_COUNT is confusing. It looks like it should -+ * set the default settings for the PHY. However, it is used for -+ * "ethtool --set-phy-tunable ethN downshift on". The intention is -+ * to enable downshift at a default number of retries. The default -+ * settings for 88x3310 are for two retries with downshift disabled. -+ * So let's use two retries with downshift enabled. -+ */ -+ if (ds == DOWNSHIFT_DEV_DEFAULT_COUNT) -+ ds = 2; -+ -+ if (ds > 8) -+ return -E2BIG; -+ -+ ds -= 1; -+ val = FIELD_PREP(MV_PCS_DSC2_2P5G, ds); -+ val |= FIELD_PREP(MV_PCS_DSC2_5G, ds); -+ err = phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC2, -+ MV_PCS_DSC2_2P5G | MV_PCS_DSC2_5G, val); -+ if (err < 0) -+ return err; -+ -+ val = MV_PCS_DSC1_ENABLE; -+ val |= FIELD_PREP(MV_PCS_DSC1_10GBT, ds); -+ val |= FIELD_PREP(MV_PCS_DSC1_1GBR, ds); -+ val |= FIELD_PREP(MV_PCS_DSC1_100BTX, ds); -+ -+ return phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1, -+ MV_PCS_DSC1_ENABLE | MV_PCS_DSC1_10GBT | -+ MV_PCS_DSC1_1GBR | MV_PCS_DSC1_100BTX, val); -+} -+ - static int mv3310_get_edpd(struct phy_device *phydev, u16 *edpd) - { - int val; -@@ -448,6 +527,9 @@ static int mv3310_probe(struct phy_device *phydev) - priv->firmware_ver >> 24, (priv->firmware_ver >> 16) & 255, - (priv->firmware_ver >> 8) & 255, priv->firmware_ver & 255); - -+ if (chip->has_downshift) -+ priv->has_downshift = chip->has_downshift(phydev); -+ - /* Powering down the port when not in use saves about 600mW */ - ret = mv3310_power_down(phydev); - if (ret) -@@ -616,7 +698,16 @@ static int mv3310_config_init(struct phy_device *phydev) - } - - /* Enable EDPD mode - saving 600mW */ -- return mv3310_set_edpd(phydev, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS); -+ err = mv3310_set_edpd(phydev, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS); -+ if (err) -+ return err; -+ -+ /* Allow downshift */ -+ err = mv3310_set_downshift(phydev, DOWNSHIFT_DEV_DEFAULT_COUNT); -+ if (err && err != -EOPNOTSUPP) -+ return err; -+ -+ return 0; - } - - static int mv3310_get_features(struct phy_device *phydev) -@@ -886,6 +977,8 @@ static int mv3310_get_tunable(struct phy_device *phydev, - struct ethtool_tunable *tuna, void *data) - { - switch (tuna->id) { -+ case ETHTOOL_PHY_DOWNSHIFT: -+ return mv3310_get_downshift(phydev, data); - case ETHTOOL_PHY_EDPD: - return mv3310_get_edpd(phydev, data); - default: -@@ -897,6 +990,8 @@ static int mv3310_set_tunable(struct phy_device *phydev, - struct ethtool_tunable *tuna, const void *data) - { - switch (tuna->id) { -+ case ETHTOOL_PHY_DOWNSHIFT: -+ return mv3310_set_downshift(phydev, *(u8 *)data); - case ETHTOOL_PHY_EDPD: - return mv3310_set_edpd(phydev, *(u16 *)data); - default: -@@ -904,6 +999,14 @@ static int mv3310_set_tunable(struct phy_device *phydev, - } - } - -+static bool mv3310_has_downshift(struct phy_device *phydev) -+{ -+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); -+ -+ /* Fails to downshift with firmware older than v0.3.5.0 */ -+ return priv->firmware_ver >= MV_VERSION(0,3,5,0); -+} -+ - static void mv3310_init_supported_interfaces(unsigned long *mask) - { - __set_bit(PHY_INTERFACE_MODE_SGMII, mask); -@@ -943,6 +1046,7 @@ static void mv2111_init_supported_interfaces(unsigned long *mask) - } - - static const struct mv3310_chip mv3310_type = { -+ .has_downshift = mv3310_has_downshift, - .init_supported_interfaces = mv3310_init_supported_interfaces, - .get_mactype = mv3310_get_mactype, - .init_interface = mv3310_init_interface, -@@ -953,6 +1057,7 @@ static const struct mv3310_chip mv3310_type = { - }; - - static const struct mv3310_chip mv3340_type = { -+ .has_downshift = mv3310_has_downshift, - .init_supported_interfaces = mv3340_init_supported_interfaces, - .get_mactype = mv3310_get_mactype, - .init_interface = mv3340_init_interface, --- -cgit v1.2.3 - - -From a9dceaa69249b72565b36e91d3c1c104b5523907 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 20 Jul 2021 15:15:40 +0100 -Subject: net: phylink: add phylink_set_10g_modes() helper - -Add a helper for setting 10Gigabit modes, so we have one central -place that sets all appropriate 10G modes for a driver. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/phy/phylink.c | 11 +++++++++++ - include/linux/phylink.h | 1 + - 2 files changed, 12 insertions(+) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index 5a58c77d0002..b32774fd65f8 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -132,6 +132,17 @@ void phylink_set_port_modes(unsigned long *mask) - } - EXPORT_SYMBOL_GPL(phylink_set_port_modes); - -+void phylink_set_10g_modes(unsigned long *mask) -+{ -+ phylink_set(mask, 10000baseT_Full); -+ phylink_set(mask, 10000baseCR_Full); -+ phylink_set(mask, 10000baseSR_Full); -+ phylink_set(mask, 10000baseLR_Full); -+ phylink_set(mask, 10000baseLRM_Full); -+ phylink_set(mask, 10000baseER_Full); -+} -+EXPORT_SYMBOL_GPL(phylink_set_10g_modes); -+ - static int phylink_is_empty_linkmode(const unsigned long *linkmode) - { - __ETHTOOL_DECLARE_LINK_MODE_MASK(tmp) = { 0, }; -diff --git a/include/linux/phylink.h b/include/linux/phylink.h -index 237291196ce2..f7b5ed06a815 100644 ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -484,6 +484,7 @@ int phylink_speed_up(struct phylink *pl); - #define phylink_test(bm, mode) __phylink_do_bit(test_bit, bm, mode) - - void phylink_set_port_modes(unsigned long *bits); -+void phylink_set_10g_modes(unsigned long *mask); - void phylink_helper_basex_speed(struct phylink_link_state *state); - - void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs, --- -cgit v1.2.3 - - -From 4b393905843b414acb4e68e875fb162124c43d32 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 20 Jul 2021 15:20:28 +0100 -Subject: net: ethernet: use phylink_set_10g_modes() - -Update three drivers to use the new phylink_set_10g_modes() helper: -Cadence macb, Freescale DPAA2 and Marvell PP2. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/cadence/macb_main.c | 7 +------ - drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 7 +------ - drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 7 +------ - 3 files changed, 3 insertions(+), 18 deletions(-) - -diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c -index d13fb1d31821..e9519b2d505f 100644 ---- a/drivers/net/ethernet/cadence/macb_main.c -+++ b/drivers/net/ethernet/cadence/macb_main.c -@@ -547,13 +547,8 @@ static void macb_validate(struct phylink_config *config, - if (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE && - (state->interface == PHY_INTERFACE_MODE_NA || - state->interface == PHY_INTERFACE_MODE_10GBASER)) { -- phylink_set(mask, 10000baseCR_Full); -- phylink_set(mask, 10000baseER_Full); -+ phylink_set_10g_modes(mask); - phylink_set(mask, 10000baseKR_Full); -- phylink_set(mask, 10000baseLR_Full); -- phylink_set(mask, 10000baseLRM_Full); -- phylink_set(mask, 10000baseSR_Full); -- phylink_set(mask, 10000baseT_Full); - if (state->interface != PHY_INTERFACE_MODE_NA) - goto out; - } -diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -index a882f7e6639a..3faf45c22c19 100644 ---- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -@@ -139,13 +139,8 @@ static void dpaa2_mac_validate(struct phylink_config *config, - case PHY_INTERFACE_MODE_NA: - case PHY_INTERFACE_MODE_10GBASER: - case PHY_INTERFACE_MODE_USXGMII: -- phylink_set(mask, 10000baseT_Full); -+ phylink_set_10g_modes(mask); - phylink_set(mask, 10000baseKR_Full); -- phylink_set(mask, 10000baseCR_Full); -- phylink_set(mask, 10000baseSR_Full); -- phylink_set(mask, 10000baseLR_Full); -- phylink_set(mask, 10000baseLRM_Full); -- phylink_set(mask, 10000baseER_Full); - if (state->interface == PHY_INTERFACE_MODE_10GBASER) - break; - phylink_set(mask, 5000baseT_Full); -diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -index d5c92e43f89e..34b997aa6c66 100644 ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -6301,12 +6301,7 @@ static void mvpp2_phylink_validate(struct phylink_config *config, - case PHY_INTERFACE_MODE_XAUI: - case PHY_INTERFACE_MODE_NA: - if (mvpp2_port_supports_xlg(port)) { -- phylink_set(mask, 10000baseT_Full); -- phylink_set(mask, 10000baseCR_Full); -- phylink_set(mask, 10000baseSR_Full); -- phylink_set(mask, 10000baseLR_Full); -- phylink_set(mask, 10000baseLRM_Full); -- phylink_set(mask, 10000baseER_Full); -+ phylink_set_10g_modes(mask); - phylink_set(mask, 10000baseKR_Full); - } - if (state->interface != PHY_INTERFACE_MODE_NA) --- -cgit v1.2.3 - - -From cc39c29dad942b6d949ecf77618eb50af847a793 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 5 Oct 2021 15:55:44 +0100 -Subject: net: mdio: add mdiobus_modify_changed() - -Add mdiobus_modify_changed() helper to reflect the phylib and similar -equivalents. This will avoid this functionality being open-coded, as -has already happened in phylink, and it looks like other users will be -appearing soon. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/phy/mdio_bus.c | 22 ++++++++++++++++++++++ - include/linux/mdio.h | 2 ++ - 2 files changed, 24 insertions(+) - -diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c -index 6865d9319197..daf8356b54f3 100644 ---- a/drivers/net/phy/mdio_bus.c -+++ b/drivers/net/phy/mdio_bus.c -@@ -936,6 +936,28 @@ int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set) - } - EXPORT_SYMBOL_GPL(mdiobus_modify); - -+/** -+ * mdiobus_modify_changed - Convenience function for modifying a given mdio -+ * device register and returning if it changed -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @regnum: register number to write -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ */ -+int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, -+ u16 mask, u16 set) -+{ -+ int err; -+ -+ mutex_lock(&bus->mdio_lock); -+ err = __mdiobus_modify_changed(bus, addr, regnum, mask, set); -+ mutex_unlock(&bus->mdio_lock); -+ -+ return err; -+} -+EXPORT_SYMBOL_GPL(mdiobus_modify_changed); -+ - /** - * mdio_bus_match - determine if given MDIO driver supports the given - * MDIO device -diff --git a/include/linux/mdio.h b/include/linux/mdio.h -index 5e6dc38f418e..f622888a4ba8 100644 ---- a/include/linux/mdio.h -+++ b/include/linux/mdio.h -@@ -349,6 +349,8 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); - int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val); - int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, - u16 set); -+int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, -+ u16 mask, u16 set); - - static inline u32 mdiobus_c45_addr(int devad, u16 regnum) - { --- -cgit v1.2.3 - - -From c35eeaaf2306ff035b069769682b2882b055e0aa Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 5 Oct 2021 15:59:17 +0100 -Subject: net: phylink: use mdiobus_modify_changed() helper - -Use the mdiobus_modify_changed() helper in the C22 PCS advertisement -helper. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/phy/phylink.c | 29 ++++------------------------- - 1 file changed, 4 insertions(+), 25 deletions(-) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index b32774fd65f8..16240f2dd161 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -2596,7 +2596,6 @@ int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs, - { - struct mii_bus *bus = pcs->bus; - int addr = pcs->addr; -- int val, ret; - u16 adv; - - switch (interface) { -@@ -2610,32 +2609,12 @@ int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs, - advertising)) - adv |= ADVERTISE_1000XPSE_ASYM; - -- val = mdiobus_read(bus, addr, MII_ADVERTISE); -- if (val < 0) -- return val; -- -- if (val == adv) -- return 0; -- -- ret = mdiobus_write(bus, addr, MII_ADVERTISE, adv); -- if (ret < 0) -- return ret; -- -- return 1; -+ return mdiobus_modify_changed(bus, addr, MII_ADVERTISE, -+ 0xffff, adv); - - case PHY_INTERFACE_MODE_SGMII: -- val = mdiobus_read(bus, addr, MII_ADVERTISE); -- if (val < 0) -- return val; -- -- if (val == 0x0001) -- return 0; -- -- ret = mdiobus_write(bus, addr, MII_ADVERTISE, 0x0001); -- if (ret < 0) -- return ret; -- -- return 1; -+ return mdiobus_modify_changed(bus, addr, MII_ADVERTISE, -+ 0xffff, 0x0001); - - default: - /* Nothing to do for other modes */ --- -cgit v1.2.3 - - -From e300459e5ce423f67857b43edf071c173ebeb934 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 30 Sep 2021 15:05:29 +0100 -Subject: net: mdio: ensure the type of mdio devices match mdio drivers - -On the MDIO bus, we have PHYLIB devices and drivers, and we have non- -PHYLIB devices and drivers. PHYLIB devices are MDIO devices that are -wrapped with a struct phy_device. - -Trying to bind a MDIO device with a PHYLIB driver results in out-of- -bounds accesses as we attempt to access struct phy_device members. So, -let's prevent this by ensuring that the type of the MDIO device -(indicated by the MDIO_DEVICE_FLAG_PHY flag) matches the type of the -MDIO driver (indicated by the MDIO_DEVICE_IS_PHY flag.) - -Link: https://lore.kernel.org/r/2b1dc053-8c9a-e3e4-b450-eecdfca3fe16@gmail.com -Tested-by: Andrew Lunn -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) ---- - drivers/net/phy/mdio_bus.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c -index daf8356b54f3..c204067f1890 100644 ---- a/drivers/net/phy/mdio_bus.c -+++ b/drivers/net/phy/mdio_bus.c -@@ -971,8 +971,14 @@ EXPORT_SYMBOL_GPL(mdiobus_modify_changed); - */ - static int mdio_bus_match(struct device *dev, struct device_driver *drv) - { -+ struct mdio_driver *mdiodrv = to_mdio_driver(drv); - struct mdio_device *mdio = to_mdio_device(dev); - -+ /* Both the driver and device must type-match */ -+ if (!(mdiodrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY) != -+ !(mdio->flags & MDIO_DEVICE_FLAG_PHY)) -+ return 0; -+ - if (of_driver_match_device(dev, drv)) - return 1; - --- -cgit v1.2.3 - - -From 75af9fd1e94a23451c76f5e2aa382e22c3617b24 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 30 Sep 2021 15:09:34 +0100 -Subject: net: phylib: ensure phy device drivers do not match by DT - -PHYLIB device drivers must match by either numerical PHY ID or by their -.match_phy_device method. Matching by DT is not permitted. - -Link: https://lore.kernel.org/r/2b1dc053-8c9a-e3e4-b450-eecdfca3fe16@gmail.com -Tested-by: Andrew Lunn -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) ---- - drivers/net/phy/phy_device.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c -index 4f9990b47a37..74d8e1dc125f 100644 ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -3149,6 +3149,16 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner) - return -EINVAL; - } - -+ /* PHYLIB device drivers must not match using a DT compatible table -+ * as this bypasses our checks that the mdiodev that is being matched -+ * is backed by a struct phy_device. If such a case happens, we will -+ * make out-of-bounds accesses and lockup in phydev->lock. -+ */ -+ if (WARN(new_driver->mdiodrv.driver.of_match_table, -+ "%s: driver must not provide a DT match table\n", -+ new_driver->name)) -+ return -EINVAL; -+ - new_driver->mdiodrv.flags |= MDIO_DEVICE_IS_PHY; - new_driver->mdiodrv.driver.name = new_driver->name; - new_driver->mdiodrv.driver.bus = &mdio_bus_type; --- -cgit v1.2.3 - - -From 6233a59885951c7ad41f4d5ef32b3b8f6695a6ac Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 15 Oct 2021 17:07:14 +0100 -Subject: net: phylink: rejig SFP interface selection in ksettings_set() - -Commit d7ef2067b00f ("net: phylink: Update SFP selected interface on -advertising changes") added a better solution to selecting the -interface mode for SFPs using the advertisement mask. This method will -work for mvneta and mvpp2 when selecting between 2500base-X and -1000base-X. - -We need to eliminate the validation prior to selecting the interface, -otherwise when we clean up mvneta's validation function, we will end -up locking to 2500base-X as we validate with an interface mode of -PHY_INERFACE_MODE_2500BASEX. - -The supported mask will already have been reduced down to the union of -support for the SFP and MAC already, so we can be confident that the -advertisement mask is already appropriately restricted. We only need to -select the appropriate interface, and then revalidate with the new -interface mode. - -Signed-off-by: Russell King ---- - drivers/net/phy/phylink.c | 20 ++++++++++---------- - 1 file changed, 10 insertions(+), 10 deletions(-) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index 16240f2dd161..9ac65f435ff1 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -1612,20 +1612,11 @@ int phylink_ethtool_ksettings_set(struct phylink *pl, - linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, config.advertising, - config.an_enabled); - -- /* Validate without changing the current supported mask. */ -- linkmode_copy(support, pl->supported); -- if (phylink_validate(pl, support, &config)) -- return -EINVAL; -- -- /* If autonegotiation is enabled, we must have an advertisement */ -- if (config.an_enabled && phylink_is_empty_linkmode(config.advertising)) -- return -EINVAL; -- - /* If this link is with an SFP, ensure that changes to advertised modes - * also cause the associated interface to be selected such that the - * link can be configured correctly. - */ -- if (pl->sfp_port && pl->sfp_bus) { -+ if (pl->sfp_bus) { - config.interface = sfp_select_interface(pl->sfp_bus, - config.advertising); - if (config.interface == PHY_INTERFACE_MODE_NA) { -@@ -1645,8 +1636,17 @@ int phylink_ethtool_ksettings_set(struct phylink *pl, - __ETHTOOL_LINK_MODE_MASK_NBITS, support); - return -EINVAL; - } -+ } else { -+ /* Validate without changing the current supported mask. */ -+ linkmode_copy(support, pl->supported); -+ if (phylink_validate(pl, support, &config)) -+ return -EINVAL; - } - -+ /* If autonegotiation is enabled, we must have an advertisement */ -+ if (config.an_enabled && phylink_is_empty_linkmode(config.advertising)) -+ return -EINVAL; -+ - mutex_lock(&pl->state_mutex); - pl->link_config.speed = config.speed; - pl->link_config.duplex = config.duplex; --- -cgit v1.2.3 - - -From 8309808283a7930fa9b809238226914a8e89b661 Mon Sep 17 00:00:00 2001 -From: Robert Hancock -Date: Wed, 30 Jun 2021 11:49:27 -0600 -Subject: net: phylink: Support disabling autonegotiation for PCS - -The auto-negotiation state in the PCS as set by -phylink_mii_c22_pcs_config was previously always enabled when the -driver is configured for in-band autonegotiation, even if -autonegotiation was disabled on the interface with ethtool. Update the -code to set the BMCR_ANENABLE bit based on the interface's -autonegotiation enabled state. - -Update phylink_mii_c22_pcs_get_state to not check -autonegotiation-related fields when autonegotiation is disabled. - -Update phylink_mac_pcs_get_state to initialize the state based on the -interface's configured speed, duplex and pause parameters rather than -to unknown when autonegotiation is disabled, before calling the -driver's pcs_get_state functions, as they are not likely to provide -meaningful data for these fields when autonegotiation is disabled. In -this case the driver is really just filling in the link state field. - -Note that in cases where there is a downstream PHY connected, such as -with SGMII and a copper PHY, the configuration set by ethtool is -handled by phy_ethtool_ksettings_set and not propagated to the PCS. -This is correct since SGMII or 1000Base-X autonegotiation with the PCS -should normally still be used even if the copper side has disabled it. - -Signed-off-by: Robert Hancock -Signed-off-by: Russell King (Oracle) ---- - drivers/net/phy/phylink.c | 21 ++++++++++++++++----- - 1 file changed, 16 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index 9ac65f435ff1..06de8c02efcb 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -551,9 +551,15 @@ static void phylink_mac_pcs_get_state(struct phylink *pl, - linkmode_zero(state->lp_advertising); - state->interface = pl->link_config.interface; - state->an_enabled = pl->link_config.an_enabled; -- state->speed = SPEED_UNKNOWN; -- state->duplex = DUPLEX_UNKNOWN; -- state->pause = MLO_PAUSE_NONE; -+ if (state->an_enabled) { -+ state->speed = SPEED_UNKNOWN; -+ state->duplex = DUPLEX_UNKNOWN; -+ state->pause = MLO_PAUSE_NONE; -+ } else { -+ state->speed = pl->link_config.speed; -+ state->duplex = pl->link_config.duplex; -+ state->pause = pl->link_config.pause; -+ } - state->an_complete = 0; - state->link = 1; - -@@ -2549,7 +2555,10 @@ void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs, - - state->link = !!(bmsr & BMSR_LSTATUS); - state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE); -- if (!state->link) -+ /* If there is no link or autonegotiation is disabled, the LP advertisement -+ * data is not meaningful, so don't go any further. -+ */ -+ if (!state->link || !state->an_enabled) - return; - - switch (state->interface) { -@@ -2651,7 +2660,9 @@ int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode, - changed = ret > 0; - - /* Ensure ISOLATE bit is disabled */ -- bmcr = mode == MLO_AN_INBAND ? BMCR_ANENABLE : 0; -+ bmcr = (mode == MLO_AN_INBAND && -+ linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) ? -+ BMCR_ANENABLE : 0; - ret = mdiobus_modify(pcs->bus, pcs->addr, MII_BMCR, - BMCR_ANENABLE | BMCR_ISOLATE, bmcr); - if (ret < 0) --- -cgit v1.2.3 - - -From 65fdb409d3d4e963ff6712dc2bc178049ec88339 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Wed, 22 Sep 2021 14:47:00 +0100 -Subject: net: phylink: avoid mvneta warning when setting pause parameters - -mvneta does not support asymetric pause modes, and it flags this by the -lack of AsymPause in the supported field. When setting pause modes, we -check that pause->rx_pause == pause->tx_pause, but only when pause -autoneg is enabled. When pause autoneg is disabled, we still allow -pause->rx_pause != pause->tx_pause, which is incorrect when the MAC -does not support asymetric pause, and causes mvneta to issue a warning. - -Fix this by removing the test for pause->autoneg, so we always check -that pause->rx_pause == pause->tx_pause for network devices that do not -support AsymPause. - -Fixes: 9525ae83959b ("phylink: add phylink infrastructure") -Signed-off-by: Russell King (Oracle) ---- - drivers/net/phy/phylink.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index 06de8c02efcb..a0bf1201cacb 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -1744,7 +1744,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl, - return -EOPNOTSUPP; - - if (!phylink_test(pl->supported, Asym_Pause) && -- !pause->autoneg && pause->rx_pause != pause->tx_pause) -+ pause->rx_pause != pause->tx_pause) - return -EINVAL; - - pause_state = 0; --- -cgit v1.2.3 - - -From e054e089ff493f677ba097626730da8220692899 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 8 Jun 2021 14:43:54 +0100 -Subject: net: phy: add phy_interface_t bitmap support - -Add support for a bitmap for phy interface modes, which includes: -- a macro to declare the interface bitmap -- an inline helper to zero the interface bitmap -- an inline helper to detect an empty interface bitmap -- an inline helper to do a bitwise AND operation on two interface - bitmaps - -Signed-off-by: Russell King (Oracle) ---- - include/linux/phy.h | 34 ++++++++++++++++++++++++++++++++++ - 1 file changed, 34 insertions(+) - -diff --git a/include/linux/phy.h b/include/linux/phy.h -index 736e1d1a47c4..1b47eca539f3 100644 ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -155,6 +155,40 @@ typedef enum { - PHY_INTERFACE_MODE_MAX, - } phy_interface_t; - -+/* PHY interface mode bitmap handling */ -+#define DECLARE_PHY_INTERFACE_MASK(name) \ -+ DECLARE_BITMAP(name, PHY_INTERFACE_MODE_MAX) -+ -+static inline void phy_interface_zero(unsigned long *intf) -+{ -+ bitmap_zero(intf, PHY_INTERFACE_MODE_MAX); -+} -+ -+static inline bool phy_interface_empty(const unsigned long *intf) -+{ -+ return bitmap_empty(intf, PHY_INTERFACE_MODE_MAX); -+} -+ -+static inline void phy_interface_and(unsigned long *dst, const unsigned long *a, -+ const unsigned long *b) -+{ -+ bitmap_and(dst, a, b, PHY_INTERFACE_MODE_MAX); -+} -+ -+static inline void phy_interface_or(unsigned long *dst, const unsigned long *a, -+ const unsigned long *b) -+{ -+ bitmap_or(dst, a, b, PHY_INTERFACE_MODE_MAX); -+} -+ -+static inline void phy_interface_set_rgmii(unsigned long *intf) -+{ -+ __set_bit(PHY_INTERFACE_MODE_RGMII, intf); -+ __set_bit(PHY_INTERFACE_MODE_RGMII_ID, intf); -+ __set_bit(PHY_INTERFACE_MODE_RGMII_RXID, intf); -+ __set_bit(PHY_INTERFACE_MODE_RGMII_TXID, intf); -+} -+ - /* - * phy_supported_speeds - return all speeds currently supported by a PHY device - */ --- -cgit v1.2.3 - - -From adfb4b36dfbbb350956ff8aa6f8741e389140469 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Tue, 3 Mar 2020 12:12:43 +0000 -Subject: net: phylink: add MAC phy_interface_t bitmap - -Add a phy_interface_t bitmap so the MAC driver can specifiy which PHY -interface modes it supports. - -Signed-off-by: Russell King ---- - include/linux/phylink.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/include/linux/phylink.h b/include/linux/phylink.h -index f7b5ed06a815..bc4b866cd99b 100644 ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -76,6 +76,7 @@ struct phylink_config { - bool ovr_an_inband; - void (*get_fixed_state)(struct phylink_config *config, - struct phylink_link_state *state); -+ DECLARE_PHY_INTERFACE_MASK(supported_interfaces); - }; - - /** --- -cgit v1.2.3 - - -From a78736fe3357aae2b069ea55d211406661f1dc97 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 15 Oct 2021 10:51:15 +0100 -Subject: net: phylink: use supported_interfaces for phylink validation - -If the network device supplies a supported interface bitmap, we can use -that during phylink's validation to simplify MAC drivers in two ways by -using the supported_interfaces bitmap to: - -1. reject unsupported interfaces before calling into the MAC driver. -2. generate the set of all supported link modes across all supported - interfaces (used mainly for SFP, but also some 10G PHYs.) - -Suggested-by: Sean Anderson -Signed-off-by: Russell King (Oracle) ---- - drivers/net/phy/phylink.c | 36 ++++++++++++++++++++++++++++++++++++ - include/linux/phylink.h | 12 ++++++++++-- - 2 files changed, 46 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index a0bf1201cacb..5fbd4de129d1 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -166,9 +166,45 @@ static const char *phylink_an_mode_str(unsigned int mode) - return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; - } - -+static int phylink_validate_any(struct phylink *pl, unsigned long *supported, -+ struct phylink_link_state *state) -+{ -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(all_adv) = { 0, }; -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(all_s) = { 0, }; -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(s); -+ struct phylink_link_state t; -+ int intf; -+ -+ for (intf = 0; intf < PHY_INTERFACE_MODE_MAX; intf++) { -+ if (test_bit(intf, pl->config->supported_interfaces)) { -+ linkmode_copy(s, supported); -+ -+ t = *state; -+ t.interface = intf; -+ pl->mac_ops->validate(pl->config, s, &t); -+ linkmode_or(all_s, all_s, s); -+ linkmode_or(all_adv, all_adv, t.advertising); -+ } -+ } -+ -+ linkmode_copy(supported, all_s); -+ linkmode_copy(state->advertising, all_adv); -+ -+ return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; -+} -+ - static int phylink_validate(struct phylink *pl, unsigned long *supported, - struct phylink_link_state *state) - { -+ if (!phy_interface_empty(pl->config->supported_interfaces)) { -+ if (state->interface == PHY_INTERFACE_MODE_NA) -+ return phylink_validate_any(pl, supported, state); -+ -+ if (!test_bit(state->interface, -+ pl->config->supported_interfaces)) -+ return -EINVAL; -+ } -+ - pl->mac_ops->validate(pl->config, supported, state); - - return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; -diff --git a/include/linux/phylink.h b/include/linux/phylink.h -index bc4b866cd99b..f037470b6fb3 100644 ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -67,6 +67,8 @@ enum phylink_op_type { - * @ovr_an_inband: if true, override PCS to MLO_AN_INBAND - * @get_fixed_state: callback to execute to determine the fixed link state, - * if MAC link is at %MLO_AN_FIXED mode. -+ * @supported_interfaces: bitmap describing which PHY_INTERFACE_MODE_xxx -+ * are supported by the MAC/PCS. - */ - struct phylink_config { - struct device *dev; -@@ -134,8 +136,14 @@ struct phylink_mac_ops { - * based on @state->advertising and/or @state->speed and update - * @state->interface accordingly. See phylink_helper_basex_speed(). - * -- * When @state->interface is %PHY_INTERFACE_MODE_NA, phylink expects the -- * MAC driver to return all supported link modes. -+ * When @config->supported_interfaces has been set, phylink will iterate -+ * over the supported interfaces to determine the full capability of the -+ * MAC. The validation function must not print errors if @state->interface -+ * is set to an unexpected value. -+ * -+ * When @config->supported_interfaces is empty, phylink will call this -+ * function with @state->interface set to %PHY_INTERFACE_MODE_NA, and -+ * expects the MAC driver to return all supported link modes. - * - * If the @state->interface mode is not supported, then the @supported - * mask must be cleared. --- -cgit v1.2.3 - - -From dd96ab95a22cc7810bbe076d7bdd35702e2a722e Mon Sep 17 00:00:00 2001 -From: Sean Anderson -Date: Fri, 22 Oct 2021 18:41:04 -0400 -Subject: net: convert users of bitmap_foo() to linkmode_foo() - -This converts instances of - bitmap_foo(args..., __ETHTOOL_LINK_MODE_MASK_NBITS) -to - linkmode_foo(args...) - -I manually fixed up some lines to prevent them from being excessively -long. Otherwise, this change was generated with the following semantic -patch: - -// Generated with -// echo linux/linkmode.h > includes -// git grep -Flf includes include/ | cut -f 2- -d / | cat includes - \ -// | sort | uniq | tee new_includes | wc -l && mv new_includes includes -// and repeating until the number stopped going up -@i@ -@@ - -( - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -| - #include -) - -@depends on i@ -expression list args; -@@ - -( -- bitmap_zero(args, __ETHTOOL_LINK_MODE_MASK_NBITS) -+ linkmode_zero(args) -| -- bitmap_copy(args, __ETHTOOL_LINK_MODE_MASK_NBITS) -+ linkmode_copy(args) -| -- bitmap_and(args, __ETHTOOL_LINK_MODE_MASK_NBITS) -+ linkmode_and(args) -| -- bitmap_or(args, __ETHTOOL_LINK_MODE_MASK_NBITS) -+ linkmode_or(args) -| -- bitmap_empty(args, ETHTOOL_LINK_MODE_MASK_NBITS) -+ linkmode_empty(args) -| -- bitmap_andnot(args, __ETHTOOL_LINK_MODE_MASK_NBITS) -+ linkmode_andnot(args) -| -- bitmap_equal(args, __ETHTOOL_LINK_MODE_MASK_NBITS) -+ linkmode_equal(args) -| -- bitmap_intersects(args, __ETHTOOL_LINK_MODE_MASK_NBITS) -+ linkmode_intersects(args) -| -- bitmap_subset(args, __ETHTOOL_LINK_MODE_MASK_NBITS) -+ linkmode_subset(args) -) - -Add missing linux/mii.h include to mellanox. -DaveM - -Signed-off-by: Sean Anderson -Signed-off-by: David S. Miller ---- - drivers/net/dsa/b53/b53_common.c | 6 ++---- - drivers/net/dsa/bcm_sf2.c | 8 +++----- - drivers/net/dsa/hirschmann/hellcreek.c | 6 ++---- - drivers/net/dsa/lantiq_gswip.c | 14 ++++++-------- - drivers/net/dsa/microchip/ksz8795.c | 8 +++----- - drivers/net/dsa/mv88e6xxx/chip.c | 5 ++--- - drivers/net/dsa/ocelot/felix_vsc9959.c | 8 +++----- - drivers/net/dsa/ocelot/seville_vsc9953.c | 8 +++----- - drivers/net/dsa/qca/ar9331.c | 10 ++++------ - drivers/net/dsa/sja1105/sja1105_main.c | 7 +++---- - drivers/net/dsa/xrs700x/xrs700x.c | 8 +++----- - drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 8 +++----- - drivers/net/ethernet/atheros/ag71xx.c | 8 +++----- - drivers/net/ethernet/cadence/macb_main.c | 11 +++++------ - drivers/net/ethernet/freescale/enetc/enetc_pf.c | 8 +++----- - drivers/net/ethernet/huawei/hinic/hinic_ethtool.c | 10 ++++------ - drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 5 ++--- - drivers/net/ethernet/marvell/mvneta.c | 10 ++++------ - drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 7 +++---- - .../ethernet/marvell/octeontx2/nic/otx2_ethtool.c | 5 ++--- - drivers/net/ethernet/marvell/pxa168_eth.c | 3 +-- - drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 21 ++++++++------------- - .../net/ethernet/microchip/sparx5/sparx5_phylink.c | 7 +++---- - drivers/net/ethernet/mscc/ocelot_net.c | 7 +++---- - drivers/net/ethernet/pensando/ionic/ionic_ethtool.c | 3 +-- - drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 8 +++----- - drivers/net/pcs/pcs-xpcs.c | 2 +- - drivers/net/phy/sfp-bus.c | 2 +- - net/ethtool/ioctl.c | 7 +++---- - 29 files changed, 87 insertions(+), 133 deletions(-) - -diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c -index 604f54112665..b6f63ff938d0 100644 ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1349,10 +1349,8 @@ void b53_phylink_validate(struct dsa_switch *ds, int port, - phylink_set(mask, 100baseT_Full); - } - -- bitmap_and(supported, supported, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - - phylink_helper_basex_speed(state); - } -diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c -index 7578a5c38df5..a46fe385acd6 100644 ---- a/drivers/net/dsa/bcm_sf2.c -+++ b/drivers/net/dsa/bcm_sf2.c -@@ -683,7 +683,7 @@ static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port, - state->interface != PHY_INTERFACE_MODE_GMII && - state->interface != PHY_INTERFACE_MODE_INTERNAL && - state->interface != PHY_INTERFACE_MODE_MOCA) { -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - if (port != core_readl(priv, CORE_IMP0_PRT_ID)) - dev_err(ds->dev, - "Unsupported interface: %d for port %d\n", -@@ -711,10 +711,8 @@ static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port, - phylink_set(mask, 100baseT_Half); - phylink_set(mask, 100baseT_Full); - -- bitmap_and(supported, supported, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - - static void bcm_sf2_sw_mac_config(struct dsa_switch *ds, int port, -diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c -index 354655f9ed00..4e0b53d94b52 100644 ---- a/drivers/net/dsa/hirschmann/hellcreek.c -+++ b/drivers/net/dsa/hirschmann/hellcreek.c -@@ -1403,10 +1403,8 @@ static void hellcreek_phylink_validate(struct dsa_switch *ds, int port, - else - phylink_set(mask, 1000baseT_Full); - -- bitmap_and(supported, supported, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - - static int -diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c -index dbd4486a173f..a3e937a371ef 100644 ---- a/drivers/net/dsa/lantiq_gswip.c -+++ b/drivers/net/dsa/lantiq_gswip.c -@@ -1447,10 +1447,8 @@ static void gswip_phylink_set_capab(unsigned long *supported, - phylink_set(mask, 100baseT_Half); - phylink_set(mask, 100baseT_Full); - -- bitmap_and(supported, supported, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - - static void gswip_xrx200_phylink_validate(struct dsa_switch *ds, int port, -@@ -1478,7 +1476,7 @@ static void gswip_xrx200_phylink_validate(struct dsa_switch *ds, int port, - goto unsupported; - break; - default: -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - dev_err(ds->dev, "Unsupported port: %i\n", port); - return; - } -@@ -1488,7 +1486,7 @@ static void gswip_xrx200_phylink_validate(struct dsa_switch *ds, int port, - return; - - unsupported: -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - dev_err(ds->dev, "Unsupported interface '%s' for port %d\n", - phy_modes(state->interface), port); - } -@@ -1518,7 +1516,7 @@ static void gswip_xrx300_phylink_validate(struct dsa_switch *ds, int port, - goto unsupported; - break; - default: -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - dev_err(ds->dev, "Unsupported port: %i\n", port); - return; - } -@@ -1528,7 +1526,7 @@ static void gswip_xrx300_phylink_validate(struct dsa_switch *ds, int port, - return; - - unsupported: -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - dev_err(ds->dev, "Unsupported interface '%s' for port %d\n", - phy_modes(state->interface), port); - } -diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c -index c5142f86a3c7..43fc3087aeb3 100644 ---- a/drivers/net/dsa/microchip/ksz8795.c -+++ b/drivers/net/dsa/microchip/ksz8795.c -@@ -1542,15 +1542,13 @@ static void ksz8_validate(struct dsa_switch *ds, int port, - phylink_set(mask, 100baseT_Half); - phylink_set(mask, 100baseT_Full); - -- bitmap_and(supported, supported, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - - return; - - unsupported: -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - dev_err(ds->dev, "Unsupported interface: %s, port: %d\n", - phy_modes(state->interface), port); - } -diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c -index 8dadcae93c9b..14c678a9e41b 100644 ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -674,9 +674,8 @@ static void mv88e6xxx_validate(struct dsa_switch *ds, int port, - if (chip->info->ops->phylink_validate) - chip->info->ops->phylink_validate(chip, port, mask, state); - -- bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - - /* We can only operate at 2500BaseX or 1000BaseX. If requested - * to advertise both, only report advertising at 2500BaseX. -diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c -index 11b42fd812e4..45c5ec7a83ea 100644 ---- a/drivers/net/dsa/ocelot/felix_vsc9959.c -+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c -@@ -943,7 +943,7 @@ static void vsc9959_phylink_validate(struct ocelot *ocelot, int port, - - if (state->interface != PHY_INTERFACE_MODE_NA && - state->interface != ocelot_port->phy_mode) { -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - return; - } - -@@ -965,10 +965,8 @@ static void vsc9959_phylink_validate(struct ocelot *ocelot, int port, - phylink_set(mask, 2500baseX_Full); - } - -- bitmap_and(supported, supported, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - - static int vsc9959_prevalidate_phy_mode(struct ocelot *ocelot, int port, -diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c -index de1d34a1f1e4..92eae63150ea 100644 ---- a/drivers/net/dsa/ocelot/seville_vsc9953.c -+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c -@@ -999,7 +999,7 @@ static void vsc9953_phylink_validate(struct ocelot *ocelot, int port, - - if (state->interface != PHY_INTERFACE_MODE_NA && - state->interface != ocelot_port->phy_mode) { -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - return; - } - -@@ -1018,10 +1018,8 @@ static void vsc9953_phylink_validate(struct ocelot *ocelot, int port, - phylink_set(mask, 2500baseX_Full); - } - -- bitmap_and(supported, supported, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - - static int vsc9953_prevalidate_phy_mode(struct ocelot *ocelot, int port, -diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c -index a6bfb6abc51a..da0d7e68643a 100644 ---- a/drivers/net/dsa/qca/ar9331.c -+++ b/drivers/net/dsa/qca/ar9331.c -@@ -522,7 +522,7 @@ static void ar9331_sw_phylink_validate(struct dsa_switch *ds, int port, - goto unsupported; - break; - default: -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - dev_err(ds->dev, "Unsupported port: %i\n", port); - return; - } -@@ -536,15 +536,13 @@ static void ar9331_sw_phylink_validate(struct dsa_switch *ds, int port, - phylink_set(mask, 100baseT_Half); - phylink_set(mask, 100baseT_Full); - -- bitmap_and(supported, supported, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - - return; - - unsupported: -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - dev_err(ds->dev, "Unsupported interface: %d, port: %d\n", - state->interface, port); - } -diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c -index 924c3f129992..b38ccc18bc6f 100644 ---- a/drivers/net/dsa/sja1105/sja1105_main.c -+++ b/drivers/net/dsa/sja1105/sja1105_main.c -@@ -1360,7 +1360,7 @@ static void sja1105_phylink_validate(struct dsa_switch *ds, int port, - */ - if (state->interface != PHY_INTERFACE_MODE_NA && - sja1105_phy_mode_mismatch(priv, port, state->interface)) { -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - return; - } - -@@ -1380,9 +1380,8 @@ static void sja1105_phylink_validate(struct dsa_switch *ds, int port, - phylink_set(mask, 2500baseX_Full); - } - -- bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - - static int -diff --git a/drivers/net/dsa/xrs700x/xrs700x.c b/drivers/net/dsa/xrs700x/xrs700x.c -index 469420941054..910fcb3b252b 100644 ---- a/drivers/net/dsa/xrs700x/xrs700x.c -+++ b/drivers/net/dsa/xrs700x/xrs700x.c -@@ -456,7 +456,7 @@ static void xrs700x_phylink_validate(struct dsa_switch *ds, int port, - phylink_set(mask, 1000baseT_Full); - break; - default: -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - dev_err(ds->dev, "Unsupported port: %i\n", port); - return; - } -@@ -467,10 +467,8 @@ static void xrs700x_phylink_validate(struct dsa_switch *ds, int port, - phylink_set(mask, 10baseT_Full); - phylink_set(mask, 100baseT_Full); - -- bitmap_and(supported, supported, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - - static void xrs700x_mac_link_up(struct dsa_switch *ds, int port, -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c -index bafc51c34e0b..94879cf8b420 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c -@@ -369,9 +369,8 @@ static int xgbe_set_link_ksettings(struct net_device *netdev, - __ETHTOOL_LINK_MODE_MASK_NBITS, cmd->link_modes.advertising, - __ETHTOOL_LINK_MODE_MASK_NBITS, lks->link_modes.supported); - -- bitmap_and(advertising, -- cmd->link_modes.advertising, lks->link_modes.supported, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(advertising, cmd->link_modes.advertising, -+ lks->link_modes.supported); - - if ((cmd->base.autoneg == AUTONEG_ENABLE) && - bitmap_empty(advertising, __ETHTOOL_LINK_MODE_MASK_NBITS)) { -@@ -384,8 +383,7 @@ static int xgbe_set_link_ksettings(struct net_device *netdev, - pdata->phy.autoneg = cmd->base.autoneg; - pdata->phy.speed = speed; - pdata->phy.duplex = cmd->base.duplex; -- bitmap_copy(lks->link_modes.advertising, advertising, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_copy(lks->link_modes.advertising, advertising); - - if (cmd->base.autoneg == AUTONEG_ENABLE) - XGBE_SET_ADV(lks, Autoneg); -diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c -index 02ae98aabf91..121536de80bb 100644 ---- a/drivers/net/ethernet/atheros/ag71xx.c -+++ b/drivers/net/ethernet/atheros/ag71xx.c -@@ -1082,14 +1082,12 @@ static void ag71xx_mac_validate(struct phylink_config *config, - phylink_set(mask, 1000baseX_Full); - } - -- bitmap_and(supported, supported, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - - return; - unsupported: -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - } - - static void ag71xx_mac_pcs_get_state(struct phylink_config *config, -diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c -index e9519b2d505f..e610fdc6ab97 100644 ---- a/drivers/net/ethernet/cadence/macb_main.c -+++ b/drivers/net/ethernet/cadence/macb_main.c -@@ -522,21 +522,21 @@ static void macb_validate(struct phylink_config *config, - state->interface != PHY_INTERFACE_MODE_SGMII && - state->interface != PHY_INTERFACE_MODE_10GBASER && - !phy_interface_mode_is_rgmii(state->interface)) { -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - return; - } - - if (!macb_is_gem(bp) && - (state->interface == PHY_INTERFACE_MODE_GMII || - phy_interface_mode_is_rgmii(state->interface))) { -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - return; - } - - if (state->interface == PHY_INTERFACE_MODE_10GBASER && - !(bp->caps & MACB_CAPS_HIGH_SPEED && - bp->caps & MACB_CAPS_PCS)) { -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - return; - } - -@@ -570,9 +570,8 @@ static void macb_validate(struct phylink_config *config, - phylink_set(mask, 1000baseT_Half); - } - out: -- bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - - static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, -diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c -index d522bd5c90b4..1c318a932460 100644 ---- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c -+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c -@@ -940,7 +940,7 @@ static void enetc_pl_mac_validate(struct phylink_config *config, - state->interface != PHY_INTERFACE_MODE_2500BASEX && - state->interface != PHY_INTERFACE_MODE_USXGMII && - !phy_interface_mode_is_rgmii(state->interface)) { -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - return; - } - -@@ -963,10 +963,8 @@ static void enetc_pl_mac_validate(struct phylink_config *config, - phylink_set(mask, 2500baseX_Full); - } - -- bitmap_and(supported, supported, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - - static void enetc_pl_mac_config(struct phylink_config *config, -diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c -index b431c300ef1b..a85667078b72 100644 ---- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c -+++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c -@@ -322,12 +322,10 @@ static int hinic_get_link_ksettings(struct net_device *netdev, - } - } - -- bitmap_copy(link_ksettings->link_modes.supported, -- (unsigned long *)&settings.supported, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_copy(link_ksettings->link_modes.advertising, -- (unsigned long *)&settings.advertising, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_copy(link_ksettings->link_modes.supported, -+ (unsigned long *)&settings.supported); -+ linkmode_copy(link_ksettings->link_modes.advertising, -+ (unsigned long *)&settings.advertising); - - return 0; - } -diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c -index beda8e0ef7d4..8362822316a9 100644 ---- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c -+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c -@@ -467,9 +467,8 @@ static int ixgbe_set_link_ksettings(struct net_device *netdev, - * this function does not support duplex forcing, but can - * limit the advertising of the adapter to the specified speed - */ -- if (!bitmap_subset(cmd->link_modes.advertising, -- cmd->link_modes.supported, -- __ETHTOOL_LINK_MODE_MASK_NBITS)) -+ if (!linkmode_subset(cmd->link_modes.advertising, -+ cmd->link_modes.supported)) - return -EINVAL; - - /* only allow one speed at a time if no autoneg */ -diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c -index 9d460a270601..58147aab1785 100644 ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -3835,14 +3835,14 @@ static void mvneta_validate(struct phylink_config *config, - */ - if (phy_interface_mode_is_8023z(state->interface)) { - if (!phylink_test(state->advertising, Autoneg)) { -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - return; - } - } else if (state->interface != PHY_INTERFACE_MODE_NA && - state->interface != PHY_INTERFACE_MODE_QSGMII && - state->interface != PHY_INTERFACE_MODE_SGMII && - !phy_interface_mode_is_rgmii(state->interface)) { -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - return; - } - -@@ -3871,10 +3871,8 @@ static void mvneta_validate(struct phylink_config *config, - phylink_set(mask, 100baseT_Full); - } - -- bitmap_and(supported, supported, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - - /* We can only operate at 2500BaseX or 1000BaseX. If requested - * to advertise both, only report advertising at 2500BaseX. -diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -index 34b997aa6c66..f30c620ff832 100644 ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -6338,15 +6338,14 @@ static void mvpp2_phylink_validate(struct phylink_config *config, - goto empty_set; - } - -- bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - - phylink_helper_basex_speed(state); - return; - - empty_set: -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - } - - static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode, -diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c -index dbfa3bc39e34..4c882ceaeb1f 100644 ---- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c -+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c -@@ -1168,9 +1168,8 @@ static int otx2_set_link_ksettings(struct net_device *netdev, - otx2_get_link_ksettings(netdev, &cur_ks); - - /* Check requested modes against supported modes by hardware */ -- if (!bitmap_subset(cmd->link_modes.advertising, -- cur_ks.link_modes.supported, -- __ETHTOOL_LINK_MODE_MASK_NBITS)) -+ if (!linkmode_subset(cmd->link_modes.advertising, -+ cur_ks.link_modes.supported)) - return -EINVAL; - - mutex_lock(&mbox->lock); -diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c -index fab53c9b8380..572061164f1f 100644 ---- a/drivers/net/ethernet/marvell/pxa168_eth.c -+++ b/drivers/net/ethernet/marvell/pxa168_eth.c -@@ -977,8 +977,7 @@ static int pxa168_init_phy(struct net_device *dev) - cmd.base.phy_address = pep->phy_addr; - cmd.base.speed = pep->phy_speed; - cmd.base.duplex = pep->phy_duplex; -- bitmap_copy(cmd.link_modes.advertising, PHY_BASIC_FEATURES, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_copy(cmd.link_modes.advertising, PHY_BASIC_FEATURES); - cmd.base.autoneg = AUTONEG_ENABLE; - - if (cmd.base.speed != 0) -diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c -index ef518b1040f7..e29d524141b0 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c -+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c -@@ -39,6 +39,7 @@ - #include - #include - #include -+#include - - #include "mlx4_en.h" - #include "en_port.h" -@@ -643,10 +644,8 @@ static unsigned long *ptys2ethtool_link_mode(struct ptys2ethtool_config *cfg, - unsigned int i; \ - cfg = &ptys2ethtool_map[reg_]; \ - cfg->speed = speed_; \ -- bitmap_zero(cfg->supported, \ -- __ETHTOOL_LINK_MODE_MASK_NBITS); \ -- bitmap_zero(cfg->advertised, \ -- __ETHTOOL_LINK_MODE_MASK_NBITS); \ -+ linkmode_zero(cfg->supported); \ -+ linkmode_zero(cfg->advertised); \ - for (i = 0 ; i < ARRAY_SIZE(modes) ; ++i) { \ - __set_bit(modes[i], cfg->supported); \ - __set_bit(modes[i], cfg->advertised); \ -@@ -702,10 +701,8 @@ static void ptys2ethtool_update_link_modes(unsigned long *link_modes, - int i; - for (i = 0; i < MLX4_LINK_MODES_SZ; i++) { - if (eth_proto & MLX4_PROT_MASK(i)) -- bitmap_or(link_modes, link_modes, -- ptys2ethtool_link_mode(&ptys2ethtool_map[i], -- report), -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_or(link_modes, link_modes, -+ ptys2ethtool_link_mode(&ptys2ethtool_map[i], report)); - } - } - -@@ -716,11 +713,9 @@ static u32 ethtool2ptys_link_modes(const unsigned long *link_modes, - u32 ptys_modes = 0; - - for (i = 0; i < MLX4_LINK_MODES_SZ; i++) { -- if (bitmap_intersects( -- ptys2ethtool_link_mode(&ptys2ethtool_map[i], -- report), -- link_modes, -- __ETHTOOL_LINK_MODE_MASK_NBITS)) -+ ulong *map_mode = ptys2ethtool_link_mode(&ptys2ethtool_map[i], -+ report); -+ if (linkmode_intersects(map_mode, link_modes)) - ptys_modes |= 1 << i; - } - return ptys_modes; -diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c -index af70e2795125..fb74752de0ca 100644 ---- a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c -+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c -@@ -92,12 +92,11 @@ static void sparx5_phylink_validate(struct phylink_config *config, - } - break; - default: -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - return; - } -- bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - - static void sparx5_phylink_mac_config(struct phylink_config *config, -diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c -index 2545727fd5b2..f2090f671034 100644 ---- a/drivers/net/ethernet/mscc/ocelot_net.c -+++ b/drivers/net/ethernet/mscc/ocelot_net.c -@@ -1509,7 +1509,7 @@ static void vsc7514_phylink_validate(struct phylink_config *config, - - if (state->interface != PHY_INTERFACE_MODE_NA && - state->interface != ocelot_port->phy_mode) { -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - return; - } - -@@ -1528,9 +1528,8 @@ static void vsc7514_phylink_validate(struct phylink_config *config, - phylink_set(mask, 2500baseT_Full); - phylink_set(mask, 2500baseX_Full); - -- bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - - static void vsc7514_phylink_mac_config(struct phylink_config *config, -diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c -index 3de1a03839e2..620fc13b5781 100644 ---- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c -+++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c -@@ -228,8 +228,7 @@ static int ionic_get_link_ksettings(struct net_device *netdev, - break; - } - -- bitmap_copy(ks->link_modes.advertising, ks->link_modes.supported, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_copy(ks->link_modes.advertising, ks->link_modes.supported); - - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); - ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); -diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -index 871b5ec3183d..360948bcab0e 100644 ---- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -@@ -1525,7 +1525,7 @@ static void axienet_validate(struct phylink_config *config, - netdev_warn(ndev, "Cannot use PHY mode %s, supported: %s\n", - phy_modes(state->interface), - phy_modes(lp->phy_mode)); -- bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(supported); - return; - } - } -@@ -1558,10 +1558,8 @@ static void axienet_validate(struct phylink_config *config, - break; - } - -- bitmap_and(supported, supported, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -- bitmap_and(state->advertising, state->advertising, mask, -- __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_and(supported, supported, mask); -+ linkmode_and(state->advertising, state->advertising, mask); - } - - static void axienet_mac_pcs_get_state(struct phylink_config *config, -diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c -index 7de631f5356f..cd6742e6ba8b 100644 ---- a/drivers/net/pcs/pcs-xpcs.c -+++ b/drivers/net/pcs/pcs-xpcs.c -@@ -646,7 +646,7 @@ void xpcs_validate(struct dw_xpcs *xpcs, unsigned long *supported, - if (state->interface == PHY_INTERFACE_MODE_NA) - return; - -- bitmap_zero(xpcs_supported, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(xpcs_supported); - - compat = xpcs_find_compat(xpcs->id, state->interface); - -diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c -index 7362f8c3271c..0c6c0d1843bc 100644 ---- a/drivers/net/phy/sfp-bus.c -+++ b/drivers/net/phy/sfp-bus.c -@@ -373,7 +373,7 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, - if (bus->sfp_quirk) - bus->sfp_quirk->modes(id, modes); - -- bitmap_or(support, support, modes, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_or(support, support, modes); - - phylink_set(support, Autoneg); - phylink_set(support, Pause); -diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c -index f2abc3152888..8f389920f429 100644 ---- a/net/ethtool/ioctl.c -+++ b/net/ethtool/ioctl.c -@@ -335,7 +335,7 @@ EXPORT_SYMBOL(ethtool_intersect_link_masks); - void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, - u32 legacy_u32) - { -- bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(dst); - dst[0] = legacy_u32; - } - EXPORT_SYMBOL(ethtool_convert_legacy_u32_to_link_mode); -@@ -350,11 +350,10 @@ bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, - if (__ETHTOOL_LINK_MODE_MASK_NBITS > 32) { - __ETHTOOL_DECLARE_LINK_MODE_MASK(ext); - -- bitmap_zero(ext, __ETHTOOL_LINK_MODE_MASK_NBITS); -+ linkmode_zero(ext); - bitmap_fill(ext, 32); - bitmap_complement(ext, ext, __ETHTOOL_LINK_MODE_MASK_NBITS); -- if (bitmap_intersects(ext, src, -- __ETHTOOL_LINK_MODE_MASK_NBITS)) { -+ if (linkmode_intersects(ext, src)) { - /* src mask goes beyond bit 31 */ - retval = false; - } --- -cgit v1.2.3 - - -From 202f1e8368daf1f81d45c7993bdf22c27c103910 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Tue, 3 Mar 2020 12:15:38 +0000 -Subject: net: mvneta: populate supported_interfaces member - -Populate the phy_interface_t bitmap for the Marvell mvneta driver with -interfaces modes supported by the MAC. - -Signed-off-by: Russell King ---- - drivers/net/ethernet/marvell/mvneta.c | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - -diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c -index 58147aab1785..76395047f635 100644 ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -5180,6 +5180,31 @@ static int mvneta_probe(struct platform_device *pdev) - - pp->phylink_config.dev = &dev->dev; - pp->phylink_config.type = PHYLINK_NETDEV; -+ phy_interface_set_rgmii(pp->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_QSGMII, -+ pp->phylink_config.supported_interfaces); -+ if (comphy) { -+ /* If a COMPHY is present, we can support any of the serdes -+ * modes and switch between them. -+ */ -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ pp->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, -+ pp->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, -+ pp->phylink_config.supported_interfaces); -+ } else if (phy_mode == PHY_INTERFACE_MODE_2500BASEX) { -+ /* No COMPHY, with only 2500BASE-X mode supported */ -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, -+ pp->phylink_config.supported_interfaces); -+ } else if (phy_mode == PHY_INTERFACE_MODE_1000BASEX || -+ phy_mode == PHY_INTERFACE_MODE_SGMII) { -+ /* No COMPHY, we can switch between 1000BASE-X and SGMII */ -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, -+ pp->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ pp->phylink_config.supported_interfaces); -+ } - - phylink = phylink_create(&pp->phylink_config, pdev->dev.fwnode, - phy_mode, &mvneta_phylink_ops); --- -cgit v1.2.3 - - -From 408f682eb642aaca2600455cfc379d2d6f574fd5 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:14:44 +0100 -Subject: net: mvneta: remove interface checks in mvneta_validate() - -As phylink checks the interface mode against the supported_interfaces -bitmap, we no longer need to validate the interface mode in the -validation function. Remove this to simplify it. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/marvell/mvneta.c | 11 ++--------- - 1 file changed, 2 insertions(+), 9 deletions(-) - -diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c -index 76395047f635..59aff5cb5999 100644 ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -3833,15 +3833,8 @@ static void mvneta_validate(struct phylink_config *config, - * "Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ... - * When = 1 (1000BASE-X) this field must be set to 1." - */ -- if (phy_interface_mode_is_8023z(state->interface)) { -- if (!phylink_test(state->advertising, Autoneg)) { -- linkmode_zero(supported); -- return; -- } -- } else if (state->interface != PHY_INTERFACE_MODE_NA && -- state->interface != PHY_INTERFACE_MODE_QSGMII && -- state->interface != PHY_INTERFACE_MODE_SGMII && -- !phy_interface_mode_is_rgmii(state->interface)) { -+ if (phy_interface_mode_is_8023z(state->interface) && -+ !phylink_test(state->advertising, Autoneg)) { - linkmode_zero(supported); - return; - } --- -cgit v1.2.3 - - -From 80a4bd15d32895df00e31b6e825d01b1ba065876 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 15 Oct 2021 11:48:19 +0100 -Subject: net: mvneta: drop use of phylink_helper_basex_speed() - -Now that we have a better method to select SFP interface modes, we -no longer need to use phylink_helper_basex_speed() in a driver's -validation function, and we can also get rid of our hack to indicate -both 1000base-X and 2500base-X if the comphy is present to make that -work. Remove this hack and use of phylink_helper_basex_speed(). - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/marvell/mvneta.c | 12 +++--------- - 1 file changed, 3 insertions(+), 9 deletions(-) - -diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c -index 59aff5cb5999..c92081d0b257 100644 ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -3824,8 +3824,6 @@ static void mvneta_validate(struct phylink_config *config, - unsigned long *supported, - struct phylink_link_state *state) - { -- struct net_device *ndev = to_net_dev(config->dev); -- struct mvneta_port *pp = netdev_priv(ndev); - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - - /* We only support QSGMII, SGMII, 802.3z and RGMII modes. -@@ -3847,11 +3845,12 @@ static void mvneta_validate(struct phylink_config *config, - phylink_set(mask, Pause); - - /* Half-duplex at speeds higher than 100Mbit is unsupported */ -- if (pp->comphy || state->interface != PHY_INTERFACE_MODE_2500BASEX) { -+ if (state->interface != PHY_INTERFACE_MODE_2500BASEX) { - phylink_set(mask, 1000baseT_Full); - phylink_set(mask, 1000baseX_Full); - } -- if (pp->comphy || state->interface == PHY_INTERFACE_MODE_2500BASEX) { -+ -+ if (state->interface == PHY_INTERFACE_MODE_2500BASEX) { - phylink_set(mask, 2500baseT_Full); - phylink_set(mask, 2500baseX_Full); - } -@@ -3866,11 +3865,6 @@ static void mvneta_validate(struct phylink_config *config, - - linkmode_and(supported, supported, mask); - linkmode_and(state->advertising, state->advertising, mask); -- -- /* We can only operate at 2500BaseX or 1000BaseX. If requested -- * to advertise both, only report advertising at 2500BaseX. -- */ -- phylink_helper_basex_speed(state); - } - - static void mvneta_mac_pcs_get_state(struct phylink_config *config, --- -cgit v1.2.3 - - -From 2aacd3ffab6846c731ddefa3fd1cd17d21a83942 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Tue, 3 Mar 2020 12:15:38 +0000 -Subject: net: mvpp2: populate supported_interfaces member - -Populate the phy interface mode bitmap for the Marvell mvpp2 driver -with interfaces modes supported by the MAC. - -Signed-off-by: Russell King ---- - drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 34 +++++++++++++++++++++++++ - 1 file changed, 34 insertions(+) - -diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -index f30c620ff832..da5726e389ea 100644 ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -6937,6 +6937,40 @@ static int mvpp2_port_probe(struct platform_device *pdev, - port->phylink_config.dev = &dev->dev; - port->phylink_config.type = PHYLINK_NETDEV; - -+ if (mvpp2_port_supports_xlg(port)) { -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_XAUI, -+ port->phylink_config.supported_interfaces); -+ } -+ -+ if (mvpp2_port_supports_rgmii(port)) -+ phy_interface_set_rgmii(port->phylink_config.supported_interfaces); -+ -+ if (comphy) { -+ /* If a COMPHY is present, we can support any of the -+ * serdes modes and switch between them. -+ */ -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, -+ port->phylink_config.supported_interfaces); -+ } else if (phy_mode == PHY_INTERFACE_MODE_2500BASEX) { -+ /* No COMPHY, with only 2500BASE-X mode supported */ -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, -+ port->phylink_config.supported_interfaces); -+ } else if (phy_mode == PHY_INTERFACE_MODE_1000BASEX || -+ phy_mode == PHY_INTERFACE_MODE_SGMII) { -+ /* No COMPHY, we can switch between 1000BASE-X and SGMII -+ */ -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ port->phylink_config.supported_interfaces); -+ } -+ - phylink = phylink_create(&port->phylink_config, port_fwnode, - phy_mode, &mvpp2_phylink_ops); - if (IS_ERR(phylink)) { --- -cgit v1.2.3 - - -From 5722811f133f6acfd8fea2edc75f6d63cf98fc49 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:17:17 +0100 -Subject: net: mvpp2: remove interface checks in mvpp2_phylink_validate() - -As phylink checks the interface mode against the supported_interfaces -bitmap, we no longer need to validate the interface mode in the -validation function. Remove this to simplify it. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 33 ++++++------------------- - 1 file changed, 7 insertions(+), 26 deletions(-) - -diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -index da5726e389ea..51dbd50e76a9 100644 ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -6261,32 +6261,13 @@ static void mvpp2_phylink_validate(struct phylink_config *config, - struct mvpp2_port *port = mvpp2_phylink_to_port(config); - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - -- /* Invalid combinations */ -- switch (state->interface) { -- case PHY_INTERFACE_MODE_10GBASER: -- case PHY_INTERFACE_MODE_XAUI: -- if (!mvpp2_port_supports_xlg(port)) -- goto empty_set; -- break; -- case PHY_INTERFACE_MODE_RGMII: -- case PHY_INTERFACE_MODE_RGMII_ID: -- case PHY_INTERFACE_MODE_RGMII_RXID: -- case PHY_INTERFACE_MODE_RGMII_TXID: -- if (!mvpp2_port_supports_rgmii(port)) -- goto empty_set; -- break; -- case PHY_INTERFACE_MODE_1000BASEX: -- case PHY_INTERFACE_MODE_2500BASEX: -- /* When in 802.3z mode, we must have AN enabled: -- * Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ... -- * When = 1 (1000BASE-X) this field must be set to 1. -- */ -- if (!phylink_test(state->advertising, Autoneg)) -- goto empty_set; -- break; -- default: -- break; -- } -+ /* When in 802.3z mode, we must have AN enabled: -+ * Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ... -+ * When = 1 (1000BASE-X) this field must be set to 1. -+ */ -+ if (phy_interface_mode_is_8023z(state->interface) && -+ !phylink_test(state->advertising, Autoneg)) -+ goto empty_set; - - phylink_set(mask, Autoneg); - phylink_set_port_modes(mask); --- -cgit v1.2.3 - - -From b21dfb7be6fc03b6f2dedff5d188ffcecc4c44f1 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Mon, 18 Oct 2021 17:27:34 +0100 -Subject: net: mvpp2: drop use of phylink_helper_basex_speed() - -Now that we have a better method to select SFP interface modes, we -no longer need to use phylink_helper_basex_speed() in a driver's -validation function, and we can also get rid of our hack to indicate -both 1000base-X and 2500base-X if the comphy is present to make that -work. Remove this hack and use of phylink_helper_basex_speed(). - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 19 +++++++------------ - 1 file changed, 7 insertions(+), 12 deletions(-) - -diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -index 51dbd50e76a9..150bbe1e8245 100644 ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -6303,17 +6303,14 @@ static void mvpp2_phylink_validate(struct phylink_config *config, - break; - fallthrough; - case PHY_INTERFACE_MODE_1000BASEX: -+ phylink_set(mask, 1000baseT_Full); -+ phylink_set(mask, 1000baseX_Full); -+ if (state->interface != PHY_INTERFACE_MODE_NA) -+ break; -+ fallthrough; - case PHY_INTERFACE_MODE_2500BASEX: -- if (port->comphy || -- state->interface != PHY_INTERFACE_MODE_2500BASEX) { -- phylink_set(mask, 1000baseT_Full); -- phylink_set(mask, 1000baseX_Full); -- } -- if (port->comphy || -- state->interface == PHY_INTERFACE_MODE_2500BASEX) { -- phylink_set(mask, 2500baseT_Full); -- phylink_set(mask, 2500baseX_Full); -- } -+ phylink_set(mask, 2500baseT_Full); -+ phylink_set(mask, 2500baseX_Full); - break; - default: - goto empty_set; -@@ -6321,8 +6318,6 @@ static void mvpp2_phylink_validate(struct phylink_config *config, - - linkmode_and(supported, supported, mask); - linkmode_and(state->advertising, state->advertising, mask); -- -- phylink_helper_basex_speed(state); - return; - - empty_set: --- -cgit v1.2.3 - - -From e4fede0c4e9c996e2a95542bcad1a41d5ed3cef1 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 14:18:15 +0100 -Subject: net: mvpp2: clean up mvpp2_phylink_validate() - -macb_validate() no longer needs to check for PHY_INTERFACE_MODE_NA as -phylink will walk the supported interface types to discover the link -mode capabilities. Remove these checks. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 17 +++++++---------- - 1 file changed, 7 insertions(+), 10 deletions(-) - -diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -index 150bbe1e8245..a774010f9478 100644 ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -6280,14 +6280,12 @@ static void mvpp2_phylink_validate(struct phylink_config *config, - switch (state->interface) { - case PHY_INTERFACE_MODE_10GBASER: - case PHY_INTERFACE_MODE_XAUI: -- case PHY_INTERFACE_MODE_NA: - if (mvpp2_port_supports_xlg(port)) { - phylink_set_10g_modes(mask); - phylink_set(mask, 10000baseKR_Full); - } -- if (state->interface != PHY_INTERFACE_MODE_NA) -- break; -- fallthrough; -+ break; -+ - case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_RXID: -@@ -6299,19 +6297,18 @@ static void mvpp2_phylink_validate(struct phylink_config *config, - phylink_set(mask, 100baseT_Full); - phylink_set(mask, 1000baseT_Full); - phylink_set(mask, 1000baseX_Full); -- if (state->interface != PHY_INTERFACE_MODE_NA) -- break; -- fallthrough; -+ break; -+ - case PHY_INTERFACE_MODE_1000BASEX: - phylink_set(mask, 1000baseT_Full); - phylink_set(mask, 1000baseX_Full); -- if (state->interface != PHY_INTERFACE_MODE_NA) -- break; -- fallthrough; -+ break; -+ - case PHY_INTERFACE_MODE_2500BASEX: - phylink_set(mask, 2500baseT_Full); - phylink_set(mask, 2500baseX_Full); - break; -+ - default: - goto empty_set; - } --- -cgit v1.2.3 - - -From 99fface7a516dc349c95682cb966e0e0c5a92969 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marek=20Beh=C3=BAn?= -Date: Tue, 20 Oct 2020 19:09:11 +0200 -Subject: net: dsa: populate supported_interfaces member -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add a new DSA switch operation, phylink_get_interfaces, which should -fill in which PHY_INTERFACE_MODE_* are supported by given port. - -Use this before phylink_create() to fill phylinks supported_interfaces -member, allowing phylink to determine which PHY_INTERFACE_MODE to use -with SFP modules. - -Signed-off-by: Marek BehĂșn -Signed-off-by: Russell King ---- - include/net/dsa.h | 2 ++ - net/dsa/port.c | 4 ++++ - net/dsa/slave.c | 4 ++++ - 3 files changed, 10 insertions(+) - -diff --git a/include/net/dsa.h b/include/net/dsa.h -index d784e76113b8..e83f2692b638 100644 ---- a/include/net/dsa.h -+++ b/include/net/dsa.h -@@ -615,6 +615,8 @@ struct dsa_switch_ops { - /* - * PHYLINK integration - */ -+ void (*phylink_get_interfaces)(struct dsa_switch *ds, int port, -+ unsigned long *supported_interfaces); - void (*phylink_validate)(struct dsa_switch *ds, int port, - unsigned long *supported, - struct phylink_link_state *state); -diff --git a/net/dsa/port.c b/net/dsa/port.c -index 616330a16d31..2d1c6afc2659 100644 ---- a/net/dsa/port.c -+++ b/net/dsa/port.c -@@ -1169,6 +1169,10 @@ static int dsa_port_phylink_register(struct dsa_port *dp) - dp->pl_config.type = PHYLINK_DEV; - dp->pl_config.pcs_poll = ds->pcs_poll; - -+ if (ds->ops->phylink_get_interfaces) -+ ds->ops->phylink_get_interfaces(ds, dp->index, -+ dp->pl_config.supported_interfaces); -+ - dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), - mode, &dsa_port_phylink_mac_ops); - if (IS_ERR(dp->pl)) { -diff --git a/net/dsa/slave.c b/net/dsa/slave.c -index a2bf2d8ac65b..be5a079fc74d 100644 ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -1837,6 +1837,10 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev) - dp->pl_config.poll_fixed_state = true; - } - -+ if (ds->ops->phylink_get_interfaces) -+ ds->ops->phylink_get_interfaces(ds, dp->index, -+ dp->pl_config.supported_interfaces); -+ - dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), mode, - &dsa_port_phylink_mac_ops); - if (IS_ERR(dp->pl)) { --- -cgit v1.2.3 - - -From 0f83852dc55fb86c6620a86357899b7eccc5f6f3 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Tue, 3 Mar 2020 12:15:38 +0000 -Subject: net: ag71xx: populate supported_interfaces member - -Populate the phy_interface_t bitmap for the Atheros ag71xx driver with -interfaces modes supported by the MAC. - -Signed-off-by: Russell King ---- - drivers/net/ethernet/atheros/ag71xx.c | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - -diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c -index 121536de80bb..15ffedb3ce8f 100644 ---- a/drivers/net/ethernet/atheros/ag71xx.c -+++ b/drivers/net/ethernet/atheros/ag71xx.c -@@ -1178,6 +1178,32 @@ static int ag71xx_phylink_setup(struct ag71xx *ag) - ag->phylink_config.dev = &ag->ndev->dev; - ag->phylink_config.type = PHYLINK_NETDEV; - -+ if ((ag71xx_is(ag, AR9330) && ag->mac_idx == 0) || -+ ag71xx_is(ag, AR9340) || -+ ag71xx_is(ag, QCA9530) || -+ (ag71xx_is(ag, QCA9550) && ag->mac_idx == 1)) -+ __set_bit(PHY_INTERFACE_MODE_MII, -+ ag->phylink_config.supported_interfaces); -+ -+ if ((ag71xx_is(ag, AR9330) && ag->mac_idx == 1) || -+ (ag71xx_is(ag, AR9340) && ag->mac_idx == 1) || -+ (ag71xx_is(ag, QCA9530) && ag->mac_idx == 1)) -+ __set_bit(PHY_INTERFACE_MODE_GMII, -+ ag->phylink_config.supported_interfaces); -+ -+ if (ag71xx_is(ag, QCA9550) && ag->mac_idx == 0) -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ ag->phylink_config.supported_interfaces); -+ -+ if (ag71xx_is(ag, AR9340) && ag->mac_idx == 0) -+ __set_bit(PHY_INTERFACE_MODE_RMII, -+ ag->phylink_config.supported_interfaces); -+ -+ if ((ag71xx_is(ag, AR9340) && ag->mac_idx == 0) || -+ (ag71xx_is(ag, QCA9550) && ag->mac_idx == 1)) -+ __set_bit(PHY_INTERFACE_MODE_RGMII, -+ ag->phylink_config.supported_interfaces); -+ - phylink = phylink_create(&ag->phylink_config, ag->pdev->dev.fwnode, - ag->phy_if_mode, &ag71xx_phylink_mac_ops); - if (IS_ERR(phylink)) --- -cgit v1.2.3 - - -From 2b7df80c463930365bc90092b3e4c6199cbaaaff Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:14:44 +0100 -Subject: net: ag71xx: remove interface checks in ag71xx_mac_validate() - -As phylink checks the interface mode against the supported_interfaces -bitmap, we no longer need to validate the interface mode, nor handle -PHY_INTERFACE_MODE_NA in the validation function. Remove these to -simplify the implementation. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/atheros/ag71xx.c | 41 +---------------------------------- - 1 file changed, 1 insertion(+), 40 deletions(-) - -diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c -index 15ffedb3ce8f..30ac8cd53e37 100644 ---- a/drivers/net/ethernet/atheros/ag71xx.c -+++ b/drivers/net/ethernet/atheros/ag71xx.c -@@ -1028,42 +1028,8 @@ static void ag71xx_mac_validate(struct phylink_config *config, - unsigned long *supported, - struct phylink_link_state *state) - { -- struct ag71xx *ag = netdev_priv(to_net_dev(config->dev)); - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - -- switch (state->interface) { -- case PHY_INTERFACE_MODE_NA: -- break; -- case PHY_INTERFACE_MODE_MII: -- if ((ag71xx_is(ag, AR9330) && ag->mac_idx == 0) || -- ag71xx_is(ag, AR9340) || -- ag71xx_is(ag, QCA9530) || -- (ag71xx_is(ag, QCA9550) && ag->mac_idx == 1)) -- break; -- goto unsupported; -- case PHY_INTERFACE_MODE_GMII: -- if ((ag71xx_is(ag, AR9330) && ag->mac_idx == 1) || -- (ag71xx_is(ag, AR9340) && ag->mac_idx == 1) || -- (ag71xx_is(ag, QCA9530) && ag->mac_idx == 1)) -- break; -- goto unsupported; -- case PHY_INTERFACE_MODE_SGMII: -- if (ag71xx_is(ag, QCA9550) && ag->mac_idx == 0) -- break; -- goto unsupported; -- case PHY_INTERFACE_MODE_RMII: -- if (ag71xx_is(ag, AR9340) && ag->mac_idx == 0) -- break; -- goto unsupported; -- case PHY_INTERFACE_MODE_RGMII: -- if ((ag71xx_is(ag, AR9340) && ag->mac_idx == 0) || -- (ag71xx_is(ag, QCA9550) && ag->mac_idx == 1)) -- break; -- goto unsupported; -- default: -- goto unsupported; -- } -- - phylink_set(mask, MII); - - phylink_set(mask, Pause); -@@ -1074,8 +1040,7 @@ static void ag71xx_mac_validate(struct phylink_config *config, - phylink_set(mask, 100baseT_Half); - phylink_set(mask, 100baseT_Full); - -- if (state->interface == PHY_INTERFACE_MODE_NA || -- state->interface == PHY_INTERFACE_MODE_SGMII || -+ if (state->interface == PHY_INTERFACE_MODE_SGMII || - state->interface == PHY_INTERFACE_MODE_RGMII || - state->interface == PHY_INTERFACE_MODE_GMII) { - phylink_set(mask, 1000baseT_Full); -@@ -1084,10 +1049,6 @@ static void ag71xx_mac_validate(struct phylink_config *config, - - linkmode_and(supported, supported, mask); - linkmode_and(state->advertising, state->advertising, mask); -- -- return; --unsupported: -- linkmode_zero(supported); - } - - static void ag71xx_mac_pcs_get_state(struct phylink_config *config, --- -cgit v1.2.3 - - -From afc88ac86769592e9d309f6302ecbe9a9b77f286 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:45:19 +0100 -Subject: net: axienet: populate supported_interfaces member - -Populate the phy_interface_t bitmap for the Xilinx axienet driver with -interfaces modes supported by the MAC. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -index 360948bcab0e..e311ad438b88 100644 ---- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -@@ -2105,6 +2105,14 @@ static int axienet_probe(struct platform_device *pdev) - lp->phylink_config.dev = &ndev->dev; - lp->phylink_config.type = PHYLINK_NETDEV; - -+ __set_bit(lp->phy_mode, lp->phylink_config.supported_interfaces); -+ if (lp->switch_x_sgmii) { -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, -+ lp->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ lp->phylink_config.supported_interfaces); -+ } -+ - lp->phylink = phylink_create(&lp->phylink_config, pdev->dev.fwnode, - lp->phy_mode, - &axienet_phylink_ops); --- -cgit v1.2.3 - - -From 7f300573b99243f052702c9b6b0bc9ffe1c51127 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:46:31 +0100 -Subject: net: axienet: remove interface checks in axienet_validate() - -As phylink checks the interface mode against the supported_interfaces -bitmap, we no longer need to validate the interface mode in the -validation function. Remove this to simplify it. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 22 ---------------------- - 1 file changed, 22 deletions(-) - -diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -index e311ad438b88..0c02b1cebdd3 100644 ---- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -@@ -1507,29 +1507,8 @@ static void axienet_validate(struct phylink_config *config, - unsigned long *supported, - struct phylink_link_state *state) - { -- struct net_device *ndev = to_net_dev(config->dev); -- struct axienet_local *lp = netdev_priv(ndev); - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - -- /* Only support the mode we are configured for */ -- switch (state->interface) { -- case PHY_INTERFACE_MODE_NA: -- break; -- case PHY_INTERFACE_MODE_1000BASEX: -- case PHY_INTERFACE_MODE_SGMII: -- if (lp->switch_x_sgmii) -- break; -- fallthrough; -- default: -- if (state->interface != lp->phy_mode) { -- netdev_warn(ndev, "Cannot use PHY mode %s, supported: %s\n", -- phy_modes(state->interface), -- phy_modes(lp->phy_mode)); -- linkmode_zero(supported); -- return; -- } -- } -- - phylink_set(mask, Autoneg); - phylink_set_port_modes(mask); - -@@ -1537,7 +1516,6 @@ static void axienet_validate(struct phylink_config *config, - phylink_set(mask, Pause); - - switch (state->interface) { -- case PHY_INTERFACE_MODE_NA: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_GMII: --- -cgit v1.2.3 - - -From e29ca7f1ad9939fe58ee699886c8f767a829991f Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:49:57 +0100 -Subject: net: enetc: populate supported_interfaces member - -Populate the phy_interface_t bitmap for the Freescale enetc driver with -interfaces modes supported by the MAC. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/freescale/enetc/enetc_pf.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c -index 1c318a932460..649bc0f15392 100644 ---- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c -+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c -@@ -1110,6 +1110,16 @@ static int enetc_phylink_create(struct enetc_ndev_priv *priv, - pf->phylink_config.dev = &priv->ndev->dev; - pf->phylink_config.type = PHYLINK_NETDEV; - -+ __set_bit(PHY_INTERFACE_MODE_INTERNAL, -+ pf->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ pf->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, -+ pf->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_USXGMII, -+ pf->phylink_config.supported_interfaces); -+ phy_interface_set_rgmii(pf->phylink_config.supported_interfaces); -+ - phylink = phylink_create(&pf->phylink_config, of_fwnode_handle(node), - pf->if_mode, &enetc_mac_phylink_ops); - if (IS_ERR(phylink)) { --- -cgit v1.2.3 - - -From 86dd3aedc8e84b53e396166057536b398fe105fe Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:50:51 +0100 -Subject: net: enetc: remove interface checks in enetc_pl_mac_validate() - -As phylink checks the interface mode against the supported_interfaces -bitmap, we no longer need to validate the interface mode in the -validation function. Remove this to simplify it. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/freescale/enetc/enetc_pf.c | 10 ---------- - 1 file changed, 10 deletions(-) - -diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c -index 649bc0f15392..b2ff5e5ac892 100644 ---- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c -+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c -@@ -934,16 +934,6 @@ static void enetc_pl_mac_validate(struct phylink_config *config, - { - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - -- if (state->interface != PHY_INTERFACE_MODE_NA && -- state->interface != PHY_INTERFACE_MODE_INTERNAL && -- state->interface != PHY_INTERFACE_MODE_SGMII && -- state->interface != PHY_INTERFACE_MODE_2500BASEX && -- state->interface != PHY_INTERFACE_MODE_USXGMII && -- !phy_interface_mode_is_rgmii(state->interface)) { -- linkmode_zero(supported); -- return; -- } -- - phylink_set_port_modes(mask); - phylink_set(mask, Autoneg); - phylink_set(mask, Pause); --- -cgit v1.2.3 - - -From b14f5f6432206421dd64ee0f0baa0756409c833b Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:56:12 +0100 -Subject: net: sparx5: populate supported_interfaces member - -Populate the phy_interface_t bitmap for the Microchip Sparx5 driver -with interfaces modes supported by the MAC. - -Signed-off-by: Russell King (Oracle) ---- - .../net/ethernet/microchip/sparx5/sparx5_main.c | 24 ++++++++++++++++++++++ - 1 file changed, 24 insertions(+) - -diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c -index 5030dfca3879..d681201ddd43 100644 ---- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c -+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c -@@ -294,6 +294,30 @@ static int sparx5_create_port(struct sparx5 *sparx5, - spx5_port->phylink_config.type = PHYLINK_NETDEV; - spx5_port->phylink_config.pcs_poll = true; - -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ spx5_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_QSGMII, -+ spx5_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, -+ spx5_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, -+ spx5_port->phylink_config.supported_interfaces); -+ -+ if (spx5_port->conf.bandwidth == SPEED_5000 || -+ spx5_port->conf.bandwidth == SPEED_10000 || -+ spx5_port->conf.bandwidth == SPEED_25000) -+ __set_bit(PHY_INTERFACE_MODE_5GBASER, -+ spx5_port->phylink_config.supported_interfaces); -+ -+ if (spx5_port->conf.bandwidth == SPEED_10000 || -+ spx5_port->conf.bandwidth == SPEED_25000) -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, -+ spx5_port->phylink_config.supported_interfaces); -+ -+ if (spx5_port->conf.bandwidth == SPEED_25000) -+ __set_bit(PHY_INTERFACE_MODE_25GBASER, -+ spx5_port->phylink_config.supported_interfaces); -+ - phylink = phylink_create(&spx5_port->phylink_config, - of_fwnode_handle(config->node), - config->conf.phy_mode, --- -cgit v1.2.3 - - -From 6176803a287f798e6d98b28492bbfc782a882b92 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 14:18:15 +0100 -Subject: net: sparx5: clean up sparx5_phylink_validate() - -sparx5_phylink_validate() no longer needs to check for -PHY_INTERFACE_MODE_NA as phylink will walk the supported interface -types to discover the link mode capabilities. Neither is it necessary -to check the device capabilities as we will not be called for -unsupported interface modes. Remove these checks. - -Signed-off-by: Russell King (Oracle) ---- - .../net/ethernet/microchip/sparx5/sparx5_phylink.c | 63 +++++++++------------- - 1 file changed, 24 insertions(+), 39 deletions(-) - -diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c -index fb74752de0ca..e77ddded4811 100644 ---- a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c -+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c -@@ -30,7 +30,6 @@ static void sparx5_phylink_validate(struct phylink_config *config, - unsigned long *supported, - struct phylink_link_state *state) - { -- struct sparx5_port *port = netdev_priv(to_net_dev(config->dev)); - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - - phylink_set(mask, Autoneg); -@@ -40,34 +39,23 @@ static void sparx5_phylink_validate(struct phylink_config *config, - - switch (state->interface) { - case PHY_INTERFACE_MODE_5GBASER: -+ phylink_set(mask, 5000baseT_Full); -+ break; -+ - case PHY_INTERFACE_MODE_10GBASER: -+ phylink_set(mask, 10000baseT_Full); -+ phylink_set(mask, 10000baseCR_Full); -+ phylink_set(mask, 10000baseSR_Full); -+ phylink_set(mask, 10000baseLR_Full); -+ phylink_set(mask, 10000baseLRM_Full); -+ phylink_set(mask, 10000baseER_Full); -+ break; -+ - case PHY_INTERFACE_MODE_25GBASER: -- case PHY_INTERFACE_MODE_NA: -- if (port->conf.bandwidth == SPEED_5000) -- phylink_set(mask, 5000baseT_Full); -- if (port->conf.bandwidth == SPEED_10000) { -- phylink_set(mask, 5000baseT_Full); -- phylink_set(mask, 10000baseT_Full); -- phylink_set(mask, 10000baseCR_Full); -- phylink_set(mask, 10000baseSR_Full); -- phylink_set(mask, 10000baseLR_Full); -- phylink_set(mask, 10000baseLRM_Full); -- phylink_set(mask, 10000baseER_Full); -- } -- if (port->conf.bandwidth == SPEED_25000) { -- phylink_set(mask, 5000baseT_Full); -- phylink_set(mask, 10000baseT_Full); -- phylink_set(mask, 10000baseCR_Full); -- phylink_set(mask, 10000baseSR_Full); -- phylink_set(mask, 10000baseLR_Full); -- phylink_set(mask, 10000baseLRM_Full); -- phylink_set(mask, 10000baseER_Full); -- phylink_set(mask, 25000baseCR_Full); -- phylink_set(mask, 25000baseSR_Full); -- } -- if (state->interface != PHY_INTERFACE_MODE_NA) -- break; -- fallthrough; -+ phylink_set(mask, 25000baseCR_Full); -+ phylink_set(mask, 25000baseSR_Full); -+ break; -+ - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: - phylink_set(mask, 10baseT_Half); -@@ -76,21 +64,18 @@ static void sparx5_phylink_validate(struct phylink_config *config, - phylink_set(mask, 100baseT_Full); - phylink_set(mask, 1000baseT_Full); - phylink_set(mask, 1000baseX_Full); -- if (state->interface != PHY_INTERFACE_MODE_NA) -- break; -- fallthrough; -+ break; -+ - case PHY_INTERFACE_MODE_1000BASEX: -+ phylink_set(mask, 1000baseT_Full); -+ phylink_set(mask, 1000baseX_Full); -+ break; -+ - case PHY_INTERFACE_MODE_2500BASEX: -- if (state->interface != PHY_INTERFACE_MODE_2500BASEX) { -- phylink_set(mask, 1000baseT_Full); -- phylink_set(mask, 1000baseX_Full); -- } -- if (state->interface == PHY_INTERFACE_MODE_2500BASEX || -- state->interface == PHY_INTERFACE_MODE_NA) { -- phylink_set(mask, 2500baseT_Full); -- phylink_set(mask, 2500baseX_Full); -- } -+ phylink_set(mask, 2500baseT_Full); -+ phylink_set(mask, 2500baseX_Full); - break; -+ - default: - linkmode_zero(supported); - return; --- -cgit v1.2.3 - - -From 0445d9008ec42cbec16e06a6497768baeeee34f3 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Thu, 30 Jan 2020 22:42:38 +0000 -Subject: net: dpaa2-mac: populate supported_interfaces member - -Populate the phy interface mode bitmap for the Freescale DPAA2 driver -with interfaces modes supported by the MAC. - -Signed-off-by: Russell King ---- - drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 29 ++++++++++++++++++++++++ - 1 file changed, 29 insertions(+) - -diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -index 3faf45c22c19..9645556dc838 100644 ---- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -@@ -337,9 +337,38 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac) - return err; - } - -+ memset(&mac->phylink_config, 0, sizeof(mac->phylink_config)); - mac->phylink_config.dev = &net_dev->dev; - mac->phylink_config.type = PHYLINK_NETDEV; - -+ /* We support the current interface mode, and if we have a PCS -+ * similar interface modes that do not require the PLLs to be -+ * reconfigured. -+ */ -+ __set_bit(mac->if_mode, mac->phylink_config.supported_interfaces); -+ if (mac->pcs) { -+ switch (mac->if_mode) { -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_SGMII: -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, -+ mac->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ mac->phylink_config.supported_interfaces); -+ break; -+ -+ case PHY_INTERFACE_MODE_10GBASER: -+ case PHY_INTERFACE_MODE_USXGMII: -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, -+ mac->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_USXGMII, -+ mac->phylink_config.supported_interfaces); -+ break; -+ -+ default: -+ break; -+ } -+ } -+ - phylink = phylink_create(&mac->phylink_config, - dpmac_node, mac->if_mode, - &dpaa2_mac_phylink_ops); --- -cgit v1.2.3 - - -From 745875b0f9fb8281be138462768bd7da9b4791a5 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:25:27 +0100 -Subject: net: dpaa2-mac: remove interface checks in dpaa2_mac_validate() - -As phylink checks the interface mode against the supported_interfaces -bitmap, we no longer need to validate the interface mode in the -validation function. Remove this to simplify it. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 34 ------------------------ - 1 file changed, 34 deletions(-) - -diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -index 9645556dc838..6f7780e9b683 100644 ---- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -@@ -90,46 +90,12 @@ static int dpaa2_mac_get_if_mode(struct fwnode_handle *dpmac_node, - return err; - } - --static bool dpaa2_mac_phy_mode_mismatch(struct dpaa2_mac *mac, -- phy_interface_t interface) --{ -- switch (interface) { -- /* We can switch between SGMII and 1000BASE-X at runtime with -- * pcs-lynx -- */ -- case PHY_INTERFACE_MODE_SGMII: -- case PHY_INTERFACE_MODE_1000BASEX: -- if (mac->pcs && -- (mac->if_mode == PHY_INTERFACE_MODE_SGMII || -- mac->if_mode == PHY_INTERFACE_MODE_1000BASEX)) -- return false; -- return interface != mac->if_mode; -- -- case PHY_INTERFACE_MODE_10GBASER: -- case PHY_INTERFACE_MODE_USXGMII: -- case PHY_INTERFACE_MODE_QSGMII: -- case PHY_INTERFACE_MODE_RGMII: -- case PHY_INTERFACE_MODE_RGMII_ID: -- case PHY_INTERFACE_MODE_RGMII_RXID: -- case PHY_INTERFACE_MODE_RGMII_TXID: -- return (interface != mac->if_mode); -- default: -- return true; -- } --} -- - static void dpaa2_mac_validate(struct phylink_config *config, - unsigned long *supported, - struct phylink_link_state *state) - { -- struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config); - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - -- if (state->interface != PHY_INTERFACE_MODE_NA && -- dpaa2_mac_phy_mode_mismatch(mac, state->interface)) { -- goto empty_set; -- } -- - phylink_set_port_modes(mask); - phylink_set(mask, Autoneg); - phylink_set(mask, Pause); --- -cgit v1.2.3 - - -From 5a2a942fe845966d0b46cd47f8f0ff22d93c1801 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 14:18:15 +0100 -Subject: net: dpaa2-mac: clean up dpaa2_mac_validate() - -dpaa2_mac_validate() no longer needs to check for PHY_INTERFACE_MODE_NA -as phylink will walk the supported interface types to discover the link -mode capabilities. Remove these checks. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -index 6f7780e9b683..9cf3386ffdb2 100644 ---- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c -@@ -102,7 +102,6 @@ static void dpaa2_mac_validate(struct phylink_config *config, - phylink_set(mask, Asym_Pause); - - switch (state->interface) { -- case PHY_INTERFACE_MODE_NA: - case PHY_INTERFACE_MODE_10GBASER: - case PHY_INTERFACE_MODE_USXGMII: - phylink_set_10g_modes(mask); --- -cgit v1.2.3 - - -From 115ee0009594610478fd9765851db518cf11e884 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:12:26 +0100 -Subject: net: mtk_eth_soc: populate supported_interfaces member - -Populate the phy interface mode bitmap for the Mediatek driver with -interfaces modes supported by the MAC. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -index 398c23cec815..c3ec5cb925a7 100644 ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3009,6 +3009,26 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) - - mac->phylink_config.dev = ð->netdev[id]->dev; - mac->phylink_config.type = PHYLINK_NETDEV; -+ __set_bit(PHY_INTERFACE_MODE_MII, -+ mac->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_GMII, -+ mac->phylink_config.supported_interfaces); -+ -+ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) -+ phy_interface_set_rgmii(mac->phylink_config.supported_interfaces); -+ -+ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_TRGMII) && !mac->id) -+ __set_bit(PHY_INTERFACE_MODE_TRGMII, -+ mac->phylink_config.supported_interfaces); -+ -+ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) { -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ mac->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, -+ mac->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, -+ mac->phylink_config.supported_interfaces); -+ } - - phylink = phylink_create(&mac->phylink_config, - of_fwnode_handle(mac->of_node), --- -cgit v1.2.3 - - -From 388a4d94e6333293a0aaca6dab4bfe346ee385bf Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:20:09 +0100 -Subject: net: mtk_eth_soc: remove interface checks in mtk_validate() - -As phylink checks the interface mode against the supported_interfaces -bitmap, we no longer need to validate the interface mode, nor handle -PHY_INTERFACE_MODE_NA in the validation function. Remove these to -simplify the implementation. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 34 ----------------------------- - 1 file changed, 34 deletions(-) - -diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -index c3ec5cb925a7..2b728fd25930 100644 ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -467,24 +467,8 @@ static void mtk_validate(struct phylink_config *config, - unsigned long *supported, - struct phylink_link_state *state) - { -- struct mtk_mac *mac = container_of(config, struct mtk_mac, -- phylink_config); - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - -- if (state->interface != PHY_INTERFACE_MODE_NA && -- state->interface != PHY_INTERFACE_MODE_MII && -- state->interface != PHY_INTERFACE_MODE_GMII && -- !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII) && -- phy_interface_mode_is_rgmii(state->interface)) && -- !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_TRGMII) && -- !mac->id && state->interface == PHY_INTERFACE_MODE_TRGMII) && -- !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII) && -- (state->interface == PHY_INTERFACE_MODE_SGMII || -- phy_interface_mode_is_8023z(state->interface)))) { -- linkmode_zero(supported); -- return; -- } -- - phylink_set_port_modes(mask); - phylink_set(mask, Autoneg); - -@@ -511,7 +495,6 @@ static void mtk_validate(struct phylink_config *config, - case PHY_INTERFACE_MODE_MII: - case PHY_INTERFACE_MODE_RMII: - case PHY_INTERFACE_MODE_REVMII: -- case PHY_INTERFACE_MODE_NA: - default: - phylink_set(mask, 10baseT_Half); - phylink_set(mask, 10baseT_Full); -@@ -520,23 +503,6 @@ static void mtk_validate(struct phylink_config *config, - break; - } - -- if (state->interface == PHY_INTERFACE_MODE_NA) { -- if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) { -- phylink_set(mask, 1000baseT_Full); -- phylink_set(mask, 1000baseX_Full); -- phylink_set(mask, 2500baseX_Full); -- } -- if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) { -- phylink_set(mask, 1000baseT_Full); -- phylink_set(mask, 1000baseT_Half); -- phylink_set(mask, 1000baseX_Full); -- } -- if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_GEPHY)) { -- phylink_set(mask, 1000baseT_Full); -- phylink_set(mask, 1000baseT_Half); -- } -- } -- - phylink_set(mask, Pause); - phylink_set(mask, Asym_Pause); - --- -cgit v1.2.3 - - -From 438e63b5f984f3090adaecac4504de280e65ad69 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:08:35 +0100 -Subject: net: mtk_eth_soc: drop use of phylink_helper_basex_speed() - -Now that we have a better method to select SFP interface modes, we -no longer need to use phylink_helper_basex_speed() in a driver's -validation function, and we can also get rid of our hack to indicate -both 1000base-X and 2500base-X if the comphy is present to make that -work. Remove this hack and use of phylink_helper_basex_speed(). - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - -diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -index 2b728fd25930..2f89bfae2445 100644 ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -477,8 +477,9 @@ static void mtk_validate(struct phylink_config *config, - phylink_set(mask, 1000baseT_Full); - break; - case PHY_INTERFACE_MODE_1000BASEX: -- case PHY_INTERFACE_MODE_2500BASEX: - phylink_set(mask, 1000baseX_Full); -+ break; -+ case PHY_INTERFACE_MODE_2500BASEX: - phylink_set(mask, 2500baseX_Full); - break; - case PHY_INTERFACE_MODE_GMII: -@@ -508,11 +509,6 @@ static void mtk_validate(struct phylink_config *config, - - linkmode_and(supported, supported, mask); - linkmode_and(state->advertising, state->advertising, mask); -- -- /* We can only operate at 2500BaseX or 1000BaseX. If requested -- * to advertise both, only report advertising at 2500BaseX. -- */ -- phylink_helper_basex_speed(state); - } - - static const struct phylink_mac_ops mtk_phylink_ops = { --- -cgit v1.2.3 - - -From c646a0b4da29a661d56e5c2eeda5cc2825171bd6 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:38:49 +0100 -Subject: net: macb: populate supported_interfaces member - -Populate the phy_interface_t bitmap for the macb driver with interfaces -modes supported by the MAC. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/cadence/macb_main.c | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - -diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c -index e610fdc6ab97..acf101c2d0ec 100644 ---- a/drivers/net/ethernet/cadence/macb_main.c -+++ b/drivers/net/ethernet/cadence/macb_main.c -@@ -879,6 +879,24 @@ static int macb_mii_probe(struct net_device *dev) - bp->phylink_config.get_fixed_state = macb_get_pcs_fixed_state; - } - -+ /* We only support MII, RMII, GMII, RGMII & SGMII. */ -+ __set_bit(PHY_INTERFACE_MODE_MII, -+ bp->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_RMII, -+ bp->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ bp->phylink_config.supported_interfaces); -+ -+ if (macb_is_gem(bp)) { -+ __set_bit(PHY_INTERFACE_MODE_GMII, -+ bp->phylink_config.supported_interfaces); -+ phy_interface_set_rgmii(bp->phylink_config.supported_interfaces); -+ } -+ -+ if (bp->caps & MACB_CAPS_HIGH_SPEED && bp->caps & MACB_CAPS_PCS) -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, -+ bp->phylink_config.supported_interfaces); -+ - bp->phylink = phylink_create(&bp->phylink_config, bp->pdev->dev.fwnode, - bp->phy_interface, &macb_phylink_ops); - if (IS_ERR(bp->phylink)) { --- -cgit v1.2.3 - - -From 90019833292756d93a8959e8b2a13464d17470bc Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 13:41:27 +0100 -Subject: net: macb: remove interface checks in macb_validate() - -As phylink checks the interface mode against the supported_interfaces -bitmap, we no longer need to validate the interface mode in the -validation function. Remove this to simplify it. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/cadence/macb_main.c | 26 -------------------------- - 1 file changed, 26 deletions(-) - -diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c -index acf101c2d0ec..3dd57467aba8 100644 ---- a/drivers/net/ethernet/cadence/macb_main.c -+++ b/drivers/net/ethernet/cadence/macb_main.c -@@ -514,32 +514,6 @@ static void macb_validate(struct phylink_config *config, - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - struct macb *bp = netdev_priv(ndev); - -- /* We only support MII, RMII, GMII, RGMII & SGMII. */ -- if (state->interface != PHY_INTERFACE_MODE_NA && -- state->interface != PHY_INTERFACE_MODE_MII && -- state->interface != PHY_INTERFACE_MODE_RMII && -- state->interface != PHY_INTERFACE_MODE_GMII && -- state->interface != PHY_INTERFACE_MODE_SGMII && -- state->interface != PHY_INTERFACE_MODE_10GBASER && -- !phy_interface_mode_is_rgmii(state->interface)) { -- linkmode_zero(supported); -- return; -- } -- -- if (!macb_is_gem(bp) && -- (state->interface == PHY_INTERFACE_MODE_GMII || -- phy_interface_mode_is_rgmii(state->interface))) { -- linkmode_zero(supported); -- return; -- } -- -- if (state->interface == PHY_INTERFACE_MODE_10GBASER && -- !(bp->caps & MACB_CAPS_HIGH_SPEED && -- bp->caps & MACB_CAPS_PCS)) { -- linkmode_zero(supported); -- return; -- } -- - phylink_set_port_modes(mask); - phylink_set(mask, Autoneg); - phylink_set(mask, Asym_Pause); --- -cgit v1.2.3 - - -From 30494cf7146c4bb31115aafdd13448e1b1eef7bb Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 19 Oct 2021 14:18:15 +0100 -Subject: net: macb: clean up macb_validate() - -macb_validate() no longer needs to check for PHY_INTERFACE_MODE_NA as -phylink will walk the supported interface types to discover the link -mode capabilities. Remove these checks. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/cadence/macb_main.c | 9 +++------ - 1 file changed, 3 insertions(+), 6 deletions(-) - -diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c -index 3dd57467aba8..d84843bb3fb9 100644 ---- a/drivers/net/ethernet/cadence/macb_main.c -+++ b/drivers/net/ethernet/cadence/macb_main.c -@@ -519,12 +519,10 @@ static void macb_validate(struct phylink_config *config, - phylink_set(mask, Asym_Pause); - - if (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE && -- (state->interface == PHY_INTERFACE_MODE_NA || -- state->interface == PHY_INTERFACE_MODE_10GBASER)) { -+ state->interface == PHY_INTERFACE_MODE_10GBASER) { - phylink_set_10g_modes(mask); - phylink_set(mask, 10000baseKR_Full); -- if (state->interface != PHY_INTERFACE_MODE_NA) -- goto out; -+ goto out; - } - - phylink_set(mask, 10baseT_Half); -@@ -533,8 +531,7 @@ static void macb_validate(struct phylink_config *config, - phylink_set(mask, 100baseT_Full); - - if (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE && -- (state->interface == PHY_INTERFACE_MODE_NA || -- state->interface == PHY_INTERFACE_MODE_GMII || -+ (state->interface == PHY_INTERFACE_MODE_GMII || - state->interface == PHY_INTERFACE_MODE_SGMII || - phy_interface_mode_is_rgmii(state->interface))) { - phylink_set(mask, 1000baseT_Full); --- -cgit v1.2.3 - - -From db515d05ffcde68a4cc2a6468f47c957abb9569a Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sat, 6 Nov 2021 10:13:24 +0000 -Subject: net: phylink: handle NA interface mode in - phylink_fwnode_phy_connect() - -Commit 4904b6ea1f9db ("net: phy: phylink: Use PHY device interface if -N/A") introduced handling for the phy interface mode where this is not -known at phylink creation time. This was never added to the OF/fwnode -paths, but is necessary when the phy-mode is not specified in DT. - -Add this handling. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/phy/phylink.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index 5fbd4de129d1..689bc4e4b7b7 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -1072,7 +1072,8 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, - mutex_unlock(&phy->lock); - - phylink_dbg(pl, -- "phy: setting supported %*pb advertising %*pb\n", -+ "phy: %s setting supported %*pb advertising %*pb\n", -+ phy_modes(interface), - __ETHTOOL_LINK_MODE_MASK_NBITS, pl->supported, - __ETHTOOL_LINK_MODE_MASK_NBITS, phy->advertising); - -@@ -1190,6 +1191,12 @@ int phylink_fwnode_phy_connect(struct phylink *pl, - if (!phy_dev) - return -ENODEV; - -+ /* Use PHY device/driver interface */ -+ if (pl->link_interface == PHY_INTERFACE_MODE_NA) { -+ pl->link_interface = phy_dev->interface; -+ pl->link_config.interface = pl->link_interface; -+ } -+ - ret = phy_attach_direct(pl->netdev, phy_dev, flags, - pl->link_interface); - if (ret) { --- -cgit v1.2.3 - - -From be47a51b70b663046c81b8410243227a5e83af0c Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 21 Oct 2021 15:52:11 +0100 -Subject: net: dsa: mv88e6xxx: add mv88e6352_g2_scratch_port_has_serdes() - -Read the hardware configuration to determine which port is attached -to the serdes. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/dsa/mv88e6xxx/global2.h | 3 +++ - drivers/net/dsa/mv88e6xxx/global2_scratch.c | 25 +++++++++++++++++++++++++ - 2 files changed, 28 insertions(+) - -diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h -index f3e27573a386..807aeaad9830 100644 ---- a/drivers/net/dsa/mv88e6xxx/global2.h -+++ b/drivers/net/dsa/mv88e6xxx/global2.h -@@ -299,6 +299,8 @@ - #define MV88E6352_G2_SCRATCH_CONFIG_DATA1_NO_CPU BIT(2) - #define MV88E6352_G2_SCRATCH_CONFIG_DATA2 0x72 - #define MV88E6352_G2_SCRATCH_CONFIG_DATA2_P0_MODE_MASK 0x3 -+#define MV88E6352_G2_SCRATCH_CONFIG_DATA3 0x73 -+#define MV88E6352_G2_SCRATCH_CONFIG_DATA3_S_SEL BIT(1) - - #define MV88E6352_G2_SCRATCH_GPIO_PCTL_GPIO 0 - #define MV88E6352_G2_SCRATCH_GPIO_PCTL_TRIG 1 -@@ -370,6 +372,7 @@ extern const struct mv88e6xxx_gpio_ops mv88e6352_gpio_ops; - - int mv88e6xxx_g2_scratch_gpio_set_smi(struct mv88e6xxx_chip *chip, - bool external); -+int mv88e6352_g2_scratch_port_has_serdes(struct mv88e6xxx_chip *chip, int port); - int mv88e6xxx_g2_atu_stats_set(struct mv88e6xxx_chip *chip, u16 kind, u16 bin); - int mv88e6xxx_g2_atu_stats_get(struct mv88e6xxx_chip *chip, u16 *stats); - -diff --git a/drivers/net/dsa/mv88e6xxx/global2_scratch.c b/drivers/net/dsa/mv88e6xxx/global2_scratch.c -index eda710062933..221e2f8280ab 100644 ---- a/drivers/net/dsa/mv88e6xxx/global2_scratch.c -+++ b/drivers/net/dsa/mv88e6xxx/global2_scratch.c -@@ -289,3 +289,28 @@ int mv88e6xxx_g2_scratch_gpio_set_smi(struct mv88e6xxx_chip *chip, - - return mv88e6xxx_g2_scratch_write(chip, misc_cfg, val); - } -+ -+/** -+ * mv88e6352_g2_scratch_port_has_serdes - get port number associated with serdes -+ * @chip: chip private data -+ * @port: port number to check for serdes -+ * -+ * Retrieve the serdes configuration for the chip. -+ */ -+int mv88e6352_g2_scratch_port_has_serdes(struct mv88e6xxx_chip *chip, int port) -+{ -+ u8 config3, p; -+ int err; -+ -+ err = mv88e6xxx_g2_scratch_read(chip, MV88E6352_G2_SCRATCH_CONFIG_DATA3, -+ &config3); -+ if (err) -+ return err; -+ -+ if (config3 & MV88E6352_G2_SCRATCH_CONFIG_DATA3_S_SEL) -+ p = 5; -+ else -+ p = 4; -+ -+ return port == p; -+} --- -cgit v1.2.3 - - -From de7aac5a9a51b1096c3501b9fdeb012fad5f05cc Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 21 Oct 2021 15:57:15 +0100 -Subject: net: dsa: mv88e6xxx: populate supported_interfaces - -Populate the supported interfaces for Marvell 88E6352, 88E6341, -88E6390, 88E6390X and 88E6393X family of switches. - -We do the best effort for 88E6393X based on the information we have -available, but this is incomplete; for the 88E6391X, apparently only -one serdes port supports speeds greater than 1G, but we don't know -which port it is. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/dsa/mv88e6xxx/chip.c | 207 ++++++++++++++++++++++++++++++++++++++- - drivers/net/dsa/mv88e6xxx/chip.h | 2 + - drivers/net/dsa/mv88e6xxx/port.h | 5 + - 3 files changed, 210 insertions(+), 4 deletions(-) - -diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c -index 14c678a9e41b..4ecfa5710cdc 100644 ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -676,11 +676,195 @@ static void mv88e6xxx_validate(struct dsa_switch *ds, int port, - - linkmode_and(supported, supported, mask); - linkmode_and(state->advertising, state->advertising, mask); -+} - -- /* We can only operate at 2500BaseX or 1000BaseX. If requested -- * to advertise both, only report advertising at 2500BaseX. -- */ -- phylink_helper_basex_speed(state); -+static const u8 mv88e6185_phy_interface_modes[] = { -+ [MV88E6185_PORT_STS_CMODE_GMII_FD] = PHY_INTERFACE_MODE_GMII, -+ [MV88E6185_PORT_STS_CMODE_MII_100_FD_PS] = PHY_INTERFACE_MODE_MII, -+ [MV88E6185_PORT_STS_CMODE_MII_100] = PHY_INTERFACE_MODE_MII, -+ [MV88E6185_PORT_STS_CMODE_MII_10] = PHY_INTERFACE_MODE_MII, -+ [MV88E6185_PORT_STS_CMODE_SERDES] = PHY_INTERFACE_MODE_1000BASEX, -+ [MV88E6185_PORT_STS_CMODE_1000BASE_X] = PHY_INTERFACE_MODE_1000BASEX, -+ [MV88E6185_PORT_STS_CMODE_PHY] = PHY_INTERFACE_MODE_SGMII, -+}; -+ -+static void mv88e6185_phylink_get_interfaces(struct mv88e6xxx_chip *chip, -+ int port, unsigned long *supported) -+{ -+ u8 cmode = chip->ports[port].cmode; -+ -+ if (cmode <= ARRAY_SIZE(mv88e6185_phy_interface_modes) && -+ mv88e6185_phy_interface_modes[cmode]) -+ __set_bit(mv88e6185_phy_interface_modes[cmode], supported); -+} -+ -+static const u8 mv88e6xxx_phy_interface_modes[] = { -+ [MV88E6XXX_PORT_STS_CMODE_MII_PHY] = PHY_INTERFACE_MODE_MII, -+ [MV88E6XXX_PORT_STS_CMODE_MII] = PHY_INTERFACE_MODE_MII, -+ [MV88E6XXX_PORT_STS_CMODE_GMII] = PHY_INTERFACE_MODE_GMII, -+ [MV88E6XXX_PORT_STS_CMODE_RMII_PHY] = PHY_INTERFACE_MODE_RMII, -+ [MV88E6XXX_PORT_STS_CMODE_RMII] = PHY_INTERFACE_MODE_RMII, -+ [MV88E6XXX_PORT_STS_CMODE_100BASEX] = PHY_INTERFACE_MODE_100BASEX, -+ [MV88E6XXX_PORT_STS_CMODE_1000BASEX] = PHY_INTERFACE_MODE_1000BASEX, -+ [MV88E6XXX_PORT_STS_CMODE_SGMII] = PHY_INTERFACE_MODE_SGMII, -+ [MV88E6XXX_PORT_STS_CMODE_2500BASEX] = PHY_INTERFACE_MODE_2500BASEX, -+ [MV88E6XXX_PORT_STS_CMODE_XAUI] = PHY_INTERFACE_MODE_XAUI, -+ [MV88E6XXX_PORT_STS_CMODE_RXAUI] = PHY_INTERFACE_MODE_RXAUI, -+}; -+ -+static void mv88e6xxx_translate_cmode(u8 cmode, unsigned long *supported) -+{ -+ if (cmode < ARRAY_SIZE(mv88e6xxx_phy_interface_modes) && -+ mv88e6xxx_phy_interface_modes[cmode]) -+ __set_bit(mv88e6xxx_phy_interface_modes[cmode], supported); -+ else if (cmode == MV88E6XXX_PORT_STS_CMODE_RGMII) -+ phy_interface_set_rgmii(supported); -+} -+ -+static int mv88e6352_get_port4_serdes_cmode(struct mv88e6xxx_chip *chip) -+{ -+ u16 reg, val; -+ int err; -+ -+ mv88e6xxx_reg_lock(chip); -+ err = mv88e6xxx_port_read(chip, 4, MV88E6XXX_PORT_STS, ®); -+ if (err) -+ goto unlock; -+ -+ /* If PHY_DETECT is zero, then we are not in auto-media mode */ -+ if (!(reg & MV88E6XXX_PORT_STS_PHY_DETECT)) { -+ val = 0xf; -+ goto unlock; -+ } -+ -+ val = reg & ~MV88E6XXX_PORT_STS_PHY_DETECT; -+ err = mv88e6xxx_port_write(chip, 4, MV88E6XXX_PORT_STS, val); -+ if (err) -+ goto unlock; -+ -+ err = mv88e6xxx_port_read(chip, 4, MV88E6XXX_PORT_STS, &val); -+ if (err) -+ goto unlock; -+ -+ /* Restore PHY_DETECT value */ -+ err = mv88e6xxx_port_write(chip, 4, MV88E6XXX_PORT_STS, reg); -+unlock: -+ mv88e6xxx_reg_unlock(chip); -+ -+ return err ? err : (val & MV88E6XXX_PORT_STS_CMODE_MASK); -+} -+ -+static void mv88e6352_phylink_get_interfaces(struct mv88e6xxx_chip *chip, -+ int port, unsigned long *supported) -+{ -+ int err, cmode; -+ -+ /* Translate the default cmode */ -+ mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported); -+ -+ /* Port 4 supports automedia if the serdes is associated with it. */ -+ if (port == 4) { -+ mv88e6xxx_reg_lock(chip); -+ err = mv88e6352_g2_scratch_port_has_serdes(chip, port); -+ mv88e6xxx_reg_unlock(chip); -+ if (err <= 0) -+ return; -+ -+ cmode = mv88e6352_get_port4_serdes_cmode(chip); -+ if (cmode >= 0) -+ mv88e6xxx_translate_cmode(cmode, supported); -+ } -+} -+ -+static void mv88e6341_phylink_get_interfaces(struct mv88e6xxx_chip *chip, -+ int port, -+ unsigned long *supported) -+{ -+ /* Translate the default cmode */ -+ mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported); -+} -+ -+static void mv88e6390_phylink_get_interfaces(struct mv88e6xxx_chip *chip, -+ int port, -+ unsigned long *supported) -+{ -+ /* Translate the default cmode */ -+ mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported); -+ -+ /* The C_Mode field is programmable on ports 9 and 10 */ -+ if (port == 9 || port == 10) { -+ __set_bit(PHY_INTERFACE_MODE_SGMII, supported); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); -+ } -+} -+ -+static void mv88e6390x_phylink_get_interfaces(struct mv88e6xxx_chip *chip, -+ int port, -+ unsigned long *supported) -+{ -+ mv88e6390_phylink_get_interfaces(chip, port, supported); -+ -+ /* The C_Mode field can also be programmed for 10G speeds */ -+ if (port == 9 || port == 10) { -+ __set_bit(PHY_INTERFACE_MODE_XAUI, supported); -+ __set_bit(PHY_INTERFACE_MODE_RXAUI, supported); -+ } -+} -+ -+static const u8 mv88e6393x_phy_interface_modes[] = { -+ [MV88E6XXX_PORT_STS_CMODE_MII_PHY] = PHY_INTERFACE_MODE_MII, -+ [MV88E6XXX_PORT_STS_CMODE_MII] = PHY_INTERFACE_MODE_MII, -+ [MV88E6XXX_PORT_STS_CMODE_GMII] = PHY_INTERFACE_MODE_GMII, -+ [MV88E6XXX_PORT_STS_CMODE_RMII_PHY] = PHY_INTERFACE_MODE_RMII, -+ [MV88E6XXX_PORT_STS_CMODE_RMII] = PHY_INTERFACE_MODE_RMII, -+ [MV88E6XXX_PORT_STS_CMODE_100BASEX] = PHY_INTERFACE_MODE_100BASEX, -+ [MV88E6XXX_PORT_STS_CMODE_1000BASEX] = PHY_INTERFACE_MODE_1000BASEX, -+ [MV88E6XXX_PORT_STS_CMODE_SGMII] = PHY_INTERFACE_MODE_SGMII, -+ [MV88E6XXX_PORT_STS_CMODE_2500BASEX] = PHY_INTERFACE_MODE_2500BASEX, -+ [MV88E6393X_PORT_STS_CMODE_5GBASER] = PHY_INTERFACE_MODE_5GBASER, -+ [MV88E6393X_PORT_STS_CMODE_10GBASER] = PHY_INTERFACE_MODE_10GBASER, -+ [MV88E6393X_PORT_STS_CMODE_USXGMII] = PHY_INTERFACE_MODE_USXGMII, -+}; -+ -+static void mv88e6393x_phylink_get_interfaces(struct mv88e6xxx_chip *chip, -+ int port, -+ unsigned long *supported) -+{ -+ u8 cmode = chip->ports[port].cmode; -+ -+ if (cmode < ARRAY_SIZE(mv88e6393x_phy_interface_modes) && -+ mv88e6393x_phy_interface_modes[cmode]) -+ __set_bit(mv88e6393x_phy_interface_modes[cmode], supported); -+ -+ if (port == 0 || port == 9 || port == 10) { -+ /* Ports 0, 9 and 10 have read/write cmodes according to the -+ * datasheet and erratum documents. -+ * -+ * FIXME: The original commit also says: "SERDESes can do -+ * USXGMII, 10GBASER and 5GBASER (on 6191X only one SERDES -+ * is capable of more than 1g; USXGMII is not yet supported -+ * with this change)" We don't know which port supports 10G, -+ * so lets assume they all do for the time being. -+ */ -+ __set_bit(PHY_INTERFACE_MODE_5GBASER, supported); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); -+ __set_bit(PHY_INTERFACE_MODE_USXGMII, supported); -+ } -+} -+ -+static void mv88e6xxx_get_interfaces(struct dsa_switch *ds, int port, -+ unsigned long *supported) -+{ -+ struct mv88e6xxx_chip *chip = ds->priv; -+ -+ if (chip->info->ops->phylink_get_interfaces) { -+ chip->info->ops->phylink_get_interfaces(chip, port, supported); -+ -+ /* Internal ports need GMII for PHYLIB */ -+ if (mv88e6xxx_phy_is_internal(ds, port)) -+ __set_bit(PHY_INTERFACE_MODE_GMII, supported); -+ } - } - - static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, -@@ -3799,6 +3983,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { - .serdes_get_stats = mv88e6390_serdes_get_stats, - .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, - .serdes_get_regs = mv88e6390_serdes_get_regs, -+ .phylink_get_interfaces = mv88e6341_phylink_get_interfaces, - .phylink_validate = mv88e6341_phylink_validate, - }; - -@@ -3974,6 +4159,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { - .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, - .serdes_get_regs = mv88e6352_serdes_get_regs, - .gpio_ops = &mv88e6352_gpio_ops, -+ .phylink_get_interfaces = mv88e6352_phylink_get_interfaces, - .phylink_validate = mv88e6352_phylink_validate, - }; - -@@ -4074,6 +4260,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { - .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, - .serdes_get_regs = mv88e6352_serdes_get_regs, - .gpio_ops = &mv88e6352_gpio_ops, -+ .phylink_get_interfaces = mv88e6352_phylink_get_interfaces, - .phylink_validate = mv88e6352_phylink_validate, - }; - -@@ -4113,6 +4300,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { - .reset = mv88e6185_g1_reset, - .vtu_getnext = mv88e6185_g1_vtu_getnext, - .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, -+ .phylink_get_interfaces = mv88e6185_phylink_get_interfaces, - .phylink_validate = mv88e6185_phylink_validate, - .set_max_frame_size = mv88e6185_g1_set_max_frame_size, - }; -@@ -4175,6 +4363,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { - .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, - .serdes_get_regs = mv88e6390_serdes_get_regs, - .gpio_ops = &mv88e6352_gpio_ops, -+ .phylink_get_interfaces = mv88e6390_phylink_get_interfaces, - .phylink_validate = mv88e6390_phylink_validate, - }; - -@@ -4236,6 +4425,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { - .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, - .serdes_get_regs = mv88e6390_serdes_get_regs, - .gpio_ops = &mv88e6352_gpio_ops, -+ .phylink_get_interfaces = mv88e6390x_phylink_get_interfaces, - .phylink_validate = mv88e6390x_phylink_validate, - }; - -@@ -4296,6 +4486,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { - .serdes_get_regs = mv88e6390_serdes_get_regs, - .avb_ops = &mv88e6390_avb_ops, - .ptp_ops = &mv88e6352_ptp_ops, -+ .phylink_get_interfaces = mv88e6390_phylink_get_interfaces, - .phylink_validate = mv88e6390_phylink_validate, - }; - -@@ -4356,6 +4547,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { - .gpio_ops = &mv88e6352_gpio_ops, - .avb_ops = &mv88e6352_avb_ops, - .ptp_ops = &mv88e6352_ptp_ops, -+ .phylink_get_interfaces = mv88e6352_phylink_get_interfaces, - .phylink_validate = mv88e6352_phylink_validate, - }; - -@@ -4458,6 +4650,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { - .gpio_ops = &mv88e6352_gpio_ops, - .avb_ops = &mv88e6390_avb_ops, - .ptp_ops = &mv88e6352_ptp_ops, -+ .phylink_get_interfaces = mv88e6390_phylink_get_interfaces, - .phylink_validate = mv88e6390_phylink_validate, - }; - -@@ -4610,6 +4803,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { - .serdes_get_stats = mv88e6390_serdes_get_stats, - .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, - .serdes_get_regs = mv88e6390_serdes_get_regs, -+ .phylink_get_interfaces = mv88e6341_phylink_get_interfaces, - .phylink_validate = mv88e6341_phylink_validate, - }; - -@@ -4759,6 +4953,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { - .serdes_get_stats = mv88e6352_serdes_get_stats, - .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, - .serdes_get_regs = mv88e6352_serdes_get_regs, -+ .phylink_get_interfaces = mv88e6352_phylink_get_interfaces, - .phylink_validate = mv88e6352_phylink_validate, - }; - -@@ -4824,6 +5019,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { - .serdes_get_stats = mv88e6390_serdes_get_stats, - .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, - .serdes_get_regs = mv88e6390_serdes_get_regs, -+ .phylink_get_interfaces = mv88e6390_phylink_get_interfaces, - .phylink_validate = mv88e6390_phylink_validate, - }; - -@@ -4888,6 +5084,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { - .gpio_ops = &mv88e6352_gpio_ops, - .avb_ops = &mv88e6390_avb_ops, - .ptp_ops = &mv88e6352_ptp_ops, -+ .phylink_get_interfaces = mv88e6390x_phylink_get_interfaces, - .phylink_validate = mv88e6390x_phylink_validate, - }; - -@@ -4952,6 +5149,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = { - .gpio_ops = &mv88e6352_gpio_ops, - .avb_ops = &mv88e6390_avb_ops, - .ptp_ops = &mv88e6352_ptp_ops, -+ .phylink_get_interfaces = mv88e6393x_phylink_get_interfaces, - .phylink_validate = mv88e6393x_phylink_validate, - }; - -@@ -6221,6 +6419,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { - .teardown = mv88e6xxx_teardown, - .port_setup = mv88e6xxx_port_setup, - .port_teardown = mv88e6xxx_port_teardown, -+ .phylink_get_interfaces = mv88e6xxx_get_interfaces, - .phylink_validate = mv88e6xxx_validate, - .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state, - .phylink_mac_config = mv88e6xxx_mac_config, -diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h -index 8271b8aa7b71..73b337478378 100644 ---- a/drivers/net/dsa/mv88e6xxx/chip.h -+++ b/drivers/net/dsa/mv88e6xxx/chip.h -@@ -609,6 +609,8 @@ struct mv88e6xxx_ops { - const struct mv88e6xxx_ptp_ops *ptp_ops; - - /* Phylink */ -+ void (*phylink_get_interfaces)(struct mv88e6xxx_chip *chip, int port, -+ unsigned long *supported); - void (*phylink_validate)(struct mv88e6xxx_chip *chip, int port, - unsigned long *mask, - struct phylink_link_state *state); -diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h -index 03382b66f800..ea6adfcfb42c 100644 ---- a/drivers/net/dsa/mv88e6xxx/port.h -+++ b/drivers/net/dsa/mv88e6xxx/port.h -@@ -42,6 +42,11 @@ - #define MV88E6XXX_PORT_STS_TX_PAUSED 0x0020 - #define MV88E6XXX_PORT_STS_FLOW_CTL 0x0010 - #define MV88E6XXX_PORT_STS_CMODE_MASK 0x000f -+#define MV88E6XXX_PORT_STS_CMODE_MII_PHY 0x0001 -+#define MV88E6XXX_PORT_STS_CMODE_MII 0x0002 -+#define MV88E6XXX_PORT_STS_CMODE_GMII 0x0003 -+#define MV88E6XXX_PORT_STS_CMODE_RMII_PHY 0x0004 -+#define MV88E6XXX_PORT_STS_CMODE_RMII 0x0005 - #define MV88E6XXX_PORT_STS_CMODE_RGMII 0x0007 - #define MV88E6XXX_PORT_STS_CMODE_100BASEX 0x0008 - #define MV88E6XXX_PORT_STS_CMODE_1000BASEX 0x0009 --- -cgit v1.2.3 - - -From 611da36301649a90688b6fb3c83918275476d113 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 21 Oct 2021 14:48:06 +0100 -Subject: net: dsa: mv88e6xxx: improve 88e6352 serdes statistics detection - -The decision whether to report serdes statistics currently depends on -the cached C_Mode value for the port, read at probe time or updated by -configuration. However, port 4 can be in "automedia" mode when it is -used as a serdes port, meaning it switches between the internal PHY and -the serdes, changing the read-only C_Mode value depending on which -first gains link. Consequently, the C_Mode value read at probe does not -accurately reflect whether the port has the serdes associated with it. - -In "net: dsa: mv88e6xxx: add mv88e6352_g2_scratch_port_has_serdes()", -we added a way to read the hardware configuration to determine which -port has the serdes associated with it. Use this to determine which -port reports the serdes statistics. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/dsa/mv88e6xxx/serdes.c | 43 ++++++++++++++++++++------------------ - 1 file changed, 23 insertions(+), 20 deletions(-) - -diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c -index 6ea003678798..da54cbadfd63 100644 ---- a/drivers/net/dsa/mv88e6xxx/serdes.c -+++ b/drivers/net/dsa/mv88e6xxx/serdes.c -@@ -243,14 +243,6 @@ int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) - return lane; - } - --static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port) --{ -- if (mv88e6xxx_serdes_get_lane(chip, port) >= 0) -- return true; -- -- return false; --} -- - struct mv88e6352_serdes_hw_stat { - char string[ETH_GSTRING_LEN]; - int sizeof_stat; -@@ -264,20 +256,24 @@ static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = { - - int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port) - { -- if (mv88e6352_port_has_serdes(chip, port)) -- return ARRAY_SIZE(mv88e6352_serdes_hw_stats); -+ int err; - -- return 0; -+ err = mv88e6352_g2_scratch_port_has_serdes(chip, port); -+ if (err <= 0) -+ return err; -+ -+ return ARRAY_SIZE(mv88e6352_serdes_hw_stats); - } - - int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, - int port, uint8_t *data) - { - struct mv88e6352_serdes_hw_stat *stat; -- int i; -+ int err, i; - -- if (!mv88e6352_port_has_serdes(chip, port)) -- return 0; -+ err = mv88e6352_g2_scratch_port_has_serdes(chip, port); -+ if (err <= 0) -+ return err; - - for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) { - stat = &mv88e6352_serdes_hw_stats[i]; -@@ -319,11 +315,12 @@ int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, - { - struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port]; - struct mv88e6352_serdes_hw_stat *stat; -+ int i, err; - u64 value; -- int i; - -- if (!mv88e6352_port_has_serdes(chip, port)) -- return 0; -+ err = mv88e6352_g2_scratch_port_has_serdes(chip, port); -+ if (err <= 0) -+ return err; - - BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) > - ARRAY_SIZE(mv88e6xxx_port->serdes_stats)); -@@ -390,8 +387,13 @@ unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) - - int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port) - { -- if (!mv88e6352_port_has_serdes(chip, port)) -- return 0; -+ int err; -+ -+ mv88e6xxx_reg_lock(chip); -+ err = mv88e6352_g2_scratch_port_has_serdes(chip, port); -+ mv88e6xxx_reg_unlock(chip); -+ if (err <= 0) -+ return err; - - return 32 * sizeof(u16); - } -@@ -403,7 +405,8 @@ void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p) - int err; - int i; - -- if (!mv88e6352_port_has_serdes(chip, port)) -+ err = mv88e6352_g2_scratch_port_has_serdes(chip, port); -+ if (err <= 0) - return; - - for (i = 0 ; i < 32; i++) { --- -cgit v1.2.3 - - -From c93f057fc14c08f250f7281e79603ff6f051d33a Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 5 Nov 2021 12:05:42 +0000 -Subject: net: dsa: mt7530: populate supported_interfaces - -Populate the supported interfaces for mt7530, mt7531 and mt7621 DSA -switches. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/dsa/mt7530.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ - drivers/net/dsa/mt7530.h | 2 ++ - 2 files changed, 59 insertions(+) - -diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c -index 9890672a206d..04ddc74bcae3 100644 ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -2376,6 +2376,27 @@ mt7531_setup(struct dsa_switch *ds) - return 0; - } - -+static void mt7530_get_phy_modes(struct dsa_switch *ds, int port, -+ unsigned long supported_interfaces) -+{ -+ switch (port) { -+ case 0 ... 4: /* Internal phy */ -+ __set_bit(PHY_INTERFACE_MODE_GMII, supported_interfaces); -+ break; -+ -+ case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ -+ phy_interface_set_rgmii(supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_MII, supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_GMII, supported_interfaces); -+ break; -+ -+ case 6: /* 1st cpu port */ -+ __set_bit(PHY_INTERFACE_MODE_RGMII, supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_TRGMII, supported_interfaces); -+ break; -+ } -+} -+ - static bool - mt7530_phy_mode_supported(struct dsa_switch *ds, int port, - const struct phylink_link_state *state) -@@ -2412,6 +2433,29 @@ static bool mt7531_is_rgmii_port(struct mt7530_priv *priv, u32 port) - return (port == 5) && (priv->p5_intf_sel != P5_INTF_SEL_GMAC5_SGMII); - } - -+static void mt7531_get_phy_modes(struct dsa_switch *ds, int port, -+ unsigned long *supported_interfaces) -+{ -+ switch (port) { -+ case 0 ... 4: /* Internal phy */ -+ __set_bit(PHY_INTERFACE_MODE_GMII, supported_interfaces); -+ break; -+ -+ case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */ -+ if (mt7531_is_rgmii_port(priv, port)) { -+ phy_interface_set_rgmii(supported_interfaces); -+ break; -+ } -+ fallthrough; -+ -+ case 6: /* 1st cpu port supports sgmii/8023z only */ -+ __set_bit(PHY_INTERFACE_MODE_SGMII, supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported_interfaces); -+ break; -+ } -+} -+ - static bool - mt7531_phy_mode_supported(struct dsa_switch *ds, int port, - const struct phylink_link_state *state) -@@ -2896,6 +2940,14 @@ mt7531_cpu_port_config(struct dsa_switch *ds, int port) - return 0; - } - -+static void mt753x_phylink_get_interfaces(struct dsa_switch *ds, int port, -+ unsigned long *supported_interfaces) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ priv->info->get_phy_modes(ds, port, supported_interfaces); -+} -+ - static void - mt7530_mac_port_validate(struct dsa_switch *ds, int port, - unsigned long *supported) -@@ -3131,6 +3183,7 @@ static const struct dsa_switch_ops mt7530_switch_ops = { - .port_vlan_del = mt7530_port_vlan_del, - .port_mirror_add = mt753x_port_mirror_add, - .port_mirror_del = mt753x_port_mirror_del, -+ .phylink_get_interfaces = mt753x_phylink_get_interfaces, - .phylink_validate = mt753x_phylink_validate, - .phylink_mac_link_state = mt753x_phylink_mac_link_state, - .phylink_mac_config = mt753x_phylink_mac_config, -@@ -3148,6 +3201,7 @@ static const struct mt753x_info mt753x_table[] = { - .phy_read = mt7530_phy_read, - .phy_write = mt7530_phy_write, - .pad_setup = mt7530_pad_clk_setup, -+ .get_phy_modes = mt7530_get_phy_modes, - .phy_mode_supported = mt7530_phy_mode_supported, - .mac_port_validate = mt7530_mac_port_validate, - .mac_port_get_state = mt7530_phylink_mac_link_state, -@@ -3159,6 +3213,7 @@ static const struct mt753x_info mt753x_table[] = { - .phy_read = mt7530_phy_read, - .phy_write = mt7530_phy_write, - .pad_setup = mt7530_pad_clk_setup, -+ .get_phy_modes = mt7530_get_phy_modes, - .phy_mode_supported = mt7530_phy_mode_supported, - .mac_port_validate = mt7530_mac_port_validate, - .mac_port_get_state = mt7530_phylink_mac_link_state, -@@ -3171,6 +3226,7 @@ static const struct mt753x_info mt753x_table[] = { - .phy_write = mt7531_ind_phy_write, - .pad_setup = mt7531_pad_setup, - .cpu_port_config = mt7531_cpu_port_config, -+ .get_phy_modes = mt7531_get_phy_modes, - .phy_mode_supported = mt7531_phy_mode_supported, - .mac_port_validate = mt7531_mac_port_validate, - .mac_port_get_state = mt7531_phylink_mac_link_state, -@@ -3233,6 +3289,7 @@ mt7530_probe(struct mdio_device *mdiodev) - */ - if (!priv->info->sw_setup || !priv->info->pad_setup || - !priv->info->phy_read || !priv->info->phy_write || -+ !priv->info->get_phy_modes || - !priv->info->phy_mode_supported || - !priv->info->mac_port_validate || - !priv->info->mac_port_get_state || !priv->info->mac_port_config) -diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h -index 91508e2feef9..cbb0b30d7123 100644 ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -769,6 +769,8 @@ struct mt753x_info { - int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val); - int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface); - int (*cpu_port_config)(struct dsa_switch *ds, int port); -+ void (*get_phy_modes)(struct dsa_switch *ds, int port, -+ unsigned long *supported_interfaces); - bool (*phy_mode_supported)(struct dsa_switch *ds, int port, - const struct phylink_link_state *state); - void (*mac_port_validate)(struct dsa_switch *ds, int port, --- -cgit v1.2.3 - - -From 13bafc22a6a082116f3fa76af3fec171962624c1 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 5 Nov 2021 12:09:00 +0000 -Subject: net: dsa: mt7530: remove interface checks - -As phylink checks the interface mode against the supported_interfaces -bitmap, we no longer need to validate the interface mode, nor handle -PHY_INTERFACE_MODE_NA in the validation function. Remove these to -simplify the implementation. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/dsa/mt7530.c | 82 ------------------------------------------------ - drivers/net/dsa/mt7530.h | 2 -- - 2 files changed, 84 deletions(-) - -diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c -index 04ddc74bcae3..c49058c26f5c 100644 ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -2397,37 +2397,6 @@ static void mt7530_get_phy_modes(struct dsa_switch *ds, int port, - } - } - --static bool --mt7530_phy_mode_supported(struct dsa_switch *ds, int port, -- const struct phylink_link_state *state) --{ -- struct mt7530_priv *priv = ds->priv; -- -- switch (port) { -- case 0 ... 4: /* Internal phy */ -- if (state->interface != PHY_INTERFACE_MODE_GMII) -- return false; -- break; -- case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ -- if (!phy_interface_mode_is_rgmii(state->interface) && -- state->interface != PHY_INTERFACE_MODE_MII && -- state->interface != PHY_INTERFACE_MODE_GMII) -- return false; -- break; -- case 6: /* 1st cpu port */ -- if (state->interface != PHY_INTERFACE_MODE_RGMII && -- state->interface != PHY_INTERFACE_MODE_TRGMII) -- return false; -- break; -- default: -- dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, -- port); -- return false; -- } -- -- return true; --} -- - static bool mt7531_is_rgmii_port(struct mt7530_priv *priv, u32 port) - { - return (port == 5) && (priv->p5_intf_sel != P5_INTF_SEL_GMAC5_SGMII); -@@ -2456,44 +2425,6 @@ static void mt7531_get_phy_modes(struct dsa_switch *ds, int port, - } - } - --static bool --mt7531_phy_mode_supported(struct dsa_switch *ds, int port, -- const struct phylink_link_state *state) --{ -- struct mt7530_priv *priv = ds->priv; -- -- switch (port) { -- case 0 ... 4: /* Internal phy */ -- if (state->interface != PHY_INTERFACE_MODE_GMII) -- return false; -- break; -- case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */ -- if (mt7531_is_rgmii_port(priv, port)) -- return phy_interface_mode_is_rgmii(state->interface); -- fallthrough; -- case 6: /* 1st cpu port supports sgmii/8023z only */ -- if (state->interface != PHY_INTERFACE_MODE_SGMII && -- !phy_interface_mode_is_8023z(state->interface)) -- return false; -- break; -- default: -- dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, -- port); -- return false; -- } -- -- return true; --} -- --static bool --mt753x_phy_mode_supported(struct dsa_switch *ds, int port, -- const struct phylink_link_state *state) --{ -- struct mt7530_priv *priv = ds->priv; -- -- return priv->info->phy_mode_supported(ds, port, state); --} -- - static int - mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) - { -@@ -2754,9 +2685,6 @@ mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, - struct mt7530_priv *priv = ds->priv; - u32 mcr_cur, mcr_new; - -- if (!mt753x_phy_mode_supported(ds, port, state)) -- goto unsupported; -- - switch (port) { - case 0 ... 4: /* Internal phy */ - if (state->interface != PHY_INTERFACE_MODE_GMII) -@@ -2972,12 +2900,6 @@ mt753x_phylink_validate(struct dsa_switch *ds, int port, - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - struct mt7530_priv *priv = ds->priv; - -- if (state->interface != PHY_INTERFACE_MODE_NA && -- !mt753x_phy_mode_supported(ds, port, state)) { -- linkmode_zero(supported); -- return; -- } -- - phylink_set_port_modes(mask); - - if (state->interface != PHY_INTERFACE_MODE_TRGMII || -@@ -3202,7 +3124,6 @@ static const struct mt753x_info mt753x_table[] = { - .phy_write = mt7530_phy_write, - .pad_setup = mt7530_pad_clk_setup, - .get_phy_modes = mt7530_get_phy_modes, -- .phy_mode_supported = mt7530_phy_mode_supported, - .mac_port_validate = mt7530_mac_port_validate, - .mac_port_get_state = mt7530_phylink_mac_link_state, - .mac_port_config = mt7530_mac_config, -@@ -3214,7 +3135,6 @@ static const struct mt753x_info mt753x_table[] = { - .phy_write = mt7530_phy_write, - .pad_setup = mt7530_pad_clk_setup, - .get_phy_modes = mt7530_get_phy_modes, -- .phy_mode_supported = mt7530_phy_mode_supported, - .mac_port_validate = mt7530_mac_port_validate, - .mac_port_get_state = mt7530_phylink_mac_link_state, - .mac_port_config = mt7530_mac_config, -@@ -3227,7 +3147,6 @@ static const struct mt753x_info mt753x_table[] = { - .pad_setup = mt7531_pad_setup, - .cpu_port_config = mt7531_cpu_port_config, - .get_phy_modes = mt7531_get_phy_modes, -- .phy_mode_supported = mt7531_phy_mode_supported, - .mac_port_validate = mt7531_mac_port_validate, - .mac_port_get_state = mt7531_phylink_mac_link_state, - .mac_port_config = mt7531_mac_config, -@@ -3290,7 +3209,6 @@ mt7530_probe(struct mdio_device *mdiodev) - if (!priv->info->sw_setup || !priv->info->pad_setup || - !priv->info->phy_read || !priv->info->phy_write || - !priv->info->get_phy_modes || -- !priv->info->phy_mode_supported || - !priv->info->mac_port_validate || - !priv->info->mac_port_get_state || !priv->info->mac_port_config) - return -EINVAL; -diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h -index cbb0b30d7123..709ceb3fa27a 100644 ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -771,8 +771,6 @@ struct mt753x_info { - int (*cpu_port_config)(struct dsa_switch *ds, int port); - void (*get_phy_modes)(struct dsa_switch *ds, int port, - unsigned long *supported_interfaces); -- bool (*phy_mode_supported)(struct dsa_switch *ds, int port, -- const struct phylink_link_state *state); - void (*mac_port_validate)(struct dsa_switch *ds, int port, - unsigned long *supported); - int (*mac_port_get_state)(struct dsa_switch *ds, int port, --- -cgit v1.2.3 - - -From 21e7c6af6f105aab306d672a6f4f760c7a77772e Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 5 Nov 2021 12:24:27 +0000 -Subject: net: dsa: mt7530: drop use of phylink_helper_basex_speed() - -Now that we have a better method to select SFP interface modes, we -no longer need to use phylink_helper_basex_speed() in a driver's -validation function. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/dsa/mt7530.c | 5 ----- - 1 file changed, 5 deletions(-) - -diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c -index c49058c26f5c..5c4df8cfb834 100644 ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -2922,11 +2922,6 @@ mt753x_phylink_validate(struct dsa_switch *ds, int port, - - linkmode_and(supported, supported, mask); - linkmode_and(state->advertising, state->advertising, mask); -- -- /* We can only operate at 2500BaseX or 1000BaseX. If requested -- * to advertise both, only report advertising at 2500BaseX. -- */ -- phylink_helper_basex_speed(state); - } - - static int --- -cgit v1.2.3 - - -From 325999c718b55a5b7e0794315655e777f1fbfac7 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 5 Nov 2021 12:23:51 +0000 -Subject: net: dsa: mt7530: only indicate linkmodes that actually are supported - -Only indicate linkmodes that can be properly supported by the requested -phy interface mode. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/dsa/mt7530.c | 19 +++++++++++++------ - drivers/net/dsa/mt7530.h | 1 + - 2 files changed, 14 insertions(+), 6 deletions(-) - -diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c -index 5c4df8cfb834..f00d5d9d3e7a 100644 ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -2496,6 +2496,7 @@ static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port, - } - - static void mt7531_sgmii_validate(struct mt7530_priv *priv, int port, -+ phy_interface_t interface, - unsigned long *supported) - { - /* Port5 supports ethier RGMII or SGMII. -@@ -2507,9 +2508,12 @@ static void mt7531_sgmii_validate(struct mt7530_priv *priv, int port, - break; - fallthrough; - case 6: -- phylink_set(supported, 1000baseX_Full); -- phylink_set(supported, 2500baseX_Full); -- phylink_set(supported, 2500baseT_Full); -+ if (interface == PHY_INTERFACE_MODE_2500BASEX) { -+ phylink_set(supported, 2500baseX_Full); -+ phylink_set(supported, 2500baseT_Full); -+ } else { -+ phylink_set(supported, 1000baseX_Full); -+ } - } - } - -@@ -2878,6 +2882,7 @@ static void mt753x_phylink_get_interfaces(struct dsa_switch *ds, int port, - - static void - mt7530_mac_port_validate(struct dsa_switch *ds, int port, -+ phy_interface_t interface, - unsigned long *supported) - { - if (port == 5) -@@ -2885,11 +2890,12 @@ mt7530_mac_port_validate(struct dsa_switch *ds, int port, - } - - static void mt7531_mac_port_validate(struct dsa_switch *ds, int port, -+ phy_interface_t interface, - unsigned long *supported) - { - struct mt7530_priv *priv = ds->priv; - -- mt7531_sgmii_validate(priv, port, supported); -+ mt7531_sgmii_validate(priv, port, interface, supported); - } - - static void -@@ -2912,10 +2918,11 @@ mt753x_phylink_validate(struct dsa_switch *ds, int port, - } - - /* This switch only supports 1G full-duplex. */ -- if (state->interface != PHY_INTERFACE_MODE_MII) -+ if (state->interface != PHY_INTERFACE_MODE_MII && -+ state->interface != PHY_INTERFACE_MODE_2500BASEX) - phylink_set(mask, 1000baseT_Full); - -- priv->info->mac_port_validate(ds, port, mask); -+ priv->info->mac_port_validate(ds, port, state->interface, mask); - - phylink_set(mask, Pause); - phylink_set(mask, Asym_Pause); -diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h -index 709ceb3fa27a..d17dff42ca32 100644 ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -772,6 +772,7 @@ struct mt753x_info { - void (*get_phy_modes)(struct dsa_switch *ds, int port, - unsigned long *supported_interfaces); - void (*mac_port_validate)(struct dsa_switch *ds, int port, -+ phy_interface_t interface, - unsigned long *supported); - int (*mac_port_get_state)(struct dsa_switch *ds, int port, - struct phylink_link_state *state); --- -cgit v1.2.3 - - -From c9f1aa2bf809c91f8473dd228a5a6dc422edadcc Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 5 Nov 2021 12:58:05 +0000 -Subject: net: dsa: mt7530: RGMII can support 1000base-X - -Using an external PHY, RGMII can be used to support 1000base-X -connections, so it makes no sense to exclude this from the linkmodes -permitted for mt7531 port 5. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/dsa/mt7530.c | 3 --- - 1 file changed, 3 deletions(-) - -diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c -index f00d5d9d3e7a..940df2ee534d 100644 ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -2504,9 +2504,6 @@ static void mt7531_sgmii_validate(struct mt7530_priv *priv, int port, - */ - switch (port) { - case 5: -- if (mt7531_is_rgmii_port(priv, port)) -- break; -- fallthrough; - case 6: - if (interface == PHY_INTERFACE_MODE_2500BASEX) { - phylink_set(supported, 2500baseX_Full); --- -cgit v1.2.3 - - -From 2e13bef37abc335c61e26a86fd9be699672447d7 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Tue, 3 Mar 2020 11:57:39 +0000 -Subject: net: sfp: augment SFP parsing with phy_interface_t bitmap - -We currently parse the SFP EEPROM to a bitmap of ethtool link modes, -and then attempt to convert the link modes to a PHY interface mode. -While this works at present, there are cases where this is sub-optimal. -For example, where a module can operate with several different PHY -interface modes. - -To start addressing this, arrange for the SFP EEPROM parsing to also -provide a bitmap of the possible PHY interface modes. - -Signed-off-by: Russell King ---- - drivers/net/phy/marvell-88x2222.c | 3 +- - drivers/net/phy/marvell.c | 3 +- - drivers/net/phy/marvell10g.c | 3 +- - drivers/net/phy/phylink.c | 4 ++- - drivers/net/phy/sfp-bus.c | 76 +++++++++++++++++++++++++++++---------- - include/linux/sfp.h | 5 +-- - 6 files changed, 69 insertions(+), 25 deletions(-) - -diff --git a/drivers/net/phy/marvell-88x2222.c b/drivers/net/phy/marvell-88x2222.c -index d8b31d4d2a73..ae285e4225d6 100644 ---- a/drivers/net/phy/marvell-88x2222.c -+++ b/drivers/net/phy/marvell-88x2222.c -@@ -478,6 +478,7 @@ static int mv2222_config_init(struct phy_device *phydev) - - static int mv2222_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) - { -+ DECLARE_PHY_INTERFACE_MASK(interfaces); - struct phy_device *phydev = upstream; - phy_interface_t sfp_interface; - struct mv2222_data *priv; -@@ -489,7 +490,7 @@ static int mv2222_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) - priv = (struct mv2222_data *)phydev->priv; - dev = &phydev->mdio.dev; - -- sfp_parse_support(phydev->sfp_bus, id, sfp_supported); -+ sfp_parse_support(phydev->sfp_bus, id, sfp_supported, interfaces); - sfp_interface = sfp_select_interface(phydev->sfp_bus, sfp_supported); - - dev_info(dev, "%s SFP module inserted\n", phy_modes(sfp_interface)); -diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c -index 4fcfca4e1702..851f242a8078 100644 ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -2745,6 +2745,7 @@ static int marvell_probe(struct phy_device *phydev) - - static int m88e1510_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) - { -+ DECLARE_PHY_INTERFACE_MASK(interfaces); - struct phy_device *phydev = upstream; - phy_interface_t interface; - struct device *dev; -@@ -2756,7 +2757,7 @@ static int m88e1510_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) - - dev = &phydev->mdio.dev; - -- sfp_parse_support(phydev->sfp_bus, id, supported); -+ sfp_parse_support(phydev->sfp_bus, id, supported, interfaces); - interface = sfp_select_interface(phydev->sfp_bus, supported); - - dev_info(dev, "%s SFP module inserted\n", phy_modes(interface)); -diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c -index b6fea119fe13..6e7ec7738054 100644 ---- a/drivers/net/phy/marvell10g.c -+++ b/drivers/net/phy/marvell10g.c -@@ -466,9 +466,10 @@ static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) - { - struct phy_device *phydev = upstream; - __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, }; -+ DECLARE_PHY_INTERFACE_MASK(interfaces); - phy_interface_t iface; - -- sfp_parse_support(phydev->sfp_bus, id, support); -+ sfp_parse_support(phydev->sfp_bus, id, support, interfaces); - iface = sfp_select_interface(phydev->sfp_bus, support); - - if (iface != PHY_INTERFACE_MODE_10GBASER) { -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index 689bc4e4b7b7..51e166e43c92 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -77,6 +77,7 @@ struct phylink { - - struct sfp_bus *sfp_bus; - bool sfp_may_have_phy; -+ DECLARE_PHY_INTERFACE_MASK(sfp_interfaces); - __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); - u8 sfp_port; - }; -@@ -2313,7 +2314,8 @@ static int phylink_sfp_module_insert(void *upstream, - ASSERT_RTNL(); - - linkmode_zero(support); -- sfp_parse_support(pl->sfp_bus, id, support); -+ phy_interface_zero(pl->sfp_interfaces); -+ sfp_parse_support(pl->sfp_bus, id, support, pl->sfp_interfaces); - pl->sfp_port = sfp_parse_port(pl->sfp_bus, id, support); - - /* If this module may have a PHY connecting later, defer until later */ -diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c -index 0c6c0d1843bc..e056035a8a8c 100644 ---- a/drivers/net/phy/sfp-bus.c -+++ b/drivers/net/phy/sfp-bus.c -@@ -13,7 +13,8 @@ - struct sfp_quirk { - const char *vendor; - const char *part; -- void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes); -+ void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes, -+ unsigned long *interfaces); - }; - - /** -@@ -39,13 +40,15 @@ struct sfp_bus { - }; - - static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id, -- unsigned long *modes) -+ unsigned long *modes, unsigned long *interfaces) - { - phylink_set(modes, 2500baseX_Full); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, interfaces); - } - - static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id, -- unsigned long *modes) -+ unsigned long *modes, -+ unsigned long *interfaces) - { - /* Ubiquiti U-Fiber Instant module claims that support all transceiver - * types including 10G Ethernet which is not truth. So clear all claimed -@@ -226,12 +229,14 @@ EXPORT_SYMBOL_GPL(sfp_may_have_phy); - * @bus: a pointer to the &struct sfp_bus structure for the sfp module - * @id: a pointer to the module's &struct sfp_eeprom_id - * @support: pointer to an array of unsigned long for the ethtool support mask -+ * @interfaces: pointer to an array of unsigned long for phy interface modes -+ * mask - * - * Parse the EEPROM identification information and derive the supported - * ethtool link modes for the module. - */ - void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, -- unsigned long *support) -+ unsigned long *support, unsigned long *interfaces) - { - unsigned int br_min, br_nom, br_max; - __ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, }; -@@ -258,27 +263,41 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, - } - - /* Set ethtool support from the compliance fields. */ -- if (id->base.e10g_base_sr) -+ if (id->base.e10g_base_sr) { - phylink_set(modes, 10000baseSR_Full); -- if (id->base.e10g_base_lr) -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); -+ } -+ if (id->base.e10g_base_lr) { - phylink_set(modes, 10000baseLR_Full); -- if (id->base.e10g_base_lrm) -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); -+ } -+ if (id->base.e10g_base_lrm) { - phylink_set(modes, 10000baseLRM_Full); -- if (id->base.e10g_base_er) -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); -+ } -+ if (id->base.e10g_base_er) { - phylink_set(modes, 10000baseER_Full); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); -+ } - if (id->base.e1000_base_sx || - id->base.e1000_base_lx || -- id->base.e1000_base_cx) -+ id->base.e1000_base_cx) { - phylink_set(modes, 1000baseX_Full); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces); -+ } - if (id->base.e1000_base_t) { - phylink_set(modes, 1000baseT_Half); - phylink_set(modes, 1000baseT_Full); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces); -+ __set_bit(PHY_INTERFACE_MODE_SGMII, interfaces); - } - - /* 1000Base-PX or 1000Base-BX10 */ - if ((id->base.e_base_px || id->base.e_base_bx10) && -- br_min <= 1300 && br_max >= 1200) -+ br_min <= 1300 && br_max >= 1200) { - phylink_set(modes, 1000baseX_Full); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces); -+ } - - /* 100Base-FX, 100Base-LX, 100Base-PX, 100Base-BX10 */ - if (id->base.e100_base_fx || id->base.e100_base_lx) -@@ -291,21 +310,30 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, - */ - if ((id->base.sfp_ct_passive || id->base.sfp_ct_active) && br_nom) { - /* This may look odd, but some manufacturers use 12000MBd */ -- if (br_min <= 12000 && br_max >= 10300) -+ if (br_min <= 12000 && br_max >= 10300) { - phylink_set(modes, 10000baseCR_Full); -- if (br_min <= 3200 && br_max >= 3100) -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); -+ } -+ if (br_min <= 3200 && br_max >= 3100) { - phylink_set(modes, 2500baseX_Full); -- if (br_min <= 1300 && br_max >= 1200) -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, interfaces); -+ } -+ if (br_min <= 1300 && br_max >= 1200) { - phylink_set(modes, 1000baseX_Full); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces); -+ } - } - if (id->base.sfp_ct_passive) { -- if (id->base.passive.sff8431_app_e) -+ if (id->base.passive.sff8431_app_e) { - phylink_set(modes, 10000baseCR_Full); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); -+ } - } - if (id->base.sfp_ct_active) { - if (id->base.active.sff8431_app_e || - id->base.active.sff8431_lim) { - phylink_set(modes, 10000baseCR_Full); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); - } - } - -@@ -330,12 +358,14 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, - case SFF8024_ECC_10GBASE_T_SFI: - case SFF8024_ECC_10GBASE_T_SR: - phylink_set(modes, 10000baseT_Full); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); - break; - case SFF8024_ECC_5GBASE_T: - phylink_set(modes, 5000baseT_Full); - break; - case SFF8024_ECC_2_5GBASE_T: - phylink_set(modes, 2500baseT_Full); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, interfaces); - break; - default: - dev_warn(bus->sfp_dev, -@@ -348,10 +378,14 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, - if (id->base.fc_speed_100 || - id->base.fc_speed_200 || - id->base.fc_speed_400) { -- if (id->base.br_nominal >= 31) -+ if (id->base.br_nominal >= 31) { - phylink_set(modes, 2500baseX_Full); -- if (id->base.br_nominal >= 12) -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, interfaces); -+ } -+ if (id->base.br_nominal >= 12) { - phylink_set(modes, 1000baseX_Full); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces); -+ } - } - - /* If we haven't discovered any modes that this module supports, try -@@ -364,14 +398,18 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, - * 2500BASE-X, so we allow some slack here. - */ - if (bitmap_empty(modes, __ETHTOOL_LINK_MODE_MASK_NBITS) && br_nom) { -- if (br_min <= 1300 && br_max >= 1200) -+ if (br_min <= 1300 && br_max >= 1200) { - phylink_set(modes, 1000baseX_Full); -- if (br_min <= 3200 && br_max >= 2500) -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces); -+ } -+ if (br_min <= 3200 && br_max >= 2500) { - phylink_set(modes, 2500baseX_Full); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, interfaces); -+ } - } - - if (bus->sfp_quirk) -- bus->sfp_quirk->modes(id, modes); -+ bus->sfp_quirk->modes(id, modes, interfaces); - - linkmode_or(support, support, modes); - -diff --git a/include/linux/sfp.h b/include/linux/sfp.h -index 302094b855fb..d1f343853b6c 100644 ---- a/include/linux/sfp.h -+++ b/include/linux/sfp.h -@@ -535,7 +535,7 @@ int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id, - unsigned long *support); - bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id); - void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, -- unsigned long *support); -+ unsigned long *support, unsigned long *interfaces); - phy_interface_t sfp_select_interface(struct sfp_bus *bus, - unsigned long *link_modes); - -@@ -568,7 +568,8 @@ static inline bool sfp_may_have_phy(struct sfp_bus *bus, - - static inline void sfp_parse_support(struct sfp_bus *bus, - const struct sfp_eeprom_id *id, -- unsigned long *support) -+ unsigned long *support, -+ unsigned long *interfaces) - { - } - --- -cgit v1.2.3 - - -From 764700878da46f5222b0f130fed66b4fd49ce28b Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Tue, 3 Mar 2020 12:12:43 +0000 -Subject: net: phylink: use phy_interface_t bitmaps for optical modules - -Where a MAC provides a phy_interface_t bitmap, use these bitmaps to -select the operating interface mode for optical SFP modules, rather -than using the linkmode bitmaps. - -Signed-off-by: Russell King ---- - drivers/net/phy/phylink.c | 125 +++++++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 118 insertions(+), 7 deletions(-) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index 51e166e43c92..6e326b3acaa7 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -2221,6 +2221,41 @@ static void phylink_sfp_detach(void *upstream, struct sfp_bus *bus) - pl->netdev->sfp_bus = NULL; - } - -+static const phy_interface_t phylink_sfp_interface_preference[] = { -+ PHY_INTERFACE_MODE_USXGMII, -+ PHY_INTERFACE_MODE_10GBASER, -+ PHY_INTERFACE_MODE_10GKR, -+ PHY_INTERFACE_MODE_2500BASEX, -+ PHY_INTERFACE_MODE_SGMII, -+ PHY_INTERFACE_MODE_1000BASEX, -+}; -+ -+static phy_interface_t phylink_select_interface(struct phylink *pl, -+ const unsigned long *intf, -+ const char *intf_name) -+{ -+ DECLARE_PHY_INTERFACE_MASK(u); -+ phy_interface_t interface; -+ size_t i; -+ -+ phy_interface_and(u, intf, pl->config->supported_interfaces); -+ -+ interface = PHY_INTERFACE_MODE_NA; -+ for (i = 0; i < ARRAY_SIZE(phylink_sfp_interface_preference); i++) -+ if (test_bit(phylink_sfp_interface_preference[i], u)) { -+ interface = phylink_sfp_interface_preference[i]; -+ break; -+ } -+ -+ phylink_dbg(pl, "interfaces=[mac=%*pbl %s=%*pbl] selected %d (%s)\n", -+ (int)PHY_INTERFACE_MODE_MAX, -+ pl->config->supported_interfaces, -+ intf_name, (int)PHY_INTERFACE_MODE_MAX, intf, -+ interface, phy_modes(interface)); -+ -+ return interface; -+} -+ - static int phylink_sfp_config(struct phylink *pl, u8 mode, - const unsigned long *supported, - const unsigned long *advertising) -@@ -2305,25 +2340,102 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode, - return ret; - } - -+static int phylink_sfp_config_nophy(struct phylink *pl) -+{ -+ __ETHTOOL_DECLARE_LINK_MODE_MASK(support); -+ struct phylink_link_state config; -+ phy_interface_t interface; -+ bool changed; -+ int ret; -+ -+ if (phy_interface_empty(pl->config->supported_interfaces)) -+ return phylink_sfp_config(pl, MLO_AN_INBAND, -+ pl->sfp_support, pl->sfp_support); -+ -+ memset(&config, 0, sizeof(config)); -+ linkmode_copy(config.advertising, pl->sfp_support); -+ config.interface = PHY_INTERFACE_MODE_NA; -+ config.speed = SPEED_UNKNOWN; -+ config.duplex = DUPLEX_UNKNOWN; -+ config.pause = MLO_PAUSE_AN; -+ config.an_enabled = true; -+ -+ /* Get the full range of supported link modes */ -+ ret = phylink_validate(pl, pl->sfp_support, &config); -+ if (ret) { -+ phylink_err(pl, -+ "initial validation with support %*pb failed: %d\n", -+ __ETHTOOL_LINK_MODE_MASK_NBITS, support, ret); -+ return ret; -+ } -+ -+ interface = phylink_select_interface(pl, pl->sfp_interfaces, "sfp"); -+ if (interface == PHY_INTERFACE_MODE_NA) -+ return -EINVAL; -+ -+ linkmode_copy(support, pl->sfp_support); -+ config.interface = interface; -+ -+ /* Ignore errors if we're expecting a PHY to attach later */ -+ ret = phylink_validate(pl, support, &config); -+ if (ret) { -+ phylink_err(pl, "validation with support %*pb failed: %d\n", -+ __ETHTOOL_LINK_MODE_MASK_NBITS, support, ret); -+ return ret; -+ } -+ -+ phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n", -+ phylink_an_mode_str(MLO_AN_INBAND), -+ phy_modes(config.interface), -+ __ETHTOOL_LINK_MODE_MASK_NBITS, pl->sfp_support); -+ -+ changed = !linkmode_equal(pl->supported, pl->sfp_support) || -+ !linkmode_equal(pl->link_config.advertising, -+ config.advertising); -+ if (changed) { -+ linkmode_copy(pl->supported, pl->sfp_support); -+ linkmode_copy(pl->link_config.advertising, config.advertising); -+ } -+ -+ if (pl->cur_link_an_mode != MLO_AN_INBAND || -+ pl->link_config.interface != config.interface) { -+ pl->link_config.interface = config.interface; -+ pl->cur_link_an_mode = MLO_AN_INBAND; -+ -+ changed = true; -+ -+ phylink_info(pl, "switched to %s/%s link mode\n", -+ phylink_an_mode_str(MLO_AN_INBAND), -+ phy_modes(config.interface)); -+ } -+ -+ pl->link_port = pl->sfp_port; -+ -+ if (changed && !test_bit(PHYLINK_DISABLE_STOPPED, -+ &pl->phylink_disable_state)) -+ phylink_mac_initial_config(pl, false); -+ -+ return 0; -+} -+ - static int phylink_sfp_module_insert(void *upstream, - const struct sfp_eeprom_id *id) - { - struct phylink *pl = upstream; -- unsigned long *support = pl->sfp_support; - - ASSERT_RTNL(); - -- linkmode_zero(support); -+ linkmode_zero(pl->sfp_support); - phy_interface_zero(pl->sfp_interfaces); -- sfp_parse_support(pl->sfp_bus, id, support, pl->sfp_interfaces); -- pl->sfp_port = sfp_parse_port(pl->sfp_bus, id, support); -+ sfp_parse_support(pl->sfp_bus, id, pl->sfp_support, pl->sfp_interfaces); -+ pl->sfp_port = sfp_parse_port(pl->sfp_bus, id, pl->sfp_support); - - /* If this module may have a PHY connecting later, defer until later */ - pl->sfp_may_have_phy = sfp_may_have_phy(pl->sfp_bus, id); - if (pl->sfp_may_have_phy) - return 0; - -- return phylink_sfp_config(pl, MLO_AN_INBAND, support, support); -+ return phylink_sfp_config_nophy(pl); - } - - static int phylink_sfp_module_start(void *upstream) -@@ -2342,8 +2454,7 @@ static int phylink_sfp_module_start(void *upstream) - if (!pl->sfp_may_have_phy) - return 0; - -- return phylink_sfp_config(pl, MLO_AN_INBAND, -- pl->sfp_support, pl->sfp_support); -+ return phylink_sfp_config_nophy(pl); - } - - static void phylink_sfp_module_stop(void *upstream) --- -cgit v1.2.3 - - -From 9fcfd601a3585c297ade179aa982c2de24b0c017 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Fri, 13 Mar 2020 10:48:32 +0000 -Subject: net: mtk_eth_soc: use resolved link config for PCS PHY - -The SGMII PCS PHY needs to be updated with the link configuration in -the mac_link_up() call rather than in mac_config(). However, -mtk_sgmii_setup_mode_force() programs the SGMII block during -mac_config() when using 802.3z interface modes with the link -configuration. - -Split that functionality from mtk_sgmii_setup_mode_force(), moving it -to a new mtk_sgmii_link_up() function, and call it from mac_link_up(). - -This does not look correct to me: 802.3z modes operate at a fixed -speed. The contents of mtk_sgmii_link_up() look more appropriate for -SGMII mode, but the original code definitely did not call -mtk_sgmii_setup_mode_force() for SGMII mode but only 802.3z mode. - -Signed-off-by: Russell King ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 11 ++++++++- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 ++- - drivers/net/ethernet/mediatek/mtk_sgmii.c | 37 ++++++++++++++++++++--------- - 3 files changed, 38 insertions(+), 13 deletions(-) - -diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -index 2f89bfae2445..55b9fffeddc3 100644 ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -337,7 +337,7 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode, - /* Setup SGMIISYS with the determined property */ - if (state->interface != PHY_INTERFACE_MODE_SGMII) - err = mtk_sgmii_setup_mode_force(eth->sgmii, sid, -- state); -+ state->interface); - else if (phylink_autoneg_inband(mode)) - err = mtk_sgmii_setup_mode_an(eth->sgmii, sid); - -@@ -434,6 +434,15 @@ static void mtk_mac_link_up(struct phylink_config *config, - phylink_config); - u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); - -+ if (phy_interface_mode_is_8023z(interface)) { -+ struct mtk_eth *eth = mac->hw; -+ -+ /* Decide how GMAC and SGMIISYS be mapped */ -+ int sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? -+ 0 : mac->id; -+ mtk_sgmii_link_up(eth->sgmii, sid, speed, duplex); -+ } -+ - mcr &= ~(MAC_MCR_SPEED_100 | MAC_MCR_SPEED_1000 | - MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_TX_FC | - MAC_MCR_FORCE_RX_FC); -diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -index 5ef70dd8b49c..c4771c29312a 100644 ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -1004,7 +1004,8 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np, - u32 ana_rgc3); - int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id); - int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id, -- const struct phylink_link_state *state); -+ phy_interface_t interface); -+void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex); - void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id); - - int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id); -diff --git a/drivers/net/ethernet/mediatek/mtk_sgmii.c b/drivers/net/ethernet/mediatek/mtk_sgmii.c -index 32d83421226a..372c85c830b5 100644 ---- a/drivers/net/ethernet/mediatek/mtk_sgmii.c -+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c -@@ -60,7 +60,7 @@ int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id) - } - - int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id, -- const struct phylink_link_state *state) -+ phy_interface_t interface) - { - unsigned int val; - -@@ -69,7 +69,7 @@ int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id, - - regmap_read(ss->regmap[id], ss->ana_rgc3, &val); - val &= ~RG_PHY_SPEED_MASK; -- if (state->interface == PHY_INTERFACE_MODE_2500BASEX) -+ if (interface == PHY_INTERFACE_MODE_2500BASEX) - val |= RG_PHY_SPEED_3_125G; - regmap_write(ss->regmap[id], ss->ana_rgc3, val); - -@@ -78,11 +78,33 @@ int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id, - val &= ~SGMII_AN_ENABLE; - regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val); - -+ if (interface == PHY_INTERFACE_MODE_1000BASEX || -+ interface == PHY_INTERFACE_MODE_2500BASEX) { -+ /* SGMII force mode setting */ -+ regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val); -+ val &= ~SGMII_IF_MODE_MASK; -+ val |= SGMII_SPEED_1000; -+ val |= SGMII_DUPLEX_FULL; -+ regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val); -+ } -+ -+ /* Release PHYA power down state */ -+ regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val); -+ val &= ~SGMII_PHYA_PWD; -+ regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val); -+ -+ return 0; -+} -+ -+void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex) -+{ -+ unsigned int val; -+ - /* SGMII force mode setting */ - regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val); - val &= ~SGMII_IF_MODE_MASK; - -- switch (state->speed) { -+ switch (speed) { - case SPEED_10: - val |= SGMII_SPEED_10; - break; -@@ -95,17 +117,10 @@ int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id, - break; - } - -- if (state->duplex == DUPLEX_FULL) -+ if (duplex == DUPLEX_FULL) - val |= SGMII_DUPLEX_FULL; - - regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val); -- -- /* Release PHYA power down state */ -- regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val); -- val &= ~SGMII_PHYA_PWD; -- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val); -- -- return 0; - } - - void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id) --- -cgit v1.2.3 - - -From 3e0cc699ff9e38d1a3a2874ae95ac54f76877fe5 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Fri, 29 Nov 2019 00:31:03 +0000 -Subject: net: phy: add helpers for comparing phy IDs - -There are several places which open code comparing PHY IDs. Provide a -couple of helpers to assist with this, using a slightly simpler test -than the original: - -- phy_id_compare() compares two arbitary PHY IDs and a mask of the - significant bits in the ID. -- phydev_id_compare() compares the bound phydev with the specified - PHY ID, using the bound driver's mask. - -Signed-off-by: Russell King ---- - drivers/net/phy/phy_device.c | 16 +++++++--------- - drivers/net/phy/phylink.c | 4 ++-- - include/linux/phy.h | 28 ++++++++++++++++++++++++++++ - 3 files changed, 37 insertions(+), 11 deletions(-) - -diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c -index 74d8e1dc125f..6a18b74ab373 100644 ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -388,8 +388,7 @@ int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask) - fixup = list_entry(pos, struct phy_fixup, list); - - if ((!strcmp(fixup->bus_id, bus_id)) && -- ((fixup->phy_uid & phy_uid_mask) == -- (phy_uid & phy_uid_mask))) { -+ phy_id_compare(fixup->phy_uid, phy_uid, phy_uid_mask)) { - list_del(&fixup->list); - kfree(fixup); - ret = 0; -@@ -425,8 +424,8 @@ static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup) - if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0) - return 0; - -- if ((fixup->phy_uid & fixup->phy_uid_mask) != -- (phydev->phy_id & fixup->phy_uid_mask)) -+ if (!phy_id_compare(phydev->phy_id, fixup->phy_uid, -+ fixup->phy_uid_mask)) - if (fixup->phy_uid != PHY_ANY_UID) - return 0; - -@@ -473,15 +472,14 @@ static int phy_bus_match(struct device *dev, struct device_driver *drv) - if (phydev->c45_ids.device_ids[i] == 0xffffffff) - continue; - -- if ((phydrv->phy_id & phydrv->phy_id_mask) == -- (phydev->c45_ids.device_ids[i] & -- phydrv->phy_id_mask)) -+ if (phy_id_compare(phydev->c45_ids.device_ids[i], -+ phydrv->phy_id, phydrv->phy_id_mask)) - return 1; - } - return 0; - } else { -- return (phydrv->phy_id & phydrv->phy_id_mask) == -- (phydev->phy_id & phydrv->phy_id_mask); -+ return phy_id_compare(phydev->phy_id, phydrv->phy_id, -+ phydrv->phy_id_mask); - } - } - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index 6e326b3acaa7..0b69dce407b8 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -2490,8 +2490,8 @@ static void phylink_sfp_link_up(void *upstream) - */ - static bool phylink_phy_no_inband(struct phy_device *phy) - { -- return phy->is_c45 && -- (phy->c45_ids.device_ids[1] & 0xfffffff0) == 0xae025150; -+ return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1], -+ 0xae025150, 0xfffffff0); - } - - static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) -diff --git a/include/linux/phy.h b/include/linux/phy.h -index 1b47eca539f3..dfe784d21e20 100644 ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -942,6 +942,34 @@ struct phy_driver { - #define PHY_ID_MATCH_MODEL(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 4) - #define PHY_ID_MATCH_VENDOR(id) .phy_id = (id), .phy_id_mask = GENMASK(31, 10) - -+/** -+ * phy_id_compare - compare @id1 with @id2 taking account of @mask -+ * @id1: first PHY ID -+ * @id2: second PHY ID -+ * @mask: the PHY ID mask, set bits are significant in matching -+ * -+ * Return true if the bits from @id1 and @id2 specified by @mask match. -+ * This uses an equivalent test to (@id & @mask) == (@phy_id & @mask). -+ */ -+static inline bool phy_id_compare(u32 id1, u32 id2, u32 mask) -+{ -+ return !((id1 ^ id2) & mask); -+} -+ -+/** -+ * phydev_id_compare - compare @id with the PHY's Clause 22 ID -+ * @phydev: the PHY device -+ * @id: the PHY ID to be matched -+ * -+ * Compare the @phydev clause 22 ID with the provided @id and return true or -+ * false depending whether it matches, using the bound driver mask. The -+ * @phydev must be bound to a driver. -+ */ -+static inline bool phydev_id_compare(struct phy_device *phydev, u32 id) -+{ -+ return phy_id_compare(id, phydev->phy_id, phydev->drv->phy_id_mask); -+} -+ - /* A Structure for boards to register fixups with the PHY Lib */ - struct phy_fixup { - struct list_head list; --- -cgit v1.2.3 - - -From d70f5a9006f24dba3b832f763f0ac25235935af5 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Tue, 17 Dec 2019 15:21:50 +0000 -Subject: dt-bindings: net: add dt bindings for marvell10g driver - -Add a DT bindings document for the Marvell 10G driver, which will -augment the generic ethernet PHY binding by having LED mode -configuration. - -Signed-off-by: Russell King ---- - .../devicetree/bindings/net/marvell,10g.yaml | 35 ++++++++++++++++++++++ - 1 file changed, 35 insertions(+) - create mode 100644 Documentation/devicetree/bindings/net/marvell,10g.yaml - -diff --git a/Documentation/devicetree/bindings/net/marvell,10g.yaml b/Documentation/devicetree/bindings/net/marvell,10g.yaml -new file mode 100644 -index 000000000000..93d2c8d7e759 ---- /dev/null -+++ b/Documentation/devicetree/bindings/net/marvell,10g.yaml -@@ -0,0 +1,35 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/net/marvell,10g.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Marvell Alaska X family Ethernet PHYs -+ -+maintainers: -+ - Russell King -+ -+allOf: -+ - $ref: ethernet-phy.yaml# -+ -+properties: -+ marvell,led-mode: -+ description: | -+ An array of one to four 16-bit integers to write to the PHY LED -+ configuration registers. -+ allOf: -+ - $ref: /schemas/types.yaml#/definitions/uint16-array -+ - minItems: 1 -+ maxItems: 4 -+ -+examples: -+ - | -+ mdio { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ ethernet-phy@0 { -+ reg = <0>; -+ compatible = "ethernet-phy-ieee802.3-c45"; -+ marvell,led-mode = /bits/ 16 <0x0129 0x095d 0x0855>; -+ }; -+ }; --- -cgit v1.2.3 - - -From c497a37330d796852c9a22f3b11d2d6a0960964a Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Sun, 1 Dec 2019 15:33:39 +0000 -Subject: net: phy: marvell10g: add support for configuring LEDs - -Add support for configuring the LEDs. Macchiatobin has an oddity in -that the left LED goes out when the cable is connected, and flashes -when there's link activity. This is because the reset default for -the LED outputs assume that the LED is connected to supply, not to -ground. Add support for configuring the LED modes and polarities. - -Signed-off-by: Russell King ---- - drivers/net/phy/marvell10g.c | 62 +++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 55 insertions(+), 7 deletions(-) - -diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c -index 6e7ec7738054..43b7e3685c4a 100644 ---- a/drivers/net/phy/marvell10g.c -+++ b/drivers/net/phy/marvell10g.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -157,6 +158,8 @@ struct mv3310_priv { - - struct device *hwmon_dev; - char *hwmon_name; -+ u8 num_leds; -+ u16 led_mode[4]; - }; - - static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev) -@@ -485,6 +488,43 @@ static const struct sfp_upstream_ops mv3310_sfp_ops = { - .module_insert = mv3310_sfp_insert, - }; - -+static int mv3310_leds_write(struct phy_device *phydev) -+{ -+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); -+ int i, ret; -+ -+ for (i = 0; i < priv->num_leds; i++) { -+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, 0xf020 + i, -+ priv->led_mode[i]); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int mv3310_fw_config(struct phy_device *phydev) -+{ -+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); -+ struct device_node *node; -+ int ret; -+ -+ node = phydev->mdio.dev.of_node; -+ if (!node) -+ return 0; -+ -+ ret = of_property_read_variable_u16_array(node, "marvell,led-mode", -+ priv->led_mode, 1, ARRAY_SIZE(priv->led_mode)); -+ if (ret == -EINVAL) -+ ret = 0; -+ if (ret < 0) -+ return ret; -+ -+ priv->num_leds = ret; -+ -+ return 0; -+} -+ - static int mv3310_probe(struct phy_device *phydev) - { - const struct mv3310_chip *chip = to_mv3310_chip(phydev); -@@ -496,6 +536,20 @@ static int mv3310_probe(struct phy_device *phydev) - (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask) - return -ENODEV; - -+ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ dev_set_drvdata(&phydev->mdio.dev, priv); -+ -+ ret = mv3310_fw_config(phydev); -+ if (ret < 0) -+ return ret; -+ -+ ret = mv3310_leds_write(phydev); -+ if (ret < 0) -+ return ret; -+ - ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT); - if (ret < 0) - return ret; -@@ -506,12 +560,6 @@ static int mv3310_probe(struct phy_device *phydev) - return -ENODEV; - } - -- priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); -- if (!priv) -- return -ENOMEM; -- -- dev_set_drvdata(&phydev->mdio.dev, priv); -- - ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER0); - if (ret < 0) - return ret; -@@ -708,7 +756,7 @@ static int mv3310_config_init(struct phy_device *phydev) - if (err && err != -EOPNOTSUPP) - return err; - -- return 0; -+ return mv3310_leds_write(phydev); - } - - static int mv3310_get_features(struct phy_device *phydev) --- -cgit v1.2.3 - - -From d3babe36d416eb931310c0e562d2237b31cf158b Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Sun, 1 Dec 2019 15:35:08 +0000 -Subject: arm64: dts: configure Macchiatobin 10G PHY LED modes - -Configure the Macchiatobin 10G PHY LED modes to correct their polarity. -We keep the existing LED behaviours, but switch their polarity to -reflect how they are connected. Tweak the LED modes as well to be: - -left: off = no link - solid green = RJ45 link up (not SFP+ cage) - flash green = traffic -right: off = no link - solid green = 10G - solid yellow = 1G - flash green = 100M - flash yellow = 10M - -Signed-off-by: Russell King ---- - arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts -index 1766cf58101b..68c27f22ff57 100644 ---- a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts -+++ b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts -@@ -21,12 +21,14 @@ - compatible = "ethernet-phy-ieee802.3-c45"; - reg = <0>; - sfp = <&sfp_eth0>; -+ marvell,led-mode = /bits/ 16 <0x0129 0x095d 0x0855>; - }; - - phy8: ethernet-phy@8 { - compatible = "ethernet-phy-ieee802.3-c45"; - reg = <8>; - sfp = <&sfp_eth1>; -+ marvell,led-mode = /bits/ 16 <0x0129 0x095d 0x0855>; - }; - }; - --- -cgit v1.2.3 - - -From b27f90a99234618bc48b16692dc9d629d7437f9a Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Fri, 3 Jan 2020 23:13:28 +0000 -Subject: net: phy: add resolved pause support - -Allow phylib drivers to pass the hardware-resolved pause state to MAC -drivers, rather than using the software-based pause resolution code. - -Signed-off-by: Russell King ---- - drivers/net/phy/phy_device.c | 6 ++++++ - include/linux/phy.h | 9 +++++++++ - 2 files changed, 15 insertions(+) - -diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c -index 6a18b74ab373..23667658b9c6 100644 ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -2798,6 +2798,12 @@ void phy_get_pause(struct phy_device *phydev, bool *tx_pause, bool *rx_pause) - return; - } - -+ if (phydev->resolved_pause_valid) { -+ *tx_pause = phydev->resolved_tx_pause; -+ *rx_pause = phydev->resolved_rx_pause; -+ return; -+ } -+ - return linkmode_resolve_pause(phydev->advertising, - phydev->lp_advertising, - tx_pause, rx_pause); -diff --git a/include/linux/phy.h b/include/linux/phy.h -index dfe784d21e20..acc9ab1a89a9 100644 ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -644,6 +644,15 @@ struct phy_device { - u8 master_slave_set; - u8 master_slave_state; - -+ /* -+ * private to phylib: the resolved pause state - only valid if -+ * resolved_pause_valid is true. only phy drivers and phylib -+ * should touch this. -+ */ -+ bool resolved_pause_valid; -+ bool resolved_tx_pause; -+ bool resolved_rx_pause; -+ - /* Union of PHY and Attached devices' supported link modes */ - /* See ethtool.h for more info */ - __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); --- -cgit v1.2.3 - - -From 996934757bf22f1c13bb66f7cb6e84bcbd4b0b88 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Sat, 4 Jan 2020 00:41:35 +0000 -Subject: net: phy: marvell*: add support for hw resolved pause modes - -Support reporting the hardware resolved pause enablement states via -phylib, overriding our software implementation. - -Signed-off-by: Russell King ---- - drivers/net/phy/marvell.c | 40 ++++++++++++++++++++++++++++++++++------ - drivers/net/phy/marvell10g.c | 6 ++++++ - 2 files changed, 40 insertions(+), 6 deletions(-) - -diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c -index 851f242a8078..5a77b1a4396b 100644 ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -172,6 +172,10 @@ - #define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000 - #define MII_M1011_PHY_STATUS_RESOLVED 0x0800 - #define MII_M1011_PHY_STATUS_LINK 0x0400 -+#define MII_M1111_PHY_STATUS_TX_PAUSE 0x0008 -+#define MII_M1111_PHY_STATUS_RX_PAUSE 0x0004 -+#define MII_88E151X_PHY_STATUS_TX_PAUSE 0x0200 -+#define MII_88E151X_PHY_STATUS_RX_PAUSE 0x0100 - - #define MII_88E3016_PHY_SPEC_CTRL 0x10 - #define MII_88E3016_DISABLE_SCRAMBLER 0x0200 -@@ -304,6 +308,8 @@ struct marvell_priv { - u32 last; - u32 step; - s8 pair; -+ u16 tx_pause_mask; -+ u16 rx_pause_mask; - }; - - static int marvell_read_page(struct phy_device *phydev) -@@ -1519,6 +1525,7 @@ static void fiber_lpa_mod_linkmode_lpa_t(unsigned long *advertising, u32 lpa) - static int marvell_read_status_page_an(struct phy_device *phydev, - int fiber, int status) - { -+ struct marvell_priv *priv = phydev->priv; - int lpa; - int err; - -@@ -1574,6 +1581,11 @@ static int marvell_read_status_page_an(struct phy_device *phydev, - } - } - -+ phydev->resolved_tx_pause = !!(status & priv->tx_pause_mask); -+ phydev->resolved_rx_pause = !!(status & priv->rx_pause_mask); -+ phydev->resolved_pause_valid = !fiber && priv->tx_pause_mask && -+ priv->rx_pause_mask; -+ - return 0; - } - -@@ -1617,6 +1629,7 @@ static int marvell_read_status_page(struct phy_device *phydev, int page) - phydev->speed = SPEED_UNKNOWN; - phydev->duplex = DUPLEX_UNKNOWN; - phydev->port = fiber ? PORT_FIBRE : PORT_TP; -+ phydev->resolved_pause_valid = false; - - if (phydev->autoneg == AUTONEG_ENABLE) - err = marvell_read_status_page_an(phydev, fiber, status); -@@ -2730,7 +2743,8 @@ static int marvell_hwmon_probe(struct phy_device *phydev) - } - #endif - --static int marvell_probe(struct phy_device *phydev) -+static int marvell_probe_pause(struct phy_device *phydev, u16 tx_pause_mask, -+ u16 rx_pause_mask) - { - struct marvell_priv *priv; - -@@ -2738,6 +2752,8 @@ static int marvell_probe(struct phy_device *phydev) - if (!priv) - return -ENOMEM; - -+ priv->tx_pause_mask = tx_pause_mask; -+ priv->rx_pause_mask = rx_pause_mask; - phydev->priv = priv; - - return marvell_hwmon_probe(phydev); -@@ -2827,11 +2843,23 @@ static const struct sfp_upstream_ops m88e1510_sfp_ops = { - .detach = phy_sfp_detach, - }; - -+static int marvell_probe(struct phy_device *phydev) -+{ -+ return marvell_probe_pause(phydev, 0, 0); -+} -+ -+static int m88e1111_probe(struct phy_device *phydev) -+{ -+ return marvell_probe_pause(phydev, MII_M1111_PHY_STATUS_TX_PAUSE, -+ MII_M1111_PHY_STATUS_RX_PAUSE); -+} -+ - static int m88e1510_probe(struct phy_device *phydev) - { - int err; - -- err = marvell_probe(phydev); -+ err = marvell_probe_pause(phydev, MII_88E151X_PHY_STATUS_TX_PAUSE, -+ MII_88E151X_PHY_STATUS_RX_PAUSE); - if (err) - return err; - -@@ -2882,7 +2910,7 @@ static struct phy_driver marvell_drivers[] = { - .phy_id_mask = MARVELL_PHY_ID_MASK, - .name = "Marvell 88E1111", - /* PHY_GBIT_FEATURES */ -- .probe = marvell_probe, -+ .probe = m88e1111_probe, - .config_init = m88e1111gbe_config_init, - .config_aneg = m88e1111_config_aneg, - .read_status = marvell_read_status, -@@ -3093,7 +3121,7 @@ static struct phy_driver marvell_drivers[] = { - .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), - /* PHY_GBIT_FEATURES */ - .flags = PHY_POLL_CABLE_TEST, -- .probe = marvell_probe, -+ .probe = m88e1510_probe, - .config_init = marvell_1011gbe_config_init, - .config_aneg = m88e1510_config_aneg, - .read_status = marvell_read_status, -@@ -3117,7 +3145,7 @@ static struct phy_driver marvell_drivers[] = { - .phy_id_mask = MARVELL_PHY_ID_MASK, - .name = "Marvell 88E1545", - .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), -- .probe = marvell_probe, -+ .probe = m88e1510_probe, - /* PHY_GBIT_FEATURES */ - .flags = PHY_POLL_CABLE_TEST, - .config_init = marvell_1011gbe_config_init, -@@ -3164,7 +3192,7 @@ static struct phy_driver marvell_drivers[] = { - .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), - /* PHY_GBIT_FEATURES */ - .flags = PHY_POLL_CABLE_TEST, -- .probe = marvell_probe, -+ .probe = m88e1510_probe, - .config_init = marvell_1011gbe_config_init, - .config_aneg = m88e6390_config_aneg, - .read_status = marvell_read_status, -diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c -index 43b7e3685c4a..ddb7dac0c3a0 100644 ---- a/drivers/net/phy/marvell10g.c -+++ b/drivers/net/phy/marvell10g.c -@@ -83,6 +83,8 @@ enum { - MV_PCS_CSSR1_SPD1_10 = 0x0000, - MV_PCS_CSSR1_DUPLEX_FULL= BIT(13), - MV_PCS_CSSR1_RESOLVED = BIT(11), -+ MV_PCS_CSSR1_TX_PAUSE = BIT(9), -+ MV_PCS_CSSR1_RX_PAUSE = BIT(8), - MV_PCS_CSSR1_MDIX = BIT(6), - MV_PCS_CSSR1_SPD2_MASK = 0x000c, - MV_PCS_CSSR1_SPD2_5000 = 0x0008, -@@ -974,6 +976,10 @@ static int mv3310_read_status_copper(struct phy_device *phydev) - phydev->mdix = cssr1 & MV_PCS_CSSR1_MDIX ? - ETH_TP_MDI_X : ETH_TP_MDI; - -+ phydev->resolved_tx_pause = !!(cssr1 & MV_PCS_CSSR1_TX_PAUSE); -+ phydev->resolved_rx_pause = !!(cssr1 & MV_PCS_CSSR1_RX_PAUSE); -+ phydev->resolved_pause_valid = true; -+ - if (val & MDIO_AN_STAT1_COMPLETE) { - val = genphy_c45_read_lpa(phydev); - if (val < 0) --- -cgit v1.2.3 - - -From a86fa121cece905e2e947d5a54b3a421a425b95a Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 26 Aug 2019 12:19:35 +0100 -Subject: net: phy: provide phy driver start/stop hooks - -Provide phy driver start/stop hooks so that the PHY driver knows when -the network driver is starting or stopping. This will be used for the -Marvell 10G driver so that we can sanely refuse to start if the PHYs -firmware is not present, and also so that we can sanely support SFPs -behind the PHY. - -Signed-off-by: Russell King ---- - drivers/net/phy/phy.c | 5 +++++ - include/linux/phy.h | 3 +++ - 2 files changed, 8 insertions(+) - -diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c -index a3bfb156c83d..9ce6a3557bff 100644 ---- a/drivers/net/phy/phy.c -+++ b/drivers/net/phy/phy.c -@@ -1046,6 +1046,8 @@ void phy_stop(struct phy_device *phydev) - sfp_upstream_stop(phydev->sfp_bus); - - phydev->state = PHY_HALTED; -+ if (phydev->drv->stop) -+ phydev->drv->stop(phydev); - - mutex_unlock(&phydev->lock); - -@@ -1079,6 +1081,9 @@ void phy_start(struct phy_device *phydev) - goto out; - } - -+ if (phydev->drv->start && phydev->drv->start(phydev)) -+ goto out; -+ - if (phydev->sfp_bus) - sfp_upstream_start(phydev->sfp_bus); - -diff --git a/include/linux/phy.h b/include/linux/phy.h -index acc9ab1a89a9..94903467a7df 100644 ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -802,6 +802,9 @@ struct phy_driver { - /** @resume: Resume the hardware, restoring state if needed */ - int (*resume)(struct phy_device *phydev); - -+ int (*start)(struct phy_device *phydev); -+ void (*stop)(struct phy_device *phydev); -+ - /** - * @config_aneg: Configures the advertisement and resets - * autonegotiation if phydev->autoneg is on, --- -cgit v1.2.3 - - -From da8e979f2571803936d220b71f0226b4362514a6 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Wed, 5 Jun 2019 11:44:55 +0100 -Subject: net: phy: marvell10g: allow PHY to probe without firmware - -Allow the PHY to probe when there is no firmware, but do not allow the -link to come up by forcing the PHY state to PHY_HALTED in a similar way -to phy_error(). - -Signed-off-by: Russell King ---- - drivers/net/phy/marvell10g.c | 18 +++++++++++++++++- - 1 file changed, 17 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c -index ddb7dac0c3a0..b9d23fc5d10a 100644 ---- a/drivers/net/phy/marvell10g.c -+++ b/drivers/net/phy/marvell10g.c -@@ -157,6 +157,7 @@ struct mv3310_priv { - bool has_downshift; - bool rate_match; - phy_interface_t const_interface; -+ bool firmware_failed; - - struct device *hwmon_dev; - char *hwmon_name; -@@ -559,7 +560,7 @@ static int mv3310_probe(struct phy_device *phydev) - if (ret & MV_PMA_BOOT_FATAL) { - dev_warn(&phydev->mdio.dev, - "PHY failed to boot firmware, status=%04x\n", ret); -- return -ENODEV; -+ priv->firmware_failed = true; - } - - ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER0); -@@ -616,6 +617,19 @@ static int mv3310_resume(struct phy_device *phydev) - return mv3310_hwmon_config(phydev, true); - } - -+static int mv3310_start(struct phy_device *phydev) -+{ -+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); -+ -+ if (priv->firmware_failed) { -+ dev_warn(&phydev->mdio.dev, -+ "PHY firmware failure: PHY not starting"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ - /* Some PHYs in the Alaska family such as the 88X3310 and the 88E2010 - * don't set bit 14 in PMA Extended Abilities (1.11), although they do - * support 2.5GBASET and 5GBASET. For these models, we can still read their -@@ -1306,6 +1320,7 @@ static struct phy_driver mv3310_drivers[] = { - .probe = mv3310_probe, - .suspend = mv3310_suspend, - .resume = mv3310_resume, -+ .start = mv3310_start, - .config_aneg = mv3310_config_aneg, - .aneg_done = mv3310_aneg_done, - .read_status = mv3310_read_status, -@@ -1343,6 +1358,7 @@ static struct phy_driver mv3310_drivers[] = { - .probe = mv3310_probe, - .suspend = mv3310_suspend, - .resume = mv3310_resume, -+ .start = mv3310_start, - .config_init = mv3310_config_init, - .config_aneg = mv3310_config_aneg, - .aneg_done = mv3310_aneg_done, --- -cgit v1.2.3 - - -From 301f01699b0165c6ee064d356136e1b6d4a6e160 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Tue, 5 Nov 2019 10:34:39 +0000 -Subject: net: phy: make phy_error() report which PHY has failed - -phy_error() is called from phy_interrupt() or phy_state_machine(), and -uses WARN_ON() to print a backtrace. The backtrace is not useful when -reporting a PHY error. - -However, a system may contain multiple ethernet PHYs, and phy_error() -gives no clue which one caused the problem. - -Replace WARN_ON() with a call to phydev_err() so that we can see which -PHY had an error, and also inform the user that we are halting the PHY. - -Signed-off-by: Russell King ---- - drivers/net/phy/phy.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c -index 9ce6a3557bff..c8975093aa80 100644 ---- a/drivers/net/phy/phy.c -+++ b/drivers/net/phy/phy.c -@@ -934,7 +934,7 @@ void phy_stop_machine(struct phy_device *phydev) - */ - void phy_error(struct phy_device *phydev) - { -- WARN_ON(1); -+ phydev_err(phydev, "Error detected, halting PHY\n"); - - mutex_lock(&phydev->lock); - phydev->state = PHY_HALTED; --- -cgit v1.2.3 - - -From 8edafc7f6833391eb45cb3c6f2bdc86aba103507 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Fri, 18 Oct 2019 10:37:44 +0100 -Subject: net: sfp: add support for cooled SFP+ transceivers - -Cooled SFP+ transceivers need a longer initialisation (startup) time. -Select the initialisation time depending on the cooled option bit. - -Signed-off-by: Russell King ---- - drivers/net/phy/sfp.c | 15 +++++++++------ - 1 file changed, 9 insertions(+), 6 deletions(-) - -diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c -index ab77a9f439ef..d4a03bd0a1cf 100644 ---- a/drivers/net/phy/sfp.c -+++ b/drivers/net/phy/sfp.c -@@ -168,6 +168,7 @@ static const enum gpiod_flags gpio_flags[] = { - #define T_WAIT msecs_to_jiffies(50) - #define T_START_UP msecs_to_jiffies(300) - #define T_START_UP_BAD_GPON msecs_to_jiffies(60000) -+#define T_START_UP_COOLED msecs_to_jiffies(90000) - - /* t_reset is the time required to assert the TX_DISABLE signal to reset - * an indicated TX_FAULT. -@@ -1925,6 +1926,8 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report) - if (!memcmp(id.base.vendor_name, "ALCATELLUCENT ", 16) && - !memcmp(id.base.vendor_pn, "3FE46541AA ", 16)) - sfp->module_t_start_up = T_START_UP_BAD_GPON; -+ else if (id.ext.options & cpu_to_be16(SFP_OPTIONS_COOLED_XCVR)) -+ sfp->module_t_start_up = T_START_UP_COOLED; - else - sfp->module_t_start_up = T_START_UP; - -@@ -2131,10 +2134,10 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event) - break; - - if (sfp->state & SFP_F_TX_FAULT) { -- /* Wait up to t_init (SFF-8472) or t_start_up (SFF-8431) -- * from the TX_DISABLE deassertion for the module to -- * initialise, which is indicated by TX_FAULT -- * deasserting. -+ /* Wait up to t_init (SFF-8472), t_start_up (SFF-8431), -+ * or t_start_up_cooled (SFF-8431) from the TX_DISABLE -+ * deassertion for the module to initialise, which is -+ * indicated by TX_FAULT deasserting. - */ - timeout = sfp->module_t_start_up; - if (timeout > T_WAIT) -@@ -2153,8 +2156,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event) - - case SFP_S_INIT: - if (event == SFP_E_TIMEOUT && sfp->state & SFP_F_TX_FAULT) { -- /* TX_FAULT is still asserted after t_init -- * or t_start_up, so assume there is a fault. -+ /* TX_FAULT is still asserted after t_init, t_start_up -+ * or t_start_up_cooled, so assume there is a fault. - */ - sfp_sm_fault(sfp, SFP_S_INIT_TX_FAULT, - sfp->sm_fault_retries == N_FAULT_INIT); --- -cgit v1.2.3 - - -From 15a50227e7f2e71d3cc0f1ab46e6fe529b6bf353 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Fri, 14 Apr 2017 20:17:13 +0100 -Subject: net: sfp: add sfp+ compatible [*not for mainline*] - -Add a compatible for SFP+ cages. SFP+ cages are backwards compatible, -but the ethernet device behind them may not support the slower speeds -of SFP modules. - -Signed-off-by: Russell King ---- - drivers/net/phy/sfp.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c -index d4a03bd0a1cf..f84f78da2154 100644 ---- a/drivers/net/phy/sfp.c -+++ b/drivers/net/phy/sfp.c -@@ -304,6 +304,7 @@ static const struct sff_data sfp_data = { - static const struct of_device_id sfp_of_match[] = { - { .compatible = "sff,sff", .data = &sff_data, }, - { .compatible = "sff,sfp", .data = &sfp_data, }, -+ { .compatible = "sff,sfp+", .data = &sfp_data, }, - { }, - }; - MODULE_DEVICE_TABLE(of, sfp_of_match); --- -cgit v1.2.3 - - -From 477e90533e82fa9ff2b21904b8e602b4c1cd46ef Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Sun, 13 Sep 2015 01:06:31 +0100 -Subject: net: sfp: display SFP module information [*not for mainline*] - -Display SFP module information verbosely, splitting the generic parts -into a separate file. - -Signed-off-by: Russell King ---- - drivers/net/phy/Makefile | 2 +- - drivers/net/phy/sff.c | 114 ++++++++++++++++++++++++ - drivers/net/phy/sff.h | 16 ++++ - drivers/net/phy/sfp.c | 228 ++++++++++++++++++++++++++++++++++++++++++++--- - 4 files changed, 349 insertions(+), 11 deletions(-) - create mode 100644 drivers/net/phy/sff.c - create mode 100644 drivers/net/phy/sff.h - -diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile -index b2728d00fc9a..48733fb58dcb 100644 ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -26,7 +26,7 @@ obj-$(CONFIG_PHYLIB) += libphy.o - - obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += mii_timestamper.o - --obj-$(CONFIG_SFP) += sfp.o -+obj-$(CONFIG_SFP) += sff.o sfp.o - sfp-obj-$(CONFIG_SFP) += sfp-bus.o - obj-y += $(sfp-obj-y) $(sfp-obj-m) - -diff --git a/drivers/net/phy/sff.c b/drivers/net/phy/sff.c -new file mode 100644 -index 000000000000..a2eb56118dd4 ---- /dev/null -+++ b/drivers/net/phy/sff.c -@@ -0,0 +1,114 @@ -+#include -+#include -+#include "sff.h" -+ -+const char *sff_link_len(char *buf, size_t size, unsigned int length, -+ unsigned int multiplier) -+{ -+ if (length == 0) -+ return "unsupported/unspecified"; -+ -+ if (length == 255) { -+ *buf++ = '>'; -+ size -= 1; -+ length -= 1; -+ } -+ -+ length *= multiplier; -+ -+ if (length >= 1000) -+ snprintf(buf, size, "%u.%0*ukm", -+ length / 1000, -+ multiplier > 100 ? 1 : -+ multiplier > 10 ? 2 : 3, -+ length % 1000); -+ else -+ snprintf(buf, size, "%um", length); -+ -+ return buf; -+} -+EXPORT_SYMBOL_GPL(sff_link_len); -+ -+const char *sff_bitfield(char *buf, size_t size, -+ const struct sff_bitfield *bits, unsigned int val) -+{ -+ char *p = buf; -+ int n; -+ -+ *p = '\0'; -+ while (bits->mask) { -+ if ((val & bits->mask) == bits->val) { -+ n = snprintf(p, size, "%s%s", -+ buf != p ? ", " : "", -+ bits->str); -+ if (n == size) -+ break; -+ p += n; -+ size -= n; -+ } -+ bits++; -+ } -+ -+ return buf; -+} -+EXPORT_SYMBOL_GPL(sff_bitfield); -+ -+const char *sff_connector(unsigned int connector) -+{ -+ switch (connector) { -+ case SFF8024_CONNECTOR_UNSPEC: -+ return "unknown/unspecified"; -+ case SFF8024_CONNECTOR_SC: -+ return "SC"; -+ case SFF8024_CONNECTOR_FIBERJACK: -+ return "Fiberjack"; -+ case SFF8024_CONNECTOR_LC: -+ return "LC"; -+ case SFF8024_CONNECTOR_MT_RJ: -+ return "MT-RJ"; -+ case SFF8024_CONNECTOR_MU: -+ return "MU"; -+ case SFF8024_CONNECTOR_SG: -+ return "SG"; -+ case SFF8024_CONNECTOR_OPTICAL_PIGTAIL: -+ return "Optical pigtail"; -+ case SFF8024_CONNECTOR_MPO_1X12: -+ return "MPO 1X12"; -+ case SFF8024_CONNECTOR_MPO_2X16: -+ return "MPO 2X16"; -+ case SFF8024_CONNECTOR_HSSDC_II: -+ return "HSSDC II"; -+ case SFF8024_CONNECTOR_COPPER_PIGTAIL: -+ return "Copper pigtail"; -+ case SFF8024_CONNECTOR_RJ45: -+ return "RJ45"; -+ case SFF8024_CONNECTOR_MXC_2X16: -+ return "MXC 2X16"; -+ default: -+ return "unknown"; -+ } -+} -+EXPORT_SYMBOL_GPL(sff_connector); -+ -+const char *sff_encoding(unsigned int encoding) -+{ -+ switch (encoding) { -+ case SFF8024_ENCODING_UNSPEC: -+ return "unspecified"; -+ case SFF8024_ENCODING_8472_64B66B: -+ return "64b66b"; -+ case SFF8024_ENCODING_8B10B: -+ return "8b10b"; -+ case SFF8024_ENCODING_4B5B: -+ return "4b5b"; -+ case SFF8024_ENCODING_NRZ: -+ return "NRZ"; -+ case SFF8024_ENCODING_8472_MANCHESTER: -+ return "MANCHESTER"; -+ default: -+ return "unknown"; -+ } -+} -+EXPORT_SYMBOL_GPL(sff_encoding); -+ -+MODULE_LICENSE("GPL"); -diff --git a/drivers/net/phy/sff.h b/drivers/net/phy/sff.h -new file mode 100644 -index 000000000000..cd7bb7c7ae4a ---- /dev/null -+++ b/drivers/net/phy/sff.h -@@ -0,0 +1,16 @@ -+#ifndef SFF_H -+#define SFF_H -+ -+struct sff_bitfield { -+ unsigned int mask; -+ unsigned int val; -+ const char *str; -+}; -+ -+const char *sff_link_len(char *buf, size_t size, unsigned int length, -+ unsigned int multiplier); -+const char *sff_bitfield(char *buf, size_t size, -+ const struct sff_bitfield *bits, unsigned int val); -+const char *sff_connector(unsigned int connector); -+const char *sff_encoding(unsigned int encoding); -+#endif -diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c -index f84f78da2154..51a1da50c608 100644 ---- a/drivers/net/phy/sfp.c -+++ b/drivers/net/phy/sfp.c -@@ -18,6 +18,7 @@ - #include - #include - -+#include "sff.h" - #include "sfp.h" - #include "swphy.h" - -@@ -1398,6 +1399,114 @@ static void sfp_hwmon_exit(struct sfp *sfp) - } - #endif - -+static const struct sff_bitfield sfp_options[] = { -+ { -+ .mask = SFP_OPTIONS_HIGH_POWER_LEVEL, -+ .val = SFP_OPTIONS_HIGH_POWER_LEVEL, -+ .str = "hpl", -+ }, { -+ .mask = SFP_OPTIONS_PAGING_A2, -+ .val = SFP_OPTIONS_PAGING_A2, -+ .str = "paginga2", -+ }, { -+ .mask = SFP_OPTIONS_RETIMER, -+ .val = SFP_OPTIONS_RETIMER, -+ .str = "retimer", -+ }, { -+ .mask = SFP_OPTIONS_COOLED_XCVR, -+ .val = SFP_OPTIONS_COOLED_XCVR, -+ .str = "cooled", -+ }, { -+ .mask = SFP_OPTIONS_POWER_DECL, -+ .val = SFP_OPTIONS_POWER_DECL, -+ .str = "powerdecl", -+ }, { -+ .mask = SFP_OPTIONS_RX_LINEAR_OUT, -+ .val = SFP_OPTIONS_RX_LINEAR_OUT, -+ .str = "rxlinear", -+ }, { -+ .mask = SFP_OPTIONS_RX_DECISION_THRESH, -+ .val = SFP_OPTIONS_RX_DECISION_THRESH, -+ .str = "rxthresh", -+ }, { -+ .mask = SFP_OPTIONS_TUNABLE_TX, -+ .val = SFP_OPTIONS_TUNABLE_TX, -+ .str = "tunabletx", -+ }, { -+ .mask = SFP_OPTIONS_RATE_SELECT, -+ .val = SFP_OPTIONS_RATE_SELECT, -+ .str = "ratesel", -+ }, { -+ .mask = SFP_OPTIONS_TX_DISABLE, -+ .val = SFP_OPTIONS_TX_DISABLE, -+ .str = "txdisable", -+ }, { -+ .mask = SFP_OPTIONS_TX_FAULT, -+ .val = SFP_OPTIONS_TX_FAULT, -+ .str = "txfault", -+ }, { -+ .mask = SFP_OPTIONS_LOS_INVERTED, -+ .val = SFP_OPTIONS_LOS_INVERTED, -+ .str = "los-", -+ }, { -+ .mask = SFP_OPTIONS_LOS_NORMAL, -+ .val = SFP_OPTIONS_LOS_NORMAL, -+ .str = "los+", -+ }, { } -+}; -+ -+static const struct sff_bitfield diagmon[] = { -+ { -+ .mask = SFP_DIAGMON_DDM, -+ .val = SFP_DIAGMON_DDM, -+ .str = "ddm", -+ }, { -+ .mask = SFP_DIAGMON_INT_CAL, -+ .val = SFP_DIAGMON_INT_CAL, -+ .str = "intcal", -+ }, { -+ .mask = SFP_DIAGMON_EXT_CAL, -+ .val = SFP_DIAGMON_EXT_CAL, -+ .str = "extcal", -+ }, { -+ .mask = SFP_DIAGMON_RXPWR_AVG, -+ .val = SFP_DIAGMON_RXPWR_AVG, -+ .str = "rxpwravg", -+ }, { } -+}; -+ -+static const struct sff_bitfield sfp_enhopts[] = { -+ { -+ .mask = SFP_ENHOPTS_ALARMWARN, -+ .val = SFP_ENHOPTS_ALARMWARN, -+ .str = "alarmwarn", -+ }, { -+ .mask = SFP_ENHOPTS_SOFT_TX_DISABLE, -+ .val = SFP_ENHOPTS_SOFT_TX_DISABLE, -+ .str = "soft_tx_dis", -+ }, { -+ .mask = SFP_ENHOPTS_SOFT_TX_FAULT, -+ .val = SFP_ENHOPTS_SOFT_TX_FAULT, -+ .str = "soft_tx_fault", -+ }, { -+ .mask = SFP_ENHOPTS_SOFT_RX_LOS, -+ .val = SFP_ENHOPTS_SOFT_RX_LOS, -+ .str = "soft_rx_los", -+ }, { -+ .mask = SFP_ENHOPTS_SOFT_RATE_SELECT, -+ .val = SFP_ENHOPTS_SOFT_RATE_SELECT, -+ .str = "soft_rs", -+ }, { -+ .mask = SFP_ENHOPTS_APP_SELECT_SFF8079, -+ .val = SFP_ENHOPTS_APP_SELECT_SFF8079, -+ .str = "app_sel", -+ }, { -+ .mask = SFP_ENHOPTS_SOFT_RATE_SFF8431, -+ .val = SFP_ENHOPTS_SOFT_RATE_SFF8431, -+ .str = "soft_r8431", -+ }, { } -+}; -+ - /* Helpers */ - static void sfp_module_tx_disable(struct sfp *sfp) - { -@@ -1781,6 +1890,110 @@ static int sfp_cotsworks_fixup_check(struct sfp *sfp, struct sfp_eeprom_id *id) - return 0; - } - -+static void sfp_print_module_info(struct sfp *sfp, const struct sfp_eeprom_id *id, bool cotsworks) -+{ -+ unsigned int br_nom, br_min, br_max; -+ char date[9]; -+ char options[80]; -+ -+ /* Cotsworks also gets the date code wrong. */ -+ date[0] = id->ext.datecode[4 - 2 * cotsworks]; -+ date[1] = id->ext.datecode[5 - 2 * cotsworks]; -+ date[2] = '-'; -+ date[3] = id->ext.datecode[2 + 2 * cotsworks]; -+ date[4] = id->ext.datecode[3 + 2 * cotsworks]; -+ date[5] = '-'; -+ date[6] = id->ext.datecode[0]; -+ date[7] = id->ext.datecode[1]; -+ date[8] = '\0'; -+ -+ if (id->base.br_nominal == 0) { -+ br_min = br_nom = br_max = 0; -+ } else if (id->base.br_nominal == 255) { -+ br_nom = 250 * id->ext.br_max; -+ br_max = br_nom + br_nom * id->ext.br_min / 100; -+ br_min = br_nom - br_nom * id->ext.br_min / 100; -+ } else { -+ br_nom = id->base.br_nominal * 100; -+ br_min = br_nom - id->base.br_nominal * id->ext.br_min; -+ br_max = br_nom + id->base.br_nominal * id->ext.br_max; -+ } -+ -+ dev_info(sfp->dev, "module %.*s %.*s rev %.*s sn %.*s dc %s\n", -+ (int)sizeof(id->base.vendor_name), id->base.vendor_name, -+ (int)sizeof(id->base.vendor_pn), id->base.vendor_pn, -+ (int)sizeof(id->base.vendor_rev), id->base.vendor_rev, -+ (int)sizeof(id->ext.vendor_sn), id->ext.vendor_sn, date); -+ dev_info(sfp->dev, " %s connector, encoding %s, bitrate %u.%03u (%u.%03u-%u.%03u) Gbps\n", -+ sff_connector(id->base.connector), -+ sff_encoding(id->base.encoding), -+ br_nom / 1000, br_nom % 1000, -+ br_min / 1000, br_min % 1000, br_max / 1000, br_max % 1000); -+ dev_info(sfp->dev, " 1000BaseSX%c 1000BaseLX%c 1000BaseCX%c 1000BaseT%c 100BaseLX%c 100BaseFX%c BaseBX10%c BasePX%c\n", -+ id->base.e1000_base_sx ? '+' : '-', -+ id->base.e1000_base_lx ? '+' : '-', -+ id->base.e1000_base_cx ? '+' : '-', -+ id->base.e1000_base_t ? '+' : '-', -+ id->base.e100_base_lx ? '+' : '-', -+ id->base.e100_base_fx ? '+' : '-', -+ id->base.e_base_bx10 ? '+' : '-', -+ id->base.e_base_px ? '+' : '-'); -+ dev_info(sfp->dev, " 10GBaseSR%c 10GBaseLR%c 10GBaseLRM%c 10GBaseER%c\n", -+ id->base.e10g_base_sr ? '+' : '-', -+ id->base.e10g_base_lr ? '+' : '-', -+ id->base.e10g_base_lrm ? '+' : '-', -+ id->base.e10g_base_er ? '+' : '-'); -+ -+ if (!id->base.sfp_ct_passive && !id->base.sfp_ct_active && -+ !id->base.e1000_base_t) { -+ char len_9um[16], len_om[16]; -+ -+ dev_info(sfp->dev, " Wavelength %unm, fiber lengths:\n", -+ be16_to_cpup(&id->base.optical_wavelength)); -+ -+ if (id->base.link_len[0] == 255) -+ strcpy(len_9um, ">254km"); -+ else if (id->base.link_len[1] && id->base.link_len[1] != 255) -+ sprintf(len_9um, "%um", -+ id->base.link_len[1] * 100); -+ else if (id->base.link_len[0]) -+ sprintf(len_9um, "%ukm", id->base.link_len[0]); -+ else if (id->base.link_len[1] == 255) -+ strcpy(len_9um, ">25.4km"); -+ else -+ strcpy(len_9um, "unsupported"); -+ -+ dev_info(sfp->dev, " 9”m SM : %s\n", len_9um); -+ dev_info(sfp->dev, " 62.5”m MM OM1: %s\n", -+ sff_link_len(len_om, sizeof(len_om), -+ id->base.link_len[3], 10)); -+ dev_info(sfp->dev, " 50”m MM OM2: %s\n", -+ sff_link_len(len_om, sizeof(len_om), -+ id->base.link_len[2], 10)); -+ dev_info(sfp->dev, " 50”m MM OM3: %s\n", -+ sff_link_len(len_om, sizeof(len_om), -+ id->base.link_len[5], 10)); -+ dev_info(sfp->dev, " 50”m MM OM4: %s\n", -+ sff_link_len(len_om, sizeof(len_om), -+ id->base.link_len[4], 10)); -+ } else { -+ char len[16]; -+ dev_info(sfp->dev, " Copper length: %s\n", -+ sff_link_len(len, sizeof(len), -+ id->base.link_len[4], 1)); -+ } -+ -+ dev_info(sfp->dev, " Options: %s\n", -+ sff_bitfield(options, sizeof(options), sfp_options, -+ be16_to_cpu(id->ext.options))); -+ dev_info(sfp->dev, " Diagnostics: %s\n", -+ sff_bitfield(options, sizeof(options), diagmon, -+ id->ext.diagmon)); -+ dev_info(sfp->dev, " EnhOpts: %s\n", -+ sff_bitfield(options, sizeof(options), sfp_enhopts, -+ id->ext.enhopts)); -+} -+ - static int sfp_sm_mod_probe(struct sfp *sfp, bool report) - { - /* SFP module inserted - read I2C data */ -@@ -1835,9 +2048,9 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report) - } - } - -- /* Cotsworks do not seem to update the checksums when they -- * do the final programming with the final module part number, -- * serial number and date code. -+ /* Cotsworks do not seem to update the checksums when they update the -+ * module part number, serial number and date code. They also format -+ * the date code incorrectly. - */ - cotsworks = !memcmp(id.base.vendor_name, "COTSWORKS ", 16); - cotsworks_sfbg = !memcmp(id.base.vendor_pn, "SFBG", 4); -@@ -1897,14 +2110,9 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report) - } - } - -- sfp->id = id; -+ sfp_print_module_info(sfp, &id, cotsworks); - -- dev_info(sfp->dev, "module %.*s %.*s rev %.*s sn %.*s dc %.*s\n", -- (int)sizeof(id.base.vendor_name), id.base.vendor_name, -- (int)sizeof(id.base.vendor_pn), id.base.vendor_pn, -- (int)sizeof(id.base.vendor_rev), id.base.vendor_rev, -- (int)sizeof(id.ext.vendor_sn), id.ext.vendor_sn, -- (int)sizeof(id.ext.datecode), id.ext.datecode); -+ sfp->id = id; - - /* Check whether we support this module */ - if (!sfp->type->module_supported(&id)) { --- -cgit v1.2.3 - - -From 00457c3a88af8a6c781bc176fd5832307da6bb44 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 23 Dec 2019 23:24:17 +0000 -Subject: net: phy: add supported_interfaces to phylib - -Add a supported_interfaces member to phylib so we know which -interfaces a PHY supports. Currently, set any unconverted driver -to indicate all interfaces are supported. - -Signed-off-by: Russell King ---- - include/linux/phy.h | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/include/linux/phy.h b/include/linux/phy.h -index 94903467a7df..b4e2366fed38 100644 ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -661,6 +661,9 @@ struct phy_device { - /* used with phy_speed_down */ - __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old); - -+ /* supported PHY interface types */ -+ DECLARE_PHY_INTERFACE_MASK(supported_interfaces); -+ - /* Energy efficient ethernet modes which should be prohibited */ - u32 eee_broken_modes; - --- -cgit v1.2.3 - - -From f2cfcd9a1a3aec87301399fdb8ef7e052e265615 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 23 Dec 2019 23:25:35 +0000 -Subject: net: phy: add supported_interfaces to bcm84881 - -Signed-off-by: Russell King ---- - drivers/net/phy/bcm84881.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/drivers/net/phy/bcm84881.c b/drivers/net/phy/bcm84881.c -index 9717a1626f3f..cba3ffc0708f 100644 ---- a/drivers/net/phy/bcm84881.c -+++ b/drivers/net/phy/bcm84881.c -@@ -51,6 +51,10 @@ static int bcm84881_probe(struct phy_device *phydev) - (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask) - return -ENODEV; - -+ __set_bit(PHY_INTERFACE_MODE_SGMII, phydev->supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, phydev->supported_interfaces); -+ - return 0; - } - --- -cgit v1.2.3 - - -From b33e017ab030bd713f84d2d99627b2e3ed493a36 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 23 Dec 2019 23:25:49 +0000 -Subject: net: phy: add supported_interfaces to marvell PHYs - -Signed-off-by: Russell King ---- - drivers/net/phy/marvell.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c -index 5a77b1a4396b..9735e1414de1 100644 ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -2748,6 +2748,15 @@ static int marvell_probe_pause(struct phy_device *phydev, u16 tx_pause_mask, - { - struct marvell_priv *priv; - -+ __set_bit(PHY_INTERFACE_MODE_GMII, phydev->supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_SGMII, phydev->supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_TBI, phydev->supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_RGMII, phydev->supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_RGMII_ID, phydev->supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_RGMII_RXID, phydev->supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_RGMII_TXID, phydev->supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_RTBI, phydev->supported_interfaces); -+ - priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; --- -cgit v1.2.3 - - -From ca3c7f5e502fe8ac88553d42602be2422393330a Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 23 Dec 2019 23:26:04 +0000 -Subject: net: phy: add supported_interfaces to marvell10g PHYs - -Signed-off-by: Russell King ---- - drivers/net/phy/marvell10g.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c -index b9d23fc5d10a..0a89d6818c46 100644 ---- a/drivers/net/phy/marvell10g.c -+++ b/drivers/net/phy/marvell10g.c -@@ -539,6 +539,10 @@ static int mv3310_probe(struct phy_device *phydev) - (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask) - return -ENODEV; - -+ __set_bit(PHY_INTERFACE_MODE_SGMII, phydev->supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, phydev->supported_interfaces); -+ - priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; --- -cgit v1.2.3 - - -From 9837e3475a4a6d03a4b458efd279f67e883bd444 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Tue, 3 Mar 2020 12:12:43 +0000 -Subject: net: phylink: use phy interface mode bitmaps - -Use the phy interface mode bitmaps for SFP modules and PHYs to select -the operating interface for SFPs and PHYs with SFPs. - -Signed-off-by: Russell King ---- - drivers/net/phy/phylink.c | 36 ++++++++++++++++++++++++++++++++---- - 1 file changed, 32 insertions(+), 4 deletions(-) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index 0b69dce407b8..1e0a7b7fe218 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -2515,12 +2515,40 @@ static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) - else - mode = MLO_AN_INBAND; - -- /* Do the initial configuration */ -- ret = phylink_sfp_config(pl, mode, phy->supported, phy->advertising); -- if (ret < 0) -- return ret; -+ if (!phy_interface_empty(phy->supported_interfaces) && -+ !phy_interface_empty(pl->config->supported_interfaces)) { -+ interface = phylink_select_interface(pl, -+ phy->supported_interfaces, -+ "phy"); -+ if (interface == PHY_INTERFACE_MODE_NA) { -+ phylink_err(pl, -+ "selection of interface for PHY failed\n"); -+ return -EINVAL; -+ } -+ -+ if (pl->cur_link_an_mode != mode || -+ pl->link_config.interface != interface) { -+ pl->link_config.interface = interface; -+ pl->cur_link_an_mode = mode; -+ -+ phylink_info(pl, "switched to %s/%s link mode\n", -+ phylink_an_mode_str(mode), -+ phy_modes(interface)); -+ } -+ -+ if (!test_bit(PHYLINK_DISABLE_STOPPED, -+ &pl->phylink_disable_state)) -+ phylink_mac_initial_config(pl, false); -+ } else { -+ /* Do the initial configuration */ -+ ret = phylink_sfp_config(pl, mode, phy->supported, -+ phy->advertising); -+ if (ret < 0) -+ return ret; -+ } - - interface = pl->link_config.interface; -+ - ret = phylink_attach_phy(pl, phy, interface); - if (ret < 0) - return ret; --- -cgit v1.2.3 - - -From 7815de591b76087433f1ff1a7c08a144eed507dd Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 22 Jun 2020 01:05:59 +0100 -Subject: net: dsa/bcm_sf2: fix pause mode validation - -The implementation appears not to support pause modes on anything -but RGMII, RGMII_TXID, MII and REVMII interface modes. Let phylink -know that detail. - -(This may not be correct; particularly see the FIXMEs in this patch.) - -Signed-off-by: Russell King ---- - drivers/net/dsa/bcm_sf2.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c -index a46fe385acd6..b5200cbf9776 100644 ---- a/drivers/net/dsa/bcm_sf2.c -+++ b/drivers/net/dsa/bcm_sf2.c -@@ -677,6 +677,7 @@ static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port, - struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - -+ /* FIXME: Are RGMII_RXID and RGMII_ID actually supported? */ - if (!phy_interface_mode_is_rgmii(state->interface) && - state->interface != PHY_INTERFACE_MODE_MII && - state->interface != PHY_INTERFACE_MODE_REVMII && -@@ -694,8 +695,13 @@ static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port, - /* Allow all the expected bits */ - phylink_set(mask, Autoneg); - phylink_set_port_modes(mask); -- phylink_set(mask, Pause); -- phylink_set(mask, Asym_Pause); -+ if (state->interface == PHY_INTERFACE_MODE_RGMII || -+ state->interface == PHY_INTERFACE_MODE_RGMII_TXID || -+ state->interface == PHY_INTERFACE_MODE_MII || -+ state->interface == PHY_INTERFACE_MODE_REVMII) { -+ phylink_set(mask, Pause); -+ phylink_set(mask, Asym_Pause); -+ } - - /* With the exclusion of MII and Reverse MII, we support Gigabit, - * including Half duplex -@@ -728,6 +734,7 @@ static void bcm_sf2_sw_mac_config(struct dsa_switch *ds, int port, - return; - - switch (state->interface) { -+ /* FIXME: Are RGMII_RXID and RGMII_ID actually supported? */ - case PHY_INTERFACE_MODE_RGMII: - id_mode_dis = 1; - fallthrough; -@@ -828,6 +835,7 @@ static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port, - else - offset = CORE_STS_OVERRIDE_GMIIP2_PORT(port); - -+ /* FIXME: Are RGMII_RXID and RGMII_ID actually supported? */ - if (interface == PHY_INTERFACE_MODE_RGMII || - interface == PHY_INTERFACE_MODE_RGMII_TXID || - interface == PHY_INTERFACE_MODE_MII || --- -cgit v1.2.3 - - -From c9521ea8f5b51c0b2fb39a073be9c85717d27ba4 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 7 Oct 2021 13:07:41 +0100 -Subject: net: phylink: add PCS selection interface - -Augment the MAC operations with a method to select the PCS interface, -rather than having MACs make the selection in their .mac_prepare() -method. - -This allows us to query which PCS the MAC wishes to use for a PHY -interface mode. - -Signed-off-by: Russell King (Oracle) ---- -Along with the switch to using phy_interface_t bitmaps, we can go a -little further by having the PCS also provide those bitmaps, and -using that in combination with the MAC and SFP bitmaps to select the -interface mode. - -Other required work is to find some way of eliminating the recently -introduced "old" approach of selecting the interface mode by -linkmodes in phylink_ethtool_ksettings_set() which conflicts with -using a phy_interface_t bitmap. Maybe we need a way to convert the -advertising mask back into a set of possible phy_interface_t's? ---- - drivers/net/phy/phylink.c | 17 +++++++++++++++++ - include/linux/phylink.h | 3 +++ - 2 files changed, 20 insertions(+) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index 1e0a7b7fe218..e9a8fa4703d0 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -197,6 +197,8 @@ static int phylink_validate_any(struct phylink *pl, unsigned long *supported, - static int phylink_validate(struct phylink *pl, unsigned long *supported, - struct phylink_link_state *state) - { -+ struct phylink_pcs *pcs; -+ - if (!phy_interface_empty(pl->config->supported_interfaces)) { - if (state->interface == PHY_INTERFACE_MODE_NA) - return phylink_validate_any(pl, supported, state); -@@ -208,6 +210,12 @@ static int phylink_validate(struct phylink *pl, unsigned long *supported, - - pl->mac_ops->validate(pl->config, supported, state); - -+ if (pl->mac_ops->mac_select_pcs) { -+ pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); -+ if (!pcs) -+ return -EINVAL; -+ } -+ - return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; - } - -@@ -498,6 +506,7 @@ static void phylink_mac_pcs_an_restart(struct phylink *pl) - static void phylink_major_config(struct phylink *pl, bool restart, - const struct phylink_link_state *state) - { -+ struct phylink_pcs *pcs; - int err; - - phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); -@@ -512,6 +521,14 @@ static void phylink_major_config(struct phylink *pl, bool restart, - } - } - -+ if (pl->mac_ops->mac_select_pcs) { -+ pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); -+ if (!pcs) -+ phylink_err(pl, "mac_select_pcs unexpectedly failed\n"); -+ else -+ phylink_set_pcs(pl, pcs); -+ } -+ - phylink_mac_config(pl, state); - - if (pl->pcs_ops) { -diff --git a/include/linux/phylink.h b/include/linux/phylink.h -index f037470b6fb3..0817248691ef 100644 ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -84,6 +84,7 @@ struct phylink_config { - /** - * struct phylink_mac_ops - MAC operations structure. - * @validate: Validate and update the link configuration. -+ * @mac_select_pcs: Select a PCS for the interface mode. - * @mac_pcs_get_state: Read the current link state from the hardware. - * @mac_prepare: prepare for a major reconfiguration of the interface. - * @mac_config: configure the MAC for the selected mode and state. -@@ -98,6 +99,8 @@ struct phylink_mac_ops { - void (*validate)(struct phylink_config *config, - unsigned long *supported, - struct phylink_link_state *state); -+ struct phylink_pcs *(*mac_select_pcs)(struct phylink_config *config, -+ phy_interface_t iface); - void (*mac_pcs_get_state)(struct phylink_config *config, - struct phylink_link_state *state); - int (*mac_prepare)(struct phylink_config *config, unsigned int mode, --- -cgit v1.2.3 - - -From 02979159241221e4e7897b8308a72f648969b067 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Thu, 7 Oct 2021 13:09:05 +0100 -Subject: net: marvell: mvpp2: use .mac_select_pcs() interface - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 3 +- - drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 74 +++++++++++++------------ - 2 files changed, 41 insertions(+), 36 deletions(-) - -diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h -index cf8acabb90ac..ad73a488fc5f 100644 ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h -@@ -1239,7 +1239,8 @@ struct mvpp2_port { - phy_interface_t phy_interface; - struct phylink *phylink; - struct phylink_config phylink_config; -- struct phylink_pcs phylink_pcs; -+ struct phylink_pcs pcs_gmac; -+ struct phylink_pcs pcs_xlg; - struct phy *comphy; - - struct mvpp2_bm_pool *pool_long; -diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -index a774010f9478..c4325b31e44c 100644 ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -6105,15 +6105,20 @@ static struct mvpp2_port *mvpp2_phylink_to_port(struct phylink_config *config) - return container_of(config, struct mvpp2_port, phylink_config); - } - --static struct mvpp2_port *mvpp2_pcs_to_port(struct phylink_pcs *pcs) -+static struct mvpp2_port *mvpp2_pcs_xlg_to_port(struct phylink_pcs *pcs) - { -- return container_of(pcs, struct mvpp2_port, phylink_pcs); -+ return container_of(pcs, struct mvpp2_port, pcs_xlg); -+} -+ -+static struct mvpp2_port *mvpp2_pcs_gmac_to_port(struct phylink_pcs *pcs) -+{ -+ return container_of(pcs, struct mvpp2_port, pcs_gmac); - } - - static void mvpp2_xlg_pcs_get_state(struct phylink_pcs *pcs, - struct phylink_link_state *state) - { -- struct mvpp2_port *port = mvpp2_pcs_to_port(pcs); -+ struct mvpp2_port *port = mvpp2_pcs_xlg_to_port(pcs); - u32 val; - - state->speed = SPEED_10000; -@@ -6148,7 +6153,7 @@ static const struct phylink_pcs_ops mvpp2_phylink_xlg_pcs_ops = { - static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs, - struct phylink_link_state *state) - { -- struct mvpp2_port *port = mvpp2_pcs_to_port(pcs); -+ struct mvpp2_port *port = mvpp2_pcs_gmac_to_port(pcs); - u32 val; - - val = readl(port->base + MVPP2_GMAC_STATUS0); -@@ -6185,7 +6190,7 @@ static int mvpp2_gmac_pcs_config(struct phylink_pcs *pcs, unsigned int mode, - const unsigned long *advertising, - bool permit_pause_to_mac) - { -- struct mvpp2_port *port = mvpp2_pcs_to_port(pcs); -+ struct mvpp2_port *port = mvpp2_pcs_gmac_to_port(pcs); - u32 mask, val, an, old_an, changed; - - mask = MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS | -@@ -6239,7 +6244,7 @@ static int mvpp2_gmac_pcs_config(struct phylink_pcs *pcs, unsigned int mode, - - static void mvpp2_gmac_pcs_an_restart(struct phylink_pcs *pcs) - { -- struct mvpp2_port *port = mvpp2_pcs_to_port(pcs); -+ struct mvpp2_port *port = mvpp2_pcs_gmac_to_port(pcs); - u32 val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); - - writel(val | MVPP2_GMAC_IN_BAND_RESTART_AN, -@@ -6400,8 +6405,23 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, - writel(ctrl4, port->base + MVPP22_GMAC_CTRL_4_REG); - } - --static int mvpp2__mac_prepare(struct phylink_config *config, unsigned int mode, -- phy_interface_t interface) -+static struct phylink_pcs *mvpp2_select_pcs(struct phylink_config *config, -+ phy_interface_t interface) -+{ -+ struct mvpp2_port *port = mvpp2_phylink_to_port(config); -+ -+ /* Select the appropriate PCS operations depending on the -+ * configured interface mode. We will only switch to a mode -+ * that the validate() checks have already passed. -+ */ -+ if (mvpp2_is_xlg(interface)) -+ return &port->pcs_xlg; -+ else -+ return &port->pcs_gmac; -+} -+ -+static int mvpp2_mac_prepare(struct phylink_config *config, unsigned int mode, -+ phy_interface_t interface) - { - struct mvpp2_port *port = mvpp2_phylink_to_port(config); - -@@ -6447,31 +6467,9 @@ static int mvpp2__mac_prepare(struct phylink_config *config, unsigned int mode, - } - } - -- /* Select the appropriate PCS operations depending on the -- * configured interface mode. We will only switch to a mode -- * that the validate() checks have already passed. -- */ -- if (mvpp2_is_xlg(interface)) -- port->phylink_pcs.ops = &mvpp2_phylink_xlg_pcs_ops; -- else -- port->phylink_pcs.ops = &mvpp2_phylink_gmac_pcs_ops; -- - return 0; - } - --static int mvpp2_mac_prepare(struct phylink_config *config, unsigned int mode, -- phy_interface_t interface) --{ -- struct mvpp2_port *port = mvpp2_phylink_to_port(config); -- int ret; -- -- ret = mvpp2__mac_prepare(config, mode, interface); -- if (ret == 0) -- phylink_set_pcs(port->phylink, &port->phylink_pcs); -- -- return ret; --} -- - static void mvpp2_mac_config(struct phylink_config *config, unsigned int mode, - const struct phylink_link_state *state) - { -@@ -6646,6 +6644,7 @@ static void mvpp2_mac_link_down(struct phylink_config *config, - - static const struct phylink_mac_ops mvpp2_phylink_ops = { - .validate = mvpp2_phylink_validate, -+ .mac_select_pcs = mvpp2_select_pcs, - .mac_prepare = mvpp2_mac_prepare, - .mac_config = mvpp2_mac_config, - .mac_finish = mvpp2_mac_finish, -@@ -6663,12 +6662,15 @@ static void mvpp2_acpi_start(struct mvpp2_port *port) - struct phylink_link_state state = { - .interface = port->phy_interface, - }; -- mvpp2__mac_prepare(&port->phylink_config, MLO_AN_INBAND, -- port->phy_interface); -+ struct phylink_pcs *pcs; -+ -+ pcs = mvpp2_select_pcs(&port->phylink_config, port->phy_interface); -+ -+ mvpp2_mac_prepare(&port->phylink_config, MLO_AN_INBAND, -+ port->phy_interface); - mvpp2_mac_config(&port->phylink_config, MLO_AN_INBAND, &state); -- port->phylink_pcs.ops->pcs_config(&port->phylink_pcs, MLO_AN_INBAND, -- port->phy_interface, -- state.advertising, false); -+ pcs->ops->pcs_config(pcs, MLO_AN_INBAND, port->phy_interface, -+ state.advertising, false); - mvpp2_mac_finish(&port->phylink_config, MLO_AN_INBAND, - port->phy_interface); - mvpp2_mac_link_up(&port->phylink_config, NULL, -@@ -6951,6 +6953,8 @@ static int mvpp2_port_probe(struct platform_device *pdev, - goto err_free_port_pcpu; - } - port->phylink = phylink; -+ port->pcs_gmac.ops = &mvpp2_phylink_gmac_pcs_ops; -+ port->pcs_xlg.ops = &mvpp2_phylink_xlg_pcs_ops; - } else { - dev_warn(&pdev->dev, "Use link irqs for port#%d. FW update required\n", port->id); - port->phylink = NULL; --- -cgit v1.2.3 - - -From 992a4e6f7d18e49b6d4973b992a034a87ecd9252 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Tue, 7 Jul 2020 15:56:12 +0100 -Subject: net: dsa/phylink: PCS interface for DSA - -Add an interface to DSA for setting the current PCS for the port. - -Signed-off-by: Russell King ---- - include/net/dsa.h | 3 +++ - net/dsa/port.c | 14 ++++++++++++++ - net/dsa/slave.c | 3 +++ - 3 files changed, 20 insertions(+) - -diff --git a/include/net/dsa.h b/include/net/dsa.h -index e83f2692b638..493cbf6161aa 100644 ---- a/include/net/dsa.h -+++ b/include/net/dsa.h -@@ -259,6 +259,7 @@ struct dsa_port { - struct devlink_port devlink_port; - bool devlink_port_setup; - struct phylink *pl; -+ struct phylink_pcs *pl_pcs; - struct phylink_config pl_config; - struct net_device *lag_dev; - bool lag_tx_enabled; -@@ -1086,6 +1087,8 @@ int dsa_port_get_phy_strings(struct dsa_port *dp, uint8_t *data); - int dsa_port_get_ethtool_phy_stats(struct dsa_port *dp, uint64_t *data); - int dsa_port_get_phy_sset_count(struct dsa_port *dp); - void dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up); -+void dsa_port_phylink_set_pcs(struct dsa_switch *ds, int port, -+ struct phylink_pcs *pcs); - - struct dsa_tag_driver { - const struct dsa_device_ops *ops; -diff --git a/net/dsa/port.c b/net/dsa/port.c -index 2d1c6afc2659..cb5c42630855 100644 ---- a/net/dsa/port.c -+++ b/net/dsa/port.c -@@ -1154,6 +1154,17 @@ static int dsa_port_fixed_link_register_of(struct dsa_port *dp) - return 0; - } - -+void dsa_port_phylink_set_pcs(struct dsa_switch *ds, int port, -+ struct phylink_pcs *pcs) -+{ -+ struct dsa_port *dp = dsa_to_port(ds, port); -+ -+ dp->pl_pcs = pcs; -+ if (dp->pl) -+ phylink_set_pcs(dp->pl, pcs); -+} -+EXPORT_SYMBOL_GPL(dsa_port_phylink_set_pcs); -+ - static int dsa_port_phylink_register(struct dsa_port *dp) - { - struct dsa_switch *ds = dp->ds; -@@ -1180,6 +1191,9 @@ static int dsa_port_phylink_register(struct dsa_port *dp) - return PTR_ERR(dp->pl); - } - -+ if (dp->pl_pcs) -+ phylink_set_pcs(dp->pl, dp->pl_pcs); -+ - err = phylink_of_phy_connect(dp->pl, port_dn, 0); - if (err && err != -ENODEV) { - pr_err("could not attach to PHY: %d\n", err); -diff --git a/net/dsa/slave.c b/net/dsa/slave.c -index be5a079fc74d..f67607d163bf 100644 ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -1849,6 +1849,9 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev) - return PTR_ERR(dp->pl); - } - -+ if (dp->pl_pcs) -+ phylink_set_pcs(dp->pl, dp->pl_pcs); -+ - if (ds->ops->get_phy_flags) - phy_flags = ds->ops->get_phy_flags(ds, dp->index); - --- -cgit v1.2.3 - - -From 4b76ad8d2d31389ddf85aa643ea2b14256d801cf Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 22 Oct 2021 18:03:11 +0100 -Subject: net: mdio: add unlocked __mdiobus_modify() - -Add an unlocked __mdiobus_modify() implementation, which we will need -for Marvell DSA PCS conversion. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/phy/mdio_bus.c | 24 ++++++++++++++++++++++-- - include/linux/mdio.h | 2 ++ - 2 files changed, 24 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c -index c204067f1890..4638d7375943 100644 ---- a/drivers/net/phy/mdio_bus.c -+++ b/drivers/net/phy/mdio_bus.c -@@ -915,6 +915,26 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) - } - EXPORT_SYMBOL(mdiobus_write); - -+/** -+ * __mdiobus_modify - Convenience function for modifying a given mdio device -+ * register -+ * @bus: the mii_bus struct -+ * @addr: the phy address -+ * @regnum: register number to write -+ * @mask: bit mask of bits to clear -+ * @set: bit mask of bits to set -+ */ -+int __mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, -+ u16 set) -+{ -+ int err; -+ -+ err = __mdiobus_modify_changed(bus, addr, regnum, mask, set); -+ -+ return err < 0 ? err : 0; -+} -+EXPORT_SYMBOL_GPL(__mdiobus_modify); -+ - /** - * mdiobus_modify - Convenience function for modifying a given mdio device - * register -@@ -929,10 +949,10 @@ int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set) - int err; - - mutex_lock(&bus->mdio_lock); -- err = __mdiobus_modify_changed(bus, addr, regnum, mask, set); -+ err = __mdiobus_modify(bus, addr, regnum, mask, set); - mutex_unlock(&bus->mdio_lock); - -- return err < 0 ? err : 0; -+ return err; - } - EXPORT_SYMBOL_GPL(mdiobus_modify); - -diff --git a/include/linux/mdio.h b/include/linux/mdio.h -index f622888a4ba8..dfb10dd3054a 100644 ---- a/include/linux/mdio.h -+++ b/include/linux/mdio.h -@@ -340,6 +340,8 @@ static inline void mii_10gbt_stat_mod_linkmode_lpa_t(unsigned long *advertising, - - int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum); - int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); -+int __mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, -+ u16 set); - int __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, - u16 mask, u16 set); - --- -cgit v1.2.3 - - -From 34cd09e4f451eedfae9cc8724d291526256095db Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Fri, 22 Oct 2021 16:11:16 +0100 -Subject: net: phylink: Add helpers for c22 registers without MDIO - -Some devices expose memory-mapped c22-compliant PHYs. Because these -devices do not have an MDIO bus, we cannot use the existing helpers. -Refactor the existing helpers to allow supplying the values for c22 -registers directly, instead of using MDIO to access them. Only get_state -and set_adversisement are converted, since they contain the most complex -logic. - -Signed-off-by: Sean Anderson -Signed-off-by: Russell King (Oracle) ---- - drivers/net/phy/phylink.c | 125 +++++++++++++++++++++++++++++++--------------- - include/linux/phylink.h | 4 ++ - 2 files changed, 90 insertions(+), 39 deletions(-) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index e9a8fa4703d0..33ae8e1ddeec 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -2727,33 +2727,21 @@ void phylink_decode_usxgmii_word(struct phylink_link_state *state, - EXPORT_SYMBOL_GPL(phylink_decode_usxgmii_word); - - /** -- * phylink_mii_c22_pcs_get_state() - read the MAC PCS state -- * @pcs: a pointer to a &struct mdio_device. -- * @state: a pointer to a &struct phylink_link_state. -+ * phylink_mii_c22_pcs_decode_state() - Decode MAC PCS state from MII registers+ * @state: a pointer to a &struct phylink_link_state. -+ * @bmsr: The value of the %MII_BMSR register -+ * @lpa: The value of the %MII_LPA register - * - * Helper for MAC PCS supporting the 802.3 clause 22 register set for - * clause 37 negotiation and/or SGMII control. - * -- * Read the MAC PCS state from the MII device configured in @config and -- * parse the Clause 37 or Cisco SGMII link partner negotiation word into -- * the phylink @state structure. This is suitable to be directly plugged -- * into the mac_pcs_get_state() member of the struct phylink_mac_ops -- * structure. -+ * Parse the Clause 37 or Cisco SGMII link partner negotiation word into -+ * the phylink @state structure. This is suitable to be used for implementing -+ * the mac_pcs_get_state() member of the struct phylink_mac_ops structure if -+ * accessing @bmsr and @lpa cannot be done with MDIO directly. - */ --void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs, -- struct phylink_link_state *state) -+void phylink_mii_c22_pcs_decode_state(struct phylink_link_state *state, -+ u16 bmsr, u16 lpa) - { -- struct mii_bus *bus = pcs->bus; -- int addr = pcs->addr; -- int bmsr, lpa; -- -- bmsr = mdiobus_read(bus, addr, MII_BMSR); -- lpa = mdiobus_read(bus, addr, MII_LPA); -- if (bmsr < 0 || lpa < 0) { -- state->link = false; -- return; -- } -- - state->link = !!(bmsr & BMSR_LSTATUS); - state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE); - /* If there is no link or autonegotiation is disabled, the LP advertisement -@@ -2781,31 +2769,58 @@ void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs, - break; - } - } --EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_get_state); -+EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_decode_state); - - /** -- * phylink_mii_c22_pcs_set_advertisement() - configure the clause 37 PCS -- * advertisement -+ * phylink_mii_c22_pcs_get_state() - read the MAC PCS state - * @pcs: a pointer to a &struct mdio_device. -+ * @state: a pointer to a &struct phylink_link_state. -+ * -+ * Helper for MAC PCS supporting the 802.3 clause 22 register set for -+ * clause 37 negotiation and/or SGMII control. -+ * -+ * Read the MAC PCS state from the MII device configured in @config and -+ * parse the Clause 37 or Cisco SGMII link partner negotiation word into -+ * the phylink @state structure. This is suitable to be directly plugged -+ * into the mac_pcs_get_state() member of the struct phylink_mac_ops -+ * structure. -+ */ -+void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs, -+ struct phylink_link_state *state) -+{ -+ struct mii_bus *bus = pcs->bus; -+ int addr = pcs->addr; -+ int bmsr, lpa; -+ -+ bmsr = mdiobus_read(bus, addr, MII_BMSR); -+ lpa = mdiobus_read(bus, addr, MII_LPA); -+ if (bmsr < 0 || lpa < 0) { -+ state->link = false; -+ return; -+ } -+ -+ phylink_mii_c22_pcs_decode_state(state, bmsr, lpa); -+} -+EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_get_state); -+ -+/** -+ * phylink_mii_c22_pcs_encode_advertisement() - configure the clause 37 PCS -+ * advertisement - * @interface: the PHY interface mode being configured - * @advertising: the ethtool advertisement mask -+ * @adv: the value of the %MII_ADVERTISE register - * - * Helper for MAC PCS supporting the 802.3 clause 22 register set for - * clause 37 negotiation and/or SGMII control. - * -- * Configure the clause 37 PCS advertisement as specified by @state. This -- * does not trigger a renegotiation; phylink will do that via the -- * mac_an_restart() method of the struct phylink_mac_ops structure. -+ * Encode the clause 37 PCS advertisement as specified by @interface and -+ * @advertising. Callers should write @adv if it has been modified. - * -- * Returns negative error code on failure to configure the advertisement, -- * zero if no change has been made, or one if the advertisement has changed. -+ * Return: The new value for @adv. - */ --int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs, -- phy_interface_t interface, -- const unsigned long *advertising) -+int phylink_mii_c22_pcs_encode_advertisement(phy_interface_t interface, -+ const unsigned long *advertising) - { -- struct mii_bus *bus = pcs->bus; -- int addr = pcs->addr; - u16 adv; - - switch (interface) { -@@ -2819,18 +2834,50 @@ int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs, - advertising)) - adv |= ADVERTISE_1000XPSE_ASYM; - -- return mdiobus_modify_changed(bus, addr, MII_ADVERTISE, -- 0xffff, adv); -+ return adv; - - case PHY_INTERFACE_MODE_SGMII: -- return mdiobus_modify_changed(bus, addr, MII_ADVERTISE, -- 0xffff, 0x0001); -+ return 0x0001; - - default: - /* Nothing to do for other modes */ -- return 0; -+ return -EINVAL; - } - } -+EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_encode_advertisement); -+ -+/** -+ * phylink_mii_c22_pcs_set_advertisement() - configure the clause 37 PCS -+ * advertisement -+ * @pcs: a pointer to a &struct mdio_device. -+ * @interface: the PHY interface mode being configured -+ * @advertising: the ethtool advertisement mask -+ * -+ * Helper for MAC PCS supporting the 802.3 clause 22 register set for -+ * clause 37 negotiation and/or SGMII control. -+ * -+ * Configure the clause 37 PCS advertisement as specified by @state. This -+ * does not trigger a renegotiation; phylink will do that via the -+ * mac_an_restart() method of the struct phylink_mac_ops structure. -+ * -+ * Returns negative error code on failure to configure the advertisement, -+ * zero if no change has been made, or one if the advertisement has changed. -+ */ -+int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs, -+ phy_interface_t interface, -+ const unsigned long *advertising) -+{ -+ struct mii_bus *bus = pcs->bus; -+ int addr = pcs->addr; -+ int adv; -+ -+ adv = phylink_mii_c22_pcs_encode_advertisement(interface, advertising); -+ if (adv < 0) -+ return 0; -+ -+ return mdiobus_modify_changed(bus, addr, MII_ADVERTISE, -+ 0xffff, adv); -+} - EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_set_advertisement); - - /** -diff --git a/include/linux/phylink.h b/include/linux/phylink.h -index 0817248691ef..e307ed35d82c 100644 ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -499,8 +499,12 @@ void phylink_set_port_modes(unsigned long *bits); - void phylink_set_10g_modes(unsigned long *mask); - void phylink_helper_basex_speed(struct phylink_link_state *state); - -+void phylink_mii_c22_pcs_decode_state(struct phylink_link_state *state, -+ u16 bmsr, u16 lpa); - void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs, - struct phylink_link_state *state); -+int phylink_mii_c22_pcs_encode_advertisement(phy_interface_t interface, -+ const unsigned long *advertising); - int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs, - phy_interface_t interface, - const unsigned long *advertising); --- -cgit v1.2.3 - - -From bd4b714702782256fdae8d45e85a69a1ebe5df78 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Tue, 5 May 2020 14:53:57 +0100 -Subject: net: phylink: tidy up disable bit clearing - -Tidy up the disable bit clearing where we clear a bit and the run the -link resolver. - -Signed-off-by: Russell King ---- - drivers/net/phy/phylink.c | 15 +++++++++------ - 1 file changed, 9 insertions(+), 6 deletions(-) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index 33ae8e1ddeec..e3641d691a32 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -831,6 +831,12 @@ static void phylink_run_resolve_and_disable(struct phylink *pl, int bit) - } - } - -+static void phylink_enable_and_run_resolve(struct phylink *pl, int bit) -+{ -+ clear_bit(bit, &pl->phylink_disable_state); -+ phylink_run_resolve(pl); -+} -+ - static void phylink_fixed_poll(struct timer_list *t) - { - struct phylink *pl = container_of(t, struct phylink, link_poll); -@@ -1315,8 +1321,7 @@ void phylink_start(struct phylink *pl) - */ - phylink_mac_initial_config(pl, true); - -- clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); -- phylink_run_resolve(pl); -+ phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED); - - if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) { - int irq = gpiod_to_irq(pl->link_gpio); -@@ -1456,8 +1461,7 @@ void phylink_resume(struct phylink *pl) - phylink_mac_initial_config(pl, true); - - /* Re-enable and re-resolve the link parameters */ -- clear_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state); -- phylink_run_resolve(pl); -+ phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_MAC_WOL); - } else { - phylink_start(pl); - } -@@ -2498,8 +2502,7 @@ static void phylink_sfp_link_up(void *upstream) - - ASSERT_RTNL(); - -- clear_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state); -- phylink_run_resolve(pl); -+ phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_LINK); - } - - /* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII --- -cgit v1.2.3 - - -From 1064211bfe88512cba9437150f9cab821903f147 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Sat, 23 Oct 2021 10:27:03 +0100 -Subject: net: phylink: add pcs enable/disable callbacks - -Add phylink PCS enable/disable callbacks that will allow us to place -IEEE 802.3 register compliant PCS in power-down mode while not being -used. - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/phy/phylink.c | 34 ++++++++++++++++++++++++++++++++++ - include/linux/phylink.h | 2 ++ - 2 files changed, 36 insertions(+) - -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index e3641d691a32..3eeceeac2b7a 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -958,6 +958,23 @@ struct phylink *phylink_create(struct phylink_config *config, - } - EXPORT_SYMBOL_GPL(phylink_create); - -+static void phylink_pcs_disable(struct phylink_pcs *pcs, -+ const struct phylink_pcs_ops *ops) -+{ -+ if (ops && ops->pcs_disable) -+ ops->pcs_disable(pcs); -+} -+ -+static int phylink_pcs_enable(struct phylink_pcs *pcs) -+{ -+ int err = 0; -+ -+ if (pcs && pcs->ops->pcs_enable) -+ err = pcs->ops->pcs_enable(pcs); -+ -+ return err; -+} -+ - /** - * phylink_set_pcs() - set the current PCS for phylink to use - * @pl: a pointer to a &struct phylink returned from phylink_create() -@@ -974,6 +991,19 @@ EXPORT_SYMBOL_GPL(phylink_create); - */ - void phylink_set_pcs(struct phylink *pl, struct phylink_pcs *pcs) - { -+ if (pl->pcs != pcs || pl->pcs_ops != pcs->ops) { -+ /* PCS has changed */ -+ if (!pl->phylink_disable_state) { -+ /* Phylink is currently started, disable the old PCS -+ * and enable the new PCS. -+ */ -+ phylink_pcs_disable(pl->pcs, pl->pcs_ops); -+ phylink_pcs_enable(pcs); -+ } else { -+ /* Phylink is currently stopped, disable the new PCS */ -+ phylink_pcs_disable(pcs, pcs->ops); -+ } -+ } - pl->pcs = pcs; - pl->pcs_ops = pcs->ops; - } -@@ -1321,6 +1351,8 @@ void phylink_start(struct phylink *pl) - */ - phylink_mac_initial_config(pl, true); - -+ phylink_pcs_enable(pl->pcs); -+ - phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED); - - if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) { -@@ -1385,6 +1417,8 @@ void phylink_stop(struct phylink *pl) - } - - phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED); -+ -+ phylink_pcs_disable(pl->pcs, pl->pcs_ops); - } - EXPORT_SYMBOL_GPL(phylink_stop); - -diff --git a/include/linux/phylink.h b/include/linux/phylink.h -index e307ed35d82c..e1b05b0c34e0 100644 ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -363,6 +363,8 @@ struct phylink_pcs { - * (where necessary). - */ - struct phylink_pcs_ops { -+ int (*pcs_enable)(struct phylink_pcs *pcs); -+ void (*pcs_disable)(struct phylink_pcs *pcs); - void (*pcs_get_state)(struct phylink_pcs *pcs, - struct phylink_link_state *state); - int (*pcs_config)(struct phylink_pcs *pcs, unsigned int mode, --- -cgit v1.2.3 - - -From c4a6ef05946399a89785d53c7e1ce71b83c71f49 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Tue, 7 Jul 2020 15:56:20 +0100 -Subject: net: dsa: mv88e6xxx: convert 88e6352 to phylink_pcs *EXPERIMENTAL* - -Experimental conversion of 88E6352 to phylink_pcs support for serdes -support. - -Signed-off-by: Russell King ---- - drivers/net/dsa/mv88e6xxx/Makefile | 2 +- - drivers/net/dsa/mv88e6xxx/chip.c | 10 + - drivers/net/dsa/mv88e6xxx/chip.h | 2 + - drivers/net/dsa/mv88e6xxx/serdes-6352.c | 329 ++++++++++++++++++++++++++++++++ - drivers/net/dsa/mv88e6xxx/serdes.h | 2 + - 5 files changed, 344 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/dsa/mv88e6xxx/serdes-6352.c - -diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile -index c8eca2b6f959..cd245ee9b853 100644 ---- a/drivers/net/dsa/mv88e6xxx/Makefile -+++ b/drivers/net/dsa/mv88e6xxx/Makefile -@@ -13,5 +13,5 @@ mv88e6xxx-objs += phy.o - mv88e6xxx-objs += port.o - mv88e6xxx-objs += port_hidden.o - mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += ptp.o --mv88e6xxx-objs += serdes.o -+mv88e6xxx-objs += serdes.o serdes-6352.o - mv88e6xxx-objs += smi.o -diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c -index 4ecfa5710cdc..92050955ee4b 100644 ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -3195,6 +3195,12 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) - return err; - } - -+ if (chip->info->ops->pcs_init) { -+ err = chip->info->ops->pcs_init(chip, port); -+ if (err) -+ return err; -+ } -+ - /* Port based VLAN map: give each port the same default address - * database, and allow bidirectional communication between the - * CPU and DSA port(s), and the other ports. -@@ -4151,6 +4157,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { - .vtu_getnext = mv88e6352_g1_vtu_getnext, - .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, - .serdes_get_lane = mv88e6352_serdes_get_lane, -+ .pcs_init = mv88e6352_pcs_init, - .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6352_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart, -@@ -4249,6 +4256,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { - .vtu_getnext = mv88e6352_g1_vtu_getnext, - .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, - .serdes_get_lane = mv88e6352_serdes_get_lane, -+ .pcs_init = mv88e6352_pcs_init, - .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6352_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart, -@@ -4534,6 +4542,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { - .vtu_getnext = mv88e6352_g1_vtu_getnext, - .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, - .serdes_get_lane = mv88e6352_serdes_get_lane, -+ .pcs_init = mv88e6352_pcs_init, - .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6352_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart, -@@ -4937,6 +4946,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { - .vtu_getnext = mv88e6352_g1_vtu_getnext, - .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, - .serdes_get_lane = mv88e6352_serdes_get_lane, -+ .pcs_init = mv88e6352_pcs_init, - .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state, - .serdes_pcs_config = mv88e6352_serdes_pcs_config, - .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart, -diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h -index 73b337478378..d589aaf6cf30 100644 ---- a/drivers/net/dsa/mv88e6xxx/chip.h -+++ b/drivers/net/dsa/mv88e6xxx/chip.h -@@ -555,6 +555,8 @@ struct mv88e6xxx_ops { - /* SERDES lane mapping */ - int (*serdes_get_lane)(struct mv88e6xxx_chip *chip, int port); - -+ int (*pcs_init)(struct mv88e6xxx_chip *chip, int port); -+ - int (*serdes_pcs_get_state)(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state); - int (*serdes_pcs_config)(struct mv88e6xxx_chip *chip, int port, -diff --git a/drivers/net/dsa/mv88e6xxx/serdes-6352.c b/drivers/net/dsa/mv88e6xxx/serdes-6352.c -new file mode 100644 -index 000000000000..fdd7b072b329 ---- /dev/null -+++ b/drivers/net/dsa/mv88e6xxx/serdes-6352.c -@@ -0,0 +1,329 @@ -+#include -+#include -+ -+#include "global2.h" -+#include "port.h" -+#include "serdes.h" -+ -+/* Definitions from drivers/net/phy/marvell.c, which would be good to reuse. */ -+#define MII_M1011_IEVENT 19 -+#define MII_M1011_IEVENT_LINK_CHANGE BIT(10) -+#define MII_M1011_IMASK 18 -+#define MII_M1011_IMASK_LINK_CHANGE BIT(10) -+#define MII_MARVELL_PHY_PAGE 22 -+#define MII_MARVELL_FIBER_PAGE 1 -+ -+struct marvell_c22_pcs { -+ struct mdio_device mdio; -+ struct phylink_pcs phylink_pcs; -+ unsigned int irq; -+ char name[64]; -+ bool (*link_check)(struct marvell_c22_pcs *mpcs); -+ void (*link_change)(struct marvell_c22_pcs *mpcs, bool up); -+ -+ struct mv88e6xxx_chip *chip; -+ int port; -+}; -+ -+static struct marvell_c22_pcs *pcs_to_marvell_c22_pcs(struct phylink_pcs *pcs) -+{ -+ return container_of(pcs, struct marvell_c22_pcs, phylink_pcs); -+} -+ -+static int marvell_c22_pcs_set_fiber_page(struct marvell_c22_pcs *mpcs) -+{ -+ struct mii_bus *bus = mpcs->mdio.bus; -+ u16 page; -+ int err; -+ -+ mutex_lock(&bus->mdio_lock); -+ -+ err = __mdiobus_read(bus, mpcs->mdio.addr, MII_MARVELL_PHY_PAGE); -+ if (err < 0) { -+ dev_err(mpcs->mdio.dev.parent, -+ "%s: can't read Serdes page register: %pe\n", -+ mpcs->name, ERR_PTR(err)); -+ return err; -+ } -+ -+ page = err; -+ -+ err = __mdiobus_write(bus, mpcs->mdio.addr, MII_MARVELL_PHY_PAGE, -+ MII_MARVELL_FIBER_PAGE); -+ if (err) { -+ dev_err(mpcs->mdio.dev.parent, -+ "%s: can't set Serdes page register: %pe\n", -+ mpcs->name, ERR_PTR(err)); -+ return err; -+ } -+ -+ return page; -+} -+ -+static int marvell_c22_pcs_restore_page(struct marvell_c22_pcs *mpcs, -+ int oldpage, int ret) -+{ -+ struct mii_bus *bus = mpcs->mdio.bus; -+ int err; -+ -+ if (oldpage >= 0) { -+ err = __mdiobus_write(bus, mpcs->mdio.addr, -+ MII_MARVELL_PHY_PAGE, oldpage); -+ if (err) -+ dev_err(mpcs->mdio.dev.parent, -+ "%s: can't restore Serdes page register: %pe\n", -+ mpcs->name, ERR_PTR(err)); -+ if (!err || ret < 0) -+ err = ret; -+ } else { -+ err = oldpage; -+ } -+ mutex_unlock(&bus->mdio_lock); -+ -+ return err; -+} -+ -+static irqreturn_t marvell_c22_pcs_handle_irq(int irq, void *dev_id) -+{ -+ struct marvell_c22_pcs *mpcs = dev_id; -+ irqreturn_t status = IRQ_NONE; -+ int err, oldpage; -+ -+ oldpage = marvell_c22_pcs_set_fiber_page(mpcs); -+ if (oldpage < 0) -+ goto fail; -+ -+ err = __mdiobus_read(mpcs->mdio.bus, mpcs->mdio.addr, MII_M1011_IEVENT); -+ if (err >= 0 && err & MII_M1011_IEVENT_LINK_CHANGE) { -+ err = __mdiobus_read(mpcs->mdio.bus, mpcs->mdio.addr, MII_BMSR); -+ if (err >= 0) -+ mpcs->link_change(mpcs, !!(err & BMSR_LSTATUS)); -+ status = IRQ_HANDLED; -+ } -+ -+fail: -+ marvell_c22_pcs_restore_page(mpcs, oldpage, 0); -+ -+ return status; -+} -+ -+static int marvell_c22_pcs_modify(struct marvell_c22_pcs *mpcs, u8 reg, -+ u16 mask, u16 val) -+{ -+ int oldpage, err; -+ -+ oldpage = marvell_c22_pcs_set_fiber_page(mpcs); -+ if (oldpage >= 0) -+ err = __mdiobus_modify(mpcs->mdio.bus, mpcs->mdio.addr, -+ reg, mask, val); -+ -+ return marvell_c22_pcs_restore_page(mpcs, oldpage, err); -+} -+ -+static int marvell_c22_pcs_control_irq(struct marvell_c22_pcs *mpcs, -+ bool enable) -+{ -+ u16 val = enable ? MII_M1011_IMASK_LINK_CHANGE : 0; -+ -+ return marvell_c22_pcs_modify(mpcs, MII_M1011_IMASK, -+ MII_M1011_IMASK_LINK_CHANGE, val); -+} -+ -+static int marvell_c22_pcs_enable(struct phylink_pcs *pcs) -+{ -+ struct marvell_c22_pcs *mpcs = pcs_to_marvell_c22_pcs(pcs); -+ int err; -+ -+ err = marvell_c22_pcs_modify(mpcs, MII_BMCR, BMCR_PDOWN, 0); -+ if (err || !mpcs->irq) -+ return err; -+ -+ return marvell_c22_pcs_control_irq(mpcs, true); -+} -+ -+static void marvell_c22_pcs_disable(struct phylink_pcs *pcs) -+{ -+ struct marvell_c22_pcs *mpcs = pcs_to_marvell_c22_pcs(pcs); -+ -+ marvell_c22_pcs_control_irq(mpcs, false); -+ marvell_c22_pcs_modify(mpcs, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN); -+} -+ -+static void marvell_c22_pcs_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state) -+{ -+ struct marvell_c22_pcs *mpcs = pcs_to_marvell_c22_pcs(pcs); -+ int oldpage, bmsr, lpa; -+ -+ state->link = false; -+ -+ if (mpcs->link_check && !mpcs->link_check(mpcs)) -+ return; -+ -+ oldpage = marvell_c22_pcs_set_fiber_page(mpcs); -+ if (oldpage >= 0) { -+ bmsr = __mdiobus_read(mpcs->mdio.bus, mpcs->mdio.addr, -+ MII_BMSR); -+ lpa = __mdiobus_read(mpcs->mdio.bus, mpcs->mdio.addr, MII_LPA); -+ } -+ -+ if (marvell_c22_pcs_restore_page(mpcs, oldpage, 0) >= 0 && -+ bmsr >= 0 && lpa >= 0) -+ phylink_mii_c22_pcs_decode_state(state, bmsr, lpa); -+} -+ -+static int marvell_c22_pcs_config(struct phylink_pcs *pcs, -+ unsigned int mode, -+ phy_interface_t interface, -+ const unsigned long *advertise, -+ bool permit_pause_to_mac) -+{ -+ struct marvell_c22_pcs *mpcs = pcs_to_marvell_c22_pcs(pcs); -+ int oldpage, adv, err; -+ -+ adv = phylink_mii_c22_pcs_encode_advertisement(interface, advertise); -+ if (adv < 0) -+ return 0; -+ -+ oldpage = marvell_c22_pcs_set_fiber_page(mpcs); -+ if (oldpage >= 0) -+ err = __mdiobus_modify_changed(mpcs->mdio.bus, mpcs->mdio.addr, -+ MII_ADVERTISE, 0xffff, adv); -+ -+ return marvell_c22_pcs_restore_page(mpcs, oldpage, err); -+} -+ -+static void marvell_c22_pcs_an_restart(struct phylink_pcs *pcs) -+{ -+ struct marvell_c22_pcs *mpcs = pcs_to_marvell_c22_pcs(pcs); -+ -+ marvell_c22_pcs_modify(mpcs, MII_BMCR, BMCR_ANRESTART, BMCR_ANRESTART); -+} -+ -+static void marvell_c22_pcs_link_up(struct phylink_pcs *pcs, -+ unsigned int mode, -+ phy_interface_t interface, -+ int speed, int duplex) -+{ -+ struct marvell_c22_pcs *mpcs = pcs_to_marvell_c22_pcs(pcs); -+ u16 bmcr; -+ int err; -+ -+ if (phylink_autoneg_inband(mode)) -+ return; -+ -+ switch (speed) { -+ case SPEED_1000: -+ bmcr = BMCR_SPEED1000; -+ break; -+ case SPEED_100: -+ bmcr = BMCR_SPEED100; -+ break; -+ case SPEED_10: -+ bmcr = 0; -+ break; -+ } -+ -+ if (duplex == DUPLEX_FULL) -+ bmcr |= BMCR_FULLDPLX; -+ -+ err = marvell_c22_pcs_modify(mpcs, MII_BMCR, BMCR_SPEED100 | -+ BMCR_FULLDPLX | BMCR_SPEED1000, bmcr); -+ if (err) -+ dev_err(mpcs->mdio.dev.parent, -+ "%s: failed to configure mpcs: %pe\n", mpcs->name, -+ ERR_PTR(err)); -+} -+ -+static const struct phylink_pcs_ops marvell_c22_pcs_ops = { -+ .pcs_enable = marvell_c22_pcs_enable, -+ .pcs_disable = marvell_c22_pcs_disable, -+ .pcs_get_state = marvell_c22_pcs_get_state, -+ .pcs_config = marvell_c22_pcs_config, -+ .pcs_an_restart = marvell_c22_pcs_an_restart, -+ .pcs_link_up = marvell_c22_pcs_link_up, -+}; -+ -+static int marvell_c22_pcs_init(struct marvell_c22_pcs *mpcs, -+ struct device *dev, struct mii_bus *bus, -+ unsigned int addr, unsigned int irq) -+{ -+ int err; -+ -+ mpcs->mdio.dev.parent = dev; -+ mpcs->mdio.bus = bus; -+ mpcs->mdio.addr = addr; -+ mpcs->phylink_pcs.ops = &marvell_c22_pcs_ops; -+ mpcs->irq = irq; -+ -+ if (irq) { -+ err = devm_request_threaded_irq(dev, irq, NULL, -+ marvell_c22_pcs_handle_irq, -+ IRQF_ONESHOT, mpcs->name, -+ mpcs); -+ if (err) -+ return err; -+ } -+ -+ return 0; -+} -+ -+static bool mv88e6352_pcs_link_check(struct marvell_c22_pcs *mpcs) -+{ -+ u8 cmode; -+ -+ /* Port 4 can be in auto-media mode. Check that the port is -+ * associated with the mpcs. -+ */ -+ mv88e6xxx_reg_lock(mpcs->chip); -+ mpcs->chip->info->ops->port_get_cmode(mpcs->chip, mpcs->port, &cmode); -+ mv88e6xxx_reg_unlock(mpcs->chip); -+ -+ return cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX || -+ cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || -+ cmode == MV88E6XXX_PORT_STS_CMODE_SGMII; -+} -+ -+static void mv88e6352_pcs_link_change(struct marvell_c22_pcs *mpcs, bool up) -+{ -+ dsa_port_phylink_mac_change(mpcs->chip->ds, mpcs->port, up); -+} -+ -+int mv88e6352_pcs_init(struct mv88e6xxx_chip *chip, int port) -+{ -+ struct marvell_c22_pcs *mpcs; -+ struct mii_bus *bus; -+ struct device *dev; -+ unsigned int irq; -+ int err; -+ -+ err = mv88e6352_g2_scratch_port_has_serdes(chip, port); -+ if (err <= 0) -+ return err; -+ -+ irq = irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ); -+ bus = mv88e6xxx_default_mdio_bus(chip); -+ dev = chip->dev; -+ -+ mpcs = devm_kzalloc(dev, sizeof(*mpcs), GFP_KERNEL); -+ if (!mpcs) -+ return -ENOMEM; -+ -+ snprintf(mpcs->name, sizeof(mpcs->name), -+ "mv88e6xxx-%s-serdes-%d", dev_name(dev), port); -+ -+ mpcs->link_check = mv88e6352_pcs_link_check; -+ mpcs->link_change = mv88e6352_pcs_link_change; -+ mpcs->chip = chip; -+ mpcs->port = port; -+ -+ mv88e6xxx_reg_unlock(chip); -+ err = marvell_c22_pcs_init(mpcs, dev, bus, MV88E6352_ADDR_SERDES, irq); -+ mv88e6xxx_reg_lock(chip); -+ if (err) -+ return err; -+ -+ dsa_port_phylink_set_pcs(chip->ds, port, &mpcs->phylink_pcs); -+ -+ return 0; -+} -diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h -index cbb3ba30caea..84d1e42e4583 100644 ---- a/drivers/net/dsa/mv88e6xxx/serdes.h -+++ b/drivers/net/dsa/mv88e6xxx/serdes.h -@@ -236,4 +236,6 @@ mv88e6xxx_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, int lane) - return chip->info->ops->serdes_irq_status(chip, port, lane); - } - -+int mv88e6352_pcs_init(struct mv88e6xxx_chip *chip, int port); -+ - #endif --- -cgit v1.2.3 - - -From f4d84d01bf4e6a747324e0790238c3c18c62cf12 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Wed, 20 Oct 2021 22:05:29 +0100 -Subject: net: dsa: mv88e6xxx: remove old 88e6352 serdes code - -Signed-off-by: Russell King (Oracle) ---- - drivers/net/dsa/mv88e6xxx/chip.c | 33 ------ - drivers/net/dsa/mv88e6xxx/serdes.c | 206 ------------------------------------- - drivers/net/dsa/mv88e6xxx/serdes.h | 19 ---- - 3 files changed, 258 deletions(-) - -diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c -index 92050955ee4b..5d6318bf6166 100644 ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -4156,13 +4156,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { - .atu_set_hash = mv88e6165_g1_atu_set_hash, - .vtu_getnext = mv88e6352_g1_vtu_getnext, - .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, -- .serdes_get_lane = mv88e6352_serdes_get_lane, - .pcs_init = mv88e6352_pcs_init, -- .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state, -- .serdes_pcs_config = mv88e6352_serdes_pcs_config, -- .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart, -- .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up, -- .serdes_power = mv88e6352_serdes_power, - .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, - .serdes_get_regs = mv88e6352_serdes_get_regs, - .gpio_ops = &mv88e6352_gpio_ops, -@@ -4255,16 +4249,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { - .atu_set_hash = mv88e6165_g1_atu_set_hash, - .vtu_getnext = mv88e6352_g1_vtu_getnext, - .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, -- .serdes_get_lane = mv88e6352_serdes_get_lane, - .pcs_init = mv88e6352_pcs_init, -- .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state, -- .serdes_pcs_config = mv88e6352_serdes_pcs_config, -- .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart, -- .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up, -- .serdes_power = mv88e6352_serdes_power, -- .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, -- .serdes_irq_enable = mv88e6352_serdes_irq_enable, -- .serdes_irq_status = mv88e6352_serdes_irq_status, - .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, - .serdes_get_regs = mv88e6352_serdes_get_regs, - .gpio_ops = &mv88e6352_gpio_ops, -@@ -4541,16 +4526,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { - .atu_set_hash = mv88e6165_g1_atu_set_hash, - .vtu_getnext = mv88e6352_g1_vtu_getnext, - .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, -- .serdes_get_lane = mv88e6352_serdes_get_lane, - .pcs_init = mv88e6352_pcs_init, -- .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state, -- .serdes_pcs_config = mv88e6352_serdes_pcs_config, -- .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart, -- .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up, -- .serdes_power = mv88e6352_serdes_power, -- .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, -- .serdes_irq_enable = mv88e6352_serdes_irq_enable, -- .serdes_irq_status = mv88e6352_serdes_irq_status, - .serdes_get_regs_len = mv88e6352_serdes_get_regs_len, - .serdes_get_regs = mv88e6352_serdes_get_regs, - .gpio_ops = &mv88e6352_gpio_ops, -@@ -4945,16 +4921,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { - .atu_set_hash = mv88e6165_g1_atu_set_hash, - .vtu_getnext = mv88e6352_g1_vtu_getnext, - .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, -- .serdes_get_lane = mv88e6352_serdes_get_lane, - .pcs_init = mv88e6352_pcs_init, -- .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state, -- .serdes_pcs_config = mv88e6352_serdes_pcs_config, -- .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart, -- .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up, -- .serdes_power = mv88e6352_serdes_power, -- .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, -- .serdes_irq_enable = mv88e6352_serdes_irq_enable, -- .serdes_irq_status = mv88e6352_serdes_irq_status, - .gpio_ops = &mv88e6352_gpio_ops, - .avb_ops = &mv88e6352_avb_ops, - .ptp_ops = &mv88e6352_ptp_ops, -diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c -index da54cbadfd63..fe9cf8ee8932 100644 ---- a/drivers/net/dsa/mv88e6xxx/serdes.c -+++ b/drivers/net/dsa/mv88e6xxx/serdes.c -@@ -25,14 +25,6 @@ static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg, - reg, val); - } - --static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg, -- u16 val) --{ -- return mv88e6xxx_phy_page_write(chip, MV88E6352_ADDR_SERDES, -- MV88E6352_SERDES_PAGE_FIBER, -- reg, val); --} -- - static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip, - int lane, int device, int reg, u16 *val) - { -@@ -95,154 +87,6 @@ static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, - return 0; - } - --int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, -- bool up) --{ -- u16 val, new_val; -- int err; -- -- err = mv88e6352_serdes_read(chip, MII_BMCR, &val); -- if (err) -- return err; -- -- if (up) -- new_val = val & ~BMCR_PDOWN; -- else -- new_val = val | BMCR_PDOWN; -- -- if (val != new_val) -- err = mv88e6352_serdes_write(chip, MII_BMCR, new_val); -- -- return err; --} -- --int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, -- int lane, unsigned int mode, -- phy_interface_t interface, -- const unsigned long *advertise) --{ -- u16 adv, bmcr, val; -- bool changed; -- int err; -- -- switch (interface) { -- case PHY_INTERFACE_MODE_SGMII: -- adv = 0x0001; -- break; -- -- case PHY_INTERFACE_MODE_1000BASEX: -- adv = linkmode_adv_to_mii_adv_x(advertise, -- ETHTOOL_LINK_MODE_1000baseX_Full_BIT); -- break; -- -- default: -- return 0; -- } -- -- err = mv88e6352_serdes_read(chip, MII_ADVERTISE, &val); -- if (err) -- return err; -- -- changed = val != adv; -- if (changed) { -- err = mv88e6352_serdes_write(chip, MII_ADVERTISE, adv); -- if (err) -- return err; -- } -- -- err = mv88e6352_serdes_read(chip, MII_BMCR, &val); -- if (err) -- return err; -- -- if (phylink_autoneg_inband(mode)) -- bmcr = val | BMCR_ANENABLE; -- else -- bmcr = val & ~BMCR_ANENABLE; -- -- if (bmcr == val) -- return changed; -- -- return mv88e6352_serdes_write(chip, MII_BMCR, bmcr); --} -- --int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, -- int lane, struct phylink_link_state *state) --{ -- u16 lpa, status; -- int err; -- -- err = mv88e6352_serdes_read(chip, 0x11, &status); -- if (err) { -- dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err); -- return err; -- } -- -- err = mv88e6352_serdes_read(chip, MII_LPA, &lpa); -- if (err) { -- dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err); -- return err; -- } -- -- return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state); --} -- --int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, -- int lane) --{ -- u16 bmcr; -- int err; -- -- err = mv88e6352_serdes_read(chip, MII_BMCR, &bmcr); -- if (err) -- return err; -- -- return mv88e6352_serdes_write(chip, MII_BMCR, bmcr | BMCR_ANRESTART); --} -- --int mv88e6352_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port, -- int lane, int speed, int duplex) --{ -- u16 val, bmcr; -- int err; -- -- err = mv88e6352_serdes_read(chip, MII_BMCR, &val); -- if (err) -- return err; -- -- bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000); -- switch (speed) { -- case SPEED_1000: -- bmcr |= BMCR_SPEED1000; -- break; -- case SPEED_100: -- bmcr |= BMCR_SPEED100; -- break; -- case SPEED_10: -- break; -- } -- -- if (duplex == DUPLEX_FULL) -- bmcr |= BMCR_FULLDPLX; -- -- if (bmcr == val) -- return 0; -- -- return mv88e6352_serdes_write(chip, MII_BMCR, bmcr); --} -- --int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) --{ -- u8 cmode = chip->ports[port].cmode; -- int lane = -ENODEV; -- -- if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) || -- (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) || -- (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII)) -- lane = 0xff; /* Unused */ -- -- return lane; --} -- - struct mv88e6352_serdes_hw_stat { - char string[ETH_GSTRING_LEN]; - int sizeof_stat; -@@ -335,56 +179,6 @@ int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, - return ARRAY_SIZE(mv88e6352_serdes_hw_stats); - } - --static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port) --{ -- u16 bmsr; -- int err; -- -- /* If the link has dropped, we want to know about it. */ -- err = mv88e6352_serdes_read(chip, MII_BMSR, &bmsr); -- if (err) { -- dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err); -- return; -- } -- -- dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS)); --} -- --irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, -- int lane) --{ -- irqreturn_t ret = IRQ_NONE; -- u16 status; -- int err; -- -- err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status); -- if (err) -- return ret; -- -- if (status & MV88E6352_SERDES_INT_LINK_CHANGE) { -- ret = IRQ_HANDLED; -- mv88e6352_serdes_irq_link(chip, port); -- } -- -- return ret; --} -- --int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, -- bool enable) --{ -- u16 val = 0; -- -- if (enable) -- val |= MV88E6352_SERDES_INT_LINK_CHANGE; -- -- return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, val); --} -- --unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) --{ -- return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ); --} -- - int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port) - { - int err; -diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h -index 84d1e42e4583..1dec34a16716 100644 ---- a/drivers/net/dsa/mv88e6xxx/serdes.h -+++ b/drivers/net/dsa/mv88e6xxx/serdes.h -@@ -99,42 +99,27 @@ - - int mv88e6185_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); - int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); --int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); - int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); - int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); - int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); --int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, -- int lane, unsigned int mode, -- phy_interface_t interface, -- const unsigned long *advertise); - int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, - int lane, unsigned int mode, - phy_interface_t interface, - const unsigned long *advertise); - int mv88e6185_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state); --int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, -- int lane, struct phylink_link_state *state); - int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state); - int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state); --int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, -- int lane); - int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, - int lane); --int mv88e6352_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port, -- int lane, int speed, int duplex); - int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port, - int lane, int speed, int duplex); --unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, -- int port); - unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, - int port); - int mv88e6185_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - bool up); --int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, -- bool on); - int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - bool on); - int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, -@@ -142,16 +127,12 @@ int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip); - int mv88e6097_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, - bool enable); --int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, -- bool enable); - int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, - bool enable); - int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, - int lane, bool enable); - irqreturn_t mv88e6097_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, - int lane); --irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, -- int lane); - irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, - int lane); - irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, --- -cgit v1.2.3 - - -From 24016b33c7042f638ed0f87b365aec0ecc0f7690 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 29 Jun 2020 23:16:21 +0100 -Subject: phy: armada-38x: further augmentation of setup - -Further augmentation of the comphy setup. - -Signed-off-by: Russell King ---- - arch/arm/boot/dts/armada-38x.dtsi | 5 +- - drivers/phy/marvell/phy-armada38x-comphy.c | 147 +++++++++++++++++++++++++---- - 2 files changed, 132 insertions(+), 20 deletions(-) - -diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi -index 9b1a24cc5e91..404943b5cdac 100644 ---- a/arch/arm/boot/dts/armada-38x.dtsi -+++ b/arch/arm/boot/dts/armada-38x.dtsi -@@ -342,8 +342,9 @@ - - comphy: phy@18300 { - compatible = "marvell,armada-380-comphy"; -- reg-names = "comphy", "conf"; -- reg = <0x18300 0x100>, <0x18460 4>; -+ reg-names = "comphy", "pipe", "conf"; -+ reg = <0x18300 0x100>, <0xa0000 0x3000>, -+ <0x18460 4>; - #address-cells = <1>; - #size-cells = <0>; - -diff --git a/drivers/phy/marvell/phy-armada38x-comphy.c b/drivers/phy/marvell/phy-armada38x-comphy.c -index 0fe408964334..0e86f484269c 100644 ---- a/drivers/phy/marvell/phy-armada38x-comphy.c -+++ b/drivers/phy/marvell/phy-armada38x-comphy.c -@@ -15,32 +15,49 @@ - #define MAX_A38X_COMPHY 6 - #define MAX_A38X_PORTS 3 - -+/* Common PHY registers */ -+#define COMPHY_REG_SIZE 0x28 - #define COMPHY_CFG1 0x00 -+#define COMPHY_CFG1_RX_INIT BIT(30) - #define COMPHY_CFG1_GEN_TX(x) ((x) << 26) - #define COMPHY_CFG1_GEN_TX_MSK COMPHY_CFG1_GEN_TX(15) - #define COMPHY_CFG1_GEN_RX(x) ((x) << 22) - #define COMPHY_CFG1_GEN_RX_MSK COMPHY_CFG1_GEN_RX(15) -+#define COMPHY_CFG1_POWER_UP_TX BIT(18) -+#define COMPHY_CFG1_POWER_UP_RX BIT(17) -+#define COMPHY_CFG1_POWER_UP_PLL BIT(16) - #define GEN_SGMII_1_25GBPS 6 - #define GEN_SGMII_3_125GBPS 8 - - #define COMPHY_STAT1 0x18 - #define COMPHY_STAT1_PLL_RDY_TX BIT(3) - #define COMPHY_STAT1_PLL_RDY_RX BIT(2) -+#define COMPHY_STAT1_RX_INIT_DONE BIT(0) - - #define COMPHY_SELECTOR 0xfc - -+/* Common PHY and Pipe Registers */ -+#define PIPE_REG_SIZE 0x800 -+#define PIPE_POWER_CTRL 0x148 -+#define PIPE_POWER_CTRL_SFT_RST_NO_REG BIT(10) -+/* u-boot sets bit 0 during comphy initialisation, but it is undocumented */ -+#define PIPE_POWER_CTRL_BIT0 BIT(0) -+ - struct a38x_comphy; - - struct a38x_comphy_lane { - void __iomem *base; -+ void __iomem *pipe; - struct a38x_comphy *priv; - unsigned int n; - - int port; -+ u8 gen; - }; - - struct a38x_comphy { - void __iomem *base; -+ void __iomem *pipe; - void __iomem *conf; - struct device *dev; - struct a38x_comphy_lane lane[MAX_A38X_COMPHY]; -@@ -88,6 +105,7 @@ static void a38x_comphy_set_speed(struct a38x_comphy_lane *lane, - COMPHY_CFG1_GEN_RX(gen_rx)); - } - -+/* Poll every 1ms for 150ms for a status */ - static int a38x_comphy_poll(struct a38x_comphy_lane *lane, - unsigned int offset, u32 mask, u32 value) - { -@@ -105,6 +123,97 @@ static int a38x_comphy_poll(struct a38x_comphy_lane *lane, - return ret; - } - -+static int a38x_comphy_power_up(struct a38x_comphy_lane *lane) -+{ -+ /* Power up TX, RX and PLL */ -+ a38x_comphy_set_reg(lane, COMPHY_CFG1, 0, -+ COMPHY_CFG1_POWER_UP_TX | COMPHY_CFG1_POWER_UP_RX | -+ COMPHY_CFG1_POWER_UP_PLL); -+ -+ /* Wait for power up */ -+ return a38x_comphy_poll(lane, COMPHY_STAT1, -+ COMPHY_STAT1_PLL_RDY_TX | -+ COMPHY_STAT1_PLL_RDY_RX, -+ COMPHY_STAT1_PLL_RDY_TX | -+ COMPHY_STAT1_PLL_RDY_RX); -+} -+ -+static int a38x_comphy_rx_init(struct a38x_comphy_lane *lane) -+{ -+ int ret; -+ -+ /* Perform RX init */ -+ a38x_comphy_set_reg(lane, COMPHY_CFG1, 0, COMPHY_CFG1_RX_INIT); -+ -+ /* Wait for RX init done */ -+ ret = a38x_comphy_poll(lane, COMPHY_STAT1, COMPHY_STAT1_RX_INIT_DONE, -+ COMPHY_STAT1_RX_INIT_DONE); -+ -+ /* Clear RX init */ -+ a38x_comphy_set_reg(lane, COMPHY_CFG1, COMPHY_CFG1_RX_INIT, 0); -+ -+ return ret; -+} -+ -+static int a38x_comphy_power_off(struct phy *phy) -+{ -+ struct a38x_comphy_lane *lane = phy_get_drvdata(phy); -+ -+ a38x_set_conf(lane, false); -+ -+ /* Soft reset */ -+ if (lane->pipe) { -+ u32 rst = PIPE_POWER_CTRL_SFT_RST_NO_REG | PIPE_POWER_CTRL_BIT0; -+ u32 val; -+ -+ val = readl_relaxed(lane->pipe + PIPE_POWER_CTRL); -+ writel(val | rst, lane->pipe + PIPE_POWER_CTRL); -+ } -+ -+ a38x_comphy_set_reg(lane, COMPHY_CFG1, -+ COMPHY_CFG1_POWER_UP_TX | COMPHY_CFG1_POWER_UP_RX | -+ COMPHY_CFG1_POWER_UP_PLL, 0); -+ -+ return 0; -+} -+ -+static int a38x_comphy_power_on(struct phy *phy) -+{ -+ struct a38x_comphy_lane *lane = phy_get_drvdata(phy); -+ int ret; -+ -+ /* Program the GEN settings */ -+ a38x_comphy_set_speed(lane, lane->gen, lane->gen); -+ -+ /* Soft reset */ -+ if (lane->pipe) { -+ u32 rst = PIPE_POWER_CTRL_SFT_RST_NO_REG | PIPE_POWER_CTRL_BIT0; -+ u32 val; -+ -+ val = readl_relaxed(lane->pipe + PIPE_POWER_CTRL); -+ writel(val | rst, lane->pipe + PIPE_POWER_CTRL); -+ writel(val & ~rst, lane->pipe + PIPE_POWER_CTRL); -+ } -+ -+ /* Power up TX, RX and PLL and wait */ -+ ret = a38x_comphy_power_up(lane); -+ if (ret) -+ goto fail; -+ -+ /* Perform RX init */ -+ ret = a38x_comphy_rx_init(lane); -+ if (ret) -+ goto fail; -+ -+ a38x_set_conf(lane, true); -+ -+ return 0; -+ -+fail: -+ a38x_comphy_power_off(phy); -+ return ret; -+} -+ - /* - * We only support changing the speed for comphys configured for GBE. - * Since that is all we do, we only poll for PLL ready status. -@@ -113,7 +222,6 @@ static int a38x_comphy_set_mode(struct phy *phy, enum phy_mode mode, int sub) - { - struct a38x_comphy_lane *lane = phy_get_drvdata(phy); - unsigned int gen; -- int ret; - - if (mode != PHY_MODE_ETHERNET) - return -EINVAL; -@@ -132,23 +240,14 @@ static int a38x_comphy_set_mode(struct phy *phy, enum phy_mode mode, int sub) - return -EINVAL; - } - -- a38x_set_conf(lane, false); -- -- a38x_comphy_set_speed(lane, gen, gen); -- -- ret = a38x_comphy_poll(lane, COMPHY_STAT1, -- COMPHY_STAT1_PLL_RDY_TX | -- COMPHY_STAT1_PLL_RDY_RX, -- COMPHY_STAT1_PLL_RDY_TX | -- COMPHY_STAT1_PLL_RDY_RX); -- -- if (ret == 0) -- a38x_set_conf(lane, true); -+ lane->gen = gen; - -- return ret; -+ return 0; - } - - static const struct phy_ops a38x_comphy_ops = { -+ .power_on = a38x_comphy_power_on, -+ .power_off = a38x_comphy_power_off, - .set_mode = a38x_comphy_set_mode, - .owner = THIS_MODULE, - }; -@@ -193,6 +292,7 @@ static int a38x_comphy_probe(struct platform_device *pdev) - struct a38x_comphy *priv; - struct resource *res; - void __iomem *base; -+ void __iomem *pipe = NULL; - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) -@@ -202,8 +302,16 @@ static int a38x_comphy_probe(struct platform_device *pdev) - if (IS_ERR(base)) - return PTR_ERR(base); - -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pipe"); -+ if (res) { -+ pipe = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ } -+ - priv->dev = &pdev->dev; - priv->base = base; -+ priv->pipe = pipe; - - /* Optional */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "conf"); -@@ -230,16 +338,19 @@ static int a38x_comphy_probe(struct platform_device *pdev) - continue; - } - -+ priv->lane[val].base = base + COMPHY_REG_SIZE * val; -+ if (pipe) -+ priv->lane[val].pipe = pipe + PIPE_REG_SIZE * val; -+ priv->lane[val].priv = priv; -+ priv->lane[val].n = val; -+ priv->lane[val].port = -1; -+ - phy = devm_phy_create(&pdev->dev, child, &a38x_comphy_ops); - if (IS_ERR(phy)) { - of_node_put(child); - return PTR_ERR(phy); - } - -- priv->lane[val].base = base + 0x28 * val; -- priv->lane[val].priv = priv; -- priv->lane[val].n = val; -- priv->lane[val].port = -1; - phy_set_drvdata(phy, &priv->lane[val]); - } - --- -cgit v1.2.3 - - -From 9bf307c0ff406cdb3012b70f1e24e405e11e5072 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Wed, 8 Jul 2020 11:37:25 +0100 -Subject: net: mvneta: program 1ms autonegotiation clock divisor - -Program the 1ms autonegotiation clock divisor according to the clocking -rate of neta - without this, the 1ms clock ticks at about 660us on -Armada 38x configured for 250MHz. Bring this into correct specification. - -Signed-off-by: Russell King ---- - drivers/net/ethernet/marvell/mvneta.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c -index c92081d0b257..73c197edc7be 100644 ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -3951,7 +3951,7 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - } else if (state->interface == PHY_INTERFACE_MODE_SGMII) { - /* SGMII mode receives the state from the PHY */ - new_ctrl2 |= MVNETA_GMAC2_INBAND_AN_ENABLE; -- new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE; -+ new_clk = MVNETA_GMAC_1MS_CLOCK_ENABLE; - new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN | - MVNETA_GMAC_FORCE_LINK_PASS | - MVNETA_GMAC_CONFIG_MII_SPEED | -@@ -3963,7 +3963,7 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - } else { - /* 802.3z negotiation - only 1000base-X */ - new_ctrl0 |= MVNETA_GMAC0_PORT_1000BASE_X; -- new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE; -+ new_clk = MVNETA_GMAC_1MS_CLOCK_ENABLE; - new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN | - MVNETA_GMAC_FORCE_LINK_PASS | - MVNETA_GMAC_CONFIG_MII_SPEED)) | -@@ -3976,6 +3976,10 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - new_an |= MVNETA_GMAC_AN_FLOW_CTRL_EN; - } - -+ /* Set the 1ms clock divisor */ -+ if (new_clk == MVNETA_GMAC_1MS_CLOCK_ENABLE) -+ new_clk |= clk_get_rate(pp->clk) / 1000; -+ - /* Armada 370 documentation says we can only change the port mode - * and in-band enable when the link is down, so force it down - * while making these changes. We also do this for GMAC_CTRL2 --- -cgit v1.2.3 - - -From f3657da2fab0d00c2dedc0bdfd1dd57ec1bbe03f Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Sun, 28 Jun 2020 13:03:47 +0100 -Subject: net: mvneta: convert to use mac_prepare()/mac_finish() - -Convert mvneta to use the mac_prepare() and mac_finish() methods in -preparation to converting mvneta to split-PCS support. - -Signed-off-by: Russell King ---- - drivers/net/ethernet/marvell/mvneta.c | 103 ++++++++++++++++++++++------------ - 1 file changed, 68 insertions(+), 35 deletions(-) - -diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c -index 73c197edc7be..3f7f2d3c6363 100644 ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -3908,6 +3908,40 @@ static void mvneta_mac_an_restart(struct phylink_config *config) - gmac_an & ~MVNETA_GMAC_INBAND_RESTART_AN); - } - -+static int mvneta_mac_prepare(struct phylink_config *config, unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct net_device *ndev = to_net_dev(config->dev); -+ struct mvneta_port *pp = netdev_priv(ndev); -+ u32 val; -+ -+ if (pp->phy_interface != interface || -+ phylink_autoneg_inband(mode)) { -+ /* Force the link down when changing the interface or if in -+ * in-band mode. According to Armada 370 documentation, we -+ * can only change the port mode and in-band enable when the -+ * link is down. -+ */ -+ val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); -+ val &= ~MVNETA_GMAC_FORCE_LINK_PASS; -+ val |= MVNETA_GMAC_FORCE_LINK_DOWN; -+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); -+ } -+ -+ if (pp->phy_interface != interface) -+ WARN_ON(phy_power_off(pp->comphy)); -+ -+ /* Enable the 1ms clock */ -+ if (phylink_autoneg_inband(mode)) { -+ unsigned long rate = clk_get_rate(pp->clk); -+ -+ mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, -+ MVNETA_GMAC_1MS_CLOCK_ENABLE | (rate / 1000)); -+ } -+ -+ return 0; -+} -+ - static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - const struct phylink_link_state *state) - { -@@ -3916,14 +3950,12 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - u32 new_ctrl0, gmac_ctrl0 = mvreg_read(pp, MVNETA_GMAC_CTRL_0); - u32 new_ctrl2, gmac_ctrl2 = mvreg_read(pp, MVNETA_GMAC_CTRL_2); - u32 new_ctrl4, gmac_ctrl4 = mvreg_read(pp, MVNETA_GMAC_CTRL_4); -- u32 new_clk, gmac_clk = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); - u32 new_an, gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); - - new_ctrl0 = gmac_ctrl0 & ~MVNETA_GMAC0_PORT_1000BASE_X; - new_ctrl2 = gmac_ctrl2 & ~(MVNETA_GMAC2_INBAND_AN_ENABLE | - MVNETA_GMAC2_PORT_RESET); - new_ctrl4 = gmac_ctrl4 & ~(MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE); -- new_clk = gmac_clk & ~MVNETA_GMAC_1MS_CLOCK_ENABLE; - new_an = gmac_an & ~(MVNETA_GMAC_INBAND_AN_ENABLE | - MVNETA_GMAC_INBAND_RESTART_AN | - MVNETA_GMAC_AN_SPEED_EN | -@@ -3951,10 +3983,7 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - } else if (state->interface == PHY_INTERFACE_MODE_SGMII) { - /* SGMII mode receives the state from the PHY */ - new_ctrl2 |= MVNETA_GMAC2_INBAND_AN_ENABLE; -- new_clk = MVNETA_GMAC_1MS_CLOCK_ENABLE; -- new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN | -- MVNETA_GMAC_FORCE_LINK_PASS | -- MVNETA_GMAC_CONFIG_MII_SPEED | -+ new_an = (new_an & ~(MVNETA_GMAC_CONFIG_MII_SPEED | - MVNETA_GMAC_CONFIG_GMII_SPEED | - MVNETA_GMAC_CONFIG_FULL_DUPLEX)) | - MVNETA_GMAC_INBAND_AN_ENABLE | -@@ -3963,10 +3992,7 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - } else { - /* 802.3z negotiation - only 1000base-X */ - new_ctrl0 |= MVNETA_GMAC0_PORT_1000BASE_X; -- new_clk = MVNETA_GMAC_1MS_CLOCK_ENABLE; -- new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN | -- MVNETA_GMAC_FORCE_LINK_PASS | -- MVNETA_GMAC_CONFIG_MII_SPEED)) | -+ new_an = (new_an & ~MVNETA_GMAC_CONFIG_MII_SPEED) | - MVNETA_GMAC_INBAND_AN_ENABLE | - MVNETA_GMAC_CONFIG_GMII_SPEED | - /* The MAC only supports FD mode */ -@@ -3976,43 +4002,18 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - new_an |= MVNETA_GMAC_AN_FLOW_CTRL_EN; - } - -- /* Set the 1ms clock divisor */ -- if (new_clk == MVNETA_GMAC_1MS_CLOCK_ENABLE) -- new_clk |= clk_get_rate(pp->clk) / 1000; -- -- /* Armada 370 documentation says we can only change the port mode -- * and in-band enable when the link is down, so force it down -- * while making these changes. We also do this for GMAC_CTRL2 -- */ -- if ((new_ctrl0 ^ gmac_ctrl0) & MVNETA_GMAC0_PORT_1000BASE_X || -- (new_ctrl2 ^ gmac_ctrl2) & MVNETA_GMAC2_INBAND_AN_ENABLE || -- (new_an ^ gmac_an) & MVNETA_GMAC_INBAND_AN_ENABLE) { -- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, -- (gmac_an & ~MVNETA_GMAC_FORCE_LINK_PASS) | -- MVNETA_GMAC_FORCE_LINK_DOWN); -- } -- -- - /* When at 2.5G, the link partner can send frames with shortened - * preambles. - */ - if (state->interface == PHY_INTERFACE_MODE_2500BASEX) - new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE; - -- if (pp->phy_interface != state->interface) { -- if (pp->comphy) -- WARN_ON(phy_power_off(pp->comphy)); -- WARN_ON(mvneta_config_interface(pp, state->interface)); -- } -- - if (new_ctrl0 != gmac_ctrl0) - mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0); - if (new_ctrl2 != gmac_ctrl2) - mvreg_write(pp, MVNETA_GMAC_CTRL_2, new_ctrl2); - if (new_ctrl4 != gmac_ctrl4) - mvreg_write(pp, MVNETA_GMAC_CTRL_4, new_ctrl4); -- if (new_clk != gmac_clk) -- mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, new_clk); - if (new_an != gmac_an) - mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, new_an); - -@@ -4023,6 +4024,36 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - } - } - -+static int mvneta_mac_finish(struct phylink_config *config, unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct net_device *ndev = to_net_dev(config->dev); -+ struct mvneta_port *pp = netdev_priv(ndev); -+ u32 val, clk; -+ -+ /* Disable 1ms clock if not in in-band mode */ -+ if (!phylink_autoneg_inband(mode)) { -+ clk = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); -+ clk &= ~MVNETA_GMAC_1MS_CLOCK_ENABLE; -+ mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, clk); -+ } -+ -+ if (pp->phy_interface != interface) -+ /* Enable the Serdes PHY */ -+ WARN_ON(mvneta_config_interface(pp, interface)); -+ -+ /* Allow the link to come up if in in-band mode, otherwise the -+ * link is forced via mac_link_down()/mac_link_up() -+ */ -+ if (phylink_autoneg_inband(mode)) { -+ val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); -+ val &= ~MVNETA_GMAC_FORCE_LINK_DOWN; -+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); -+ } -+ -+ return 0; -+} -+ - static void mvneta_set_eee(struct mvneta_port *pp, bool enable) - { - u32 lpi_ctl1; -@@ -4112,7 +4143,9 @@ static const struct phylink_mac_ops mvneta_phylink_ops = { - .validate = mvneta_validate, - .mac_pcs_get_state = mvneta_mac_pcs_get_state, - .mac_an_restart = mvneta_mac_an_restart, -+ .mac_prepare = mvneta_mac_prepare, - .mac_config = mvneta_mac_config, -+ .mac_finish = mvneta_mac_finish, - .mac_link_down = mvneta_mac_link_down, - .mac_link_up = mvneta_mac_link_up, - }; --- -cgit v1.2.3 - - -From c6c43d068a02f7ccf3e792a6824149024133bba4 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 22 Jun 2020 17:21:43 +0100 -Subject: net: mvneta: convert to phylink pcs operations - -An initial stab at converting mvneta to PCS operations. There's a few -FIXMEs to be solved. - -Signed-off-by: Russell King ---- - drivers/net/ethernet/marvell/mvneta.c | 178 +++++++++++++++++++++------------- - 1 file changed, 109 insertions(+), 69 deletions(-) - -diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c -index 3f7f2d3c6363..423c369906a4 100644 ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -499,6 +499,7 @@ struct mvneta_port { - unsigned int tx_csum_limit; - struct phylink *phylink; - struct phylink_config phylink_config; -+ struct phylink_pcs phylink_pcs; - struct phy *comphy; - - struct mvneta_bm *bm_priv; -@@ -3820,6 +3821,111 @@ static int mvneta_set_mac_addr(struct net_device *dev, void *addr) - return 0; - } - -+static struct mvneta_port *mvneta_pcs_to_port(struct phylink_pcs *pcs) -+{ -+ return container_of(pcs, struct mvneta_port, phylink_pcs); -+} -+ -+static void mvneta_pcs_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state) -+{ -+ struct mvneta_port *pp = mvneta_pcs_to_port(pcs); -+ u32 gmac_stat; -+ -+ gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS); -+ -+ if (gmac_stat & MVNETA_GMAC_SPEED_1000) -+ state->speed = -+ state->interface == PHY_INTERFACE_MODE_2500BASEX ? -+ SPEED_2500 : SPEED_1000; -+ else if (gmac_stat & MVNETA_GMAC_SPEED_100) -+ state->speed = SPEED_100; -+ else -+ state->speed = SPEED_10; -+ -+ state->an_complete = !!(gmac_stat & MVNETA_GMAC_AN_COMPLETE); -+ state->link = !!(gmac_stat & MVNETA_GMAC_LINK_UP); -+ state->duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX); -+ -+ if (gmac_stat & MVNETA_GMAC_RX_FLOW_CTRL_ENABLE) -+ state->pause |= MLO_PAUSE_RX; -+ if (gmac_stat & MVNETA_GMAC_TX_FLOW_CTRL_ENABLE) -+ state->pause |= MLO_PAUSE_TX; -+} -+ -+static int mvneta_pcs_config(struct phylink_pcs *pcs, -+ unsigned int mode, phy_interface_t interface, -+ const unsigned long *advertising, -+ bool permit_pause_to_mac) -+{ -+ struct mvneta_port *pp = mvneta_pcs_to_port(pcs); -+ u32 mask, val, an, old_an, changed; -+ -+ mask = MVNETA_GMAC_INBAND_AN_ENABLE | -+ MVNETA_GMAC_INBAND_RESTART_AN | -+ MVNETA_GMAC_AN_SPEED_EN | -+ MVNETA_GMAC_AN_FLOW_CTRL_EN | -+ MVNETA_GMAC_AN_DUPLEX_EN; -+ -+ if (phylink_autoneg_inband(mode)) { -+ mask |= MVNETA_GMAC_CONFIG_MII_SPEED | -+ MVNETA_GMAC_CONFIG_GMII_SPEED | -+ MVNETA_GMAC_CONFIG_FULL_DUPLEX; -+ val = MVNETA_GMAC_INBAND_AN_ENABLE; -+ -+ if (state->interface == PHY_INTERFACE_MODE_SGMII) { -+ /* SGMII mode receives the speed and duplex from PHY */ -+ val |= MVNETA_GMAC_AN_SPEED_EN | -+ MVNETA_GMAC_AN_DUPLEX_EN; -+ } else { -+ /* 802.3z mode has fixed speed and duplex */ -+ val |= MVNETA_GMAC_CONFIG_GMII_SPEED | -+ MVNETA_GMAC_CONFIG_FULL_DUPLEX; -+ -+ /* The FLOW_CTRL_EN bit selects either the hardware -+ * automatically or the CONFIG_FLOW_CTRL manually -+ * controls the GMAC pause mode. -+ */ -+ if (permit_pause_to_mac) -+ val |= MVNETA_GMAC_AN_FLOW_CTRL_EN; -+ -+ /* Update the advertisement bits */ -+ mask |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL; -+ if (phylink_test(advertising, Pause)) -+ val |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL; -+ } -+ } else { -+ /* Phy or fixed speed - disable in-band AN modes */ -+ val = 0; -+ } -+ -+ old_an = an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); -+ an = (an & ~mask) | val; -+ changed = old_an ^ an; -+ if (changed) -+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, an); -+ -+ /* We are only interested in the advertisement bits changing */ -+ return !!(changed & MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL); -+} -+ -+static void mvneta_pcs_an_restart(struct phylink_pcs *pcs) -+{ -+ struct mvneta_port *pp = mvneta_pcs_to_port(pcs); -+ u32 gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); -+ -+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, -+ gmac_an | MVNETA_GMAC_INBAND_RESTART_AN); -+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, -+ gmac_an & ~MVNETA_GMAC_INBAND_RESTART_AN); -+} -+ -+static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = { -+ .pcs_get_state = mvneta_pcs_get_state, -+ .pcs_config = mvneta_pcs_config, -+ .pcs_an_restart = mvneta_pcs_an_restart, -+}; -+ - static void mvneta_validate(struct phylink_config *config, - unsigned long *supported, - struct phylink_link_state *state) -@@ -3867,47 +3973,6 @@ static void mvneta_validate(struct phylink_config *config, - linkmode_and(state->advertising, state->advertising, mask); - } - --static void mvneta_mac_pcs_get_state(struct phylink_config *config, -- struct phylink_link_state *state) --{ -- struct net_device *ndev = to_net_dev(config->dev); -- struct mvneta_port *pp = netdev_priv(ndev); -- u32 gmac_stat; -- -- gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS); -- -- if (gmac_stat & MVNETA_GMAC_SPEED_1000) -- state->speed = -- state->interface == PHY_INTERFACE_MODE_2500BASEX ? -- SPEED_2500 : SPEED_1000; -- else if (gmac_stat & MVNETA_GMAC_SPEED_100) -- state->speed = SPEED_100; -- else -- state->speed = SPEED_10; -- -- state->an_complete = !!(gmac_stat & MVNETA_GMAC_AN_COMPLETE); -- state->link = !!(gmac_stat & MVNETA_GMAC_LINK_UP); -- state->duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX); -- -- state->pause = 0; -- if (gmac_stat & MVNETA_GMAC_RX_FLOW_CTRL_ENABLE) -- state->pause |= MLO_PAUSE_RX; -- if (gmac_stat & MVNETA_GMAC_TX_FLOW_CTRL_ENABLE) -- state->pause |= MLO_PAUSE_TX; --} -- --static void mvneta_mac_an_restart(struct phylink_config *config) --{ -- struct net_device *ndev = to_net_dev(config->dev); -- struct mvneta_port *pp = netdev_priv(ndev); -- u32 gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); -- -- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, -- gmac_an | MVNETA_GMAC_INBAND_RESTART_AN); -- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, -- gmac_an & ~MVNETA_GMAC_INBAND_RESTART_AN); --} -- - static int mvneta_mac_prepare(struct phylink_config *config, unsigned int mode, - phy_interface_t interface) - { -@@ -3950,18 +4015,11 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - u32 new_ctrl0, gmac_ctrl0 = mvreg_read(pp, MVNETA_GMAC_CTRL_0); - u32 new_ctrl2, gmac_ctrl2 = mvreg_read(pp, MVNETA_GMAC_CTRL_2); - u32 new_ctrl4, gmac_ctrl4 = mvreg_read(pp, MVNETA_GMAC_CTRL_4); -- u32 new_an, gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); - - new_ctrl0 = gmac_ctrl0 & ~MVNETA_GMAC0_PORT_1000BASE_X; - new_ctrl2 = gmac_ctrl2 & ~(MVNETA_GMAC2_INBAND_AN_ENABLE | - MVNETA_GMAC2_PORT_RESET); - new_ctrl4 = gmac_ctrl4 & ~(MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE); -- new_an = gmac_an & ~(MVNETA_GMAC_INBAND_AN_ENABLE | -- MVNETA_GMAC_INBAND_RESTART_AN | -- MVNETA_GMAC_AN_SPEED_EN | -- MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL | -- MVNETA_GMAC_AN_FLOW_CTRL_EN | -- MVNETA_GMAC_AN_DUPLEX_EN); - - /* Even though it might look weird, when we're configured in - * SGMII or QSGMII mode, the RGMII bit needs to be set. -@@ -3973,9 +4031,6 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - phy_interface_mode_is_8023z(state->interface)) - new_ctrl2 |= MVNETA_GMAC2_PCS_ENABLE; - -- if (phylink_test(state->advertising, Pause)) -- new_an |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL; -- - if (!phylink_autoneg_inband(mode)) { - /* Phy or fixed speed - nothing to do, leave the - * configured speed, duplex and flow control as-is. -@@ -3983,23 +4038,9 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - } else if (state->interface == PHY_INTERFACE_MODE_SGMII) { - /* SGMII mode receives the state from the PHY */ - new_ctrl2 |= MVNETA_GMAC2_INBAND_AN_ENABLE; -- new_an = (new_an & ~(MVNETA_GMAC_CONFIG_MII_SPEED | -- MVNETA_GMAC_CONFIG_GMII_SPEED | -- MVNETA_GMAC_CONFIG_FULL_DUPLEX)) | -- MVNETA_GMAC_INBAND_AN_ENABLE | -- MVNETA_GMAC_AN_SPEED_EN | -- MVNETA_GMAC_AN_DUPLEX_EN; - } else { - /* 802.3z negotiation - only 1000base-X */ - new_ctrl0 |= MVNETA_GMAC0_PORT_1000BASE_X; -- new_an = (new_an & ~MVNETA_GMAC_CONFIG_MII_SPEED) | -- MVNETA_GMAC_INBAND_AN_ENABLE | -- MVNETA_GMAC_CONFIG_GMII_SPEED | -- /* The MAC only supports FD mode */ -- MVNETA_GMAC_CONFIG_FULL_DUPLEX; -- -- if (state->pause & MLO_PAUSE_AN && state->an_enabled) -- new_an |= MVNETA_GMAC_AN_FLOW_CTRL_EN; - } - - /* When at 2.5G, the link partner can send frames with shortened -@@ -4014,8 +4055,6 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - mvreg_write(pp, MVNETA_GMAC_CTRL_2, new_ctrl2); - if (new_ctrl4 != gmac_ctrl4) - mvreg_write(pp, MVNETA_GMAC_CTRL_4, new_ctrl4); -- if (new_an != gmac_an) -- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, new_an); - - if (gmac_ctrl2 & MVNETA_GMAC2_PORT_RESET) { - while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) & -@@ -4141,8 +4180,6 @@ static void mvneta_mac_link_up(struct phylink_config *config, - - static const struct phylink_mac_ops mvneta_phylink_ops = { - .validate = mvneta_validate, -- .mac_pcs_get_state = mvneta_mac_pcs_get_state, -- .mac_an_restart = mvneta_mac_an_restart, - .mac_prepare = mvneta_mac_prepare, - .mac_config = mvneta_mac_config, - .mac_finish = mvneta_mac_finish, -@@ -5275,6 +5312,9 @@ static int mvneta_probe(struct platform_device *pdev) - goto err_clk; - } - -+ pp->phylink_pcs.ops = &mvneta_phylink_pcs_ops; -+ phylink_set_pcs(phylink, &pp->phylink_pcs); -+ - /* Alloc per-cpu port structure */ - pp->ports = alloc_percpu(struct mvneta_pcpu_port); - if (!pp->ports) { --- -cgit v1.2.3 - - -From f5bf12036c77e5ccee1aa0cc9ae31055ff77c3a4 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Thu, 22 Dec 2016 16:03:15 +0000 -Subject: net: mvneta: split out GMAC - -Split out the code handling the GMAC from the rest of the driver. This -block appears to be shared amongst several revisions of the IP. - -Signed-off-by: Russell King ---- - drivers/net/ethernet/marvell/Kconfig | 4 + - drivers/net/ethernet/marvell/Makefile | 1 + - drivers/net/ethernet/marvell/mvgmac.c | 350 ++++++++++++++++++++++++++++++++++ - drivers/net/ethernet/marvell/mvgmac.h | 47 +++++ - drivers/net/ethernet/marvell/mvneta.c | 338 ++++---------------------------- - 5 files changed, 438 insertions(+), 302 deletions(-) - create mode 100644 drivers/net/ethernet/marvell/mvgmac.c - create mode 100644 drivers/net/ethernet/marvell/mvgmac.h - -diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig -index fe0989c0fc25..e9149e6fab10 100644 ---- a/drivers/net/ethernet/marvell/Kconfig -+++ b/drivers/net/ethernet/marvell/Kconfig -@@ -59,6 +59,7 @@ config MVNETA_BM_ENABLE - config MVNETA - tristate "Marvell Armada 370/38x/XP/37xx network interface support" - depends on ARCH_MVEBU || COMPILE_TEST -+ select MVGMAC - select MVMDIO - select PHYLINK - select PAGE_POOL -@@ -71,6 +72,9 @@ config MVNETA - driver, which should be used for the older Marvell SoCs - (Dove, Orion, Discovery, Kirkwood). - -+config MVGMAC -+ tristate -+ - config MVNETA_BM - tristate - depends on !64BIT -diff --git a/drivers/net/ethernet/marvell/Makefile b/drivers/net/ethernet/marvell/Makefile -index 9f88fe822555..b1442ff46abf 100644 ---- a/drivers/net/ethernet/marvell/Makefile -+++ b/drivers/net/ethernet/marvell/Makefile -@@ -7,6 +7,7 @@ obj-$(CONFIG_MVMDIO) += mvmdio.o - obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o - obj-$(CONFIG_MVNETA_BM) += mvneta_bm.o - obj-$(CONFIG_MVNETA) += mvneta.o -+obj-$(CONFIG_MVGMAC) += mvgmac.o - obj-$(CONFIG_MVPP2) += mvpp2/ - obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o - obj-$(CONFIG_SKGE) += skge.o -diff --git a/drivers/net/ethernet/marvell/mvgmac.c b/drivers/net/ethernet/marvell/mvgmac.c -new file mode 100644 -index 000000000000..aee6dff9f569 ---- /dev/null -+++ b/drivers/net/ethernet/marvell/mvgmac.c -@@ -0,0 +1,350 @@ -+/* -+ * GMAC driver for Marvell network interfaces on Armada SoCs. -+ * -+ * Copyright (C) 2012 Marvell -+ * -+ * Rami Rosen -+ * Thomas Petazzoni -+ * -+ * Split from mvneta and mvpp2 by Russell King. -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+#include -+#include -+#include -+#include -+ -+#include "mvgmac.h" -+ -+enum { -+ GMAC_CTRL0_REG = 0x00, -+ GMAC_CTRL0_PORT_ENABLE = BIT(0), -+ GMAC_CTRL0_PORT_1000BASE_X = BIT(1), -+ GMAC_CTRL0_MAX_RX_SIZE_SHIFT = 2, -+ GMAC_CTRL0_MAX_RX_SIZE_MASK = 0x1fff << GMAC_CTRL0_MAX_RX_SIZE_SHIFT, -+ GMAC_CTRL0_MIB_CNTR_ENABLE = BIT(15), -+ -+ GMAC_CTRL2_REG = 0x08, -+ GMAC_CTRL2_INBAND_AN_SGMII = BIT(0), -+ GMAC_CTRL2_PCS_ENABLE = BIT(3), -+ GMAC_CTRL2_PORT_RGMII = BIT(4), -+ GMAC_CTRL2_PORT_RESET = BIT(6), -+ -+ GMAC_ANEG_REG = 0x0c, -+ GMAC_ANEG_FORCE_LINK_DOWN = BIT(0), -+ GMAC_ANEG_FORCE_LINK_PASS = BIT(1), -+ GMAC_ANEG_INBAND_AN_ENABLE = BIT(2), -+ GMAC_ANEG_AN_BYPASS_ENABLE = BIT(3), -+ GMAC_ANEG_INBAND_RESTART_AN = BIT(4), -+ GMAC_ANEG_MII_SPEED = BIT(5), -+ GMAC_ANEG_GMII_SPEED = BIT(6), -+ GMAC_ANEG_AN_SPEED_ENABLE = BIT(7), -+ GMAC_ANEG_CONFIG_FLOW_CTRL = BIT(8), -+ GMAC_ANEG_ADVERT_SYM_FLOW_CTRL = BIT(9), -+ GMAC_ANEG_AN_FLOW_CTRL_ENABLE = BIT(11), -+ GMAC_ANEG_FULL_DUPLEX = BIT(12), -+ GMAC_ANEG_AN_DUPLEX_ENABLE = BIT(13), -+ -+ GMAC_STATUS_REG = 0x10, -+ MVGMAC_LINK_UP = BIT(0), -+ MVGMAC_SPEED_1000 = BIT(1), -+ MVGMAC_SPEED_100 = BIT(2), -+ MVGMAC_FULL_DUPLEX = BIT(3), -+ MVGMAC_RX_FLOW_CTRL_ENABLE = BIT(4), -+ MVGMAC_TX_FLOW_CTRL_ENABLE = BIT(5), -+ MVGMAC_RX_FLOW_CTRL_ACTIVE = BIT(6), -+ MVGMAC_TX_FLOW_CTRL_ACTIVE = BIT(7), -+ MVGMAC_AN_COMPLETE = BIT(11), -+ MVGMAC_SYNC_OK = BIT(14), -+ -+ GMAC_CTRL4_REG = 0x90, -+ GMAC_CTRL4_SHORT_PREAMBLE_ENABLE = BIT(1), -+ -+ GMAC_LPI_CTRL0_REG = 0xc0, -+ GMAC_LPI_CTRL0_TS = 0xff << 8, -+ GMAC_LPI_CTRL1_REG = 0xc4, -+ GMAC_LPI_CTRL1_REQ_EN = BIT(0), -+ GMAC_LPI_CTRL2_REG = 0xc8, -+ GMAC_LPI_STATUS_REG = 0xcc, -+ GMAC_LPI_CNTR_REG = 0xd0, -+}; -+ -+#define insert(var, mask, val) ({ \ -+ u32 __mask = mask; \ -+ ((var) & ~(__mask)) | (((val) << __ffs(__mask)) & (__mask)); \ -+}) -+ -+static void mvgmac_modify(void __iomem *reg, u32 mask, u32 val) -+{ -+ u32 v; -+ -+ val &= mask; -+ v = readl_relaxed(reg) & ~mask; -+ writel_relaxed(v | val, reg); -+} -+ -+#define mvgmac_set(reg, val) mvgmac_modify(reg, val, val) -+#define mvgmac_clear(reg, val) mvgmac_modify(reg, val, 0) -+ -+/* Change maximum receive size of the port. */ -+void mvgmac_set_max_rx_size(struct mvgmac *gmac, size_t max_rx_size) -+{ -+ int size = (max_rx_size - MARVELL_HEADER_SIZE) / 2; -+ -+ mvgmac_modify(gmac->base + GMAC_CTRL0_REG, -+ GMAC_CTRL0_MAX_RX_SIZE_MASK, -+ FIELD_PREP(GMAC_CTRL0_MAX_RX_SIZE_MASK, size)); -+} -+EXPORT_SYMBOL_GPL(mvgmac_set_max_rx_size); -+ -+/* Enable the port by setting the port enable bit of the MAC control register */ -+void mvgmac_port_enable(struct mvgmac *gmac) -+{ -+ mvgmac_set(gmac->base + GMAC_CTRL0_REG, -+ GMAC_CTRL0_PORT_ENABLE | GMAC_CTRL0_MIB_CNTR_ENABLE); -+} -+EXPORT_SYMBOL_GPL(mvgmac_port_enable); -+ -+/* Disable the port */ -+void mvgmac_port_disable(struct mvgmac *gmac) -+{ -+ mvgmac_clear(gmac->base + GMAC_CTRL0_REG, GMAC_CTRL0_PORT_ENABLE); -+} -+EXPORT_SYMBOL_GPL(mvgmac_port_disable); -+ -+void mvgmac_link_unforce(struct mvgmac *gmac) -+{ -+ mvgmac_clear(gmac->base + GMAC_ANEG_REG, -+ GMAC_ANEG_FORCE_LINK_PASS | GMAC_ANEG_FORCE_LINK_DOWN); -+} -+EXPORT_SYMBOL_GPL(mvgmac_link_unforce); -+ -+void mvgmac_link_force_down(struct mvgmac *gmac) -+{ -+ mvgmac_modify(gmac->base + GMAC_ANEG_REG, -+ GMAC_ANEG_FORCE_LINK_PASS | GMAC_ANEG_FORCE_LINK_DOWN, -+ GMAC_ANEG_FORCE_LINK_DOWN); -+} -+EXPORT_SYMBOL_GPL(mvgmac_link_force_down); -+ -+void mvgmac_link_down(struct mvgmac *gmac, int mode) -+{ -+ if (!phylink_autoneg_inband(mode)) -+ mvgmac_link_force_down(gmac); -+} -+EXPORT_SYMBOL_GPL(mvgmac_link_down); -+ -+void mvgmac_link_up(struct mvgmac *gmac, int mode, int speed, int duplex, -+ bool tx_pause, bool rx_pause) -+{ -+ u32 an_mask, an_val; -+ -+ an_mask = GMAC_ANEG_CONFIG_FLOW_CTRL; -+ an_val = FIELD_PREP(GMAC_ANEG_CONFIG_FLOW_CTRL, tx_pause || rx_pause); -+ -+ if (!phylink_autoneg_inband(mode)) { -+ an_mask |= GMAC_ANEG_FORCE_LINK_DOWN | -+ GMAC_ANEG_FORCE_LINK_PASS | -+ GMAC_ANEG_MII_SPEED | -+ GMAC_ANEG_GMII_SPEED | -+ GMAC_ANEG_FULL_DUPLEX; -+ an_val |= GMAC_ANEG_FORCE_LINK_PASS; -+ -+ if (speed == SPEED_1000 || speed == SPEED_2500) -+ an_val |= GMAC_ANEG_GMII_SPEED; -+ else if (speed == SPEED_100) -+ an_val |= GMAC_ANEG_MII_SPEED; -+ -+ if (duplex == DUPLEX_FULL) -+ an_val |= GMAC_ANEG_FULL_DUPLEX; -+ } -+ -+ mvgmac_modify(gmac->base + GMAC_ANEG_REG, an_mask, an_val); -+} -+EXPORT_SYMBOL_GPL(mvgmac_link_up); -+ -+bool mvgmac_link_is_up(struct mvgmac *gmac) -+{ -+ u32 gmac_stat = readl_relaxed(gmac->base + GMAC_STATUS_REG); -+ -+ return !!(gmac_stat & MVGMAC_LINK_UP); -+} -+EXPORT_SYMBOL_GPL(mvgmac_link_is_up); -+ -+void mvgmac_pcs_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state) -+{ -+ struct mvgmac *gmac = pcs_to_mvgmac(pcs); -+ u32 gmac_stat = readl_relaxed(gmac->base + GMAC_STATUS_REG); -+ -+ if (gmac_stat & MVGMAC_SPEED_1000) -+ state->speed = -+ state->interface == PHY_INTERFACE_MODE_2500BASEX ? -+ SPEED_2500 : SPEED_1000; -+ else if (gmac_stat & MVGMAC_SPEED_100) -+ state->speed = SPEED_100; -+ else -+ state->speed = SPEED_10; -+ -+ state->an_complete = !!(gmac_stat & MVGMAC_AN_COMPLETE); -+ state->link = !!(gmac_stat & MVGMAC_LINK_UP); -+ state->duplex = !!(gmac_stat & MVGMAC_FULL_DUPLEX); -+ -+ if (gmac_stat & MVGMAC_RX_FLOW_CTRL_ENABLE) -+ state->pause |= MLO_PAUSE_RX; -+ if (gmac_stat & MVGMAC_TX_FLOW_CTRL_ENABLE) -+ state->pause |= MLO_PAUSE_TX; -+} -+EXPORT_SYMBOL_GPL(mvgmac_pcs_get_state); -+ -+void mvgmac_pcs_an_restart(struct phylink_pcs *pcs) -+{ -+ struct mvgmac *gmac = pcs_to_mvgmac(pcs); -+ u32 gmac_an = readl_relaxed(gmac->base + GMAC_ANEG_REG); -+ -+ writel_relaxed(gmac_an | GMAC_ANEG_INBAND_RESTART_AN, -+ gmac->base + GMAC_ANEG_REG); -+ writel_relaxed(gmac_an & ~GMAC_ANEG_INBAND_RESTART_AN, -+ gmac->base + GMAC_ANEG_REG); -+} -+EXPORT_SYMBOL_GPL(mvgmac_pcs_an_restart); -+ -+int mvgmac_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+ phy_interface_t interface, -+ const unsigned long *advertising, -+ bool permit_pause_to_mac) -+{ -+ struct mvgmac *gmac = pcs_to_mvgmac(pcs); -+ u32 mask, val, an, old_an, changed; -+ -+ mask = GMAC_ANEG_INBAND_AN_ENABLE | -+ GMAC_ANEG_INBAND_RESTART_AN | -+ GMAC_ANEG_AN_SPEED_ENABLE | -+ GMAC_ANEG_AN_FLOW_CTRL_ENABLE | -+ GMAC_ANEG_AN_DUPLEX_ENABLE; -+ -+ if (phylink_autoneg_inband(mode)) { -+ mask |= GMAC_ANEG_MII_SPEED | -+ GMAC_ANEG_GMII_SPEED | -+ GMAC_ANEG_FULL_DUPLEX; -+ val = GMAC_ANEG_INBAND_AN_ENABLE; -+ -+ if (interface == PHY_INTERFACE_MODE_SGMII) { -+ /* SGMII mode receives the speed and duplex from PHY */ -+ val |= GMAC_ANEG_AN_SPEED_ENABLE | -+ GMAC_ANEG_AN_DUPLEX_ENABLE; -+ } else { -+ /* 802.3z mode has fixed speed and duplex */ -+ val |= GMAC_ANEG_GMII_SPEED | -+ GMAC_ANEG_FULL_DUPLEX; -+ -+ /* The FLOW_CTRL_ENABLE bit selects either the hardware -+ * automatically or the GMAC_ANEG_FLOW_CTRL manually -+ * controls the GMAC pause mode. -+ */ -+ if (permit_pause_to_mac) -+ val |= GMAC_ANEG_AN_FLOW_CTRL_ENABLE; -+ -+ /* Update the advertisement bits */ -+ mask |= GMAC_ANEG_ADVERT_SYM_FLOW_CTRL; -+ if (phylink_test(advertising, Pause)) -+ val |= GMAC_ANEG_ADVERT_SYM_FLOW_CTRL; -+ } -+ } else { -+ /* Phy or fixed speed - disable in-band AN modes */ -+ val = 0; -+ } -+ -+ old_an = an = readl_relaxed(gmac->base + GMAC_ANEG_REG); -+ an = (an & ~mask) | val; -+ changed = old_an ^ an; -+ if (changed) -+ writel_relaxed(an, gmac->base + GMAC_ANEG_REG); -+ -+ /* We are only interested in the advertisement bits changing */ -+ return !!(changed & GMAC_ANEG_ADVERT_SYM_FLOW_CTRL); -+} -+EXPORT_SYMBOL_GPL(mvgmac_pcs_config); -+ -+void mvgmac_config_mac(struct mvgmac *gmac, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+ u32 new_ctrl0, gmac_ctrl0 = readl_relaxed(gmac->base + GMAC_CTRL0_REG); -+ u32 new_ctrl2, gmac_ctrl2 = readl_relaxed(gmac->base + GMAC_CTRL2_REG); -+ u32 new_ctrl4, gmac_ctrl4 = readl_relaxed(gmac->base + GMAC_CTRL4_REG); -+ -+ new_ctrl0 = gmac_ctrl0 & ~GMAC_CTRL0_PORT_1000BASE_X; -+ new_ctrl2 = gmac_ctrl2 & ~(GMAC_CTRL2_INBAND_AN_SGMII | -+ GMAC_CTRL2_PORT_RESET); -+ new_ctrl4 = gmac_ctrl4 & ~GMAC_CTRL4_SHORT_PREAMBLE_ENABLE; -+ -+ /* Even though it might look weird, when we're configured in -+ * SGMII or QSGMII mode, the RGMII bit needs to be set. -+ */ -+ new_ctrl2 |= GMAC_CTRL2_PORT_RGMII; -+ -+ if (state->interface == PHY_INTERFACE_MODE_QSGMII || -+ state->interface == PHY_INTERFACE_MODE_SGMII || -+ phy_interface_mode_is_8023z(state->interface)) -+ new_ctrl2 |= GMAC_CTRL2_PCS_ENABLE; -+ -+ if (!phylink_autoneg_inband(mode)) { -+ /* Phy or fixed speed - nothing to do, leave the -+ * configured speed, duplex and flow control as-is. -+ */ -+ } else if (state->interface == PHY_INTERFACE_MODE_SGMII) { -+ /* SGMII mode receives the state from the PHY */ -+ new_ctrl2 |= GMAC_CTRL2_INBAND_AN_SGMII; -+ } else { -+ /* 802.3z negotiation - 1000BaseX */ -+ new_ctrl0 |= GMAC_CTRL0_PORT_1000BASE_X; -+ } -+ -+ /* When at 2.5G, the link partner can send frames with shortened -+ * preambles. -+ */ -+ if (state->interface == PHY_INTERFACE_MODE_2500BASEX) -+ new_ctrl4 |= GMAC_CTRL4_SHORT_PREAMBLE_ENABLE; -+ -+ if (new_ctrl0 != gmac_ctrl0) -+ writel_relaxed(new_ctrl0, gmac->base + GMAC_CTRL0_REG); -+ if (new_ctrl2 != gmac_ctrl2) -+ writel_relaxed(new_ctrl2, gmac->base + GMAC_CTRL2_REG); -+ if (new_ctrl4 != gmac_ctrl4) -+ writel_relaxed(new_ctrl4, gmac->base + GMAC_CTRL4_REG); -+ -+ if (gmac_ctrl2 & GMAC_CTRL2_PORT_RESET) { -+ while ((readl_relaxed(gmac->base + GMAC_CTRL2_REG) & -+ GMAC_CTRL2_PORT_RESET) != 0) -+ continue; -+ } -+} -+EXPORT_SYMBOL_GPL(mvgmac_config_mac); -+ -+void mvgmac_set_lpi_ts(struct mvgmac *gmac, unsigned int ts) -+{ -+ if (!(readl_relaxed(gmac->base + GMAC_STATUS_REG) & MVGMAC_SPEED_1000)) -+ ts = DIV_ROUND_UP(ts, 10); -+ -+ if (ts > 255) -+ ts = 255; -+ -+ mvgmac_modify(gmac->base + GMAC_LPI_CTRL0_REG, -+ GMAC_LPI_CTRL0_TS, -+ FIELD_PREP(GMAC_LPI_CTRL0_TS, ts)); -+} -+EXPORT_SYMBOL_GPL(mvgmac_set_lpi_ts); -+ -+void mvgmac_set_eee(struct mvgmac *gmac, bool enable) -+{ -+ mvgmac_modify(gmac->base + GMAC_LPI_CTRL1_REG, -+ GMAC_LPI_CTRL1_REQ_EN, -+ FIELD_PREP(GMAC_LPI_CTRL1_REQ_EN, enable)); -+} -+EXPORT_SYMBOL_GPL(mvgmac_set_eee); -+ -+MODULE_DESCRIPTION("Marvell GMAC driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/net/ethernet/marvell/mvgmac.h b/drivers/net/ethernet/marvell/mvgmac.h -new file mode 100644 -index 000000000000..dea376505eb3 ---- /dev/null -+++ b/drivers/net/ethernet/marvell/mvgmac.h -@@ -0,0 +1,47 @@ -+#ifndef MVGMAC_H -+#define MVGMAC_H -+ -+#include -+ -+/* The two bytes Marvell header. Either contains a special value used by -+ * Marvell switches when a specific hardware mode is enabled (not supported -+ * by this driver) or is filled automatically by zeroes on the RX side. -+ * Those two bytes being at the front of the Ethernet header, they allow -+ * to have the IP header aligned on a 4 bytes boundary automatically: the -+ * hardware skips those two bytes on its own. -+ */ -+#define MARVELL_HEADER_SIZE 2 -+ -+struct mvgmac { -+ void __iomem *base; -+ struct phylink_pcs pcs; -+}; -+ -+static inline struct mvgmac *pcs_to_mvgmac(struct phylink_pcs *pcs) -+{ -+ return container_of(pcs, struct mvgmac, pcs); -+} -+ -+void mvgmac_set_max_rx_size(struct mvgmac *gmac, size_t max_rx_size); -+void mvgmac_port_enable(struct mvgmac *gmac); -+void mvgmac_port_disable(struct mvgmac *gmac); -+void mvgmac_link_unforce(struct mvgmac *gmac); -+void mvgmac_link_force_down(struct mvgmac *gmac); -+void mvgmac_link_down(struct mvgmac *gmac, int mode); -+void mvgmac_link_up(struct mvgmac *gmac, int mode, int speed, int duplex, -+ bool tx_pause, bool rx_pause); -+bool mvgmac_link_is_up(struct mvgmac *gmac); -+void mvgmac_pcs_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state); -+void mvgmac_pcs_an_restart(struct phylink_pcs *pcs); -+int mvgmac_pcs_config(struct phylink_pcs *pcs, unsigned int mode, -+ phy_interface_t interface, -+ const unsigned long *advertising, -+ bool permit_pause_to_mac); -+void mvgmac_config_mac(struct mvgmac *gmac, unsigned int mode, -+ const struct phylink_link_state *state); -+ -+void mvgmac_set_lpi_ts(struct mvgmac *gmac, unsigned int ts); -+void mvgmac_set_eee(struct mvgmac *gmac, bool enable); -+ -+#endif -diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c -index 423c369906a4..e1974cfd48a9 100644 ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -34,6 +34,7 @@ - #include - #include - #include "mvneta_bm.h" -+#include "mvgmac.h" - #include - #include - #include -@@ -193,43 +194,7 @@ - #define MVNETA_RXQ_ENABLE_MASK 0x000000ff - #define MVETH_TXQ_TOKEN_COUNT_REG(q) (0x2700 + ((q) << 4)) - #define MVETH_TXQ_TOKEN_CFG_REG(q) (0x2704 + ((q) << 4)) --#define MVNETA_GMAC_CTRL_0 0x2c00 --#define MVNETA_GMAC_MAX_RX_SIZE_SHIFT 2 --#define MVNETA_GMAC_MAX_RX_SIZE_MASK 0x7ffc --#define MVNETA_GMAC0_PORT_1000BASE_X BIT(1) --#define MVNETA_GMAC0_PORT_ENABLE BIT(0) --#define MVNETA_GMAC_CTRL_2 0x2c08 --#define MVNETA_GMAC2_INBAND_AN_ENABLE BIT(0) --#define MVNETA_GMAC2_PCS_ENABLE BIT(3) --#define MVNETA_GMAC2_PORT_RGMII BIT(4) --#define MVNETA_GMAC2_PORT_RESET BIT(6) --#define MVNETA_GMAC_STATUS 0x2c10 --#define MVNETA_GMAC_LINK_UP BIT(0) --#define MVNETA_GMAC_SPEED_1000 BIT(1) --#define MVNETA_GMAC_SPEED_100 BIT(2) --#define MVNETA_GMAC_FULL_DUPLEX BIT(3) --#define MVNETA_GMAC_RX_FLOW_CTRL_ENABLE BIT(4) --#define MVNETA_GMAC_TX_FLOW_CTRL_ENABLE BIT(5) --#define MVNETA_GMAC_RX_FLOW_CTRL_ACTIVE BIT(6) --#define MVNETA_GMAC_TX_FLOW_CTRL_ACTIVE BIT(7) --#define MVNETA_GMAC_AN_COMPLETE BIT(11) --#define MVNETA_GMAC_SYNC_OK BIT(14) --#define MVNETA_GMAC_AUTONEG_CONFIG 0x2c0c --#define MVNETA_GMAC_FORCE_LINK_DOWN BIT(0) --#define MVNETA_GMAC_FORCE_LINK_PASS BIT(1) --#define MVNETA_GMAC_INBAND_AN_ENABLE BIT(2) --#define MVNETA_GMAC_AN_BYPASS_ENABLE BIT(3) --#define MVNETA_GMAC_INBAND_RESTART_AN BIT(4) --#define MVNETA_GMAC_CONFIG_MII_SPEED BIT(5) --#define MVNETA_GMAC_CONFIG_GMII_SPEED BIT(6) --#define MVNETA_GMAC_AN_SPEED_EN BIT(7) --#define MVNETA_GMAC_CONFIG_FLOW_CTRL BIT(8) --#define MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL BIT(9) --#define MVNETA_GMAC_AN_FLOW_CTRL_EN BIT(11) --#define MVNETA_GMAC_CONFIG_FULL_DUPLEX BIT(12) --#define MVNETA_GMAC_AN_DUPLEX_EN BIT(13) --#define MVNETA_GMAC_CTRL_4 0x2c90 --#define MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE BIT(1) -+#define MVNETA_GMAC_BASE 0x2c00 - #define MVNETA_MIB_COUNTERS_BASE 0x3000 - #define MVNETA_MIB_LATE_COLLISION 0x7c - #define MVNETA_DA_FILT_SPEC_MCAST 0x3400 -@@ -253,12 +218,6 @@ - #define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2)) - #define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff - --#define MVNETA_LPI_CTRL_0 0x2cc0 --#define MVNETA_LPI_CTRL_1 0x2cc4 --#define MVNETA_LPI_REQUEST_ENABLE BIT(0) --#define MVNETA_LPI_CTRL_2 0x2cc8 --#define MVNETA_LPI_STATUS 0x2ccc -- - #define MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK 0xff - - /* Descriptor ring Macros */ -@@ -280,7 +239,7 @@ - * boundary automatically: the hardware skips those two bytes on its - * own. - */ --#define MVNETA_MH_SIZE 2 -+#define MVNETA_MH_SIZE MARVELL_HEADER_SIZE - - #define MVNETA_VLAN_TAG_LEN 4 - -@@ -499,9 +458,9 @@ struct mvneta_port { - unsigned int tx_csum_limit; - struct phylink *phylink; - struct phylink_config phylink_config; -- struct phylink_pcs phylink_pcs; - struct phy *comphy; - -+ struct mvgmac gmac; - struct mvneta_bm *bm_priv; - struct mvneta_bm_pool *pool_long; - struct mvneta_bm_pool *pool_short; -@@ -510,6 +469,7 @@ struct mvneta_port { - bool eee_enabled; - bool eee_active; - bool tx_lpi_enabled; -+ u32 tx_lpi_timer; - - u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)]; - -@@ -892,19 +852,6 @@ mvneta_rxq_next_desc_get(struct mvneta_rx_queue *rxq) - return rxq->descs + rx_desc; - } - --/* Change maximum receive size of the port. */ --static void mvneta_max_rx_size_set(struct mvneta_port *pp, int max_rx_size) --{ -- u32 val; -- -- val = mvreg_read(pp, MVNETA_GMAC_CTRL_0); -- val &= ~MVNETA_GMAC_MAX_RX_SIZE_MASK; -- val |= ((max_rx_size - MVNETA_MH_SIZE) / 2) << -- MVNETA_GMAC_MAX_RX_SIZE_SHIFT; -- mvreg_write(pp, MVNETA_GMAC_CTRL_0, val); --} -- -- - /* Set rx queue offset */ - static void mvneta_rxq_offset_set(struct mvneta_port *pp, - struct mvneta_rx_queue *rxq, -@@ -1309,26 +1256,10 @@ static void mvneta_port_down(struct mvneta_port *pp) - udelay(200); - } - --/* Enable the port by setting the port enable bit of the MAC control register */ --static void mvneta_port_enable(struct mvneta_port *pp) --{ -- u32 val; -- -- /* Enable port */ -- val = mvreg_read(pp, MVNETA_GMAC_CTRL_0); -- val |= MVNETA_GMAC0_PORT_ENABLE; -- mvreg_write(pp, MVNETA_GMAC_CTRL_0, val); --} -- - /* Disable the port and wait for about 200 usec before retuning */ - static void mvneta_port_disable(struct mvneta_port *pp) - { -- u32 val; -- -- /* Reset the Enable bit in the Serial Control Register */ -- val = mvreg_read(pp, MVNETA_GMAC_CTRL_0); -- val &= ~MVNETA_GMAC0_PORT_ENABLE; -- mvreg_write(pp, MVNETA_GMAC_CTRL_0, val); -+ mvgmac_port_disable(&pp->gmac); - - udelay(200); - } -@@ -3125,9 +3056,9 @@ static irqreturn_t mvneta_percpu_isr(int irq, void *dev_id) - - static void mvneta_link_change(struct mvneta_port *pp) - { -- u32 gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS); -+ bool link_is_up = mvgmac_link_is_up(&pp->gmac); - -- phylink_mac_change(pp->phylink, !!(gmac_stat & MVNETA_GMAC_LINK_UP)); -+ phylink_mac_change(pp->phylink, link_is_up); - } - - /* NAPI handler -@@ -3619,11 +3550,11 @@ static void mvneta_start_dev(struct mvneta_port *pp) - - WARN_ON(mvneta_config_interface(pp, pp->phy_interface)); - -- mvneta_max_rx_size_set(pp, pp->pkt_size); -+ mvgmac_set_max_rx_size(&pp->gmac, pp->pkt_size); - mvneta_txq_max_tx_size_set(pp, pp->pkt_size); - - /* start the Rx/Tx activity */ -- mvneta_port_enable(pp); -+ mvgmac_port_enable(&pp->gmac); - - if (!pp->neta_armada3700) { - /* Enable polling on the port */ -@@ -3821,109 +3752,22 @@ static int mvneta_set_mac_addr(struct net_device *dev, void *addr) - return 0; - } - --static struct mvneta_port *mvneta_pcs_to_port(struct phylink_pcs *pcs) --{ -- return container_of(pcs, struct mvneta_port, phylink_pcs); --} -- --static void mvneta_pcs_get_state(struct phylink_pcs *pcs, -- struct phylink_link_state *state) --{ -- struct mvneta_port *pp = mvneta_pcs_to_port(pcs); -- u32 gmac_stat; -- -- gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS); -- -- if (gmac_stat & MVNETA_GMAC_SPEED_1000) -- state->speed = -- state->interface == PHY_INTERFACE_MODE_2500BASEX ? -- SPEED_2500 : SPEED_1000; -- else if (gmac_stat & MVNETA_GMAC_SPEED_100) -- state->speed = SPEED_100; -- else -- state->speed = SPEED_10; -- -- state->an_complete = !!(gmac_stat & MVNETA_GMAC_AN_COMPLETE); -- state->link = !!(gmac_stat & MVNETA_GMAC_LINK_UP); -- state->duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX); -- -- if (gmac_stat & MVNETA_GMAC_RX_FLOW_CTRL_ENABLE) -- state->pause |= MLO_PAUSE_RX; -- if (gmac_stat & MVNETA_GMAC_TX_FLOW_CTRL_ENABLE) -- state->pause |= MLO_PAUSE_TX; --} -- - static int mvneta_pcs_config(struct phylink_pcs *pcs, - unsigned int mode, phy_interface_t interface, - const unsigned long *advertising, - bool permit_pause_to_mac) - { -- struct mvneta_port *pp = mvneta_pcs_to_port(pcs); -- u32 mask, val, an, old_an, changed; -- -- mask = MVNETA_GMAC_INBAND_AN_ENABLE | -- MVNETA_GMAC_INBAND_RESTART_AN | -- MVNETA_GMAC_AN_SPEED_EN | -- MVNETA_GMAC_AN_FLOW_CTRL_EN | -- MVNETA_GMAC_AN_DUPLEX_EN; -- -- if (phylink_autoneg_inband(mode)) { -- mask |= MVNETA_GMAC_CONFIG_MII_SPEED | -- MVNETA_GMAC_CONFIG_GMII_SPEED | -- MVNETA_GMAC_CONFIG_FULL_DUPLEX; -- val = MVNETA_GMAC_INBAND_AN_ENABLE; -- -- if (state->interface == PHY_INTERFACE_MODE_SGMII) { -- /* SGMII mode receives the speed and duplex from PHY */ -- val |= MVNETA_GMAC_AN_SPEED_EN | -- MVNETA_GMAC_AN_DUPLEX_EN; -- } else { -- /* 802.3z mode has fixed speed and duplex */ -- val |= MVNETA_GMAC_CONFIG_GMII_SPEED | -- MVNETA_GMAC_CONFIG_FULL_DUPLEX; -- -- /* The FLOW_CTRL_EN bit selects either the hardware -- * automatically or the CONFIG_FLOW_CTRL manually -- * controls the GMAC pause mode. -- */ -- if (permit_pause_to_mac) -- val |= MVNETA_GMAC_AN_FLOW_CTRL_EN; -- -- /* Update the advertisement bits */ -- mask |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL; -- if (phylink_test(advertising, Pause)) -- val |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL; -- } -- } else { -- /* Phy or fixed speed - disable in-band AN modes */ -- val = 0; -- } -- -- old_an = an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); -- an = (an & ~mask) | val; -- changed = old_an ^ an; -- if (changed) -- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, an); -- -- /* We are only interested in the advertisement bits changing */ -- return !!(changed & MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL); --} -- --static void mvneta_pcs_an_restart(struct phylink_pcs *pcs) --{ -- struct mvneta_port *pp = mvneta_pcs_to_port(pcs); -- u32 gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); -+ /* We should never see Asym_Pause set */ -+ WARN_ON(phylink_test(advertising, Asym_Pause)); - -- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, -- gmac_an | MVNETA_GMAC_INBAND_RESTART_AN); -- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, -- gmac_an & ~MVNETA_GMAC_INBAND_RESTART_AN); -+ return mvgmac_pcs_config(pcs, mode, interface, advertising, -+ permit_pause_to_mac); - } - - static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = { -- .pcs_get_state = mvneta_pcs_get_state, -+ .pcs_get_state = mvgmac_pcs_get_state, - .pcs_config = mvneta_pcs_config, -- .pcs_an_restart = mvneta_pcs_an_restart, -+ .pcs_an_restart = mvgmac_pcs_an_restart, - }; - - static void mvneta_validate(struct phylink_config *config, -@@ -3978,7 +3822,6 @@ static int mvneta_mac_prepare(struct phylink_config *config, unsigned int mode, - { - struct net_device *ndev = to_net_dev(config->dev); - struct mvneta_port *pp = netdev_priv(ndev); -- u32 val; - - if (pp->phy_interface != interface || - phylink_autoneg_inband(mode)) { -@@ -3987,10 +3830,7 @@ static int mvneta_mac_prepare(struct phylink_config *config, unsigned int mode, - * can only change the port mode and in-band enable when the - * link is down. - */ -- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); -- val &= ~MVNETA_GMAC_FORCE_LINK_PASS; -- val |= MVNETA_GMAC_FORCE_LINK_DOWN; -- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); -+ mvgmac_link_force_down(&pp->gmac); - } - - if (pp->phy_interface != interface) -@@ -4012,55 +3852,8 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode, - { - struct net_device *ndev = to_net_dev(config->dev); - struct mvneta_port *pp = netdev_priv(ndev); -- u32 new_ctrl0, gmac_ctrl0 = mvreg_read(pp, MVNETA_GMAC_CTRL_0); -- u32 new_ctrl2, gmac_ctrl2 = mvreg_read(pp, MVNETA_GMAC_CTRL_2); -- u32 new_ctrl4, gmac_ctrl4 = mvreg_read(pp, MVNETA_GMAC_CTRL_4); -- -- new_ctrl0 = gmac_ctrl0 & ~MVNETA_GMAC0_PORT_1000BASE_X; -- new_ctrl2 = gmac_ctrl2 & ~(MVNETA_GMAC2_INBAND_AN_ENABLE | -- MVNETA_GMAC2_PORT_RESET); -- new_ctrl4 = gmac_ctrl4 & ~(MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE); - -- /* Even though it might look weird, when we're configured in -- * SGMII or QSGMII mode, the RGMII bit needs to be set. -- */ -- new_ctrl2 |= MVNETA_GMAC2_PORT_RGMII; -- -- if (state->interface == PHY_INTERFACE_MODE_QSGMII || -- state->interface == PHY_INTERFACE_MODE_SGMII || -- phy_interface_mode_is_8023z(state->interface)) -- new_ctrl2 |= MVNETA_GMAC2_PCS_ENABLE; -- -- if (!phylink_autoneg_inband(mode)) { -- /* Phy or fixed speed - nothing to do, leave the -- * configured speed, duplex and flow control as-is. -- */ -- } else if (state->interface == PHY_INTERFACE_MODE_SGMII) { -- /* SGMII mode receives the state from the PHY */ -- new_ctrl2 |= MVNETA_GMAC2_INBAND_AN_ENABLE; -- } else { -- /* 802.3z negotiation - only 1000base-X */ -- new_ctrl0 |= MVNETA_GMAC0_PORT_1000BASE_X; -- } -- -- /* When at 2.5G, the link partner can send frames with shortened -- * preambles. -- */ -- if (state->interface == PHY_INTERFACE_MODE_2500BASEX) -- new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE; -- -- if (new_ctrl0 != gmac_ctrl0) -- mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0); -- if (new_ctrl2 != gmac_ctrl2) -- mvreg_write(pp, MVNETA_GMAC_CTRL_2, new_ctrl2); -- if (new_ctrl4 != gmac_ctrl4) -- mvreg_write(pp, MVNETA_GMAC_CTRL_4, new_ctrl4); -- -- if (gmac_ctrl2 & MVNETA_GMAC2_PORT_RESET) { -- while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) & -- MVNETA_GMAC2_PORT_RESET) != 0) -- continue; -- } -+ mvgmac_config_mac(&pp->gmac, mode, state); - } - - static int mvneta_mac_finish(struct phylink_config *config, unsigned int mode, -@@ -4068,7 +3861,7 @@ static int mvneta_mac_finish(struct phylink_config *config, unsigned int mode, - { - struct net_device *ndev = to_net_dev(config->dev); - struct mvneta_port *pp = netdev_priv(ndev); -- u32 val, clk; -+ u32 clk; - - /* Disable 1ms clock if not in in-band mode */ - if (!phylink_autoneg_inband(mode)) { -@@ -4084,45 +3877,23 @@ static int mvneta_mac_finish(struct phylink_config *config, unsigned int mode, - /* Allow the link to come up if in in-band mode, otherwise the - * link is forced via mac_link_down()/mac_link_up() - */ -- if (phylink_autoneg_inband(mode)) { -- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); -- val &= ~MVNETA_GMAC_FORCE_LINK_DOWN; -- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); -- } -+ if (phylink_autoneg_inband(mode)) -+ mvgmac_link_unforce(&pp->gmac); - - return 0; - } - --static void mvneta_set_eee(struct mvneta_port *pp, bool enable) --{ -- u32 lpi_ctl1; -- -- lpi_ctl1 = mvreg_read(pp, MVNETA_LPI_CTRL_1); -- if (enable) -- lpi_ctl1 |= MVNETA_LPI_REQUEST_ENABLE; -- else -- lpi_ctl1 &= ~MVNETA_LPI_REQUEST_ENABLE; -- mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi_ctl1); --} -- - static void mvneta_mac_link_down(struct phylink_config *config, - unsigned int mode, phy_interface_t interface) - { - struct net_device *ndev = to_net_dev(config->dev); - struct mvneta_port *pp = netdev_priv(ndev); -- u32 val; - - mvneta_port_down(pp); -- -- if (!phylink_autoneg_inband(mode)) { -- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); -- val &= ~MVNETA_GMAC_FORCE_LINK_PASS; -- val |= MVNETA_GMAC_FORCE_LINK_DOWN; -- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); -- } -+ mvgmac_link_down(&pp->gmac, mode); - - pp->eee_active = false; -- mvneta_set_eee(pp, false); -+ mvgmac_set_eee(&pp->gmac, false); - } - - static void mvneta_mac_link_up(struct phylink_config *config, -@@ -4133,48 +3904,14 @@ static void mvneta_mac_link_up(struct phylink_config *config, - { - struct net_device *ndev = to_net_dev(config->dev); - struct mvneta_port *pp = netdev_priv(ndev); -- u32 val; -- -- if (!phylink_autoneg_inband(mode)) { -- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); -- val &= ~(MVNETA_GMAC_FORCE_LINK_DOWN | -- MVNETA_GMAC_CONFIG_MII_SPEED | -- MVNETA_GMAC_CONFIG_GMII_SPEED | -- MVNETA_GMAC_CONFIG_FLOW_CTRL | -- MVNETA_GMAC_CONFIG_FULL_DUPLEX); -- val |= MVNETA_GMAC_FORCE_LINK_PASS; -- -- if (speed == SPEED_1000 || speed == SPEED_2500) -- val |= MVNETA_GMAC_CONFIG_GMII_SPEED; -- else if (speed == SPEED_100) -- val |= MVNETA_GMAC_CONFIG_MII_SPEED; -- -- if (duplex == DUPLEX_FULL) -- val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; -- -- if (tx_pause || rx_pause) -- val |= MVNETA_GMAC_CONFIG_FLOW_CTRL; -- -- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); -- } else { -- /* When inband doesn't cover flow control or flow control is -- * disabled, we need to manually configure it. This bit will -- * only have effect if MVNETA_GMAC_AN_FLOW_CTRL_EN is unset. -- */ -- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); -- val &= ~MVNETA_GMAC_CONFIG_FLOW_CTRL; -- -- if (tx_pause || rx_pause) -- val |= MVNETA_GMAC_CONFIG_FLOW_CTRL; -- -- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); -- } - -+ mvgmac_link_up(&pp->gmac, mode, speed, duplex, tx_pause, rx_pause); - mvneta_port_up(pp); - - if (phy && pp->eee_enabled) { - pp->eee_active = phy_init_eee(phy, 0) >= 0; -- mvneta_set_eee(pp, pp->eee_active && pp->tx_lpi_enabled); -+ mvgmac_set_lpi_ts(&pp->gmac, pp->tx_lpi_timer); -+ mvgmac_set_eee(&pp->gmac, pp->eee_active && pp->tx_lpi_enabled); - } - } - -@@ -4952,14 +4689,11 @@ static int mvneta_ethtool_get_eee(struct net_device *dev, - struct ethtool_eee *eee) - { - struct mvneta_port *pp = netdev_priv(dev); -- u32 lpi_ctl0; -- -- lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0); - - eee->eee_enabled = pp->eee_enabled; - eee->eee_active = pp->eee_active; - eee->tx_lpi_enabled = pp->tx_lpi_enabled; -- eee->tx_lpi_timer = (lpi_ctl0) >> 8; // * scale; -+ eee->tx_lpi_timer = pp->tx_lpi_timer; - - return phylink_ethtool_get_eee(pp->phylink, eee); - } -@@ -4968,7 +4702,6 @@ static int mvneta_ethtool_set_eee(struct net_device *dev, - struct ethtool_eee *eee) - { - struct mvneta_port *pp = netdev_priv(dev); -- u32 lpi_ctl0; - - /* The Armada 37x documents do not give limits for this other than - * it being an 8-bit register. -@@ -4976,15 +4709,13 @@ static int mvneta_ethtool_set_eee(struct net_device *dev, - if (eee->tx_lpi_enabled && eee->tx_lpi_timer > 255) - return -EINVAL; - -- lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0); -- lpi_ctl0 &= ~(0xff << 8); -- lpi_ctl0 |= eee->tx_lpi_timer << 8; -- mvreg_write(pp, MVNETA_LPI_CTRL_0, lpi_ctl0); -- - pp->eee_enabled = eee->eee_enabled; - pp->tx_lpi_enabled = eee->tx_lpi_enabled; -+ pp->tx_lpi_timer = eee->tx_lpi_timer; - -- mvneta_set_eee(pp, eee->tx_lpi_enabled && eee->eee_enabled); -+ mvgmac_set_eee(&pp->gmac, false); -+ mvgmac_set_lpi_ts(&pp->gmac, eee->tx_lpi_timer); -+ mvgmac_set_eee(&pp->gmac, pp->eee_active && pp->tx_lpi_enabled); - - return phylink_ethtool_set_eee(pp->phylink, eee); - } -@@ -5312,8 +5043,11 @@ static int mvneta_probe(struct platform_device *pdev) - goto err_clk; - } - -- pp->phylink_pcs.ops = &mvneta_phylink_pcs_ops; -- phylink_set_pcs(phylink, &pp->phylink_pcs); -+ pp->gmac.base = pp->base + MVNETA_GMAC_BASE; -+ pp->gmac.pcs.ops = &mvneta_phylink_pcs_ops; -+ phylink_set_pcs(phylink, &pp->gmac.pcs); -+ -+ pp->tx_lpi_timer = 16; - - /* Alloc per-cpu port structure */ - pp->ports = alloc_percpu(struct mvneta_pcpu_port); --- -cgit v1.2.3 - - -From 9a5b9e4bfe7301158732d4b321b4e702a54427e2 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Fri, 23 Dec 2016 01:09:44 +0000 -Subject: net: mvgmac: support different hw versions - -Signed-off-by: Russell King ---- - drivers/net/ethernet/marvell/mvgmac.c | 118 ++++++++++++++++++++++++++++++---- - drivers/net/ethernet/marvell/mvgmac.h | 9 +++ - drivers/net/ethernet/marvell/mvneta.c | 1 + - 3 files changed, 115 insertions(+), 13 deletions(-) - -diff --git a/drivers/net/ethernet/marvell/mvgmac.c b/drivers/net/ethernet/marvell/mvgmac.c -index aee6dff9f569..04da6d475ff1 100644 ---- a/drivers/net/ethernet/marvell/mvgmac.c -+++ b/drivers/net/ethernet/marvell/mvgmac.c -@@ -20,6 +20,8 @@ - #include "mvgmac.h" - - enum { -+ /* N = Neta, 21 = PPV2.1, 22 = PPV2.2 */ -+ /* N: 0-14 21: 0,2-15 22: 0-14 */ - GMAC_CTRL0_REG = 0x00, - GMAC_CTRL0_PORT_ENABLE = BIT(0), - GMAC_CTRL0_PORT_1000BASE_X = BIT(1), -@@ -27,12 +29,21 @@ enum { - GMAC_CTRL0_MAX_RX_SIZE_MASK = 0x1fff << GMAC_CTRL0_MAX_RX_SIZE_SHIFT, - GMAC_CTRL0_MIB_CNTR_ENABLE = BIT(15), - -+ /* N: 21: 1,5,6 22: */ -+ GMAC_CTRL1_REG = 0x04, -+ GMAC_CTRL1_PERIODIC_XON_ENABLE = BIT(1), -+ GMAC_CTRL1_GMII_LB_ENABLE = BIT(5), -+ GMAC_CTRL1_PCS_LB_ENABLE = BIT(6), -+ -+ /* ALL: 0,3,4,6 */ - GMAC_CTRL2_REG = 0x08, - GMAC_CTRL2_INBAND_AN_SGMII = BIT(0), - GMAC_CTRL2_PCS_ENABLE = BIT(3), - GMAC_CTRL2_PORT_RGMII = BIT(4), - GMAC_CTRL2_PORT_RESET = BIT(6), - -+ /* N:0-9,11-13 21:0,1,5-7,9,12,13 22:0-7,9-15 */ -+ /* 22 bit 2 - EN_PCS_AN */ - GMAC_ANEG_REG = 0x0c, - GMAC_ANEG_FORCE_LINK_DOWN = BIT(0), - GMAC_ANEG_FORCE_LINK_PASS = BIT(1), -@@ -44,9 +55,12 @@ enum { - GMAC_ANEG_AN_SPEED_ENABLE = BIT(7), - GMAC_ANEG_CONFIG_FLOW_CTRL = BIT(8), - GMAC_ANEG_ADVERT_SYM_FLOW_CTRL = BIT(9), -+ GMAC_ANEG_ADVERT_ASYM_FLOW_CTRL = BIT(10), - GMAC_ANEG_AN_FLOW_CTRL_ENABLE = BIT(11), - GMAC_ANEG_FULL_DUPLEX = BIT(12), - GMAC_ANEG_AN_DUPLEX_ENABLE = BIT(13), -+ /* pp22: bit 14 - phy mode */ -+ /* pp22: bit 15 - choose sample tx config */ - - GMAC_STATUS_REG = 0x10, - MVGMAC_LINK_UP = BIT(0), -@@ -60,8 +74,21 @@ enum { - MVGMAC_AN_COMPLETE = BIT(11), - MVGMAC_SYNC_OK = BIT(14), - -+ /* N: 21:6-13 22: */ -+ GMAC_FIFO_CFG1_REG = 0x1c, -+ GMAC_FIFO_CFG1_TX_MIN_TH_SHIFT = 6, -+ GMAC_FIFO_CFG1_TX_MIN_TH_MASK = 0x7f << -+ GMAC_FIFO_CFG1_TX_MIN_TH_SHIFT, -+ -+ /* N:1 21: 22:0,3-7 */ - GMAC_CTRL4_REG = 0x90, -+ GMAC_CTRL4_EXT_PIN_GMII_SEL = BIT(0), - GMAC_CTRL4_SHORT_PREAMBLE_ENABLE = BIT(1), -+ GMAC_CTRL4_FC_RX_ENABLE = BIT(3), -+ GMAC_CTRL4_FC_TX_ENABLE = BIT(4), -+ GMAC_CTRL4_DP_CLK_SEL = BIT(5), -+ GMAC_CTRL4_SYNC_BYPASS = BIT(6), -+ GMAC_CTRL4_QSGMII_BYPASS = BIT(7), - - GMAC_LPI_CTRL0_REG = 0xc0, - GMAC_LPI_CTRL0_TS = 0xff << 8, -@@ -115,6 +142,49 @@ void mvgmac_port_disable(struct mvgmac *gmac) - } - EXPORT_SYMBOL_GPL(mvgmac_port_disable); - -+int mvgmac_configure(struct mvgmac *gmac, phy_interface_t phy_mode) -+{ -+ u32 ctrl4; -+ -+ switch (phy_mode) { -+ case PHY_INTERFACE_MODE_QSGMII: -+ ctrl4 = 0; -+ break; -+ -+ case PHY_INTERFACE_MODE_SGMII: -+ ctrl4 = GMAC_CTRL4_QSGMII_BYPASS; -+ break; -+ -+ case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ ctrl4 = GMAC_CTRL4_QSGMII_BYPASS | -+ GMAC_CTRL4_EXT_PIN_GMII_SEL; -+ break; -+ -+ default: -+ return -EINVAL; -+ } -+ -+ if (gmac->version == MVGMAC_PP21) { -+ /* Min. TX threshold must be less than minimum packet length */ -+ mvgmac_modify(gmac->base + GMAC_FIFO_CFG1_REG, -+ GMAC_FIFO_CFG1_TX_MIN_TH_MASK, -+ FIELD_PREP(GMAC_FIFO_CFG1_TX_MIN_TH_MASK, -+ 64 - 4 - 2)); -+ } else if (gmac->version == MVGMAC_PP22) { -+ mvgmac_modify(gmac->base + GMAC_CTRL4_REG, -+ GMAC_CTRL4_DP_CLK_SEL | GMAC_CTRL4_SYNC_BYPASS | -+ GMAC_CTRL4_QSGMII_BYPASS | -+ GMAC_CTRL4_EXT_PIN_GMII_SEL, -+ GMAC_CTRL4_SYNC_BYPASS | ctrl4); -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(mvgmac_configure); -+ - void mvgmac_link_unforce(struct mvgmac *gmac) - { - mvgmac_clear(gmac->base + GMAC_ANEG_REG, -@@ -140,16 +210,21 @@ EXPORT_SYMBOL_GPL(mvgmac_link_down); - void mvgmac_link_up(struct mvgmac *gmac, int mode, int speed, int duplex, - bool tx_pause, bool rx_pause) - { -- u32 an_mask, an_val; -+ u32 an_mask, an_val, ctrl4; - -- an_mask = GMAC_ANEG_CONFIG_FLOW_CTRL; -- an_val = FIELD_PREP(GMAC_ANEG_CONFIG_FLOW_CTRL, tx_pause || rx_pause); -+ if (gmac->version == MVGMAC_NETA) { -+ an_mask = GMAC_ANEG_CONFIG_FLOW_CTRL; -+ an_val = FIELD_PREP(GMAC_ANEG_CONFIG_FLOW_CTRL, -+ tx_pause || rx_pause); -+ } else { -+ an_mask = 0; -+ an_val = 0; -+ } - - if (!phylink_autoneg_inband(mode)) { - an_mask |= GMAC_ANEG_FORCE_LINK_DOWN | - GMAC_ANEG_FORCE_LINK_PASS | -- GMAC_ANEG_MII_SPEED | -- GMAC_ANEG_GMII_SPEED | -+ GMAC_ANEG_MII_SPEED | GMAC_ANEG_GMII_SPEED | - GMAC_ANEG_FULL_DUPLEX; - an_val |= GMAC_ANEG_FORCE_LINK_PASS; - -@@ -162,7 +237,15 @@ void mvgmac_link_up(struct mvgmac *gmac, int mode, int speed, int duplex, - an_val |= GMAC_ANEG_FULL_DUPLEX; - } - -- mvgmac_modify(gmac->base + GMAC_ANEG_REG, an_mask, an_val); -+ if (an_mask) -+ mvgmac_modify(gmac->base + GMAC_ANEG_REG, an_mask, an_val); -+ -+ if (gmac->version == MVGMAC_PP22) { -+ ctrl4 = readl_relaxed(gmac->base + GMAC_CTRL4_REG); -+ ctrl4 = insert(ctrl4, GMAC_CTRL4_FC_TX_ENABLE, tx_pause); -+ ctrl4 = insert(ctrl4, GMAC_CTRL4_FC_RX_ENABLE, rx_pause); -+ writel_relaxed(ctrl4, gmac->base + GMAC_CTRL4_REG); -+ } - } - EXPORT_SYMBOL_GPL(mvgmac_link_up); - -@@ -252,6 +335,11 @@ int mvgmac_pcs_config(struct phylink_pcs *pcs, unsigned int mode, - mask |= GMAC_ANEG_ADVERT_SYM_FLOW_CTRL; - if (phylink_test(advertising, Pause)) - val |= GMAC_ANEG_ADVERT_SYM_FLOW_CTRL; -+ if (gmac->version == MVGMAC_PP22) { -+ mask |= GMAC_ANEG_ADVERT_ASYM_FLOW_CTRL; -+ if (phylink_test(advertising, Asym_Pause)) -+ val |= GMAC_ANEG_ADVERT_ASYM_FLOW_CTRL; -+ } - } - } else { - /* Phy or fixed speed - disable in-band AN modes */ -@@ -265,7 +353,8 @@ int mvgmac_pcs_config(struct phylink_pcs *pcs, unsigned int mode, - writel_relaxed(an, gmac->base + GMAC_ANEG_REG); - - /* We are only interested in the advertisement bits changing */ -- return !!(changed & GMAC_ANEG_ADVERT_SYM_FLOW_CTRL); -+ return !!(changed & (GMAC_ANEG_ADVERT_SYM_FLOW_CTRL | -+ GMAC_ANEG_ADVERT_ASYM_FLOW_CTRL)); - } - EXPORT_SYMBOL_GPL(mvgmac_pcs_config); - -@@ -279,7 +368,7 @@ void mvgmac_config_mac(struct mvgmac *gmac, unsigned int mode, - new_ctrl0 = gmac_ctrl0 & ~GMAC_CTRL0_PORT_1000BASE_X; - new_ctrl2 = gmac_ctrl2 & ~(GMAC_CTRL2_INBAND_AN_SGMII | - GMAC_CTRL2_PORT_RESET); -- new_ctrl4 = gmac_ctrl4 & ~GMAC_CTRL4_SHORT_PREAMBLE_ENABLE; -+ new_ctrl4 = gmac_ctrl4; - - /* Even though it might look weird, when we're configured in - * SGMII or QSGMII mode, the RGMII bit needs to be set. -@@ -303,11 +392,14 @@ void mvgmac_config_mac(struct mvgmac *gmac, unsigned int mode, - new_ctrl0 |= GMAC_CTRL0_PORT_1000BASE_X; - } - -- /* When at 2.5G, the link partner can send frames with shortened -- * preambles. -- */ -- if (state->interface == PHY_INTERFACE_MODE_2500BASEX) -- new_ctrl4 |= GMAC_CTRL4_SHORT_PREAMBLE_ENABLE; -+ if (gmac->version == MVGMAC_NETA) { -+ /* When at 2.5G, the link partner can send frames with -+ * shortened preambles. -+ */ -+ new_ctrl4 &= ~GMAC_CTRL4_SHORT_PREAMBLE_ENABLE; -+ if (state->interface == PHY_INTERFACE_MODE_2500BASEX) -+ new_ctrl4 |= GMAC_CTRL4_SHORT_PREAMBLE_ENABLE; -+ } - - if (new_ctrl0 != gmac_ctrl0) - writel_relaxed(new_ctrl0, gmac->base + GMAC_CTRL0_REG); -diff --git a/drivers/net/ethernet/marvell/mvgmac.h b/drivers/net/ethernet/marvell/mvgmac.h -index dea376505eb3..36ed203094be 100644 ---- a/drivers/net/ethernet/marvell/mvgmac.h -+++ b/drivers/net/ethernet/marvell/mvgmac.h -@@ -12,8 +12,16 @@ - */ - #define MARVELL_HEADER_SIZE 2 - -+enum { -+ /* GMAC version */ -+ MVGMAC_NETA, -+ MVGMAC_PP21, -+ MVGMAC_PP22, -+}; -+ - struct mvgmac { - void __iomem *base; -+ unsigned int version; - struct phylink_pcs pcs; - }; - -@@ -25,6 +33,7 @@ static inline struct mvgmac *pcs_to_mvgmac(struct phylink_pcs *pcs) - void mvgmac_set_max_rx_size(struct mvgmac *gmac, size_t max_rx_size); - void mvgmac_port_enable(struct mvgmac *gmac); - void mvgmac_port_disable(struct mvgmac *gmac); -+int mvgmac_configure(struct mvgmac *gmac, phy_interface_t phy_mode); - void mvgmac_link_unforce(struct mvgmac *gmac); - void mvgmac_link_force_down(struct mvgmac *gmac); - void mvgmac_link_down(struct mvgmac *gmac, int mode); -diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c -index e1974cfd48a9..45203d547c7d 100644 ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -5044,6 +5044,7 @@ static int mvneta_probe(struct platform_device *pdev) - } - - pp->gmac.base = pp->base + MVNETA_GMAC_BASE; -+ pp->gmac.version = MVGMAC_NETA; - pp->gmac.pcs.ops = &mvneta_phylink_pcs_ops; - phylink_set_pcs(phylink, &pp->gmac.pcs); - --- -cgit v1.2.3 - diff --git a/patch/kernel/archive/mvebu-5.15/21-pcie-bridge-emul.patch b/patch/kernel/archive/mvebu-5.15/21-pcie-bridge-emul.patch.disabled similarity index 100% rename from patch/kernel/archive/mvebu-5.15/21-pcie-bridge-emul.patch rename to patch/kernel/archive/mvebu-5.15/21-pcie-bridge-emul.patch.disabled