Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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()

+55 -176
-31
Documentation/driver-api/cxl/allocation/page-allocator.rst
··· 41 41 will fallback to allocate from :code:`ZONE_NORMAL`. 42 42 43 43 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 - 75 44 CGroups and CPUSets 76 45 =================== 77 46 Finally, assuming CXL memory is reachable via the page allocation (i.e. onlined
+6 -5
drivers/acpi/numa/hmat.c
··· 888 888 * Register generic port perf numbers. The nid may not be 889 889 * initialized and is still NUMA_NO_NODE. 890 890 */ 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 + } 895 897 } 896 - mutex_unlock(&target_lock); 897 898 898 899 /* 899 900 * Skip offline nodes. This can happen when memory
+2 -2
drivers/cxl/core/cdat.c
··· 826 826 cxl_coordinates_combine(coords, coords, ctx->coord); 827 827 828 828 /* 829 - * Take the min of the calculated bandwdith and the upstream 829 + * Take the min of the calculated bandwidth and the upstream 830 830 * switch SSLBIS bandwidth if there's a parent switch 831 831 */ 832 832 if (!is_root) ··· 949 949 /** 950 950 * cxl_region_update_bandwidth - Update the bandwidth access coordinates of a region 951 951 * @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 953 953 */ 954 954 static void cxl_region_update_bandwidth(struct cxl_region *cxlr, 955 955 struct xarray *input_xa)
+3
drivers/cxl/core/hdm.c
··· 905 905 if ((cxld->flags & CXL_DECODER_F_ENABLE) == 0) 906 906 return; 907 907 908 + if (test_bit(CXL_DECODER_F_LOCK, &cxld->flags)) 909 + return; 910 + 908 911 if (port->commit_end == id) 909 912 cxl_port_commit_reap(cxld); 910 913 else
+8 -79
drivers/cxl/core/pci.c
··· 71 71 } 72 72 EXPORT_SYMBOL_NS_GPL(__devm_cxl_add_dport_by_dev, "CXL"); 73 73 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 - 153 74 static int cxl_dvsec_mem_range_valid(struct cxl_dev_state *cxlds, int id) 154 75 { 155 76 struct pci_dev *pdev = to_pci_dev(cxlds->dev); ··· 1137 1216 1138 1217 return 0; 1139 1218 } 1219 + 1220 + struct cxl_walk_context { 1221 + struct pci_bus *bus; 1222 + struct cxl_port *port; 1223 + int type; 1224 + int error; 1225 + int count; 1226 + }; 1140 1227 1141 1228 static int count_dports(struct pci_dev *pdev, void *data) 1142 1229 {
+27 -8
drivers/cxl/core/region.c
··· 245 245 struct cxl_region_params *p = &cxlr->params; 246 246 int i; 247 247 248 + if (test_bit(CXL_REGION_F_LOCK, &cxlr->flags)) 249 + return; 250 + 248 251 /* 249 252 * Before region teardown attempt to flush, evict any data cached for 250 253 * this region, or scream loudly about missing arch / platform support ··· 421 418 return rc; 422 419 return len; 423 420 } 421 + 422 + if (test_bit(CXL_REGION_F_LOCK, &cxlr->flags)) 423 + return -EPERM; 424 424 425 425 rc = queue_reset(cxlr); 426 426 if (rc) ··· 844 838 return 1; 845 839 } 846 840 847 - static bool region_res_match_cxl_range(const struct cxl_region_params *p, 848 - const struct range *range) 841 + static bool spa_maps_hpa(const struct cxl_region_params *p, 842 + const struct range *range) 849 843 { 850 844 if (!p->res) 851 845 return false; 852 846 853 847 /* 854 - * If an extended linear cache region then the CXL range is assumed 855 - * to be fronted by the DRAM range in current known implementation. 856 - * This assumption will be made until a variant implementation exists. 848 + * The extended linear cache region is constructed by a 1:1 ratio 849 + * where the SPA maps equal amounts of DRAM and CXL HPA capacity with 850 + * CXL decoders at the high end of the SPA range. 857 851 */ 858 852 return p->res->start + p->cache_size == range->start && 859 853 p->res->end == range->end; ··· 871 865 cxld = to_cxl_decoder(dev); 872 866 r = &cxld->hpa_range; 873 867 874 - if (region_res_match_cxl_range(p, r)) 868 + if (spa_maps_hpa(p, r)) 875 869 return 1; 876 870 877 871 return 0; ··· 1065 1059 return 0; 1066 1060 } 1067 1061 1062 + static void cxl_region_set_lock(struct cxl_region *cxlr, 1063 + struct cxl_decoder *cxld) 1064 + { 1065 + if (!test_bit(CXL_DECODER_F_LOCK, &cxld->flags)) 1066 + return; 1067 + 1068 + set_bit(CXL_REGION_F_LOCK, &cxlr->flags); 1069 + clear_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags); 1070 + } 1071 + 1068 1072 /** 1069 1073 * cxl_port_attach_region() - track a region's interest in a port by endpoint 1070 1074 * @port: port to add a new region reference 'struct cxl_region_ref' ··· 1185 1169 goto out_erase; 1186 1170 } 1187 1171 } 1172 + 1173 + cxl_region_set_lock(cxlr, cxld); 1188 1174 1189 1175 rc = cxl_rr_ep_add(cxl_rr, cxled); 1190 1176 if (rc) { ··· 1483 1465 if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) { 1484 1466 if (cxld->interleave_ways != iw || 1485 1467 (iw > 1 && cxld->interleave_granularity != ig) || 1486 - !region_res_match_cxl_range(p, &cxld->hpa_range) || 1468 + !spa_maps_hpa(p, &cxld->hpa_range) || 1487 1469 ((cxld->flags & CXL_DECODER_F_ENABLE) == 0)) { 1488 1470 dev_err(&cxlr->dev, 1489 1471 "%s:%s %s expected iw: %d ig: %d %pr\n", ··· 2457 2439 dev->bus = &cxl_bus_type; 2458 2440 dev->type = &cxl_region_type; 2459 2441 cxlr->id = id; 2442 + cxl_region_set_lock(cxlr, &cxlrd->cxlsd.cxld); 2460 2443 2461 2444 return cxlr; 2462 2445 } ··· 3417 3398 p = &cxlr->params; 3418 3399 3419 3400 guard(rwsem_read)(&cxl_rwsem.region); 3420 - return region_res_match_cxl_range(p, r); 3401 + return spa_maps_hpa(p, r); 3421 3402 } 3422 3403 3423 3404 static int cxl_extended_linear_cache_resize(struct cxl_region *cxlr,
+8
drivers/cxl/cxl.h
··· 517 517 */ 518 518 #define CXL_REGION_F_NEEDS_RESET 1 519 519 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 + 520 528 /** 521 529 * struct cxl_region - CXL region 522 530 * @dev: This region's device
-1
drivers/cxl/cxlpci.h
··· 127 127 return lnksta2 & PCI_EXP_LNKSTA2_FLIT; 128 128 } 129 129 130 - int devm_cxl_port_enumerate_dports(struct cxl_port *port); 131 130 struct cxl_dev_state; 132 131 void read_cdat_data(struct cxl_port *port); 133 132 void cxl_cor_error_detected(struct pci_dev *pdev);
+1 -1
drivers/cxl/pci.c
··· 136 136 if (opcode == CXL_MBOX_OP_SANITIZE) { 137 137 mutex_lock(&cxl_mbox->mbox_mutex); 138 138 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); 140 140 mutex_unlock(&cxl_mbox->mbox_mutex); 141 141 } else { 142 142 /* short-circuit the wait in __cxl_pci_mbox_send_cmd() */
-1
tools/testing/cxl/Kbuild
··· 4 4 ldflags-y += --wrap=acpi_evaluate_integer 5 5 ldflags-y += --wrap=acpi_pci_find_root 6 6 ldflags-y += --wrap=nvdimm_bus_register 7 - ldflags-y += --wrap=devm_cxl_port_enumerate_dports 8 7 ldflags-y += --wrap=cxl_await_media_ready 9 8 ldflags-y += --wrap=devm_cxl_add_rch_dport 10 9 ldflags-y += --wrap=cxl_rcd_component_reg_phys
-32
tools/testing/cxl/test/cxl.c
··· 995 995 return 0; 996 996 } 997 997 998 - static int mock_cxl_port_enumerate_dports(struct cxl_port *port) 999 - { 1000 - struct platform_device **array; 1001 - int i, array_size; 1002 - int rc; 1003 - 1004 - rc = get_port_array(port, &array, &array_size); 1005 - if (rc) 1006 - return rc; 1007 - 1008 - for (i = 0; i < array_size; i++) { 1009 - struct platform_device *pdev = array[i]; 1010 - struct cxl_dport *dport; 1011 - 1012 - if (pdev->dev.parent != port->uport_dev) { 1013 - dev_dbg(&port->dev, "%s: mismatch parent %s\n", 1014 - dev_name(port->uport_dev), 1015 - dev_name(pdev->dev.parent)); 1016 - continue; 1017 - } 1018 - 1019 - dport = devm_cxl_add_dport(port, &pdev->dev, pdev->id, 1020 - CXL_RESOURCE_NONE); 1021 - 1022 - if (IS_ERR(dport)) 1023 - return PTR_ERR(dport); 1024 - } 1025 - 1026 - return 0; 1027 - } 1028 - 1029 998 static struct cxl_dport *mock_cxl_add_dport_by_dev(struct cxl_port *port, 1030 999 struct device *dport_dev) 1031 1000 { ··· 1083 1114 .acpi_pci_find_root = mock_acpi_pci_find_root, 1084 1115 .devm_cxl_switch_port_decoders_setup = mock_cxl_switch_port_decoders_setup, 1085 1116 .devm_cxl_endpoint_decoders_setup = mock_cxl_endpoint_decoders_setup, 1086 - .devm_cxl_port_enumerate_dports = mock_cxl_port_enumerate_dports, 1087 1117 .cxl_endpoint_parse_cdat = mock_cxl_endpoint_parse_cdat, 1088 1118 .devm_cxl_add_dport_by_dev = mock_cxl_add_dport_by_dev, 1089 1119 .list = LIST_HEAD_INIT(cxl_mock_ops.list),
-15
tools/testing/cxl/test/mock.c
··· 172 172 } 173 173 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_endpoint_decoders_setup, "CXL"); 174 174 175 - int __wrap_devm_cxl_port_enumerate_dports(struct cxl_port *port) 176 - { 177 - int rc, index; 178 - struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 179 - 180 - if (ops && ops->is_mock_port(port->uport_dev)) 181 - rc = ops->devm_cxl_port_enumerate_dports(port); 182 - else 183 - rc = devm_cxl_port_enumerate_dports(port); 184 - put_cxl_mock_ops(index); 185 - 186 - return rc; 187 - } 188 - EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, "CXL"); 189 - 190 175 int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds) 191 176 { 192 177 int rc, index;
-1
tools/testing/cxl/test/mock.h
··· 19 19 bool (*is_mock_bus)(struct pci_bus *bus); 20 20 bool (*is_mock_port)(struct device *dev); 21 21 bool (*is_mock_dev)(struct device *dev); 22 - int (*devm_cxl_port_enumerate_dports)(struct cxl_port *port); 23 22 int (*devm_cxl_switch_port_decoders_setup)(struct cxl_port *port); 24 23 int (*devm_cxl_endpoint_decoders_setup)(struct cxl_port *port); 25 24 void (*cxl_endpoint_parse_cdat)(struct cxl_port *port);