Skip to content

Commit

Permalink
driver core: fw_devlink: Handle suppliers that don't use driver core
Browse files Browse the repository at this point in the history
Device links only work between devices that use the driver core to match
and bind a driver to a device. So, add an API for frameworks to let the
driver core know that a fwnode has been initialized by a driver without
using the driver core.

Then use this information to make sure that fw_devlink doesn't make the
consumers wait indefinitely on suppliers that'll never bind to a driver.

Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Saravana Kannan <saravanak@google.com>
Link: https://lore.kernel.org/r/20210205222644.2357303-6-saravanak@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Saravana Kannan authored and Greg Kroah-Hartman committed Feb 9, 2021
1 parent a9dd8f3 commit 74c782c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
15 changes: 15 additions & 0 deletions drivers/base/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1636,6 +1636,17 @@ static int fw_devlink_create_devlink(struct device *con,

sup_dev = get_dev_from_fwnode(sup_handle);
if (sup_dev) {
/*
* If it's one of those drivers that don't actually bind to
* their device using driver core, then don't wait on this
* supplier device indefinitely.
*/
if (sup_dev->links.status == DL_DEV_NO_DRIVER &&
sup_handle->flags & FWNODE_FLAG_INITIALIZED) {
ret = -EINVAL;
goto out;
}

/*
* If this fails, it is due to cycles in device links. Just
* give up on this link and treat it as invalid.
Expand All @@ -1655,6 +1666,10 @@ static int fw_devlink_create_devlink(struct device *con,
goto out;
}

/* Supplier that's already initialized without a struct device. */
if (sup_handle->flags & FWNODE_FLAG_INITIALIZED)
return -EINVAL;

/*
* DL_FLAG_SYNC_STATE_ONLY doesn't block probing and supports
* cycles. So cycle detection isn't necessary and shouldn't be
Expand Down
19 changes: 17 additions & 2 deletions include/linux/fwnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,21 @@

#include <linux/types.h>
#include <linux/list.h>
#include <linux/err.h>

struct fwnode_operations;
struct device;

/*
* fwnode link flags
*
* LINKS_ADDED: The fwnode has already be parsed to add fwnode links.
* NOT_DEVICE: The fwnode will never be populated as a struct device.
* LINKS_ADDED: The fwnode has already be parsed to add fwnode links.
* NOT_DEVICE: The fwnode will never be populated as a struct device.
* INITIALIZED: The hardware corresponding to fwnode has been initialized.
*/
#define FWNODE_FLAG_LINKS_ADDED BIT(0)
#define FWNODE_FLAG_NOT_DEVICE BIT(1)
#define FWNODE_FLAG_INITIALIZED BIT(2)

struct fwnode_handle {
struct fwnode_handle *secondary;
Expand Down Expand Up @@ -161,6 +164,18 @@ static inline void fwnode_init(struct fwnode_handle *fwnode,
INIT_LIST_HEAD(&fwnode->suppliers);
}

static inline void fwnode_dev_initialized(struct fwnode_handle *fwnode,
bool initialized)
{
if (IS_ERR_OR_NULL(fwnode))
return;

if (initialized)
fwnode->flags |= FWNODE_FLAG_INITIALIZED;
else
fwnode->flags &= ~FWNODE_FLAG_INITIALIZED;
}

extern u32 fw_devlink_get_flags(void);
extern bool fw_devlink_is_strict(void);
int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup);
Expand Down

0 comments on commit 74c782c

Please sign in to comment.