mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
platform/x86: serdev_helpers: Add get_serdev_controller_from_parent() helper
The x86-android-tablets code needs to be able to get a serdev_controller device from a PCI parent, rather then by the ACPI HID+UID of the parent, because on some tablets the UARTs are enumerated as PCI devices instead of ACPI devices. Split the code to walk the device hierarchy to find the serdev_controller from its parents out into a get_serdev_controller_from_parent() helper so that the x86-android-tablets code can re-use it. Reviewed-by: Andy Shevchenko <andy@kernel.org> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://lore.kernel.org/r/20241204204227.95757-5-hdegoede@redhat.com Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
This commit is contained in:
parent
478b00a623
commit
a6593c5c50
@ -22,32 +22,14 @@
|
|||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
|
||||||
static inline struct device *
|
static inline struct device *
|
||||||
get_serdev_controller(const char *serial_ctrl_hid,
|
get_serdev_controller_from_parent(struct device *ctrl_dev,
|
||||||
const char *serial_ctrl_uid,
|
|
||||||
int serial_ctrl_port,
|
int serial_ctrl_port,
|
||||||
const char *serdev_ctrl_name)
|
const char *serdev_ctrl_name)
|
||||||
{
|
{
|
||||||
struct device *ctrl_dev, *child;
|
struct device *child;
|
||||||
struct acpi_device *ctrl_adev;
|
|
||||||
char name[32];
|
char name[32];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ctrl_adev = acpi_dev_get_first_match_dev(serial_ctrl_hid, serial_ctrl_uid, -1);
|
|
||||||
if (!ctrl_adev) {
|
|
||||||
pr_err("error could not get %s/%s serial-ctrl adev\n",
|
|
||||||
serial_ctrl_hid, serial_ctrl_uid ?: "*");
|
|
||||||
return ERR_PTR(-ENODEV);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get_first_physical_node() returns a weak ref */
|
|
||||||
ctrl_dev = get_device(acpi_get_first_physical_node(ctrl_adev));
|
|
||||||
if (!ctrl_dev) {
|
|
||||||
pr_err("error could not get %s/%s serial-ctrl physical node\n",
|
|
||||||
serial_ctrl_hid, serial_ctrl_uid ?: "*");
|
|
||||||
ctrl_dev = ERR_PTR(-ENODEV);
|
|
||||||
goto put_ctrl_adev;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Walk host -> uart-ctrl -> port -> serdev-ctrl */
|
/* Walk host -> uart-ctrl -> port -> serdev-ctrl */
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
@ -67,14 +49,40 @@ get_serdev_controller(const char *serial_ctrl_hid,
|
|||||||
put_device(ctrl_dev);
|
put_device(ctrl_dev);
|
||||||
if (!child) {
|
if (!child) {
|
||||||
pr_err("error could not find '%s' device\n", name);
|
pr_err("error could not find '%s' device\n", name);
|
||||||
ctrl_dev = ERR_PTR(-ENODEV);
|
return ERR_PTR(-ENODEV);
|
||||||
goto put_ctrl_adev;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrl_dev = child;
|
ctrl_dev = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
put_ctrl_adev:
|
|
||||||
acpi_dev_put(ctrl_adev);
|
|
||||||
return ctrl_dev;
|
return ctrl_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct device *
|
||||||
|
get_serdev_controller(const char *serial_ctrl_hid,
|
||||||
|
const char *serial_ctrl_uid,
|
||||||
|
int serial_ctrl_port,
|
||||||
|
const char *serdev_ctrl_name)
|
||||||
|
{
|
||||||
|
struct acpi_device *adev;
|
||||||
|
struct device *parent;
|
||||||
|
|
||||||
|
adev = acpi_dev_get_first_match_dev(serial_ctrl_hid, serial_ctrl_uid, -1);
|
||||||
|
if (!adev) {
|
||||||
|
pr_err("error could not get %s/%s serial-ctrl adev\n",
|
||||||
|
serial_ctrl_hid, serial_ctrl_uid ?: "*");
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get_first_physical_node() returns a weak ref */
|
||||||
|
parent = get_device(acpi_get_first_physical_node(adev));
|
||||||
|
acpi_dev_put(adev);
|
||||||
|
if (!parent) {
|
||||||
|
pr_err("error could not get %s/%s serial-ctrl physical node\n",
|
||||||
|
serial_ctrl_hid, serial_ctrl_uid ?: "*");
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This puts our reference on parent and returns a ref on the ctrl */
|
||||||
|
return get_serdev_controller_from_parent(parent, serial_ctrl_port, serdev_ctrl_name);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user