|
4 | 4 | #include <linux/genalloc.h> |
5 | 5 | #include <linux/device.h> |
6 | 6 | #include <linux/module.h> |
| 7 | +#include <linux/memory.h> |
7 | 8 | #include <linux/slab.h> |
8 | 9 | #include <linux/uuid.h> |
9 | 10 | #include <linux/sort.h> |
@@ -116,12 +117,22 @@ static const struct attribute_group cxl_region_access0_coordinate_group = { |
116 | 117 | .is_visible = cxl_region_access0_coordinate_visible, |
117 | 118 | }; |
118 | 119 |
|
| 120 | +static const struct attribute_group *get_cxl_region_access0_group(void) |
| 121 | +{ |
| 122 | + return &cxl_region_access0_coordinate_group; |
| 123 | +} |
| 124 | + |
119 | 125 | static const struct attribute_group cxl_region_access1_coordinate_group = { |
120 | 126 | .name = "access1", |
121 | 127 | .attrs = access1_coordinate_attrs, |
122 | 128 | .is_visible = cxl_region_access1_coordinate_visible, |
123 | 129 | }; |
124 | 130 |
|
| 131 | +static const struct attribute_group *get_cxl_region_access1_group(void) |
| 132 | +{ |
| 133 | + return &cxl_region_access1_coordinate_group; |
| 134 | +} |
| 135 | + |
125 | 136 | static ssize_t uuid_show(struct device *dev, struct device_attribute *attr, |
126 | 137 | char *buf) |
127 | 138 | { |
@@ -2216,6 +2227,7 @@ static void unregister_region(void *_cxlr) |
2216 | 2227 | struct cxl_region_params *p = &cxlr->params; |
2217 | 2228 | int i; |
2218 | 2229 |
|
| 2230 | + unregister_memory_notifier(&cxlr->memory_notifier); |
2219 | 2231 | device_del(&cxlr->dev); |
2220 | 2232 |
|
2221 | 2233 | /* |
@@ -2260,6 +2272,58 @@ static struct cxl_region *cxl_region_alloc(struct cxl_root_decoder *cxlrd, int i |
2260 | 2272 | return cxlr; |
2261 | 2273 | } |
2262 | 2274 |
|
| 2275 | +static bool cxl_region_update_coordinates(struct cxl_region *cxlr, int nid) |
| 2276 | +{ |
| 2277 | + int cset = 0; |
| 2278 | + int rc; |
| 2279 | + |
| 2280 | + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) { |
| 2281 | + if (cxlr->coord[i].read_bandwidth) { |
| 2282 | + rc = cxl_update_hmat_access_coordinates(nid, cxlr, i); |
| 2283 | + if (rc == 0) |
| 2284 | + cset++; |
| 2285 | + } |
| 2286 | + } |
| 2287 | + |
| 2288 | + if (!cset) |
| 2289 | + return false; |
| 2290 | + |
| 2291 | + rc = sysfs_update_group(&cxlr->dev.kobj, get_cxl_region_access0_group()); |
| 2292 | + if (rc) |
| 2293 | + dev_dbg(&cxlr->dev, "Failed to update access0 group\n"); |
| 2294 | + |
| 2295 | + rc = sysfs_update_group(&cxlr->dev.kobj, get_cxl_region_access1_group()); |
| 2296 | + if (rc) |
| 2297 | + dev_dbg(&cxlr->dev, "Failed to update access1 group\n"); |
| 2298 | + |
| 2299 | + return true; |
| 2300 | +} |
| 2301 | + |
| 2302 | +static int cxl_region_perf_attrs_callback(struct notifier_block *nb, |
| 2303 | + unsigned long action, void *arg) |
| 2304 | +{ |
| 2305 | + struct cxl_region *cxlr = container_of(nb, struct cxl_region, |
| 2306 | + memory_notifier); |
| 2307 | + struct cxl_region_params *p = &cxlr->params; |
| 2308 | + struct cxl_endpoint_decoder *cxled = p->targets[0]; |
| 2309 | + struct cxl_decoder *cxld = &cxled->cxld; |
| 2310 | + struct memory_notify *mnb = arg; |
| 2311 | + int nid = mnb->status_change_nid; |
| 2312 | + int region_nid; |
| 2313 | + |
| 2314 | + if (nid == NUMA_NO_NODE || action != MEM_ONLINE) |
| 2315 | + return NOTIFY_DONE; |
| 2316 | + |
| 2317 | + region_nid = phys_to_target_node(cxld->hpa_range.start); |
| 2318 | + if (nid != region_nid) |
| 2319 | + return NOTIFY_DONE; |
| 2320 | + |
| 2321 | + if (!cxl_region_update_coordinates(cxlr, nid)) |
| 2322 | + return NOTIFY_DONE; |
| 2323 | + |
| 2324 | + return NOTIFY_OK; |
| 2325 | +} |
| 2326 | + |
2263 | 2327 | /** |
2264 | 2328 | * devm_cxl_add_region - Adds a region to a decoder |
2265 | 2329 | * @cxlrd: root decoder |
@@ -2307,6 +2371,10 @@ static struct cxl_region *devm_cxl_add_region(struct cxl_root_decoder *cxlrd, |
2307 | 2371 | if (rc) |
2308 | 2372 | goto err; |
2309 | 2373 |
|
| 2374 | + cxlr->memory_notifier.notifier_call = cxl_region_perf_attrs_callback; |
| 2375 | + cxlr->memory_notifier.priority = CXL_CALLBACK_PRI; |
| 2376 | + register_memory_notifier(&cxlr->memory_notifier); |
| 2377 | + |
2310 | 2378 | rc = devm_add_action_or_reset(port->uport_dev, unregister_region, cxlr); |
2311 | 2379 | if (rc) |
2312 | 2380 | return ERR_PTR(rc); |
|
0 commit comments