mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
Merge branch 'for-7.0/cxl-aer-prep' into cxl-for-next
Fixup and refactor downstream port enumeration to prepare for CXL port protocol error handling. Main motivation is to move endpoint component register mapping to a port object. cxl/port: Unify endpoint and switch port lookup cxl/port: Move endpoint component register management to cxl_port cxl/port: Map Port RAS registers cxl/port: Move dport RAS setup to dport add time cxl/port: Move dport probe operations to a driver event cxl/port: Move decoder setup before dport creation cxl/port: Cleanup dport removal with a devres group cxl/port: Reduce number of @dport variables in cxl_port_add_dport() cxl/port: Cleanup handling of the nr_dports 0 -> 1 transition
This commit is contained in:
commit
0da3050bdd
|
|
@ -144,6 +144,14 @@ int cxl_pci_get_bandwidth(struct pci_dev *pdev, struct access_coordinate *c);
|
|||
int cxl_port_get_switch_dport_bandwidth(struct cxl_port *port,
|
||||
struct access_coordinate *c);
|
||||
|
||||
static inline struct device *dport_to_host(struct cxl_dport *dport)
|
||||
{
|
||||
struct cxl_port *port = dport->port;
|
||||
|
||||
if (is_cxl_root(port))
|
||||
return port->uport_dev;
|
||||
return &port->dev;
|
||||
}
|
||||
#ifdef CONFIG_CXL_RAS
|
||||
int cxl_ras_init(void);
|
||||
void cxl_ras_exit(void);
|
||||
|
|
@ -152,6 +160,7 @@ void cxl_handle_cor_ras(struct device *dev, void __iomem *ras_base);
|
|||
void cxl_dport_map_rch_aer(struct cxl_dport *dport);
|
||||
void cxl_disable_rch_root_ints(struct cxl_dport *dport);
|
||||
void cxl_handle_rdport_errors(struct cxl_dev_state *cxlds);
|
||||
void devm_cxl_dport_ras_setup(struct cxl_dport *dport);
|
||||
#else
|
||||
static inline int cxl_ras_init(void)
|
||||
{
|
||||
|
|
@ -166,6 +175,7 @@ static inline void cxl_handle_cor_ras(struct device *dev, void __iomem *ras_base
|
|||
static inline void cxl_dport_map_rch_aer(struct cxl_dport *dport) { }
|
||||
static inline void cxl_disable_rch_root_ints(struct cxl_dport *dport) { }
|
||||
static inline void cxl_handle_rdport_errors(struct cxl_dev_state *cxlds) { }
|
||||
static inline void devm_cxl_dport_ras_setup(struct cxl_dport *dport) { }
|
||||
#endif /* CONFIG_CXL_RAS */
|
||||
|
||||
int cxl_gpf_port_setup(struct cxl_dport *dport);
|
||||
|
|
|
|||
|
|
@ -1218,12 +1218,12 @@ static int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
|
|||
}
|
||||
|
||||
/**
|
||||
* __devm_cxl_switch_port_decoders_setup - allocate and setup switch decoders
|
||||
* devm_cxl_switch_port_decoders_setup - allocate and setup switch decoders
|
||||
* @port: CXL port context
|
||||
*
|
||||
* Return 0 or -errno on error
|
||||
*/
|
||||
int __devm_cxl_switch_port_decoders_setup(struct cxl_port *port)
|
||||
int devm_cxl_switch_port_decoders_setup(struct cxl_port *port)
|
||||
{
|
||||
struct cxl_hdm *cxlhdm;
|
||||
|
||||
|
|
@ -1247,7 +1247,7 @@ int __devm_cxl_switch_port_decoders_setup(struct cxl_port *port)
|
|||
dev_err(&port->dev, "HDM decoder capability not found\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(__devm_cxl_switch_port_decoders_setup, "CXL");
|
||||
EXPORT_SYMBOL_NS_GPL(devm_cxl_switch_port_decoders_setup, "CXL");
|
||||
|
||||
/**
|
||||
* devm_cxl_endpoint_decoders_setup - allocate and setup endpoint decoders
|
||||
|
|
|
|||
|
|
@ -41,14 +41,14 @@ static int pci_get_port_num(struct pci_dev *pdev)
|
|||
}
|
||||
|
||||
/**
|
||||
* __devm_cxl_add_dport_by_dev - allocate a dport by dport device
|
||||
* devm_cxl_add_dport_by_dev - allocate a dport by dport device
|
||||
* @port: cxl_port that hosts the dport
|
||||
* @dport_dev: 'struct device' of the dport
|
||||
*
|
||||
* Returns the allocated dport on success or ERR_PTR() of -errno on error
|
||||
*/
|
||||
struct cxl_dport *__devm_cxl_add_dport_by_dev(struct cxl_port *port,
|
||||
struct device *dport_dev)
|
||||
struct cxl_dport *devm_cxl_add_dport_by_dev(struct cxl_port *port,
|
||||
struct device *dport_dev)
|
||||
{
|
||||
struct cxl_register_map map;
|
||||
struct pci_dev *pdev;
|
||||
|
|
@ -69,7 +69,7 @@ struct cxl_dport *__devm_cxl_add_dport_by_dev(struct cxl_port *port,
|
|||
device_lock_assert(&port->dev);
|
||||
return devm_cxl_add_dport(port, dport_dev, port_num, map.resource);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(__devm_cxl_add_dport_by_dev, "CXL");
|
||||
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport_by_dev, "CXL");
|
||||
|
||||
static int cxl_dvsec_mem_range_valid(struct cxl_dev_state *cxlds, int id)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -778,7 +778,7 @@ static int cxl_setup_comp_regs(struct device *host, struct cxl_register_map *map
|
|||
return cxl_setup_regs(map);
|
||||
}
|
||||
|
||||
static int cxl_port_setup_regs(struct cxl_port *port,
|
||||
int cxl_port_setup_regs(struct cxl_port *port,
|
||||
resource_size_t component_reg_phys)
|
||||
{
|
||||
if (dev_is_platform(port->uport_dev))
|
||||
|
|
@ -786,6 +786,7 @@ static int cxl_port_setup_regs(struct cxl_port *port,
|
|||
return cxl_setup_comp_regs(&port->dev, &port->reg_map,
|
||||
component_reg_phys);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(cxl_port_setup_regs, "CXL");
|
||||
|
||||
static int cxl_dport_setup_regs(struct device *host, struct cxl_dport *dport,
|
||||
resource_size_t component_reg_phys)
|
||||
|
|
@ -1068,11 +1069,15 @@ static int add_dport(struct cxl_port *port, struct cxl_dport *dport)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Arrange for dport_dev to be valid through remove_dport() */
|
||||
struct device *dev __free(put_device) = get_device(dport->dport_dev);
|
||||
|
||||
rc = xa_insert(&port->dports, (unsigned long)dport->dport_dev, dport,
|
||||
GFP_KERNEL);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
retain_and_null_ptr(dev);
|
||||
port->nr_dports++;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1101,6 +1106,7 @@ static void cxl_dport_remove(void *data)
|
|||
struct cxl_dport *dport = data;
|
||||
struct cxl_port *port = dport->port;
|
||||
|
||||
port->nr_dports--;
|
||||
xa_erase(&port->dports, (unsigned long) dport->dport_dev);
|
||||
put_device(dport->dport_dev);
|
||||
}
|
||||
|
|
@ -1115,6 +1121,48 @@ static void cxl_dport_unlink(void *data)
|
|||
sysfs_remove_link(&port->dev.kobj, link_name);
|
||||
}
|
||||
|
||||
static void free_dport(void *dport)
|
||||
{
|
||||
kfree(dport);
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon return either a group is established with one action (free_dport()), or
|
||||
* no group established and @dport is freed.
|
||||
*/
|
||||
static void *cxl_dport_open_dr_group_or_free(struct cxl_dport *dport)
|
||||
{
|
||||
int rc;
|
||||
struct device *host = dport_to_host(dport);
|
||||
void *group = devres_open_group(host, dport, GFP_KERNEL);
|
||||
|
||||
if (!group) {
|
||||
kfree(dport);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = devm_add_action_or_reset(host, free_dport, dport);
|
||||
if (rc) {
|
||||
devres_release_group(host, group);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
static void cxl_dport_close_dr_group(struct cxl_dport *dport, void *group)
|
||||
{
|
||||
devres_close_group(dport_to_host(dport), group);
|
||||
}
|
||||
|
||||
static void del_dport(struct cxl_dport *dport)
|
||||
{
|
||||
devres_release_group(dport_to_host(dport), dport);
|
||||
}
|
||||
|
||||
/* The dport group id is the dport */
|
||||
DEFINE_FREE(cxl_dport_release_dr_group, void *, if (_T) del_dport(_T))
|
||||
|
||||
static struct cxl_dport *
|
||||
__devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
|
||||
int port_id, resource_size_t component_reg_phys,
|
||||
|
|
@ -1140,14 +1188,20 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
|
|||
CXL_TARGET_STRLEN)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
dport = devm_kzalloc(host, sizeof(*dport), GFP_KERNEL);
|
||||
dport = kzalloc(sizeof(*dport), GFP_KERNEL);
|
||||
if (!dport)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* Just enough init to manage the devres group */
|
||||
dport->dport_dev = dport_dev;
|
||||
dport->port_id = port_id;
|
||||
dport->port = port;
|
||||
|
||||
void *dport_dr_group __free(cxl_dport_release_dr_group) =
|
||||
cxl_dport_open_dr_group_or_free(dport);
|
||||
if (!dport_dr_group)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (rcrb == CXL_RESOURCE_NONE) {
|
||||
rc = cxl_dport_setup_regs(&port->dev, dport,
|
||||
component_reg_phys);
|
||||
|
|
@ -1183,21 +1237,6 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
|
|||
if (rc)
|
||||
return ERR_PTR(rc);
|
||||
|
||||
/*
|
||||
* Setup port register if this is the first dport showed up. Having
|
||||
* a dport also means that there is at least 1 active link.
|
||||
*/
|
||||
if (port->nr_dports == 1 &&
|
||||
port->component_reg_phys != CXL_RESOURCE_NONE) {
|
||||
rc = cxl_port_setup_regs(port, port->component_reg_phys);
|
||||
if (rc) {
|
||||
xa_erase(&port->dports, (unsigned long)dport->dport_dev);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
port->component_reg_phys = CXL_RESOURCE_NONE;
|
||||
}
|
||||
|
||||
get_device(dport_dev);
|
||||
rc = devm_add_action_or_reset(host, cxl_dport_remove, dport);
|
||||
if (rc)
|
||||
return ERR_PTR(rc);
|
||||
|
|
@ -1215,6 +1254,12 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
|
|||
|
||||
cxl_debugfs_create_dport_dir(dport);
|
||||
|
||||
if (!dport->rch)
|
||||
devm_cxl_dport_ras_setup(dport);
|
||||
|
||||
/* keep the group, and mark the end of devm actions */
|
||||
cxl_dport_close_dr_group(dport, no_free_ptr(dport_dr_group));
|
||||
|
||||
return dport;
|
||||
}
|
||||
|
||||
|
|
@ -1441,15 +1486,6 @@ static void delete_switch_port(struct cxl_port *port)
|
|||
devm_release_action(port->dev.parent, unregister_port, port);
|
||||
}
|
||||
|
||||
static void del_dport(struct cxl_dport *dport)
|
||||
{
|
||||
struct cxl_port *port = dport->port;
|
||||
|
||||
devm_release_action(&port->dev, cxl_dport_unlink, dport);
|
||||
devm_release_action(&port->dev, cxl_dport_remove, dport);
|
||||
devm_kfree(&port->dev, dport);
|
||||
}
|
||||
|
||||
static void del_dports(struct cxl_port *port)
|
||||
{
|
||||
struct cxl_dport *dport;
|
||||
|
|
@ -1556,10 +1592,20 @@ static int match_port_by_uport(struct device *dev, const void *data)
|
|||
return 0;
|
||||
|
||||
port = to_cxl_port(dev);
|
||||
/* Endpoint ports are hosted by memdevs */
|
||||
if (is_cxl_memdev(port->uport_dev))
|
||||
return uport_dev == port->uport_dev->parent;
|
||||
return uport_dev == port->uport_dev;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* find_cxl_port_by_uport - Find a CXL port device companion
|
||||
* @uport_dev: Device that acts as a switch or endpoint in the CXL hierarchy
|
||||
*
|
||||
* In the case of endpoint ports recall that port->uport_dev points to a 'struct
|
||||
* cxl_memdev' device. So, the @uport_dev argument is the parent device of the
|
||||
* 'struct cxl_memdev' in that case.
|
||||
*
|
||||
* Function takes a device reference on the port device. Caller should do a
|
||||
* put_device() when done.
|
||||
*/
|
||||
|
|
@ -1599,47 +1645,44 @@ static int update_decoder_targets(struct device *dev, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_FREE(del_cxl_dport, struct cxl_dport *, if (!IS_ERR_OR_NULL(_T)) del_dport(_T))
|
||||
static struct cxl_dport *cxl_port_add_dport(struct cxl_port *port,
|
||||
struct device *dport_dev)
|
||||
void cxl_port_update_decoder_targets(struct cxl_port *port,
|
||||
struct cxl_dport *dport)
|
||||
{
|
||||
struct cxl_dport *dport;
|
||||
int rc;
|
||||
device_for_each_child(&port->dev, dport, update_decoder_targets);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(cxl_port_update_decoder_targets, "CXL");
|
||||
|
||||
static bool dport_exists(struct cxl_port *port, struct device *dport_dev)
|
||||
{
|
||||
struct cxl_dport *dport = cxl_find_dport_by_dev(port, dport_dev);
|
||||
|
||||
if (dport) {
|
||||
dev_dbg(&port->dev, "dport%d:%s already exists\n",
|
||||
dport->port_id, dev_name(dport_dev));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct cxl_dport *probe_dport(struct cxl_port *port,
|
||||
struct device *dport_dev)
|
||||
{
|
||||
struct cxl_driver *drv;
|
||||
|
||||
device_lock_assert(&port->dev);
|
||||
if (!port->dev.driver)
|
||||
return ERR_PTR(-ENXIO);
|
||||
|
||||
dport = cxl_find_dport_by_dev(port, dport_dev);
|
||||
if (dport) {
|
||||
dev_dbg(&port->dev, "dport%d:%s already exists\n",
|
||||
dport->port_id, dev_name(dport_dev));
|
||||
if (dport_exists(port, dport_dev))
|
||||
return ERR_PTR(-EBUSY);
|
||||
}
|
||||
|
||||
struct cxl_dport *new_dport __free(del_cxl_dport) =
|
||||
devm_cxl_add_dport_by_dev(port, dport_dev);
|
||||
if (IS_ERR(new_dport))
|
||||
return new_dport;
|
||||
drv = container_of(port->dev.driver, struct cxl_driver, drv);
|
||||
if (!drv->add_dport)
|
||||
return ERR_PTR(-ENXIO);
|
||||
|
||||
cxl_switch_parse_cdat(new_dport);
|
||||
|
||||
if (ida_is_empty(&port->decoder_ida)) {
|
||||
rc = devm_cxl_switch_port_decoders_setup(port);
|
||||
if (rc)
|
||||
return ERR_PTR(rc);
|
||||
dev_dbg(&port->dev, "first dport%d:%s added with decoders\n",
|
||||
new_dport->port_id, dev_name(dport_dev));
|
||||
return no_free_ptr(new_dport);
|
||||
}
|
||||
|
||||
/* New dport added, update the decoder targets */
|
||||
device_for_each_child(&port->dev, new_dport, update_decoder_targets);
|
||||
|
||||
dev_dbg(&port->dev, "dport%d:%s added\n", new_dport->port_id,
|
||||
dev_name(dport_dev));
|
||||
|
||||
return no_free_ptr(new_dport);
|
||||
/* see cxl_port_add_dport() */
|
||||
return drv->add_dport(port, dport_dev);
|
||||
}
|
||||
|
||||
static struct cxl_dport *devm_cxl_create_port(struct device *ep_dev,
|
||||
|
|
@ -1686,7 +1729,7 @@ static struct cxl_dport *devm_cxl_create_port(struct device *ep_dev,
|
|||
}
|
||||
|
||||
guard(device)(&port->dev);
|
||||
return cxl_port_add_dport(port, dport_dev);
|
||||
return probe_dport(port, dport_dev);
|
||||
}
|
||||
|
||||
static int add_port_attach_ep(struct cxl_memdev *cxlmd,
|
||||
|
|
@ -1718,7 +1761,7 @@ static int add_port_attach_ep(struct cxl_memdev *cxlmd,
|
|||
scoped_guard(device, &parent_port->dev) {
|
||||
parent_dport = cxl_find_dport_by_dev(parent_port, dparent);
|
||||
if (!parent_dport) {
|
||||
parent_dport = cxl_port_add_dport(parent_port, dparent);
|
||||
parent_dport = probe_dport(parent_port, dparent);
|
||||
if (IS_ERR(parent_dport))
|
||||
return PTR_ERR(parent_dport);
|
||||
}
|
||||
|
|
@ -1754,7 +1797,7 @@ static struct cxl_dport *find_or_add_dport(struct cxl_port *port,
|
|||
device_lock_assert(&port->dev);
|
||||
dport = cxl_find_dport_by_dev(port, dport_dev);
|
||||
if (!dport) {
|
||||
dport = cxl_port_add_dport(port, dport_dev);
|
||||
dport = probe_dport(port, dport_dev);
|
||||
if (IS_ERR(dport))
|
||||
return dport;
|
||||
|
||||
|
|
|
|||
|
|
@ -139,26 +139,48 @@ static void cxl_dport_map_ras(struct cxl_dport *dport)
|
|||
}
|
||||
|
||||
/**
|
||||
* cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport
|
||||
* devm_cxl_dport_ras_setup - Setup CXL RAS report on this dport
|
||||
* @dport: the cxl_dport that needs to be initialized
|
||||
* @host: host device for devm operations
|
||||
*/
|
||||
void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
|
||||
void devm_cxl_dport_ras_setup(struct cxl_dport *dport)
|
||||
{
|
||||
dport->reg_map.host = host;
|
||||
dport->reg_map.host = dport_to_host(dport);
|
||||
cxl_dport_map_ras(dport);
|
||||
|
||||
if (dport->rch) {
|
||||
struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport->dport_dev);
|
||||
|
||||
if (!host_bridge->native_aer)
|
||||
return;
|
||||
|
||||
cxl_dport_map_rch_aer(dport);
|
||||
cxl_disable_rch_root_ints(dport);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
|
||||
|
||||
void devm_cxl_dport_rch_ras_setup(struct cxl_dport *dport)
|
||||
{
|
||||
struct pci_host_bridge *host_bridge;
|
||||
|
||||
if (!dev_is_pci(dport->dport_dev))
|
||||
return;
|
||||
|
||||
devm_cxl_dport_ras_setup(dport);
|
||||
|
||||
host_bridge = to_pci_host_bridge(dport->dport_dev);
|
||||
if (!host_bridge->native_aer)
|
||||
return;
|
||||
|
||||
cxl_dport_map_rch_aer(dport);
|
||||
cxl_disable_rch_root_ints(dport);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(devm_cxl_dport_rch_ras_setup, "CXL");
|
||||
|
||||
void devm_cxl_port_ras_setup(struct cxl_port *port)
|
||||
{
|
||||
struct cxl_register_map *map = &port->reg_map;
|
||||
|
||||
if (!map->component_map.ras.valid) {
|
||||
dev_dbg(&port->dev, "RAS registers not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
map->host = &port->dev;
|
||||
if (cxl_map_component_regs(map, &port->regs,
|
||||
BIT(CXL_CM_CAP_CAP_ID_RAS)))
|
||||
dev_dbg(&port->dev, "Failed to map RAS capability\n");
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(devm_cxl_port_ras_setup, "CXL");
|
||||
|
||||
void cxl_handle_cor_ras(struct device *dev, void __iomem *ras_base)
|
||||
{
|
||||
|
|
@ -233,6 +255,7 @@ bool cxl_handle_ras(struct device *dev, void __iomem *ras_base)
|
|||
void cxl_cor_error_detected(struct pci_dev *pdev)
|
||||
{
|
||||
struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
|
||||
struct cxl_memdev *cxlmd = cxlds->cxlmd;
|
||||
struct device *dev = &cxlds->cxlmd->dev;
|
||||
|
||||
scoped_guard(device, dev) {
|
||||
|
|
@ -246,7 +269,7 @@ void cxl_cor_error_detected(struct pci_dev *pdev)
|
|||
if (cxlds->rcd)
|
||||
cxl_handle_rdport_errors(cxlds);
|
||||
|
||||
cxl_handle_cor_ras(&cxlds->cxlmd->dev, cxlds->regs.ras);
|
||||
cxl_handle_cor_ras(&cxlds->cxlmd->dev, cxlmd->endpoint->regs.ras);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(cxl_cor_error_detected, "CXL");
|
||||
|
|
@ -275,10 +298,9 @@ pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
|
|||
* chance the situation is recoverable dump the status of the RAS
|
||||
* capability registers and bounce the active state of the memdev.
|
||||
*/
|
||||
ue = cxl_handle_ras(&cxlds->cxlmd->dev, cxlds->regs.ras);
|
||||
ue = cxl_handle_ras(&cxlds->cxlmd->dev, cxlmd->endpoint->regs.ras);
|
||||
}
|
||||
|
||||
|
||||
switch (state) {
|
||||
case pci_channel_io_normal:
|
||||
if (ue) {
|
||||
|
|
|
|||
|
|
@ -607,6 +607,7 @@ struct cxl_dax_region {
|
|||
* @parent_dport: dport that points to this port in the parent
|
||||
* @decoder_ida: allocator for decoder ids
|
||||
* @reg_map: component and ras register mapping parameters
|
||||
* @regs: mapped component registers
|
||||
* @nr_dports: number of entries in @dports
|
||||
* @hdm_end: track last allocated HDM decoder instance for allocation ordering
|
||||
* @commit_end: cursor to track highest committed decoder for commit ordering
|
||||
|
|
@ -628,6 +629,7 @@ struct cxl_port {
|
|||
struct cxl_dport *parent_dport;
|
||||
struct ida decoder_ida;
|
||||
struct cxl_register_map reg_map;
|
||||
struct cxl_component_regs regs;
|
||||
int nr_dports;
|
||||
int hdm_end;
|
||||
int commit_end;
|
||||
|
|
@ -842,8 +844,11 @@ struct cxl_endpoint_dvsec_info {
|
|||
};
|
||||
|
||||
int devm_cxl_switch_port_decoders_setup(struct cxl_port *port);
|
||||
int __devm_cxl_switch_port_decoders_setup(struct cxl_port *port);
|
||||
int devm_cxl_endpoint_decoders_setup(struct cxl_port *port);
|
||||
void cxl_port_update_decoder_targets(struct cxl_port *port,
|
||||
struct cxl_dport *dport);
|
||||
int cxl_port_setup_regs(struct cxl_port *port,
|
||||
resource_size_t component_reg_phys);
|
||||
|
||||
struct cxl_dev_state;
|
||||
int cxl_dvsec_rr_decode(struct cxl_dev_state *cxlds,
|
||||
|
|
@ -853,10 +858,18 @@ bool is_cxl_region(struct device *dev);
|
|||
|
||||
extern const struct bus_type cxl_bus_type;
|
||||
|
||||
/*
|
||||
* Note, add_dport() is expressly for the cxl_port driver. TODO: investigate a
|
||||
* type-safe driver model where probe()/remove() take the type of object implied
|
||||
* by @id and the add_dport() op only defined for the CXL_DEVICE_PORT driver
|
||||
* template.
|
||||
*/
|
||||
struct cxl_driver {
|
||||
const char *name;
|
||||
int (*probe)(struct device *dev);
|
||||
void (*remove)(struct device *dev);
|
||||
struct cxl_dport *(*add_dport)(struct cxl_port *port,
|
||||
struct device *dport_dev);
|
||||
struct device_driver drv;
|
||||
int id;
|
||||
};
|
||||
|
|
@ -941,8 +954,6 @@ void cxl_coordinates_combine(struct access_coordinate *out,
|
|||
bool cxl_endpoint_decoder_reset_detected(struct cxl_port *port);
|
||||
struct cxl_dport *devm_cxl_add_dport_by_dev(struct cxl_port *port,
|
||||
struct device *dport_dev);
|
||||
struct cxl_dport *__devm_cxl_add_dport_by_dev(struct cxl_port *port,
|
||||
struct device *dport_dev);
|
||||
|
||||
/*
|
||||
* Unit test builds overrides this to __weak, find the 'strong' version
|
||||
|
|
@ -954,20 +965,4 @@ struct cxl_dport *__devm_cxl_add_dport_by_dev(struct cxl_port *port,
|
|||
|
||||
u16 cxl_gpf_get_dvsec(struct device *dev);
|
||||
|
||||
/*
|
||||
* Declaration for functions that are mocked by cxl_test that are called by
|
||||
* cxl_core. The respective functions are defined as __foo() and called by
|
||||
* cxl_core as foo(). The macros below ensures that those functions would
|
||||
* exist as foo(). See tools/testing/cxl/cxl_core_exports.c and
|
||||
* tools/testing/cxl/exports.h for setting up the mock functions. The dance
|
||||
* is done to avoid a circular dependency where cxl_core calls a function that
|
||||
* ends up being a mock function and goes to * cxl_test where it calls a
|
||||
* cxl_core function.
|
||||
*/
|
||||
#ifndef CXL_TEST_ENABLE
|
||||
#define DECLARE_TESTABLE(x) __##x
|
||||
#define devm_cxl_add_dport_by_dev DECLARE_TESTABLE(devm_cxl_add_dport_by_dev)
|
||||
#define devm_cxl_switch_port_decoders_setup DECLARE_TESTABLE(devm_cxl_switch_port_decoders_setup)
|
||||
#endif
|
||||
|
||||
#endif /* __CXL_H__ */
|
||||
|
|
|
|||
|
|
@ -423,7 +423,7 @@ struct cxl_dpa_partition {
|
|||
* @dev: The device associated with this CXL state
|
||||
* @cxlmd: The device representing the CXL.mem capabilities of @dev
|
||||
* @reg_map: component and ras register mapping parameters
|
||||
* @regs: Parsed register blocks
|
||||
* @regs: Class device "Device" registers
|
||||
* @cxl_dvsec: Offset to the PCIe device DVSEC
|
||||
* @rcd: operating in RCD mode (CXL 3.0 9.11.8 CXL Devices Attached to an RCH)
|
||||
* @media_ready: Indicate whether the device media is usable
|
||||
|
|
@ -439,7 +439,7 @@ struct cxl_dev_state {
|
|||
struct device *dev;
|
||||
struct cxl_memdev *cxlmd;
|
||||
struct cxl_register_map reg_map;
|
||||
struct cxl_regs regs;
|
||||
struct cxl_device_regs regs;
|
||||
int cxl_dvsec;
|
||||
bool rcd;
|
||||
bool media_ready;
|
||||
|
|
|
|||
|
|
@ -81,7 +81,8 @@ void read_cdat_data(struct cxl_port *port);
|
|||
void cxl_cor_error_detected(struct pci_dev *pdev);
|
||||
pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
|
||||
pci_channel_state_t state);
|
||||
void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host);
|
||||
void devm_cxl_dport_rch_ras_setup(struct cxl_dport *dport);
|
||||
void devm_cxl_port_ras_setup(struct cxl_port *port);
|
||||
#else
|
||||
static inline void cxl_cor_error_detected(struct pci_dev *pdev) { }
|
||||
|
||||
|
|
@ -91,8 +92,13 @@ static inline pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
|
|||
return PCI_ERS_RESULT_NONE;
|
||||
}
|
||||
|
||||
static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport,
|
||||
struct device *host) { }
|
||||
static inline void devm_cxl_dport_rch_ras_setup(struct cxl_dport *dport)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void devm_cxl_port_ras_setup(struct cxl_port *port)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CXL_PCI_H__ */
|
||||
|
|
|
|||
|
|
@ -128,8 +128,6 @@ static int cxl_mem_probe(struct device *dev)
|
|||
else
|
||||
endpoint_parent = &parent_port->dev;
|
||||
|
||||
cxl_dport_init_ras_reporting(dport, dev);
|
||||
|
||||
scoped_guard(device, endpoint_parent) {
|
||||
if (!endpoint_parent->driver) {
|
||||
dev_err(dev, "CXL port topology %s not enabled\n",
|
||||
|
|
|
|||
|
|
@ -535,52 +535,6 @@ static int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
|
|||
return cxl_setup_regs(map);
|
||||
}
|
||||
|
||||
static int cxl_pci_ras_unmask(struct pci_dev *pdev)
|
||||
{
|
||||
struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
|
||||
void __iomem *addr;
|
||||
u32 orig_val, val, mask;
|
||||
u16 cap;
|
||||
int rc;
|
||||
|
||||
if (!cxlds->regs.ras) {
|
||||
dev_dbg(&pdev->dev, "No RAS registers.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* BIOS has PCIe AER error control */
|
||||
if (!pcie_aer_is_native(pdev))
|
||||
return 0;
|
||||
|
||||
rc = pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &cap);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (cap & PCI_EXP_DEVCTL_URRE) {
|
||||
addr = cxlds->regs.ras + CXL_RAS_UNCORRECTABLE_MASK_OFFSET;
|
||||
orig_val = readl(addr);
|
||||
|
||||
mask = CXL_RAS_UNCORRECTABLE_MASK_MASK |
|
||||
CXL_RAS_UNCORRECTABLE_MASK_F256B_MASK;
|
||||
val = orig_val & ~mask;
|
||||
writel(val, addr);
|
||||
dev_dbg(&pdev->dev,
|
||||
"Uncorrectable RAS Errors Mask: %#x -> %#x\n",
|
||||
orig_val, val);
|
||||
}
|
||||
|
||||
if (cap & PCI_EXP_DEVCTL_CERE) {
|
||||
addr = cxlds->regs.ras + CXL_RAS_CORRECTABLE_MASK_OFFSET;
|
||||
orig_val = readl(addr);
|
||||
val = orig_val & ~CXL_RAS_CORRECTABLE_MASK_MASK;
|
||||
writel(val, addr);
|
||||
dev_dbg(&pdev->dev, "Correctable RAS Errors Mask: %#x -> %#x\n",
|
||||
orig_val, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_event_buf(void *buf)
|
||||
{
|
||||
kvfree(buf);
|
||||
|
|
@ -935,7 +889,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = cxl_map_device_regs(&map, &cxlds->regs.device_regs);
|
||||
rc = cxl_map_device_regs(&map, &cxlds->regs);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -950,11 +904,6 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
else if (!cxlds->reg_map.component_map.ras.valid)
|
||||
dev_dbg(&pdev->dev, "RAS registers not found\n");
|
||||
|
||||
rc = cxl_map_component_regs(&cxlds->reg_map, &cxlds->regs.component,
|
||||
BIT(CXL_CM_CAP_CAP_ID_RAS));
|
||||
if (rc)
|
||||
dev_dbg(&pdev->dev, "Failed to map RAS capability.\n");
|
||||
|
||||
rc = cxl_pci_type3_init_mailbox(cxlds);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
|
@ -1045,9 +994,6 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (cxl_pci_ras_unmask(pdev))
|
||||
dev_dbg(&pdev->dev, "No RAS reporting unmasked\n");
|
||||
|
||||
pci_save_state(pdev);
|
||||
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright(c) 2022 Intel Corporation. All rights reserved. */
|
||||
#include <linux/aer.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
@ -68,9 +69,59 @@ static int cxl_switch_port_probe(struct cxl_port *port)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cxl_ras_unmask(struct cxl_port *port)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
void __iomem *addr;
|
||||
u32 orig_val, val, mask;
|
||||
u16 cap;
|
||||
int rc;
|
||||
|
||||
if (!dev_is_pci(port->uport_dev))
|
||||
return 0;
|
||||
pdev = to_pci_dev(port->uport_dev);
|
||||
|
||||
if (!port->regs.ras) {
|
||||
pci_dbg(pdev, "No RAS registers.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* BIOS has PCIe AER error control */
|
||||
if (!pcie_aer_is_native(pdev))
|
||||
return 0;
|
||||
|
||||
rc = pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &cap);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (cap & PCI_EXP_DEVCTL_URRE) {
|
||||
addr = port->regs.ras + CXL_RAS_UNCORRECTABLE_MASK_OFFSET;
|
||||
orig_val = readl(addr);
|
||||
|
||||
mask = CXL_RAS_UNCORRECTABLE_MASK_MASK |
|
||||
CXL_RAS_UNCORRECTABLE_MASK_F256B_MASK;
|
||||
val = orig_val & ~mask;
|
||||
writel(val, addr);
|
||||
pci_dbg(pdev, "Uncorrectable RAS Errors Mask: %#x -> %#x\n",
|
||||
orig_val, val);
|
||||
}
|
||||
|
||||
if (cap & PCI_EXP_DEVCTL_CERE) {
|
||||
addr = port->regs.ras + CXL_RAS_CORRECTABLE_MASK_OFFSET;
|
||||
orig_val = readl(addr);
|
||||
val = orig_val & ~CXL_RAS_CORRECTABLE_MASK_MASK;
|
||||
writel(val, addr);
|
||||
pci_dbg(pdev, "Correctable RAS Errors Mask: %#x -> %#x\n",
|
||||
orig_val, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxl_endpoint_port_probe(struct cxl_port *port)
|
||||
{
|
||||
struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
|
||||
struct cxl_dport *dport = port->parent_dport;
|
||||
int rc;
|
||||
|
||||
/* Cache the data early to ensure is_visible() works */
|
||||
|
|
@ -86,6 +137,21 @@ static int cxl_endpoint_port_probe(struct cxl_port *port)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
/*
|
||||
* With VH (CXL Virtual Host) topology the cxl_port::add_dport() method
|
||||
* handles RAS setup for downstream ports. With RCH (CXL Restricted CXL
|
||||
* Host) topologies the downstream port is enumerated early by platform
|
||||
* firmware, but the RCRB (root complex register block) is not mapped
|
||||
* until after the cxl_pci driver attaches to the RCIeP (root complex
|
||||
* integrated endpoint).
|
||||
*/
|
||||
if (dport->rch)
|
||||
devm_cxl_dport_rch_ras_setup(dport);
|
||||
|
||||
devm_cxl_port_ras_setup(port);
|
||||
if (cxl_ras_unmask(port))
|
||||
dev_dbg(&port->dev, "failed to unmask RAS interrupts\n");
|
||||
|
||||
/*
|
||||
* Now that all endpoint decoders are successfully enumerated, try to
|
||||
* assemble regions from committed decoders
|
||||
|
|
@ -151,9 +217,65 @@ static const struct attribute_group *cxl_port_attribute_groups[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
/* note this implicitly casts the group back to its @port */
|
||||
DEFINE_FREE(cxl_port_release_dr_group, struct cxl_port *,
|
||||
if (_T) devres_release_group(&_T->dev, _T))
|
||||
|
||||
static struct cxl_dport *cxl_port_add_dport(struct cxl_port *port,
|
||||
struct device *dport_dev)
|
||||
{
|
||||
struct cxl_dport *dport;
|
||||
int rc;
|
||||
|
||||
/* Temp group for all "first dport" and "per dport" setup actions */
|
||||
void *port_dr_group __free(cxl_port_release_dr_group) =
|
||||
devres_open_group(&port->dev, port, GFP_KERNEL);
|
||||
if (!port_dr_group)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (port->nr_dports == 0) {
|
||||
/*
|
||||
* Some host bridges are known to not have component regsisters
|
||||
* available until a root port has trained CXL. Perform that
|
||||
* setup now.
|
||||
*/
|
||||
rc = cxl_port_setup_regs(port, port->component_reg_phys);
|
||||
if (rc)
|
||||
return ERR_PTR(rc);
|
||||
|
||||
rc = devm_cxl_switch_port_decoders_setup(port);
|
||||
if (rc)
|
||||
return ERR_PTR(rc);
|
||||
|
||||
/*
|
||||
* RAS setup is optional, either driver operation can continue
|
||||
* on failure, or the device does not implement RAS registers.
|
||||
*/
|
||||
devm_cxl_port_ras_setup(port);
|
||||
}
|
||||
|
||||
dport = devm_cxl_add_dport_by_dev(port, dport_dev);
|
||||
if (IS_ERR(dport))
|
||||
return dport;
|
||||
|
||||
/* This group was only needed for early exit above */
|
||||
devres_remove_group(&port->dev, no_free_ptr(port_dr_group));
|
||||
|
||||
cxl_switch_parse_cdat(dport);
|
||||
|
||||
/* New dport added, update the decoder targets */
|
||||
cxl_port_update_decoder_targets(port, dport);
|
||||
|
||||
dev_dbg(&port->dev, "dport%d:%s added\n", dport->port_id,
|
||||
dev_name(dport_dev));
|
||||
|
||||
return dport;
|
||||
}
|
||||
|
||||
static struct cxl_driver cxl_port_driver = {
|
||||
.name = "cxl_port",
|
||||
.probe = cxl_port_probe,
|
||||
.add_dport = cxl_port_add_dport,
|
||||
.id = CXL_DEVICE_PORT,
|
||||
.drv = {
|
||||
.probe_type = PROBE_FORCE_SYNCHRONOUS,
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@ ldflags-y += --wrap=nvdimm_bus_register
|
|||
ldflags-y += --wrap=cxl_await_media_ready
|
||||
ldflags-y += --wrap=devm_cxl_add_rch_dport
|
||||
ldflags-y += --wrap=cxl_endpoint_parse_cdat
|
||||
ldflags-y += --wrap=cxl_dport_init_ras_reporting
|
||||
ldflags-y += --wrap=devm_cxl_endpoint_decoders_setup
|
||||
ldflags-y += --wrap=hmat_get_extended_linear_cache_size
|
||||
ldflags-y += --wrap=devm_cxl_add_dport_by_dev
|
||||
ldflags-y += --wrap=devm_cxl_switch_port_decoders_setup
|
||||
|
||||
DRIVERS := ../../../drivers
|
||||
CXL_SRC := $(DRIVERS)/cxl
|
||||
|
|
|
|||
|
|
@ -2,28 +2,6 @@
|
|||
/* Copyright(c) 2022 Intel Corporation. All rights reserved. */
|
||||
|
||||
#include "cxl.h"
|
||||
#include "exports.h"
|
||||
|
||||
/* Exporting of cxl_core symbols that are only used by cxl_test */
|
||||
EXPORT_SYMBOL_NS_GPL(cxl_num_decoders_committed, "CXL");
|
||||
|
||||
cxl_add_dport_by_dev_fn _devm_cxl_add_dport_by_dev =
|
||||
__devm_cxl_add_dport_by_dev;
|
||||
EXPORT_SYMBOL_NS_GPL(_devm_cxl_add_dport_by_dev, "CXL");
|
||||
|
||||
struct cxl_dport *devm_cxl_add_dport_by_dev(struct cxl_port *port,
|
||||
struct device *dport_dev)
|
||||
{
|
||||
return _devm_cxl_add_dport_by_dev(port, dport_dev);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport_by_dev, "CXL");
|
||||
|
||||
cxl_switch_decoders_setup_fn _devm_cxl_switch_port_decoders_setup =
|
||||
__devm_cxl_switch_port_decoders_setup;
|
||||
EXPORT_SYMBOL_NS_GPL(_devm_cxl_switch_port_decoders_setup, "CXL");
|
||||
|
||||
int devm_cxl_switch_port_decoders_setup(struct cxl_port *port)
|
||||
{
|
||||
return _devm_cxl_switch_port_decoders_setup(port);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(devm_cxl_switch_port_decoders_setup, "CXL");
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2025 Intel Corporation */
|
||||
#ifndef __MOCK_CXL_EXPORTS_H_
|
||||
#define __MOCK_CXL_EXPORTS_H_
|
||||
|
||||
typedef struct cxl_dport *(*cxl_add_dport_by_dev_fn)(struct cxl_port *port,
|
||||
struct device *dport_dev);
|
||||
extern cxl_add_dport_by_dev_fn _devm_cxl_add_dport_by_dev;
|
||||
|
||||
typedef int(*cxl_switch_decoders_setup_fn)(struct cxl_port *port);
|
||||
extern cxl_switch_decoders_setup_fn _devm_cxl_switch_port_decoders_setup;
|
||||
|
||||
#endif
|
||||
|
|
@ -10,21 +10,12 @@
|
|||
#include <cxlmem.h>
|
||||
#include <cxlpci.h>
|
||||
#include "mock.h"
|
||||
#include "../exports.h"
|
||||
|
||||
static LIST_HEAD(mock);
|
||||
|
||||
static struct cxl_dport *
|
||||
redirect_devm_cxl_add_dport_by_dev(struct cxl_port *port,
|
||||
struct device *dport_dev);
|
||||
static int redirect_devm_cxl_switch_port_decoders_setup(struct cxl_port *port);
|
||||
|
||||
void register_cxl_mock_ops(struct cxl_mock_ops *ops)
|
||||
{
|
||||
list_add_rcu(&ops->list, &mock);
|
||||
_devm_cxl_add_dport_by_dev = redirect_devm_cxl_add_dport_by_dev;
|
||||
_devm_cxl_switch_port_decoders_setup =
|
||||
redirect_devm_cxl_switch_port_decoders_setup;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(register_cxl_mock_ops);
|
||||
|
||||
|
|
@ -32,9 +23,6 @@ DEFINE_STATIC_SRCU(cxl_mock_srcu);
|
|||
|
||||
void unregister_cxl_mock_ops(struct cxl_mock_ops *ops)
|
||||
{
|
||||
_devm_cxl_switch_port_decoders_setup =
|
||||
__devm_cxl_switch_port_decoders_setup;
|
||||
_devm_cxl_add_dport_by_dev = __devm_cxl_add_dport_by_dev;
|
||||
list_del_rcu(&ops->list);
|
||||
synchronize_srcu(&cxl_mock_srcu);
|
||||
}
|
||||
|
|
@ -163,7 +151,7 @@ __wrap_nvdimm_bus_register(struct device *dev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register);
|
||||
|
||||
int redirect_devm_cxl_switch_port_decoders_setup(struct cxl_port *port)
|
||||
int __wrap_devm_cxl_switch_port_decoders_setup(struct cxl_port *port)
|
||||
{
|
||||
int rc, index;
|
||||
struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
|
||||
|
|
@ -171,11 +159,12 @@ int redirect_devm_cxl_switch_port_decoders_setup(struct cxl_port *port)
|
|||
if (ops && ops->is_mock_port(port->uport_dev))
|
||||
rc = ops->devm_cxl_switch_port_decoders_setup(port);
|
||||
else
|
||||
rc = __devm_cxl_switch_port_decoders_setup(port);
|
||||
rc = devm_cxl_switch_port_decoders_setup(port);
|
||||
put_cxl_mock_ops(index);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_switch_port_decoders_setup, "CXL");
|
||||
|
||||
int __wrap_devm_cxl_endpoint_decoders_setup(struct cxl_port *port)
|
||||
{
|
||||
|
|
@ -245,20 +234,8 @@ void __wrap_cxl_endpoint_parse_cdat(struct cxl_port *port)
|
|||
}
|
||||
EXPORT_SYMBOL_NS_GPL(__wrap_cxl_endpoint_parse_cdat, "CXL");
|
||||
|
||||
void __wrap_cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
|
||||
{
|
||||
int index;
|
||||
struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
|
||||
|
||||
if (!ops || !ops->is_mock_port(dport->dport_dev))
|
||||
cxl_dport_init_ras_reporting(dport, host);
|
||||
|
||||
put_cxl_mock_ops(index);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dport_init_ras_reporting, "CXL");
|
||||
|
||||
struct cxl_dport *redirect_devm_cxl_add_dport_by_dev(struct cxl_port *port,
|
||||
struct device *dport_dev)
|
||||
struct cxl_dport *__wrap_devm_cxl_add_dport_by_dev(struct cxl_port *port,
|
||||
struct device *dport_dev)
|
||||
{
|
||||
int index;
|
||||
struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
|
||||
|
|
@ -267,11 +244,12 @@ struct cxl_dport *redirect_devm_cxl_add_dport_by_dev(struct cxl_port *port,
|
|||
if (ops && ops->is_mock_port(port->uport_dev))
|
||||
dport = ops->devm_cxl_add_dport_by_dev(port, dport_dev);
|
||||
else
|
||||
dport = __devm_cxl_add_dport_by_dev(port, dport_dev);
|
||||
dport = devm_cxl_add_dport_by_dev(port, dport_dev);
|
||||
put_cxl_mock_ops(index);
|
||||
|
||||
return dport;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_dport_by_dev, "CXL");
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("cxl_test: emulation module");
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user