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>
This commit is contained in:
Jakub Kicinski 2023-06-08 19:19:52 -07:00
commit 68bd67b43f
4 changed files with 59 additions and 51 deletions

View File

@ -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;
}
}

View File

@ -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,21 +1039,15 @@ 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);
if (!node)
return ERR_PTR(-ENODEV);
pcs = lynx_pcs_create_fwnode(of_fwnode_handle(node));
of_node_put(node);
if (!mdiodev)
return ERR_PTR(-EPROBE_DEFER);
pcs = lynx_pcs_create(mdiodev);
if (!pcs)
mdio_device_free(mdiodev);
return pcs;
}

View File

@ -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,12 +335,6 @@ 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.
*/
if (!pcs)
pcs = ERR_PTR(-ENOMEM);
/* 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
@ -361,6 +347,42 @@ struct phylink_pcs *lynx_pcs_create_mdiodev(struct mii_bus *bus, int addr)
}
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
* 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.
*/
mdio_device_put(mdio);
return pcs;
}
EXPORT_SYMBOL_GPL(lynx_pcs_create_fwnode);
void lynx_pcs_destroy(struct phylink_pcs *pcs)
{
struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);

View File

@ -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);