mirror of
https://github.com/torvalds/linux.git
synced 2024-09-20 15:03:04 +00:00
cxl/region: Add volatile region creation support
Expand the region creation infrastructure to enable 'ram' (volatile-memory) regions. The internals of create_pmem_region_store() and create_pmem_region_show() are factored out into helpers __create_region() and __create_region_show() for the 'ram' case to reuse. Reviewed-by: Vishal Verma <vishal.l.verma@intel.com> Reviewed-by: Gregory Price <gregory.price@memverge.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Ira Weiny <ira.weiny@intel.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Tested-by: Fan Ni <fan.ni@samsung.com> Link: https://lore.kernel.org/r/167601995775.1924368.352616146815830591.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
parent
1b9b7a6fd6
commit
6e09926418
|
@ -285,20 +285,20 @@ Description:
|
|||
interleave_granularity).
|
||||
|
||||
|
||||
What: /sys/bus/cxl/devices/decoderX.Y/create_pmem_region
|
||||
Date: May, 2022
|
||||
KernelVersion: v6.0
|
||||
What: /sys/bus/cxl/devices/decoderX.Y/create_{pmem,ram}_region
|
||||
Date: May, 2022, January, 2023
|
||||
KernelVersion: v6.0 (pmem), v6.3 (ram)
|
||||
Contact: linux-cxl@vger.kernel.org
|
||||
Description:
|
||||
(RW) Write a string in the form 'regionZ' to start the process
|
||||
of defining a new persistent memory region (interleave-set)
|
||||
within the decode range bounded by root decoder 'decoderX.Y'.
|
||||
The value written must match the current value returned from
|
||||
reading this attribute. An atomic compare exchange operation is
|
||||
done on write to assign the requested id to a region and
|
||||
allocate the region-id for the next creation attempt. EBUSY is
|
||||
returned if the region name written does not match the current
|
||||
cached value.
|
||||
of defining a new persistent, or volatile memory region
|
||||
(interleave-set) within the decode range bounded by root decoder
|
||||
'decoderX.Y'. The value written must match the current value
|
||||
returned from reading this attribute. An atomic compare exchange
|
||||
operation is done on write to assign the requested id to a
|
||||
region and allocate the region-id for the next creation attempt.
|
||||
EBUSY is returned if the region name written does not match the
|
||||
current cached value.
|
||||
|
||||
|
||||
What: /sys/bus/cxl/devices/decoderX.Y/delete_region
|
||||
|
|
|
@ -11,6 +11,7 @@ extern struct attribute_group cxl_base_attribute_group;
|
|||
|
||||
#ifdef CONFIG_CXL_REGION
|
||||
extern struct device_attribute dev_attr_create_pmem_region;
|
||||
extern struct device_attribute dev_attr_create_ram_region;
|
||||
extern struct device_attribute dev_attr_delete_region;
|
||||
extern struct device_attribute dev_attr_region;
|
||||
extern const struct device_type cxl_pmem_region_type;
|
||||
|
|
|
@ -294,6 +294,7 @@ static struct attribute *cxl_decoder_root_attrs[] = {
|
|||
&dev_attr_cap_type3.attr,
|
||||
&dev_attr_target_list.attr,
|
||||
SET_CXL_REGION_ATTR(create_pmem_region)
|
||||
SET_CXL_REGION_ATTR(create_ram_region)
|
||||
SET_CXL_REGION_ATTR(delete_region)
|
||||
NULL,
|
||||
};
|
||||
|
@ -305,6 +306,13 @@ static bool can_create_pmem(struct cxl_root_decoder *cxlrd)
|
|||
return (cxlrd->cxlsd.cxld.flags & flags) == flags;
|
||||
}
|
||||
|
||||
static bool can_create_ram(struct cxl_root_decoder *cxlrd)
|
||||
{
|
||||
unsigned long flags = CXL_DECODER_F_TYPE3 | CXL_DECODER_F_RAM;
|
||||
|
||||
return (cxlrd->cxlsd.cxld.flags & flags) == flags;
|
||||
}
|
||||
|
||||
static umode_t cxl_root_decoder_visible(struct kobject *kobj, struct attribute *a, int n)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
|
@ -313,7 +321,11 @@ static umode_t cxl_root_decoder_visible(struct kobject *kobj, struct attribute *
|
|||
if (a == CXL_REGION_ATTR(create_pmem_region) && !can_create_pmem(cxlrd))
|
||||
return 0;
|
||||
|
||||
if (a == CXL_REGION_ATTR(delete_region) && !can_create_pmem(cxlrd))
|
||||
if (a == CXL_REGION_ATTR(create_ram_region) && !can_create_ram(cxlrd))
|
||||
return 0;
|
||||
|
||||
if (a == CXL_REGION_ATTR(delete_region) &&
|
||||
!(can_create_pmem(cxlrd) || can_create_ram(cxlrd)))
|
||||
return 0;
|
||||
|
||||
return a->mode;
|
||||
|
|
|
@ -1689,6 +1689,15 @@ static struct cxl_region *devm_cxl_add_region(struct cxl_root_decoder *cxlrd,
|
|||
struct device *dev;
|
||||
int rc;
|
||||
|
||||
switch (mode) {
|
||||
case CXL_DECODER_RAM:
|
||||
case CXL_DECODER_PMEM:
|
||||
break;
|
||||
default:
|
||||
dev_err(&cxlrd->cxlsd.cxld.dev, "unsupported mode %d\n", mode);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
cxlr = cxl_region_alloc(cxlrd, id);
|
||||
if (IS_ERR(cxlr))
|
||||
return cxlr;
|
||||
|
@ -1717,12 +1726,38 @@ err:
|
|||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
static ssize_t __create_region_show(struct cxl_root_decoder *cxlrd, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "region%u\n", atomic_read(&cxlrd->region_id));
|
||||
}
|
||||
|
||||
static ssize_t create_pmem_region_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev);
|
||||
return __create_region_show(to_cxl_root_decoder(dev), buf);
|
||||
}
|
||||
|
||||
return sysfs_emit(buf, "region%u\n", atomic_read(&cxlrd->region_id));
|
||||
static ssize_t create_ram_region_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return __create_region_show(to_cxl_root_decoder(dev), buf);
|
||||
}
|
||||
|
||||
static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd,
|
||||
enum cxl_decoder_mode mode, int id)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = memregion_alloc(GFP_KERNEL);
|
||||
if (rc < 0)
|
||||
return ERR_PTR(rc);
|
||||
|
||||
if (atomic_cmpxchg(&cxlrd->region_id, id, rc) != id) {
|
||||
memregion_free(rc);
|
||||
return ERR_PTR(-EBUSY);
|
||||
}
|
||||
|
||||
return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_EXPANDER);
|
||||
}
|
||||
|
||||
static ssize_t create_pmem_region_store(struct device *dev,
|
||||
|
@ -1731,23 +1766,13 @@ static ssize_t create_pmem_region_store(struct device *dev,
|
|||
{
|
||||
struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev);
|
||||
struct cxl_region *cxlr;
|
||||
int id, rc;
|
||||
int rc, id;
|
||||
|
||||
rc = sscanf(buf, "region%d\n", &id);
|
||||
if (rc != 1)
|
||||
return -EINVAL;
|
||||
|
||||
rc = memregion_alloc(GFP_KERNEL);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (atomic_cmpxchg(&cxlrd->region_id, id, rc) != id) {
|
||||
memregion_free(rc);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
cxlr = devm_cxl_add_region(cxlrd, id, CXL_DECODER_PMEM,
|
||||
CXL_DECODER_EXPANDER);
|
||||
cxlr = __create_region(cxlrd, CXL_DECODER_PMEM, id);
|
||||
if (IS_ERR(cxlr))
|
||||
return PTR_ERR(cxlr);
|
||||
|
||||
|
@ -1755,6 +1780,26 @@ static ssize_t create_pmem_region_store(struct device *dev,
|
|||
}
|
||||
DEVICE_ATTR_RW(create_pmem_region);
|
||||
|
||||
static ssize_t create_ram_region_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev);
|
||||
struct cxl_region *cxlr;
|
||||
int rc, id;
|
||||
|
||||
rc = sscanf(buf, "region%d\n", &id);
|
||||
if (rc != 1)
|
||||
return -EINVAL;
|
||||
|
||||
cxlr = __create_region(cxlrd, CXL_DECODER_RAM, id);
|
||||
if (IS_ERR(cxlr))
|
||||
return PTR_ERR(cxlr);
|
||||
|
||||
return len;
|
||||
}
|
||||
DEVICE_ATTR_RW(create_ram_region);
|
||||
|
||||
static ssize_t region_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user