[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210601003325.1631980-3-olteanv@gmail.com>
Date: Tue, 1 Jun 2021 03:33:18 +0300
From: Vladimir Oltean <olteanv@...il.com>
To: Jakub Kicinski <kuba@...nel.org>,
"David S. Miller" <davem@...emloft.net>, netdev@...r.kernel.org
Cc: Wong Vee Khee <vee.khee.wong@...ux.intel.com>,
Ong Boon Leong <boon.leong.ong@...el.com>,
Michael Sit Wei Hong <michael.wei.hong.sit@...el.com>,
Giuseppe Cavallaro <peppe.cavallaro@...com>,
Alexandre Torgue <alexandre.torgue@...s.st.com>,
Jose Abreu <joabreu@...opsys.com>,
Maxime Coquelin <mcoquelin.stm32@...il.com>,
Heiner Kallweit <hkallweit1@...il.com>,
Russell King - ARM Linux admin <linux@...linux.org.uk>,
Florian Fainelli <f.fainelli@...il.com>,
Andrew Lunn <andrew@...n.ch>,
Vladimir Oltean <vladimir.oltean@....com>
Subject: [RFC PATCH v2 net-next 2/9] net: pcs: xpcs: there is only one PHY ID
From: Vladimir Oltean <vladimir.oltean@....com>
The xpcs driver has an apparently inadequate structure for the actual
hardware it drives.
These defines and the xpcs_probe() function would suggest that there is
one PHY ID per supported PHY interface type, and the driver simply
validates whether the mode it should operate in (the argument of
xpcs_probe) matches what the hardware is capable of:
#define SYNOPSYS_XPCS_USXGMII_ID 0x7996ced0
#define SYNOPSYS_XPCS_10GKR_ID 0x7996ced0
#define SYNOPSYS_XPCS_XLGMII_ID 0x7996ced0
#define SYNOPSYS_XPCS_SGMII_ID 0x7996ced0
#define SYNOPSYS_XPCS_MASK 0xffffffff
but that is not the case, because upon closer inspection, all the above
4 PHY ID definitions are in fact equal.
So it is the same XPCS that is compatible with all 4 sets of PHY
interface types.
This change introduces an array of struct xpcs_compat which is populated
by the single struct xpcs_id instance. It also eliminates the bogus
defines for multiple Synopsys XPCS PHY IDs and replaces them with a
single XPCS_ID, which better reflects the way in which the hardware
operates.
Signed-off-by: Vladimir Oltean <vladimir.oltean@....com>
---
drivers/net/pcs/pcs-xpcs.c | 103 +++++++++++++++++++++++--------------
1 file changed, 65 insertions(+), 38 deletions(-)
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index aa985a5aae8d..8491cfe1c11d 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -12,10 +12,7 @@
#include <linux/phylink.h>
#include <linux/workqueue.h>
-#define SYNOPSYS_XPCS_USXGMII_ID 0x7996ced0
-#define SYNOPSYS_XPCS_10GKR_ID 0x7996ced0
-#define SYNOPSYS_XPCS_XLGMII_ID 0x7996ced0
-#define SYNOPSYS_XPCS_SGMII_ID 0x7996ced0
+#define SYNOPSYS_XPCS_ID 0x7996ced0
#define SYNOPSYS_XPCS_MASK 0xffffffff
/* Vendor regs access */
@@ -163,58 +160,76 @@ static const int xpcs_sgmii_features[] = {
static const phy_interface_t xpcs_usxgmii_interfaces[] = {
PHY_INTERFACE_MODE_USXGMII,
- PHY_INTERFACE_MODE_MAX,
};
static const phy_interface_t xpcs_10gkr_interfaces[] = {
PHY_INTERFACE_MODE_10GKR,
- PHY_INTERFACE_MODE_MAX,
};
static const phy_interface_t xpcs_xlgmii_interfaces[] = {
PHY_INTERFACE_MODE_XLGMII,
- PHY_INTERFACE_MODE_MAX,
};
static const phy_interface_t xpcs_sgmii_interfaces[] = {
PHY_INTERFACE_MODE_SGMII,
- PHY_INTERFACE_MODE_MAX,
};
-static struct xpcs_id {
- u32 id;
- u32 mask;
+enum {
+ DW_XPCS_USXGMII,
+ DW_XPCS_10GKR,
+ DW_XPCS_XLGMII,
+ DW_XPCS_SGMII,
+ DW_XPCS_INTERFACE_MAX,
+};
+
+struct xpcs_compat {
const int *supported;
const phy_interface_t *interface;
+ int num_interfaces;
int an_mode;
-} xpcs_id_list[] = {
- {
- .id = SYNOPSYS_XPCS_USXGMII_ID,
- .mask = SYNOPSYS_XPCS_MASK,
+};
+
+static const struct xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
+ [DW_XPCS_USXGMII] = {
.supported = xpcs_usxgmii_features,
.interface = xpcs_usxgmii_interfaces,
+ .num_interfaces = ARRAY_SIZE(xpcs_usxgmii_interfaces),
.an_mode = DW_AN_C73,
- }, {
- .id = SYNOPSYS_XPCS_10GKR_ID,
- .mask = SYNOPSYS_XPCS_MASK,
+ },
+ [DW_XPCS_10GKR] = {
.supported = xpcs_10gkr_features,
.interface = xpcs_10gkr_interfaces,
+ .num_interfaces = ARRAY_SIZE(xpcs_10gkr_interfaces),
.an_mode = DW_AN_C73,
- }, {
- .id = SYNOPSYS_XPCS_XLGMII_ID,
- .mask = SYNOPSYS_XPCS_MASK,
+ },
+ [DW_XPCS_XLGMII] = {
.supported = xpcs_xlgmii_features,
.interface = xpcs_xlgmii_interfaces,
+ .num_interfaces = ARRAY_SIZE(xpcs_xlgmii_interfaces),
.an_mode = DW_AN_C73,
- }, {
- .id = SYNOPSYS_XPCS_SGMII_ID,
- .mask = SYNOPSYS_XPCS_MASK,
+ },
+ [DW_XPCS_SGMII] = {
.supported = xpcs_sgmii_features,
.interface = xpcs_sgmii_interfaces,
+ .num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces),
.an_mode = DW_AN_C37_SGMII,
},
};
+struct xpcs_id {
+ u32 id;
+ u32 mask;
+ const struct xpcs_compat *compat;
+};
+
+static const struct xpcs_id xpcs_id_list[] = {
+ {
+ .id = SYNOPSYS_XPCS_ID,
+ .mask = SYNOPSYS_XPCS_MASK,
+ .compat = synopsys_xpcs_compat,
+ },
+};
+
static int xpcs_read(struct mdio_xpcs_args *xpcs, int dev, u32 reg)
{
u32 reg_addr = MII_ADDR_C45 | dev << 16 | reg;
@@ -911,35 +926,47 @@ static u32 xpcs_get_id(struct mdio_xpcs_args *xpcs)
}
static bool xpcs_check_features(struct mdio_xpcs_args *xpcs,
- struct xpcs_id *match,
+ const struct xpcs_id *match,
phy_interface_t interface)
{
- int i;
+ int i, j;
- for (i = 0; match->interface[i] != PHY_INTERFACE_MODE_MAX; i++) {
- if (match->interface[i] == interface)
- break;
- }
+ for (i = 0; i < DW_XPCS_INTERFACE_MAX; i++) {
+ const struct xpcs_compat *compat = &match->compat[i];
+ bool supports_interface = false;
- if (match->interface[i] == PHY_INTERFACE_MODE_MAX)
- return false;
+ for (j = 0; j < compat->num_interfaces; j++) {
+ if (compat->interface[j] == interface) {
+ supports_interface = true;
+ break;
+ }
+ }
- for (i = 0; match->supported[i] != __ETHTOOL_LINK_MODE_MASK_NBITS; i++)
- set_bit(match->supported[i], xpcs->supported);
+ if (!supports_interface)
+ continue;
+
+ /* Populate the supported link modes for this
+ * PHY interface type
+ */
+ for (j = 0; compat->supported[j] != __ETHTOOL_LINK_MODE_MASK_NBITS; j++)
+ set_bit(compat->supported[j], xpcs->supported);
- xpcs->an_mode = match->an_mode;
+ xpcs->an_mode = compat->an_mode;
+
+ return true;
+ }
- return true;
+ return false;
}
static int xpcs_probe(struct mdio_xpcs_args *xpcs, phy_interface_t interface)
{
+ const struct xpcs_id *match = NULL;
u32 xpcs_id = xpcs_get_id(xpcs);
- struct xpcs_id *match = NULL;
int i;
for (i = 0; i < ARRAY_SIZE(xpcs_id_list); i++) {
- struct xpcs_id *entry = &xpcs_id_list[i];
+ const struct xpcs_id *entry = &xpcs_id_list[i];
if ((xpcs_id & entry->mask) == entry->id) {
match = entry;
--
2.25.1
Powered by blists - more mailing lists