Skip to content

Commit 3864cb6

Browse files
djbwdavejiang
authored andcommitted
cxl/port: Move dport probe operations to a driver event
In preparation for adding more register setup to the cxl_port_add_dport() path (for RAS register mapping), move the dport creation event to a driver callback. This achieves two goals, it puts driver operations logically where they belong, in a driver, and it obviates the gymnastics of DECLARE_TESTABLE() which just makes a mess of grepping for CXL symbols. In other words, a driver callback is less of an ongoing maintenance burden than this DECLARE_TESTABLE arrangement that does not scale and diminishes the grep-ability of the codebase. cxl_port_add_dport() moves mostly unmodified from drivers/cxl/core/port.c. The only deliberate change is that it now assumes that the device_lock is held on entry and the driver is attached (just like cxl_port_probe()). Reviewed-by: Terry Bowman <terry.bowman@amd.com> Tested-by: Terry Bowman <terry.bowman@amd.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Link: https://patch.msgid.link/20260131000403.2135324-6-dan.j.williams@intel.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
1 parent 86e7567 commit 3864cb6

9 files changed

Lines changed: 98 additions & 126 deletions

File tree

drivers/cxl/core/hdm.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,12 +1219,12 @@ static int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
12191219
}
12201220

12211221
/**
1222-
* __devm_cxl_switch_port_decoders_setup - allocate and setup switch decoders
1222+
* devm_cxl_switch_port_decoders_setup - allocate and setup switch decoders
12231223
* @port: CXL port context
12241224
*
12251225
* Return 0 or -errno on error
12261226
*/
1227-
int __devm_cxl_switch_port_decoders_setup(struct cxl_port *port)
1227+
int devm_cxl_switch_port_decoders_setup(struct cxl_port *port)
12281228
{
12291229
struct cxl_hdm *cxlhdm;
12301230

@@ -1248,7 +1248,7 @@ int __devm_cxl_switch_port_decoders_setup(struct cxl_port *port)
12481248
dev_err(&port->dev, "HDM decoder capability not found\n");
12491249
return -ENXIO;
12501250
}
1251-
EXPORT_SYMBOL_NS_GPL(__devm_cxl_switch_port_decoders_setup, "CXL");
1251+
EXPORT_SYMBOL_NS_GPL(devm_cxl_switch_port_decoders_setup, "CXL");
12521252

12531253
/**
12541254
* devm_cxl_endpoint_decoders_setup - allocate and setup endpoint decoders

drivers/cxl/core/pci.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ static int pci_get_port_num(struct pci_dev *pdev)
4141
}
4242

4343
/**
44-
* __devm_cxl_add_dport_by_dev - allocate a dport by dport device
44+
* devm_cxl_add_dport_by_dev - allocate a dport by dport device
4545
* @port: cxl_port that hosts the dport
4646
* @dport_dev: 'struct device' of the dport
4747
*
4848
* Returns the allocated dport on success or ERR_PTR() of -errno on error
4949
*/
50-
struct cxl_dport *__devm_cxl_add_dport_by_dev(struct cxl_port *port,
51-
struct device *dport_dev)
50+
struct cxl_dport *devm_cxl_add_dport_by_dev(struct cxl_port *port,
51+
struct device *dport_dev)
5252
{
5353
struct cxl_register_map map;
5454
struct pci_dev *pdev;
@@ -69,7 +69,7 @@ struct cxl_dport *__devm_cxl_add_dport_by_dev(struct cxl_port *port,
6969
device_lock_assert(&port->dev);
7070
return devm_cxl_add_dport(port, dport_dev, port_num, map.resource);
7171
}
72-
EXPORT_SYMBOL_NS_GPL(__devm_cxl_add_dport_by_dev, "CXL");
72+
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport_by_dev, "CXL");
7373

7474
static int cxl_dvsec_mem_range_valid(struct cxl_dev_state *cxlds, int id)
7575
{

drivers/cxl/core/port.c

Lines changed: 20 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -778,14 +778,15 @@ static int cxl_setup_comp_regs(struct device *host, struct cxl_register_map *map
778778
return cxl_setup_regs(map);
779779
}
780780

781-
static int cxl_port_setup_regs(struct cxl_port *port,
781+
int cxl_port_setup_regs(struct cxl_port *port,
782782
resource_size_t component_reg_phys)
783783
{
784784
if (dev_is_platform(port->uport_dev))
785785
return 0;
786786
return cxl_setup_comp_regs(&port->dev, &port->reg_map,
787787
component_reg_phys);
788788
}
789+
EXPORT_SYMBOL_NS_GPL(cxl_port_setup_regs, "CXL");
789790

790791
static int cxl_dport_setup_regs(struct device *host, struct cxl_dport *dport,
791792
resource_size_t component_reg_phys)
@@ -1638,6 +1639,13 @@ static int update_decoder_targets(struct device *dev, void *data)
16381639
return 0;
16391640
}
16401641

1642+
void cxl_port_update_decoder_targets(struct cxl_port *port,
1643+
struct cxl_dport *dport)
1644+
{
1645+
device_for_each_child(&port->dev, dport, update_decoder_targets);
1646+
}
1647+
EXPORT_SYMBOL_NS_GPL(cxl_port_update_decoder_targets, "CXL");
1648+
16411649
static bool dport_exists(struct cxl_port *port, struct device *dport_dev)
16421650
{
16431651
struct cxl_dport *dport = cxl_find_dport_by_dev(port, dport_dev);
@@ -1651,15 +1659,10 @@ static bool dport_exists(struct cxl_port *port, struct device *dport_dev)
16511659
return false;
16521660
}
16531661

1654-
/* note this implicitly casts the group back to its @port */
1655-
DEFINE_FREE(cxl_port_release_dr_group, struct cxl_port *,
1656-
if (_T) devres_release_group(&_T->dev, _T))
1657-
1658-
static struct cxl_dport *cxl_port_add_dport(struct cxl_port *port,
1659-
struct device *dport_dev)
1662+
static struct cxl_dport *probe_dport(struct cxl_port *port,
1663+
struct device *dport_dev)
16601664
{
1661-
struct cxl_dport *dport;
1662-
int rc;
1665+
struct cxl_driver *drv;
16631666

16641667
device_lock_assert(&port->dev);
16651668
if (!port->dev.driver)
@@ -1668,43 +1671,12 @@ static struct cxl_dport *cxl_port_add_dport(struct cxl_port *port,
16681671
if (dport_exists(port, dport_dev))
16691672
return ERR_PTR(-EBUSY);
16701673

1671-
/* Temp group for all "first dport" and "per dport" setup actions */
1672-
void *port_dr_group __free(cxl_port_release_dr_group) =
1673-
devres_open_group(&port->dev, port, GFP_KERNEL);
1674-
if (!port_dr_group)
1675-
return ERR_PTR(-ENOMEM);
1676-
1677-
if (port->nr_dports == 0) {
1678-
/*
1679-
* Some host bridges are known to not have component regsisters
1680-
* available until a root port has trained CXL. Perform that
1681-
* setup now.
1682-
*/
1683-
rc = cxl_port_setup_regs(port, port->component_reg_phys);
1684-
if (rc)
1685-
return ERR_PTR(rc);
1686-
1687-
rc = devm_cxl_switch_port_decoders_setup(port);
1688-
if (rc)
1689-
return ERR_PTR(rc);
1690-
}
1691-
1692-
dport = devm_cxl_add_dport_by_dev(port, dport_dev);
1693-
if (IS_ERR(dport))
1694-
return dport;
1695-
1696-
/* This group was only needed for early exit above */
1697-
devres_remove_group(&port->dev, no_free_ptr(port_dr_group));
1698-
1699-
cxl_switch_parse_cdat(dport);
1700-
1701-
/* New dport added, update the decoder targets */
1702-
device_for_each_child(&port->dev, dport, update_decoder_targets);
1703-
1704-
dev_dbg(&port->dev, "dport%d:%s added\n", dport->port_id,
1705-
dev_name(dport_dev));
1674+
drv = container_of(port->dev.driver, struct cxl_driver, drv);
1675+
if (!drv->add_dport)
1676+
return ERR_PTR(-ENXIO);
17061677

1707-
return dport;
1678+
/* see cxl_port_add_dport() */
1679+
return drv->add_dport(port, dport_dev);
17081680
}
17091681

17101682
static struct cxl_dport *devm_cxl_create_port(struct device *ep_dev,
@@ -1751,7 +1723,7 @@ static struct cxl_dport *devm_cxl_create_port(struct device *ep_dev,
17511723
}
17521724

17531725
guard(device)(&port->dev);
1754-
return cxl_port_add_dport(port, dport_dev);
1726+
return probe_dport(port, dport_dev);
17551727
}
17561728

17571729
static int add_port_attach_ep(struct cxl_memdev *cxlmd,
@@ -1783,7 +1755,7 @@ static int add_port_attach_ep(struct cxl_memdev *cxlmd,
17831755
scoped_guard(device, &parent_port->dev) {
17841756
parent_dport = cxl_find_dport_by_dev(parent_port, dparent);
17851757
if (!parent_dport) {
1786-
parent_dport = cxl_port_add_dport(parent_port, dparent);
1758+
parent_dport = probe_dport(parent_port, dparent);
17871759
if (IS_ERR(parent_dport))
17881760
return PTR_ERR(parent_dport);
17891761
}
@@ -1819,7 +1791,7 @@ static struct cxl_dport *find_or_add_dport(struct cxl_port *port,
18191791
device_lock_assert(&port->dev);
18201792
dport = cxl_find_dport_by_dev(port, dport_dev);
18211793
if (!dport) {
1822-
dport = cxl_port_add_dport(port, dport_dev);
1794+
dport = probe_dport(port, dport_dev);
18231795
if (IS_ERR(dport))
18241796
return dport;
18251797

drivers/cxl/cxl.h

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -840,8 +840,11 @@ struct cxl_endpoint_dvsec_info {
840840
};
841841

842842
int devm_cxl_switch_port_decoders_setup(struct cxl_port *port);
843-
int __devm_cxl_switch_port_decoders_setup(struct cxl_port *port);
844843
int devm_cxl_endpoint_decoders_setup(struct cxl_port *port);
844+
void cxl_port_update_decoder_targets(struct cxl_port *port,
845+
struct cxl_dport *dport);
846+
int cxl_port_setup_regs(struct cxl_port *port,
847+
resource_size_t component_reg_phys);
845848

846849
struct cxl_dev_state;
847850
int cxl_dvsec_rr_decode(struct cxl_dev_state *cxlds,
@@ -851,10 +854,18 @@ bool is_cxl_region(struct device *dev);
851854

852855
extern const struct bus_type cxl_bus_type;
853856

857+
/*
858+
* Note, add_dport() is expressly for the cxl_port driver. TODO: investigate a
859+
* type-safe driver model where probe()/remove() take the type of object implied
860+
* by @id and the add_dport() op only defined for the CXL_DEVICE_PORT driver
861+
* template.
862+
*/
854863
struct cxl_driver {
855864
const char *name;
856865
int (*probe)(struct device *dev);
857866
void (*remove)(struct device *dev);
867+
struct cxl_dport *(*add_dport)(struct cxl_port *port,
868+
struct device *dport_dev);
858869
struct device_driver drv;
859870
int id;
860871
};
@@ -939,8 +950,6 @@ void cxl_coordinates_combine(struct access_coordinate *out,
939950
bool cxl_endpoint_decoder_reset_detected(struct cxl_port *port);
940951
struct cxl_dport *devm_cxl_add_dport_by_dev(struct cxl_port *port,
941952
struct device *dport_dev);
942-
struct cxl_dport *__devm_cxl_add_dport_by_dev(struct cxl_port *port,
943-
struct device *dport_dev);
944953

945954
/*
946955
* Unit test builds overrides this to __weak, find the 'strong' version
@@ -952,20 +961,4 @@ struct cxl_dport *__devm_cxl_add_dport_by_dev(struct cxl_port *port,
952961

953962
u16 cxl_gpf_get_dvsec(struct device *dev);
954963

955-
/*
956-
* Declaration for functions that are mocked by cxl_test that are called by
957-
* cxl_core. The respective functions are defined as __foo() and called by
958-
* cxl_core as foo(). The macros below ensures that those functions would
959-
* exist as foo(). See tools/testing/cxl/cxl_core_exports.c and
960-
* tools/testing/cxl/exports.h for setting up the mock functions. The dance
961-
* is done to avoid a circular dependency where cxl_core calls a function that
962-
* ends up being a mock function and goes to * cxl_test where it calls a
963-
* cxl_core function.
964-
*/
965-
#ifndef CXL_TEST_ENABLE
966-
#define DECLARE_TESTABLE(x) __##x
967-
#define devm_cxl_add_dport_by_dev DECLARE_TESTABLE(devm_cxl_add_dport_by_dev)
968-
#define devm_cxl_switch_port_decoders_setup DECLARE_TESTABLE(devm_cxl_switch_port_decoders_setup)
969-
#endif
970-
971964
#endif /* __CXL_H__ */

drivers/cxl/port.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,59 @@ static const struct attribute_group *cxl_port_attribute_groups[] = {
151151
NULL,
152152
};
153153

154+
/* note this implicitly casts the group back to its @port */
155+
DEFINE_FREE(cxl_port_release_dr_group, struct cxl_port *,
156+
if (_T) devres_release_group(&_T->dev, _T))
157+
158+
static struct cxl_dport *cxl_port_add_dport(struct cxl_port *port,
159+
struct device *dport_dev)
160+
{
161+
struct cxl_dport *dport;
162+
int rc;
163+
164+
/* Temp group for all "first dport" and "per dport" setup actions */
165+
void *port_dr_group __free(cxl_port_release_dr_group) =
166+
devres_open_group(&port->dev, port, GFP_KERNEL);
167+
if (!port_dr_group)
168+
return ERR_PTR(-ENOMEM);
169+
170+
if (port->nr_dports == 0) {
171+
/*
172+
* Some host bridges are known to not have component regsisters
173+
* available until a root port has trained CXL. Perform that
174+
* setup now.
175+
*/
176+
rc = cxl_port_setup_regs(port, port->component_reg_phys);
177+
if (rc)
178+
return ERR_PTR(rc);
179+
180+
rc = devm_cxl_switch_port_decoders_setup(port);
181+
if (rc)
182+
return ERR_PTR(rc);
183+
}
184+
185+
dport = devm_cxl_add_dport_by_dev(port, dport_dev);
186+
if (IS_ERR(dport))
187+
return dport;
188+
189+
/* This group was only needed for early exit above */
190+
devres_remove_group(&port->dev, no_free_ptr(port_dr_group));
191+
192+
cxl_switch_parse_cdat(dport);
193+
194+
/* New dport added, update the decoder targets */
195+
cxl_port_update_decoder_targets(port, dport);
196+
197+
dev_dbg(&port->dev, "dport%d:%s added\n", dport->port_id,
198+
dev_name(dport_dev));
199+
200+
return dport;
201+
}
202+
154203
static struct cxl_driver cxl_port_driver = {
155204
.name = "cxl_port",
156205
.probe = cxl_port_probe,
206+
.add_dport = cxl_port_add_dport,
157207
.id = CXL_DEVICE_PORT,
158208
.drv = {
159209
.dev_groups = cxl_port_attribute_groups,

tools/testing/cxl/Kbuild

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ ldflags-y += --wrap=cxl_endpoint_parse_cdat
1010
ldflags-y += --wrap=cxl_dport_init_ras_reporting
1111
ldflags-y += --wrap=devm_cxl_endpoint_decoders_setup
1212
ldflags-y += --wrap=hmat_get_extended_linear_cache_size
13+
ldflags-y += --wrap=devm_cxl_add_dport_by_dev
14+
ldflags-y += --wrap=devm_cxl_switch_port_decoders_setup
1315

1416
DRIVERS := ../../../drivers
1517
CXL_SRC := $(DRIVERS)/cxl

tools/testing/cxl/cxl_core_exports.c

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,6 @@
22
/* Copyright(c) 2022 Intel Corporation. All rights reserved. */
33

44
#include "cxl.h"
5-
#include "exports.h"
65

76
/* Exporting of cxl_core symbols that are only used by cxl_test */
87
EXPORT_SYMBOL_NS_GPL(cxl_num_decoders_committed, "CXL");
9-
10-
cxl_add_dport_by_dev_fn _devm_cxl_add_dport_by_dev =
11-
__devm_cxl_add_dport_by_dev;
12-
EXPORT_SYMBOL_NS_GPL(_devm_cxl_add_dport_by_dev, "CXL");
13-
14-
struct cxl_dport *devm_cxl_add_dport_by_dev(struct cxl_port *port,
15-
struct device *dport_dev)
16-
{
17-
return _devm_cxl_add_dport_by_dev(port, dport_dev);
18-
}
19-
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport_by_dev, "CXL");
20-
21-
cxl_switch_decoders_setup_fn _devm_cxl_switch_port_decoders_setup =
22-
__devm_cxl_switch_port_decoders_setup;
23-
EXPORT_SYMBOL_NS_GPL(_devm_cxl_switch_port_decoders_setup, "CXL");
24-
25-
int devm_cxl_switch_port_decoders_setup(struct cxl_port *port)
26-
{
27-
return _devm_cxl_switch_port_decoders_setup(port);
28-
}
29-
EXPORT_SYMBOL_NS_GPL(devm_cxl_switch_port_decoders_setup, "CXL");

tools/testing/cxl/exports.h

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)