Commit 9d004b2f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull cxl updates from Dan Williams:
 "Compute Express Link (CXL) updates for this cycle.

  The highlight is new driver-core infrastructure and CXL subsystem
  changes for allowing lockdep to validate device_lock() usage. Thanks
  to PeterZ for setting me straight on the current capabilities of the
  lockdep API, and Greg acked it as well.

  On the CXL ACPI side this update adds support for CXL _OSC so that
  platform firmware knows that it is safe to still grant Linux native
  control of PCIe hotplug and error handling in the presence of CXL
  devices. A circular dependency problem was discovered between suspend
  and CXL memory for cases where the suspend image might be stored in
  CXL memory where that image also contains the PCI register state to
  restore to re-enable the device. Disable suspend for now until an
  architecture is defined to clarify that conflict.

  Lastly a collection of reworks, fixes, and cleanups to the CXL
  subsystem where support for snooping mailbox commands and properly
  handling the "mem_enable" flow are the highlights.

  Summary:

   - Add driver-core infrastructure for lockdep validation of
     device_lock(), and fixup a deadlock report that was previously
     hidden behind the 'lockdep no validate' policy.

   - Add CXL _OSC support for claiming native control of CXL hotplug and
     error handling.

   - Disable suspend in the presence of CXL memory unless and until a
     protocol is identified for restoring PCI device context from memory
     hosted on CXL PCI devices.

   - Add support for snooping CXL mailbox commands to protect against
     inopportune changes, like set-partition with the 'immediate' flag
     set.

   - Rework how the driver detects legacy CXL 1.1 configurations (CXL
     DVSEC / 'mem_enable') before enabling new CXL 2.0 decode
     configurations (CXL HDM Capability).

   - Miscellaneous cleanups and fixes from -next exposure"

* tag 'cxl-for-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl: (47 commits)
  cxl/port: Enable HDM Capability after validating DVSEC Ranges
  cxl/port: Reuse 'struct cxl_hdm' context for hdm init
  cxl/port: Move endpoint HDM Decoder Capability init to port driver
  cxl/pci: Drop @info argument to cxl_hdm_decode_init()
  cxl/mem: Merge cxl_dvsec_ranges() and cxl_hdm_decode_init()
  cxl/mem: Skip range enumeration if mem_enable clear
  cxl/mem: Consolidate CXL DVSEC Range enumeration in the core
  cxl/pci: Move cxl_await_media_ready() to the core
  cxl/mem: Validate port connectivity before dvsec ranges
  cxl/mem: Fix cxl_mem_probe() error exit
  cxl/pci: Drop wait_for_valid() from cxl_await_media_ready()
  cxl/pci: Consolidate wait_for_media() and wait_for_media_ready()
  cxl/mem: Drop mem_enabled check from wait_for_media()
  nvdimm: Fix firmware activation deadlock scenarios
  device-core: Kill the lockdep_mutex
  nvdimm: Drop nd_device_lock()
  ACPI: NFIT: Drop nfit_device_lock()
  nvdimm: Replace lockdep_mutex with local lock classes
  cxl: Drop cxl_device_lock()
  cxl/acpi: Add root device lockdep validation
  ...
parents a9f94826 34e37b4c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -72,9 +72,9 @@ obj-$(CONFIG_PARPORT) += parport/
obj-y				+= base/ block/ misc/ mfd/ nfc/
obj-$(CONFIG_LIBNVDIMM)		+= nvdimm/
obj-$(CONFIG_DAX)		+= dax/
obj-$(CONFIG_CXL_BUS)		+= cxl/
obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/
obj-$(CONFIG_NUBUS)		+= nubus/
obj-y				+= cxl/
obj-y				+= macintosh/
obj-y				+= scsi/
obj-y				+= nvme/
+1 −1
Original line number Diff line number Diff line
@@ -443,7 +443,7 @@ static void acpi_bus_osc_negotiate_usb_control(void)
	}

	osc_sb_native_usb4_control =
		control & ((u32 *)context.ret.pointer)[OSC_CONTROL_DWORD];
		control &  acpi_osc_ctx_get_pci_control(&context);

	acpi_bus_decode_usb_osc("USB4 _OSC: OS supports", control);
	acpi_bus_decode_usb_osc("USB4 _OSC: OS controls",
+15 −15
Original line number Diff line number Diff line
@@ -1230,7 +1230,7 @@ static ssize_t hw_error_scrub_store(struct device *dev,
	if (rc)
		return rc;

	nfit_device_lock(dev);
	device_lock(dev);
	nd_desc = dev_get_drvdata(dev);
	if (nd_desc) {
		struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
@@ -1247,7 +1247,7 @@ static ssize_t hw_error_scrub_store(struct device *dev,
			break;
		}
	}
	nfit_device_unlock(dev);
	device_unlock(dev);
	if (rc)
		return rc;
	return size;
@@ -1267,10 +1267,10 @@ static ssize_t scrub_show(struct device *dev,
	ssize_t rc = -ENXIO;
	bool busy;

	nfit_device_lock(dev);
	device_lock(dev);
	nd_desc = dev_get_drvdata(dev);
	if (!nd_desc) {
		nfit_device_unlock(dev);
		device_unlock(dev);
		return rc;
	}
	acpi_desc = to_acpi_desc(nd_desc);
@@ -1287,7 +1287,7 @@ static ssize_t scrub_show(struct device *dev,
	}

	mutex_unlock(&acpi_desc->init_mutex);
	nfit_device_unlock(dev);
	device_unlock(dev);
	return rc;
}

@@ -1304,14 +1304,14 @@ static ssize_t scrub_store(struct device *dev,
	if (val != 1)
		return -EINVAL;

	nfit_device_lock(dev);
	device_lock(dev);
	nd_desc = dev_get_drvdata(dev);
	if (nd_desc) {
		struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);

		rc = acpi_nfit_ars_rescan(acpi_desc, ARS_REQ_LONG);
	}
	nfit_device_unlock(dev);
	device_unlock(dev);
	if (rc)
		return rc;
	return size;
@@ -1697,9 +1697,9 @@ static void acpi_nvdimm_notify(acpi_handle handle, u32 event, void *data)
	struct acpi_device *adev = data;
	struct device *dev = &adev->dev;

	nfit_device_lock(dev->parent);
	device_lock(dev->parent);
	__acpi_nvdimm_notify(dev, event);
	nfit_device_unlock(dev->parent);
	device_unlock(dev->parent);
}

static bool acpi_nvdimm_has_method(struct acpi_device *adev, char *method)
@@ -3152,8 +3152,8 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
	struct device *dev = acpi_desc->dev;

	/* Bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
	nfit_device_lock(dev);
	nfit_device_unlock(dev);
	device_lock(dev);
	device_unlock(dev);

	/* Bounce the init_mutex to complete initial registration */
	mutex_lock(&acpi_desc->init_mutex);
@@ -3305,8 +3305,8 @@ void acpi_nfit_shutdown(void *data)
	 * acpi_nfit_ars_rescan() submissions have had a chance to
	 * either submit or see ->cancel set.
	 */
	nfit_device_lock(bus_dev);
	nfit_device_unlock(bus_dev);
	device_lock(bus_dev);
	device_unlock(bus_dev);

	flush_workqueue(nfit_wq);
}
@@ -3449,9 +3449,9 @@ EXPORT_SYMBOL_GPL(__acpi_nfit_notify);

static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
{
	nfit_device_lock(&adev->dev);
	device_lock(&adev->dev);
	__acpi_nfit_notify(&adev->dev, adev->handle, event);
	nfit_device_unlock(&adev->dev);
	device_unlock(&adev->dev);
}

static const struct acpi_device_id acpi_nfit_ids[] = {
+0 −24
Original line number Diff line number Diff line
@@ -337,30 +337,6 @@ static inline struct acpi_nfit_desc *to_acpi_desc(
	return container_of(nd_desc, struct acpi_nfit_desc, nd_desc);
}

#ifdef CONFIG_PROVE_LOCKING
static inline void nfit_device_lock(struct device *dev)
{
	device_lock(dev);
	mutex_lock(&dev->lockdep_mutex);
}

static inline void nfit_device_unlock(struct device *dev)
{
	mutex_unlock(&dev->lockdep_mutex);
	device_unlock(dev);
}
#else
static inline void nfit_device_lock(struct device *dev)
{
	device_lock(dev);
}

static inline void nfit_device_unlock(struct device *dev)
{
	device_unlock(dev);
}
#endif

const guid_t *to_nfit_uuid(enum nfit_uuids id);
int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz);
void acpi_nfit_shutdown(void *data);
+209 −29
Original line number Diff line number Diff line
@@ -140,6 +140,17 @@ static struct pci_osc_bit_struct pci_osc_control_bit[] = {
	{ OSC_PCI_EXPRESS_DPC_CONTROL, "DPC" },
};

static struct pci_osc_bit_struct cxl_osc_support_bit[] = {
	{ OSC_CXL_1_1_PORT_REG_ACCESS_SUPPORT, "CXL11PortRegAccess" },
	{ OSC_CXL_2_0_PORT_DEV_REG_ACCESS_SUPPORT, "CXL20PortDevRegAccess" },
	{ OSC_CXL_PROTOCOL_ERR_REPORTING_SUPPORT, "CXLProtocolErrorReporting" },
	{ OSC_CXL_NATIVE_HP_SUPPORT, "CXLNativeHotPlug" },
};

static struct pci_osc_bit_struct cxl_osc_control_bit[] = {
	{ OSC_CXL_ERROR_REPORTING_CONTROL, "CXLMemErrorReporting" },
};

static void decode_osc_bits(struct acpi_pci_root *root, char *msg, u32 word,
			    struct pci_osc_bit_struct *table, int size)
{
@@ -168,33 +179,73 @@ static void decode_osc_control(struct acpi_pci_root *root, char *msg, u32 word)
			ARRAY_SIZE(pci_osc_control_bit));
}

static void decode_cxl_osc_support(struct acpi_pci_root *root, char *msg, u32 word)
{
	decode_osc_bits(root, msg, word, cxl_osc_support_bit,
			ARRAY_SIZE(cxl_osc_support_bit));
}

static void decode_cxl_osc_control(struct acpi_pci_root *root, char *msg, u32 word)
{
	decode_osc_bits(root, msg, word, cxl_osc_control_bit,
			ARRAY_SIZE(cxl_osc_control_bit));
}

static inline bool is_pcie(struct acpi_pci_root *root)
{
	return root->bridge_type == ACPI_BRIDGE_TYPE_PCIE;
}

static inline bool is_cxl(struct acpi_pci_root *root)
{
	return root->bridge_type == ACPI_BRIDGE_TYPE_CXL;
}

static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766";
static u8 cxl_osc_uuid_str[] = "68F2D50B-C469-4d8A-BD3D-941A103FD3FC";

static acpi_status acpi_pci_run_osc(acpi_handle handle,
				    const u32 *capbuf, u32 *retval)
static char *to_uuid(struct acpi_pci_root *root)
{
	if (is_cxl(root))
		return cxl_osc_uuid_str;
	return pci_osc_uuid_str;
}

static int cap_length(struct acpi_pci_root *root)
{
	if (is_cxl(root))
		return sizeof(u32) * OSC_CXL_CAPABILITY_DWORDS;
	return sizeof(u32) * OSC_PCI_CAPABILITY_DWORDS;
}

static acpi_status acpi_pci_run_osc(struct acpi_pci_root *root,
				    const u32 *capbuf, u32 *pci_control,
				    u32 *cxl_control)
{
	struct acpi_osc_context context = {
		.uuid_str = pci_osc_uuid_str,
		.uuid_str = to_uuid(root),
		.rev = 1,
		.cap.length = 12,
		.cap.length = cap_length(root),
		.cap.pointer = (void *)capbuf,
	};
	acpi_status status;

	status = acpi_run_osc(handle, &context);
	status = acpi_run_osc(root->device->handle, &context);
	if (ACPI_SUCCESS(status)) {
		*retval = *((u32 *)(context.ret.pointer + 8));
		*pci_control = acpi_osc_ctx_get_pci_control(&context);
		if (is_cxl(root))
			*cxl_control = acpi_osc_ctx_get_cxl_control(&context);
		kfree(context.ret.pointer);
	}
	return status;
}

static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
					u32 support,
					u32 *control)
static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 support,
				      u32 *control, u32 cxl_support,
				      u32 *cxl_control)
{
	acpi_status status;
	u32 result, capbuf[3];
	u32 pci_result, cxl_result, capbuf[OSC_CXL_CAPABILITY_DWORDS];

	support |= root->osc_support_set;

@@ -202,10 +253,28 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
	capbuf[OSC_SUPPORT_DWORD] = support;
	capbuf[OSC_CONTROL_DWORD] = *control | root->osc_control_set;

	status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
	if (is_cxl(root)) {
		cxl_support |= root->osc_ext_support_set;
		capbuf[OSC_EXT_SUPPORT_DWORD] = cxl_support;
		capbuf[OSC_EXT_CONTROL_DWORD] = *cxl_control | root->osc_ext_control_set;
	}

retry:
	status = acpi_pci_run_osc(root, capbuf, &pci_result, &cxl_result);
	if (ACPI_SUCCESS(status)) {
		root->osc_support_set = support;
		*control = result;
		*control = pci_result;
		if (is_cxl(root)) {
			root->osc_ext_support_set = cxl_support;
			*cxl_control = cxl_result;
		}
	} else if (is_cxl(root)) {
		/*
		 * CXL _OSC is optional on CXL 1.1 hosts. Fall back to PCIe _OSC
		 * upon any failure using CXL _OSC.
		 */
		root->bridge_type = ACPI_BRIDGE_TYPE_PCIE;
		goto retry;
	}
	return status;
}
@@ -321,6 +390,8 @@ EXPORT_SYMBOL_GPL(acpi_get_pci_dev);
 * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex).
 * @mask: Mask of _OSC bits to request control of, place to store control mask.
 * @support: _OSC supported capability.
 * @cxl_mask: Mask of CXL _OSC control bits, place to store control mask.
 * @cxl_support: CXL _OSC supported capability.
 *
 * Run _OSC query for @mask and if that is successful, compare the returned
 * mask of control bits with @req.  If all of the @req bits are set in the
@@ -331,12 +402,14 @@ EXPORT_SYMBOL_GPL(acpi_get_pci_dev);
 * _OSC bits the BIOS has granted control of, but its contents are meaningless
 * on failure.
 **/
static acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 support)
static acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask,
					    u32 support, u32 *cxl_mask,
					    u32 cxl_support)
{
	u32 req = OSC_PCI_EXPRESS_CAPABILITY_CONTROL;
	struct acpi_pci_root *root;
	acpi_status status;
	u32 ctrl, capbuf[3];
	u32 ctrl, cxl_ctrl = 0, capbuf[OSC_CXL_CAPABILITY_DWORDS];

	if (!mask)
		return AE_BAD_PARAMETER;
@@ -348,20 +421,42 @@ static acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 s
	ctrl   = *mask;
	*mask |= root->osc_control_set;

	if (is_cxl(root)) {
		cxl_ctrl = *cxl_mask;
		*cxl_mask |= root->osc_ext_control_set;
	}

	/* Need to check the available controls bits before requesting them. */
	do {
		status = acpi_pci_query_osc(root, support, mask);
		u32 pci_missing = 0, cxl_missing = 0;

		status = acpi_pci_query_osc(root, support, mask, cxl_support,
					    cxl_mask);
		if (ACPI_FAILURE(status))
			return status;
		if (is_cxl(root)) {
			if (ctrl == *mask && cxl_ctrl == *cxl_mask)
				break;
			pci_missing = ctrl & ~(*mask);
			cxl_missing = cxl_ctrl & ~(*cxl_mask);
		} else {
			if (ctrl == *mask)
				break;
			pci_missing = ctrl & ~(*mask);
		}
		if (pci_missing)
			decode_osc_control(root, "platform does not support",
				   ctrl & ~(*mask));
					   pci_missing);
		if (cxl_missing)
			decode_cxl_osc_control(root, "CXL platform does not support",
					   cxl_missing);
		ctrl = *mask;
	} while (*mask);
		cxl_ctrl = *cxl_mask;
	} while (*mask || *cxl_mask);

	/* No need to request _OSC if the control was already granted. */
	if ((root->osc_control_set & ctrl) == ctrl)
	if ((root->osc_control_set & ctrl) == ctrl &&
	    (root->osc_ext_control_set & cxl_ctrl) == cxl_ctrl)
		return AE_OK;

	if ((ctrl & req) != req) {
@@ -373,11 +468,17 @@ static acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 s
	capbuf[OSC_QUERY_DWORD] = 0;
	capbuf[OSC_SUPPORT_DWORD] = root->osc_support_set;
	capbuf[OSC_CONTROL_DWORD] = ctrl;
	status = acpi_pci_run_osc(handle, capbuf, mask);
	if (is_cxl(root)) {
		capbuf[OSC_EXT_SUPPORT_DWORD] = root->osc_ext_support_set;
		capbuf[OSC_EXT_CONTROL_DWORD] = cxl_ctrl;
	}

	status = acpi_pci_run_osc(root, capbuf, mask, cxl_mask);
	if (ACPI_FAILURE(status))
		return status;

	root->osc_control_set = *mask;
	root->osc_ext_control_set = *cxl_mask;
	return AE_OK;
}

@@ -403,6 +504,53 @@ static u32 calculate_support(void)
	return support;
}

/*
 * Background on hotplug support, and making it depend on only
 * CONFIG_HOTPLUG_PCI_PCIE vs. also considering CONFIG_MEMORY_HOTPLUG:
 *
 * CONFIG_ACPI_HOTPLUG_MEMORY does depend on CONFIG_MEMORY_HOTPLUG, but
 * there is no existing _OSC for memory hotplug support. The reason is that
 * ACPI memory hotplug requires the OS to acknowledge / coordinate with
 * memory plug events via a scan handler. On the CXL side the equivalent
 * would be if Linux supported the Mechanical Retention Lock [1], or
 * otherwise had some coordination for the driver of a PCI device
 * undergoing hotplug to be consulted on whether the hotplug should
 * proceed or not.
 *
 * The concern is that if Linux says no to supporting CXL hotplug then
 * the BIOS may say no to giving the OS hotplug control of any other PCIe
 * device. So the question here is not whether hotplug is enabled, it's
 * whether it is handled natively by the at all OS, and if
 * CONFIG_HOTPLUG_PCI_PCIE is enabled then the answer is "yes".
 *
 * Otherwise, the plan for CXL coordinated remove, since the kernel does
 * not support blocking hotplug, is to require the memory device to be
 * disabled before hotplug is attempted. When CONFIG_MEMORY_HOTPLUG is
 * disabled that step will fail and the remove attempt cancelled by the
 * user. If that is not honored and the card is removed anyway then it
 * does not matter if CONFIG_MEMORY_HOTPLUG is enabled or not, it will
 * cause a crash and other badness.
 *
 * Therefore, just say yes to CXL hotplug and require removal to
 * be coordinated by userspace unless and until the kernel grows better
 * mechanisms for doing "managed" removal of devices in consultation with
 * the driver.
 *
 * [1]: https://lore.kernel.org/all/20201122014203.4706-1-ashok.raj@intel.com/
 */
static u32 calculate_cxl_support(void)
{
	u32 support;

	support = OSC_CXL_2_0_PORT_DEV_REG_ACCESS_SUPPORT;
	if (pci_aer_available())
		support |= OSC_CXL_PROTOCOL_ERR_REPORTING_SUPPORT;
	if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE))
		support |= OSC_CXL_NATIVE_HP_SUPPORT;

	return support;
}

static u32 calculate_control(void)
{
	u32 control;
@@ -434,6 +582,16 @@ static u32 calculate_control(void)
	return control;
}

static u32 calculate_cxl_control(void)
{
	u32 control = 0;

	if (IS_ENABLED(CONFIG_MEMORY_FAILURE))
		control |= OSC_CXL_ERROR_REPORTING_CONTROL;

	return control;
}

static bool os_control_query_checks(struct acpi_pci_root *root, u32 support)
{
	struct acpi_device *device = root->device;
@@ -452,10 +610,10 @@ static bool os_control_query_checks(struct acpi_pci_root *root, u32 support)
	return true;
}

static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm,
				 bool is_pcie)
static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm)
{
	u32 support, control = 0, requested = 0;
	u32 cxl_support = 0, cxl_control = 0, cxl_requested = 0;
	acpi_status status;
	struct acpi_device *device = root->device;
	acpi_handle handle = device->handle;
@@ -479,10 +637,20 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm,
	if (os_control_query_checks(root, support))
		requested = control = calculate_control();

	status = acpi_pci_osc_control_set(handle, &control, support);
	if (is_cxl(root)) {
		cxl_support = calculate_cxl_support();
		decode_cxl_osc_support(root, "OS supports", cxl_support);
		cxl_requested = cxl_control = calculate_cxl_control();
	}

	status = acpi_pci_osc_control_set(handle, &control, support,
					  &cxl_control, cxl_support);
	if (ACPI_SUCCESS(status)) {
		if (control)
			decode_osc_control(root, "OS now controls", control);
		if (cxl_control)
			decode_cxl_osc_control(root, "OS now controls",
					   cxl_control);

		if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
			/*
@@ -504,13 +672,18 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm,
		*no_aspm = 1;

		/* _OSC is optional for PCI host bridges */
		if ((status == AE_NOT_FOUND) && !is_pcie)
		if (status == AE_NOT_FOUND && !is_pcie(root))
			return;

		if (control) {
			decode_osc_control(root, "OS requested", requested);
			decode_osc_control(root, "platform willing to grant", control);
		}
		if (cxl_control) {
			decode_cxl_osc_control(root, "OS requested", cxl_requested);
			decode_cxl_osc_control(root, "platform willing to grant",
					   cxl_control);
		}

		dev_info(&device->dev, "_OSC: platform retains control of PCIe features (%s)\n",
			 acpi_format_exception(status));
@@ -527,7 +700,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
	acpi_handle handle = device->handle;
	int no_aspm = 0;
	bool hotadd = system_state == SYSTEM_RUNNING;
	bool is_pcie;
	const char *acpi_hid;

	root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
	if (!root)
@@ -585,8 +758,15 @@ static int acpi_pci_root_add(struct acpi_device *device,

	root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle);

	is_pcie = strcmp(acpi_device_hid(device), "PNP0A08") == 0;
	negotiate_os_control(root, &no_aspm, is_pcie);
	acpi_hid = acpi_device_hid(root->device);
	if (strcmp(acpi_hid, "PNP0A08") == 0)
		root->bridge_type = ACPI_BRIDGE_TYPE_PCIE;
	else if (strcmp(acpi_hid, "ACPI0016") == 0)
		root->bridge_type = ACPI_BRIDGE_TYPE_CXL;
	else
		dev_dbg(&device->dev, "Assuming non-PCIe host bridge\n");

	negotiate_os_control(root, &no_aspm);

	/*
	 * TBD: Need PCI interface for enumeration/configuration of roots.
Loading