Skip to content

Commit 2be5754

Browse files
committed
Merge branch 'for-6.19/cxl-misc' into cxl-for-next
Misc patches for CXL 6.19 - Remove incorrect page-allocator quirk section in documentation. - Remove unused devm_cxl_port_enumerate_dports() function. - Fix typo in cdat.c code comment. - Replace use of system_wq with system_percpu_wq - Add locked decoder support - Return when generic target updated - Rename region_res_match_cxl_range() to spa_maps_hpa() - Clarify comment in spa_maps_hpa()
2 parents e9a6fb0 + 8d27dd0 commit 2be5754

13 files changed

Lines changed: 55 additions & 176 deletions

File tree

Documentation/driver-api/cxl/allocation/page-allocator.rst

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -41,37 +41,6 @@ To simplify this, the page allocator will prefer :code:`ZONE_MOVABLE` over
4141
will fallback to allocate from :code:`ZONE_NORMAL`.
4242

4343

44-
Zone and Node Quirks
45-
====================
46-
Let's consider a configuration where the local DRAM capacity is largely onlined
47-
into :code:`ZONE_NORMAL`, with no :code:`ZONE_MOVABLE` capacity present. The
48-
CXL capacity has the opposite configuration - all onlined in
49-
:code:`ZONE_MOVABLE`.
50-
51-
Under the default allocation policy, the page allocator will completely skip
52-
:code:`ZONE_MOVABLE` as a valid allocation target. This is because, as of
53-
Linux v6.15, the page allocator does (approximately) the following: ::
54-
55-
for (each zone in local_node):
56-
57-
for (each node in fallback_order):
58-
59-
attempt_allocation(gfp_flags);
60-
61-
Because the local node does not have :code:`ZONE_MOVABLE`, the CXL node is
62-
functionally unreachable for direct allocation. As a result, the only way
63-
for CXL capacity to be used is via `demotion` in the reclaim path.
64-
65-
This configuration also means that if the DRAM ndoe has :code:`ZONE_MOVABLE`
66-
capacity - when that capacity is depleted, the page allocator will actually
67-
prefer CXL :code:`ZONE_MOVABLE` pages over DRAM :code:`ZONE_NORMAL` pages.
68-
69-
We may wish to invert this priority in future Linux versions.
70-
71-
If `demotion` and `swap` are disabled, Linux will begin to cause OOM crashes
72-
when the DRAM nodes are depleted. See the reclaim section for more details.
73-
74-
7544
CGroups and CPUSets
7645
===================
7746
Finally, assuming CXL memory is reachable via the page allocation (i.e. onlined

drivers/acpi/numa/hmat.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -888,12 +888,13 @@ static void hmat_register_target(struct memory_target *target)
888888
* Register generic port perf numbers. The nid may not be
889889
* initialized and is still NUMA_NO_NODE.
890890
*/
891-
mutex_lock(&target_lock);
892-
if (*(u16 *)target->gen_port_device_handle) {
893-
hmat_update_generic_target(target);
894-
target->registered = true;
891+
scoped_guard(mutex, &target_lock) {
892+
if (*(u16 *)target->gen_port_device_handle) {
893+
hmat_update_generic_target(target);
894+
target->registered = true;
895+
return;
896+
}
895897
}
896-
mutex_unlock(&target_lock);
897898

898899
/*
899900
* Skip offline nodes. This can happen when memory

drivers/cxl/core/cdat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,7 @@ static struct xarray *cxl_switch_gather_bandwidth(struct cxl_region *cxlr,
826826
cxl_coordinates_combine(coords, coords, ctx->coord);
827827

828828
/*
829-
* Take the min of the calculated bandwdith and the upstream
829+
* Take the min of the calculated bandwidth and the upstream
830830
* switch SSLBIS bandwidth if there's a parent switch
831831
*/
832832
if (!is_root)
@@ -949,7 +949,7 @@ static struct xarray *cxl_hb_gather_bandwidth(struct xarray *xa)
949949
/**
950950
* cxl_region_update_bandwidth - Update the bandwidth access coordinates of a region
951951
* @cxlr: The region being operated on
952-
* @input_xa: xarray holds cxl_perf_ctx wht calculated bandwidth per ACPI0017 instance
952+
* @input_xa: xarray holds cxl_perf_ctx with calculated bandwidth per ACPI0017 instance
953953
*/
954954
static void cxl_region_update_bandwidth(struct cxl_region *cxlr,
955955
struct xarray *input_xa)

drivers/cxl/core/hdm.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,9 @@ static void cxl_decoder_reset(struct cxl_decoder *cxld)
905905
if ((cxld->flags & CXL_DECODER_F_ENABLE) == 0)
906906
return;
907907

908+
if (test_bit(CXL_DECODER_F_LOCK, &cxld->flags))
909+
return;
910+
908911
if (port->commit_end == id)
909912
cxl_port_commit_reap(cxld);
910913
else

drivers/cxl/core/pci.c

Lines changed: 8 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -71,85 +71,6 @@ struct cxl_dport *__devm_cxl_add_dport_by_dev(struct cxl_port *port,
7171
}
7272
EXPORT_SYMBOL_NS_GPL(__devm_cxl_add_dport_by_dev, "CXL");
7373

74-
struct cxl_walk_context {
75-
struct pci_bus *bus;
76-
struct cxl_port *port;
77-
int type;
78-
int error;
79-
int count;
80-
};
81-
82-
static int match_add_dports(struct pci_dev *pdev, void *data)
83-
{
84-
struct cxl_walk_context *ctx = data;
85-
struct cxl_port *port = ctx->port;
86-
int type = pci_pcie_type(pdev);
87-
struct cxl_register_map map;
88-
struct cxl_dport *dport;
89-
u32 lnkcap, port_num;
90-
int rc;
91-
92-
if (pdev->bus != ctx->bus)
93-
return 0;
94-
if (!pci_is_pcie(pdev))
95-
return 0;
96-
if (type != ctx->type)
97-
return 0;
98-
if (pci_read_config_dword(pdev, pci_pcie_cap(pdev) + PCI_EXP_LNKCAP,
99-
&lnkcap))
100-
return 0;
101-
102-
rc = cxl_find_regblock(pdev, CXL_REGLOC_RBI_COMPONENT, &map);
103-
if (rc)
104-
dev_dbg(&port->dev, "failed to find component registers\n");
105-
106-
port_num = FIELD_GET(PCI_EXP_LNKCAP_PN, lnkcap);
107-
dport = devm_cxl_add_dport(port, &pdev->dev, port_num, map.resource);
108-
if (IS_ERR(dport)) {
109-
ctx->error = PTR_ERR(dport);
110-
return PTR_ERR(dport);
111-
}
112-
ctx->count++;
113-
114-
return 0;
115-
}
116-
117-
/**
118-
* devm_cxl_port_enumerate_dports - enumerate downstream ports of the upstream port
119-
* @port: cxl_port whose ->uport_dev is the upstream of dports to be enumerated
120-
*
121-
* Returns a positive number of dports enumerated or a negative error
122-
* code.
123-
*/
124-
int devm_cxl_port_enumerate_dports(struct cxl_port *port)
125-
{
126-
struct pci_bus *bus = cxl_port_to_pci_bus(port);
127-
struct cxl_walk_context ctx;
128-
int type;
129-
130-
if (!bus)
131-
return -ENXIO;
132-
133-
if (pci_is_root_bus(bus))
134-
type = PCI_EXP_TYPE_ROOT_PORT;
135-
else
136-
type = PCI_EXP_TYPE_DOWNSTREAM;
137-
138-
ctx = (struct cxl_walk_context) {
139-
.port = port,
140-
.bus = bus,
141-
.type = type,
142-
};
143-
pci_walk_bus(bus, match_add_dports, &ctx);
144-
145-
if (ctx.count == 0)
146-
return -ENODEV;
147-
if (ctx.error)
148-
return ctx.error;
149-
return ctx.count;
150-
}
151-
EXPORT_SYMBOL_NS_GPL(devm_cxl_port_enumerate_dports, "CXL");
152-
15374
static int cxl_dvsec_mem_range_valid(struct cxl_dev_state *cxlds, int id)
15475
{
15576
struct pci_dev *pdev = to_pci_dev(cxlds->dev);
@@ -1217,6 +1138,14 @@ int cxl_gpf_port_setup(struct cxl_dport *dport)
12171138
return 0;
12181139
}
12191140

1141+
struct cxl_walk_context {
1142+
struct pci_bus *bus;
1143+
struct cxl_port *port;
1144+
int type;
1145+
int error;
1146+
int count;
1147+
};
1148+
12201149
static int count_dports(struct pci_dev *pdev, void *data)
12211150
{
12221151
struct cxl_walk_context *ctx = data;

drivers/cxl/core/region.c

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ static void cxl_region_decode_reset(struct cxl_region *cxlr, int count)
245245
struct cxl_region_params *p = &cxlr->params;
246246
int i;
247247

248+
if (test_bit(CXL_REGION_F_LOCK, &cxlr->flags))
249+
return;
250+
248251
/*
249252
* Before region teardown attempt to flush, evict any data cached for
250253
* this region, or scream loudly about missing arch / platform support
@@ -419,6 +422,9 @@ static ssize_t commit_store(struct device *dev, struct device_attribute *attr,
419422
return len;
420423
}
421424

425+
if (test_bit(CXL_REGION_F_LOCK, &cxlr->flags))
426+
return -EPERM;
427+
422428
rc = queue_reset(cxlr);
423429
if (rc)
424430
return rc;
@@ -838,16 +844,16 @@ static int match_free_decoder(struct device *dev, const void *data)
838844
return 1;
839845
}
840846

841-
static bool region_res_match_cxl_range(const struct cxl_region_params *p,
842-
const struct range *range)
847+
static bool spa_maps_hpa(const struct cxl_region_params *p,
848+
const struct range *range)
843849
{
844850
if (!p->res)
845851
return false;
846852

847853
/*
848-
* If an extended linear cache region then the CXL range is assumed
849-
* to be fronted by the DRAM range in current known implementation.
850-
* This assumption will be made until a variant implementation exists.
854+
* The extended linear cache region is constructed by a 1:1 ratio
855+
* where the SPA maps equal amounts of DRAM and CXL HPA capacity with
856+
* CXL decoders at the high end of the SPA range.
851857
*/
852858
return p->res->start + p->cache_size == range->start &&
853859
p->res->end == range->end;
@@ -865,7 +871,7 @@ static int match_auto_decoder(struct device *dev, const void *data)
865871
cxld = to_cxl_decoder(dev);
866872
r = &cxld->hpa_range;
867873

868-
if (region_res_match_cxl_range(p, r))
874+
if (spa_maps_hpa(p, r))
869875
return 1;
870876

871877
return 0;
@@ -1059,6 +1065,16 @@ static int cxl_rr_assign_decoder(struct cxl_port *port, struct cxl_region *cxlr,
10591065
return 0;
10601066
}
10611067

1068+
static void cxl_region_set_lock(struct cxl_region *cxlr,
1069+
struct cxl_decoder *cxld)
1070+
{
1071+
if (!test_bit(CXL_DECODER_F_LOCK, &cxld->flags))
1072+
return;
1073+
1074+
set_bit(CXL_REGION_F_LOCK, &cxlr->flags);
1075+
clear_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
1076+
}
1077+
10621078
/**
10631079
* cxl_port_attach_region() - track a region's interest in a port by endpoint
10641080
* @port: port to add a new region reference 'struct cxl_region_ref'
@@ -1170,6 +1186,8 @@ static int cxl_port_attach_region(struct cxl_port *port,
11701186
}
11711187
}
11721188

1189+
cxl_region_set_lock(cxlr, cxld);
1190+
11731191
rc = cxl_rr_ep_add(cxl_rr, cxled);
11741192
if (rc) {
11751193
dev_dbg(&cxlr->dev,
@@ -1465,7 +1483,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
14651483
if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) {
14661484
if (cxld->interleave_ways != iw ||
14671485
(iw > 1 && cxld->interleave_granularity != ig) ||
1468-
!region_res_match_cxl_range(p, &cxld->hpa_range) ||
1486+
!spa_maps_hpa(p, &cxld->hpa_range) ||
14691487
((cxld->flags & CXL_DECODER_F_ENABLE) == 0)) {
14701488
dev_err(&cxlr->dev,
14711489
"%s:%s %s expected iw: %d ig: %d %pr\n",
@@ -2439,6 +2457,7 @@ static struct cxl_region *cxl_region_alloc(struct cxl_root_decoder *cxlrd, int i
24392457
dev->bus = &cxl_bus_type;
24402458
dev->type = &cxl_region_type;
24412459
cxlr->id = id;
2460+
cxl_region_set_lock(cxlr, &cxlrd->cxlsd.cxld);
24422461

24432462
return cxlr;
24442463
}
@@ -3398,7 +3417,7 @@ static int match_region_by_range(struct device *dev, const void *data)
33983417
p = &cxlr->params;
33993418

34003419
guard(rwsem_read)(&cxl_rwsem.region);
3401-
return region_res_match_cxl_range(p, r);
3420+
return spa_maps_hpa(p, r);
34023421
}
34033422

34043423
static int cxl_extended_linear_cache_resize(struct cxl_region *cxlr,

drivers/cxl/cxl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,14 @@ enum cxl_partition_mode {
517517
*/
518518
#define CXL_REGION_F_NEEDS_RESET 1
519519

520+
/*
521+
* Indicate whether this region is locked due to 1 or more decoders that have
522+
* been locked. The approach of all or nothing is taken with regard to the
523+
* locked attribute. CXL_REGION_F_NEEDS_RESET should not be set if this flag is
524+
* set.
525+
*/
526+
#define CXL_REGION_F_LOCK 2
527+
520528
/**
521529
* struct cxl_region - CXL region
522530
* @dev: This region's device

drivers/cxl/cxlpci.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ static inline bool cxl_pci_flit_256(struct pci_dev *pdev)
127127
return lnksta2 & PCI_EXP_LNKSTA2_FLIT;
128128
}
129129

130-
int devm_cxl_port_enumerate_dports(struct cxl_port *port);
131130
struct cxl_dev_state;
132131
void read_cdat_data(struct cxl_port *port);
133132
void cxl_cor_error_detected(struct pci_dev *pdev);

drivers/cxl/pci.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ static irqreturn_t cxl_pci_mbox_irq(int irq, void *id)
136136
if (opcode == CXL_MBOX_OP_SANITIZE) {
137137
mutex_lock(&cxl_mbox->mbox_mutex);
138138
if (mds->security.sanitize_node)
139-
mod_delayed_work(system_wq, &mds->security.poll_dwork, 0);
139+
mod_delayed_work(system_percpu_wq, &mds->security.poll_dwork, 0);
140140
mutex_unlock(&cxl_mbox->mbox_mutex);
141141
} else {
142142
/* short-circuit the wait in __cxl_pci_mbox_send_cmd() */

tools/testing/cxl/Kbuild

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ ldflags-y += --wrap=is_acpi_device_node
44
ldflags-y += --wrap=acpi_evaluate_integer
55
ldflags-y += --wrap=acpi_pci_find_root
66
ldflags-y += --wrap=nvdimm_bus_register
7-
ldflags-y += --wrap=devm_cxl_port_enumerate_dports
87
ldflags-y += --wrap=cxl_await_media_ready
98
ldflags-y += --wrap=devm_cxl_add_rch_dport
109
ldflags-y += --wrap=cxl_rcd_component_reg_phys

0 commit comments

Comments
 (0)