Skip to content

Commit 9d9bcae

Browse files
committed
ACPI: delay enumeration of devices with a _DEP pointing to an INT3472 device
The clk and regulator frameworks expect clk/regulator consumer-devices to have info about the consumed clks/regulators described in the device's fw_node. To work around cases where this info is not present in the firmware tables, which is often the case on x86/ACPI devices, both frameworks allow the provider-driver to attach info about consumers to the clks/regulators when registering these. This causes problems with the probe ordering wrt drivers for consumers of these clks/regulators. Since the lookups are only registered when the provider-driver binds, trying to get these clks/regulators before then results in a -ENOENT error for clks and a dummy regulator for regulators. One case where we hit this issue is camera sensors such as e.g. the OV8865 sensor found on the Microsoft Surface Go. The sensor uses clks, regulators and GPIOs provided by a TPS68470 PMIC which is described in an INT3472 ACPI device. There is special platform code handling this and setting platform_data with the necessary consumer info on the MFD cells instantiated for the PMIC under: drivers/platform/x86/intel/int3472. For this to work properly the ov8865 driver must not bind to the I2C-client for the OV8865 sensor until after the TPS68470 PMIC gpio, regulator and clk MFD cells have all been fully setup. The OV8865 on the Microsoft Surface Go is just one example, all X86 devices using the Intel IPU3 camera block found on recent Intel SoCs have similar issues where there is an INT3472 HID ACPI-device, which describes the clks and regulators, and the driver for this INT3472 device must be fully initialized before the sensor driver (any sensor driver) binds for things to work properly. On these devices the ACPI nodes describing the sensors all have a _DEP dependency on the matching INT3472 ACPI device (there is one per sensor). This allows solving the probe-ordering problem by delaying the enumeration (instantiation of the I2C-client in the ov8865 example) of ACPI-devices which have a _DEP dependency on an INT3472 device. The new acpi_dev_ready_for_enumeration() helper used for this is also exported because for devices, which have the enumeration_by_parent flag set, the parent-driver will do its own scan of child ACPI devices and it will try to enumerate those during its probe(). Code doing this such as e.g. the i2c-core-acpi.c code must call this new helper to ensure that it too delays the enumeration until all the _DEP dependencies are met on devices which have the new honor_deps flag set. Acked-by: Rafael J. Wysocki <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Signed-off-by: Hans de Goede <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent fa55b7d commit 9d9bcae

File tree

2 files changed

+37
-5
lines changed

2 files changed

+37
-5
lines changed

drivers/acpi/scan.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,12 @@ static const char * const acpi_ignore_dep_ids[] = {
797797
NULL
798798
};
799799

800+
/* List of HIDs for which we honor deps of matching ACPI devs, when checking _DEP lists. */
801+
static const char * const acpi_honor_dep_ids[] = {
802+
"INT3472", /* Camera sensor PMIC / clk and regulator info */
803+
NULL
804+
};
805+
800806
static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
801807
{
802808
struct acpi_device *device = NULL;
@@ -1762,8 +1768,12 @@ static void acpi_scan_dep_init(struct acpi_device *adev)
17621768
struct acpi_dep_data *dep;
17631769

17641770
list_for_each_entry(dep, &acpi_dep_list, node) {
1765-
if (dep->consumer == adev->handle)
1771+
if (dep->consumer == adev->handle) {
1772+
if (dep->honor_dep)
1773+
adev->flags.honor_deps = 1;
1774+
17661775
adev->dep_unmet++;
1776+
}
17671777
}
17681778
}
17691779

@@ -1967,7 +1977,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
19671977
for (count = 0, i = 0; i < dep_devices.count; i++) {
19681978
struct acpi_device_info *info;
19691979
struct acpi_dep_data *dep;
1970-
bool skip;
1980+
bool skip, honor_dep;
19711981

19721982
status = acpi_get_object_info(dep_devices.handles[i], &info);
19731983
if (ACPI_FAILURE(status)) {
@@ -1976,6 +1986,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
19761986
}
19771987

19781988
skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids);
1989+
honor_dep = acpi_info_matches_ids(info, acpi_honor_dep_ids);
19791990
kfree(info);
19801991

19811992
if (skip)
@@ -1989,6 +2000,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
19892000

19902001
dep->supplier = dep_devices.handles[i];
19912002
dep->consumer = handle;
2003+
dep->honor_dep = honor_dep;
19922004

19932005
mutex_lock(&acpi_dep_list_lock);
19942006
list_add_tail(&dep->node , &acpi_dep_list);
@@ -2155,8 +2167,8 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
21552167
register_dock_dependent_device(device, ejd);
21562168

21572169
acpi_bus_get_status(device);
2158-
/* Skip devices that are not present. */
2159-
if (!acpi_device_is_present(device)) {
2170+
/* Skip devices that are not ready for enumeration (e.g. not present) */
2171+
if (!acpi_dev_ready_for_enumeration(device)) {
21602172
device->flags.initialized = false;
21612173
acpi_device_clear_enumerated(device);
21622174
device->flags.power_manageable = 0;
@@ -2318,6 +2330,23 @@ void acpi_dev_clear_dependencies(struct acpi_device *supplier)
23182330
}
23192331
EXPORT_SYMBOL_GPL(acpi_dev_clear_dependencies);
23202332

2333+
/**
2334+
* acpi_dev_ready_for_enumeration - Check if the ACPI device is ready for enumeration
2335+
* @device: Pointer to the &struct acpi_device to check
2336+
*
2337+
* Check if the device is present and has no unmet dependencies.
2338+
*
2339+
* Return true if the device is ready for enumeratino. Otherwise, return false.
2340+
*/
2341+
bool acpi_dev_ready_for_enumeration(const struct acpi_device *device)
2342+
{
2343+
if (device->flags.honor_deps && device->dep_unmet)
2344+
return false;
2345+
2346+
return acpi_device_is_present(device);
2347+
}
2348+
EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration);
2349+
23212350
/**
23222351
* acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier
23232352
* @supplier: Pointer to the dependee device

include/acpi/acpi_bus.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ struct acpi_device_flags {
202202
u32 coherent_dma:1;
203203
u32 cca_seen:1;
204204
u32 enumeration_by_parent:1;
205-
u32 reserved:19;
205+
u32 honor_deps:1;
206+
u32 reserved:18;
206207
};
207208

208209
/* File System */
@@ -285,6 +286,7 @@ struct acpi_dep_data {
285286
struct list_head node;
286287
acpi_handle supplier;
287288
acpi_handle consumer;
289+
bool honor_dep;
288290
};
289291

290292
/* Performance Management */
@@ -693,6 +695,7 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev)
693695
bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2);
694696

695697
void acpi_dev_clear_dependencies(struct acpi_device *supplier);
698+
bool acpi_dev_ready_for_enumeration(const struct acpi_device *device);
696699
struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier);
697700
struct acpi_device *
698701
acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv);

0 commit comments

Comments
 (0)