Skip to content

Commit 586b5df

Browse files
committed
Merge tag 'cxl-fixes-6.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl
Pull cxl fixes from Dave Jiang: - Fix index of Clear Event Record handles in cxl_clear_event_record() - Fix use before init of map->reg_type in cxl_decode_regblock() - Fix initialization of mbox_cmd.size_out in cxl_mem_get_records_log() - Fix CXL path access_coordinate computation: - Remove unneded check of iter in loop - Fix of retrieving of access_coordinate in PCI topology walk - Fix of incorrect region access_coordinate data calculation - Consolidate of access_coordinates attached to downstream port context - Add check to validate access_coordinate validity to prevent incorrect data being exposed via sysfs * tag 'cxl-fixes-6.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl: cxl: Add checks to access_coordinate calculation to fail missing data cxl: Consolidate dport access_coordinate ->hb_coord and ->sw_coord into ->coord cxl: Fix incorrect region perf data calculation cxl: Fix retrieving of access_coordinates in PCIe path cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates() cxl/core: Fix initialization of mbox_cmd.size_out in get event cxl/core/regs: Fix usage of map->reg_type in cxl_decode_regblock() before assigned cxl/mem: Fix for the index of Clear Event Record Handle
2 parents 52e5070 + 7bcf809 commit 586b5df

File tree

8 files changed

+164
-145
lines changed

8 files changed

+164
-145
lines changed

drivers/cxl/acpi.c

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -525,22 +525,11 @@ static int get_genport_coordinates(struct device *dev, struct cxl_dport *dport)
525525
{
526526
struct acpi_device *hb = to_cxl_host_bridge(NULL, dev);
527527
u32 uid;
528-
int rc;
529528

530529
if (kstrtou32(acpi_device_uid(hb), 0, &uid))
531530
return -EINVAL;
532531

533-
rc = acpi_get_genport_coordinates(uid, dport->hb_coord);
534-
if (rc < 0)
535-
return rc;
536-
537-
/* Adjust back to picoseconds from nanoseconds */
538-
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
539-
dport->hb_coord[i].read_latency *= 1000;
540-
dport->hb_coord[i].write_latency *= 1000;
541-
}
542-
543-
return 0;
532+
return acpi_get_genport_coordinates(uid, dport->coord);
544533
}
545534

546535
static int add_host_bridge_dport(struct device *match, void *arg)

drivers/cxl/core/cdat.c

Lines changed: 79 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,42 @@
1414
struct dsmas_entry {
1515
struct range dpa_range;
1616
u8 handle;
17-
struct access_coordinate coord;
17+
struct access_coordinate coord[ACCESS_COORDINATE_MAX];
1818

1919
int entries;
2020
int qos_class;
2121
};
2222

23+
static u32 cdat_normalize(u16 entry, u64 base, u8 type)
24+
{
25+
u32 value;
26+
27+
/*
28+
* Check for invalid and overflow values
29+
*/
30+
if (entry == 0xffff || !entry)
31+
return 0;
32+
else if (base > (UINT_MAX / (entry)))
33+
return 0;
34+
35+
/*
36+
* CDAT fields follow the format of HMAT fields. See table 5 Device
37+
* Scoped Latency and Bandwidth Information Structure in Coherent Device
38+
* Attribute Table (CDAT) Specification v1.01.
39+
*/
40+
value = entry * base;
41+
switch (type) {
42+
case ACPI_HMAT_ACCESS_LATENCY:
43+
case ACPI_HMAT_READ_LATENCY:
44+
case ACPI_HMAT_WRITE_LATENCY:
45+
value = DIV_ROUND_UP(value, 1000);
46+
break;
47+
default:
48+
break;
49+
}
50+
return value;
51+
}
52+
2353
static int cdat_dsmas_handler(union acpi_subtable_headers *header, void *arg,
2454
const unsigned long end)
2555
{
@@ -58,8 +88,8 @@ static int cdat_dsmas_handler(union acpi_subtable_headers *header, void *arg,
5888
return 0;
5989
}
6090

61-
static void cxl_access_coordinate_set(struct access_coordinate *coord,
62-
int access, unsigned int val)
91+
static void __cxl_access_coordinate_set(struct access_coordinate *coord,
92+
int access, unsigned int val)
6393
{
6494
switch (access) {
6595
case ACPI_HMAT_ACCESS_LATENCY:
@@ -85,6 +115,13 @@ static void cxl_access_coordinate_set(struct access_coordinate *coord,
85115
}
86116
}
87117

118+
static void cxl_access_coordinate_set(struct access_coordinate *coord,
119+
int access, unsigned int val)
120+
{
121+
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++)
122+
__cxl_access_coordinate_set(&coord[i], access, val);
123+
}
124+
88125
static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg,
89126
const unsigned long end)
90127
{
@@ -97,7 +134,6 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg,
97134
__le16 le_val;
98135
u64 val;
99136
u16 len;
100-
int rc;
101137

102138
len = le16_to_cpu((__force __le16)hdr->length);
103139
if (len != size || (unsigned long)hdr + len > end) {
@@ -124,12 +160,10 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg,
124160

125161
le_base = (__force __le64)dslbis->entry_base_unit;
126162
le_val = (__force __le16)dslbis->entry[0];
127-
rc = check_mul_overflow(le64_to_cpu(le_base),
128-
le16_to_cpu(le_val), &val);
129-
if (rc)
130-
pr_warn("DSLBIS value overflowed.\n");
163+
val = cdat_normalize(le16_to_cpu(le_val), le64_to_cpu(le_base),
164+
dslbis->data_type);
131165

132-
cxl_access_coordinate_set(&dent->coord, dslbis->data_type, val);
166+
cxl_access_coordinate_set(dent->coord, dslbis->data_type, val);
133167

134168
return 0;
135169
}
@@ -163,25 +197,18 @@ static int cxl_cdat_endpoint_process(struct cxl_port *port,
163197
static int cxl_port_perf_data_calculate(struct cxl_port *port,
164198
struct xarray *dsmas_xa)
165199
{
166-
struct access_coordinate ep_c;
167-
struct access_coordinate coord[ACCESS_COORDINATE_MAX];
200+
struct access_coordinate ep_c[ACCESS_COORDINATE_MAX];
168201
struct dsmas_entry *dent;
169202
int valid_entries = 0;
170203
unsigned long index;
171204
int rc;
172205

173-
rc = cxl_endpoint_get_perf_coordinates(port, &ep_c);
206+
rc = cxl_endpoint_get_perf_coordinates(port, ep_c);
174207
if (rc) {
175208
dev_dbg(&port->dev, "Failed to retrieve ep perf coordinates.\n");
176209
return rc;
177210
}
178211

179-
rc = cxl_hb_get_perf_coordinates(port, coord);
180-
if (rc) {
181-
dev_dbg(&port->dev, "Failed to retrieve hb perf coordinates.\n");
182-
return rc;
183-
}
184-
185212
struct cxl_root *cxl_root __free(put_cxl_root) = find_cxl_root(port);
186213

187214
if (!cxl_root)
@@ -193,18 +220,10 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port,
193220
xa_for_each(dsmas_xa, index, dent) {
194221
int qos_class;
195222

196-
cxl_coordinates_combine(&dent->coord, &dent->coord, &ep_c);
197-
/*
198-
* Keeping the host bridge coordinates separate from the dsmas
199-
* coordinates in order to allow calculation of access class
200-
* 0 and 1 for region later.
201-
*/
202-
cxl_coordinates_combine(&coord[ACCESS_COORDINATE_CPU],
203-
&coord[ACCESS_COORDINATE_CPU],
204-
&dent->coord);
223+
cxl_coordinates_combine(dent->coord, dent->coord, ep_c);
205224
dent->entries = 1;
206225
rc = cxl_root->ops->qos_class(cxl_root,
207-
&coord[ACCESS_COORDINATE_CPU],
226+
&dent->coord[ACCESS_COORDINATE_CPU],
208227
1, &qos_class);
209228
if (rc != 1)
210229
continue;
@@ -222,14 +241,17 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port,
222241
static void update_perf_entry(struct device *dev, struct dsmas_entry *dent,
223242
struct cxl_dpa_perf *dpa_perf)
224243
{
244+
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++)
245+
dpa_perf->coord[i] = dent->coord[i];
225246
dpa_perf->dpa_range = dent->dpa_range;
226-
dpa_perf->coord = dent->coord;
227247
dpa_perf->qos_class = dent->qos_class;
228248
dev_dbg(dev,
229249
"DSMAS: dpa: %#llx qos: %d read_bw: %d write_bw %d read_lat: %d write_lat: %d\n",
230250
dent->dpa_range.start, dpa_perf->qos_class,
231-
dent->coord.read_bandwidth, dent->coord.write_bandwidth,
232-
dent->coord.read_latency, dent->coord.write_latency);
251+
dent->coord[ACCESS_COORDINATE_CPU].read_bandwidth,
252+
dent->coord[ACCESS_COORDINATE_CPU].write_bandwidth,
253+
dent->coord[ACCESS_COORDINATE_CPU].read_latency,
254+
dent->coord[ACCESS_COORDINATE_CPU].write_latency);
233255
}
234256

235257
static void cxl_memdev_set_qos_class(struct cxl_dev_state *cxlds,
@@ -461,17 +483,16 @@ static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg,
461483

462484
le_base = (__force __le64)tbl->sslbis_header.entry_base_unit;
463485
le_val = (__force __le16)tbl->entries[i].latency_or_bandwidth;
464-
465-
if (check_mul_overflow(le64_to_cpu(le_base),
466-
le16_to_cpu(le_val), &val))
467-
dev_warn(dev, "SSLBIS value overflowed!\n");
486+
val = cdat_normalize(le16_to_cpu(le_val), le64_to_cpu(le_base),
487+
sslbis->data_type);
468488

469489
xa_for_each(&port->dports, index, dport) {
470490
if (dsp_id == ACPI_CDAT_SSLBIS_ANY_PORT ||
471-
dsp_id == dport->port_id)
472-
cxl_access_coordinate_set(&dport->sw_coord,
491+
dsp_id == dport->port_id) {
492+
cxl_access_coordinate_set(dport->coord,
473493
sslbis->data_type,
474494
val);
495+
}
475496
}
476497
}
477498

@@ -493,6 +514,21 @@ void cxl_switch_parse_cdat(struct cxl_port *port)
493514
}
494515
EXPORT_SYMBOL_NS_GPL(cxl_switch_parse_cdat, CXL);
495516

517+
static void __cxl_coordinates_combine(struct access_coordinate *out,
518+
struct access_coordinate *c1,
519+
struct access_coordinate *c2)
520+
{
521+
if (c1->write_bandwidth && c2->write_bandwidth)
522+
out->write_bandwidth = min(c1->write_bandwidth,
523+
c2->write_bandwidth);
524+
out->write_latency = c1->write_latency + c2->write_latency;
525+
526+
if (c1->read_bandwidth && c2->read_bandwidth)
527+
out->read_bandwidth = min(c1->read_bandwidth,
528+
c2->read_bandwidth);
529+
out->read_latency = c1->read_latency + c2->read_latency;
530+
}
531+
496532
/**
497533
* cxl_coordinates_combine - Combine the two input coordinates
498534
*
@@ -504,15 +540,8 @@ void cxl_coordinates_combine(struct access_coordinate *out,
504540
struct access_coordinate *c1,
505541
struct access_coordinate *c2)
506542
{
507-
if (c1->write_bandwidth && c2->write_bandwidth)
508-
out->write_bandwidth = min(c1->write_bandwidth,
509-
c2->write_bandwidth);
510-
out->write_latency = c1->write_latency + c2->write_latency;
511-
512-
if (c1->read_bandwidth && c2->read_bandwidth)
513-
out->read_bandwidth = min(c1->read_bandwidth,
514-
c2->read_bandwidth);
515-
out->read_latency = c1->read_latency + c2->read_latency;
543+
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++)
544+
__cxl_coordinates_combine(&out[i], &c1[i], &c2[i]);
516545
}
517546

518547
MODULE_IMPORT_NS(CXL);
@@ -521,17 +550,13 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr,
521550
struct cxl_endpoint_decoder *cxled)
522551
{
523552
struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
524-
struct cxl_port *port = cxlmd->endpoint;
525553
struct cxl_dev_state *cxlds = cxlmd->cxlds;
526554
struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
527-
struct access_coordinate hb_coord[ACCESS_COORDINATE_MAX];
528-
struct access_coordinate coord;
529555
struct range dpa = {
530556
.start = cxled->dpa_res->start,
531557
.end = cxled->dpa_res->end,
532558
};
533559
struct cxl_dpa_perf *perf;
534-
int rc;
535560

536561
switch (cxlr->mode) {
537562
case CXL_DECODER_RAM:
@@ -549,35 +574,16 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr,
549574
if (!range_contains(&perf->dpa_range, &dpa))
550575
return;
551576

552-
rc = cxl_hb_get_perf_coordinates(port, hb_coord);
553-
if (rc) {
554-
dev_dbg(&port->dev, "Failed to retrieve hb perf coordinates.\n");
555-
return;
556-
}
557-
558577
for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
559-
/* Pickup the host bridge coords */
560-
cxl_coordinates_combine(&coord, &hb_coord[i], &perf->coord);
561-
562578
/* Get total bandwidth and the worst latency for the cxl region */
563579
cxlr->coord[i].read_latency = max_t(unsigned int,
564580
cxlr->coord[i].read_latency,
565-
coord.read_latency);
581+
perf->coord[i].read_latency);
566582
cxlr->coord[i].write_latency = max_t(unsigned int,
567583
cxlr->coord[i].write_latency,
568-
coord.write_latency);
569-
cxlr->coord[i].read_bandwidth += coord.read_bandwidth;
570-
cxlr->coord[i].write_bandwidth += coord.write_bandwidth;
571-
572-
/*
573-
* Convert latency to nanosec from picosec to be consistent
574-
* with the resulting latency coordinates computed by the
575-
* HMAT_REPORTING code.
576-
*/
577-
cxlr->coord[i].read_latency =
578-
DIV_ROUND_UP(cxlr->coord[i].read_latency, 1000);
579-
cxlr->coord[i].write_latency =
580-
DIV_ROUND_UP(cxlr->coord[i].write_latency, 1000);
584+
perf->coord[i].write_latency);
585+
cxlr->coord[i].read_bandwidth += perf->coord[i].read_bandwidth;
586+
cxlr->coord[i].write_bandwidth += perf->coord[i].write_bandwidth;
581587
}
582588
}
583589

drivers/cxl/core/mbox.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,7 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds,
915915

916916
payload->handles[i++] = gen->hdr.handle;
917917
dev_dbg(mds->cxlds.dev, "Event log '%d': Clearing %u\n", log,
918-
le16_to_cpu(payload->handles[i]));
918+
le16_to_cpu(payload->handles[i - 1]));
919919

920920
if (i == max_handles) {
921921
payload->nr_recs = i;
@@ -958,13 +958,14 @@ static void cxl_mem_get_records_log(struct cxl_memdev_state *mds,
958958
.payload_in = &log_type,
959959
.size_in = sizeof(log_type),
960960
.payload_out = payload,
961-
.size_out = mds->payload_size,
962961
.min_out = struct_size(payload, records, 0),
963962
};
964963

965964
do {
966965
int rc, i;
967966

967+
mbox_cmd.size_out = mds->payload_size;
968+
968969
rc = cxl_internal_send_cmd(mds, &mbox_cmd);
969970
if (rc) {
970971
dev_err_ratelimited(dev,

0 commit comments

Comments
 (0)