Skip to content

Commit

Permalink
Merge tag 'cxl-fixes-6.7-rc6' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/cxl/cxl

Pull CXL (Compute Express Link) fixes from Dan Williams:
 "A collection of CXL fixes.

  The touch outside of drivers/cxl/ is for a helper that allocates
  physical address space. Device hotplug tests showed that the driver
  failed to utilize (skipped over) valid capacity when allocating a new
  memory region. Outside of that, new tests uncovered a small crop of
  lockdep reports.

  There is also some miscellaneous error path and leak fixups that are
  not urgent, but useful to cleanup now.

   - Fix alloc_free_mem_region()'s scan for address space, prevent false
     negative out-of-space events

   - Fix sleeping lock acquisition from CXL trace event (atomic context)

   - Fix put_device() like for the new CXL PMU driver

   - Fix wrong pointer freed on error path

   - Fixup several lockdep reports (missing lock hold) from new
     assertion in cxl_num_decoders_committed() and new tests"

* tag 'cxl-fixes-6.7-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl:
  cxl/pmu: Ensure put_device on pmu devices
  cxl/cdat: Free correct buffer on checksum error
  cxl/hdm: Fix dpa translation locking
  kernel/resource: Increment by align value in get_free_mem_region()
  cxl: Add cxl_num_decoders_committed() usage to cxl_test
  cxl/memdev: Hold region_rwsem during inject and clear poison ops
  cxl/core: Always hold region_rwsem while reading poison lists
  cxl/hdm: Fix a benign lockdep splat
  • Loading branch information
Linus Torvalds committed Dec 17, 2023
2 parents ef6a7c2 + ef3d5cf commit 134fdb8
Show file tree
Hide file tree
Showing 10 changed files with 49 additions and 24 deletions.
5 changes: 3 additions & 2 deletions drivers/cxl/core/hdm.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,10 +363,9 @@ resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled)
{
resource_size_t base = -1;

down_read(&cxl_dpa_rwsem);
lockdep_assert_held(&cxl_dpa_rwsem);
if (cxled->dpa_res)
base = cxled->dpa_res->start;
up_read(&cxl_dpa_rwsem);

return base;
}
Expand Down Expand Up @@ -839,6 +838,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
cxld->target_type = CXL_DECODER_HOSTONLYMEM;
else
cxld->target_type = CXL_DECODER_DEVMEM;

guard(rwsem_write)(&cxl_region_rwsem);
if (cxld->id != cxl_num_decoders_committed(port)) {
dev_warn(&port->dev,
"decoder%d.%d: Committed out of order\n",
Expand Down
27 changes: 24 additions & 3 deletions drivers/cxl/core/memdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,16 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
if (!port || !is_cxl_endpoint(port))
return -EINVAL;

rc = down_read_interruptible(&cxl_dpa_rwsem);
rc = down_read_interruptible(&cxl_region_rwsem);
if (rc)
return rc;

rc = down_read_interruptible(&cxl_dpa_rwsem);
if (rc) {
up_read(&cxl_region_rwsem);
return rc;
}

if (cxl_num_decoders_committed(port) == 0) {
/* No regions mapped to this memdev */
rc = cxl_get_poison_by_memdev(cxlmd);
Expand All @@ -239,6 +245,7 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
rc = cxl_get_poison_by_endpoint(port);
}
up_read(&cxl_dpa_rwsem);
up_read(&cxl_region_rwsem);

return rc;
}
Expand Down Expand Up @@ -324,10 +331,16 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
if (!IS_ENABLED(CONFIG_DEBUG_FS))
return 0;

rc = down_read_interruptible(&cxl_dpa_rwsem);
rc = down_read_interruptible(&cxl_region_rwsem);
if (rc)
return rc;

rc = down_read_interruptible(&cxl_dpa_rwsem);
if (rc) {
up_read(&cxl_region_rwsem);
return rc;
}

rc = cxl_validate_poison_dpa(cxlmd, dpa);
if (rc)
goto out;
Expand Down Expand Up @@ -355,6 +368,7 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
trace_cxl_poison(cxlmd, cxlr, &record, 0, 0, CXL_POISON_TRACE_INJECT);
out:
up_read(&cxl_dpa_rwsem);
up_read(&cxl_region_rwsem);

return rc;
}
Expand All @@ -372,10 +386,16 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
if (!IS_ENABLED(CONFIG_DEBUG_FS))
return 0;

rc = down_read_interruptible(&cxl_dpa_rwsem);
rc = down_read_interruptible(&cxl_region_rwsem);
if (rc)
return rc;

rc = down_read_interruptible(&cxl_dpa_rwsem);
if (rc) {
up_read(&cxl_region_rwsem);
return rc;
}

rc = cxl_validate_poison_dpa(cxlmd, dpa);
if (rc)
goto out;
Expand Down Expand Up @@ -412,6 +432,7 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
trace_cxl_poison(cxlmd, cxlr, &record, 0, 0, CXL_POISON_TRACE_CLEAR);
out:
up_read(&cxl_dpa_rwsem);
up_read(&cxl_region_rwsem);

return rc;
}
Expand Down
13 changes: 6 additions & 7 deletions drivers/cxl/core/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ void read_cdat_data(struct cxl_port *port)
struct pci_dev *pdev = NULL;
struct cxl_memdev *cxlmd;
size_t cdat_length;
void *cdat_table;
void *cdat_table, *cdat_buf;
int rc;

if (is_cxl_memdev(uport)) {
Expand Down Expand Up @@ -651,16 +651,15 @@ void read_cdat_data(struct cxl_port *port)
return;
}

cdat_table = devm_kzalloc(dev, cdat_length + sizeof(__le32),
GFP_KERNEL);
if (!cdat_table)
cdat_buf = devm_kzalloc(dev, cdat_length + sizeof(__le32), GFP_KERNEL);
if (!cdat_buf)
return;

rc = cxl_cdat_read_table(dev, cdat_doe, cdat_table, &cdat_length);
rc = cxl_cdat_read_table(dev, cdat_doe, cdat_buf, &cdat_length);
if (rc)
goto err;

cdat_table = cdat_table + sizeof(__le32);
cdat_table = cdat_buf + sizeof(__le32);
if (cdat_checksum(cdat_table, cdat_length))
goto err;

Expand All @@ -670,7 +669,7 @@ void read_cdat_data(struct cxl_port *port)

err:
/* Don't leave table data allocated on error */
devm_kfree(dev, cdat_table);
devm_kfree(dev, cdat_buf);
dev_err(dev, "Failed to read/validate CDAT.\n");
}
EXPORT_SYMBOL_NS_GPL(read_cdat_data, CXL);
Expand Down
2 changes: 1 addition & 1 deletion drivers/cxl/core/pmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const struct device_type cxl_pmu_type = {

static void remove_dev(void *dev)
{
device_del(dev);
device_unregister(dev);
}

int devm_cxl_pmu_add(struct device *parent, struct cxl_pmu_regs *regs,
Expand Down
4 changes: 2 additions & 2 deletions drivers/cxl/core/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,9 @@ static ssize_t dpa_resource_show(struct device *dev, struct device_attribute *at
char *buf)
{
struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev);
u64 base = cxl_dpa_resource_start(cxled);

return sysfs_emit(buf, "%#llx\n", base);
guard(rwsem_read)(&cxl_dpa_rwsem);
return sysfs_emit(buf, "%#llx\n", (u64)cxl_dpa_resource_start(cxled));
}
static DEVICE_ATTR_RO(dpa_resource);

Expand Down
5 changes: 0 additions & 5 deletions drivers/cxl/core/region.c
Original file line number Diff line number Diff line change
Expand Up @@ -2467,10 +2467,6 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port)
struct cxl_poison_context ctx;
int rc = 0;

rc = down_read_interruptible(&cxl_region_rwsem);
if (rc)
return rc;

ctx = (struct cxl_poison_context) {
.port = port
};
Expand All @@ -2480,7 +2476,6 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port)
rc = cxl_get_poison_unmapped(to_cxl_memdev(port->uport_dev),
&ctx);

up_read(&cxl_region_rwsem);
return rc;
}

Expand Down
4 changes: 2 additions & 2 deletions kernel/resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -1844,8 +1844,8 @@ get_free_mem_region(struct device *dev, struct resource *base,

write_lock(&resource_lock);
for (addr = gfr_start(base, size, align, flags);
gfr_continue(base, addr, size, flags);
addr = gfr_next(addr, size, flags)) {
gfr_continue(base, addr, align, flags);
addr = gfr_next(addr, align, flags)) {
if (__region_intersects(base, addr, size, 0, IORES_DESC_NONE) !=
REGION_DISJOINT)
continue;
Expand Down
1 change: 1 addition & 0 deletions tools/testing/cxl/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,6 @@ cxl_core-$(CONFIG_TRACING) += $(CXL_CORE_SRC)/trace.o
cxl_core-$(CONFIG_CXL_REGION) += $(CXL_CORE_SRC)/region.o
cxl_core-y += config_check.o
cxl_core-y += cxl_core_test.o
cxl_core-y += cxl_core_exports.o

obj-m += test/
7 changes: 7 additions & 0 deletions tools/testing/cxl/cxl_core_exports.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2022 Intel Corporation. All rights reserved. */

#include "cxl.h"

/* Exporting of cxl_core symbols that are only used by cxl_test */
EXPORT_SYMBOL_NS_GPL(cxl_num_decoders_committed, CXL);
5 changes: 3 additions & 2 deletions tools/testing/cxl/test/cxl.c
Original file line number Diff line number Diff line change
Expand Up @@ -669,10 +669,11 @@ static int mock_decoder_commit(struct cxl_decoder *cxld)
return 0;

dev_dbg(&port->dev, "%s commit\n", dev_name(&cxld->dev));
if (port->commit_end + 1 != id) {
if (cxl_num_decoders_committed(port) != id) {
dev_dbg(&port->dev,
"%s: out of order commit, expected decoder%d.%d\n",
dev_name(&cxld->dev), port->id, port->commit_end + 1);
dev_name(&cxld->dev), port->id,
cxl_num_decoders_committed(port));
return -EBUSY;
}

Expand Down

0 comments on commit 134fdb8

Please sign in to comment.