Commit b6faa9c6 authored by Dave Jiang's avatar Dave Jiang
Browse files

Merge branch 'for-6.15/guard_cleanups' into cxl-for-next2

A series of CXL refactoring using scope based resource management to
remove goto patterns on the cleanup paths.
parents 17218b02 5ec67596
Loading
Loading
Loading
Loading
+28 −41
Original line number Diff line number Diff line
@@ -213,13 +213,12 @@ void cxl_dpa_debug(struct seq_file *file, struct cxl_dev_state *cxlds)
{
	struct resource *p1, *p2;

	down_read(&cxl_dpa_rwsem);
	guard(rwsem_read)(&cxl_dpa_rwsem);
	for (p1 = cxlds->dpa_res.child; p1; p1 = p1->sibling) {
		__cxl_dpa_debug(file, p1, 0);
		for (p2 = p1->child; p2; p2 = p2->sibling)
			__cxl_dpa_debug(file, p2, 1);
	}
	up_read(&cxl_dpa_rwsem);
}
EXPORT_SYMBOL_NS_GPL(cxl_dpa_debug, "CXL");

@@ -281,9 +280,8 @@ static void __cxl_dpa_release(struct cxl_endpoint_decoder *cxled)

static void cxl_dpa_release(void *cxled)
{
	down_write(&cxl_dpa_rwsem);
	guard(rwsem_write)(&cxl_dpa_rwsem);
	__cxl_dpa_release(cxled);
	up_write(&cxl_dpa_rwsem);
}

/*
@@ -530,14 +528,11 @@ EXPORT_SYMBOL_NS_GPL(devm_cxl_dpa_reserve, "CXL");

resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled)
{
	resource_size_t size = 0;

	down_read(&cxl_dpa_rwsem);
	guard(rwsem_read)(&cxl_dpa_rwsem);
	if (cxled->dpa_res)
		size = resource_size(cxled->dpa_res);
	up_read(&cxl_dpa_rwsem);
		return resource_size(cxled->dpa_res);

	return size;
	return 0;
}

resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled)
@@ -555,35 +550,27 @@ int cxl_dpa_free(struct cxl_endpoint_decoder *cxled)
{
	struct cxl_port *port = cxled_to_port(cxled);
	struct device *dev = &cxled->cxld.dev;
	int rc;

	down_write(&cxl_dpa_rwsem);
	if (!cxled->dpa_res) {
		rc = 0;
		goto out;
	}
	guard(rwsem_write)(&cxl_dpa_rwsem);
	if (!cxled->dpa_res)
		return 0;
	if (cxled->cxld.region) {
		dev_dbg(dev, "decoder assigned to: %s\n",
			dev_name(&cxled->cxld.region->dev));
		rc = -EBUSY;
		goto out;
		return -EBUSY;
	}
	if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) {
		dev_dbg(dev, "decoder enabled\n");
		rc = -EBUSY;
		goto out;
		return -EBUSY;
	}
	if (cxled->cxld.id != port->hdm_end) {
		dev_dbg(dev, "expected decoder%d.%d\n", port->id,
			port->hdm_end);
		rc = -EBUSY;
		goto out;
		return -EBUSY;
	}

	devm_cxl_dpa_release(cxled);
	rc = 0;
out:
	up_write(&cxl_dpa_rwsem);
	return rc;
	return 0;
}

int cxl_dpa_set_part(struct cxl_endpoint_decoder *cxled,
@@ -616,36 +603,32 @@ int cxl_dpa_set_part(struct cxl_endpoint_decoder *cxled,
	return 0;
}

int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size)
static int __cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size)
{
	struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
	struct cxl_port *port = cxled_to_port(cxled);
	struct cxl_dev_state *cxlds = cxlmd->cxlds;
	struct device *dev = &cxled->cxld.dev;
	struct resource *res, *prev = NULL;
	resource_size_t start, avail, skip, skip_start;
	struct resource *p, *last;
	int part, rc;
	int part;

	down_write(&cxl_dpa_rwsem);
	guard(rwsem_write)(&cxl_dpa_rwsem);
	if (cxled->cxld.region) {
		dev_dbg(dev, "decoder attached to %s\n",
			dev_name(&cxled->cxld.region->dev));
		rc = -EBUSY;
		goto out;
		return -EBUSY;
	}

	if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) {
		dev_dbg(dev, "decoder enabled\n");
		rc = -EBUSY;
		goto out;
		return -EBUSY;
	}

	part = cxled->part;
	if (part < 0) {
		dev_dbg(dev, "partition not set\n");
		rc = -EBUSY;
		goto out;
		return -EBUSY;
	}

	res = &cxlds->part[part].res;
@@ -685,14 +668,18 @@ int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size)
	if (size > avail) {
		dev_dbg(dev, "%pa exceeds available %s capacity: %pa\n", &size,
			res->name, &avail);
		rc = -ENOSPC;
		goto out;
		return -ENOSPC;
	}

	rc = __cxl_dpa_reserve(cxled, start, size, skip);
out:
	up_write(&cxl_dpa_rwsem);
	return __cxl_dpa_reserve(cxled, start, size, skip);
}

int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size)
{
	struct cxl_port *port = cxled_to_port(cxled);
	int rc;

	rc = __cxl_dpa_alloc(cxled, size);
	if (rc)
		return rc;

+3 −7
Original line number Diff line number Diff line
@@ -1218,23 +1218,19 @@ int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd)
{
	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
	struct cxl_port  *endpoint;
	int rc;

	/* synchronize with cxl_mem_probe() and decoder write operations */
	guard(device)(&cxlmd->dev);
	endpoint = cxlmd->endpoint;
	down_read(&cxl_region_rwsem);
	guard(rwsem_read)(&cxl_region_rwsem);
	/*
	 * Require an endpoint to be safe otherwise the driver can not
	 * be sure that the device is unmapped.
	 */
	if (endpoint && cxl_num_decoders_committed(endpoint) == 0)
		rc = __cxl_mem_sanitize(mds, cmd);
	else
		rc = -EBUSY;
	up_read(&cxl_region_rwsem);
		return __cxl_mem_sanitize(mds, cmd);

	return rc;
	return -EBUSY;
}

static void add_part(struct cxl_dpa_info *info, u64 start, u64 size, enum cxl_partition_mode mode)
+6 −11
Original line number Diff line number Diff line
@@ -580,10 +580,9 @@ EXPORT_SYMBOL_NS_GPL(is_cxl_memdev, "CXL");
void set_exclusive_cxl_commands(struct cxl_memdev_state *mds,
				unsigned long *cmds)
{
	down_write(&cxl_memdev_rwsem);
	guard(rwsem_write)(&cxl_memdev_rwsem);
	bitmap_or(mds->exclusive_cmds, mds->exclusive_cmds, cmds,
		  CXL_MEM_COMMAND_ID_MAX);
	up_write(&cxl_memdev_rwsem);
}
EXPORT_SYMBOL_NS_GPL(set_exclusive_cxl_commands, "CXL");

@@ -595,10 +594,9 @@ EXPORT_SYMBOL_NS_GPL(set_exclusive_cxl_commands, "CXL");
void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds,
				  unsigned long *cmds)
{
	down_write(&cxl_memdev_rwsem);
	guard(rwsem_write)(&cxl_memdev_rwsem);
	bitmap_andnot(mds->exclusive_cmds, mds->exclusive_cmds, cmds,
		      CXL_MEM_COMMAND_ID_MAX);
	up_write(&cxl_memdev_rwsem);
}
EXPORT_SYMBOL_NS_GPL(clear_exclusive_cxl_commands, "CXL");

@@ -606,9 +604,8 @@ static void cxl_memdev_shutdown(struct device *dev)
{
	struct cxl_memdev *cxlmd = to_cxl_memdev(dev);

	down_write(&cxl_memdev_rwsem);
	guard(rwsem_write)(&cxl_memdev_rwsem);
	cxlmd->cxlds = NULL;
	up_write(&cxl_memdev_rwsem);
}

static void cxl_memdev_unregister(void *_cxlmd)
@@ -687,15 +684,13 @@ static long cxl_memdev_ioctl(struct file *file, unsigned int cmd,
{
	struct cxl_memdev *cxlmd = file->private_data;
	struct cxl_dev_state *cxlds;
	int rc = -ENXIO;

	down_read(&cxl_memdev_rwsem);
	guard(rwsem_read)(&cxl_memdev_rwsem);
	cxlds = cxlmd->cxlds;
	if (cxlds && cxlds->type == CXL_DEVTYPE_CLASSMEM)
		rc = __cxl_memdev_ioctl(cxlmd, cmd, arg);
	up_read(&cxl_memdev_rwsem);
		return __cxl_memdev_ioctl(cxlmd, cmd, arg);

	return rc;
	return -ENXIO;
}

static int cxl_memdev_open(struct inode *inode, struct file *file)
+2 −6
Original line number Diff line number Diff line
@@ -559,13 +559,9 @@ static ssize_t decoders_committed_show(struct device *dev,
				       struct device_attribute *attr, char *buf)
{
	struct cxl_port *port = to_cxl_port(dev);
	int rc;

	down_read(&cxl_region_rwsem);
	rc = sysfs_emit(buf, "%d\n", cxl_num_decoders_committed(port));
	up_read(&cxl_region_rwsem);

	return rc;
	guard(rwsem_read)(&cxl_region_rwsem);
	return sysfs_emit(buf, "%d\n", cxl_num_decoders_committed(port));
}

static DEVICE_ATTR_RO(decoders_committed);
+49 −53
Original line number Diff line number Diff line
@@ -3037,17 +3037,13 @@ static struct cxl_dax_region *cxl_dax_region_alloc(struct cxl_region *cxlr)
	struct cxl_dax_region *cxlr_dax;
	struct device *dev;

	down_read(&cxl_region_rwsem);
	if (p->state != CXL_CONFIG_COMMIT) {
		cxlr_dax = ERR_PTR(-ENXIO);
		goto out;
	}
	guard(rwsem_read)(&cxl_region_rwsem);
	if (p->state != CXL_CONFIG_COMMIT)
		return ERR_PTR(-ENXIO);

	cxlr_dax = kzalloc(sizeof(*cxlr_dax), GFP_KERNEL);
	if (!cxlr_dax) {
		cxlr_dax = ERR_PTR(-ENOMEM);
		goto out;
	}
	if (!cxlr_dax)
		return ERR_PTR(-ENOMEM);

	cxlr_dax->hpa_range.start = p->res->start;
	cxlr_dax->hpa_range.end = p->res->end;
@@ -3060,8 +3056,6 @@ static struct cxl_dax_region *cxl_dax_region_alloc(struct cxl_region *cxlr)
	dev->parent = &cxlr->dev;
	dev->bus = &cxl_bus_type;
	dev->type = &cxl_dax_region_type;
out:
	up_read(&cxl_region_rwsem);

	return cxlr_dax;
}
@@ -3207,7 +3201,6 @@ static int match_region_by_range(struct device *dev, const void *data)
	struct cxl_region_params *p;
	struct cxl_region *cxlr;
	const struct range *r = data;
	int rc = 0;

	if (!is_cxl_region(dev))
		return 0;
@@ -3215,61 +3208,38 @@ static int match_region_by_range(struct device *dev, const void *data)
	cxlr = to_cxl_region(dev);
	p = &cxlr->params;

	down_read(&cxl_region_rwsem);
	guard(rwsem_read)(&cxl_region_rwsem);
	if (p->res && p->res->start == r->start && p->res->end == r->end)
		rc = 1;
	up_read(&cxl_region_rwsem);
		return 1;

	return rc;
	return 0;
}

/* Establish an empty region covering the given HPA range */
static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,
static int __construct_region(struct cxl_region *cxlr,
			      struct cxl_root_decoder *cxlrd,
			      struct cxl_endpoint_decoder *cxled)
{
	struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
	struct cxl_port *port = cxlrd_to_port(cxlrd);
	struct cxl_dev_state *cxlds = cxlmd->cxlds;
	struct range *hpa = &cxled->cxld.hpa_range;
	int rc, part = READ_ONCE(cxled->part);
	struct cxl_region_params *p;
	struct cxl_region *cxlr;
	struct resource *res;
	int rc;

	if (part < 0)
		return ERR_PTR(-EBUSY);

	do {
		cxlr = __create_region(cxlrd, cxlds->part[part].mode,
				       atomic_read(&cxlrd->region_id));
	} while (IS_ERR(cxlr) && PTR_ERR(cxlr) == -EBUSY);

	if (IS_ERR(cxlr)) {
		dev_err(cxlmd->dev.parent,
			"%s:%s: %s failed assign region: %ld\n",
			dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev),
			__func__, PTR_ERR(cxlr));
		return cxlr;
	}

	down_write(&cxl_region_rwsem);
	guard(rwsem_write)(&cxl_region_rwsem);
	p = &cxlr->params;
	if (p->state >= CXL_CONFIG_INTERLEAVE_ACTIVE) {
		dev_err(cxlmd->dev.parent,
			"%s:%s: %s autodiscovery interrupted\n",
			dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev),
			__func__);
		rc = -EBUSY;
		goto err;
		return -EBUSY;
	}

	set_bit(CXL_REGION_F_AUTO, &cxlr->flags);

	res = kmalloc(sizeof(*res), GFP_KERNEL);
	if (!res) {
		rc = -ENOMEM;
		goto err;
	}
	if (!res)
		return -ENOMEM;

	*res = DEFINE_RES_MEM_NAMED(hpa->start, range_len(hpa),
				    dev_name(&cxlr->dev));
@@ -3292,7 +3262,7 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,

	rc = sysfs_update_group(&cxlr->dev.kobj, get_cxl_region_target_group());
	if (rc)
		goto err;
		return rc;

	dev_dbg(cxlmd->dev.parent, "%s:%s: %s %s res: %pr iw: %d ig: %d\n",
		dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev), __func__,
@@ -3301,16 +3271,42 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,

	/* ...to match put_device() in cxl_add_to_region() */
	get_device(&cxlr->dev);
	up_write(&cxl_region_rwsem);

	return 0;
}

/* Establish an empty region covering the given HPA range */
static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,
					   struct cxl_endpoint_decoder *cxled)
{
	struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
	struct cxl_port *port = cxlrd_to_port(cxlrd);
	struct cxl_dev_state *cxlds = cxlmd->cxlds;
	int rc, part = READ_ONCE(cxled->part);
	struct cxl_region *cxlr;

	do {
		cxlr = __create_region(cxlrd, cxlds->part[part].mode,
				       atomic_read(&cxlrd->region_id));
	} while (IS_ERR(cxlr) && PTR_ERR(cxlr) == -EBUSY);

	if (IS_ERR(cxlr)) {
		dev_err(cxlmd->dev.parent,
			"%s:%s: %s failed assign region: %ld\n",
			dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev),
			__func__, PTR_ERR(cxlr));
		return cxlr;
	}

err:
	up_write(&cxl_region_rwsem);
	rc = __construct_region(cxlr, cxlrd, cxled);
	if (rc) {
		devm_release_action(port->uport_dev, unregister_region, cxlr);
		return ERR_PTR(rc);
	}

	return cxlr;
}

int cxl_add_to_region(struct cxl_port *root, struct cxl_endpoint_decoder *cxled)
{
	struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);