Skip to content

Commit 3f7938b

Browse files
committed
Merge branch 'for-7.0/cxl-init' into cxl-for-next
Merge in patches to support several patch series such as Soft Reserve handling, type2 accelerator enabling, and LSA 2.1 labeling support. Mainly addition of cxl_memdev_attach() to allow the memdev probe to make a decision of proceed/fail depending success of CXL topology enumeration. dax/hmem, e820, resource: Defer Soft Reserved insertion until hmem is ready cxl/mem: Introduce cxl_memdev_attach for CXL-dependent operation cxl/mem: Drop @host argument to devm_cxl_add_memdev() cxl/mem: Convert devm_cxl_add_memdev() to scope-based-cleanup cxl/port: Arrange for always synchronous endpoint attach cxl/mem: Arrange for always-synchronous memdev attach cxl/mem: Fix devm_cxl_memdev_edac_release() confusion
2 parents 914c743 + bc62f5b commit 3f7938b

14 files changed

Lines changed: 280 additions & 130 deletions

File tree

arch/x86/kernel/e820.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,11 +1151,18 @@ void __init e820__reserve_resources_late(void)
11511151
int i;
11521152
struct resource *res;
11531153

1154-
res = e820_res;
1155-
for (i = 0; i < e820_table->nr_entries; i++) {
1156-
if (!res->parent && res->end)
1154+
for (i = 0, res = e820_res; i < e820_table->nr_entries; i++, res++) {
1155+
/* skip added or uninitialized resources */
1156+
if (res->parent || !res->end)
1157+
continue;
1158+
1159+
/* set aside soft-reserved resources for driver consideration */
1160+
if (res->desc == IORES_DESC_SOFT_RESERVED) {
1161+
insert_resource_expand_to_fit(&soft_reserve_resource, res);
1162+
} else {
1163+
/* publish the rest immediately */
11571164
insert_resource_expand_to_fit(&iomem_resource, res);
1158-
res++;
1165+
}
11591166
}
11601167

11611168
/*

drivers/cxl/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ if CXL_BUS
2222
config CXL_PCI
2323
tristate "PCI manageability"
2424
default CXL_BUS
25+
select CXL_MEM
2526
help
2627
The CXL specification defines a "CXL memory device" sub-class in the
2728
PCI "memory controller" base class of devices. Device's identified by
@@ -89,7 +90,6 @@ config CXL_PMEM
8990

9091
config CXL_MEM
9192
tristate "CXL: Memory Expansion"
92-
depends on CXL_PCI
9393
default CXL_BUS
9494
help
9595
The CXL.mem protocol allows a device to act as a provider of "System

drivers/cxl/core/edac.c

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,6 +1988,40 @@ static int cxl_memdev_soft_ppr_init(struct cxl_memdev *cxlmd,
19881988
return 0;
19891989
}
19901990

1991+
static void err_rec_free(void *_cxlmd)
1992+
{
1993+
struct cxl_memdev *cxlmd = _cxlmd;
1994+
struct cxl_mem_err_rec *array_rec = cxlmd->err_rec_array;
1995+
struct cxl_event_gen_media *rec_gen_media;
1996+
struct cxl_event_dram *rec_dram;
1997+
unsigned long index;
1998+
1999+
cxlmd->err_rec_array = NULL;
2000+
xa_for_each(&array_rec->rec_dram, index, rec_dram)
2001+
kfree(rec_dram);
2002+
xa_destroy(&array_rec->rec_dram);
2003+
2004+
xa_for_each(&array_rec->rec_gen_media, index, rec_gen_media)
2005+
kfree(rec_gen_media);
2006+
xa_destroy(&array_rec->rec_gen_media);
2007+
kfree(array_rec);
2008+
}
2009+
2010+
static int devm_cxl_memdev_setup_err_rec(struct cxl_memdev *cxlmd)
2011+
{
2012+
struct cxl_mem_err_rec *array_rec =
2013+
kzalloc(sizeof(*array_rec), GFP_KERNEL);
2014+
2015+
if (!array_rec)
2016+
return -ENOMEM;
2017+
2018+
xa_init(&array_rec->rec_gen_media);
2019+
xa_init(&array_rec->rec_dram);
2020+
cxlmd->err_rec_array = array_rec;
2021+
2022+
return devm_add_action_or_reset(&cxlmd->dev, err_rec_free, cxlmd);
2023+
}
2024+
19912025
int devm_cxl_memdev_edac_register(struct cxl_memdev *cxlmd)
19922026
{
19932027
struct edac_dev_feature ras_features[CXL_NR_EDAC_DEV_FEATURES];
@@ -2038,15 +2072,9 @@ int devm_cxl_memdev_edac_register(struct cxl_memdev *cxlmd)
20382072
}
20392073

20402074
if (repair_inst) {
2041-
struct cxl_mem_err_rec *array_rec =
2042-
devm_kzalloc(&cxlmd->dev, sizeof(*array_rec),
2043-
GFP_KERNEL);
2044-
if (!array_rec)
2045-
return -ENOMEM;
2046-
2047-
xa_init(&array_rec->rec_gen_media);
2048-
xa_init(&array_rec->rec_dram);
2049-
cxlmd->err_rec_array = array_rec;
2075+
rc = devm_cxl_memdev_setup_err_rec(cxlmd);
2076+
if (rc)
2077+
return rc;
20502078
}
20512079
}
20522080

@@ -2088,22 +2116,4 @@ int devm_cxl_region_edac_register(struct cxl_region *cxlr)
20882116
}
20892117
EXPORT_SYMBOL_NS_GPL(devm_cxl_region_edac_register, "CXL");
20902118

2091-
void devm_cxl_memdev_edac_release(struct cxl_memdev *cxlmd)
2092-
{
2093-
struct cxl_mem_err_rec *array_rec = cxlmd->err_rec_array;
2094-
struct cxl_event_gen_media *rec_gen_media;
2095-
struct cxl_event_dram *rec_dram;
2096-
unsigned long index;
2097-
2098-
if (!IS_ENABLED(CONFIG_CXL_EDAC_MEM_REPAIR) || !array_rec)
2099-
return;
2100-
2101-
xa_for_each(&array_rec->rec_dram, index, rec_dram)
2102-
kfree(rec_dram);
2103-
xa_destroy(&array_rec->rec_dram);
21042119

2105-
xa_for_each(&array_rec->rec_gen_media, index, rec_gen_media)
2106-
kfree(rec_gen_media);
2107-
xa_destroy(&array_rec->rec_gen_media);
2108-
}
2109-
EXPORT_SYMBOL_NS_GPL(devm_cxl_memdev_edac_release, "CXL");

drivers/cxl/core/memdev.c

Lines changed: 77 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ static void cxl_memdev_release(struct device *dev)
2727
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
2828

2929
ida_free(&cxl_memdev_ida, cxlmd->id);
30-
devm_cxl_memdev_edac_release(cxlmd);
3130
kfree(cxlmd);
3231
}
3332

@@ -642,14 +641,24 @@ static void detach_memdev(struct work_struct *work)
642641
struct cxl_memdev *cxlmd;
643642

644643
cxlmd = container_of(work, typeof(*cxlmd), detach_work);
645-
device_release_driver(&cxlmd->dev);
644+
645+
/*
646+
* When the creator of @cxlmd sets ->attach it indicates CXL operation
647+
* is required. In that case, @cxlmd detach escalates to parent device
648+
* detach.
649+
*/
650+
if (cxlmd->attach)
651+
device_release_driver(cxlmd->dev.parent);
652+
else
653+
device_release_driver(&cxlmd->dev);
646654
put_device(&cxlmd->dev);
647655
}
648656

649657
static struct lock_class_key cxl_memdev_key;
650658

651659
static struct cxl_memdev *cxl_memdev_alloc(struct cxl_dev_state *cxlds,
652-
const struct file_operations *fops)
660+
const struct file_operations *fops,
661+
const struct cxl_memdev_attach *attach)
653662
{
654663
struct cxl_memdev *cxlmd;
655664
struct device *dev;
@@ -665,6 +674,8 @@ static struct cxl_memdev *cxl_memdev_alloc(struct cxl_dev_state *cxlds,
665674
goto err;
666675
cxlmd->id = rc;
667676
cxlmd->depth = -1;
677+
cxlmd->attach = attach;
678+
cxlmd->endpoint = ERR_PTR(-ENXIO);
668679

669680
dev = &cxlmd->dev;
670681
device_initialize(dev);
@@ -1051,50 +1062,84 @@ static const struct file_operations cxl_memdev_fops = {
10511062
.llseek = noop_llseek,
10521063
};
10531064

1054-
struct cxl_memdev *devm_cxl_add_memdev(struct device *host,
1055-
struct cxl_dev_state *cxlds)
1065+
/*
1066+
* Activate ioctl operations, no cxl_memdev_rwsem manipulation needed as this is
1067+
* ordered with cdev_add() publishing the device.
1068+
*/
1069+
static int cxlmd_add(struct cxl_memdev *cxlmd, struct cxl_dev_state *cxlds)
1070+
{
1071+
int rc;
1072+
1073+
cxlmd->cxlds = cxlds;
1074+
cxlds->cxlmd = cxlmd;
1075+
1076+
rc = cdev_device_add(&cxlmd->cdev, &cxlmd->dev);
1077+
if (rc) {
1078+
/*
1079+
* The cdev was briefly live, shutdown any ioctl operations that
1080+
* saw that state.
1081+
*/
1082+
cxl_memdev_shutdown(&cxlmd->dev);
1083+
return rc;
1084+
}
1085+
1086+
return 0;
1087+
}
1088+
1089+
DEFINE_FREE(put_cxlmd, struct cxl_memdev *,
1090+
if (!IS_ERR_OR_NULL(_T)) put_device(&_T->dev))
1091+
1092+
static struct cxl_memdev *cxl_memdev_autoremove(struct cxl_memdev *cxlmd)
1093+
{
1094+
int rc;
1095+
1096+
/*
1097+
* If @attach is provided fail if the driver is not attached upon
1098+
* return. Note that failure here could be the result of a race to
1099+
* teardown the CXL port topology. I.e. cxl_mem_probe() could have
1100+
* succeeded and then cxl_mem unbound before the lock is acquired.
1101+
*/
1102+
guard(device)(&cxlmd->dev);
1103+
if (cxlmd->attach && !cxlmd->dev.driver) {
1104+
cxl_memdev_unregister(cxlmd);
1105+
return ERR_PTR(-ENXIO);
1106+
}
1107+
1108+
rc = devm_add_action_or_reset(cxlmd->cxlds->dev, cxl_memdev_unregister,
1109+
cxlmd);
1110+
if (rc)
1111+
return ERR_PTR(rc);
1112+
1113+
return cxlmd;
1114+
}
1115+
1116+
/*
1117+
* Core helper for devm_cxl_add_memdev() that wants to both create a device and
1118+
* assert to the caller that upon return cxl_mem::probe() has been invoked.
1119+
*/
1120+
struct cxl_memdev *__devm_cxl_add_memdev(struct cxl_dev_state *cxlds,
1121+
const struct cxl_memdev_attach *attach)
10561122
{
1057-
struct cxl_memdev *cxlmd;
10581123
struct device *dev;
1059-
struct cdev *cdev;
10601124
int rc;
10611125

1062-
cxlmd = cxl_memdev_alloc(cxlds, &cxl_memdev_fops);
1126+
struct cxl_memdev *cxlmd __free(put_cxlmd) =
1127+
cxl_memdev_alloc(cxlds, &cxl_memdev_fops, attach);
10631128
if (IS_ERR(cxlmd))
10641129
return cxlmd;
10651130

10661131
dev = &cxlmd->dev;
10671132
rc = dev_set_name(dev, "mem%d", cxlmd->id);
10681133
if (rc)
1069-
goto err;
1070-
1071-
/*
1072-
* Activate ioctl operations, no cxl_memdev_rwsem manipulation
1073-
* needed as this is ordered with cdev_add() publishing the device.
1074-
*/
1075-
cxlmd->cxlds = cxlds;
1076-
cxlds->cxlmd = cxlmd;
1077-
1078-
cdev = &cxlmd->cdev;
1079-
rc = cdev_device_add(cdev, dev);
1080-
if (rc)
1081-
goto err;
1134+
return ERR_PTR(rc);
10821135

1083-
rc = devm_add_action_or_reset(host, cxl_memdev_unregister, cxlmd);
1136+
rc = cxlmd_add(cxlmd, cxlds);
10841137
if (rc)
10851138
return ERR_PTR(rc);
1086-
return cxlmd;
10871139

1088-
err:
1089-
/*
1090-
* The cdev was briefly live, shutdown any ioctl operations that
1091-
* saw that state.
1092-
*/
1093-
cxl_memdev_shutdown(dev);
1094-
put_device(dev);
1095-
return ERR_PTR(rc);
1140+
return cxl_memdev_autoremove(no_free_ptr(cxlmd));
10961141
}
1097-
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_memdev, "CXL");
1142+
EXPORT_SYMBOL_FOR_MODULES(__devm_cxl_add_memdev, "cxl_mem");
10981143

10991144
static void sanitize_teardown_notifier(void *data)
11001145
{

drivers/cxl/cxl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,8 @@ struct cxl_port *devm_cxl_add_port(struct device *host,
780780
struct cxl_dport *parent_dport);
781781
struct cxl_root *devm_cxl_add_root(struct device *host,
782782
const struct cxl_root_ops *ops);
783+
int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
784+
struct cxl_dport *parent_dport);
783785
struct cxl_root *find_cxl_root(struct cxl_port *port);
784786

785787
DEFINE_FREE(put_cxl_root, struct cxl_root *, if (_T) put_device(&_T->port.dev))

drivers/cxl/cxlmem.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
(FIELD_GET(CXLMDEV_RESET_NEEDED_MASK, status) != \
3535
CXLMDEV_RESET_NEEDED_NOT)
3636

37+
struct cxl_memdev_attach {
38+
int (*probe)(struct cxl_memdev *cxlmd);
39+
};
40+
3741
/**
3842
* struct cxl_memdev - CXL bus object representing a Type-3 Memory Device
3943
* @dev: driver core device object
@@ -43,6 +47,7 @@
4347
* @cxl_nvb: coordinate removal of @cxl_nvd if present
4448
* @cxl_nvd: optional bridge to an nvdimm if the device supports pmem
4549
* @endpoint: connection to the CXL port topology for this memory device
50+
* @attach: creator of this memdev depends on CXL link attach to operate
4651
* @id: id number of this memdev instance.
4752
* @depth: endpoint port depth
4853
* @scrub_cycle: current scrub cycle set for this device
@@ -59,11 +64,12 @@ struct cxl_memdev {
5964
struct cxl_nvdimm_bridge *cxl_nvb;
6065
struct cxl_nvdimm *cxl_nvd;
6166
struct cxl_port *endpoint;
67+
const struct cxl_memdev_attach *attach;
6268
int id;
6369
int depth;
6470
u8 scrub_cycle;
6571
int scrub_region_id;
66-
void *err_rec_array;
72+
struct cxl_mem_err_rec *err_rec_array;
6773
};
6874

6975
static inline struct cxl_memdev *to_cxl_memdev(struct device *dev)
@@ -95,8 +101,10 @@ static inline bool is_cxl_endpoint(struct cxl_port *port)
95101
return is_cxl_memdev(port->uport_dev);
96102
}
97103

98-
struct cxl_memdev *devm_cxl_add_memdev(struct device *host,
99-
struct cxl_dev_state *cxlds);
104+
struct cxl_memdev *__devm_cxl_add_memdev(struct cxl_dev_state *cxlds,
105+
const struct cxl_memdev_attach *attach);
106+
struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds,
107+
const struct cxl_memdev_attach *attach);
100108
int devm_cxl_sanitize_setup_notifier(struct device *host,
101109
struct cxl_memdev *cxlmd);
102110
struct cxl_memdev_state;
@@ -877,7 +885,6 @@ int devm_cxl_memdev_edac_register(struct cxl_memdev *cxlmd);
877885
int devm_cxl_region_edac_register(struct cxl_region *cxlr);
878886
int cxl_store_rec_gen_media(struct cxl_memdev *cxlmd, union cxl_event *evt);
879887
int cxl_store_rec_dram(struct cxl_memdev *cxlmd, union cxl_event *evt);
880-
void devm_cxl_memdev_edac_release(struct cxl_memdev *cxlmd);
881888
#else
882889
static inline int devm_cxl_memdev_edac_register(struct cxl_memdev *cxlmd)
883890
{ return 0; }
@@ -889,8 +896,6 @@ static inline int cxl_store_rec_gen_media(struct cxl_memdev *cxlmd,
889896
static inline int cxl_store_rec_dram(struct cxl_memdev *cxlmd,
890897
union cxl_event *evt)
891898
{ return 0; }
892-
static inline void devm_cxl_memdev_edac_release(struct cxl_memdev *cxlmd)
893-
{ return; }
894899
#endif
895900

896901
#ifdef CONFIG_CXL_SUSPEND

0 commit comments

Comments
 (0)