Skip to content

Commit 02e7567

Browse files
MingLi-4davejiang
authored andcommitted
cxl/port: Avoid missing port component registers setup
port->nr_dports is used to represent how many dports added to the cxl port, it will increase in add_dport() when a new dport is being added to the cxl port, but it will not be reduced when a dport is removed from the cxl port. Currently, when the first dport is added to a cxl port, it will trigger component registers setup on the cxl port, the implementation is using port->nr_dports to confirm if the dport is the first dport. A corner case here is that adding dport could fail after port->nr_dports updating and before checking port->nr_dports for component registers setup. If the failure happens during the first dport attaching, it will cause that CXL subsystem has not chance to execute component registers setup for the cxl port. the failure flow like below: port->nr_dports = 0 dport 1 adding to the port: add_dport() # port->nr_dports: 1 failed on devm_add_action_or_reset() or sysfs_create_link() return error # port->nr_dports: 1 dport 2 adding to the port: add_dport() # port->nr_dports: 2 no failure skip component registers setup because of port->nr_dports is 2 The solution here is that moving component registers setup closer to add_dport(), so if add_dport() is executed correctly for the first dport, component registers setup on the port will be executed immediately after that. Fixes: f6ee249 ("cxl: Move port register setup to when first dport appear") Signed-off-by: Li Ming <ming.li@zohomail.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Davidlohr Bueso <dave@stgolabs.net> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
1 parent 3a86608 commit 02e7567

File tree

1 file changed

+14
-12
lines changed

1 file changed

+14
-12
lines changed

drivers/cxl/core/port.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,20 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
11821182
if (rc)
11831183
return ERR_PTR(rc);
11841184

1185+
/*
1186+
* Setup port register if this is the first dport showed up. Having
1187+
* a dport also means that there is at least 1 active link.
1188+
*/
1189+
if (port->nr_dports == 1 &&
1190+
port->component_reg_phys != CXL_RESOURCE_NONE) {
1191+
rc = cxl_port_setup_regs(port, port->component_reg_phys);
1192+
if (rc) {
1193+
xa_erase(&port->dports, (unsigned long)dport->dport_dev);
1194+
return ERR_PTR(rc);
1195+
}
1196+
port->component_reg_phys = CXL_RESOURCE_NONE;
1197+
}
1198+
11851199
get_device(dport_dev);
11861200
rc = devm_add_action_or_reset(host, cxl_dport_remove, dport);
11871201
if (rc)
@@ -1200,18 +1214,6 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
12001214

12011215
cxl_debugfs_create_dport_dir(dport);
12021216

1203-
/*
1204-
* Setup port register if this is the first dport showed up. Having
1205-
* a dport also means that there is at least 1 active link.
1206-
*/
1207-
if (port->nr_dports == 1 &&
1208-
port->component_reg_phys != CXL_RESOURCE_NONE) {
1209-
rc = cxl_port_setup_regs(port, port->component_reg_phys);
1210-
if (rc)
1211-
return ERR_PTR(rc);
1212-
port->component_reg_phys = CXL_RESOURCE_NONE;
1213-
}
1214-
12151217
return dport;
12161218
}
12171219

0 commit comments

Comments
 (0)