Commit 134fdb80 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents ef6a7c27 ef3d5cf9
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -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;
}
@@ -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",
+24 −3
Original line number Diff line number Diff line
@@ -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);
@@ -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;
}
@@ -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;
@@ -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;
}
@@ -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;
@@ -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;
}
+6 −7
Original line number Diff line number Diff line
@@ -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)) {
@@ -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;

@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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,
+2 −2
Original line number Diff line number Diff line
@@ -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);

Loading