Commit 8c34f112 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branches 'acpi-scan', 'acpi-bus', 'acpi-pm' and 'acpi-resource'

Merge ACPI device enumeration and bus type changes, ACPI power
management changes and ACPI IRQ override handling quirks for 6.9-rc1:

 - Rearrange Device Check and Bus Check notification handling in the
   ACPI device hotplug code to make it get the "enabled" _STA bit into
   account (Rafael Wysocki).

 - Modify acpi_processor_add() to skip processors with the "enabled"
   _STA bit clear, as per the specification (Rafael Wysocki).

 - Stop failing Device Check notification handling without a valid
   reason (Rafael Wysocki).

 - Defer enumeration of devices that depend on a device with an ACPI
   device ID equalt to INTC10CF to address probe ordering issues on
   some platforms (Wentong Wu).

 - Constify acpi_bus_type (Ricardo Marliere).

 - Make the ACPI-specific suspend-to-idle code take the Low-Power S0
   Idle MSFT UUID into account on non-AMD systems (Rafael Wysocki).

 - Add ACPI IRQ override quirks for some new platforms (Sergey
   Kalinichev, Maxim Kudinov, Alexey Froloff, Sviatoslav Harasymchuk,
   Nicolas Haye).

* acpi-scan:
  ACPI: scan: Consolidate Device Check and Bus Check notification handling
  ACPI: scan: Rework Device Check and Bus Check notification handling
  ACPI: scan: Make acpi_processor_add() check the device enabled bit
  ACPI: scan: Relocate acpi_bus_trim_one()
  ACPI: scan: Fix device check notification handling
  ACPI: scan: Defer enumeration of devices with a _DEP pointing to IVSC device

* acpi-bus:
  ACPI: bus: make acpi_bus_type const

* acpi-pm:
  ACPI: PM: s2idle: Enable Low-Power S0 Idle MSFT UUID for non-AMD systems

* acpi-resource:
  ACPI: resource: Use IRQ override on Maibenben X565
  ACPI: resource: Add MAIBENBEN X577 to irq1_edge_low_force_override
  ACPI: resource: Do IRQ override on Lunnen Ground laptops
  ACPI: resource: Add IRQ override quirk for ASUS ExpertBook B2502FBA
  ACPI: resource: Skip IRQ override on ASUS ExpertBook B1502CVA
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -381,6 +381,9 @@ static int acpi_processor_add(struct acpi_device *device,
	struct device *dev;
	int result = 0;

	if (!acpi_device_is_enabled(device))
		return -ENODEV;

	pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
	if (!pr)
		return -ENOMEM;
+1 −1
Original line number Diff line number Diff line
@@ -1097,7 +1097,7 @@ static void acpi_device_remove(struct device *dev)
	put_device(dev);
}

struct bus_type acpi_bus_type = {
const struct bus_type acpi_bus_type = {
	.name		= "acpi",
	.match		= acpi_bus_match,
	.probe		= acpi_device_probe,
+1 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ int acpi_device_setup_files(struct acpi_device *dev);
void acpi_device_remove_files(struct acpi_device *dev);
void acpi_device_add_finalize(struct acpi_device *device);
void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
bool acpi_device_is_enabled(const struct acpi_device *adev);
bool acpi_device_is_present(const struct acpi_device *adev);
bool acpi_device_is_battery(struct acpi_device *adev);
bool acpi_device_is_first_physical_node(struct acpi_device *adev,
+42 −0
Original line number Diff line number Diff line
@@ -468,6 +468,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = {
			DMI_MATCH(DMI_BOARD_NAME, "B1502CGA"),
		},
	},
        {
                /* Asus ExpertBook B1502CVA */
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
                        DMI_MATCH(DMI_BOARD_NAME, "B1502CVA"),
                },
        },
	{
		/* Asus ExpertBook B2402CBA */
		.matches = {
@@ -489,6 +496,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = {
			DMI_MATCH(DMI_BOARD_NAME, "B2502CBA"),
		},
	},
	{
		/* Asus ExpertBook B2502FBA */
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
			DMI_MATCH(DMI_BOARD_NAME, "B2502FBA"),
		},
	},
	{
		/* Asus Vivobook E1504GA */
		.matches = {
@@ -588,6 +602,34 @@ static const struct dmi_system_id irq1_edge_low_force_override[] = {
			DMI_MATCH(DMI_BOARD_NAME, "GM5RGEE0016COM"),
		},
	},
	{
		/* Lunnen Ground 15 / AMD Ryzen 5 5500U */
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Lunnen"),
			DMI_MATCH(DMI_BOARD_NAME, "LLL5DAW"),
		},
	},
	{
		/* Lunnen Ground 16 / AMD Ryzen 7 5800U */
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Lunnen"),
			DMI_MATCH(DMI_BOARD_NAME, "LL6FA"),
		},
	},
	{
		/* MAIBENBEN X577 */
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "MAIBENBEN"),
			DMI_MATCH(DMI_BOARD_NAME, "X577"),
		},
	},
	{
		/* Maibenben X565 */
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "MAIBENBEN"),
			DMI_MATCH(DMI_BOARD_NAME, "X565"),
		},
	},
	{ }
};

+93 −79
Original line number Diff line number Diff line
@@ -244,6 +244,53 @@ static int acpi_scan_try_to_offline(struct acpi_device *device)
	return 0;
}

static int acpi_scan_check_and_detach(struct acpi_device *adev, void *check)
{
	struct acpi_scan_handler *handler = adev->handler;

	acpi_dev_for_each_child_reverse(adev, acpi_scan_check_and_detach, check);

	if (check) {
		acpi_bus_get_status(adev);
		/*
		 * Skip devices that are still there and take the enabled
		 * flag into account.
		 */
		if (acpi_device_is_enabled(adev))
			return 0;

		/* Skip device that have not been enumerated. */
		if (!acpi_device_enumerated(adev)) {
			dev_dbg(&adev->dev, "Still not enumerated\n");
			return 0;
		}
	}

	adev->flags.match_driver = false;
	if (handler) {
		if (handler->detach)
			handler->detach(adev);

		adev->handler = NULL;
	} else {
		device_release_driver(&adev->dev);
	}
	/*
	 * Most likely, the device is going away, so put it into D3cold before
	 * that.
	 */
	acpi_device_set_power(adev, ACPI_STATE_D3_COLD);
	adev->flags.initialized = false;
	acpi_device_clear_enumerated(adev);

	return 0;
}

static void acpi_scan_check_subtree(struct acpi_device *adev)
{
	acpi_scan_check_and_detach(adev, (void *)true);
}

static int acpi_scan_hot_remove(struct acpi_device *device)
{
	acpi_handle handle = device->handle;
@@ -289,75 +336,62 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
	return 0;
}

static int acpi_scan_device_not_enumerated(struct acpi_device *adev)
static int acpi_scan_rescan_bus(struct acpi_device *adev)
{
	if (!acpi_device_enumerated(adev)) {
		dev_warn(&adev->dev, "Still not enumerated\n");
		return -EALREADY;
	}
	acpi_bus_trim(adev);
	return 0;
	struct acpi_scan_handler *handler = adev->handler;
	int ret;

	if (handler && handler->hotplug.scan_dependent)
		ret = handler->hotplug.scan_dependent(adev);
	else
		ret = acpi_bus_scan(adev->handle);

	if (ret)
		dev_info(&adev->dev, "Namespace scan failure\n");

	return ret;
}

static int acpi_scan_device_check(struct acpi_device *adev)
{
	int error;
	struct acpi_device *parent;

	acpi_scan_check_subtree(adev);

	if (!acpi_device_is_present(adev))
		return 0;

	acpi_bus_get_status(adev);
	if (acpi_device_is_present(adev)) {
	/*
		 * This function is only called for device objects for which
		 * matching scan handlers exist.  The only situation in which
		 * the scan handler is not attached to this device object yet
		 * is when the device has just appeared (either it wasn't
		 * present at all before or it was removed and then added
		 * again).
	 * This function is only called for device objects for which matching
	 * scan handlers exist.  The only situation in which the scan handler
	 * is not attached to this device object yet is when the device has
	 * just appeared (either it wasn't present at all before or it was
	 * removed and then added again).
	 */
	if (adev->handler) {
			dev_warn(&adev->dev, "Already enumerated\n");
			return -EALREADY;
		}
		error = acpi_bus_scan(adev->handle);
		if (error) {
			dev_warn(&adev->dev, "Namespace scan failure\n");
			return error;
		}
		if (!adev->handler) {
			dev_warn(&adev->dev, "Enumeration failure\n");
			error = -ENODEV;
		}
	} else {
		error = acpi_scan_device_not_enumerated(adev);
	}
	return error;
		dev_dbg(&adev->dev, "Already enumerated\n");
		return 0;
	}

static int acpi_scan_bus_check(struct acpi_device *adev, void *not_used)
{
	struct acpi_scan_handler *handler = adev->handler;
	int error;
	parent = acpi_dev_parent(adev);
	if (!parent)
		parent = adev;

	acpi_bus_get_status(adev);
	if (!acpi_device_is_present(adev)) {
		acpi_scan_device_not_enumerated(adev);
		return 0;
	return acpi_scan_rescan_bus(parent);
}
	if (handler && handler->hotplug.scan_dependent)
		return handler->hotplug.scan_dependent(adev);

	error = acpi_bus_scan(adev->handle);
	if (error) {
		dev_warn(&adev->dev, "Namespace scan failure\n");
		return error;
	}
	return acpi_dev_for_each_child(adev, acpi_scan_bus_check, NULL);
static int acpi_scan_bus_check(struct acpi_device *adev)
{
	acpi_scan_check_subtree(adev);

	return acpi_scan_rescan_bus(adev);
}

static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
{
	switch (type) {
	case ACPI_NOTIFY_BUS_CHECK:
		return acpi_scan_bus_check(adev, NULL);
		return acpi_scan_bus_check(adev);
	case ACPI_NOTIFY_DEVICE_CHECK:
		return acpi_scan_device_check(adev);
	case ACPI_NOTIFY_EJECT_REQUEST:
@@ -798,6 +832,7 @@ static const char * const acpi_honor_dep_ids[] = {
	"INTC1059", /* IVSC (TGL) driver must be loaded to allow i2c access to camera sensors */
	"INTC1095", /* IVSC (ADL) driver must be loaded to allow i2c access to camera sensors */
	"INTC100A", /* IVSC (RPL) driver must be loaded to allow i2c access to camera sensors */
	"INTC10CF", /* IVSC (MTL) driver must be loaded to allow i2c access to camera sensors */
	NULL
};

@@ -1922,6 +1957,11 @@ bool acpi_device_is_present(const struct acpi_device *adev)
	return adev->status.present || adev->status.functional;
}

bool acpi_device_is_enabled(const struct acpi_device *adev)
{
	return adev->status.present && adev->status.enabled;
}

static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
				       const char *idstr,
				       const struct acpi_device_id **matchid)
@@ -2550,32 +2590,6 @@ int acpi_bus_scan(acpi_handle handle)
}
EXPORT_SYMBOL(acpi_bus_scan);

static int acpi_bus_trim_one(struct acpi_device *adev, void *not_used)
{
	struct acpi_scan_handler *handler = adev->handler;

	acpi_dev_for_each_child_reverse(adev, acpi_bus_trim_one, NULL);

	adev->flags.match_driver = false;
	if (handler) {
		if (handler->detach)
			handler->detach(adev);

		adev->handler = NULL;
	} else {
		device_release_driver(&adev->dev);
	}
	/*
	 * Most likely, the device is going away, so put it into D3cold before
	 * that.
	 */
	acpi_device_set_power(adev, ACPI_STATE_D3_COLD);
	adev->flags.initialized = false;
	acpi_device_clear_enumerated(adev);

	return 0;
}

/**
 * acpi_bus_trim - Detach scan handlers and drivers from ACPI device objects.
 * @adev: Root of the ACPI namespace scope to walk.
@@ -2584,7 +2598,7 @@ static int acpi_bus_trim_one(struct acpi_device *adev, void *not_used)
 */
void acpi_bus_trim(struct acpi_device *adev)
{
	acpi_bus_trim_one(adev, NULL);
	acpi_scan_check_and_detach(adev, NULL);
}
EXPORT_SYMBOL_GPL(acpi_bus_trim);

Loading