mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
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.
This commit is contained in:
commit
b6faa9c613
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
struct cxl_endpoint_decoder *cxled)
|
||||
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,14 +3271,40 @@ 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;
|
||||
}
|
||||
|
||||
rc = __construct_region(cxlr, cxlrd, cxled);
|
||||
if (rc) {
|
||||
devm_release_action(port->uport_dev, unregister_region, cxlr);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
return cxlr;
|
||||
|
||||
err:
|
||||
up_write(&cxl_region_rwsem);
|
||||
devm_release_action(port->uport_dev, unregister_region, cxlr);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
int cxl_add_to_region(struct cxl_port *root, struct cxl_endpoint_decoder *cxled)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user