summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2023-06-09 05:19:52 +0300
committerJakub Kicinski <kuba@kernel.org>2023-06-09 05:19:52 +0300
commit68bd67b43fe9e6f8128d1bedf698b5f13ec6a766 (patch)
treeb5bab0b67e74e1a595f59168827808217c6d2d9f
parentc8cc2ae229ff0aa9b7e67fd38f5d73bece111e71 (diff)
parent32fc30353f7c4d5370acf6ef8fb3be9363dce3c2 (diff)
downloadlinux-68bd67b43fe9e6f8128d1bedf698b5f13ec6a766.tar.xz
Merge branch 'complete-lynx-mdio-device-handling'
Russell King says: ==================== complete Lynx mdio device handling This series completes the mdio device lifetime handling for Lynx PCS users which do not create their own mdio device, but instead fetch it using a firmware description - namely the DPAA2 and FMAN_MEMAC drivers. In a previous patch set, lynx_pcs_create() was modified to increase the mdio device refcount, and lynx_pcs_destroy() to drop that refcount. The first two patches change these two drivers to put the reference which they hold immediately after lynx_pcs_create(), effectively handing the responsibility for maintaining the refcount to the Lynx PCS driver. A side effect of the first two patches is that lynx_get_mdio_device() is no longer used, so patch 3 removes it. Patch 4 adds a new helper - lynx_pcs_create_fwnode(), which creates a Lynx PCS instance from the fwnode. Patch 5 and 6 convert the two drivers to make use of this new helper, which simply has to find the mdio device, and then create the Lynx PCS from that. With those conversions done, lynx_pcs_create() is no longer required outside pcs-lynx.c, so remove it from public view. Patch 8 we changes lynx_pcs_create() to return an error-pointer rather than NULL to bring consistency to the return style, and means that we can remove the NULL-to-error-pointer conversion from both lynx_pcs_create_fwnode() and lynx_pcs_create_mdiodev(). Patch 9 adds a check for the fwnode being available, and returns an -ENODEV error pointer if unavailable. Patch 10 removes this check from DPAA2, detecting the error pointer value to continue printing the helpful message. Patch 11 removes this check from fman_memac, and in doing so fixes a bug where if the node is unavailable, the reference count is not dropped. ==================== Link: https://lore.kernel.org/r/ZIBwuw+IuGQo5yV8@shell.armlinux.org.uk Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c32
-rw-r--r--drivers/net/ethernet/freescale/fman/fman_memac.c18
-rw-r--r--drivers/net/pcs/pcs-lynx.c54
-rw-r--r--include/linux/pcs-lynx.h4
4 files changed, 58 insertions, 50 deletions
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
index cb70855e2b9a..d860d9fe73af 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
@@ -247,8 +247,8 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac,
struct fwnode_handle *dpmac_node,
int id)
{
- struct mdio_device *mdiodev;
struct fwnode_handle *node;
+ struct phylink_pcs *pcs;
node = fwnode_find_reference(dpmac_node, "pcs-handle", 0);
if (IS_ERR(node)) {
@@ -257,26 +257,27 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac,
return 0;
}
- if (!fwnode_device_is_available(node)) {
- netdev_err(mac->net_dev, "pcs-handle node not available\n");
- fwnode_handle_put(node);
- return -ENODEV;
- }
-
- mdiodev = fwnode_mdio_find_device(node);
+ pcs = lynx_pcs_create_fwnode(node);
fwnode_handle_put(node);
- if (!mdiodev) {
+
+ if (pcs == ERR_PTR(-EPROBE_DEFER)) {
netdev_dbg(mac->net_dev, "missing PCS device\n");
return -EPROBE_DEFER;
}
- mac->pcs = lynx_pcs_create(mdiodev);
- if (!mac->pcs) {
- netdev_err(mac->net_dev, "lynx_pcs_create() failed\n");
- mdio_device_free(mdiodev);
- return -ENOMEM;
+ if (pcs == ERR_PTR(-ENODEV)) {
+ netdev_err(mac->net_dev, "pcs-handle node not available\n");
+ return PTR_ERR(pcs);
+ }
+
+ if (IS_ERR(pcs)) {
+ netdev_err(mac->net_dev,
+ "lynx_pcs_create_fwnode() failed: %pe\n", pcs);
+ return PTR_ERR(pcs);
}
+ mac->pcs = pcs;
+
return 0;
}
@@ -285,10 +286,7 @@ static void dpaa2_pcs_destroy(struct dpaa2_mac *mac)
struct phylink_pcs *phylink_pcs = mac->pcs;
if (phylink_pcs) {
- struct mdio_device *mdio = lynx_get_mdio_device(phylink_pcs);
-
lynx_pcs_destroy(phylink_pcs);
- mdio_device_free(mdio);
mac->pcs = NULL;
}
}
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 625c79d5636f..3b75cc543be9 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -976,14 +976,10 @@ static int memac_init(struct fman_mac *memac)
static void pcs_put(struct phylink_pcs *pcs)
{
- struct mdio_device *mdiodev;
-
if (IS_ERR_OR_NULL(pcs))
return;
- mdiodev = lynx_get_mdio_device(pcs);
lynx_pcs_destroy(pcs);
- mdio_device_free(mdiodev);
}
static int memac_free(struct fman_mac *memac)
@@ -1043,20 +1039,14 @@ static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node,
int index)
{
struct device_node *node;
- struct mdio_device *mdiodev = NULL;
struct phylink_pcs *pcs;
node = of_parse_phandle(mac_node, "pcsphy-handle", index);
- if (node && of_device_is_available(node))
- mdiodev = of_mdio_find_device(node);
- of_node_put(node);
+ if (!node)
+ return ERR_PTR(-ENODEV);
- if (!mdiodev)
- return ERR_PTR(-EPROBE_DEFER);
-
- pcs = lynx_pcs_create(mdiodev);
- if (!pcs)
- mdio_device_free(mdiodev);
+ pcs = lynx_pcs_create_fwnode(of_fwnode_handle(node));
+ of_node_put(node);
return pcs;
}
diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c
index f04dc580ffb8..fca48ebf0b81 100644
--- a/drivers/net/pcs/pcs-lynx.c
+++ b/drivers/net/pcs/pcs-lynx.c
@@ -6,6 +6,7 @@
#include <linux/mdio.h>
#include <linux/phylink.h>
#include <linux/pcs-lynx.h>
+#include <linux/property.h>
#define SGMII_CLOCK_PERIOD_NS 8 /* PCS is clocked at 125 MHz */
#define LINK_TIMER_VAL(ns) ((u32)((ns) / SGMII_CLOCK_PERIOD_NS))
@@ -34,14 +35,6 @@ enum sgmii_speed {
#define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs)
#define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs)
-struct mdio_device *lynx_get_mdio_device(struct phylink_pcs *pcs)
-{
- struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);
-
- return lynx->mdio;
-}
-EXPORT_SYMBOL(lynx_get_mdio_device);
-
static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs,
struct phylink_link_state *state)
{
@@ -315,13 +308,13 @@ static const struct phylink_pcs_ops lynx_pcs_phylink_ops = {
.pcs_link_up = lynx_pcs_link_up,
};
-struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
+static struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
{
struct lynx_pcs *lynx;
lynx = kzalloc(sizeof(*lynx), GFP_KERNEL);
if (!lynx)
- return NULL;
+ return ERR_PTR(-ENOMEM);
mdio_device_get(mdio);
lynx->mdio = mdio;
@@ -330,7 +323,6 @@ struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
return lynx_to_phylink_pcs(lynx);
}
-EXPORT_SYMBOL(lynx_pcs_create);
struct phylink_pcs *lynx_pcs_create_mdiodev(struct mii_bus *bus, int addr)
{
@@ -343,11 +335,41 @@ struct phylink_pcs *lynx_pcs_create_mdiodev(struct mii_bus *bus, int addr)
pcs = lynx_pcs_create(mdio);
- /* Convert failure to create the PCS to an error pointer, so this
- * function has a consistent return value strategy.
+ /* lynx_create() has taken a refcount on the mdiodev if it was
+ * successful. If lynx_create() fails, this will free the mdio
+ * device here. In any case, we don't need to hold our reference
+ * anymore, and putting it here will allow mdio_device_put() in
+ * lynx_destroy() to automatically free the mdio device.
*/
- if (!pcs)
- pcs = ERR_PTR(-ENOMEM);
+ mdio_device_put(mdio);
+
+ return pcs;
+}
+EXPORT_SYMBOL(lynx_pcs_create_mdiodev);
+
+/*
+ * lynx_pcs_create_fwnode() creates a lynx PCS instance from the fwnode
+ * device indicated by node.
+ *
+ * Returns:
+ * -ENODEV if the fwnode is marked unavailable
+ * -EPROBE_DEFER if we fail to find the device
+ * -ENOMEM if we fail to allocate memory
+ * pointer to a phylink_pcs on success
+ */
+struct phylink_pcs *lynx_pcs_create_fwnode(struct fwnode_handle *node)
+{
+ struct mdio_device *mdio;
+ struct phylink_pcs *pcs;
+
+ if (!fwnode_device_is_available(node))
+ return ERR_PTR(-ENODEV);
+
+ mdio = fwnode_mdio_find_device(node);
+ if (!mdio)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ pcs = lynx_pcs_create(mdio);
/* lynx_create() has taken a refcount on the mdiodev if it was
* successful. If lynx_create() fails, this will free the mdio
@@ -359,7 +381,7 @@ struct phylink_pcs *lynx_pcs_create_mdiodev(struct mii_bus *bus, int addr)
return pcs;
}
-EXPORT_SYMBOL(lynx_pcs_create_mdiodev);
+EXPORT_SYMBOL_GPL(lynx_pcs_create_fwnode);
void lynx_pcs_destroy(struct phylink_pcs *pcs)
{
diff --git a/include/linux/pcs-lynx.h b/include/linux/pcs-lynx.h
index 885b59d10581..7958cccd16f2 100644
--- a/include/linux/pcs-lynx.h
+++ b/include/linux/pcs-lynx.h
@@ -9,10 +9,8 @@
#include <linux/mdio.h>
#include <linux/phylink.h>
-struct mdio_device *lynx_get_mdio_device(struct phylink_pcs *pcs);
-
-struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio);
struct phylink_pcs *lynx_pcs_create_mdiodev(struct mii_bus *bus, int addr);
+struct phylink_pcs *lynx_pcs_create_fwnode(struct fwnode_handle *node);
void lynx_pcs_destroy(struct phylink_pcs *pcs);