projects/linux·commit 9d004b2f

Merge tag 'cxl-for-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl

9d004b2f · Linus Torvalds <[email protected]> · 2022-05-27 21:24:19 -07:00

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
  ...
Commit
9d004b2f4fea97cde123e7f1939b80e77bf2e695
Parents
a9f94826 · 34e37b4c

Merge commit. Changes below are compared with the first parent: a9f94826.

Changes

48 files changed · +1266 −863

FileStatusAddDelContent
drivers/Makefilemodified+1−1View file
drivers/acpi/bus.cmodified+1−1View file
drivers/acpi/nfit/core.cmodified+15−15View file
drivers/acpi/nfit/nfit.hmodified+0−24View file
drivers/acpi/pci_root.cmodified+209−29View file
drivers/base/core.cmodified+0−3View file
drivers/cxl/Kconfigmodified+4−0View file
drivers/cxl/Makefilemodified+1−1View file
drivers/cxl/acpi.cmodified+13−0View file
drivers/cxl/core/Makefilemodified+1−0View file
drivers/cxl/core/mbox.cmodified+205−129View file
drivers/cxl/core/memdev.cmodified+3−0View file
drivers/cxl/core/pci.cmodified+364−0View file
drivers/cxl/core/pmem.cmodified+8−2View file
drivers/cxl/core/port.cmodified+32−36View file
drivers/cxl/core/suspend.cadded+24−0View file
drivers/cxl/cxl.hmodified+0−78View file
drivers/cxl/cxlmem.hmodified+71−4View file
drivers/cxl/cxlpci.hmodified+2−0View file
drivers/cxl/mem.cmodified+24−124View file
drivers/cxl/pci.cmodified+5−170View file
drivers/cxl/pmem.cmodified+6−7View file
drivers/cxl/port.cmodified+21−7View file
drivers/nvdimm/btt_devs.cmodified+13−10View file
drivers/nvdimm/bus.cmodified+16−22View file
drivers/nvdimm/core.cmodified+5−14View file
drivers/nvdimm/dax_devs.cmodified+2−2View file
drivers/nvdimm/dimm_devs.cmodified+8−4View file
drivers/nvdimm/namespace_devs.cmodified+27−19View file
drivers/nvdimm/nd-core.hmodified+1−67View file
drivers/nvdimm/pfn_devs.cmodified+17−14View file
drivers/nvdimm/pmem.cmodified+1−1View file
drivers/nvdimm/region.cmodified+1−1View file
drivers/nvdimm/region_devs.cmodified+12−8View file
include/acpi/acpi_bus.hmodified+10−2View file
include/linux/acpi.hmodified+41−1View file
include/linux/device.hmodified+43−5View file
include/linux/lockdep.hmodified+5−1View file
include/linux/pm.hmodified+9−0View file
include/uapi/linux/cxl_mem.hmodified+7−7View file
kernel/power/hibernate.cmodified+1−1View file
kernel/power/main.cmodified+4−1View file
kernel/power/suspend.cmodified+2−1View file
lib/Kconfig.debugmodified+0−23View file
tools/testing/cxl/Kbuildmodified+2−1View file
tools/testing/cxl/mock_mem.cdeleted+0−10View before deletion
tools/testing/cxl/test/mem.cmodified+0−17View file
tools/testing/cxl/test/mock.cmodified+29−0View file

Only the first 600 diff lines are shown. Download the complete patch.

drivers/Makefile

View file
diff --git a/drivers/Makefile b/drivers/Makefile
index 020780b..f735c49 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -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/

drivers/acpi/bus.c

View file
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index b67d2ee..86fa61a 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -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",

drivers/acpi/nfit/core.c

View file
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index fe61f61..ae5f4ac 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -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[] = {

drivers/acpi/nfit/nfit.h

View file
diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h
index 50882bd..6023ad6 100644
--- a/drivers/acpi/nfit/nfit.h
+++ b/drivers/acpi/nfit/nfit.h
@@ -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);

drivers/acpi/pci_root.c

View file
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index b3b507f..d57cf84 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -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 (ctrl == *mask)
- break;
- decode_osc_control(root, "platform does not support",
- ctrl & ~(*mask));
+ 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",
+ 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/[email protected]/
+ */
+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.

drivers/base/core.c

View file
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 3d6430e..2eede2e 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2864,9 +2864,6 @@ void device_initialize(struct device *dev)
kobject_init(&dev->kobj, &device_ktype);
INIT_LIST_HEAD(&dev->dma_pools);
mutex_init(&dev->mutex);
-#ifdef CONFIG_PROVE_LOCKING
- mutex_init(&dev->lockdep_mutex);
-#endif
lockdep_set_novalidate_class(&dev->mutex);
spin_lock_init(&dev->devres_lock);
INIT_LIST_HEAD(&dev->devres_head);

drivers/cxl/Kconfig

View file
diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig
index b88ab95..f64e398 100644
--- a/drivers/cxl/Kconfig
+++ b/drivers/cxl/Kconfig
@@ -98,4 +98,8 @@ config CXL_PORT
default CXL_BUS
tristate
+config CXL_SUSPEND
+ def_bool y
+ depends on SUSPEND && CXL_MEM
+
endif

drivers/cxl/Makefile

View file
diff --git a/drivers/cxl/Makefile b/drivers/cxl/Makefile
index ce267ef..a782707 100644
--- a/drivers/cxl/Makefile
+++ b/drivers/cxl/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_CXL_BUS) += core/
+obj-y += core/
obj-$(CONFIG_CXL_PCI) += cxl_pci.o
obj-$(CONFIG_CXL_MEM) += cxl_mem.o
obj-$(CONFIG_CXL_ACPI) += cxl_acpi.o

drivers/cxl/acpi.c

View file
diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
index d15a6ae..40286f5 100644
--- a/drivers/cxl/acpi.c
+++ b/drivers/cxl/acpi.c
@@ -275,6 +275,13 @@ static int add_root_nvdimm_bridge(struct device *match, void *data)
return 1;
}

This diff is incomplete. Download the complete patch.

drivers/cxl/core/Makefile

View file

This diff is incomplete. Download the complete patch.

drivers/cxl/core/mbox.c

View file

This diff is incomplete. Download the complete patch.

drivers/cxl/core/memdev.c

View file

This diff is incomplete. Download the complete patch.

drivers/cxl/core/pci.c

View file

This diff is incomplete. Download the complete patch.

drivers/cxl/core/pmem.c

View file

This diff is incomplete. Download the complete patch.

drivers/cxl/core/port.c

View file

This diff is incomplete. Download the complete patch.

drivers/cxl/core/suspend.c

View file

This diff is incomplete. Download the complete patch.

drivers/cxl/cxl.h

View file

This diff is incomplete. Download the complete patch.

drivers/cxl/cxlmem.h

View file

This diff is incomplete. Download the complete patch.

drivers/cxl/cxlpci.h

View file

This diff is incomplete. Download the complete patch.

drivers/cxl/mem.c

View file

This diff is incomplete. Download the complete patch.

drivers/cxl/pci.c

View file

This diff is incomplete. Download the complete patch.

drivers/cxl/pmem.c

View file

This diff is incomplete. Download the complete patch.

drivers/cxl/port.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/btt_devs.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/bus.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/core.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/dax_devs.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/dimm_devs.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/namespace_devs.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/nd-core.h

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/pfn_devs.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/pmem.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/region.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/region_devs.c

View file

This diff is incomplete. Download the complete patch.

include/acpi/acpi_bus.h

View file

This diff is incomplete. Download the complete patch.

include/linux/acpi.h

View file

This diff is incomplete. Download the complete patch.

include/linux/device.h

View file

This diff is incomplete. Download the complete patch.

include/linux/lockdep.h

View file

This diff is incomplete. Download the complete patch.

include/linux/pm.h

View file

This diff is incomplete. Download the complete patch.

include/uapi/linux/cxl_mem.h

View file

This diff is incomplete. Download the complete patch.

kernel/power/hibernate.c

View file

This diff is incomplete. Download the complete patch.

kernel/power/main.c

View file

This diff is incomplete. Download the complete patch.

kernel/power/suspend.c

View file

This diff is incomplete. Download the complete patch.

lib/Kconfig.debug

View file

This diff is incomplete. Download the complete patch.

tools/testing/cxl/Kbuild

View file

This diff is incomplete. Download the complete patch.

tools/testing/cxl/mock_mem.c

View before deletion

This diff is incomplete. Download the complete patch.

tools/testing/cxl/test/mem.c

View file

This diff is incomplete. Download the complete patch.

tools/testing/cxl/test/mock.c

View file

This diff is incomplete. Download the complete patch.