Skip to content

Commit 57d3744

Browse files
committed
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl.git
# Conflicts: # drivers/pci/pcie/aer.c
2 parents 976ded4 + 2630b39 commit 57d3744

File tree

27 files changed

+949
-366
lines changed

27 files changed

+949
-366
lines changed

Documentation/ABI/testing/sysfs-bus-cxl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,21 @@ Description:
178178
hardware decoder target list.
179179

180180

181+
What: /sys/bus/cxl/devices/portX/decoders_committed
182+
Date: October, 2023
183+
KernelVersion: v6.7
184+
Contact: linux-cxl@vger.kernel.org
185+
Description:
186+
(RO) A memory device is considered active when any of its
187+
decoders are in the "committed" state (See CXL 3.0 8.2.4.19.7
188+
CXL HDM Decoder n Control Register). Hotplug and destructive
189+
operations like "sanitize" are blocked while device is actively
190+
decoding a Host Physical Address range. Note that this number
191+
may be elevated without any regionX objects active or even
192+
enumerated, as this may be due to decoders established by
193+
platform firwmare or a previous kernel (kexec).
194+
195+
181196
What: /sys/bus/cxl/devices/decoderX.Y
182197
Date: June, 2021
183198
KernelVersion: v5.14
@@ -369,6 +384,21 @@ Description:
369384
provided it is currently idle / not bound to a driver.
370385

371386

387+
What: /sys/bus/cxl/devices/decoderX.Y/qos_class
388+
Date: May, 2023
389+
KernelVersion: v6.5
390+
Contact: linux-cxl@vger.kernel.org
391+
Description:
392+
(RO) For CXL host platforms that support "QoS Telemmetry" this
393+
root-decoder-only attribute conveys a platform specific cookie
394+
that identifies a QoS performance class for the CXL Window.
395+
This class-id can be compared against a similar "qos_class"
396+
published for each memory-type that an endpoint supports. While
397+
it is not required that endpoints map their local memory-class
398+
to a matching platform class, mismatches are not recommended and
399+
there are platform specific side-effects that may result.
400+
401+
372402
What: /sys/bus/cxl/devices/regionZ/uuid
373403
Date: May, 2022
374404
KernelVersion: v6.0

MAINTAINERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ F: drivers/pnp/pnpacpi/
294294
F: include/acpi/
295295
F: include/linux/acpi.h
296296
F: include/linux/fwnode.h
297+
F: include/linux/fw_table.h
298+
F: lib/fw_table.c
297299
F: tools/power/acpi/
298300

299301
ACPI APEI
@@ -5258,6 +5260,7 @@ L: linux-cxl@vger.kernel.org
52585260
S: Maintained
52595261
F: drivers/cxl/
52605262
F: include/uapi/linux/cxl_mem.h
5263+
F: tools/testing/cxl/
52615264

52625265
COMPUTE EXPRESS LINK PMU (CPMU)
52635266
M: Jonathan Cameron <jonathan.cameron@huawei.com>

drivers/acpi/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ menuconfig ACPI
1212
select PNP
1313
select NLS
1414
select CRC32
15+
select FIRMWARE_TABLE
1516
default y if X86
1617
help
1718
Advanced Configuration and Power Interface (ACPI) support for

drivers/acpi/tables.c

Lines changed: 0 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,6 @@ static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata;
3737

3838
static int acpi_apic_instance __initdata_or_acpilib;
3939

40-
enum acpi_subtable_type {
41-
ACPI_SUBTABLE_COMMON,
42-
ACPI_SUBTABLE_HMAT,
43-
ACPI_SUBTABLE_PRMT,
44-
ACPI_SUBTABLE_CEDT,
45-
};
46-
47-
struct acpi_subtable_entry {
48-
union acpi_subtable_headers *hdr;
49-
enum acpi_subtable_type type;
50-
};
51-
5240
/*
5341
* Disable table checksum verification for the early stage due to the size
5442
* limitation of the current x86 early mapping implementation.
@@ -237,167 +225,6 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
237225
}
238226
}
239227

240-
static unsigned long __init_or_acpilib
241-
acpi_get_entry_type(struct acpi_subtable_entry *entry)
242-
{
243-
switch (entry->type) {
244-
case ACPI_SUBTABLE_COMMON:
245-
return entry->hdr->common.type;
246-
case ACPI_SUBTABLE_HMAT:
247-
return entry->hdr->hmat.type;
248-
case ACPI_SUBTABLE_PRMT:
249-
return 0;
250-
case ACPI_SUBTABLE_CEDT:
251-
return entry->hdr->cedt.type;
252-
}
253-
return 0;
254-
}
255-
256-
static unsigned long __init_or_acpilib
257-
acpi_get_entry_length(struct acpi_subtable_entry *entry)
258-
{
259-
switch (entry->type) {
260-
case ACPI_SUBTABLE_COMMON:
261-
return entry->hdr->common.length;
262-
case ACPI_SUBTABLE_HMAT:
263-
return entry->hdr->hmat.length;
264-
case ACPI_SUBTABLE_PRMT:
265-
return entry->hdr->prmt.length;
266-
case ACPI_SUBTABLE_CEDT:
267-
return entry->hdr->cedt.length;
268-
}
269-
return 0;
270-
}
271-
272-
static unsigned long __init_or_acpilib
273-
acpi_get_subtable_header_length(struct acpi_subtable_entry *entry)
274-
{
275-
switch (entry->type) {
276-
case ACPI_SUBTABLE_COMMON:
277-
return sizeof(entry->hdr->common);
278-
case ACPI_SUBTABLE_HMAT:
279-
return sizeof(entry->hdr->hmat);
280-
case ACPI_SUBTABLE_PRMT:
281-
return sizeof(entry->hdr->prmt);
282-
case ACPI_SUBTABLE_CEDT:
283-
return sizeof(entry->hdr->cedt);
284-
}
285-
return 0;
286-
}
287-
288-
static enum acpi_subtable_type __init_or_acpilib
289-
acpi_get_subtable_type(char *id)
290-
{
291-
if (strncmp(id, ACPI_SIG_HMAT, 4) == 0)
292-
return ACPI_SUBTABLE_HMAT;
293-
if (strncmp(id, ACPI_SIG_PRMT, 4) == 0)
294-
return ACPI_SUBTABLE_PRMT;
295-
if (strncmp(id, ACPI_SIG_CEDT, 4) == 0)
296-
return ACPI_SUBTABLE_CEDT;
297-
return ACPI_SUBTABLE_COMMON;
298-
}
299-
300-
static __init_or_acpilib bool has_handler(struct acpi_subtable_proc *proc)
301-
{
302-
return proc->handler || proc->handler_arg;
303-
}
304-
305-
static __init_or_acpilib int call_handler(struct acpi_subtable_proc *proc,
306-
union acpi_subtable_headers *hdr,
307-
unsigned long end)
308-
{
309-
if (proc->handler)
310-
return proc->handler(hdr, end);
311-
if (proc->handler_arg)
312-
return proc->handler_arg(hdr, proc->arg, end);
313-
return -EINVAL;
314-
}
315-
316-
/**
317-
* acpi_parse_entries_array - for each proc_num find a suitable subtable
318-
*
319-
* @id: table id (for debugging purposes)
320-
* @table_size: size of the root table
321-
* @table_header: where does the table start?
322-
* @proc: array of acpi_subtable_proc struct containing entry id
323-
* and associated handler with it
324-
* @proc_num: how big proc is?
325-
* @max_entries: how many entries can we process?
326-
*
327-
* For each proc_num find a subtable with proc->id and run proc->handler
328-
* on it. Assumption is that there's only single handler for particular
329-
* entry id.
330-
*
331-
* The table_size is not the size of the complete ACPI table (the length
332-
* field in the header struct), but only the size of the root table; i.e.,
333-
* the offset from the very first byte of the complete ACPI table, to the
334-
* first byte of the very first subtable.
335-
*
336-
* On success returns sum of all matching entries for all proc handlers.
337-
* Otherwise, -ENODEV or -EINVAL is returned.
338-
*/
339-
static int __init_or_acpilib acpi_parse_entries_array(
340-
char *id, unsigned long table_size,
341-
struct acpi_table_header *table_header, struct acpi_subtable_proc *proc,
342-
int proc_num, unsigned int max_entries)
343-
{
344-
struct acpi_subtable_entry entry;
345-
unsigned long table_end, subtable_len, entry_len;
346-
int count = 0;
347-
int errs = 0;
348-
int i;
349-
350-
table_end = (unsigned long)table_header + table_header->length;
351-
352-
/* Parse all entries looking for a match. */
353-
354-
entry.type = acpi_get_subtable_type(id);
355-
entry.hdr = (union acpi_subtable_headers *)
356-
((unsigned long)table_header + table_size);
357-
subtable_len = acpi_get_subtable_header_length(&entry);
358-
359-
while (((unsigned long)entry.hdr) + subtable_len < table_end) {
360-
if (max_entries && count >= max_entries)
361-
break;
362-
363-
for (i = 0; i < proc_num; i++) {
364-
if (acpi_get_entry_type(&entry) != proc[i].id)
365-
continue;
366-
if (!has_handler(&proc[i]) ||
367-
(!errs &&
368-
call_handler(&proc[i], entry.hdr, table_end))) {
369-
errs++;
370-
continue;
371-
}
372-
373-
proc[i].count++;
374-
break;
375-
}
376-
if (i != proc_num)
377-
count++;
378-
379-
/*
380-
* If entry->length is 0, break from this loop to avoid
381-
* infinite loop.
382-
*/
383-
entry_len = acpi_get_entry_length(&entry);
384-
if (entry_len == 0) {
385-
pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, proc->id);
386-
return -EINVAL;
387-
}
388-
389-
entry.hdr = (union acpi_subtable_headers *)
390-
((unsigned long)entry.hdr + entry_len);
391-
}
392-
393-
if (max_entries && count > max_entries) {
394-
pr_warn("[%4.4s:0x%02x] found the maximum %i entries\n",
395-
id, proc->id, count);
396-
}
397-
398-
return errs ? -EINVAL : count;
399-
}
400-
401228
int __init_or_acpilib acpi_table_parse_entries_array(
402229
char *id, unsigned long table_size, struct acpi_subtable_proc *proc,
403230
int proc_num, unsigned int max_entries)

drivers/cxl/acpi.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,9 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
289289
}
290290
}
291291
}
292+
293+
cxlrd->qos_class = cfmws->qtg_id;
294+
292295
rc = cxl_decoder_add(cxld, target_map);
293296
err_xormap:
294297
if (rc)

drivers/cxl/core/core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ struct cxl_rcrb_info;
7373
resource_size_t __rcrb_to_component(struct device *dev,
7474
struct cxl_rcrb_info *ri,
7575
enum cxl_rcrb which);
76+
u16 cxl_rcrb_to_aer(struct device *dev, resource_size_t rcrb);
7677

7778
extern struct rw_semaphore cxl_dpa_rwsem;
7879
extern struct rw_semaphore cxl_region_rwsem;

drivers/cxl/core/hdm.c

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -81,26 +81,6 @@ static void parse_hdm_decoder_caps(struct cxl_hdm *cxlhdm)
8181
cxlhdm->interleave_mask |= GENMASK(14, 12);
8282
}
8383

84-
static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
85-
struct cxl_component_regs *regs)
86-
{
87-
struct cxl_register_map map = {
88-
.dev = &port->dev,
89-
.resource = port->component_reg_phys,
90-
.base = crb,
91-
.max_size = CXL_COMPONENT_REG_BLOCK_SIZE,
92-
};
93-
94-
cxl_probe_component_regs(&port->dev, crb, &map.component_map);
95-
if (!map.component_map.hdm_decoder.valid) {
96-
dev_dbg(&port->dev, "HDM decoder registers not implemented\n");
97-
/* unique error code to indicate no HDM decoder capability */
98-
return -ENODEV;
99-
}
100-
101-
return cxl_map_component_regs(&map, regs, BIT(CXL_CM_CAP_CAP_ID_HDM));
102-
}
103-
10484
static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
10585
{
10686
struct cxl_hdm *cxlhdm;
@@ -153,9 +133,9 @@ static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
153133
struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port,
154134
struct cxl_endpoint_dvsec_info *info)
155135
{
136+
struct cxl_register_map *reg_map = &port->reg_map;
156137
struct device *dev = &port->dev;
157138
struct cxl_hdm *cxlhdm;
158-
void __iomem *crb;
159139
int rc;
160140

161141
cxlhdm = devm_kzalloc(dev, sizeof(*cxlhdm), GFP_KERNEL);
@@ -164,19 +144,29 @@ struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port,
164144
cxlhdm->port = port;
165145
dev_set_drvdata(dev, cxlhdm);
166146

167-
crb = ioremap(port->component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE);
168-
if (!crb && info && info->mem_enabled) {
147+
/* Memory devices can configure device HDM using DVSEC range regs. */
148+
if (reg_map->resource == CXL_RESOURCE_NONE) {
149+
if (!info && !info->mem_enabled) {
150+
dev_err(dev, "No component registers mapped\n");
151+
return ERR_PTR(-ENXIO);
152+
}
153+
169154
cxlhdm->decoder_count = info->ranges;
170155
return cxlhdm;
171-
} else if (!crb) {
172-
dev_err(dev, "No component registers mapped\n");
173-
return ERR_PTR(-ENXIO);
174156
}
175157

176-
rc = map_hdm_decoder_regs(port, crb, &cxlhdm->regs);
177-
iounmap(crb);
178-
if (rc)
158+
if (!reg_map->component_map.hdm_decoder.valid) {
159+
dev_dbg(&port->dev, "HDM decoder registers not implemented\n");
160+
/* unique error code to indicate no HDM decoder capability */
161+
return ERR_PTR(-ENODEV);
162+
}
163+
164+
rc = cxl_map_component_regs(reg_map, &cxlhdm->regs,
165+
BIT(CXL_CM_CAP_CAP_ID_HDM));
166+
if (rc) {
167+
dev_err(dev, "Failed to map HDM capability.\n");
179168
return ERR_PTR(rc);
169+
}
180170

181171
parse_hdm_decoder_caps(cxlhdm);
182172
if (cxlhdm->decoder_count == 0) {
@@ -643,10 +633,11 @@ static int cxl_decoder_commit(struct cxl_decoder *cxld)
643633
if (cxld->flags & CXL_DECODER_F_ENABLE)
644634
return 0;
645635

646-
if (port->commit_end + 1 != id) {
636+
if (cxl_num_decoders_committed(port) != id) {
647637
dev_dbg(&port->dev,
648638
"%s: out of order commit, expected decoder%d.%d\n",
649-
dev_name(&cxld->dev), port->id, port->commit_end + 1);
639+
dev_name(&cxld->dev), port->id,
640+
cxl_num_decoders_committed(port));
650641
return -EBUSY;
651642
}
652643

@@ -863,7 +854,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
863854
cxld->target_type = CXL_DECODER_HOSTONLYMEM;
864855
else
865856
cxld->target_type = CXL_DECODER_DEVMEM;
866-
if (cxld->id != port->commit_end + 1) {
857+
if (cxld->id != cxl_num_decoders_committed(port)) {
867858
dev_warn(&port->dev,
868859
"decoder%d.%d: Committed out of order\n",
869860
port->id, cxld->id);

0 commit comments

Comments
 (0)