diff mbox series

[net-next,v9,03/15] net: phy: Introduce phy related fwnode functions

Message ID 20210611105401.270673-4-ciorneiioana@gmail.com (mailing list archive)
State Not Applicable, archived
Headers show
Series ACPI support for dpaa2 driver | expand

Commit Message

Ioana Ciornei June 11, 2021, 10:53 a.m. UTC
From: Calvin Johnson <calvin.johnson@oss.nxp.com>

Define fwnode_phy_find_device() to iterate an mdiobus and find the
phy device of the provided phy fwnode. Additionally define
device_phy_find_device() to find phy device of provided device.

Define fwnode_get_phy_node() to get phy_node using named reference.

Signed-off-by: Calvin Johnson <calvin.johnson@oss.nxp.com>
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Acked-by: Grant Likely <grant.likely@arm.com>
---

Changes in v9: None
Changes in v8: None
Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
- Add more info on legacy DT properties "phy" and "phy-device"
- Redefine fwnode_phy_find_device() to follow of_phy_find_device()

Changes in v2:
- use reverse christmas tree ordering for local variables


 drivers/net/phy/phy_device.c | 62 ++++++++++++++++++++++++++++++++++++
 include/linux/phy.h          | 20 ++++++++++++
 2 files changed, 82 insertions(+)

Comments

Andy Shevchenko June 11, 2021, 11:26 a.m. UTC | #1
On Fri, Jun 11, 2021 at 1:54 PM Ioana Ciornei <ciorneiioana@gmail.com> wrote:
>
> From: Calvin Johnson <calvin.johnson@oss.nxp.com>
>
> Define fwnode_phy_find_device() to iterate an mdiobus and find the
> phy device of the provided phy fwnode. Additionally define
> device_phy_find_device() to find phy device of provided device.
>
> Define fwnode_get_phy_node() to get phy_node using named reference.

using a named

...

> +struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
> +{
> +       struct fwnode_handle *phy_node;
> +
> +       /* Only phy-handle is used for ACPI */
> +       phy_node = fwnode_find_reference(fwnode, "phy-handle", 0);
> +       if (is_acpi_node(fwnode) || !IS_ERR(phy_node))
> +               return phy_node;
> +       phy_node = fwnode_find_reference(fwnode, "phy", 0);
> +       if (IS_ERR(phy_node))
> +               phy_node = fwnode_find_reference(fwnode, "phy-device", 0);
> +       return phy_node;

Looking into the patterns in this code I would perhaps refactor it the
following way:

     /* First try "phy-handle" as most common in use */
     phy_node = fwnode_find_reference(fwnode, "phy-handle", 0);
     /* Only phy-handle is used for ACPI */
     if (is_acpi_node(fwnode))
              return phy_node;
     if (!IS_ERR(phy_node))
              return phy_node;
     /* Try "phy" reference */
     phy_node = fwnode_find_reference(fwnode, "phy", 0);
     if (!IS_ERR(phy_node))
              return phy_node;
     /* At last try "phy-device" reference */
     return fwnode_find_reference(fwnode, "phy-device", 0);

> +}
Rafael J. Wysocki June 11, 2021, 11:40 a.m. UTC | #2
On Fri, Jun 11, 2021 at 1:26 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
>
> On Fri, Jun 11, 2021 at 1:54 PM Ioana Ciornei <ciorneiioana@gmail.com> wrote:
> >
> > From: Calvin Johnson <calvin.johnson@oss.nxp.com>
> >
> > Define fwnode_phy_find_device() to iterate an mdiobus and find the
> > phy device of the provided phy fwnode. Additionally define
> > device_phy_find_device() to find phy device of provided device.
> >
> > Define fwnode_get_phy_node() to get phy_node using named reference.
>
> using a named
>
> ...
>
> > +struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
> > +{
> > +       struct fwnode_handle *phy_node;
> > +
> > +       /* Only phy-handle is used for ACPI */
> > +       phy_node = fwnode_find_reference(fwnode, "phy-handle", 0);
> > +       if (is_acpi_node(fwnode) || !IS_ERR(phy_node))
> > +               return phy_node;
> > +       phy_node = fwnode_find_reference(fwnode, "phy", 0);
> > +       if (IS_ERR(phy_node))
> > +               phy_node = fwnode_find_reference(fwnode, "phy-device", 0);
> > +       return phy_node;
>
> Looking into the patterns in this code I would perhaps refactor it the
> following way:
>
>      /* First try "phy-handle" as most common in use */
>      phy_node = fwnode_find_reference(fwnode, "phy-handle", 0);
>      /* Only phy-handle is used for ACPI */
>      if (is_acpi_node(fwnode))
>               return phy_node;
>      if (!IS_ERR(phy_node))
>               return phy_node;

I'm not sure why you want the above to be two if () statements instead of one?

I would change the ordering anyway, that is

if (!IS_ERR(phy_node) || is_acpi_node(fwnode))
        return phy_node;

And I think that the is_acpi_node() check is there to return the error
code right away so as to avoid returning a "not found" error later.

But I'm not sure if this is really necessary.  Namely, if nothing
depends on the specific error code returned by this function, it would
be somewhat cleaner to let the code below run if phy_node is an error
pointer in the ACPI case, because in that case the code below will
produce an error pointer anyway.

>      /* Try "phy" reference */
>      phy_node = fwnode_find_reference(fwnode, "phy", 0);
>      if (!IS_ERR(phy_node))
>               return phy_node;
>      /* At last try "phy-device" reference */
>      return fwnode_find_reference(fwnode, "phy-device", 0);
>
> > +}
Russell King (Oracle) June 11, 2021, 12:08 p.m. UTC | #3
On Fri, Jun 11, 2021 at 01:40:59PM +0200, Rafael J. Wysocki wrote:
> I'm not sure why you want the above to be two if () statements instead of one?
> 
> I would change the ordering anyway, that is
> 
> if (!IS_ERR(phy_node) || is_acpi_node(fwnode))
>         return phy_node;
> 
> And I think that the is_acpi_node() check is there to return the error
> code right away so as to avoid returning a "not found" error later.
> 
> But I'm not sure if this is really necessary.  Namely, if nothing
> depends on the specific error code returned by this function, it would
> be somewhat cleaner to let the code below run if phy_node is an error
> pointer in the ACPI case, because in that case the code below will
> produce an error pointer anyway.

However, that opens the door to someone shipping "working" ACPI with
one of these names that we've taken the decision not to support on
ACPI firmware. Surely, it's much better that we don't accept the
legacy names so we don't allow such configurations to work.
Rafael J. Wysocki June 11, 2021, 12:31 p.m. UTC | #4
On Fri, Jun 11, 2021 at 2:08 PM Russell King (Oracle)
<linux@armlinux.org.uk> wrote:
>
> On Fri, Jun 11, 2021 at 01:40:59PM +0200, Rafael J. Wysocki wrote:
> > I'm not sure why you want the above to be two if () statements instead of one?
> >
> > I would change the ordering anyway, that is
> >
> > if (!IS_ERR(phy_node) || is_acpi_node(fwnode))
> >         return phy_node;
> >
> > And I think that the is_acpi_node() check is there to return the error
> > code right away so as to avoid returning a "not found" error later.
> >
> > But I'm not sure if this is really necessary.  Namely, if nothing
> > depends on the specific error code returned by this function, it would
> > be somewhat cleaner to let the code below run if phy_node is an error
> > pointer in the ACPI case, because in that case the code below will
> > produce an error pointer anyway.
>
> However, that opens the door to someone shipping "working" ACPI with
> one of these names that we've taken the decision not to support on
> ACPI firmware. Surely, it's much better that we don't accept the
> legacy names so we don't allow such configurations to work.

Fair enough.
diff mbox series

Patch

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index dca454b5c209..786f464216dd 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -9,6 +9,7 @@ 
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/acpi.h>
 #include <linux/bitmap.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -2898,6 +2899,67 @@  struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode)
 }
 EXPORT_SYMBOL(fwnode_mdio_find_device);
 
+/**
+ * fwnode_phy_find_device - For provided phy_fwnode, find phy_device.
+ *
+ * @phy_fwnode: Pointer to the phy's fwnode.
+ *
+ * If successful, returns a pointer to the phy_device with the embedded
+ * struct device refcount incremented by one, or NULL on failure.
+ */
+struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode)
+{
+	struct mdio_device *mdiodev;
+
+	mdiodev = fwnode_mdio_find_device(phy_fwnode);
+	if (!mdiodev)
+		return NULL;
+
+	if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY)
+		return to_phy_device(&mdiodev->dev);
+
+	put_device(&mdiodev->dev);
+
+	return NULL;
+}
+EXPORT_SYMBOL(fwnode_phy_find_device);
+
+/**
+ * device_phy_find_device - For the given device, get the phy_device
+ * @dev: Pointer to the given device
+ *
+ * Refer return conditions of fwnode_phy_find_device().
+ */
+struct phy_device *device_phy_find_device(struct device *dev)
+{
+	return fwnode_phy_find_device(dev_fwnode(dev));
+}
+EXPORT_SYMBOL_GPL(device_phy_find_device);
+
+/**
+ * fwnode_get_phy_node - Get the phy_node using the named reference.
+ * @fwnode: Pointer to fwnode from which phy_node has to be obtained.
+ *
+ * Refer return conditions of fwnode_find_reference().
+ * For ACPI, only "phy-handle" is supported. Legacy DT properties "phy"
+ * and "phy-device" are not supported in ACPI. DT supports all the three
+ * named references to the phy node.
+ */
+struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
+{
+	struct fwnode_handle *phy_node;
+
+	/* Only phy-handle is used for ACPI */
+	phy_node = fwnode_find_reference(fwnode, "phy-handle", 0);
+	if (is_acpi_node(fwnode) || !IS_ERR(phy_node))
+		return phy_node;
+	phy_node = fwnode_find_reference(fwnode, "phy", 0);
+	if (IS_ERR(phy_node))
+		phy_node = fwnode_find_reference(fwnode, "phy-device", 0);
+	return phy_node;
+}
+EXPORT_SYMBOL_GPL(fwnode_get_phy_node);
+
 /**
  * phy_probe - probe and init a PHY device
  * @dev: device to probe and init
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 7aa97f4e5387..f9b5fb099fa6 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1378,6 +1378,9 @@  struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
 				     struct phy_c45_device_ids *c45_ids);
 #if IS_ENABLED(CONFIG_PHYLIB)
 struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode);
+struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode);
+struct phy_device *device_phy_find_device(struct device *dev);
+struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode);
 struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);
 int phy_device_register(struct phy_device *phy);
 void phy_device_free(struct phy_device *phydev);
@@ -1388,6 +1391,23 @@  struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode)
 	return 0;
 }
 
+static inline
+struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode)
+{
+	return NULL;
+}
+
+static inline struct phy_device *device_phy_find_device(struct device *dev)
+{
+	return NULL;
+}
+
+static inline
+struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
 static inline
 struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
 {