linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [net-next PATCH v7 0/4] net: phy: add PHY package base addr + mmd APIs
@ 2023-12-14 12:10 Christian Marangi
  2023-12-14 12:10 ` [net-next PATCH v7 1/4] net: phy: make addr type u8 in phy_package_shared struct Christian Marangi
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: Christian Marangi @ 2023-12-14 12:10 UTC (permalink / raw)
  To: Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Vladimir Oltean,
	David Epping, Russell King (Oracle),
	Christian Marangi, Harini Katakam, netdev, linux-kernel

This small series is required for the upcoming qca807x PHY that
will make use of PHY package mmd API and the new implementation
with read/write based on base addr.

The MMD PHY package patch currently has no use but it will be
used in the upcoming patch and it does complete what a PHY package
may require in addition to basic read/write to setup global PHY address.

(Changelog for all the revision is present in the single patch)

Christian Marangi (4):
  net: phy: make addr type u8 in phy_package_shared struct
  net: phy: extend PHY package API to support multiple global address
  net: phy: restructure __phy_write/read_mmd to helper and phydev user
  net: phy: add support for PHY package MMD read/write

 drivers/net/phy/bcm54140.c       |  16 ++-
 drivers/net/phy/mscc/mscc.h      |   5 +
 drivers/net/phy/mscc/mscc_main.c |   4 +-
 drivers/net/phy/phy-core.c       | 208 ++++++++++++++++++++++++++-----
 drivers/net/phy/phy_device.c     |  35 +++---
 include/linux/phy.h              |  57 ++++++---
 6 files changed, 253 insertions(+), 72 deletions(-)

-- 
2.40.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [net-next PATCH v7 1/4] net: phy: make addr type u8 in phy_package_shared struct
  2023-12-14 12:10 [net-next PATCH v7 0/4] net: phy: add PHY package base addr + mmd APIs Christian Marangi
@ 2023-12-14 12:10 ` Christian Marangi
  2023-12-14 16:56   ` Russell King (Oracle)
  2023-12-14 12:10 ` [net-next PATCH v7 2/4] net: phy: extend PHY package API to support multiple global address Christian Marangi
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 12+ messages in thread
From: Christian Marangi @ 2023-12-14 12:10 UTC (permalink / raw)
  To: Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Vladimir Oltean,
	David Epping, Russell King (Oracle),
	Christian Marangi, Harini Katakam, netdev, linux-kernel

Switch addr type in phy_package_shared struct to u8.

The value is already checked to be non negative and to be less than
PHY_MAX_ADDR, hence u8 is better suited than using int.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
Changes v7:
- Add this patch

 include/linux/phy.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/phy.h b/include/linux/phy.h
index e5f1f41e399c..e5e29fca4d17 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -338,7 +338,7 @@ struct mdio_bus_stats {
  * phy_package_leave().
  */
 struct phy_package_shared {
-	int addr;
+	u8 addr;
 	refcount_t refcnt;
 	unsigned long flags;
 	size_t priv_size;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [net-next PATCH v7 2/4] net: phy: extend PHY package API to support multiple global address
  2023-12-14 12:10 [net-next PATCH v7 0/4] net: phy: add PHY package base addr + mmd APIs Christian Marangi
  2023-12-14 12:10 ` [net-next PATCH v7 1/4] net: phy: make addr type u8 in phy_package_shared struct Christian Marangi
@ 2023-12-14 12:10 ` Christian Marangi
  2023-12-14 17:05   ` Russell King (Oracle)
  2023-12-14 12:10 ` [net-next PATCH v7 3/4] net: phy: restructure __phy_write/read_mmd to helper and phydev user Christian Marangi
  2023-12-14 12:10 ` [net-next PATCH v7 4/4] net: phy: add support for PHY package MMD read/write Christian Marangi
  3 siblings, 1 reply; 12+ messages in thread
From: Christian Marangi @ 2023-12-14 12:10 UTC (permalink / raw)
  To: Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Vladimir Oltean,
	David Epping, Russell King (Oracle),
	Christian Marangi, Harini Katakam, netdev, linux-kernel

Current API for PHY package are limited to single address to configure
global settings for the PHY package.

It was found that some PHY package (for example the qca807x, a PHY
package that is shipped with a bundle of 5 PHY) requires multiple PHY
address to configure global settings. An example scenario is a PHY that
have a dedicated PHY for PSGMII/serdes calibrarion and have a specific
PHY in the package where the global PHY mode is set and affects every
other PHY in the package.

Change the API in the following way:
- Change phy_package_join() to take the base addr of the PHY package
  instead of the global PHY addr.
- Make __/phy_package_write/read() require an additional arg that
  select what global PHY address to use by passing the offset from the
  base addr passed on phy_package_join().

Each user of this API is updated to follow this new implementation
following a pattern where an enum is defined to declare the offset of the
addr.

We also drop the check if shared is defined as any user of the
phy_package_read/write is expected to use phy_package_join first. Misuse
of this will correctly trigger a kernel panic for NULL pointer
exception.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
Changes v7:
- Change addr to u8
Changes v2:
- Make kernel panic if shared is not init (bugged scenario)
- Fix some confusing comments

 drivers/net/phy/bcm54140.c       | 16 +++++++++----
 drivers/net/phy/mscc/mscc.h      |  5 ++++
 drivers/net/phy/mscc/mscc_main.c |  4 ++--
 drivers/net/phy/phy_device.c     | 35 ++++++++++++++-------------
 include/linux/phy.h              | 41 +++++++++++++++++++-------------
 5 files changed, 63 insertions(+), 38 deletions(-)

diff --git a/drivers/net/phy/bcm54140.c b/drivers/net/phy/bcm54140.c
index d43076592f81..2eea3d09b1e6 100644
--- a/drivers/net/phy/bcm54140.c
+++ b/drivers/net/phy/bcm54140.c
@@ -128,6 +128,10 @@
 #define BCM54140_DEFAULT_DOWNSHIFT 5
 #define BCM54140_MAX_DOWNSHIFT 9
 
+enum bcm54140_global_phy {
+	BCM54140_BASE_ADDR = 0,
+};
+
 struct bcm54140_priv {
 	int port;
 	int base_addr;
@@ -429,11 +433,13 @@ static int bcm54140_base_read_rdb(struct phy_device *phydev, u16 rdb)
 	int ret;
 
 	phy_lock_mdio_bus(phydev);
-	ret = __phy_package_write(phydev, MII_BCM54XX_RDB_ADDR, rdb);
+	ret = __phy_package_write(phydev, BCM54140_BASE_ADDR,
+				  MII_BCM54XX_RDB_ADDR, rdb);
 	if (ret < 0)
 		goto out;
 
-	ret = __phy_package_read(phydev, MII_BCM54XX_RDB_DATA);
+	ret = __phy_package_read(phydev, BCM54140_BASE_ADDR,
+				 MII_BCM54XX_RDB_DATA);
 
 out:
 	phy_unlock_mdio_bus(phydev);
@@ -446,11 +452,13 @@ static int bcm54140_base_write_rdb(struct phy_device *phydev,
 	int ret;
 
 	phy_lock_mdio_bus(phydev);
-	ret = __phy_package_write(phydev, MII_BCM54XX_RDB_ADDR, rdb);
+	ret = __phy_package_write(phydev, BCM54140_BASE_ADDR,
+				  MII_BCM54XX_RDB_ADDR, rdb);
 	if (ret < 0)
 		goto out;
 
-	ret = __phy_package_write(phydev, MII_BCM54XX_RDB_DATA, val);
+	ret = __phy_package_write(phydev, BCM54140_BASE_ADDR,
+				  MII_BCM54XX_RDB_DATA, val);
 
 out:
 	phy_unlock_mdio_bus(phydev);
diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h
index 7a962050a4d4..6a3d8a754eb8 100644
--- a/drivers/net/phy/mscc/mscc.h
+++ b/drivers/net/phy/mscc/mscc.h
@@ -416,6 +416,11 @@ struct vsc8531_private {
  * gpio_lock: used for PHC operations. Common for all PHYs as the load/save GPIO
  * is shared.
  */
+
+enum vsc85xx_global_phy {
+	VSC88XX_BASE_ADDR = 0,
+};
+
 struct vsc85xx_shared_private {
 	struct mutex gpio_lock;
 };
diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c
index 4171f01d34e5..6f74ce0ab1aa 100644
--- a/drivers/net/phy/mscc/mscc_main.c
+++ b/drivers/net/phy/mscc/mscc_main.c
@@ -711,7 +711,7 @@ int phy_base_write(struct phy_device *phydev, u32 regnum, u16 val)
 		dump_stack();
 	}
 
-	return __phy_package_write(phydev, regnum, val);
+	return __phy_package_write(phydev, VSC88XX_BASE_ADDR, regnum, val);
 }
 
 /* phydev->bus->mdio_lock should be locked when using this function */
@@ -722,7 +722,7 @@ int phy_base_read(struct phy_device *phydev, u32 regnum)
 		dump_stack();
 	}
 
-	return __phy_package_read(phydev, regnum);
+	return __phy_package_read(phydev, VSC88XX_BASE_ADDR, regnum);
 }
 
 u32 vsc85xx_csr_read(struct phy_device *phydev,
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 478126f6b5bc..424cbb13de13 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1648,20 +1648,22 @@ EXPORT_SYMBOL_GPL(phy_driver_is_genphy_10g);
 /**
  * phy_package_join - join a common PHY group
  * @phydev: target phy_device struct
- * @addr: cookie and PHY address for global register access
+ * @base_addr: cookie and base PHY address of PHY package for offset
+ *   calculation of global register access
  * @priv_size: if non-zero allocate this amount of bytes for private data
  *
  * This joins a PHY group and provides a shared storage for all phydevs in
  * this group. This is intended to be used for packages which contain
  * more than one PHY, for example a quad PHY transceiver.
  *
- * The addr parameter serves as a cookie which has to have the same value
- * for all members of one group and as a PHY address to access generic
- * registers of a PHY package. Usually, one of the PHY addresses of the
- * different PHYs in the package provides access to these global registers.
+ * The base_addr parameter serves as cookie which has to have the same values
+ * for all members of one group and as the base PHY address of the PHY package
+ * for offset calculation to access generic registers of a PHY package.
+ * Usually, one of the PHY addresses of the different PHYs in the package
+ * provides access to these global registers.
  * The address which is given here, will be used in the phy_package_read()
- * and phy_package_write() convenience functions. If your PHY doesn't have
- * global registers you can just pick any of the PHY addresses.
+ * and phy_package_write() convenience functions as base and added to the
+ * passed offset in those functions.
  *
  * This will set the shared pointer of the phydev to the shared storage.
  * If this is the first call for a this cookie the shared storage will be
@@ -1671,17 +1673,17 @@ EXPORT_SYMBOL_GPL(phy_driver_is_genphy_10g);
  * Returns < 1 on error, 0 on success. Esp. calling phy_package_join()
  * with the same cookie but a different priv_size is an error.
  */
-int phy_package_join(struct phy_device *phydev, int addr, size_t priv_size)
+int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size)
 {
 	struct mii_bus *bus = phydev->mdio.bus;
 	struct phy_package_shared *shared;
 	int ret;
 
-	if (addr < 0 || addr >= PHY_MAX_ADDR)
+	if (base_addr < 0 || base_addr >= PHY_MAX_ADDR)
 		return -EINVAL;
 
 	mutex_lock(&bus->shared_lock);
-	shared = bus->shared[addr];
+	shared = bus->shared[base_addr];
 	if (!shared) {
 		ret = -ENOMEM;
 		shared = kzalloc(sizeof(*shared), GFP_KERNEL);
@@ -1693,9 +1695,9 @@ int phy_package_join(struct phy_device *phydev, int addr, size_t priv_size)
 				goto err_free;
 			shared->priv_size = priv_size;
 		}
-		shared->addr = addr;
+		shared->base_addr = base_addr;
 		refcount_set(&shared->refcnt, 1);
-		bus->shared[addr] = shared;
+		bus->shared[base_addr] = shared;
 	} else {
 		ret = -EINVAL;
 		if (priv_size && priv_size != shared->priv_size)
@@ -1733,7 +1735,7 @@ void phy_package_leave(struct phy_device *phydev)
 		return;
 
 	if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) {
-		bus->shared[shared->addr] = NULL;
+		bus->shared[shared->base_addr] = NULL;
 		mutex_unlock(&bus->shared_lock);
 		kfree(shared->priv);
 		kfree(shared);
@@ -1752,7 +1754,8 @@ static void devm_phy_package_leave(struct device *dev, void *res)
  * devm_phy_package_join - resource managed phy_package_join()
  * @dev: device that is registering this PHY package
  * @phydev: target phy_device struct
- * @addr: cookie and PHY address for global register access
+ * @base_addr: cookie and base PHY address of PHY package for offset
+ *   calculation of global register access
  * @priv_size: if non-zero allocate this amount of bytes for private data
  *
  * Managed phy_package_join(). Shared storage fetched by this function,
@@ -1760,7 +1763,7 @@ static void devm_phy_package_leave(struct device *dev, void *res)
  * phy_package_join() for more information.
  */
 int devm_phy_package_join(struct device *dev, struct phy_device *phydev,
-			  int addr, size_t priv_size)
+			  int base_addr, size_t priv_size)
 {
 	struct phy_device **ptr;
 	int ret;
@@ -1770,7 +1773,7 @@ int devm_phy_package_join(struct device *dev, struct phy_device *phydev,
 	if (!ptr)
 		return -ENOMEM;
 
-	ret = phy_package_join(phydev, addr, priv_size);
+	ret = phy_package_join(phydev, base_addr, priv_size);
 
 	if (!ret) {
 		*ptr = phydev;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index e5e29fca4d17..aaec34389f48 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -327,7 +327,8 @@ struct mdio_bus_stats {
 
 /**
  * struct phy_package_shared - Shared information in PHY packages
- * @addr: Common PHY address used to combine PHYs in one package
+ * @base_addr: Base PHY address of PHY package used to combine PHYs
+ *   in one package and for offset calculation of phy_package_read/write
  * @refcnt: Number of PHYs connected to this shared data
  * @flags: Initialization of PHY package
  * @priv_size: Size of the shared private data @priv
@@ -338,7 +339,7 @@ struct mdio_bus_stats {
  * phy_package_leave().
  */
 struct phy_package_shared {
-	u8 addr;
+	u8 base_addr;
 	refcount_t refcnt;
 	unsigned long flags;
 	size_t priv_size;
@@ -1972,10 +1973,10 @@ int phy_ethtool_get_link_ksettings(struct net_device *ndev,
 int phy_ethtool_set_link_ksettings(struct net_device *ndev,
 				   const struct ethtool_link_ksettings *cmd);
 int phy_ethtool_nway_reset(struct net_device *ndev);
-int phy_package_join(struct phy_device *phydev, int addr, size_t priv_size);
+int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size);
 void phy_package_leave(struct phy_device *phydev);
 int devm_phy_package_join(struct device *dev, struct phy_device *phydev,
-			  int addr, size_t priv_size);
+			  int base_addr, size_t priv_size);
 
 int __init mdio_bus_init(void);
 void mdio_bus_exit(void);
@@ -1998,46 +1999,54 @@ int __phy_hwtstamp_set(struct phy_device *phydev,
 		       struct kernel_hwtstamp_config *config,
 		       struct netlink_ext_ack *extack);
 
-static inline int phy_package_read(struct phy_device *phydev, u32 regnum)
+static inline int phy_package_read(struct phy_device *phydev,
+				   unsigned int addr_offset, u32 regnum)
 {
 	struct phy_package_shared *shared = phydev->shared;
+	u8 addr = shared->base_addr + addr_offset;
 
-	if (!shared)
+	if (addr >= PHY_MAX_ADDR)
 		return -EIO;
 
-	return mdiobus_read(phydev->mdio.bus, shared->addr, regnum);
+	return mdiobus_read(phydev->mdio.bus, addr, regnum);
 }
 
-static inline int __phy_package_read(struct phy_device *phydev, u32 regnum)
+static inline int __phy_package_read(struct phy_device *phydev,
+				     unsigned int addr_offset, u32 regnum)
 {
 	struct phy_package_shared *shared = phydev->shared;
+	u8 addr = shared->base_addr + addr_offset;
 
-	if (!shared)
+	if (addr >= PHY_MAX_ADDR)
 		return -EIO;
 
-	return __mdiobus_read(phydev->mdio.bus, shared->addr, regnum);
+	return __mdiobus_read(phydev->mdio.bus, addr, regnum);
 }
 
 static inline int phy_package_write(struct phy_device *phydev,
-				    u32 regnum, u16 val)
+				    unsigned int addr_offset, u32 regnum,
+				    u16 val)
 {
 	struct phy_package_shared *shared = phydev->shared;
+	u8 addr = shared->base_addr + addr_offset;
 
-	if (!shared)
+	if (addr >= PHY_MAX_ADDR)
 		return -EIO;
 
-	return mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val);
+	return mdiobus_write(phydev->mdio.bus, addr, regnum, val);
 }
 
 static inline int __phy_package_write(struct phy_device *phydev,
-				      u32 regnum, u16 val)
+				      unsigned int addr_offset, u32 regnum,
+				      u16 val)
 {
 	struct phy_package_shared *shared = phydev->shared;
+	u8 addr = shared->base_addr + addr_offset;
 
-	if (!shared)
+	if (addr >= PHY_MAX_ADDR)
 		return -EIO;
 
-	return __mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val);
+	return __mdiobus_write(phydev->mdio.bus, addr, regnum, val);
 }
 
 static inline bool __phy_package_set_once(struct phy_device *phydev,
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [net-next PATCH v7 3/4] net: phy: restructure __phy_write/read_mmd to helper and phydev user
  2023-12-14 12:10 [net-next PATCH v7 0/4] net: phy: add PHY package base addr + mmd APIs Christian Marangi
  2023-12-14 12:10 ` [net-next PATCH v7 1/4] net: phy: make addr type u8 in phy_package_shared struct Christian Marangi
  2023-12-14 12:10 ` [net-next PATCH v7 2/4] net: phy: extend PHY package API to support multiple global address Christian Marangi
@ 2023-12-14 12:10 ` Christian Marangi
  2023-12-14 12:10 ` [net-next PATCH v7 4/4] net: phy: add support for PHY package MMD read/write Christian Marangi
  3 siblings, 0 replies; 12+ messages in thread
From: Christian Marangi @ 2023-12-14 12:10 UTC (permalink / raw)
  To: Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Vladimir Oltean,
	David Epping, Russell King (Oracle),
	Christian Marangi, Harini Katakam, netdev, linux-kernel

Restructure phy_write_mmd and phy_read_mmd to implement generic helper
for direct mdiobus access for mmd and use these helper for phydev user.

This is needed in preparation of PHY package API that requires generic
access to the mdiobus and are deatched from phydev struct but instead
access them based on PHY package base_addr and offsets.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
Changes v6:
- Add Reviewed-by tag
Changes v3:
- Move to phy-core.c instead of inline in phy.h
Changes v2:
- Introduce this patch

 drivers/net/phy/phy-core.c | 64 ++++++++++++++++++--------------------
 1 file changed, 30 insertions(+), 34 deletions(-)

diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index 966c93cbe616..b729ac8b2640 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -540,6 +540,28 @@ static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,
 			devad | MII_MMD_CTRL_NOINCR);
 }
 
+static int mmd_phy_read(struct mii_bus *bus, int phy_addr, bool is_c45,
+			int devad, u32 regnum)
+{
+	if (is_c45)
+		return __mdiobus_c45_read(bus, phy_addr, devad, regnum);
+
+	mmd_phy_indirect(bus, phy_addr, devad, regnum);
+	/* Read the content of the MMD's selected register */
+	return __mdiobus_read(bus, phy_addr, MII_MMD_DATA);
+}
+
+static int mmd_phy_write(struct mii_bus *bus, int phy_addr, bool is_c45,
+			 int devad, u32 regnum, u16 val)
+{
+	if (is_c45)
+		return __mdiobus_c45_write(bus, phy_addr, devad, regnum, val);
+
+	mmd_phy_indirect(bus, phy_addr, devad, regnum);
+	/* Write the data into MMD's selected register */
+	return __mdiobus_write(bus, phy_addr, MII_MMD_DATA, val);
+}
+
 /**
  * __phy_read_mmd - Convenience function for reading a register
  * from an MMD on a given PHY.
@@ -551,26 +573,14 @@ static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,
  */
 int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
 {
-	int val;
-
 	if (regnum > (u16)~0 || devad > 32)
 		return -EINVAL;
 
-	if (phydev->drv && phydev->drv->read_mmd) {
-		val = phydev->drv->read_mmd(phydev, devad, regnum);
-	} else if (phydev->is_c45) {
-		val = __mdiobus_c45_read(phydev->mdio.bus, phydev->mdio.addr,
-					 devad, regnum);
-	} else {
-		struct mii_bus *bus = phydev->mdio.bus;
-		int phy_addr = phydev->mdio.addr;
+	if (phydev->drv && phydev->drv->read_mmd)
+		return phydev->drv->read_mmd(phydev, devad, regnum);
 
-		mmd_phy_indirect(bus, phy_addr, devad, regnum);
-
-		/* Read the content of the MMD's selected register */
-		val = __mdiobus_read(bus, phy_addr, MII_MMD_DATA);
-	}
-	return val;
+	return mmd_phy_read(phydev->mdio.bus, phydev->mdio.addr,
+			    phydev->is_c45, devad, regnum);
 }
 EXPORT_SYMBOL(__phy_read_mmd);
 
@@ -607,28 +617,14 @@ EXPORT_SYMBOL(phy_read_mmd);
  */
 int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
 {
-	int ret;
-
 	if (regnum > (u16)~0 || devad > 32)
 		return -EINVAL;
 
-	if (phydev->drv && phydev->drv->write_mmd) {
-		ret = phydev->drv->write_mmd(phydev, devad, regnum, val);
-	} else if (phydev->is_c45) {
-		ret = __mdiobus_c45_write(phydev->mdio.bus, phydev->mdio.addr,
-					  devad, regnum, val);
-	} else {
-		struct mii_bus *bus = phydev->mdio.bus;
-		int phy_addr = phydev->mdio.addr;
+	if (phydev->drv && phydev->drv->write_mmd)
+		return phydev->drv->write_mmd(phydev, devad, regnum, val);
 
-		mmd_phy_indirect(bus, phy_addr, devad, regnum);
-
-		/* Write the data into MMD's selected register */
-		__mdiobus_write(bus, phy_addr, MII_MMD_DATA, val);
-
-		ret = 0;
-	}
-	return ret;
+	return mmd_phy_write(phydev->mdio.bus, phydev->mdio.addr,
+			     phydev->is_c45, devad, regnum, val);
 }
 EXPORT_SYMBOL(__phy_write_mmd);
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [net-next PATCH v7 4/4] net: phy: add support for PHY package MMD read/write
  2023-12-14 12:10 [net-next PATCH v7 0/4] net: phy: add PHY package base addr + mmd APIs Christian Marangi
                   ` (2 preceding siblings ...)
  2023-12-14 12:10 ` [net-next PATCH v7 3/4] net: phy: restructure __phy_write/read_mmd to helper and phydev user Christian Marangi
@ 2023-12-14 12:10 ` Christian Marangi
  2023-12-14 17:06   ` Russell King (Oracle)
  3 siblings, 1 reply; 12+ messages in thread
From: Christian Marangi @ 2023-12-14 12:10 UTC (permalink / raw)
  To: Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Vladimir Oltean,
	David Epping, Russell King (Oracle),
	Christian Marangi, Harini Katakam, netdev, linux-kernel

Some PHY in PHY package may require to read/write MMD regs to correctly
configure the PHY package.

Add support for these additional required function in both lock and no
lock variant.

It's assumed that the entire PHY package is either C22 or C45. We use
C22 or C45 way of writing/reading to mmd regs based on the passed phydev
whether it's C22 or C45.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
Changes v7:
- Change addr to u8
Changes v6:
- Fix copy paste error for kdoc
Changes v5:
- Improve function description
Changes v4:
- Drop function comments in header file
Changes v3:
- Move in phy-core.c from phy.h
- Base c45 from phydev
Changes v2:
- Rework to use newly introduced helper
- Add common check for regnum and devad

 drivers/net/phy/phy-core.c | 144 +++++++++++++++++++++++++++++++++++++
 include/linux/phy.h        |  16 +++++
 2 files changed, 160 insertions(+)

diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index b729ac8b2640..7af935c6abe5 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -650,6 +650,150 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
 }
 EXPORT_SYMBOL(phy_write_mmd);
 
+/**
+ * __phy_package_read_mmd - read MMD reg relative to PHY package base addr
+ * @phydev: The phy_device struct
+ * @addr_offset: The offset to be added to PHY package base_addr
+ * @devad: The MMD to read from
+ * @regnum: The register on the MMD to read
+ *
+ * Convenience helper for reading a register of an MMD on a given PHY
+ * using the PHY package base address. The base address is added to
+ * the addr_offset value.
+ *
+ * Same calling rules as for __phy_read();
+ *
+ * NOTE: It's assumed that the entire PHY package is either C22 or C45.
+ */
+int __phy_package_read_mmd(struct phy_device *phydev,
+			   unsigned int addr_offset, int devad,
+			   u32 regnum)
+{
+	struct phy_package_shared *shared = phydev->shared;
+	u8 addr = shared->base_addr + addr_offset;
+
+	if (addr >= PHY_MAX_ADDR)
+		return -EIO;
+
+	if (regnum > (u16)~0 || devad > 32)
+		return -EINVAL;
+
+	return mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad,
+			    regnum);
+}
+EXPORT_SYMBOL(__phy_package_read_mmd);
+
+/**
+ * phy_package_read_mmd - read MMD reg relative to PHY package base addr
+ * @phydev: The phy_device struct
+ * @addr_offset: The offset to be added to PHY package base_addr
+ * @devad: The MMD to read from
+ * @regnum: The register on the MMD to read
+ *
+ * Convenience helper for reading a register of an MMD on a given PHY
+ * using the PHY package base address. The base address is added to
+ * the addr_offset value.
+ *
+ * Same calling rules as for phy_read();
+ *
+ * NOTE: It's assumed that the entire PHY package is either C22 or C45.
+ */
+int phy_package_read_mmd(struct phy_device *phydev,
+			 unsigned int addr_offset, int devad,
+			 u32 regnum)
+{
+	struct phy_package_shared *shared = phydev->shared;
+	u8 addr = shared->base_addr + addr_offset;
+	int val;
+
+	if (addr >= PHY_MAX_ADDR)
+		return -EIO;
+
+	if (regnum > (u16)~0 || devad > 32)
+		return -EINVAL;
+
+	phy_lock_mdio_bus(phydev);
+	val = mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad,
+			   regnum);
+	phy_unlock_mdio_bus(phydev);
+
+	return val;
+}
+EXPORT_SYMBOL(phy_package_read_mmd);
+
+/**
+ * __phy_package_write_mmd - write MMD reg relative to PHY package base addr
+ * @phydev: The phy_device struct
+ * @addr_offset: The offset to be added to PHY package base_addr
+ * @devad: The MMD to write to
+ * @regnum: The register on the MMD to write
+ * @val: value to write to @regnum
+ *
+ * Convenience helper for writing a register of an MMD on a given PHY
+ * using the PHY package base address. The base address is added to
+ * the addr_offset value.
+ *
+ * Same calling rules as for __phy_write();
+ *
+ * NOTE: It's assumed that the entire PHY package is either C22 or C45.
+ */
+int __phy_package_write_mmd(struct phy_device *phydev,
+			    unsigned int addr_offset, int devad,
+			    u32 regnum, u16 val)
+{
+	struct phy_package_shared *shared = phydev->shared;
+	u8 addr = shared->base_addr + addr_offset;
+
+	if (addr >= PHY_MAX_ADDR)
+		return -EIO;
+
+	if (regnum > (u16)~0 || devad > 32)
+		return -EINVAL;
+
+	return mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad,
+			     regnum, val);
+}
+EXPORT_SYMBOL(__phy_package_write_mmd);
+
+/**
+ * phy_package_write_mmd - write MMD reg relative to PHY package base addr
+ * @phydev: The phy_device struct
+ * @addr_offset: The offset to be added to PHY package base_addr
+ * @devad: The MMD to write to
+ * @regnum: The register on the MMD to write
+ * @val: value to write to @regnum
+ *
+ * Convenience helper for writing a register of an MMD on a given PHY
+ * using the PHY package base address. The base address is added to
+ * the addr_offset value.
+ *
+ * Same calling rules as for phy_write();
+ *
+ * NOTE: It's assumed that the entire PHY package is either C22 or C45.
+ */
+int phy_package_write_mmd(struct phy_device *phydev,
+			  unsigned int addr_offset, int devad,
+			  u32 regnum, u16 val)
+{
+	struct phy_package_shared *shared = phydev->shared;
+	u8 addr = shared->base_addr + addr_offset;
+	int ret;
+
+	if (addr >= PHY_MAX_ADDR)
+		return -EIO;
+
+	if (regnum > (u16)~0 || devad > 32)
+		return -EINVAL;
+
+	phy_lock_mdio_bus(phydev);
+	ret = mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad,
+			    regnum, val);
+	phy_unlock_mdio_bus(phydev);
+
+	return ret;
+}
+EXPORT_SYMBOL(phy_package_write_mmd);
+
 /**
  * phy_modify_changed - Function for modifying a PHY register
  * @phydev: the phy_device struct
diff --git a/include/linux/phy.h b/include/linux/phy.h
index aaec34389f48..78daac729385 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -2049,6 +2049,22 @@ static inline int __phy_package_write(struct phy_device *phydev,
 	return __mdiobus_write(phydev->mdio.bus, addr, regnum, val);
 }
 
+int __phy_package_read_mmd(struct phy_device *phydev,
+			   unsigned int addr_offset, int devad,
+			   u32 regnum);
+
+int phy_package_read_mmd(struct phy_device *phydev,
+			 unsigned int addr_offset, int devad,
+			 u32 regnum);
+
+int __phy_package_write_mmd(struct phy_device *phydev,
+			    unsigned int addr_offset, int devad,
+			    u32 regnum, u16 val);
+
+int phy_package_write_mmd(struct phy_device *phydev,
+			  unsigned int addr_offset, int devad,
+			  u32 regnum, u16 val);
+
 static inline bool __phy_package_set_once(struct phy_device *phydev,
 					  unsigned int b)
 {
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [net-next PATCH v7 2/4] net: phy: extend PHY package API to support multiple global address
  2023-12-14 17:05   ` Russell King (Oracle)
@ 2023-12-14 16:54     ` Christian Marangi
  2023-12-14 23:54       ` Russell King (Oracle)
  0 siblings, 1 reply; 12+ messages in thread
From: Christian Marangi @ 2023-12-14 16:54 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Vladimir Oltean, David Epping,
	Harini Katakam, netdev, linux-kernel

On Thu, Dec 14, 2023 at 05:05:39PM +0000, Russell King (Oracle) wrote:
> On Thu, Dec 14, 2023 at 01:10:24PM +0100, Christian Marangi wrote:
> > @@ -1998,46 +1999,54 @@ int __phy_hwtstamp_set(struct phy_device *phydev,
> >  		       struct kernel_hwtstamp_config *config,
> >  		       struct netlink_ext_ack *extack);
> >  
> > -static inline int phy_package_read(struct phy_device *phydev, u32 regnum)
> > +static inline int phy_package_read(struct phy_device *phydev,
> > +				   unsigned int addr_offset, u32 regnum)
> >  {
> >  	struct phy_package_shared *shared = phydev->shared;
> > +	u8 addr = shared->base_addr + addr_offset;
> >  
> > -	if (!shared)
> > +	if (addr >= PHY_MAX_ADDR)
> >  		return -EIO;
> 
> I did notice that you're using u8 in patch 1 as well - and while it's
> fine in patch 1 (because we validate the range of the value we will
> assign to that variable) that is not the case here.
> 
> Yes, shared->base_addr is a u8, but addr_offset is an unsigned int,
> and this is implicitly cast-down to a u8 in the calculation of addr,
> chopping off the bits above bit 7.
> 
> How about this approach:
> 
> static int phy_package_address(struct phy_device *phydev,
> 			       unsigned int addr_offset)
> {
> 	struct phy_package_shared *shared = phydev->shared;
> 	unsigned int addr = shared->addr + addr_offset;
> 
> 	/* detect wrap */
> 	if (addr < addr_offset)
> 		return -EIO;
> 
> 	/* detect invalid address */
> 	if (addr >= PHY_ADDR_MAX)
> 		return -EIO;
> 
> 	/* we know that addr will be in the range 0..31 and thus the
> 	 * implicit cast to a signed int is not a problem.
> 	 */
> 	return addr;
> }
> 
> and then these functions all become:
> 
> 	int addr = phy_package_address(phydev, addr_offset);
> 
> 	if (addr < 0)
> 		return addr;
> 
> I'll give you that this is belt and braces, but it avoids problems
> should a negative errno value be passed in as addr_offset (which will
> be cast to a very large positive integer.)

I also feel an helper is needed (since as you pointed out in the mmd
function we would have duplicated logic)

What I don't like is the wrap check.

But I wonder... Isn't it easier to have 

unsigned int addr = shared->base_addr + addr_offset;

and check if >= PHY_MAC_ADDR?

Everything is unsigned (so no negative case) and wrap is not possible as
nothing is downcasted.

After the check value is O.K. and can be trated as an int in
mdiobus_read (as we are sure it's in the limits and positive)

If this is correct, and the thing is a simple condition I think the
helper is not needed (or should we use it anyway for consistency in each
function?)

> 
> Andrew, any opinions on how far this should be taken?
> 

-- 
	Ansuel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [net-next PATCH v7 1/4] net: phy: make addr type u8 in phy_package_shared struct
  2023-12-14 12:10 ` [net-next PATCH v7 1/4] net: phy: make addr type u8 in phy_package_shared struct Christian Marangi
@ 2023-12-14 16:56   ` Russell King (Oracle)
  0 siblings, 0 replies; 12+ messages in thread
From: Russell King (Oracle) @ 2023-12-14 16:56 UTC (permalink / raw)
  To: Christian Marangi
  Cc: Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Vladimir Oltean, David Epping,
	Harini Katakam, netdev, linux-kernel

On Thu, Dec 14, 2023 at 01:10:23PM +0100, Christian Marangi wrote:
> Switch addr type in phy_package_shared struct to u8.
> 
> The value is already checked to be non negative and to be less than
> PHY_MAX_ADDR, hence u8 is better suited than using int.
> 
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>

Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>

Thanks!

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [net-next PATCH v7 2/4] net: phy: extend PHY package API to support multiple global address
  2023-12-14 12:10 ` [net-next PATCH v7 2/4] net: phy: extend PHY package API to support multiple global address Christian Marangi
@ 2023-12-14 17:05   ` Russell King (Oracle)
  2023-12-14 16:54     ` Christian Marangi
  0 siblings, 1 reply; 12+ messages in thread
From: Russell King (Oracle) @ 2023-12-14 17:05 UTC (permalink / raw)
  To: Christian Marangi
  Cc: Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Vladimir Oltean, David Epping,
	Harini Katakam, netdev, linux-kernel

On Thu, Dec 14, 2023 at 01:10:24PM +0100, Christian Marangi wrote:
> @@ -1998,46 +1999,54 @@ int __phy_hwtstamp_set(struct phy_device *phydev,
>  		       struct kernel_hwtstamp_config *config,
>  		       struct netlink_ext_ack *extack);
>  
> -static inline int phy_package_read(struct phy_device *phydev, u32 regnum)
> +static inline int phy_package_read(struct phy_device *phydev,
> +				   unsigned int addr_offset, u32 regnum)
>  {
>  	struct phy_package_shared *shared = phydev->shared;
> +	u8 addr = shared->base_addr + addr_offset;
>  
> -	if (!shared)
> +	if (addr >= PHY_MAX_ADDR)
>  		return -EIO;

I did notice that you're using u8 in patch 1 as well - and while it's
fine in patch 1 (because we validate the range of the value we will
assign to that variable) that is not the case here.

Yes, shared->base_addr is a u8, but addr_offset is an unsigned int,
and this is implicitly cast-down to a u8 in the calculation of addr,
chopping off the bits above bit 7.

How about this approach:

static int phy_package_address(struct phy_device *phydev,
			       unsigned int addr_offset)
{
	struct phy_package_shared *shared = phydev->shared;
	unsigned int addr = shared->addr + addr_offset;

	/* detect wrap */
	if (addr < addr_offset)
		return -EIO;

	/* detect invalid address */
	if (addr >= PHY_ADDR_MAX)
		return -EIO;

	/* we know that addr will be in the range 0..31 and thus the
	 * implicit cast to a signed int is not a problem.
	 */
	return addr;
}

and then these functions all become:

	int addr = phy_package_address(phydev, addr_offset);

	if (addr < 0)
		return addr;

I'll give you that this is belt and braces, but it avoids problems
should a negative errno value be passed in as addr_offset (which will
be cast to a very large positive integer.)

Andrew, any opinions on how far this should be taken?

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [net-next PATCH v7 4/4] net: phy: add support for PHY package MMD read/write
  2023-12-14 12:10 ` [net-next PATCH v7 4/4] net: phy: add support for PHY package MMD read/write Christian Marangi
@ 2023-12-14 17:06   ` Russell King (Oracle)
  0 siblings, 0 replies; 12+ messages in thread
From: Russell King (Oracle) @ 2023-12-14 17:06 UTC (permalink / raw)
  To: Christian Marangi
  Cc: Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Vladimir Oltean, David Epping,
	Harini Katakam, netdev, linux-kernel

On Thu, Dec 14, 2023 at 01:10:26PM +0100, Christian Marangi wrote:
> Some PHY in PHY package may require to read/write MMD regs to correctly
> configure the PHY package.
> 
> Add support for these additional required function in both lock and no
> lock variant.
> 
> It's assumed that the entire PHY package is either C22 or C45. We use
> C22 or C45 way of writing/reading to mmd regs based on the passed phydev
> whether it's C22 or C45.
> 
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> ---
> Changes v7:
> - Change addr to u8
> Changes v6:
> - Fix copy paste error for kdoc
> Changes v5:
> - Improve function description
> Changes v4:
> - Drop function comments in header file
> Changes v3:
> - Move in phy-core.c from phy.h
> - Base c45 from phydev
> Changes v2:
> - Rework to use newly introduced helper
> - Add common check for regnum and devad
> 
>  drivers/net/phy/phy-core.c | 144 +++++++++++++++++++++++++++++++++++++
>  include/linux/phy.h        |  16 +++++
>  2 files changed, 160 insertions(+)
> 
> diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
> index b729ac8b2640..7af935c6abe5 100644
> --- a/drivers/net/phy/phy-core.c
> +++ b/drivers/net/phy/phy-core.c
> @@ -650,6 +650,150 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
>  }
>  EXPORT_SYMBOL(phy_write_mmd);
>  
> +/**
> + * __phy_package_read_mmd - read MMD reg relative to PHY package base addr
> + * @phydev: The phy_device struct
> + * @addr_offset: The offset to be added to PHY package base_addr
> + * @devad: The MMD to read from
> + * @regnum: The register on the MMD to read
> + *
> + * Convenience helper for reading a register of an MMD on a given PHY
> + * using the PHY package base address. The base address is added to
> + * the addr_offset value.
> + *
> + * Same calling rules as for __phy_read();
> + *
> + * NOTE: It's assumed that the entire PHY package is either C22 or C45.
> + */
> +int __phy_package_read_mmd(struct phy_device *phydev,
> +			   unsigned int addr_offset, int devad,
> +			   u32 regnum)
> +{
> +	struct phy_package_shared *shared = phydev->shared;
> +	u8 addr = shared->base_addr + addr_offset;
> +
> +	if (addr >= PHY_MAX_ADDR)
> +		return -EIO;

The helper I mentioned in the previous patch (whether or not we do the
rest of the range checks) would probably be a good idea to get away from
the repetitive nature of this logic. This patch adds four more!

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [net-next PATCH v7 2/4] net: phy: extend PHY package API to support multiple global address
  2023-12-14 23:54       ` Russell King (Oracle)
@ 2023-12-14 17:29         ` Christian Marangi
  2023-12-15  9:16           ` Russell King (Oracle)
  0 siblings, 1 reply; 12+ messages in thread
From: Christian Marangi @ 2023-12-14 17:29 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Vladimir Oltean, David Epping,
	Harini Katakam, netdev, linux-kernel

On Thu, Dec 14, 2023 at 11:54:26PM +0000, Russell King (Oracle) wrote:
> On Thu, Dec 14, 2023 at 05:54:51PM +0100, Christian Marangi wrote:
> > What I don't like is the wrap check.
> > 
> > But I wonder... Isn't it easier to have 
> > 
> > unsigned int addr = shared->base_addr + addr_offset;
> > 
> > and check if >= PHY_MAC_ADDR?
> > 
> > Everything is unsigned (so no negative case) and wrap is not possible as
> > nothing is downcasted.
> 
> I'm afraid that I LOL'd at "wrap is not possible" ! Of course it's
> possible. Here's an example:
>

Yes I just think about it and I'm also LOLing at the "not possible"...

> 	shared->base_addr is 20
> 	addr_offset is ~0 (or -1 casted to an unsigned int)
> 	addr becomes 19
> 
> How about:
> 
> 	if (addr_offset >= PHY_MAX_ADDR)
> 		return -EIO;
> 
> 	addr = shared->base_addr + addr_offset;
> 	if (addr >= PHY_MAX_ADDR)
> 		return -EIO;
> 
> and then we could keep 'addr' as u8.

Ok just to make sure

static int phy_package_address(struct phy_device *phydev,
                               unsigned int addr_offset)
{
        struct phy_package_shared *shared = phydev->shared;
        unsigned int addr;

        if (addr_offset >= PHY_MAX_ADDR)
                return -EIO;

        addr = shared->base_addr + addr_offset;
        if (addr >= PHY_ADDR_MAX)
                return -EIO;

        /* we know that addr will be in the range 0..31 and thus the
         * implicit cast to a signed int is not a problem.
         */
        return addr;
}

And call u8 addr = phy_package_address(phydev, addr_offset);

Maybe one if can be skipped with the following fun thing?

static int phy_package_address(struct phy_device *phydev,
                               unsigned int addr_offset)
{
        struct phy_package_shared *shared = phydev->shared;
        u8 base_addr = shared->base_addr;

        if (addr_offset >= PHY_MAX_ADDR - base_addr)
                return -EIO;

        /* we know that addr will be in the range 0..31 and thus the
         * implicit cast to a signed int is not a problem.
         */
        return base_addr + addr_offset;
}

(don't hate me it's late here and my brain is half working ahahha)

> 
> Honestly, I have wondered why the mdio bus address is a signed int, but
> never decided to do anything about it.
> 

Maybe because direct usage of mdiobus_ is discouraged and phy_write will
use an addr that is already validated.

-- 
	Ansuel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [net-next PATCH v7 2/4] net: phy: extend PHY package API to support multiple global address
  2023-12-14 16:54     ` Christian Marangi
@ 2023-12-14 23:54       ` Russell King (Oracle)
  2023-12-14 17:29         ` Christian Marangi
  0 siblings, 1 reply; 12+ messages in thread
From: Russell King (Oracle) @ 2023-12-14 23:54 UTC (permalink / raw)
  To: Christian Marangi
  Cc: Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Vladimir Oltean, David Epping,
	Harini Katakam, netdev, linux-kernel

On Thu, Dec 14, 2023 at 05:54:51PM +0100, Christian Marangi wrote:
> What I don't like is the wrap check.
> 
> But I wonder... Isn't it easier to have 
> 
> unsigned int addr = shared->base_addr + addr_offset;
> 
> and check if >= PHY_MAC_ADDR?
> 
> Everything is unsigned (so no negative case) and wrap is not possible as
> nothing is downcasted.

I'm afraid that I LOL'd at "wrap is not possible" ! Of course it's
possible. Here's an example:

	shared->base_addr is 20
	addr_offset is ~0 (or -1 casted to an unsigned int)
	addr becomes 19

How about:

	if (addr_offset >= PHY_MAX_ADDR)
		return -EIO;

	addr = shared->base_addr + addr_offset;
	if (addr >= PHY_MAX_ADDR)
		return -EIO;

and then we could keep 'addr' as u8.

Honestly, I have wondered why the mdio bus address is a signed int, but
never decided to do anything about it.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [net-next PATCH v7 2/4] net: phy: extend PHY package API to support multiple global address
  2023-12-14 17:29         ` Christian Marangi
@ 2023-12-15  9:16           ` Russell King (Oracle)
  0 siblings, 0 replies; 12+ messages in thread
From: Russell King (Oracle) @ 2023-12-15  9:16 UTC (permalink / raw)
  To: Christian Marangi
  Cc: Florian Fainelli, Broadcom internal kernel review list,
	Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Vladimir Oltean, David Epping,
	Harini Katakam, netdev, linux-kernel

On Thu, Dec 14, 2023 at 06:29:28PM +0100, Christian Marangi wrote:
> On Thu, Dec 14, 2023 at 11:54:26PM +0000, Russell King (Oracle) wrote:
> > On Thu, Dec 14, 2023 at 05:54:51PM +0100, Christian Marangi wrote:
> > > What I don't like is the wrap check.
> > > 
> > > But I wonder... Isn't it easier to have 
> > > 
> > > unsigned int addr = shared->base_addr + addr_offset;
> > > 
> > > and check if >= PHY_MAC_ADDR?
> > > 
> > > Everything is unsigned (so no negative case) and wrap is not possible as
> > > nothing is downcasted.
> > 
> > I'm afraid that I LOL'd at "wrap is not possible" ! Of course it's
> > possible. Here's an example:
> >
> 
> Yes I just think about it and I'm also LOLing at the "not possible"...
> 
> > 	shared->base_addr is 20
> > 	addr_offset is ~0 (or -1 casted to an unsigned int)
> > 	addr becomes 19
> > 
> > How about:
> > 
> > 	if (addr_offset >= PHY_MAX_ADDR)
> > 		return -EIO;
> > 
> > 	addr = shared->base_addr + addr_offset;
> > 	if (addr >= PHY_MAX_ADDR)
> > 		return -EIO;
> > 
> > and then we could keep 'addr' as u8.
> 
> Ok just to make sure
> 
> static int phy_package_address(struct phy_device *phydev,
>                                unsigned int addr_offset)
> {
>         struct phy_package_shared *shared = phydev->shared;
>         unsigned int addr;
> 
>         if (addr_offset >= PHY_MAX_ADDR)
>                 return -EIO;
> 
>         addr = shared->base_addr + addr_offset;
>         if (addr >= PHY_ADDR_MAX)
>                 return -EIO;
> 
>         /* we know that addr will be in the range 0..31 and thus the
>          * implicit cast to a signed int is not a problem.
>          */
>         return addr;
> }

Yep.

> And call u8 addr = phy_package_address(phydev, addr_offset);

This has to be int to cater for -EIO

> Maybe one if can be skipped with the following fun thing?
> 
> static int phy_package_address(struct phy_device *phydev,
>                                unsigned int addr_offset)
> {
>         struct phy_package_shared *shared = phydev->shared;
>         u8 base_addr = shared->base_addr;
> 
>         if (addr_offset >= PHY_MAX_ADDR - base_addr)
>                 return -EIO;

That also works.
> 
>         /* we know that addr will be in the range 0..31 and thus the
>          * implicit cast to a signed int is not a problem.
>          */
>         return base_addr + addr_offset;
> }
> 
> (don't hate me it's late here and my brain is half working ahahha)
> 
> > 
> > Honestly, I have wondered why the mdio bus address is a signed int, but
> > never decided to do anything about it.
> > 
> 
> Maybe because direct usage of mdiobus_ is discouraged and phy_write will
> use an addr that is already validated.

It's discourged in PHY drivers where one has the phy_device.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2023-12-15  9:16 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-14 12:10 [net-next PATCH v7 0/4] net: phy: add PHY package base addr + mmd APIs Christian Marangi
2023-12-14 12:10 ` [net-next PATCH v7 1/4] net: phy: make addr type u8 in phy_package_shared struct Christian Marangi
2023-12-14 16:56   ` Russell King (Oracle)
2023-12-14 12:10 ` [net-next PATCH v7 2/4] net: phy: extend PHY package API to support multiple global address Christian Marangi
2023-12-14 17:05   ` Russell King (Oracle)
2023-12-14 16:54     ` Christian Marangi
2023-12-14 23:54       ` Russell King (Oracle)
2023-12-14 17:29         ` Christian Marangi
2023-12-15  9:16           ` Russell King (Oracle)
2023-12-14 12:10 ` [net-next PATCH v7 3/4] net: phy: restructure __phy_write/read_mmd to helper and phydev user Christian Marangi
2023-12-14 12:10 ` [net-next PATCH v7 4/4] net: phy: add support for PHY package MMD read/write Christian Marangi
2023-12-14 17:06   ` Russell King (Oracle)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).