From ed87f476de90e4c437c117ceebba9ddc06351020 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Mon, 30 Sep 2024 16:09:20 +0000 Subject: [PATCH] import CS ndctl-78-2.el9 --- .gitignore | 2 +- .ndctl.metadata | 2 +- ...vices.sh-increase-the-namespace-size.patch | 41 + SOURCES/0002-ndctl-vendor-iniparser.patch | 1894 ++++++ ...k-the-old-directory-for-monitor.conf.patch | 70 + ...Fix-btt-expect-table-compile-warning.patch | 51 - ...l-test-Cleanup-unnecessary-out-label.patch | 57 - ...dctl-test-Fix-device-dax-mremap-test.patch | 40 - ...rcise-soft_offline_page-corner-cases.patch | 134 - ...rmware_status-for-JEDEC-Byte-Address.patch | 73 - ...Fix-disable-namespace-accounting-rel.patch | 140 - ...09-zero_info_block-skip-seed-devices.patch | 50 - SOURCES/0010-ndctl-update-.gitignore.patch | 51 - ...hecking-the-presence-of-jq-command-a.patch | 127 - ..._nfit_translate_spa-as-a-public-func.patch | 78 - ...e-ndctl_region_set_ro-to-change-disk.patch | 72 - ...nfigure-device-based-on-kernel-onlin.patch | 221 - ...n-API-to-check-if-a-device-is-active.patch | 63 - ...or-active-system-ram-before-disablin.patch | 113 - ...counts-of-total-and-online-memblocks.patch | 49 - ...dding-dimms-for-papr-and-nfit-famili.patch | 220 - ...ip-tests-if-nfit-modules-are-missing.patch | 211 - ...ort-to-parse-save_fail-flag-for-dimm.patch | 41 - ...021-Use-page-size-as-alignment-value.patch | 129 - ...ove-redundant-checks-and-assignments.patch | 38 - ...l-Update-nvdimm-mailing-list-address.patch | 56 - ...x-probe-for-papr-scm-compatible-nvdi.patch | 122 - ...scrub-Stop-translating-return-values.patch | 38 - ...-Reread-scrub-engine-status-at-start.patch | 48 - ...m-Fix-label-index-block-calculations.patch | 167 - ...Skip-seed-namespaces-when-processing.patch | 58 - ...Suppress-ENXIO-when-processing-all-n.patch | 82 - ...ce-action-Drop-zero-namespace-checks.patch | 85 - SOURCES/0031-ndctl-add-.clang-format.patch | 187 - ...add-a-cxl-utility-and-libcxl-library.patch | 1277 ---- ...ocal-copy-of-the-cxl_mem-UAPI-header.patch | 256 - ...e-struct_size-helper-from-the-kernel.patch | 114 - ...ort-for-command-query-and-submission.patch | 535 -- ...port-for-the-Identify-Device-command.patch | 157 - ...EALTH_INFO-mailbox-command-and-acces.patch | 575 -- ...-add-support-for-the-GET_LSA-command.patch | 113 - ..._size-to-cxl_memdev-and-an-API-to-re.patch | 89 - ...sentation-for-an-nvdimm-bridge-objec.patch | 184 - ...-add-interfaces-for-label-operations.patch | 247 - ...mmands-to-read-write-and-zero-labels.patch | 583 -- ...on-cxl-add-library-API-documentation.patch | 248 - ...ctl-Add-CXL-packages-to-the-RPM-spec.patch | 147 - .../0045-cxl-cli-add-bash-completion.patch | 139 - ...l-add-health-information-to-cxl-list.patch | 308 - ...ctl-install-bash-completion-symlinks.patch | 75 - ...ts-Add-a-man-page-template-generator.patch | 400 -- ...Soft-Reservation-theory-of-operation.patch | 167 - ...tial-NULL-dereference-in-cxl_memdev_.patch | 46 - SOURCES/0064-ndctl-release-v72.patch | 142 - ...tl-add-repology-graphic-to-README.md.patch | 32 - ...ctl-fix-self-reference-of-ndctl-disa.patch | 29 - ...fy-update-firwmware-activation-overf.patch | 97 - ...are-for-BLK-aperture-support-removal.patch | 171 - ...est-Move-reset-to-function-in-common.patch | 428 -- ...Initialize-the-label-area-by-default.patch | 104 - ...073-ndctl-test-Skip-BLK-flags-checks.patch | 43 - ...ve-sector-mode-to-a-different-region.patch | 41 - ...ndctl-Deprecate-BLK-aperture-support.patch | 1966 ------ ...upport-for-missing-dax_pmem_compat-m.patch | 78 - ...filter-and-json-helpers-to-per-tool-.patch | 5595 ----------------- ...ocumentation-Drop-attrs.adoc-include.patch | 104 - ...p-unnecessary-tool-config.h-includes.patch | 53 - ...0080-test-Prepare-out-of-line-builds.patch | 355 -- ...table-bit-for-bash-completion-script.patch | 28 - ...build-Add-meson-build-infrastructure.patch | 1577 ----- ...083-build-Add-meson-rpmbuild-support.patch | 223 - SOURCES/0084-ndctl-Jettison-autotools.patch | 1423 ----- ...build-Default-asciidoctor-to-enabled.patch | 32 - ...ctl-update-README.md-for-meson-build.patch | 88 - ...-test-Add-suite-identifiers-to-tests.patch | 122 - ...l-Rename-util_filter-to-ndctl_filter.patch | 287 - SOURCES/0089-build-Add-tags.patch | 54 - ...d-support-for-json_object_new_uint64.patch | 194 - ...n-Cleanup-object-leak-false-positive.patch | 32 - ...-multiple-memdev-device-name-filter-.patch | 118 - ...l-list-Support-comma-separated-lists.patch | 55 - ...4-cxl-list-Introduce-cxl_filter_walk.patch | 292 - ...-cxl-list-Emit-device-serial-numbers.patch | 159 - ...xl-list-Add-filter-by-serial-support.patch | 163 - ...cxl-lib-Rename-nvdimm-bridge-to-pmem.patch | 164 - ...cxl-list-Cleanup-options-definitions.patch | 61 - ...hance-libcxl-memdev-API-documentatio.patch | 170 - SOURCES/0100-cxl-list-Add-bus-objects.patch | 739 --- ...n-on-stderr-about-empty-list-results.patch | 44 - ...level-modalias-lookup-helper-to-util.patch | 165 - .../0103-cxl-list-Add-port-enumeration.patch | 862 --- SOURCES/0104-cxl-list-Add-debug-option.patch | 103 - SOURCES/0105-cxl-list-Add-endpoints.patch | 746 --- ...d-host-entries-for-port-like-objects.patch | 154 - ...xl-list-Add-host-entries-for-memdevs.patch | 175 - ...abled-memdevs-underneath-their-endpo.patch | 499 -- ...9-cxl-list-Filter-memdev-by-ancestry.patch | 329 - ...-memdev-Use-a-local-logger-for-debug.patch | 173 - ...111-cxl-memdev-Cleanup-memdev-filter.patch | 64 - ...erial-support-for-memdev-related-com.patch | 133 - ...ist-Add-numa_node-to-memdev-listings.patch | 136 - ...Implement-common-bind-unbind-helpers.patch | 329 - ...15-cxl-memdev-Enable-disable-support.patch | 379 -- .../0116-cxl-list-Add-decoder-support.patch | 1108 ---- ...decoder-objects-with-target-informat.patch | 537 -- ...sical_node-for-root-port-attachment-.patch | 156 - ...st-Reuse-the-target-option-for-ports.patch | 457 -- ...upport-filtering-memdevs-by-decoders.patch | 205 - ...t-Support-filtering-memdevs-by-ports.patch | 200 - ...port-Add-disable-enable-port-command.patch | 734 --- ...Filter-dports-and-targets-by-memdevs.patch | 340 - ...inject-smart.sh-more-tolerant-of-dec.patch | 46 - ...d-support-for-reporting-shutdown-cou.patch | 136 - ...ndicate-supported-smart-inject-types.patch | 161 - ...Add-limited-support-for-inject-smart.patch | 180 - ...utdown-count-Skip-the-test-on-ndtest.patch | 41 - ...pdate-nvdimm-flags-after-smart-injec.patch | 218 - ...ARTITION_INFO-mailbox-command-and-ac.patch | 202 - ...sors-for-capacity-fields-of-the-IDEN.patch | 118 - ...e-partition-alignment-field-in-bytes.patch | 53 - ...ev-partition-information-to-cxl-list.patch | 267 - ...faces-for-SET_PARTITION_INFO-mailbox.patch | 154 - ...37-cxl-add-command-cxl-set-partition.patch | 400 -- ...e-ndctl.spec-to-allow-flatpak-builds.patch | 41 - ...ovide-safe-versions-of-iteration-API.patch | 47 - ...size.h-fix-build-for-older-compilers.patch | 216 - SOURCES/0141-build-Automate-rpmbuild.sh.patch | 49 - ...il-size.h-Fix-build-error-for-GCC-10.patch | 48 - ...traneous-NULL-checks-when-validating.patch | 47 - ...ree-resource-allocated-with-asprintf.patch | 35 - ...dy-the-error-path-in-add_cxl_decoder.patch | 51 - ...free-the-path-var-in-add_cxl_decoder.patch | 38 - ...on-Fix-document-header-for-section-1.patch | 40 - SOURCES/0148-ndctl-release-v73.patch | 156 - .../0150-build-Fix-Wall-and-O2-warnings.patch | 49 - SOURCES/0151-build-Fix-test-timeouts.patch | 33 - ...ld-Move-utility-helpers-to-libutil.a.patch | 68 - ...-Use-SZ_-size-macros-in-display-size.patch | 60 - .../0157-util-Pretty-print-terabytes.patch | 61 - ...8-cxl-port-Fix-disable-port-man-page.patch | 49 - ...0159-cxl-bus-Add-bus-disable-support.patch | 384 -- ...enable-single-mode-for-port-listings.patch | 37 - ...-cxl-memdev-Fix-bus_invalidate-crash.patch | 50 - ...port-for-filtering-by-host-identifie.patch | 73 - ...ort-Relax-port-identifier-validation.patch | 92 - ...opology-enumeration-and-hotplug-test.patch | 236 - ...l-option-typo-in-Soft-Reservation-th.patch | 32 - ...meson-make-modprobedatadir-an-option.patch | 38 - ...tion-Drop-more-zero-namespace-checks.patch | 116 - ...h-invalidated-labels-after-overwrite.patch | 94 - ...-segfault-when-memdev-pmem-is-absent.patch | 45 - ...-missing-scrub-commands-more-gracefu.patch | 83 - ...rapper.c-Fix-gcc-warning-in-xrealloc.patch | 58 - ...-Fix-memory-leakage-in-cxl_port_init.patch | 31 - .../0175-cxl-list-Reformat-option-list.patch | 47 - ...endpoint-decoders-filtered-by-memdev.patch | 46 - ...Hide-0s-in-disabled-decoder-listings.patch | 59 - ...PA-span-to-endpoint-decoder-listings.patch | 167 - ...ccan-list-Import-latest-list-helpers.patch | 459 -- ...xl-lib-Maintain-decoders-in-id-order.patch | 103 - ...x-json-for-multi-device-partitioning.patch | 93 - ...it-mode-for-endpoint-decoder-objects.patch | 181 - ...n-Accept-ram-as-an-alias-for-volatil.patch | 56 - ...memdev-Add-reserve-free-dpa-commands.patch | 763 --- ...xl-test-Update-CXL-memory-parameters.patch | 86 - ...-test-Checkout-region-setup-teardown.patch | 169 - ...add-a-test-to-read-write-zero-labels.patch | 121 - .../0188-cxl-list-Clarify-B-vs-P-p-root.patch | 93 - ...xl-add-a-depth-attribute-to-cxl_port.patch | 45 - ...date-the-debug-option-in-cxl-port-ma.patch | 82 - ...refactor-decoder-mode-string-parsing.patch | 74 - ...ce-libcxl-region-and-mapping-objects.patch | 651 -- ...3-cxl-cli-add-region-listing-support.patch | 548 -- ...d-low-level-APIs-for-region-creation.patch | 644 -- ...0195-cxl-add-a-create-region-command.patch | 829 --- ...nds-to-enable-disable-destroy-region.patch | 459 -- ...mdevs-and-regions-the-default-listin.patch | 39 - ...98-test-add-a-cxl-create-region-test.patch | 173 - ...add-a-max_available_extent-attribute.patch | 240 - ...st-verbose-option-to-the-cxl-command.patch | 108 - ...alidate-endpoint-interleave-geometry.patch | 57 - ...erleave-parameters-to-decoder-listin.patch | 49 - ...-list-Add-region-to-decoder-listings.patch | 140 - ...4-cxl-list-Filter-decoders-by-region.patch | 59 - ...-cxl-list-Add-depth-to-port-listings.patch | 90 - ...e-switch-port-settings-in-cxl-region.patch | 63 - ...on-fix-modprobedatadir-default-value.patch | 34 - ...oper-scripts-from-contrib-to-scripts.patch | 49 - ...9-ndctl-remove-obsolete-m4-directory.patch | 31 - SOURCES/0210-ndctl-update-.gitignore.patch | 32 - ...ontrib-do_abidiff-for-updated-fedpkg.patch | 30 - ...elease-helper-scripts-for-meson-and-.patch | 66 - ...n.build-be-specific-for-library-path.patch | 48 - ...-fix-a-dereferecnce-after-NULL-check.patch | 39 - ...source-leak-and-a-forward-NULL-check.patch | 50 - ...an-uninitialized-pointer-dereference.patch | 33 - SOURCES/0217-ndctl-release-v74.patch | 133 - SPECS/ndctl.spec | 249 +- 198 files changed, 2052 insertions(+), 43685 deletions(-) create mode 100644 SOURCES/0001-test-daxctl-devices.sh-increase-the-namespace-size.patch create mode 100644 SOURCES/0002-ndctl-vendor-iniparser.patch create mode 100644 SOURCES/0003-ndctl-check-the-old-directory-for-monitor.conf.patch delete mode 100644 SOURCES/0003-ndctl-test-Fix-btt-expect-table-compile-warning.patch delete mode 100644 SOURCES/0004-ndctl-test-Cleanup-unnecessary-out-label.patch delete mode 100644 SOURCES/0005-ndctl-test-Fix-device-dax-mremap-test.patch delete mode 100644 SOURCES/0006-ndctl-test-Exercise-soft_offline_page-corner-cases.patch delete mode 100644 SOURCES/0007-msft-Add-xlat_firmware_status-for-JEDEC-Byte-Address.patch delete mode 100644 SOURCES/0008-ndctl-namespace-Fix-disable-namespace-accounting-rel.patch delete mode 100644 SOURCES/0009-zero_info_block-skip-seed-devices.patch delete mode 100644 SOURCES/0010-ndctl-update-.gitignore.patch delete mode 100644 SOURCES/0011-ndctl-test-add-checking-the-presence-of-jq-command-a.patch delete mode 100644 SOURCES/0012-Expose-ndctl_bus_nfit_translate_spa-as-a-public-func.patch delete mode 100644 SOURCES/0013-test-libndctl-Use-ndctl_region_set_ro-to-change-disk.patch delete mode 100644 SOURCES/0014-daxctl-fail-reconfigure-device-based-on-kernel-onlin.patch delete mode 100644 SOURCES/0015-libdaxctl-add-an-API-to-check-if-a-device-is-active.patch delete mode 100644 SOURCES/0016-libndctl-check-for-active-system-ram-before-disablin.patch delete mode 100644 SOURCES/0017-daxctl-emit-counts-of-total-and-online-memblocks.patch delete mode 100644 SOURCES/0018-libndctl-Unify-adding-dimms-for-papr-and-nfit-famili.patch delete mode 100644 SOURCES/0019-test-Don-t-skip-tests-if-nfit-modules-are-missing.patch delete mode 100644 SOURCES/0020-papr-Add-support-to-parse-save_fail-flag-for-dimm.patch delete mode 100644 SOURCES/0021-Use-page-size-as-alignment-value.patch delete mode 100644 SOURCES/0022-libndctl-Remove-redundant-checks-and-assignments.patch delete mode 100644 SOURCES/0023-ndctl-Update-nvdimm-mailing-list-address.patch delete mode 100644 SOURCES/0024-libndctl-papr-Fix-probe-for-papr-scm-compatible-nvdi.patch delete mode 100644 SOURCES/0025-ndctl-scrub-Stop-translating-return-values.patch delete mode 100644 SOURCES/0026-ndctl-scrub-Reread-scrub-engine-status-at-start.patch delete mode 100644 SOURCES/0027-ndctl-dimm-Fix-label-index-block-calculations.patch delete mode 100644 SOURCES/0028-ndctl-namespace-Skip-seed-namespaces-when-processing.patch delete mode 100644 SOURCES/0029-ndctl-namespace-Suppress-ENXIO-when-processing-all-n.patch delete mode 100644 SOURCES/0030-namespace-action-Drop-zero-namespace-checks.patch delete mode 100644 SOURCES/0031-ndctl-add-.clang-format.patch delete mode 100644 SOURCES/0032-cxl-add-a-cxl-utility-and-libcxl-library.patch delete mode 100644 SOURCES/0033-cxl-add-a-local-copy-of-the-cxl_mem-UAPI-header.patch delete mode 100644 SOURCES/0034-util-add-the-struct_size-helper-from-the-kernel.patch delete mode 100644 SOURCES/0035-libcxl-add-support-for-command-query-and-submission.patch delete mode 100644 SOURCES/0036-libcxl-add-support-for-the-Identify-Device-command.patch delete mode 100644 SOURCES/0037-libcxl-add-GET_HEALTH_INFO-mailbox-command-and-acces.patch delete mode 100644 SOURCES/0038-libcxl-add-support-for-the-GET_LSA-command.patch delete mode 100644 SOURCES/0039-libcxl-add-label_size-to-cxl_memdev-and-an-API-to-re.patch delete mode 100644 SOURCES/0040-libcxl-add-representation-for-an-nvdimm-bridge-objec.patch delete mode 100644 SOURCES/0041-libcxl-add-interfaces-for-label-operations.patch delete mode 100644 SOURCES/0042-cxl-add-commands-to-read-write-and-zero-labels.patch delete mode 100644 SOURCES/0043-Documentation-cxl-add-library-API-documentation.patch delete mode 100644 SOURCES/0044-ndctl-Add-CXL-packages-to-the-RPM-spec.patch delete mode 100644 SOURCES/0045-cxl-cli-add-bash-completion.patch delete mode 100644 SOURCES/0046-cxl-add-health-information-to-cxl-list.patch delete mode 100644 SOURCES/0047-ndctl-install-bash-completion-symlinks.patch delete mode 100644 SOURCES/0048-scripts-Add-a-man-page-template-generator.patch delete mode 100644 SOURCES/0049-daxctl-Add-Soft-Reservation-theory-of-operation.patch delete mode 100644 SOURCES/0061-libcxl-fix-potential-NULL-dereference-in-cxl_memdev_.patch delete mode 100644 SOURCES/0064-ndctl-release-v72.patch delete mode 100644 SOURCES/0067-ndctl-add-repology-graphic-to-README.md.patch delete mode 100644 SOURCES/0068-Documentation-ndctl-fix-self-reference-of-ndctl-disa.patch delete mode 100644 SOURCES/0069-ndctl-docs-Clarify-update-firwmware-activation-overf.patch delete mode 100644 SOURCES/0070-ndctl-test-Prepare-for-BLK-aperture-support-removal.patch delete mode 100644 SOURCES/0071-ndctl-test-Move-reset-to-function-in-common.patch delete mode 100644 SOURCES/0072-ndctl-test-Initialize-the-label-area-by-default.patch delete mode 100644 SOURCES/0073-ndctl-test-Skip-BLK-flags-checks.patch delete mode 100644 SOURCES/0074-ndctl-test-Move-sector-mode-to-a-different-region.patch delete mode 100644 SOURCES/0075-ndctl-Deprecate-BLK-aperture-support.patch delete mode 100644 SOURCES/0076-ndctl-test-Fix-support-for-missing-dax_pmem_compat-m.patch delete mode 100644 SOURCES/0077-util-Distribute-filter-and-json-helpers-to-per-tool-.patch delete mode 100644 SOURCES/0078-Documentation-Drop-attrs.adoc-include.patch delete mode 100644 SOURCES/0079-build-Drop-unnecessary-tool-config.h-includes.patch delete mode 100644 SOURCES/0080-test-Prepare-out-of-line-builds.patch delete mode 100644 SOURCES/0081-ndctl-Drop-executable-bit-for-bash-completion-script.patch delete mode 100644 SOURCES/0082-build-Add-meson-build-infrastructure.patch delete mode 100644 SOURCES/0083-build-Add-meson-rpmbuild-support.patch delete mode 100644 SOURCES/0084-ndctl-Jettison-autotools.patch delete mode 100644 SOURCES/0085-ndctl-build-Default-asciidoctor-to-enabled.patch delete mode 100644 SOURCES/0086-ndctl-update-README.md-for-meson-build.patch delete mode 100644 SOURCES/0087-test-Add-suite-identifiers-to-tests.patch delete mode 100644 SOURCES/0088-ndctl-Rename-util_filter-to-ndctl_filter.patch delete mode 100644 SOURCES/0089-build-Add-tags.patch delete mode 100644 SOURCES/0090-json-Add-support-for-json_object_new_uint64.patch delete mode 100644 SOURCES/0091-cxl-json-Cleanup-object-leak-false-positive.patch delete mode 100644 SOURCES/0092-cxl-list-Support-multiple-memdev-device-name-filter-.patch delete mode 100644 SOURCES/0093-cxl-list-Support-comma-separated-lists.patch delete mode 100644 SOURCES/0094-cxl-list-Introduce-cxl_filter_walk.patch delete mode 100644 SOURCES/0095-cxl-list-Emit-device-serial-numbers.patch delete mode 100644 SOURCES/0096-cxl-list-Add-filter-by-serial-support.patch delete mode 100644 SOURCES/0097-cxl-lib-Rename-nvdimm-bridge-to-pmem.patch delete mode 100644 SOURCES/0098-cxl-list-Cleanup-options-definitions.patch delete mode 100644 SOURCES/0099-Documentation-Enhance-libcxl-memdev-API-documentatio.patch delete mode 100644 SOURCES/0100-cxl-list-Add-bus-objects.patch delete mode 100644 SOURCES/0101-util-json-Warn-on-stderr-about-empty-list-results.patch delete mode 100644 SOURCES/0102-util-sysfs-Uplevel-modalias-lookup-helper-to-util.patch delete mode 100644 SOURCES/0103-cxl-list-Add-port-enumeration.patch delete mode 100644 SOURCES/0104-cxl-list-Add-debug-option.patch delete mode 100644 SOURCES/0105-cxl-list-Add-endpoints.patch delete mode 100644 SOURCES/0106-cxl-list-Add-host-entries-for-port-like-objects.patch delete mode 100644 SOURCES/0107-cxl-list-Add-host-entries-for-memdevs.patch delete mode 100644 SOURCES/0108-cxl-list-Move-enabled-memdevs-underneath-their-endpo.patch delete mode 100644 SOURCES/0109-cxl-list-Filter-memdev-by-ancestry.patch delete mode 100644 SOURCES/0110-cxl-memdev-Use-a-local-logger-for-debug.patch delete mode 100644 SOURCES/0111-cxl-memdev-Cleanup-memdev-filter.patch delete mode 100644 SOURCES/0112-cxl-memdev-Add-serial-support-for-memdev-related-com.patch delete mode 100644 SOURCES/0113-cxl-list-Add-numa_node-to-memdev-listings.patch delete mode 100644 SOURCES/0114-util-Implement-common-bind-unbind-helpers.patch delete mode 100644 SOURCES/0115-cxl-memdev-Enable-disable-support.patch delete mode 100644 SOURCES/0116-cxl-list-Add-decoder-support.patch delete mode 100644 SOURCES/0117-cxl-list-Extend-decoder-objects-with-target-informat.patch delete mode 100644 SOURCES/0118-cxl-list-Use-physical_node-for-root-port-attachment-.patch delete mode 100644 SOURCES/0119-cxl-list-Reuse-the-target-option-for-ports.patch delete mode 100644 SOURCES/0120-cxl-list-Support-filtering-memdevs-by-decoders.patch delete mode 100644 SOURCES/0121-cxl-list-Support-filtering-memdevs-by-ports.patch delete mode 100644 SOURCES/0122-cxl-port-Add-disable-enable-port-command.patch delete mode 100644 SOURCES/0123-cxl-list-Filter-dports-and-targets-by-memdevs.patch delete mode 100644 SOURCES/0124-ndctl-test-make-inject-smart.sh-more-tolerant-of-dec.patch delete mode 100644 SOURCES/0125-libndctl-papr-Add-support-for-reporting-shutdown-cou.patch delete mode 100644 SOURCES/0126-libndctl-intel-Indicate-supported-smart-inject-types.patch delete mode 100644 SOURCES/0127-libndctl-papr-Add-limited-support-for-inject-smart.patch delete mode 100644 SOURCES/0128-ndtest-ack-shutdown-count-Skip-the-test-on-ndtest.patch delete mode 100644 SOURCES/0129-ndctl-libndctl-Update-nvdimm-flags-after-smart-injec.patch delete mode 100644 SOURCES/0132-libcxl-add-GET_PARTITION_INFO-mailbox-command-and-ac.patch delete mode 100644 SOURCES/0133-libcxl-add-accessors-for-capacity-fields-of-the-IDEN.patch delete mode 100644 SOURCES/0134-libcxl-return-the-partition-alignment-field-in-bytes.patch delete mode 100644 SOURCES/0135-cxl-add-memdev-partition-information-to-cxl-list.patch delete mode 100644 SOURCES/0136-libcxl-add-interfaces-for-SET_PARTITION_INFO-mailbox.patch delete mode 100644 SOURCES/0137-cxl-add-command-cxl-set-partition.patch delete mode 100644 SOURCES/0138-Update-ndctl.spec-to-allow-flatpak-builds.patch delete mode 100644 SOURCES/0139-daxctl-provide-safe-versions-of-iteration-API.patch delete mode 100644 SOURCES/0140-util-size.h-fix-build-for-older-compilers.patch delete mode 100644 SOURCES/0141-build-Automate-rpmbuild.sh.patch delete mode 100644 SOURCES/0142-util-size.h-Fix-build-error-for-GCC-10.patch delete mode 100644 SOURCES/0143-libcxl-Remove-extraneous-NULL-checks-when-validating.patch delete mode 100644 SOURCES/0144-libdaxctl-free-resource-allocated-with-asprintf.patch delete mode 100644 SOURCES/0145-cxl-list-tidy-the-error-path-in-add_cxl_decoder.patch delete mode 100644 SOURCES/0146-cxl-list-always-free-the-path-var-in-add_cxl_decoder.patch delete mode 100644 SOURCES/0147-scripts-docsurgeon-Fix-document-header-for-section-1.patch delete mode 100644 SOURCES/0148-ndctl-release-v73.patch delete mode 100644 SOURCES/0150-build-Fix-Wall-and-O2-warnings.patch delete mode 100644 SOURCES/0151-build-Fix-test-timeouts.patch delete mode 100644 SOURCES/0155-build-Move-utility-helpers-to-libutil.a.patch delete mode 100644 SOURCES/0156-util-Use-SZ_-size-macros-in-display-size.patch delete mode 100644 SOURCES/0157-util-Pretty-print-terabytes.patch delete mode 100644 SOURCES/0158-cxl-port-Fix-disable-port-man-page.patch delete mode 100644 SOURCES/0159-cxl-bus-Add-bus-disable-support.patch delete mode 100644 SOURCES/0160-cxl-list-Auto-enable-single-mode-for-port-listings.patch delete mode 100644 SOURCES/0161-cxl-memdev-Fix-bus_invalidate-crash.patch delete mode 100644 SOURCES/0162-cxl-list-Add-support-for-filtering-by-host-identifie.patch delete mode 100644 SOURCES/0163-cxl-port-Relax-port-identifier-validation.patch delete mode 100644 SOURCES/0165-cxl-test-Add-topology-enumeration-and-hotplug-test.patch delete mode 100644 SOURCES/0167-daxctl-Fix-kernel-option-typo-in-Soft-Reservation-th.patch delete mode 100644 SOURCES/0168-meson-make-modprobedatadir-an-option.patch delete mode 100644 SOURCES/0169-namespace-action-Drop-more-zero-namespace-checks.patch delete mode 100644 SOURCES/0170-ndctl-dimm-Flush-invalidated-labels-after-overwrite.patch delete mode 100644 SOURCES/0171-libcxl-fix-a-segfault-when-memdev-pmem-is-absent.patch delete mode 100644 SOURCES/0172-ndctl-bus-Handle-missing-scrub-commands-more-gracefu.patch delete mode 100644 SOURCES/0173-util-wrapper.c-Fix-gcc-warning-in-xrealloc.patch delete mode 100644 SOURCES/0174-libcxl-Fix-memory-leakage-in-cxl_port_init.patch delete mode 100644 SOURCES/0175-cxl-list-Reformat-option-list.patch delete mode 100644 SOURCES/0176-cxl-list-Emit-endpoint-decoders-filtered-by-memdev.patch delete mode 100644 SOURCES/0177-cxl-list-Hide-0s-in-disabled-decoder-listings.patch delete mode 100644 SOURCES/0178-cxl-list-Add-DPA-span-to-endpoint-decoder-listings.patch delete mode 100644 SOURCES/0179-ccan-list-Import-latest-list-helpers.patch delete mode 100644 SOURCES/0180-cxl-lib-Maintain-decoders-in-id-order.patch delete mode 100644 SOURCES/0181-cxl-memdev-Fix-json-for-multi-device-partitioning.patch delete mode 100644 SOURCES/0182-cxl-list-Emit-mode-for-endpoint-decoder-objects.patch delete mode 100644 SOURCES/0183-cxl-set-partition-Accept-ram-as-an-alias-for-volatil.patch delete mode 100644 SOURCES/0184-cxl-memdev-Add-reserve-free-dpa-commands.patch delete mode 100644 SOURCES/0185-cxl-test-Update-CXL-memory-parameters.patch delete mode 100644 SOURCES/0186-cxl-test-Checkout-region-setup-teardown.patch delete mode 100644 SOURCES/0187-cxl-test-add-a-test-to-read-write-zero-labels.patch delete mode 100644 SOURCES/0188-cxl-list-Clarify-B-vs-P-p-root.patch delete mode 100644 SOURCES/0189-libcxl-add-a-depth-attribute-to-cxl_port.patch delete mode 100644 SOURCES/0190-cxl-port-Consolidate-the-debug-option-in-cxl-port-ma.patch delete mode 100644 SOURCES/0191-cxl-memdev-refactor-decoder-mode-string-parsing.patch delete mode 100644 SOURCES/0192-libcxl-Introduce-libcxl-region-and-mapping-objects.patch delete mode 100644 SOURCES/0193-cxl-cli-add-region-listing-support.patch delete mode 100644 SOURCES/0194-libcxl-add-low-level-APIs-for-region-creation.patch delete mode 100644 SOURCES/0195-cxl-add-a-create-region-command.patch delete mode 100644 SOURCES/0196-cxl-add-commands-to-enable-disable-destroy-region.patch delete mode 100644 SOURCES/0197-cxl-list-make-memdevs-and-regions-the-default-listin.patch delete mode 100644 SOURCES/0198-test-add-a-cxl-create-region-test.patch delete mode 100644 SOURCES/0199-cxl-decoder-add-a-max_available_extent-attribute.patch delete mode 100644 SOURCES/0200-cxl-Add-list-verbose-option-to-the-cxl-command.patch delete mode 100644 SOURCES/0201-cxl-test-Validate-endpoint-interleave-geometry.patch delete mode 100644 SOURCES/0202-cxl-list-Add-interleave-parameters-to-decoder-listin.patch delete mode 100644 SOURCES/0203-cxl-list-Add-region-to-decoder-listings.patch delete mode 100644 SOURCES/0204-cxl-list-Filter-decoders-by-region.patch delete mode 100644 SOURCES/0205-cxl-list-Add-depth-to-port-listings.patch delete mode 100644 SOURCES/0206-cxl-test-Validate-switch-port-settings-in-cxl-region.patch delete mode 100644 SOURCES/0207-meson-fix-modprobedatadir-default-value.patch delete mode 100644 SOURCES/0208-ndctl-move-developer-scripts-from-contrib-to-scripts.patch delete mode 100644 SOURCES/0209-ndctl-remove-obsolete-m4-directory.patch delete mode 100644 SOURCES/0210-ndctl-update-.gitignore.patch delete mode 100644 SOURCES/0211-scripts-fix-contrib-do_abidiff-for-updated-fedpkg.patch delete mode 100644 SOURCES/0212-scripts-update-release-helper-scripts-for-meson-and-.patch delete mode 100644 SOURCES/0213-meson.build-be-specific-for-library-path.patch delete mode 100644 SOURCES/0214-cxl-region-fix-a-dereferecnce-after-NULL-check.patch delete mode 100644 SOURCES/0215-libcxl-fox-a-resource-leak-and-a-forward-NULL-check.patch delete mode 100644 SOURCES/0216-cxl-filter-Fix-an-uninitialized-pointer-dereference.patch delete mode 100644 SOURCES/0217-ndctl-release-v74.patch diff --git a/.gitignore b/.gitignore index 80588c1..f6b12dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/ndctl-71.1.tar.gz +SOURCES/ndctl-78.tar.gz diff --git a/.ndctl.metadata b/.ndctl.metadata index e5b0136..2546fe8 100644 --- a/.ndctl.metadata +++ b/.ndctl.metadata @@ -1 +1 @@ -f8266aca55afba19aad91626a6da60e88dba0577 SOURCES/ndctl-71.1.tar.gz +458c97987feb2dbf82b95baa1ffec360b76d0db2 SOURCES/ndctl-78.tar.gz diff --git a/SOURCES/0001-test-daxctl-devices.sh-increase-the-namespace-size.patch b/SOURCES/0001-test-daxctl-devices.sh-increase-the-namespace-size.patch new file mode 100644 index 0000000..7f3642b --- /dev/null +++ b/SOURCES/0001-test-daxctl-devices.sh-increase-the-namespace-size.patch @@ -0,0 +1,41 @@ +From 95e837700d0229c2a75ca6b77e7ed0f74ae2f433 Mon Sep 17 00:00:00 2001 +From: Jeff Moyer +Date: Tue, 12 Dec 2023 16:59:54 -0500 +Subject: [PATCH 1/3] test/daxctl-devices.sh: increase the namespace size + +Memory hotplug requires the namespace to be aligned to a boundary that +depends on several factors. Upstream kernel commit fe124c95df9e +("x86/mm: use max memory block size on bare metal") increased the +typical size/alignment to 2GiB from 256MiB. As a result, this test no +longer passes on our bare metal test systems. + +This patch fixes the test failure by bumping the namespace size to +4GiB, which leaves room for aligning the start and end to 2GiB. + +Signed-off-by: Jeff Moyer + +Related: RHEL-10382diff --git a/test/daxctl-devices.sh b/test/daxctl-devices.sh +index 56c9691..dfce74b 100755 +--- + test/daxctl-devices.sh | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/test/daxctl-devices.sh b/test/daxctl-devices.sh +index 56c9691..dfce74b 100755 +--- a/test/daxctl-devices.sh ++++ b/test/daxctl-devices.sh +@@ -44,7 +44,10 @@ setup_dev() + test -n "$testdev" + + "$NDCTL" destroy-namespace -f -b "$testbus" "$testdev" +- testdev=$("$NDCTL" create-namespace -b "$testbus" -m devdax -fe "$testdev" -s 256M | \ ++ # x86_64 memory hotplug can require up to a 2GiB-aligned chunk ++ # of memory. Create a 4GiB namespace, so that we will still have ++ # enough room left after aligning the start and end. ++ testdev=$("$NDCTL" create-namespace -b "$testbus" -m devdax -fe "$testdev" -s 4G | \ + jq -er '.dev') + test -n "$testdev" + } +-- +2.39.3 + diff --git a/SOURCES/0002-ndctl-vendor-iniparser.patch b/SOURCES/0002-ndctl-vendor-iniparser.patch new file mode 100644 index 0000000..fb7191c --- /dev/null +++ b/SOURCES/0002-ndctl-vendor-iniparser.patch @@ -0,0 +1,1894 @@ +From af76c3191d7da98a82bfa5142eeac74034d0a0bd Mon Sep 17 00:00:00 2001 +From: Jeff Moyer +Date: Tue, 12 Dec 2023 17:11:16 -0500 +Subject: [PATCH 2/3] ndctl: vendor iniparser + +Upstream added a dependency on libiniparser, but that package is not +shipped in RHEL. The library was designed to be included into any +project that wishes to use it, so that's what this patch does. + +Signed-off-by: Jeff Moyer + +Related: RHEL-10382 +--- + LICENSES/other/iniparser-MIT | 21 + + meson.build | 20 +- + meson_options.txt | 2 - + util/dictionary.c | 380 ++++++++++++++++ + util/dictionary.h | 173 ++++++++ + util/iniparser.c | 836 +++++++++++++++++++++++++++++++++++ + util/iniparser.h | 358 +++++++++++++++ + util/meson.build | 3 +- + 8 files changed, 1771 insertions(+), 22 deletions(-) + create mode 100644 LICENSES/other/iniparser-MIT + create mode 100644 util/dictionary.c + create mode 100644 util/dictionary.h + create mode 100644 util/iniparser.c + create mode 100644 util/iniparser.h + +diff --git a/LICENSES/other/iniparser-MIT b/LICENSES/other/iniparser-MIT +new file mode 100644 +index 0000000..5a3a80b +--- /dev/null ++++ b/LICENSES/other/iniparser-MIT +@@ -0,0 +1,21 @@ ++Copyright (c) 2000-2011 by Nicolas Devillard. ++MIT License ++ ++Permission is hereby granted, free of charge, to any person obtaining a ++copy of this software and associated documentation files (the "Software"), ++to deal in the Software without restriction, including without limitation ++the rights to use, copy, modify, merge, publish, distribute, sublicense, ++and/or sell copies of the Software, and to permit persons to whom the ++Software is furnished to do so, subject to the following conditions: ++ ++The above copyright notice and this permission notice shall be included in ++all copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++DEALINGS IN THE SOFTWARE. ++ +diff --git a/meson.build b/meson.build +index ef001f8..2cb188f 100644 +--- a/meson.build ++++ b/meson.build +@@ -5,6 +5,7 @@ project('ndctl', 'c', + 'LGPL-2.1', + 'CC0-1.0', + 'MIT', ++ 'iniparser-MIT', + ], + default_options : [ + 'c_std=gnu99', +@@ -170,25 +171,6 @@ cc = meson.get_compiler('c') + # keyutils lacks pkgconfig + keyutils = cc.find_library('keyutils', required : get_option('keyutils')) + +-# iniparser lacks pkgconfig and its header files are either at '/usr/include' or '/usr/include/iniparser' +-# Use the path provided by user via meson configure -Diniparserdir= +-# if thats not provided then try searching for 'iniparser.h' in default system include path +-# and if that not found then as a last resort try looking at '/usr/include/iniparser' +-iniparser_headers = ['iniparser.h', 'dictionary.h'] +- +-message('Looking for iniparser include headers', iniparser_headers) +- +-iniparserdir = include_directories(includedir / get_option('iniparserdir'), is_system:true) +-iniparser = cc.find_library('iniparser', required : (get_option('iniparserdir') != '') , +- has_headers :iniparser_headers ,header_include_directories : iniparserdir) +- +-if not iniparser.found() +- iniparserdir = include_directories(includedir / 'iniparser', is_system:true) +- iniparser = cc.find_library('iniparser', required : true, has_headers : iniparser_headers, +- header_include_directories : iniparserdir) +-endif +-iniparser = declare_dependency(include_directories: iniparserdir, dependencies:iniparser) +- + conf = configuration_data() + check_headers = [ + ['HAVE_DLFCN_H', 'dlfcn.h'], +diff --git a/meson_options.txt b/meson_options.txt +index 5c41b1a..2209eab 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -24,7 +24,5 @@ option('pkgconfiglibdir', type : 'string', value : '', + description : 'directory for standard pkg-config files') + option('bashcompletiondir', type : 'string', + description : '''${datadir}/bash-completion/completions''') +-option('iniparserdir', type : 'string', +- description : 'Path containing the iniparser header files') + option('modprobedatadir', type : 'string', + description : '''${sysconfdir}/modprobe.d/''') +diff --git a/util/dictionary.c b/util/dictionary.c +new file mode 100644 +index 0000000..aa3d232 +--- /dev/null ++++ b/util/dictionary.c +@@ -0,0 +1,380 @@ ++/*-------------------------------------------------------------------------*/ ++/** ++ @file dictionary.c ++ @author N. Devillard ++ @brief Implements a dictionary for string variables. ++ ++ This module implements a simple dictionary object, i.e. a list ++ of string/string associations. This object is useful to store e.g. ++ informations retrieved from a configuration file (ini files). ++*/ ++/*--------------------------------------------------------------------------*/ ++ ++/*--------------------------------------------------------------------------- ++ Includes ++ ---------------------------------------------------------------------------*/ ++#include "dictionary.h" ++ ++#include ++#include ++#include ++#include ++ ++/** Maximum value size for integers and doubles. */ ++#define MAXVALSZ 1024 ++ ++/** Minimal allocated number of entries in a dictionary */ ++#define DICTMINSZ 128 ++ ++/** Invalid key token */ ++#define DICT_INVALID_KEY ((char*)-1) ++ ++/*--------------------------------------------------------------------------- ++ Private functions ++ ---------------------------------------------------------------------------*/ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Duplicate a string ++ @param s String to duplicate ++ @return Pointer to a newly allocated string, to be freed with free() ++ ++ This is a replacement for strdup(). This implementation is provided ++ for systems that do not have it. ++ */ ++/*--------------------------------------------------------------------------*/ ++static char * xstrdup(const char * s) ++{ ++ char * t ; ++ size_t len ; ++ if (!s) ++ return NULL ; ++ ++ len = strlen(s) + 1 ; ++ t = (char*) malloc(len) ; ++ if (t) { ++ memcpy(t, s, len) ; ++ } ++ return t ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Double the size of the dictionary ++ @param d Dictionary to grow ++ @return This function returns non-zero in case of failure ++ */ ++/*--------------------------------------------------------------------------*/ ++static int dictionary_grow(dictionary * d) ++{ ++ char ** new_val ; ++ char ** new_key ; ++ unsigned * new_hash ; ++ ++ new_val = (char**) calloc(d->size * 2, sizeof *d->val); ++ new_key = (char**) calloc(d->size * 2, sizeof *d->key); ++ new_hash = (unsigned*) calloc(d->size * 2, sizeof *d->hash); ++ if (!new_val || !new_key || !new_hash) { ++ /* An allocation failed, leave the dictionary unchanged */ ++ if (new_val) ++ free(new_val); ++ if (new_key) ++ free(new_key); ++ if (new_hash) ++ free(new_hash); ++ return -1 ; ++ } ++ /* Initialize the newly allocated space */ ++ memcpy(new_val, d->val, d->size * sizeof(char *)); ++ memcpy(new_key, d->key, d->size * sizeof(char *)); ++ memcpy(new_hash, d->hash, d->size * sizeof(unsigned)); ++ /* Delete previous data */ ++ free(d->val); ++ free(d->key); ++ free(d->hash); ++ /* Actually update the dictionary */ ++ d->size *= 2 ; ++ d->val = new_val; ++ d->key = new_key; ++ d->hash = new_hash; ++ return 0 ; ++} ++ ++/*--------------------------------------------------------------------------- ++ Function codes ++ ---------------------------------------------------------------------------*/ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Compute the hash key for a string. ++ @param key Character string to use for key. ++ @return 1 unsigned int on at least 32 bits. ++ ++ This hash function has been taken from an Article in Dr Dobbs Journal. ++ This is normally a collision-free function, distributing keys evenly. ++ The key is stored anyway in the struct so that collision can be avoided ++ by comparing the key itself in last resort. ++ */ ++/*--------------------------------------------------------------------------*/ ++unsigned dictionary_hash(const char * key) ++{ ++ size_t len ; ++ unsigned hash ; ++ size_t i ; ++ ++ if (!key) ++ return 0 ; ++ ++ len = strlen(key); ++ for (hash=0, i=0 ; i>6) ; ++ } ++ hash += (hash <<3); ++ hash ^= (hash >>11); ++ hash += (hash <<15); ++ return hash ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Create a new dictionary object. ++ @param size Optional initial size of the dictionary. ++ @return 1 newly allocated dictionary object. ++ ++ This function allocates a new dictionary object of given size and returns ++ it. If you do not know in advance (roughly) the number of entries in the ++ dictionary, give size=0. ++ */ ++/*-------------------------------------------------------------------------*/ ++dictionary * dictionary_new(size_t size) ++{ ++ dictionary * d ; ++ ++ /* If no size was specified, allocate space for DICTMINSZ */ ++ if (sizesize = size ; ++ d->val = (char**) calloc(size, sizeof *d->val); ++ d->key = (char**) calloc(size, sizeof *d->key); ++ d->hash = (unsigned*) calloc(size, sizeof *d->hash); ++ } ++ return d ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Delete a dictionary object ++ @param d dictionary object to deallocate. ++ @return void ++ ++ Deallocate a dictionary object and all memory associated to it. ++ */ ++/*--------------------------------------------------------------------------*/ ++void dictionary_del(dictionary * d) ++{ ++ ssize_t i ; ++ ++ if (d==NULL) return ; ++ for (i=0 ; isize ; i++) { ++ if (d->key[i]!=NULL) ++ free(d->key[i]); ++ if (d->val[i]!=NULL) ++ free(d->val[i]); ++ } ++ free(d->val); ++ free(d->key); ++ free(d->hash); ++ free(d); ++ return ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get a value from a dictionary. ++ @param d dictionary object to search. ++ @param key Key to look for in the dictionary. ++ @param def Default value to return if key not found. ++ @return 1 pointer to internally allocated character string. ++ ++ This function locates a key in a dictionary and returns a pointer to its ++ value, or the passed 'def' pointer if no such key can be found in ++ dictionary. The returned character pointer points to data internal to the ++ dictionary object, you should not try to free it or modify it. ++ */ ++/*--------------------------------------------------------------------------*/ ++const char * dictionary_get(const dictionary * d, const char * key, const char * def) ++{ ++ unsigned hash ; ++ ssize_t i ; ++ ++ hash = dictionary_hash(key); ++ for (i=0 ; isize ; i++) { ++ if (d->key[i]==NULL) ++ continue ; ++ /* Compare hash */ ++ if (hash==d->hash[i]) { ++ /* Compare string, to avoid hash collisions */ ++ if (!strcmp(key, d->key[i])) { ++ return d->val[i] ; ++ } ++ } ++ } ++ return def ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Set a value in a dictionary. ++ @param d dictionary object to modify. ++ @param key Key to modify or add. ++ @param val Value to add. ++ @return int 0 if Ok, anything else otherwise ++ ++ If the given key is found in the dictionary, the associated value is ++ replaced by the provided one. If the key cannot be found in the ++ dictionary, it is added to it. ++ ++ It is Ok to provide a NULL value for val, but NULL values for the dictionary ++ or the key are considered as errors: the function will return immediately ++ in such a case. ++ ++ Notice that if you dictionary_set a variable to NULL, a call to ++ dictionary_get will return a NULL value: the variable will be found, and ++ its value (NULL) is returned. In other words, setting the variable ++ content to NULL is equivalent to deleting the variable from the ++ dictionary. It is not possible (in this implementation) to have a key in ++ the dictionary without value. ++ ++ This function returns non-zero in case of failure. ++ */ ++/*--------------------------------------------------------------------------*/ ++int dictionary_set(dictionary * d, const char * key, const char * val) ++{ ++ ssize_t i ; ++ unsigned hash ; ++ ++ if (d==NULL || key==NULL) return -1 ; ++ ++ /* Compute hash for this key */ ++ hash = dictionary_hash(key) ; ++ /* Find if value is already in dictionary */ ++ if (d->n>0) { ++ for (i=0 ; isize ; i++) { ++ if (d->key[i]==NULL) ++ continue ; ++ if (hash==d->hash[i]) { /* Same hash value */ ++ if (!strcmp(key, d->key[i])) { /* Same key */ ++ /* Found a value: modify and return */ ++ if (d->val[i]!=NULL) ++ free(d->val[i]); ++ d->val[i] = (val ? xstrdup(val) : NULL); ++ /* Value has been modified: return */ ++ return 0 ; ++ } ++ } ++ } ++ } ++ /* Add a new value */ ++ /* See if dictionary needs to grow */ ++ if (d->n==d->size) { ++ /* Reached maximum size: reallocate dictionary */ ++ if (dictionary_grow(d) != 0) ++ return -1; ++ } ++ ++ /* Insert key in the first empty slot. Start at d->n and wrap at ++ d->size. Because d->n < d->size this will necessarily ++ terminate. */ ++ for (i=d->n ; d->key[i] ; ) { ++ if(++i == d->size) i = 0; ++ } ++ /* Copy key */ ++ d->key[i] = xstrdup(key); ++ d->val[i] = (val ? xstrdup(val) : NULL) ; ++ d->hash[i] = hash; ++ d->n ++ ; ++ return 0 ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Delete a key in a dictionary ++ @param d dictionary object to modify. ++ @param key Key to remove. ++ @return void ++ ++ This function deletes a key in a dictionary. Nothing is done if the ++ key cannot be found. ++ */ ++/*--------------------------------------------------------------------------*/ ++void dictionary_unset(dictionary * d, const char * key) ++{ ++ unsigned hash ; ++ ssize_t i ; ++ ++ if (key == NULL || d == NULL) { ++ return; ++ } ++ ++ hash = dictionary_hash(key); ++ for (i=0 ; isize ; i++) { ++ if (d->key[i]==NULL) ++ continue ; ++ /* Compare hash */ ++ if (hash==d->hash[i]) { ++ /* Compare string, to avoid hash collisions */ ++ if (!strcmp(key, d->key[i])) { ++ /* Found key */ ++ break ; ++ } ++ } ++ } ++ if (i>=d->size) ++ /* Key not found */ ++ return ; ++ ++ free(d->key[i]); ++ d->key[i] = NULL ; ++ if (d->val[i]!=NULL) { ++ free(d->val[i]); ++ d->val[i] = NULL ; ++ } ++ d->hash[i] = 0 ; ++ d->n -- ; ++ return ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Dump a dictionary to an opened file pointer. ++ @param d Dictionary to dump ++ @param f Opened file pointer. ++ @return void ++ ++ Dumps a dictionary onto an opened file pointer. Key pairs are printed out ++ as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as ++ output file pointers. ++ */ ++/*--------------------------------------------------------------------------*/ ++void dictionary_dump(const dictionary * d, FILE * out) ++{ ++ ssize_t i ; ++ ++ if (d==NULL || out==NULL) return ; ++ if (d->n<1) { ++ fprintf(out, "empty dictionary\n"); ++ return ; ++ } ++ for (i=0 ; isize ; i++) { ++ if (d->key[i]) { ++ fprintf(out, "%20s\t[%s]\n", ++ d->key[i], ++ d->val[i] ? d->val[i] : "UNDEF"); ++ } ++ } ++ return ; ++} +diff --git a/util/dictionary.h b/util/dictionary.h +new file mode 100644 +index 0000000..f0fd540 +--- /dev/null ++++ b/util/dictionary.h +@@ -0,0 +1,173 @@ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @file dictionary.h ++ @author N. Devillard ++ @brief Implements a dictionary for string variables. ++ ++ This module implements a simple dictionary object, i.e. a list ++ of string/string associations. This object is useful to store e.g. ++ informations retrieved from a configuration file (ini files). ++*/ ++/*--------------------------------------------------------------------------*/ ++ ++#ifndef _DICTIONARY_H_ ++#define _DICTIONARY_H_ ++ ++/*--------------------------------------------------------------------------- ++ Includes ++ ---------------------------------------------------------------------------*/ ++ ++#include ++#include ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*--------------------------------------------------------------------------- ++ New types ++ ---------------------------------------------------------------------------*/ ++ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Dictionary object ++ ++ This object contains a list of string/string associations. Each ++ association is identified by a unique string key. Looking up values ++ in the dictionary is speeded up by the use of a (hopefully collision-free) ++ hash function. ++ */ ++/*-------------------------------------------------------------------------*/ ++typedef struct _dictionary_ { ++ int n ; /** Number of entries in dictionary */ ++ ssize_t size ; /** Storage size */ ++ char ** val ; /** List of string values */ ++ char ** key ; /** List of string keys */ ++ unsigned * hash ; /** List of hash values for keys */ ++} dictionary ; ++ ++ ++/*--------------------------------------------------------------------------- ++ Function prototypes ++ ---------------------------------------------------------------------------*/ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Compute the hash key for a string. ++ @param key Character string to use for key. ++ @return 1 unsigned int on at least 32 bits. ++ ++ This hash function has been taken from an Article in Dr Dobbs Journal. ++ This is normally a collision-free function, distributing keys evenly. ++ The key is stored anyway in the struct so that collision can be avoided ++ by comparing the key itself in last resort. ++ */ ++/*--------------------------------------------------------------------------*/ ++unsigned dictionary_hash(const char * key); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Create a new dictionary object. ++ @param size Optional initial size of the dictionary. ++ @return 1 newly allocated dictionary object. ++ ++ This function allocates a new dictionary object of given size and returns ++ it. If you do not know in advance (roughly) the number of entries in the ++ dictionary, give size=0. ++ */ ++/*--------------------------------------------------------------------------*/ ++dictionary * dictionary_new(size_t size); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Delete a dictionary object ++ @param d dictionary object to deallocate. ++ @return void ++ ++ Deallocate a dictionary object and all memory associated to it. ++ */ ++/*--------------------------------------------------------------------------*/ ++void dictionary_del(dictionary * vd); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get a value from a dictionary. ++ @param d dictionary object to search. ++ @param key Key to look for in the dictionary. ++ @param def Default value to return if key not found. ++ @return 1 pointer to internally allocated character string. ++ ++ This function locates a key in a dictionary and returns a pointer to its ++ value, or the passed 'def' pointer if no such key can be found in ++ dictionary. The returned character pointer points to data internal to the ++ dictionary object, you should not try to free it or modify it. ++ */ ++/*--------------------------------------------------------------------------*/ ++const char * dictionary_get(const dictionary * d, const char * key, const char * def); ++ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Set a value in a dictionary. ++ @param d dictionary object to modify. ++ @param key Key to modify or add. ++ @param val Value to add. ++ @return int 0 if Ok, anything else otherwise ++ ++ If the given key is found in the dictionary, the associated value is ++ replaced by the provided one. If the key cannot be found in the ++ dictionary, it is added to it. ++ ++ It is Ok to provide a NULL value for val, but NULL values for the dictionary ++ or the key are considered as errors: the function will return immediately ++ in such a case. ++ ++ Notice that if you dictionary_set a variable to NULL, a call to ++ dictionary_get will return a NULL value: the variable will be found, and ++ its value (NULL) is returned. In other words, setting the variable ++ content to NULL is equivalent to deleting the variable from the ++ dictionary. It is not possible (in this implementation) to have a key in ++ the dictionary without value. ++ ++ This function returns non-zero in case of failure. ++ */ ++/*--------------------------------------------------------------------------*/ ++int dictionary_set(dictionary * vd, const char * key, const char * val); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Delete a key in a dictionary ++ @param d dictionary object to modify. ++ @param key Key to remove. ++ @return void ++ ++ This function deletes a key in a dictionary. Nothing is done if the ++ key cannot be found. ++ */ ++/*--------------------------------------------------------------------------*/ ++void dictionary_unset(dictionary * d, const char * key); ++ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Dump a dictionary to an opened file pointer. ++ @param d Dictionary to dump ++ @param f Opened file pointer. ++ @return void ++ ++ Dumps a dictionary onto an opened file pointer. Key pairs are printed out ++ as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as ++ output file pointers. ++ */ ++/*--------------------------------------------------------------------------*/ ++void dictionary_dump(const dictionary * d, FILE * out); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/util/iniparser.c b/util/iniparser.c +new file mode 100644 +index 0000000..dbceb20 +--- /dev/null ++++ b/util/iniparser.c +@@ -0,0 +1,836 @@ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @file iniparser.c ++ @author N. Devillard ++ @brief Parser for ini files. ++*/ ++/*--------------------------------------------------------------------------*/ ++/*---------------------------- Includes ------------------------------------*/ ++#include ++#include ++#include "iniparser.h" ++ ++/*---------------------------- Defines -------------------------------------*/ ++#define ASCIILINESZ (1024) ++#define INI_INVALID_KEY ((char*)-1) ++ ++/*--------------------------------------------------------------------------- ++ Private to this module ++ ---------------------------------------------------------------------------*/ ++/** ++ * This enum stores the status for each parsed line (internal use only). ++ */ ++typedef enum _line_status_ { ++ LINE_UNPROCESSED, ++ LINE_ERROR, ++ LINE_EMPTY, ++ LINE_COMMENT, ++ LINE_SECTION, ++ LINE_VALUE ++} line_status ; ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Convert a string to lowercase. ++ @param in String to convert. ++ @param out Output buffer. ++ @param len Size of the out buffer. ++ @return ptr to the out buffer or NULL if an error occured. ++ ++ This function convert a string into lowercase. ++ At most len - 1 elements of the input string will be converted. ++ */ ++/*--------------------------------------------------------------------------*/ ++static const char * strlwc(const char * in, char *out, unsigned len) ++{ ++ unsigned i ; ++ ++ if (in==NULL || out == NULL || len==0) return NULL ; ++ i=0 ; ++ while (in[i] != '\0' && i < len-1) { ++ out[i] = (char)tolower((int)in[i]); ++ i++ ; ++ } ++ out[i] = '\0'; ++ return out ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Duplicate a string ++ @param s String to duplicate ++ @return Pointer to a newly allocated string, to be freed with free() ++ ++ This is a replacement for strdup(). This implementation is provided ++ for systems that do not have it. ++ */ ++/*--------------------------------------------------------------------------*/ ++static char * xstrdup(const char * s) ++{ ++ char * t ; ++ size_t len ; ++ if (!s) ++ return NULL ; ++ ++ len = strlen(s) + 1 ; ++ t = (char*) malloc(len) ; ++ if (t) { ++ memcpy(t, s, len) ; ++ } ++ return t ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Remove blanks at the beginning and the end of a string. ++ @param str String to parse and alter. ++ @return unsigned New size of the string. ++ */ ++/*--------------------------------------------------------------------------*/ ++static unsigned strstrip(char * s) ++{ ++ char *last = NULL ; ++ char *dest = s; ++ ++ if (s==NULL) return 0; ++ ++ last = s + strlen(s); ++ while (isspace((int)*s) && *s) s++; ++ while (last > s) { ++ if (!isspace((int)*(last-1))) ++ break ; ++ last -- ; ++ } ++ *last = (char)0; ++ ++ memmove(dest,s,last - s + 1); ++ return last - s; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Default error callback for iniparser: wraps `fprintf(stderr, ...)`. ++ */ ++/*--------------------------------------------------------------------------*/ ++static int default_error_callback(const char *format, ...) ++{ ++ int ret; ++ va_list argptr; ++ va_start(argptr, format); ++ ret = vfprintf(stderr, format, argptr); ++ va_end(argptr); ++ return ret; ++} ++ ++static int (*iniparser_error_callback)(const char*, ...) = default_error_callback; ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Configure a function to receive the error messages. ++ @param errback Function to call. ++ ++ By default, the error will be printed on stderr. If a null pointer is passed ++ as errback the error callback will be switched back to default. ++ */ ++/*--------------------------------------------------------------------------*/ ++void iniparser_set_error_callback(int (*errback)(const char *, ...)) ++{ ++ if (errback) { ++ iniparser_error_callback = errback; ++ } else { ++ iniparser_error_callback = default_error_callback; ++ } ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get number of sections in a dictionary ++ @param d Dictionary to examine ++ @return int Number of sections found in dictionary ++ ++ This function returns the number of sections found in a dictionary. ++ The test to recognize sections is done on the string stored in the ++ dictionary: a section name is given as "section" whereas a key is ++ stored as "section:key", thus the test looks for entries that do not ++ contain a colon. ++ ++ This clearly fails in the case a section name contains a colon, but ++ this should simply be avoided. ++ ++ This function returns -1 in case of error. ++ */ ++/*--------------------------------------------------------------------------*/ ++int iniparser_getnsec(const dictionary * d) ++{ ++ int i ; ++ int nsec ; ++ ++ if (d==NULL) return -1 ; ++ nsec=0 ; ++ for (i=0 ; isize ; i++) { ++ if (d->key[i]==NULL) ++ continue ; ++ if (strchr(d->key[i], ':')==NULL) { ++ nsec ++ ; ++ } ++ } ++ return nsec ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get name for section n in a dictionary. ++ @param d Dictionary to examine ++ @param n Section number (from 0 to nsec-1). ++ @return Pointer to char string ++ ++ This function locates the n-th section in a dictionary and returns ++ its name as a pointer to a string statically allocated inside the ++ dictionary. Do not free or modify the returned string! ++ ++ This function returns NULL in case of error. ++ */ ++/*--------------------------------------------------------------------------*/ ++const char * iniparser_getsecname(const dictionary * d, int n) ++{ ++ int i ; ++ int foundsec ; ++ ++ if (d==NULL || n<0) return NULL ; ++ foundsec=0 ; ++ for (i=0 ; isize ; i++) { ++ if (d->key[i]==NULL) ++ continue ; ++ if (strchr(d->key[i], ':')==NULL) { ++ foundsec++ ; ++ if (foundsec>n) ++ break ; ++ } ++ } ++ if (foundsec<=n) { ++ return NULL ; ++ } ++ return d->key[i] ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Dump a dictionary to an opened file pointer. ++ @param d Dictionary to dump. ++ @param f Opened file pointer to dump to. ++ @return void ++ ++ This function prints out the contents of a dictionary, one element by ++ line, onto the provided file pointer. It is OK to specify @c stderr ++ or @c stdout as output files. This function is meant for debugging ++ purposes mostly. ++ */ ++/*--------------------------------------------------------------------------*/ ++void iniparser_dump(const dictionary * d, FILE * f) ++{ ++ int i ; ++ ++ if (d==NULL || f==NULL) return ; ++ for (i=0 ; isize ; i++) { ++ if (d->key[i]==NULL) ++ continue ; ++ if (d->val[i]!=NULL) { ++ fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]); ++ } else { ++ fprintf(f, "[%s]=UNDEF\n", d->key[i]); ++ } ++ } ++ return ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Save a dictionary to a loadable ini file ++ @param d Dictionary to dump ++ @param f Opened file pointer to dump to ++ @return void ++ ++ This function dumps a given dictionary into a loadable ini file. ++ It is Ok to specify @c stderr or @c stdout as output files. ++ */ ++/*--------------------------------------------------------------------------*/ ++void iniparser_dump_ini(const dictionary * d, FILE * f) ++{ ++ int i ; ++ int nsec ; ++ const char * secname ; ++ ++ if (d==NULL || f==NULL) return ; ++ ++ nsec = iniparser_getnsec(d); ++ if (nsec<1) { ++ /* No section in file: dump all keys as they are */ ++ for (i=0 ; isize ; i++) { ++ if (d->key[i]==NULL) ++ continue ; ++ fprintf(f, "%s = %s\n", d->key[i], d->val[i]); ++ } ++ return ; ++ } ++ for (i=0 ; isize ; j++) { ++ if (d->key[j]==NULL) ++ continue ; ++ if (!strncmp(d->key[j], keym, seclen+1)) { ++ fprintf(f, ++ "%-30s = %s\n", ++ d->key[j]+seclen+1, ++ d->val[j] ? d->val[j] : ""); ++ } ++ } ++ fprintf(f, "\n"); ++ return ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the number of keys in a section of a dictionary. ++ @param d Dictionary to examine ++ @param s Section name of dictionary to examine ++ @return Number of keys in section ++ */ ++/*--------------------------------------------------------------------------*/ ++int iniparser_getsecnkeys(const dictionary * d, const char * s) ++{ ++ int seclen, nkeys ; ++ char keym[ASCIILINESZ+1]; ++ int j ; ++ ++ nkeys = 0; ++ ++ if (d==NULL) return nkeys; ++ if (! iniparser_find_entry(d, s)) return nkeys; ++ ++ seclen = (int)strlen(s); ++ strlwc(s, keym, sizeof(keym)); ++ keym[seclen] = ':'; ++ ++ for (j=0 ; jsize ; j++) { ++ if (d->key[j]==NULL) ++ continue ; ++ if (!strncmp(d->key[j], keym, seclen+1)) ++ nkeys++; ++ } ++ ++ return nkeys; ++ ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the number of keys in a section of a dictionary. ++ @param d Dictionary to examine ++ @param s Section name of dictionary to examine ++ @param keys Already allocated array to store the keys in ++ @return The pointer passed as `keys` argument or NULL in case of error ++ ++ This function queries a dictionary and finds all keys in a given section. ++ The keys argument should be an array of pointers which size has been ++ determined by calling `iniparser_getsecnkeys` function prior to this one. ++ ++ Each pointer in the returned char pointer-to-pointer is pointing to ++ a string allocated in the dictionary; do not free or modify them. ++ */ ++/*--------------------------------------------------------------------------*/ ++const char ** iniparser_getseckeys(const dictionary * d, const char * s, const char ** keys) ++{ ++ int i, j, seclen ; ++ char keym[ASCIILINESZ+1]; ++ ++ if (d==NULL || keys==NULL) return NULL; ++ if (! iniparser_find_entry(d, s)) return NULL; ++ ++ seclen = (int)strlen(s); ++ strlwc(s, keym, sizeof(keym)); ++ keym[seclen] = ':'; ++ ++ i = 0; ++ ++ for (j=0 ; jsize ; j++) { ++ if (d->key[j]==NULL) ++ continue ; ++ if (!strncmp(d->key[j], keym, seclen+1)) { ++ keys[i] = d->key[j]; ++ i++; ++ } ++ } ++ ++ return keys; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the string associated to a key ++ @param d Dictionary to search ++ @param key Key string to look for ++ @param def Default value to return if key not found. ++ @return pointer to statically allocated character string ++ ++ This function queries a dictionary for a key. A key as read from an ++ ini file is given as "section:key". If the key cannot be found, ++ the pointer passed as 'def' is returned. ++ The returned char pointer is pointing to a string allocated in ++ the dictionary, do not free or modify it. ++ */ ++/*--------------------------------------------------------------------------*/ ++const char * iniparser_getstring(const dictionary * d, const char * key, const char * def) ++{ ++ const char * lc_key ; ++ const char * sval ; ++ char tmp_str[ASCIILINESZ+1]; ++ ++ if (d==NULL || key==NULL) ++ return def ; ++ ++ lc_key = strlwc(key, tmp_str, sizeof(tmp_str)); ++ sval = dictionary_get(d, lc_key, def); ++ return sval ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the string associated to a key, convert to an long int ++ @param d Dictionary to search ++ @param key Key string to look for ++ @param notfound Value to return in case of error ++ @return long integer ++ ++ This function queries a dictionary for a key. A key as read from an ++ ini file is given as "section:key". If the key cannot be found, ++ the notfound value is returned. ++ ++ Supported values for integers include the usual C notation ++ so decimal, octal (starting with 0) and hexadecimal (starting with 0x) ++ are supported. Examples: ++ ++ "42" -> 42 ++ "042" -> 34 (octal -> decimal) ++ "0x42" -> 66 (hexa -> decimal) ++ ++ Warning: the conversion may overflow in various ways. Conversion is ++ totally outsourced to strtol(), see the associated man page for overflow ++ handling. ++ ++ Credits: Thanks to A. Becker for suggesting strtol() ++ */ ++/*--------------------------------------------------------------------------*/ ++long int iniparser_getlongint(const dictionary * d, const char * key, long int notfound) ++{ ++ const char * str ; ++ ++ str = iniparser_getstring(d, key, INI_INVALID_KEY); ++ if (str==NULL || str==INI_INVALID_KEY) return notfound ; ++ return strtol(str, NULL, 0); ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the string associated to a key, convert to an int ++ @param d Dictionary to search ++ @param key Key string to look for ++ @param notfound Value to return in case of error ++ @return integer ++ ++ This function queries a dictionary for a key. A key as read from an ++ ini file is given as "section:key". If the key cannot be found, ++ the notfound value is returned. ++ ++ Supported values for integers include the usual C notation ++ so decimal, octal (starting with 0) and hexadecimal (starting with 0x) ++ are supported. Examples: ++ ++ "42" -> 42 ++ "042" -> 34 (octal -> decimal) ++ "0x42" -> 66 (hexa -> decimal) ++ ++ Warning: the conversion may overflow in various ways. Conversion is ++ totally outsourced to strtol(), see the associated man page for overflow ++ handling. ++ ++ Credits: Thanks to A. Becker for suggesting strtol() ++ */ ++/*--------------------------------------------------------------------------*/ ++int iniparser_getint(const dictionary * d, const char * key, int notfound) ++{ ++ return (int)iniparser_getlongint(d, key, notfound); ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the string associated to a key, convert to a double ++ @param d Dictionary to search ++ @param key Key string to look for ++ @param notfound Value to return in case of error ++ @return double ++ ++ This function queries a dictionary for a key. A key as read from an ++ ini file is given as "section:key". If the key cannot be found, ++ the notfound value is returned. ++ */ ++/*--------------------------------------------------------------------------*/ ++double iniparser_getdouble(const dictionary * d, const char * key, double notfound) ++{ ++ const char * str ; ++ ++ str = iniparser_getstring(d, key, INI_INVALID_KEY); ++ if (str==NULL || str==INI_INVALID_KEY) return notfound ; ++ return atof(str); ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the string associated to a key, convert to a boolean ++ @param d Dictionary to search ++ @param key Key string to look for ++ @param notfound Value to return in case of error ++ @return integer ++ ++ This function queries a dictionary for a key. A key as read from an ++ ini file is given as "section:key". If the key cannot be found, ++ the notfound value is returned. ++ ++ A true boolean is found if one of the following is matched: ++ ++ - A string starting with 'y' ++ - A string starting with 'Y' ++ - A string starting with 't' ++ - A string starting with 'T' ++ - A string starting with '1' ++ ++ A false boolean is found if one of the following is matched: ++ ++ - A string starting with 'n' ++ - A string starting with 'N' ++ - A string starting with 'f' ++ - A string starting with 'F' ++ - A string starting with '0' ++ ++ The notfound value returned if no boolean is identified, does not ++ necessarily have to be 0 or 1. ++ */ ++/*--------------------------------------------------------------------------*/ ++int iniparser_getboolean(const dictionary * d, const char * key, int notfound) ++{ ++ int ret ; ++ const char * c ; ++ ++ c = iniparser_getstring(d, key, INI_INVALID_KEY); ++ if (c==NULL || c==INI_INVALID_KEY) return notfound ; ++ if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') { ++ ret = 1 ; ++ } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') { ++ ret = 0 ; ++ } else { ++ ret = notfound ; ++ } ++ return ret; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Finds out if a given entry exists in a dictionary ++ @param ini Dictionary to search ++ @param entry Name of the entry to look for ++ @return integer 1 if entry exists, 0 otherwise ++ ++ Finds out if a given entry exists in the dictionary. Since sections ++ are stored as keys with NULL associated values, this is the only way ++ of querying for the presence of sections in a dictionary. ++ */ ++/*--------------------------------------------------------------------------*/ ++int iniparser_find_entry(const dictionary * ini, const char * entry) ++{ ++ int found=0 ; ++ if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) { ++ found = 1 ; ++ } ++ return found ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Set an entry in a dictionary. ++ @param ini Dictionary to modify. ++ @param entry Entry to modify (entry name) ++ @param val New value to associate to the entry. ++ @return int 0 if Ok, -1 otherwise. ++ ++ If the given entry can be found in the dictionary, it is modified to ++ contain the provided value. If it cannot be found, the entry is created. ++ It is Ok to set val to NULL. ++ */ ++/*--------------------------------------------------------------------------*/ ++int iniparser_set(dictionary * ini, const char * entry, const char * val) ++{ ++ char tmp_str[ASCIILINESZ+1]; ++ return dictionary_set(ini, strlwc(entry, tmp_str, sizeof(tmp_str)), val) ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Delete an entry in a dictionary ++ @param ini Dictionary to modify ++ @param entry Entry to delete (entry name) ++ @return void ++ ++ If the given entry can be found, it is deleted from the dictionary. ++ */ ++/*--------------------------------------------------------------------------*/ ++void iniparser_unset(dictionary * ini, const char * entry) ++{ ++ char tmp_str[ASCIILINESZ+1]; ++ dictionary_unset(ini, strlwc(entry, tmp_str, sizeof(tmp_str))); ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Load a single line from an INI file ++ @param input_line Input line, may be concatenated multi-line input ++ @param section Output space to store section ++ @param key Output space to store key ++ @param value Output space to store value ++ @return line_status value ++ */ ++/*--------------------------------------------------------------------------*/ ++static line_status iniparser_line( ++ const char * input_line, ++ char * section, ++ char * key, ++ char * value) ++{ ++ line_status sta ; ++ char * line = NULL; ++ size_t len ; ++ ++ line = xstrdup(input_line); ++ len = strstrip(line); ++ ++ sta = LINE_UNPROCESSED ; ++ if (len<1) { ++ /* Empty line */ ++ sta = LINE_EMPTY ; ++ } else if (line[0]=='#' || line[0]==';') { ++ /* Comment line */ ++ sta = LINE_COMMENT ; ++ } else if (line[0]=='[' && line[len-1]==']') { ++ /* Section name */ ++ sscanf(line, "[%[^]]", section); ++ strstrip(section); ++ strlwc(section, section, len); ++ sta = LINE_SECTION ; ++ } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2 ++ || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2) { ++ /* Usual key=value with quotes, with or without comments */ ++ strstrip(key); ++ strlwc(key, key, len); ++ /* Don't strip spaces from values surrounded with quotes */ ++ sta = LINE_VALUE ; ++ } else if (sscanf (line, "%[^=] = %[^;#]", key, value) == 2) { ++ /* Usual key=value without quotes, with or without comments */ ++ strstrip(key); ++ strlwc(key, key, len); ++ strstrip(value); ++ /* ++ * sscanf cannot handle '' or "" as empty values ++ * this is done here ++ */ ++ if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) { ++ value[0]=0 ; ++ } ++ sta = LINE_VALUE ; ++ } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2 ++ || sscanf(line, "%[^=] %[=]", key, value) == 2) { ++ /* ++ * Special cases: ++ * key= ++ * key=; ++ * key=# ++ */ ++ strstrip(key); ++ strlwc(key, key, len); ++ value[0]=0 ; ++ sta = LINE_VALUE ; ++ } else { ++ /* Generate syntax error */ ++ sta = LINE_ERROR ; ++ } ++ ++ free(line); ++ return sta ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Parse an ini file and return an allocated dictionary object ++ @param ininame Name of the ini file to read. ++ @return Pointer to newly allocated dictionary ++ ++ This is the parser for ini files. This function is called, providing ++ the name of the file to be read. It returns a dictionary object that ++ should not be accessed directly, but through accessor functions ++ instead. ++ ++ The returned dictionary must be freed using iniparser_freedict(). ++ */ ++/*--------------------------------------------------------------------------*/ ++dictionary * iniparser_load(const char * ininame) ++{ ++ FILE * in ; ++ ++ char line [ASCIILINESZ+1] ; ++ char section [ASCIILINESZ+1] ; ++ char key [ASCIILINESZ+1] ; ++ char tmp [(ASCIILINESZ * 2) + 2] ; ++ char val [ASCIILINESZ+1] ; ++ ++ int last=0 ; ++ int len ; ++ int lineno=0 ; ++ int errs=0; ++ int mem_err=0; ++ ++ dictionary * dict ; ++ ++ if ((in=fopen(ininame, "r"))==NULL) { ++ iniparser_error_callback("iniparser: cannot open %s\n", ininame); ++ return NULL ; ++ } ++ ++ dict = dictionary_new(0) ; ++ if (!dict) { ++ fclose(in); ++ return NULL ; ++ } ++ ++ memset(line, 0, ASCIILINESZ); ++ memset(section, 0, ASCIILINESZ); ++ memset(key, 0, ASCIILINESZ); ++ memset(val, 0, ASCIILINESZ); ++ last=0 ; ++ ++ while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) { ++ lineno++ ; ++ len = (int)strlen(line)-1; ++ if (len<=0) ++ continue; ++ /* Safety check against buffer overflows */ ++ if (line[len]!='\n' && !feof(in)) { ++ iniparser_error_callback( ++ "iniparser: input line too long in %s (%d)\n", ++ ininame, ++ lineno); ++ dictionary_del(dict); ++ fclose(in); ++ return NULL ; ++ } ++ /* Get rid of \n and spaces at end of line */ ++ while ((len>=0) && ++ ((line[len]=='\n') || (isspace(line[len])))) { ++ line[len]=0 ; ++ len-- ; ++ } ++ if (len < 0) { /* Line was entirely \n and/or spaces */ ++ len = 0; ++ } ++ /* Detect multi-line */ ++ if (line[len]=='\\') { ++ /* Multi-line value */ ++ last=len ; ++ continue ; ++ } else { ++ last=0 ; ++ } ++ switch (iniparser_line(line, section, key, val)) { ++ case LINE_EMPTY: ++ case LINE_COMMENT: ++ break ; ++ ++ case LINE_SECTION: ++ mem_err = dictionary_set(dict, section, NULL); ++ break ; ++ ++ case LINE_VALUE: ++ sprintf(tmp, "%s:%s", section, key); ++ mem_err = dictionary_set(dict, tmp, val); ++ break ; ++ ++ case LINE_ERROR: ++ iniparser_error_callback( ++ "iniparser: syntax error in %s (%d):\n-> %s\n", ++ ininame, ++ lineno, ++ line); ++ errs++ ; ++ break; ++ ++ default: ++ break ; ++ } ++ memset(line, 0, ASCIILINESZ); ++ last=0; ++ if (mem_err<0) { ++ iniparser_error_callback("iniparser: memory allocation failure\n"); ++ break ; ++ } ++ } ++ if (errs) { ++ dictionary_del(dict); ++ dict = NULL ; ++ } ++ fclose(in); ++ return dict ; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Free all memory associated to an ini dictionary ++ @param d Dictionary to free ++ @return void ++ ++ Free all memory associated to an ini dictionary. ++ It is mandatory to call this function before the dictionary object ++ gets out of the current context. ++ */ ++/*--------------------------------------------------------------------------*/ ++void iniparser_freedict(dictionary * d) ++{ ++ dictionary_del(d); ++} +diff --git a/util/iniparser.h b/util/iniparser.h +new file mode 100644 +index 0000000..37ff7b7 +--- /dev/null ++++ b/util/iniparser.h +@@ -0,0 +1,358 @@ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @file iniparser.h ++ @author N. Devillard ++ @brief Parser for ini files. ++*/ ++/*--------------------------------------------------------------------------*/ ++ ++#ifndef _INIPARSER_H_ ++#define _INIPARSER_H_ ++ ++/*--------------------------------------------------------------------------- ++ Includes ++ ---------------------------------------------------------------------------*/ ++ ++#include ++#include ++#include ++ ++/* ++ * The following #include is necessary on many Unixes but not Linux. ++ * It is not needed for Windows platforms. ++ * Uncomment it if needed. ++ */ ++/* #include */ ++ ++#include "dictionary.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Configure a function to receive the error messages. ++ @param errback Function to call. ++ ++ By default, the error will be printed on stderr. If a null pointer is passed ++ as errback the error callback will be switched back to default. ++ */ ++/*--------------------------------------------------------------------------*/ ++ ++void iniparser_set_error_callback(int (*errback)(const char *, ...)); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get number of sections in a dictionary ++ @param d Dictionary to examine ++ @return int Number of sections found in dictionary ++ ++ This function returns the number of sections found in a dictionary. ++ The test to recognize sections is done on the string stored in the ++ dictionary: a section name is given as "section" whereas a key is ++ stored as "section:key", thus the test looks for entries that do not ++ contain a colon. ++ ++ This clearly fails in the case a section name contains a colon, but ++ this should simply be avoided. ++ ++ This function returns -1 in case of error. ++ */ ++/*--------------------------------------------------------------------------*/ ++ ++int iniparser_getnsec(const dictionary * d); ++ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get name for section n in a dictionary. ++ @param d Dictionary to examine ++ @param n Section number (from 0 to nsec-1). ++ @return Pointer to char string ++ ++ This function locates the n-th section in a dictionary and returns ++ its name as a pointer to a string statically allocated inside the ++ dictionary. Do not free or modify the returned string! ++ ++ This function returns NULL in case of error. ++ */ ++/*--------------------------------------------------------------------------*/ ++ ++const char * iniparser_getsecname(const dictionary * d, int n); ++ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Save a dictionary to a loadable ini file ++ @param d Dictionary to dump ++ @param f Opened file pointer to dump to ++ @return void ++ ++ This function dumps a given dictionary into a loadable ini file. ++ It is Ok to specify @c stderr or @c stdout as output files. ++ */ ++/*--------------------------------------------------------------------------*/ ++ ++void iniparser_dump_ini(const dictionary * d, FILE * f); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Save a dictionary section to a loadable ini file ++ @param d Dictionary to dump ++ @param s Section name of dictionary to dump ++ @param f Opened file pointer to dump to ++ @return void ++ ++ This function dumps a given section of a given dictionary into a loadable ini ++ file. It is Ok to specify @c stderr or @c stdout as output files. ++ */ ++/*--------------------------------------------------------------------------*/ ++ ++void iniparser_dumpsection_ini(const dictionary * d, const char * s, FILE * f); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Dump a dictionary to an opened file pointer. ++ @param d Dictionary to dump. ++ @param f Opened file pointer to dump to. ++ @return void ++ ++ This function prints out the contents of a dictionary, one element by ++ line, onto the provided file pointer. It is OK to specify @c stderr ++ or @c stdout as output files. This function is meant for debugging ++ purposes mostly. ++ */ ++/*--------------------------------------------------------------------------*/ ++void iniparser_dump(const dictionary * d, FILE * f); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the number of keys in a section of a dictionary. ++ @param d Dictionary to examine ++ @param s Section name of dictionary to examine ++ @return Number of keys in section ++ */ ++/*--------------------------------------------------------------------------*/ ++int iniparser_getsecnkeys(const dictionary * d, const char * s); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the number of keys in a section of a dictionary. ++ @param d Dictionary to examine ++ @param s Section name of dictionary to examine ++ @param keys Already allocated array to store the keys in ++ @return The pointer passed as `keys` argument or NULL in case of error ++ ++ This function queries a dictionary and finds all keys in a given section. ++ The keys argument should be an array of pointers which size has been ++ determined by calling `iniparser_getsecnkeys` function prior to this one. ++ ++ Each pointer in the returned char pointer-to-pointer is pointing to ++ a string allocated in the dictionary; do not free or modify them. ++ */ ++/*--------------------------------------------------------------------------*/ ++const char ** iniparser_getseckeys(const dictionary * d, const char * s, const char ** keys); ++ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the string associated to a key ++ @param d Dictionary to search ++ @param key Key string to look for ++ @param def Default value to return if key not found. ++ @return pointer to statically allocated character string ++ ++ This function queries a dictionary for a key. A key as read from an ++ ini file is given as "section:key". If the key cannot be found, ++ the pointer passed as 'def' is returned. ++ The returned char pointer is pointing to a string allocated in ++ the dictionary, do not free or modify it. ++ */ ++/*--------------------------------------------------------------------------*/ ++const char * iniparser_getstring(const dictionary * d, const char * key, const char * def); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the string associated to a key, convert to an int ++ @param d Dictionary to search ++ @param key Key string to look for ++ @param notfound Value to return in case of error ++ @return integer ++ ++ This function queries a dictionary for a key. A key as read from an ++ ini file is given as "section:key". If the key cannot be found, ++ the notfound value is returned. ++ ++ Supported values for integers include the usual C notation ++ so decimal, octal (starting with 0) and hexadecimal (starting with 0x) ++ are supported. Examples: ++ ++ - "42" -> 42 ++ - "042" -> 34 (octal -> decimal) ++ - "0x42" -> 66 (hexa -> decimal) ++ ++ Warning: the conversion may overflow in various ways. Conversion is ++ totally outsourced to strtol(), see the associated man page for overflow ++ handling. ++ ++ Credits: Thanks to A. Becker for suggesting strtol() ++ */ ++/*--------------------------------------------------------------------------*/ ++int iniparser_getint(const dictionary * d, const char * key, int notfound); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the string associated to a key, convert to an long int ++ @param d Dictionary to search ++ @param key Key string to look for ++ @param notfound Value to return in case of error ++ @return integer ++ ++ This function queries a dictionary for a key. A key as read from an ++ ini file is given as "section:key". If the key cannot be found, ++ the notfound value is returned. ++ ++ Supported values for integers include the usual C notation ++ so decimal, octal (starting with 0) and hexadecimal (starting with 0x) ++ are supported. Examples: ++ ++ - "42" -> 42 ++ - "042" -> 34 (octal -> decimal) ++ - "0x42" -> 66 (hexa -> decimal) ++ ++ Warning: the conversion may overflow in various ways. Conversion is ++ totally outsourced to strtol(), see the associated man page for overflow ++ handling. ++ */ ++/*--------------------------------------------------------------------------*/ ++long int iniparser_getlongint(const dictionary * d, const char * key, long int notfound); ++ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the string associated to a key, convert to a double ++ @param d Dictionary to search ++ @param key Key string to look for ++ @param notfound Value to return in case of error ++ @return double ++ ++ This function queries a dictionary for a key. A key as read from an ++ ini file is given as "section:key". If the key cannot be found, ++ the notfound value is returned. ++ */ ++/*--------------------------------------------------------------------------*/ ++double iniparser_getdouble(const dictionary * d, const char * key, double notfound); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Get the string associated to a key, convert to a boolean ++ @param d Dictionary to search ++ @param key Key string to look for ++ @param notfound Value to return in case of error ++ @return integer ++ ++ This function queries a dictionary for a key. A key as read from an ++ ini file is given as "section:key". If the key cannot be found, ++ the notfound value is returned. ++ ++ A true boolean is found if one of the following is matched: ++ ++ - A string starting with 'y' ++ - A string starting with 'Y' ++ - A string starting with 't' ++ - A string starting with 'T' ++ - A string starting with '1' ++ ++ A false boolean is found if one of the following is matched: ++ ++ - A string starting with 'n' ++ - A string starting with 'N' ++ - A string starting with 'f' ++ - A string starting with 'F' ++ - A string starting with '0' ++ ++ The notfound value returned if no boolean is identified, does not ++ necessarily have to be 0 or 1. ++ */ ++/*--------------------------------------------------------------------------*/ ++int iniparser_getboolean(const dictionary * d, const char * key, int notfound); ++ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Set an entry in a dictionary. ++ @param ini Dictionary to modify. ++ @param entry Entry to modify (entry name) ++ @param val New value to associate to the entry. ++ @return int 0 if Ok, -1 otherwise. ++ ++ If the given entry can be found in the dictionary, it is modified to ++ contain the provided value. If it cannot be found, the entry is created. ++ It is Ok to set val to NULL. ++ */ ++/*--------------------------------------------------------------------------*/ ++int iniparser_set(dictionary * ini, const char * entry, const char * val); ++ ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Delete an entry in a dictionary ++ @param ini Dictionary to modify ++ @param entry Entry to delete (entry name) ++ @return void ++ ++ If the given entry can be found, it is deleted from the dictionary. ++ */ ++/*--------------------------------------------------------------------------*/ ++void iniparser_unset(dictionary * ini, const char * entry); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Finds out if a given entry exists in a dictionary ++ @param ini Dictionary to search ++ @param entry Name of the entry to look for ++ @return integer 1 if entry exists, 0 otherwise ++ ++ Finds out if a given entry exists in the dictionary. Since sections ++ are stored as keys with NULL associated values, this is the only way ++ of querying for the presence of sections in a dictionary. ++ */ ++/*--------------------------------------------------------------------------*/ ++int iniparser_find_entry(const dictionary * ini, const char * entry) ; ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Parse an ini file and return an allocated dictionary object ++ @param ininame Name of the ini file to read. ++ @return Pointer to newly allocated dictionary ++ ++ This is the parser for ini files. This function is called, providing ++ the name of the file to be read. It returns a dictionary object that ++ should not be accessed directly, but through accessor functions ++ instead. ++ ++ The returned dictionary must be freed using iniparser_freedict(). ++ */ ++/*--------------------------------------------------------------------------*/ ++dictionary * iniparser_load(const char * ininame); ++ ++/*-------------------------------------------------------------------------*/ ++/** ++ @brief Free all memory associated to an ini dictionary ++ @param d Dictionary to free ++ @return void ++ ++ Free all memory associated to an ini dictionary. ++ It is mandatory to call this function before the dictionary object ++ gets out of the current context. ++ */ ++/*--------------------------------------------------------------------------*/ ++void iniparser_freedict(dictionary * d); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/util/meson.build b/util/meson.build +index a6ded7e..97b27b5 100644 +--- a/util/meson.build ++++ b/util/meson.build +@@ -12,8 +12,9 @@ util = static_library('util', [ + 'bitmap.c', + 'abspath.c', + 'iomem.c', ++ 'dictionary.c', ++ 'iniparser.c', + ], +- dependencies: iniparser, + include_directories : root_inc, + ) + util_dep = declare_dependency(link_with : util) +-- +2.39.3 + diff --git a/SOURCES/0003-ndctl-check-the-old-directory-for-monitor.conf.patch b/SOURCES/0003-ndctl-check-the-old-directory-for-monitor.conf.patch new file mode 100644 index 0000000..9f4135f --- /dev/null +++ b/SOURCES/0003-ndctl-check-the-old-directory-for-monitor.conf.patch @@ -0,0 +1,70 @@ +ndctl: check the old directory for monitor.conf + +Scripts may still reference / install the monitor.conf file +in the old path. Check there first to avoid breaking backwards +compatibility. + +Signed-off-by: Jeff Moyer + +Related: RHEL-10382 +diff --git a/config.h.meson b/config.h.meson +index 5441dff..32e7941 100644 +--- a/config.h.meson ++++ b/config.h.meson +@@ -149,6 +149,7 @@ + /* Locations to install configuration files, key config, man pages, etc.. */ + #mesondefine NDCTL_CONF_FILE + #mesondefine NDCTL_CONF_DIR ++#mesondefine LEGACY_CONF_FILE + #mesondefine DAXCTL_CONF_DIR + #mesondefine NDCTL_KEYS_DIR + #mesondefine NDCTL_MAN_PATH +diff --git a/meson.build b/meson.build +index 2cb188f..96bc386 100644 +--- a/meson.build ++++ b/meson.build +@@ -259,8 +259,11 @@ conf.set10('HAVE_JSON_U64', + + ndctlconf_dir = sysconfdir / 'ndctl.conf.d' + ndctlconf = ndctlconf_dir / 'monitor.conf' ++legacyconf_dir = sysconfdir / 'ndctl' ++legacyconf = legacyconf_dir / 'monitor.conf' + conf.set_quoted('NDCTL_CONF_FILE', ndctlconf) + conf.set_quoted('NDCTL_CONF_DIR', ndctlconf_dir) ++conf.set_quoted('LEGACY_CONF_FILE', legacyconf) + + ndctlkeys_dir = sysconfdir / 'ndctl' / 'keys' + conf.set_quoted('NDCTL_KEYS_DIR', ndctlkeys_dir) +diff --git a/ndctl/meson.build b/ndctl/meson.build +index 050d576..dd13a41 100644 +--- a/ndctl/meson.build ++++ b/ndctl/meson.build +@@ -59,7 +59,7 @@ endif + if get_option('systemd').enabled() + install_data('ndctl-monitor.service', install_dir : systemdunitdir) + endif +-install_data('monitor.conf', install_dir : ndctlconf_dir) ++install_data('monitor.conf', install_dir : legacyconf_dir) + install_data('ndctl.conf', install_dir : ndctlconf_dir) + install_data('keys.readme', install_dir : ndctlkeys_dir) + +diff --git a/ndctl/monitor.c b/ndctl/monitor.c +index bd8a748..07da7f5 100644 +--- a/ndctl/monitor.c ++++ b/ndctl/monitor.c +@@ -591,6 +591,15 @@ int cmd_monitor(int argc, const char **argv, struct ndctl_ctx *ctx) + else + monitor.ctx.log_priority = LOG_INFO; + ++ /* ++ * First, check the legacy path to see if a monitor.conf ++ * file exists there. If so, add a [monitor] header ++ * and use its contents. ++ */ ++ if (!monitor.configs && (stat(LEGACY_CONF_FILE, &st) == 0) && ++ S_ISREG(st.st_mode)) ++ monitor.configs = LEGACY_CONF_FILE; ++ + ndctl_configs = ndctl_get_config_path(ctx); + if (!monitor.configs && ndctl_configs) { + rc = asprintf(&path, "%s/monitor.conf", ndctl_configs); diff --git a/SOURCES/0003-ndctl-test-Fix-btt-expect-table-compile-warning.patch b/SOURCES/0003-ndctl-test-Fix-btt-expect-table-compile-warning.patch deleted file mode 100644 index 5ec6ca1..0000000 --- a/SOURCES/0003-ndctl-test-Fix-btt-expect-table-compile-warning.patch +++ /dev/null @@ -1,51 +0,0 @@ -From ee7fabed859d07809dc3cfe6b23b7ad3b0c6cd73 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Tue, 12 Jan 2021 23:14:58 -0800 -Subject: [PATCH 003/217] ndctl/test: Fix btt expect table compile warning - -../test/libndctl.c:989:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] - 989 | unsigned long long expect_table[][2] = { - | ^~~~~~~~ - -...just move the declaration a few lines up. - -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma -Link: https://lore.kernel.org/r/161052209839.1804207.11951679046842122849.stgit@dwillia2-desk3.amr.corp.intel.com ---- - test/libndctl.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/test/libndctl.c b/test/libndctl.c -index 24d72b3..fc65149 100644 ---- a/test/libndctl.c -+++ b/test/libndctl.c -@@ -980,12 +980,6 @@ static int check_btt_size(struct ndctl_btt *btt) - struct ndctl_ctx *ctx = ndctl_btt_get_ctx(btt); - struct ndctl_test *test = ndctl_get_private_data(ctx); - struct ndctl_namespace *ndns = ndctl_btt_get_namespace(btt); -- -- if (!ndns) -- return -ENXIO; -- -- ns_size = ndctl_namespace_get_size(ndns); -- sect_size = ndctl_btt_get_sector_size(btt); - unsigned long long expect_table[][2] = { - [0] = { - [0] = 0x11b5400, -@@ -1001,6 +995,12 @@ static int check_btt_size(struct ndctl_btt *btt) - }, - }; - -+ if (!ndns) -+ return -ENXIO; -+ -+ ns_size = ndctl_namespace_get_size(ndns); -+ sect_size = ndctl_btt_get_sector_size(btt); -+ - if (sect_size >= SZ_4K) - sect_select = 1; - else if (sect_size >= 512) --- -2.27.0 - diff --git a/SOURCES/0004-ndctl-test-Cleanup-unnecessary-out-label.patch b/SOURCES/0004-ndctl-test-Cleanup-unnecessary-out-label.patch deleted file mode 100644 index 848d018..0000000 --- a/SOURCES/0004-ndctl-test-Cleanup-unnecessary-out-label.patch +++ /dev/null @@ -1,57 +0,0 @@ -From ff4030e88da2cdcaf52c0d7457cd30264ea8915b Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Tue, 12 Jan 2021 23:15:03 -0800 -Subject: [PATCH 004/217] ndctl/test: Cleanup unnecessary out label - -There are no cleanup actions to take in test_dax_remap(), and it is already -inconsistent for having a single return point, so remove the out label. - -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma -Link: https://lore.kernel.org/r/161052210395.1804207.7318263492906073721.stgit@dwillia2-desk3.amr.corp.intel.com ---- - test/dax-pmd.c | 12 ++++-------- - 1 file changed, 4 insertions(+), 8 deletions(-) - -diff --git a/test/dax-pmd.c b/test/dax-pmd.c -index 401826d..b1251db 100644 ---- a/test/dax-pmd.c -+++ b/test/dax-pmd.c -@@ -83,20 +83,18 @@ int test_dax_remap(struct ndctl_test *test, int dax_fd, unsigned long align, voi - act.sa_flags = SA_SIGINFO; - if (sigaction(SIGBUS, &act, 0)) { - perror("sigaction"); -- rc = EXIT_FAILURE; -- goto out; -+ return EXIT_FAILURE; - } - - /* test fault after device-dax instance disabled */ - if (sigsetjmp(sj_env, 1)) { - if (!fsdax && align > SZ_4K) { - fprintf(stderr, "got expected SIGBUS after mremap() of device-dax\n"); -- rc = 0; -+ return 0; - } else { - fprintf(stderr, "unpexpected SIGBUS after mremap()\n"); -- rc = -EIO; -+ return -EIO; - } -- goto out; - } - - *(int *) anon = 0xAA; -@@ -107,9 +105,7 @@ int test_dax_remap(struct ndctl_test *test, int dax_fd, unsigned long align, voi - return -ENXIO; - } - -- rc = 0; --out: -- return rc; -+ return 0; - } - - int test_dax_directio(int dax_fd, unsigned long align, void *dax_addr, off_t offset) --- -2.27.0 - diff --git a/SOURCES/0005-ndctl-test-Fix-device-dax-mremap-test.patch b/SOURCES/0005-ndctl-test-Fix-device-dax-mremap-test.patch deleted file mode 100644 index 6fb688c..0000000 --- a/SOURCES/0005-ndctl-test-Fix-device-dax-mremap-test.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 6694afe31dd67d186199a58d2252be5ea3472692 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Tue, 12 Jan 2021 23:15:09 -0800 -Subject: [PATCH 005/217] ndctl/test: Fix device-dax mremap() test - -The test_dax_remap() test is a regression check for mishandling of mremap() -in the presence of pmd_devmap(). My understanding is that it was a fuzzing -condition not something an application would want to do in practice. - -On recent kernels with commit 73d5e0629919 ("mremap: check if it's possible -to split original vma"), the test fails for device-dax. That seems an -equally acceptable result of attempting this remap, so update the test -rather than ask the kernel to preserve the old behaviour. - -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma -Link: https://lore.kernel.org/r/161052210936.1804207.17896246772670985157.stgit@dwillia2-desk3.amr.corp.intel.com ---- - test/dax-pmd.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/test/dax-pmd.c b/test/dax-pmd.c -index b1251db..7648e34 100644 ---- a/test/dax-pmd.c -+++ b/test/dax-pmd.c -@@ -69,6 +69,11 @@ int test_dax_remap(struct ndctl_test *test, int dax_fd, unsigned long align, voi - - remap = mremap(addr, REMAP_SIZE, REMAP_SIZE, MREMAP_MAYMOVE|MREMAP_FIXED, anon); - -+ if (remap == MAP_FAILED) { -+ fprintf(stderr, "%s: mremap failed, that's ok too\n", __func__); -+ return 0; -+ } -+ - if (remap != anon) { - rc = -ENXIO; - perror("mremap"); --- -2.27.0 - diff --git a/SOURCES/0006-ndctl-test-Exercise-soft_offline_page-corner-cases.patch b/SOURCES/0006-ndctl-test-Exercise-soft_offline_page-corner-cases.patch deleted file mode 100644 index b46bfbf..0000000 --- a/SOURCES/0006-ndctl-test-Exercise-soft_offline_page-corner-cases.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 940acf65a61595e8c0db3aebe1c74307acbbef68 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Tue, 12 Jan 2021 23:15:14 -0800 -Subject: [PATCH 006/217] ndctl/test: Exercise soft_offline_page() corner cases - -Test soft-offline injection into PMEM namespace metadata and user mapped -space. Both attempts should fail on kernels with a pfn_to_online_page() -implementation that considers subsection ZONE_DEVICE ranges. - -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma -Link: https://lore.kernel.org/r/161052211455.1804207.13884321454837200896.stgit@dwillia2-desk3.amr.corp.intel.com ---- - test/dax-poison.c | 19 +++++++++++++++++++ - test/device-dax.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 64 insertions(+) - -diff --git a/test/dax-poison.c b/test/dax-poison.c -index a4ef12e..4e09761 100644 ---- a/test/dax-poison.c -+++ b/test/dax-poison.c -@@ -5,6 +5,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -49,6 +50,7 @@ int test_dax_poison(struct ndctl_test *test, int dax_fd, unsigned long align, - unsigned char *addr = MAP_FAILED; - struct sigaction act; - unsigned x = x; -+ FILE *smaps; - void *buf; - int rc; - -@@ -94,6 +96,9 @@ int test_dax_poison(struct ndctl_test *test, int dax_fd, unsigned long align, - goto out; - } - -+ fprintf(stderr, "%s: mmap got %p align: %ld offset: %zd\n", -+ __func__, addr, align, offset); -+ - if (sigsetjmp(sj_env, 1)) { - if (sig_mcerr_ar) { - fprintf(stderr, "madvise triggered 'action required' sigbus\n"); -@@ -104,6 +109,20 @@ int test_dax_poison(struct ndctl_test *test, int dax_fd, unsigned long align, - } - } - -+ rc = madvise(addr + align / 2, 4096, MADV_SOFT_OFFLINE); -+ if (rc == 0) { -+ fprintf(stderr, "softoffline should always fail for dax\n"); -+ smaps = fopen("/proc/self/smaps", "r"); -+ do { -+ rc = fread(buf, 1, 4096, smaps); -+ fwrite(buf, 1, rc, stderr); -+ } while (rc); -+ fclose(smaps); -+ fail(); -+ rc = -ENXIO; -+ goto out; -+ } -+ - rc = madvise(addr + align / 2, 4096, MADV_HWPOISON); - if (rc) { - fail(); -diff --git a/test/device-dax.c b/test/device-dax.c -index 5f0da29..aad8fa5 100644 ---- a/test/device-dax.c -+++ b/test/device-dax.c -@@ -128,6 +128,44 @@ static int verify_data(struct daxctl_dev *dev, char *dax_buf, - return 0; - } - -+static int test_dax_soft_offline(struct ndctl_test *test, struct ndctl_namespace *ndns) -+{ -+ unsigned long long resource = ndctl_namespace_get_resource(ndns); -+ int fd, rc; -+ char *buf; -+ -+ if (resource == ULLONG_MAX) { -+ fprintf(stderr, "failed to get resource: %s\n", -+ ndctl_namespace_get_devname(ndns)); -+ return -ENXIO; -+ } -+ -+ fd = open("/sys/devices/system/memory/soft_offline_page", O_WRONLY); -+ if (fd < 0) { -+ fprintf(stderr, "failed to open soft_offline_page\n"); -+ return -ENOENT; -+ } -+ -+ rc = asprintf(&buf, "%#llx\n", resource); -+ if (rc < 0) { -+ fprintf(stderr, "failed to alloc resource\n"); -+ close(fd); -+ return -ENOMEM; -+ } -+ -+ fprintf(stderr, "%s: try to offline page @%#llx\n", __func__, resource); -+ rc = write(fd, buf, rc); -+ free(buf); -+ close(fd); -+ -+ if (rc >= 0) { -+ fprintf(stderr, "%s: should have failed\n", __func__); -+ return -ENXIO; -+ } -+ -+ return 0; -+} -+ - static int __test_device_dax(unsigned long align, int loglevel, - struct ndctl_test *test, struct ndctl_ctx *ctx) - { -@@ -278,6 +316,13 @@ static int __test_device_dax(unsigned long align, int loglevel, - goto out; - } - -+ rc = test_dax_soft_offline(test, ndns); -+ if (rc) { -+ fprintf(stderr, "%s: failed dax soft offline\n", -+ ndctl_namespace_get_devname(ndns)); -+ goto out; -+ } -+ - rc = test_dax_poison(test, fd, align, NULL, 0, devdax); - if (rc) { - fprintf(stderr, "%s: failed dax poison\n", --- -2.27.0 - diff --git a/SOURCES/0007-msft-Add-xlat_firmware_status-for-JEDEC-Byte-Address.patch b/SOURCES/0007-msft-Add-xlat_firmware_status-for-JEDEC-Byte-Address.patch deleted file mode 100644 index aa0420e..0000000 --- a/SOURCES/0007-msft-Add-xlat_firmware_status-for-JEDEC-Byte-Address.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 11357d68b77392e4360ae2824e75bf8397a84885 Mon Sep 17 00:00:00 2001 -From: Redhairer Li -Date: Sat, 9 Jan 2021 23:36:33 +0800 -Subject: [PATCH 007/217] msft: Add xlat_firmware_status for JEDEC Byte - Addressable Energy Backed DSM - -Translate the status codes of the result of JEDEC Byte Addressable Energy Backed -DSM to generic errno style error codes. - -Signed-off-by: Li Redhairer -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma -Link: https://lore.kernel.org/r/20210109153633.8493-1-redhairer.li@intel.com ---- - ndctl/lib/msft.c | 22 ++++++++++++++++++++++ - ndctl/lib/msft.h | 6 ++++++ - 2 files changed, 28 insertions(+) - -diff --git a/ndctl/lib/msft.c b/ndctl/lib/msft.c -index 145872c..3112799 100644 ---- a/ndctl/lib/msft.c -+++ b/ndctl/lib/msft.c -@@ -149,10 +149,32 @@ static unsigned int msft_cmd_smart_get_life_used(struct ndctl_cmd *cmd) - return 100 - CMD_MSFT_SMART(cmd)->nvm_lifetime; - } - -+static int msft_cmd_xlat_firmware_status(struct ndctl_cmd *cmd) -+{ -+ unsigned int status; -+ -+ status = cmd->get_firmware_status(cmd) & NDN_MSFT_STATUS_MASK; -+ -+ /* Common statuses */ -+ switch (status) { -+ case NDN_MSFT_STATUS_SUCCESS: -+ return 0; -+ case NDN_MSFT_STATUS_NOTSUPP: -+ return -EOPNOTSUPP; -+ case NDN_MSFT_STATUS_INVALPARM: -+ return -EINVAL; -+ case NDN_MSFT_STATUS_I2CERR: -+ return -EIO; -+ } -+ -+ return -ENOMSG; -+} -+ - struct ndctl_dimm_ops * const msft_dimm_ops = &(struct ndctl_dimm_ops) { - .new_smart = msft_dimm_cmd_new_smart, - .smart_get_flags = msft_cmd_smart_get_flags, - .smart_get_health = msft_cmd_smart_get_health, - .smart_get_media_temperature = msft_cmd_smart_get_media_temperature, - .smart_get_life_used = msft_cmd_smart_get_life_used, -+ .xlat_firmware_status = msft_cmd_xlat_firmware_status, - }; -diff --git a/ndctl/lib/msft.h b/ndctl/lib/msft.h -index 7cfd26f..978cc11 100644 ---- a/ndctl/lib/msft.h -+++ b/ndctl/lib/msft.h -@@ -50,4 +50,10 @@ struct ndn_pkg_msft { - union ndn_msft_cmd u; - } __attribute__((packed)); - -+#define NDN_MSFT_STATUS_MASK 0xffff -+#define NDN_MSFT_STATUS_SUCCESS 0 -+#define NDN_MSFT_STATUS_NOTSUPP 1 -+#define NDN_MSFT_STATUS_INVALPARM 2 -+#define NDN_MSFT_STATUS_I2CERR 3 -+ - #endif /* __NDCTL_MSFT_H__ */ --- -2.27.0 - diff --git a/SOURCES/0008-ndctl-namespace-Fix-disable-namespace-accounting-rel.patch b/SOURCES/0008-ndctl-namespace-Fix-disable-namespace-accounting-rel.patch deleted file mode 100644 index 76b77cf..0000000 --- a/SOURCES/0008-ndctl-namespace-Fix-disable-namespace-accounting-rel.patch +++ /dev/null @@ -1,140 +0,0 @@ -From fe626a8a8a1b1bc94ea95c693ec672109909e3dc Mon Sep 17 00:00:00 2001 -From: Redhairer Li -Date: Thu, 28 Jan 2021 22:03:39 +0800 -Subject: [PATCH 008/217] ndctl/namespace: Fix disable-namespace accounting - relative to seed devices - -Seed namespaces are included in "ndctl disable-namespace all". However -since the user never "creates" them it is surprising to see -"disable-namespace" report 1 more namespace relative to the number that -have been created. Catch attempts to disable a zero-sized namespace: - -Before: -{ - "dev":"namespace1.0", - "size":"492.00 MiB (515.90 MB)", - "blockdev":"pmem1" -} -{ - "dev":"namespace1.1", - "size":"492.00 MiB (515.90 MB)", - "blockdev":"pmem1.1" -} -{ - "dev":"namespace1.2", - "size":"492.00 MiB (515.90 MB)", - "blockdev":"pmem1.2" -} -disabled 4 namespaces - -After: -{ - "dev":"namespace1.0", - "size":"492.00 MiB (515.90 MB)", - "blockdev":"pmem1" -} -{ - "dev":"namespace1.3", - "size":"492.00 MiB (515.90 MB)", - "blockdev":"pmem1.3" -} -{ - "dev":"namespace1.1", - "size":"492.00 MiB (515.90 MB)", - "blockdev":"pmem1.1" -} -disabled 3 namespaces - -Signed-off-by: Redhairer Li -Signed-off-by: Vishal Verma -Link: https://lore.kernel.org/linux-nvdimm/20210128140339.3080-1-redhairer.li@intel.com/ ---- - ndctl/lib/libndctl.c | 10 ++++++++-- - ndctl/namespace.c | 8 ++++---- - ndctl/region.c | 2 +- - 3 files changed, 13 insertions(+), 7 deletions(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index 36fb6fe..2f6d806 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -4602,6 +4602,7 @@ NDCTL_EXPORT int ndctl_namespace_disable_safe(struct ndctl_namespace *ndns) - const char *bdev = NULL; - char path[50]; - int fd; -+ unsigned long long size = ndctl_namespace_get_size(ndns); - - if (pfn && ndctl_pfn_is_enabled(pfn)) - bdev = ndctl_pfn_get_block_device(pfn); -@@ -4631,8 +4632,13 @@ NDCTL_EXPORT int ndctl_namespace_disable_safe(struct ndctl_namespace *ndns) - devname, bdev, strerror(errno)); - return -errno; - } -- } else -- ndctl_namespace_disable_invalidate(ndns); -+ } else { -+ if (size == 0) -+ /* No disable necessary due to no capacity allocated */ -+ return 1; -+ else -+ ndctl_namespace_disable_invalidate(ndns); -+ } - - return 0; - } -diff --git a/ndctl/namespace.c b/ndctl/namespace.c -index 0c8df9f..1feb74d 100644 ---- a/ndctl/namespace.c -+++ b/ndctl/namespace.c -@@ -1125,7 +1125,7 @@ static int namespace_prep_reconfig(struct ndctl_region *region, - } - - rc = ndctl_namespace_disable_safe(ndns); -- if (rc) -+ if (rc < 0) - return rc; - - ndctl_namespace_set_enforce_mode(ndns, NDCTL_NS_MODE_RAW); -@@ -1431,7 +1431,7 @@ static int dax_clear_badblocks(struct ndctl_dax *dax) - return -ENXIO; - - rc = ndctl_namespace_disable_safe(ndns); -- if (rc) { -+ if (rc < 0) { - error("%s: unable to disable namespace: %s\n", devname, - strerror(-rc)); - return rc; -@@ -1455,7 +1455,7 @@ static int pfn_clear_badblocks(struct ndctl_pfn *pfn) - return -ENXIO; - - rc = ndctl_namespace_disable_safe(ndns); -- if (rc) { -+ if (rc < 0) { - error("%s: unable to disable namespace: %s\n", devname, - strerror(-rc)); - return rc; -@@ -1478,7 +1478,7 @@ static int raw_clear_badblocks(struct ndctl_namespace *ndns) - return -ENXIO; - - rc = ndctl_namespace_disable_safe(ndns); -- if (rc) { -+ if (rc < 0) { - error("%s: unable to disable namespace: %s\n", devname, - strerror(-rc)); - return rc; -diff --git a/ndctl/region.c b/ndctl/region.c -index 3edb9b3..4552c4a 100644 ---- a/ndctl/region.c -+++ b/ndctl/region.c -@@ -70,7 +70,7 @@ static int region_action(struct ndctl_region *region, enum device_action mode) - case ACTION_DISABLE: - ndctl_namespace_foreach(region, ndns) { - rc = ndctl_namespace_disable_safe(ndns); -- if (rc) -+ if (rc < 0) - return rc; - } - rc = ndctl_region_disable_invalidate(region); --- -2.27.0 - diff --git a/SOURCES/0009-zero_info_block-skip-seed-devices.patch b/SOURCES/0009-zero_info_block-skip-seed-devices.patch deleted file mode 100644 index 12d36c0..0000000 --- a/SOURCES/0009-zero_info_block-skip-seed-devices.patch +++ /dev/null @@ -1,50 +0,0 @@ -From fb13dfb8d84c4f0a749665c8f07179450b199f3e Mon Sep 17 00:00:00 2001 -From: Jeff Moyer -Date: Tue, 9 Feb 2021 16:51:53 -0500 -Subject: [PATCH 009/217] zero_info_block: skip seed devices - -Currently, ndctl destroy-namespace -f all will output errors of the -form: - - Error: destroy namespace: namespace0.0 failed to enable for zeroing, continuing - -for any zero-sized namespace. That particular namespace looks like this: - - { - "dev":"namespace0.0", - "mode":"raw", - "size":0, - "uuid":"00000000-0000-0000-0000-000000000000", - "sector_size":512, - "state":"disabled" - } - -This patch skips over namespaces with size=0 when zeroing out info -blocks. - -Fixes: 46654c2d60b70 ("ndctl/namespace: Always zero info-blocks") -Reported-by: Zhang Yi -Signed-off-by: Jeff Moyer -Signed-off-by: Vishal Verma -Link: https://lore.kernel.org/r/x49r1lohpty.fsf@segfault.boston.devel.redhat.com ---- - ndctl/namespace.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/ndctl/namespace.c b/ndctl/namespace.c -index 1feb74d..1e8a2cd 100644 ---- a/ndctl/namespace.c -+++ b/ndctl/namespace.c -@@ -1052,6 +1052,9 @@ static int zero_info_block(struct ndctl_namespace *ndns) - void *buf = NULL, *read_buf = NULL; - char path[50]; - -+ if (ndctl_namespace_get_size(ndns) == 0) -+ return 1; -+ - ndctl_namespace_set_raw_mode(ndns, 1); - rc = ndctl_namespace_enable(ndns); - if (rc < 0) { --- -2.27.0 - diff --git a/SOURCES/0010-ndctl-update-.gitignore.patch b/SOURCES/0010-ndctl-update-.gitignore.patch deleted file mode 100644 index b7432cf..0000000 --- a/SOURCES/0010-ndctl-update-.gitignore.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 5d0d4dc5ae1de82de92212c98297b24fbba09227 Mon Sep 17 00:00:00 2001 -From: QI Fuli -Date: Tue, 2 Feb 2021 22:02:06 +0900 -Subject: [PATCH 010/217] ndctl: update .gitignore - -Add Documentation/ndctl/attrs.adoc and *.lo to .gitignore. - -Signed-off-by: QI Fuli -Signed-off-by: Vishal Verma -Link: https://lore.kernel.org/r/20210202130206.3761-1-qi.fuli@fujitsu.com ---- - .gitignore | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/.gitignore b/.gitignore -index 3ef9ff7..53512b2 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -1,4 +1,5 @@ - *.o -+*.lo - *.xml - .deps/ - .libs/ -@@ -15,13 +16,13 @@ Makefile.in - *.1 - Documentation/daxctl/asciidoc.conf - Documentation/ndctl/asciidoc.conf -+Documentation/ndctl/attrs.adoc - Documentation/daxctl/asciidoctor-extensions.rb - Documentation/ndctl/asciidoctor-extensions.rb - .dirstamp - daxctl/config.h - daxctl/daxctl - daxctl/lib/libdaxctl.la --daxctl/lib/libdaxctl.lo - daxctl/lib/libdaxctl.pc - *.a - ndctl/config.h -@@ -29,8 +30,6 @@ ndctl/lib/libndctl.pc - ndctl/ndctl - rhel/ - sles/ndctl.spec --util/log.lo --util/sysfs.lo - version.m4 - *.swp - cscope.files --- -2.27.0 - diff --git a/SOURCES/0011-ndctl-test-add-checking-the-presence-of-jq-command-a.patch b/SOURCES/0011-ndctl-test-add-checking-the-presence-of-jq-command-a.patch deleted file mode 100644 index cacd0a6..0000000 --- a/SOURCES/0011-ndctl-test-add-checking-the-presence-of-jq-command-a.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 7ce2fddfa3f108036a2d81de4d2e66ac29e4631e Mon Sep 17 00:00:00 2001 -From: QI Fuli -Date: Wed, 3 Feb 2021 22:21:08 +0900 -Subject: [PATCH 011/217] ndctl/test: add checking the presence of jq command - ahead - -Due to the lack of jq command, the result of the test will be 'fail'. -This patch adds checking the presence of jq commmand ahead. -If there is no jq command in the system, the test will be marked as 'skip'. - -Signed-off-by: QI Fuli -Link: https://github.com/pmem/ndctl/issues/141 -Signed-off-by: Vishal Verma -Link: https://lore.kernel.org/r/20210203132108.6246-1-qi.fuli@fujitsu.com ---- - test/daxdev-errors.sh | 1 + - test/inject-error.sh | 2 ++ - test/inject-smart.sh | 1 + - test/label-compat.sh | 1 + - test/max_available_extent_ns.sh | 1 + - test/monitor.sh | 2 ++ - test/multi-dax.sh | 1 + - test/sector-mode.sh | 2 ++ - 8 files changed, 11 insertions(+) - -diff --git a/test/daxdev-errors.sh b/test/daxdev-errors.sh -index 6281f32..9547d78 100755 ---- a/test/daxdev-errors.sh -+++ b/test/daxdev-errors.sh -@@ -9,6 +9,7 @@ rc=77 - . $(dirname $0)/common - - check_min_kver "4.12" || do_skip "lacks dax dev error handling" -+check_prereq "jq" - - trap 'err $LINENO' ERR - -diff --git a/test/inject-error.sh b/test/inject-error.sh -index c636033..7d0b826 100755 ---- a/test/inject-error.sh -+++ b/test/inject-error.sh -@@ -11,6 +11,8 @@ err_count=8 - - . $(dirname $0)/common - -+check_prereq "jq" -+ - trap 'err $LINENO' ERR - - # sample json: -diff --git a/test/inject-smart.sh b/test/inject-smart.sh -index 94705df..4ca83b8 100755 ---- a/test/inject-smart.sh -+++ b/test/inject-smart.sh -@@ -166,6 +166,7 @@ do_tests() - } - - check_min_kver "4.19" || do_skip "kernel $KVER may not support smart (un)injection" -+check_prereq "jq" - modprobe nfit_test - rc=1 - -diff --git a/test/label-compat.sh b/test/label-compat.sh -index 340b93d..8ab2858 100755 ---- a/test/label-compat.sh -+++ b/test/label-compat.sh -@@ -10,6 +10,7 @@ BASE=$(dirname $0) - . $BASE/common - - check_min_kver "4.11" || do_skip "may not provide reliable isetcookie values" -+check_prereq "jq" - - trap 'err $LINENO' ERR - -diff --git a/test/max_available_extent_ns.sh b/test/max_available_extent_ns.sh -index 14d741d..343f3c9 100755 ---- a/test/max_available_extent_ns.sh -+++ b/test/max_available_extent_ns.sh -@@ -9,6 +9,7 @@ rc=77 - trap 'err $LINENO' ERR - - check_min_kver "4.19" || do_skip "kernel $KVER may not support max_available_size" -+check_prereq "jq" - - init() - { -diff --git a/test/monitor.sh b/test/monitor.sh -index cdab5e1..28c5541 100755 ---- a/test/monitor.sh -+++ b/test/monitor.sh -@@ -13,6 +13,8 @@ smart_supported_bus="" - - . $(dirname $0)/common - -+check_prereq "jq" -+ - trap 'err $LINENO' ERR - - check_min_kver "4.15" || do_skip "kernel $KVER may not support monitor service" -diff --git a/test/multi-dax.sh b/test/multi-dax.sh -index e932569..8496619 100755 ---- a/test/multi-dax.sh -+++ b/test/multi-dax.sh -@@ -9,6 +9,7 @@ rc=77 - . $(dirname $0)/common - - check_min_kver "4.13" || do_skip "may lack multi-dax support" -+check_prereq "jq" - - trap 'err $LINENO' ERR - -diff --git a/test/sector-mode.sh b/test/sector-mode.sh -index dd7013e..54fa806 100755 ---- a/test/sector-mode.sh -+++ b/test/sector-mode.sh -@@ -6,6 +6,8 @@ rc=77 - - . $(dirname $0)/common - -+check_prereq "jq" -+ - set -e - trap 'err $LINENO' ERR - --- -2.27.0 - diff --git a/SOURCES/0012-Expose-ndctl_bus_nfit_translate_spa-as-a-public-func.patch b/SOURCES/0012-Expose-ndctl_bus_nfit_translate_spa-as-a-public-func.patch deleted file mode 100644 index e873924..0000000 --- a/SOURCES/0012-Expose-ndctl_bus_nfit_translate_spa-as-a-public-func.patch +++ /dev/null @@ -1,78 +0,0 @@ -From c81fa15bafb1295aaa7d7f09500c3fbdd68b0011 Mon Sep 17 00:00:00 2001 -From: "Tsaur, Erwin" -Date: Thu, 4 Mar 2021 17:18:04 -0800 -Subject: [PATCH 012/217] Expose ndctl_bus_nfit_translate_spa as a public - function. - -The motivation is to allow access to ACPI defined NVDIMM Root Device -_DSM Function Index 5(Translate SPA). The rest of the _DSM functions, -which are mostly ARS related, are already public. - -Basically move ndctl_bus_nfit_translate_spa declaration from private.h -to libndctl.h. - -Reviewed-by: Dan Williams -Signed-off-by: "Tsaur, Erwin" -Signed-off-by: Vishal Verma -Link: https://lore.kernel.org/r/20210305011804.3573-1-erwin.tsaur@intel.com ---- - ndctl/lib/libndctl.sym | 4 ++++ - ndctl/lib/nfit.c | 2 +- - ndctl/lib/private.h | 2 -- - ndctl/libndctl.h | 2 ++ - 4 files changed, 7 insertions(+), 3 deletions(-) - -diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym -index 0a82616..58afb74 100644 ---- a/ndctl/lib/libndctl.sym -+++ b/ndctl/lib/libndctl.sym -@@ -451,3 +451,7 @@ LIBNDCTL_25 { - ndctl_bus_clear_fw_activate_nosuspend; - ndctl_bus_activate_firmware; - } LIBNDCTL_24; -+ -+LIBNDCTL_26 { -+ ndctl_bus_nfit_translate_spa; -+} LIBNDCTL_25; -diff --git a/ndctl/lib/nfit.c b/ndctl/lib/nfit.c -index 6f68fcf..d85682f 100644 ---- a/ndctl/lib/nfit.c -+++ b/ndctl/lib/nfit.c -@@ -114,7 +114,7 @@ static int is_valid_spa(struct ndctl_bus *bus, unsigned long long spa) - * - * If success, returns zero, store dimm's @handle, and @dpa. - */ --int ndctl_bus_nfit_translate_spa(struct ndctl_bus *bus, -+NDCTL_EXPORT int ndctl_bus_nfit_translate_spa(struct ndctl_bus *bus, - unsigned long long address, unsigned int *handle, unsigned long long *dpa) - { - -diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h -index ede1300..8f4510e 100644 ---- a/ndctl/lib/private.h -+++ b/ndctl/lib/private.h -@@ -370,8 +370,6 @@ static inline int check_kmod(struct kmod_ctx *kmod_ctx) - return kmod_ctx ? 0 : -ENXIO; - } - --int ndctl_bus_nfit_translate_spa(struct ndctl_bus *bus, unsigned long long addr, -- unsigned int *handle, unsigned long long *dpa); - struct ndctl_cmd *ndctl_bus_cmd_new_err_inj(struct ndctl_bus *bus); - struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_clr(struct ndctl_bus *bus); - struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_stat(struct ndctl_bus *bus, -diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h -index 60e1288..87d07b7 100644 ---- a/ndctl/libndctl.h -+++ b/ndctl/libndctl.h -@@ -152,6 +152,8 @@ int ndctl_bus_clear_fw_activate_noidle(struct ndctl_bus *bus); - int ndctl_bus_set_fw_activate_nosuspend(struct ndctl_bus *bus); - int ndctl_bus_clear_fw_activate_nosuspend(struct ndctl_bus *bus); - int ndctl_bus_activate_firmware(struct ndctl_bus *bus, enum ndctl_fwa_method method); -+int ndctl_bus_nfit_translate_spa(struct ndctl_bus *bus, unsigned long long addr, -+ unsigned int *handle, unsigned long long *dpa); - - struct ndctl_dimm; - struct ndctl_dimm *ndctl_dimm_get_first(struct ndctl_bus *bus); --- -2.27.0 - diff --git a/SOURCES/0013-test-libndctl-Use-ndctl_region_set_ro-to-change-disk.patch b/SOURCES/0013-test-libndctl-Use-ndctl_region_set_ro-to-change-disk.patch deleted file mode 100644 index 596947c..0000000 --- a/SOURCES/0013-test-libndctl-Use-ndctl_region_set_ro-to-change-disk.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 43e48c0d2f271cba4237f6eefc3e4912a74c102b Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Tue, 9 Mar 2021 22:09:49 -0800 -Subject: [PATCH 013/217] test/libndctl: Use ndctl_region_set_ro() to change - disk read-only state - -Kernel commit 52f019d43c22 ("block: add a hard-readonly flag to struct -gendisk") broke the read-only management test, by fixing the broken -behavior that BLKROSET could make a block device read-write even when the -disk is read-only. The fix [1] propagates changes of the region -read-only state to the underlying disk. Add ndctl_region_set_ro() ahead of -BLKROSET so that BLKROSET does not conflict the block_device state with the -disk state. - -[1]: http://lore.kernel.org/r/161534060720.528671.2341213328968989192.stgit@dwillia2-desk3.amr.corp.intel.com - -Reported-by: kernel test robot -Reported-by: Vishal Verma -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma -Link: https://lore.kernel.org/r/161535658913.530219.12194565167385663385.stgit@dwillia2-desk3.amr.corp.intel.com ---- - test/libndctl.c | 18 +++++++++++++++++- - 1 file changed, 17 insertions(+), 1 deletion(-) - -diff --git a/test/libndctl.c b/test/libndctl.c -index fc65149..c42f785 100644 ---- a/test/libndctl.c -+++ b/test/libndctl.c -@@ -1541,6 +1541,7 @@ static int validate_bdev(const char *devname, struct ndctl_btt *btt, - struct ndctl_pfn *pfn, struct ndctl_namespace *ndns, - struct namespace *namespace, void *buf) - { -+ struct ndctl_region *region = ndctl_namespace_get_region(ndns); - char bdevpath[50]; - int fd, rc, ro; - -@@ -1578,6 +1579,13 @@ static int validate_bdev(const char *devname, struct ndctl_btt *btt, - } - - ro = 0; -+ rc = ndctl_region_set_ro(region, ro); -+ if (rc < 0) { -+ fprintf(stderr, "%s: ndctl_region_set_ro failed\n", devname); -+ rc = -errno; -+ goto out; -+ } -+ - rc = ioctl(fd, BLKROSET, &ro); - if (rc < 0) { - fprintf(stderr, "%s: BLKROSET failed\n", -@@ -1605,8 +1613,16 @@ static int validate_bdev(const char *devname, struct ndctl_btt *btt, - rc = -ENXIO; - goto out; - } -+ -+ rc = ndctl_region_set_ro(region, namespace->ro); -+ if (rc < 0) { -+ fprintf(stderr, "%s: ndctl_region_set_ro reset failed\n", devname); -+ rc = -errno; -+ goto out; -+ } -+ - rc = 0; -- out: -+out: - close(fd); - return rc; - } --- -2.27.0 - diff --git a/SOURCES/0014-daxctl-fail-reconfigure-device-based-on-kernel-onlin.patch b/SOURCES/0014-daxctl-fail-reconfigure-device-based-on-kernel-onlin.patch deleted file mode 100644 index 3470017..0000000 --- a/SOURCES/0014-daxctl-fail-reconfigure-device-based-on-kernel-onlin.patch +++ /dev/null @@ -1,221 +0,0 @@ -From 99415dfc7c5167c49a5732f577836f68872645b2 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Wed, 24 Mar 2021 12:09:29 -0700 -Subject: [PATCH 014/217] daxctl: fail reconfigure-device based on kernel - onlining policy - -If the kernel has a policy set to auto-online any new memory blocks, we -know that an attempt to reconfigure a device either in ZONE_MOVABLE, or -with the --no-online is going to fail. While we detect this race after -the fact, and print a warning, that is often insufficient as the user -may be forced to reboot to get out of the situation, resulting in an -unpleasant experience. - -Detect whether the kernel policy is set to auto-online. If so, fail -device reconfigure operations that we know can't be satisfied. Allow -for overriding this safety check via the -f (--force) option. Update the -man page to talk about this, and the unit test to test for an expected -failure by enabling auto-onlining. - -Cc: Dave Hansen -Reported-by: Chunye Xu -Reported-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .../daxctl/daxctl-reconfigure-device.txt | 12 ++++++- - daxctl/device.c | 10 ++++++ - daxctl/lib/libdaxctl-private.h | 1 + - daxctl/lib/libdaxctl.c | 21 +++++++++++ - daxctl/lib/libdaxctl.sym | 5 +++ - daxctl/libdaxctl.h | 1 + - test/daxctl-devices.sh | 36 +++++++++++++++++++ - 7 files changed, 85 insertions(+), 1 deletion(-) - -diff --git a/Documentation/daxctl/daxctl-reconfigure-device.txt b/Documentation/daxctl/daxctl-reconfigure-device.txt -index ad33eda..f112b3c 100644 ---- a/Documentation/daxctl/daxctl-reconfigure-device.txt -+++ b/Documentation/daxctl/daxctl-reconfigure-device.txt -@@ -119,6 +119,10 @@ recommended to use the --no-online option described below. This will abridge - the device reconfiguration operation to just hotplugging the memory, and - refrain from then onlining it. - -+In case daxctl detects that there is a kernel policy to auto-online blocks -+(via /sys/devices/system/memory/auto_online_blocks), then reconfiguring to -+system-ram will result in a failure. This can be overridden with '--force'. -+ - OPTIONS - ------- - include::region-option.txt[] -@@ -162,12 +166,18 @@ include::movable-options.txt[] - - -f:: - --force:: -- When converting from "system-ram" mode to "devdax", it is expected -+ - When converting from "system-ram" mode to "devdax", it is expected - that all the memory sections are first made offline. By default, - daxctl won't touch online memory. However with this option, attempt - to offline the memory on the NUMA node associated with the dax device - before converting it back to "devdax" mode. - -+ - Additionally, if a kernel policy to auto-online blocks is detected, -+ reconfiguration to system-ram fails. With this option, the failure can -+ be overridden to allow reconfiguration regardless of kernel policy. -+ Doing this may result in a successful reconfiguration, but it may -+ not be possible to subsequently offline the memory without a reboot. -+ - - include::human-option.txt[] - -diff --git a/daxctl/device.c b/daxctl/device.c -index 0721a57..a427b7d 100644 ---- a/daxctl/device.c -+++ b/daxctl/device.c -@@ -541,8 +541,18 @@ static int disable_devdax_device(struct daxctl_dev *dev) - - static int reconfig_mode_system_ram(struct daxctl_dev *dev) - { -+ const char *devname = daxctl_dev_get_devname(dev); - int rc, skip_enable = 0; - -+ if (param.no_online || !param.no_movable) { -+ if (!param.force && daxctl_dev_will_auto_online_memory(dev)) { -+ fprintf(stderr, -+ "%s: error: kernel policy will auto-online memory, aborting\n", -+ devname); -+ return -EBUSY; -+ } -+ } -+ - if (daxctl_dev_is_enabled(dev)) { - rc = disable_devdax_device(dev); - if (rc < 0) -diff --git a/daxctl/lib/libdaxctl-private.h b/daxctl/lib/libdaxctl-private.h -index af257fd..ae45311 100644 ---- a/daxctl/lib/libdaxctl-private.h -+++ b/daxctl/lib/libdaxctl-private.h -@@ -111,6 +111,7 @@ struct daxctl_memory { - char *node_path; - unsigned long block_size; - enum memory_zones zone; -+ bool auto_online; - }; - - -diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c -index 479e8f6..879f7e6 100644 ---- a/daxctl/lib/libdaxctl.c -+++ b/daxctl/lib/libdaxctl.c -@@ -1644,3 +1644,24 @@ DAXCTL_EXPORT int daxctl_memory_is_movable(struct daxctl_memory *mem) - return rc; - return (mem->zone == MEM_ZONE_MOVABLE) ? 1 : 0; - } -+ -+DAXCTL_EXPORT int daxctl_dev_will_auto_online_memory(struct daxctl_dev *dev) -+{ -+ const char *auto_path = "/sys/devices/system/memory/auto_online_blocks"; -+ const char *devname = daxctl_dev_get_devname(dev); -+ struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev); -+ char buf[SYSFS_ATTR_SIZE]; -+ -+ /* -+ * If we can't read the policy for some reason, don't fail yet. Assume -+ * the auto-onlining policy is absent, and carry on. If onlining blocks -+ * does result in the memory being in an inconsistent state, we have a -+ * check and warning for it after the fact -+ */ -+ if (sysfs_read_attr(ctx, auto_path, buf) != 0) -+ err(ctx, "%s: Unable to determine auto-online policy: %s\n", -+ devname, strerror(errno)); -+ -+ /* match both "online" and "online_movable" */ -+ return !strncmp(buf, "online", 6); -+} -diff --git a/daxctl/lib/libdaxctl.sym b/daxctl/lib/libdaxctl.sym -index a4e1684..892e393 100644 ---- a/daxctl/lib/libdaxctl.sym -+++ b/daxctl/lib/libdaxctl.sym -@@ -91,3 +91,8 @@ global: - daxctl_mapping_get_size; - daxctl_dev_set_mapping; - } LIBDAXCTL_7; -+ -+LIBDAXCTL_9 { -+global: -+ daxctl_dev_will_auto_online_memory; -+} LIBDAXCTL_8; -diff --git a/daxctl/libdaxctl.h b/daxctl/libdaxctl.h -index e82b274..30ab51a 100644 ---- a/daxctl/libdaxctl.h -+++ b/daxctl/libdaxctl.h -@@ -71,6 +71,7 @@ int daxctl_dev_disable(struct daxctl_dev *dev); - int daxctl_dev_enable_devdax(struct daxctl_dev *dev); - int daxctl_dev_enable_ram(struct daxctl_dev *dev); - int daxctl_dev_get_target_node(struct daxctl_dev *dev); -+int daxctl_dev_will_auto_online_memory(struct daxctl_dev *dev); - - struct daxctl_memory; - struct daxctl_memory *daxctl_dev_get_memory(struct daxctl_dev *dev); -diff --git a/test/daxctl-devices.sh b/test/daxctl-devices.sh -index 496e4f2..eed5906 100755 ---- a/test/daxctl-devices.sh -+++ b/test/daxctl-devices.sh -@@ -64,6 +64,26 @@ daxctl_get_mode() - "$DAXCTL" list -d "$1" | jq -er '.[].mode' - } - -+set_online_policy() -+{ -+ echo "online" > /sys/devices/system/memory/auto_online_blocks -+} -+ -+unset_online_policy() -+{ -+ echo "offline" > /sys/devices/system/memory/auto_online_blocks -+} -+ -+save_online_policy() -+{ -+ saved_policy="$(cat /sys/devices/system/memory/auto_online_blocks)" -+} -+ -+restore_online_policy() -+{ -+ echo "$saved_policy" > /sys/devices/system/memory/auto_online_blocks -+} -+ - daxctl_test() - { - local daxdev -@@ -71,6 +91,9 @@ daxctl_test() - daxdev=$(daxctl_get_dev "$testdev") - test -n "$daxdev" - -+ # these tests need to run with kernel onlining policy turned off -+ save_online_policy -+ unset_online_policy - "$DAXCTL" reconfigure-device -N -m system-ram "$daxdev" - [[ $(daxctl_get_mode "$daxdev") == "system-ram" ]] - "$DAXCTL" online-memory "$daxdev" -@@ -81,6 +104,19 @@ daxctl_test() - [[ $(daxctl_get_mode "$daxdev") == "system-ram" ]] - "$DAXCTL" reconfigure-device -f -m devdax "$daxdev" - [[ $(daxctl_get_mode "$daxdev") == "devdax" ]] -+ -+ # this tests for reconfiguration failure if an online-policy is set -+ set_online_policy -+ : "This command is expected to fail:" -+ if ! "$DAXCTL" reconfigure-device -N -m system-ram "$daxdev"; then -+ echo "reconfigure failed as expected" -+ else -+ echo "reconfigure succeded, expected failure" -+ restore_online_policy -+ return 1 -+ fi -+ -+ restore_online_policy - } - - find_testdev --- -2.27.0 - diff --git a/SOURCES/0015-libdaxctl-add-an-API-to-check-if-a-device-is-active.patch b/SOURCES/0015-libdaxctl-add-an-API-to-check-if-a-device-is-active.patch deleted file mode 100644 index 72ba1f4..0000000 --- a/SOURCES/0015-libdaxctl-add-an-API-to-check-if-a-device-is-active.patch +++ /dev/null @@ -1,63 +0,0 @@ -From e563e6a7c55e65c554e07db6215f8bcb2d411d3b Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Tue, 30 Mar 2021 20:50:37 -0600 -Subject: [PATCH 015/217] libdaxctl: add an API to check if a device is active - -Add an API to check whether a daxctl device is active in system-ram -mode. This would be used from libndctl during -ndctl_namespace_disable_safe(), so that we don't disable/destroy an -underlying namespace while the memory is active and online. - -Reported-by: Chunye Xu -Cc: Dan Williams -Cc: Dave Hansen -Signed-off-by: Vishal Verma ---- - daxctl/lib/libdaxctl.c | 10 ++++++++++ - daxctl/lib/libdaxctl.sym | 1 + - daxctl/libdaxctl.h | 1 + - 3 files changed, 12 insertions(+) - -diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c -index 879f7e6..860bd9c 100644 ---- a/daxctl/lib/libdaxctl.c -+++ b/daxctl/lib/libdaxctl.c -@@ -1665,3 +1665,13 @@ DAXCTL_EXPORT int daxctl_dev_will_auto_online_memory(struct daxctl_dev *dev) - /* match both "online" and "online_movable" */ - return !strncmp(buf, "online", 6); - } -+ -+DAXCTL_EXPORT int daxctl_dev_has_online_memory(struct daxctl_dev *dev) -+{ -+ struct daxctl_memory *mem = daxctl_dev_get_memory(dev); -+ -+ if (mem) -+ return daxctl_memory_is_online(mem); -+ else -+ return 0; -+} -diff --git a/daxctl/lib/libdaxctl.sym b/daxctl/lib/libdaxctl.sym -index 892e393..a13e93d 100644 ---- a/daxctl/lib/libdaxctl.sym -+++ b/daxctl/lib/libdaxctl.sym -@@ -95,4 +95,5 @@ global: - LIBDAXCTL_9 { - global: - daxctl_dev_will_auto_online_memory; -+ daxctl_dev_has_online_memory; - } LIBDAXCTL_8; -diff --git a/daxctl/libdaxctl.h b/daxctl/libdaxctl.h -index 30ab51a..683ae9c 100644 ---- a/daxctl/libdaxctl.h -+++ b/daxctl/libdaxctl.h -@@ -72,6 +72,7 @@ int daxctl_dev_enable_devdax(struct daxctl_dev *dev); - int daxctl_dev_enable_ram(struct daxctl_dev *dev); - int daxctl_dev_get_target_node(struct daxctl_dev *dev); - int daxctl_dev_will_auto_online_memory(struct daxctl_dev *dev); -+int daxctl_dev_has_online_memory(struct daxctl_dev *dev); - - struct daxctl_memory; - struct daxctl_memory *daxctl_dev_get_memory(struct daxctl_dev *dev); --- -2.27.0 - diff --git a/SOURCES/0016-libndctl-check-for-active-system-ram-before-disablin.patch b/SOURCES/0016-libndctl-check-for-active-system-ram-before-disablin.patch deleted file mode 100644 index 3f6587f..0000000 --- a/SOURCES/0016-libndctl-check-for-active-system-ram-before-disablin.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 573f0d46cff15fff2804b3fb444d1e34f482e788 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Tue, 30 Mar 2021 20:54:55 -0600 -Subject: [PATCH 016/217] libndctl: check for active system-ram before - disabling daxctl devices - -Teach ndctl_namespace_disable_safe() to look at the state of a -daxctl_dev with respect to whether it is active in 'system-ram' mode -before disabling it. This is similar to checking whether a filesystem is -actively mounted on a namespace before disabling it. - -Without this, libndctl would happily disable a devdax namespace while the -device was active in system-ram mode. If the namespace was subsequently -also destroyed, this would leave the memory without any sort of a -'handle' to perform any subsequent operation on it, and the system would -have to be rebooted to get out of this situation. - -Reported-by: Chunye Xu -Cc: Dan Williams -Cc: Dave Hansen -Signed-off-by: Vishal Verma ---- - ndctl/lib/libndctl.c | 25 ++++++++++++++++++++++++- - test/daxctl-devices.sh | 16 ++++++++++++++++ - 2 files changed, 40 insertions(+), 1 deletion(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index 2f6d806..2eda56c 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -4593,21 +4593,40 @@ NDCTL_EXPORT int ndctl_namespace_disable_invalidate(struct ndctl_namespace *ndns - return ndctl_namespace_disable(ndns); - } - -+static int ndctl_dax_has_active_memory(struct ndctl_dax *dax) -+{ -+ struct daxctl_region *dax_region; -+ struct daxctl_dev *dax_dev; -+ -+ dax_region = ndctl_dax_get_daxctl_region(dax); -+ if (!dax_region) -+ return 0; -+ -+ daxctl_dev_foreach(dax_region, dax_dev) -+ if (daxctl_dev_has_online_memory(dax_dev)) -+ return 1; -+ -+ return 0; -+} -+ - NDCTL_EXPORT int ndctl_namespace_disable_safe(struct ndctl_namespace *ndns) - { - const char *devname = ndctl_namespace_get_devname(ndns); - struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns); - struct ndctl_pfn *pfn = ndctl_namespace_get_pfn(ndns); - struct ndctl_btt *btt = ndctl_namespace_get_btt(ndns); -+ struct ndctl_dax *dax = ndctl_namespace_get_dax(ndns); - const char *bdev = NULL; -+ int fd, active = 0; - char path[50]; -- int fd; - unsigned long long size = ndctl_namespace_get_size(ndns); - - if (pfn && ndctl_pfn_is_enabled(pfn)) - bdev = ndctl_pfn_get_block_device(pfn); - else if (btt && ndctl_btt_is_enabled(btt)) - bdev = ndctl_btt_get_block_device(btt); -+ else if (dax && ndctl_dax_is_enabled(dax)) -+ active = ndctl_dax_has_active_memory(dax); - else if (ndctl_namespace_is_enabled(ndns)) - bdev = ndctl_namespace_get_block_device(ndns); - -@@ -4632,6 +4651,10 @@ NDCTL_EXPORT int ndctl_namespace_disable_safe(struct ndctl_namespace *ndns) - devname, bdev, strerror(errno)); - return -errno; - } -+ } else if (active) { -+ dbg(ctx, "%s: active as system-ram, refusing to disable\n", -+ devname); -+ return -EBUSY; - } else { - if (size == 0) - /* No disable necessary due to no capacity allocated */ -diff --git a/test/daxctl-devices.sh b/test/daxctl-devices.sh -index eed5906..56c9691 100755 ---- a/test/daxctl-devices.sh -+++ b/test/daxctl-devices.sh -@@ -105,6 +105,22 @@ daxctl_test() - "$DAXCTL" reconfigure-device -f -m devdax "$daxdev" - [[ $(daxctl_get_mode "$daxdev") == "devdax" ]] - -+ # fail 'ndctl-disable-namespace' while the devdax namespace is active -+ # as system-ram. If this test fails, a reboot will be required to -+ # recover from the resulting state. -+ test -n "$testdev" -+ "$DAXCTL" reconfigure-device -m system-ram "$daxdev" -+ [[ $(daxctl_get_mode "$daxdev") == "system-ram" ]] -+ if ! "$NDCTL" disable-namespace "$testdev"; then -+ echo "disable-namespace failed as expected" -+ else -+ echo "disable-namespace succeded, expected failure" -+ echo "reboot required to recover from this state" -+ return 1 -+ fi -+ "$DAXCTL" reconfigure-device -f -m devdax "$daxdev" -+ [[ $(daxctl_get_mode "$daxdev") == "devdax" ]] -+ - # this tests for reconfiguration failure if an online-policy is set - set_online_policy - : "This command is expected to fail:" --- -2.27.0 - diff --git a/SOURCES/0017-daxctl-emit-counts-of-total-and-online-memblocks.patch b/SOURCES/0017-daxctl-emit-counts-of-total-and-online-memblocks.patch deleted file mode 100644 index 28f1ee6..0000000 --- a/SOURCES/0017-daxctl-emit-counts-of-total-and-online-memblocks.patch +++ /dev/null @@ -1,49 +0,0 @@ -From e81f890c7ae1c940c7f52b8984e8728706489728 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Wed, 31 Mar 2021 13:51:35 -0600 -Subject: [PATCH 017/217] daxctl: emit counts of total and online memblocks - -Fir daxctl device listings, if in 'system-ram' mode, it is useful to -know whether the memory associated with the device is online or not. -Since the memory is comprised of a number of 'memblocks', and it is -possible (albeit rare) to have a subset of them online, and the rest -offline, we can't just use a boolean online-or-offline flag for the -state. - -Add a couple of counts, one for the total number of memblocks associated -with the device, and another for the ones that are online. - -Link: https://github.com/pmem/ndctl/issues/139 -Cc: Dan Williams -Cc: Dave Hansen -Reported-by: Steve Scargall -Signed-off-by: Vishal Verma ---- - util/json.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/util/json.c b/util/json.c -index ca0167b..a8d2412 100644 ---- a/util/json.c -+++ b/util/json.c -@@ -482,6 +482,17 @@ struct json_object *util_daxctl_dev_to_json(struct daxctl_dev *dev, - json_object_object_add(jdev, "mode", jobj); - - if (mem && daxctl_dev_get_resource(dev) != 0) { -+ int num_sections = daxctl_memory_num_sections(mem); -+ int num_online = daxctl_memory_is_online(mem); -+ -+ jobj = json_object_new_int(num_online); -+ if (jobj) -+ json_object_object_add(jdev, "online_memblocks", jobj); -+ -+ jobj = json_object_new_int(num_sections); -+ if (jobj) -+ json_object_object_add(jdev, "total_memblocks", jobj); -+ - movable = daxctl_memory_is_movable(mem); - if (movable == 1) - jobj = json_object_new_boolean(true); --- -2.27.0 - diff --git a/SOURCES/0018-libndctl-Unify-adding-dimms-for-papr-and-nfit-famili.patch b/SOURCES/0018-libndctl-Unify-adding-dimms-for-papr-and-nfit-famili.patch deleted file mode 100644 index 3e499c2..0000000 --- a/SOURCES/0018-libndctl-Unify-adding-dimms-for-papr-and-nfit-famili.patch +++ /dev/null @@ -1,220 +0,0 @@ -From daef3a386a9c45105a2c045ddee46600e265939f Mon Sep 17 00:00:00 2001 -From: Santosh Sivaraj -Date: Thu, 13 May 2021 11:42:15 +0530 -Subject: [PATCH 018/217] libndctl: Unify adding dimms for papr and nfit - families - -In preparation for enabling tests on non-nfit devices, unify both, already very -similar, functions into one. This will help in adding all attributes needed for -the unit tests. Since the function doesn't fail if some of the dimm attributes -are missing, this will work fine on PAPR platforms though only part of the DIMM -attributes are provided (This doesn't mean that all of the DIMM attributes can -be missing). - -Link: https://lore.kernel.org/r/20210513061218.760322-1-santosh@fossix.org -Signed-off-by: Santosh Sivaraj -Signed-off-by: Vishal Verma ---- - ndctl/lib/libndctl.c | 103 ++++++++++++++++--------------------------- - 1 file changed, 38 insertions(+), 65 deletions(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index 2f6d806..e45353f 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -1646,41 +1646,9 @@ static int ndctl_bind(struct ndctl_ctx *ctx, struct kmod_module *module, - static int ndctl_unbind(struct ndctl_ctx *ctx, const char *devpath); - static struct kmod_module *to_module(struct ndctl_ctx *ctx, const char *alias); - --static int add_papr_dimm(struct ndctl_dimm *dimm, const char *dimm_base) --{ -- int rc = -ENODEV; -- char buf[SYSFS_ATTR_SIZE]; -- struct ndctl_ctx *ctx = dimm->bus->ctx; -- char *path = calloc(1, strlen(dimm_base) + 100); -- const char * const devname = ndctl_dimm_get_devname(dimm); -- -- dbg(ctx, "%s: Probing of_pmem dimm at %s\n", devname, dimm_base); -- -- if (!path) -- return -ENOMEM; -- -- /* construct path to the papr compatible dimm flags file */ -- sprintf(path, "%s/papr/flags", dimm_base); -- -- if (ndctl_bus_is_papr_scm(dimm->bus) && -- sysfs_read_attr(ctx, path, buf) == 0) { -- -- dbg(ctx, "%s: Adding papr-scm dimm flags:\"%s\"\n", devname, buf); -- dimm->cmd_family = NVDIMM_FAMILY_PAPR; -- -- /* Parse dimm flags */ -- parse_papr_flags(dimm, buf); -- -- /* Allocate monitor mode fd */ -- dimm->health_eventfd = open(path, O_RDONLY|O_CLOEXEC); -- rc = 0; -- } -- -- free(path); -- return rc; --} -- --static int add_nfit_dimm(struct ndctl_dimm *dimm, const char *dimm_base) -+static int populate_dimm_attributes(struct ndctl_dimm *dimm, -+ const char *dimm_base, -+ const char *bus_prefix) - { - int i, rc = -1; - char buf[SYSFS_ATTR_SIZE]; -@@ -1694,7 +1662,7 @@ static int add_nfit_dimm(struct ndctl_dimm *dimm, const char *dimm_base) - * 'unique_id' may not be available on older kernels, so don't - * fail if the read fails. - */ -- sprintf(path, "%s/nfit/id", dimm_base); -+ sprintf(path, "%s/%s/id", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) == 0) { - unsigned int b[9]; - -@@ -1709,68 +1677,74 @@ static int add_nfit_dimm(struct ndctl_dimm *dimm, const char *dimm_base) - } - } - -- sprintf(path, "%s/nfit/handle", dimm_base); -+ sprintf(path, "%s/%s/handle", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) < 0) - goto err_read; - dimm->handle = strtoul(buf, NULL, 0); - -- sprintf(path, "%s/nfit/phys_id", dimm_base); -+ sprintf(path, "%s/%s/phys_id", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) < 0) - goto err_read; - dimm->phys_id = strtoul(buf, NULL, 0); - -- sprintf(path, "%s/nfit/serial", dimm_base); -+ sprintf(path, "%s/%s/serial", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) == 0) - dimm->serial = strtoul(buf, NULL, 0); - -- sprintf(path, "%s/nfit/vendor", dimm_base); -+ sprintf(path, "%s/%s/vendor", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) == 0) - dimm->vendor_id = strtoul(buf, NULL, 0); - -- sprintf(path, "%s/nfit/device", dimm_base); -+ sprintf(path, "%s/%s/device", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) == 0) - dimm->device_id = strtoul(buf, NULL, 0); - -- sprintf(path, "%s/nfit/rev_id", dimm_base); -+ sprintf(path, "%s/%s/rev_id", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) == 0) - dimm->revision_id = strtoul(buf, NULL, 0); - -- sprintf(path, "%s/nfit/dirty_shutdown", dimm_base); -+ sprintf(path, "%s/%s/dirty_shutdown", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) == 0) - dimm->dirty_shutdown = strtoll(buf, NULL, 0); - -- sprintf(path, "%s/nfit/subsystem_vendor", dimm_base); -+ sprintf(path, "%s/%s/subsystem_vendor", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) == 0) - dimm->subsystem_vendor_id = strtoul(buf, NULL, 0); - -- sprintf(path, "%s/nfit/subsystem_device", dimm_base); -+ sprintf(path, "%s/%s/subsystem_device", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) == 0) - dimm->subsystem_device_id = strtoul(buf, NULL, 0); - -- sprintf(path, "%s/nfit/subsystem_rev_id", dimm_base); -+ sprintf(path, "%s/%s/subsystem_rev_id", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) == 0) - dimm->subsystem_revision_id = strtoul(buf, NULL, 0); - -- sprintf(path, "%s/nfit/family", dimm_base); -+ sprintf(path, "%s/%s/family", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) == 0) - dimm->cmd_family = strtoul(buf, NULL, 0); - -- sprintf(path, "%s/nfit/dsm_mask", dimm_base); -+ sprintf(path, "%s/%s/dsm_mask", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) == 0) - dimm->nfit_dsm_mask = strtoul(buf, NULL, 0); - -- sprintf(path, "%s/nfit/format", dimm_base); -+ sprintf(path, "%s/%s/format", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) == 0) - dimm->format[0] = strtoul(buf, NULL, 0); - for (i = 1; i < dimm->formats; i++) { -- sprintf(path, "%s/nfit/format%d", dimm_base, i); -+ sprintf(path, "%s/%s/format%d", dimm_base, bus_prefix, i); - if (sysfs_read_attr(ctx, path, buf) == 0) - dimm->format[i] = strtoul(buf, NULL, 0); - } - -- sprintf(path, "%s/nfit/flags", dimm_base); -- if (sysfs_read_attr(ctx, path, buf) == 0) -- parse_nfit_mem_flags(dimm, buf); -+ sprintf(path, "%s/%s/flags", dimm_base, bus_prefix); -+ if (sysfs_read_attr(ctx, path, buf) == 0) { -+ if (ndctl_bus_has_nfit(dimm->bus)) -+ parse_nfit_mem_flags(dimm, buf); -+ else if (ndctl_bus_is_papr_scm(dimm->bus)) { -+ dimm->cmd_family = NVDIMM_FAMILY_PAPR; -+ parse_papr_flags(dimm, buf); -+ } -+ } - - dimm->health_eventfd = open(path, O_RDONLY|O_CLOEXEC); - rc = 0; -@@ -1792,7 +1766,8 @@ static void *add_dimm(void *parent, int id, const char *dimm_base) - if (!path) - return NULL; - -- sprintf(path, "%s/nfit/formats", dimm_base); -+ sprintf(path, "%s/%s/formats", dimm_base, -+ ndctl_bus_has_nfit(bus) ? "nfit" : "papr"); - if (sysfs_read_attr(ctx, path, buf) < 0) - formats = 1; - else -@@ -1866,13 +1841,12 @@ static void *add_dimm(void *parent, int id, const char *dimm_base) - else - dimm->fwa_result = fwa_result_to_result(buf); - -+ dimm->formats = formats; - /* Check if the given dimm supports nfit */ - if (ndctl_bus_has_nfit(bus)) { -- dimm->formats = formats; -- rc = add_nfit_dimm(dimm, dimm_base); -- } else if (ndctl_bus_has_of_node(bus)) { -- rc = add_papr_dimm(dimm, dimm_base); -- } -+ rc = populate_dimm_attributes(dimm, dimm_base, "nfit"); -+ } else if (ndctl_bus_has_of_node(bus)) -+ rc = populate_dimm_attributes(dimm, dimm_base, "papr"); - - if (rc == -ENODEV) { - /* Unprobed dimm with no family */ -@@ -2531,13 +2505,12 @@ static void *add_region(void *parent, int id, const char *region_base) - goto err_read; - region->num_mappings = strtoul(buf, NULL, 0); - -- sprintf(path, "%s/nfit/range_index", region_base); -- if (ndctl_bus_has_nfit(bus)) { -- if (sysfs_read_attr(ctx, path, buf) < 0) -- goto err_read; -- region->range_index = strtoul(buf, NULL, 0); -- } else -+ sprintf(path, "%s/%s/range_index", region_base, -+ ndctl_bus_has_nfit(bus) ? "nfit": "papr"); -+ if (sysfs_read_attr(ctx, path, buf) < 0) - region->range_index = -1; -+ else -+ region->range_index = strtoul(buf, NULL, 0); - - sprintf(path, "%s/read_only", region_base); - if (sysfs_read_attr(ctx, path, buf) < 0) --- -2.27.0 - diff --git a/SOURCES/0019-test-Don-t-skip-tests-if-nfit-modules-are-missing.patch b/SOURCES/0019-test-Don-t-skip-tests-if-nfit-modules-are-missing.patch deleted file mode 100644 index 573a272..0000000 --- a/SOURCES/0019-test-Don-t-skip-tests-if-nfit-modules-are-missing.patch +++ /dev/null @@ -1,211 +0,0 @@ -From 1649ad9c3e2c6e9c47870c8d3b54f10b24177bc7 Mon Sep 17 00:00:00 2001 -From: Santosh Sivaraj -Date: Thu, 13 May 2021 11:42:16 +0530 -Subject: [PATCH 019/217] test: Don't skip tests if nfit modules are missing - -For NFIT to be available ACPI is a must, so don't fail when nfit modules -are missing on a platform that doesn't support ACPI. - -Link: https://lore.kernel.org/r/20210513061218.760322-2-santosh@fossix.org -Signed-off-by: Santosh Sivaraj -Signed-off-by: Vishal Verma ---- - test.h | 2 +- - test/ack-shutdown-count-set.c | 2 +- - test/blk_namespaces.c | 2 +- - test/core.c | 28 ++++++++++++++++++++++++++-- - test/dpa-alloc.c | 2 +- - test/dsm-fail.c | 2 +- - test/libndctl.c | 2 +- - test/multi-pmem.c | 2 +- - test/parent-uuid.c | 2 +- - test/pmem_namespaces.c | 2 +- - 10 files changed, 35 insertions(+), 11 deletions(-) - -diff --git a/test.h b/test.h -index cba8d41..7de13fe 100644 ---- a/test.h -+++ b/test.h -@@ -20,7 +20,7 @@ void builtin_xaction_namespace_reset(void); - - struct kmod_ctx; - struct kmod_module; --int nfit_test_init(struct kmod_ctx **ctx, struct kmod_module **mod, -+int ndctl_test_init(struct kmod_ctx **ctx, struct kmod_module **mod, - struct ndctl_ctx *nd_ctx, int log_level, - struct ndctl_test *test); - -diff --git a/test/ack-shutdown-count-set.c b/test/ack-shutdown-count-set.c -index fb1d82b..c561ff3 100644 ---- a/test/ack-shutdown-count-set.c -+++ b/test/ack-shutdown-count-set.c -@@ -99,7 +99,7 @@ static int test_ack_shutdown_count_set(int loglevel, struct ndctl_test *test, - int result = EXIT_FAILURE, err; - - ndctl_set_log_priority(ctx, loglevel); -- err = nfit_test_init(&kmod_ctx, &mod, NULL, loglevel, test); -+ err = ndctl_test_init(&kmod_ctx, &mod, NULL, loglevel, test); - if (err < 0) { - result = 77; - ndctl_test_skip(test); -diff --git a/test/blk_namespaces.c b/test/blk_namespaces.c -index d7f00cb..f076e85 100644 ---- a/test/blk_namespaces.c -+++ b/test/blk_namespaces.c -@@ -228,7 +228,7 @@ int test_blk_namespaces(int log_level, struct ndctl_test *test, - - if (!bus) { - fprintf(stderr, "ACPI.NFIT unavailable falling back to nfit_test\n"); -- rc = nfit_test_init(&kmod_ctx, &mod, NULL, log_level, test); -+ rc = ndctl_test_init(&kmod_ctx, &mod, NULL, log_level, test); - ndctl_invalidate(ctx); - bus = ndctl_bus_get_by_provider(ctx, "nfit_test.0"); - if (rc < 0 || !bus) { -diff --git a/test/core.c b/test/core.c -index cc7d8d9..2b03aa9 100644 ---- a/test/core.c -+++ b/test/core.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - - #define KVER_STRLEN 20 -@@ -106,11 +107,11 @@ int ndctl_test_get_skipped(struct ndctl_test *test) - return test->skip; - } - --int nfit_test_init(struct kmod_ctx **ctx, struct kmod_module **mod, -+int ndctl_test_init(struct kmod_ctx **ctx, struct kmod_module **mod, - struct ndctl_ctx *nd_ctx, int log_level, - struct ndctl_test *test) - { -- int rc; -+ int rc, family = -1; - unsigned int i; - const char *name; - struct ndctl_bus *bus; -@@ -127,10 +128,28 @@ int nfit_test_init(struct kmod_ctx **ctx, struct kmod_module **mod, - "nd_e820", - "nd_pmem", - }; -+ char *test_env; - - log_init(&log_ctx, "test/init", "NDCTL_TEST"); - log_ctx.log_priority = log_level; - -+ /* -+ * The following two checks determine the platform family. For -+ * Intel/platforms which support ACPI, check sysfs; for other platforms -+ * determine from the environment variable NVDIMM_TEST_FAMILY -+ */ -+ if (access("/sys/bus/acpi", F_OK) == 0) -+ family = NVDIMM_FAMILY_INTEL; -+ -+ test_env = getenv("NDCTL_TEST_FAMILY"); -+ if (test_env && strcmp(test_env, "PAPR") == 0) -+ family = NVDIMM_FAMILY_PAPR; -+ -+ if (family == -1) { -+ log_err(&log_ctx, "Cannot determine NVDIMM family\n"); -+ return -ENOTSUP; -+ } -+ - *ctx = kmod_new(NULL, NULL); - if (!*ctx) - return -ENXIO; -@@ -185,6 +204,11 @@ retry: - - path = kmod_module_get_path(*mod); - if (!path) { -+ if (family != NVDIMM_FAMILY_INTEL && -+ (strcmp(name, "nfit") == 0 || -+ strcmp(name, "nd_e820") == 0)) -+ continue; -+ - log_err(&log_ctx, "%s.ko: failed to get path\n", name); - break; - } -diff --git a/test/dpa-alloc.c b/test/dpa-alloc.c -index e922009..0b3bb7a 100644 ---- a/test/dpa-alloc.c -+++ b/test/dpa-alloc.c -@@ -289,7 +289,7 @@ int test_dpa_alloc(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx) - return 77; - - ndctl_set_log_priority(ctx, loglevel); -- err = nfit_test_init(&kmod_ctx, &mod, NULL, loglevel, test); -+ err = ndctl_test_init(&kmod_ctx, &mod, NULL, loglevel, test); - if (err < 0) { - ndctl_test_skip(test); - fprintf(stderr, "nfit_test unavailable skipping tests\n"); -diff --git a/test/dsm-fail.c b/test/dsm-fail.c -index 9dfd8b0..0a6383d 100644 ---- a/test/dsm-fail.c -+++ b/test/dsm-fail.c -@@ -346,7 +346,7 @@ int test_dsm_fail(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx) - int result = EXIT_FAILURE, err; - - ndctl_set_log_priority(ctx, loglevel); -- err = nfit_test_init(&kmod_ctx, &mod, NULL, loglevel, test); -+ err = ndctl_test_init(&kmod_ctx, &mod, NULL, loglevel, test); - if (err < 0) { - result = 77; - ndctl_test_skip(test); -diff --git a/test/libndctl.c b/test/libndctl.c -index c42f785..d9b50f4 100644 ---- a/test/libndctl.c -+++ b/test/libndctl.c -@@ -2708,7 +2708,7 @@ int test_libndctl(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx) - daxctl_set_log_priority(daxctl_ctx, loglevel); - ndctl_set_private_data(ctx, test); - -- err = nfit_test_init(&kmod_ctx, &mod, ctx, loglevel, test); -+ err = ndctl_test_init(&kmod_ctx, &mod, ctx, loglevel, test); - if (err < 0) { - ndctl_test_skip(test); - fprintf(stderr, "nfit_test unavailable skipping tests\n"); -diff --git a/test/multi-pmem.c b/test/multi-pmem.c -index 3d10952..3ea08cc 100644 ---- a/test/multi-pmem.c -+++ b/test/multi-pmem.c -@@ -249,7 +249,7 @@ int test_multi_pmem(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx - - ndctl_set_log_priority(ctx, loglevel); - -- err = nfit_test_init(&kmod_ctx, &mod, NULL, loglevel, test); -+ err = ndctl_test_init(&kmod_ctx, &mod, NULL, loglevel, test); - if (err < 0) { - result = 77; - ndctl_test_skip(test); -diff --git a/test/parent-uuid.c b/test/parent-uuid.c -index 6424e9f..bded33a 100644 ---- a/test/parent-uuid.c -+++ b/test/parent-uuid.c -@@ -218,7 +218,7 @@ int test_parent_uuid(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ct - return 77; - - ndctl_set_log_priority(ctx, loglevel); -- err = nfit_test_init(&kmod_ctx, &mod, NULL, loglevel, test); -+ err = ndctl_test_init(&kmod_ctx, &mod, NULL, loglevel, test); - if (err < 0) { - ndctl_test_skip(test); - fprintf(stderr, "nfit_test unavailable skipping tests\n"); -diff --git a/test/pmem_namespaces.c b/test/pmem_namespaces.c -index f0f2edd..a4db1ae 100644 ---- a/test/pmem_namespaces.c -+++ b/test/pmem_namespaces.c -@@ -191,7 +191,7 @@ int test_pmem_namespaces(int log_level, struct ndctl_test *test, - - if (!bus) { - fprintf(stderr, "ACPI.NFIT unavailable falling back to nfit_test\n"); -- rc = nfit_test_init(&kmod_ctx, &mod, NULL, log_level, test); -+ rc = ndctl_test_init(&kmod_ctx, &mod, NULL, log_level, test); - ndctl_invalidate(ctx); - bus = ndctl_bus_get_by_provider(ctx, "nfit_test.0"); - if (rc < 0 || !bus) { --- -2.27.0 - diff --git a/SOURCES/0020-papr-Add-support-to-parse-save_fail-flag-for-dimm.patch b/SOURCES/0020-papr-Add-support-to-parse-save_fail-flag-for-dimm.patch deleted file mode 100644 index 7994e22..0000000 --- a/SOURCES/0020-papr-Add-support-to-parse-save_fail-flag-for-dimm.patch +++ /dev/null @@ -1,41 +0,0 @@ -From f081f302505209430df46908775a3cffb875a5c7 Mon Sep 17 00:00:00 2001 -From: Santosh Sivaraj -Date: Thu, 13 May 2021 11:42:17 +0530 -Subject: [PATCH 020/217] papr: Add support to parse save_fail flag for dimm - -This will help in getting the dimm fail tests to run on papr family too. -Also add nvdimm_test compatibility string for recognizing the test module. - -Link: https://lore.kernel.org/r/20210513061218.760322-3-santosh@fossix.org -Signed-off-by: Santosh Sivaraj -Signed-off-by: Vishal Verma ---- - ndctl/lib/libndctl.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index e45353f..a8b99ea 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -805,6 +805,8 @@ static void parse_papr_flags(struct ndctl_dimm *dimm, char *flags) - dimm->flags.f_restore = 1; - else if (strcmp(start, "smart_notify") == 0) - dimm->flags.f_smart = 1; -+ else if (strcmp(start, "save_fail") == 0) -+ dimm->flags.f_save = 1; - start = end + 1; - } - if (end != start) -@@ -1035,7 +1037,8 @@ NDCTL_EXPORT int ndctl_bus_is_papr_scm(struct ndctl_bus *bus) - if (sysfs_read_attr(bus->ctx, bus->bus_buf, buf) < 0) - return 0; - -- return (strcmp(buf, "ibm,pmemory") == 0); -+ return (strcmp(buf, "ibm,pmemory") == 0 || -+ strcmp(buf, "nvdimm_test") == 0); - } - - /** --- -2.27.0 - diff --git a/SOURCES/0021-Use-page-size-as-alignment-value.patch b/SOURCES/0021-Use-page-size-as-alignment-value.patch deleted file mode 100644 index c1000b0..0000000 --- a/SOURCES/0021-Use-page-size-as-alignment-value.patch +++ /dev/null @@ -1,129 +0,0 @@ -From fe831b526b88f6ca7a27fdb149b8a7d2ecddbc55 Mon Sep 17 00:00:00 2001 -From: Santosh Sivaraj -Date: Thu, 13 May 2021 11:42:18 +0530 -Subject: [PATCH 021/217] Use page size as alignment value - -The alignment sizes passed to ndctl in the tests are all hardcoded to 4k, -the default page size on x86. Change those to the default page size on that -architecture (sysconf/getconf). No functional changes otherwise. - -Link: https://lore.kernel.org/r/20210513061218.760322-4-santosh@fossix.org -Signed-off-by: Santosh Sivaraj -Signed-off-by: Vishal Verma ---- - test/dpa-alloc.c | 15 ++++++++------- - test/multi-dax.sh | 6 ++++-- - test/sector-mode.sh | 4 +++- - 3 files changed, 15 insertions(+), 10 deletions(-) - -diff --git a/test/dpa-alloc.c b/test/dpa-alloc.c -index 0b3bb7a..59185cf 100644 ---- a/test/dpa-alloc.c -+++ b/test/dpa-alloc.c -@@ -38,12 +38,13 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test) - struct ndctl_region *region, *blk_region = NULL; - struct ndctl_namespace *ndns; - struct ndctl_dimm *dimm; -- unsigned long size; -+ unsigned long size, page_size; - struct ndctl_bus *bus; - char uuid_str[40]; - int round; - int rc; - -+ page_size = sysconf(_SC_PAGESIZE); - /* disable nfit_test.1, not used in this test */ - bus = ndctl_bus_get_by_provider(ctx, NFIT_PROVIDER1); - if (!bus) -@@ -124,11 +125,11 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test) - return rc; - } - ndctl_namespace_disable_invalidate(ndns); -- rc = ndctl_namespace_set_size(ndns, SZ_4K); -+ rc = ndctl_namespace_set_size(ndns, page_size); - if (rc) { -- fprintf(stderr, "failed to init %s to size: %d\n", -+ fprintf(stderr, "failed to init %s to size: %lu\n", - ndctl_namespace_get_devname(ndns), -- SZ_4K); -+ page_size); - return rc; - } - namespaces[i].ndns = ndns; -@@ -150,7 +151,7 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test) - ndns = namespaces[i % ARRAY_SIZE(namespaces)].ndns; - if (i % ARRAY_SIZE(namespaces) == 0) - round++; -- size = SZ_4K * round; -+ size = page_size * round; - rc = ndctl_namespace_set_size(ndns, size); - if (rc) { - fprintf(stderr, "%s: set_size: %lx failed: %d\n", -@@ -166,7 +167,7 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test) - i--; - round++; - ndns = namespaces[i % ARRAY_SIZE(namespaces)].ndns; -- size = SZ_4K * round; -+ size = page_size * round; - rc = ndctl_namespace_set_size(ndns, size); - if (rc) { - fprintf(stderr, "%s failed to update while labels full\n", -@@ -175,7 +176,7 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test) - } - - round--; -- size = SZ_4K * round; -+ size = page_size * round; - rc = ndctl_namespace_set_size(ndns, size); - if (rc) { - fprintf(stderr, "%s failed to reduce size while labels full\n", -diff --git a/test/multi-dax.sh b/test/multi-dax.sh -index 8496619..b343a38 100755 ---- a/test/multi-dax.sh -+++ b/test/multi-dax.sh -@@ -13,6 +13,8 @@ check_prereq "jq" - - trap 'err $LINENO' ERR - -+ALIGN_SIZE=`getconf PAGESIZE` -+ - # setup (reset nfit_test dimms) - modprobe nfit_test - $NDCTL disable-region -b $NFIT_TEST_BUS0 all -@@ -23,9 +25,9 @@ rc=1 - query=". | sort_by(.available_size) | reverse | .[0].dev" - region=$($NDCTL list -b $NFIT_TEST_BUS0 -t pmem -Ri | jq -r "$query") - --json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -r $region -t pmem -m devdax -a 4096 -s 16M) -+json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -r $region -t pmem -m devdax -a $ALIGN_SIZE -s 16M) - chardev1=$(echo $json | jq ". | select(.mode == \"devdax\") | .daxregion.devices[0].chardev") --json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -r $region -t pmem -m devdax -a 4096 -s 16M) -+json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -r $region -t pmem -m devdax -a $ALIGN_SIZE -s 16M) - chardev2=$(echo $json | jq ". | select(.mode == \"devdax\") | .daxregion.devices[0].chardev") - - _cleanup -diff --git a/test/sector-mode.sh b/test/sector-mode.sh -index 54fa806..7a2faea 100755 ---- a/test/sector-mode.sh -+++ b/test/sector-mode.sh -@@ -11,6 +11,8 @@ check_prereq "jq" - set -e - trap 'err $LINENO' ERR - -+ALIGN_SIZE=`getconf PAGESIZE` -+ - # setup (reset nfit_test dimms) - modprobe nfit_test - $NDCTL disable-region -b $NFIT_TEST_BUS0 all -@@ -27,7 +29,7 @@ NAMESPACE=$($NDCTL list -b $NFIT_TEST_BUS1 -N | jq -r "$query") - REGION=$($NDCTL list -R --namespace=$NAMESPACE | jq -r "(.[]) | .dev") - echo 0 > /sys/bus/nd/devices/$REGION/read_only - $NDCTL create-namespace --no-autolabel -e $NAMESPACE -m sector -f -l 4K --$NDCTL create-namespace --no-autolabel -e $NAMESPACE -m dax -f -a 4K -+$NDCTL create-namespace --no-autolabel -e $NAMESPACE -m dax -f -a $ALIGN_SIZE - $NDCTL create-namespace --no-autolabel -e $NAMESPACE -m sector -f -l 4K - - _cleanup --- -2.27.0 - diff --git a/SOURCES/0022-libndctl-Remove-redundant-checks-and-assignments.patch b/SOURCES/0022-libndctl-Remove-redundant-checks-and-assignments.patch deleted file mode 100644 index bcc65b8..0000000 --- a/SOURCES/0022-libndctl-Remove-redundant-checks-and-assignments.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 561af4f919b3f1b3d1a213137f1d024420996d56 Mon Sep 17 00:00:00 2001 -From: Santosh Sivaraj -Date: Sun, 28 Mar 2021 05:43:51 +0530 -Subject: [PATCH 022/217] libndctl: Remove redundant checks and assignments - -check_udev already checks for udev allocation failure, remove the redundant -check. - -Link: https://lore.kernel.org/r/20210328001351.2245032-1-santosh@fossix.org -Signed-off-by: Santosh Sivaraj -Signed-off-by: Vishal Verma ---- - ndctl/lib/libndctl.c | 9 +++------ - 1 file changed, 3 insertions(+), 6 deletions(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index bf0968c..3a496ed 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -323,12 +323,9 @@ NDCTL_EXPORT int ndctl_new(struct ndctl_ctx **ctx) - dbg(c, "timeout = %ld\n", tmo); - } - -- if (udev) { -- c->udev = udev; -- c->udev_queue = udev_queue_new(udev); -- if (!c->udev_queue) -- err(c, "failed to retrieve udev queue\n"); -- } -+ c->udev_queue = udev_queue_new(udev); -+ if (!c->udev_queue) -+ err(c, "failed to retrieve udev queue\n"); - - c->kmod_ctx = kmod_ctx; - c->daxctl_ctx = daxctl_ctx; --- -2.27.0 - diff --git a/SOURCES/0023-ndctl-Update-nvdimm-mailing-list-address.patch b/SOURCES/0023-ndctl-Update-nvdimm-mailing-list-address.patch deleted file mode 100644 index 4217357..0000000 --- a/SOURCES/0023-ndctl-Update-nvdimm-mailing-list-address.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 063af7c447d257397a925df81897da2c71e31653 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Tue, 18 May 2021 16:25:27 -0600 -Subject: [PATCH 023/217] ndctl: Update nvdimm mailing list address - -The 'nvdimm' mailing list has moved from lists.01.org to -lists.linux.dev. Update CONTRIBUTING.md and configure.ac to reflect -this. - -Link: https://lore.kernel.org/r/20210518222527.550730-1-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - CONTRIBUTING.md | 7 ++++--- - configure.ac | 2 +- - 2 files changed, 5 insertions(+), 4 deletions(-) - -diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md -index 4c29d31..4f4865d 100644 ---- a/CONTRIBUTING.md -+++ b/CONTRIBUTING.md -@@ -6,13 +6,14 @@ The following is a set of guidelines that we adhere to, and request that - contributors follow. - - 1. The libnvdimm (kernel subsystem) and ndctl developers primarily use -- the [linux-nvdimm](https://lists.01.org/postorius/lists/linux-nvdimm.lists.01.org/) -+ the [nvdimm](https://subspace.kernel.org/lists.linux.dev.html) - mailing list for everything. It is recommended to send patches to -- **```linux-nvdimm@lists.01.org```** -+ **```nvdimm@lists.linux.dev```** -+ An archive is available on [lore](https://lore.kernel.org/nvdimm/) - - 1. Github [issues](https://github.com/pmem/ndctl/issues) are an acceptable - way to report a problem, but if you just have a question, -- [email](mailto:linux-nvdimm@lists.01.org) the above list. -+ [email](mailto:nvdimm@lists.linux.dev) the above list. - - 1. We follow the Linux Kernel [Coding Style Guide][cs] as applicable. - -diff --git a/configure.ac b/configure.ac -index 5ec8d2f..dc39dbe 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -2,7 +2,7 @@ AC_PREREQ(2.60) - m4_include([version.m4]) - AC_INIT([ndctl], - GIT_VERSION, -- [linux-nvdimm@lists.01.org], -+ [nvdimm@lists.linux.dev], - [ndctl], - [https://github.com/pmem/ndctl]) - AC_CONFIG_SRCDIR([ndctl/lib/libndctl.c]) --- -2.27.0 - diff --git a/SOURCES/0024-libndctl-papr-Fix-probe-for-papr-scm-compatible-nvdi.patch b/SOURCES/0024-libndctl-papr-Fix-probe-for-papr-scm-compatible-nvdi.patch deleted file mode 100644 index 01b34fe..0000000 --- a/SOURCES/0024-libndctl-papr-Fix-probe-for-papr-scm-compatible-nvdi.patch +++ /dev/null @@ -1,122 +0,0 @@ -From e086106b4d81a2079141c848db7695451c04e877 Mon Sep 17 00:00:00 2001 -From: Vaibhav Jain -Date: Mon, 17 May 2021 21:18:24 +0530 -Subject: [PATCH 024/217] libndctl/papr: Fix probe for papr-scm compatible - nvdimms - -With recent changes introduced for unification of PAPR and NFIT -families the probe for papr-scm nvdimms is broken since they don't -expose 'handle' or 'phys_id' sysfs attributes. These attributes are -only exposed by NFIT and 'nvdimm_test' nvdimms. Since 'unable to read' -these sysfs attributes is a non-recoverable error hence this prevents -probing of 'PAPR-SCM' nvdimms and ndctl reports following error: - -$ sudo NDCTL_LOG=debug ndctl list -DH -libndctl: ndctl_new: ctx 0x10015342c70 created -libndctl: add_dimm: nmem1: probe failed: Operation not permitted -libndctl: __sysfs_device_parse: nmem1: add_dev() failed -libndctl: add_dimm: nmem0: probe failed: Operation not permitted -libndctl: __sysfs_device_parse: nmem0: add_dev() failed - -Fixing this bug is complicated by the fact these attributes are needed -for by the 'nvdimm_test' nvdimms which also uses the -NVDIMM_FAMILY_PAPR. Adding a two way comparison for these two -attributes in populate_dimm_attributes() to distinguish between -'nvdimm_test' and papr-scm nvdimms will be clunky and make future -updates to populate_dimm_attributes() error prone. - -So, this patch proposes to fix the issue by re-introducing -add_papr_dimm() to probe both papr-scm and 'nvdimm_test' nvdimms. The -'compatible' sysfs attribute associated with the PAPR device is used -to distinguish between the two nvdimm types and in case an -'nvdimm_test' device is detected then forward its probe to -populate_dimm_attributes(). - -families") - -Link: https://lore.kernel.org/r/20210517154824.142237-1-vaibhav@linux.ibm.com -Fixes: daef3a386a9c("libndctl: Unify adding dimms for papr and nfit -Signed-off-by: Vaibhav Jain -Signed-off-by: Vishal Verma ---- - ndctl/lib/libndctl.c | 57 ++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 55 insertions(+), 2 deletions(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index 3a496ed..aa36a3c 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -1754,6 +1754,58 @@ static int populate_dimm_attributes(struct ndctl_dimm *dimm, - return rc; - } - -+static int add_papr_dimm(struct ndctl_dimm *dimm, const char *dimm_base) -+{ -+ int rc = -ENODEV; -+ char buf[SYSFS_ATTR_SIZE]; -+ struct ndctl_ctx *ctx = dimm->bus->ctx; -+ char *path = calloc(1, strlen(dimm_base) + 100); -+ const char * const devname = ndctl_dimm_get_devname(dimm); -+ -+ dbg(ctx, "%s: Probing of_pmem dimm at %s\n", devname, dimm_base); -+ -+ if (!path) -+ return -ENOMEM; -+ -+ /* Check the compatibility of the probed nvdimm */ -+ sprintf(path, "%s/../of_node/compatible", dimm_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) { -+ dbg(ctx, "%s: Unable to read compatible field\n", devname); -+ rc = -ENODEV; -+ goto out; -+ } -+ -+ dbg(ctx, "%s:Compatible of_pmem = '%s'\n", devname, buf); -+ -+ /* Probe for papr-scm memory */ -+ if (strcmp(buf, "ibm,pmemory") == 0) { -+ /* Read the dimm flags file */ -+ sprintf(path, "%s/papr/flags", dimm_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) { -+ rc = -errno; -+ err(ctx, "%s: Unable to read dimm-flags\n", devname); -+ goto out; -+ } -+ -+ dbg(ctx, "%s: Adding papr-scm dimm flags:\"%s\"\n", devname, buf); -+ dimm->cmd_family = NVDIMM_FAMILY_PAPR; -+ -+ /* Parse dimm flags */ -+ parse_papr_flags(dimm, buf); -+ -+ /* Allocate monitor mode fd */ -+ dimm->health_eventfd = open(path, O_RDONLY|O_CLOEXEC); -+ rc = 0; -+ -+ } else if (strcmp(buf, "nvdimm_test") == 0) { -+ /* probe via common populate_dimm_attributes() */ -+ rc = populate_dimm_attributes(dimm, dimm_base, "papr"); -+ } -+out: -+ free(path); -+ return rc; -+} -+ - static void *add_dimm(void *parent, int id, const char *dimm_base) - { - int formats, i, rc = -ENODEV; -@@ -1845,8 +1897,9 @@ static void *add_dimm(void *parent, int id, const char *dimm_base) - /* Check if the given dimm supports nfit */ - if (ndctl_bus_has_nfit(bus)) { - rc = populate_dimm_attributes(dimm, dimm_base, "nfit"); -- } else if (ndctl_bus_has_of_node(bus)) -- rc = populate_dimm_attributes(dimm, dimm_base, "papr"); -+ } else if (ndctl_bus_has_of_node(bus)) { -+ rc = add_papr_dimm(dimm, dimm_base); -+ } - - if (rc == -ENODEV) { - /* Unprobed dimm with no family */ --- -2.27.0 - diff --git a/SOURCES/0025-ndctl-scrub-Stop-translating-return-values.patch b/SOURCES/0025-ndctl-scrub-Stop-translating-return-values.patch deleted file mode 100644 index 1123cf8..0000000 --- a/SOURCES/0025-ndctl-scrub-Stop-translating-return-values.patch +++ /dev/null @@ -1,38 +0,0 @@ -From c52109355b715bbe21e284090435bee7563863cc Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 26 May 2021 16:33:04 -0700 -Subject: [PATCH 025/217] ndctl/scrub: Stop translating return values - -In preparation for triggering a poll loop within ndctl_bus_start_scrub(), -stop translating return values into -EOPNOTSUPP. - -Link: https://lore.kernel.org/r/162207198482.3715490.5994844104395495686.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - ndctl/lib/libndctl.c | 8 +------- - 1 file changed, 1 insertion(+), 7 deletions(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index aa36a3c..e5641fe 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -1354,14 +1354,8 @@ static int __ndctl_bus_get_scrub_state(struct ndctl_bus *bus, - NDCTL_EXPORT int ndctl_bus_start_scrub(struct ndctl_bus *bus) - { - struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus); -- int rc; - -- rc = sysfs_write_attr(ctx, bus->scrub_path, "1\n"); -- if (rc == -EBUSY) -- return rc; -- else if (rc < 0) -- return -EOPNOTSUPP; -- return 0; -+ return sysfs_write_attr(ctx, bus->scrub_path, "1\n"); - } - - NDCTL_EXPORT int ndctl_bus_get_scrub_state(struct ndctl_bus *bus) --- -2.27.0 - diff --git a/SOURCES/0026-ndctl-scrub-Reread-scrub-engine-status-at-start.patch b/SOURCES/0026-ndctl-scrub-Reread-scrub-engine-status-at-start.patch deleted file mode 100644 index ec7035f..0000000 --- a/SOURCES/0026-ndctl-scrub-Reread-scrub-engine-status-at-start.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 4e646fa490ba4b782afa188dd8818b94c419924e Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 26 May 2021 16:33:10 -0700 -Subject: [PATCH 026/217] ndctl/scrub: Reread scrub-engine status at start - -Given that the kernel has exponential backoff to cover the lack of -interrupts for scrub completion status there is a reasonable likelihood -that 'ndctl start-scrub' is issued while the hardware/platform scrub-state -is idle, but the kernel engine poll timer has not fired. - -Trigger at least one poll cycle for the kernel to re-read the scrub-state -before reporting that ARS is busy. - -Link: https://lore.kernel.org/r/162207199057.3715490.2469820075085914776.stgit@dwillia2-desk3.amr.corp.intel.com -Reported-by: Krzysztof Rusocki -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - ndctl/lib/libndctl.c | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index e5641fe..536e142 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -1354,8 +1354,18 @@ static int __ndctl_bus_get_scrub_state(struct ndctl_bus *bus, - NDCTL_EXPORT int ndctl_bus_start_scrub(struct ndctl_bus *bus) - { - struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus); -+ int rc; -+ -+ rc = sysfs_write_attr(ctx, bus->scrub_path, "1\n"); - -- return sysfs_write_attr(ctx, bus->scrub_path, "1\n"); -+ /* -+ * Try at least 1 poll cycle before reporting busy in case this -+ * request hits the kernel's exponential backoff while the -+ * hardware/platform scrub state is idle. -+ */ -+ if (rc == -EBUSY && ndctl_bus_poll_scrub_completion(bus, 1, 1) == 0) -+ return sysfs_write_attr(ctx, bus->scrub_path, "1\n"); -+ return rc; - } - - NDCTL_EXPORT int ndctl_bus_get_scrub_state(struct ndctl_bus *bus) --- -2.27.0 - diff --git a/SOURCES/0027-ndctl-dimm-Fix-label-index-block-calculations.patch b/SOURCES/0027-ndctl-dimm-Fix-label-index-block-calculations.patch deleted file mode 100644 index ad2e6c2..0000000 --- a/SOURCES/0027-ndctl-dimm-Fix-label-index-block-calculations.patch +++ /dev/null @@ -1,167 +0,0 @@ -From 7e98977c10ad5f4baf5e3bc4d5b4b2fd733a8b7e Mon Sep 17 00:00:00 2001 -From: Jingqi Liu -Date: Thu, 8 Jul 2021 16:14:46 +0800 -Subject: [PATCH 027/217] ndctl/dimm: Fix label index block calculations - -The following bug is caused by setting the size of Label Index Block -to a fixed 256 bytes. - -Use the following Qemu command to start a Guest with 2MB label-size: - -object memory-backend-file,id=mem1,share=on,mem-path=/dev/dax1.1,size=14G,align=2M - -device nvdimm,memdev=mem1,id=nv1,label-size=2M - -There is a namespace in the Guest as follows: - $ ndctl list - [ - { - "dev":"namespace0.0", - "mode":"devdax", - "map":"dev", - "size":14780727296, - "uuid":"58ad5282-5a16-404f-b8ee-e28b4c784eb8", - "chardev":"dax0.0", - "align":2097152, - "name":"namespace0.0" - } - ] - -Fail to read labels. The result is as follows: - $ ndctl read-labels -u nmem0 - [ - ] - read 0 nmem - -If using the following Qemu command to start the Guest with 128K -label-size, this label can be read correctly. - -object memory-backend-file,id=mem1,share=on,mem-path=/dev/dax1.1,size=14G,align=2M - -device nvdimm,memdev=mem1,id=nv1,label-size=128K - -The size of a Label Index Block depends on how many label slots fit into -the label storage area. The minimum size of an index block is 256 bytes -and the size must be a multiple of 256 bytes. For a storage area of 128KB, -the corresponding Label Index Block size is 256 bytes. But if the label -storage area is not 128KB, the Label Index Block size should not be 256 bytes. - -Namespace Label Index Block appears twice at the top of the label storage area. -Following the two index blocks, an array for storing labels takes up the -remainder of the label storage area. - -For obtaining the size of Namespace Index Block, we also cannot rely on -the field of 'mysize' in this index block since it might be corrupted. -Similar to the linux kernel, we use sizeof_namespace_index() to get the size -of Namespace Index Block. Then we can also correctly calculate the starting -offset of the following namespace labels. - -Link: https://lore.kernel.org/r/20210708081446.14323-1-jingqi.liu@intel.com -Suggested-by: Dan Williams -Reviewed-by: Dan Williams -Reviewed-by: Vishal Verma -Signed-off-by: Jingqi Liu -Signed-off-by: Vishal Verma ---- - ndctl/dimm.c | 19 +++++++++++++++---- - ndctl/lib/dimm.c | 5 +++++ - ndctl/lib/libndctl.sym | 1 + - ndctl/libndctl.h | 1 + - 4 files changed, 22 insertions(+), 4 deletions(-) - -diff --git a/ndctl/dimm.c b/ndctl/dimm.c -index 09ce49e..1d2d9a2 100644 ---- a/ndctl/dimm.c -+++ b/ndctl/dimm.c -@@ -94,13 +94,18 @@ static struct json_object *dump_label_json(struct ndctl_dimm *dimm, - struct json_object *jarray = json_object_new_array(); - struct json_object *jlabel = NULL; - struct namespace_label nslabel; -+ unsigned int nsindex_size; - unsigned int slot = -1; - ssize_t offset; - - if (!jarray) - return NULL; - -- for (offset = NSINDEX_ALIGN * 2; offset < size; -+ nsindex_size = ndctl_dimm_sizeof_namespace_index(dimm); -+ if (nsindex_size == 0) -+ return NULL; -+ -+ for (offset = nsindex_size * 2; offset < size; - offset += ndctl_dimm_sizeof_namespace_label(dimm)) { - ssize_t len = min_t(ssize_t, - ndctl_dimm_sizeof_namespace_label(dimm), -@@ -204,17 +209,23 @@ static struct json_object *dump_label_json(struct ndctl_dimm *dimm, - return jarray; - } - --static struct json_object *dump_index_json(struct ndctl_cmd *cmd_read, ssize_t size) -+static struct json_object *dump_index_json(struct ndctl_dimm *dimm, -+ struct ndctl_cmd *cmd_read, ssize_t size) - { - struct json_object *jarray = json_object_new_array(); - struct json_object *jindex = NULL; - struct namespace_index nsindex; -+ unsigned int nsindex_size; - ssize_t offset; - - if (!jarray) - return NULL; - -- for (offset = 0; offset < NSINDEX_ALIGN * 2; offset += NSINDEX_ALIGN) { -+ nsindex_size = ndctl_dimm_sizeof_namespace_index(dimm); -+ if (nsindex_size == 0) -+ return NULL; -+ -+ for (offset = 0; offset < nsindex_size * 2; offset += nsindex_size) { - ssize_t len = min_t(ssize_t, sizeof(nsindex), size - offset); - struct json_object *jobj; - -@@ -288,7 +299,7 @@ static struct json_object *dump_json(struct ndctl_dimm *dimm, - goto err; - json_object_object_add(jdimm, "dev", jobj); - -- jindex = dump_index_json(cmd_read, size); -+ jindex = dump_index_json(dimm, cmd_read, size); - if (!jindex) - goto err; - json_object_object_add(jdimm, "index", jindex); -diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c -index c045cbe..9e36e28 100644 ---- a/ndctl/lib/dimm.c -+++ b/ndctl/lib/dimm.c -@@ -256,6 +256,11 @@ static int __label_validate(struct nvdimm_data *ndd) - return -EINVAL; - } - -+NDCTL_EXPORT unsigned int ndctl_dimm_sizeof_namespace_index(struct ndctl_dimm *dimm) -+{ -+ return sizeof_namespace_index(&dimm->ndd); -+} -+ - /* - * If the dimm labels have not been previously validated this routine - * will make up a default size. Otherwise, it will pick the size based -diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym -index 58afb74..5ee73b7 100644 ---- a/ndctl/lib/libndctl.sym -+++ b/ndctl/lib/libndctl.sym -@@ -454,4 +454,5 @@ LIBNDCTL_25 { - - LIBNDCTL_26 { - ndctl_bus_nfit_translate_spa; -+ ndctl_dimm_sizeof_namespace_index; - } LIBNDCTL_25; -diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h -index 87d07b7..df109bb 100644 ---- a/ndctl/libndctl.h -+++ b/ndctl/libndctl.h -@@ -337,6 +337,7 @@ int ndctl_dimm_init_labels(struct ndctl_dimm *dimm, - enum ndctl_namespace_version v); - unsigned long ndctl_dimm_get_available_labels(struct ndctl_dimm *dimm); - unsigned int ndctl_dimm_sizeof_namespace_label(struct ndctl_dimm *dimm); -+unsigned int ndctl_dimm_sizeof_namespace_index(struct ndctl_dimm *dimm); - unsigned int ndctl_cmd_cfg_size_get_size(struct ndctl_cmd *cfg_size); - ssize_t ndctl_cmd_cfg_read_get_data(struct ndctl_cmd *cfg_read, void *buf, - unsigned int len, unsigned int offset); --- -2.27.0 - diff --git a/SOURCES/0028-ndctl-namespace-Skip-seed-namespaces-when-processing.patch b/SOURCES/0028-ndctl-namespace-Skip-seed-namespaces-when-processing.patch deleted file mode 100644 index 5d2ebd0..0000000 --- a/SOURCES/0028-ndctl-namespace-Skip-seed-namespaces-when-processing.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 9bd2994f91bb77604521cbe09a76a51d092c2cfd Mon Sep 17 00:00:00 2001 -From: Michal Suchanek -Date: Wed, 6 Jan 2021 14:17:40 +0100 -Subject: [PATCH 028/217] ndctl/namespace: Skip seed namespaces when processing - all namespaces. - -The seed namespaces are exposed by the kernel but most operations are -not valid on seed namespaces. - -When processing all namespaces the user gets confusing errors from ndctl -trying to process seed namespaces. The kernel does not provide any way -to tell that a namspace is seed namespace but skipping namespaces with -zero size and UUID is a good heuristic. - -The user can still specify the namespace by name directly in case -processing it is desirable. - -Link: https://patchwork.kernel.org/patch/11473645/ -Link: https://lore.kernel.org/r/e55ae2c17b8b9c3288491efe6214338118e8c5ae.1609938610.git.msuchanek@suse.de -Fixes: #41 -Tested-by: Harish Sriram -Reviewed-by: Santosh S -Signed-off-by: Michal Suchanek -Signed-off-by: Vishal Verma ---- - ndctl/namespace.c | 16 +++++++++++++--- - 1 file changed, 13 insertions(+), 3 deletions(-) - -diff --git a/ndctl/namespace.c b/ndctl/namespace.c -index 1e8a2cd..5e65ed5 100644 ---- a/ndctl/namespace.c -+++ b/ndctl/namespace.c -@@ -2210,9 +2210,19 @@ static int do_xaction_namespace(const char *namespace, - ndctl_namespace_foreach_safe(region, ndns, _n) { - ndns_name = ndctl_namespace_get_devname(ndns); - -- if (strcmp(namespace, "all") != 0 -- && strcmp(namespace, ndns_name) != 0) -- continue; -+ if (strcmp(namespace, "all") == 0) { -+ static const uuid_t zero_uuid; -+ uuid_t uuid; -+ -+ ndctl_namespace_get_uuid(ndns, uuid); -+ if (!ndctl_namespace_get_size(ndns) && -+ !memcmp(uuid, zero_uuid, sizeof(uuid_t))) -+ continue; -+ } else { -+ if (strcmp(namespace, ndns_name) != 0) -+ continue; -+ } -+ - switch (action) { - case ACTION_DISABLE: - rc = ndctl_namespace_disable_safe(ndns); --- -2.27.0 - diff --git a/SOURCES/0029-ndctl-namespace-Suppress-ENXIO-when-processing-all-n.patch b/SOURCES/0029-ndctl-namespace-Suppress-ENXIO-when-processing-all-n.patch deleted file mode 100644 index 75b7c3f..0000000 --- a/SOURCES/0029-ndctl-namespace-Suppress-ENXIO-when-processing-all-n.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 07011a334fd1e4b641cdbfaf5de7500f7bdc941d Mon Sep 17 00:00:00 2001 -From: Michal Suchanek -Date: Wed, 6 Jan 2021 14:17:41 +0100 -Subject: [PATCH 029/217] ndctl/namespace: Suppress -ENXIO when processing all - namespaces. - -When processing all namespaces and no namespaces exist user gets the -default -ENXIO. Set default rc to 0 when processing all namespaces. -This avoids confusing error message printed in addition to the message -saying 0 namespaces were affected. - -Before: - - # ndctl check-namespace all -namespace0.0: namespace_check: namespace0.0: check aborted, namespace online -error checking namespaces: Device or resource busy -checked 0 namespaces - # ndctl disable-namespace all -disabled 1 namespace - # ndctl check-namespace all -namespace0.0: namespace_check: Unable to recover any BTT info blocks -error checking namespaces: No such device or address -checked 0 namespaces - # ndctl destroy-namespace all -destroyed 1 namespace - # ndctl check-namespace all -error checking namespaces: No such device or address -checked 0 namespaces - # ndctl destroy-namespace all -error destroying namespaces: No such device or address -destroyed 0 namespaces - -After: - - # ndctl check-namespace all -namespace0.0: namespace_check: namespace0.0: check aborted, namespace online -error checking namespaces: Device or resource busy -checked 0 namespaces - # ndctl disable-namespace namespace0.0 -disabled 1 namespace - # ndctl check-namespace all -namespace0.0: namespace_check: Unable to recover any BTT info blocks -error checking namespaces: No such device or address -checked 0 namespaces - # ndctl destroy-namespace all -destroyed 1 namespace - # ndctl check-namespace all -checked 0 namespaces - # ndctl destroy-namespace all -destroyed 0 namespaces - # ndctl destroy-namespace all -destroyed 0 namespaces - -Note: this does change the return value from -ENXIO to 0 in the cases -when no namespaces exist and processing all namespaces was requested. - -Link: https://patchwork.kernel.org/patch/11681431/ -Link: https://lore.kernel.org/r/32c8cd8d2716f5e52aebea4e4d303eeb4e0550f9.1609938610.git.msuchanek@suse.de -Reviewed-by: Santosh S -Signed-off-by: Michal Suchanek -Signed-off-by: Vishal Verma ---- - ndctl/namespace.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/ndctl/namespace.c b/ndctl/namespace.c -index 5e65ed5..cd822b3 100644 ---- a/ndctl/namespace.c -+++ b/ndctl/namespace.c -@@ -2151,6 +2151,9 @@ static int do_xaction_namespace(const char *namespace, - if (!namespace && action != ACTION_CREATE) - return rc; - -+ if (namespace && (strcmp(namespace, "all") == 0)) -+ rc = 0; -+ - if (verbose) - ndctl_set_log_priority(ctx, LOG_DEBUG); - --- -2.27.0 - diff --git a/SOURCES/0030-namespace-action-Drop-zero-namespace-checks.patch b/SOURCES/0030-namespace-action-Drop-zero-namespace-checks.patch deleted file mode 100644 index dde5c63..0000000 --- a/SOURCES/0030-namespace-action-Drop-zero-namespace-checks.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 80e0d88c3098bd419e26146a8cb3b693fdd06417 Mon Sep 17 00:00:00 2001 -From: Santosh Sivaraj -Date: Wed, 6 Jan 2021 14:17:42 +0100 -Subject: [PATCH 030/217] namespace-action: Drop zero namespace checks. - -With seed namespaces catched early on these checks for sizes in enable -and destroy namespace code path are not needed. - -Reverts commit b9cb03f6d5a8 ("ndctl/namespace: Fix enable-namespace -error for seed namespaces") - -Reverts commit e01045e58ad5 ("ndctl/namespace: Fix destroy-namespace -accounting relative to seed devices") - -Link: https://patchwork.kernel.org/patch/11739975/ -Link: https://lore.kernel.org/r/eb4bc7885708fa13e3d37286bc4a4219b1e4e5b6.1609938610.git.msuchanek@suse.de -Fixes: b9cb03f6d5a8 ("ndctl/namespace: Fix enable-namespace error for seed namespaces") -Fixes: e01045e58ad5 ("ndctl/namespace: Fix destroy-namespace accounting relative to seed devices") -Signed-off-by: Santosh Sivaraj -[rebased on top of the previous patches] -Signed-off-by: Michal Suchanek -Signed-off-by: Vishal Verma ---- - ndctl/lib/libndctl.c | 5 ----- - ndctl/namespace.c | 10 ---------- - 2 files changed, 15 deletions(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index 536e142..87f60b9 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -4531,16 +4531,11 @@ NDCTL_EXPORT int ndctl_namespace_enable(struct ndctl_namespace *ndns) - const char *devname = ndctl_namespace_get_devname(ndns); - struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns); - struct ndctl_region *region = ndns->region; -- unsigned long long size = ndctl_namespace_get_size(ndns); - int rc; - - if (ndctl_namespace_is_enabled(ndns)) - return 0; - -- /* Don't try to enable idle namespace (no capacity allocated) */ -- if (size == 0) -- return -ENXIO; -- - rc = ndctl_bind(ctx, ndns->module, devname); - - /* -diff --git a/ndctl/namespace.c b/ndctl/namespace.c -index cd822b3..c67c086 100644 ---- a/ndctl/namespace.c -+++ b/ndctl/namespace.c -@@ -1164,15 +1164,12 @@ static int namespace_destroy(struct ndctl_region *region, - struct ndctl_namespace *ndns) - { - const char *devname = ndctl_namespace_get_devname(ndns); -- unsigned long long size; - int rc; - - rc = namespace_prep_reconfig(region, ndns); - if (rc < 0) - return rc; - -- size = ndctl_namespace_get_size(ndns); -- - /* Labeled namespace, destroy label / allocation */ - if (rc == 2) { - rc = ndctl_namespace_delete(ndns); -@@ -1180,13 +1177,6 @@ static int namespace_destroy(struct ndctl_region *region, - debug("%s: failed to reclaim\n", devname); - } - -- /* -- * Don't report a destroyed namespace when no capacity was -- * allocated. -- */ -- if (size == 0 && rc == 0) -- rc = 1; -- - return rc; - } - --- -2.27.0 - diff --git a/SOURCES/0031-ndctl-add-.clang-format.patch b/SOURCES/0031-ndctl-add-.clang-format.patch deleted file mode 100644 index a447ec3..0000000 --- a/SOURCES/0031-ndctl-add-.clang-format.patch +++ /dev/null @@ -1,187 +0,0 @@ -From dc712e47c39f4dbc5f089831fd50dd1a2752c8fc Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:23 -0600 -Subject: [PATCH 031/217] ndctl: add .clang-format - -Copy the Linux kernel's .clang-format and modify it for ndctl. Only the -'ForEachMacros' section has been modified from the original kernel copy. - -Cc: Dan Williams -Reported-by: Ben Widawsky -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .clang-format | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 161 insertions(+) - create mode 100644 .clang-format - -diff --git a/.clang-format b/.clang-format -new file mode 100644 -index 0000000..4e00fff ---- /dev/null -+++ b/.clang-format -@@ -0,0 +1,161 @@ -+# SPDX-License-Identifier: GPL-2.0 -+# -+# clang-format configuration file. Intended for clang-format >= 4. -+# Copied from Linux's .clang-format -+# -+# For more information, see: -+# -+# https://clang.llvm.org/docs/ClangFormat.html -+# https://clang.llvm.org/docs/ClangFormatStyleOptions.html -+# -+--- -+AccessModifierOffset: -4 -+AlignAfterOpenBracket: Align -+AlignConsecutiveAssignments: false -+AlignConsecutiveDeclarations: false -+#AlignEscapedNewlines: Left # Unknown to clang-format-4.0 -+AlignOperands: true -+AlignTrailingComments: false -+AllowAllParametersOfDeclarationOnNextLine: false -+AllowShortBlocksOnASingleLine: false -+AllowShortCaseLabelsOnASingleLine: false -+AllowShortFunctionsOnASingleLine: None -+AllowShortIfStatementsOnASingleLine: false -+AllowShortLoopsOnASingleLine: false -+AlwaysBreakAfterDefinitionReturnType: None -+AlwaysBreakAfterReturnType: None -+AlwaysBreakBeforeMultilineStrings: false -+AlwaysBreakTemplateDeclarations: false -+BinPackArguments: true -+BinPackParameters: true -+BraceWrapping: -+ AfterClass: false -+ AfterControlStatement: false -+ AfterEnum: false -+ AfterFunction: true -+ AfterNamespace: true -+ AfterObjCDeclaration: false -+ AfterStruct: false -+ AfterUnion: false -+ #AfterExternBlock: false # Unknown to clang-format-5.0 -+ BeforeCatch: false -+ BeforeElse: false -+ IndentBraces: false -+ #SplitEmptyFunction: true # Unknown to clang-format-4.0 -+ #SplitEmptyRecord: true # Unknown to clang-format-4.0 -+ #SplitEmptyNamespace: true # Unknown to clang-format-4.0 -+BreakBeforeBinaryOperators: None -+BreakBeforeBraces: Custom -+#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0 -+BreakBeforeTernaryOperators: false -+BreakConstructorInitializersBeforeComma: false -+#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0 -+BreakAfterJavaFieldAnnotations: false -+BreakStringLiterals: false -+ColumnLimit: 80 -+CommentPragmas: '^ IWYU pragma:' -+#CompactNamespaces: false # Unknown to clang-format-4.0 -+ConstructorInitializerAllOnOneLineOrOnePerLine: false -+ConstructorInitializerIndentWidth: 8 -+ContinuationIndentWidth: 8 -+Cpp11BracedListStyle: false -+DerivePointerAlignment: false -+DisableFormat: false -+ExperimentalAutoDetectBinPacking: false -+#FixNamespaceComments: false # Unknown to clang-format-4.0 -+ -+# Taken from: -+# while read -r sym; do -+# printf " - '%s'\n" "$sym"; -+# done < \ -+# <(cscope -dL6 "foreach|for_each" \ -+# | awk '{ print $4 $5 }' | grep -E 'foreach|for_each' \ -+# | sed -e 's/#define//' \ -+# -e 's/*//' \ -+# -e 's/://' \ -+# -e 's/\(.*for_each.*\)(.*/\1/' \ -+# -e 's/\(.*foreach.*\)(.*/\1/' \ -+# | sort -u) -+ForEachMacros: -+ - 'daxctl_dev_foreach' -+ - 'daxctl_mapping_foreach' -+ - 'daxctl_region_foreach' -+ - 'kmod_list_foreach' -+ - 'kmod_list_foreach_reverse' -+ - 'list_for_each' -+ - 'list_for_each_off' -+ - 'list_for_each_rev' -+ - 'list_for_each_safe' -+ - 'list_for_each_safe_off' -+ - 'ndctl_btt_foreach' -+ - 'ndctl_btt_foreach_safe' -+ - 'ndctl_bus_foreach' -+ - 'ndctl_dax_foreach' -+ - 'ndctl_dax_foreach_safe' -+ - 'ndctl_dimm_foreach' -+ - 'ndctl_dimm_foreach_in_interleave_set' -+ - 'ndctl_dimm_foreach_in_region' -+ - 'ndctl_interleave_set_foreach' -+ - 'ndctl_mapping_foreach' -+ - 'ndctl_namespace_badblock_foreach' -+ - 'ndctl_namespace_bb_foreach' -+ - 'ndctl_namespace_foreach' -+ - 'ndctl_namespace_foreach_safe' -+ - 'ndctl_pfn_foreach' -+ - 'ndctl_pfn_foreach_safe' -+ - 'ndctl_region_badblock_foreach' -+ - 'ndctl_region_foreach' -+ - 'udev_list_entry_foreach' -+ -+#IncludeBlocks: Preserve # Unknown to clang-format-5.0 -+IncludeCategories: -+ - Regex: '.*' -+ Priority: 1 -+IncludeIsMainRegex: '(Test)?$' -+IndentCaseLabels: false -+#IndentPPDirectives: None # Unknown to clang-format-5.0 -+IndentWidth: 8 -+IndentWrappedFunctionNames: false -+JavaScriptQuotes: Leave -+JavaScriptWrapImports: true -+KeepEmptyLinesAtTheStartOfBlocks: false -+MacroBlockBegin: '' -+MacroBlockEnd: '' -+MaxEmptyLinesToKeep: 1 -+NamespaceIndentation: None -+#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0 -+ObjCBlockIndentWidth: 8 -+ObjCSpaceAfterProperty: true -+ObjCSpaceBeforeProtocolList: true -+ -+# Taken from git's rules -+#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0 -+PenaltyBreakBeforeFirstCallParameter: 30 -+PenaltyBreakComment: 10 -+PenaltyBreakFirstLessLess: 0 -+PenaltyBreakString: 10 -+PenaltyExcessCharacter: 100 -+PenaltyReturnTypeOnItsOwnLine: 60 -+ -+PointerAlignment: Right -+ReflowComments: false -+SortIncludes: false -+#SortUsingDeclarations: false # Unknown to clang-format-4.0 -+SpaceAfterCStyleCast: false -+SpaceAfterTemplateKeyword: true -+SpaceBeforeAssignmentOperators: true -+#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0 -+#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0 -+SpaceBeforeParens: ControlStatements -+#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0 -+SpaceInEmptyParentheses: false -+SpacesBeforeTrailingComments: 1 -+SpacesInAngles: false -+SpacesInContainerLiterals: false -+SpacesInCStyleCastParentheses: false -+SpacesInParentheses: false -+SpacesInSquareBrackets: false -+Standard: Cpp03 -+TabWidth: 8 -+UseTab: Always -+... --- -2.27.0 - diff --git a/SOURCES/0032-cxl-add-a-cxl-utility-and-libcxl-library.patch b/SOURCES/0032-cxl-add-a-cxl-utility-and-libcxl-library.patch deleted file mode 100644 index a283fd4..0000000 --- a/SOURCES/0032-cxl-add-a-cxl-utility-and-libcxl-library.patch +++ /dev/null @@ -1,1277 +0,0 @@ -From 6cd8155dd5a600f1bb435a49ebddc1fae2f60e73 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:24 -0600 -Subject: [PATCH 032/217] cxl: add a cxl utility and libcxl library - -CXL - or Compute eXpress Link - is a new interconnect that extends PCIe -to support a wide range of devices, including cache coherent memory -expanders. As such, these devices can be new sources of 'persistent -memory', and the 'ndctl' umbrella of tools and libraries needs to be able -to interact with them. - -Add a new utility and library for managing these CXL memory devices. This -is an initial bring-up for interacting with CXL devices, and only includes -adding the utility and library infrastructure, parsing device information -from sysfs for CXL devices, and providing a 'cxl-list' command to -display this information in JSON formatted output. - -Cc: Ben Widawsky -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .clang-format | 1 + - .gitignore | 4 +- - Documentation/cxl/Makefile.am | 58 +++++ - Documentation/cxl/cxl-list.txt | 59 +++++ - Documentation/cxl/cxl.txt | 34 +++ - Documentation/cxl/human-option.txt | 8 + - Documentation/cxl/verbose-option.txt | 5 + - Makefile.am | 8 +- - Makefile.am.in | 4 + - configure.ac | 3 + - cxl/Makefile.am | 21 ++ - cxl/builtin.h | 8 + - cxl/cxl.c | 96 ++++++++ - cxl/lib/Makefile.am | 32 +++ - cxl/lib/libcxl.c | 345 +++++++++++++++++++++++++++ - cxl/lib/libcxl.pc.in | 11 + - cxl/lib/libcxl.sym | 25 ++ - cxl/lib/private.h | 29 +++ - cxl/libcxl.h | 55 +++++ - cxl/list.c | 121 ++++++++++ - util/filter.c | 20 ++ - util/filter.h | 2 + - util/json.c | 26 ++ - util/json.h | 3 + - util/main.h | 3 + - 25 files changed, 977 insertions(+), 4 deletions(-) - create mode 100644 Documentation/cxl/Makefile.am - create mode 100644 Documentation/cxl/cxl-list.txt - create mode 100644 Documentation/cxl/cxl.txt - create mode 100644 Documentation/cxl/human-option.txt - create mode 100644 Documentation/cxl/verbose-option.txt - create mode 100644 cxl/Makefile.am - create mode 100644 cxl/builtin.h - create mode 100644 cxl/cxl.c - create mode 100644 cxl/lib/Makefile.am - create mode 100644 cxl/lib/libcxl.c - create mode 100644 cxl/lib/libcxl.pc.in - create mode 100644 cxl/lib/libcxl.sym - create mode 100644 cxl/lib/private.h - create mode 100644 cxl/libcxl.h - create mode 100644 cxl/list.c - -diff --git a/.clang-format b/.clang-format -index 4e00fff..d2e77d0 100644 ---- a/.clang-format -+++ b/.clang-format -@@ -77,6 +77,7 @@ ExperimentalAutoDetectBinPacking: false - # -e 's/\(.*foreach.*\)(.*/\1/' \ - # | sort -u) - ForEachMacros: -+ - 'cxl_memdev_foreach' - - 'daxctl_dev_foreach' - - 'daxctl_mapping_foreach' - - 'daxctl_region_foreach' -diff --git a/.gitignore b/.gitignore -index 53512b2..6a97b92 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -16,9 +16,11 @@ Makefile.in - *.1 - Documentation/daxctl/asciidoc.conf - Documentation/ndctl/asciidoc.conf --Documentation/ndctl/attrs.adoc -+Documentation/cxl/asciidoc.conf - Documentation/daxctl/asciidoctor-extensions.rb - Documentation/ndctl/asciidoctor-extensions.rb -+Documentation/cxl/asciidoctor-extensions.rb -+Documentation/ndctl/attrs.adoc - .dirstamp - daxctl/config.h - daxctl/daxctl -diff --git a/Documentation/cxl/Makefile.am b/Documentation/cxl/Makefile.am -new file mode 100644 -index 0000000..db98dd7 ---- /dev/null -+++ b/Documentation/cxl/Makefile.am -@@ -0,0 +1,58 @@ -+# SPDX-License-Identifier: GPL-2.0 -+# Copyright (C) 2020-2021 Intel Corporation. All rights reserved. -+ -+if USE_ASCIIDOCTOR -+ -+do_subst = sed -e 's,@Utility@,Cxl,g' -e's,@utility@,cxl,g' -+CONFFILE = asciidoctor-extensions.rb -+asciidoctor-extensions.rb: ../asciidoctor-extensions.rb.in -+ $(AM_V_GEN) $(do_subst) < $< > $@ -+ -+else -+ -+do_subst = sed -e 's,UTILITY,cxl,g' -+CONFFILE = asciidoc.conf -+asciidoc.conf: ../asciidoc.conf.in -+ $(AM_V_GEN) $(do_subst) < $< > $@ -+ -+endif -+ -+man1_MANS = \ -+ cxl.1 \ -+ cxl-list.1 -+ -+EXTRA_DIST = $(man1_MANS) -+ -+CLEANFILES = $(man1_MANS) -+ -+XML_DEPS = \ -+ ../../version.m4 \ -+ ../copyright.txt \ -+ Makefile \ -+ $(CONFFILE) -+ -+RM ?= rm -f -+ -+if USE_ASCIIDOCTOR -+ -+%.1: %.txt $(XML_DEPS) -+ $(AM_V_GEN)$(RM) $@+ $@ && \ -+ $(ASCIIDOC) -b manpage -d manpage -acompat-mode \ -+ -I. -rasciidoctor-extensions \ -+ -amansource=cxl -amanmanual="cxl Manual" \ -+ -andctl_version=$(VERSION) -o $@+ $< && \ -+ mv $@+ $@ -+ -+else -+ -+%.xml: %.txt $(XML_DEPS) -+ $(AM_V_GEN)$(RM) $@+ $@ && \ -+ $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \ -+ --unsafe -acxl_version=$(VERSION) -o $@+ $< && \ -+ mv $@+ $@ -+ -+%.1: %.xml $(XML_DEPS) -+ $(AM_V_GEN)$(RM) $@ && \ -+ $(XMLTO) -o . -m ../manpage-normal.xsl man $< -+ -+endif -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -new file mode 100644 -index 0000000..370d5b8 ---- /dev/null -+++ b/Documentation/cxl/cxl-list.txt -@@ -0,0 +1,59 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-list(1) -+=========== -+ -+NAME -+---- -+cxl-list - List CXL capable memory devices, and their attributes in json. -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl list' [] -+ -+Walk the CXL capable device hierarchy in the system and list all device -+instances along with some of their major attributes. -+ -+EXAMPLE -+------- -+---- -+# cxl list --memdevs -+{ -+ "memdev":"mem0", -+ "pmem_size":268435456, -+ "ram_size":0, -+} -+---- -+ -+OPTIONS -+------- -+-m:: -+--memdev=:: -+ Specify a cxl memory device name to filter the listing. For example: -+---- -+# cxl list --memdev=mem0 -+{ -+ "memdev":"mem0", -+ "pmem_size":268435456, -+ "ram_size":0, -+} -+---- -+ -+-M:: -+--memdevs:: -+ Include CXL memory devices in the listing -+ -+-i:: -+--idle:: -+ Include idle (not enabled / zero-sized) devices in the listing -+ -+include::human-option.txt[] -+ -+include::verbose-option.txt[] -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:ndctl-list[1] -diff --git a/Documentation/cxl/cxl.txt b/Documentation/cxl/cxl.txt -new file mode 100644 -index 0000000..41a51c7 ---- /dev/null -+++ b/Documentation/cxl/cxl.txt -@@ -0,0 +1,34 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl(1) -+====== -+ -+NAME -+---- -+cxl - Provides enumeration and provisioning commands for CXL platforms -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl' [--version] [--help] COMMAND [ARGS] -+ -+OPTIONS -+------- -+-v:: -+--version:: -+ Display the version of the 'cxl' utility. -+ -+-h:: -+--help:: -+ Run the 'cxl help' command. -+ -+DESCRIPTION -+----------- -+The cxl utility provides enumeration and provisioning commands for -+the CXL devices managed by the Linux kernel. -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:ndctl[1] -diff --git a/Documentation/cxl/human-option.txt b/Documentation/cxl/human-option.txt -new file mode 100644 -index 0000000..2f4de7a ---- /dev/null -+++ b/Documentation/cxl/human-option.txt -@@ -0,0 +1,8 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+-u:: -+--human:: -+ By default the command will output machine-friendly raw-integer -+ data. Instead, with this flag, numbers representing storage size -+ will be formatted as human readable strings with units, other -+ fields are converted to hexadecimal strings. -diff --git a/Documentation/cxl/verbose-option.txt b/Documentation/cxl/verbose-option.txt -new file mode 100644 -index 0000000..cb62c8e ---- /dev/null -+++ b/Documentation/cxl/verbose-option.txt -@@ -0,0 +1,5 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+-v:: -+--verbose:: -+ Emit more debug messages -diff --git a/Makefile.am b/Makefile.am -index 60a1998..428fd40 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1,9 +1,9 @@ - include Makefile.am.in - - ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} --SUBDIRS = . daxctl/lib ndctl/lib ndctl daxctl -+SUBDIRS = . cxl/lib daxctl/lib ndctl/lib cxl ndctl daxctl - if ENABLE_DOCS --SUBDIRS += Documentation/ndctl Documentation/daxctl -+SUBDIRS += Documentation/ndctl Documentation/daxctl Documentation/cxl - endif - SUBDIRS += test - -@@ -87,4 +87,6 @@ libutil_a_SOURCES = \ - util/filter.h \ - util/bitmap.h - --nobase_include_HEADERS = daxctl/libdaxctl.h -+nobase_include_HEADERS = \ -+ daxctl/libdaxctl.h \ -+ cxl/libcxl.h -diff --git a/Makefile.am.in b/Makefile.am.in -index bdceda9..aaeee53 100644 ---- a/Makefile.am.in -+++ b/Makefile.am.in -@@ -42,3 +42,7 @@ LIBNDCTL_AGE=19 - LIBDAXCTL_CURRENT=6 - LIBDAXCTL_REVISION=0 - LIBDAXCTL_AGE=5 -+ -+LIBCXL_CURRENT=1 -+LIBCXL_REVISION=0 -+LIBCXL_AGE=0 -diff --git a/configure.ac b/configure.ac -index dc39dbe..dadae0a 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -222,12 +222,15 @@ AC_CONFIG_HEADERS(config.h) - AC_CONFIG_FILES([ - Makefile - daxctl/lib/Makefile -+ cxl/lib/Makefile - ndctl/lib/Makefile - ndctl/Makefile - daxctl/Makefile -+ cxl/Makefile - test/Makefile - Documentation/ndctl/Makefile - Documentation/daxctl/Makefile -+ Documentation/cxl/Makefile - ]) - - AC_OUTPUT -diff --git a/cxl/Makefile.am b/cxl/Makefile.am -new file mode 100644 -index 0000000..98606b9 ---- /dev/null -+++ b/cxl/Makefile.am -@@ -0,0 +1,21 @@ -+include $(top_srcdir)/Makefile.am.in -+ -+bin_PROGRAMS = cxl -+ -+DISTCLEANFILES = config.h -+BUILT_SOURCES = config.h -+config.h: $(srcdir)/Makefile.am -+ $(AM_V_GEN) echo "/* Autogenerated by cxl/Makefile.am */" >$@ -+ -+cxl_SOURCES =\ -+ cxl.c \ -+ list.c \ -+ ../util/json.c \ -+ builtin.h -+ -+cxl_LDADD =\ -+ lib/libcxl.la \ -+ ../libutil.a \ -+ $(UUID_LIBS) \ -+ $(KMOD_LIBS) \ -+ $(JSON_LIBS) -diff --git a/cxl/builtin.h b/cxl/builtin.h -new file mode 100644 -index 0000000..3797f98 ---- /dev/null -+++ b/cxl/builtin.h -@@ -0,0 +1,8 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright (C) 2020-2021 Intel Corporation. All rights reserved. */ -+#ifndef _CXL_BUILTIN_H_ -+#define _CXL_BUILTIN_H_ -+ -+struct cxl_ctx; -+int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx); -+#endif /* _CXL_BUILTIN_H_ */ -diff --git a/cxl/cxl.c b/cxl/cxl.c -new file mode 100644 -index 0000000..a7725f8 ---- /dev/null -+++ b/cxl/cxl.c -@@ -0,0 +1,96 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* Copyright (C) 2020-2021 Intel Corporation. All rights reserved. */ -+/* Copyright (C) 2005 Andreas Ericsson. All rights reserved. */ -+ -+/* originally copied from perf and git */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+const char cxl_usage_string[] = "cxl [--version] [--help] COMMAND [ARGS]"; -+const char cxl_more_info_string[] = -+ "See 'cxl help COMMAND' for more information on a specific command.\n" -+ " cxl --list-cmds to see all available commands"; -+ -+static int cmd_version(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ printf("%s\n", VERSION); -+ return 0; -+} -+ -+static int cmd_help(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ const char * const builtin_help_subcommands[] = { -+ "list", -+ NULL, -+ }; -+ struct option builtin_help_options[] = { -+ OPT_END(), -+ }; -+ const char *builtin_help_usage[] = { -+ "cxl help [command]", -+ NULL -+ }; -+ -+ argc = parse_options_subcommand(argc, argv, builtin_help_options, -+ builtin_help_subcommands, builtin_help_usage, 0); -+ -+ if (!argv[0]) { -+ printf("\n usage: %s\n\n", cxl_usage_string); -+ printf("\n %s\n\n", cxl_more_info_string); -+ return 0; -+ } -+ -+ return help_show_man_page(argv[0], "cxl", "CXL_MAN_VIEWER"); -+} -+ -+static struct cmd_struct commands[] = { -+ { "version", .c_fn = cmd_version }, -+ { "list", .c_fn = cmd_list }, -+ { "help", .c_fn = cmd_help }, -+}; -+ -+int main(int argc, const char **argv) -+{ -+ struct cxl_ctx *ctx; -+ int rc; -+ -+ /* Look for flags.. */ -+ argv++; -+ argc--; -+ main_handle_options(&argv, &argc, cxl_usage_string, commands, -+ ARRAY_SIZE(commands)); -+ -+ if (argc > 0) { -+ if (!prefixcmp(argv[0], "--")) -+ argv[0] += 2; -+ } else { -+ /* The user didn't specify a command; give them help */ -+ printf("\n usage: %s\n\n", cxl_usage_string); -+ printf("\n %s\n\n", cxl_more_info_string); -+ goto out; -+ } -+ -+ rc = cxl_new(&ctx); -+ if (rc) -+ goto out; -+ main_handle_internal_command(argc, argv, ctx, commands, -+ ARRAY_SIZE(commands), PROG_CXL); -+ cxl_unref(ctx); -+ fprintf(stderr, "Unknown command: '%s'\n", argv[0]); -+out: -+ return 1; -+} -diff --git a/cxl/lib/Makefile.am b/cxl/lib/Makefile.am -new file mode 100644 -index 0000000..277f0cd ---- /dev/null -+++ b/cxl/lib/Makefile.am -@@ -0,0 +1,32 @@ -+include $(top_srcdir)/Makefile.am.in -+ -+%.pc: %.pc.in Makefile -+ $(SED_PROCESS) -+ -+pkginclude_HEADERS = ../libcxl.h -+lib_LTLIBRARIES = libcxl.la -+ -+libcxl_la_SOURCES =\ -+ ../libcxl.h \ -+ private.h \ -+ ../../util/sysfs.c \ -+ ../../util/sysfs.h \ -+ ../../util/log.c \ -+ ../../util/log.h \ -+ libcxl.c -+ -+libcxl_la_LIBADD =\ -+ $(UUID_LIBS) \ -+ $(KMOD_LIBS) -+ -+EXTRA_DIST += libcxl.sym -+ -+libcxl_la_LDFLAGS = $(AM_LDFLAGS) \ -+ -version-info $(LIBCXL_CURRENT):$(LIBCXL_REVISION):$(LIBCXL_AGE) \ -+ -Wl,--version-script=$(top_srcdir)/cxl/lib/libcxl.sym -+libcxl_la_DEPENDENCIES = libcxl.sym -+ -+pkgconfigdir = $(libdir)/pkgconfig -+pkgconfig_DATA = libcxl.pc -+EXTRA_DIST += libcxl.pc.in -+CLEANFILES += libcxl.pc -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -new file mode 100644 -index 0000000..c15e987 ---- /dev/null -+++ b/cxl/lib/libcxl.c -@@ -0,0 +1,345 @@ -+// SPDX-License-Identifier: LGPL-2.1 -+// Copyright (C) 2020-2021, Intel Corporation. All rights reserved. -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include "private.h" -+ -+/** -+ * struct cxl_ctx - library user context to find "nd" instances -+ * -+ * Instantiate with cxl_new(), which takes an initial reference. Free -+ * the context by dropping the reference count to zero with -+ * cxl_unref(), or take additional references with cxl_ref() -+ * @timeout: default library timeout in milliseconds -+ */ -+struct cxl_ctx { -+ /* log_ctx must be first member for cxl_set_log_fn compat */ -+ struct log_ctx ctx; -+ int refcount; -+ void *userdata; -+ int memdevs_init; -+ struct list_head memdevs; -+ struct kmod_ctx *kmod_ctx; -+ void *private_data; -+}; -+ -+static void free_memdev(struct cxl_memdev *memdev, struct list_head *head) -+{ -+ if (head) -+ list_del_from(head, &memdev->list); -+ kmod_module_unref(memdev->module); -+ free(memdev->firmware_version); -+ free(memdev->dev_buf); -+ free(memdev->dev_path); -+ free(memdev); -+} -+ -+/** -+ * cxl_get_userdata - retrieve stored data pointer from library context -+ * @ctx: cxl library context -+ * -+ * This might be useful to access from callbacks like a custom logging -+ * function. -+ */ -+CXL_EXPORT void *cxl_get_userdata(struct cxl_ctx *ctx) -+{ -+ if (ctx == NULL) -+ return NULL; -+ return ctx->userdata; -+} -+ -+/** -+ * cxl_set_userdata - store custom @userdata in the library context -+ * @ctx: cxl library context -+ * @userdata: data pointer -+ */ -+CXL_EXPORT void cxl_set_userdata(struct cxl_ctx *ctx, void *userdata) -+{ -+ if (ctx == NULL) -+ return; -+ ctx->userdata = userdata; -+} -+ -+CXL_EXPORT void cxl_set_private_data(struct cxl_ctx *ctx, void *data) -+{ -+ ctx->private_data = data; -+} -+ -+CXL_EXPORT void *cxl_get_private_data(struct cxl_ctx *ctx) -+{ -+ return ctx->private_data; -+} -+ -+/** -+ * cxl_new - instantiate a new library context -+ * @ctx: context to establish -+ * -+ * Returns zero on success and stores an opaque pointer in ctx. The -+ * context is freed by cxl_unref(), i.e. cxl_new() implies an -+ * internal cxl_ref(). -+ */ -+CXL_EXPORT int cxl_new(struct cxl_ctx **ctx) -+{ -+ struct kmod_ctx *kmod_ctx; -+ struct cxl_ctx *c; -+ int rc = 0; -+ -+ c = calloc(1, sizeof(struct cxl_ctx)); -+ if (!c) -+ return -ENOMEM; -+ -+ kmod_ctx = kmod_new(NULL, NULL); -+ if (check_kmod(kmod_ctx) != 0) { -+ rc = -ENXIO; -+ goto out; -+ } -+ -+ c->refcount = 1; -+ log_init(&c->ctx, "libcxl", "CXL_LOG"); -+ info(c, "ctx %p created\n", c); -+ dbg(c, "log_priority=%d\n", c->ctx.log_priority); -+ *ctx = c; -+ list_head_init(&c->memdevs); -+ c->kmod_ctx = kmod_ctx; -+ -+ return 0; -+out: -+ free(c); -+ return rc; -+} -+ -+/** -+ * cxl_ref - take an additional reference on the context -+ * @ctx: context established by cxl_new() -+ */ -+CXL_EXPORT struct cxl_ctx *cxl_ref(struct cxl_ctx *ctx) -+{ -+ if (ctx == NULL) -+ return NULL; -+ ctx->refcount++; -+ return ctx; -+} -+ -+/** -+ * cxl_unref - drop a context reference count -+ * @ctx: context established by cxl_new() -+ * -+ * Drop a reference and if the resulting reference count is 0 destroy -+ * the context. -+ */ -+CXL_EXPORT void cxl_unref(struct cxl_ctx *ctx) -+{ -+ struct cxl_memdev *memdev, *_d; -+ -+ if (ctx == NULL) -+ return; -+ ctx->refcount--; -+ if (ctx->refcount > 0) -+ return; -+ -+ list_for_each_safe(&ctx->memdevs, memdev, _d, list) -+ free_memdev(memdev, &ctx->memdevs); -+ -+ kmod_unref(ctx->kmod_ctx); -+ info(ctx, "context %p released\n", ctx); -+ free(ctx); -+} -+ -+/** -+ * cxl_set_log_fn - override default log routine -+ * @ctx: cxl library context -+ * @log_fn: function to be called for logging messages -+ * -+ * The built-in logging writes to stderr. It can be overridden by a -+ * custom function, to plug log messages into the user's logging -+ * functionality. -+ */ -+CXL_EXPORT void cxl_set_log_fn(struct cxl_ctx *ctx, -+ void (*cxl_log_fn)(struct cxl_ctx *ctx, int priority, -+ const char *file, int line, const char *fn, -+ const char *format, va_list args)) -+{ -+ ctx->ctx.log_fn = (log_fn) cxl_log_fn; -+ info(ctx, "custom logging function %p registered\n", cxl_log_fn); -+} -+ -+/** -+ * cxl_get_log_priority - retrieve current library loglevel (syslog) -+ * @ctx: cxl library context -+ */ -+CXL_EXPORT int cxl_get_log_priority(struct cxl_ctx *ctx) -+{ -+ return ctx->ctx.log_priority; -+} -+ -+/** -+ * cxl_set_log_priority - set log verbosity -+ * @priority: from syslog.h, LOG_ERR, LOG_INFO, LOG_DEBUG -+ * -+ * Note: LOG_DEBUG requires library be built with "configure --enable-debug" -+ */ -+CXL_EXPORT void cxl_set_log_priority(struct cxl_ctx *ctx, int priority) -+{ -+ ctx->ctx.log_priority = priority; -+} -+ -+static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) -+{ -+ const char *devname = devpath_to_devname(cxlmem_base); -+ char *path = calloc(1, strlen(cxlmem_base) + 100); -+ struct cxl_ctx *ctx = parent; -+ struct cxl_memdev *memdev, *memdev_dup; -+ char buf[SYSFS_ATTR_SIZE]; -+ struct stat st; -+ -+ if (!path) -+ return NULL; -+ dbg(ctx, "%s: base: \'%s\'\n", devname, cxlmem_base); -+ -+ memdev = calloc(1, sizeof(*memdev)); -+ if (!memdev) -+ goto err_dev; -+ memdev->id = id; -+ memdev->ctx = ctx; -+ -+ sprintf(path, "/dev/cxl/%s", devname); -+ if (stat(path, &st) < 0) -+ goto err_read; -+ memdev->major = major(st.st_rdev); -+ memdev->minor = minor(st.st_rdev); -+ -+ sprintf(path, "%s/pmem/size", cxlmem_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ goto err_read; -+ memdev->pmem_size = strtoull(buf, NULL, 0); -+ -+ sprintf(path, "%s/ram/size", cxlmem_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ goto err_read; -+ memdev->ram_size = strtoull(buf, NULL, 0); -+ -+ sprintf(path, "%s/payload_max", cxlmem_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ goto err_read; -+ memdev->payload_max = strtoull(buf, NULL, 0); -+ if (memdev->payload_max < 0) -+ goto err_read; -+ -+ memdev->dev_path = strdup(cxlmem_base); -+ if (!memdev->dev_path) -+ goto err_read; -+ -+ sprintf(path, "%s/firmware_version", cxlmem_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ goto err_read; -+ -+ memdev->firmware_version = strdup(buf); -+ if (!memdev->firmware_version) -+ goto err_read; -+ -+ memdev->dev_buf = calloc(1, strlen(cxlmem_base) + 50); -+ if (!memdev->dev_buf) -+ goto err_read; -+ memdev->buf_len = strlen(cxlmem_base) + 50; -+ -+ cxl_memdev_foreach(ctx, memdev_dup) -+ if (memdev_dup->id == memdev->id) { -+ free_memdev(memdev, NULL); -+ free(path); -+ return memdev_dup; -+ } -+ -+ list_add(&ctx->memdevs, &memdev->list); -+ free(path); -+ return memdev; -+ -+ err_read: -+ free(memdev->firmware_version); -+ free(memdev->dev_buf); -+ free(memdev->dev_path); -+ free(memdev); -+ err_dev: -+ free(path); -+ return NULL; -+} -+ -+static void cxl_memdevs_init(struct cxl_ctx *ctx) -+{ -+ if (ctx->memdevs_init) -+ return; -+ -+ ctx->memdevs_init = 1; -+ -+ sysfs_device_parse(ctx, "/sys/bus/cxl/devices", "mem", ctx, -+ add_cxl_memdev); -+} -+ -+CXL_EXPORT struct cxl_ctx *cxl_memdev_get_ctx(struct cxl_memdev *memdev) -+{ -+ return memdev->ctx; -+} -+ -+CXL_EXPORT struct cxl_memdev *cxl_memdev_get_first(struct cxl_ctx *ctx) -+{ -+ cxl_memdevs_init(ctx); -+ -+ return list_top(&ctx->memdevs, struct cxl_memdev, list); -+} -+ -+CXL_EXPORT struct cxl_memdev *cxl_memdev_get_next(struct cxl_memdev *memdev) -+{ -+ struct cxl_ctx *ctx = memdev->ctx; -+ -+ return list_next(&ctx->memdevs, memdev, list); -+} -+ -+CXL_EXPORT int cxl_memdev_get_id(struct cxl_memdev *memdev) -+{ -+ return memdev->id; -+} -+ -+CXL_EXPORT const char *cxl_memdev_get_devname(struct cxl_memdev *memdev) -+{ -+ return devpath_to_devname(memdev->dev_path); -+} -+ -+CXL_EXPORT int cxl_memdev_get_major(struct cxl_memdev *memdev) -+{ -+ return memdev->major; -+} -+ -+CXL_EXPORT int cxl_memdev_get_minor(struct cxl_memdev *memdev) -+{ -+ return memdev->minor; -+} -+ -+CXL_EXPORT unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev) -+{ -+ return memdev->pmem_size; -+} -+ -+CXL_EXPORT unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev) -+{ -+ return memdev->ram_size; -+} -+ -+CXL_EXPORT const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev) -+{ -+ return memdev->firmware_version; -+} -diff --git a/cxl/lib/libcxl.pc.in b/cxl/lib/libcxl.pc.in -new file mode 100644 -index 0000000..949fcdc ---- /dev/null -+++ b/cxl/lib/libcxl.pc.in -@@ -0,0 +1,11 @@ -+prefix=@prefix@ -+exec_prefix=@exec_prefix@ -+libdir=@libdir@ -+includedir=@includedir@ -+ -+Name: libcxl -+Description: Manage CXL devices -+Version: @VERSION@ -+Libs: -L${libdir} -lcxl -+Libs.private: -+Cflags: -I${includedir} -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -new file mode 100644 -index 0000000..2616e5c ---- /dev/null -+++ b/cxl/lib/libcxl.sym -@@ -0,0 +1,25 @@ -+LIBCXL_1 { -+global: -+ cxl_get_userdata; -+ cxl_set_userdata; -+ cxl_get_private_data; -+ cxl_set_private_data; -+ cxl_ref; -+ cxl_get_log_priority; -+ cxl_set_log_fn; -+ cxl_unref; -+ cxl_set_log_priority; -+ cxl_new; -+ cxl_memdev_get_first; -+ cxl_memdev_get_next; -+ cxl_memdev_get_id; -+ cxl_memdev_get_devname; -+ cxl_memdev_get_major; -+ cxl_memdev_get_minor; -+ cxl_memdev_get_ctx; -+ cxl_memdev_get_pmem_size; -+ cxl_memdev_get_ram_size; -+ cxl_memdev_get_firmware_verison; -+local: -+ *; -+}; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -new file mode 100644 -index 0000000..fc88fa1 ---- /dev/null -+++ b/cxl/lib/private.h -@@ -0,0 +1,29 @@ -+/* SPDX-License-Identifier: LGPL-2.1 */ -+/* Copyright (C) 2020-2021, Intel Corporation. All rights reserved. */ -+#ifndef _LIBCXL_PRIVATE_H_ -+#define _LIBCXL_PRIVATE_H_ -+ -+#include -+ -+#define CXL_EXPORT __attribute__ ((visibility("default"))) -+ -+struct cxl_memdev { -+ int id, major, minor; -+ void *dev_buf; -+ size_t buf_len; -+ char *dev_path; -+ char *firmware_version; -+ struct cxl_ctx *ctx; -+ struct list_node list; -+ unsigned long long pmem_size; -+ unsigned long long ram_size; -+ int payload_max; -+ struct kmod_module *module; -+}; -+ -+static inline int check_kmod(struct kmod_ctx *kmod_ctx) -+{ -+ return kmod_ctx ? 0 : -ENXIO; -+} -+ -+#endif /* _LIBCXL_PRIVATE_H_ */ -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -new file mode 100644 -index 0000000..fd06790 ---- /dev/null -+++ b/cxl/libcxl.h -@@ -0,0 +1,55 @@ -+/* SPDX-License-Identifier: LGPL-2.1 */ -+/* Copyright (C) 2020-2021, Intel Corporation. All rights reserved. */ -+#ifndef _LIBCXL_H_ -+#define _LIBCXL_H_ -+ -+#include -+#include -+ -+#ifdef HAVE_UUID -+#include -+#else -+typedef unsigned char uuid_t[16]; -+#endif -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+struct cxl_ctx; -+struct cxl_ctx *cxl_ref(struct cxl_ctx *ctx); -+void cxl_unref(struct cxl_ctx *ctx); -+int cxl_new(struct cxl_ctx **ctx); -+void cxl_set_log_fn(struct cxl_ctx *ctx, -+ void (*log_fn)(struct cxl_ctx *ctx, int priority, -+ const char *file, int line, const char *fn, -+ const char *format, va_list args)); -+int cxl_get_log_priority(struct cxl_ctx *ctx); -+void cxl_set_log_priority(struct cxl_ctx *ctx, int priority); -+void cxl_set_userdata(struct cxl_ctx *ctx, void *userdata); -+void *cxl_get_userdata(struct cxl_ctx *ctx); -+void cxl_set_private_data(struct cxl_ctx *ctx, void *data); -+void *cxl_get_private_data(struct cxl_ctx *ctx); -+ -+struct cxl_memdev; -+struct cxl_memdev *cxl_memdev_get_first(struct cxl_ctx *ctx); -+struct cxl_memdev *cxl_memdev_get_next(struct cxl_memdev *memdev); -+int cxl_memdev_get_id(struct cxl_memdev *memdev); -+const char *cxl_memdev_get_devname(struct cxl_memdev *memdev); -+int cxl_memdev_get_major(struct cxl_memdev *memdev); -+int cxl_memdev_get_minor(struct cxl_memdev *memdev); -+struct cxl_ctx *cxl_memdev_get_ctx(struct cxl_memdev *memdev); -+unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev); -+unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev); -+const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev); -+ -+#define cxl_memdev_foreach(ctx, memdev) \ -+ for (memdev = cxl_memdev_get_first(ctx); \ -+ memdev != NULL; \ -+ memdev = cxl_memdev_get_next(memdev)) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif -diff --git a/cxl/list.c b/cxl/list.c -new file mode 100644 -index 0000000..043d20c ---- /dev/null -+++ b/cxl/list.c -@@ -0,0 +1,121 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* Copyright (C) 2020-2021 Intel Corporation. All rights reserved. */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct { -+ bool memdevs; -+ bool idle; -+ bool human; -+} list; -+ -+static unsigned long listopts_to_flags(void) -+{ -+ unsigned long flags = 0; -+ -+ if (list.idle) -+ flags |= UTIL_JSON_IDLE; -+ if (list.human) -+ flags |= UTIL_JSON_HUMAN; -+ return flags; -+} -+ -+static struct { -+ const char *memdev; -+} param; -+ -+static int did_fail; -+ -+#define fail(fmt, ...) \ -+do { \ -+ did_fail = 1; \ -+ fprintf(stderr, "cxl-%s:%s:%d: " fmt, \ -+ VERSION, __func__, __LINE__, ##__VA_ARGS__); \ -+} while (0) -+ -+static int num_list_flags(void) -+{ -+ return list.memdevs; -+} -+ -+int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ const struct option options[] = { -+ OPT_STRING('m', "memdev", ¶m.memdev, "memory device name", -+ "filter by CXL memory device name"), -+ OPT_BOOLEAN('M', "memdevs", &list.memdevs, -+ "include CXL memory device info"), -+ OPT_BOOLEAN('i', "idle", &list.idle, "include idle devices"), -+ OPT_BOOLEAN('u', "human", &list.human, -+ "use human friendly number formats "), -+ OPT_END(), -+ }; -+ const char * const u[] = { -+ "cxl list []", -+ NULL -+ }; -+ struct json_object *jdevs = NULL; -+ unsigned long list_flags; -+ struct cxl_memdev *memdev; -+ int i; -+ -+ argc = parse_options(argc, argv, options, u, 0); -+ for (i = 0; i < argc; i++) -+ error("unknown parameter \"%s\"\n", argv[i]); -+ -+ if (argc) -+ usage_with_options(u, options); -+ -+ if (num_list_flags() == 0) { -+ /* -+ * TODO: We likely want to list regions by default if nothing -+ * was explicitly asked for. But until we have region support, -+ * print this error asking for devices explicitly. -+ * Once region support is added, this TODO can be removed. -+ */ -+ error("please specify entities to list, e.g. using -m/-M\n"); -+ usage_with_options(u, options); -+ } -+ -+ list_flags = listopts_to_flags(); -+ -+ cxl_memdev_foreach(ctx, memdev) { -+ struct json_object *jdev = NULL; -+ -+ if (!util_cxl_memdev_filter(memdev, param.memdev)) -+ continue; -+ -+ if (list.memdevs) { -+ if (!jdevs) { -+ jdevs = json_object_new_array(); -+ if (!jdevs) { -+ fail("\n"); -+ continue; -+ } -+ } -+ -+ jdev = util_cxl_memdev_to_json(memdev, list_flags); -+ if (!jdev) { -+ fail("\n"); -+ continue; -+ } -+ json_object_array_add(jdevs, jdev); -+ } -+ } -+ -+ if (jdevs) -+ util_display_json_array(stdout, jdevs, list_flags); -+ -+ if (did_fail) -+ return -ENOMEM; -+ return 0; -+} -diff --git a/util/filter.c b/util/filter.c -index 8b4aad3..d81dade 100644 ---- a/util/filter.c -+++ b/util/filter.c -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - - struct ndctl_bus *util_bus_filter(struct ndctl_bus *bus, const char *__ident) - { -@@ -339,6 +340,25 @@ struct daxctl_region *util_daxctl_region_filter(struct daxctl_region *region, - return NULL; - } - -+struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, -+ const char *ident) -+{ -+ int memdev_id; -+ -+ if (!ident || strcmp(ident, "all") == 0) -+ return memdev; -+ -+ if (strcmp(ident, cxl_memdev_get_devname(memdev)) == 0) -+ return memdev; -+ -+ if ((sscanf(ident, "%d", &memdev_id) == 1 -+ || sscanf(ident, "mem%d", &memdev_id) == 1) -+ && cxl_memdev_get_id(memdev) == memdev_id) -+ return memdev; -+ -+ return NULL; -+} -+ - enum ndctl_namespace_mode util_nsmode(const char *mode) - { - if (!mode) -diff --git a/util/filter.h b/util/filter.h -index 1e1a41c..9a80d65 100644 ---- a/util/filter.h -+++ b/util/filter.h -@@ -29,6 +29,8 @@ struct daxctl_dev *util_daxctl_dev_filter(struct daxctl_dev *dev, - const char *ident); - struct daxctl_region *util_daxctl_region_filter(struct daxctl_region *region, - const char *ident); -+struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, -+ const char *ident); - - enum ndctl_namespace_mode util_nsmode(const char *mode); - const char *util_nsmode_name(enum ndctl_namespace_mode mode); -diff --git a/util/json.c b/util/json.c -index a8d2412..3be3a92 100644 ---- a/util/json.c -+++ b/util/json.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1440,3 +1441,28 @@ struct json_object *util_badblock_rec_to_json(u64 block, u64 count, - json_object_put(jerr); - return NULL; - } -+ -+struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, -+ unsigned long flags) -+{ -+ const char *devname = cxl_memdev_get_devname(memdev); -+ struct json_object *jdev, *jobj; -+ -+ jdev = json_object_new_object(); -+ if (!devname || !jdev) -+ return NULL; -+ -+ jobj = json_object_new_string(devname); -+ if (jobj) -+ json_object_object_add(jdev, "memdev", jobj); -+ -+ jobj = util_json_object_size(cxl_memdev_get_pmem_size(memdev), flags); -+ if (jobj) -+ json_object_object_add(jdev, "pmem_size", jobj); -+ -+ jobj = util_json_object_size(cxl_memdev_get_ram_size(memdev), flags); -+ if (jobj) -+ json_object_object_add(jdev, "ram_size", jobj); -+ -+ return jdev; -+} -diff --git a/util/json.h b/util/json.h -index 0f09e36..91918c8 100644 ---- a/util/json.h -+++ b/util/json.h -@@ -55,4 +55,7 @@ struct json_object *util_dimm_health_to_json(struct ndctl_dimm *dimm); - struct json_object *util_dimm_firmware_to_json(struct ndctl_dimm *dimm, - unsigned long flags); - struct json_object *util_region_capabilities_to_json(struct ndctl_region *region); -+struct cxl_memdev; -+struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, -+ unsigned long flags); - #endif /* __NDCTL_JSON_H__ */ -diff --git a/util/main.h b/util/main.h -index c89a843..80b55c4 100644 ---- a/util/main.h -+++ b/util/main.h -@@ -10,16 +10,19 @@ - enum program { - PROG_NDCTL, - PROG_DAXCTL, -+ PROG_CXL, - }; - - struct ndctl_ctx; - struct daxctl_ctx; -+struct cxl_ctx; - - struct cmd_struct { - const char *cmd; - union { - int (*n_fn)(int, const char **, struct ndctl_ctx *ctx); - int (*d_fn)(int, const char **, struct daxctl_ctx *ctx); -+ int (*c_fn)(int, const char **, struct cxl_ctx *ctx); - }; - }; - --- -2.27.0 - diff --git a/SOURCES/0033-cxl-add-a-local-copy-of-the-cxl_mem-UAPI-header.patch b/SOURCES/0033-cxl-add-a-local-copy-of-the-cxl_mem-UAPI-header.patch deleted file mode 100644 index 54d2230..0000000 --- a/SOURCES/0033-cxl-add-a-local-copy-of-the-cxl_mem-UAPI-header.patch +++ /dev/null @@ -1,256 +0,0 @@ -From 894fb9b2b59364f7f5683ea68c8bd765223a4ca8 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:25 -0600 -Subject: [PATCH 033/217] cxl: add a local copy of the cxl_mem UAPI header - -While CXL functionality is under development, it is useful to have a -local copy of the UAPI header for cxl_mem definitions. This allows -building cxl and libcxl on systems where the appropriate kernel headers -are not installed in the usual locations. - -Cc: Ben Widawsky -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Makefile.am | 3 +- - Makefile.am.in | 1 + - cxl/cxl_mem.h | 189 ++++++++++++++++++++++++++++++++++++++++++++ - cxl/lib/Makefile.am | 2 +- - 4 files changed, 193 insertions(+), 2 deletions(-) - create mode 100644 cxl/cxl_mem.h - -diff --git a/Makefile.am b/Makefile.am -index 428fd40..4904ee7 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -89,4 +89,5 @@ libutil_a_SOURCES = \ - - nobase_include_HEADERS = \ - daxctl/libdaxctl.h \ -- cxl/libcxl.h -+ cxl/libcxl.h \ -+ cxl/cxl_mem.h -diff --git a/Makefile.am.in b/Makefile.am.in -index aaeee53..a748128 100644 ---- a/Makefile.am.in -+++ b/Makefile.am.in -@@ -11,6 +11,7 @@ AM_CPPFLAGS = \ - -DNDCTL_MAN_PATH=\""$(mandir)"\" \ - -I${top_srcdir}/ndctl/lib \ - -I${top_srcdir}/ndctl \ -+ -I${top_srcdir}/cxl \ - -I${top_srcdir}/ \ - $(KMOD_CFLAGS) \ - $(UDEV_CFLAGS) \ -diff --git a/cxl/cxl_mem.h b/cxl/cxl_mem.h -new file mode 100644 -index 0000000..d38cc9c ---- /dev/null -+++ b/cxl/cxl_mem.h -@@ -0,0 +1,189 @@ -+/* SPDX-License-Identifier: LGPL-2.1 */ -+/* Copyright (C) 2020-2021, Intel Corporation. All rights reserved. */ -+/* -+ * CXL IOCTLs for Memory Devices -+ */ -+ -+#ifndef _UAPI_CXL_MEM_H_ -+#define _UAPI_CXL_MEM_H_ -+ -+#include -+#include -+#include -+ -+#define __user -+ -+/** -+ * DOC: UAPI -+ * -+ * Not all of all commands that the driver supports are always available for use -+ * by userspace. Userspace must check the results from the QUERY command in -+ * order to determine the live set of commands. -+ */ -+ -+#define CXL_MEM_QUERY_COMMANDS _IOR(0xCE, 1, struct cxl_mem_query_commands) -+#define CXL_MEM_SEND_COMMAND _IOWR(0xCE, 2, struct cxl_send_command) -+ -+#define CXL_CMDS \ -+ ___C(INVALID, "Invalid Command"), \ -+ ___C(IDENTIFY, "Identify Command"), \ -+ ___C(RAW, "Raw device command"), \ -+ ___C(GET_SUPPORTED_LOGS, "Get Supported Logs"), \ -+ ___C(GET_FW_INFO, "Get FW Info"), \ -+ ___C(GET_PARTITION_INFO, "Get Partition Information"), \ -+ ___C(GET_LSA, "Get Label Storage Area"), \ -+ ___C(GET_HEALTH_INFO, "Get Health Info"), \ -+ ___C(GET_LOG, "Get Log"), \ -+ ___C(SET_PARTITION_INFO, "Set Partition Information"), \ -+ ___C(SET_LSA, "Set Label Storage Area"), \ -+ ___C(GET_ALERT_CONFIG, "Get Alert Configuration"), \ -+ ___C(SET_ALERT_CONFIG, "Set Alert Configuration"), \ -+ ___C(GET_SHUTDOWN_STATE, "Get Shutdown State"), \ -+ ___C(SET_SHUTDOWN_STATE, "Set Shutdown State"), \ -+ ___C(GET_POISON, "Get Poison List"), \ -+ ___C(INJECT_POISON, "Inject Poison"), \ -+ ___C(CLEAR_POISON, "Clear Poison"), \ -+ ___C(GET_SCAN_MEDIA_CAPS, "Get Scan Media Capabilities"), \ -+ ___C(SCAN_MEDIA, "Scan Media"), \ -+ ___C(GET_SCAN_MEDIA, "Get Scan Media Results"), \ -+ ___C(MAX, "invalid / last command") -+ -+#define ___C(a, b) CXL_MEM_COMMAND_ID_##a -+enum { CXL_CMDS }; -+ -+#undef ___C -+#define ___C(a, b) { b } -+static const struct { -+ const char *name; -+} cxl_command_names[] = { CXL_CMDS }; -+ -+/* -+ * Here's how this actually breaks out: -+ * cxl_command_names[] = { -+ * [CXL_MEM_COMMAND_ID_INVALID] = { "Invalid Command" }, -+ * [CXL_MEM_COMMAND_ID_IDENTIFY] = { "Identify Command" }, -+ * ... -+ * [CXL_MEM_COMMAND_ID_MAX] = { "invalid / last command" }, -+ * }; -+ */ -+ -+#undef ___C -+ -+/** -+ * struct cxl_command_info - Command information returned from a query. -+ * @id: ID number for the command. -+ * @flags: Flags that specify command behavior. -+ * @size_in: Expected input size, or -1 if variable length. -+ * @size_out: Expected output size, or -1 if variable length. -+ * -+ * Represents a single command that is supported by both the driver and the -+ * hardware. This is returned as part of an array from the query ioctl. The -+ * following would be a command that takes a variable length input and returns 0 -+ * bytes of output. -+ * -+ * - @id = 10 -+ * - @flags = 0 -+ * - @size_in = -1 -+ * - @size_out = 0 -+ * -+ * See struct cxl_mem_query_commands. -+ */ -+struct cxl_command_info { -+ __u32 id; -+ -+ __u32 flags; -+#define CXL_MEM_COMMAND_FLAG_MASK GENMASK(0, 0) -+ -+ __s32 size_in; -+ __s32 size_out; -+}; -+ -+/** -+ * struct cxl_mem_query_commands - Query supported commands. -+ * @n_commands: In/out parameter. When @n_commands is > 0, the driver will -+ * return min(num_support_commands, n_commands). When @n_commands -+ * is 0, driver will return the number of total supported commands. -+ * @rsvd: Reserved for future use. -+ * @commands: Output array of supported commands. This array must be allocated -+ * by userspace to be at least min(num_support_commands, @n_commands) -+ * -+ * Allow userspace to query the available commands supported by both the driver, -+ * and the hardware. Commands that aren't supported by either the driver, or the -+ * hardware are not returned in the query. -+ * -+ * Examples: -+ * -+ * - { .n_commands = 0 } // Get number of supported commands -+ * - { .n_commands = 15, .commands = buf } // Return first 15 (or less) -+ * supported commands -+ * -+ * See struct cxl_command_info. -+ */ -+struct cxl_mem_query_commands { -+ /* -+ * Input: Number of commands to return (space allocated by user) -+ * Output: Number of commands supported by the driver/hardware -+ * -+ * If n_commands is 0, kernel will only return number of commands and -+ * not try to populate commands[], thus allowing userspace to know how -+ * much space to allocate -+ */ -+ __u32 n_commands; -+ __u32 rsvd; -+ -+ struct cxl_command_info __user commands[]; /* out: supported commands */ -+}; -+ -+/** -+ * struct cxl_send_command - Send a command to a memory device. -+ * @id: The command to send to the memory device. This must be one of the -+ * commands returned by the query command. -+ * @flags: Flags for the command (input). -+ * @raw: Special fields for raw commands -+ * @raw.opcode: Opcode passed to hardware when using the RAW command. -+ * @raw.rsvd: Must be zero. -+ * @rsvd: Must be zero. -+ * @retval: Return value from the memory device (output). -+ * @in: Parameters associated with input payload. -+ * @in.size: Size of the payload to provide to the device (input). -+ * @in.rsvd: Must be zero. -+ * @in.payload: Pointer to memory for payload input, payload is little endian. -+ * @out: Parameters associated with output payload. -+ * @out.size: Size of the payload received from the device (input/output). This -+ * field is filled in by userspace to let the driver know how much -+ * space was allocated for output. It is populated by the driver to -+ * let userspace know how large the output payload actually was. -+ * @out.rsvd: Must be zero. -+ * @out.payload: Pointer to memory for payload output, payload is little endian. -+ * -+ * Mechanism for userspace to send a command to the hardware for processing. The -+ * driver will do basic validation on the command sizes. In some cases even the -+ * payload may be introspected. Userspace is required to allocate large enough -+ * buffers for size_out which can be variable length in certain situations. -+ */ -+struct cxl_send_command { -+ __u32 id; -+ __u32 flags; -+ union { -+ struct { -+ __u16 opcode; -+ __u16 rsvd; -+ } raw; -+ __u32 rsvd; -+ }; -+ __u32 retval; -+ -+ struct { -+ __s32 size; -+ __u32 rsvd; -+ __u64 payload; -+ } in; -+ -+ struct { -+ __s32 size; -+ __u32 rsvd; -+ __u64 payload; -+ } out; -+}; -+ -+#endif -diff --git a/cxl/lib/Makefile.am b/cxl/lib/Makefile.am -index 277f0cd..72c9ccd 100644 ---- a/cxl/lib/Makefile.am -+++ b/cxl/lib/Makefile.am -@@ -3,7 +3,7 @@ include $(top_srcdir)/Makefile.am.in - %.pc: %.pc.in Makefile - $(SED_PROCESS) - --pkginclude_HEADERS = ../libcxl.h -+pkginclude_HEADERS = ../libcxl.h ../cxl_mem.h - lib_LTLIBRARIES = libcxl.la - - libcxl_la_SOURCES =\ --- -2.27.0 - diff --git a/SOURCES/0034-util-add-the-struct_size-helper-from-the-kernel.patch b/SOURCES/0034-util-add-the-struct_size-helper-from-the-kernel.patch deleted file mode 100644 index e2291d5..0000000 --- a/SOURCES/0034-util-add-the-struct_size-helper-from-the-kernel.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 7aa7c7be6e803de267a165237e23577ab496e792 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:26 -0600 -Subject: [PATCH 034/217] util: add the struct_size() helper from the kernel - -Add struct_size() from include/linux/overflow.h which calculates the -size of a struct with a trailing variable length array. - -Suggested-by: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - util/size.h | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ - util/util.h | 6 ++++++ - 2 files changed, 68 insertions(+) - -diff --git a/util/size.h b/util/size.h -index 646edae..a0f3593 100644 ---- a/util/size.h -+++ b/util/size.h -@@ -4,6 +4,8 @@ - #ifndef _NDCTL_SIZE_H_ - #define _NDCTL_SIZE_H_ - #include -+#include -+#include - - #define SZ_1K 0x00000400 - #define SZ_4K 0x00001000 -@@ -30,4 +32,64 @@ static inline bool is_power_of_2(unsigned long long v) - #define BITS_PER_LONG (sizeof(unsigned long) * 8) - #define HPAGE_SIZE (2 << 20) - -+/* -+ * Helpers for struct_size() copied from include/linux/overflow.h (GPL-2.0) -+ * -+ * For simplicity and code hygiene, the fallback code below insists on -+ * a, b and *d having the same type (similar to the min() and max() -+ * macros), whereas gcc's type-generic overflow checkers accept -+ * different types. Hence we don't just make check_add_overflow an -+ * alias for __builtin_add_overflow, but add type checks similar to -+ * below. -+ */ -+#define check_add_overflow(a, b, d) (({ \ -+ typeof(a) __a = (a); \ -+ typeof(b) __b = (b); \ -+ typeof(d) __d = (d); \ -+ (void) (&__a == &__b); \ -+ (void) (&__a == __d); \ -+ __builtin_add_overflow(__a, __b, __d); \ -+})) -+ -+#define check_mul_overflow(a, b, d) (({ \ -+ typeof(a) __a = (a); \ -+ typeof(b) __b = (b); \ -+ typeof(d) __d = (d); \ -+ (void) (&__a == &__b); \ -+ (void) (&__a == __d); \ -+ __builtin_mul_overflow(__a, __b, __d); \ -+})) -+ -+/* -+ * Compute a*b+c, returning SIZE_MAX on overflow. Internal helper for -+ * struct_size() below. -+ */ -+static inline size_t __ab_c_size(size_t a, size_t b, size_t c) -+{ -+ size_t bytes; -+ -+ if (check_mul_overflow(a, b, &bytes)) -+ return SIZE_MAX; -+ if (check_add_overflow(bytes, c, &bytes)) -+ return SIZE_MAX; -+ -+ return bytes; -+} -+ -+/** -+ * struct_size() - Calculate size of structure with trailing array. -+ * @p: Pointer to the structure. -+ * @member: Name of the array member. -+ * @count: Number of elements in the array. -+ * -+ * Calculates size of memory needed for structure @p followed by an -+ * array of @count number of @member elements. -+ * -+ * Return: number of bytes needed or SIZE_MAX on overflow. -+ */ -+#define struct_size(p, member, count) \ -+ __ab_c_size(count, \ -+ sizeof(*(p)->member) + __must_be_array((p)->member),\ -+ sizeof(*(p))) -+ - #endif /* _NDCTL_SIZE_H_ */ -diff --git a/util/util.h b/util/util.h -index ae0e4e1..b2b4ae6 100644 ---- a/util/util.h -+++ b/util/util.h -@@ -63,6 +63,12 @@ - #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) - #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) - -+/* Are two types/vars the same type (ignoring qualifiers)? */ -+#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) -+ -+/* &a[0] degrades to a pointer: a different type from an array */ -+#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) -+ - enum { - READ, WRITE, - }; --- -2.27.0 - diff --git a/SOURCES/0035-libcxl-add-support-for-command-query-and-submission.patch b/SOURCES/0035-libcxl-add-support-for-command-query-and-submission.patch deleted file mode 100644 index f2af1f0..0000000 --- a/SOURCES/0035-libcxl-add-support-for-command-query-and-submission.patch +++ /dev/null @@ -1,535 +0,0 @@ -From 96afebd1b32ff839129f3bc0ba323ab5f04674ea Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:27 -0600 -Subject: [PATCH 035/217] libcxl: add support for command query and submission - -Add a set of APIs around 'cxl_cmd' for querying the kernel for supported -commands, allocating and validating command structures against the -supported set, and submitting the commands. - -'Query Commands' and 'Send Command' are implemented as IOCTLs in the -kernel. 'Query Commands' returns information about each supported -command, such as flags governing its use, or input and output payload -sizes. This information is used to validate command support, as well as -set up input and output buffers for command submission. - -Cc: Ben Widawsky -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 390 +++++++++++++++++++++++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 9 ++ - cxl/lib/private.h | 33 ++++ - cxl/libcxl.h | 11 ++ - 4 files changed, 443 insertions(+) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index c15e987..727d599 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -9,14 +9,17 @@ - #include - #include - #include -+#include - #include - #include - #include - #include - - #include -+#include - #include - #include -+#include - #include - #include "private.h" - -@@ -343,3 +346,390 @@ CXL_EXPORT const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev - { - return memdev->firmware_version; - } -+ -+CXL_EXPORT void cxl_cmd_unref(struct cxl_cmd *cmd) -+{ -+ if (!cmd) -+ return; -+ if (--cmd->refcount == 0) { -+ free(cmd->query_cmd); -+ free(cmd->send_cmd); -+ free(cmd->input_payload); -+ free(cmd->output_payload); -+ free(cmd); -+ } -+} -+ -+CXL_EXPORT void cxl_cmd_ref(struct cxl_cmd *cmd) -+{ -+ cmd->refcount++; -+} -+ -+static int cxl_cmd_alloc_query(struct cxl_cmd *cmd, int num_cmds) -+{ -+ size_t size; -+ -+ if (!cmd) -+ return -EINVAL; -+ -+ if (cmd->query_cmd != NULL) -+ free(cmd->query_cmd); -+ -+ size = struct_size(cmd->query_cmd, commands, num_cmds); -+ if (size == SIZE_MAX) -+ return -EOVERFLOW; -+ -+ cmd->query_cmd = calloc(1, size); -+ if (!cmd->query_cmd) -+ return -ENOMEM; -+ -+ cmd->query_cmd->n_commands = num_cmds; -+ -+ return 0; -+} -+ -+static struct cxl_cmd *cxl_cmd_new(struct cxl_memdev *memdev) -+{ -+ struct cxl_cmd *cmd; -+ size_t size; -+ -+ size = sizeof(*cmd); -+ cmd = calloc(1, size); -+ if (!cmd) -+ return NULL; -+ -+ cxl_cmd_ref(cmd); -+ cmd->memdev = memdev; -+ -+ return cmd; -+} -+ -+static int __do_cmd(struct cxl_cmd *cmd, int ioctl_cmd, int fd) -+{ -+ void *cmd_buf; -+ int rc; -+ -+ switch (ioctl_cmd) { -+ case CXL_MEM_QUERY_COMMANDS: -+ cmd_buf = cmd->query_cmd; -+ break; -+ case CXL_MEM_SEND_COMMAND: -+ cmd_buf = cmd->send_cmd; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ rc = ioctl(fd, ioctl_cmd, cmd_buf); -+ if (rc < 0) -+ rc = -errno; -+ -+ return rc; -+} -+ -+static int do_cmd(struct cxl_cmd *cmd, int ioctl_cmd) -+{ -+ char *path; -+ struct stat st; -+ unsigned int major, minor; -+ int rc = 0, fd; -+ struct cxl_memdev *memdev = cmd->memdev; -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ const char *devname = cxl_memdev_get_devname(memdev); -+ -+ major = cxl_memdev_get_major(memdev); -+ minor = cxl_memdev_get_minor(memdev); -+ -+ if (asprintf(&path, "/dev/cxl/%s", devname) < 0) -+ return -ENOMEM; -+ -+ fd = open(path, O_RDWR); -+ if (fd < 0) { -+ err(ctx, "failed to open %s: %s\n", path, strerror(errno)); -+ rc = -errno; -+ goto out; -+ } -+ -+ if (fstat(fd, &st) >= 0 && S_ISCHR(st.st_mode) -+ && major(st.st_rdev) == major -+ && minor(st.st_rdev) == minor) { -+ rc = __do_cmd(cmd, ioctl_cmd, fd); -+ } else { -+ err(ctx, "failed to validate %s as a CXL memdev node\n", path); -+ rc = -ENXIO; -+ } -+ close(fd); -+out: -+ free(path); -+ return rc; -+} -+ -+static int alloc_do_query(struct cxl_cmd *cmd, int num_cmds) -+{ -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(cmd->memdev); -+ int rc; -+ -+ rc = cxl_cmd_alloc_query(cmd, num_cmds); -+ if (rc) -+ return rc; -+ -+ rc = do_cmd(cmd, CXL_MEM_QUERY_COMMANDS); -+ if (rc < 0) -+ err(ctx, "%s: query commands failed: %s\n", -+ cxl_memdev_get_devname(cmd->memdev), -+ strerror(-rc)); -+ return rc; -+} -+ -+static int cxl_cmd_do_query(struct cxl_cmd *cmd) -+{ -+ struct cxl_memdev *memdev = cmd->memdev; -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ const char *devname = cxl_memdev_get_devname(memdev); -+ int rc, n_commands; -+ -+ switch (cmd->query_status) { -+ case CXL_CMD_QUERY_OK: -+ return 0; -+ case CXL_CMD_QUERY_UNSUPPORTED: -+ return -EOPNOTSUPP; -+ case CXL_CMD_QUERY_NOT_RUN: -+ break; -+ default: -+ err(ctx, "%s: Unknown query_status %d\n", -+ devname, cmd->query_status); -+ return -EINVAL; -+ } -+ -+ rc = alloc_do_query(cmd, 0); -+ if (rc) -+ return rc; -+ -+ n_commands = cmd->query_cmd->n_commands; -+ dbg(ctx, "%s: supports %d commands\n", devname, n_commands); -+ -+ return alloc_do_query(cmd, n_commands); -+} -+ -+static int cxl_cmd_validate(struct cxl_cmd *cmd, u32 cmd_id) -+{ -+ struct cxl_memdev *memdev = cmd->memdev; -+ struct cxl_mem_query_commands *query = cmd->query_cmd; -+ const char *devname = cxl_memdev_get_devname(memdev); -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ u32 i; -+ -+ for (i = 0; i < query->n_commands; i++) { -+ struct cxl_command_info *cinfo = &query->commands[i]; -+ const char *cmd_name = cxl_command_names[cinfo->id].name; -+ -+ if (cinfo->id != cmd_id) -+ continue; -+ -+ dbg(ctx, "%s: %s: in: %d, out %d, flags: %#08x\n", -+ devname, cmd_name, cinfo->size_in, -+ cinfo->size_out, cinfo->flags); -+ -+ cmd->query_idx = i; -+ cmd->query_status = CXL_CMD_QUERY_OK; -+ return 0; -+ } -+ cmd->query_status = CXL_CMD_QUERY_UNSUPPORTED; -+ return -EOPNOTSUPP; -+} -+ -+CXL_EXPORT int cxl_cmd_set_input_payload(struct cxl_cmd *cmd, void *buf, -+ int size) -+{ -+ struct cxl_memdev *memdev = cmd->memdev; -+ -+ if (size > memdev->payload_max || size < 0) -+ return -EINVAL; -+ -+ if (!buf) { -+ -+ /* If the user didn't supply a buffer, allocate it */ -+ cmd->input_payload = calloc(1, size); -+ if (!cmd->input_payload) -+ return -ENOMEM; -+ cmd->send_cmd->in.payload = (u64)cmd->input_payload; -+ } else { -+ /* -+ * Use user-buffer as is. If an automatic allocation was -+ * previously made (based on a fixed size from query), -+ * it will get freed during unref. -+ */ -+ cmd->send_cmd->in.payload = (u64)buf; -+ } -+ cmd->send_cmd->in.size = size; -+ -+ return 0; -+} -+ -+CXL_EXPORT int cxl_cmd_set_output_payload(struct cxl_cmd *cmd, void *buf, -+ int size) -+{ -+ struct cxl_memdev *memdev = cmd->memdev; -+ -+ if (size > memdev->payload_max || size < 0) -+ return -EINVAL; -+ -+ if (!buf) { -+ -+ /* If the user didn't supply a buffer, allocate it */ -+ cmd->output_payload = calloc(1, size); -+ if (!cmd->output_payload) -+ return -ENOMEM; -+ cmd->send_cmd->out.payload = (u64)cmd->output_payload; -+ } else { -+ /* -+ * Use user-buffer as is. If an automatic allocation was -+ * previously made (based on a fixed size from query), -+ * it will get freed during unref. -+ */ -+ cmd->send_cmd->out.payload = (u64)buf; -+ } -+ cmd->send_cmd->out.size = size; -+ -+ return 0; -+} -+ -+static int cxl_cmd_alloc_send(struct cxl_cmd *cmd, u32 cmd_id) -+{ -+ struct cxl_mem_query_commands *query = cmd->query_cmd; -+ struct cxl_command_info *cinfo = &query->commands[cmd->query_idx]; -+ size_t size; -+ -+ if (!query) -+ return -EINVAL; -+ -+ size = sizeof(struct cxl_send_command); -+ cmd->send_cmd = calloc(1, size); -+ if (!cmd->send_cmd) -+ return -ENOMEM; -+ -+ if (cinfo->id != cmd_id) -+ return -EINVAL; -+ -+ cmd->send_cmd->id = cmd_id; -+ -+ if (cinfo->size_in > 0) { -+ cmd->input_payload = calloc(1, cinfo->size_in); -+ if (!cmd->input_payload) -+ return -ENOMEM; -+ cmd->send_cmd->in.payload = (u64)cmd->input_payload; -+ cmd->send_cmd->in.size = cinfo->size_in; -+ } -+ if (cinfo->size_out > 0) { -+ cmd->output_payload = calloc(1, cinfo->size_out); -+ if (!cmd->output_payload) -+ return -ENOMEM; -+ cmd->send_cmd->out.payload = (u64)cmd->output_payload; -+ cmd->send_cmd->out.size = cinfo->size_out; -+ } -+ -+ return 0; -+} -+ -+static struct cxl_cmd *cxl_cmd_new_generic(struct cxl_memdev *memdev, -+ u32 cmd_id) -+{ -+ const char *devname = cxl_memdev_get_devname(memdev); -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ struct cxl_cmd *cmd; -+ int rc; -+ -+ cmd = cxl_cmd_new(memdev); -+ if (!cmd) -+ return NULL; -+ -+ rc = cxl_cmd_do_query(cmd); -+ if (rc) { -+ err(ctx, "%s: query returned: %s\n", devname, strerror(-rc)); -+ goto fail; -+ } -+ -+ rc = cxl_cmd_validate(cmd, cmd_id); -+ if (rc) { -+ errno = -rc; -+ goto fail; -+ } -+ -+ rc = cxl_cmd_alloc_send(cmd, cmd_id); -+ if (rc) { -+ errno = -rc; -+ goto fail; -+ } -+ -+ cmd->status = 1; -+ return cmd; -+ -+fail: -+ cxl_cmd_unref(cmd); -+ return NULL; -+} -+ -+CXL_EXPORT const char *cxl_cmd_get_devname(struct cxl_cmd *cmd) -+{ -+ return cxl_memdev_get_devname(cmd->memdev); -+} -+ -+CXL_EXPORT struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, -+ int opcode) -+{ -+ struct cxl_cmd *cmd; -+ -+ /* opcode '0' is reserved */ -+ if (opcode <= 0) { -+ errno = EINVAL; -+ return NULL; -+ } -+ -+ cmd = cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_RAW); -+ if (!cmd) -+ return NULL; -+ -+ cmd->send_cmd->raw.opcode = opcode; -+ return cmd; -+} -+ -+CXL_EXPORT int cxl_cmd_submit(struct cxl_cmd *cmd) -+{ -+ struct cxl_memdev *memdev = cmd->memdev; -+ const char *devname = cxl_memdev_get_devname(memdev); -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ int rc; -+ -+ switch (cmd->query_status) { -+ case CXL_CMD_QUERY_OK: -+ break; -+ case CXL_CMD_QUERY_UNSUPPORTED: -+ return -EOPNOTSUPP; -+ case CXL_CMD_QUERY_NOT_RUN: -+ return -EINVAL; -+ default: -+ err(ctx, "%s: Unknown query_status %d\n", -+ devname, cmd->query_status); -+ return -EINVAL; -+ } -+ -+ dbg(ctx, "%s: submitting SEND cmd: in: %d, out: %d\n", devname, -+ cmd->send_cmd->in.size, cmd->send_cmd->out.size); -+ rc = do_cmd(cmd, CXL_MEM_SEND_COMMAND); -+ cmd->status = cmd->send_cmd->retval; -+ dbg(ctx, "%s: got SEND cmd: in: %d, out: %d, retval: %d, status: %d\n", -+ devname, cmd->send_cmd->in.size, cmd->send_cmd->out.size, -+ rc, cmd->status); -+ -+ return rc; -+} -+ -+CXL_EXPORT int cxl_cmd_get_mbox_status(struct cxl_cmd *cmd) -+{ -+ return cmd->status; -+} -+ -+CXL_EXPORT int cxl_cmd_get_out_size(struct cxl_cmd *cmd) -+{ -+ return cmd->send_cmd->out.size; -+} -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 2616e5c..3900f90 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -20,6 +20,15 @@ global: - cxl_memdev_get_pmem_size; - cxl_memdev_get_ram_size; - cxl_memdev_get_firmware_verison; -+ cxl_cmd_get_devname; -+ cxl_cmd_new_raw; -+ cxl_cmd_set_input_payload; -+ cxl_cmd_set_output_payload; -+ cxl_cmd_ref; -+ cxl_cmd_unref; -+ cxl_cmd_submit; -+ cxl_cmd_get_mbox_status; -+ cxl_cmd_get_out_size; - local: - *; - }; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index fc88fa1..87ca17e 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -4,6 +4,9 @@ - #define _LIBCXL_PRIVATE_H_ - - #include -+#include -+#include -+#include - - #define CXL_EXPORT __attribute__ ((visibility("default"))) - -@@ -21,6 +24,36 @@ struct cxl_memdev { - struct kmod_module *module; - }; - -+enum cxl_cmd_query_status { -+ CXL_CMD_QUERY_NOT_RUN = 0, -+ CXL_CMD_QUERY_OK, -+ CXL_CMD_QUERY_UNSUPPORTED, -+}; -+ -+/** -+ * struct cxl_cmd - CXL memdev command -+ * @memdev: the memory device to which the command is being sent -+ * @query_cmd: structure for the Linux 'Query commands' ioctl -+ * @send_cmd: structure for the Linux 'Send command' ioctl -+ * @input_payload: buffer for input payload managed by libcxl -+ * @output_payload: buffer for output payload managed by libcxl -+ * @refcount: reference for passing command buffer around -+ * @query_status: status from query_commands -+ * @query_idx: index of 'this' command in the query_commands array -+ * @status: command return status from the device -+ */ -+struct cxl_cmd { -+ struct cxl_memdev *memdev; -+ struct cxl_mem_query_commands *query_cmd; -+ struct cxl_send_command *send_cmd; -+ void *input_payload; -+ void *output_payload; -+ int refcount; -+ int query_status; -+ int query_idx; -+ int status; -+}; -+ - static inline int check_kmod(struct kmod_ctx *kmod_ctx) - { - return kmod_ctx ? 0 : -ENXIO; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index fd06790..6e87b80 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -48,6 +48,17 @@ const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev); - memdev != NULL; \ - memdev = cxl_memdev_get_next(memdev)) - -+struct cxl_cmd; -+const char *cxl_cmd_get_devname(struct cxl_cmd *cmd); -+struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode); -+int cxl_cmd_set_input_payload(struct cxl_cmd *cmd, void *in, int size); -+int cxl_cmd_set_output_payload(struct cxl_cmd *cmd, void *out, int size); -+void cxl_cmd_ref(struct cxl_cmd *cmd); -+void cxl_cmd_unref(struct cxl_cmd *cmd); -+int cxl_cmd_submit(struct cxl_cmd *cmd); -+int cxl_cmd_get_mbox_status(struct cxl_cmd *cmd); -+int cxl_cmd_get_out_size(struct cxl_cmd *cmd); -+ - #ifdef __cplusplus - } /* extern "C" */ - #endif --- -2.27.0 - diff --git a/SOURCES/0036-libcxl-add-support-for-the-Identify-Device-command.patch b/SOURCES/0036-libcxl-add-support-for-the-Identify-Device-command.patch deleted file mode 100644 index e134c74..0000000 --- a/SOURCES/0036-libcxl-add-support-for-the-Identify-Device-command.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 244862cbbfecda9b6b638eccaca526f4daba2795 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:28 -0600 -Subject: [PATCH 036/217] libcxl: add support for the 'Identify Device' command - -Add APIs to allocate and send an 'Identify Device' command, and -accessors to retrieve some of the fields from the resulting data. - -Only add a handful accessor functions; more can be added as the need -arises. The fields added are fw_revision, partition_align, and -lsa_size. - -Cc: Ben Widawsky -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 4 ++++ - cxl/lib/private.h | 19 +++++++++++++++++ - cxl/libcxl.h | 4 ++++ - 4 files changed, 79 insertions(+) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 727d599..ed21670 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -13,7 +13,10 @@ - #include - #include - #include -+#include -+#include - #include -+#include - - #include - #include -@@ -674,6 +677,55 @@ CXL_EXPORT const char *cxl_cmd_get_devname(struct cxl_cmd *cmd) - return cxl_memdev_get_devname(cmd->memdev); - } - -+CXL_EXPORT struct cxl_cmd *cxl_cmd_new_identify(struct cxl_memdev *memdev) -+{ -+ return cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_IDENTIFY); -+} -+ -+CXL_EXPORT int cxl_cmd_identify_get_fw_rev(struct cxl_cmd *cmd, char *fw_rev, -+ int fw_len) -+{ -+ struct cxl_cmd_identify *id = -+ (struct cxl_cmd_identify *)cmd->send_cmd->out.payload; -+ -+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_IDENTIFY) -+ return -EINVAL; -+ if (cmd->status < 0) -+ return cmd->status; -+ -+ if (fw_len > 0) -+ memcpy(fw_rev, id->fw_revision, -+ min(fw_len, CXL_CMD_IDENTIFY_FW_REV_LENGTH)); -+ return 0; -+} -+ -+CXL_EXPORT unsigned long long cxl_cmd_identify_get_partition_align( -+ struct cxl_cmd *cmd) -+{ -+ struct cxl_cmd_identify *id = -+ (struct cxl_cmd_identify *)cmd->send_cmd->out.payload; -+ -+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_IDENTIFY) -+ return -EINVAL; -+ if (cmd->status < 0) -+ return cmd->status; -+ -+ return le64_to_cpu(id->partition_align); -+} -+ -+CXL_EXPORT unsigned int cxl_cmd_identify_get_label_size(struct cxl_cmd *cmd) -+{ -+ struct cxl_cmd_identify *id = -+ (struct cxl_cmd_identify *)cmd->send_cmd->out.payload; -+ -+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_IDENTIFY) -+ return -EINVAL; -+ if (cmd->status < 0) -+ return cmd->status; -+ -+ return le32_to_cpu(id->lsa_size); -+} -+ - CXL_EXPORT struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, - int opcode) - { -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 3900f90..1dc45f4 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -29,6 +29,10 @@ global: - cxl_cmd_submit; - cxl_cmd_get_mbox_status; - cxl_cmd_get_out_size; -+ cxl_cmd_new_identify; -+ cxl_cmd_identify_get_fw_rev; -+ cxl_cmd_identify_get_partition_align; -+ cxl_cmd_identify_get_label_size; - local: - *; - }; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 87ca17e..3273f21 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -54,6 +54,25 @@ struct cxl_cmd { - int status; - }; - -+#define CXL_CMD_IDENTIFY_FW_REV_LENGTH 0x10 -+ -+struct cxl_cmd_identify { -+ char fw_revision[CXL_CMD_IDENTIFY_FW_REV_LENGTH]; -+ le64 total_capacity; -+ le64 volatile_capacity; -+ le64 persistent_capacity; -+ le64 partition_align; -+ le16 info_event_log_size; -+ le16 warning_event_log_size; -+ le16 failure_event_log_size; -+ le16 fatal_event_log_size; -+ le32 lsa_size; -+ u8 poison_list_max_mer[3]; -+ le16 inject_poison_limit; -+ u8 poison_caps; -+ u8 qos_telemetry_caps; -+} __attribute__((packed)); -+ - static inline int check_kmod(struct kmod_ctx *kmod_ctx) - { - return kmod_ctx ? 0 : -ENXIO; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 6e87b80..0f2d5e9 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -58,6 +58,10 @@ void cxl_cmd_unref(struct cxl_cmd *cmd); - int cxl_cmd_submit(struct cxl_cmd *cmd); - int cxl_cmd_get_mbox_status(struct cxl_cmd *cmd); - int cxl_cmd_get_out_size(struct cxl_cmd *cmd); -+struct cxl_cmd *cxl_cmd_new_identify(struct cxl_memdev *memdev); -+int cxl_cmd_identify_get_fw_rev(struct cxl_cmd *cmd, char *fw_rev, int fw_len); -+unsigned long long cxl_cmd_identify_get_partition_align(struct cxl_cmd *cmd); -+unsigned int cxl_cmd_identify_get_label_size(struct cxl_cmd *cmd); - - #ifdef __cplusplus - } /* extern "C" */ --- -2.27.0 - diff --git a/SOURCES/0037-libcxl-add-GET_HEALTH_INFO-mailbox-command-and-acces.patch b/SOURCES/0037-libcxl-add-GET_HEALTH_INFO-mailbox-command-and-acces.patch deleted file mode 100644 index 60a3fd6..0000000 --- a/SOURCES/0037-libcxl-add-GET_HEALTH_INFO-mailbox-command-and-acces.patch +++ /dev/null @@ -1,575 +0,0 @@ -From 55ada0eab92d52826c9be0186db664ba9eeba749 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:29 -0600 -Subject: [PATCH 037/217] libcxl: add GET_HEALTH_INFO mailbox command and - accessors - -Add libcxl APIs to create a new GET_HEALTH_INFO mailbox command, the -command output data structure (privately), and accessor APIs to return -the different fields in the health info output. - -Cc: Ben Widawsky -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 291 +++++++++++++++++++++++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 29 +++++ - cxl/lib/private.h | 47 ++++++++ - cxl/libcxl.h | 33 +++++ - util/bitmap.h | 85 +++++++++++++ - 5 files changed, 485 insertions(+) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index ed21670..065824d 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -677,6 +677,297 @@ CXL_EXPORT const char *cxl_cmd_get_devname(struct cxl_cmd *cmd) - return cxl_memdev_get_devname(cmd->memdev); - } - -+static int cxl_cmd_validate_status(struct cxl_cmd *cmd, u32 id) -+{ -+ if (cmd->send_cmd->id != id) -+ return -EINVAL; -+ if (cmd->status < 0) -+ return cmd->status; -+ return 0; -+} -+ -+/* Helpers for health_info fields (no endian conversion) */ -+#define cmd_get_field_u8(cmd, n, N, field) \ -+do { \ -+ struct cxl_cmd_##n *c = \ -+ (struct cxl_cmd_##n *)cmd->send_cmd->out.payload; \ -+ int rc = cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_##N); \ -+ if (rc) \ -+ return rc; \ -+ return c->field; \ -+} while(0) -+ -+#define cmd_get_field_u16(cmd, n, N, field) \ -+do { \ -+ struct cxl_cmd_##n *c = \ -+ (struct cxl_cmd_##n *)cmd->send_cmd->out.payload; \ -+ int rc = cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_##N); \ -+ if (rc) \ -+ return rc; \ -+ return le16_to_cpu(c->field); \ -+} while(0) -+ -+ -+#define cmd_get_field_u32(cmd, n, N, field) \ -+do { \ -+ struct cxl_cmd_##n *c = \ -+ (struct cxl_cmd_##n *)cmd->send_cmd->out.payload; \ -+ int rc = cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_##N); \ -+ if (rc) \ -+ return rc; \ -+ return le32_to_cpu(c->field); \ -+} while(0) -+ -+ -+#define cmd_get_field_u8_mask(cmd, n, N, field, mask) \ -+do { \ -+ struct cxl_cmd_##n *c = \ -+ (struct cxl_cmd_##n *)cmd->send_cmd->out.payload; \ -+ int rc = cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_##N); \ -+ if (rc) \ -+ return rc; \ -+ return !!(c->field & mask); \ -+} while(0) -+ -+CXL_EXPORT struct cxl_cmd *cxl_cmd_new_get_health_info( -+ struct cxl_memdev *memdev) -+{ -+ return cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_GET_HEALTH_INFO); -+} -+ -+#define cmd_health_get_status_field(c, m) \ -+ cmd_get_field_u8_mask(c, get_health_info, GET_HEALTH_INFO, health_status, m) -+ -+CXL_EXPORT int cxl_cmd_health_info_get_maintenance_needed(struct cxl_cmd *cmd) -+{ -+ cmd_health_get_status_field(cmd, -+ CXL_CMD_HEALTH_INFO_STATUS_MAINTENANCE_NEEDED_MASK); -+} -+ -+CXL_EXPORT int cxl_cmd_health_info_get_performance_degraded(struct cxl_cmd *cmd) -+{ -+ cmd_health_get_status_field(cmd, -+ CXL_CMD_HEALTH_INFO_STATUS_PERFORMANCE_DEGRADED_MASK); -+} -+ -+CXL_EXPORT int cxl_cmd_health_info_get_hw_replacement_needed(struct cxl_cmd *cmd) -+{ -+ cmd_health_get_status_field(cmd, -+ CXL_CMD_HEALTH_INFO_STATUS_HW_REPLACEMENT_NEEDED_MASK); -+} -+ -+#define cmd_health_check_media_field(cmd, f) \ -+do { \ -+ struct cxl_cmd_get_health_info *c = \ -+ (struct cxl_cmd_get_health_info *)cmd->send_cmd->out.payload; \ -+ int rc = cxl_cmd_validate_status(cmd, \ -+ CXL_MEM_COMMAND_ID_GET_HEALTH_INFO); \ -+ if (rc) \ -+ return rc; \ -+ return (c->media_status == f); \ -+} while(0) -+ -+CXL_EXPORT int cxl_cmd_health_info_get_media_normal(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_media_field(cmd, -+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_NORMAL); -+} -+ -+CXL_EXPORT int cxl_cmd_health_info_get_media_not_ready(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_media_field(cmd, -+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_NOT_READY); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_media_persistence_lost(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_media_field(cmd, -+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_PERSISTENCE_LOST); -+} -+ -+CXL_EXPORT int cxl_cmd_health_info_get_media_data_lost(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_media_field(cmd, -+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_DATA_LOST); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_media_powerloss_persistence_loss(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_media_field(cmd, -+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_POWERLOSS_PERSISTENCE_LOSS); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_media_shutdown_persistence_loss(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_media_field(cmd, -+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_SHUTDOWN_PERSISTENCE_LOSS); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_media_persistence_loss_imminent(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_media_field(cmd, -+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_PERSISTENCE_LOSS_IMMINENT); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_media_powerloss_data_loss(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_media_field(cmd, -+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_POWERLOSS_DATA_LOSS); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_media_shutdown_data_loss(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_media_field(cmd, -+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_SHUTDOWN_DATA_LOSS); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_media_data_loss_imminent(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_media_field(cmd, -+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_DATA_LOSS_IMMINENT); -+} -+ -+#define cmd_health_check_ext_field(cmd, fname, type) \ -+do { \ -+ struct cxl_cmd_get_health_info *c = \ -+ (struct cxl_cmd_get_health_info *)cmd->send_cmd->out.payload; \ -+ int rc = cxl_cmd_validate_status(cmd, \ -+ CXL_MEM_COMMAND_ID_GET_HEALTH_INFO); \ -+ if (rc) \ -+ return rc; \ -+ return (FIELD_GET(fname##_MASK, c->ext_status) == \ -+ fname##_##type); \ -+} while(0) -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_ext_life_used_normal(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_ext_field(cmd, -+ CXL_CMD_HEALTH_INFO_EXT_LIFE_USED, NORMAL); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_ext_life_used_warning(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_ext_field(cmd, -+ CXL_CMD_HEALTH_INFO_EXT_LIFE_USED, WARNING); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_ext_life_used_critical(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_ext_field(cmd, -+ CXL_CMD_HEALTH_INFO_EXT_LIFE_USED, CRITICAL); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_ext_temperature_normal(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_ext_field(cmd, -+ CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE, NORMAL); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_ext_temperature_warning(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_ext_field(cmd, -+ CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE, WARNING); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_ext_temperature_critical(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_ext_field(cmd, -+ CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE, CRITICAL); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_ext_corrected_volatile_normal(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_ext_field(cmd, -+ CXL_CMD_HEALTH_INFO_EXT_CORRECTED_VOLATILE, NORMAL); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_ext_corrected_volatile_warning(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_ext_field(cmd, -+ CXL_CMD_HEALTH_INFO_EXT_CORRECTED_VOLATILE, WARNING); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_ext_corrected_persistent_normal(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_ext_field(cmd, -+ CXL_CMD_HEALTH_INFO_EXT_CORRECTED_PERSISTENT, NORMAL); -+} -+ -+CXL_EXPORT int -+cxl_cmd_health_info_get_ext_corrected_persistent_warning(struct cxl_cmd *cmd) -+{ -+ cmd_health_check_ext_field(cmd, -+ CXL_CMD_HEALTH_INFO_EXT_CORRECTED_PERSISTENT, WARNING); -+} -+ -+static int health_info_get_life_used_raw(struct cxl_cmd *cmd) -+{ -+ cmd_get_field_u8(cmd, get_health_info, GET_HEALTH_INFO, -+ life_used); -+} -+ -+CXL_EXPORT int cxl_cmd_health_info_get_life_used(struct cxl_cmd *cmd) -+{ -+ int rc = health_info_get_life_used_raw(cmd); -+ -+ if (rc < 0) -+ return rc; -+ if (rc == CXL_CMD_HEALTH_INFO_LIFE_USED_NOT_IMPL) -+ return -EOPNOTSUPP; -+ return rc; -+} -+ -+static int health_info_get_temperature_raw(struct cxl_cmd *cmd) -+{ -+ cmd_get_field_u16(cmd, get_health_info, GET_HEALTH_INFO, -+ temperature); -+} -+ -+CXL_EXPORT int cxl_cmd_health_info_get_temperature(struct cxl_cmd *cmd) -+{ -+ int rc = health_info_get_temperature_raw(cmd); -+ -+ if (rc < 0) -+ return rc; -+ if (rc == CXL_CMD_HEALTH_INFO_TEMPERATURE_NOT_IMPL) -+ return -EOPNOTSUPP; -+ return rc; -+} -+ -+CXL_EXPORT int cxl_cmd_health_info_get_dirty_shutdowns(struct cxl_cmd *cmd) -+{ -+ cmd_get_field_u32(cmd, get_health_info, GET_HEALTH_INFO, -+ dirty_shutdowns); -+} -+ -+CXL_EXPORT int cxl_cmd_health_info_get_volatile_errors(struct cxl_cmd *cmd) -+{ -+ cmd_get_field_u32(cmd, get_health_info, GET_HEALTH_INFO, -+ volatile_errors); -+} -+ -+CXL_EXPORT int cxl_cmd_health_info_get_pmem_errors(struct cxl_cmd *cmd) -+{ -+ cmd_get_field_u32(cmd, get_health_info, GET_HEALTH_INFO, -+ pmem_errors); -+} -+ - CXL_EXPORT struct cxl_cmd *cxl_cmd_new_identify(struct cxl_memdev *memdev) - { - return cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_IDENTIFY); -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 1dc45f4..c83bc28 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -33,6 +33,35 @@ global: - cxl_cmd_identify_get_fw_rev; - cxl_cmd_identify_get_partition_align; - cxl_cmd_identify_get_label_size; -+ cxl_cmd_new_get_health_info; -+ cxl_cmd_health_info_get_maintenance_needed; -+ cxl_cmd_health_info_get_performance_degraded; -+ cxl_cmd_health_info_get_hw_replacement_needed; -+ cxl_cmd_health_info_get_media_normal; -+ cxl_cmd_health_info_get_media_not_ready; -+ cxl_cmd_health_info_get_media_persistence_lost; -+ cxl_cmd_health_info_get_media_data_lost; -+ cxl_cmd_health_info_get_media_powerloss_persistence_loss; -+ cxl_cmd_health_info_get_media_shutdown_persistence_loss; -+ cxl_cmd_health_info_get_media_persistence_loss_imminent; -+ cxl_cmd_health_info_get_media_powerloss_data_loss; -+ cxl_cmd_health_info_get_media_shutdown_data_loss; -+ cxl_cmd_health_info_get_media_data_loss_imminent; -+ cxl_cmd_health_info_get_ext_life_used_normal; -+ cxl_cmd_health_info_get_ext_life_used_warning; -+ cxl_cmd_health_info_get_ext_life_used_critical; -+ cxl_cmd_health_info_get_ext_temperature_normal; -+ cxl_cmd_health_info_get_ext_temperature_warning; -+ cxl_cmd_health_info_get_ext_temperature_critical; -+ cxl_cmd_health_info_get_ext_corrected_volatile_normal; -+ cxl_cmd_health_info_get_ext_corrected_volatile_warning; -+ cxl_cmd_health_info_get_ext_corrected_persistent_normal; -+ cxl_cmd_health_info_get_ext_corrected_persistent_warning; -+ cxl_cmd_health_info_get_life_used; -+ cxl_cmd_health_info_get_temperature; -+ cxl_cmd_health_info_get_dirty_shutdowns; -+ cxl_cmd_health_info_get_volatile_errors; -+ cxl_cmd_health_info_get_pmem_errors; - local: - *; - }; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 3273f21..885553a 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -73,6 +73,53 @@ struct cxl_cmd_identify { - u8 qos_telemetry_caps; - } __attribute__((packed)); - -+struct cxl_cmd_get_health_info { -+ u8 health_status; -+ u8 media_status; -+ u8 ext_status; -+ u8 life_used; -+ le16 temperature; -+ le32 dirty_shutdowns; -+ le32 volatile_errors; -+ le32 pmem_errors; -+} __attribute__((packed)); -+ -+/* CXL 2.0 8.2.9.5.3 Byte 0 Health Status */ -+#define CXL_CMD_HEALTH_INFO_STATUS_MAINTENANCE_NEEDED_MASK BIT(0) -+#define CXL_CMD_HEALTH_INFO_STATUS_PERFORMANCE_DEGRADED_MASK BIT(1) -+#define CXL_CMD_HEALTH_INFO_STATUS_HW_REPLACEMENT_NEEDED_MASK BIT(2) -+ -+/* CXL 2.0 8.2.9.5.3 Byte 1 Media Status */ -+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_NORMAL 0x0 -+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_NOT_READY 0x1 -+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_PERSISTENCE_LOST 0x2 -+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_DATA_LOST 0x3 -+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_POWERLOSS_PERSISTENCE_LOSS 0x4 -+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_SHUTDOWN_PERSISTENCE_LOSS 0x5 -+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_PERSISTENCE_LOSS_IMMINENT 0x6 -+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_POWERLOSS_DATA_LOSS 0x7 -+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_SHUTDOWN_DATA_LOSS 0x8 -+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_DATA_LOSS_IMMINENT 0x9 -+ -+/* CXL 2.0 8.2.9.5.3 Byte 2 Additional Status */ -+#define CXL_CMD_HEALTH_INFO_EXT_LIFE_USED_MASK GENMASK(1, 0) -+#define CXL_CMD_HEALTH_INFO_EXT_LIFE_USED_NORMAL (0) -+#define CXL_CMD_HEALTH_INFO_EXT_LIFE_USED_WARNING (1) -+#define CXL_CMD_HEALTH_INFO_EXT_LIFE_USED_CRITICAL (2) -+#define CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE_MASK GENMASK(3, 2) -+#define CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE_NORMAL (0) -+#define CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE_WARNING (1) -+#define CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE_CRITICAL (2) -+#define CXL_CMD_HEALTH_INFO_EXT_CORRECTED_VOLATILE_MASK BIT(4) -+#define CXL_CMD_HEALTH_INFO_EXT_CORRECTED_VOLATILE_NORMAL (0) -+#define CXL_CMD_HEALTH_INFO_EXT_CORRECTED_VOLATILE_WARNING (1) -+#define CXL_CMD_HEALTH_INFO_EXT_CORRECTED_PERSISTENT_MASK BIT(5) -+#define CXL_CMD_HEALTH_INFO_EXT_CORRECTED_PERSISTENT_NORMAL (0) -+#define CXL_CMD_HEALTH_INFO_EXT_CORRECTED_PERSISTENT_WARNING (1) -+ -+#define CXL_CMD_HEALTH_INFO_LIFE_USED_NOT_IMPL 0xff -+#define CXL_CMD_HEALTH_INFO_TEMPERATURE_NOT_IMPL 0xffff -+ - static inline int check_kmod(struct kmod_ctx *kmod_ctx) - { - return kmod_ctx ? 0 : -ENXIO; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 0f2d5e9..eae2db8 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -62,6 +62,39 @@ struct cxl_cmd *cxl_cmd_new_identify(struct cxl_memdev *memdev); - int cxl_cmd_identify_get_fw_rev(struct cxl_cmd *cmd, char *fw_rev, int fw_len); - unsigned long long cxl_cmd_identify_get_partition_align(struct cxl_cmd *cmd); - unsigned int cxl_cmd_identify_get_label_size(struct cxl_cmd *cmd); -+struct cxl_cmd *cxl_cmd_new_get_health_info(struct cxl_memdev *memdev); -+int cxl_cmd_health_info_get_maintenance_needed(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_performance_degraded(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_hw_replacement_needed(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_normal(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_not_ready(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_persistence_lost(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_data_lost(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_normal(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_not_ready(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_persistence_lost(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_data_lost(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_powerloss_persistence_loss(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_shutdown_persistence_loss(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_persistence_loss_imminent(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_powerloss_data_loss(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_shutdown_data_loss(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_media_data_loss_imminent(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_ext_life_used_normal(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_ext_life_used_warning(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_ext_life_used_critical(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_ext_temperature_normal(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_ext_temperature_warning(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_ext_temperature_critical(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_ext_corrected_volatile_normal(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_ext_corrected_volatile_warning(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_ext_corrected_persistent_normal(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_ext_corrected_persistent_warning(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_life_used(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_temperature(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_dirty_shutdowns(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_volatile_errors(struct cxl_cmd *cmd); -+int cxl_cmd_health_info_get_pmem_errors(struct cxl_cmd *cmd); - - #ifdef __cplusplus - } /* extern "C" */ -diff --git a/util/bitmap.h b/util/bitmap.h -index 490f3f0..04b3429 100644 ---- a/util/bitmap.h -+++ b/util/bitmap.h -@@ -3,10 +3,33 @@ - #ifndef _NDCTL_BITMAP_H_ - #define _NDCTL_BITMAP_H_ - -+#include - #include -+#include - #include - -+#ifndef _UL -+#define _UL(x) (_AC(x, UL)) -+#endif -+#ifndef _ULL -+#define _ULL(x) (_AC(x, ULL)) -+#endif -+ - #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) -+#define UL(x) (_UL(x)) -+#define ULL(x) (_ULL(x)) -+ -+/* GENMASK() and its dependencies copied from include/linux/{bits.h, const.h} */ -+#define __is_constexpr(x) \ -+ (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8))) -+#define GENMASK_INPUT_CHECK(h, l) \ -+ (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \ -+ __is_constexpr((l) > (h)), (l) > (h), 0))) -+#define __GENMASK(h, l) \ -+ (((~UL(0)) - (UL(1) << (l)) + 1) & \ -+ (~UL(0) >> (BITS_PER_LONG - 1 - (h)))) -+#define GENMASK(h, l) \ -+ (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l)) - - #define BIT(nr) (1UL << (nr)) - #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) -@@ -30,5 +53,67 @@ unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, - unsigned long offset); - int bitmap_full(const unsigned long *src, unsigned int nbits); - -+/* -+ * Bitfield access macros -+ * (Copied from Linux's include/linux/bitfield.h) -+ * -+ * FIELD_{GET,PREP} macros take as first parameter shifted mask -+ * from which they extract the base mask and shift amount. -+ * Mask must be a compilation time constant. -+ * -+ * Example: -+ * -+ * #define REG_FIELD_A GENMASK(6, 0) -+ * #define REG_FIELD_B BIT(7) -+ * #define REG_FIELD_C GENMASK(15, 8) -+ * #define REG_FIELD_D GENMASK(31, 16) -+ * -+ * Get: -+ * a = FIELD_GET(REG_FIELD_A, reg); -+ * b = FIELD_GET(REG_FIELD_B, reg); -+ * -+ * Set: -+ * reg = FIELD_PREP(REG_FIELD_A, 1) | -+ * FIELD_PREP(REG_FIELD_B, 0) | -+ * FIELD_PREP(REG_FIELD_C, c) | -+ * FIELD_PREP(REG_FIELD_D, 0x40); -+ * -+ * Modify: -+ * reg &= ~REG_FIELD_C; -+ * reg |= FIELD_PREP(REG_FIELD_C, c); -+ */ -+ -+/* Force a compilation error if a constant expression is not a power of 2 */ -+#define __BUILD_BUG_ON_NOT_POWER_OF_2(n) \ -+ BUILD_BUG_ON(((n) & ((n) - 1)) != 0) -+#define BUILD_BUG_ON_NOT_POWER_OF_2(n) \ -+ BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0)) -+ -+#define __bf_shf(x) (__builtin_ffsll(x) - 1) -+ -+#define __BF_FIELD_CHECK(_mask, _reg, _val) \ -+ ({ \ -+ BUILD_BUG_ON(!__builtin_constant_p(_mask)); \ -+ BUILD_BUG_ON((_mask) == 0); \ -+ BUILD_BUG_ON(__builtin_constant_p(_val) ? \ -+ ~((_mask) >> __bf_shf(_mask)) & (_val) : 0); \ -+ BUILD_BUG_ON((_mask) > (typeof(_reg))~0ull); \ -+ __BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \ -+ (1ULL << __bf_shf(_mask))); \ -+ }) -+ -+/** -+ * FIELD_GET() - extract a bitfield element -+ * @_mask: shifted mask defining the field's length and position -+ * @_reg: value of entire bitfield -+ * -+ * FIELD_GET() extracts the field specified by @_mask from the -+ * bitfield passed in as @_reg by masking and shifting it down. -+ */ -+#define FIELD_GET(_mask, _reg) \ -+ ({ \ -+ __BF_FIELD_CHECK(_mask, _reg, 0U); \ -+ (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \ -+ }) - - #endif /* _NDCTL_BITMAP_H_ */ --- -2.27.0 - diff --git a/SOURCES/0038-libcxl-add-support-for-the-GET_LSA-command.patch b/SOURCES/0038-libcxl-add-support-for-the-GET_LSA-command.patch deleted file mode 100644 index d9db687..0000000 --- a/SOURCES/0038-libcxl-add-support-for-the-GET_LSA-command.patch +++ /dev/null @@ -1,113 +0,0 @@ -From c7ae078f1050ed54e254377404af2ae0879f2a39 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:30 -0600 -Subject: [PATCH 038/217] libcxl: add support for the 'GET_LSA' command - -Add a command allocator and accessor APIs for the 'GET_LSA' mailbox -command. - -Cc: Ben Widawsky -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 36 ++++++++++++++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 2 ++ - cxl/lib/private.h | 5 +++++ - cxl/libcxl.h | 4 ++++ - 4 files changed, 47 insertions(+) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 065824d..76913a2 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -1036,6 +1036,42 @@ CXL_EXPORT struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, - return cmd; - } - -+CXL_EXPORT struct cxl_cmd *cxl_cmd_new_read_label(struct cxl_memdev *memdev, -+ unsigned int offset, unsigned int length) -+{ -+ struct cxl_cmd_get_lsa_in *get_lsa; -+ struct cxl_cmd *cmd; -+ -+ cmd = cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_GET_LSA); -+ if (!cmd) -+ return NULL; -+ -+ get_lsa = (struct cxl_cmd_get_lsa_in *)cmd->send_cmd->in.payload; -+ get_lsa->offset = cpu_to_le32(offset); -+ get_lsa->length = cpu_to_le32(length); -+ return cmd; -+} -+ -+CXL_EXPORT ssize_t cxl_cmd_read_label_get_payload(struct cxl_cmd *cmd, -+ void *buf, unsigned int length) -+{ -+ struct cxl_cmd_get_lsa_in *get_lsa; -+ void *payload; -+ int rc; -+ -+ rc = cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_GET_LSA); -+ if (rc) -+ return rc; -+ -+ get_lsa = (struct cxl_cmd_get_lsa_in *)cmd->send_cmd->in.payload; -+ if (length > le32_to_cpu(get_lsa->length)) -+ return -EINVAL; -+ -+ payload = (void *)cmd->send_cmd->out.payload; -+ memcpy(buf, payload, length); -+ return length; -+} -+ - CXL_EXPORT int cxl_cmd_submit(struct cxl_cmd *cmd) - { - struct cxl_memdev *memdev = cmd->memdev; -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index c83bc28..629322c 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -62,6 +62,8 @@ global: - cxl_cmd_health_info_get_dirty_shutdowns; - cxl_cmd_health_info_get_volatile_errors; - cxl_cmd_health_info_get_pmem_errors; -+ cxl_cmd_new_read_label; -+ cxl_cmd_read_label_get_payload; - local: - *; - }; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 885553a..bf3a897 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -73,6 +73,11 @@ struct cxl_cmd_identify { - u8 qos_telemetry_caps; - } __attribute__((packed)); - -+struct cxl_cmd_get_lsa_in { -+ le32 offset; -+ le32 length; -+} __attribute__((packed)); -+ - struct cxl_cmd_get_health_info { - u8 health_status; - u8 media_status; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index eae2db8..7408745 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -95,6 +95,10 @@ int cxl_cmd_health_info_get_temperature(struct cxl_cmd *cmd); - int cxl_cmd_health_info_get_dirty_shutdowns(struct cxl_cmd *cmd); - int cxl_cmd_health_info_get_volatile_errors(struct cxl_cmd *cmd); - int cxl_cmd_health_info_get_pmem_errors(struct cxl_cmd *cmd); -+struct cxl_cmd *cxl_cmd_new_read_label(struct cxl_memdev *memdev, -+ unsigned int offset, unsigned int length); -+ssize_t cxl_cmd_read_label_get_payload(struct cxl_cmd *cmd, void *buf, -+ unsigned int length); - - #ifdef __cplusplus - } /* extern "C" */ --- -2.27.0 - diff --git a/SOURCES/0039-libcxl-add-label_size-to-cxl_memdev-and-an-API-to-re.patch b/SOURCES/0039-libcxl-add-label_size-to-cxl_memdev-and-an-API-to-re.patch deleted file mode 100644 index 7a0eb25..0000000 --- a/SOURCES/0039-libcxl-add-label_size-to-cxl_memdev-and-an-API-to-re.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 101966ed3e4a73a6e0e1c269306e976040e068a9 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:32 -0600 -Subject: [PATCH 039/217] libcxl: add label_size to cxl_memdev, and an API to - retrieve it - -Size of the Label Storage Area (LSA) is available as a sysfs attribute -called 'label_storage_size'. Add that to libcxl's memdev so that it is available -for label related commands. - -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 12 ++++++++++++ - cxl/lib/libcxl.sym | 1 + - cxl/lib/private.h | 1 + - cxl/libcxl.h | 1 + - 4 files changed, 15 insertions(+) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 76913a2..def3a97 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -247,6 +247,13 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) - if (memdev->payload_max < 0) - goto err_read; - -+ sprintf(path, "%s/label_storage_size", cxlmem_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ goto err_read; -+ memdev->lsa_size = strtoull(buf, NULL, 0); -+ if (memdev->lsa_size == ULLONG_MAX) -+ goto err_read; -+ - memdev->dev_path = strdup(cxlmem_base); - if (!memdev->dev_path) - goto err_read; -@@ -350,6 +357,11 @@ CXL_EXPORT const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev - return memdev->firmware_version; - } - -+CXL_EXPORT size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev) -+{ -+ return memdev->lsa_size; -+} -+ - CXL_EXPORT void cxl_cmd_unref(struct cxl_cmd *cmd) - { - if (!cmd) -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 629322c..858e953 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -64,6 +64,7 @@ global: - cxl_cmd_health_info_get_pmem_errors; - cxl_cmd_new_read_label; - cxl_cmd_read_label_get_payload; -+ cxl_memdev_get_label_size; - local: - *; - }; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index bf3a897..c4ed741 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -21,6 +21,7 @@ struct cxl_memdev { - unsigned long long pmem_size; - unsigned long long ram_size; - int payload_max; -+ size_t lsa_size; - struct kmod_module *module; - }; - -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 7408745..d3b97a1 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -42,6 +42,7 @@ struct cxl_ctx *cxl_memdev_get_ctx(struct cxl_memdev *memdev); - unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev); - unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev); - const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev); -+size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev); - - #define cxl_memdev_foreach(ctx, memdev) \ - for (memdev = cxl_memdev_get_first(ctx); \ --- -2.27.0 - diff --git a/SOURCES/0040-libcxl-add-representation-for-an-nvdimm-bridge-objec.patch b/SOURCES/0040-libcxl-add-representation-for-an-nvdimm-bridge-objec.patch deleted file mode 100644 index 533f398..0000000 --- a/SOURCES/0040-libcxl-add-representation-for-an-nvdimm-bridge-objec.patch +++ /dev/null @@ -1,184 +0,0 @@ -From cd1aed6cefe8f4f2043349e1a614876f67743439 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:33 -0600 -Subject: [PATCH 040/217] libcxl: add representation for an nvdimm bridge - object - -Add an nvdimm bridge object representation internal to libcxl. A bridge -object is tied to its parent memdev object, and this patch adds its -first interface, which checks whether a bridge is 'active' - i.e. -implying the label space on the memdev is owned by the kernel. - -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 1 + - cxl/lib/private.h | 8 +++++ - cxl/libcxl.h | 1 + - 4 files changed, 83 insertions(+) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index def3a97..60ed646 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -45,11 +45,19 @@ struct cxl_ctx { - void *private_data; - }; - -+static void free_bridge(struct cxl_nvdimm_bridge *bridge) -+{ -+ free(bridge->dev_buf); -+ free(bridge->dev_path); -+ free(bridge); -+} -+ - static void free_memdev(struct cxl_memdev *memdev, struct list_head *head) - { - if (head) - list_del_from(head, &memdev->list); - kmod_module_unref(memdev->module); -+ free_bridge(memdev->bridge); - free(memdev->firmware_version); - free(memdev->dev_buf); - free(memdev->dev_path); -@@ -205,6 +213,40 @@ CXL_EXPORT void cxl_set_log_priority(struct cxl_ctx *ctx, int priority) - ctx->ctx.log_priority = priority; - } - -+static void *add_cxl_bridge(void *parent, int id, const char *br_base) -+{ -+ const char *devname = devpath_to_devname(br_base); -+ struct cxl_memdev *memdev = parent; -+ struct cxl_ctx *ctx = memdev->ctx; -+ struct cxl_nvdimm_bridge *bridge; -+ -+ dbg(ctx, "%s: bridge_base: \'%s\'\n", devname, br_base); -+ -+ bridge = calloc(1, sizeof(*bridge)); -+ if (!bridge) -+ goto err_dev; -+ bridge->id = id; -+ -+ bridge->dev_path = strdup(br_base); -+ if (!bridge->dev_path) -+ goto err_read; -+ -+ bridge->dev_buf = calloc(1, strlen(br_base) + 50); -+ if (!bridge->dev_buf) -+ goto err_read; -+ bridge->buf_len = strlen(br_base) + 50; -+ -+ memdev->bridge = bridge; -+ return bridge; -+ -+ err_read: -+ free(bridge->dev_buf); -+ free(bridge->dev_path); -+ free(bridge); -+ err_dev: -+ return NULL; -+} -+ - static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) - { - const char *devname = devpath_to_devname(cxlmem_base); -@@ -271,6 +313,8 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) - goto err_read; - memdev->buf_len = strlen(cxlmem_base) + 50; - -+ sysfs_device_parse(ctx, cxlmem_base, "pmem", memdev, add_cxl_bridge); -+ - cxl_memdev_foreach(ctx, memdev_dup) - if (memdev_dup->id == memdev->id) { - free_memdev(memdev, NULL); -@@ -362,6 +406,35 @@ CXL_EXPORT size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev) - return memdev->lsa_size; - } - -+static int is_enabled(const char *drvpath) -+{ -+ struct stat st; -+ -+ if (lstat(drvpath, &st) < 0 || !S_ISLNK(st.st_mode)) -+ return 0; -+ else -+ return 1; -+} -+ -+CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev) -+{ -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ struct cxl_nvdimm_bridge *bridge = memdev->bridge; -+ char *path = bridge->dev_buf; -+ int len = bridge->buf_len; -+ -+ if (!bridge) -+ return 0; -+ -+ if (snprintf(path, len, "%s/driver", bridge->dev_path) >= len) { -+ err(ctx, "%s: nvdimm bridge buffer too small!\n", -+ cxl_memdev_get_devname(memdev)); -+ return 0; -+ } -+ -+ return is_enabled(path); -+} -+ - CXL_EXPORT void cxl_cmd_unref(struct cxl_cmd *cmd) - { - if (!cmd) -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 858e953..f3b0c63 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -65,6 +65,7 @@ global: - cxl_cmd_new_read_label; - cxl_cmd_read_label_get_payload; - cxl_memdev_get_label_size; -+ cxl_memdev_nvdimm_bridge_active; - local: - *; - }; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index c4ed741..525c41e 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -10,6 +10,13 @@ - - #define CXL_EXPORT __attribute__ ((visibility("default"))) - -+struct cxl_nvdimm_bridge { -+ int id; -+ void *dev_buf; -+ size_t buf_len; -+ char *dev_path; -+}; -+ - struct cxl_memdev { - int id, major, minor; - void *dev_buf; -@@ -23,6 +30,7 @@ struct cxl_memdev { - int payload_max; - size_t lsa_size; - struct kmod_module *module; -+ struct cxl_nvdimm_bridge *bridge; - }; - - enum cxl_cmd_query_status { -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index d3b97a1..535e349 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -43,6 +43,7 @@ unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev); - unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev); - const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev); - size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev); -+int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev); - - #define cxl_memdev_foreach(ctx, memdev) \ - for (memdev = cxl_memdev_get_first(ctx); \ --- -2.27.0 - diff --git a/SOURCES/0041-libcxl-add-interfaces-for-label-operations.patch b/SOURCES/0041-libcxl-add-interfaces-for-label-operations.patch deleted file mode 100644 index ff7e247..0000000 --- a/SOURCES/0041-libcxl-add-interfaces-for-label-operations.patch +++ /dev/null @@ -1,247 +0,0 @@ -From 6255d23452809ddc6d48083c35fc935e4fa420d8 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:34 -0600 -Subject: [PATCH 041/217] libcxl: add interfaces for label operations - -Add libcxl interfaces to allow performinfg label (LSA) manipulations. -Add a 'cxl_cmd_new_set_lsa' interface to create a 'Set LSA' mailbox -command payload, and interfaces to read, write, and zero the LSA area on -a memdev. - -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 158 +++++++++++++++++++++++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 4 ++ - cxl/lib/private.h | 6 ++ - cxl/libcxl.h | 8 +++ - 4 files changed, 176 insertions(+) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 60ed646..f0664be 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -1197,3 +1197,161 @@ CXL_EXPORT int cxl_cmd_get_out_size(struct cxl_cmd *cmd) - { - return cmd->send_cmd->out.size; - } -+ -+CXL_EXPORT struct cxl_cmd *cxl_cmd_new_write_label(struct cxl_memdev *memdev, -+ void *lsa_buf, unsigned int offset, unsigned int length) -+{ -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ struct cxl_cmd_set_lsa *set_lsa; -+ struct cxl_cmd *cmd; -+ int rc; -+ -+ cmd = cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_SET_LSA); -+ if (!cmd) -+ return NULL; -+ -+ /* this will allocate 'in.payload' */ -+ rc = cxl_cmd_set_input_payload(cmd, NULL, sizeof(*set_lsa) + length); -+ if (rc) { -+ err(ctx, "%s: cmd setup failed: %s\n", -+ cxl_memdev_get_devname(memdev), strerror(-rc)); -+ goto out_fail; -+ } -+ set_lsa = (struct cxl_cmd_set_lsa *)cmd->send_cmd->in.payload; -+ set_lsa->offset = cpu_to_le32(offset); -+ memcpy(set_lsa->lsa_data, lsa_buf, length); -+ -+ return cmd; -+ -+out_fail: -+ cxl_cmd_unref(cmd); -+ return NULL; -+} -+ -+enum lsa_op { -+ LSA_OP_GET, -+ LSA_OP_SET, -+ LSA_OP_ZERO, -+}; -+ -+static int __lsa_op(struct cxl_memdev *memdev, int op, void *buf, -+ size_t length, size_t offset) -+{ -+ const char *devname = cxl_memdev_get_devname(memdev); -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ void *zero_buf = NULL; -+ struct cxl_cmd *cmd; -+ ssize_t ret_len; -+ int rc = 0; -+ -+ switch (op) { -+ case LSA_OP_GET: -+ cmd = cxl_cmd_new_read_label(memdev, offset, length); -+ if (!cmd) -+ return -ENOMEM; -+ rc = cxl_cmd_set_output_payload(cmd, buf, length); -+ if (rc) { -+ err(ctx, "%s: cmd setup failed: %s\n", -+ cxl_memdev_get_devname(memdev), strerror(-rc)); -+ goto out; -+ } -+ break; -+ case LSA_OP_ZERO: -+ zero_buf = calloc(1, length); -+ if (!zero_buf) -+ return -ENOMEM; -+ buf = zero_buf; -+ /* fall through */ -+ case LSA_OP_SET: -+ cmd = cxl_cmd_new_write_label(memdev, buf, offset, length); -+ if (!cmd) { -+ rc = -ENOMEM; -+ goto out_free; -+ } -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ rc = cxl_cmd_submit(cmd); -+ if (rc < 0) { -+ err(ctx, "%s: cmd submission failed: %s\n", -+ devname, strerror(-rc)); -+ goto out; -+ } -+ -+ rc = cxl_cmd_get_mbox_status(cmd); -+ if (rc != 0) { -+ err(ctx, "%s: firmware status: %d\n", -+ devname, rc); -+ rc = -ENXIO; -+ goto out; -+ } -+ -+ if (op == LSA_OP_GET) { -+ ret_len = cxl_cmd_read_label_get_payload(cmd, buf, length); -+ if (ret_len < 0) { -+ rc = ret_len; -+ goto out; -+ } -+ } -+ -+out: -+ cxl_cmd_unref(cmd); -+out_free: -+ free(zero_buf); -+ return rc; -+ -+} -+ -+static int lsa_op(struct cxl_memdev *memdev, int op, void *buf, -+ size_t length, size_t offset) -+{ -+ const char *devname = cxl_memdev_get_devname(memdev); -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ size_t remaining = length, cur_len, cur_off = 0; -+ int label_iter_max, rc = 0; -+ -+ if (op != LSA_OP_ZERO && buf == NULL) { -+ err(ctx, "%s: LSA buffer cannot be NULL\n", devname); -+ return -EINVAL; -+ } -+ -+ if (length == 0) -+ return 0; -+ -+ label_iter_max = memdev->payload_max - sizeof(struct cxl_cmd_set_lsa); -+ while (remaining) { -+ cur_len = min((size_t)label_iter_max, remaining); -+ rc = __lsa_op(memdev, op, buf + cur_off, -+ cur_len, offset + cur_off); -+ if (rc) -+ break; -+ -+ remaining -= cur_len; -+ cur_off += cur_len; -+ } -+ -+ if (rc && (op == LSA_OP_SET)) -+ err(ctx, "%s: labels may be in an inconsistent state\n", -+ devname); -+ return rc; -+} -+ -+CXL_EXPORT int cxl_memdev_zero_label(struct cxl_memdev *memdev, size_t length, -+ size_t offset) -+{ -+ return lsa_op(memdev, LSA_OP_ZERO, NULL, length, offset); -+} -+ -+CXL_EXPORT int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf, -+ size_t length, size_t offset) -+{ -+ return lsa_op(memdev, LSA_OP_SET, buf, length, offset); -+} -+ -+CXL_EXPORT int cxl_memdev_read_label(struct cxl_memdev *memdev, void *buf, -+ size_t length, size_t offset) -+{ -+ return lsa_op(memdev, LSA_OP_GET, buf, length, offset); -+} -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index f3b0c63..077d104 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -66,6 +66,10 @@ global: - cxl_cmd_read_label_get_payload; - cxl_memdev_get_label_size; - cxl_memdev_nvdimm_bridge_active; -+ cxl_cmd_new_write_label; -+ cxl_memdev_zero_label; -+ cxl_memdev_write_label; -+ cxl_memdev_read_label; - local: - *; - }; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 525c41e..a1b8b50 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -87,6 +87,12 @@ struct cxl_cmd_get_lsa_in { - le32 length; - } __attribute__((packed)); - -+struct cxl_cmd_set_lsa { -+ le32 offset; -+ le32 rsvd; -+ unsigned char lsa_data[0]; -+} __attribute__ ((packed)); -+ - struct cxl_cmd_get_health_info { - u8 health_status; - u8 media_status; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 535e349..89d35ba 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -44,6 +44,12 @@ unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev); - const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev); - size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev); - int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev); -+int cxl_memdev_zero_label(struct cxl_memdev *memdev, size_t length, -+ size_t offset); -+int cxl_memdev_read_label(struct cxl_memdev *memdev, void *buf, size_t length, -+ size_t offset); -+int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf, size_t length, -+ size_t offset); - - #define cxl_memdev_foreach(ctx, memdev) \ - for (memdev = cxl_memdev_get_first(ctx); \ -@@ -101,6 +107,8 @@ struct cxl_cmd *cxl_cmd_new_read_label(struct cxl_memdev *memdev, - unsigned int offset, unsigned int length); - ssize_t cxl_cmd_read_label_get_payload(struct cxl_cmd *cmd, void *buf, - unsigned int length); -+struct cxl_cmd *cxl_cmd_new_write_label(struct cxl_memdev *memdev, -+ void *buf, unsigned int offset, unsigned int length); - - #ifdef __cplusplus - } /* extern "C" */ --- -2.27.0 - diff --git a/SOURCES/0042-cxl-add-commands-to-read-write-and-zero-labels.patch b/SOURCES/0042-cxl-add-commands-to-read-write-and-zero-labels.patch deleted file mode 100644 index b98f75b..0000000 --- a/SOURCES/0042-cxl-add-commands-to-read-write-and-zero-labels.patch +++ /dev/null @@ -1,583 +0,0 @@ -From c415cebe4b5ca50e06db78a4719f312e33106936 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:35 -0600 -Subject: [PATCH 042/217] cxl: add commands to read, write, and zero labels - -Add the following cxl-cli commands: read-labels, write-labels, -zero-labels. They operate on a CXL memdev, or a set of memdevs, and -allow interacting with the label storage area (LSA) on the device. - -Add man pages for the above cxl-cli commands. - -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/Makefile.am | 5 +- - Documentation/cxl/cxl-read-labels.txt | 33 +++ - Documentation/cxl/cxl-write-labels.txt | 32 +++ - Documentation/cxl/cxl-zero-labels.txt | 29 ++ - Documentation/cxl/labels-description.txt | 8 + - Documentation/cxl/labels-options.txt | 17 ++ - Documentation/cxl/memdev-option.txt | 4 + - cxl/Makefile.am | 1 + - cxl/builtin.h | 5 + - cxl/cxl.c | 3 + - cxl/memdev.c | 324 +++++++++++++++++++++++ - 11 files changed, 460 insertions(+), 1 deletion(-) - create mode 100644 Documentation/cxl/cxl-read-labels.txt - create mode 100644 Documentation/cxl/cxl-write-labels.txt - create mode 100644 Documentation/cxl/cxl-zero-labels.txt - create mode 100644 Documentation/cxl/labels-description.txt - create mode 100644 Documentation/cxl/labels-options.txt - create mode 100644 Documentation/cxl/memdev-option.txt - create mode 100644 cxl/memdev.c - -diff --git a/Documentation/cxl/Makefile.am b/Documentation/cxl/Makefile.am -index db98dd7..efabaa3 100644 ---- a/Documentation/cxl/Makefile.am -+++ b/Documentation/cxl/Makefile.am -@@ -19,7 +19,10 @@ endif - - man1_MANS = \ - cxl.1 \ -- cxl-list.1 -+ cxl-list.1 \ -+ cxl-read-labels.1 \ -+ cxl-write-labels.1 \ -+ cxl-zero-labels.1 - - EXTRA_DIST = $(man1_MANS) - -diff --git a/Documentation/cxl/cxl-read-labels.txt b/Documentation/cxl/cxl-read-labels.txt -new file mode 100644 -index 0000000..143f296 ---- /dev/null -+++ b/Documentation/cxl/cxl-read-labels.txt -@@ -0,0 +1,33 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-read-labels(1) -+================== -+ -+NAME -+---- -+cxl-read-labels - read out the label area on a CXL memdev -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl read-labels' [..] [] -+ -+include::labels-description.txt[] -+This command dumps the raw binary data in a memdev's label area to stdout or a -+file. In the multi-memdev case the data is concatenated. -+ -+OPTIONS -+------- -+include::labels-options.txt[] -+ -+-o:: -+--output:: -+ output file -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-write-labels[1], -+linkcxl:cxl-zero-labels[1], -+CXL-2.0 9.13.2 -diff --git a/Documentation/cxl/cxl-write-labels.txt b/Documentation/cxl/cxl-write-labels.txt -new file mode 100644 -index 0000000..75f42a5 ---- /dev/null -+++ b/Documentation/cxl/cxl-write-labels.txt -@@ -0,0 +1,32 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-write-labels(1) -+=================== -+ -+NAME -+---- -+cxl-write-labels - write data to the label area on a memdev -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl write-labels [-i ]' -+ -+include::labels-description.txt[] -+Read data from the input filename, or stdin, and write it to the given -+ device. Note that the device must not be active in any region, or -+actively registered with the nvdimm subsystem. If it is, the kernel will -+not allow write access to the device's label data area. -+ -+OPTIONS -+------- -+include::labels-options.txt[] -+-i:: -+--input:: -+ input file -+ -+SEE ALSO -+-------- -+linkcxl:cxl-read-labels[1], -+linkcxl:cxl-zero-labels[1], -+CXL-2.0 9.13.2 -diff --git a/Documentation/cxl/cxl-zero-labels.txt b/Documentation/cxl/cxl-zero-labels.txt -new file mode 100644 -index 0000000..bf95b24 ---- /dev/null -+++ b/Documentation/cxl/cxl-zero-labels.txt -@@ -0,0 +1,29 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-zero-labels(1) -+================== -+ -+NAME -+---- -+cxl-zero-labels - zero out the label area on a set of memdevs -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl zero-labels' [..] [] -+ -+include::labels-description.txt[] -+This command resets the device to its default state by -+deleting all labels. -+ -+OPTIONS -+------- -+include::labels-options.txt[] -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-read-labels[1], -+linkcxl:cxl-write-labels[1], -+CXL-2.0 9.13.2 -diff --git a/Documentation/cxl/labels-description.txt b/Documentation/cxl/labels-description.txt -new file mode 100644 -index 0000000..f60bd5d ---- /dev/null -+++ b/Documentation/cxl/labels-description.txt -@@ -0,0 +1,8 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+DESCRIPTION -+----------- -+The region label area is a small persistent partition of capacity -+available on some CXL memory devices. The label area is used to -+and configure or determine the set of memory devices participating -+in different interleave sets. -diff --git a/Documentation/cxl/labels-options.txt b/Documentation/cxl/labels-options.txt -new file mode 100644 -index 0000000..06fbac3 ---- /dev/null -+++ b/Documentation/cxl/labels-options.txt -@@ -0,0 +1,17 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+:: -+include::memdev-option.txt[] -+ -+-s:: -+--size=:: -+ Limit the operation to the given number of bytes. A size of 0 -+ indicates to operate over the entire label capacity. -+ -+-O:: -+--offset=:: -+ Begin the operation at the given offset into the label area. -+ -+-v:: -+ Turn on verbose debug messages in the library (if libcxl was built with -+ logging and debug enabled). -diff --git a/Documentation/cxl/memdev-option.txt b/Documentation/cxl/memdev-option.txt -new file mode 100644 -index 0000000..e778582 ---- /dev/null -+++ b/Documentation/cxl/memdev-option.txt -@@ -0,0 +1,4 @@ -+// SPDX-License-Identifier: GPL-2.0 -+A 'memX' device name, or a memdev id number. Restrict the operation to -+the specified memdev(s). The keyword 'all' can be specified to indicate -+the lack of any restriction. -diff --git a/cxl/Makefile.am b/cxl/Makefile.am -index 98606b9..da9f91d 100644 ---- a/cxl/Makefile.am -+++ b/cxl/Makefile.am -@@ -10,6 +10,7 @@ config.h: $(srcdir)/Makefile.am - cxl_SOURCES =\ - cxl.c \ - list.c \ -+ memdev.c \ - ../util/json.c \ - builtin.h - -diff --git a/cxl/builtin.h b/cxl/builtin.h -index 3797f98..78eca6e 100644 ---- a/cxl/builtin.h -+++ b/cxl/builtin.h -@@ -5,4 +5,9 @@ - - struct cxl_ctx; - int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_write_labels(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_read_labels(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_zero_labels(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_init_labels(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_check_labels(int argc, const char **argv, struct cxl_ctx *ctx); - #endif /* _CXL_BUILTIN_H_ */ -diff --git a/cxl/cxl.c b/cxl/cxl.c -index a7725f8..4b1661d 100644 ---- a/cxl/cxl.c -+++ b/cxl/cxl.c -@@ -61,6 +61,9 @@ static struct cmd_struct commands[] = { - { "version", .c_fn = cmd_version }, - { "list", .c_fn = cmd_list }, - { "help", .c_fn = cmd_help }, -+ { "zero-labels", .c_fn = cmd_zero_labels }, -+ { "read-labels", .c_fn = cmd_read_labels }, -+ { "write-labels", .c_fn = cmd_write_labels }, - }; - - int main(int argc, const char **argv) -diff --git a/cxl/memdev.c b/cxl/memdev.c -new file mode 100644 -index 0000000..5ee38e5 ---- /dev/null -+++ b/cxl/memdev.c -@@ -0,0 +1,324 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* Copyright (C) 2020-2021 Intel Corporation. All rights reserved. */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct action_context { -+ FILE *f_out; -+ FILE *f_in; -+}; -+ -+static struct parameters { -+ const char *outfile; -+ const char *infile; -+ unsigned len; -+ unsigned offset; -+ bool verbose; -+} param; -+ -+#define fail(fmt, ...) \ -+do { \ -+ fprintf(stderr, "cxl-%s:%s:%d: " fmt, \ -+ VERSION, __func__, __LINE__, ##__VA_ARGS__); \ -+} while (0) -+ -+#define BASE_OPTIONS() \ -+OPT_BOOLEAN('v',"verbose", ¶m.verbose, "turn on debug") -+ -+#define READ_OPTIONS() \ -+OPT_STRING('o', "output", ¶m.outfile, "output-file", \ -+ "filename to write label area contents") -+ -+#define WRITE_OPTIONS() \ -+OPT_STRING('i', "input", ¶m.infile, "input-file", \ -+ "filename to read label area data") -+ -+#define LABEL_OPTIONS() \ -+OPT_UINTEGER('s', "size", ¶m.len, "number of label bytes to operate"), \ -+OPT_UINTEGER('O', "offset", ¶m.offset, \ -+ "offset into the label area to start operation") -+ -+static const struct option read_options[] = { -+ BASE_OPTIONS(), -+ LABEL_OPTIONS(), -+ READ_OPTIONS(), -+ OPT_END(), -+}; -+ -+static const struct option write_options[] = { -+ BASE_OPTIONS(), -+ LABEL_OPTIONS(), -+ WRITE_OPTIONS(), -+ OPT_END(), -+}; -+ -+static const struct option zero_options[] = { -+ BASE_OPTIONS(), -+ LABEL_OPTIONS(), -+ OPT_END(), -+}; -+ -+static int action_zero(struct cxl_memdev *memdev, struct action_context *actx) -+{ -+ size_t size; -+ int rc; -+ -+ if (param.len) -+ size = param.len; -+ else -+ size = cxl_memdev_get_label_size(memdev); -+ -+ if (cxl_memdev_nvdimm_bridge_active(memdev)) { -+ fprintf(stderr, -+ "%s: has active nvdimm bridge, abort label write\n", -+ cxl_memdev_get_devname(memdev)); -+ return -EBUSY; -+ } -+ -+ rc = cxl_memdev_zero_label(memdev, size, param.offset); -+ if (rc < 0) -+ fprintf(stderr, "%s: label zeroing failed: %s\n", -+ cxl_memdev_get_devname(memdev), strerror(-rc)); -+ -+ return rc; -+} -+ -+static int action_write(struct cxl_memdev *memdev, struct action_context *actx) -+{ -+ size_t size = param.len, read_len; -+ unsigned char *buf; -+ int rc; -+ -+ if (cxl_memdev_nvdimm_bridge_active(memdev)) { -+ fprintf(stderr, -+ "%s: has active nvdimm bridge, abort label write\n", -+ cxl_memdev_get_devname(memdev)); -+ return -EBUSY; -+ } -+ -+ if (!size) { -+ size_t label_size = cxl_memdev_get_label_size(memdev); -+ -+ fseek(actx->f_in, 0L, SEEK_END); -+ size = ftell(actx->f_in); -+ fseek(actx->f_in, 0L, SEEK_SET); -+ -+ if (size > label_size) { -+ fprintf(stderr, -+ "File size (%zu) greater than label area size (%zu), aborting\n", -+ size, label_size); -+ return -EINVAL; -+ } -+ } -+ -+ buf = calloc(1, size); -+ if (!buf) -+ return -ENOMEM; -+ -+ read_len = fread(buf, 1, size, actx->f_in); -+ if (read_len != size) { -+ rc = -ENXIO; -+ goto out; -+ } -+ -+ rc = cxl_memdev_write_label(memdev, buf, size, param.offset); -+ if (rc < 0) -+ fprintf(stderr, "%s: label write failed: %s\n", -+ cxl_memdev_get_devname(memdev), strerror(-rc)); -+ -+out: -+ free(buf); -+ return rc; -+} -+ -+static int action_read(struct cxl_memdev *memdev, struct action_context *actx) -+{ -+ size_t size, write_len; -+ char *buf; -+ int rc; -+ -+ if (param.len) -+ size = param.len; -+ else -+ size = cxl_memdev_get_label_size(memdev); -+ -+ buf = calloc(1, size); -+ if (!buf) -+ return -ENOMEM; -+ -+ rc = cxl_memdev_read_label(memdev, buf, size, param.offset); -+ if (rc < 0) { -+ fprintf(stderr, "%s: label read failed: %s\n", -+ cxl_memdev_get_devname(memdev), strerror(-rc)); -+ goto out; -+ } -+ -+ write_len = fwrite(buf, 1, size, actx->f_out); -+ if (write_len != size) { -+ rc = -ENXIO; -+ goto out; -+ } -+ fflush(actx->f_out); -+ -+out: -+ free(buf); -+ return rc; -+} -+ -+static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, -+ int (*action)(struct cxl_memdev *memdev, struct action_context *actx), -+ const struct option *options, const char *usage) -+{ -+ struct cxl_memdev *memdev, *single = NULL; -+ struct action_context actx = { 0 }; -+ int i, rc = 0, count = 0, err = 0; -+ const char * const u[] = { -+ usage, -+ NULL -+ }; -+ unsigned long id; -+ -+ argc = parse_options(argc, argv, options, u, 0); -+ -+ if (argc == 0) -+ usage_with_options(u, options); -+ for (i = 0; i < argc; i++) { -+ if (strcmp(argv[i], "all") == 0) { -+ argv[0] = "all"; -+ argc = 1; -+ break; -+ } -+ -+ if (sscanf(argv[i], "mem%lu", &id) != 1) { -+ fprintf(stderr, "'%s' is not a valid memdev name\n", -+ argv[i]); -+ err++; -+ } -+ } -+ -+ if (err == argc) { -+ usage_with_options(u, options); -+ return -EINVAL; -+ } -+ -+ if (!param.outfile) -+ actx.f_out = stdout; -+ else { -+ actx.f_out = fopen(param.outfile, "w+"); -+ if (!actx.f_out) { -+ fprintf(stderr, "failed to open: %s: (%s)\n", -+ param.outfile, strerror(errno)); -+ rc = -errno; -+ goto out; -+ } -+ } -+ -+ if (!param.infile) { -+ actx.f_in = stdin; -+ } else { -+ actx.f_in = fopen(param.infile, "r"); -+ if (!actx.f_in) { -+ fprintf(stderr, "failed to open: %s: (%s)\n", -+ param.infile, strerror(errno)); -+ rc = -errno; -+ goto out_close_fout; -+ } -+ } -+ -+ if (param.verbose) -+ cxl_set_log_priority(ctx, LOG_DEBUG); -+ -+ rc = 0; -+ err = 0; -+ count = 0; -+ -+ for (i = 0; i < argc; i++) { -+ if (sscanf(argv[i], "mem%lu", &id) != 1 -+ && strcmp(argv[i], "all") != 0) -+ continue; -+ -+ cxl_memdev_foreach (ctx, memdev) { -+ if (!util_cxl_memdev_filter(memdev, argv[i])) -+ continue; -+ -+ if (action == action_write) { -+ single = memdev; -+ rc = 0; -+ } else -+ rc = action(memdev, &actx); -+ -+ if (rc == 0) -+ count++; -+ else if (rc && !err) -+ err = rc; -+ } -+ } -+ rc = err; -+ -+ if (action == action_write) { -+ if (count > 1) { -+ error("write-labels only supports writing a single memdev\n"); -+ usage_with_options(u, options); -+ return -EINVAL; -+ } else if (single) { -+ rc = action(single, &actx); -+ if (rc) -+ count = 0; -+ } -+ } -+ -+ if (actx.f_in != stdin) -+ fclose(actx.f_in); -+ -+ out_close_fout: -+ if (actx.f_out != stdout) -+ fclose(actx.f_out); -+ -+ out: -+ /* -+ * count if some actions succeeded, 0 if none were attempted, -+ * negative error code otherwise. -+ */ -+ if (count > 0) -+ return count; -+ return rc; -+} -+ -+int cmd_write_labels(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ int count = memdev_action(argc, argv, ctx, action_write, write_options, -+ "cxl write-labels [-i ]"); -+ -+ fprintf(stderr, "wrote %d mem%s\n", count >= 0 ? count : 0, -+ count > 1 ? "s" : ""); -+ return count >= 0 ? 0 : EXIT_FAILURE; -+} -+ -+int cmd_read_labels(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ int count = memdev_action(argc, argv, ctx, action_read, read_options, -+ "cxl read-labels [..] [-o ]"); -+ -+ fprintf(stderr, "read %d mem%s\n", count >= 0 ? count : 0, -+ count > 1 ? "s" : ""); -+ return count >= 0 ? 0 : EXIT_FAILURE; -+} -+ -+int cmd_zero_labels(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ int count = memdev_action(argc, argv, ctx, action_zero, zero_options, -+ "cxl zero-labels [..] []"); -+ -+ fprintf(stderr, "zeroed %d mem%s\n", count >= 0 ? count : 0, -+ count > 1 ? "s" : ""); -+ return count >= 0 ? 0 : EXIT_FAILURE; -+} --- -2.27.0 - diff --git a/SOURCES/0043-Documentation-cxl-add-library-API-documentation.patch b/SOURCES/0043-Documentation-cxl-add-library-API-documentation.patch deleted file mode 100644 index 4645a63..0000000 --- a/SOURCES/0043-Documentation-cxl-add-library-API-documentation.patch +++ /dev/null @@ -1,248 +0,0 @@ -From 62fe17528d362110e258d56d8a2f44f2798f3f45 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:36 -0600 -Subject: [PATCH 043/217] Documentation/cxl: add library API documentation - -Add library API documentation for libcxl(3) using the existing -asciidoc(tor) build system. Add a section 3 man page for 'libcxl' that -provides an overview of the library and its usage, and a man page for -the 'cxl_new()' API. - -Cc: Ben Widawsky -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .gitignore | 3 ++ - Documentation/cxl/lib/Makefile.am | 58 +++++++++++++++++++++++++++++++ - Documentation/cxl/lib/cxl_new.txt | 43 +++++++++++++++++++++++ - Documentation/cxl/lib/libcxl.txt | 56 +++++++++++++++++++++++++++++ - Makefile.am | 1 + - configure.ac | 1 + - 6 files changed, 162 insertions(+) - create mode 100644 Documentation/cxl/lib/Makefile.am - create mode 100644 Documentation/cxl/lib/cxl_new.txt - create mode 100644 Documentation/cxl/lib/libcxl.txt - -diff --git a/.gitignore b/.gitignore -index 6a97b92..6468c7a 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -14,12 +14,15 @@ Makefile.in - /libtool - /stamp-h1 - *.1 -+*.3 - Documentation/daxctl/asciidoc.conf - Documentation/ndctl/asciidoc.conf - Documentation/cxl/asciidoc.conf -+Documentation/cxl/lib/asciidoc.conf - Documentation/daxctl/asciidoctor-extensions.rb - Documentation/ndctl/asciidoctor-extensions.rb - Documentation/cxl/asciidoctor-extensions.rb -+Documentation/cxl/lib/asciidoctor-extensions.rb - Documentation/ndctl/attrs.adoc - .dirstamp - daxctl/config.h -diff --git a/Documentation/cxl/lib/Makefile.am b/Documentation/cxl/lib/Makefile.am -new file mode 100644 -index 0000000..41e3a5f ---- /dev/null -+++ b/Documentation/cxl/lib/Makefile.am -@@ -0,0 +1,58 @@ -+# SPDX-License-Identifier: GPL-2.0 -+# Copyright (C) 2020-2021 Intel Corporation. All rights reserved. -+ -+if USE_ASCIIDOCTOR -+ -+do_subst = sed -e 's,@Utility@,Libcxl,g' -e's,@utility@,libcxl,g' -+CONFFILE = asciidoctor-extensions.rb -+asciidoctor-extensions.rb: ../../asciidoctor-extensions.rb.in -+ $(AM_V_GEN) $(do_subst) < $< > $@ -+ -+else -+ -+do_subst = sed -e 's,UTILITY,libcxl,g' -+CONFFILE = asciidoc.conf -+asciidoc.conf: ../../asciidoc.conf.in -+ $(AM_V_GEN) $(do_subst) < $< > $@ -+ -+endif -+ -+man3_MANS = \ -+ libcxl.3 \ -+ cxl_new.3 -+ -+EXTRA_DIST = $(man3_MANS) -+ -+CLEANFILES = $(man3_MANS) -+ -+XML_DEPS = \ -+ ../../../version.m4 \ -+ ../../copyright.txt \ -+ Makefile \ -+ $(CONFFILE) -+ -+RM ?= rm -f -+ -+if USE_ASCIIDOCTOR -+ -+%.3: %.txt $(XML_DEPS) -+ $(AM_V_GEN)$(RM) $@+ $@ && \ -+ $(ASCIIDOC) -b manpage -d manpage -acompat-mode \ -+ -I. -rasciidoctor-extensions \ -+ -amansource=libcxl -amanmanual="libcxl Manual" \ -+ -andctl_version=$(VERSION) -o $@+ $< && \ -+ mv $@+ $@ -+ -+else -+ -+%.xml: %.txt $(XML_DEPS) -+ $(AM_V_GEN)$(RM) $@+ $@ && \ -+ $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \ -+ --unsafe -alibcxl_version=$(VERSION) -o $@+ $< && \ -+ mv $@+ $@ -+ -+%.3: %.xml $(XML_DEPS) -+ $(AM_V_GEN)$(RM) $@ && \ -+ $(XMLTO) -o . -m ../../manpage-normal.xsl man $< -+ -+endif -diff --git a/Documentation/cxl/lib/cxl_new.txt b/Documentation/cxl/lib/cxl_new.txt -new file mode 100644 -index 0000000..147d4e0 ---- /dev/null -+++ b/Documentation/cxl/lib/cxl_new.txt -@@ -0,0 +1,43 @@ -+// SPDX-License-Identifier: LGPL-2.0 -+ -+cxl_new(3) -+========== -+ -+NAME -+---- -+cxl_new - Create a new library context object that acts as a handle for all -+library operations -+ -+SYNOPSIS -+-------- -+[verse] -+---- -+#include -+ -+int cxl_new(struct cxl_ctx **ctx); -+---- -+ -+DESCRIPTION -+----------- -+Instantiates a new library context, and stores an opaque pointer in ctx. The -+context is freed by linklibcxl:cxl_unref[3], i.e. cxl_new(3) implies an -+internal linklibcxl:cxl_ref[3]. -+ -+ -+RETURN VALUE -+------------ -+Returns 0 on success, and a negative errno on failure. -+Possible error codes are: -+ -+ * -ENOMEM -+ * -ENXIO -+ -+EXAMPLE -+------- -+See example usage in test/libcxl.c -+ -+include::../../copyright.txt[] -+ -+SEE ALSO -+-------- -+linklibcxl:cxl_ref[3], linklibcxl:cxl_unref[3] -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -new file mode 100644 -index 0000000..2539369 ---- /dev/null -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -0,0 +1,56 @@ -+// SPDX-License-Identifier: LGPL-2.0 -+ -+libcxl(3) -+========= -+ -+NAME -+---- -+libcxl - A library to interact with CXL devices through sysfs(5) -+and ioctl(2) interfaces -+ -+SYNOPSIS -+-------- -+[verse] -+#include -+cc ... -lcxl -+ -+DESCRIPTION -+----------- -+libcxl provides interfaces to interact with CXL devices in Linux, using sysfs -+interfaces for most kernel interactions, and the ioctl() interface for command -+submission. -+ -+The starting point for all library interfaces is a 'cxl_ctx' object, returned -+by linklibcxl:cxl_new[3]. CXL 'Type 3' memory devices are children of the -+cxl_ctx object, and can be iterated through using an iterator API. -+ -+Library level interfaces that are agnostic to any device, or a specific -+subclass of operations have the prefix 'cxl_' -+ -+The object representing a CXL Type 3 device is 'cxl_memdev'. Library interfaces -+related to these devices have the prefix 'cxl_memdev_'. These interfaces are -+mostly associated with sysfs interactions (unless otherwise noted in their -+respective documentation pages). They are typically used to retrieve data -+published by the kernel, or to send data or trigger kernel operations for a -+given device. -+ -+A 'cxl_cmd' is a reference counted object which is used to perform 'Mailbox' -+commands as described in the CXL Specification. A 'cxl_cmd' object is tied to a -+'cxl_memdev'. Associated library interfaces have the prefix 'cxl_cmd_'. Within -+this sub-class of interfaces, there are: -+ -+ * 'cxl_cmd_new_*' interfaces that allocate a new cxl_cmd object for a given -+ command type. -+ -+ * 'cxl_cmd_submit' which submits the command via ioctl() -+ -+ * 'cxl_cmd__get_' interfaces that get specific fields out of the -+ command response -+ -+ * 'cxl_cmd_get_*' interfaces to get general command related information. -+ -+include::../../copyright.txt[] -+ -+SEE ALSO -+-------- -+linklibcxl:cxl[1] -diff --git a/Makefile.am b/Makefile.am -index 4904ee7..e2f6bef 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -4,6 +4,7 @@ ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} - SUBDIRS = . cxl/lib daxctl/lib ndctl/lib cxl ndctl daxctl - if ENABLE_DOCS - SUBDIRS += Documentation/ndctl Documentation/daxctl Documentation/cxl -+SUBDIRS += Documentation/cxl/lib - endif - SUBDIRS += test - -diff --git a/configure.ac b/configure.ac -index dadae0a..00497ae 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -231,6 +231,7 @@ AC_CONFIG_FILES([ - Documentation/ndctl/Makefile - Documentation/daxctl/Makefile - Documentation/cxl/Makefile -+ Documentation/cxl/lib/Makefile - ]) - - AC_OUTPUT --- -2.27.0 - diff --git a/SOURCES/0044-ndctl-Add-CXL-packages-to-the-RPM-spec.patch b/SOURCES/0044-ndctl-Add-CXL-packages-to-the-RPM-spec.patch deleted file mode 100644 index 89de3d6..0000000 --- a/SOURCES/0044-ndctl-Add-CXL-packages-to-the-RPM-spec.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 57b1484fa427228afd52cdfa4fa3916a7a5878bf Mon Sep 17 00:00:00 2001 -From: Ira Weiny -Date: Thu, 7 Oct 2021 02:21:37 -0600 -Subject: [PATCH 044/217] ndctl: Add CXL packages to the RPM spec - -Add CXL related packages - the cxl-cli utility, the libcxl library, and -development headers to respective RPM packages in the main spec file. - -Reviewed-by: Dan Williams -Signed-off-by: Ira Weiny -Signed-off-by: Vishal Verma ---- - Makefile.am | 4 ++++ - ndctl.spec.in | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 53 insertions(+) - -diff --git a/Makefile.am b/Makefile.am -index e2f6bef..fa2010a 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -23,17 +23,21 @@ CLEANFILES += $(noinst_SCRIPTS) - - do_rhel_subst = sed -e 's,VERSION,$(VERSION),g' \ - -e 's,DAX_DNAME,daxctl-devel,g' \ -+ -e 's,CXL_DNAME,cxl-devel,g' \ - -e 's,DNAME,ndctl-devel,g' \ - -e '/^%defattr.*/d' \ - -e 's,DAX_LNAME,daxctl-libs,g' \ -+ -e 's,CXL_LNAME,cxl-libs,g' \ - -e 's,LNAME,ndctl-libs,g' - - do_sles_subst = sed -e 's,VERSION,$(VERSION),g' \ - -e 's,DAX_DNAME,libdaxctl-devel,g' \ -+ -e 's,CXL_DNAME,libcxl-devel,g' \ - -e 's,DNAME,libndctl-devel,g' \ - -e 's,%license,%doc,g' \ - -e 's,\(^License:.*GPL\)v2,\1-2.0,g' \ - -e "s,DAX_LNAME,libdaxctl$$(($(LIBDAXCTL_CURRENT) - $(LIBDAXCTL_AGE))),g" \ -+ -e "s,CXL_LNAME,libcxl$$(($(LIBCXL_CURRENT) - $(LIBCXL_AGE))),g" \ - -e "s,LNAME,libndctl$$(($(LIBNDCTL_CURRENT) - $(LIBNDCTL_AGE))),g" - - rhel/ndctl.spec: ndctl.spec.in Makefile.am version.m4 -diff --git a/ndctl.spec.in b/ndctl.spec.in -index 0563b2d..4b08c05 100644 ---- a/ndctl.spec.in -+++ b/ndctl.spec.in -@@ -8,6 +8,7 @@ Source0: https://github.com/pmem/%{name}/archive/v%{version}.tar.gz#/%{name}-%{v - - Requires: LNAME%{?_isa} = %{version}-%{release} - Requires: DAX_LNAME%{?_isa} = %{version}-%{release} -+Requires: CXL_LNAME%{?_isa} = %{version}-%{release} - BuildRequires: autoconf - %if 0%{?rhel} < 9 - BuildRequires: asciidoc -@@ -54,6 +55,24 @@ the Linux kernel Device-DAX facility. This facility enables DAX mappings - of performance / feature differentiated memory without need of a - filesystem. - -+%package -n cxl-cli -+Summary: Manage CXL devices -+License: GPLv2 -+Requires: CXL_LNAME%{?_isa} = %{version}-%{release} -+ -+%description -n cxl-cli -+The cxl utility provides enumeration and provisioning commands for -+the Linux kernel CXL devices. -+ -+%package -n CXL_DNAME -+Summary: Development files for libcxl -+License: LGPLv2 -+Requires: CXL_LNAME%{?_isa} = %{version}-%{release} -+ -+%description -n CXL_DNAME -+This package contains libraries and header files for developing applications -+that use libcxl, a library for enumerating and communicating with CXL devices. -+ - %package -n DAX_DNAME - Summary: Development files for libdaxctl - License: LGPLv2 -@@ -84,6 +103,13 @@ Device DAX is a facility for establishing DAX mappings of performance / - feature-differentiated memory. DAX_LNAME provides an enumeration / - control API for these devices. - -+%package -n CXL_LNAME -+Summary: Management library for CXL devices -+License: LGPLv2 -+ -+%description -n CXL_LNAME -+libcxl is a library for enumerating and communicating with CXL devices. -+ - - %prep - %setup -q ndctl-%{version} -@@ -105,6 +131,8 @@ make check - - %ldconfig_scriptlets -n DAX_LNAME - -+%ldconfig_scriptlets -n CXL_LNAME -+ - %define bashcompdir %(pkg-config --variable=completionsdir bash-completion) - - %files -@@ -126,6 +154,12 @@ make check - %{_mandir}/man1/daxctl* - %{_datadir}/daxctl/daxctl.conf - -+%files -n cxl-cli -+%defattr(-,root,root) -+%license LICENSES/preferred/GPL-2.0 LICENSES/other/MIT LICENSES/other/CC0-1.0 -+%{_bindir}/cxl -+%{_mandir}/man1/cxl* -+ - %files -n LNAME - %defattr(-,root,root) - %doc README.md -@@ -138,6 +172,12 @@ make check - %license LICENSES/preferred/LGPL-2.1 LICENSES/other/MIT LICENSES/other/CC0-1.0 - %{_libdir}/libdaxctl.so.* - -+%files -n CXL_LNAME -+%defattr(-,root,root) -+%doc README.md -+%license LICENSES/preferred/LGPL-2.1 LICENSES/other/MIT LICENSES/other/CC0-1.0 -+%{_libdir}/libcxl.so.* -+ - %files -n DNAME - %defattr(-,root,root) - %license LICENSES/preferred/LGPL-2.1 -@@ -152,6 +192,15 @@ make check - %{_libdir}/libdaxctl.so - %{_libdir}/pkgconfig/libdaxctl.pc - -+%files -n CXL_DNAME -+%defattr(-,root,root) -+%license LICENSES/preferred/LGPL-2.1 -+%{_includedir}/cxl/ -+%{_libdir}/libcxl.so -+%{_libdir}/pkgconfig/libcxl.pc -+%{_mandir}/man3/cxl* -+%{_mandir}/man3/libcxl.3.gz -+ - - %changelog - * Fri May 27 2016 Dan Williams - 53-1 --- -2.27.0 - diff --git a/SOURCES/0045-cxl-cli-add-bash-completion.patch b/SOURCES/0045-cxl-cli-add-bash-completion.patch deleted file mode 100644 index a99e567..0000000 --- a/SOURCES/0045-cxl-cli-add-bash-completion.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 02c40b971bd4d092b3612fcb5e9ddd57548e6dbb Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:38 -0600 -Subject: [PATCH 045/217] cxl-cli: add bash completion - -Add bash completion for the cxl-cli commands implemented so far: - cxl-list - cxl-read-labels - cxl-write-labels - cxl-zero-labels - -Acked-by: Dan Williams -Signed-off-by: Vishal Verma ---- - contrib/ndctl | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 109 insertions(+) - -diff --git a/contrib/ndctl b/contrib/ndctl -index 680fe6a..cae4b1b 100755 ---- a/contrib/ndctl -+++ b/contrib/ndctl -@@ -647,5 +647,114 @@ _daxctl() - __daxctl_main - } - -+### cxl-cli ### -+ -+__cxl_get_devs() -+{ -+ local opts=("--memdevs" "$*") -+ cxl list "${opts[@]}" | grep -E "^\s*\"memdev\":" | cut -d'"' -f4 -+} -+ -+__cxlcomp() -+{ -+ local i=0 -+ -+ COMPREPLY=( $( compgen -W "$1" -- "$2" ) ) -+ for cword in "${COMPREPLY[@]}"; do -+ if [[ "$cword" == @(--memdev|--offset|--size|--input|--output) ]]; then -+ COMPREPLY[$i]="${cword}=" -+ else -+ COMPREPLY[$i]="${cword} " -+ fi -+ ((i++)) -+ done -+} -+ -+__cxl_comp_options() -+{ -+ -+ local cur=$1 -+ local opts -+ -+ if [[ "$cur" == *=* ]]; then -+ local cur_subopt=${cur%%=*} -+ local cur_arg=${cur##*=} -+ case $cur_subopt in -+ --memdev) -+ opts="$(__cxl_get_devs -i)" -+ ;; -+ *) -+ return -+ ;; -+ esac -+ __cxlcomp "$opts" "$cur_arg" -+ fi -+} -+ -+__cxl_comp_non_option_args() -+{ -+ local subcmd=$1 -+ local cur=$2 -+ local opts -+ -+ case $subcmd in -+ read-labels) -+ ;& -+ write-labels) -+ ;& -+ zero-labels) -+ opts="$(__cxl_get_devs -i) all" -+ ;; -+ *) -+ return -+ ;; -+ esac -+ __cxlcomp "$opts" "$cur" -+} -+ -+__cxl_main() -+{ -+ local cmd subcmd -+ -+ cmd=${words[0]} -+ COMPREPLY=() -+ -+ # Skip options backward and find the last cxl command -+ __nd_common_prev_skip_opts -+ subcmd=$prev_skip_opts -+ # List cxl subcommands or long options -+ if [ -z $subcmd ]; then -+ if [[ $cur == --* ]]; then -+ cmds="--version --help --list-cmds" -+ else -+ cmds=$($cmd --list-cmds) -+ fi -+ __cxlcomp "$cmds" "$cur" -+ else -+ # List long option names -+ if [[ $cur == --* ]]; then -+ opts=$($cmd $subcmd --list-opts) -+ __cxlcomp "$opts" "$cur" -+ __cxl_comp_options "$cur" -+ else -+ [ -z "$subcmd" ] && return -+ __cxl_comp_non_option_args "$subcmd" "$cur" -+ fi -+ fi -+} -+ -+type cxl &>/dev/null && -+_cxl() -+{ -+ local cur words cword prev -+ if [ $preload_get_comp_words_by_ref = "true" ]; then -+ _get_comp_words_by_ref -n =: cur words cword prev -+ else -+ __nd_common_get_comp_words_by_ref -n =: cur words cword prev -+ fi -+ __cxl_main -+} -+ - complete -o nospace -F _ndctl ndctl - complete -o nospace -F _daxctl daxctl -+complete -o nospace -F _cxl cxl --- -2.27.0 - diff --git a/SOURCES/0046-cxl-add-health-information-to-cxl-list.patch b/SOURCES/0046-cxl-add-health-information-to-cxl-list.patch deleted file mode 100644 index 1bd79bb..0000000 --- a/SOURCES/0046-cxl-add-health-information-to-cxl-list.patch +++ /dev/null @@ -1,308 +0,0 @@ -From f5d1e2133c54c1f420a0c3cf45fa633f097823be Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 7 Oct 2021 02:21:39 -0600 -Subject: [PATCH 046/217] cxl: add health information to cxl-list - -Add JSON output for fields from the 'GET_HEALTH_INFO' mailbox command -to memory device listings. - -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 38 +++++++ - cxl/list.c | 5 + - util/json.c | 179 +++++++++++++++++++++++++++++++++ - util/json.h | 1 + - 4 files changed, 223 insertions(+) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 370d5b8..c8d10fb 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -48,6 +48,44 @@ OPTIONS - --idle:: - Include idle (not enabled / zero-sized) devices in the listing - -+-H:: -+--health:: -+ Include health information in the memdev listing. Example listing: -+---- -+# cxl list -m mem0 -H -+[ -+ { -+ "memdev":"mem0", -+ "pmem_size":268435456, -+ "ram_size":268435456, -+ "health":{ -+ "maintenance_needed":true, -+ "performance_degraded":true, -+ "hw_replacement_needed":true, -+ "media_normal":false, -+ "media_not_ready":false, -+ "media_persistence_lost":false, -+ "media_data_lost":true, -+ "media_powerloss_persistence_loss":false, -+ "media_shutdown_persistence_loss":false, -+ "media_persistence_loss_imminent":false, -+ "media_powerloss_data_loss":false, -+ "media_shutdown_data_loss":false, -+ "media_data_loss_imminent":false, -+ "ext_life_used":"normal", -+ "ext_temperature":"critical", -+ "ext_corrected_volatile":"warning", -+ "ext_corrected_persistent":"normal", -+ "life_used_percent":15, -+ "temperature":25, -+ "dirty_shutdowns":10, -+ "volatile_errors":20, -+ "pmem_errors":30 -+ } -+ } -+] -+---- -+ - include::human-option.txt[] - - include::verbose-option.txt[] -diff --git a/cxl/list.c b/cxl/list.c -index 043d20c..b1468b7 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -16,6 +16,7 @@ static struct { - bool memdevs; - bool idle; - bool human; -+ bool health; - } list; - - static unsigned long listopts_to_flags(void) -@@ -26,6 +27,8 @@ static unsigned long listopts_to_flags(void) - flags |= UTIL_JSON_IDLE; - if (list.human) - flags |= UTIL_JSON_HUMAN; -+ if (list.health) -+ flags |= UTIL_JSON_HEALTH; - return flags; - } - -@@ -57,6 +60,8 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - OPT_BOOLEAN('i', "idle", &list.idle, "include idle devices"), - OPT_BOOLEAN('u', "human", &list.human, - "use human friendly number formats "), -+ OPT_BOOLEAN('H', "health", &list.health, -+ "include memory device health information "), - OPT_END(), - }; - const char * const u[] = { -diff --git a/util/json.c b/util/json.c -index 3be3a92..f97cf07 100644 ---- a/util/json.c -+++ b/util/json.c -@@ -1442,6 +1442,180 @@ struct json_object *util_badblock_rec_to_json(u64 block, u64 count, - return NULL; - } - -+static struct json_object *util_cxl_memdev_health_to_json( -+ struct cxl_memdev *memdev, unsigned long flags) -+{ -+ struct json_object *jhealth; -+ struct json_object *jobj; -+ struct cxl_cmd *cmd; -+ u32 field; -+ int rc; -+ -+ jhealth = json_object_new_object(); -+ if (!jhealth) -+ return NULL; -+ if (!memdev) -+ goto err_jobj; -+ -+ cmd = cxl_cmd_new_get_health_info(memdev); -+ if (!cmd) -+ goto err_jobj; -+ -+ rc = cxl_cmd_submit(cmd); -+ if (rc < 0) -+ goto err_cmd; -+ rc = cxl_cmd_get_mbox_status(cmd); -+ if (rc != 0) -+ goto err_cmd; -+ -+ /* health_status fields */ -+ rc = cxl_cmd_health_info_get_maintenance_needed(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "maintenance_needed", jobj); -+ -+ rc = cxl_cmd_health_info_get_performance_degraded(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "performance_degraded", jobj); -+ -+ rc = cxl_cmd_health_info_get_hw_replacement_needed(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "hw_replacement_needed", jobj); -+ -+ /* media_status fields */ -+ rc = cxl_cmd_health_info_get_media_normal(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_normal", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_not_ready(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_not_ready", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_persistence_lost(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_persistence_lost", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_data_lost(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_data_lost", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_powerloss_persistence_loss(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_powerloss_persistence_loss", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_shutdown_persistence_loss(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_shutdown_persistence_loss", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_persistence_loss_imminent(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_persistence_loss_imminent", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_powerloss_data_loss(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_powerloss_data_loss", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_shutdown_data_loss(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_shutdown_data_loss", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_data_loss_imminent(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_data_loss_imminent", jobj); -+ -+ /* ext_status fields */ -+ if (cxl_cmd_health_info_get_ext_life_used_normal(cmd)) -+ jobj = json_object_new_string("normal"); -+ else if (cxl_cmd_health_info_get_ext_life_used_warning(cmd)) -+ jobj = json_object_new_string("warning"); -+ else if (cxl_cmd_health_info_get_ext_life_used_critical(cmd)) -+ jobj = json_object_new_string("critical"); -+ else -+ jobj = json_object_new_string("unknown"); -+ if (jobj) -+ json_object_object_add(jhealth, "ext_life_used", jobj); -+ -+ if (cxl_cmd_health_info_get_ext_temperature_normal(cmd)) -+ jobj = json_object_new_string("normal"); -+ else if (cxl_cmd_health_info_get_ext_temperature_warning(cmd)) -+ jobj = json_object_new_string("warning"); -+ else if (cxl_cmd_health_info_get_ext_temperature_critical(cmd)) -+ jobj = json_object_new_string("critical"); -+ else -+ jobj = json_object_new_string("unknown"); -+ if (jobj) -+ json_object_object_add(jhealth, "ext_temperature", jobj); -+ -+ if (cxl_cmd_health_info_get_ext_corrected_volatile_normal(cmd)) -+ jobj = json_object_new_string("normal"); -+ else if (cxl_cmd_health_info_get_ext_corrected_volatile_warning(cmd)) -+ jobj = json_object_new_string("warning"); -+ else -+ jobj = json_object_new_string("unknown"); -+ if (jobj) -+ json_object_object_add(jhealth, "ext_corrected_volatile", jobj); -+ -+ if (cxl_cmd_health_info_get_ext_corrected_persistent_normal(cmd)) -+ jobj = json_object_new_string("normal"); -+ else if (cxl_cmd_health_info_get_ext_corrected_persistent_warning(cmd)) -+ jobj = json_object_new_string("warning"); -+ else -+ jobj = json_object_new_string("unknown"); -+ if (jobj) -+ json_object_object_add(jhealth, "ext_corrected_persistent", jobj); -+ -+ /* other fields */ -+ field = cxl_cmd_health_info_get_life_used(cmd); -+ if (field != 0xff) { -+ jobj = json_object_new_int(field); -+ if (jobj) -+ json_object_object_add(jhealth, "life_used_percent", jobj); -+ } -+ -+ field = cxl_cmd_health_info_get_temperature(cmd); -+ if (field != 0xffff) { -+ jobj = json_object_new_int(field); -+ if (jobj) -+ json_object_object_add(jhealth, "temperature", jobj); -+ } -+ -+ field = cxl_cmd_health_info_get_dirty_shutdowns(cmd); -+ jobj = json_object_new_int64(field); -+ if (jobj) -+ json_object_object_add(jhealth, "dirty_shutdowns", jobj); -+ -+ field = cxl_cmd_health_info_get_volatile_errors(cmd); -+ jobj = json_object_new_int64(field); -+ if (jobj) -+ json_object_object_add(jhealth, "volatile_errors", jobj); -+ -+ field = cxl_cmd_health_info_get_pmem_errors(cmd); -+ jobj = json_object_new_int64(field); -+ if (jobj) -+ json_object_object_add(jhealth, "pmem_errors", jobj); -+ -+ cxl_cmd_unref(cmd); -+ return jhealth; -+ -+err_cmd: -+ cxl_cmd_unref(cmd); -+err_jobj: -+ json_object_put(jhealth); -+ return NULL; -+} -+ - struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - unsigned long flags) - { -@@ -1464,5 +1638,10 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - if (jobj) - json_object_object_add(jdev, "ram_size", jobj); - -+ if (flags & UTIL_JSON_HEALTH) { -+ jobj = util_cxl_memdev_health_to_json(memdev, flags); -+ if (jobj) -+ json_object_object_add(jdev, "health", jobj); -+ } - return jdev; - } -diff --git a/util/json.h b/util/json.h -index 91918c8..ce575e6 100644 ---- a/util/json.h -+++ b/util/json.h -@@ -19,6 +19,7 @@ enum util_json_flags { - UTIL_JSON_CONFIGURED = (1 << 7), - UTIL_JSON_FIRMWARE = (1 << 8), - UTIL_JSON_DAX_MAPPINGS = (1 << 9), -+ UTIL_JSON_HEALTH = (1 << 10), - }; - - struct json_object; --- -2.27.0 - diff --git a/SOURCES/0047-ndctl-install-bash-completion-symlinks.patch b/SOURCES/0047-ndctl-install-bash-completion-symlinks.patch deleted file mode 100644 index 09109eb..0000000 --- a/SOURCES/0047-ndctl-install-bash-completion-symlinks.patch +++ /dev/null @@ -1,75 +0,0 @@ -From ac46d00d7d4d555a238bb898e2ff4af0c444bebe Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Tue, 16 Nov 2021 17:51:31 -0700 -Subject: [PATCH 047/217] ndctl: install bash-completion symlinks - -Install symlinks for other utilities (daxctl, cxl-cli) in the -completions directory so that the dynamic completion loader can pick up -their respective names. Without this, completions for daxctl and cxl -would only work after a prior invocation of ndctl's completion. - -Reported-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Makefile.am | 3 +++ - configure.ac | 1 + - ndctl.spec.in | 4 +++- - 3 files changed, 7 insertions(+), 1 deletion(-) - -diff --git a/Makefile.am b/Makefile.am -index fa2010a..bd0037e 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -49,6 +49,9 @@ sles/ndctl.spec: sles/header ndctl.spec.in Makefile.am version.m4 - if ENABLE_BASH_COMPLETION - bashcompletiondir = $(BASH_COMPLETION_DIR) - dist_bashcompletion_DATA = contrib/ndctl -+install-data-hook: -+ $(LN_S) -f $(BASH_COMPLETION_DIR)/ndctl $(DESTDIR)/$(BASH_COMPLETION_DIR)/daxctl -+ $(LN_S) -f $(BASH_COMPLETION_DIR)/ndctl $(DESTDIR)/$(BASH_COMPLETION_DIR)/cxl - endif - - modprobe_file = contrib/nvdimm-security.conf -diff --git a/configure.ac b/configure.ac -index 00497ae..9ac785f 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -31,6 +31,7 @@ AC_PREFIX_DEFAULT([/usr]) - - AC_PROG_SED - AC_PROG_MKDIR_P -+AC_PROG_LN_S - - AC_ARG_ENABLE([docs], - AS_HELP_STRING([--disable-docs], -diff --git a/ndctl.spec.in b/ndctl.spec.in -index 4b08c05..27ca097 100644 ---- a/ndctl.spec.in -+++ b/ndctl.spec.in -@@ -140,7 +140,7 @@ make check - %license LICENSES/preferred/GPL-2.0 LICENSES/other/MIT LICENSES/other/CC0-1.0 - %{_bindir}/ndctl - %{_mandir}/man1/ndctl* --%{bashcompdir}/ -+%{bashcompdir}/ndctl - %{_unitdir}/ndctl-monitor.service - %{_sysconfdir}/ndctl/keys/keys.readme - %{_sysconfdir}/modprobe.d/nvdimm-security.conf -@@ -153,12 +153,14 @@ make check - %{_bindir}/daxctl - %{_mandir}/man1/daxctl* - %{_datadir}/daxctl/daxctl.conf -+%{bashcompdir}/daxctl - - %files -n cxl-cli - %defattr(-,root,root) - %license LICENSES/preferred/GPL-2.0 LICENSES/other/MIT LICENSES/other/CC0-1.0 - %{_bindir}/cxl - %{_mandir}/man1/cxl* -+%{bashcompdir}/cxl - - %files -n LNAME - %defattr(-,root,root) --- -2.27.0 - diff --git a/SOURCES/0048-scripts-Add-a-man-page-template-generator.patch b/SOURCES/0048-scripts-Add-a-man-page-template-generator.patch deleted file mode 100644 index 712ed42..0000000 --- a/SOURCES/0048-scripts-Add-a-man-page-template-generator.patch +++ /dev/null @@ -1,400 +0,0 @@ -From 706a418798633ccb550b114eca7cc11038ab2695 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Tue, 14 Dec 2021 19:01:02 -0700 -Subject: [PATCH 048/217] scripts: Add a man page template generator - -Add a script to generate man page templates for the utils and libraries -under ndctl - including cxl, libcxl, ndctl, and daxctl. - -The script can control certain include options depending on the options -supplied, and either dump the templates to stdout, or write the actual -files in their eventual directories, and open up an editor to further -edit them (unless --no-edit is used). - -Link: https://lore.kernel.org/r/20211215020102.97880-1-vishal.l.verma@intel.com -Cc: Dan Williams -Signed-off-by: Vishal Verma ---- - scripts/docsurgeon | 339 +++++++++++++++++++++++++ - scripts/docsurgeon_parser_generator.m4 | 23 ++ - 2 files changed, 362 insertions(+) - create mode 100755 scripts/docsurgeon - create mode 100644 scripts/docsurgeon_parser_generator.m4 - -diff --git a/scripts/docsurgeon b/scripts/docsurgeon -new file mode 100755 -index 0000000..ca0ad78 ---- /dev/null -+++ b/scripts/docsurgeon -@@ -0,0 +1,339 @@ -+#!/bin/bash -eE -+ -+this_script="docsurgeon" -+script_dir="$(cd "$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")" && pwd)" -+env_file="${script_dir}/.env" -+if [ -e "$env_file" ]; then -+ # shellcheck source=.env -+ . "$env_file" -+fi -+ -+sources_file="${script_dir}/.sources" -+ -+parser_generator="${script_dir}/${this_script}_parser_generator.m4" -+parser_lib="${script_dir}/${this_script}_parser.sh" -+if [ ! -e "$parser_lib" ] || [ "$parser_generator" -nt "$parser_lib" ]; then -+ if command -V argbash > /dev/null; then -+ argbash --strip user-content "$parser_generator" -o "$parser_lib" -+ else -+ echo "error: please install argbash" >&2 -+ exit 1 -+ fi -+fi -+ -+if [[ $1 != "bin" ]]; then -+ # shellcheck source=docsurgeon_parser.sh -+ . "${script_dir}/${this_script}_parser.sh" || { echo "Couldn't find $parser_lib" >&2; exit 1; } -+fi -+ -+# some script defaults - override using '.env' -+docbase="Documentation" -+copyright_cli="// SPDX-License-Identifier: GPL-2.0" -+copyright_footer_cli="include::../copyright.txt[]" -+copyright_lib="// SPDX-License-Identifier: LGPL-2.0" -+copyright_footer_lib="include::../../copyright.txt[]" -+ -+# List of files we're creating, to be edited/renamed later -+# This starts out blank, and is filled in as we go by gen_*() functions -+declare -a outfiles -+ -+cleanup() -+{ -+ if [ ${#outfiles[@]} -gt 0 ]; then -+ rm -f "${outfiles[@]}" -+ fi -+ set +x -+} -+ -+trap cleanup EXIT -+ -+auto_detect_params() -+{ -+ fs="" -+ module="" -+ section="" -+ -+ # if module and section were explicitly specified, respect them -+ if [[ $_arg_module ]] && [[ $_arg_section ]]; then -+ return -+ fi -+ -+ # check if names are self-consistent, and determine 'fs' -+ for name in ${_arg_name[@]}; do -+ if [[ ! $fs ]]; then -+ if [[ $name == *-* ]]; then -+ fs="-" -+ elif [[ $name == *_* ]]; then -+ fs="_" -+ else -+ # can't autodetect section -+ return -+ fi -+ fi -+ if [[ $fs == "-" ]] && [[ $name == *_* ]]; then -+ die "can't auto-detect params with mixed-style names" -+ fi -+ if [[ $fs == "_" ]] && [[ $name == *-* ]]; then -+ die "can't auto-detect params with mixed-style names" -+ fi -+ done -+ -+ # try to detect module name -+ for name in ${_arg_name[@]}; do -+ str=${name%%$fs*} -+ if [[ $module ]]; then -+ if [[ $str != $module ]]; then -+ die "Can't autodetect module because of mixed names ($str and $module)" -+ fi -+ else -+ module="$str" -+ fi -+ done -+ -+ # try to detect section number -+ case "$fs" in -+ -) -+ section=1 -+ ;; -+ _) -+ section=3 -+ ;; -+ *) -+ die "Unknown fs, can't autodetect section number" -+ ;; -+ esac -+ -+ if [[ $module ]]; then -+ _arg_module="$module" -+ fi -+ if [[ $section ]]; then -+ _arg_section="$section" -+ fi -+} -+ -+process_options_logic() -+{ -+ if [[ $_arg_debug == "on" ]]; then -+ set -x -+ fi -+ -+ auto_detect_params -+} -+ -+gen_underline() -+{ -+ name="$1" -+ char="$2" -+ num="${#name}" -+ -+ printf -v tmpstring "%-${num}s" " " -+ echo "${tmpstring// /$char}" -+} -+ -+gen_header() -+{ -+ printf "\n%s\n%s\n" "$1" "$(gen_underline "$1" "=")" -+} -+ -+gen_section() -+{ -+ printf "\n%s\n%s\n" "$1" "$(gen_underline "$1" "-")" -+} -+ -+gen_section_name() -+{ -+ name="$1" -+ -+ gen_section "NAME" -+ cat <<- EOF -+ $name - -+ EOF -+} -+ -+gen_section_synopsis_1() -+{ -+ name="$1" -+ -+ gen_section "SYNOPSIS" -+ cat <<- EOF -+ [verse] -+ '$_arg_module ${name#*-} []' -+ EOF -+} -+ -+gen_section_synopsis_3() -+{ -+ name="$1" -+ -+ gen_section "SYNOPSIS" -+ cat <<- EOF -+ [verse] -+ ---- -+ #include <$_arg_module/lib$_arg_module.h> -+ -+ $name(); -+ ---- -+ EOF -+} -+ -+gen_section_example_1() -+{ -+ name="$1" -+ -+ gen_section "EXAMPLE" -+ cat <<- EOF -+ ---- -+ # $_arg_module ${name#*-} -+ ---- -+ EOF -+} -+ -+gen_section_example_3() -+{ -+ name="$1" -+ -+ gen_section "EXAMPLE" -+ cat <<- EOF -+ See example usage in test/lib$_arg_module.c -+ EOF -+} -+ -+gen_section_options_1() -+{ -+ gen_section "OPTIONS" -+cat << EOF -+-o:: -+--option:: -+ Description -+EOF -+ -+ if [[ $_arg_human_option == "on" ]]; then -+ printf "\n%s\n" "include::human-option.txt[]" -+ fi -+ if [[ $_arg_verbose_option == "on" ]]; then -+ printf "\n%s\n" "include::verbose-option.txt[]" -+ fi -+} -+ -+gen_section_seealso_1() -+{ -+ gen_section "SEE ALSO" -+ cat <<- EOF -+ link$_arg_module:$_arg_module-list[$_arg_section], -+ EOF -+} -+ -+gen_section_seealso_3() -+{ -+ gen_section "SEE ALSO" -+ cat <<- EOF -+ linklib$_arg_module:${_arg_module}_other_API[$_arg_section], -+ EOF -+} -+ -+gen_cli() -+{ -+ name="$1" -+ path="$docbase/$_arg_module" -+ if [ ! -d "$path" ]; then -+ die "Not found: $path" -+ fi -+ -+ tmp="$(mktemp -p "$path" "$name.txt.XXXX")" -+ outfiles+=("$tmp") -+ -+ # Start template generation -+ printf "%s\n" "$copyright_cli" > "$tmp" -+ gen_header "$name" >> "$tmp" -+ gen_section_name "$name" >> "$tmp" -+ gen_section_synopsis_1 "$name" >> "$tmp" -+ gen_section "DESCRIPTION" >> "$tmp" -+ gen_section_example_1 "$name" >> "$tmp" -+ gen_section_options_1 >> "$tmp" -+ printf "\n%s\n" "$copyright_footer_cli" >> "$tmp" -+ gen_section_seealso_1 >> "$tmp" -+} -+ -+gen_lib() -+{ -+ name="$1" -+ path="$docbase/$_arg_module/lib" -+ if [ ! -d "$path" ]; then -+ die "Not found: $path" -+ fi -+ -+ tmp="$(mktemp -p "$path" "$name.txt.XXXX")" -+ outfiles+=("$tmp") -+ -+ # Start template generation -+ printf "%s\n" "$copyright_lib" > "$tmp" -+ gen_header "$name($_arg_section)" >> "$tmp" -+ gen_section_name "$name" >> "$tmp" -+ gen_section_synopsis_3 "$name" >> "$tmp" -+ gen_section "DESCRIPTION" >> "$tmp" -+ gen_section "RETURN VALUE" >> "$tmp" -+ gen_section_example_3 "$name" >> "$tmp" -+ printf "\n%s\n" "$copyright_footer_lib" >> "$tmp" -+ gen_section_seealso_3 >> "$tmp" -+} -+ -+gen_man() -+{ -+ name="$1" -+ case "$_arg_section" in -+ 1) -+ gen_cli "$name" -+ ;; -+ 3) -+ gen_lib "$name" -+ ;; -+ *) -+ die "Unknown section: $_arg_section" -+ ;; -+ esac -+} -+ -+gen_include() -+{ -+ echo "in gen_include" -+} -+ -+main() -+{ -+ process_options_logic -+ -+ cmd="$_arg_command" -+ case "$cmd" in -+ gen-man) -+ for name in ${_arg_name[@]}; do -+ gen_man "$name" -+ done -+ ;; -+ gen-include) -+ for name in ${_arg_name[@]}; do -+ gen_include -+ done -+ ;; -+ *) -+ die "Unknown command: $cmd" -+ ;; -+ esac -+ -+ if [[ $_arg_dump == "on" ]]; then -+ for file in ${outfiles[@]}; do -+ echo "${file##*/}" -+ cat "$file" -+ rm "$file" -+ done -+ elif [ ${#outfiles[@]} -gt 0 ]; then -+ if [[ $_arg_edit = "on" ]]; then -+ vim -p "${outfiles[@]}" -+ fi -+ -+ for file in ${outfiles[@]}; do -+ mv "$file" "${file%.*}" -+ done -+ fi -+} -+ -+main "$@" -diff --git a/scripts/docsurgeon_parser_generator.m4 b/scripts/docsurgeon_parser_generator.m4 -new file mode 100644 -index 0000000..9283c7c ---- /dev/null -+++ b/scripts/docsurgeon_parser_generator.m4 -@@ -0,0 +1,23 @@ -+#!/bin/bash -+ -+# m4_ignore( -+echo "This is just a parsing library template, not the library - pass this file to 'argbash' to fix this." >&2 -+exit 11 #)Created by argbash-init v2.9.0 -+# Rearrange the order of options below according to what you would like to see in the help message. -+# ARG_OPTIONAL_REPEATED([name], [n], [Command or function name to generate a template for.\n Can be repeated for multiple names. ], []) -+# ARG_OPTIONAL_BOOLEAN([edit], [e], [Edit template files after creation], [on]) -+# ARG_OPTIONAL_BOOLEAN([debug], [], [Debug script problems (enables set -x)], ) -+# ARG_OPTIONAL_BOOLEAN([dump], [], [Write generated file to stdout instead of a file], ) -+# ARG_OPTIONAL_SINGLE([module], [m], [Module (Docs subdir) in which to create the template], []) -+# ARG_OPTIONAL_SINGLE([section], [s], [man section for which to create the template], []) -+# ARG_OPTIONAL_BOOLEAN([human-option], [u], [Include the human option in 'OPTIONS'], ) -+# ARG_OPTIONAL_BOOLEAN([verbose-option], [V], [Include the verbose option in 'OPTIONS'], ) -+# ARG_POSITIONAL_DOUBLEDASH() -+# ARG_POSITIONAL_SINGLE([command], [Operation to perform:\n gen-man\n gen-include], []) -+# ARGBASH_SET_DELIM([ =]) -+# ARG_OPTION_STACKING([getopt]) -+# ARG_RESTRICT_VALUES([no-local-options]) -+# ARG_DEFAULTS_POS -+# ARG_HELP([Tool to aid in creating and managing man page templates]) -+# ARG_VERSION([echo "docsurgeon 0.1"]) -+# ARGBASH_GO --- -2.27.0 - diff --git a/SOURCES/0049-daxctl-Add-Soft-Reservation-theory-of-operation.patch b/SOURCES/0049-daxctl-Add-Soft-Reservation-theory-of-operation.patch deleted file mode 100644 index 54dfad0..0000000 --- a/SOURCES/0049-daxctl-Add-Soft-Reservation-theory-of-operation.patch +++ /dev/null @@ -1,167 +0,0 @@ -From 8f4e42c0c526e85b045fd0329df7cb904f511c98 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 7 Oct 2021 14:59:53 -0700 -Subject: [PATCH 049/217] daxctl: Add "Soft Reservation" theory of operation - -As systems are starting to ship memory with the EFI "Special Purpose" -attribute that Linux optionally turns into "Soft Reserved" ranges one of -the immediate first questions is "where is my special memory, and how do -access it". Add some documentation to explain the default behaviour of -"Soft Reserved". - -Link: https://lore.kernel.org/r/163364399303.201290.6835215953983673447.stgit@dwillia2-desk3.amr.corp.intel.com -Reported-by: John Groves -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .../daxctl/daxctl-reconfigure-device.txt | 127 ++++++++++++------ - 1 file changed, 88 insertions(+), 39 deletions(-) - -diff --git a/Documentation/daxctl/daxctl-reconfigure-device.txt b/Documentation/daxctl/daxctl-reconfigure-device.txt -index f112b3c..132684c 100644 ---- a/Documentation/daxctl/daxctl-reconfigure-device.txt -+++ b/Documentation/daxctl/daxctl-reconfigure-device.txt -@@ -12,6 +12,94 @@ SYNOPSIS - [verse] - 'daxctl reconfigure-device' [...] [] - -+DESCRIPTION -+----------- -+ -+Reconfigure the operational mode of a dax device. This can be used to convert -+a regular 'devdax' mode device to the 'system-ram' mode which arranges for the -+dax range to be hot-plugged into the system as regular memory. -+ -+NOTE: This is a destructive operation. Any data on the dax device *will* be -+lost. -+ -+NOTE: Device reconfiguration depends on the dax-bus device model. See -+linkdaxctl:daxctl-migrate-device-model[1] for more information. If dax-class is -+in use (via the dax_pmem_compat driver), the reconfiguration will fail with an -+error such as the following: -+---- -+# daxctl reconfigure-device --mode=system-ram --region=0 all -+libdaxctl: daxctl_dev_disable: dax3.0: error: device model is dax-class -+dax3.0: disable failed: Operation not supported -+error reconfiguring devices: Operation not supported -+reconfigured 0 devices -+---- -+ -+'daxctl-reconfigure-device' nominally expects that it will online new memory -+blocks as 'movable', so that kernel data doesn't make it into this memory. -+However, there are other potential agents that may be configured to -+automatically online new hot-plugged memory as it appears. Most notably, -+these are the '/sys/devices/system/memory/auto_online_blocks' configuration, -+or system udev rules. If such an agent races to online memory sections, daxctl -+checks if the blocks were onlined as 'movable' memory. If this was not the -+case, and the memory blocks are found to be in a different zone, then a -+warning is displayed. If it is desired that a different agent control the -+onlining of memory blocks, and the associated memory zone, then it is -+recommended to use the --no-online option described below. This will abridge -+the device reconfiguration operation to just hotplugging the memory, and -+refrain from then onlining it. -+ -+In case daxctl detects that there is a kernel policy to auto-online blocks -+(via /sys/devices/system/memory/auto_online_blocks), then reconfiguring to -+system-ram will result in a failure. This can be overridden with '--force'. -+ -+ -+THEORY OF OPERATION -+------------------- -+The kernel device-dax subsystem surfaces character devices -+that provide DAX-access (direct mappings sans page-cache buffering) to a -+given memory region. The devices are named /dev/daxX.Y where X is a -+region-id and Y is an instance-id within that region. There are 2 -+mechanisms that trigger device-dax instances to appear: -+ -+1. Persistent Memory (PMEM) namespace configured in "devdax" mode. See -+"ndctl create-namspace --help" and -+https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/dax/Kconfig[CONFIG_DEV_DAX_PMEM]. -+In this case the device-dax instance is statically sized to its host -+memory region which is bounded to the physical address range of the host -+namespace. -+ -+2. Soft Reserved memory enumerated by platform firmware. On EFI systems -+this is communicated via the so called EFI_MEMORY_SP "Special Purpose" -+attribute. See -+https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/dax/Kconfig[CONFIG_DEV_DAX_HMEM]. -+In this case the device-dax instance(s) associated with the given memory -+region can be resized and divided into multiple devices. -+ -+In the Soft Reservation case the expectation for EFI + ACPI based -+platforms is that in addition to the EFI_MEMORY_SP attribute the -+firmware also creates distinct ACPI proximity domains for any address -+range that has different performance characteristics than default -+"System RAM". So, the SRAT will define the proximity domain, the SLIT -+communicates relative distance to other proximity domains, and the HMAT -+is populated with nominal read/write latency and read/write bandwidth -+data. That HMAT data is emitted to the kernel log on bootup, and also -+exported to sysfs. See -+https://www.kernel.org/doc/html/latest/admin-guide/mm/numaperf.html[NUMAPERF], -+for the runtime representation of CPU to Memory node performance -+details. -+ -+Outside of the NUMA performance details linked above the other method to -+detect the presence of "Soft Reserved" memory is to dump /proc/iomem and -+look for "Soft Reserved" ranges. If the kernel was not built with -+CONFIG_EFI_SOFTRESERVE, predates the introduction of -+CONFIG_EFI_SOFTRESERVE (v5.5), or was booted with the efi=nosoftreserve -+command line then device-dax will not attach and the expectation is that -+the memory shows up as a memory-only NUMA node. Otherwise the memory -+shows up as a device-dax instance and DAXCTL(1) can be used to -+optionally partition it and assign the memory back to the kernel as -+"System RAM", or the device can be mapped directly as the back end of a -+userspace memory allocator like https://pmem.io/vmem/libvmem/[LIBVMEM]. -+ - EXAMPLES - -------- - -@@ -83,45 +171,6 @@ reconfigured 1 device - reconfigured 1 device - ---- - --DESCRIPTION ------------- -- --Reconfigure the operational mode of a dax device. This can be used to convert --a regular 'devdax' mode device to the 'system-ram' mode which arranges for the --dax range to be hot-plugged into the system as regular memory. -- --NOTE: This is a destructive operation. Any data on the dax device *will* be --lost. -- --NOTE: Device reconfiguration depends on the dax-bus device model. See --linkdaxctl:daxctl-migrate-device-model[1] for more information. If dax-class is --in use (via the dax_pmem_compat driver), the reconfiguration will fail with an --error such as the following: ------ --# daxctl reconfigure-device --mode=system-ram --region=0 all --libdaxctl: daxctl_dev_disable: dax3.0: error: device model is dax-class --dax3.0: disable failed: Operation not supported --error reconfiguring devices: Operation not supported --reconfigured 0 devices ------ -- --'daxctl-reconfigure-device' nominally expects that it will online new memory --blocks as 'movable', so that kernel data doesn't make it into this memory. --However, there are other potential agents that may be configured to --automatically online new hot-plugged memory as it appears. Most notably, --these are the '/sys/devices/system/memory/auto_online_blocks' configuration, --or system udev rules. If such an agent races to online memory sections, daxctl --checks if the blocks were onlined as 'movable' memory. If this was not the --case, and the memory blocks are found to be in a different zone, then a --warning is displayed. If it is desired that a different agent control the --onlining of memory blocks, and the associated memory zone, then it is --recommended to use the --no-online option described below. This will abridge --the device reconfiguration operation to just hotplugging the memory, and --refrain from then onlining it. -- --In case daxctl detects that there is a kernel policy to auto-online blocks --(via /sys/devices/system/memory/auto_online_blocks), then reconfiguring to --system-ram will result in a failure. This can be overridden with '--force'. - - OPTIONS - ------- --- -2.27.0 - diff --git a/SOURCES/0061-libcxl-fix-potential-NULL-dereference-in-cxl_memdev_.patch b/SOURCES/0061-libcxl-fix-potential-NULL-dereference-in-cxl_memdev_.patch deleted file mode 100644 index 00d8bd5..0000000 --- a/SOURCES/0061-libcxl-fix-potential-NULL-dereference-in-cxl_memdev_.patch +++ /dev/null @@ -1,46 +0,0 @@ -From c55b18181281b2fffadb9e0e8955d74b8b719349 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Fri, 17 Dec 2021 19:25:11 -0700 -Subject: [PATCH 061/217] libcxl: fix potential NULL dereference in - cxl_memdev_nvdimm_bridge_active() - -Static analysis points out that the function above has a check for -'if (!bridge)', implying that bridge maybe NULL, but it is dereferenced -before the check, which could result in a NULL dereference. - -Fix this by moving any accesses to the bridge structure after the NULL -check. - -Link: https://lore.kernel.org/r/20211218022511.314928-1-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index f0664be..3390eb9 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -420,12 +420,15 @@ CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev) - { - struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); - struct cxl_nvdimm_bridge *bridge = memdev->bridge; -- char *path = bridge->dev_buf; -- int len = bridge->buf_len; -+ char *path; -+ int len; - - if (!bridge) - return 0; - -+ path = bridge->dev_buf; -+ len = bridge->buf_len; -+ - if (snprintf(path, len, "%s/driver", bridge->dev_path) >= len) { - err(ctx, "%s: nvdimm bridge buffer too small!\n", - cxl_memdev_get_devname(memdev)); --- -2.27.0 - diff --git a/SOURCES/0064-ndctl-release-v72.patch b/SOURCES/0064-ndctl-release-v72.patch deleted file mode 100644 index c81b9f4..0000000 --- a/SOURCES/0064-ndctl-release-v72.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 25062cf34c70012f5d42ce1fef7e2dc129807c10 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Fri, 17 Dec 2021 21:14:37 -0700 -Subject: [PATCH 064/217] ndctl: release v72 - -This release incorporates functionality up to the 5.16 kernel. - -Highlights include a new utility and library for interfacing with the -'CXL' drivers and devices, a policy based configuration mechanism for -ndctl and daxctl, fixes, test updates, and general additions for the -PAPR family of NVDIMMs, more seed device accounting fixes, misc unit -test and documentation updates, and fixes to NVDIMM bus scrubbing. - -Commands: - cxl-cli: new utility providing list, {read,write,zero}-label commands - daxctl-reconfigure-device: new --check-config option - ndctl-monitor: add support for a new unified config file format - ndctl-*-namespace: seed namespace accounting fixes - -Tests: - Fix device-dax mremap() test - Exercise soft_offline_page() corner cases - Fix btt expect table compile warning - monitor.sh: add checking the presence of jq command ahead of time - -APIs: - ndctl_bus_nfit_translate_spa - ndctl_dimm_sizeof_namespace_index - ndctl_get_config_path - ndctl_set_config_path - daxctl_dev_has_online_memory - daxctl_dev_will_auto_online_memory - daxctl_get_config_path - daxctl_set_config_path - cxl_cmd_get_devname - cxl_cmd_get_mbox_status - cxl_cmd_get_out_size - cxl_cmd_health_info_get_dirty_shutdowns - cxl_cmd_health_info_get_ext_corrected_persistent_normal - cxl_cmd_health_info_get_ext_corrected_persistent_warning - cxl_cmd_health_info_get_ext_corrected_volatile_normal - cxl_cmd_health_info_get_ext_corrected_volatile_warning - cxl_cmd_health_info_get_ext_life_used_critical - cxl_cmd_health_info_get_ext_life_used_normal - cxl_cmd_health_info_get_ext_life_used_warning - cxl_cmd_health_info_get_ext_temperature_critical - cxl_cmd_health_info_get_ext_temperature_normal - cxl_cmd_health_info_get_ext_temperature_warning - cxl_cmd_health_info_get_hw_replacement_needed - cxl_cmd_health_info_get_life_used - cxl_cmd_health_info_get_maintenance_needed - cxl_cmd_health_info_get_media_data_loss_imminent - cxl_cmd_health_info_get_media_data_lost - cxl_cmd_health_info_get_media_normal - cxl_cmd_health_info_get_media_not_ready - cxl_cmd_health_info_get_media_persistence_loss_imminent - cxl_cmd_health_info_get_media_persistence_lost - cxl_cmd_health_info_get_media_powerloss_data_loss - cxl_cmd_health_info_get_media_powerloss_persistence_loss - cxl_cmd_health_info_get_media_shutdown_data_loss - cxl_cmd_health_info_get_media_shutdown_persistence_loss - cxl_cmd_health_info_get_performance_degraded - cxl_cmd_health_info_get_pmem_errors - cxl_cmd_health_info_get_temperature - cxl_cmd_health_info_get_volatile_errors - cxl_cmd_identify_get_fw_rev - cxl_cmd_identify_get_label_size - cxl_cmd_identify_get_partition_align - cxl_cmd_new_get_health_info - cxl_cmd_new_identify - cxl_cmd_new_raw - cxl_cmd_new_read_label - cxl_cmd_new_write_label - cxl_cmd_read_label_get_payload - cxl_cmd_ref - cxl_cmd_set_input_payload - cxl_cmd_set_output_payload - cxl_cmd_submit - cxl_cmd_unref - cxl_get_log_priority - cxl_get_private_data - cxl_get_userdata - cxl_memdev_get_ctx - cxl_memdev_get_devname - cxl_memdev_get_firmware_verison - cxl_memdev_get_first - cxl_memdev_get_id - cxl_memdev_get_label_size - cxl_memdev_get_major - cxl_memdev_get_minor - cxl_memdev_get_next - cxl_memdev_get_pmem_size - cxl_memdev_get_ram_size - cxl_memdev_nvdimm_bridge_active - cxl_memdev_read_label - cxl_memdev_write_label - cxl_memdev_zero_label - cxl_new - cxl_ref - cxl_set_log_fn - cxl_set_log_priority - cxl_set_private_data - cxl_set_userdata - cxl_unref ---- - Makefile.am.in | 8 ++++---- - git-version | 2 +- - 2 files changed, 5 insertions(+), 5 deletions(-) - -diff -up ndctl-71.1/Makefile.am.in.orig ndctl-71.1/Makefile.am.in ---- ndctl-71.1/Makefile.am.in.orig 2022-10-07 15:20:47.982353042 -0400 -+++ ndctl-71.1/Makefile.am.in 2022-10-07 15:21:02.174401362 -0400 -@@ -36,13 +36,13 @@ SED_PROCESS = \ - -e 's,@includedir\@,$(includedir),g' \ - < $< > $@ || rm $@ - --LIBNDCTL_CURRENT=25 -+LIBNDCTL_CURRENT=26 - LIBNDCTL_REVISION=1 --LIBNDCTL_AGE=19 -+LIBNDCTL_AGE=20 - --LIBDAXCTL_CURRENT=6 -+LIBDAXCTL_CURRENT=7 - LIBDAXCTL_REVISION=0 --LIBDAXCTL_AGE=5 -+LIBDAXCTL_AGE=6 - - LIBCXL_CURRENT=1 - LIBCXL_REVISION=0 -diff -up ndctl-71.1/git-version.orig ndctl-71.1/git-version ---- ndctl-71.1/git-version.orig 2022-10-07 15:21:02.175401365 -0400 -+++ ndctl-71.1/git-version 2022-10-07 15:21:27.267486796 -0400 -@@ -19,7 +19,7 @@ dirty() { - fi - } - --DEF_VER=71.1 -+DEF_VER=72 - - LF=' - ' diff --git a/SOURCES/0067-ndctl-add-repology-graphic-to-README.md.patch b/SOURCES/0067-ndctl-add-repology-graphic-to-README.md.patch deleted file mode 100644 index 3e66ade..0000000 --- a/SOURCES/0067-ndctl-add-repology-graphic-to-README.md.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 20a714fe89a7941ef99898821719a46f04f7488b Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Tue, 4 Jan 2022 17:18:23 -0700 -Subject: [PATCH 067/217] ndctl: add repology graphic to README.md - -Add a graphic/badge from repology showing the packaging status of ndctl -with various distros. - -Link: https://lore.kernel.org/r/20220105001823.299797-1-vishal.l.verma@intel.com -Reviewed-by: Ira Weiny -Signed-off-by: Vishal Verma ---- - README.md | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/README.md b/README.md -index 89dfc87..4ab4523 100644 ---- a/README.md -+++ b/README.md -@@ -4,6 +4,9 @@ - Utility library for managing the libnvdimm (non-volatile memory device) - sub-system in the Linux kernel - -+ -+ Packaging status -+ - - Build - ===== --- -2.27.0 - diff --git a/SOURCES/0068-Documentation-ndctl-fix-self-reference-of-ndctl-disa.patch b/SOURCES/0068-Documentation-ndctl-fix-self-reference-of-ndctl-disa.patch deleted file mode 100644 index 20eccea..0000000 --- a/SOURCES/0068-Documentation-ndctl-fix-self-reference-of-ndctl-disa.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 3f2a2973b23fa86c810aab49eeb8ff5f97a02720 Mon Sep 17 00:00:00 2001 -From: Yasunori Goto -Date: Wed, 3 Feb 2021 19:17:07 +0900 -Subject: [PATCH 068/217] Documentation/ndctl: fix self-reference of ndctl - disable-namespace - -The man manual of ndctl disable-namespace link to itself at See -Also section. It should be enable-namespace instead of it. - -Signed-off-by: Yasunori Goto -Signed-off-by: Vishal Verma -Link: https://github.com/pmem/ndctl/pull/160 ---- - Documentation/ndctl/ndctl-disable-namespace.txt | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/Documentation/ndctl/ndctl-disable-namespace.txt b/Documentation/ndctl/ndctl-disable-namespace.txt -index 5d3a8be..187348f 100644 ---- a/Documentation/ndctl/ndctl-disable-namespace.txt -+++ b/Documentation/ndctl/ndctl-disable-namespace.txt -@@ -22,4 +22,4 @@ include::../copyright.txt[] - - SEE ALSO - -------- --linkndctl:ndctl-disable-namespace[1] -+linkndctl:ndctl-enable-namespace[1] --- -2.27.0 - diff --git a/SOURCES/0069-ndctl-docs-Clarify-update-firwmware-activation-overf.patch b/SOURCES/0069-ndctl-docs-Clarify-update-firwmware-activation-overf.patch deleted file mode 100644 index a88e013..0000000 --- a/SOURCES/0069-ndctl-docs-Clarify-update-firwmware-activation-overf.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 475cb041a97d3c7140efd1b0cda820fb22b69d11 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:31:44 -0800 -Subject: [PATCH 069/217] ndctl/docs: Clarify update-firwmware activation - 'overflow' conditions - -Give examples and remediation for "overflow" events, i.e. where the -estimated time to complete activation exceeds the platform advertised -maximum. When that happens forced activation can lead to undefined results. - -Link: https://lore.kernel.org/r/164141830490.3990253.6263569501446070716.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/ndctl/ndctl-update-firmware.txt | 64 ++++++++++++++++++- - 1 file changed, 63 insertions(+), 1 deletion(-) - -diff --git a/Documentation/ndctl/ndctl-update-firmware.txt b/Documentation/ndctl/ndctl-update-firmware.txt -index 1080d62..6166457 100644 ---- a/Documentation/ndctl/ndctl-update-firmware.txt -+++ b/Documentation/ndctl/ndctl-update-firmware.txt -@@ -58,7 +58,69 @@ include::xable-bus-options.txt[] - Arm a device for firmware activation. This is enabled by default - when a firmware image is specified. Specify --no-arm to disable - this default. Otherwise, without a firmware image, this option can be -- used to manually arm a device for firmware activate. -+ used to manually arm a device for firmware activate. When a -+ device transitions from unarmed to armed the platform recalculates the -+ firmware activation time and compares it against the maximum platform -+ supported time. If the activation time would exceed the platform maximum the -+ arm attempt is aborted: -+ -+[verse] -+ndctl update-firmware --arm --bus=nfit_test.0 all -+ Error: update firmware: nmem4: arm aborted, tripped overflow -+[ -+ { -+ "dev":"nmem1", -+ "id":"cdab-0a-07e0-ffffffff", -+ "handle":"0", -+ "phys_id":"0", -+ "security":"disabled", -+ "firmware":{ -+ "current_version":"0", -+ "can_update":true -+ } -+ }, -+ { -+ "dev":"nmem3", -+ "id":"cdab-0a-07e0-fffeffff", -+ "handle":"0x100", -+ "phys_id":"0x2", -+ "security":"disabled", -+ "firmware":{ -+ "current_version":"0", -+ "can_update":true -+ } -+ }, -+ { -+ "dev":"nmem2", -+ "id":"cdab-0a-07e0-feffffff", -+ "handle":"0x1", -+ "phys_id":"0x1", -+ "security":"disabled", -+ "firmware":{ -+ "current_version":"0", -+ "can_update":true -+ } -+ } -+] -+updated 3 nmems. -+ -+ It is possible, but not recommended, to ignore timeout overflows -+ with the --force option. At any point to view the 'armed' state of the -+ bus do: -+ -+[verse] -+ndctl list -BF -b nfit_test.0 -+[ -+ { -+ "provider":"nfit_test.0", -+ "dev":"ndbus2", -+ "scrub_state":"idle", -+ "firmware":{ -+ "activate_method":"suspend", -+ "activate_state":"overflow" -+ } -+ } -+] - - -D:: - --disarm:: --- -2.27.0 - diff --git a/SOURCES/0070-ndctl-test-Prepare-for-BLK-aperture-support-removal.patch b/SOURCES/0070-ndctl-test-Prepare-for-BLK-aperture-support-removal.patch deleted file mode 100644 index 697f46c..0000000 --- a/SOURCES/0070-ndctl-test-Prepare-for-BLK-aperture-support-removal.patch +++ /dev/null @@ -1,171 +0,0 @@ -From e423b467e10e3405e6e09260b7669e7022b5f5f7 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:31:50 -0800 -Subject: [PATCH 070/217] ndctl/test: Prepare for BLK-aperture support removal - -The kernel is dropping its support for the BLK-aperture access method. The -primary side effect of this for nfit_test is that NVDIMM namespace labeling -will not be enabled by default. Update the unit tests to initialize the -label index area in this scenario. - -Link: https://lore.kernel.org/r/164141830999.3990253.5021445352398348657.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/core.c | 31 ++++++++++++++++++++++++++++--- - test/libndctl.c | 49 +++++++++++++++++++++++++++++++++++-------------- - 2 files changed, 63 insertions(+), 17 deletions(-) - -diff --git a/test/core.c b/test/core.c -index 2b03aa9..93e1dae 100644 ---- a/test/core.c -+++ b/test/core.c -@@ -261,8 +261,8 @@ retry: - ndctl_bus_foreach(nd_ctx, bus) { - struct ndctl_region *region; - -- if (strncmp(ndctl_bus_get_provider(bus), -- "nfit_test", 9) != 0) -+ if (strcmp(ndctl_bus_get_provider(bus), -+ "nfit_test.0") != 0) - continue; - ndctl_region_foreach(bus, region) - ndctl_region_disable_invalidate(region); -@@ -280,5 +280,30 @@ retry: - NULL, NULL, NULL, NULL); - if (rc) - kmod_unref(*ctx); -- return rc; -+ -+ if (!nd_ctx) -+ return rc; -+ -+ ndctl_bus_foreach (nd_ctx, bus) { -+ struct ndctl_region *region; -+ struct ndctl_dimm *dimm; -+ -+ if (strcmp(ndctl_bus_get_provider(bus), "nfit_test.0") != 0) -+ continue; -+ -+ ndctl_region_foreach (bus, region) -+ ndctl_region_disable_invalidate(region); -+ -+ ndctl_dimm_foreach (bus, dimm) { -+ ndctl_dimm_read_label_index(dimm); -+ ndctl_dimm_init_labels(dimm, NDCTL_NS_VERSION_1_2); -+ ndctl_dimm_disable(dimm); -+ ndctl_dimm_enable(dimm); -+ } -+ -+ ndctl_region_foreach (bus, region) -+ ndctl_region_enable(region); -+ } -+ -+ return 0; - } -diff --git a/test/libndctl.c b/test/libndctl.c -index d9b50f4..c0e4b4c 100644 ---- a/test/libndctl.c -+++ b/test/libndctl.c -@@ -2587,17 +2587,41 @@ static int check_dimms(struct ndctl_bus *bus, struct dimm *dimms, int n, - return 0; - } - --static void reset_bus(struct ndctl_bus *bus) -+enum dimm_reset { -+ DIMM_INIT, -+ DIMM_ZERO, -+}; -+ -+static int reset_dimms(struct ndctl_bus *bus, enum dimm_reset reset) - { -- struct ndctl_region *region; - struct ndctl_dimm *dimm; -+ int rc = 0; -+ -+ ndctl_dimm_foreach(bus, dimm) { -+ if (reset == DIMM_ZERO) -+ ndctl_dimm_zero_labels(dimm); -+ else { -+ ndctl_dimm_read_label_index(dimm); -+ ndctl_dimm_init_labels(dimm, NDCTL_NS_VERSION_1_2); -+ } -+ ndctl_dimm_disable(dimm); -+ rc = ndctl_dimm_enable(dimm); -+ if (rc) -+ break; -+ } -+ -+ return rc; -+} -+ -+static void reset_bus(struct ndctl_bus *bus, enum dimm_reset reset) -+{ -+ struct ndctl_region *region; - - /* disable all regions so that set_config_data commands are permitted */ - ndctl_region_foreach(bus, region) - ndctl_region_disable_invalidate(region); - -- ndctl_dimm_foreach(bus, dimm) -- ndctl_dimm_zero_labels(dimm); -+ reset_dimms(bus, reset); - - /* set regions back to their default state */ - ndctl_region_foreach(bus, region) -@@ -2608,7 +2632,6 @@ static int do_test0(struct ndctl_ctx *ctx, struct ndctl_test *test) - { - struct ndctl_bus *bus = ndctl_bus_get_by_provider(ctx, NFIT_PROVIDER0); - struct ndctl_region *region; -- struct ndctl_dimm *dimm; - int rc; - - if (!bus) -@@ -2625,13 +2648,10 @@ static int do_test0(struct ndctl_ctx *ctx, struct ndctl_test *test) - if (rc) - return rc; - -- ndctl_dimm_foreach(bus, dimm) { -- rc = ndctl_dimm_zero_labels(dimm); -- if (rc < 0) { -- fprintf(stderr, "failed to zero %s\n", -- ndctl_dimm_get_devname(dimm)); -- return rc; -- } -+ rc = reset_dimms(bus, DIMM_INIT); -+ if (rc < 0) { -+ fprintf(stderr, "failed to reset dimms\n"); -+ return rc; - } - - /* -@@ -2649,14 +2669,14 @@ static int do_test0(struct ndctl_ctx *ctx, struct ndctl_test *test) - rc = check_regions(bus, regions0, ARRAY_SIZE(regions0), DAX); - if (rc) - return rc; -- reset_bus(bus); -+ reset_bus(bus, DIMM_INIT); - } - - if (ndctl_test_attempt(test, KERNEL_VERSION(4, 8, 0))) { - rc = check_regions(bus, regions0, ARRAY_SIZE(regions0), PFN); - if (rc) - return rc; -- reset_bus(bus); -+ reset_bus(bus, DIMM_INIT); - } - - return check_regions(bus, regions0, ARRAY_SIZE(regions0), BTT); -@@ -2671,6 +2691,7 @@ static int do_test1(struct ndctl_ctx *ctx, struct ndctl_test *test) - return -ENXIO; - - ndctl_bus_wait_probe(bus); -+ reset_bus(bus, DIMM_ZERO); - - /* - * Starting with v4.10 the dimm on nfit_test.1 gets a unique --- -2.27.0 - diff --git a/SOURCES/0071-ndctl-test-Move-reset-to-function-in-common.patch b/SOURCES/0071-ndctl-test-Move-reset-to-function-in-common.patch deleted file mode 100644 index e61cfd2..0000000 --- a/SOURCES/0071-ndctl-test-Move-reset-to-function-in-common.patch +++ /dev/null @@ -1,428 +0,0 @@ -From 6538529be5738f06543a0d7178f97e0b0e6b63c2 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:31:55 -0800 -Subject: [PATCH 071/217] ndctl/test: Move 'reset()' to function in 'common' - -When BLK mode is removed, tests that expect the nfit_test region to allow -pmem namespace creation will need to 'init' rather than 'zero' labels. In -preparation, take the time opportunity to move reset() to a common -function. So that 'ndctl zero-labels' can be replaced with 'ndctl -init-labels' in one central location. - -Link: https://lore.kernel.org/r/164141831509.3990253.14783946910211635678.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/blk-exhaust.sh | 4 +--- - test/btt-check.sh | 7 ------- - test/btt-errors.sh | 12 +++--------- - test/btt-pad-compat.sh | 7 ------- - test/clear.sh | 4 +--- - test/common | 15 +++++++++++++++ - test/create.sh | 4 +--- - test/daxctl-create.sh | 4 ++-- - test/daxdev-errors.sh | 4 +--- - test/firmware-update.sh | 8 +++----- - test/inject-error.sh | 7 ------- - test/max_available_extent_ns.sh | 9 +-------- - test/monitor.sh | 11 ++--------- - test/multi-dax.sh | 4 +--- - test/pfn-meta-errors.sh | 4 +--- - test/pmem-errors.sh | 4 +--- - test/rescan-partitions.sh | 7 ------- - test/sector-mode.sh | 9 ++------- - test/track-uuid.sh | 4 +--- - 19 files changed, 36 insertions(+), 92 deletions(-) - -diff --git a/test/blk-exhaust.sh b/test/blk-exhaust.sh -index 09c4aae..b6d3808 100755 ---- a/test/blk-exhaust.sh -+++ b/test/blk-exhaust.sh -@@ -14,9 +14,7 @@ trap 'err $LINENO' ERR - - # setup (reset nfit_test dimms) - modprobe nfit_test --$NDCTL disable-region -b $NFIT_TEST_BUS0 all --$NDCTL zero-labels -b $NFIT_TEST_BUS0 all --$NDCTL enable-region -b $NFIT_TEST_BUS0 all -+reset - - # if the kernel accounting is correct we should be able to create two - # pmem and two blk namespaces on nfit_test.0 -diff --git a/test/btt-check.sh b/test/btt-check.sh -index 8e0b489..65b5c58 100755 ---- a/test/btt-check.sh -+++ b/test/btt-check.sh -@@ -39,13 +39,6 @@ create() - [ $size -gt 0 ] || err "$LINENO" - } - --reset() --{ -- $NDCTL disable-region -b $NFIT_TEST_BUS0 all -- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all -- $NDCTL enable-region -b $NFIT_TEST_BUS0 all --} -- - # re-enable the BTT namespace, and do IO to it in an attempt to - # verify it still comes up ok, and functions as expected - post_repair_test() -diff --git a/test/btt-errors.sh b/test/btt-errors.sh -index 4e59f57..5a20d26 100755 ---- a/test/btt-errors.sh -+++ b/test/btt-errors.sh -@@ -45,9 +45,7 @@ trap 'err $LINENO cleanup' ERR - - # setup (reset nfit_test dimms) - modprobe nfit_test --$NDCTL disable-region -b $NFIT_TEST_BUS0 all --$NDCTL zero-labels -b $NFIT_TEST_BUS0 all --$NDCTL enable-region -b $NFIT_TEST_BUS0 all -+reset - - rc=1 - -@@ -126,9 +124,7 @@ dd if=$MNT/$FILE of=/dev/null iflag=direct bs=4096 count=1 - - # reset everything to get a clean log - if grep -q "$MNT" /proc/mounts; then umount $MNT; fi --$NDCTL disable-region -b $NFIT_TEST_BUS0 all --$NDCTL zero-labels -b $NFIT_TEST_BUS0 all --$NDCTL enable-region -b $NFIT_TEST_BUS0 all -+reset - dev="x" - json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem -m sector) - eval "$(echo "$json" | json2var)" -@@ -148,9 +144,7 @@ force_raw 0 - dd if=/dev/$blockdev of=/dev/null iflag=direct bs=4096 count=1 && err $LINENO || true - - # done, exit --$NDCTL disable-region -b $NFIT_TEST_BUS0 all --$NDCTL zero-labels -b $NFIT_TEST_BUS0 all --$NDCTL enable-region -b $NFIT_TEST_BUS0 all -+reset - cleanup - _cleanup - exit 0 -diff --git a/test/btt-pad-compat.sh b/test/btt-pad-compat.sh -index bf1ea54..be538b7 100755 ---- a/test/btt-pad-compat.sh -+++ b/test/btt-pad-compat.sh -@@ -37,13 +37,6 @@ create() - fi - } - --reset() --{ -- $NDCTL disable-region -b $NFIT_TEST_BUS0 all -- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all -- $NDCTL enable-region -b $NFIT_TEST_BUS0 all --} -- - verify_idx() - { - idx0="$1" -diff --git a/test/clear.sh b/test/clear.sh -index fb9d52c..c4d02d5 100755 ---- a/test/clear.sh -+++ b/test/clear.sh -@@ -14,9 +14,7 @@ trap 'err $LINENO' ERR - - # setup (reset nfit_test dimms) - modprobe nfit_test --$NDCTL disable-region -b $NFIT_TEST_BUS0 all --$NDCTL zero-labels -b $NFIT_TEST_BUS0 all --$NDCTL enable-region -b $NFIT_TEST_BUS0 all -+reset - - rc=1 - -diff --git a/test/common b/test/common -index 6bcefca..3c54d63 100644 ---- a/test/common -+++ b/test/common -@@ -46,6 +46,21 @@ err() - exit $rc - } - -+reset() -+{ -+ $NDCTL disable-region -b $NFIT_TEST_BUS0 all -+ $NDCTL zero-labels -b $NFIT_TEST_BUS0 all -+ $NDCTL enable-region -b $NFIT_TEST_BUS0 all -+} -+ -+reset1() -+{ -+ $NDCTL disable-region -b $NFIT_TEST_BUS1 all -+ $NDCTL zero-labels -b $NFIT_TEST_BUS1 all -+ $NDCTL enable-region -b $NFIT_TEST_BUS1 all -+} -+ -+ - # check_min_kver - # $1: Supported kernel version. format: X.Y - # -diff --git a/test/create.sh b/test/create.sh -index b0fd99f..e9baaa0 100755 ---- a/test/create.sh -+++ b/test/create.sh -@@ -15,9 +15,7 @@ trap 'err $LINENO' ERR - - # setup (reset nfit_test dimms) - modprobe nfit_test --$NDCTL disable-region -b $NFIT_TEST_BUS0 all --$NDCTL zero-labels -b $NFIT_TEST_BUS0 all --$NDCTL enable-region -b $NFIT_TEST_BUS0 all -+reset - - rc=1 - -diff --git a/test/daxctl-create.sh b/test/daxctl-create.sh -index 198779a..d319a39 100755 ---- a/test/daxctl-create.sh -+++ b/test/daxctl-create.sh -@@ -10,7 +10,7 @@ trap 'cleanup $LINENO' ERR - cleanup() - { - printf "Error at line %d\n" "$1" -- [[ $testdev ]] && reset -+ [[ $testdev ]] && reset_dax - exit $rc - } - -@@ -70,7 +70,7 @@ reset_dev() - "$DAXCTL" enable-device "$testdev" - } - --reset() -+reset_dax() - { - test -n "$testdev" - -diff --git a/test/daxdev-errors.sh b/test/daxdev-errors.sh -index 9547d78..e13453d 100755 ---- a/test/daxdev-errors.sh -+++ b/test/daxdev-errors.sh -@@ -15,9 +15,7 @@ trap 'err $LINENO' ERR - - # setup (reset nfit_test dimms) - modprobe nfit_test --$NDCTL disable-region -b $NFIT_TEST_BUS0 all --$NDCTL zero-labels -b $NFIT_TEST_BUS0 all --$NDCTL enable-region -b $NFIT_TEST_BUS0 all -+reset - - rc=1 - -diff --git a/test/firmware-update.sh b/test/firmware-update.sh -index 8cc9c41..93ce166 100755 ---- a/test/firmware-update.sh -+++ b/test/firmware-update.sh -@@ -10,11 +10,9 @@ image="update-fw.img" - - trap 'err $LINENO' ERR - --reset() -+fwupd_reset() - { -- $NDCTL disable-region -b $NFIT_TEST_BUS0 all -- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all -- $NDCTL enable-region -b $NFIT_TEST_BUS0 all -+ reset - if [ -f $image ]; then - rm -f $image - fi -@@ -73,7 +71,7 @@ do_tests() - check_min_kver "4.16" || do_skip "may lack firmware update test handling" - - modprobe nfit_test --reset -+fwupd_reset - detect - rc=1 - do_tests -diff --git a/test/inject-error.sh b/test/inject-error.sh -index 7d0b826..fd823b6 100755 ---- a/test/inject-error.sh -+++ b/test/inject-error.sh -@@ -37,13 +37,6 @@ create() - [ $size -gt 0 ] || err "$LINENO" - } - --reset() --{ -- $NDCTL disable-region -b $NFIT_TEST_BUS0 all -- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all -- $NDCTL enable-region -b $NFIT_TEST_BUS0 all --} -- - check_status() - { - local sector="$1" -diff --git a/test/max_available_extent_ns.sh b/test/max_available_extent_ns.sh -index 343f3c9..47a921f 100755 ---- a/test/max_available_extent_ns.sh -+++ b/test/max_available_extent_ns.sh -@@ -11,13 +11,6 @@ trap 'err $LINENO' ERR - check_min_kver "4.19" || do_skip "kernel $KVER may not support max_available_size" - check_prereq "jq" - --init() --{ -- $NDCTL disable-region -b $NFIT_TEST_BUS0 all -- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all -- $NDCTL enable-region -b $NFIT_TEST_BUS0 all --} -- - do_test() - { - region=$($NDCTL list -b $NFIT_TEST_BUS0 -R -t pmem | jq -r 'sort_by(-.size) | .[].dev' | head -1) -@@ -40,7 +33,7 @@ do_test() - - modprobe nfit_test - rc=1 --init -+reset - do_test - _cleanup - exit 0 -diff --git a/test/monitor.sh b/test/monitor.sh -index c015c11..6aa4196 100755 ---- a/test/monitor.sh -+++ b/test/monitor.sh -@@ -19,13 +19,6 @@ trap 'err $LINENO' ERR - - check_min_kver "4.15" || do_skip "kernel $KVER may not support monitor service" - --init() --{ -- $NDCTL disable-region -b $NFIT_TEST_BUS0 all -- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all -- $NDCTL enable-region -b $NFIT_TEST_BUS0 all --} -- - start_monitor() - { - logfile=$(mktemp) -@@ -112,7 +105,7 @@ test_filter_region() - - test_filter_namespace() - { -- init -+ reset - monitor_namespace=$($NDCTL create-namespace -b $smart_supported_bus | jq -r .dev) - monitor_dimms=$(get_monitor_dimm "-n $monitor_namespace") - start_monitor "-n $monitor_namespace" -@@ -170,7 +163,7 @@ do_tests() - - modprobe nfit_test - rc=1 --init -+reset - set_smart_supported_bus - do_tests - _cleanup -diff --git a/test/multi-dax.sh b/test/multi-dax.sh -index b343a38..04070ad 100755 ---- a/test/multi-dax.sh -+++ b/test/multi-dax.sh -@@ -17,9 +17,7 @@ ALIGN_SIZE=`getconf PAGESIZE` - - # setup (reset nfit_test dimms) - modprobe nfit_test --$NDCTL disable-region -b $NFIT_TEST_BUS0 all --$NDCTL zero-labels -b $NFIT_TEST_BUS0 all --$NDCTL enable-region -b $NFIT_TEST_BUS0 all -+reset - rc=1 - - query=". | sort_by(.available_size) | reverse | .[0].dev" -diff --git a/test/pfn-meta-errors.sh b/test/pfn-meta-errors.sh -index 0ade2e5..6314897 100755 ---- a/test/pfn-meta-errors.sh -+++ b/test/pfn-meta-errors.sh -@@ -29,9 +29,7 @@ trap 'err $LINENO' ERR - - # setup (reset nfit_test dimms) - modprobe nfit_test --$NDCTL disable-region -b $NFIT_TEST_BUS0 all --$NDCTL zero-labels -b $NFIT_TEST_BUS0 all --$NDCTL enable-region -b $NFIT_TEST_BUS0 all -+reset - - rc=1 - -diff --git a/test/pmem-errors.sh b/test/pmem-errors.sh -index 4225c3b..2065780 100755 ---- a/test/pmem-errors.sh -+++ b/test/pmem-errors.sh -@@ -28,9 +28,7 @@ trap 'err $LINENO cleanup' ERR - - # setup (reset nfit_test dimms) - modprobe nfit_test --$NDCTL disable-region -b $NFIT_TEST_BUS0 all --$NDCTL zero-labels -b $NFIT_TEST_BUS0 all --$NDCTL enable-region -b $NFIT_TEST_BUS0 all -+reset - - rc=1 - -diff --git a/test/rescan-partitions.sh b/test/rescan-partitions.sh -index 1686de3..51bbd73 100755 ---- a/test/rescan-partitions.sh -+++ b/test/rescan-partitions.sh -@@ -25,13 +25,6 @@ check_min_kver "4.16" || do_skip "may not contain fixes for partition rescanning - check_prereq "parted" - check_prereq "blockdev" - --reset() --{ -- $NDCTL disable-region -b $NFIT_TEST_BUS0 all -- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all -- $NDCTL enable-region -b $NFIT_TEST_BUS0 all --} -- - test_mode() - { - local mode="$1" -diff --git a/test/sector-mode.sh b/test/sector-mode.sh -index 7a2faea..439ef33 100755 ---- a/test/sector-mode.sh -+++ b/test/sector-mode.sh -@@ -15,13 +15,8 @@ ALIGN_SIZE=`getconf PAGESIZE` - - # setup (reset nfit_test dimms) - modprobe nfit_test --$NDCTL disable-region -b $NFIT_TEST_BUS0 all --$NDCTL zero-labels -b $NFIT_TEST_BUS0 all --$NDCTL enable-region -b $NFIT_TEST_BUS0 all -- --$NDCTL disable-region -b $NFIT_TEST_BUS1 all --$NDCTL zero-labels -b $NFIT_TEST_BUS1 all --$NDCTL enable-region -b $NFIT_TEST_BUS1 all -+reset -+reset1 - - rc=1 - query=". | sort_by(.size) | reverse | .[0].dev" -diff --git a/test/track-uuid.sh b/test/track-uuid.sh -index be3cf9c..3bacd2c 100755 ---- a/test/track-uuid.sh -+++ b/test/track-uuid.sh -@@ -12,9 +12,7 @@ trap 'err $LINENO' ERR - - # setup (reset nfit_test dimms) - modprobe nfit_test --$NDCTL disable-region -b $NFIT_TEST_BUS0 all --$NDCTL zero-labels -b $NFIT_TEST_BUS0 all --$NDCTL enable-region -b $NFIT_TEST_BUS0 all -+reset - - rc=1 - --- -2.27.0 - diff --git a/SOURCES/0072-ndctl-test-Initialize-the-label-area-by-default.patch b/SOURCES/0072-ndctl-test-Initialize-the-label-area-by-default.patch deleted file mode 100644 index ba3de4d..0000000 --- a/SOURCES/0072-ndctl-test-Initialize-the-label-area-by-default.patch +++ /dev/null @@ -1,104 +0,0 @@ -From fe37c85f1ffb0b2d04ef60e8ece6a9a44a145cc5 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:32:00 -0800 -Subject: [PATCH 072/217] ndctl/test: Initialize the label area by default - -The removal of BLK-mode support causes nfit_test regions to not be -'aliased' by default, which means that the only way to enable labels is to -initialize the namespace label index block. In support of that the common -'reset()' helper is updated to initialize v1.1 labels instead of zero them. -Additionally, it highlighted that some btt tests have silent assumptions of -v1.1 vs v1.2 label support. Add a 'resetV()' alternative to the common -'reset()' function that initializes the label area to v1.2. - -Link: https://lore.kernel.org/r/164141832017.3990253.10383328274835531066.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/btt-errors.sh | 4 ++-- - test/btt-pad-compat.sh | 2 +- - test/common | 11 +++++++++-- - test/label-compat.sh | 2 +- - 4 files changed, 13 insertions(+), 6 deletions(-) - -diff --git a/test/btt-errors.sh b/test/btt-errors.sh -index 5a20d26..6e69178 100755 ---- a/test/btt-errors.sh -+++ b/test/btt-errors.sh -@@ -45,7 +45,7 @@ trap 'err $LINENO cleanup' ERR - - # setup (reset nfit_test dimms) - modprobe nfit_test --reset -+resetV - - rc=1 - -@@ -124,7 +124,7 @@ dd if=$MNT/$FILE of=/dev/null iflag=direct bs=4096 count=1 - - # reset everything to get a clean log - if grep -q "$MNT" /proc/mounts; then umount $MNT; fi --reset -+resetV - dev="x" - json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem -m sector) - eval "$(echo "$json" | json2var)" -diff --git a/test/btt-pad-compat.sh b/test/btt-pad-compat.sh -index be538b7..005316a 100755 ---- a/test/btt-pad-compat.sh -+++ b/test/btt-pad-compat.sh -@@ -148,7 +148,7 @@ do_tests() - verify_idx 0 1 - - # do the same with an old format namespace -- reset -+ resetV - create_oldfmt_ns - verify_idx 0 2 - -diff --git a/test/common b/test/common -index 3c54d63..b6d4712 100644 ---- a/test/common -+++ b/test/common -@@ -49,14 +49,21 @@ err() - reset() - { - $NDCTL disable-region -b $NFIT_TEST_BUS0 all -- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all -+ $NDCTL init-labels -f -b $NFIT_TEST_BUS0 all -+ $NDCTL enable-region -b $NFIT_TEST_BUS0 all -+} -+ -+resetV() -+{ -+ $NDCTL disable-region -b $NFIT_TEST_BUS0 all -+ $NDCTL init-labels -f -V 1.2 -b $NFIT_TEST_BUS0 all - $NDCTL enable-region -b $NFIT_TEST_BUS0 all - } - - reset1() - { - $NDCTL disable-region -b $NFIT_TEST_BUS1 all -- $NDCTL zero-labels -b $NFIT_TEST_BUS1 all -+ $NDCTL init-labels -f -b $NFIT_TEST_BUS1 all - $NDCTL enable-region -b $NFIT_TEST_BUS1 all - } - -diff --git a/test/label-compat.sh b/test/label-compat.sh -index 8ab2858..7ae4d5e 100755 ---- a/test/label-compat.sh -+++ b/test/label-compat.sh -@@ -17,7 +17,7 @@ trap 'err $LINENO' ERR - # setup (reset nfit_test dimms) - modprobe nfit_test - $NDCTL disable-region -b $NFIT_TEST_BUS0 all --$NDCTL zero-labels -b $NFIT_TEST_BUS0 all -+$NDCTL init-labels -f -b $NFIT_TEST_BUS0 all - - # grab the largest pmem region on -b $NFIT_TEST_BUS0 - query=". | sort_by(.available_size) | reverse | .[0].dev" --- -2.27.0 - diff --git a/SOURCES/0073-ndctl-test-Skip-BLK-flags-checks.patch b/SOURCES/0073-ndctl-test-Skip-BLK-flags-checks.patch deleted file mode 100644 index 6933080..0000000 --- a/SOURCES/0073-ndctl-test-Skip-BLK-flags-checks.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 756a6598a0fa6cebdd0e98564af089ca6b463fb1 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:32:05 -0800 -Subject: [PATCH 073/217] ndctl/test: Skip BLK flags checks - -With the removal of BLK-mode support, test/libndctl will fail to detect the -JEDEC format on the nfit_test bus. Report + skip that check rather than -fail the test when that happens. - -Link: https://lore.kernel.org/r/164141832529.3990253.16538298357542644310.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/libndctl.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/test/libndctl.c b/test/libndctl.c -index c0e4b4c..1e97926 100644 ---- a/test/libndctl.c -+++ b/test/libndctl.c -@@ -2535,7 +2535,7 @@ static int check_dimms(struct ndctl_bus *bus, struct dimm *dimms, int n, - fprintf(stderr, "dimm%d expected formats: %d got: %d\n", - i, dimms[i].formats, - ndctl_dimm_get_formats(dimm)); -- return -ENXIO; -+ fprintf(stderr, "continuing...\n"); - } - for (j = 0; j < dimms[i].formats; j++) { - if (ndctl_dimm_get_formatN(dimm, j) != dimms[i].format[j]) { -@@ -2543,7 +2543,7 @@ static int check_dimms(struct ndctl_bus *bus, struct dimm *dimms, int n, - "dimm%d expected format[%d]: %d got: %d\n", - i, j, dimms[i].format[j], - ndctl_dimm_get_formatN(dimm, j)); -- return -ENXIO; -+ fprintf(stderr, "continuing...\n"); - } - } - } --- -2.27.0 - diff --git a/SOURCES/0074-ndctl-test-Move-sector-mode-to-a-different-region.patch b/SOURCES/0074-ndctl-test-Move-sector-mode-to-a-different-region.patch deleted file mode 100644 index d69249e..0000000 --- a/SOURCES/0074-ndctl-test-Move-sector-mode-to-a-different-region.patch +++ /dev/null @@ -1,41 +0,0 @@ -From b787320498508192f1e04ac38d39da4eb3ca26e9 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:32:10 -0800 -Subject: [PATCH 074/217] ndctl/test: Move sector-mode to a different region - -Previously the largest region on the nfit_test.1 bus belonged to a BLK-mode -region. With the removal of BLK-mode support update the test to instead -find a suitable PMEM region to perform the checkout. - -Link: https://lore.kernel.org/r/164141833068.3990253.15694496866707006837.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/sector-mode.sh | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/test/sector-mode.sh b/test/sector-mode.sh -index 439ef33..f70b0f1 100755 ---- a/test/sector-mode.sh -+++ b/test/sector-mode.sh -@@ -19,11 +19,11 @@ reset - reset1 - - rc=1 --query=". | sort_by(.size) | reverse | .[0].dev" --NAMESPACE=$($NDCTL list -b $NFIT_TEST_BUS1 -N | jq -r "$query") --REGION=$($NDCTL list -R --namespace=$NAMESPACE | jq -r "(.[]) | .dev") -+query=". | sort_by(.available_size) | reverse | .[0].dev" -+REGION=$($NDCTL list -R -b $NFIT_TEST_BUS1 | jq -r "$query") - echo 0 > /sys/bus/nd/devices/$REGION/read_only --$NDCTL create-namespace --no-autolabel -e $NAMESPACE -m sector -f -l 4K -+echo $ALIGN_SIZE > /sys/bus/nd/devices/$REGION/align -+NAMESPACE=$($NDCTL create-namespace --no-autolabel -r $REGION -m sector -f -l 4K | jq -r ".dev") - $NDCTL create-namespace --no-autolabel -e $NAMESPACE -m dax -f -a $ALIGN_SIZE - $NDCTL create-namespace --no-autolabel -e $NAMESPACE -m sector -f -l 4K - --- -2.27.0 - diff --git a/SOURCES/0075-ndctl-Deprecate-BLK-aperture-support.patch b/SOURCES/0075-ndctl-Deprecate-BLK-aperture-support.patch deleted file mode 100644 index 556f887..0000000 --- a/SOURCES/0075-ndctl-Deprecate-BLK-aperture-support.patch +++ /dev/null @@ -1,1966 +0,0 @@ -From 2e05cd6b4aee656f69e11cf8b5e280dd47a14b1b Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:32:15 -0800 -Subject: [PATCH 075/217] ndctl: Deprecate BLK aperture support - -The kernel is dropping its BLK aperture support, so deprecate the same in -ndctl. The options will still be supported, and the library calls will not -be deleted in case code needs them to compile. However the documentation -and the tests for BLK mode can be removed. - -Link: https://lore.kernel.org/r/164141833579.3990253.17885822648406789915.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .gitignore | 4 - - Documentation/ndctl/labels-description.txt | 5 +- - .../ndctl/ndctl-create-namespace.txt | 29 +- - Documentation/ndctl/ndctl-init-labels.txt | 7 +- - Documentation/ndctl/ndctl-list.txt | 4 - - Documentation/ndctl/region-description.txt | 10 +- - README.md | 1 - - contrib/nfit_test_depmod.conf | 1 - - ndctl/Makefile.am | 6 +- - ndctl/bat.c | 5 - - ndctl/test.c | 11 - - test.h | 3 - - test/Makefile.am | 31 -- - test/blk-exhaust.sh | 30 -- - test/blk_namespaces.c | 357 ------------------ - test/core.c | 1 - - test/create.sh | 13 - - test/dpa-alloc.c | 326 ---------------- - test/libndctl.c | 198 ++-------- - test/multi-pmem.c | 285 -------------- - test/parent-uuid.c | 254 ------------- - 21 files changed, 51 insertions(+), 1530 deletions(-) - delete mode 100755 test/blk-exhaust.sh - delete mode 100644 test/blk_namespaces.c - delete mode 100644 test/dpa-alloc.c - delete mode 100644 test/multi-pmem.c - delete mode 100644 test/parent-uuid.c - -diff --git a/.gitignore b/.gitignore -index 6468c7a..6b19d90 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -42,20 +42,16 @@ cscope*.out - tags - test/*.log - test/*.trs --test/blk-ns - test/dax-dev - test/dax-errors - test/dax-pmd - test/daxdev-errors - test/device-dax --test/dpa-alloc - test/dsm-fail - test/hugetlb - test/image - test/libndctl - test/mmap --test/multi-pmem --test/parent-uuid - test/pmem-ns - test/smart-listen - test/smart-notify -diff --git a/Documentation/ndctl/labels-description.txt b/Documentation/ndctl/labels-description.txt -index 6244a49..a246edc 100644 ---- a/Documentation/ndctl/labels-description.txt -+++ b/Documentation/ndctl/labels-description.txt -@@ -3,6 +3,5 @@ - DESCRIPTION - ----------- - The namespace label area is a small persistent partition of capacity --available on some NVDIMM devices. The label area is used to resolve --aliasing between 'pmem' and 'blk' capacity by delineating namespace --boundaries. -+available on some NVDIMM devices. The label area is used to provision -+one, or more, namespaces from regions. -diff --git a/Documentation/ndctl/ndctl-create-namespace.txt b/Documentation/ndctl/ndctl-create-namespace.txt -index 92a89dd..afb085e 100644 ---- a/Documentation/ndctl/ndctl-create-namespace.txt -+++ b/Documentation/ndctl/ndctl-create-namespace.txt -@@ -28,27 +28,17 @@ ndctl create-namespace -f -e namespace0.0 --mode=sector - - OPTIONS - ------- ---t:: ----type=:: -- Create a 'pmem' or 'blk' namespace (subject to available -- capacity). A pmem namespace supports the dax (direct access) -- capability to linkndctl:mmap[2] persistent memory directly into -- a process address space. A blk namespace access persistent -- memory through a block-window-aperture. Compared to pmem it -- supports a traditional storage error model (EIO on error rather -- than a cpu exception on a bad memory access), but it does not -- support dax. -- - -m:: - --mode=:: - - "raw": expose the namespace capacity directly with -- limitations. Neither a raw pmem namepace nor raw blk -- namespace support sector atomicity by default (see "sector" -- mode below). A raw pmem namespace may have limited to no dax -- support depending the kernel. In other words operations like -- direct-I/O targeting a dax buffer may fail for a pmem -- namespace in raw mode or indirect through a page-cache buffer. -- See "fsdax" and "devdax" mode for dax operation. -+ limitations. A raw pmem namepace namespace does not support -+ sector atomicity (see "sector" mode below). A raw pmem -+ namespace may have limited to no dax support depending the -+ kernel. In other words operations like direct-I/O targeting a -+ dax buffer may fail for a pmem namespace in raw mode or -+ indirect through a page-cache buffer. See "fsdax" and -+ "devdax" mode for dax operation. -+ - - - "sector": persistent memory, given that it is byte - addressable, does not support sector atomicity. The -@@ -206,8 +196,7 @@ OPTIONS - * NVDIMM does not support labels - - * The NVDIMM supports labels, but the Label Index Block (see -- UEFI 2.7) is not present and there is no capacity aliasing -- between 'blk' and 'pmem' regions. -+ UEFI 2.7) is not present. - - - In the latter case the configuration can be upgraded to - labelled operation by writing an index block on all DIMMs in a -diff --git a/Documentation/ndctl/ndctl-init-labels.txt b/Documentation/ndctl/ndctl-init-labels.txt -index 733ef0e..73685b3 100644 ---- a/Documentation/ndctl/ndctl-init-labels.txt -+++ b/Documentation/ndctl/ndctl-init-labels.txt -@@ -13,10 +13,9 @@ SYNOPSIS - 'ndctl init-labels' [..] [] - - include::labels-description.txt[] --By default, and in kernels prior to v4.10, the kernel only honors labels --when a DIMM aliases PMEM and BLK capacity. Starting with v4.10 the --kernel will honor labels for sub-dividing PMEM if all the DIMMs in an --interleave set / region have a valid namespace index block. -+Starting with v4.10 the kernel will honor labels for sub-dividing PMEM -+if all the DIMMs in an interleave set / region have a valid namespace -+index block. - - This command can be used to initialize the namespace index block if it - is missing or reinitialize it if it is damaged. Note that -diff --git a/Documentation/ndctl/ndctl-list.txt b/Documentation/ndctl/ndctl-list.txt -index b8d517d..2922f10 100644 ---- a/Documentation/ndctl/ndctl-list.txt -+++ b/Documentation/ndctl/ndctl-list.txt -@@ -82,10 +82,6 @@ include::xable-bus-options.txt[] - 'X.Y'. Limit the namespace list to the single identified device - if present. - ---t:: ----type=:: -- Filter listing by region type ('pmem' or 'blk') -- - -m:: - --mode=:: - Filter listing by the mode ('raw', 'fsdax', 'sector' or 'devdax') -diff --git a/Documentation/ndctl/region-description.txt b/Documentation/ndctl/region-description.txt -index c14416a..ce268a0 100644 ---- a/Documentation/ndctl/region-description.txt -+++ b/Documentation/ndctl/region-description.txt -@@ -2,9 +2,7 @@ - - DESCRIPTION - ----------- --A generic REGION device is registered for each PMEM range or --BLK-aperture set. LIBNVDIMM provides a built-in driver for these REGION --devices. This driver is responsible for reconciling the aliased DPA --mappings across all regions, parsing the LABEL, if present, and then --emitting NAMESPACE devices with the resolved/exclusive DPA-boundaries --for the nd_pmem or nd_blk device driver to consume. -+A generic REGION device is registered for each PMEM range / -+interleave-set. LIBNVDIMM provides a built-in driver for these REGION -+devices. This driver is responsible for parsing namespace labels and -+instantiating PMEM namespaces for each coherent set of labels. -diff --git a/README.md b/README.md -index 89dfc87..6f36a6d 100644 ---- a/README.md -+++ b/README.md -@@ -110,7 +110,6 @@ override dax_pmem * extra - override dax_pmem_core * extra - override dax_pmem_compat * extra - override libnvdimm * extra --override nd_blk * extra - override nd_btt * extra - override nd_e820 * extra - override nd_pmem * extra -diff --git a/contrib/nfit_test_depmod.conf b/contrib/nfit_test_depmod.conf -index 9f8498e..0e0574e 100644 ---- a/contrib/nfit_test_depmod.conf -+++ b/contrib/nfit_test_depmod.conf -@@ -5,7 +5,6 @@ override dax_pmem * extra - override dax_pmem_core * extra - override dax_pmem_compat * extra - override libnvdimm * extra --override nd_blk * extra - override nd_btt * extra - override nd_e820 * extra - override nd_pmem * extra -diff --git a/ndctl/Makefile.am b/ndctl/Makefile.am -index 4e99510..93b682e 100644 ---- a/ndctl/Makefile.am -+++ b/ndctl/Makefile.am -@@ -45,8 +45,7 @@ endif - EXTRA_DIST += keys.readme monitor.conf ndctl-monitor.service - - if ENABLE_DESTRUCTIVE --ndctl_SOURCES += ../test/blk_namespaces.c \ -- ../test/pmem_namespaces.c -+ndctl_SOURCES += ../test/pmem_namespaces.c - ndctl_SOURCES += bat.c - endif - -@@ -67,9 +66,6 @@ if ENABLE_TEST - ndctl_SOURCES += ../test/libndctl.c \ - ../test/dsm-fail.c \ - ../util/sysfs.c \ -- ../test/dpa-alloc.c \ -- ../test/parent-uuid.c \ -- ../test/multi-pmem.c \ - ../test/core.c \ - test.c - endif -diff --git a/ndctl/bat.c b/ndctl/bat.c -index ef00a3b..13e964d 100644 ---- a/ndctl/bat.c -+++ b/ndctl/bat.c -@@ -41,11 +41,6 @@ int cmd_bat(int argc, const char **argv, struct ndctl_ctx *ctx) - return EXIT_FAILURE; - } - -- rc = test_blk_namespaces(loglevel, test, ctx); -- fprintf(stderr, "test_blk_namespaces: %s\n", rc ? "FAIL" : "PASS"); -- if (rc && rc != 77) -- return rc; -- - rc = test_pmem_namespaces(loglevel, test, ctx); - fprintf(stderr, "test_pmem_namespaces: %s\n", rc ? "FAIL" : "PASS"); - return ndctl_test_result(test, rc); -diff --git a/ndctl/test.c b/ndctl/test.c -index 6a05d8d..a0f5bc9 100644 ---- a/ndctl/test.c -+++ b/ndctl/test.c -@@ -58,16 +58,5 @@ int cmd_test(int argc, const char **argv, struct ndctl_ctx *ctx) - if (rc && rc != 77) - return rc; - -- rc = test_dpa_alloc(loglevel, test, ctx); -- fprintf(stderr, "test-dpa-alloc: %s\n", result(rc)); -- if (rc && rc != 77) -- return rc; -- -- rc = test_parent_uuid(loglevel, test, ctx); -- fprintf(stderr, "test-parent-uuid: %s\n", result(rc)); -- -- rc = test_multi_pmem(loglevel, test, ctx); -- fprintf(stderr, "test-multi-pmem: %s\n", result(rc)); -- - return ndctl_test_result(test, rc); - } -diff --git a/test.h b/test.h -index 7de13fe..b2267e6 100644 ---- a/test.h -+++ b/test.h -@@ -26,7 +26,6 @@ int ndctl_test_init(struct kmod_ctx **ctx, struct kmod_module **mod, - - struct ndctl_ctx; - int test_parent_uuid(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx); --int test_multi_pmem(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx); - int test_dax_directio(int dax_fd, unsigned long align, void *dax_addr, off_t offset); - int test_dax_remap(struct ndctl_test *test, int dax_fd, unsigned long align, void *dax_addr, - off_t offset, bool fsdax); -@@ -40,9 +39,7 @@ static inline int test_dax_poison(struct ndctl_test *test, int dax_fd, - return 0; - } - #endif --int test_dpa_alloc(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx); - int test_dsm_fail(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx); - int test_libndctl(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx); --int test_blk_namespaces(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx); - int test_pmem_namespaces(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx); - #endif /* __TEST_H__ */ -diff --git a/test/Makefile.am b/test/Makefile.am -index c5b8764..a5a54df 100644 ---- a/test/Makefile.am -+++ b/test/Makefile.am -@@ -3,9 +3,6 @@ include $(top_srcdir)/Makefile.am.in - TESTS =\ - libndctl \ - dsm-fail \ -- dpa-alloc \ -- parent-uuid \ -- multi-pmem \ - create.sh \ - clear.sh \ - pmem-errors.sh \ -@@ -13,7 +10,6 @@ TESTS =\ - multi-dax.sh \ - btt-check.sh \ - label-compat.sh \ -- blk-exhaust.sh \ - sector-mode.sh \ - inject-error.sh \ - btt-errors.sh \ -@@ -35,9 +31,6 @@ EXTRA_DIST += $(TESTS) common \ - check_PROGRAMS =\ - libndctl \ - dsm-fail \ -- dpa-alloc \ -- parent-uuid \ -- multi-pmem \ - dax-errors \ - smart-notify \ - smart-listen \ -@@ -48,7 +41,6 @@ check_PROGRAMS =\ - - if ENABLE_DESTRUCTIVE - TESTS +=\ -- blk-ns \ - pmem-ns \ - sub-section.sh \ - dax-dev \ -@@ -68,7 +60,6 @@ TESTS += security.sh - endif - - check_PROGRAMS +=\ -- blk-ns \ - pmem-ns \ - dax-dev \ - dax-pmd \ -@@ -108,18 +99,9 @@ ack_shutdown_count_set_SOURCES =\ - - ack_shutdown_count_set_LDADD = $(LIBNDCTL_LIB) $(KMOD_LIBS) - --blk_ns_SOURCES = blk_namespaces.c $(testcore) --blk_ns_LDADD = $(LIBNDCTL_LIB) $(KMOD_LIBS) $(UUID_LIBS) -- - pmem_ns_SOURCES = pmem_namespaces.c $(testcore) - pmem_ns_LDADD = $(LIBNDCTL_LIB) $(KMOD_LIBS) $(UUID_LIBS) - --dpa_alloc_SOURCES = dpa-alloc.c $(testcore) --dpa_alloc_LDADD = $(LIBNDCTL_LIB) $(UUID_LIBS) $(KMOD_LIBS) -- --parent_uuid_SOURCES = parent-uuid.c $(testcore) --parent_uuid_LDADD = $(LIBNDCTL_LIB) $(UUID_LIBS) $(KMOD_LIBS) -- - dax_dev_SOURCES = dax-dev.c $(testcore) - dax_dev_LDADD = $(LIBNDCTL_LIB) $(KMOD_LIBS) - -@@ -169,19 +151,6 @@ smart_notify_LDADD = $(LIBNDCTL_LIB) - smart_listen_SOURCES = smart-listen.c - smart_listen_LDADD = $(LIBNDCTL_LIB) - --multi_pmem_SOURCES = \ -- multi-pmem.c \ -- $(testcore) \ -- ../ndctl/namespace.c \ -- ../ndctl/check.c \ -- ../util/json.c --multi_pmem_LDADD = \ -- $(LIBNDCTL_LIB) \ -- $(JSON_LIBS) \ -- $(UUID_LIBS) \ -- $(KMOD_LIBS) \ -- ../libutil.a -- - list_smart_dimm_SOURCES = \ - list-smart-dimm.c \ - ../util/json.c -diff --git a/test/blk-exhaust.sh b/test/blk-exhaust.sh -deleted file mode 100755 -index b6d3808..0000000 ---- a/test/blk-exhaust.sh -+++ /dev/null -@@ -1,30 +0,0 @@ --#!/bin/bash -x --# SPDX-License-Identifier: GPL-2.0 --# Copyright (C) 2015-2020 Intel Corporation. All rights reserved. -- --set -e -- --rc=77 -- --. $(dirname $0)/common -- --check_min_kver "4.11" || do_skip "may lack blk-exhaustion fix" -- --trap 'err $LINENO' ERR -- --# setup (reset nfit_test dimms) --modprobe nfit_test --reset -- --# if the kernel accounting is correct we should be able to create two --# pmem and two blk namespaces on nfit_test.0 --rc=1 --$NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem --$NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem --$NDCTL create-namespace -b $NFIT_TEST_BUS0 -t blk -m raw --$NDCTL create-namespace -b $NFIT_TEST_BUS0 -t blk -m raw -- --# clearnup and exit --_cleanup -- --exit 0 -diff --git a/test/blk_namespaces.c b/test/blk_namespaces.c -deleted file mode 100644 -index f076e85..0000000 ---- a/test/blk_namespaces.c -+++ /dev/null -@@ -1,357 +0,0 @@ --// SPDX-License-Identifier: LGPL-2.1 --// Copyright (C) 2015-2020, Intel Corporation. All rights reserved. --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --/* The purpose of this test is to verify that we can successfully do I/O to -- * multiple nd_blk namespaces that have discontiguous segments. It first -- * sets up two namespaces, each 1/2 the total size of the NVDIMM and each with -- * two discontiguous segments, arranged like this: -- * -- * +-------+-------+-------+-------+ -- * | nd0 | nd1 | nd0 | nd1 | -- * +-------+-------+-------+-------+ -- * -- * It then runs some I/O to the beginning, middle and end of each of these -- * namespaces, checking data integrity. The I/O to the middle of the -- * namespace will hit two pages, one on either side of the segment boundary. -- */ --#define err(msg)\ -- fprintf(stderr, "%s:%d: %s (%s)\n", __func__, __LINE__, msg, strerror(errno)) -- --static struct ndctl_namespace *create_blk_namespace(int region_fraction, -- struct ndctl_region *region) --{ -- struct ndctl_namespace *ndns, *seed_ns = NULL; -- unsigned long long size; -- uuid_t uuid; -- -- ndctl_region_set_align(region, sysconf(_SC_PAGESIZE)); -- ndctl_namespace_foreach(region, ndns) -- if (ndctl_namespace_get_size(ndns) == 0) { -- seed_ns = ndns; -- break; -- } -- -- if (!seed_ns) -- return NULL; -- -- uuid_generate(uuid); -- size = ndctl_region_get_size(region)/region_fraction; -- -- if (ndctl_namespace_set_uuid(seed_ns, uuid) < 0) -- return NULL; -- -- if (ndctl_namespace_set_size(seed_ns, size) < 0) -- return NULL; -- -- if (ndctl_namespace_set_sector_size(seed_ns, 512) < 0) -- return NULL; -- -- if (ndctl_namespace_enable(seed_ns) < 0) -- return NULL; -- -- return seed_ns; --} -- --static int disable_blk_namespace(struct ndctl_namespace *ndns) --{ -- if (ndctl_namespace_disable_invalidate(ndns) < 0) -- return -ENODEV; -- -- if (ndctl_namespace_delete(ndns) < 0) -- return -ENODEV; -- -- return 0; --} -- --static int ns_do_io(const char *bdev) --{ -- int fd, i; -- int rc = 0; -- const int page_size = 4096; -- const int num_pages = 4; -- unsigned long num_dev_pages, num_blocks; -- off_t addr; -- -- void *random_page[num_pages]; -- void *blk_page[num_pages]; -- -- rc = posix_memalign(random_page, page_size, page_size * num_pages); -- if (rc) { -- fprintf(stderr, "posix_memalign failure\n"); -- return rc; -- } -- -- rc = posix_memalign(blk_page, page_size, page_size * num_pages); -- if (rc) { -- fprintf(stderr, "posix_memalign failure\n"); -- goto err_free_blk; -- } -- -- for (i = 1; i < num_pages; i++) { -- random_page[i] = (char*)random_page[0] + page_size * i; -- blk_page[i] = (char*)blk_page[0] + page_size * i; -- } -- -- /* read random data into random_page */ -- if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { -- err("open"); -- rc = -ENODEV; -- goto err_free_all; -- } -- -- rc = read(fd, random_page[0], page_size * num_pages); -- if (rc < 0) { -- err("read"); -- close(fd); -- goto err_free_all; -- } -- -- close(fd); -- -- if ((fd = open(bdev, O_RDWR|O_DIRECT)) < 0) { -- err("open"); -- rc = -ENODEV; -- goto err_free_all; -- } -- -- ioctl(fd, BLKGETSIZE, &num_blocks); -- num_dev_pages = num_blocks / 8; -- -- /* write the random data out to each of the segments */ -- rc = pwrite(fd, random_page[0], page_size, 0); -- if (rc < 0) { -- err("write"); -- goto err_close; -- } -- -- /* two pages that span the region discontinuity */ -- addr = page_size * (num_dev_pages/2 - 1); -- rc = pwrite(fd, random_page[1], page_size*2, addr); -- if (rc < 0) { -- err("write"); -- goto err_close; -- } -- -- addr = page_size * (num_dev_pages - 1); -- rc = pwrite(fd, random_page[3], page_size, addr); -- if (rc < 0) { -- err("write"); -- goto err_close; -- } -- -- /* read back the random data into blk_page */ -- rc = pread(fd, blk_page[0], page_size, 0); -- if (rc < 0) { -- err("read"); -- goto err_close; -- } -- -- /* two pages that span the region discontinuity */ -- addr = page_size * (num_dev_pages/2 - 1); -- rc = pread(fd, blk_page[1], page_size*2, addr); -- if (rc < 0) { -- err("read"); -- goto err_close; -- } -- -- addr = page_size * (num_dev_pages - 1); -- rc = pread(fd, blk_page[3], page_size, addr); -- if (rc < 0) { -- err("read"); -- goto err_close; -- } -- -- /* verify the data */ -- if (memcmp(random_page[0], blk_page[0], page_size * num_pages)) { -- fprintf(stderr, "Block data miscompare\n"); -- rc = -EIO; -- goto err_close; -- } -- -- rc = 0; -- err_close: -- close(fd); -- err_free_all: -- free(random_page[0]); -- err_free_blk: -- free(blk_page[0]); -- return rc; --} -- --static const char *comm = "test-blk-namespaces"; -- --int test_blk_namespaces(int log_level, struct ndctl_test *test, -- struct ndctl_ctx *ctx) --{ -- char bdev[50]; -- int rc = -ENXIO; -- struct ndctl_bus *bus; -- struct ndctl_dimm *dimm; -- struct kmod_module *mod = NULL; -- struct kmod_ctx *kmod_ctx = NULL; -- struct ndctl_namespace *ndns[2]; -- struct ndctl_region *region, *blk_region = NULL; -- -- if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 2, 0))) -- return 77; -- -- ndctl_set_log_priority(ctx, log_level); -- -- bus = ndctl_bus_get_by_provider(ctx, "ACPI.NFIT"); -- if (bus) { -- /* skip this bus if no BLK regions */ -- ndctl_region_foreach(bus, region) -- if (ndctl_region_get_nstype(region) -- == ND_DEVICE_NAMESPACE_BLK) -- break; -- if (!region) -- bus = NULL; -- } -- -- if (!bus) { -- fprintf(stderr, "ACPI.NFIT unavailable falling back to nfit_test\n"); -- rc = ndctl_test_init(&kmod_ctx, &mod, NULL, log_level, test); -- ndctl_invalidate(ctx); -- bus = ndctl_bus_get_by_provider(ctx, "nfit_test.0"); -- if (rc < 0 || !bus) { -- ndctl_test_skip(test); -- fprintf(stderr, "nfit_test unavailable skipping tests\n"); -- return 77; -- } -- } -- -- fprintf(stderr, "%s: found provider: %s\n", comm, -- ndctl_bus_get_provider(bus)); -- -- /* get the system to a clean state */ -- ndctl_region_foreach(bus, region) -- ndctl_region_disable_invalidate(region); -- -- ndctl_dimm_foreach(bus, dimm) { -- rc = ndctl_dimm_zero_labels(dimm); -- if (rc < 0) { -- fprintf(stderr, "failed to zero %s\n", -- ndctl_dimm_get_devname(dimm)); -- goto err_module; -- } -- } -- -- /* create our config */ -- ndctl_region_foreach(bus, region) -- if (strcmp(ndctl_region_get_type_name(region), "blk") == 0) { -- blk_region = region; -- break; -- } -- -- if (!blk_region || ndctl_region_enable(blk_region) < 0) { -- fprintf(stderr, "%s: failed to find block region\n", comm); -- rc = -ENODEV; -- goto err_cleanup; -- } -- -- rc = -ENODEV; -- ndns[0] = create_blk_namespace(4, blk_region); -- if (!ndns[0]) { -- fprintf(stderr, "%s: failed to create block namespace\n", comm); -- goto err_cleanup; -- } -- -- ndns[1] = create_blk_namespace(4, blk_region); -- if (!ndns[1]) { -- fprintf(stderr, "%s: failed to create block namespace\n", comm); -- goto err_cleanup; -- } -- -- rc = disable_blk_namespace(ndns[0]); -- if (rc < 0) { -- fprintf(stderr, "%s: failed to disable block namespace\n", comm); -- goto err_cleanup; -- } -- -- ndns[0] = create_blk_namespace(2, blk_region); -- if (!ndns[0]) { -- fprintf(stderr, "%s: failed to create block namespace\n", comm); -- rc = -ENODEV; -- goto err_cleanup; -- } -- -- rc = disable_blk_namespace(ndns[1]); -- if (rc < 0) { -- fprintf(stderr, "%s: failed to disable block namespace\n", comm); -- goto err_cleanup; -- } -- -- rc = -ENODEV; -- ndns[1] = create_blk_namespace(2, blk_region); -- if (!ndns[1]) { -- fprintf(stderr, "%s: failed to create block namespace\n", comm); -- goto err_cleanup; -- } -- -- /* okay, all set up, do some I/O */ -- rc = -EIO; -- sprintf(bdev, "/dev/%s", ndctl_namespace_get_block_device(ndns[0])); -- if (ns_do_io(bdev)) -- goto err_cleanup; -- sprintf(bdev, "/dev/%s", ndctl_namespace_get_block_device(ndns[1])); -- if (ns_do_io(bdev)) -- goto err_cleanup; -- rc = 0; -- -- err_cleanup: -- /* unload nfit_test */ -- bus = ndctl_bus_get_by_provider(ctx, "nfit_test.0"); -- if (bus) -- ndctl_region_foreach(bus, region) -- ndctl_region_disable_invalidate(region); -- bus = ndctl_bus_get_by_provider(ctx, "nfit_test.1"); -- if (bus) -- ndctl_region_foreach(bus, region) -- ndctl_region_disable_invalidate(region); -- if (mod) -- kmod_module_remove_module(mod, 0); -- -- err_module: -- if (kmod_ctx) -- kmod_unref(kmod_ctx); -- return rc; --} -- --int __attribute__((weak)) main(int argc, char *argv[]) --{ -- struct ndctl_test *test = ndctl_test_new(0); -- struct ndctl_ctx *ctx; -- int rc; -- -- comm = argv[0]; -- if (!test) { -- fprintf(stderr, "failed to initialize test\n"); -- return EXIT_FAILURE; -- } -- -- rc = ndctl_new(&ctx); -- if (rc) -- return ndctl_test_result(test, rc); -- -- rc = test_blk_namespaces(LOG_DEBUG, test, ctx); -- ndctl_unref(ctx); -- return ndctl_test_result(test, rc); --} -diff --git a/test/core.c b/test/core.c -index 93e1dae..dc1405d 100644 ---- a/test/core.c -+++ b/test/core.c -@@ -123,7 +123,6 @@ int ndctl_test_init(struct kmod_ctx **ctx, struct kmod_module **mod, - "dax_pmem_core", - "dax_pmem_compat", - "libnvdimm", -- "nd_blk", - "nd_btt", - "nd_e820", - "nd_pmem", -diff --git a/test/create.sh b/test/create.sh -index e9baaa0..9a6f373 100755 ---- a/test/create.sh -+++ b/test/create.sh -@@ -40,19 +40,6 @@ eval $(echo $json | json2var) - # free capacity for blk creation - $NDCTL destroy-namespace -f $dev - --# create blk --dev="x" --json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t blk -m raw -v) --eval $(echo $json | json2var) --[ $dev = "x" ] && echo "fail: $LINENO" && exit 1 --[ $mode != "raw" ] && echo "fail: $LINENO" && exit 1 -- --# convert blk to sector mode --json=$($NDCTL create-namespace -m sector -l $SECTOR_SIZE -f -e $dev) --eval $(echo $json | json2var) --[ $sector_size != $SECTOR_SIZE ] && echo "fail: $LINENO" && exit 1 --[ $mode != "sector" ] && echo "fail: $LINENO" && exit 1 -- - _cleanup - - exit 0 -diff --git a/test/dpa-alloc.c b/test/dpa-alloc.c -deleted file mode 100644 -index 59185cf..0000000 ---- a/test/dpa-alloc.c -+++ /dev/null -@@ -1,326 +0,0 @@ --// SPDX-License-Identifier: LGPL-2.1 --// Copyright (C) 2014-2020, Intel Corporation. All rights reserved. --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include --#include --#include --#include --#include --#include -- --static const char *NFIT_PROVIDER0 = "nfit_test.0"; --static const char *NFIT_PROVIDER1 = "nfit_test.1"; --#define NUM_NAMESPACES 4 -- --struct test_dpa_namespace { -- struct ndctl_namespace *ndns; -- unsigned long long size; -- uuid_t uuid; --} namespaces[NUM_NAMESPACES]; -- --#define MIN_SIZE SZ_4M -- --static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test) --{ -- unsigned int default_available_slots, available_slots, i; -- struct ndctl_region *region, *blk_region = NULL; -- struct ndctl_namespace *ndns; -- struct ndctl_dimm *dimm; -- unsigned long size, page_size; -- struct ndctl_bus *bus; -- char uuid_str[40]; -- int round; -- int rc; -- -- page_size = sysconf(_SC_PAGESIZE); -- /* disable nfit_test.1, not used in this test */ -- bus = ndctl_bus_get_by_provider(ctx, NFIT_PROVIDER1); -- if (!bus) -- return -ENXIO; -- ndctl_region_foreach(bus, region) { -- ndctl_region_disable_invalidate(region); -- ndctl_region_set_align(region, sysconf(_SC_PAGESIZE) -- * ndctl_region_get_interleave_ways(region)); -- } -- -- /* init nfit_test.0 */ -- bus = ndctl_bus_get_by_provider(ctx, NFIT_PROVIDER0); -- if (!bus) -- return -ENXIO; -- ndctl_region_foreach(bus, region) { -- ndctl_region_disable_invalidate(region); -- ndctl_region_set_align(region, sysconf(_SC_PAGESIZE) -- * ndctl_region_get_interleave_ways(region)); -- } -- -- ndctl_dimm_foreach(bus, dimm) { -- rc = ndctl_dimm_zero_labels(dimm); -- if (rc < 0) { -- fprintf(stderr, "failed to zero %s\n", -- ndctl_dimm_get_devname(dimm)); -- return rc; -- } -- } -- -- /* -- * Find a guineapig BLK region, we know that the dimm with -- * handle==0 from nfit_test.0 always allocates from highest DPA -- * to lowest with no excursions into BLK only ranges. -- */ -- ndctl_region_foreach(bus, region) { -- if (ndctl_region_get_type(region) != ND_DEVICE_REGION_BLK) -- continue; -- dimm = ndctl_region_get_first_dimm(region); -- if (!dimm) -- continue; -- if (ndctl_dimm_get_handle(dimm) == 0) { -- blk_region = region; -- break; -- } -- } -- if (!blk_region || ndctl_region_enable(blk_region) < 0) { -- fprintf(stderr, "failed to find a usable BLK region\n"); -- return -ENXIO; -- } -- region = blk_region; -- -- if (ndctl_region_get_available_size(region) / MIN_SIZE < NUM_NAMESPACES) { -- fprintf(stderr, "%s insufficient available_size\n", -- ndctl_region_get_devname(region)); -- return -ENXIO; -- } -- -- default_available_slots = ndctl_dimm_get_available_labels(dimm); -- -- /* grow namespaces */ -- for (i = 0; i < ARRAY_SIZE(namespaces); i++) { -- uuid_t uuid; -- -- ndns = ndctl_region_get_namespace_seed(region); -- if (!ndns) { -- fprintf(stderr, "%s: failed to get seed: %d\n", -- ndctl_region_get_devname(region), i); -- return -ENXIO; -- } -- uuid_generate_random(uuid); -- ndctl_namespace_set_uuid(ndns, uuid); -- ndctl_namespace_set_sector_size(ndns, 512); -- ndctl_namespace_set_size(ndns, MIN_SIZE); -- rc = ndctl_namespace_enable(ndns); -- if (rc) { -- fprintf(stderr, "failed to enable %s: %d\n", -- ndctl_namespace_get_devname(ndns), rc); -- return rc; -- } -- ndctl_namespace_disable_invalidate(ndns); -- rc = ndctl_namespace_set_size(ndns, page_size); -- if (rc) { -- fprintf(stderr, "failed to init %s to size: %lu\n", -- ndctl_namespace_get_devname(ndns), -- page_size); -- return rc; -- } -- namespaces[i].ndns = ndns; -- ndctl_namespace_get_uuid(ndns, namespaces[i].uuid); -- } -- -- available_slots = ndctl_dimm_get_available_labels(dimm); -- if (available_slots != default_available_slots -- - ARRAY_SIZE(namespaces)) { -- fprintf(stderr, "expected %ld slots available\n", -- default_available_slots -- - ARRAY_SIZE(namespaces)); -- return -ENOSPC; -- } -- -- /* exhaust label space, by round-robin allocating 4K */ -- round = 1; -- for (i = 0; i < available_slots; i++) { -- ndns = namespaces[i % ARRAY_SIZE(namespaces)].ndns; -- if (i % ARRAY_SIZE(namespaces) == 0) -- round++; -- size = page_size * round; -- rc = ndctl_namespace_set_size(ndns, size); -- if (rc) { -- fprintf(stderr, "%s: set_size: %lx failed: %d\n", -- ndctl_namespace_get_devname(ndns), size, rc); -- return rc; -- } -- } -- -- /* -- * The last namespace we updated should still be modifiable via -- * the kernel's reserve label -- */ -- i--; -- round++; -- ndns = namespaces[i % ARRAY_SIZE(namespaces)].ndns; -- size = page_size * round; -- rc = ndctl_namespace_set_size(ndns, size); -- if (rc) { -- fprintf(stderr, "%s failed to update while labels full\n", -- ndctl_namespace_get_devname(ndns)); -- return rc; -- } -- -- round--; -- size = page_size * round; -- rc = ndctl_namespace_set_size(ndns, size); -- if (rc) { -- fprintf(stderr, "%s failed to reduce size while labels full\n", -- ndctl_namespace_get_devname(ndns)); -- return rc; -- } -- -- /* do the allocations survive a region cycle? */ -- for (i = 0; i < ARRAY_SIZE(namespaces); i++) { -- ndns = namespaces[i].ndns; -- namespaces[i].size = ndctl_namespace_get_size(ndns); -- namespaces[i].ndns = NULL; -- } -- -- ndctl_region_disable_invalidate(region); -- rc = ndctl_region_enable(region); -- if (rc) { -- fprintf(stderr, "failed to re-enable %s: %d\n", -- ndctl_region_get_devname(region), rc); -- return rc; -- } -- -- ndctl_namespace_foreach(region, ndns) { -- uuid_t uuid; -- -- ndctl_namespace_get_uuid(ndns, uuid); -- for (i = 0; i < ARRAY_SIZE(namespaces); i++) { -- if (uuid_compare(uuid, namespaces[i].uuid) == 0) { -- namespaces[i].ndns = ndns; -- break; -- } -- } -- } -- -- /* validate that they all came back */ -- for (i = 0; i < ARRAY_SIZE(namespaces); i++) { -- ndns = namespaces[i].ndns; -- size = ndns ? ndctl_namespace_get_size(ndns) : 0; -- -- if (ndns && size == namespaces[i].size) -- continue; -- uuid_unparse(namespaces[i].uuid, uuid_str); -- fprintf(stderr, "failed to recover %s\n", uuid_str); -- return -ENODEV; -- } -- -- /* test deletion and merging */ -- ndns = namespaces[0].ndns; -- for (i = 1; i < ARRAY_SIZE(namespaces); i++) { -- struct ndctl_namespace *victim = namespaces[i].ndns; -- -- uuid_unparse(namespaces[i].uuid, uuid_str); -- size = ndctl_namespace_get_size(victim); -- rc = ndctl_namespace_disable(victim); -- if (rc) { -- fprintf(stderr, "failed to disable %s\n", uuid_str); -- return rc; -- } -- rc = ndctl_namespace_delete(victim); -- if (rc) { -- fprintf(stderr, "failed to delete %s\n", uuid_str); -- return rc; -- } -- size += ndctl_namespace_get_size(ndns); -- rc = ndctl_namespace_set_size(ndns, size); -- if (rc) { -- fprintf(stderr, "failed to merge %s\n", uuid_str); -- return rc; -- } -- } -- -- /* there can be only one */ -- i = 0; -- ndctl_namespace_foreach(region, ndns) { -- unsigned long long sz = ndctl_namespace_get_size(ndns); -- -- if (sz) { -- i++; -- if (sz == size) -- continue; -- fprintf(stderr, "%s size: %llx expected %lx\n", -- ndctl_namespace_get_devname(ndns), -- sz, size); -- return -ENXIO; -- } -- } -- if (i != 1) { -- fprintf(stderr, "failed to delete namespaces\n"); -- return -ENXIO; -- } -- -- available_slots = ndctl_dimm_get_available_labels(dimm); -- if (available_slots != default_available_slots - 1) { -- fprintf(stderr, "mishandled slot count\n"); -- return -ENXIO; -- } -- -- ndctl_region_foreach(bus, region) -- ndctl_region_disable_invalidate(region); -- -- return 0; --} -- --int test_dpa_alloc(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx) --{ -- struct kmod_module *mod; -- struct kmod_ctx *kmod_ctx; -- int err, result = EXIT_FAILURE; -- -- if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 2, 0))) -- return 77; -- -- ndctl_set_log_priority(ctx, loglevel); -- err = ndctl_test_init(&kmod_ctx, &mod, NULL, loglevel, test); -- if (err < 0) { -- ndctl_test_skip(test); -- fprintf(stderr, "nfit_test unavailable skipping tests\n"); -- return 77; -- } -- -- err = do_test(ctx, test); -- if (err == 0) -- result = EXIT_SUCCESS; -- kmod_module_remove_module(mod, 0); -- kmod_unref(kmod_ctx); -- return result; --} -- --int __attribute__((weak)) main(int argc, char *argv[]) --{ -- struct ndctl_test *test = ndctl_test_new(0); -- struct ndctl_ctx *ctx; -- int rc; -- -- if (!test) { -- fprintf(stderr, "failed to initialize test\n"); -- return EXIT_FAILURE; -- } -- -- rc = ndctl_new(&ctx); -- if (rc) -- return ndctl_test_result(test, rc); -- -- rc = test_dpa_alloc(LOG_DEBUG, test, ctx); -- ndctl_unref(ctx); -- return ndctl_test_result(test, rc); --} -diff --git a/test/libndctl.c b/test/libndctl.c -index 1e97926..35e7cfa 100644 ---- a/test/libndctl.c -+++ b/test/libndctl.c -@@ -30,46 +30,35 @@ - /* - * Kernel provider "nfit_test.0" produces an NFIT with the following attributes: - * -- * (a) (b) DIMM BLK-REGION -- * +-------------------+--------+--------+--------+ -- * +------+ | pm0.0 | blk2.0 | pm1.0 | blk2.1 | 0 region2 -- * | imc0 +--+- - - region0- - - +--------+ +--------+ -- * +--+---+ | pm0.0 | blk3.0 | pm1.0 | blk3.1 | 1 region3 -- * | +-------------------+--------v v--------+ -- * +--+---+ | | -- * | cpu0 | region1 -- * +--+---+ | | -- * | +----------------------------^ ^--------+ -- * +--+---+ | blk4.0 | pm1.0 | blk4.0 | 2 region4 -- * | imc1 +--+----------------------------| +--------+ -- * +------+ | blk5.0 | pm1.0 | blk5.0 | 3 region5 -- * +----------------------------+--------+--------+ -+ * (a) (b) DIMM -+ * +-------------------+--------+--------+--------+ -+ * +------+ | pm0.0 | free | pm1.0 | free | 0 -+ * | imc0 +--+- - - region0- - - +--------+ +--------+ -+ * +--+---+ | pm0.0 | free | pm1.0 | free | 1 -+ * | +-------------------+--------v v--------+ -+ * +--+---+ | | -+ * | cpu0 | region1 -+ * +--+---+ | | -+ * | +----------------------------^ ^--------+ -+ * +--+---+ | free | pm1.0 | free | 2 -+ * | imc1 +--+----------------------------| +--------+ -+ * +------+ | free | pm1.0 | free | 3 -+ * +----------------------------+--------+--------+ - * -- * *) In this layout we have four dimms and two memory controllers in one -- * socket. Each unique interface ("blk" or "pmem") to DPA space -- * is identified by a region device with a dynamically assigned id. -+ * In this platform we have four DIMMs and two memory controllers in one -+ * socket. Each PMEM interleave set is identified by a region device with -+ * a dynamically assigned id. - * -- * *) The first portion of dimm0 and dimm1 are interleaved as REGION0. -- * A single "pmem" namespace is created in the REGION0-"spa"-range -- * that spans dimm0 and dimm1 with a user-specified name of "pm0.0". -- * Some of that interleaved "spa" range is reclaimed as "bdw" -- * accessed space starting at offset (a) into each dimm. In that -- * reclaimed space we create two "bdw" "namespaces" from REGION2 and -- * REGION3 where "blk2.0" and "blk3.0" are just human readable names -- * that could be set to any user-desired name in the label. -+ * 1. The first portion of DIMM0 and DIMM1 are interleaved as REGION0. A -+ * single PMEM namespace is created in the REGION0-SPA-range that spans most -+ * of DIMM0 and DIMM1 with a user-specified name of "pm0.0". Some of that -+ * interleaved system-physical-address range is left free for -+ * another PMEM namespace to be defined. - * -- * *) In the last portion of dimm0 and dimm1 we have an interleaved -- * "spa" range, REGION1, that spans those two dimms as well as dimm2 -- * and dimm3. Some of REGION1 allocated to a "pmem" namespace named -- * "pm1.0" the rest is reclaimed in 4 "bdw" namespaces (for each -- * dimm in the interleave set), "blk2.1", "blk3.1", "blk4.0", and -- * "blk5.0". -- * -- * *) The portion of dimm2 and dimm3 that do not participate in the -- * REGION1 interleaved "spa" range (i.e. the DPA address below -- * offset (b) are also included in the "blk4.0" and "blk5.0" -- * namespaces. Note, that this example shows that "bdw" namespaces -- * don't need to be contiguous in DPA-space. -+ * 2. In the last portion of DIMM0 and DIMM1 we have an interleaved -+ * system-physical-address range, REGION1, that spans those two DIMMs as -+ * well as DIMM2 and DIMM3. Some of REGION1 is allocated to a PMEM namespace -+ * named "pm1.0". - * - * Kernel provider "nfit_test.1" produces an NFIT with the following attributes: - * -@@ -127,10 +116,10 @@ struct dimm { - (((n & 0xfff) << 16) | ((s & 0xf) << 12) | ((i & 0xf) << 8) \ - | ((c & 0xf) << 4) | (d & 0xf)) - static struct dimm dimms0[] = { -- { DIMM_HANDLE(0, 0, 0, 0, 0), 0, 0, 2016, 10, 42, { 0 }, 2, { 0x201, 0x301, }, }, -- { DIMM_HANDLE(0, 0, 0, 0, 1), 1, 0, 2016, 10, 42, { 0 }, 2, { 0x201, 0x301, }, }, -- { DIMM_HANDLE(0, 0, 1, 0, 0), 2, 0, 2016, 10, 42, { 0 }, 2, { 0x201, 0x301, }, }, -- { DIMM_HANDLE(0, 0, 1, 0, 1), 3, 0, 2016, 10, 42, { 0 }, 2, { 0x201, 0x301, }, }, -+ { DIMM_HANDLE(0, 0, 0, 0, 0), 0, 0, 2016, 10, 42, { 0 }, 1, { 0x201, }, }, -+ { DIMM_HANDLE(0, 0, 0, 0, 1), 1, 0, 2016, 10, 42, { 0 }, 1, { 0x201, }, }, -+ { DIMM_HANDLE(0, 0, 1, 0, 0), 2, 0, 2016, 10, 42, { 0 }, 1, { 0x201, }, }, -+ { DIMM_HANDLE(0, 0, 1, 0, 1), 3, 0, 2016, 10, 42, { 0 }, 1, { 0x201, }, }, - }; - - static struct dimm dimms1[] = { -@@ -240,7 +229,6 @@ struct namespace { - }; - - static uuid_t null_uuid; --static unsigned long blk_sector_sizes[] = { 512, 520, 528, 4096, 4104, 4160, 4224, }; - static unsigned long pmem_sector_sizes[] = { 512, 4096 }; - static unsigned long io_sector_sizes[] = { 0 }; - -@@ -262,60 +250,6 @@ static struct namespace namespace1_pmem0 = { - ARRAY_SIZE(pmem_sector_sizes), pmem_sector_sizes, - }; - --static struct namespace namespace2_blk0 = { -- 0, "namespace_blk", NULL, NULL, NULL, SZ_7M, -- { 3, 3, 3, 3, -- 3, 3, 3, 3, -- 3, 3, 3, 3, -- 3, 3, 3, 3, }, 1, 1, 0, -- ARRAY_SIZE(blk_sector_sizes), blk_sector_sizes, --}; -- --static struct namespace namespace2_blk1 = { -- 1, "namespace_blk", NULL, NULL, NULL, SZ_11M, -- { 4, 4, 4, 4, -- 4, 4, 4, 4, -- 4, 4, 4, 4, -- 4, 4, 4, 4, }, 1, 1, 0, -- ARRAY_SIZE(blk_sector_sizes), blk_sector_sizes, --}; -- --static struct namespace namespace3_blk0 = { -- 0, "namespace_blk", NULL, NULL, NULL, SZ_7M, -- { 5, 5, 5, 5, -- 5, 5, 5, 5, -- 5, 5, 5, 5, -- 5, 5, 5, 5, }, 1, 1, 0, -- ARRAY_SIZE(blk_sector_sizes), blk_sector_sizes, --}; -- --static struct namespace namespace3_blk1 = { -- 1, "namespace_blk", NULL, NULL, NULL, SZ_11M, -- { 6, 6, 6, 6, -- 6, 6, 6, 6, -- 6, 6, 6, 6, -- 6, 6, 6, 6, }, 1, 1, 0, -- ARRAY_SIZE(blk_sector_sizes), blk_sector_sizes, --}; -- --static struct namespace namespace4_blk0 = { -- 0, "namespace_blk", &btt_settings, NULL, NULL, SZ_27M, -- { 7, 7, 7, 7, -- 7, 7, 7, 7, -- 7, 7, 7, 7, -- 7, 7, 7, 7, }, 1, 1, 0, -- ARRAY_SIZE(blk_sector_sizes), blk_sector_sizes, --}; -- --static struct namespace namespace5_blk0 = { -- 0, "namespace_blk", &btt_settings, NULL, NULL, SZ_27M, -- { 8, 8, 8, 8, -- 8, 8, 8, 8, -- 8, 8, 8, 8, -- 8, 8, 8, 8, }, 1, 1, 0, -- ARRAY_SIZE(blk_sector_sizes), blk_sector_sizes, --}; -- - static struct region regions0[] = { - { { 1 }, 2, 1, "pmem", SZ_32M, SZ_32M, { 1 }, - .namespaces = { -@@ -339,40 +273,6 @@ static struct region regions0[] = { - [0] = &default_pfn, - }, - }, -- { { DIMM_HANDLE(0, 0, 0, 0, 0) }, 1, 1, "blk", SZ_18M, SZ_32M, -- .namespaces = { -- [0] = &namespace2_blk0, -- [1] = &namespace2_blk1, -- }, -- .btts = { -- [0] = &default_btt, -- }, -- }, -- { { DIMM_HANDLE(0, 0, 0, 0, 1) }, 1, 1, "blk", SZ_18M, SZ_32M, -- .namespaces = { -- [0] = &namespace3_blk0, -- [1] = &namespace3_blk1, -- }, -- .btts = { -- [0] = &default_btt, -- }, -- }, -- { { DIMM_HANDLE(0, 0, 1, 0, 0) }, 1, 1, "blk", SZ_27M, SZ_32M, -- .namespaces = { -- [0] = &namespace4_blk0, -- }, -- .btts = { -- [0] = &default_btt, -- }, -- }, -- { { DIMM_HANDLE(0, 0, 1, 0, 1) }, 1, 1, "blk", SZ_27M, SZ_32M, -- .namespaces = { -- [0] = &namespace5_blk0, -- }, -- .btts = { -- [0] = &default_btt, -- }, -- }, - }; - - static struct namespace namespace1 = { -@@ -485,26 +385,6 @@ static struct ndctl_region *get_pmem_region_by_range_index(struct ndctl_bus *bus - return NULL; - } - --static struct ndctl_region *get_blk_region_by_dimm_handle(struct ndctl_bus *bus, -- unsigned int handle) --{ -- struct ndctl_region *region; -- -- ndctl_region_foreach(bus, region) { -- struct ndctl_mapping *map; -- -- if (ndctl_region_get_type(region) != ND_DEVICE_REGION_BLK) -- continue; -- ndctl_mapping_foreach(region, map) { -- struct ndctl_dimm *dimm = ndctl_mapping_get_dimm(map); -- -- if (ndctl_dimm_get_handle(dimm) == handle) -- return region; -- } -- } -- return NULL; --} -- - enum ns_mode { - BTT, PFN, DAX, - }; -@@ -522,11 +402,8 @@ static int check_regions(struct ndctl_bus *bus, struct region *regions, int n, - struct ndctl_interleave_set *iset; - char devname[50]; - -- if (strcmp(regions[i].type, "pmem") == 0) -- region = get_pmem_region_by_range_index(bus, regions[i].range_index); -- else -- region = get_blk_region_by_dimm_handle(bus, regions[i].handle); -- -+ region = get_pmem_region_by_range_index(bus, -+ regions[i].range_index); - if (!region) { - fprintf(stderr, "failed to find region type: %s ident: %x\n", - regions[i].type, regions[i].handle); -@@ -1065,7 +942,6 @@ static int check_btt_create(struct ndctl_region *region, struct ndctl_namespace - return -ENXIO; - - for (i = 0; i < btt_s->num_sector_sizes; i++) { -- struct ndctl_namespace *ns_seed = ndctl_region_get_namespace_seed(region); - struct ndctl_btt *btt_seed = ndctl_region_get_btt_seed(region); - enum ndctl_namespace_mode mode; - -@@ -1115,16 +991,6 @@ static int check_btt_create(struct ndctl_region *region, struct ndctl_namespace - goto err; - } - -- /* check new seed creation for BLK regions */ -- if (ndctl_region_get_type(region) == ND_DEVICE_REGION_BLK) { -- if (ns_seed == ndctl_region_get_namespace_seed(region) -- && ndns == ns_seed) { -- fprintf(stderr, "%s: failed to advance namespace seed\n", -- ndctl_region_get_devname(region)); -- goto err; -- } -- } -- - if (namespace->ro) { - ndctl_region_set_ro(region, 0); - rc = ndctl_btt_enable(btt); -diff --git a/test/multi-pmem.c b/test/multi-pmem.c -deleted file mode 100644 -index 3ea08cc..0000000 ---- a/test/multi-pmem.c -+++ /dev/null -@@ -1,285 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --// Copyright (C) 2015-2020 Intel Corporation. All rights reserved. --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include --#include --#include -- --#define NUM_NAMESPACES 4 --#define SZ_NAMESPACE SZ_16M -- --static int setup_namespace(struct ndctl_region *region) --{ -- struct ndctl_ctx *ctx = ndctl_region_get_ctx(region); -- const char *argv[] = { -- "__func__", "-v", "-m", "raw", "-s", "16M", "-r", "", -- }; -- int argc = ARRAY_SIZE(argv); -- -- argv[argc - 1] = ndctl_region_get_devname(region); -- builtin_xaction_namespace_reset(); -- return cmd_create_namespace(argc, argv, ctx); --} -- --static void destroy_namespace(struct ndctl_namespace *ndns) --{ -- struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns); -- const char *argv[] = { -- "__func__", "-v", "-f", "", -- }; -- int argc = ARRAY_SIZE(argv); -- -- argv[argc - 1] = ndctl_namespace_get_devname(ndns); -- builtin_xaction_namespace_reset(); -- cmd_destroy_namespace(argc, argv, ctx); --} -- --/* Check that the namespace device is gone (if it wasn't the seed) */ --static int check_deleted(struct ndctl_region *region, const char *devname, -- struct ndctl_test *test) --{ -- struct ndctl_namespace *ndns; -- -- if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 10, 0))) -- return 0; -- -- ndctl_namespace_foreach(region, ndns) { -- if (strcmp(devname, ndctl_namespace_get_devname(ndns))) -- continue; -- if (ndns == ndctl_region_get_namespace_seed(region)) -- continue; -- fprintf(stderr, "multi-pmem: expected %s to be deleted\n", -- devname); -- return -ENXIO; -- } -- -- return 0; --} -- --static int do_multi_pmem(struct ndctl_ctx *ctx, struct ndctl_test *test) --{ -- int i; -- char devname[100]; -- struct ndctl_bus *bus; -- uuid_t uuid[NUM_NAMESPACES]; -- struct ndctl_namespace *ndns; -- struct ndctl_dimm *dimm_target, *dimm; -- struct ndctl_region *region, *target = NULL; -- struct ndctl_namespace *namespaces[NUM_NAMESPACES]; -- unsigned long long blk_avail, blk_avail_orig, expect; -- -- if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 9, 0))) { -- ndctl_test_skip(test); -- return 77; -- } -- -- bus = ndctl_bus_get_by_provider(ctx, "nfit_test.0"); -- if (!bus) -- return -ENXIO; -- -- /* disable all regions so that set_config_data commands are permitted */ -- ndctl_region_foreach(bus, region) -- ndctl_region_disable_invalidate(region); -- -- ndctl_dimm_foreach(bus, dimm) { -- int rc = ndctl_dimm_zero_labels(dimm); -- -- if (rc < 0) { -- fprintf(stderr, "failed to zero %s\n", -- ndctl_dimm_get_devname(dimm)); -- return rc; -- } -- } -- -- /* -- * Set regions back to their default state and find our target -- * region. -- */ -- ndctl_region_foreach(bus, region) { -- ndctl_region_enable(region); -- if (ndctl_region_get_available_size(region) -- == SZ_NAMESPACE * NUM_NAMESPACES) -- target = region; -- } -- -- if (!target) { -- fprintf(stderr, "multi-pmem: failed to find target region\n"); -- return -ENXIO; -- } -- region = target; -- -- for (i = 0; i < (int) ARRAY_SIZE(uuid); i++) { -- if (setup_namespace(region) != 0) { -- fprintf(stderr, "multi-pmem: failed to setup namespace: %d\n", i); -- return -ENXIO; -- } -- sprintf(devname, "namespace%d.%d", -- ndctl_region_get_id(region), i); -- ndctl_namespace_foreach(region, ndns) -- if (strcmp(ndctl_namespace_get_devname(ndns), devname) == 0 -- && ndctl_namespace_is_enabled(ndns)) -- break; -- if (!ndns) { -- fprintf(stderr, "multi-pmem: failed to find namespace: %s\n", -- devname); -- return -ENXIO; -- } -- ndctl_namespace_get_uuid(ndns, uuid[i]); -- } -- -- /* bounce the region and verify everything came back as expected */ -- ndctl_region_disable_invalidate(region); -- ndctl_region_enable(region); -- -- for (i = 0; i < (int) ARRAY_SIZE(uuid); i++) { -- char uuid_str1[40], uuid_str2[40]; -- uuid_t uuid_check; -- -- sprintf(devname, "namespace%d.%d", -- ndctl_region_get_id(region), i); -- ndctl_namespace_foreach(region, ndns) -- if (strcmp(ndctl_namespace_get_devname(ndns), devname) == 0 -- && ndctl_namespace_is_enabled(ndns)) -- break; -- if (!ndns) { -- fprintf(stderr, "multi-pmem: failed to restore namespace: %s\n", -- devname); -- return -ENXIO; -- } -- -- ndctl_namespace_get_uuid(ndns, uuid_check); -- uuid_unparse(uuid_check, uuid_str2); -- uuid_unparse(uuid[i], uuid_str1); -- if (uuid_compare(uuid_check, uuid[i]) != 0) { -- fprintf(stderr, "multi-pmem: expected uuid[%d]: %s, got %s\n", -- i, uuid_str1, uuid_str2); -- return -ENXIO; -- } -- namespaces[i] = ndns; -- } -- -- /* -- * Check that aliased blk capacity does not increase until the -- * highest dpa pmem-namespace is deleted. -- */ -- dimm_target = ndctl_region_get_first_dimm(region); -- if (!dimm_target) { -- fprintf(stderr, "multi-pmem: failed to retrieve dimm from %s\n", -- ndctl_region_get_devname(region)); -- return -ENXIO; -- } -- -- dimm = NULL; -- ndctl_region_foreach(bus, region) { -- if (ndctl_region_get_type(region) != ND_DEVICE_REGION_BLK) -- continue; -- ndctl_dimm_foreach_in_region(region, dimm) -- if (dimm == dimm_target) -- break; -- if (dimm) -- break; -- } -- -- blk_avail_orig = ndctl_region_get_available_size(region); -- for (i = 1; i < NUM_NAMESPACES - 1; i++) { -- ndns = namespaces[i]; -- sprintf(devname, "%s", ndctl_namespace_get_devname(ndns)); -- destroy_namespace(ndns); -- blk_avail = ndctl_region_get_available_size(region); -- if (blk_avail != blk_avail_orig) { -- fprintf(stderr, "multi-pmem: destroy %s %llx avail, expect %llx\n", -- devname, blk_avail, blk_avail_orig); -- return -ENXIO; -- } -- -- if (check_deleted(target, devname, test) != 0) -- return -ENXIO; -- } -- -- ndns = namespaces[NUM_NAMESPACES - 1]; -- sprintf(devname, "%s", ndctl_namespace_get_devname(ndns)); -- destroy_namespace(ndns); -- blk_avail = ndctl_region_get_available_size(region); -- expect = (SZ_NAMESPACE / ndctl_region_get_interleave_ways(target)) -- * (NUM_NAMESPACES - 1) + blk_avail_orig; -- if (blk_avail != expect) { -- fprintf(stderr, "multi-pmem: destroy %s %llx avail, expect %llx\n", -- devname, blk_avail, expect); -- return -ENXIO; -- } -- -- if (check_deleted(target, devname, test) != 0) -- return -ENXIO; -- -- ndctl_bus_foreach(ctx, bus) { -- if (strncmp(ndctl_bus_get_provider(bus), "nfit_test", 9) != 0) -- continue; -- ndctl_region_foreach(bus, region) -- ndctl_region_disable_invalidate(region); -- } -- -- return 0; --} -- --int test_multi_pmem(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx) --{ -- struct kmod_module *mod; -- struct kmod_ctx *kmod_ctx; -- int err, result = EXIT_FAILURE; -- -- if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 2, 0))) -- return 77; -- -- ndctl_set_log_priority(ctx, loglevel); -- -- err = ndctl_test_init(&kmod_ctx, &mod, NULL, loglevel, test); -- if (err < 0) { -- result = 77; -- ndctl_test_skip(test); -- fprintf(stderr, "%s unavailable skipping tests\n", -- "nfit_test"); -- return result; -- } -- -- result = do_multi_pmem(ctx, test); -- -- kmod_module_remove_module(mod, 0); -- kmod_unref(kmod_ctx); -- return result; --} -- --int __attribute__((weak)) main(int argc, char *argv[]) --{ -- struct ndctl_test *test = ndctl_test_new(0); -- struct ndctl_ctx *ctx; -- int rc; -- -- if (!test) { -- fprintf(stderr, "failed to initialize test\n"); -- return EXIT_FAILURE; -- } -- -- rc = ndctl_new(&ctx); -- if (rc) -- return ndctl_test_result(test, rc); -- rc = test_multi_pmem(LOG_DEBUG, test, ctx); -- ndctl_unref(ctx); -- return ndctl_test_result(test, rc); --} -diff --git a/test/parent-uuid.c b/test/parent-uuid.c -deleted file mode 100644 -index bded33a..0000000 ---- a/test/parent-uuid.c -+++ /dev/null -@@ -1,254 +0,0 @@ --// SPDX-License-Identifier: LGPL-2.1 --// Copyright (C) 2015-2020, Intel Corporation. All rights reserved. --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include -- --static const char *PROVIDER = "nfit_test.0"; -- --static struct ndctl_bus *get_bus_by_provider(struct ndctl_ctx *ctx, -- const char *provider) --{ -- struct ndctl_bus *bus; -- -- ndctl_bus_foreach(ctx, bus) -- if (strcmp(provider, ndctl_bus_get_provider(bus)) == 0) -- return bus; -- -- return NULL; --} -- --static struct ndctl_btt *get_idle_btt(struct ndctl_region *region) --{ -- struct ndctl_btt *btt; -- -- ndctl_btt_foreach(region, btt) -- if (!ndctl_btt_is_enabled(btt) -- && !ndctl_btt_is_configured(btt)) -- return btt; -- return NULL; --} -- --static struct ndctl_namespace *create_blk_namespace(int region_fraction, -- struct ndctl_region *region, unsigned long long req_size, -- uuid_t uuid) --{ -- struct ndctl_namespace *ndns, *seed_ns = NULL; -- unsigned long long size; -- -- ndctl_region_set_align(region, sysconf(_SC_PAGESIZE)); -- ndctl_namespace_foreach(region, ndns) -- if (ndctl_namespace_get_size(ndns) == 0) { -- seed_ns = ndns; -- break; -- } -- -- if (!seed_ns) -- return NULL; -- -- size = ndctl_region_get_size(region)/region_fraction; -- if (req_size) -- size = req_size; -- -- if (ndctl_namespace_set_uuid(seed_ns, uuid) < 0) -- return NULL; -- -- if (ndctl_namespace_set_size(seed_ns, size) < 0) -- return NULL; -- -- if (ndctl_namespace_set_sector_size(seed_ns, 512) < 0) -- return NULL; -- -- if (ndctl_namespace_enable(seed_ns) < 0) -- return NULL; -- -- return seed_ns; --} -- --static int disable_blk_namespace(struct ndctl_namespace *ndns) --{ -- if (ndctl_namespace_disable_invalidate(ndns) < 0) -- return -ENODEV; -- -- if (ndctl_namespace_delete(ndns) < 0) -- return -ENODEV; -- -- return 0; --} -- --static struct ndctl_btt *check_valid_btt(struct ndctl_region *region, -- struct ndctl_namespace *ndns, uuid_t btt_uuid) --{ -- struct ndctl_btt *btt = NULL; -- ndctl_btt_foreach(region, btt) { -- struct ndctl_namespace *btt_ndns; -- uuid_t uu; -- -- ndctl_btt_get_uuid(btt, uu); -- if (uuid_compare(uu, btt_uuid) != 0) -- continue; -- if (!ndctl_btt_is_enabled(btt)) -- continue; -- btt_ndns = ndctl_btt_get_namespace(btt); -- if (!btt_ndns || strcmp(ndctl_namespace_get_devname(btt_ndns), -- ndctl_namespace_get_devname(ndns)) != 0) -- continue; -- return btt; -- } -- return NULL; --} -- --static int do_test(struct ndctl_ctx *ctx) --{ -- int rc; -- struct ndctl_bus *bus; -- struct ndctl_btt *btt, *found = NULL, *_btt; -- struct ndctl_region *region, *blk_region = NULL; -- struct ndctl_namespace *ndns, *_ndns; -- unsigned long long ns_size = 18874368; -- uuid_t uuid = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16}; -- uuid_t btt_uuid; -- -- bus = get_bus_by_provider(ctx, PROVIDER); -- if (!bus) { -- fprintf(stderr, "failed to find NFIT-provider: %s\n", PROVIDER); -- return -ENODEV; -- } -- -- ndctl_region_foreach(bus, region) -- if (strcmp(ndctl_region_get_type_name(region), "blk") == 0) { -- blk_region = region; -- break; -- } -- -- if (!blk_region) { -- fprintf(stderr, "failed to find block region\n"); -- return -ENODEV; -- } -- -- /* create a blk namespace */ -- ndns = create_blk_namespace(1, blk_region, ns_size, uuid); -- if (!ndns) { -- fprintf(stderr, "failed to create block namespace\n"); -- return -ENXIO; -- } -- -- /* create a btt for this namespace */ -- uuid_generate(btt_uuid); -- btt = get_idle_btt(region); -- if (!btt) -- return -ENXIO; -- -- ndctl_namespace_disable_invalidate(ndns); -- ndctl_btt_set_uuid(btt, btt_uuid); -- ndctl_btt_set_sector_size(btt, 512); -- ndctl_btt_set_namespace(btt, ndns); -- rc = ndctl_btt_enable(btt); -- if (rc) { -- fprintf(stderr, "failed to create btt 0\n"); -- return rc; -- } -- -- /* re-create the namespace - this should auto-enable the btt */ -- disable_blk_namespace(ndns); -- ndns = create_blk_namespace(1, blk_region, ns_size, uuid); -- if (!ndns) { -- fprintf(stderr, "failed to re-create block namespace\n"); -- return -ENXIO; -- } -- -- /* Verify btt was auto-created */ -- found = check_valid_btt(blk_region, ndns, btt_uuid); -- if (!found) -- return -ENXIO; -- btt = found; -- -- /*disable the btt and namespace again */ -- ndctl_btt_delete(btt); -- disable_blk_namespace(ndns); -- -- /* recreate the namespace with a different uuid */ -- uuid_generate(uuid); -- ndns = create_blk_namespace(1, blk_region, ns_size, uuid); -- if (!ndns) { -- fprintf(stderr, "failed to re-create block namespace\n"); -- return -ENXIO; -- } -- -- /* make sure there is no btt on this namespace */ -- found = check_valid_btt(blk_region, ndns, btt_uuid); -- if (found) { -- fprintf(stderr, "found a stale btt\n"); -- return -ENXIO; -- } -- -- ndctl_btt_foreach_safe(blk_region, btt, _btt) -- ndctl_btt_delete(btt); -- -- ndctl_namespace_foreach_safe(blk_region, ndns, _ndns) -- if (ndctl_namespace_get_size(ndns) != 0) -- disable_blk_namespace(ndns); -- -- ndctl_region_foreach(bus, region) -- ndctl_region_disable_invalidate(region); -- -- return 0; --} -- --int test_parent_uuid(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx) --{ -- struct kmod_module *mod; -- struct kmod_ctx *kmod_ctx; -- int err, result = EXIT_FAILURE; -- -- if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 3, 0))) -- return 77; -- -- ndctl_set_log_priority(ctx, loglevel); -- err = ndctl_test_init(&kmod_ctx, &mod, NULL, loglevel, test); -- if (err < 0) { -- ndctl_test_skip(test); -- fprintf(stderr, "nfit_test unavailable skipping tests\n"); -- return 77; -- } -- -- err = do_test(ctx); -- if (err == 0) -- result = EXIT_SUCCESS; -- kmod_module_remove_module(mod, 0); -- kmod_unref(kmod_ctx); -- return result; --} -- --int __attribute__((weak)) main(int argc, char *argv[]) --{ -- struct ndctl_test *test = ndctl_test_new(0); -- struct ndctl_ctx *ctx; -- int rc; -- -- if (!test) { -- fprintf(stderr, "failed to initialize test\n"); -- return EXIT_FAILURE; -- } -- -- rc = ndctl_new(&ctx); -- if (rc) -- return ndctl_test_result(test, rc); -- -- rc = test_parent_uuid(LOG_DEBUG, test, ctx); -- ndctl_unref(ctx); -- return ndctl_test_result(test, rc); --} --- -2.27.0 - diff --git a/SOURCES/0076-ndctl-test-Fix-support-for-missing-dax_pmem_compat-m.patch b/SOURCES/0076-ndctl-test-Fix-support-for-missing-dax_pmem_compat-m.patch deleted file mode 100644 index 027c0ab..0000000 --- a/SOURCES/0076-ndctl-test-Fix-support-for-missing-dax_pmem_compat-m.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 9bfb567715d1b45e6598e6b38bef531312c72db3 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:32:21 -0800 -Subject: [PATCH 076/217] ndctl/test: Fix support for missing dax_pmem_compat - module - -The kernel is moving to drop CONFIG_DEV_DAX_PMEM_COMPAT. Update -ndctl_test_init() to not error out if dax_pmem_compat is missing. It seems -that the original implementation of support for missing dax_pmem_compat was -broken, or since that time newer versions of kmod_module_new_from_name() no -longer fail when the module is missing. - -Link: https://lore.kernel.org/r/164141834155.3990253.5388773351209410262.stgit@dwillia2-desk3.amr.corp.intel.com -Fixes: b7991dbc22f3 ("ndctl/test: Relax dax_pmem_compat requirement") -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/core.c | 25 +++++++++++-------------- - 1 file changed, 11 insertions(+), 14 deletions(-) - -diff --git a/test/core.c b/test/core.c -index dc1405d..5d1aa23 100644 ---- a/test/core.c -+++ b/test/core.c -@@ -120,7 +120,6 @@ int ndctl_test_init(struct kmod_ctx **ctx, struct kmod_module **mod, - "nfit", - "device_dax", - "dax_pmem", -- "dax_pmem_core", - "dax_pmem_compat", - "libnvdimm", - "nd_btt", -@@ -180,29 +179,27 @@ int ndctl_test_init(struct kmod_ctx **ctx, struct kmod_module **mod, - /* - * Skip device-dax bus-model modules on pre-v5.1 - */ -- if ((strcmp(name, "dax_pmem_core") == 0 -- || strcmp(name, "dax_pmem_compat") == 0) -- && !ndctl_test_attempt(test, -- KERNEL_VERSION(5, 1, 0))) -+ if ((strcmp(name, "dax_pmem_compat") == 0) && -+ !ndctl_test_attempt(test, KERNEL_VERSION(5, 1, 0))) - continue; - - retry: - rc = kmod_module_new_from_name(*ctx, name, mod); -- -- /* -- * dax_pmem_compat is not required, missing is ok, -- * present-but-production is not ok. -- */ -- if (rc && strcmp(name, "dax_pmem_compat") == 0) -- continue; -- - if (rc) { -- log_err(&log_ctx, "%s.ko: missing\n", name); -+ log_err(&log_ctx, "failed to interrogate %s.ko\n", -+ name); - break; - } - - path = kmod_module_get_path(*mod); - if (!path) { -+ /* -+ * dax_pmem_compat is not required, missing is -+ * ok, present-but-production is not ok. -+ */ -+ if (strcmp(name, "dax_pmem_compat") == 0) -+ continue; -+ - if (family != NVDIMM_FAMILY_INTEL && - (strcmp(name, "nfit") == 0 || - strcmp(name, "nd_e820") == 0)) --- -2.27.0 - diff --git a/SOURCES/0077-util-Distribute-filter-and-json-helpers-to-per-tool-.patch b/SOURCES/0077-util-Distribute-filter-and-json-helpers-to-per-tool-.patch deleted file mode 100644 index dc8a474..0000000 --- a/SOURCES/0077-util-Distribute-filter-and-json-helpers-to-per-tool-.patch +++ /dev/null @@ -1,5595 +0,0 @@ -From 965fa02e372fe3a05acc9ae8379f6dd796b7346d Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:32:26 -0800 -Subject: [PATCH 077/217] util: Distribute 'filter' and 'json' helpers to - per-tool objects - -In preparation for switching build systems, fix the long standing wart -of mixing ndctl, daxctl, and cxl 'filter' and 'json' utilities in the -top-level util/filter.[ch]. Distribute them to their respective -{ndctl,daxctl,cxl}/filter.{c,h} locations. - -This also removes the naming collisions for util/json.h between util/ -and ndct/util/. I.e. is no longer ambiguous or subject to -being shadowed by the tool local "util" directory. - -Unfortunately unwinding this caused a lot of code to move all at once. -The benefit is that now it is clear that ndctl is the only tool that -reaches across into the 'filter' and 'json' functionality of another -tool (daxctl). - -Link: https://lore.kernel.org/r/164141834691.3990253.16681105368577841032.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Makefile.am | 1 - - Makefile.am.in | 3 - - cxl/Makefile.am | 3 + - cxl/filter.c | 25 + - cxl/filter.h | 7 + - cxl/json.c | 214 +++++ - cxl/json.h | 8 + - cxl/list.c | 4 +- - cxl/memdev.c | 3 +- - daxctl/Makefile.am | 5 + - daxctl/device.c | 4 +- - daxctl/filter.c | 43 + - daxctl/filter.h | 12 + - daxctl/json.c | 245 ++++++ - daxctl/json.h | 18 + - daxctl/list.c | 4 +- - ndctl/Makefile.am | 16 +- - ndctl/bus.c | 4 +- - ndctl/check.c | 2 +- - ndctl/dimm.c | 6 +- - {util => ndctl}/filter.c | 60 +- - {util => ndctl}/filter.h | 12 +- - ndctl/inject-error.c | 6 +- - ndctl/inject-smart.c | 6 +- - ndctl/{util => }/json-smart.c | 5 +- - ndctl/json.c | 1114 ++++++++++++++++++++++++ - ndctl/json.h | 24 + - ndctl/{util => }/keys.c | 5 +- - ndctl/{util => }/keys.h | 0 - ndctl/lib/libndctl.c | 2 +- - ndctl/lib/papr.c | 4 +- - ndctl/lib/private.h | 4 +- - ndctl/list.c | 5 +- - ndctl/load-keys.c | 7 +- - ndctl/monitor.c | 4 +- - ndctl/namespace.c | 6 +- - ndctl/region.c | 3 +- - test/Makefile.am | 22 +- - test/ack-shutdown-count-set.c | 2 +- - test/daxdev-errors.c | 2 +- - test/device-dax.c | 2 +- - test/dsm-fail.c | 4 +- - test/libndctl.c | 2 +- - test/list-smart-dimm.c | 6 +- - test/pmem_namespaces.c | 2 +- - test/revoke-devmem.c | 2 +- - util/help.c | 2 +- - util/json.c | 1542 +-------------------------------- - util/json.h | 39 +- - 49 files changed, 1820 insertions(+), 1701 deletions(-) - create mode 100644 cxl/filter.c - create mode 100644 cxl/filter.h - create mode 100644 cxl/json.c - create mode 100644 cxl/json.h - create mode 100644 daxctl/filter.c - create mode 100644 daxctl/filter.h - create mode 100644 daxctl/json.c - create mode 100644 daxctl/json.h - rename {util => ndctl}/filter.c (88%) - rename {util => ndctl}/filter.h (89%) - rename ndctl/{util => }/json-smart.c (99%) - create mode 100644 ndctl/json.c - create mode 100644 ndctl/json.h - rename ndctl/{util => }/keys.c (99%) - rename ndctl/{util => }/keys.h (100%) - -diff -up ndctl-71.1/Makefile.am.in.orig ndctl-71.1/Makefile.am.in ---- ndctl-71.1/Makefile.am.in.orig 2022-10-07 15:50:40.071454550 -0400 -+++ ndctl-71.1/Makefile.am.in 2022-10-07 15:51:03.900535680 -0400 -@@ -9,9 +9,6 @@ AM_CPPFLAGS = \ - -DLIBEXECDIR=\""$(libexecdir)"\" \ - -DPREFIX=\""$(prefix)"\" \ - -DNDCTL_MAN_PATH=\""$(mandir)"\" \ -- -I${top_srcdir}/ndctl/lib \ -- -I${top_srcdir}/ndctl \ -- -I${top_srcdir}/cxl \ - -I${top_srcdir}/ \ - $(KMOD_CFLAGS) \ - $(UDEV_CFLAGS) \ -diff -up ndctl-71.1/Makefile.am.orig ndctl-71.1/Makefile.am ---- ndctl-71.1/Makefile.am.orig 2022-10-07 15:50:40.071454550 -0400 -+++ ndctl-71.1/Makefile.am 2022-10-07 15:51:03.900535680 -0400 -@@ -84,7 +84,6 @@ libutil_a_SOURCES = \ - util/help.c \ - util/strbuf.c \ - util/wrapper.c \ -- util/filter.c \ - util/bitmap.c \ - util/abspath.c \ - util/iomem.c \ -diff -up ndctl-71.1/cxl/Makefile.am.orig ndctl-71.1/cxl/Makefile.am ---- ndctl-71.1/cxl/Makefile.am.orig 2022-10-07 15:50:40.071454550 -0400 -+++ ndctl-71.1/cxl/Makefile.am 2022-10-07 15:51:03.900535680 -0400 -@@ -12,6 +12,9 @@ cxl_SOURCES =\ - list.c \ - memdev.c \ - ../util/json.c \ -+ json.c \ -+ filter.c \ -+ filter.h \ - builtin.h - - cxl_LDADD =\ -diff -up ndctl-71.1/cxl/filter.c.orig ndctl-71.1/cxl/filter.c ---- ndctl-71.1/cxl/filter.c.orig 2022-10-07 15:51:03.900535680 -0400 -+++ ndctl-71.1/cxl/filter.c 2022-10-07 15:51:03.900535680 -0400 -@@ -0,0 +1,25 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (C) 2015-2020 Intel Corporation. All rights reserved. -+#include -+#include -+#include -+#include "filter.h" -+ -+struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, -+ const char *ident) -+{ -+ int memdev_id; -+ -+ if (!ident || strcmp(ident, "all") == 0) -+ return memdev; -+ -+ if (strcmp(ident, cxl_memdev_get_devname(memdev)) == 0) -+ return memdev; -+ -+ if ((sscanf(ident, "%d", &memdev_id) == 1 -+ || sscanf(ident, "mem%d", &memdev_id) == 1) -+ && cxl_memdev_get_id(memdev) == memdev_id) -+ return memdev; -+ -+ return NULL; -+} -diff -up ndctl-71.1/cxl/filter.h.orig ndctl-71.1/cxl/filter.h ---- ndctl-71.1/cxl/filter.h.orig 2022-10-07 15:51:03.901535684 -0400 -+++ ndctl-71.1/cxl/filter.h 2022-10-07 15:51:03.901535684 -0400 -@@ -0,0 +1,7 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */ -+#ifndef _CXL_UTIL_FILTER_H_ -+#define _CXL_UTIL_FILTER_H_ -+struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, -+ const char *ident); -+#endif /* _CXL_UTIL_FILTER_H_ */ -diff -up ndctl-71.1/cxl/json.c.orig ndctl-71.1/cxl/json.c ---- ndctl-71.1/cxl/json.c.orig 2022-10-07 15:51:03.901535684 -0400 -+++ ndctl-71.1/cxl/json.c 2022-10-07 15:51:03.901535684 -0400 -@@ -0,0 +1,214 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (C) 2015-2020 Intel Corporation. All rights reserved. -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "json.h" -+ -+static struct json_object *util_cxl_memdev_health_to_json( -+ struct cxl_memdev *memdev, unsigned long flags) -+{ -+ struct json_object *jhealth; -+ struct json_object *jobj; -+ struct cxl_cmd *cmd; -+ u32 field; -+ int rc; -+ -+ jhealth = json_object_new_object(); -+ if (!jhealth) -+ return NULL; -+ if (!memdev) -+ goto err_jobj; -+ -+ cmd = cxl_cmd_new_get_health_info(memdev); -+ if (!cmd) -+ goto err_jobj; -+ -+ rc = cxl_cmd_submit(cmd); -+ if (rc < 0) -+ goto err_cmd; -+ rc = cxl_cmd_get_mbox_status(cmd); -+ if (rc != 0) -+ goto err_cmd; -+ -+ /* health_status fields */ -+ rc = cxl_cmd_health_info_get_maintenance_needed(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "maintenance_needed", jobj); -+ -+ rc = cxl_cmd_health_info_get_performance_degraded(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "performance_degraded", jobj); -+ -+ rc = cxl_cmd_health_info_get_hw_replacement_needed(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "hw_replacement_needed", jobj); -+ -+ /* media_status fields */ -+ rc = cxl_cmd_health_info_get_media_normal(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_normal", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_not_ready(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_not_ready", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_persistence_lost(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_persistence_lost", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_data_lost(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_data_lost", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_powerloss_persistence_loss(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_powerloss_persistence_loss", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_shutdown_persistence_loss(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_shutdown_persistence_loss", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_persistence_loss_imminent(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_persistence_loss_imminent", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_powerloss_data_loss(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_powerloss_data_loss", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_shutdown_data_loss(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_shutdown_data_loss", jobj); -+ -+ rc = cxl_cmd_health_info_get_media_data_loss_imminent(cmd); -+ jobj = json_object_new_boolean(rc); -+ if (jobj) -+ json_object_object_add(jhealth, "media_data_loss_imminent", jobj); -+ -+ /* ext_status fields */ -+ if (cxl_cmd_health_info_get_ext_life_used_normal(cmd)) -+ jobj = json_object_new_string("normal"); -+ else if (cxl_cmd_health_info_get_ext_life_used_warning(cmd)) -+ jobj = json_object_new_string("warning"); -+ else if (cxl_cmd_health_info_get_ext_life_used_critical(cmd)) -+ jobj = json_object_new_string("critical"); -+ else -+ jobj = json_object_new_string("unknown"); -+ if (jobj) -+ json_object_object_add(jhealth, "ext_life_used", jobj); -+ -+ if (cxl_cmd_health_info_get_ext_temperature_normal(cmd)) -+ jobj = json_object_new_string("normal"); -+ else if (cxl_cmd_health_info_get_ext_temperature_warning(cmd)) -+ jobj = json_object_new_string("warning"); -+ else if (cxl_cmd_health_info_get_ext_temperature_critical(cmd)) -+ jobj = json_object_new_string("critical"); -+ else -+ jobj = json_object_new_string("unknown"); -+ if (jobj) -+ json_object_object_add(jhealth, "ext_temperature", jobj); -+ -+ if (cxl_cmd_health_info_get_ext_corrected_volatile_normal(cmd)) -+ jobj = json_object_new_string("normal"); -+ else if (cxl_cmd_health_info_get_ext_corrected_volatile_warning(cmd)) -+ jobj = json_object_new_string("warning"); -+ else -+ jobj = json_object_new_string("unknown"); -+ if (jobj) -+ json_object_object_add(jhealth, "ext_corrected_volatile", jobj); -+ -+ if (cxl_cmd_health_info_get_ext_corrected_persistent_normal(cmd)) -+ jobj = json_object_new_string("normal"); -+ else if (cxl_cmd_health_info_get_ext_corrected_persistent_warning(cmd)) -+ jobj = json_object_new_string("warning"); -+ else -+ jobj = json_object_new_string("unknown"); -+ if (jobj) -+ json_object_object_add(jhealth, "ext_corrected_persistent", jobj); -+ -+ /* other fields */ -+ field = cxl_cmd_health_info_get_life_used(cmd); -+ if (field != 0xff) { -+ jobj = json_object_new_int(field); -+ if (jobj) -+ json_object_object_add(jhealth, "life_used_percent", jobj); -+ } -+ -+ field = cxl_cmd_health_info_get_temperature(cmd); -+ if (field != 0xffff) { -+ jobj = json_object_new_int(field); -+ if (jobj) -+ json_object_object_add(jhealth, "temperature", jobj); -+ } -+ -+ field = cxl_cmd_health_info_get_dirty_shutdowns(cmd); -+ jobj = json_object_new_int64(field); -+ if (jobj) -+ json_object_object_add(jhealth, "dirty_shutdowns", jobj); -+ -+ field = cxl_cmd_health_info_get_volatile_errors(cmd); -+ jobj = json_object_new_int64(field); -+ if (jobj) -+ json_object_object_add(jhealth, "volatile_errors", jobj); -+ -+ field = cxl_cmd_health_info_get_pmem_errors(cmd); -+ jobj = json_object_new_int64(field); -+ if (jobj) -+ json_object_object_add(jhealth, "pmem_errors", jobj); -+ -+ cxl_cmd_unref(cmd); -+ return jhealth; -+ -+err_cmd: -+ cxl_cmd_unref(cmd); -+err_jobj: -+ json_object_put(jhealth); -+ return NULL; -+} -+ -+struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, -+ unsigned long flags) -+{ -+ const char *devname = cxl_memdev_get_devname(memdev); -+ struct json_object *jdev, *jobj; -+ -+ jdev = json_object_new_object(); -+ if (!devname || !jdev) -+ return NULL; -+ -+ jobj = json_object_new_string(devname); -+ if (jobj) -+ json_object_object_add(jdev, "memdev", jobj); -+ -+ jobj = util_json_object_size(cxl_memdev_get_pmem_size(memdev), flags); -+ if (jobj) -+ json_object_object_add(jdev, "pmem_size", jobj); -+ -+ jobj = util_json_object_size(cxl_memdev_get_ram_size(memdev), flags); -+ if (jobj) -+ json_object_object_add(jdev, "ram_size", jobj); -+ -+ if (flags & UTIL_JSON_HEALTH) { -+ jobj = util_cxl_memdev_health_to_json(memdev, flags); -+ if (jobj) -+ json_object_object_add(jdev, "health", jobj); -+ } -+ return jdev; -+} -diff -up ndctl-71.1/cxl/json.h.orig ndctl-71.1/cxl/json.h ---- ndctl-71.1/cxl/json.h.orig 2022-10-07 15:51:03.901535684 -0400 -+++ ndctl-71.1/cxl/json.h 2022-10-07 15:51:03.901535684 -0400 -@@ -0,0 +1,8 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */ -+#ifndef __CXL_UTIL_JSON_H__ -+#define __CXL_UTIL_JSON_H__ -+struct cxl_memdev; -+struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, -+ unsigned long flags); -+#endif /* __CXL_UTIL_JSON_H__ */ -diff -up ndctl-71.1/cxl/list.c.orig ndctl-71.1/cxl/list.c ---- ndctl-71.1/cxl/list.c.orig 2022-10-07 15:50:40.072454553 -0400 -+++ ndctl-71.1/cxl/list.c 2022-10-07 15:51:03.901535684 -0400 -@@ -6,12 +6,14 @@ - #include - #include - #include --#include - #include - #include - #include - #include - -+#include "json.h" -+#include "filter.h" -+ - static struct { - bool memdevs; - bool idle; -diff -up ndctl-71.1/cxl/memdev.c.orig ndctl-71.1/cxl/memdev.c ---- ndctl-71.1/cxl/memdev.c.orig 2022-10-07 15:50:40.072454553 -0400 -+++ ndctl-71.1/cxl/memdev.c 2022-10-07 15:51:03.901535684 -0400 -@@ -6,12 +6,13 @@ - #include - #include - #include --#include - #include - #include - #include - #include - -+#include "filter.h" -+ - struct action_context { - FILE *f_out; - FILE *f_in; -diff -up ndctl-71.1/daxctl/Makefile.am.orig ndctl-71.1/daxctl/Makefile.am ---- ndctl-71.1/daxctl/Makefile.am.orig 2022-10-07 15:50:40.073454556 -0400 -+++ ndctl-71.1/daxctl/Makefile.am 2022-10-07 15:51:03.902535687 -0400 -@@ -18,6 +18,11 @@ daxctl_SOURCES =\ - migrate.c \ - device.c \ - ../util/json.c \ -+ ../util/json.h \ -+ json.c \ -+ json.h \ -+ filter.c \ -+ filter.h \ - builtin.h - - daxctl_LDADD =\ -diff -up ndctl-71.1/daxctl/device.c.orig ndctl-71.1/daxctl/device.c ---- ndctl-71.1/daxctl/device.c.orig 2022-10-07 15:50:40.074454560 -0400 -+++ ndctl-71.1/daxctl/device.c 2022-10-07 15:51:03.902535687 -0400 -@@ -11,13 +11,15 @@ - #include - #include - #include --#include - #include - #include - #include - #include - #include - -+#include "filter.h" -+#include "json.h" -+ - static struct { - const char *dev; - const char *mode; -diff -up ndctl-71.1/daxctl/filter.c.orig ndctl-71.1/daxctl/filter.c ---- ndctl-71.1/daxctl/filter.c.orig 2022-10-07 15:51:03.902535687 -0400 -+++ ndctl-71.1/daxctl/filter.c 2022-10-07 15:51:03.902535687 -0400 -@@ -0,0 +1,43 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (C) 2015-2020 Intel Corporation. All rights reserved. -+#include -+#include -+#include -+ -+#include "filter.h" -+ -+struct daxctl_dev *util_daxctl_dev_filter(struct daxctl_dev *dev, -+ const char *ident) -+{ -+ struct daxctl_region *region = daxctl_dev_get_region(dev); -+ int region_id, dev_id; -+ -+ if (!ident || strcmp(ident, "all") == 0) -+ return dev; -+ -+ if (strcmp(ident, daxctl_dev_get_devname(dev)) == 0) -+ return dev; -+ -+ if (sscanf(ident, "%d.%d", ®ion_id, &dev_id) == 2 && -+ daxctl_region_get_id(region) == region_id && -+ daxctl_dev_get_id(dev) == dev_id) -+ return dev; -+ -+ return NULL; -+} -+ -+struct daxctl_region *util_daxctl_region_filter(struct daxctl_region *region, -+ const char *ident) -+{ -+ int region_id; -+ -+ if (!ident || strcmp(ident, "all") == 0) -+ return region; -+ -+ if ((sscanf(ident, "%d", ®ion_id) == 1 || -+ sscanf(ident, "region%d", ®ion_id) == 1) && -+ daxctl_region_get_id(region) == region_id) -+ return region; -+ -+ return NULL; -+} -diff -up ndctl-71.1/daxctl/filter.h.orig ndctl-71.1/daxctl/filter.h ---- ndctl-71.1/daxctl/filter.h.orig 2022-10-07 15:51:03.902535687 -0400 -+++ ndctl-71.1/daxctl/filter.h 2022-10-07 15:51:03.902535687 -0400 -@@ -0,0 +1,12 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */ -+#ifndef _DAXCTL_UTIL_FILTER_H_ -+#define _DAXCTL_UTIL_FILTER_H_ -+#include -+#include -+ -+struct daxctl_dev *util_daxctl_dev_filter(struct daxctl_dev *dev, -+ const char *ident); -+struct daxctl_region *util_daxctl_region_filter(struct daxctl_region *region, -+ const char *ident); -+#endif /* _DAXCTL_UTIL_FILTER_H_ */ -diff -up ndctl-71.1/daxctl/json.c.orig ndctl-71.1/daxctl/json.c ---- ndctl-71.1/daxctl/json.c.orig 2022-10-07 15:51:03.903535690 -0400 -+++ ndctl-71.1/daxctl/json.c 2022-10-07 15:51:03.902535687 -0400 -@@ -0,0 +1,245 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (C) 2015-2020 Intel Corporation. All rights reserved. -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "filter.h" -+#include "json.h" -+ -+struct json_object *util_daxctl_dev_to_json(struct daxctl_dev *dev, -+ unsigned long flags) -+{ -+ struct daxctl_memory *mem = daxctl_dev_get_memory(dev); -+ const char *devname = daxctl_dev_get_devname(dev); -+ struct json_object *jdev, *jobj, *jmappings = NULL; -+ struct daxctl_mapping *mapping = NULL; -+ int node, movable, align; -+ -+ jdev = json_object_new_object(); -+ if (!devname || !jdev) -+ return NULL; -+ -+ jobj = json_object_new_string(devname); -+ if (jobj) -+ json_object_object_add(jdev, "chardev", jobj); -+ -+ jobj = util_json_object_size(daxctl_dev_get_size(dev), flags); -+ if (jobj) -+ json_object_object_add(jdev, "size", jobj); -+ -+ node = daxctl_dev_get_target_node(dev); -+ if (node >= 0) { -+ jobj = json_object_new_int(node); -+ if (jobj) -+ json_object_object_add(jdev, "target_node", jobj); -+ } -+ -+ align = daxctl_dev_get_align(dev); -+ if (align > 0) { -+ jobj = util_json_object_size(daxctl_dev_get_align(dev), flags); -+ if (jobj) -+ json_object_object_add(jdev, "align", jobj); -+ } -+ -+ if (mem) -+ jobj = json_object_new_string("system-ram"); -+ else -+ jobj = json_object_new_string("devdax"); -+ if (jobj) -+ json_object_object_add(jdev, "mode", jobj); -+ -+ if (mem && daxctl_dev_get_resource(dev) != 0) { -+ int num_sections = daxctl_memory_num_sections(mem); -+ int num_online = daxctl_memory_is_online(mem); -+ -+ jobj = json_object_new_int(num_online); -+ if (jobj) -+ json_object_object_add(jdev, "online_memblocks", jobj); -+ -+ jobj = json_object_new_int(num_sections); -+ if (jobj) -+ json_object_object_add(jdev, "total_memblocks", jobj); -+ -+ movable = daxctl_memory_is_movable(mem); -+ if (movable == 1) -+ jobj = json_object_new_boolean(true); -+ else if (movable == 0) -+ jobj = json_object_new_boolean(false); -+ else -+ jobj = NULL; -+ if (jobj) -+ json_object_object_add(jdev, "movable", jobj); -+ } -+ -+ if (!daxctl_dev_is_enabled(dev)) { -+ jobj = json_object_new_string("disabled"); -+ if (jobj) -+ json_object_object_add(jdev, "state", jobj); -+ } -+ -+ if (!(flags & UTIL_JSON_DAX_MAPPINGS)) -+ return jdev; -+ -+ daxctl_mapping_foreach(dev, mapping) { -+ struct json_object *jmapping; -+ -+ if (!jmappings) { -+ jmappings = json_object_new_array(); -+ if (!jmappings) -+ continue; -+ -+ json_object_object_add(jdev, "mappings", jmappings); -+ } -+ -+ jmapping = util_daxctl_mapping_to_json(mapping, flags); -+ if (!jmapping) -+ continue; -+ json_object_array_add(jmappings, jmapping); -+ } -+ return jdev; -+} -+ -+struct json_object *util_daxctl_devs_to_list(struct daxctl_region *region, -+ struct json_object *jdevs, const char *ident, -+ unsigned long flags) -+{ -+ struct daxctl_dev *dev; -+ -+ daxctl_dev_foreach(region, dev) { -+ struct json_object *jdev; -+ -+ if (!util_daxctl_dev_filter(dev, ident)) -+ continue; -+ -+ if (!(flags & (UTIL_JSON_IDLE|UTIL_JSON_CONFIGURED)) -+ && !daxctl_dev_get_size(dev)) -+ continue; -+ -+ if (!jdevs) { -+ jdevs = json_object_new_array(); -+ if (!jdevs) -+ return NULL; -+ } -+ -+ jdev = util_daxctl_dev_to_json(dev, flags); -+ if (!jdev) { -+ json_object_put(jdevs); -+ return NULL; -+ } -+ -+ json_object_array_add(jdevs, jdev); -+ } -+ -+ return jdevs; -+} -+ -+struct json_object *util_daxctl_region_to_json(struct daxctl_region *region, -+ const char *ident, unsigned long flags) -+{ -+ unsigned long align; -+ struct json_object *jregion, *jobj; -+ unsigned long long available_size, size; -+ -+ jregion = json_object_new_object(); -+ if (!jregion) -+ return NULL; -+ -+ /* -+ * The flag indicates when we are being called by an agent that -+ * already knows about the parent device information. -+ */ -+ if (!(flags & UTIL_JSON_DAX)) { -+ /* trim off the redundant /sys/devices prefix */ -+ const char *path = daxctl_region_get_path(region); -+ int len = strlen("/sys/devices"); -+ const char *trim = &path[len]; -+ -+ if (strncmp(path, "/sys/devices", len) != 0) -+ goto err; -+ jobj = json_object_new_string(trim); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jregion, "path", jobj); -+ } -+ -+ jobj = json_object_new_int(daxctl_region_get_id(region)); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jregion, "id", jobj); -+ -+ size = daxctl_region_get_size(region); -+ if (size < ULLONG_MAX) { -+ jobj = util_json_object_size(size, flags); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jregion, "size", jobj); -+ } -+ -+ available_size = daxctl_region_get_available_size(region); -+ if (available_size) { -+ jobj = util_json_object_size(available_size, flags); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jregion, "available_size", jobj); -+ } -+ -+ align = daxctl_region_get_align(region); -+ if (align < ULONG_MAX) { -+ jobj = json_object_new_int64(align); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jregion, "align", jobj); -+ } -+ -+ if (!(flags & UTIL_JSON_DAX_DEVS)) -+ return jregion; -+ -+ jobj = util_daxctl_devs_to_list(region, NULL, ident, flags); -+ if (jobj) -+ json_object_object_add(jregion, "devices", jobj); -+ -+ return jregion; -+ err: -+ json_object_put(jregion); -+ return NULL; -+} -+ -+struct json_object *util_daxctl_mapping_to_json(struct daxctl_mapping *mapping, -+ unsigned long flags) -+{ -+ struct json_object *jmapping = json_object_new_object(); -+ struct json_object *jobj; -+ -+ if (!jmapping) -+ return NULL; -+ -+ jobj = util_json_object_hex(daxctl_mapping_get_offset(mapping), flags); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jmapping, "page_offset", jobj); -+ -+ jobj = util_json_object_hex(daxctl_mapping_get_start(mapping), flags); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jmapping, "start", jobj); -+ -+ jobj = util_json_object_hex(daxctl_mapping_get_end(mapping), flags); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jmapping, "end", jobj); -+ -+ jobj = util_json_object_size(daxctl_mapping_get_size(mapping), flags); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jmapping, "size", jobj); -+ -+ return jmapping; -+ err: -+ json_object_put(jmapping); -+ return NULL; -+} -diff -up ndctl-71.1/daxctl/json.h.orig ndctl-71.1/daxctl/json.h ---- ndctl-71.1/daxctl/json.h.orig 2022-10-07 15:51:03.905535697 -0400 -+++ ndctl-71.1/daxctl/json.h 2022-10-07 15:51:03.904535694 -0400 -@@ -0,0 +1,18 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */ -+#ifndef __DAXCTL_JSON_H__ -+#define __DAXCTL_JSON_H__ -+#include -+ -+struct json_object *util_daxctl_mapping_to_json(struct daxctl_mapping *mapping, -+ unsigned long flags); -+struct daxctl_region; -+struct daxctl_dev; -+struct json_object *util_daxctl_region_to_json(struct daxctl_region *region, -+ const char *ident, unsigned long flags); -+struct json_object *util_daxctl_dev_to_json(struct daxctl_dev *dev, -+ unsigned long flags); -+struct json_object *util_daxctl_devs_to_list(struct daxctl_region *region, -+ struct json_object *jdevs, const char *ident, -+ unsigned long flags); -+#endif /* __CXL_UTIL_JSON_H__ */ -diff -up ndctl-71.1/daxctl/list.c.orig ndctl-71.1/daxctl/list.c ---- ndctl-71.1/daxctl/list.c.orig 2022-10-07 15:50:40.075454563 -0400 -+++ ndctl-71.1/daxctl/list.c 2022-10-07 15:51:03.905535697 -0400 -@@ -6,12 +6,14 @@ - #include - #include - #include --#include - #include - #include - #include - #include - -+#include "filter.h" -+#include "json.h" -+ - static struct { - bool devs; - bool regions; -diff -up ndctl-71.1/ndctl/Makefile.am.orig ndctl-71.1/ndctl/Makefile.am ---- ndctl-71.1/ndctl/Makefile.am.orig 2022-10-07 15:50:40.076454567 -0400 -+++ ndctl-71.1/ndctl/Makefile.am 2022-10-07 15:51:03.905535697 -0400 -@@ -19,13 +19,19 @@ ndctl_SOURCES = ndctl.c \ - region.c \ - dimm.c \ - ../util/log.c \ -- ../util/filter.c \ -- ../util/filter.h \ -+ ../daxctl/filter.c \ -+ ../daxctl/filter.h \ -+ filter.c \ -+ filter.h \ - list.c \ - ../util/json.c \ - ../util/json.h \ -- util/json-smart.c \ -- util/keys.h \ -+ ../daxctl/json.c \ -+ ../daxctl/json.h \ -+ json.c \ -+ json.h \ -+ json-smart.c \ -+ keys.h \ - inject-error.c \ - inject-smart.c \ - monitor.c \ -@@ -36,7 +42,7 @@ ndctl_SOURCES = ndctl.c \ - firmware-update.h - - if ENABLE_KEYUTILS --ndctl_SOURCES += util/keys.c \ -+ndctl_SOURCES += keys.c \ - load-keys.c - keys_configdir = $(ndctl_keysdir) - keys_config_DATA = $(ndctl_keysreadme) -diff -up ndctl-71.1/ndctl/bus.c.orig ndctl-71.1/ndctl/bus.c ---- ndctl-71.1/ndctl/bus.c.orig 2022-10-07 15:50:40.077454570 -0400 -+++ ndctl-71.1/ndctl/bus.c 2022-10-07 15:51:03.905535697 -0400 -@@ -8,12 +8,14 @@ - #include - #include - #include --#include - #include - #include - #include - #include - -+#include "filter.h" -+#include "json.h" -+ - static struct { - bool verbose; - bool force; -diff -up ndctl-71.1/ndctl/check.c.orig ndctl-71.1/ndctl/check.c ---- ndctl-71.1/ndctl/check.c.orig 2022-10-07 15:50:40.078454573 -0400 -+++ ndctl-71.1/ndctl/check.c 2022-10-07 15:51:03.906535700 -0400 -@@ -8,7 +8,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -20,6 +19,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff -up ndctl-71.1/ndctl/dimm.c.orig ndctl-71.1/ndctl/dimm.c ---- ndctl-71.1/ndctl/dimm.c.orig 2022-10-07 15:50:40.078454573 -0400 -+++ ndctl-71.1/ndctl/dimm.c 2022-10-07 15:51:03.907535704 -0400 -@@ -11,7 +11,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -20,7 +19,10 @@ - #include - #include - #include --#include -+ -+#include "filter.h" -+#include "json.h" -+#include "keys.h" - - static const char *cmd_name = "dimm"; - static int err_count; -diff -up ndctl-71.1/ndctl/filter.c.orig ndctl-71.1/ndctl/filter.c ---- ndctl-71.1/ndctl/filter.c.orig 2022-10-07 15:51:03.928535775 -0400 -+++ ndctl-71.1/ndctl/filter.c 2022-10-07 15:51:03.908535707 -0400 -@@ -0,0 +1,468 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (C) 2015-2020 Intel Corporation. All rights reserved. -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "filter.h" -+ -+struct ndctl_bus *util_bus_filter(struct ndctl_bus *bus, const char *__ident) -+{ -+ char *end = NULL, *ident, *save; -+ unsigned long bus_id, id; -+ const char *provider, *devname, *name; -+ -+ if (!__ident) -+ return bus; -+ -+ ident = strdup(__ident); -+ if (!ident) -+ return NULL; -+ -+ for (name = strtok_r(ident, " ", &save); name; -+ name = strtok_r(NULL, " ", &save)) { -+ if (strcmp(name, "all") == 0) -+ break; -+ -+ bus_id = strtoul(ident, &end, 0); -+ if (end == ident || end[0]) -+ bus_id = ULONG_MAX; -+ -+ provider = ndctl_bus_get_provider(bus); -+ devname = ndctl_bus_get_devname(bus); -+ id = ndctl_bus_get_id(bus); -+ -+ if (bus_id < ULONG_MAX && bus_id == id) -+ break; -+ -+ if (bus_id == ULONG_MAX && (strcmp(provider, name) == 0 -+ || strcmp(devname, name) == 0)) -+ break; -+ } -+ free(ident); -+ -+ if (name) -+ return bus; -+ return NULL; -+} -+ -+struct ndctl_region *util_region_filter(struct ndctl_region *region, -+ const char *__ident) -+{ -+ char *end = NULL, *ident, *save; -+ const char *name, *region_name; -+ unsigned long region_id, id; -+ -+ if (!__ident) -+ return region; -+ -+ ident = strdup(__ident); -+ if (!ident) -+ return NULL; -+ -+ for (name = strtok_r(ident, " ", &save); name; -+ name = strtok_r(NULL, " ", &save)) { -+ if (strcmp(name, "all") == 0) -+ break; -+ -+ region_id = strtoul(ident, &end, 0); -+ if (end == ident || end[0]) -+ region_id = ULONG_MAX; -+ -+ region_name = ndctl_region_get_devname(region); -+ id = ndctl_region_get_id(region); -+ -+ if (region_id < ULONG_MAX && region_id == id) -+ break; -+ -+ if (region_id == ULONG_MAX && strcmp(region_name, name) == 0) -+ break; -+ } -+ free(ident); -+ -+ if (name) -+ return region; -+ return NULL; -+} -+ -+struct ndctl_namespace *util_namespace_filter(struct ndctl_namespace *ndns, -+ const char *__ident) -+{ -+ struct ndctl_region *region = ndctl_namespace_get_region(ndns); -+ unsigned long region_id, ndns_id; -+ const char *name; -+ char *ident, *save; -+ -+ if (!__ident) -+ return ndns; -+ -+ ident = strdup(__ident); -+ if (!ident) -+ return NULL; -+ -+ for (name = strtok_r(ident, " ", &save); name; -+ name = strtok_r(NULL, " ", &save)) { -+ if (strcmp(name, "all") == 0) -+ break; -+ -+ if (strcmp(name, ndctl_namespace_get_devname(ndns)) == 0) -+ break; -+ -+ if (sscanf(name, "%ld.%ld", ®ion_id, &ndns_id) == 2 -+ && ndctl_region_get_id(region) == region_id -+ && ndctl_namespace_get_id(ndns) == ndns_id) -+ break; -+ } -+ free(ident); -+ -+ if (name) -+ return ndns; -+ return NULL; -+} -+ -+struct ndctl_dimm *util_dimm_filter(struct ndctl_dimm *dimm, -+ const char *__ident) -+{ -+ char *end = NULL, *ident, *save; -+ const char *name, *dimm_name; -+ unsigned long dimm_id, id; -+ -+ if (!__ident) -+ return dimm; -+ -+ ident = strdup(__ident); -+ if (!ident) -+ return NULL; -+ -+ for (name = strtok_r(ident, " ", &save); name; -+ name = strtok_r(NULL, " ", &save)) { -+ if (strcmp(name, "all") == 0) -+ break; -+ -+ dimm_id = strtoul(ident, &end, 0); -+ if (end == ident || end[0]) -+ dimm_id = ULONG_MAX; -+ -+ dimm_name = ndctl_dimm_get_devname(dimm); -+ id = ndctl_dimm_get_id(dimm); -+ -+ if (dimm_id < ULONG_MAX && dimm_id == id) -+ break; -+ -+ if (dimm_id == ULONG_MAX && strcmp(dimm_name, name) == 0) -+ break; -+ } -+ free(ident); -+ -+ if (name) -+ return dimm; -+ return NULL; -+} -+ -+struct ndctl_bus *util_bus_filter_by_dimm(struct ndctl_bus *bus, -+ const char *ident) -+{ -+ struct ndctl_dimm *dimm; -+ -+ if (!ident || strcmp(ident, "all") == 0) -+ return bus; -+ -+ ndctl_dimm_foreach(bus, dimm) -+ if (util_dimm_filter(dimm, ident)) -+ return bus; -+ return NULL; -+} -+ -+struct ndctl_bus *util_bus_filter_by_region(struct ndctl_bus *bus, -+ const char *ident) -+{ -+ struct ndctl_region *region; -+ -+ if (!ident || strcmp(ident, "all") == 0) -+ return bus; -+ -+ ndctl_region_foreach(bus, region) -+ if (util_region_filter(region, ident)) -+ return bus; -+ return NULL; -+} -+ -+struct ndctl_bus *util_bus_filter_by_namespace(struct ndctl_bus *bus, -+ const char *ident) -+{ -+ struct ndctl_region *region; -+ struct ndctl_namespace *ndns; -+ -+ if (!ident || strcmp(ident, "all") == 0) -+ return bus; -+ -+ ndctl_region_foreach(bus, region) -+ ndctl_namespace_foreach(region, ndns) -+ if (util_namespace_filter(ndns, ident)) -+ return bus; -+ return NULL; -+} -+ -+struct ndctl_region *util_region_filter_by_dimm(struct ndctl_region *region, -+ const char *ident) -+{ -+ struct ndctl_dimm *dimm; -+ -+ if (!ident || strcmp(ident, "all") == 0) -+ return region; -+ -+ ndctl_dimm_foreach_in_region(region, dimm) -+ if (util_dimm_filter(dimm, ident)) -+ return region; -+ -+ return NULL; -+} -+ -+struct ndctl_dimm *util_dimm_filter_by_region(struct ndctl_dimm *dimm, -+ const char *ident) -+{ -+ struct ndctl_bus *bus = ndctl_dimm_get_bus(dimm); -+ struct ndctl_region *region; -+ struct ndctl_dimm *check; -+ -+ if (!ident || strcmp(ident, "all") == 0) -+ return dimm; -+ -+ ndctl_region_foreach(bus, region) { -+ if (!util_region_filter(region, ident)) -+ continue; -+ ndctl_dimm_foreach_in_region(region, check) -+ if (check == dimm) -+ return dimm; -+ } -+ -+ return NULL; -+} -+ -+struct ndctl_dimm *util_dimm_filter_by_namespace(struct ndctl_dimm *dimm, -+ const char *ident) -+{ -+ struct ndctl_bus *bus = ndctl_dimm_get_bus(dimm); -+ struct ndctl_namespace *ndns; -+ struct ndctl_region *region; -+ struct ndctl_dimm *check; -+ -+ if (!ident || strcmp(ident, "all") == 0) -+ return dimm; -+ -+ ndctl_region_foreach(bus, region) { -+ ndctl_namespace_foreach(region, ndns) { -+ if (!util_namespace_filter(ndns, ident)) -+ continue; -+ ndctl_dimm_foreach_in_region(region, check) -+ if (check == dimm) -+ return dimm; -+ } -+ } -+ -+ return NULL; -+} -+ -+struct ndctl_dimm *util_dimm_filter_by_numa_node(struct ndctl_dimm *dimm, -+ int numa_node) -+{ -+ struct ndctl_bus *bus = ndctl_dimm_get_bus(dimm); -+ struct ndctl_region *region; -+ struct ndctl_dimm *check; -+ -+ if (numa_node == NUMA_NO_NODE) -+ return dimm; -+ -+ ndctl_region_foreach(bus, region) -+ ndctl_dimm_foreach_in_region(region, check) -+ if (check == dimm && -+ ndctl_region_get_numa_node(region) == numa_node) -+ return dimm; -+ -+ return NULL; -+} -+ -+struct ndctl_region *util_region_filter_by_namespace(struct ndctl_region *region, -+ const char *ident) -+{ -+ struct ndctl_namespace *ndns; -+ -+ if (!ident || strcmp(ident, "all") == 0) -+ return region; -+ -+ ndctl_namespace_foreach(region, ndns) -+ if (util_namespace_filter(ndns, ident)) -+ return region; -+ return NULL; -+} -+ -+enum ndctl_namespace_mode util_nsmode(const char *mode) -+{ -+ if (!mode) -+ return NDCTL_NS_MODE_UNKNOWN; -+ if (strcasecmp(mode, "memory") == 0) -+ return NDCTL_NS_MODE_FSDAX; -+ if (strcasecmp(mode, "fsdax") == 0) -+ return NDCTL_NS_MODE_FSDAX; -+ if (strcasecmp(mode, "sector") == 0) -+ return NDCTL_NS_MODE_SECTOR; -+ if (strcasecmp(mode, "safe") == 0) -+ return NDCTL_NS_MODE_SECTOR; -+ if (strcasecmp(mode, "dax") == 0) -+ return NDCTL_NS_MODE_DEVDAX; -+ if (strcasecmp(mode, "devdax") == 0) -+ return NDCTL_NS_MODE_DEVDAX; -+ if (strcasecmp(mode, "raw") == 0) -+ return NDCTL_NS_MODE_RAW; -+ -+ return NDCTL_NS_MODE_UNKNOWN; -+} -+ -+const char *util_nsmode_name(enum ndctl_namespace_mode mode) -+{ -+ static const char * const modes[] = { -+ [NDCTL_NS_MODE_FSDAX] = "fsdax", -+ [NDCTL_NS_MODE_DEVDAX] = "devdax", -+ [NDCTL_NS_MODE_RAW] = "raw", -+ [NDCTL_NS_MODE_SECTOR] = "sector", -+ [NDCTL_NS_MODE_UNKNOWN] = "unknown", -+ }; -+ -+ return modes[mode]; -+} -+ -+int util_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx, -+ struct util_filter_params *param) -+{ -+ struct ndctl_bus *bus; -+ unsigned int type = 0; -+ int numa_node = NUMA_NO_NODE; -+ char *end = NULL; -+ -+ if (param->type && (strcmp(param->type, "pmem") != 0 -+ && strcmp(param->type, "blk") != 0)) { -+ error("unknown type \"%s\" must be \"pmem\" or \"blk\"\n", -+ param->type); -+ return -EINVAL; -+ } -+ -+ if (param->type) { -+ if (strcmp(param->type, "pmem") == 0) -+ type = ND_DEVICE_REGION_PMEM; -+ else -+ type = ND_DEVICE_REGION_BLK; -+ } -+ -+ if (param->mode && util_nsmode(param->mode) == NDCTL_NS_MODE_UNKNOWN) { -+ error("invalid mode: '%s'\n", param->mode); -+ return -EINVAL; -+ } -+ -+ if (param->numa_node && strcmp(param->numa_node, "all") != 0) { -+ struct stat st; -+ -+ if (stat("/sys/devices/system/node", &st) != 0) { -+ error("This system does not support NUMA"); -+ return -EINVAL; -+ } -+ -+ numa_node = strtol(param->numa_node, &end, 0); -+ if (end == param->numa_node || end[0]) { -+ error("invalid numa_node: '%s'\n", param->numa_node); -+ return -EINVAL; -+ } -+ } -+ -+ ndctl_bus_foreach(ctx, bus) { -+ struct ndctl_region *region; -+ struct ndctl_dimm *dimm; -+ -+ if (!util_bus_filter(bus, param->bus) -+ || !util_bus_filter_by_dimm(bus, param->dimm) -+ || !util_bus_filter_by_region(bus, param->region) -+ || !util_bus_filter_by_namespace(bus, param->namespace)) -+ continue; -+ -+ if (!fctx->filter_bus(bus, fctx)) -+ continue; -+ -+ ndctl_dimm_foreach(bus, dimm) { -+ if (!fctx->filter_dimm) -+ break; -+ -+ if (!util_dimm_filter(dimm, param->dimm) -+ || !util_dimm_filter_by_region(dimm, -+ param->region) -+ || !util_dimm_filter_by_namespace(dimm, -+ param->namespace) -+ || !util_dimm_filter_by_numa_node(dimm, -+ numa_node)) -+ continue; -+ -+ fctx->filter_dimm(dimm, fctx); -+ } -+ -+ ndctl_region_foreach(bus, region) { -+ struct ndctl_namespace *ndns; -+ -+ if (!util_region_filter(region, param->region) -+ || !util_region_filter_by_dimm(region, -+ param->dimm) -+ || !util_region_filter_by_namespace(region, -+ param->namespace)) -+ continue; -+ -+ /* -+ * if numa_node attribute is not available for regions -+ * (which is true for pre 5.4 kernels), don't skip the -+ * region if namespace is also requested, let the -+ * namespace filter handle the NUMA node filtering. -+ */ -+ if (numa_node != NUMA_NO_NODE && -+ !ndctl_region_has_numa(region) && -+ !fctx->filter_namespace) { -+ fprintf(stderr, -+ "This kernel does not provide NUMA node information per-region\n"); -+ continue; -+ } -+ -+ if (ndctl_region_has_numa(region) && -+ numa_node != NUMA_NO_NODE && -+ ndctl_region_get_numa_node(region) != numa_node) -+ continue; -+ -+ if (type && ndctl_region_get_type(region) != type) -+ continue; -+ -+ if (!fctx->filter_region(region, fctx)) -+ continue; -+ -+ ndctl_namespace_foreach(region, ndns) { -+ enum ndctl_namespace_mode mode; -+ -+ if (!fctx->filter_namespace) -+ break; -+ if (!util_namespace_filter(ndns, param->namespace)) -+ continue; -+ -+ mode = ndctl_namespace_get_mode(ndns); -+ if (param->mode && util_nsmode(param->mode) != mode) -+ continue; -+ -+ if (numa_node != NUMA_NO_NODE && -+ ndctl_namespace_get_numa_node(ndns) != numa_node) -+ continue; -+ -+ fctx->filter_namespace(ndns, fctx); -+ } -+ } -+ } -+ return 0; -+} -diff -up ndctl-71.1/ndctl/filter.h.orig ndctl-71.1/ndctl/filter.h ---- ndctl-71.1/ndctl/filter.h.orig 2022-10-07 15:51:03.929535779 -0400 -+++ ndctl-71.1/ndctl/filter.h 2022-10-07 15:51:03.908535707 -0400 -@@ -0,0 +1,86 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */ -+#ifndef _NDCTL_UTIL_FILTER_H_ -+#define _NDCTL_UTIL_FILTER_H_ -+#include -+#include -+ -+struct ndctl_bus *util_bus_filter(struct ndctl_bus *bus, const char *ident); -+struct ndctl_region *util_region_filter(struct ndctl_region *region, -+ const char *ident); -+struct ndctl_namespace *util_namespace_filter(struct ndctl_namespace *ndns, -+ const char *ident); -+struct ndctl_dimm *util_dimm_filter(struct ndctl_dimm *dimm, const char *ident); -+struct ndctl_bus *util_bus_filter_by_dimm(struct ndctl_bus *bus, -+ const char *ident); -+struct ndctl_bus *util_bus_filter_by_region(struct ndctl_bus *bus, -+ const char *ident); -+struct ndctl_bus *util_bus_filter_by_namespace(struct ndctl_bus *bus, -+ const char *ident); -+struct ndctl_region *util_region_filter_by_dimm(struct ndctl_region *region, -+ const char *ident); -+struct ndctl_dimm *util_dimm_filter_by_region(struct ndctl_dimm *dimm, -+ const char *ident); -+struct ndctl_dimm *util_dimm_filter_by_namespace(struct ndctl_dimm *dimm, -+ const char *ident); -+struct ndctl_region *util_region_filter_by_namespace(struct ndctl_region *region, -+ const char *ident); -+ -+enum ndctl_namespace_mode util_nsmode(const char *mode); -+const char *util_nsmode_name(enum ndctl_namespace_mode mode); -+ -+struct json_object; -+ -+/* json object hierarchy for the util_filter_walk() performed by cmd_list() */ -+struct list_filter_arg { -+ struct json_object *jnamespaces; -+ struct json_object *jregions; -+ struct json_object *jdimms; -+ struct json_object *jbuses; -+ struct json_object *jregion; -+ struct json_object *jbus; -+ unsigned long flags; -+}; -+ -+struct monitor_filter_arg { -+ struct list_head dimms; -+ int maxfd_dimm; -+ int num_dimm; -+ unsigned long flags; -+}; -+ -+/* -+ * struct util_filter_ctx - control and callbacks for util_filter_walk() -+ * ->filter_bus() and ->filter_region() return bool because the -+ * child-object filter routines can not be called if the parent context -+ * is not established. ->filter_dimm() and ->filter_namespace() are leaf -+ * objects, so no child dependencies to check. -+ */ -+struct util_filter_ctx { -+ bool (*filter_bus)(struct ndctl_bus *bus, struct util_filter_ctx *ctx); -+ void (*filter_dimm)(struct ndctl_dimm *dimm, struct util_filter_ctx *ctx); -+ bool (*filter_region)(struct ndctl_region *region, -+ struct util_filter_ctx *ctx); -+ void (*filter_namespace)(struct ndctl_namespace *ndns, -+ struct util_filter_ctx *ctx); -+ union { -+ void *arg; -+ struct list_filter_arg *list; -+ struct monitor_filter_arg *monitor; -+ }; -+}; -+ -+struct util_filter_params { -+ const char *bus; -+ const char *region; -+ const char *type; -+ const char *dimm; -+ const char *mode; -+ const char *namespace; -+ const char *numa_node; -+}; -+ -+struct ndctl_ctx; -+int util_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx, -+ struct util_filter_params *param); -+#endif /* _NDCTL_UTIL_FILTER_H_ */ -diff -up ndctl-71.1/ndctl/inject-error.c.orig ndctl-71.1/ndctl/inject-error.c ---- ndctl-71.1/ndctl/inject-error.c.orig 2022-10-07 15:50:40.081454584 -0400 -+++ ndctl-71.1/ndctl/inject-error.c 2022-10-07 15:51:03.909535711 -0400 -@@ -12,12 +12,11 @@ - #include - #include - --#include - #include - #include - #include - #include --#include -+#include - #include - #include - #include -@@ -26,6 +25,9 @@ - #include - #include - -+#include "filter.h" -+#include "json.h" -+ - static bool verbose; - static struct parameters { - const char *bus; -diff -up ndctl-71.1/ndctl/inject-smart.c.orig ndctl-71.1/ndctl/inject-smart.c ---- ndctl-71.1/ndctl/inject-smart.c.orig 2022-10-07 15:50:40.081454584 -0400 -+++ ndctl-71.1/ndctl/inject-smart.c 2022-10-07 15:51:03.910535714 -0400 -@@ -13,12 +13,11 @@ - #include - #include - --#include - #include - #include - #include - #include --#include -+#include - #include - #include - #include -@@ -27,6 +26,9 @@ - #include - #include - -+#include "filter.h" -+#include "json.h" -+ - static struct parameters { - const char *bus; - const char *dimm; -diff -up ndctl-71.1/ndctl/json-smart.c.orig ndctl-71.1/ndctl/json-smart.c ---- ndctl-71.1/ndctl/json-smart.c.orig 2022-10-07 15:51:03.929535779 -0400 -+++ ndctl-71.1/ndctl/json-smart.c 2022-10-07 15:51:03.910535714 -0400 -@@ -0,0 +1,214 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (C) 2015-2020 Intel Corporation. All rights reserved. -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "json.h" -+ -+static void smart_threshold_to_json(struct ndctl_dimm *dimm, -+ struct json_object *jhealth) -+{ -+ unsigned int alarm_control; -+ struct json_object *jobj; -+ struct ndctl_cmd *cmd; -+ int rc; -+ -+ cmd = ndctl_dimm_cmd_new_smart_threshold(dimm); -+ if (!cmd) -+ return; -+ -+ rc = ndctl_cmd_submit_xlat(cmd); -+ if (rc < 0) -+ goto out; -+ -+ alarm_control = ndctl_cmd_smart_threshold_get_alarm_control(cmd); -+ if (alarm_control & ND_SMART_TEMP_TRIP) { -+ unsigned int temp; -+ double t; -+ -+ jobj = json_object_new_boolean(true); -+ if (jobj) -+ json_object_object_add(jhealth, -+ "alarm_enabled_media_temperature", jobj); -+ temp = ndctl_cmd_smart_threshold_get_temperature(cmd); -+ t = ndctl_decode_smart_temperature(temp); -+ jobj = json_object_new_double(t); -+ if (jobj) -+ json_object_object_add(jhealth, -+ "temperature_threshold", jobj); -+ } else { -+ jobj = json_object_new_boolean(false); -+ if (jobj) -+ json_object_object_add(jhealth, -+ "alarm_enabled_media_temperature", jobj); -+ } -+ -+ if (alarm_control & ND_SMART_CTEMP_TRIP) { -+ unsigned int temp; -+ double t; -+ -+ jobj = json_object_new_boolean(true); -+ if (jobj) -+ json_object_object_add(jhealth, -+ "alarm_enabled_ctrl_temperature", jobj); -+ temp = ndctl_cmd_smart_threshold_get_ctrl_temperature(cmd); -+ t = ndctl_decode_smart_temperature(temp); -+ jobj = json_object_new_double(t); -+ if (jobj) -+ json_object_object_add(jhealth, -+ "controller_temperature_threshold", jobj); -+ } else { -+ jobj = json_object_new_boolean(false); -+ if (jobj) -+ json_object_object_add(jhealth, -+ "alarm_enabled_ctrl_temperature", jobj); -+ } -+ -+ if (alarm_control & ND_SMART_SPARE_TRIP) { -+ unsigned int spares; -+ -+ jobj = json_object_new_boolean(true); -+ if (jobj) -+ json_object_object_add(jhealth, -+ "alarm_enabled_spares", jobj); -+ spares = ndctl_cmd_smart_threshold_get_spares(cmd); -+ jobj = json_object_new_int(spares); -+ if (jobj) -+ json_object_object_add(jhealth, -+ "spares_threshold", jobj); -+ } else { -+ jobj = json_object_new_boolean(false); -+ if (jobj) -+ json_object_object_add(jhealth, -+ "alarm_enabled_spares", jobj); -+ } -+ -+ out: -+ ndctl_cmd_unref(cmd); -+} -+ -+struct json_object *util_dimm_health_to_json(struct ndctl_dimm *dimm) -+{ -+ struct json_object *jhealth = json_object_new_object(); -+ struct json_object *jobj; -+ struct ndctl_cmd *cmd; -+ unsigned int flags; -+ int rc; -+ -+ if (!jhealth) -+ return NULL; -+ -+ cmd = ndctl_dimm_cmd_new_smart(dimm); -+ if (!cmd) -+ goto err; -+ -+ rc = ndctl_cmd_submit_xlat(cmd); -+ if (rc < 0) { -+ jobj = json_object_new_string("unknown"); -+ if (jobj) -+ json_object_object_add(jhealth, "health_state", jobj); -+ goto out; -+ } -+ -+ flags = ndctl_cmd_smart_get_flags(cmd); -+ if (flags & ND_SMART_HEALTH_VALID) { -+ unsigned int health = ndctl_cmd_smart_get_health(cmd); -+ -+ if (health & ND_SMART_FATAL_HEALTH) -+ jobj = json_object_new_string("fatal"); -+ else if (health & ND_SMART_CRITICAL_HEALTH) -+ jobj = json_object_new_string("critical"); -+ else if (health & ND_SMART_NON_CRITICAL_HEALTH) -+ jobj = json_object_new_string("non-critical"); -+ else -+ jobj = json_object_new_string("ok"); -+ if (jobj) -+ json_object_object_add(jhealth, "health_state", jobj); -+ } -+ -+ if (flags & ND_SMART_TEMP_VALID) { -+ unsigned int temp = ndctl_cmd_smart_get_temperature(cmd); -+ double t = ndctl_decode_smart_temperature(temp); -+ -+ jobj = json_object_new_double(t); -+ if (jobj) -+ json_object_object_add(jhealth, "temperature_celsius", jobj); -+ } -+ -+ if (flags & ND_SMART_CTEMP_VALID) { -+ unsigned int temp = ndctl_cmd_smart_get_ctrl_temperature(cmd); -+ double t = ndctl_decode_smart_temperature(temp); -+ -+ jobj = json_object_new_double(t); -+ if (jobj) -+ json_object_object_add(jhealth, -+ "controller_temperature_celsius", jobj); -+ } -+ -+ if (flags & ND_SMART_SPARES_VALID) { -+ unsigned int spares = ndctl_cmd_smart_get_spares(cmd); -+ -+ jobj = json_object_new_int(spares); -+ if (jobj) -+ json_object_object_add(jhealth, "spares_percentage", jobj); -+ } -+ -+ if (flags & ND_SMART_ALARM_VALID) { -+ unsigned int alarm_flags = ndctl_cmd_smart_get_alarm_flags(cmd); -+ bool temp_flag = !!(alarm_flags & ND_SMART_TEMP_TRIP); -+ bool ctrl_temp_flag = !!(alarm_flags & ND_SMART_CTEMP_TRIP); -+ bool spares_flag = !!(alarm_flags & ND_SMART_SPARE_TRIP); -+ -+ jobj = json_object_new_boolean(temp_flag); -+ if (jobj) -+ json_object_object_add(jhealth, "alarm_temperature", jobj); -+ -+ jobj = json_object_new_boolean(ctrl_temp_flag); -+ if (jobj) -+ json_object_object_add(jhealth, "alarm_controller_temperature", jobj); -+ -+ jobj = json_object_new_boolean(spares_flag); -+ if (jobj) -+ json_object_object_add(jhealth, "alarm_spares", jobj); -+ } -+ -+ smart_threshold_to_json(dimm, jhealth); -+ -+ if (flags & ND_SMART_USED_VALID) { -+ unsigned int life_used = ndctl_cmd_smart_get_life_used(cmd); -+ -+ jobj = json_object_new_int(life_used); -+ if (jobj) -+ json_object_object_add(jhealth, "life_used_percentage", jobj); -+ } -+ -+ if (flags & ND_SMART_SHUTDOWN_VALID) { -+ unsigned int shutdown = ndctl_cmd_smart_get_shutdown_state(cmd); -+ -+ jobj = json_object_new_string(shutdown ? "dirty" : "clean"); -+ if (jobj) -+ json_object_object_add(jhealth, "shutdown_state", jobj); -+ } -+ -+ if (flags & ND_SMART_SHUTDOWN_COUNT_VALID) { -+ unsigned int shutdown = ndctl_cmd_smart_get_shutdown_count(cmd); -+ -+ jobj = json_object_new_int(shutdown); -+ if (jobj) -+ json_object_object_add(jhealth, "shutdown_count", jobj); -+ } -+ -+ ndctl_cmd_unref(cmd); -+ return jhealth; -+ err: -+ json_object_put(jhealth); -+ jhealth = NULL; -+ out: -+ if (cmd) -+ ndctl_cmd_unref(cmd); -+ return jhealth; -+} -diff -up ndctl-71.1/ndctl/json.c.orig ndctl-71.1/ndctl/json.c ---- ndctl-71.1/ndctl/json.c.orig 2022-10-07 15:51:03.912535721 -0400 -+++ ndctl-71.1/ndctl/json.c 2022-10-07 15:51:03.912535721 -0400 -@@ -0,0 +1,1114 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (C) 2015-2020 Intel Corporation. All rights reserved. -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "json.h" -+#include "ndctl.h" -+#include "../daxctl/json.h" -+ -+struct json_object *util_bus_to_json(struct ndctl_bus *bus, unsigned long flags) -+{ -+ struct json_object *jbus = json_object_new_object(); -+ struct json_object *jobj, *fw_obj = NULL; -+ int scrub; -+ -+ if (!jbus) -+ return NULL; -+ -+ jobj = json_object_new_string(ndctl_bus_get_provider(bus)); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jbus, "provider", jobj); -+ -+ jobj = json_object_new_string(ndctl_bus_get_devname(bus)); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jbus, "dev", jobj); -+ -+ scrub = ndctl_bus_get_scrub_state(bus); -+ if (scrub < 0) -+ return jbus; -+ -+ jobj = json_object_new_string(scrub ? "active" : "idle"); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jbus, "scrub_state", jobj); -+ -+ if (flags & UTIL_JSON_FIRMWARE) { -+ struct ndctl_dimm *dimm; -+ -+ /* -+ * Skip displaying firmware activation capability if no -+ * DIMMs support firmware update. -+ */ -+ ndctl_dimm_foreach(bus, dimm) -+ if (ndctl_dimm_fw_update_supported(dimm) == 0) { -+ fw_obj = json_object_new_object(); -+ break; -+ } -+ } -+ -+ if (fw_obj) { -+ enum ndctl_fwa_state state; -+ enum ndctl_fwa_method method; -+ -+ jobj = NULL; -+ method = ndctl_bus_get_fw_activate_method(bus); -+ if (method == NDCTL_FWA_METHOD_RESET) -+ jobj = json_object_new_string("reset"); -+ if (method == NDCTL_FWA_METHOD_SUSPEND) -+ jobj = json_object_new_string("suspend"); -+ if (method == NDCTL_FWA_METHOD_LIVE) -+ jobj = json_object_new_string("live"); -+ if (jobj) -+ json_object_object_add(fw_obj, "activate_method", jobj); -+ -+ jobj = NULL; -+ state = ndctl_bus_get_fw_activate_state(bus); -+ if (state == NDCTL_FWA_ARMED) -+ jobj = json_object_new_string("armed"); -+ if (state == NDCTL_FWA_IDLE) -+ jobj = json_object_new_string("idle"); -+ if (state == NDCTL_FWA_ARM_OVERFLOW) -+ jobj = json_object_new_string("overflow"); -+ if (jobj) -+ json_object_object_add(fw_obj, "activate_state", jobj); -+ -+ json_object_object_add(jbus, "firmware", fw_obj); -+ } -+ -+ return jbus; -+ err: -+ json_object_put(jbus); -+ return NULL; -+} -+ -+ -+ -+struct json_object *util_dimm_firmware_to_json(struct ndctl_dimm *dimm, -+ unsigned long flags) -+{ -+ struct json_object *jfirmware = json_object_new_object(); -+ bool can_update, need_powercycle; -+ enum ndctl_fwa_result result; -+ enum ndctl_fwa_state state; -+ struct json_object *jobj; -+ struct ndctl_cmd *cmd; -+ uint64_t run, next; -+ int rc; -+ -+ if (!jfirmware) -+ return NULL; -+ -+ cmd = ndctl_dimm_cmd_new_fw_get_info(dimm); -+ if (!cmd) -+ goto err; -+ -+ rc = ndctl_cmd_submit(cmd); -+ if ((rc < 0) || ndctl_cmd_fw_xlat_firmware_status(cmd) != FW_SUCCESS) { -+ jobj = util_json_object_hex(-1, flags); -+ if (jobj) -+ json_object_object_add(jfirmware, "current_version", -+ jobj); -+ goto out; -+ } -+ -+ run = ndctl_cmd_fw_info_get_run_version(cmd); -+ if (run == ULLONG_MAX) { -+ jobj = util_json_object_hex(-1, flags); -+ if (jobj) -+ json_object_object_add(jfirmware, "current_version", -+ jobj); -+ goto out; -+ } -+ -+ jobj = util_json_object_hex(run, flags); -+ if (jobj) -+ json_object_object_add(jfirmware, "current_version", jobj); -+ -+ rc = ndctl_dimm_fw_update_supported(dimm); -+ can_update = rc == 0; -+ jobj = json_object_new_boolean(can_update); -+ if (jobj) -+ json_object_object_add(jfirmware, "can_update", jobj); -+ -+ -+ next = ndctl_cmd_fw_info_get_updated_version(cmd); -+ if (next == ULLONG_MAX) { -+ jobj = util_json_object_hex(-1, flags); -+ if (jobj) -+ json_object_object_add(jfirmware, "next_version", -+ jobj); -+ goto out; -+ } -+ -+ if (!next) -+ goto out; -+ -+ jobj = util_json_object_hex(next, flags); -+ if (jobj) -+ json_object_object_add(jfirmware, -+ "next_version", jobj); -+ -+ state = ndctl_dimm_get_fw_activate_state(dimm); -+ switch (state) { -+ case NDCTL_FWA_IDLE: -+ jobj = json_object_new_string("idle"); -+ break; -+ case NDCTL_FWA_ARMED: -+ jobj = json_object_new_string("armed"); -+ break; -+ case NDCTL_FWA_BUSY: -+ jobj = json_object_new_string("busy"); -+ break; -+ default: -+ jobj = NULL; -+ break; -+ } -+ if (jobj) -+ json_object_object_add(jfirmware, "activate_state", jobj); -+ -+ result = ndctl_dimm_get_fw_activate_result(dimm); -+ switch (result) { -+ case NDCTL_FWA_RESULT_NONE: -+ case NDCTL_FWA_RESULT_SUCCESS: -+ case NDCTL_FWA_RESULT_NOTSTAGED: -+ /* -+ * If a 'next' firmware version is staged then this -+ * result is stale, if the activation succeeds that is -+ * indicated by not finding a 'next' entry. -+ */ -+ need_powercycle = false; -+ break; -+ case NDCTL_FWA_RESULT_NEEDRESET: -+ case NDCTL_FWA_RESULT_FAIL: -+ default: -+ /* -+ * If the last activation failed, or if the activation -+ * result is unavailable it is always the case that the -+ * only remediation is powercycle. -+ */ -+ need_powercycle = true; -+ break; -+ } -+ -+ if (need_powercycle) { -+ jobj = json_object_new_boolean(true); -+ if (!jobj) -+ goto out; -+ json_object_object_add(jfirmware, "need_powercycle", jobj); -+ } -+ -+ ndctl_cmd_unref(cmd); -+ return jfirmware; -+ -+err: -+ json_object_put(jfirmware); -+ jfirmware = NULL; -+out: -+ if (cmd) -+ ndctl_cmd_unref(cmd); -+ return jfirmware; -+} -+ -+ -+ -+struct json_object *util_dimm_to_json(struct ndctl_dimm *dimm, -+ unsigned long flags) -+{ -+ struct json_object *jdimm = json_object_new_object(); -+ const char *id = ndctl_dimm_get_unique_id(dimm); -+ unsigned int handle = ndctl_dimm_get_handle(dimm); -+ unsigned short phys_id = ndctl_dimm_get_phys_id(dimm); -+ struct json_object *jobj; -+ enum ndctl_security_state sstate; -+ -+ if (!jdimm) -+ return NULL; -+ -+ jobj = json_object_new_string(ndctl_dimm_get_devname(dimm)); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jdimm, "dev", jobj); -+ -+ if (id) { -+ jobj = json_object_new_string(id); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jdimm, "id", jobj); -+ } -+ -+ if (handle < UINT_MAX) { -+ jobj = util_json_object_hex(handle, flags); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jdimm, "handle", jobj); -+ } -+ -+ if (phys_id < USHRT_MAX) { -+ jobj = util_json_object_hex(phys_id, flags); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jdimm, "phys_id", jobj); -+ } -+ -+ if (!ndctl_dimm_is_enabled(dimm)) { -+ jobj = json_object_new_string("disabled"); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jdimm, "state", jobj); -+ } -+ -+ if (ndctl_dimm_failed_map(dimm)) { -+ jobj = json_object_new_boolean(true); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jdimm, "flag_failed_map", jobj); -+ } -+ -+ if (ndctl_dimm_failed_save(dimm)) { -+ jobj = json_object_new_boolean(true); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jdimm, "flag_failed_save", jobj); -+ } -+ -+ if (ndctl_dimm_failed_arm(dimm)) { -+ jobj = json_object_new_boolean(true); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jdimm, "flag_failed_arm", jobj); -+ } -+ -+ if (ndctl_dimm_failed_restore(dimm)) { -+ jobj = json_object_new_boolean(true); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jdimm, "flag_failed_restore", jobj); -+ } -+ -+ if (ndctl_dimm_failed_flush(dimm)) { -+ jobj = json_object_new_boolean(true); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jdimm, "flag_failed_flush", jobj); -+ } -+ -+ if (ndctl_dimm_smart_pending(dimm)) { -+ jobj = json_object_new_boolean(true); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jdimm, "flag_smart_event", jobj); -+ } -+ -+ sstate = ndctl_dimm_get_security(dimm); -+ if (sstate == NDCTL_SECURITY_DISABLED) -+ jobj = json_object_new_string("disabled"); -+ else if (sstate == NDCTL_SECURITY_UNLOCKED) -+ jobj = json_object_new_string("unlocked"); -+ else if (sstate == NDCTL_SECURITY_LOCKED) -+ jobj = json_object_new_string("locked"); -+ else if (sstate == NDCTL_SECURITY_FROZEN) -+ jobj = json_object_new_string("frozen"); -+ else if (sstate == NDCTL_SECURITY_OVERWRITE) -+ jobj = json_object_new_string("overwrite"); -+ else -+ jobj = NULL; -+ if (jobj) -+ json_object_object_add(jdimm, "security", jobj); -+ -+ if (ndctl_dimm_security_is_frozen(dimm)) { -+ jobj = json_object_new_boolean(true); -+ if (jobj) -+ json_object_object_add(jdimm, "security_frozen", jobj); -+ } -+ -+ if (flags & UTIL_JSON_FIRMWARE) { -+ struct json_object *jfirmware; -+ -+ jfirmware = util_dimm_firmware_to_json(dimm, flags); -+ if (jfirmware) -+ json_object_object_add(jdimm, "firmware", jfirmware); -+ } -+ -+ return jdimm; -+ err: -+ json_object_put(jdimm); -+ return NULL; -+} -+ -+#define _SZ(get_max, get_elem, type) \ -+static struct json_object *util_##type##_build_size_array(struct ndctl_##type *arg) \ -+{ \ -+ struct json_object *arr = json_object_new_array(); \ -+ int i; \ -+ \ -+ if (!arr) \ -+ return NULL; \ -+ \ -+ for (i = 0; i < get_max(arg); i++) { \ -+ struct json_object *jobj; \ -+ int64_t align; \ -+ \ -+ align = get_elem(arg, i); \ -+ jobj = json_object_new_int64(align); \ -+ if (!jobj) \ -+ goto err; \ -+ json_object_array_add(arr, jobj); \ -+ } \ -+ \ -+ return arr; \ -+err: \ -+ json_object_put(arr); \ -+ return NULL; \ -+} -+#define SZ(type, kind) _SZ(ndctl_##type##_get_num_##kind##s, \ -+ ndctl_##type##_get_supported_##kind, type) -+SZ(pfn, alignment) -+SZ(dax, alignment) -+SZ(btt, sector_size) -+ -+struct json_object *util_region_capabilities_to_json(struct ndctl_region *region) -+{ -+ struct json_object *jcaps, *jcap, *jobj; -+ struct ndctl_btt *btt = ndctl_region_get_btt_seed(region); -+ struct ndctl_pfn *pfn = ndctl_region_get_pfn_seed(region); -+ struct ndctl_dax *dax = ndctl_region_get_dax_seed(region); -+ -+ if (!btt || !pfn || !dax) -+ return NULL; -+ -+ jcaps = json_object_new_array(); -+ if (!jcaps) -+ return NULL; -+ -+ if (btt) { -+ jcap = json_object_new_object(); -+ if (!jcap) -+ goto err; -+ json_object_array_add(jcaps, jcap); -+ -+ jobj = json_object_new_string("sector"); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jcap, "mode", jobj); -+ jobj = util_btt_build_size_array(btt); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jcap, "sector_sizes", jobj); -+ } -+ -+ if (pfn) { -+ jcap = json_object_new_object(); -+ if (!jcap) -+ goto err; -+ json_object_array_add(jcaps, jcap); -+ -+ jobj = json_object_new_string("fsdax"); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jcap, "mode", jobj); -+ jobj = util_pfn_build_size_array(pfn); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jcap, "alignments", jobj); -+ } -+ -+ if (dax) { -+ jcap = json_object_new_object(); -+ if (!jcap) -+ goto err; -+ json_object_array_add(jcaps, jcap); -+ -+ jobj = json_object_new_string("devdax"); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jcap, "mode", jobj); -+ jobj = util_dax_build_size_array(dax); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jcap, "alignments", jobj); -+ } -+ -+ return jcaps; -+err: -+ json_object_put(jcaps); -+ return NULL; -+} -+ -+ -+static int compare_dimm_number(const void *p1, const void *p2) -+{ -+ struct ndctl_dimm *dimm1 = *(struct ndctl_dimm **)p1; -+ struct ndctl_dimm *dimm2 = *(struct ndctl_dimm **)p2; -+ const char *dimm1_name = ndctl_dimm_get_devname(dimm1); -+ const char *dimm2_name = ndctl_dimm_get_devname(dimm2); -+ int num1, num2; -+ -+ if (sscanf(dimm1_name, "nmem%d", &num1) != 1) -+ num1 = 0; -+ if (sscanf(dimm2_name, "nmem%d", &num2) != 1) -+ num2 = 0; -+ -+ return num1 - num2; -+} -+ -+static struct json_object *badblocks_to_jdimms(struct ndctl_region *region, -+ unsigned long long addr, unsigned long len) -+{ -+ struct ndctl_bus *bus = ndctl_region_get_bus(region); -+ int count = ndctl_region_get_interleave_ways(region); -+ unsigned long long end = addr + len; -+ struct json_object *jdimms, *jobj; -+ struct ndctl_dimm **dimms, *dimm; -+ int found, i; -+ -+ jdimms = json_object_new_array(); -+ if (!jdimms) -+ return NULL; -+ -+ dimms = calloc(count, sizeof(struct ndctl_dimm *)); -+ if (!dimms) -+ goto err_dimms; -+ -+ for (found = 0; found < count && addr < end; addr += 512) { -+ dimm = ndctl_bus_get_dimm_by_physical_address(bus, addr); -+ if (!dimm) -+ continue; -+ -+ for (i = 0; i < count; i++) -+ if (dimms[i] == dimm) -+ break; -+ if (i >= count) -+ dimms[found++] = dimm; -+ } -+ -+ if (!found) -+ goto err_found; -+ -+ qsort(dimms, found, sizeof(dimm), compare_dimm_number); -+ -+ for (i = 0; i < found; i++) { -+ const char *devname = ndctl_dimm_get_devname(dimms[i]); -+ -+ jobj = json_object_new_string(devname); -+ if (!jobj) -+ break; -+ json_object_array_add(jdimms, jobj); -+ } -+ -+ if (!i) -+ goto err_found; -+ free(dimms); -+ return jdimms; -+ -+err_found: -+ free(dimms); -+err_dimms: -+ json_object_put(jdimms); -+ return NULL; -+} -+ -+struct json_object *util_region_badblocks_to_json(struct ndctl_region *region, -+ unsigned int *bb_count, unsigned long flags) -+{ -+ struct json_object *jbb = NULL, *jbbs = NULL, *jobj; -+ struct badblock *bb; -+ int bbs = 0; -+ -+ if (flags & UTIL_JSON_MEDIA_ERRORS) { -+ jbbs = json_object_new_array(); -+ if (!jbbs) -+ return NULL; -+ } -+ -+ ndctl_region_badblock_foreach(region, bb) { -+ struct json_object *jdimms; -+ unsigned long long addr; -+ -+ bbs += bb->len; -+ -+ /* recheck so we can still get the badblocks_count from above */ -+ if (!(flags & UTIL_JSON_MEDIA_ERRORS)) -+ continue; -+ -+ /* get start address of region */ -+ addr = ndctl_region_get_resource(region); -+ if (addr == ULLONG_MAX) -+ goto err_array; -+ -+ /* get address of bad block */ -+ addr += bb->offset << 9; -+ -+ jbb = json_object_new_object(); -+ if (!jbb) -+ goto err_array; -+ -+ jobj = json_object_new_int64(bb->offset); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jbb, "offset", jobj); -+ -+ jobj = json_object_new_int(bb->len); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jbb, "length", jobj); -+ -+ jdimms = badblocks_to_jdimms(region, addr, bb->len << 9); -+ if (jdimms) -+ json_object_object_add(jbb, "dimms", jdimms); -+ json_object_array_add(jbbs, jbb); -+ } -+ -+ *bb_count = bbs; -+ -+ if (bbs) -+ return jbbs; -+ -+ err: -+ json_object_put(jbb); -+ err_array: -+ json_object_put(jbbs); -+ return NULL; -+} -+ -+static struct json_object *util_namespace_badblocks_to_json( -+ struct ndctl_namespace *ndns, -+ unsigned int *bb_count, unsigned long flags) -+{ -+ struct json_object *jbb = NULL, *jbbs = NULL, *jobj; -+ struct badblock *bb; -+ int bbs = 0; -+ -+ if (flags & UTIL_JSON_MEDIA_ERRORS) { -+ jbbs = json_object_new_array(); -+ if (!jbbs) -+ return NULL; -+ } else -+ return NULL; -+ -+ ndctl_namespace_badblock_foreach(ndns, bb) { -+ bbs += bb->len; -+ -+ /* recheck so we can still get the badblocks_count from above */ -+ if (!(flags & UTIL_JSON_MEDIA_ERRORS)) -+ continue; -+ -+ jbb = json_object_new_object(); -+ if (!jbb) -+ goto err_array; -+ -+ jobj = json_object_new_int64(bb->offset); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jbb, "offset", jobj); -+ -+ jobj = json_object_new_int(bb->len); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jbb, "length", jobj); -+ json_object_array_add(jbbs, jbb); -+ } -+ -+ *bb_count = bbs; -+ -+ if (bbs) -+ return jbbs; -+ -+ err: -+ json_object_put(jbb); -+ err_array: -+ json_object_put(jbbs); -+ return NULL; -+} -+ -+static struct json_object *dev_badblocks_to_json(struct ndctl_region *region, -+ unsigned long long dev_begin, unsigned long long dev_size, -+ unsigned int *bb_count, unsigned long flags) -+{ -+ struct json_object *jbb = NULL, *jbbs = NULL, *jobj; -+ unsigned long long region_begin, dev_end, offset; -+ unsigned int len, bbs = 0; -+ struct badblock *bb; -+ -+ region_begin = ndctl_region_get_resource(region); -+ if (region_begin == ULLONG_MAX) -+ return NULL; -+ -+ dev_end = dev_begin + dev_size - 1; -+ -+ if (flags & UTIL_JSON_MEDIA_ERRORS) { -+ jbbs = json_object_new_array(); -+ if (!jbbs) -+ return NULL; -+ } -+ -+ ndctl_region_badblock_foreach(region, bb) { -+ unsigned long long bb_begin, bb_end, begin, end; -+ struct json_object *jdimms; -+ -+ bb_begin = region_begin + (bb->offset << 9); -+ bb_end = bb_begin + (bb->len << 9) - 1; -+ -+ if (bb_end <= dev_begin || bb_begin >= dev_end) -+ continue; -+ -+ if (bb_begin < dev_begin) -+ begin = dev_begin; -+ else -+ begin = bb_begin; -+ -+ if (bb_end > dev_end) -+ end = dev_end; -+ else -+ end = bb_end; -+ -+ offset = (begin - dev_begin) >> 9; -+ len = (end - begin + 1) >> 9; -+ -+ bbs += len; -+ -+ /* recheck so we can still get the badblocks_count from above */ -+ if (!(flags & UTIL_JSON_MEDIA_ERRORS)) -+ continue; -+ -+ jbb = json_object_new_object(); -+ if (!jbb) -+ goto err_array; -+ -+ jobj = json_object_new_int64(offset); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jbb, "offset", jobj); -+ -+ jobj = json_object_new_int(len); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jbb, "length", jobj); -+ -+ jdimms = badblocks_to_jdimms(region, begin, len << 9); -+ if (jdimms) -+ json_object_object_add(jbb, "dimms", jdimms); -+ -+ json_object_array_add(jbbs, jbb); -+ } -+ -+ *bb_count = bbs; -+ -+ if (bbs) -+ return jbbs; -+ -+ err: -+ json_object_put(jbb); -+ err_array: -+ json_object_put(jbbs); -+ return NULL; -+} -+ -+static struct json_object *util_pfn_badblocks_to_json(struct ndctl_pfn *pfn, -+ unsigned int *bb_count, unsigned long flags) -+{ -+ struct ndctl_region *region = ndctl_pfn_get_region(pfn); -+ unsigned long long pfn_begin, pfn_size; -+ -+ pfn_begin = ndctl_pfn_get_resource(pfn); -+ if (pfn_begin == ULLONG_MAX) { -+ struct ndctl_namespace *ndns = ndctl_pfn_get_namespace(pfn); -+ -+ return util_namespace_badblocks_to_json(ndns, bb_count, flags); -+ } -+ -+ pfn_size = ndctl_pfn_get_size(pfn); -+ if (pfn_size == ULLONG_MAX) -+ return NULL; -+ -+ return dev_badblocks_to_json(region, pfn_begin, pfn_size, -+ bb_count, flags); -+} -+ -+static void util_btt_badblocks_to_json(struct ndctl_btt *btt, -+ unsigned int *bb_count) -+{ -+ struct ndctl_region *region = ndctl_btt_get_region(btt); -+ struct ndctl_namespace *ndns = ndctl_btt_get_namespace(btt); -+ unsigned long long begin, size; -+ -+ if (!ndns) -+ return; -+ -+ begin = ndctl_namespace_get_resource(ndns); -+ if (begin == ULLONG_MAX) -+ return; -+ -+ size = ndctl_namespace_get_size(ndns); -+ if (size == ULLONG_MAX) -+ return; -+ -+ /* -+ * The dev_badblocks_to_json() for BTT is not accurate with -+ * respect to data vs metadata badblocks, and is only useful for -+ * a potential bb_count. -+ * -+ * FIXME: switch to native BTT badblocks representation -+ * when / if the kernel provides it. -+ */ -+ dev_badblocks_to_json(region, begin, size, bb_count, 0); -+} -+static struct json_object *util_dax_badblocks_to_json(struct ndctl_dax *dax, -+ unsigned int *bb_count, unsigned long flags) -+{ -+ struct ndctl_region *region = ndctl_dax_get_region(dax); -+ unsigned long long dax_begin, dax_size; -+ -+ dax_begin = ndctl_dax_get_resource(dax); -+ if (dax_begin == ULLONG_MAX) -+ return NULL; -+ -+ dax_size = ndctl_dax_get_size(dax); -+ if (dax_size == ULLONG_MAX) -+ return NULL; -+ -+ return dev_badblocks_to_json(region, dax_begin, dax_size, -+ bb_count, flags); -+} -+ -+static struct json_object *util_raw_uuid(struct ndctl_namespace *ndns) -+{ -+ char buf[40]; -+ uuid_t raw_uuid; -+ -+ ndctl_namespace_get_uuid(ndns, raw_uuid); -+ if (uuid_is_null(raw_uuid)) -+ return NULL; -+ uuid_unparse(raw_uuid, buf); -+ return json_object_new_string(buf); -+} -+ -+static void util_raw_uuid_to_json(struct ndctl_namespace *ndns, -+ unsigned long flags, -+ struct json_object *jndns) -+{ -+ struct json_object *jobj; -+ -+ if (!(flags & UTIL_JSON_VERBOSE)) -+ return; -+ -+ jobj = util_raw_uuid(ndns); -+ if (!jobj) -+ return; -+ json_object_object_add(jndns, "raw_uuid", jobj); -+} -+ -+struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns, -+ unsigned long flags) -+{ -+ struct json_object *jndns = json_object_new_object(); -+ enum ndctl_pfn_loc loc = NDCTL_PFN_LOC_NONE; -+ struct json_object *jobj, *jbbs = NULL; -+ const char *locations[] = { -+ [NDCTL_PFN_LOC_NONE] = "none", -+ [NDCTL_PFN_LOC_RAM] = "mem", -+ [NDCTL_PFN_LOC_PMEM] = "dev", -+ }; -+ unsigned long long size = ULLONG_MAX; -+ unsigned int sector_size = UINT_MAX; -+ enum ndctl_namespace_mode mode; -+ const char *bdev = NULL, *name; -+ unsigned int bb_count = 0; -+ struct ndctl_btt *btt; -+ struct ndctl_pfn *pfn; -+ struct ndctl_dax *dax; -+ unsigned long align = 0; -+ char buf[40]; -+ uuid_t uuid; -+ int numa, target; -+ -+ if (!jndns) -+ return NULL; -+ -+ jobj = json_object_new_string(ndctl_namespace_get_devname(ndns)); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jndns, "dev", jobj); -+ -+ btt = ndctl_namespace_get_btt(ndns); -+ dax = ndctl_namespace_get_dax(ndns); -+ pfn = ndctl_namespace_get_pfn(ndns); -+ mode = ndctl_namespace_get_mode(ndns); -+ switch (mode) { -+ case NDCTL_NS_MODE_MEMORY: -+ if (pfn) { /* dynamic memory mode */ -+ size = ndctl_pfn_get_size(pfn); -+ loc = ndctl_pfn_get_location(pfn); -+ } else { /* native/static memory mode */ -+ size = ndctl_namespace_get_size(ndns); -+ loc = NDCTL_PFN_LOC_RAM; -+ } -+ jobj = json_object_new_string("fsdax"); -+ break; -+ case NDCTL_NS_MODE_DAX: -+ if (!dax) -+ goto err; -+ size = ndctl_dax_get_size(dax); -+ jobj = json_object_new_string("devdax"); -+ loc = ndctl_dax_get_location(dax); -+ break; -+ case NDCTL_NS_MODE_SECTOR: -+ if (!btt) -+ goto err; -+ jobj = json_object_new_string("sector"); -+ size = ndctl_btt_get_size(btt); -+ break; -+ case NDCTL_NS_MODE_RAW: -+ size = ndctl_namespace_get_size(ndns); -+ jobj = json_object_new_string("raw"); -+ break; -+ default: -+ jobj = NULL; -+ } -+ if (jobj) -+ json_object_object_add(jndns, "mode", jobj); -+ -+ if ((mode != NDCTL_NS_MODE_SECTOR) && (mode != NDCTL_NS_MODE_RAW)) { -+ jobj = json_object_new_string(locations[loc]); -+ if (jobj) -+ json_object_object_add(jndns, "map", jobj); -+ } -+ -+ if (size < ULLONG_MAX) { -+ jobj = util_json_object_size(size, flags); -+ if (jobj) -+ json_object_object_add(jndns, "size", jobj); -+ } -+ -+ if (btt) { -+ ndctl_btt_get_uuid(btt, uuid); -+ uuid_unparse(uuid, buf); -+ jobj = json_object_new_string(buf); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jndns, "uuid", jobj); -+ util_raw_uuid_to_json(ndns, flags, jndns); -+ bdev = ndctl_btt_get_block_device(btt); -+ } else if (pfn) { -+ align = ndctl_pfn_get_align(pfn); -+ ndctl_pfn_get_uuid(pfn, uuid); -+ uuid_unparse(uuid, buf); -+ jobj = json_object_new_string(buf); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jndns, "uuid", jobj); -+ util_raw_uuid_to_json(ndns, flags, jndns); -+ bdev = ndctl_pfn_get_block_device(pfn); -+ } else if (dax) { -+ struct daxctl_region *dax_region; -+ -+ dax_region = ndctl_dax_get_daxctl_region(dax); -+ align = ndctl_dax_get_align(dax); -+ ndctl_dax_get_uuid(dax, uuid); -+ uuid_unparse(uuid, buf); -+ jobj = json_object_new_string(buf); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jndns, "uuid", jobj); -+ util_raw_uuid_to_json(ndns, flags, jndns); -+ if ((flags & UTIL_JSON_DAX) && dax_region) { -+ jobj = util_daxctl_region_to_json(dax_region, NULL, -+ flags); -+ if (jobj) -+ json_object_object_add(jndns, "daxregion", jobj); -+ } else if (dax_region) { -+ struct daxctl_dev *dev; -+ -+ /* -+ * We can only find/list these device-dax -+ * details when the instance is enabled. -+ */ -+ dev = daxctl_dev_get_first(dax_region); -+ if (dev) { -+ name = daxctl_dev_get_devname(dev); -+ jobj = json_object_new_string(name); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jndns, "chardev", jobj); -+ } -+ } -+ } else if (ndctl_namespace_get_type(ndns) != ND_DEVICE_NAMESPACE_IO) { -+ ndctl_namespace_get_uuid(ndns, uuid); -+ uuid_unparse(uuid, buf); -+ jobj = json_object_new_string(buf); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jndns, "uuid", jobj); -+ bdev = ndctl_namespace_get_block_device(ndns); -+ } else -+ bdev = ndctl_namespace_get_block_device(ndns); -+ -+ if (btt) -+ sector_size = ndctl_btt_get_sector_size(btt); -+ else if (!dax) { -+ sector_size = ndctl_namespace_get_sector_size(ndns); -+ if (!sector_size || sector_size == UINT_MAX) -+ sector_size = 512; -+ } -+ -+ /* -+ * The kernel will default to a 512 byte sector size on PMEM -+ * namespaces that don't explicitly have a sector size. This -+ * happens because they use pre-v1.2 labels or because they -+ * don't have a label space (devtype=nd_namespace_io). -+ */ -+ if (sector_size < UINT_MAX) { -+ jobj = json_object_new_int(sector_size); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jndns, "sector_size", jobj); -+ } -+ -+ if (align) { -+ jobj = json_object_new_int64(align); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jndns, "align", jobj); -+ } -+ -+ if (bdev && bdev[0]) { -+ jobj = json_object_new_string(bdev); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jndns, "blockdev", jobj); -+ } -+ -+ if (!ndctl_namespace_is_active(ndns)) { -+ jobj = json_object_new_string("disabled"); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jndns, "state", jobj); -+ } -+ -+ name = ndctl_namespace_get_alt_name(ndns); -+ if (name && name[0]) { -+ jobj = json_object_new_string(name); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jndns, "name", jobj); -+ } -+ -+ numa = ndctl_namespace_get_numa_node(ndns); -+ if (numa >= 0 && flags & UTIL_JSON_VERBOSE) { -+ jobj = json_object_new_int(numa); -+ if (jobj) -+ json_object_object_add(jndns, "numa_node", jobj); -+ } -+ -+ target = ndctl_namespace_get_target_node(ndns); -+ if (target >= 0 && flags & UTIL_JSON_VERBOSE) { -+ jobj = json_object_new_int(target); -+ if (jobj) -+ json_object_object_add(jndns, "target_node", jobj); -+ } -+ -+ if (pfn) -+ jbbs = util_pfn_badblocks_to_json(pfn, &bb_count, flags); -+ else if (dax) -+ jbbs = util_dax_badblocks_to_json(dax, &bb_count, flags); -+ else if (btt) -+ util_btt_badblocks_to_json(btt, &bb_count); -+ else { -+ jbbs = util_region_badblocks_to_json( -+ ndctl_namespace_get_region(ndns), &bb_count, -+ flags); -+ if (!jbbs) -+ jbbs = util_namespace_badblocks_to_json(ndns, &bb_count, -+ flags); -+ } -+ -+ if (bb_count) { -+ jobj = json_object_new_int(bb_count); -+ if (!jobj) { -+ json_object_put(jbbs); -+ goto err; -+ } -+ json_object_object_add(jndns, "badblock_count", jobj); -+ } -+ -+ if ((flags & UTIL_JSON_MEDIA_ERRORS) && jbbs) -+ json_object_object_add(jndns, "badblocks", jbbs); -+ -+ return jndns; -+ err: -+ json_object_put(jndns); -+ return NULL; -+} -+ -+ -+struct json_object *util_mapping_to_json(struct ndctl_mapping *mapping, -+ unsigned long flags) -+{ -+ struct json_object *jmapping = json_object_new_object(); -+ struct ndctl_dimm *dimm = ndctl_mapping_get_dimm(mapping); -+ struct json_object *jobj; -+ int position; -+ -+ if (!jmapping) -+ return NULL; -+ -+ jobj = json_object_new_string(ndctl_dimm_get_devname(dimm)); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jmapping, "dimm", jobj); -+ -+ jobj = util_json_object_hex(ndctl_mapping_get_offset(mapping), flags); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jmapping, "offset", jobj); -+ -+ jobj = util_json_object_hex(ndctl_mapping_get_length(mapping), flags); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jmapping, "length", jobj); -+ -+ position = ndctl_mapping_get_position(mapping); -+ if (position >= 0) { -+ jobj = json_object_new_int(position); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jmapping, "position", jobj); -+ } -+ -+ return jmapping; -+ err: -+ json_object_put(jmapping); -+ return NULL; -+} -+ -+struct json_object *util_badblock_rec_to_json(u64 block, u64 count, -+ unsigned long flags) -+{ -+ struct json_object *jerr = json_object_new_object(); -+ struct json_object *jobj; -+ -+ if (!jerr) -+ return NULL; -+ -+ jobj = util_json_object_hex(block, flags); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jerr, "block", jobj); -+ -+ jobj = util_json_object_hex(count, flags); -+ if (!jobj) -+ goto err; -+ json_object_object_add(jerr, "count", jobj); -+ -+ return jerr; -+ err: -+ json_object_put(jerr); -+ return NULL; -+} -diff -up ndctl-71.1/ndctl/json.h.orig ndctl-71.1/ndctl/json.h ---- ndctl-71.1/ndctl/json.h.orig 2022-10-07 15:51:03.913535724 -0400 -+++ ndctl-71.1/ndctl/json.h 2022-10-07 15:51:03.913535724 -0400 -@@ -0,0 +1,24 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */ -+#ifndef __NDCTL_UTIL_JSON_H__ -+#define __NDCTL_UTIL_JSON_H__ -+#include -+#include -+ -+struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns, -+ unsigned long flags); -+struct json_object *util_badblock_rec_to_json(u64 block, u64 count, -+ unsigned long flags); -+struct json_object *util_region_badblocks_to_json(struct ndctl_region *region, -+ unsigned int *bb_count, unsigned long flags); -+struct json_object *util_bus_to_json(struct ndctl_bus *bus, -+ unsigned long flags); -+struct json_object *util_dimm_to_json(struct ndctl_dimm *dimm, -+ unsigned long flags); -+struct json_object *util_mapping_to_json(struct ndctl_mapping *mapping, -+ unsigned long flags); -+struct json_object *util_dimm_health_to_json(struct ndctl_dimm *dimm); -+struct json_object *util_dimm_firmware_to_json(struct ndctl_dimm *dimm, -+ unsigned long flags); -+struct json_object *util_region_capabilities_to_json(struct ndctl_region *region); -+#endif /* __NDCTL_UTIL_JSON_H__ */ -diff -up ndctl-71.1/ndctl/keys.c.orig ndctl-71.1/ndctl/keys.c ---- ndctl-71.1/ndctl/keys.c.orig 2022-10-07 15:51:03.930535782 -0400 -+++ ndctl-71.1/ndctl/keys.c 2022-10-07 15:51:03.913535724 -0400 -@@ -0,0 +1,667 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* Copyright (C) 2018-2020 Intel Corporation. All rights reserved. */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "keys.h" -+ -+static int get_key_path(struct ndctl_dimm *dimm, char *path, -+ enum ndctl_key_type key_type) -+{ -+ char hostname[HOST_NAME_MAX]; -+ int rc; -+ -+ rc = gethostname(hostname, HOST_NAME_MAX); -+ if (rc < 0) { -+ fprintf(stderr, "gethostname: %s\n", strerror(errno)); -+ return -errno; -+ } -+ -+ switch (key_type) { -+ case ND_USER_OLD_KEY: -+ rc = sprintf(path, "%s/nvdimm-old_%s_%s.blob", -+ NDCTL_KEYS_DIR, -+ ndctl_dimm_get_unique_id(dimm), -+ hostname); -+ break; -+ case ND_USER_KEY: -+ rc = sprintf(path, "%s/nvdimm_%s_%s.blob", -+ NDCTL_KEYS_DIR, -+ ndctl_dimm_get_unique_id(dimm), -+ hostname); -+ break; -+ case ND_MASTER_OLD_KEY: -+ rc = sprintf(path, "%s/nvdimm-master-old_%s_%s.blob", -+ NDCTL_KEYS_DIR, -+ ndctl_dimm_get_unique_id(dimm), -+ hostname); -+ break; -+ case ND_MASTER_KEY: -+ rc = sprintf(path, "%s/nvdimm-master_%s_%s.blob", -+ NDCTL_KEYS_DIR, -+ ndctl_dimm_get_unique_id(dimm), -+ hostname); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ if (rc < 0) { -+ fprintf(stderr, "error setting path: %s\n", strerror(errno)); -+ return -errno; -+ } -+ -+ return 0; -+} -+ -+static int get_key_desc(struct ndctl_dimm *dimm, char *desc, -+ enum ndctl_key_type key_type) -+{ -+ int rc; -+ -+ switch (key_type) { -+ case ND_USER_OLD_KEY: -+ rc = sprintf(desc, "nvdimm-old:%s", -+ ndctl_dimm_get_unique_id(dimm)); -+ break; -+ case ND_USER_KEY: -+ rc = sprintf(desc, "nvdimm:%s", -+ ndctl_dimm_get_unique_id(dimm)); -+ break; -+ case ND_MASTER_OLD_KEY: -+ rc = sprintf(desc, "nvdimm-master-old:%s", -+ ndctl_dimm_get_unique_id(dimm)); -+ break; -+ case ND_MASTER_KEY: -+ rc = sprintf(desc, "nvdimm-master:%s", -+ ndctl_dimm_get_unique_id(dimm)); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ if (rc < 0) { -+ fprintf(stderr, "error setting key description: %s\n", -+ strerror(errno)); -+ return -errno; -+ } -+ -+ return 0; -+} -+ -+char *ndctl_load_key_blob(const char *path, int *size, const char *postfix, -+ int dirfd, enum key_type key_type) -+{ -+ struct stat st; -+ ssize_t read_bytes = 0; -+ int rc, fd; -+ char *blob, *pl, *rdptr; -+ char prefix[] = "load "; -+ bool need_prefix = false; -+ -+ if (key_type == KEY_ENCRYPTED || key_type == KEY_TRUSTED) -+ need_prefix = true; -+ -+ fd = openat(dirfd, path, O_RDONLY); -+ if (fd < 0) { -+ fprintf(stderr, "failed to open file %s: %s\n", -+ path, strerror(errno)); -+ return NULL; -+ } -+ -+ rc = fstat(fd, &st); -+ if (rc < 0) { -+ fprintf(stderr, "stat: %s\n", strerror(errno)); -+ return NULL; -+ } -+ if ((st.st_mode & S_IFMT) != S_IFREG) { -+ fprintf(stderr, "%s not a regular file\n", path); -+ return NULL; -+ } -+ -+ if (st.st_size == 0 || st.st_size > 4096) { -+ fprintf(stderr, "Invalid blob file size\n"); -+ return NULL; -+ } -+ -+ *size = st.st_size; -+ if (need_prefix) -+ *size += strlen(prefix); -+ -+ /* -+ * We need to increment postfix and space. -+ * "keyhandle=" is 10 bytes, plus null termination. -+ */ -+ if (postfix) -+ *size += strlen(postfix) + 10 + 1; -+ blob = malloc(*size); -+ if (!blob) { -+ fprintf(stderr, "Unable to allocate memory for blob\n"); -+ return NULL; -+ } -+ -+ if (need_prefix) { -+ memcpy(blob, prefix, strlen(prefix)); -+ pl = blob + strlen(prefix); -+ } else -+ pl = blob; -+ -+ rdptr = pl; -+ do { -+ rc = read(fd, rdptr, st.st_size - read_bytes); -+ if (rc < 0) { -+ fprintf(stderr, "Failed to read from blob file: %s\n", -+ strerror(errno)); -+ free(blob); -+ close(fd); -+ return NULL; -+ } -+ read_bytes += rc; -+ rdptr += rc; -+ } while (read_bytes != st.st_size); -+ -+ close(fd); -+ -+ if (postfix) { -+ pl += read_bytes; -+ *pl = ' '; -+ pl++; -+ rc = sprintf(pl, "keyhandle=%s", postfix); -+ } -+ -+ return blob; -+} -+ -+static key_serial_t dimm_check_key(struct ndctl_dimm *dimm, -+ enum ndctl_key_type key_type) -+{ -+ char desc[ND_KEY_DESC_SIZE]; -+ int rc; -+ -+ rc = get_key_desc(dimm, desc, key_type); -+ if (rc < 0) -+ return rc; -+ -+ return keyctl_search(KEY_SPEC_USER_KEYRING, "encrypted", desc, 0); -+} -+ -+static key_serial_t dimm_create_key(struct ndctl_dimm *dimm, -+ const char *kek, enum ndctl_key_type key_type) -+{ -+ char desc[ND_KEY_DESC_SIZE]; -+ char path[PATH_MAX]; -+ char cmd[ND_KEY_CMD_SIZE]; -+ key_serial_t key; -+ void *buffer; -+ int rc; -+ ssize_t size; -+ FILE *fp; -+ ssize_t wrote; -+ struct stat st; -+ -+ if (ndctl_dimm_is_active(dimm)) { -+ fprintf(stderr, "regions active on %s, op failed\n", -+ ndctl_dimm_get_devname(dimm)); -+ return -EBUSY; -+ } -+ -+ rc = get_key_desc(dimm, desc, key_type); -+ if (rc < 0) -+ return rc; -+ -+ /* make sure it's not already in the key ring */ -+ key = keyctl_search(KEY_SPEC_USER_KEYRING, "encrypted", desc, 0); -+ if (key > 0) { -+ fprintf(stderr, "Error: key already present in user keyring\n"); -+ return -EEXIST; -+ } -+ -+ rc = get_key_path(dimm, path, key_type); -+ if (rc < 0) -+ return rc; -+ -+ rc = stat(path, &st); -+ if (rc == 0) { -+ fprintf(stderr, "%s already exists!\n", path); -+ return -EEXIST; -+ } -+ -+ rc = sprintf(cmd, "new enc32 %s 32", kek); -+ if (rc < 0) { -+ fprintf(stderr, "sprintf: %s\n", strerror(errno)); -+ return -errno; -+ } -+ -+ key = add_key("encrypted", desc, cmd, strlen(cmd), -+ KEY_SPEC_USER_KEYRING); -+ if (key < 0) { -+ fprintf(stderr, "add_key failed: %s\n", strerror(errno)); -+ return -errno; -+ } -+ -+ size = keyctl_read_alloc(key, &buffer); -+ if (size < 0) { -+ fprintf(stderr, "keyctl_read_alloc failed: %s\n", strerror(errno)); -+ keyctl_unlink(key, KEY_SPEC_USER_KEYRING); -+ return rc; -+ } -+ -+ fp = fopen(path, "w"); -+ if (!fp) { -+ rc = -errno; -+ fprintf(stderr, "Unable to open file %s: %s\n", -+ path, strerror(errno)); -+ free(buffer); -+ return rc; -+ } -+ -+ wrote = fwrite(buffer, 1, size, fp); -+ if (wrote != size) { -+ if (wrote == -1) -+ rc = -errno; -+ else -+ rc = -EIO; -+ fprintf(stderr, "Failed to write to %s: %s\n", -+ path, strerror(-rc)); -+ fclose(fp); -+ free(buffer); -+ return rc; -+ } -+ -+ fclose(fp); -+ free(buffer); -+ return key; -+} -+ -+static key_serial_t dimm_load_key(struct ndctl_dimm *dimm, -+ enum ndctl_key_type key_type) -+{ -+ key_serial_t key; -+ char desc[ND_KEY_DESC_SIZE]; -+ char path[PATH_MAX]; -+ int rc; -+ char *blob; -+ int size; -+ -+ if (ndctl_dimm_is_active(dimm)) { -+ fprintf(stderr, "regions active on %s, op failed\n", -+ ndctl_dimm_get_devname(dimm)); -+ return -EBUSY; -+ } -+ -+ rc = get_key_desc(dimm, desc, key_type); -+ if (rc < 0) -+ return rc; -+ -+ rc = get_key_path(dimm, path, key_type); -+ if (rc < 0) -+ return rc; -+ -+ blob = ndctl_load_key_blob(path, &size, NULL, -1, KEY_ENCRYPTED); -+ if (!blob) -+ return -ENOMEM; -+ -+ key = add_key("encrypted", desc, blob, size, KEY_SPEC_USER_KEYRING); -+ free(blob); -+ if (key < 0) { -+ fprintf(stderr, "add_key failed: %s\n", strerror(errno)); -+ return -errno; -+ } -+ -+ return key; -+} -+ -+/* -+ * The function will check to see if the existing key is there and remove -+ * from user key ring if it is. Rename the existing key blob to old key -+ * blob, and then attempt to inject the key as old key into the user key -+ * ring. -+ */ -+static key_serial_t move_key_to_old(struct ndctl_dimm *dimm, -+ enum ndctl_key_type key_type) -+{ -+ int rc; -+ key_serial_t key; -+ char old_path[PATH_MAX]; -+ char new_path[PATH_MAX]; -+ enum ndctl_key_type okey_type; -+ -+ if (ndctl_dimm_is_active(dimm)) { -+ fprintf(stderr, "regions active on %s, op failed\n", -+ ndctl_dimm_get_devname(dimm)); -+ return -EBUSY; -+ } -+ -+ key = dimm_check_key(dimm, key_type); -+ if (key > 0) -+ keyctl_unlink(key, KEY_SPEC_USER_KEYRING); -+ -+ if (key_type == ND_USER_KEY) -+ okey_type = ND_USER_OLD_KEY; -+ else if (key_type == ND_MASTER_KEY) -+ okey_type = ND_MASTER_OLD_KEY; -+ else -+ return -EINVAL; -+ -+ rc = get_key_path(dimm, old_path, key_type); -+ if (rc < 0) -+ return rc; -+ -+ rc = get_key_path(dimm, new_path, okey_type); -+ if (rc < 0) -+ return rc; -+ -+ rc = rename(old_path, new_path); -+ if (rc < 0) { -+ fprintf(stderr, "rename failed from %s to %s: %s\n", -+ old_path, new_path, strerror(errno)); -+ return -errno; -+ } -+ -+ return dimm_load_key(dimm, okey_type); -+} -+ -+static int dimm_remove_key(struct ndctl_dimm *dimm, -+ enum ndctl_key_type key_type) -+{ -+ key_serial_t key; -+ char path[PATH_MAX]; -+ int rc; -+ -+ key = dimm_check_key(dimm, key_type); -+ if (key > 0) -+ keyctl_unlink(key, KEY_SPEC_USER_KEYRING); -+ -+ rc = get_key_path(dimm, path, key_type); -+ if (rc < 0) -+ return rc; -+ -+ rc = unlink(path); -+ if (rc < 0) { -+ fprintf(stderr, "delete file %s failed: %s\n", -+ path, strerror(errno)); -+ return -errno; -+ } -+ -+ return 0; -+} -+ -+static int verify_kek(struct ndctl_dimm *dimm, const char *kek) -+{ -+ char *type, *desc, *key_handle; -+ key_serial_t key; -+ int rc = 0; -+ -+ key_handle = strdup(kek); -+ if (!key_handle) -+ return -ENOMEM; -+ -+ type = strtok(key_handle, ":"); -+ if (!type) { -+ fprintf(stderr, "No key type found for kek handle\n"); -+ rc = -EINVAL; -+ goto out; -+ } -+ -+ if (strcmp(type, "trusted") != 0 && -+ strcmp(type, "user") != 0) { -+ fprintf(stderr, "No such key type: %s", type); -+ rc = -EINVAL; -+ goto out; -+ } -+ -+ desc = strtok(NULL, ":"); -+ if (!desc) { -+ fprintf(stderr, "No description found for kek handle\n"); -+ rc = -EINVAL; -+ goto out; -+ } -+ -+ key = keyctl_search(KEY_SPEC_USER_KEYRING, type, desc, 0); -+ if (key < 0) { -+ fprintf(stderr, "No key encryption key found\n"); -+ rc = key; -+ goto out; -+ } -+ -+out: -+ free(key_handle); -+ return rc; -+} -+ -+int ndctl_dimm_setup_key(struct ndctl_dimm *dimm, const char *kek, -+ enum ndctl_key_type key_type) -+{ -+ key_serial_t key; -+ int rc; -+ -+ rc = verify_kek(dimm, kek); -+ if (rc < 0) -+ return rc; -+ -+ key = dimm_create_key(dimm, kek, key_type); -+ if (key < 0) -+ return key; -+ -+ if (key_type == ND_MASTER_KEY) -+ rc = ndctl_dimm_update_master_passphrase(dimm, 0, key); -+ else -+ rc = ndctl_dimm_update_passphrase(dimm, 0, key); -+ if (rc < 0) { -+ dimm_remove_key(dimm, key_type); -+ return rc; -+ } -+ -+ return 0; -+} -+ -+static char *get_current_kek(struct ndctl_dimm *dimm, -+ enum ndctl_key_type key_type) -+{ -+ key_serial_t key; -+ char *key_buf; -+ long rc; -+ char *type, *desc; -+ -+ key = dimm_check_key(dimm, key_type); -+ if (key < 0) -+ return NULL; -+ -+ rc = keyctl_read_alloc(key, (void **)&key_buf); -+ if (rc < 0) -+ return NULL; -+ -+ rc = sscanf(key_buf, "%ms %ms", &type, &desc); -+ if (rc < 0) -+ return NULL; -+ -+ free(key_buf); -+ free(type); -+ -+ return desc; -+} -+ -+int ndctl_dimm_update_key(struct ndctl_dimm *dimm, const char *kek, -+ enum ndctl_key_type key_type) -+{ -+ int rc; -+ key_serial_t old_key, new_key; -+ char *current_kek = NULL; -+ enum ndctl_key_type okey_type; -+ -+ if (kek) { -+ rc = verify_kek(dimm, kek); -+ if (rc < 0) -+ return rc; -+ } else { /* find current kek */ -+ current_kek = get_current_kek(dimm, key_type); -+ if (!current_kek) -+ return -ENOKEY; -+ } -+ -+ if (key_type == ND_USER_KEY) -+ okey_type = ND_USER_OLD_KEY; -+ else if (key_type == ND_MASTER_KEY) -+ okey_type = ND_MASTER_OLD_KEY; -+ else -+ return -EINVAL; -+ -+ /* -+ * 1. check if current key is loaded and remove -+ * 2. move current key blob to old key blob -+ * 3. load old key blob -+ * 4. trigger change key with old and new key -+ * 5. remove old key -+ * 6. remove old key blob -+ */ -+ old_key = move_key_to_old(dimm, key_type); -+ if (old_key < 0) -+ return old_key; -+ -+ new_key = dimm_create_key(dimm, current_kek ? current_kek : kek, -+ key_type); -+ free(current_kek); -+ /* need to create new key here */ -+ if (new_key < 0) { -+ new_key = dimm_load_key(dimm, key_type); -+ if (new_key < 0) -+ return new_key; -+ } -+ -+ if (key_type == ND_MASTER_KEY) -+ rc = ndctl_dimm_update_master_passphrase(dimm, -+ old_key, new_key); -+ else -+ rc = ndctl_dimm_update_passphrase(dimm, old_key, new_key); -+ if (rc < 0) -+ return rc; -+ -+ rc = dimm_remove_key(dimm, okey_type); -+ if (rc < 0) -+ return rc; -+ -+ return 0; -+} -+ -+static key_serial_t check_dimm_key(struct ndctl_dimm *dimm, bool need_key, -+ enum ndctl_key_type key_type) -+{ -+ key_serial_t key; -+ -+ key = dimm_check_key(dimm, key_type); -+ if (key < 0) { -+ key = dimm_load_key(dimm, key_type); -+ if (key < 0 && need_key) { -+ fprintf(stderr, "Unable to load key\n"); -+ return -ENOKEY; -+ } else -+ key = 0; -+ } -+ return key; -+} -+ -+static int run_key_op(struct ndctl_dimm *dimm, -+ key_serial_t key, -+ int (*run_op)(struct ndctl_dimm *, long), const char *name) -+{ -+ int rc; -+ -+ rc = run_op(dimm, key); -+ if (rc < 0) { -+ fprintf(stderr, "Failed %s for %s\n", name, -+ ndctl_dimm_get_devname(dimm)); -+ return rc; -+ } -+ -+ return 0; -+} -+ -+static int discard_key(struct ndctl_dimm *dimm) -+{ -+ int rc; -+ -+ rc = dimm_remove_key(dimm, ND_USER_KEY); -+ if (rc < 0) { -+ fprintf(stderr, "Unable to cleanup key.\n"); -+ return rc; -+ } -+ -+ return 0; -+} -+ -+int ndctl_dimm_remove_key(struct ndctl_dimm *dimm) -+{ -+ key_serial_t key; -+ int rc; -+ -+ key = check_dimm_key(dimm, true, ND_USER_KEY); -+ if (key < 0) -+ return key; -+ -+ rc = run_key_op(dimm, key, ndctl_dimm_disable_passphrase, -+ "remove passphrase"); -+ if (rc < 0) -+ return rc; -+ -+ return discard_key(dimm); -+} -+ -+int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm, -+ enum ndctl_key_type key_type) -+{ -+ key_serial_t key = 0; -+ int rc; -+ -+ if (key_type != ND_ZERO_KEY) { -+ key = check_dimm_key(dimm, true, key_type); -+ if (key < 0) -+ return key; -+ } -+ -+ if (key_type == ND_MASTER_KEY) -+ rc = run_key_op(dimm, key, ndctl_dimm_master_secure_erase, -+ "master crypto erase"); -+ else if (key_type == ND_USER_KEY || key_type == ND_ZERO_KEY) -+ rc = run_key_op(dimm, key, ndctl_dimm_secure_erase, -+ "crypto erase"); -+ else -+ rc = -EINVAL; -+ if (rc < 0) -+ return rc; -+ -+ if (key_type == ND_USER_KEY) -+ return discard_key(dimm); -+ -+ return 0; -+} -+ -+int ndctl_dimm_overwrite_key(struct ndctl_dimm *dimm) -+{ -+ key_serial_t key; -+ int rc; -+ -+ key = check_dimm_key(dimm, false, ND_USER_KEY); -+ if (key < 0) -+ return key; -+ -+ rc = run_key_op(dimm, key, ndctl_dimm_overwrite, -+ "overwrite"); -+ if (rc < 0) -+ return rc; -+ -+ return 0; -+} -diff -up ndctl-71.1/ndctl/keys.h.orig ndctl-71.1/ndctl/keys.h ---- ndctl-71.1/ndctl/keys.h.orig 2022-10-07 15:51:03.930535782 -0400 -+++ ndctl-71.1/ndctl/keys.h 2022-10-07 15:51:03.914535728 -0400 -@@ -0,0 +1,67 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright (C) 2019-2020 Intel Corporation. All rights reserved. */ -+ -+#ifndef _NDCTL_UTIL_KEYS_H_ -+#define _NDCTL_UTIL_KEYS_H_ -+ -+enum ndctl_key_type { -+ ND_USER_KEY, -+ ND_USER_OLD_KEY, -+ ND_MASTER_KEY, -+ ND_MASTER_OLD_KEY, -+ ND_ZERO_KEY, -+}; -+ -+enum key_type { -+ KEY_USER = 0, -+ KEY_TRUSTED, -+ KEY_ENCRYPTED, -+}; -+ -+#ifdef ENABLE_KEYUTILS -+char *ndctl_load_key_blob(const char *path, int *size, const char *postfix, -+ int dirfd, enum key_type key_type); -+int ndctl_dimm_setup_key(struct ndctl_dimm *dimm, const char *kek, -+ enum ndctl_key_type key_type); -+int ndctl_dimm_update_key(struct ndctl_dimm *dimm, const char *kek, -+ enum ndctl_key_type key_type); -+int ndctl_dimm_remove_key(struct ndctl_dimm *dimm); -+int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm, -+ enum ndctl_key_type key_type); -+int ndctl_dimm_overwrite_key(struct ndctl_dimm *dimm); -+#else -+char *ndctl_load_key_blob(const char *path, int *size, const char *postfix, -+ int dirfd, enum key_type key_type) -+{ -+ return NULL; -+} -+static inline int ndctl_dimm_setup_key(struct ndctl_dimm *dimm, -+ const char *kek, enum ndctl_key_type key_type) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline int ndctl_dimm_update_key(struct ndctl_dimm *dimm, -+ const char *kek, enum ndctl_key_type key_type) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline int ndctl_dimm_remove_key(struct ndctl_dimm *dimm) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm, -+ enum ndctl_key_type key_type) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline int ndctl_dimm_overwrite_key(struct ndctl_dimm *dimm) -+{ -+ return -EOPNOTSUPP; -+} -+#endif /* ENABLE_KEYUTILS */ -+ -+#endif -diff -up ndctl-71.1/ndctl/lib/libndctl.c.orig ndctl-71.1/ndctl/lib/libndctl.c ---- ndctl-71.1/ndctl/lib/libndctl.c.orig 2022-10-07 15:50:40.085454597 -0400 -+++ ndctl-71.1/ndctl/lib/libndctl.c 2022-10-07 15:51:03.915535731 -0400 -@@ -20,10 +20,10 @@ - #include - #include - --#include - #include - #include - #include -+#include - #include - #include - #include -diff -up ndctl-71.1/ndctl/lib/papr.c.orig ndctl-71.1/ndctl/lib/papr.c ---- ndctl-71.1/ndctl/lib/papr.c.orig 2022-10-07 15:50:40.086454601 -0400 -+++ ndctl-71.1/ndctl/lib/papr.c 2022-10-07 15:51:03.916535735 -0400 -@@ -10,9 +10,9 @@ - #include - #include - #include --#include -+#include - #include --#include -+#include "private.h" - #include "papr.h" - - /* Utility logging maros for simplify logging */ -diff -up ndctl-71.1/ndctl/lib/private.h.orig ndctl-71.1/ndctl/lib/private.h ---- ndctl-71.1/ndctl/lib/private.h.orig 2022-10-07 15:50:40.086454601 -0400 -+++ ndctl-71.1/ndctl/lib/private.h 2022-10-07 15:51:03.917535738 -0400 -@@ -14,8 +14,9 @@ - #include - #include - --#include -+#include - #include -+#include - #include - #include - #include "intel.h" -@@ -23,7 +24,6 @@ - #include "msft.h" - #include "hyperv.h" - #include "papr.h" --#include "libndctl-nfit.h" - - struct nvdimm_data { - struct ndctl_cmd *cmd_read; -diff -up ndctl-71.1/ndctl/list.c.orig ndctl-71.1/ndctl/list.c ---- ndctl-71.1/ndctl/list.c.orig 2022-10-07 15:50:40.087454604 -0400 -+++ ndctl-71.1/ndctl/list.c 2022-10-07 15:51:03.917535738 -0400 -@@ -7,13 +7,14 @@ - #include - - #include --#include - #include - #include - #include - #include - --#include -+#include "ndctl.h" -+#include "filter.h" -+#include "json.h" - - static struct { - bool buses; -diff -up ndctl-71.1/ndctl/load-keys.c.orig ndctl-71.1/ndctl/load-keys.c ---- ndctl-71.1/ndctl/load-keys.c.orig 2022-10-07 15:50:40.087454604 -0400 -+++ ndctl-71.1/ndctl/load-keys.c 2022-10-07 15:51:03.917535738 -0400 -@@ -12,13 +12,14 @@ - #include - #include - #include --#include - #include -+#include - #include - #include - #include --#include --#include -+ -+#include "filter.h" -+#include "keys.h" - - static struct parameters { - const char *key_path; -diff -up ndctl-71.1/ndctl/monitor.c.orig ndctl-71.1/ndctl/monitor.c ---- ndctl-71.1/ndctl/monitor.c.orig 2022-10-07 15:50:40.087454604 -0400 -+++ ndctl-71.1/ndctl/monitor.c 2022-10-07 15:51:03.917535738 -0400 -@@ -7,7 +7,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -26,6 +25,9 @@ - #endif - #include - -+#include "filter.h" -+#include "json.h" -+ - static struct monitor { - const char *log; - const char *config_file; -diff -up ndctl-71.1/ndctl/namespace.c.orig ndctl-71.1/ndctl/namespace.c ---- ndctl-71.1/ndctl/namespace.c.orig 2022-10-07 15:50:40.088454607 -0400 -+++ ndctl-71.1/ndctl/namespace.c 2022-10-07 15:51:03.918535741 -0400 -@@ -9,7 +9,6 @@ - #include - #include - --#include - #include "action.h" - #include "namespace.h" - #include -@@ -20,11 +19,14 @@ - #include - #include - #include --#include -+#include - #include - #include - #include - -+#include "filter.h" -+#include "json.h" -+ - static bool verbose; - static bool force; - static bool repair; -diff -up ndctl-71.1/ndctl/region.c.orig ndctl-71.1/ndctl/region.c ---- ndctl-71.1/ndctl/region.c.orig 2022-10-07 15:50:40.088454607 -0400 -+++ ndctl-71.1/ndctl/region.c 2022-10-07 15:51:03.918535741 -0400 -@@ -5,10 +5,11 @@ - #include - #include - #include "action.h" --#include - #include - #include - -+#include "filter.h" -+ - static struct { - const char *bus; - const char *type; -diff -up ndctl-71.1/ndctl/util/json-smart.c.orig ndctl-71.1/ndctl/util/json-smart.c -diff -up ndctl-71.1/ndctl/util/keys.c.orig ndctl-71.1/ndctl/util/keys.c -diff -up ndctl-71.1/ndctl/util/keys.h.orig ndctl-71.1/ndctl/util/keys.h -diff -up ndctl-71.1/test/Makefile.am.orig ndctl-71.1/test/Makefile.am ---- ndctl-71.1/test/Makefile.am.orig 2022-10-07 15:50:40.088454607 -0400 -+++ ndctl-71.1/test/Makefile.am 2022-10-07 15:51:03.919535745 -0400 -@@ -80,12 +80,19 @@ testcore =\ - libndctl_SOURCES = libndctl.c $(testcore) - libndctl_LDADD = $(LIBNDCTL_LIB) $(UUID_LIBS) $(KMOD_LIBS) - -+namespace_core =\ -+ ../ndctl/namespace.c \ -+ ../ndctl/filter.c \ -+ ../ndctl/check.c \ -+ ../util/json.c \ -+ ../ndctl/json.c \ -+ ../daxctl/filter.c \ -+ ../daxctl/json.c -+ - dsm_fail_SOURCES =\ - dsm-fail.c \ - $(testcore) \ -- ../ndctl/namespace.c \ -- ../ndctl/check.c \ -- ../util/json.c -+ $(namespace_core) - - dsm_fail_LDADD = $(LIBNDCTL_LIB) \ - $(KMOD_LIBS) \ -@@ -122,9 +129,7 @@ device_dax_SOURCES = \ - dax-dev.c \ - dax-pmd.c \ - $(testcore) \ -- ../ndctl/namespace.c \ -- ../ndctl/check.c \ -- ../util/json.c -+ $(namespace_core) - - if ENABLE_POISON - dax_pmd_SOURCES += dax-poison.c -@@ -153,7 +158,10 @@ smart_listen_LDADD = $(LIBNDCTL_LIB) - - list_smart_dimm_SOURCES = \ - list-smart-dimm.c \ -- ../util/json.c -+ ../ndctl/filter.c \ -+ ../util/json.c \ -+ ../ndctl/json.c -+ - list_smart_dimm_LDADD = \ - $(LIBNDCTL_LIB) \ - $(JSON_LIBS) \ -diff -up ndctl-71.1/test/ack-shutdown-count-set.c.orig ndctl-71.1/test/ack-shutdown-count-set.c ---- ndctl-71.1/test/ack-shutdown-count-set.c.orig 2022-10-07 15:50:40.089454611 -0400 -+++ ndctl-71.1/test/ack-shutdown-count-set.c 2022-10-07 15:51:03.919535745 -0400 -@@ -15,7 +15,7 @@ - - #include - #include --#include -+#include - #include - - static int test_dimm(struct ndctl_dimm *dimm) -diff -up ndctl-71.1/test/daxdev-errors.c.orig ndctl-71.1/test/daxdev-errors.c ---- ndctl-71.1/test/daxdev-errors.c.orig 2022-10-07 15:50:40.090454614 -0400 -+++ ndctl-71.1/test/daxdev-errors.c 2022-10-07 15:51:03.920535748 -0400 -@@ -23,7 +23,7 @@ - #include - #include - #include --#include -+#include - - #define fail() fprintf(stderr, "%s: failed at: %d\n", __func__, __LINE__) - -diff -up ndctl-71.1/test/device-dax.c.orig ndctl-71.1/test/device-dax.c ---- ndctl-71.1/test/device-dax.c.orig 2022-10-07 15:50:40.090454614 -0400 -+++ ndctl-71.1/test/device-dax.c 2022-10-07 15:51:03.921535752 -0400 -@@ -20,7 +20,7 @@ - #include - #include - --#include -+#include - #include - - static sigjmp_buf sj_env; -diff -up ndctl-71.1/test/dsm-fail.c.orig ndctl-71.1/test/dsm-fail.c ---- ndctl-71.1/test/dsm-fail.c.orig 2022-10-07 15:50:40.091454617 -0400 -+++ ndctl-71.1/test/dsm-fail.c 2022-10-07 15:51:03.921535752 -0400 -@@ -14,8 +14,8 @@ - - #include - #include --#include --#include -+#include -+#include - #include - - #define DIMM_PATH "/sys/devices/platform/nfit_test.0/nfit_test_dimm/test_dimm0" -diff -up ndctl-71.1/test/libndctl.c.orig ndctl-71.1/test/libndctl.c ---- ndctl-71.1/test/libndctl.c.orig 2022-10-07 15:50:40.092454621 -0400 -+++ ndctl-71.1/test/libndctl.c 2022-10-07 15:51:03.922535755 -0400 -@@ -21,7 +21,7 @@ - #include - #include - #include --#include -+#include - #include - - #define BLKROGET _IO(0x12,94) /* get read-only status (0 = read_write) */ -diff -up ndctl-71.1/test/list-smart-dimm.c.orig ndctl-71.1/test/list-smart-dimm.c ---- ndctl-71.1/test/list-smart-dimm.c.orig 2022-10-07 15:50:40.093454624 -0400 -+++ ndctl-71.1/test/list-smart-dimm.c 2022-10-07 15:51:03.923535758 -0400 -@@ -3,11 +3,13 @@ - #include - #include - #include --#include - #include - #include - #include --#include -+ -+#include -+#include -+#include - - struct util_filter_params param; - static int did_fail; -diff -up ndctl-71.1/test/pmem_namespaces.c.orig ndctl-71.1/test/pmem_namespaces.c ---- ndctl-71.1/test/pmem_namespaces.c.orig 2022-10-07 15:50:40.093454624 -0400 -+++ ndctl-71.1/test/pmem_namespaces.c 2022-10-07 15:51:03.923535758 -0400 -@@ -3,6 +3,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -18,7 +19,6 @@ - #include - - #include --#include - - #define err(msg)\ - fprintf(stderr, "%s:%d: %s (%s)\n", __func__, __LINE__, msg, strerror(errno)) -diff -up ndctl-71.1/test/revoke-devmem.c.orig ndctl-71.1/test/revoke-devmem.c ---- ndctl-71.1/test/revoke-devmem.c.orig 2022-10-07 15:50:40.094454628 -0400 -+++ ndctl-71.1/test/revoke-devmem.c 2022-10-07 15:51:03.924535762 -0400 -@@ -19,7 +19,7 @@ - #include - #include - --#include -+#include - #include - - static sigjmp_buf sj_env; -diff -up ndctl-71.1/util/filter.c.orig ndctl-71.1/util/filter.c -diff -up ndctl-71.1/util/filter.h.orig ndctl-71.1/util/filter.h -diff -up ndctl-71.1/util/help.c.orig ndctl-71.1/util/help.c ---- ndctl-71.1/util/help.c.orig 2022-10-07 15:50:40.095454631 -0400 -+++ ndctl-71.1/util/help.c 2022-10-07 15:51:03.925535765 -0400 -@@ -14,7 +14,7 @@ - #include - #include - #include --#include -+#include - #include - #include - -diff -up ndctl-71.1/util/json.c.orig ndctl-71.1/util/json.c ---- ndctl-71.1/util/json.c.orig 2022-10-07 15:50:40.096454635 -0400 -+++ ndctl-71.1/util/json.c 2022-10-07 15:51:03.926535769 -0400 -@@ -2,17 +2,10 @@ - // Copyright (C) 2015-2020 Intel Corporation. All rights reserved. - #include - #include -+#include - #include --#include --#include - #include - #include --#include --#include --#include --#include --#include --#include - - /* adapted from mdadm::human_size_brief() */ - static int display_size(struct json_object *jobj, struct printbuf *pbuf, -@@ -112,1536 +105,3 @@ void util_display_json_array(FILE *f_out - } - json_object_put(jarray); - } -- --struct json_object *util_bus_to_json(struct ndctl_bus *bus, unsigned long flags) --{ -- struct json_object *jbus = json_object_new_object(); -- struct json_object *jobj, *fw_obj = NULL; -- int scrub; -- -- if (!jbus) -- return NULL; -- -- jobj = json_object_new_string(ndctl_bus_get_provider(bus)); -- if (!jobj) -- goto err; -- json_object_object_add(jbus, "provider", jobj); -- -- jobj = json_object_new_string(ndctl_bus_get_devname(bus)); -- if (!jobj) -- goto err; -- json_object_object_add(jbus, "dev", jobj); -- -- scrub = ndctl_bus_get_scrub_state(bus); -- if (scrub < 0) -- return jbus; -- -- jobj = json_object_new_string(scrub ? "active" : "idle"); -- if (!jobj) -- goto err; -- json_object_object_add(jbus, "scrub_state", jobj); -- -- if (flags & UTIL_JSON_FIRMWARE) { -- struct ndctl_dimm *dimm; -- -- /* -- * Skip displaying firmware activation capability if no -- * DIMMs support firmware update. -- */ -- ndctl_dimm_foreach(bus, dimm) -- if (ndctl_dimm_fw_update_supported(dimm) == 0) { -- fw_obj = json_object_new_object(); -- break; -- } -- } -- -- if (fw_obj) { -- enum ndctl_fwa_state state; -- enum ndctl_fwa_method method; -- -- jobj = NULL; -- method = ndctl_bus_get_fw_activate_method(bus); -- if (method == NDCTL_FWA_METHOD_RESET) -- jobj = json_object_new_string("reset"); -- if (method == NDCTL_FWA_METHOD_SUSPEND) -- jobj = json_object_new_string("suspend"); -- if (method == NDCTL_FWA_METHOD_LIVE) -- jobj = json_object_new_string("live"); -- if (jobj) -- json_object_object_add(fw_obj, "activate_method", jobj); -- -- jobj = NULL; -- state = ndctl_bus_get_fw_activate_state(bus); -- if (state == NDCTL_FWA_ARMED) -- jobj = json_object_new_string("armed"); -- if (state == NDCTL_FWA_IDLE) -- jobj = json_object_new_string("idle"); -- if (state == NDCTL_FWA_ARM_OVERFLOW) -- jobj = json_object_new_string("overflow"); -- if (jobj) -- json_object_object_add(fw_obj, "activate_state", jobj); -- -- json_object_object_add(jbus, "firmware", fw_obj); -- } -- -- return jbus; -- err: -- json_object_put(jbus); -- return NULL; --} -- --struct json_object *util_dimm_firmware_to_json(struct ndctl_dimm *dimm, -- unsigned long flags) --{ -- struct json_object *jfirmware = json_object_new_object(); -- bool can_update, need_powercycle; -- enum ndctl_fwa_result result; -- enum ndctl_fwa_state state; -- struct json_object *jobj; -- struct ndctl_cmd *cmd; -- uint64_t run, next; -- int rc; -- -- if (!jfirmware) -- return NULL; -- -- cmd = ndctl_dimm_cmd_new_fw_get_info(dimm); -- if (!cmd) -- goto err; -- -- rc = ndctl_cmd_submit(cmd); -- if ((rc < 0) || ndctl_cmd_fw_xlat_firmware_status(cmd) != FW_SUCCESS) { -- jobj = util_json_object_hex(-1, flags); -- if (jobj) -- json_object_object_add(jfirmware, "current_version", -- jobj); -- goto out; -- } -- -- run = ndctl_cmd_fw_info_get_run_version(cmd); -- if (run == ULLONG_MAX) { -- jobj = util_json_object_hex(-1, flags); -- if (jobj) -- json_object_object_add(jfirmware, "current_version", -- jobj); -- goto out; -- } -- -- jobj = util_json_object_hex(run, flags); -- if (jobj) -- json_object_object_add(jfirmware, "current_version", jobj); -- -- rc = ndctl_dimm_fw_update_supported(dimm); -- can_update = rc == 0; -- jobj = json_object_new_boolean(can_update); -- if (jobj) -- json_object_object_add(jfirmware, "can_update", jobj); -- -- -- next = ndctl_cmd_fw_info_get_updated_version(cmd); -- if (next == ULLONG_MAX) { -- jobj = util_json_object_hex(-1, flags); -- if (jobj) -- json_object_object_add(jfirmware, "next_version", -- jobj); -- goto out; -- } -- -- if (!next) -- goto out; -- -- jobj = util_json_object_hex(next, flags); -- if (jobj) -- json_object_object_add(jfirmware, -- "next_version", jobj); -- -- state = ndctl_dimm_get_fw_activate_state(dimm); -- switch (state) { -- case NDCTL_FWA_IDLE: -- jobj = json_object_new_string("idle"); -- break; -- case NDCTL_FWA_ARMED: -- jobj = json_object_new_string("armed"); -- break; -- case NDCTL_FWA_BUSY: -- jobj = json_object_new_string("busy"); -- break; -- default: -- jobj = NULL; -- break; -- } -- if (jobj) -- json_object_object_add(jfirmware, "activate_state", jobj); -- -- result = ndctl_dimm_get_fw_activate_result(dimm); -- switch (result) { -- case NDCTL_FWA_RESULT_NONE: -- case NDCTL_FWA_RESULT_SUCCESS: -- case NDCTL_FWA_RESULT_NOTSTAGED: -- /* -- * If a 'next' firmware version is staged then this -- * result is stale, if the activation succeeds that is -- * indicated by not finding a 'next' entry. -- */ -- need_powercycle = false; -- break; -- case NDCTL_FWA_RESULT_NEEDRESET: -- case NDCTL_FWA_RESULT_FAIL: -- default: -- /* -- * If the last activation failed, or if the activation -- * result is unavailable it is always the case that the -- * only remediation is powercycle. -- */ -- need_powercycle = true; -- break; -- } -- -- if (need_powercycle) { -- jobj = json_object_new_boolean(true); -- if (!jobj) -- goto out; -- json_object_object_add(jfirmware, "need_powercycle", jobj); -- } -- -- ndctl_cmd_unref(cmd); -- return jfirmware; -- --err: -- json_object_put(jfirmware); -- jfirmware = NULL; --out: -- if (cmd) -- ndctl_cmd_unref(cmd); -- return jfirmware; --} -- --struct json_object *util_dimm_to_json(struct ndctl_dimm *dimm, -- unsigned long flags) --{ -- struct json_object *jdimm = json_object_new_object(); -- const char *id = ndctl_dimm_get_unique_id(dimm); -- unsigned int handle = ndctl_dimm_get_handle(dimm); -- unsigned short phys_id = ndctl_dimm_get_phys_id(dimm); -- struct json_object *jobj; -- enum ndctl_security_state sstate; -- -- if (!jdimm) -- return NULL; -- -- jobj = json_object_new_string(ndctl_dimm_get_devname(dimm)); -- if (!jobj) -- goto err; -- json_object_object_add(jdimm, "dev", jobj); -- -- if (id) { -- jobj = json_object_new_string(id); -- if (!jobj) -- goto err; -- json_object_object_add(jdimm, "id", jobj); -- } -- -- if (handle < UINT_MAX) { -- jobj = util_json_object_hex(handle, flags); -- if (!jobj) -- goto err; -- json_object_object_add(jdimm, "handle", jobj); -- } -- -- if (phys_id < USHRT_MAX) { -- jobj = util_json_object_hex(phys_id, flags); -- if (!jobj) -- goto err; -- json_object_object_add(jdimm, "phys_id", jobj); -- } -- -- if (!ndctl_dimm_is_enabled(dimm)) { -- jobj = json_object_new_string("disabled"); -- if (!jobj) -- goto err; -- json_object_object_add(jdimm, "state", jobj); -- } -- -- if (ndctl_dimm_failed_map(dimm)) { -- jobj = json_object_new_boolean(true); -- if (!jobj) -- goto err; -- json_object_object_add(jdimm, "flag_failed_map", jobj); -- } -- -- if (ndctl_dimm_failed_save(dimm)) { -- jobj = json_object_new_boolean(true); -- if (!jobj) -- goto err; -- json_object_object_add(jdimm, "flag_failed_save", jobj); -- } -- -- if (ndctl_dimm_failed_arm(dimm)) { -- jobj = json_object_new_boolean(true); -- if (!jobj) -- goto err; -- json_object_object_add(jdimm, "flag_failed_arm", jobj); -- } -- -- if (ndctl_dimm_failed_restore(dimm)) { -- jobj = json_object_new_boolean(true); -- if (!jobj) -- goto err; -- json_object_object_add(jdimm, "flag_failed_restore", jobj); -- } -- -- if (ndctl_dimm_failed_flush(dimm)) { -- jobj = json_object_new_boolean(true); -- if (!jobj) -- goto err; -- json_object_object_add(jdimm, "flag_failed_flush", jobj); -- } -- -- if (ndctl_dimm_smart_pending(dimm)) { -- jobj = json_object_new_boolean(true); -- if (!jobj) -- goto err; -- json_object_object_add(jdimm, "flag_smart_event", jobj); -- } -- -- sstate = ndctl_dimm_get_security(dimm); -- if (sstate == NDCTL_SECURITY_DISABLED) -- jobj = json_object_new_string("disabled"); -- else if (sstate == NDCTL_SECURITY_UNLOCKED) -- jobj = json_object_new_string("unlocked"); -- else if (sstate == NDCTL_SECURITY_LOCKED) -- jobj = json_object_new_string("locked"); -- else if (sstate == NDCTL_SECURITY_FROZEN) -- jobj = json_object_new_string("frozen"); -- else if (sstate == NDCTL_SECURITY_OVERWRITE) -- jobj = json_object_new_string("overwrite"); -- else -- jobj = NULL; -- if (jobj) -- json_object_object_add(jdimm, "security", jobj); -- -- if (ndctl_dimm_security_is_frozen(dimm)) { -- jobj = json_object_new_boolean(true); -- if (jobj) -- json_object_object_add(jdimm, "security_frozen", jobj); -- } -- -- if (flags & UTIL_JSON_FIRMWARE) { -- struct json_object *jfirmware; -- -- jfirmware = util_dimm_firmware_to_json(dimm, flags); -- if (jfirmware) -- json_object_object_add(jdimm, "firmware", jfirmware); -- } -- -- return jdimm; -- err: -- json_object_put(jdimm); -- return NULL; --} -- --struct json_object *util_daxctl_dev_to_json(struct daxctl_dev *dev, -- unsigned long flags) --{ -- struct daxctl_memory *mem = daxctl_dev_get_memory(dev); -- const char *devname = daxctl_dev_get_devname(dev); -- struct json_object *jdev, *jobj, *jmappings = NULL; -- struct daxctl_mapping *mapping = NULL; -- int node, movable, align; -- -- jdev = json_object_new_object(); -- if (!devname || !jdev) -- return NULL; -- -- jobj = json_object_new_string(devname); -- if (jobj) -- json_object_object_add(jdev, "chardev", jobj); -- -- jobj = util_json_object_size(daxctl_dev_get_size(dev), flags); -- if (jobj) -- json_object_object_add(jdev, "size", jobj); -- -- node = daxctl_dev_get_target_node(dev); -- if (node >= 0) { -- jobj = json_object_new_int(node); -- if (jobj) -- json_object_object_add(jdev, "target_node", jobj); -- } -- -- align = daxctl_dev_get_align(dev); -- if (align > 0) { -- jobj = util_json_object_size(daxctl_dev_get_align(dev), flags); -- if (jobj) -- json_object_object_add(jdev, "align", jobj); -- } -- -- if (mem) -- jobj = json_object_new_string("system-ram"); -- else -- jobj = json_object_new_string("devdax"); -- if (jobj) -- json_object_object_add(jdev, "mode", jobj); -- -- if (mem && daxctl_dev_get_resource(dev) != 0) { -- int num_sections = daxctl_memory_num_sections(mem); -- int num_online = daxctl_memory_is_online(mem); -- -- jobj = json_object_new_int(num_online); -- if (jobj) -- json_object_object_add(jdev, "online_memblocks", jobj); -- -- jobj = json_object_new_int(num_sections); -- if (jobj) -- json_object_object_add(jdev, "total_memblocks", jobj); -- -- movable = daxctl_memory_is_movable(mem); -- if (movable == 1) -- jobj = json_object_new_boolean(true); -- else if (movable == 0) -- jobj = json_object_new_boolean(false); -- else -- jobj = NULL; -- if (jobj) -- json_object_object_add(jdev, "movable", jobj); -- } -- -- if (!daxctl_dev_is_enabled(dev)) { -- jobj = json_object_new_string("disabled"); -- if (jobj) -- json_object_object_add(jdev, "state", jobj); -- } -- -- if (!(flags & UTIL_JSON_DAX_MAPPINGS)) -- return jdev; -- -- daxctl_mapping_foreach(dev, mapping) { -- struct json_object *jmapping; -- -- if (!jmappings) { -- jmappings = json_object_new_array(); -- if (!jmappings) -- continue; -- -- json_object_object_add(jdev, "mappings", jmappings); -- } -- -- jmapping = util_daxctl_mapping_to_json(mapping, flags); -- if (!jmapping) -- continue; -- json_object_array_add(jmappings, jmapping); -- } -- return jdev; --} -- --struct json_object *util_daxctl_devs_to_list(struct daxctl_region *region, -- struct json_object *jdevs, const char *ident, -- unsigned long flags) --{ -- struct daxctl_dev *dev; -- -- daxctl_dev_foreach(region, dev) { -- struct json_object *jdev; -- -- if (!util_daxctl_dev_filter(dev, ident)) -- continue; -- -- if (!(flags & (UTIL_JSON_IDLE|UTIL_JSON_CONFIGURED)) -- && !daxctl_dev_get_size(dev)) -- continue; -- -- if (!jdevs) { -- jdevs = json_object_new_array(); -- if (!jdevs) -- return NULL; -- } -- -- jdev = util_daxctl_dev_to_json(dev, flags); -- if (!jdev) { -- json_object_put(jdevs); -- return NULL; -- } -- -- json_object_array_add(jdevs, jdev); -- } -- -- return jdevs; --} -- --#define _SZ(get_max, get_elem, type) \ --static struct json_object *util_##type##_build_size_array(struct ndctl_##type *arg) \ --{ \ -- struct json_object *arr = json_object_new_array(); \ -- int i; \ -- \ -- if (!arr) \ -- return NULL; \ -- \ -- for (i = 0; i < get_max(arg); i++) { \ -- struct json_object *jobj; \ -- int64_t align; \ -- \ -- align = get_elem(arg, i); \ -- jobj = json_object_new_int64(align); \ -- if (!jobj) \ -- goto err; \ -- json_object_array_add(arr, jobj); \ -- } \ -- \ -- return arr; \ --err: \ -- json_object_put(arr); \ -- return NULL; \ --} --#define SZ(type, kind) _SZ(ndctl_##type##_get_num_##kind##s, \ -- ndctl_##type##_get_supported_##kind, type) --SZ(pfn, alignment) --SZ(dax, alignment) --SZ(btt, sector_size) -- --struct json_object *util_region_capabilities_to_json(struct ndctl_region *region) --{ -- struct json_object *jcaps, *jcap, *jobj; -- struct ndctl_btt *btt = ndctl_region_get_btt_seed(region); -- struct ndctl_pfn *pfn = ndctl_region_get_pfn_seed(region); -- struct ndctl_dax *dax = ndctl_region_get_dax_seed(region); -- -- if (!btt || !pfn || !dax) -- return NULL; -- -- jcaps = json_object_new_array(); -- if (!jcaps) -- return NULL; -- -- if (btt) { -- jcap = json_object_new_object(); -- if (!jcap) -- goto err; -- json_object_array_add(jcaps, jcap); -- -- jobj = json_object_new_string("sector"); -- if (!jobj) -- goto err; -- json_object_object_add(jcap, "mode", jobj); -- jobj = util_btt_build_size_array(btt); -- if (!jobj) -- goto err; -- json_object_object_add(jcap, "sector_sizes", jobj); -- } -- -- if (pfn) { -- jcap = json_object_new_object(); -- if (!jcap) -- goto err; -- json_object_array_add(jcaps, jcap); -- -- jobj = json_object_new_string("fsdax"); -- if (!jobj) -- goto err; -- json_object_object_add(jcap, "mode", jobj); -- jobj = util_pfn_build_size_array(pfn); -- if (!jobj) -- goto err; -- json_object_object_add(jcap, "alignments", jobj); -- } -- -- if (dax) { -- jcap = json_object_new_object(); -- if (!jcap) -- goto err; -- json_object_array_add(jcaps, jcap); -- -- jobj = json_object_new_string("devdax"); -- if (!jobj) -- goto err; -- json_object_object_add(jcap, "mode", jobj); -- jobj = util_dax_build_size_array(dax); -- if (!jobj) -- goto err; -- json_object_object_add(jcap, "alignments", jobj); -- } -- -- return jcaps; --err: -- json_object_put(jcaps); -- return NULL; --} -- --struct json_object *util_daxctl_region_to_json(struct daxctl_region *region, -- const char *ident, unsigned long flags) --{ -- unsigned long align; -- struct json_object *jregion, *jobj; -- unsigned long long available_size, size; -- -- jregion = json_object_new_object(); -- if (!jregion) -- return NULL; -- -- /* -- * The flag indicates when we are being called by an agent that -- * already knows about the parent device information. -- */ -- if (!(flags & UTIL_JSON_DAX)) { -- /* trim off the redundant /sys/devices prefix */ -- const char *path = daxctl_region_get_path(region); -- int len = strlen("/sys/devices"); -- const char *trim = &path[len]; -- -- if (strncmp(path, "/sys/devices", len) != 0) -- goto err; -- jobj = json_object_new_string(trim); -- if (!jobj) -- goto err; -- json_object_object_add(jregion, "path", jobj); -- } -- -- jobj = json_object_new_int(daxctl_region_get_id(region)); -- if (!jobj) -- goto err; -- json_object_object_add(jregion, "id", jobj); -- -- size = daxctl_region_get_size(region); -- if (size < ULLONG_MAX) { -- jobj = util_json_object_size(size, flags); -- if (!jobj) -- goto err; -- json_object_object_add(jregion, "size", jobj); -- } -- -- available_size = daxctl_region_get_available_size(region); -- if (available_size) { -- jobj = util_json_object_size(available_size, flags); -- if (!jobj) -- goto err; -- json_object_object_add(jregion, "available_size", jobj); -- } -- -- align = daxctl_region_get_align(region); -- if (align < ULONG_MAX) { -- jobj = json_object_new_int64(align); -- if (!jobj) -- goto err; -- json_object_object_add(jregion, "align", jobj); -- } -- -- if (!(flags & UTIL_JSON_DAX_DEVS)) -- return jregion; -- -- jobj = util_daxctl_devs_to_list(region, NULL, ident, flags); -- if (jobj) -- json_object_object_add(jregion, "devices", jobj); -- -- return jregion; -- err: -- json_object_put(jregion); -- return NULL; --} -- --static int compare_dimm_number(const void *p1, const void *p2) --{ -- struct ndctl_dimm *dimm1 = *(struct ndctl_dimm **)p1; -- struct ndctl_dimm *dimm2 = *(struct ndctl_dimm **)p2; -- const char *dimm1_name = ndctl_dimm_get_devname(dimm1); -- const char *dimm2_name = ndctl_dimm_get_devname(dimm2); -- int num1, num2; -- -- if (sscanf(dimm1_name, "nmem%d", &num1) != 1) -- num1 = 0; -- if (sscanf(dimm2_name, "nmem%d", &num2) != 1) -- num2 = 0; -- -- return num1 - num2; --} -- --static struct json_object *badblocks_to_jdimms(struct ndctl_region *region, -- unsigned long long addr, unsigned long len) --{ -- struct ndctl_bus *bus = ndctl_region_get_bus(region); -- int count = ndctl_region_get_interleave_ways(region); -- unsigned long long end = addr + len; -- struct json_object *jdimms, *jobj; -- struct ndctl_dimm **dimms, *dimm; -- int found, i; -- -- jdimms = json_object_new_array(); -- if (!jdimms) -- return NULL; -- -- dimms = calloc(count, sizeof(struct ndctl_dimm *)); -- if (!dimms) -- goto err_dimms; -- -- for (found = 0; found < count && addr < end; addr += 512) { -- dimm = ndctl_bus_get_dimm_by_physical_address(bus, addr); -- if (!dimm) -- continue; -- -- for (i = 0; i < count; i++) -- if (dimms[i] == dimm) -- break; -- if (i >= count) -- dimms[found++] = dimm; -- } -- -- if (!found) -- goto err_found; -- -- qsort(dimms, found, sizeof(dimm), compare_dimm_number); -- -- for (i = 0; i < found; i++) { -- const char *devname = ndctl_dimm_get_devname(dimms[i]); -- -- jobj = json_object_new_string(devname); -- if (!jobj) -- break; -- json_object_array_add(jdimms, jobj); -- } -- -- if (!i) -- goto err_found; -- free(dimms); -- return jdimms; -- --err_found: -- free(dimms); --err_dimms: -- json_object_put(jdimms); -- return NULL; --} -- --struct json_object *util_region_badblocks_to_json(struct ndctl_region *region, -- unsigned int *bb_count, unsigned long flags) --{ -- struct json_object *jbb = NULL, *jbbs = NULL, *jobj; -- struct badblock *bb; -- int bbs = 0; -- -- if (flags & UTIL_JSON_MEDIA_ERRORS) { -- jbbs = json_object_new_array(); -- if (!jbbs) -- return NULL; -- } -- -- ndctl_region_badblock_foreach(region, bb) { -- struct json_object *jdimms; -- unsigned long long addr; -- -- bbs += bb->len; -- -- /* recheck so we can still get the badblocks_count from above */ -- if (!(flags & UTIL_JSON_MEDIA_ERRORS)) -- continue; -- -- /* get start address of region */ -- addr = ndctl_region_get_resource(region); -- if (addr == ULLONG_MAX) -- goto err_array; -- -- /* get address of bad block */ -- addr += bb->offset << 9; -- -- jbb = json_object_new_object(); -- if (!jbb) -- goto err_array; -- -- jobj = json_object_new_int64(bb->offset); -- if (!jobj) -- goto err; -- json_object_object_add(jbb, "offset", jobj); -- -- jobj = json_object_new_int(bb->len); -- if (!jobj) -- goto err; -- json_object_object_add(jbb, "length", jobj); -- -- jdimms = badblocks_to_jdimms(region, addr, bb->len << 9); -- if (jdimms) -- json_object_object_add(jbb, "dimms", jdimms); -- json_object_array_add(jbbs, jbb); -- } -- -- *bb_count = bbs; -- -- if (bbs) -- return jbbs; -- -- err: -- json_object_put(jbb); -- err_array: -- json_object_put(jbbs); -- return NULL; --} -- --static struct json_object *util_namespace_badblocks_to_json( -- struct ndctl_namespace *ndns, -- unsigned int *bb_count, unsigned long flags) --{ -- struct json_object *jbb = NULL, *jbbs = NULL, *jobj; -- struct badblock *bb; -- int bbs = 0; -- -- if (flags & UTIL_JSON_MEDIA_ERRORS) { -- jbbs = json_object_new_array(); -- if (!jbbs) -- return NULL; -- } else -- return NULL; -- -- ndctl_namespace_badblock_foreach(ndns, bb) { -- bbs += bb->len; -- -- /* recheck so we can still get the badblocks_count from above */ -- if (!(flags & UTIL_JSON_MEDIA_ERRORS)) -- continue; -- -- jbb = json_object_new_object(); -- if (!jbb) -- goto err_array; -- -- jobj = json_object_new_int64(bb->offset); -- if (!jobj) -- goto err; -- json_object_object_add(jbb, "offset", jobj); -- -- jobj = json_object_new_int(bb->len); -- if (!jobj) -- goto err; -- json_object_object_add(jbb, "length", jobj); -- json_object_array_add(jbbs, jbb); -- } -- -- *bb_count = bbs; -- -- if (bbs) -- return jbbs; -- -- err: -- json_object_put(jbb); -- err_array: -- json_object_put(jbbs); -- return NULL; --} -- --static struct json_object *dev_badblocks_to_json(struct ndctl_region *region, -- unsigned long long dev_begin, unsigned long long dev_size, -- unsigned int *bb_count, unsigned long flags) --{ -- struct json_object *jbb = NULL, *jbbs = NULL, *jobj; -- unsigned long long region_begin, dev_end, offset; -- unsigned int len, bbs = 0; -- struct badblock *bb; -- -- region_begin = ndctl_region_get_resource(region); -- if (region_begin == ULLONG_MAX) -- return NULL; -- -- dev_end = dev_begin + dev_size - 1; -- -- if (flags & UTIL_JSON_MEDIA_ERRORS) { -- jbbs = json_object_new_array(); -- if (!jbbs) -- return NULL; -- } -- -- ndctl_region_badblock_foreach(region, bb) { -- unsigned long long bb_begin, bb_end, begin, end; -- struct json_object *jdimms; -- -- bb_begin = region_begin + (bb->offset << 9); -- bb_end = bb_begin + (bb->len << 9) - 1; -- -- if (bb_end <= dev_begin || bb_begin >= dev_end) -- continue; -- -- if (bb_begin < dev_begin) -- begin = dev_begin; -- else -- begin = bb_begin; -- -- if (bb_end > dev_end) -- end = dev_end; -- else -- end = bb_end; -- -- offset = (begin - dev_begin) >> 9; -- len = (end - begin + 1) >> 9; -- -- bbs += len; -- -- /* recheck so we can still get the badblocks_count from above */ -- if (!(flags & UTIL_JSON_MEDIA_ERRORS)) -- continue; -- -- jbb = json_object_new_object(); -- if (!jbb) -- goto err_array; -- -- jobj = json_object_new_int64(offset); -- if (!jobj) -- goto err; -- json_object_object_add(jbb, "offset", jobj); -- -- jobj = json_object_new_int(len); -- if (!jobj) -- goto err; -- json_object_object_add(jbb, "length", jobj); -- -- jdimms = badblocks_to_jdimms(region, begin, len << 9); -- if (jdimms) -- json_object_object_add(jbb, "dimms", jdimms); -- -- json_object_array_add(jbbs, jbb); -- } -- -- *bb_count = bbs; -- -- if (bbs) -- return jbbs; -- -- err: -- json_object_put(jbb); -- err_array: -- json_object_put(jbbs); -- return NULL; --} -- --static struct json_object *util_pfn_badblocks_to_json(struct ndctl_pfn *pfn, -- unsigned int *bb_count, unsigned long flags) --{ -- struct ndctl_region *region = ndctl_pfn_get_region(pfn); -- unsigned long long pfn_begin, pfn_size; -- -- pfn_begin = ndctl_pfn_get_resource(pfn); -- if (pfn_begin == ULLONG_MAX) { -- struct ndctl_namespace *ndns = ndctl_pfn_get_namespace(pfn); -- -- return util_namespace_badblocks_to_json(ndns, bb_count, flags); -- } -- -- pfn_size = ndctl_pfn_get_size(pfn); -- if (pfn_size == ULLONG_MAX) -- return NULL; -- -- return dev_badblocks_to_json(region, pfn_begin, pfn_size, -- bb_count, flags); --} -- --static void util_btt_badblocks_to_json(struct ndctl_btt *btt, -- unsigned int *bb_count) --{ -- struct ndctl_region *region = ndctl_btt_get_region(btt); -- struct ndctl_namespace *ndns = ndctl_btt_get_namespace(btt); -- unsigned long long begin, size; -- -- if (!ndns) -- return; -- -- begin = ndctl_namespace_get_resource(ndns); -- if (begin == ULLONG_MAX) -- return; -- -- size = ndctl_namespace_get_size(ndns); -- if (size == ULLONG_MAX) -- return; -- -- /* -- * The dev_badblocks_to_json() for BTT is not accurate with -- * respect to data vs metadata badblocks, and is only useful for -- * a potential bb_count. -- * -- * FIXME: switch to native BTT badblocks representation -- * when / if the kernel provides it. -- */ -- dev_badblocks_to_json(region, begin, size, bb_count, 0); --} -- --static struct json_object *util_dax_badblocks_to_json(struct ndctl_dax *dax, -- unsigned int *bb_count, unsigned long flags) --{ -- struct ndctl_region *region = ndctl_dax_get_region(dax); -- unsigned long long dax_begin, dax_size; -- -- dax_begin = ndctl_dax_get_resource(dax); -- if (dax_begin == ULLONG_MAX) -- return NULL; -- -- dax_size = ndctl_dax_get_size(dax); -- if (dax_size == ULLONG_MAX) -- return NULL; -- -- return dev_badblocks_to_json(region, dax_begin, dax_size, -- bb_count, flags); --} -- --static struct json_object *util_raw_uuid(struct ndctl_namespace *ndns) --{ -- char buf[40]; -- uuid_t raw_uuid; -- -- ndctl_namespace_get_uuid(ndns, raw_uuid); -- if (uuid_is_null(raw_uuid)) -- return NULL; -- uuid_unparse(raw_uuid, buf); -- return json_object_new_string(buf); --} -- --static void util_raw_uuid_to_json(struct ndctl_namespace *ndns, -- unsigned long flags, -- struct json_object *jndns) --{ -- struct json_object *jobj; -- -- if (!(flags & UTIL_JSON_VERBOSE)) -- return; -- -- jobj = util_raw_uuid(ndns); -- if (!jobj) -- return; -- json_object_object_add(jndns, "raw_uuid", jobj); --} -- --struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns, -- unsigned long flags) --{ -- struct json_object *jndns = json_object_new_object(); -- enum ndctl_pfn_loc loc = NDCTL_PFN_LOC_NONE; -- struct json_object *jobj, *jbbs = NULL; -- const char *locations[] = { -- [NDCTL_PFN_LOC_NONE] = "none", -- [NDCTL_PFN_LOC_RAM] = "mem", -- [NDCTL_PFN_LOC_PMEM] = "dev", -- }; -- unsigned long long size = ULLONG_MAX; -- unsigned int sector_size = UINT_MAX; -- enum ndctl_namespace_mode mode; -- const char *bdev = NULL, *name; -- unsigned int bb_count = 0; -- struct ndctl_btt *btt; -- struct ndctl_pfn *pfn; -- struct ndctl_dax *dax; -- unsigned long align = 0; -- char buf[40]; -- uuid_t uuid; -- int numa, target; -- -- if (!jndns) -- return NULL; -- -- jobj = json_object_new_string(ndctl_namespace_get_devname(ndns)); -- if (!jobj) -- goto err; -- json_object_object_add(jndns, "dev", jobj); -- -- btt = ndctl_namespace_get_btt(ndns); -- dax = ndctl_namespace_get_dax(ndns); -- pfn = ndctl_namespace_get_pfn(ndns); -- mode = ndctl_namespace_get_mode(ndns); -- switch (mode) { -- case NDCTL_NS_MODE_MEMORY: -- if (pfn) { /* dynamic memory mode */ -- size = ndctl_pfn_get_size(pfn); -- loc = ndctl_pfn_get_location(pfn); -- } else { /* native/static memory mode */ -- size = ndctl_namespace_get_size(ndns); -- loc = NDCTL_PFN_LOC_RAM; -- } -- jobj = json_object_new_string("fsdax"); -- break; -- case NDCTL_NS_MODE_DAX: -- if (!dax) -- goto err; -- size = ndctl_dax_get_size(dax); -- jobj = json_object_new_string("devdax"); -- loc = ndctl_dax_get_location(dax); -- break; -- case NDCTL_NS_MODE_SECTOR: -- if (!btt) -- goto err; -- jobj = json_object_new_string("sector"); -- size = ndctl_btt_get_size(btt); -- break; -- case NDCTL_NS_MODE_RAW: -- size = ndctl_namespace_get_size(ndns); -- jobj = json_object_new_string("raw"); -- break; -- default: -- jobj = NULL; -- } -- if (jobj) -- json_object_object_add(jndns, "mode", jobj); -- -- if ((mode != NDCTL_NS_MODE_SECTOR) && (mode != NDCTL_NS_MODE_RAW)) { -- jobj = json_object_new_string(locations[loc]); -- if (jobj) -- json_object_object_add(jndns, "map", jobj); -- } -- -- if (size < ULLONG_MAX) { -- jobj = util_json_object_size(size, flags); -- if (jobj) -- json_object_object_add(jndns, "size", jobj); -- } -- -- if (btt) { -- ndctl_btt_get_uuid(btt, uuid); -- uuid_unparse(uuid, buf); -- jobj = json_object_new_string(buf); -- if (!jobj) -- goto err; -- json_object_object_add(jndns, "uuid", jobj); -- util_raw_uuid_to_json(ndns, flags, jndns); -- bdev = ndctl_btt_get_block_device(btt); -- } else if (pfn) { -- align = ndctl_pfn_get_align(pfn); -- ndctl_pfn_get_uuid(pfn, uuid); -- uuid_unparse(uuid, buf); -- jobj = json_object_new_string(buf); -- if (!jobj) -- goto err; -- json_object_object_add(jndns, "uuid", jobj); -- util_raw_uuid_to_json(ndns, flags, jndns); -- bdev = ndctl_pfn_get_block_device(pfn); -- } else if (dax) { -- struct daxctl_region *dax_region; -- -- dax_region = ndctl_dax_get_daxctl_region(dax); -- align = ndctl_dax_get_align(dax); -- ndctl_dax_get_uuid(dax, uuid); -- uuid_unparse(uuid, buf); -- jobj = json_object_new_string(buf); -- if (!jobj) -- goto err; -- json_object_object_add(jndns, "uuid", jobj); -- util_raw_uuid_to_json(ndns, flags, jndns); -- if ((flags & UTIL_JSON_DAX) && dax_region) { -- jobj = util_daxctl_region_to_json(dax_region, NULL, -- flags); -- if (jobj) -- json_object_object_add(jndns, "daxregion", jobj); -- } else if (dax_region) { -- struct daxctl_dev *dev; -- -- /* -- * We can only find/list these device-dax -- * details when the instance is enabled. -- */ -- dev = daxctl_dev_get_first(dax_region); -- if (dev) { -- name = daxctl_dev_get_devname(dev); -- jobj = json_object_new_string(name); -- if (!jobj) -- goto err; -- json_object_object_add(jndns, "chardev", jobj); -- } -- } -- } else if (ndctl_namespace_get_type(ndns) != ND_DEVICE_NAMESPACE_IO) { -- ndctl_namespace_get_uuid(ndns, uuid); -- uuid_unparse(uuid, buf); -- jobj = json_object_new_string(buf); -- if (!jobj) -- goto err; -- json_object_object_add(jndns, "uuid", jobj); -- bdev = ndctl_namespace_get_block_device(ndns); -- } else -- bdev = ndctl_namespace_get_block_device(ndns); -- -- if (btt) -- sector_size = ndctl_btt_get_sector_size(btt); -- else if (!dax) { -- sector_size = ndctl_namespace_get_sector_size(ndns); -- if (!sector_size || sector_size == UINT_MAX) -- sector_size = 512; -- } -- -- /* -- * The kernel will default to a 512 byte sector size on PMEM -- * namespaces that don't explicitly have a sector size. This -- * happens because they use pre-v1.2 labels or because they -- * don't have a label space (devtype=nd_namespace_io). -- */ -- if (sector_size < UINT_MAX) { -- jobj = json_object_new_int(sector_size); -- if (!jobj) -- goto err; -- json_object_object_add(jndns, "sector_size", jobj); -- } -- -- if (align) { -- jobj = json_object_new_int64(align); -- if (!jobj) -- goto err; -- json_object_object_add(jndns, "align", jobj); -- } -- -- if (bdev && bdev[0]) { -- jobj = json_object_new_string(bdev); -- if (!jobj) -- goto err; -- json_object_object_add(jndns, "blockdev", jobj); -- } -- -- if (!ndctl_namespace_is_active(ndns)) { -- jobj = json_object_new_string("disabled"); -- if (!jobj) -- goto err; -- json_object_object_add(jndns, "state", jobj); -- } -- -- name = ndctl_namespace_get_alt_name(ndns); -- if (name && name[0]) { -- jobj = json_object_new_string(name); -- if (!jobj) -- goto err; -- json_object_object_add(jndns, "name", jobj); -- } -- -- numa = ndctl_namespace_get_numa_node(ndns); -- if (numa >= 0 && flags & UTIL_JSON_VERBOSE) { -- jobj = json_object_new_int(numa); -- if (jobj) -- json_object_object_add(jndns, "numa_node", jobj); -- } -- -- target = ndctl_namespace_get_target_node(ndns); -- if (target >= 0 && flags & UTIL_JSON_VERBOSE) { -- jobj = json_object_new_int(target); -- if (jobj) -- json_object_object_add(jndns, "target_node", jobj); -- } -- -- if (pfn) -- jbbs = util_pfn_badblocks_to_json(pfn, &bb_count, flags); -- else if (dax) -- jbbs = util_dax_badblocks_to_json(dax, &bb_count, flags); -- else if (btt) -- util_btt_badblocks_to_json(btt, &bb_count); -- else { -- jbbs = util_region_badblocks_to_json( -- ndctl_namespace_get_region(ndns), &bb_count, -- flags); -- if (!jbbs) -- jbbs = util_namespace_badblocks_to_json(ndns, &bb_count, -- flags); -- } -- -- if (bb_count) { -- jobj = json_object_new_int(bb_count); -- if (!jobj) { -- json_object_put(jbbs); -- goto err; -- } -- json_object_object_add(jndns, "badblock_count", jobj); -- } -- -- if ((flags & UTIL_JSON_MEDIA_ERRORS) && jbbs) -- json_object_object_add(jndns, "badblocks", jbbs); -- -- return jndns; -- err: -- json_object_put(jndns); -- return NULL; --} -- --struct json_object *util_mapping_to_json(struct ndctl_mapping *mapping, -- unsigned long flags) --{ -- struct json_object *jmapping = json_object_new_object(); -- struct ndctl_dimm *dimm = ndctl_mapping_get_dimm(mapping); -- struct json_object *jobj; -- int position; -- -- if (!jmapping) -- return NULL; -- -- jobj = json_object_new_string(ndctl_dimm_get_devname(dimm)); -- if (!jobj) -- goto err; -- json_object_object_add(jmapping, "dimm", jobj); -- -- jobj = util_json_object_hex(ndctl_mapping_get_offset(mapping), flags); -- if (!jobj) -- goto err; -- json_object_object_add(jmapping, "offset", jobj); -- -- jobj = util_json_object_hex(ndctl_mapping_get_length(mapping), flags); -- if (!jobj) -- goto err; -- json_object_object_add(jmapping, "length", jobj); -- -- position = ndctl_mapping_get_position(mapping); -- if (position >= 0) { -- jobj = json_object_new_int(position); -- if (!jobj) -- goto err; -- json_object_object_add(jmapping, "position", jobj); -- } -- -- return jmapping; -- err: -- json_object_put(jmapping); -- return NULL; --} -- --struct json_object *util_daxctl_mapping_to_json(struct daxctl_mapping *mapping, -- unsigned long flags) --{ -- struct json_object *jmapping = json_object_new_object(); -- struct json_object *jobj; -- -- if (!jmapping) -- return NULL; -- -- jobj = util_json_object_hex(daxctl_mapping_get_offset(mapping), flags); -- if (!jobj) -- goto err; -- json_object_object_add(jmapping, "page_offset", jobj); -- -- jobj = util_json_object_hex(daxctl_mapping_get_start(mapping), flags); -- if (!jobj) -- goto err; -- json_object_object_add(jmapping, "start", jobj); -- -- jobj = util_json_object_hex(daxctl_mapping_get_end(mapping), flags); -- if (!jobj) -- goto err; -- json_object_object_add(jmapping, "end", jobj); -- -- jobj = util_json_object_size(daxctl_mapping_get_size(mapping), flags); -- if (!jobj) -- goto err; -- json_object_object_add(jmapping, "size", jobj); -- -- return jmapping; -- err: -- json_object_put(jmapping); -- return NULL; --} -- --struct json_object *util_badblock_rec_to_json(u64 block, u64 count, -- unsigned long flags) --{ -- struct json_object *jerr = json_object_new_object(); -- struct json_object *jobj; -- -- if (!jerr) -- return NULL; -- -- jobj = util_json_object_hex(block, flags); -- if (!jobj) -- goto err; -- json_object_object_add(jerr, "block", jobj); -- -- jobj = util_json_object_hex(count, flags); -- if (!jobj) -- goto err; -- json_object_object_add(jerr, "count", jobj); -- -- return jerr; -- err: -- json_object_put(jerr); -- return NULL; --} -- --static struct json_object *util_cxl_memdev_health_to_json( -- struct cxl_memdev *memdev, unsigned long flags) --{ -- struct json_object *jhealth; -- struct json_object *jobj; -- struct cxl_cmd *cmd; -- u32 field; -- int rc; -- -- jhealth = json_object_new_object(); -- if (!jhealth) -- return NULL; -- if (!memdev) -- goto err_jobj; -- -- cmd = cxl_cmd_new_get_health_info(memdev); -- if (!cmd) -- goto err_jobj; -- -- rc = cxl_cmd_submit(cmd); -- if (rc < 0) -- goto err_cmd; -- rc = cxl_cmd_get_mbox_status(cmd); -- if (rc != 0) -- goto err_cmd; -- -- /* health_status fields */ -- rc = cxl_cmd_health_info_get_maintenance_needed(cmd); -- jobj = json_object_new_boolean(rc); -- if (jobj) -- json_object_object_add(jhealth, "maintenance_needed", jobj); -- -- rc = cxl_cmd_health_info_get_performance_degraded(cmd); -- jobj = json_object_new_boolean(rc); -- if (jobj) -- json_object_object_add(jhealth, "performance_degraded", jobj); -- -- rc = cxl_cmd_health_info_get_hw_replacement_needed(cmd); -- jobj = json_object_new_boolean(rc); -- if (jobj) -- json_object_object_add(jhealth, "hw_replacement_needed", jobj); -- -- /* media_status fields */ -- rc = cxl_cmd_health_info_get_media_normal(cmd); -- jobj = json_object_new_boolean(rc); -- if (jobj) -- json_object_object_add(jhealth, "media_normal", jobj); -- -- rc = cxl_cmd_health_info_get_media_not_ready(cmd); -- jobj = json_object_new_boolean(rc); -- if (jobj) -- json_object_object_add(jhealth, "media_not_ready", jobj); -- -- rc = cxl_cmd_health_info_get_media_persistence_lost(cmd); -- jobj = json_object_new_boolean(rc); -- if (jobj) -- json_object_object_add(jhealth, "media_persistence_lost", jobj); -- -- rc = cxl_cmd_health_info_get_media_data_lost(cmd); -- jobj = json_object_new_boolean(rc); -- if (jobj) -- json_object_object_add(jhealth, "media_data_lost", jobj); -- -- rc = cxl_cmd_health_info_get_media_powerloss_persistence_loss(cmd); -- jobj = json_object_new_boolean(rc); -- if (jobj) -- json_object_object_add(jhealth, "media_powerloss_persistence_loss", jobj); -- -- rc = cxl_cmd_health_info_get_media_shutdown_persistence_loss(cmd); -- jobj = json_object_new_boolean(rc); -- if (jobj) -- json_object_object_add(jhealth, "media_shutdown_persistence_loss", jobj); -- -- rc = cxl_cmd_health_info_get_media_persistence_loss_imminent(cmd); -- jobj = json_object_new_boolean(rc); -- if (jobj) -- json_object_object_add(jhealth, "media_persistence_loss_imminent", jobj); -- -- rc = cxl_cmd_health_info_get_media_powerloss_data_loss(cmd); -- jobj = json_object_new_boolean(rc); -- if (jobj) -- json_object_object_add(jhealth, "media_powerloss_data_loss", jobj); -- -- rc = cxl_cmd_health_info_get_media_shutdown_data_loss(cmd); -- jobj = json_object_new_boolean(rc); -- if (jobj) -- json_object_object_add(jhealth, "media_shutdown_data_loss", jobj); -- -- rc = cxl_cmd_health_info_get_media_data_loss_imminent(cmd); -- jobj = json_object_new_boolean(rc); -- if (jobj) -- json_object_object_add(jhealth, "media_data_loss_imminent", jobj); -- -- /* ext_status fields */ -- if (cxl_cmd_health_info_get_ext_life_used_normal(cmd)) -- jobj = json_object_new_string("normal"); -- else if (cxl_cmd_health_info_get_ext_life_used_warning(cmd)) -- jobj = json_object_new_string("warning"); -- else if (cxl_cmd_health_info_get_ext_life_used_critical(cmd)) -- jobj = json_object_new_string("critical"); -- else -- jobj = json_object_new_string("unknown"); -- if (jobj) -- json_object_object_add(jhealth, "ext_life_used", jobj); -- -- if (cxl_cmd_health_info_get_ext_temperature_normal(cmd)) -- jobj = json_object_new_string("normal"); -- else if (cxl_cmd_health_info_get_ext_temperature_warning(cmd)) -- jobj = json_object_new_string("warning"); -- else if (cxl_cmd_health_info_get_ext_temperature_critical(cmd)) -- jobj = json_object_new_string("critical"); -- else -- jobj = json_object_new_string("unknown"); -- if (jobj) -- json_object_object_add(jhealth, "ext_temperature", jobj); -- -- if (cxl_cmd_health_info_get_ext_corrected_volatile_normal(cmd)) -- jobj = json_object_new_string("normal"); -- else if (cxl_cmd_health_info_get_ext_corrected_volatile_warning(cmd)) -- jobj = json_object_new_string("warning"); -- else -- jobj = json_object_new_string("unknown"); -- if (jobj) -- json_object_object_add(jhealth, "ext_corrected_volatile", jobj); -- -- if (cxl_cmd_health_info_get_ext_corrected_persistent_normal(cmd)) -- jobj = json_object_new_string("normal"); -- else if (cxl_cmd_health_info_get_ext_corrected_persistent_warning(cmd)) -- jobj = json_object_new_string("warning"); -- else -- jobj = json_object_new_string("unknown"); -- if (jobj) -- json_object_object_add(jhealth, "ext_corrected_persistent", jobj); -- -- /* other fields */ -- field = cxl_cmd_health_info_get_life_used(cmd); -- if (field != 0xff) { -- jobj = json_object_new_int(field); -- if (jobj) -- json_object_object_add(jhealth, "life_used_percent", jobj); -- } -- -- field = cxl_cmd_health_info_get_temperature(cmd); -- if (field != 0xffff) { -- jobj = json_object_new_int(field); -- if (jobj) -- json_object_object_add(jhealth, "temperature", jobj); -- } -- -- field = cxl_cmd_health_info_get_dirty_shutdowns(cmd); -- jobj = json_object_new_int64(field); -- if (jobj) -- json_object_object_add(jhealth, "dirty_shutdowns", jobj); -- -- field = cxl_cmd_health_info_get_volatile_errors(cmd); -- jobj = json_object_new_int64(field); -- if (jobj) -- json_object_object_add(jhealth, "volatile_errors", jobj); -- -- field = cxl_cmd_health_info_get_pmem_errors(cmd); -- jobj = json_object_new_int64(field); -- if (jobj) -- json_object_object_add(jhealth, "pmem_errors", jobj); -- -- cxl_cmd_unref(cmd); -- return jhealth; -- --err_cmd: -- cxl_cmd_unref(cmd); --err_jobj: -- json_object_put(jhealth); -- return NULL; --} -- --struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, -- unsigned long flags) --{ -- const char *devname = cxl_memdev_get_devname(memdev); -- struct json_object *jdev, *jobj; -- -- jdev = json_object_new_object(); -- if (!devname || !jdev) -- return NULL; -- -- jobj = json_object_new_string(devname); -- if (jobj) -- json_object_object_add(jdev, "memdev", jobj); -- -- jobj = util_json_object_size(cxl_memdev_get_pmem_size(memdev), flags); -- if (jobj) -- json_object_object_add(jdev, "pmem_size", jobj); -- -- jobj = util_json_object_size(cxl_memdev_get_ram_size(memdev), flags); -- if (jobj) -- json_object_object_add(jdev, "ram_size", jobj); -- -- if (flags & UTIL_JSON_HEALTH) { -- jobj = util_cxl_memdev_health_to_json(memdev, flags); -- if (jobj) -- json_object_object_add(jdev, "health", jobj); -- } -- return jdev; --} -diff -up ndctl-71.1/util/json.h.orig ndctl-71.1/util/json.h ---- ndctl-71.1/util/json.h.orig 2022-10-07 15:50:40.097454638 -0400 -+++ ndctl-71.1/util/json.h 2022-10-07 15:51:03.927535772 -0400 -@@ -1,12 +1,9 @@ - /* SPDX-License-Identifier: GPL-2.0 */ - /* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */ --#ifndef __NDCTL_JSON_H__ --#define __NDCTL_JSON_H__ -+#ifndef __UTIL_JSON_H__ -+#define __UTIL_JSON_H__ - #include - #include --#include --#include --#include - - enum util_json_flags { - UTIL_JSON_IDLE = (1 << 0), -@@ -25,38 +22,8 @@ enum util_json_flags { - struct json_object; - void util_display_json_array(FILE *f_out, struct json_object *jarray, - unsigned long flags); --struct json_object *util_bus_to_json(struct ndctl_bus *bus, -- unsigned long flags); --struct json_object *util_dimm_to_json(struct ndctl_dimm *dimm, -- unsigned long flags); --struct json_object *util_mapping_to_json(struct ndctl_mapping *mapping, -- unsigned long flags); --struct json_object *util_daxctl_mapping_to_json(struct daxctl_mapping *mapping, -- unsigned long flags); --struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns, -- unsigned long flags); --struct json_object *util_badblock_rec_to_json(u64 block, u64 count, -- unsigned long flags); --struct daxctl_region; --struct daxctl_dev; --struct json_object *util_region_badblocks_to_json(struct ndctl_region *region, -- unsigned int *bb_count, unsigned long flags); --struct json_object *util_daxctl_region_to_json(struct daxctl_region *region, -- const char *ident, unsigned long flags); --struct json_object *util_daxctl_dev_to_json(struct daxctl_dev *dev, -- unsigned long flags); --struct json_object *util_daxctl_devs_to_list(struct daxctl_region *region, -- struct json_object *jdevs, const char *ident, -- unsigned long flags); - struct json_object *util_json_object_size(unsigned long long size, - unsigned long flags); - struct json_object *util_json_object_hex(unsigned long long val, - unsigned long flags); --struct json_object *util_dimm_health_to_json(struct ndctl_dimm *dimm); --struct json_object *util_dimm_firmware_to_json(struct ndctl_dimm *dimm, -- unsigned long flags); --struct json_object *util_region_capabilities_to_json(struct ndctl_region *region); --struct cxl_memdev; --struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, -- unsigned long flags); --#endif /* __NDCTL_JSON_H__ */ -+#endif /* __UTIL_JSON_H__ */ diff --git a/SOURCES/0078-Documentation-Drop-attrs.adoc-include.patch b/SOURCES/0078-Documentation-Drop-attrs.adoc-include.patch deleted file mode 100644 index 5233185..0000000 --- a/SOURCES/0078-Documentation-Drop-attrs.adoc-include.patch +++ /dev/null @@ -1,104 +0,0 @@ -From d1b966de2b32f6152bc3b9c3f5d842ba12407a87 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:32:32 -0800 -Subject: [PATCH 078/217] Documentation: Drop attrs.adoc include - -In preparation for switching build systems, drop the attrs.adoc include for -communicating variables to asciidoc. Simply add the necessary variable -values to the invocation of the command using the --attribute argument. - -Link: https://lore.kernel.org/r/164141835217.3990253.17678912974035740752.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .gitignore | 1 - - Documentation/daxctl/Makefile.am | 17 +++++++---------- - .../daxctl/daxctl-reconfigure-device.txt | 2 -- - Documentation/ndctl/Makefile.am | 17 +++++++---------- - Documentation/ndctl/intel-nvdimm-security.txt | 2 -- - Documentation/ndctl/ndctl-load-keys.txt | 2 -- - Documentation/ndctl/ndctl-monitor.txt | 2 -- - Documentation/ndctl/ndctl-sanitize-dimm.txt | 2 -- - Documentation/ndctl/ndctl-setup-passphrase.txt | 2 -- - Documentation/ndctl/ndctl-update-passphrase.txt | 2 -- - 10 files changed, 14 insertions(+), 35 deletions(-) - -diff -up ndctl-71.1/.gitignore.orig ndctl-71.1/.gitignore ---- ndctl-71.1/.gitignore.orig 2022-10-07 15:58:15.663005697 -0400 -+++ ndctl-71.1/.gitignore 2022-10-07 15:58:57.238147247 -0400 -@@ -23,7 +23,6 @@ Documentation/daxctl/asciidoctor-extensi - Documentation/ndctl/asciidoctor-extensions.rb - Documentation/cxl/asciidoctor-extensions.rb - Documentation/cxl/lib/asciidoctor-extensions.rb --Documentation/ndctl/attrs.adoc - .dirstamp - daxctl/config.h - daxctl/daxctl -diff -up ndctl-71.1/Documentation/ndctl/intel-nvdimm-security.txt.orig ndctl-71.1/Documentation/ndctl/intel-nvdimm-security.txt ---- ndctl-71.1/Documentation/ndctl/intel-nvdimm-security.txt.orig 2020-12-22 16:44:57.000000000 -0500 -+++ ndctl-71.1/Documentation/ndctl/intel-nvdimm-security.txt 2022-10-07 15:59:06.192177733 -0400 -@@ -1,7 +1,5 @@ - // SPDX-License-Identifier: GPL-2.0 - --include::attrs.adoc[] -- - THEORY OF OPERATION - ------------------- - The Intel Device Specific Methods (DSM) specification v1.7 and v1.8 [1] -diff -up ndctl-71.1/Documentation/ndctl/ndctl-load-keys.txt.orig ndctl-71.1/Documentation/ndctl/ndctl-load-keys.txt ---- ndctl-71.1/Documentation/ndctl/ndctl-load-keys.txt.orig 2020-12-22 16:44:57.000000000 -0500 -+++ ndctl-71.1/Documentation/ndctl/ndctl-load-keys.txt 2022-10-07 15:59:06.192177733 -0400 -@@ -1,7 +1,5 @@ - // SPDX-License-Identifier: GPL-2.0 - --include::attrs.adoc[] -- - ndctl-load-keys(1) - ================== - -diff -up ndctl-71.1/Documentation/ndctl/ndctl-monitor.txt.orig ndctl-71.1/Documentation/ndctl/ndctl-monitor.txt ---- ndctl-71.1/Documentation/ndctl/ndctl-monitor.txt.orig 2020-12-22 16:44:57.000000000 -0500 -+++ ndctl-71.1/Documentation/ndctl/ndctl-monitor.txt 2022-10-07 15:59:06.192177733 -0400 -@@ -1,7 +1,5 @@ - // SPDX-License-Identifier: GPL-2.0 - --include::attrs.adoc[] -- - ndctl-monitor(1) - ================ - -diff -up ndctl-71.1/Documentation/ndctl/ndctl-sanitize-dimm.txt.orig ndctl-71.1/Documentation/ndctl/ndctl-sanitize-dimm.txt ---- ndctl-71.1/Documentation/ndctl/ndctl-sanitize-dimm.txt.orig 2020-12-22 16:44:57.000000000 -0500 -+++ ndctl-71.1/Documentation/ndctl/ndctl-sanitize-dimm.txt 2022-10-07 15:59:06.192177733 -0400 -@@ -1,7 +1,5 @@ - // SPDX-License-Identifier: GPL-2.0 - --include::attrs.adoc[] -- - ndctl-sanitize-dimm(1) - ====================== - -diff -up ndctl-71.1/Documentation/ndctl/ndctl-setup-passphrase.txt.orig ndctl-71.1/Documentation/ndctl/ndctl-setup-passphrase.txt ---- ndctl-71.1/Documentation/ndctl/ndctl-setup-passphrase.txt.orig 2020-12-22 16:44:57.000000000 -0500 -+++ ndctl-71.1/Documentation/ndctl/ndctl-setup-passphrase.txt 2022-10-07 15:59:06.193177737 -0400 -@@ -1,7 +1,5 @@ - // SPDX-License-Identifier: GPL-2.0 - --include::attrs.adoc[] -- - ndctl-setup-passphrase(1) - ========================= - -diff -up ndctl-71.1/Documentation/ndctl/ndctl-update-passphrase.txt.orig ndctl-71.1/Documentation/ndctl/ndctl-update-passphrase.txt ---- ndctl-71.1/Documentation/ndctl/ndctl-update-passphrase.txt.orig 2020-12-22 16:44:57.000000000 -0500 -+++ ndctl-71.1/Documentation/ndctl/ndctl-update-passphrase.txt 2022-10-07 15:59:06.193177737 -0400 -@@ -1,7 +1,5 @@ - // SPDX-License-Identifier: GPL-2.0 - --include::attrs.adoc[] -- - ndctl-update-passphrase(1) - ========================== - diff --git a/SOURCES/0079-build-Drop-unnecessary-tool-config.h-includes.patch b/SOURCES/0079-build-Drop-unnecessary-tool-config.h-includes.patch deleted file mode 100644 index ee5daad..0000000 --- a/SOURCES/0079-build-Drop-unnecessary-tool-config.h-includes.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 3297995248081d31d282fc9a339894989ff94e23 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:32:37 -0800 -Subject: [PATCH 079/217] build: Drop unnecessary $tool/config.h includes - -In preparation for support for meson as the build infrastructure remove -some explicit config.h includes that will be replaced by a unified config.h -at the top of the project. - -Link: https://lore.kernel.org/r/164141835727.3990253.12971738434561351928.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - daxctl/migrate.c | 1 - - ndctl/keys.c | 1 - - ndctl/monitor.c | 1 - - 3 files changed, 3 deletions(-) - -diff -up ndctl-71.1/daxctl/migrate.c.orig ndctl-71.1/daxctl/migrate.c ---- ndctl-71.1/daxctl/migrate.c.orig 2020-12-22 16:44:57.000000000 -0500 -+++ ndctl-71.1/daxctl/migrate.c 2022-10-07 16:01:20.316634385 -0400 -@@ -5,7 +5,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -up ndctl-71.1/ndctl/keys.c.orig ndctl-71.1/ndctl/keys.c ---- ndctl-71.1/ndctl/keys.c.orig 2022-10-07 16:01:03.161575978 -0400 -+++ ndctl-71.1/ndctl/keys.c 2022-10-07 16:01:20.317634389 -0400 -@@ -13,7 +13,6 @@ - #include - #include - --#include - #include - #include - -diff -up ndctl-71.1/ndctl/monitor.c.orig ndctl-71.1/ndctl/monitor.c ---- ndctl-71.1/ndctl/monitor.c.orig 2022-10-07 16:01:03.164575988 -0400 -+++ ndctl-71.1/ndctl/monitor.c 2022-10-07 16:01:20.318634392 -0400 -@@ -10,7 +10,6 @@ - #include - #include - #include --#include - #include - #include - #include diff --git a/SOURCES/0080-test-Prepare-out-of-line-builds.patch b/SOURCES/0080-test-Prepare-out-of-line-builds.patch deleted file mode 100644 index cdc8ba8..0000000 --- a/SOURCES/0080-test-Prepare-out-of-line-builds.patch +++ /dev/null @@ -1,355 +0,0 @@ -From d12d5f82755db50277e50c8daa97be15107f924d Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:32:42 -0800 -Subject: [PATCH 080/217] test: Prepare out of line builds - -In preparation for converting to meson prepare the unit tests to run out of -a build directory rather than out of the source directory. Introduce -TEST_PATH for the location of the test executables. - -Link: https://lore.kernel.org/r/164141836235.3990253.5237538466465550643.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/btt-errors.sh | 4 +--- - test/common | 37 +++++++++++++++++++++---------------- - test/dax-pmd.c | 11 +++++++++-- - test/dax.sh | 6 +++--- - test/daxdev-errors.sh | 4 ++-- - test/device-dax-fio.sh | 2 +- - test/dm.sh | 4 ++-- - test/inject-smart.sh | 2 +- - test/mmap.sh | 6 +++--- - test/monitor.sh | 6 +++--- - test/pmem-errors.sh | 8 +++----- - test/sub-section.sh | 4 ++-- - test/track-uuid.sh | 2 +- - 13 files changed, 52 insertions(+), 44 deletions(-) - -diff --git a/test/btt-errors.sh b/test/btt-errors.sh -index 6e69178..18518d5 100755 ---- a/test/btt-errors.sh -+++ b/test/btt-errors.sh -@@ -11,14 +11,12 @@ rc=77 - - cleanup() - { -- rm -f $FILE -- rm -f $MNT/$FILE - if grep -q "$MNT" /proc/mounts; then - umount $MNT - else - rc=77 - fi -- rmdir $MNT -+ rm -rf $MNT - } - - force_raw() -diff --git a/test/common b/test/common -index b6d4712..fb48795 100644 ---- a/test/common -+++ b/test/common -@@ -4,27 +4,32 @@ - # Global variables - - # NDCTL --# --if [ -f "../ndctl/ndctl" ] && [ -x "../ndctl/ndctl" ]; then -- export NDCTL=../ndctl/ndctl --elif [ -f "./ndctl/ndctl" ] && [ -x "./ndctl/ndctl" ]; then -- export NDCTL=./ndctl/ndctl --else -- echo "Couldn't find an ndctl binary" -- exit 1 -+if [ -z $NDCTL ]; then -+ if [ -f "../ndctl/ndctl" ] && [ -x "../ndctl/ndctl" ]; then -+ export NDCTL=../ndctl/ndctl -+ elif [ -f "./ndctl/ndctl" ] && [ -x "./ndctl/ndctl" ]; then -+ export NDCTL=./ndctl/ndctl -+ else -+ echo "Couldn't find an ndctl binary" -+ exit 1 -+ fi - fi - - # DAXCTL --# --if [ -f "../daxctl/daxctl" ] && [ -x "../daxctl/daxctl" ]; then -- export DAXCTL=../daxctl/daxctl --elif [ -f "./daxctl/daxctl" ] && [ -x "./daxctl/daxctl" ]; then -- export DAXCTL=./daxctl/daxctl --else -- echo "Couldn't find an daxctl binary" -- exit 1 -+if [ -z $DAXCTL ]; then -+ if [ -f "../daxctl/daxctl" ] && [ -x "../daxctl/daxctl" ]; then -+ export DAXCTL=../daxctl/daxctl -+ elif [ -f "./daxctl/daxctl" ] && [ -x "./daxctl/daxctl" ]; then -+ export DAXCTL=./daxctl/daxctl -+ else -+ echo "Couldn't find an daxctl binary" -+ exit 1 -+ fi - fi - -+if [ -z $TEST_PATH ]; then -+ export TEST_PATH=. -+fi - - # NFIT_TEST_BUS[01] - # -diff --git a/test/dax-pmd.c b/test/dax-pmd.c -index 7648e34..f840875 100644 ---- a/test/dax-pmd.c -+++ b/test/dax-pmd.c -@@ -24,7 +24,8 @@ - __func__, __LINE__, strerror(errno)) - #define faili(i) fprintf(stderr, "%s: failed at: %d: %d (%s)\n", \ - __func__, __LINE__, i, strerror(errno)) --#define TEST_FILE "test_dax_data" -+#define TEST_DIR "test_dax_mnt" -+#define TEST_FILE TEST_DIR "/test_dax_data" - - #define REGION_MEM_SIZE 4096*4 - #define REGION_PM_SIZE 4096*512 -@@ -171,8 +172,14 @@ int test_dax_directio(int dax_fd, unsigned long align, void *dax_addr, off_t off - } - rc = -ENXIO; - -+ rc = mkdir(TEST_DIR, 0600); -+ if (rc < 0 && errno != EEXIST) { -+ faili(i); -+ munmap(addr, 2 * align); -+ break; -+ } - fd2 = open(TEST_FILE, O_CREAT|O_TRUNC|O_DIRECT|O_RDWR, -- DEFFILEMODE); -+ 0600); - if (fd2 < 0) { - faili(i); - munmap(addr, 2*align); -diff --git a/test/dax.sh b/test/dax.sh -index bcdd4e9..bb9848b 100755 ---- a/test/dax.sh -+++ b/test/dax.sh -@@ -15,13 +15,13 @@ cleanup() { - else - rc=77 - fi -- rmdir $MNT -+ rm -rf $MNT - exit $rc - } - - run_test() { - rc=0 -- if ! trace-cmd record -e fs_dax:dax_pmd_fault_done ./dax-pmd $MNT/$FILE; then -+ if ! trace-cmd record -e fs_dax:dax_pmd_fault_done $TEST_PATH/dax-pmd $MNT/$FILE; then - rc=$? - if [ "$rc" -ne 77 ] && [ "$rc" -ne 0 ]; then - cleanup "$1" -@@ -104,7 +104,7 @@ set -e - mkdir -p $MNT - trap 'err $LINENO cleanup' ERR - --dev=$(./dax-dev) -+dev=$($TEST_PATH/dax-dev) - json=$($NDCTL list -N -n $dev) - eval $(json2var <<< "$json") - rc=1 -diff --git a/test/daxdev-errors.sh b/test/daxdev-errors.sh -index e13453d..7f79718 100755 ---- a/test/daxdev-errors.sh -+++ b/test/daxdev-errors.sh -@@ -62,8 +62,8 @@ read sector len < /sys/bus/nd/devices/$region/badblocks - echo "sector: $sector len: $len" - - # run the daxdev-errors test --test -x ./daxdev-errors --./daxdev-errors $busdev $region -+test -x $TEST_PATH/daxdev-errors -+$TEST_PATH/daxdev-errors $busdev $region - - # check badblocks, should be empty - if read sector len < /sys/bus/platform/devices/nfit_test.0/$busdev/$region/badblocks; then -diff --git a/test/device-dax-fio.sh b/test/device-dax-fio.sh -index f57a9d2..c43ac05 100755 ---- a/test/device-dax-fio.sh -+++ b/test/device-dax-fio.sh -@@ -18,7 +18,7 @@ if ! fio --enghelp | grep -q "dev-dax"; then - exit 77 - fi - --dev=$(./dax-dev) -+dev=$($TEST_PATH/dax-dev) - for align in 4k 2m 1g - do - json=$($NDCTL create-namespace -m devdax -a $align -f -e $dev) -diff --git a/test/dm.sh b/test/dm.sh -index 4656e5b..b780a65 100755 ---- a/test/dm.sh -+++ b/test/dm.sh -@@ -8,7 +8,7 @@ SKIP=77 - FAIL=1 - SUCCESS=0 - --. ./common -+. $(dirname $0)/common - - MNT=test_dax_mnt - TEST_DM_PMEM=/dev/mapper/test_pmem -@@ -30,7 +30,7 @@ cleanup() { - if [ -L $TEST_DM_PMEM ]; then - dmsetup remove $TEST_DM_PMEM - fi -- rmdir $MNT -+ rm -rf $MNT - # opportunistic cleanup, not fatal if these fail - namespaces=$($NDCTL list -N | jq -r ".[] | select(.name==\"$NAME\") | .dev") - for i in $namespaces -diff --git a/test/inject-smart.sh b/test/inject-smart.sh -index 4ca83b8..8b91360 100755 ---- a/test/inject-smart.sh -+++ b/test/inject-smart.sh -@@ -170,7 +170,7 @@ check_prereq "jq" - modprobe nfit_test - rc=1 - --jlist=$(./list-smart-dimm -b $bus) -+jlist=$($TEST_PATH/list-smart-dimm -b $bus) - dimm="$(jq '.[]."dev"?, ."dev"?' <<< $jlist | sort | head -1 | xargs)" - test -n "$dimm" - -diff --git a/test/mmap.sh b/test/mmap.sh -index 50a1d34..760257d 100755 ---- a/test/mmap.sh -+++ b/test/mmap.sh -@@ -7,7 +7,7 @@ - MNT=test_mmap_mnt - FILE=image - DEV="" --TEST=./mmap -+TEST=$TEST_PATH/mmap - rc=77 - - cleanup() { -@@ -17,7 +17,7 @@ cleanup() { - else - rc=77 - fi -- rmdir $MNT -+ rm -rf $MNT - exit $rc - } - -@@ -49,7 +49,7 @@ set -e - mkdir -p $MNT - trap 'err $LINENO cleanup' ERR - --dev=$(./dax-dev) -+dev=$($TEST_PATH/dax-dev) - json=$($NDCTL list -N -n $dev) - eval $(json2var <<< "$json") - DEV="/dev/${blockdev}" -diff --git a/test/monitor.sh b/test/monitor.sh -index 6aa4196..e58c908 100755 ---- a/test/monitor.sh -+++ b/test/monitor.sh -@@ -31,7 +31,7 @@ start_monitor() - set_smart_supported_bus() - { - smart_supported_bus=$NFIT_TEST_BUS0 -- monitor_dimms=$(./list-smart-dimm -b $smart_supported_bus | jq -r .[0].dev) -+ monitor_dimms=$($TEST_PATH/list-smart-dimm -b $smart_supported_bus | jq -r .[0].dev) - if [ -z $monitor_dimms ]; then - smart_supported_bus=$NFIT_TEST_BUS1 - fi -@@ -39,14 +39,14 @@ set_smart_supported_bus() - - get_monitor_dimm() - { -- jlist=$(./list-smart-dimm -b $smart_supported_bus $1) -+ jlist=$($TEST_PATH/list-smart-dimm -b $smart_supported_bus $1) - monitor_dimms=$(jq '.[]."dev"?, ."dev"?' <<<$jlist | sort | uniq | xargs) - echo $monitor_dimms - } - - call_notify() - { -- ./smart-notify $smart_supported_bus -+ $TEST_PATH/smart-notify $smart_supported_bus - sync; sleep 3 - } - -diff --git a/test/pmem-errors.sh b/test/pmem-errors.sh -index 2065780..9a59c25 100755 ---- a/test/pmem-errors.sh -+++ b/test/pmem-errors.sh -@@ -10,14 +10,12 @@ rc=77 - - cleanup() - { -- rm -f $FILE -- rm -f $MNT/$FILE - if [ -n "$blockdev" ]; then - umount /dev/$blockdev - else - rc=77 - fi -- rmdir $MNT -+ rm -rf $MNT - } - - check_min_kver "4.7" || do_skip "may lack dax error handling" -@@ -82,8 +80,8 @@ echo $start_sect 8 > /sys/block/$blockdev/badblocks - dd if=$MNT/$FILE of=/dev/null iflag=direct bs=4096 count=1 && err $LINENO || true - - # run the dax-errors test --test -x ./dax-errors --./dax-errors $MNT/$FILE -+test -x $TEST_PATH/dax-errors -+$TEST_PATH/dax-errors $MNT/$FILE - - # TODO: disable this check till we have clear-on-write in the kernel - #if read sector len < /sys/block/$blockdev/badblocks; then -diff --git a/test/sub-section.sh b/test/sub-section.sh -index 92ae816..77b9633 100755 ---- a/test/sub-section.sh -+++ b/test/sub-section.sh -@@ -8,7 +8,7 @@ SKIP=77 - FAIL=1 - SUCCESS=0 - --. ./common -+. $(dirname $0)/common - - check_min_kver "5.3" || do_skip "may lack align sub-section hotplug support" - -@@ -30,7 +30,7 @@ cleanup() { - if mountpoint -q $MNT; then - umount $MNT - fi -- rmdir $MNT -+ rm -rf $MNT - # opportunistic cleanup, not fatal if these fail - namespaces=$($NDCTL list -N | jq -r ".[] | select(.name==\"$NAME\") | .dev") - for i in $namespaces -diff --git a/test/track-uuid.sh b/test/track-uuid.sh -index 3bacd2c..a967d0e 100755 ---- a/test/track-uuid.sh -+++ b/test/track-uuid.sh -@@ -5,7 +5,7 @@ - blockdev="" - rc=77 - --. ./common -+. $(dirname $0)/common - - set -e - trap 'err $LINENO' ERR --- -2.27.0 - diff --git a/SOURCES/0081-ndctl-Drop-executable-bit-for-bash-completion-script.patch b/SOURCES/0081-ndctl-Drop-executable-bit-for-bash-completion-script.patch deleted file mode 100644 index d062f20..0000000 --- a/SOURCES/0081-ndctl-Drop-executable-bit-for-bash-completion-script.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 7912cb0d19b5d17321439d118d41e57236b5484b Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:32:47 -0800 -Subject: [PATCH 081/217] ndctl: Drop executable bit for bash-completion script - -The rpm build process warns: - -*** WARNING: ./usr/share/bash-completion/completions/ndctl is executable but has no shebang, removing executable bit - -Clear the unnecessary executable bit since completion helpers are sourced, -not executed. - -Link: https://lore.kernel.org/r/164141836772.3990253.4996882214531720931.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - contrib/ndctl | 0 - 1 file changed, 0 insertions(+), 0 deletions(-) - mode change 100755 => 100644 contrib/ndctl - -diff --git a/contrib/ndctl b/contrib/ndctl -old mode 100755 -new mode 100644 --- -2.27.0 - diff --git a/SOURCES/0082-build-Add-meson-build-infrastructure.patch b/SOURCES/0082-build-Add-meson-build-infrastructure.patch deleted file mode 100644 index 72348d7..0000000 --- a/SOURCES/0082-build-Add-meson-build-infrastructure.patch +++ /dev/null @@ -1,1577 +0,0 @@ -From 4e5faa1726d22e8ef51e860d56f4300077a3e9ba Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:32:53 -0800 -Subject: [PATCH 082/217] build: Add meson build infrastructure - -Build times improve from 10s of seconds to sub-second builds especially -when ccache gets involved and the only change is a git version bump. Recall -that every time the version changes with autotools it does a reconfigure. -With meson only the objects that depend on the version string are rebuilt. -So the primary motivation is to make the ndctl project more enjoyable to -develop. - -Tools, libraries, documentation, and tests all seem to be working. The -remaining work is to redo the rpm build infrastructure, and validate that -installation is working as expected. - -Given the long standing momentum on the old build system it is still kept -functional for now. The only compatibility hack when moving from an -autotools build to a meson build is to delete the config.h files generated -by the old system in favor of the unified configuration header build from -the config.h.meson template. - -Link: https://lore.kernel.org/r/164141837329.3990253.11664056350173402543.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Vaibhav Jain -Tested-by: Alison Schofield -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .gitignore | 5 +- - Documentation/cxl/lib/meson.build | 79 +++++++++ - Documentation/cxl/meson.build | 84 +++++++++ - Documentation/daxctl/meson.build | 94 ++++++++++ - Documentation/ndctl/meson.build | 124 +++++++++++++ - clean_config.sh | 2 + - config.h.meson | 151 ++++++++++++++++ - contrib/meson.build | 28 +++ - cxl/lib/meson.build | 35 ++++ - cxl/meson.build | 25 +++ - daxctl/device.c | 1 + - daxctl/lib/meson.build | 44 +++++ - daxctl/meson.build | 35 ++++ - meson.build | 280 ++++++++++++++++++++++++++++++ - meson_options.txt | 25 +++ - ndctl/lib/meson.build | 48 +++++ - ndctl/meson.build | 82 +++++++++ - test/meson.build | 237 +++++++++++++++++++++++++ - tools/meson-vcs-tag.sh | 18 ++ - util/meson.build | 16 ++ - version.h.in | 2 + - 21 files changed, 1414 insertions(+), 1 deletion(-) - create mode 100644 Documentation/cxl/lib/meson.build - create mode 100644 Documentation/cxl/meson.build - create mode 100644 Documentation/daxctl/meson.build - create mode 100644 Documentation/ndctl/meson.build - create mode 100755 clean_config.sh - create mode 100644 config.h.meson - create mode 100644 contrib/meson.build - create mode 100644 cxl/lib/meson.build - create mode 100644 cxl/meson.build - create mode 100644 daxctl/lib/meson.build - create mode 100644 daxctl/meson.build - create mode 100644 meson.build - create mode 100644 meson_options.txt - create mode 100644 ndctl/lib/meson.build - create mode 100644 ndctl/meson.build - create mode 100644 test/meson.build - create mode 100755 tools/meson-vcs-tag.sh - create mode 100644 util/meson.build - create mode 100644 version.h.in - -diff -up ndctl-71.1/.gitignore.orig ndctl-71.1/.gitignore ---- ndctl-71.1/.gitignore.orig 2022-10-07 17:29:42.924688214 -0400 -+++ ndctl-71.1/.gitignore 2022-10-07 17:29:51.566717638 -0400 -@@ -9,7 +9,9 @@ Makefile.in - /aclocal.m4 - /autom4te.cache - /build-aux --/config.* -+/config.h -+/config.log -+/config.status - /configure - /libtool - /stamp-h1 -@@ -24,6 +26,7 @@ Documentation/ndctl/asciidoctor-extensio - Documentation/cxl/asciidoctor-extensions.rb - Documentation/cxl/lib/asciidoctor-extensions.rb - .dirstamp -+build/ - daxctl/config.h - daxctl/daxctl - daxctl/lib/libdaxctl.la -diff -up ndctl-71.1/Documentation/cxl/lib/meson.build.orig ndctl-71.1/Documentation/cxl/lib/meson.build ---- ndctl-71.1/Documentation/cxl/lib/meson.build.orig 2022-10-07 17:29:51.567717641 -0400 -+++ ndctl-71.1/Documentation/cxl/lib/meson.build 2022-10-07 17:29:51.567717641 -0400 -@@ -0,0 +1,79 @@ -+if get_option('asciidoctor').enabled() -+ asciidoc_conf = custom_target('asciidoctor-extensions.rb', -+ command : [ -+ 'sed', '-e', 's,@Utility@,Libcxl,g', '-e', 's,@utility@,cxl,g', '@INPUT@' -+ ], -+ input : '../../asciidoctor-extensions.rb.in', -+ output : 'asciidoctor-extensions.rb', -+ capture : true, -+ ) -+else -+ asciidoc_conf = custom_target('asciidoc.conf', -+ command : [ -+ 'sed', '-e', 's,UTILITY,libcxl,g', -+ ], -+ input : '../../asciidoc.conf.in', -+ output : 'asciidoc.conf', -+ capture : true, -+ ) -+endif -+ -+filedeps = [ -+ '../../copyright.txt', -+] -+ -+libcxl_manpages = [ -+ 'libcxl.txt', -+ 'cxl_new.txt', -+] -+ -+foreach man : libcxl_manpages -+ name = man.split('.')[0] -+ output = name + '.3' -+ output_xml = name + '.xml' -+ if get_option('asciidoctor').enabled() -+ custom_target(name, -+ command : [ -+ asciidoc, -+ '-b', 'manpage', '-d', 'manpage', '-acompat-mode', '-I', '@OUTDIR@', -+ '-rasciidoctor-extensions', '-amansource=libcxl', -+ '-amanmanual=libcxl Manual', -+ '-andctl_version=@0@'.format(meson.project_version()), -+ '-o', '@OUTPUT@', '@INPUT@' -+ ], -+ input : man, -+ output : output, -+ depend_files : filedeps, -+ depends : asciidoc_conf, -+ install : get_option('docs').enabled(), -+ install_dir : join_paths(get_option('mandir'), 'man3'), -+ ) -+ else -+ xml = custom_target(output_xml, -+ command : [ -+ asciidoc, -+ '-b', 'docbook', '-d', 'manpage', '-f', asciidoc_conf, '--unsafe', -+ '-andctl_version=@0@'.format(meson.project_version()), -+ '-o', '@OUTPUT@', '@INPUT@', -+ ], -+ input : man, -+ output : output_xml, -+ depend_files : filedeps, -+ depends : asciidoc_conf, -+ ) -+ -+ xsl = files('../../manpage-normal.xsl') -+ -+ custom_target(name, -+ command : [ -+ xmlto, '-o', '@OUTDIR@', '-m', xsl, 'man', '@INPUT@' -+ ], -+ depends : xml, -+ depend_files : xsl, -+ input : xml, -+ output : output, -+ install : get_option('docs').enabled(), -+ install_dir : join_paths(get_option('mandir'), 'man3'), -+ ) -+ endif -+endforeach -diff -up ndctl-71.1/Documentation/cxl/meson.build.orig ndctl-71.1/Documentation/cxl/meson.build ---- ndctl-71.1/Documentation/cxl/meson.build.orig 2022-10-07 17:29:51.568717645 -0400 -+++ ndctl-71.1/Documentation/cxl/meson.build 2022-10-07 17:29:51.568717645 -0400 -@@ -0,0 +1,84 @@ -+if get_option('asciidoctor').enabled() -+ asciidoc_conf = custom_target('asciidoctor-extensions.rb', -+ command : [ -+ 'sed', '-e', 's,@Utility@,Cxl,g', '-e', 's,@utility@,cxl,g', '@INPUT@' -+ ], -+ input : '../asciidoctor-extensions.rb.in', -+ output : 'asciidoctor-extensions.rb', -+ capture : true, -+ ) -+else -+ asciidoc_conf = custom_target('asciidoc.conf', -+ command : [ -+ 'sed', '-e', 's,UTILITY,cxl,g', -+ ], -+ input : '../asciidoc.conf.in', -+ output : 'asciidoc.conf', -+ capture : true, -+ ) -+endif -+ -+filedeps = [ -+ '../copyright.txt', -+] -+ -+cxl_manpages = [ -+ 'cxl.txt', -+ 'cxl-list.txt', -+ 'cxl-read-labels.txt', -+ 'cxl-write-labels.txt', -+ 'cxl-zero-labels.txt', -+] -+ -+foreach man : cxl_manpages -+ name = man.split('.')[0] -+ output = name + '.1' -+ output_xml = name + '.xml' -+ if get_option('asciidoctor').enabled() -+ custom_target(name, -+ command : [ -+ asciidoc, -+ '-b', 'manpage', '-d', 'manpage', '-acompat-mode', '-I', '@OUTDIR@', -+ '-rasciidoctor-extensions', '-amansource=cxl', -+ '-amanmanual=cxl Manual', -+ '-andctl_version=@0@'.format(meson.project_version()), -+ '-o', '@OUTPUT@', '@INPUT@' -+ ], -+ input : man, -+ output : output, -+ depend_files : filedeps, -+ depends : asciidoc_conf, -+ install : get_option('docs').enabled(), -+ install_dir : join_paths(get_option('mandir'), 'man1'), -+ ) -+ else -+ xml = custom_target(output_xml, -+ command : [ -+ asciidoc, -+ '-b', 'docbook', '-d', 'manpage', '-f', asciidoc_conf, '--unsafe', -+ '-andctl_version=@0@'.format(meson.project_version()), -+ '-o', '@OUTPUT@', '@INPUT@', -+ ], -+ input : man, -+ output : output_xml, -+ depend_files : filedeps, -+ depends : asciidoc_conf, -+ ) -+ -+ xsl = files('../manpage-normal.xsl') -+ -+ custom_target(name, -+ command : [ -+ xmlto, '-o', '@OUTDIR@', '-m', xsl, 'man', '@INPUT@' -+ ], -+ depends : xml, -+ depend_files : xsl, -+ input : xml, -+ output : output, -+ install : get_option('docs').enabled(), -+ install_dir : join_paths(get_option('mandir'), 'man1'), -+ ) -+ endif -+endforeach -+ -+subdir('lib') -diff -up ndctl-71.1/Documentation/daxctl/meson.build.orig ndctl-71.1/Documentation/daxctl/meson.build ---- ndctl-71.1/Documentation/daxctl/meson.build.orig 2022-10-07 17:29:51.569717648 -0400 -+++ ndctl-71.1/Documentation/daxctl/meson.build 2022-10-07 17:29:51.568717645 -0400 -@@ -0,0 +1,94 @@ -+if get_option('asciidoctor').enabled() -+ asciidoc_conf = custom_target('asciidoctor-extensions.rb', -+ command : [ -+ 'sed', '-e', 's,@Utility@,Daxctl,g', '-e', 's,@utility@,daxctl,g', '@INPUT@' -+ ], -+ input : '../asciidoctor-extensions.rb.in', -+ output : 'asciidoctor-extensions.rb', -+ capture : true, -+ ) -+else -+ asciidoc_conf = custom_target('asciidoc.conf', -+ command : [ -+ 'sed', '-e', 's,UTILITY,daxctl,g', -+ ], -+ input : '../asciidoc.conf.in', -+ output : 'asciidoc.conf', -+ capture : true, -+ ) -+endif -+ -+filedeps = [ -+ 'human-option.txt', -+ '../copyright.txt', -+] -+ -+daxctl_manpages = [ -+ 'daxctl.txt', -+ 'daxctl-list.txt', -+ 'daxctl-migrate-device-model.txt', -+ 'daxctl-reconfigure-device.txt', -+ 'daxctl-online-memory.txt', -+ 'daxctl-offline-memory.txt', -+ 'daxctl-disable-device.txt', -+ 'daxctl-enable-device.txt', -+ 'daxctl-create-device.txt', -+ 'daxctl-destroy-device.txt', -+] -+ -+foreach man : daxctl_manpages -+ name = man.split('.')[0] -+ output = name + '.1' -+ output_xml = name + '.xml' -+ if get_option('asciidoctor').enabled() -+ custom_target(name, -+ command : [ -+ asciidoc, -+ '-b', 'manpage', '-d', 'manpage', '-acompat-mode', '-I', '@OUTDIR@', -+ '-rasciidoctor-extensions', '-amansource=daxctl', -+ '-amanmanual=daxctl Manual', -+ '-adaxctl_confdir=@0@'.format(daxctlconf_dir), -+ '-adaxctl_conf=@0@'.format(daxctlconf), -+ '-andctl_keysdir=@0@'.format(ndctlkeys_dir), -+ '-andctl_version=@0@'.format(meson.project_version()), -+ '-o', '@OUTPUT@', '@INPUT@' -+ ], -+ input : man, -+ output : output, -+ depend_files : filedeps, -+ depends : asciidoc_conf, -+ install : get_option('docs').enabled(), -+ install_dir : join_paths(get_option('mandir'), 'man1'), -+ ) -+ else -+ xml = custom_target(output_xml, -+ command : [ -+ asciidoc, -+ '-b', 'docbook', '-d', 'manpage', '-f', asciidoc_conf, '--unsafe', -+ '-adaxctl_confdir=@0@'.format(daxctlconf_dir), -+ '-adaxctl_conf=@0@'.format(daxctlconf), -+ '-andctl_keysdir=@0@'.format(ndctlkeys_dir), -+ '-andctl_version=@0@'.format(meson.project_version()), -+ '-o', '@OUTPUT@', '@INPUT@', -+ ], -+ input : man, -+ output : output_xml, -+ depend_files : filedeps, -+ depends : asciidoc_conf, -+ ) -+ -+ xsl = files('../manpage-normal.xsl') -+ -+ custom_target(name, -+ command : [ -+ xmlto, '-o', '@OUTDIR@', '-m', xsl, 'man', '@INPUT@' -+ ], -+ depends : xml, -+ depend_files : xsl, -+ input : xml, -+ output : output, -+ install : get_option('docs').enabled(), -+ install_dir : join_paths(get_option('mandir'), 'man1'), -+ ) -+ endif -+endforeach -diff -up ndctl-71.1/Documentation/ndctl/meson.build.orig ndctl-71.1/Documentation/ndctl/meson.build ---- ndctl-71.1/Documentation/ndctl/meson.build.orig 2022-10-07 17:29:51.570717651 -0400 -+++ ndctl-71.1/Documentation/ndctl/meson.build 2022-10-07 17:29:51.570717651 -0400 -@@ -0,0 +1,124 @@ -+if get_option('asciidoctor').enabled() -+ asciidoc_conf = custom_target('asciidoctor-extensions.rb', -+ command : [ -+ 'sed', '-e', 's,@Utility@,Ndctl,g', '-e', 's,@utility@,ndctl,g', '@INPUT@' -+ ], -+ input : '../asciidoctor-extensions.rb.in', -+ output : 'asciidoctor-extensions.rb', -+ capture : true, -+ ) -+else -+ asciidoc_conf = custom_target('asciidoc.conf', -+ command : [ -+ 'sed', '-e', 's,UTILITY,ndctl,g', -+ ], -+ input : '../asciidoc.conf.in', -+ output : 'asciidoc.conf', -+ capture : true, -+ ) -+endif -+ -+filedeps = [ -+ '../copyright.txt', -+ 'region-description.txt', -+ 'xable-region-options.txt', -+ 'dimm-description.txt', -+ 'xable-dimm-options.txt', -+ 'xable-namespace-options.txt', -+ 'ars-description.txt', -+ 'labels-description.txt', -+ 'labels-options.txt', -+] -+ -+ndctl_manpages = [ -+ 'ndctl.txt', -+ 'ndctl-wait-scrub.txt', -+ 'ndctl-start-scrub.txt', -+ 'ndctl-zero-labels.txt', -+ 'ndctl-read-labels.txt', -+ 'ndctl-write-labels.txt', -+ 'ndctl-init-labels.txt', -+ 'ndctl-check-labels.txt', -+ 'ndctl-enable-region.txt', -+ 'ndctl-disable-region.txt', -+ 'ndctl-enable-dimm.txt', -+ 'ndctl-disable-dimm.txt', -+ 'ndctl-enable-namespace.txt', -+ 'ndctl-disable-namespace.txt', -+ 'ndctl-create-namespace.txt', -+ 'ndctl-destroy-namespace.txt', -+ 'ndctl-check-namespace.txt', -+ 'ndctl-clear-errors.txt', -+ 'ndctl-inject-error.txt', -+ 'ndctl-inject-smart.txt', -+ 'ndctl-update-firmware.txt', -+ 'ndctl-list.txt', -+ 'ndctl-monitor.txt', -+ 'ndctl-setup-passphrase.txt', -+ 'ndctl-update-passphrase.txt', -+ 'ndctl-remove-passphrase.txt', -+ 'ndctl-freeze-security.txt', -+ 'ndctl-sanitize-dimm.txt', -+ 'ndctl-load-keys.txt', -+ 'ndctl-wait-overwrite.txt', -+ 'ndctl-read-infoblock.txt', -+ 'ndctl-write-infoblock.txt', -+ 'ndctl-activate-firmware.txt', -+] -+ -+foreach man : ndctl_manpages -+ name = man.split('.')[0] -+ output = name + '.1' -+ output_xml = name + '.xml' -+ if get_option('asciidoctor').enabled() -+ custom_target(name, -+ command : [ -+ asciidoc, -+ '-b', 'manpage', '-d', 'manpage', '-acompat-mode', '-I', '@OUTDIR@', -+ '-rasciidoctor-extensions', '-amansource=ndctl', -+ '-amanmanual=ndctl Manual', -+ '-andctl_confdir=@0@'.format(ndctlconf_dir), -+ '-andctl_monitorconf=@0@'.format(ndctlconf), -+ '-andctl_keysdir=@0@'.format(ndctlkeys_dir), -+ '-andctl_version=@0@'.format(meson.project_version()), -+ '-o', '@OUTPUT@', '@INPUT@' -+ ], -+ input : man, -+ output : output, -+ depend_files : filedeps, -+ depends : asciidoc_conf, -+ install : get_option('docs').enabled(), -+ install_dir : join_paths(get_option('mandir'), 'man1'), -+ ) -+ else -+ xml = custom_target(output_xml, -+ command : [ -+ asciidoc, -+ '-b', 'docbook', '-d', 'manpage', '-f', asciidoc_conf, '--unsafe', -+ '-andctl_version=@0@'.format(meson.project_version()), -+ '-andctl_confdir=@0@'.format(ndctlconf_dir), -+ '-andctl_monitorconf=@0@'.format(ndctlconf), -+ '-andctl_keysdir=@0@'.format(ndctlkeys_dir), -+ '-o', '@OUTPUT@', '@INPUT@', -+ ], -+ input : man, -+ output : output_xml, -+ depend_files : filedeps, -+ depends : asciidoc_conf, -+ ) -+ -+ xsl = files('../manpage-normal.xsl') -+ -+ custom_target(name, -+ command : [ -+ xmlto, '-o', '@OUTDIR@', '-m', xsl, 'man', '@INPUT@' -+ ], -+ depends : xml, -+ depend_files : xsl, -+ input : xml, -+ output : output, -+ install : get_option('docs').enabled(), -+ install_dir : join_paths(get_option('mandir'), 'man1'), -+ ) -+ endif -+endforeach -diff -up ndctl-71.1/clean_config.sh.orig ndctl-71.1/clean_config.sh ---- ndctl-71.1/clean_config.sh.orig 2022-10-07 17:29:51.570717651 -0400 -+++ ndctl-71.1/clean_config.sh 2022-10-07 17:29:51.570717651 -0400 -@@ -0,0 +1,2 @@ -+#!/bin/bash -+git ls-files -o --exclude build | grep config.h\$ | xargs rm -diff -up ndctl-71.1/config.h.meson.orig ndctl-71.1/config.h.meson ---- ndctl-71.1/config.h.meson.orig 2022-10-07 17:29:51.570717651 -0400 -+++ ndctl-71.1/config.h.meson 2022-10-07 17:29:51.570717651 -0400 -@@ -0,0 +1,151 @@ -+/* Debug messages. */ -+#mesondefine ENABLE_DEBUG -+ -+/* destructive functional tests support */ -+#mesondefine ENABLE_DESTRUCTIVE -+ -+/* Documentation / man pages. */ -+#mesondefine ENABLE_DOCS -+ -+/* Enable keyutils support */ -+#mesondefine ENABLE_KEYUTILS -+ -+/* System logging. */ -+#mesondefine ENABLE_LOGGING -+ -+/* ndctl test poison support */ -+#mesondefine ENABLE_POISON -+ -+/* ndctl test support */ -+#mesondefine ENABLE_TEST -+ -+/* Define to 1 if big-endian-arch */ -+#mesondefine HAVE_BIG_ENDIAN -+ -+/* Define to 1 if you have the declaration of `BUS_MCEERR_AR', and to 0 if you -+ don't. */ -+#mesondefine HAVE_DECL_BUS_MCEERR_AR -+ -+/* Define to 1 if you have the declaration of `MAP_SHARED_VALIDATE', and to 0 -+ if you don't. */ -+#mesondefine HAVE_DECL_MAP_SHARED_VALIDATE -+ -+/* Define to 1 if you have the declaration of `MAP_SYNC', and to 0 if you -+ don't. */ -+#mesondefine HAVE_DECL_MAP_SYNC -+ -+/* Define to 1 if you have the header file. */ -+#mesondefine HAVE_DLFCN_H -+ -+/* Define to 1 if you have the header file. */ -+#mesondefine HAVE_INTTYPES_H -+ -+/* Define to 1 if you have the header file. */ -+#mesondefine HAVE_KEYUTILS_H -+ -+/* Define to 1 if you have the header file. */ -+#mesondefine HAVE_LINUX_VERSION_H -+ -+/* Define to 1 if little-endian-arch */ -+#mesondefine HAVE_LITTLE_ENDIAN -+ -+/* Define to 1 if you have the header file. */ -+#mesondefine HAVE_MEMORY_H -+ -+/* Define to 1 if you have the `secure_getenv' function. */ -+#mesondefine HAVE_SECURE_GETENV -+ -+/* Define to 1 if you have statement expressions. */ -+#mesondefine HAVE_STATEMENT_EXPR -+ -+/* Define to 1 if you have the header file. */ -+#mesondefine HAVE_STDINT_H -+ -+/* Define to 1 if you have the header file. */ -+#mesondefine HAVE_STDLIB_H -+ -+/* Define to 1 if you have the header file. */ -+#mesondefine HAVE_STRINGS_H -+ -+/* Define to 1 if you have the header file. */ -+#mesondefine HAVE_STRING_H -+ -+/* Define to 1 if you have the header file. */ -+#mesondefine HAVE_SYS_STAT_H -+ -+/* Define to 1 if you have the header file. */ -+#mesondefine HAVE_SYS_TYPES_H -+ -+/* Define to 1 if typeof works with your compiler. */ -+#mesondefine HAVE_TYPEOF -+ -+/* Define to 1 if you have the header file. */ -+#mesondefine HAVE_UNISTD_H -+ -+/* Define to 1 if using libuuid */ -+#mesondefine HAVE_UUID -+ -+/* Define to 1 if you have the `__secure_getenv' function. */ -+#mesondefine HAVE___SECURE_GETENV -+ -+/* Define to the sub-directory where libtool stores uninstalled libraries. */ -+#mesondefine LT_OBJDIR -+ -+/* Name of package */ -+#mesondefine PACKAGE -+ -+/* Define to the address where bug reports for this package should be sent. */ -+#mesondefine PACKAGE_BUGREPORT -+ -+/* Define to the full name of this package. */ -+#mesondefine PACKAGE_NAME -+ -+/* Define to the full name and version of this package. */ -+#mesondefine PACKAGE_STRING -+ -+/* Define to the one symbol short name of this package. */ -+#mesondefine PACKAGE_TARNAME -+ -+/* Define to the home page for this package. */ -+#mesondefine PACKAGE_URL -+ -+/* Define to the version of this package. */ -+#mesondefine PACKAGE_VERSION -+ -+/* Define to 1 if you have the ANSI C header files. */ -+#mesondefine STDC_HEADERS -+ -+/* Version number of package */ -+#mesondefine VERSION -+ -+/* Number of bits in a file offset, on hosts where this is settable. */ -+#mesondefine _FILE_OFFSET_BITS -+ -+/* Define for large files, on AIX-style hosts. */ -+#mesondefine _LARGE_FILES -+ -+/* Define to 1 if on MINIX. */ -+#mesondefine _MINIX -+ -+/* Define to 2 if the system does not provide POSIX.1 features except with -+ this defined. */ -+#mesondefine _POSIX_1_SOURCE -+ -+/* Define to 1 if you need to in order for `stat' and other things to work. */ -+#mesondefine _POSIX_SOURCE -+ -+/* Define to __typeof__ if your compiler spells it that way. */ -+#mesondefine typeof -+ -+/* Define to enable GNU Source Extensions */ -+#mesondefine _GNU_SOURCE -+ -+/* Locations to install configuration files, key config, man pages, etc.. */ -+#mesondefine NDCTL_CONF_FILE -+#mesondefine NDCTL_CONF_DIR -+#mesondefine DAXCTL_CONF_DIR -+#mesondefine NDCTL_KEYS_DIR -+#mesondefine NDCTL_MAN_PATH -+#mesondefine DAXCTL_MODPROBE_DATA -+#mesondefine DAXCTL_MODPROBE_INSTALL -+#mesondefine PREFIX -diff -up ndctl-71.1/contrib/meson.build.orig ndctl-71.1/contrib/meson.build ---- ndctl-71.1/contrib/meson.build.orig 2022-10-07 17:29:51.571717655 -0400 -+++ ndctl-71.1/contrib/meson.build 2022-10-07 17:29:51.570717651 -0400 -@@ -0,0 +1,28 @@ -+bashcompletiondir = get_option('bashcompletiondir') -+if bashcompletiondir == '' -+ bash_completion = dependency('bash-completion', required : false) -+ if bash_completion.found() -+ bashcompletiondir = bash_completion.get_pkgconfig_variable('completionsdir') -+ else -+ bashcompletiondir = datadir / 'bash-completion/completions' -+ endif -+endif -+ -+if bashcompletiondir != 'no' -+ install_data('ndctl', install_dir : bashcompletiondir) -+ -+# TODO Switch to symlinks once 0.61.0 is more widely available -+# install_symlink('daxctl', -+# install_dir : bashcompletiondir, -+# pointing_to : 'ndctl' -+# ) -+# install_symlink('cxl', -+# install_dir : bashcompletiondir, -+# pointing_to : 'ndctl' -+# ) -+ install_data('ndctl', rename : 'daxctl', install_dir : bashcompletiondir) -+ install_data('ndctl', rename : 'cxl', install_dir : bashcompletiondir) -+endif -+ -+modprobedatadir = get_option('sysconfdir') + '/modprobe.d/' -+install_data('nvdimm-security.conf', install_dir : modprobedatadir) -diff -up ndctl-71.1/cxl/lib/meson.build.orig ndctl-71.1/cxl/lib/meson.build ---- ndctl-71.1/cxl/lib/meson.build.orig 2022-10-07 17:29:51.571717655 -0400 -+++ ndctl-71.1/cxl/lib/meson.build 2022-10-07 17:29:51.571717655 -0400 -@@ -0,0 +1,35 @@ -+libcxl_version = '@0@.@1@.@2@'.format( -+ LIBCXL_CURRENT - LIBCXL_AGE, -+ LIBCXL_REVISION, -+ LIBCXL_AGE) -+ -+mapfile = files('libcxl.sym') -+vflag = '-Wl,--version-script,@0@/@1@'.format(project_source_root, mapfile[0]) -+ -+cxl = library('cxl', -+ '../../util/sysfs.c', -+ '../../util/log.c', -+ '../../util/log.h', -+ 'libcxl.c', -+ include_directories : root_inc, -+ dependencies : [ -+ uuid, -+ kmod, -+ ], -+ version : libcxl_version, -+ install : true, -+ install_dir : rootlibdir, -+ link_args : vflag, -+ link_depends : mapfile, -+) -+cxl_dep = declare_dependency(link_with : cxl) -+ -+custom_target( -+ 'libcxl.pc', -+ command : pkgconfig_script + [ '@INPUT@' ], -+ input : 'libcxl.pc.in', -+ output : 'libcxl.pc', -+ capture : true, -+ install : true, -+ install_dir : pkgconfiglibdir, -+) -diff -up ndctl-71.1/cxl/meson.build.orig ndctl-71.1/cxl/meson.build ---- ndctl-71.1/cxl/meson.build.orig 2022-10-07 17:29:51.571717655 -0400 -+++ ndctl-71.1/cxl/meson.build 2022-10-07 17:29:51.571717655 -0400 -@@ -0,0 +1,25 @@ -+cxl_src = [ -+ 'cxl.c', -+ 'list.c', -+ 'memdev.c', -+ '../util/json.c', -+ 'json.c', -+ 'filter.c', -+] -+ -+cxl_tool = executable('cxl', -+ cxl_src, -+ include_directories : root_inc, -+ dependencies : [ -+ cxl_dep, -+ util_dep, -+ uuid, -+ kmod, -+ json, -+ versiondep, -+ ], -+ install : true, -+ install_dir : rootbindir, -+) -+ -+install_headers('libcxl.h', subdir : 'cxl') -diff -up ndctl-71.1/daxctl/device.c.orig ndctl-71.1/daxctl/device.c ---- ndctl-71.1/daxctl/device.c.orig 2022-10-07 17:29:42.909688163 -0400 -+++ ndctl-71.1/daxctl/device.c 2022-10-07 17:29:51.572717658 -0400 -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff -up ndctl-71.1/daxctl/lib/meson.build.orig ndctl-71.1/daxctl/lib/meson.build ---- ndctl-71.1/daxctl/lib/meson.build.orig 2022-10-07 17:29:51.573717662 -0400 -+++ ndctl-71.1/daxctl/lib/meson.build 2022-10-07 17:29:51.573717662 -0400 -@@ -0,0 +1,44 @@ -+libdaxctl_version = '@0@.@1@.@2@'.format( -+ LIBDAXCTL_CURRENT - LIBDAXCTL_AGE, -+ LIBDAXCTL_REVISION, -+ LIBDAXCTL_AGE, -+) -+ -+mapfile = files('libdaxctl.sym') -+vflag = '-Wl,--version-script,@0@/@1@'.format(project_source_root, mapfile[0]) -+ -+libdaxctl_src = [ -+ '../../util/iomem.c', -+ '../../util/sysfs.c', -+ '../../util/log.c', -+ 'libdaxctl.c', -+] -+ -+daxctl = library( -+ 'daxctl', -+ libdaxctl_src, -+ version : libdaxctl_version, -+ include_directories : root_inc, -+ dependencies : [ -+ uuid, -+ kmod, -+ ], -+ install : true, -+ install_dir : rootlibdir, -+ link_args : vflag, -+ link_depends : mapfile, -+) -+ -+daxctl_dep = declare_dependency(link_with : daxctl) -+ -+custom_target( -+ 'libdaxctl.pc', -+ command : pkgconfig_script + [ '@INPUT@' ], -+ input : 'libdaxctl.pc.in', -+ output : 'libdaxctl.pc', -+ capture : true, -+ install : true, -+ install_dir : pkgconfiglibdir, -+) -+ -+install_data('daxctl.conf', install_dir : datadir / 'daxctl') -diff -up ndctl-71.1/daxctl/meson.build.orig ndctl-71.1/daxctl/meson.build ---- ndctl-71.1/daxctl/meson.build.orig 2022-10-07 17:29:51.574717665 -0400 -+++ ndctl-71.1/daxctl/meson.build 2022-10-07 17:29:51.574717665 -0400 -@@ -0,0 +1,28 @@ -+daxctl_src = [ -+ 'daxctl.c', -+ 'acpi.c', -+ 'list.c', -+ 'migrate.c', -+ 'device.c', -+ '../util/json.c', -+ 'json.c', -+ 'filter.c', -+] -+ -+daxctl_tool = executable('daxctl', -+ daxctl_src, -+ include_directories : root_inc, -+ dependencies : [ -+ daxctl_dep, -+ ndctl_dep, -+ util_dep, -+ uuid, -+ kmod, -+ json, -+ versiondep, -+ ], -+ install : true, -+ install_dir : rootbindir, -+) -+ -+install_headers('libdaxctl.h', subdir : 'daxctl') -diff -up ndctl-71.1/meson.build.orig ndctl-71.1/meson.build ---- ndctl-71.1/meson.build.orig 2022-10-07 17:29:51.575717669 -0400 -+++ ndctl-71.1/meson.build 2022-10-07 17:33:21.562432608 -0400 -@@ -0,0 +1,279 @@ -+project('ndctl', 'c', -+ version : '72', -+ license : [ -+ 'GPL-2.0', -+ 'LGPL-2.1', -+ 'CC0-1.0', -+ 'MIT', -+ ], -+ default_options : [ -+ 'c_std=gnu99', -+ 'prefix=/usr', -+ 'sysconfdir=/etc', -+ 'localstatedir=/var', -+ ], -+) -+ -+# rootprefixdir and rootlibdir setup copied from systemd: -+rootprefixdir = get_option('rootprefix') -+rootprefix_default = '/usr' -+if rootprefixdir == '' -+ rootprefixdir = rootprefix_default -+endif -+rootbindir = join_paths(rootprefixdir, 'bin') -+ -+# join_paths ignores the preceding arguments if an absolute component is -+# encountered, so this should canonicalize various paths when they are -+# absolute or relative. -+prefixdir = get_option('prefix') -+if not prefixdir.startswith('/') -+ error('Prefix is not absolute: "@0@"'.format(prefixdir)) -+endif -+if prefixdir != rootprefixdir and rootprefixdir != '/' and not prefixdir.strip('/').startswith(rootprefixdir.strip('/') + '/') -+ error('Prefix is not below root prefix (now rootprefix=@0@ prefix=@1@)'.format( -+ rootprefixdir, prefixdir)) -+endif -+ -+libdir = join_paths(prefixdir, get_option('libdir')) -+rootlibdir = get_option('rootlibdir') -+if rootlibdir == '' -+ rootlibdir = join_paths(rootprefixdir, libdir.split('/')[-1]) -+endif -+datadir = prefixdir / get_option('datadir') -+includedir = prefixdir / get_option('includedir') -+ -+pkgconfiglibdir = get_option('pkgconfiglibdir') != '' ? get_option('pkgconfiglibdir') : libdir / 'pkgconfig' -+ -+datadir = prefixdir / get_option('datadir') -+includedir = prefixdir / get_option('includedir') -+sysconfdir = get_option('sysconfdir') -+ -+pkgconfig_script = ''' -+sed -e s,@VERSION@,@0@,g -+ -e s,@prefix@,@1@,g -+ -e s,@exec_prefix@,@1@,g -+ -e s,@libdir@,@2@,g -+ -e s,@includedir@,@3@,g -+'''.format(meson.project_version(), prefixdir, libdir, includedir).split() -+ -+cc_flags = [ -+ '-Wall', -+ '-Wchar-subscripts', -+ '-Wformat-security', -+ '-Wmissing-declarations', -+ '-Wmissing-prototypes', -+ '-Wnested-externs ', -+ '-Wshadow', -+ '-Wsign-compare', -+ '-Wstrict-prototypes', -+ '-Wtype-limits', -+ '-Wmaybe-uninitialized', -+ '-Wdeclaration-after-statement', -+ '-Wunused-result', -+ '-D_FORTIFY_SOURCE=2', -+ '-O2', -+] -+cc = meson.get_compiler('c') -+add_project_arguments(cc.get_supported_arguments(cc_flags), language : 'c') -+ -+project_source_root = meson.current_source_dir() -+ -+# Remove this after the conversion to meson has been completed -+# Cleanup the leftover config.h files to avoid conflicts with the meson -+# generated config.h -+git = find_program('git', required : false) -+if git.found() -+ run_command('clean_config.sh', -+ env : 'GIT_DIR=@0@/.git'.format(project_source_root), -+ ) -+endif -+ -+version_tag = get_option('version-tag') -+if version_tag != '' -+ vcs_data = configuration_data() -+ vcs_data.set('VCS_TAG', version_tag) -+ version_h = configure_file( -+ configuration : vcs_data, -+ input : 'version.h.in', -+ output : 'version.h' -+ ) -+else -+ vcs_tagger = [ -+ project_source_root + '/tools/meson-vcs-tag.sh', -+ project_source_root, -+ meson.project_version() -+ ] -+ -+ version_h = vcs_tag( -+ input : 'version.h.in', -+ output : 'version.h', -+ command: vcs_tagger -+ ) -+endif -+ -+versiondep = declare_dependency( -+ compile_args: ['-include', 'version.h'], -+ sources: version_h -+) -+ -+kmod = dependency('libkmod') -+libudev = dependency('libudev') -+uuid = dependency('uuid') -+json = dependency('json-c') -+if get_option('docs').enabled() -+ if get_option('asciidoctor').enabled() -+ asciidoc = find_program('asciidoctor', required : true) -+ else -+ asciidoc = find_program('asciidoc', required : true) -+ xmlto = find_program('xmlto', required : true) -+ endif -+endif -+ -+if get_option('systemd').enabled() -+ systemd = dependency('systemd', required : true) -+ systemdunitdir = systemd.get_pkgconfig_variable('systemdsystemunitdir') -+ udev = dependency('udev', required : true) -+ udevdir = udev.get_pkgconfig_variable('udevdir') -+ udevrulesdir = udevdir / 'rules.d' -+endif -+ -+cc = meson.get_compiler('c') -+ -+# keyutils and iniparser lack pkgconfig -+keyutils = cc.find_library('keyutils', required : get_option('keyutils')) -+ -+conf = configuration_data() -+check_headers = [ -+ ['HAVE_DLFCN_H', 'dlfcn.h'], -+ ['HAVE_INTTYPES_H', 'inttypes.h'], -+ ['HAVE_KEYUTILS_H', 'keyutils.h'], -+ ['HAVE_LINUX_VERSION_H', 'linux/version.h'], -+ ['HAVE_MEMORY_H', 'memory.h'], -+ ['HAVE_STDINT_H', 'stdint.h'], -+ ['HAVE_STDLIB_H', 'stdlib.h'], -+ ['HAVE_STRINGS_H', 'strings.h'], -+ ['HAVE_STRING_H', 'string.h'], -+ ['HAVE_SYS_STAT_H', 'sys/stat.h'], -+ ['HAVE_SYS_TYPES_H', 'sys/types.h'], -+ ['HAVE_UNISTD_H', 'unistd.h'], -+] -+ -+foreach h : check_headers -+ if cc.has_header(h.get(1)) -+ conf.set(h.get(0), 1) -+ endif -+endforeach -+ -+map_sync_symbols = [ -+ [ 'signal.h', 'BUS_MCEERR_AR' ], -+ [ 'linux/mman.h', 'MAP_SHARED_VALIDATE' ], -+ [ 'linux/mman.h', 'MAP_SYNC' ], -+] -+ -+count = 0 -+foreach symbol : map_sync_symbols -+ if cc.has_header_symbol(symbol[0], symbol[1]) -+ conf.set('HAVE_DECL_@0@'.format(symbol[1].to_upper()), 1) -+ count = count + 1 -+ endif -+endforeach -+ -+poison_enabled = false -+if get_option('poison').enabled() and count == 3 -+ poison_enabled = true -+endif -+ -+conf.set('ENABLE_POISON', poison_enabled) -+conf.set('ENABLE_KEYUTILS', get_option('keyutils').enabled()) -+conf.set('ENABLE_TEST', get_option('test').enabled()) -+conf.set('ENABLE_DESTRUCTIVE', get_option('destructive').enabled()) -+conf.set('ENABLE_LOGGING', get_option('logging').enabled()) -+conf.set('ENABLE_DEBUG', get_option('dbg').enabled()) -+ -+typeof = cc.run(''' -+ int main() { -+ struct { -+ char a[16]; -+ } x; -+ typeof(x) y; -+ -+ return sizeof(x) == sizeof(y); -+ } -+ ''' -+) -+ -+if typeof.compiled() and typeof.returncode() == 1 -+ conf.set('HAVE_TYPEOF', 1) -+ conf.set('HAVE_STATEMENT_EXPR', 1) -+endif -+ -+if target_machine.endian() == 'big' -+ conf.set('HAVE_BIG_ENDIAN', 1) -+else -+ conf.set('HAVE_LITTLE_ENDIAN', 1) -+endif -+ -+conf.set('_GNU_SOURCE', true) -+conf.set_quoted('PREFIX', get_option('prefix')) -+conf.set_quoted('NDCTL_MAN_PATH', get_option('mandir')) -+ -+foreach ident : ['secure_getenv', '__secure_getenv'] -+ conf.set10('HAVE_' + ident.to_upper(), cc.has_function(ident)) -+endforeach -+ -+ -+ndctlconf_dir = sysconfdir / 'ndctl' -+ndctlconf = ndctlconf_dir / 'monitor.conf' -+conf.set_quoted('NDCTL_CONF_FILE', ndctlconf) -+conf.set_quoted('NDCTL_CONF_DIR', ndctlconf_dir) -+ -+ndctlkeys_dir = sysconfdir / 'ndctl' / 'keys' -+conf.set_quoted('NDCTL_KEYS_DIR', ndctlkeys_dir) -+ -+daxctlconf_dir = sysconfdir / 'daxctl.conf.d' -+daxctlconf = daxctlconf_dir / 'dax.conf' -+conf.set_quoted('DAXCTL_CONF_DIR', daxctlconf_dir) -+ -+conf.set_quoted('DAXCTL_MODPROBE_DATA', datadir / 'daxctl/daxctl.conf') -+conf.set_quoted('DAXCTL_MODPROBE_INSTALL', sysconfdir / 'modprobe.d/daxctl.conf') -+ -+config_h = configure_file( -+ input : 'config.h.meson', -+ output : 'config.h', -+ configuration : conf -+) -+add_project_arguments('-include', 'config.h', language : 'c') -+ -+LIBNDCTL_CURRENT=25 -+LIBNDCTL_REVISION=1 -+LIBNDCTL_AGE=19 -+ -+LIBDAXCTL_CURRENT=6 -+LIBDAXCTL_REVISION=0 -+LIBDAXCTL_AGE=5 -+ -+LIBCXL_CURRENT=1 -+LIBCXL_REVISION=0 -+LIBCXL_AGE=0 -+ -+root_inc = include_directories(['.', 'ndctl', ]) -+ -+ccan = static_library('ccan', -+ [ 'ccan/str/str.c', 'ccan/list/list.c' ], -+) -+ccan_dep = declare_dependency(link_with : ccan) -+ -+subdir('daxctl/lib') -+subdir('ndctl/lib') -+subdir('cxl/lib') -+subdir('util') -+subdir('ndctl') -+subdir('daxctl') -+subdir('cxl') -+if get_option('docs').enabled() -+ subdir('Documentation/ndctl') -+ subdir('Documentation/daxctl') -+ subdir('Documentation/cxl') -+endif -+subdir('test') -+subdir('contrib') -diff -up ndctl-71.1/meson_options.txt.orig ndctl-71.1/meson_options.txt ---- ndctl-71.1/meson_options.txt.orig 2022-10-07 17:29:51.575717669 -0400 -+++ ndctl-71.1/meson_options.txt 2022-10-07 17:29:51.575717669 -0400 -@@ -0,0 +1,25 @@ -+option('version-tag', type : 'string', -+ description : 'override the git version string') -+option('docs', type : 'feature', value : 'enabled') -+option('asciidoctor', type : 'feature', value : 'disabled') -+option('systemd', type : 'feature', value : 'enabled') -+option('keyutils', type : 'feature', value : 'enabled', -+ description : 'enable nvdimm device passphrase management') -+option('test', type : 'feature', value : 'disabled', -+ description : 'enable shipping tests in ndctl') -+option('destructive', type : 'feature', value : 'disabled', -+ description : 'enable tests that may clobber live system resources') -+option('poison', type : 'feature', value : 'enabled', -+ description : 'enable tests that inject poison / memory-failure') -+option('logging', type : 'feature', value : 'enabled', -+ description : 'enable log infrastructure') -+option('dbg', type : 'feature', value : 'enabled', -+ description : 'enable dbg messages') -+option('rootprefix', type : 'string', -+ description : '''override the root prefix [default '/' if split-usr and '/usr' otherwise]''') -+option('rootlibdir', type : 'string', -+ description : '''[/usr]/lib/x86_64-linux-gnu or such''') -+option('pkgconfiglibdir', type : 'string', value : '', -+ description : 'directory for standard pkg-config files') -+option('bashcompletiondir', type : 'string', -+ description : '''${datadir}/bash-completion/completions''') -diff -up ndctl-71.1/ndctl/lib/meson.build.orig ndctl-71.1/ndctl/lib/meson.build ---- ndctl-71.1/ndctl/lib/meson.build.orig 2022-10-07 17:29:51.576717672 -0400 -+++ ndctl-71.1/ndctl/lib/meson.build 2022-10-07 17:29:51.576717672 -0400 -@@ -0,0 +1,48 @@ -+libndctl_version = '@0@.@1@.@2@'.format( -+ LIBNDCTL_CURRENT - LIBNDCTL_AGE, -+ LIBNDCTL_REVISION, -+ LIBNDCTL_AGE) -+ -+mapfile = files('libndctl.sym') -+vflag = '-Wl,--version-script,@0@/@1@'.format(project_source_root, mapfile[0]) -+ -+ndctl = library( -+ 'ndctl', -+ '../../util/log.c', -+ '../../util/sysfs.c', -+ 'dimm.c', -+ 'inject.c', -+ 'nfit.c', -+ 'smart.c', -+ 'intel.c', -+ 'hpe1.c', -+ 'msft.c', -+ 'hyperv.c', -+ 'papr.c', -+ 'ars.c', -+ 'firmware.c', -+ 'libndctl.c', -+ dependencies : [ -+ daxctl_dep, -+ libudev, -+ uuid, -+ kmod, -+ ], -+ include_directories : root_inc, -+ version : libndctl_version, -+ install : true, -+ install_dir : rootlibdir, -+ link_args : vflag, -+ link_depends : mapfile, -+) -+ndctl_dep = declare_dependency(link_with : ndctl) -+ -+custom_target( -+ 'libndctl.pc', -+ command : pkgconfig_script + [ '@INPUT@' ], -+ input : 'libndctl.pc.in', -+ output : 'libndctl.pc', -+ capture : true, -+ install : true, -+ install_dir : pkgconfiglibdir, -+) -diff -up ndctl-71.1/ndctl/meson.build.orig ndctl-71.1/ndctl/meson.build ---- ndctl-71.1/ndctl/meson.build.orig 2022-10-07 17:29:51.576717672 -0400 -+++ ndctl-71.1/ndctl/meson.build 2022-10-07 17:29:51.576717672 -0400 -@@ -0,0 +1,80 @@ -+ndctl_src = [ -+ 'ndctl.c', -+ 'bus.c', -+ 'create-nfit.c', -+ 'namespace.c', -+ 'check.c', -+ 'region.c', -+ 'dimm.c', -+ '../util/log.c', -+ '../daxctl/filter.c', -+ 'filter.c', -+ 'list.c', -+ '../util/json.c', -+ '../daxctl/json.c', -+ 'json.c', -+ 'json-smart.c', -+ 'inject-error.c', -+ 'inject-smart.c', -+ 'monitor.c', -+] -+ -+deps = [ -+ util_dep, -+ ndctl_dep, -+ daxctl_dep, -+ cxl_dep, -+ uuid, -+ kmod, -+ json, -+ versiondep, -+] -+ -+if get_option('keyutils').enabled() -+ ndctl_src += [ -+ 'keys.c', -+ 'load-keys.c', -+ ] -+ deps += keyutils -+endif -+ -+if get_option('test').enabled() -+ ndctl_src += [ -+ '../test/libndctl.c', -+ '../test/dsm-fail.c', -+ '../util/sysfs.c', -+ '../test/core.c', -+ 'test.c', -+] -+endif -+ -+if get_option('destructive').enabled() -+ if get_option('test').disabled() -+ error('\'-D=destructive=enabled\' requires \'-Dtest=enabled\'\n') -+ endif -+ ndctl_src += [ -+ '../test/pmem_namespaces.c', -+ 'bat.c', -+ ] -+endif -+ -+if get_option('systemd').enabled() -+ install_data('ndctl-monitor.service', install_dir : systemdunitdir) -+endif -+install_data('monitor.conf', install_dir : ndctlconf_dir) -+install_data('keys.readme', install_dir : ndctlkeys_dir) -+ -+ndctl_tool = executable('ndctl', ndctl_src, -+ dependencies : deps, -+ install : true, -+ install_dir : rootbindir, -+ include_directories : root_inc, -+) -+ -+install_headers( -+ [ -+ 'libndctl.h', -+ 'ndctl.h' -+ ], -+ subdir : 'ndctl' -+) -diff -up ndctl-71.1/test/meson.build.orig ndctl-71.1/test/meson.build ---- ndctl-71.1/test/meson.build.orig 2022-10-07 17:29:51.577717675 -0400 -+++ ndctl-71.1/test/meson.build 2022-10-07 17:29:51.577717675 -0400 -@@ -0,0 +1,237 @@ -+testcore = [ -+ 'core.c', -+ '../util/log.c', -+ '../util/sysfs.c', -+] -+ -+libndctl_deps = [ -+ ndctl_dep, -+ daxctl_dep, -+ uuid, -+ kmod, -+] -+ -+ndctl_deps = libndctl_deps + [ -+ json, -+ util_dep, -+ versiondep, -+] -+ -+libndctl = executable('libndctl', testcore + [ 'libndctl.c'], -+ dependencies : libndctl_deps, -+ include_directories : root_inc, -+) -+ -+namespace_core = [ -+ '../ndctl/namespace.c', -+ '../ndctl/filter.c', -+ '../ndctl/check.c', -+ '../util/json.c', -+ '../ndctl/json.c', -+ '../daxctl/filter.c', -+ '../daxctl/json.c', -+] -+ -+dsm_fail = executable('dsm-fail', testcore + namespace_core + [ 'dsm-fail.c' ], -+ dependencies : ndctl_deps, -+ include_directories : root_inc, -+) -+ -+hugetlb_src = testcore + [ 'hugetlb.c', 'dax-pmd.c' ] -+if poison_enabled -+ hugetlb_src += [ 'dax-poison.c' ] -+endif -+hugetlb = executable('hugetlb', hugetlb_src, -+ dependencies : libndctl_deps, -+ include_directories : root_inc, -+) -+ -+ack_shutdown_count = executable('ack-shutdown-count-set', -+ testcore + [ 'ack-shutdown-count-set.c' ], -+ dependencies : libndctl_deps, -+ include_directories : root_inc, -+) -+ -+dax_errors = executable('dax-errors', -+ 'dax-errors.c', -+) -+ -+smart_notify = executable('smart-notify', 'smart-notify.c', -+ dependencies : libndctl_deps, -+ include_directories : root_inc, -+) -+ -+smart_listen = executable('smart-listen', 'smart-listen.c', -+ dependencies : libndctl_deps, -+ include_directories : root_inc, -+) -+ -+daxdev_errors = executable('daxdev-errors', [ -+ 'daxdev-errors.c', -+ '../util/log.c', -+ '../util/sysfs.c', -+ ], -+ dependencies : libndctl_deps, -+ include_directories : root_inc, -+) -+ -+list_smart_dimm = executable('list-smart-dimm', [ -+ 'list-smart-dimm.c', -+ '../ndctl/filter.c', -+ '../util/json.c', -+ '../ndctl/json.c', -+ '../daxctl/json.c', -+ '../daxctl/filter.c', -+ ], -+ dependencies : ndctl_deps, -+ include_directories : root_inc, -+) -+ -+pmem_ns = executable('pmem-ns', testcore + [ 'pmem_namespaces.c' ], -+ dependencies : libndctl_deps, -+ include_directories : root_inc, -+) -+ -+dax_dev = executable('dax-dev', testcore + [ 'dax-dev.c' ], -+ dependencies : libndctl_deps, -+ include_directories : root_inc, -+) -+ -+dax_pmd_src = testcore + [ 'dax-pmd.c' ] -+if poison_enabled -+ dax_pmd_src += [ 'dax-poison.c' ] -+endif -+ -+dax_pmd = executable('dax-pmd', dax_pmd_src, -+ dependencies : libndctl_deps, -+ include_directories : root_inc, -+) -+ -+device_dax_src = testcore + namespace_core + [ -+ 'device-dax.c', -+ 'dax-dev.c', -+ 'dax-pmd.c', -+] -+ -+if poison_enabled -+ device_dax_src += 'dax-poison.c' -+endif -+ -+device_dax = executable('device-dax', device_dax_src, -+ dependencies : ndctl_deps, -+ include_directories : root_inc, -+) -+ -+revoke_devmem = executable('revoke_devmem', testcore + [ -+ 'revoke-devmem.c', -+ 'dax-dev.c', -+ ], -+ dependencies : libndctl_deps, -+ include_directories : root_inc, -+) -+ -+mmap = executable('mmap', 'mmap.c',) -+ -+create = find_program('create.sh') -+clear = find_program('clear.sh') -+pmem_errors = find_program('pmem-errors.sh') -+daxdev_errors_sh = find_program('daxdev-errors.sh') -+multi_dax = find_program('multi-dax.sh') -+btt_check = find_program('btt-check.sh') -+label_compat = find_program('label-compat.sh') -+sector_mode = find_program('sector-mode.sh') -+inject_error = find_program('inject-error.sh') -+btt_errors = find_program('btt-errors.sh') -+btt_pad_compat = find_program('btt-pad-compat.sh') -+firmware_update = find_program('firmware-update.sh') -+rescan_partitions = find_program('rescan-partitions.sh') -+inject_smart = find_program('inject-smart.sh') -+monitor = find_program('monitor.sh') -+max_extent = find_program('max_available_extent_ns.sh') -+pfn_meta_errors = find_program('pfn-meta-errors.sh') -+track_uuid = find_program('track-uuid.sh') -+ -+tests = [ -+ [ 'libndctl', libndctl ], -+ [ 'dsm-fail', dsm_fail ], -+ [ 'create.sh', create ], -+ [ 'clear.sh', clear ], -+ [ 'pmem-errors.sh', pmem_errors ], -+ [ 'daxdev-errors.sh', daxdev_errors_sh ], -+ [ 'multi-dax.sh', multi_dax ], -+ [ 'btt-check.sh', btt_check ], -+ [ 'label-compat.sh', label_compat ], -+ [ 'sector-mode.sh', sector_mode ], -+ [ 'inject-error.sh', inject_error ], -+ [ 'btt-errors.sh', btt_errors ], -+ [ 'hugetlb', hugetlb ], -+ [ 'btt-pad-compat.sh', btt_pad_compat ], -+ [ 'firmware-update.sh', firmware_update ], -+ [ 'ack-shutdown-count-set', ack_shutdown_count ], -+ [ 'rescan-partitions.sh', rescan_partitions ], -+ [ 'inject-smart.sh', inject_smart ], -+ [ 'monitor.sh', monitor ], -+ [ 'max_extent_ns', max_extent ], -+ [ 'pfn-meta-errors.sh', pfn_meta_errors ], -+ [ 'track-uuid.sh', track_uuid ], -+] -+ -+if get_option('destructive').enabled() -+ sub_section = find_program('sub-section.sh') -+ dax_ext4 = find_program('dax-ext4.sh') -+ dax_xfs = find_program('dax-xfs.sh') -+ align = find_program('align.sh') -+ device_dax_fio = find_program('device-dax-fio.sh') -+ daxctl_devices = find_program('daxctl-devices.sh') -+ daxctl_create = find_program('daxctl-create.sh') -+ dm = find_program('dm.sh') -+ mmap_test = find_program('mmap.sh') -+ -+ tests += [ -+ [ 'pmem-ns', pmem_ns ], -+ [ 'sub-section.sh', sub_section ], -+ [ 'dax-dev', dax_dev ], -+ [ 'dax-ext4.sh', dax_ext4 ], -+ [ 'dax-xfs.sh', dax_xfs ], -+ [ 'align.sh', align ], -+ [ 'device-dax', device_dax ], -+ [ 'revoke-devmem', revoke_devmem ], -+ [ 'device-dax-fio.sh', device_dax_fio ], -+ [ 'daxctl-devices.sh', daxctl_devices ], -+ [ 'daxctl-create.sh', daxctl_create ], -+ [ 'dm.sh', dm ], -+ [ 'mmap.sh', mmap_test ], -+ ] -+endif -+ -+if get_option('keyutils').enabled() -+ security = find_program('security.sh') -+ tests += [ -+ [ 'security.sh', security ] -+ ] -+endif -+ -+foreach t : tests -+ test(t[0], t[1], -+ is_parallel : false, -+ depends : [ -+ ndctl_tool, -+ daxctl_tool, -+ cxl_tool, -+ smart_notify, -+ list_smart_dimm, -+ dax_pmd, -+ dax_errors, -+ daxdev_errors, -+ dax_dev, -+ mmap, -+ ], -+ timeout : 0, -+ env : [ -+ 'NDCTL=@0@'.format(ndctl_tool.full_path()), -+ 'DAXCTL=@0@'.format(daxctl_tool.full_path()), -+ 'TEST_PATH=@0@'.format(meson.current_build_dir()), -+ 'DATA_PATH=@0@'.format(meson.current_source_dir()), -+ ], -+ ) -+endforeach -diff -up ndctl-71.1/tools/meson-vcs-tag.sh.orig ndctl-71.1/tools/meson-vcs-tag.sh ---- ndctl-71.1/tools/meson-vcs-tag.sh.orig 2022-10-07 17:29:51.577717675 -0400 -+++ ndctl-71.1/tools/meson-vcs-tag.sh 2022-10-07 17:29:51.577717675 -0400 -@@ -0,0 +1,18 @@ -+#!/usr/bin/env bash -+# SPDX-License-Identifier: LGPL-2.1-or-later -+ -+set -eu -+set -o pipefail -+ -+dir="${1:?}" -+fallback="${2:?}" -+ -+# Apparently git describe has a bug where it always considers the work-tree -+# dirty when invoked with --git-dir (even though 'git status' is happy). Work -+# around this issue by cd-ing to the source directory. -+cd "$dir" -+# Check that we have either .git/ (a normal clone) or a .git file (a work-tree) -+# and that we don't get confused if a tarball is extracted in a higher-level -+# git repository. -+[ -e .git ] && git describe --abbrev=7 --dirty=+ 2>/dev/null | \ -+ sed -e 's/^v//' -e 's/-/./g' || echo "$fallback" -diff -up ndctl-71.1/util/meson.build.orig ndctl-71.1/util/meson.build ---- ndctl-71.1/util/meson.build.orig 2022-10-07 17:29:51.578717679 -0400 -+++ ndctl-71.1/util/meson.build 2022-10-07 17:29:51.578717679 -0400 -@@ -0,0 +1,15 @@ -+util = static_library('util', [ -+ 'parse-options.c', -+ 'usage.c', -+ 'size.c', -+ 'main.c', -+ 'help.c', -+ 'strbuf.c', -+ 'wrapper.c', -+ 'bitmap.c', -+ 'abspath.c', -+ 'iomem.c', -+ ], -+ include_directories : root_inc, -+) -+util_dep = declare_dependency(link_with : util) -diff -up ndctl-71.1/version.h.in.orig ndctl-71.1/version.h.in ---- ndctl-71.1/version.h.in.orig 2022-10-07 17:29:51.578717679 -0400 -+++ ndctl-71.1/version.h.in 2022-10-07 17:29:51.578717679 -0400 -@@ -0,0 +1,2 @@ -+/* SPDX-License-Identifier: LGPL-2.1 */ -+#define VERSION "@VCS_TAG@" diff --git a/SOURCES/0083-build-Add-meson-rpmbuild-support.patch b/SOURCES/0083-build-Add-meson-rpmbuild-support.patch deleted file mode 100644 index 4000682..0000000 --- a/SOURCES/0083-build-Add-meson-rpmbuild-support.patch +++ /dev/null @@ -1,223 +0,0 @@ -From 8b5b941093521dd18fcc99659b3e3b1b9e9456b7 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:32:58 -0800 -Subject: [PATCH 083/217] build: Add meson rpmbuild support - -Beyond being a prerequisite for removing autotools support, this capability -served as validation that the meson conversion generated all the same files -as autotools and installed them to the same expected locations. - -The procedure to use the rpmbuild.sh script is: - - meson setup build - meson compile -C build rhel/ndctl.spec - ./rpmbuild.sh build/rhel/ndctl.spec - -Link: https://lore.kernel.org/r/164141837841.3990253.11379060834465142446.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .gitignore | 2 +- - Makefile.am | 2 ++ - meson.build | 6 ++++++ - ndctl.spec.in | 23 +++++++++++++++++++++++ - rhel/meson.build | 23 +++++++++++++++++++++++ - rpmbuild.sh | 5 ++++- - sles/meson.build | 36 ++++++++++++++++++++++++++++++++++++ - 7 files changed, 95 insertions(+), 2 deletions(-) - create mode 100644 rhel/meson.build - create mode 100644 sles/meson.build - -diff -up ndctl-71.1/.gitignore.orig ndctl-71.1/.gitignore ---- ndctl-71.1/.gitignore.orig 2022-10-07 16:34:40.712445112 -0400 -+++ ndctl-71.1/.gitignore 2022-10-07 16:34:52.832486377 -0400 -@@ -35,7 +35,7 @@ daxctl/lib/libdaxctl.pc - ndctl/config.h - ndctl/lib/libndctl.pc - ndctl/ndctl --rhel/ -+rhel/ndctl.spec - sles/ndctl.spec - version.m4 - *.swp -diff -up ndctl-71.1/Makefile.am.orig ndctl-71.1/Makefile.am ---- ndctl-71.1/Makefile.am.orig 2022-10-07 16:34:40.687445027 -0400 -+++ ndctl-71.1/Makefile.am 2022-10-07 16:34:52.832486377 -0400 -@@ -22,6 +22,7 @@ noinst_SCRIPTS = rhel/ndctl.spec sles/nd - CLEANFILES += $(noinst_SCRIPTS) - - do_rhel_subst = sed -e 's,VERSION,$(VERSION),g' \ -+ -e 's,MESON,0,g' \ - -e 's,DAX_DNAME,daxctl-devel,g' \ - -e 's,CXL_DNAME,cxl-devel,g' \ - -e 's,DNAME,ndctl-devel,g' \ -@@ -31,6 +32,7 @@ do_rhel_subst = sed -e 's,VERSION,$(VERS - -e 's,LNAME,ndctl-libs,g' - - do_sles_subst = sed -e 's,VERSION,$(VERSION),g' \ -+ -e 's,MESON,0,g' \ - -e 's,DAX_DNAME,libdaxctl-devel,g' \ - -e 's,CXL_DNAME,libcxl-devel,g' \ - -e 's,DNAME,libndctl-devel,g' \ -diff -up ndctl-71.1/meson.build.orig ndctl-71.1/meson.build ---- ndctl-71.1/meson.build.orig 2022-10-07 16:34:40.715445122 -0400 -+++ ndctl-71.1/meson.build 2022-10-07 16:34:52.833486380 -0400 -@@ -278,3 +278,9 @@ if get_option('docs').enabled() - endif - subdir('test') - subdir('contrib') -+ -+# only support spec file generation from git builds -+if version_tag == '' -+ subdir('rhel') -+ subdir('sles') -+endif -diff -up ndctl-71.1/ndctl.spec.in.orig ndctl-71.1/ndctl.spec.in ---- ndctl-71.1/ndctl.spec.in.orig 2022-10-07 16:34:40.645444884 -0400 -+++ ndctl-71.1/ndctl.spec.in 2022-10-07 16:34:52.833486380 -0400 -@@ -6,14 +6,20 @@ License: GPLv2 - Url: https://github.com/pmem/ndctl - Source0: https://github.com/pmem/%{name}/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz - -+%define with_meson MESON - Requires: LNAME%{?_isa} = %{version}-%{release} - Requires: DAX_LNAME%{?_isa} = %{version}-%{release} - Requires: CXL_LNAME%{?_isa} = %{version}-%{release} - BuildRequires: autoconf - %if 0%{?rhel} < 9 - BuildRequires: asciidoc -+%if !%{with_meson} - %define asciidoc --disable-asciidoctor -+%endif - %else -+%if %{with_meson} -+%define asciidoctor -Dasciidoctor=enabled -+%endif - BuildRequires: rubygem-asciidoctor - %endif - BuildRequires: xmlto -@@ -28,6 +34,10 @@ BuildRequires: pkgconfig(bash-completion - BuildRequires: pkgconfig(systemd) - BuildRequires: keyutils-libs-devel - -+%if %{with_meson} -+BuildRequires: meson -+%endif -+ - %description - Utility library for managing the "libnvdimm" subsystem. The "libnvdimm" - subsystem defines a kernel device model and control message interface for -@@ -115,17 +125,30 @@ libcxl is a library for enumerating and - %setup -q ndctl-%{version} - - %build -+%if %{with_meson} -+%meson %{?asciidoctor} -Dversion-tag=%{version} -+%meson_build -+%else - echo %{version} > version - ./autogen.sh - %configure --disable-static --disable-silent-rules %{?asciidoc} - make %{?_smp_mflags} -+%endif - - %install -+%if %{with_meson} -+%meson_install -+%else - %make_install - find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' -+%endif - - %check -+%if %{with_meson} -+%meson_test -+%else - make check -+%endif - - %ldconfig_scriptlets -n LNAME - -diff -up ndctl-71.1/rhel/meson.build.orig ndctl-71.1/rhel/meson.build ---- ndctl-71.1/rhel/meson.build.orig 2022-10-07 16:34:52.834486384 -0400 -+++ ndctl-71.1/rhel/meson.build 2022-10-07 16:34:52.834486384 -0400 -@@ -0,0 +1,23 @@ -+rhel_spec1 = vcs_tag( -+ input : '../ndctl.spec.in', -+ output : 'ndctl.spec.in', -+ command: vcs_tagger, -+ replace_string : 'VERSION', -+) -+ -+rhel_spec2 = custom_target('ndctl.spec', -+ command : [ -+ 'sed', '-e', 's,MESON,1,g', -+ '-e', 's,DAX_DNAME,daxctl-devel,g', -+ '-e', 's,CXL_DNAME,cxl-devel,g', -+ '-e', 's,DNAME,ndctl-devel,g', -+ '-e', '/^%defattr.*/d', -+ '-e', 's,DAX_LNAME,daxctl-libs,g', -+ '-e', 's,CXL_LNAME,cxl-libs,g', -+ '-e', 's,LNAME,ndctl-libs,g', -+ '@INPUT@' -+ ], -+ input : rhel_spec1, -+ output : 'ndctl.spec', -+ capture : true, -+) -diff -up ndctl-71.1/rpmbuild.sh.orig ndctl-71.1/rpmbuild.sh ---- ndctl-71.1/rpmbuild.sh.orig 2020-12-22 16:44:57.000000000 -0500 -+++ ndctl-71.1/rpmbuild.sh 2022-10-07 16:34:52.834486384 -0400 -@@ -1,6 +1,9 @@ - #!/bin/bash -+ -+spec=${1:-$(dirname $0)/rhel/ndctl.spec)} -+ - pushd $(dirname $0) >/dev/null - [ ! -d ~/rpmbuild/SOURCES ] && echo "rpmdev tree not found" && exit 1 - ./make-git-snapshot.sh - popd > /dev/null --rpmbuild -ba $(dirname $0)/rhel/ndctl.spec -+rpmbuild --nocheck -ba $spec -diff -up ndctl-71.1/sles/meson.build.orig ndctl-71.1/sles/meson.build ---- ndctl-71.1/sles/meson.build.orig 2022-10-07 16:34:52.836486391 -0400 -+++ ndctl-71.1/sles/meson.build 2022-10-07 16:34:52.835486387 -0400 -@@ -0,0 +1,36 @@ -+sles_spec1 = vcs_tag( -+ input : '../ndctl.spec.in', -+ output : 'ndctl.spec.sles.in', -+ command: vcs_tagger, -+ replace_string : 'VERSION', -+) -+ -+header = files('header') -+ -+sles_spec2 = custom_target('ndctl.spec.in', -+ command : [ -+ 'cat', header, '@INPUT@', -+ ], -+ input : sles_spec1, -+ output : 'ndctl.spec.in', -+ capture : true, -+) -+ -+sles_spec3 = custom_target('ndctl.spec', -+ command : [ -+ 'sed', '-e', 's,MESON,1,g', -+ '-e', 's,DAX_DNAME,libdaxctl-devel,g', -+ '-e', 's,CXL_DNAME,libcxl-devel,g', -+ '-e', 's,DNAME,libndctl-devel,g', -+ '-e', 's,%license,%doc,g', -+ '-e', 's,\(^License:.*GPL\)v2,\1-2.0,g', -+ '-e', 's,DAX_LNAME,libdaxctl@0@,g'.format(LIBDAXCTL_CURRENT - LIBDAXCTL_AGE), -+ '-e', 's,CXL_LNAME,libcxl@0@,g'.format(LIBCXL_CURRENT - LIBCXL_AGE), -+ '-e', 's,LNAME,libndctl@0@,g'.format(LIBNDCTL_CURRENT - LIBNDCTL_AGE), -+ '@INPUT@' -+ ], -+ -+ input : sles_spec2, -+ output : 'ndctl.spec', -+ capture : true, -+) diff --git a/SOURCES/0084-ndctl-Jettison-autotools.patch b/SOURCES/0084-ndctl-Jettison-autotools.patch deleted file mode 100644 index 2b83e0e..0000000 --- a/SOURCES/0084-ndctl-Jettison-autotools.patch +++ /dev/null @@ -1,1423 +0,0 @@ -From 44f2f06c688fec84db41b26b47c2de45040906eb Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 5 Jan 2022 13:33:03 -0800 -Subject: [PATCH 084/217] ndctl: Jettison autotools - -Similar to several other projects, ndctl has run its course with autotools -and sees a better path forward with Meson. Now that the Meson conversion is -complete, remove the autotools infrastructure. - -Link: https://lore.kernel.org/r/164141838349.3990253.14745993061779737304.stgit@dwillia2-desk3.amr.corp.intel.com -Tested-by: Alison Schofield -Tested-by: Vaibhav Jain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .gitignore | 58 ------- - Documentation/cxl/Makefile.am | 61 ------- - Documentation/cxl/lib/Makefile.am | 58 ------- - Documentation/daxctl/Makefile.am | 72 -------- - Documentation/ndctl/Makefile.am | 103 ------------ - Makefile.am | 104 ------------ - Makefile.am.in | 46 ----- - autogen.sh | 28 ---- - configure.ac | 270 ------------------------------ - cxl/Makefile.am | 25 --- - cxl/lib/Makefile.am | 32 ---- - daxctl/Makefile.am | 45 ----- - daxctl/lib/Makefile.am | 42 ----- - ndctl.spec.in | 28 +--- - ndctl/Makefile.am | 86 ---------- - ndctl/lib/Makefile.am | 58 ------- - rhel/meson.build | 3 +- - sles/meson.build | 3 +- - test/Makefile.am | 169 ------------------- - 19 files changed, 4 insertions(+), 1287 deletions(-) - delete mode 100644 Documentation/cxl/Makefile.am - delete mode 100644 Documentation/cxl/lib/Makefile.am - delete mode 100644 Documentation/daxctl/Makefile.am - delete mode 100644 Documentation/ndctl/Makefile.am - delete mode 100644 Makefile.am - delete mode 100644 Makefile.am.in - delete mode 100755 autogen.sh - delete mode 100644 configure.ac - delete mode 100644 cxl/Makefile.am - delete mode 100644 cxl/lib/Makefile.am - delete mode 100644 daxctl/Makefile.am - delete mode 100644 daxctl/lib/Makefile.am - delete mode 100644 ndctl/Makefile.am - delete mode 100644 ndctl/lib/Makefile.am - delete mode 100644 test/Makefile.am - -diff -up ndctl-71.1/.gitignore.orig ndctl-71.1/.gitignore ---- ndctl-71.1/.gitignore.orig 2022-10-07 18:39:13.182886649 -0400 -+++ ndctl-71.1/.gitignore 2022-10-07 18:39:43.934991351 -0400 -@@ -1,63 +1,5 @@ --*.o --*.lo --*.xml --.deps/ --.libs/ --Makefile --!contrib/Makefile --Makefile.in --/aclocal.m4 --/autom4te.cache --/build-aux --/config.h --/config.log --/config.status --/configure --/libtool --/stamp-h1 --*.1 --*.3 --Documentation/daxctl/asciidoc.conf --Documentation/ndctl/asciidoc.conf --Documentation/cxl/asciidoc.conf --Documentation/cxl/lib/asciidoc.conf --Documentation/daxctl/asciidoctor-extensions.rb --Documentation/ndctl/asciidoctor-extensions.rb --Documentation/cxl/asciidoctor-extensions.rb --Documentation/cxl/lib/asciidoctor-extensions.rb --.dirstamp - build/ --daxctl/config.h --daxctl/daxctl --daxctl/lib/libdaxctl.la --daxctl/lib/libdaxctl.pc --*.a --ndctl/config.h --ndctl/lib/libndctl.pc --ndctl/ndctl - rhel/ndctl.spec - sles/ndctl.spec --version.m4 - *.swp --cscope.files --cscope*.out - tags --test/*.log --test/*.trs --test/dax-dev --test/dax-errors --test/dax-pmd --test/daxdev-errors --test/device-dax --test/dsm-fail --test/hugetlb --test/image --test/libndctl --test/mmap --test/pmem-ns --test/smart-listen --test/smart-notify --test/fio.job --test/local-write-0-verify.state --test/ack-shutdown-count-set --test/list-smart-dimm -diff -up ndctl-71.1/Documentation/cxl/Makefile.am.orig /dev/null ---- ndctl-71.1/Documentation/cxl/Makefile.am 2022-10-07 18:39:13.067886258 -0400 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,61 +0,0 @@ --# SPDX-License-Identifier: GPL-2.0 --# Copyright (C) 2020-2021 Intel Corporation. All rights reserved. -- --if USE_ASCIIDOCTOR -- --do_subst = sed -e 's,@Utility@,Cxl,g' -e's,@utility@,cxl,g' --CONFFILE = asciidoctor-extensions.rb --asciidoctor-extensions.rb: ../asciidoctor-extensions.rb.in -- $(AM_V_GEN) $(do_subst) < $< > $@ -- --else -- --do_subst = sed -e 's,UTILITY,cxl,g' --CONFFILE = asciidoc.conf --asciidoc.conf: ../asciidoc.conf.in -- $(AM_V_GEN) $(do_subst) < $< > $@ -- --endif -- --man1_MANS = \ -- cxl.1 \ -- cxl-list.1 \ -- cxl-read-labels.1 \ -- cxl-write-labels.1 \ -- cxl-zero-labels.1 -- --EXTRA_DIST = $(man1_MANS) -- --CLEANFILES = $(man1_MANS) -- --XML_DEPS = \ -- ../../version.m4 \ -- ../copyright.txt \ -- Makefile \ -- $(CONFFILE) -- --RM ?= rm -f -- --if USE_ASCIIDOCTOR -- --%.1: %.txt $(XML_DEPS) -- $(AM_V_GEN)$(RM) $@+ $@ && \ -- $(ASCIIDOC) -b manpage -d manpage -acompat-mode \ -- -I. -rasciidoctor-extensions \ -- -amansource=cxl -amanmanual="cxl Manual" \ -- -andctl_version=$(VERSION) -o $@+ $< && \ -- mv $@+ $@ -- --else -- --%.xml: %.txt $(XML_DEPS) -- $(AM_V_GEN)$(RM) $@+ $@ && \ -- $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \ -- --unsafe -acxl_version=$(VERSION) -o $@+ $< && \ -- mv $@+ $@ -- --%.1: %.xml $(XML_DEPS) -- $(AM_V_GEN)$(RM) $@ && \ -- $(XMLTO) -o . -m ../manpage-normal.xsl man $< -- --endif -diff -up ndctl-71.1/Documentation/cxl/lib/Makefile.am /dev/null ---- ndctl-71.1/Documentation/cxl/lib/Makefile.am 2022-10-07 18:39:13.071886271 -0400 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,58 +0,0 @@ --# SPDX-License-Identifier: GPL-2.0 --# Copyright (C) 2020-2021 Intel Corporation. All rights reserved. -- --if USE_ASCIIDOCTOR -- --do_subst = sed -e 's,@Utility@,Libcxl,g' -e's,@utility@,libcxl,g' --CONFFILE = asciidoctor-extensions.rb --asciidoctor-extensions.rb: ../../asciidoctor-extensions.rb.in -- $(AM_V_GEN) $(do_subst) < $< > $@ -- --else -- --do_subst = sed -e 's,UTILITY,libcxl,g' --CONFFILE = asciidoc.conf --asciidoc.conf: ../../asciidoc.conf.in -- $(AM_V_GEN) $(do_subst) < $< > $@ -- --endif -- --man3_MANS = \ -- libcxl.3 \ -- cxl_new.3 -- --EXTRA_DIST = $(man3_MANS) -- --CLEANFILES = $(man3_MANS) -- --XML_DEPS = \ -- ../../../version.m4 \ -- ../../copyright.txt \ -- Makefile \ -- $(CONFFILE) -- --RM ?= rm -f -- --if USE_ASCIIDOCTOR -- --%.3: %.txt $(XML_DEPS) -- $(AM_V_GEN)$(RM) $@+ $@ && \ -- $(ASCIIDOC) -b manpage -d manpage -acompat-mode \ -- -I. -rasciidoctor-extensions \ -- -amansource=libcxl -amanmanual="libcxl Manual" \ -- -andctl_version=$(VERSION) -o $@+ $< && \ -- mv $@+ $@ -- --else -- --%.xml: %.txt $(XML_DEPS) -- $(AM_V_GEN)$(RM) $@+ $@ && \ -- $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \ -- --unsafe -alibcxl_version=$(VERSION) -o $@+ $< && \ -- mv $@+ $@ -- --%.3: %.xml $(XML_DEPS) -- $(AM_V_GEN)$(RM) $@ && \ -- $(XMLTO) -o . -m ../../manpage-normal.xsl man $< -- --endif -diff -up ndctl-71.1/Documentation/daxctl/Makefile.am /dev/null ---- ndctl-71.1/Documentation/daxctl/Makefile.am 2022-10-07 18:42:19.341520462 -0400 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,66 +0,0 @@ --# SPDX-License-Identifier: GPL-2.0 --# Copyright (C) 2015-2020 Intel Corporation. All rights reserved. -- --if USE_ASCIIDOCTOR -- --do_subst = sed -e 's,@Utility@,Daxctl,g' -e's,@utility@,daxctl,g' --CONFFILE = asciidoctor-extensions.rb --asciidoctor-extensions.rb: ../asciidoctor-extensions.rb.in -- $(AM_V_GEN) $(do_subst) < $< > $@ -- --else -- --do_subst = sed -e 's,UTILITY,daxctl,g' --CONFFILE = asciidoc.conf --asciidoc.conf: ../asciidoc.conf.in -- $(AM_V_GEN) $(do_subst) < $< > $@ -- --endif -- --man1_MANS = \ -- daxctl.1 \ -- daxctl-list.1 \ -- daxctl-migrate-device-model.1 \ -- daxctl-reconfigure-device.1 \ -- daxctl-online-memory.1 \ -- daxctl-offline-memory.1 \ -- daxctl-disable-device.1 \ -- daxctl-enable-device.1 \ -- daxctl-create-device.1 \ -- daxctl-destroy-device.1 -- --EXTRA_DIST = $(man1_MANS) -- --CLEANFILES = $(man1_MANS) -- --XML_DEPS = \ -- ../../version.m4 \ -- ../copyright.txt \ -- Makefile \ -- $(CONFFILE) -- --RM ?= rm -f -- --if USE_ASCIIDOCTOR -- --%.1: %.txt $(XML_DEPS) -- $(AM_V_GEN)$(RM) $@+ $@ && \ -- $(ASCIIDOC) -b manpage -d manpage -acompat-mode \ -- -I. -rasciidoctor-extensions \ -- -amansource=daxctl -amanmanual="daxctl Manual" \ -- -andctl_version=$(VERSION) -o $@+ $< && \ -- mv $@+ $@ -- --else -- --%.xml: %.txt $(XML_DEPS) -- $(AM_V_GEN)$(RM) $@+ $@ && \ -- $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \ -- --unsafe -adaxctl_version=$(VERSION) -o $@+ $< && \ -- mv $@+ $@ -- --%.1: %.xml $(XML_DEPS) -- $(AM_V_GEN)$(RM) $@ && \ -- $(XMLTO) -o . -m ../manpage-normal.xsl man $< -- --endif -diff -up ndctl-71.1/Documentation/ndctl/Makefile.am /dev/null ---- ndctl-71.1/Documentation/ndctl/Makefile.am 2020-12-22 16:44:57.000000000 -0500 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,106 +0,0 @@ --# SPDX-License-Identifier: GPL-2.0 --# Copyright (C) 2015-2020 Intel Corporation. All rights reserved. -- --if USE_ASCIIDOCTOR -- --do_subst = sed -e 's,@Utility@,Ndctl,g' -e's,@utility@,ndctl,g' --CONFFILE = asciidoctor-extensions.rb --asciidoctor-extensions.rb: ../asciidoctor-extensions.rb.in -- $(AM_V_GEN) $(do_subst) < $< > $@ -- --else -- --do_subst = sed -e 's,UTILITY,ndctl,g' --CONFFILE = asciidoc.conf --asciidoc.conf: ../asciidoc.conf.in -- $(AM_V_GEN) $(do_subst) < $< > $@ -- --endif -- --man1_MANS = \ -- ndctl.1 \ -- ndctl-wait-scrub.1 \ -- ndctl-start-scrub.1 \ -- ndctl-zero-labels.1 \ -- ndctl-read-labels.1 \ -- ndctl-write-labels.1 \ -- ndctl-init-labels.1 \ -- ndctl-check-labels.1 \ -- ndctl-enable-region.1 \ -- ndctl-disable-region.1 \ -- ndctl-enable-dimm.1 \ -- ndctl-disable-dimm.1 \ -- ndctl-enable-namespace.1 \ -- ndctl-disable-namespace.1 \ -- ndctl-create-namespace.1 \ -- ndctl-destroy-namespace.1 \ -- ndctl-check-namespace.1 \ -- ndctl-clear-errors.1 \ -- ndctl-inject-error.1 \ -- ndctl-inject-smart.1 \ -- ndctl-update-firmware.1 \ -- ndctl-list.1 \ -- ndctl-monitor.1 \ -- ndctl-setup-passphrase.1 \ -- ndctl-update-passphrase.1 \ -- ndctl-remove-passphrase.1 \ -- ndctl-freeze-security.1 \ -- ndctl-sanitize-dimm.1 \ -- ndctl-load-keys.1 \ -- ndctl-wait-overwrite.1 \ -- ndctl-read-infoblock.1 \ -- ndctl-write-infoblock.1 \ -- ndctl-activate-firmware.1 -- --EXTRA_DIST = $(man1_MANS) -- --CLEANFILES = $(man1_MANS) -- --.ONESHELL: --attrs.adoc: $(srcdir)/Makefile.am -- $(AM_V_GEN) cat <<- EOF >$@ -- :ndctl_monitorconfdir: $(ndctl_monitorconfdir) -- :ndctl_monitorconf: $(ndctl_monitorconf) -- :ndctl_keysdir: $(ndctl_keysdir) -- EOF -- --XML_DEPS = \ -- ../../version.m4 \ -- Makefile \ -- $(CONFFILE) \ -- ../copyright.txt \ -- region-description.txt \ -- xable-region-options.txt \ -- dimm-description.txt \ -- xable-dimm-options.txt \ -- xable-namespace-options.txt \ -- ars-description.txt \ -- labels-description.txt \ -- labels-options.txt \ -- attrs.adoc -- --RM ?= rm -f -- --if USE_ASCIIDOCTOR -- --%.1: %.txt $(XML_DEPS) -- $(AM_V_GEN)$(RM) $@+ $@ && \ -- $(ASCIIDOC) -b manpage -d manpage -acompat-mode \ -- -I. -rasciidoctor-extensions \ -- -amansource=ndctl -amanmanual="ndctl Manual" \ -- -andctl_version=$(VERSION) -o $@+ $< && \ -- mv $@+ $@ -- --else -- --%.xml: %.txt $(XML_DEPS) -- $(AM_V_GEN)$(RM) $@+ $@ && \ -- $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \ -- --unsafe -andctl_version=$(VERSION) -o $@+ $< && \ -- mv $@+ $@ -- --%.1: %.xml $(XML_DEPS) -- $(AM_V_GEN)$(RM) $@ && \ -- $(XMLTO) -o . -m ../manpage-normal.xsl man $< -- --endif -diff -up ndctl-71.1/Makefile.am.in /dev/null ---- ndctl-71.1/Makefile.am.in 2022-10-07 18:39:13.130886472 -0400 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,46 +0,0 @@ --EXTRA_DIST = --CLEANFILES = -- --AM_MAKEFLAGS = --no-print-directory -- --AM_CPPFLAGS = \ -- -include $(top_builddir)/config.h \ -- -DSYSCONFDIR=\""$(sysconfdir)"\" \ -- -DLIBEXECDIR=\""$(libexecdir)"\" \ -- -DPREFIX=\""$(prefix)"\" \ -- -DNDCTL_MAN_PATH=\""$(mandir)"\" \ -- -I${top_srcdir}/ \ -- $(KMOD_CFLAGS) \ -- $(UDEV_CFLAGS) \ -- $(UUID_CFLAGS) \ -- $(JSON_CFLAGS) -- --AM_CFLAGS = ${my_CFLAGS} \ -- -fvisibility=hidden \ -- -ffunction-sections \ -- -fdata-sections -- --AM_LDFLAGS = \ -- -Wl,--gc-sections \ -- -Wl,--as-needed -- --SED_PROCESS = \ -- $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(SED) \ -- -e 's,@VERSION\@,$(VERSION),g' \ -- -e 's,@prefix\@,$(prefix),g' \ -- -e 's,@exec_prefix\@,$(exec_prefix),g' \ -- -e 's,@libdir\@,$(libdir),g' \ -- -e 's,@includedir\@,$(includedir),g' \ -- < $< > $@ || rm $@ -- --LIBNDCTL_CURRENT=26 --LIBNDCTL_REVISION=1 --LIBNDCTL_AGE=20 -- --LIBDAXCTL_CURRENT=7 --LIBDAXCTL_REVISION=0 --LIBDAXCTL_AGE=6 -- --LIBCXL_CURRENT=1 --LIBCXL_REVISION=0 --LIBCXL_AGE=0 -diff -up ndctl-71.1/Makefile.am /dev/null ---- ndctl-71.1/Makefile.am 2022-10-07 18:39:13.182886649 -0400 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,102 +0,0 @@ --include Makefile.am.in -- --ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} --SUBDIRS = . cxl/lib daxctl/lib ndctl/lib cxl ndctl daxctl --if ENABLE_DOCS --SUBDIRS += Documentation/ndctl Documentation/daxctl Documentation/cxl --SUBDIRS += Documentation/cxl/lib --endif --SUBDIRS += test -- --BUILT_SOURCES = version.m4 --version.m4: FORCE -- $(AM_V_GEN)$(top_srcdir)/git-version-gen -- --FORCE: -- --EXTRA_DIST += ndctl.spec.in \ -- sles/header \ -- contrib/nvdimm-security.conf -- --noinst_SCRIPTS = rhel/ndctl.spec sles/ndctl.spec --CLEANFILES += $(noinst_SCRIPTS) -- --do_rhel_subst = sed -e 's,VERSION,$(VERSION),g' \ -- -e 's,MESON,0,g' \ -- -e 's,DAX_DNAME,daxctl-devel,g' \ -- -e 's,CXL_DNAME,cxl-devel,g' \ -- -e 's,DNAME,ndctl-devel,g' \ -- -e '/^%defattr.*/d' \ -- -e 's,DAX_LNAME,daxctl-libs,g' \ -- -e 's,CXL_LNAME,cxl-libs,g' \ -- -e 's,LNAME,ndctl-libs,g' -- --do_sles_subst = sed -e 's,VERSION,$(VERSION),g' \ -- -e 's,MESON,0,g' \ -- -e 's,DAX_DNAME,libdaxctl-devel,g' \ -- -e 's,CXL_DNAME,libcxl-devel,g' \ -- -e 's,DNAME,libndctl-devel,g' \ -- -e 's,%license,%doc,g' \ -- -e 's,\(^License:.*GPL\)v2,\1-2.0,g' \ -- -e "s,DAX_LNAME,libdaxctl$$(($(LIBDAXCTL_CURRENT) - $(LIBDAXCTL_AGE))),g" \ -- -e "s,CXL_LNAME,libcxl$$(($(LIBCXL_CURRENT) - $(LIBCXL_AGE))),g" \ -- -e "s,LNAME,libndctl$$(($(LIBNDCTL_CURRENT) - $(LIBNDCTL_AGE))),g" -- --rhel/ndctl.spec: ndctl.spec.in Makefile.am version.m4 -- $(AM_V_GEN)$(MKDIR_P) rhel; $(do_rhel_subst) < $< > $@ -- --sles/ndctl.spec: sles/header ndctl.spec.in Makefile.am version.m4 -- $(AM_V_GEN)$(MKDIR_P) sles; cat sles/header $< | $(do_sles_subst) > $@ -- --if ENABLE_BASH_COMPLETION --bashcompletiondir = $(BASH_COMPLETION_DIR) --dist_bashcompletion_DATA = contrib/ndctl --install-data-hook: -- $(LN_S) -f $(BASH_COMPLETION_DIR)/ndctl $(DESTDIR)/$(BASH_COMPLETION_DIR)/daxctl -- $(LN_S) -f $(BASH_COMPLETION_DIR)/ndctl $(DESTDIR)/$(BASH_COMPLETION_DIR)/cxl --endif -- --modprobe_file = contrib/nvdimm-security.conf --modprobedir = $(sysconfdir)/modprobe.d/ --modprobe_DATA = $(modprobe_file) -- --noinst_LIBRARIES = libccan.a --libccan_a_SOURCES = \ -- ccan/str/str.h \ -- ccan/str/str_debug.h \ -- ccan/str/str.c \ -- ccan/str/debug.c \ -- ccan/list/list.h \ -- ccan/list/list.c \ -- ccan/container_of/container_of.h \ -- ccan/check_type/check_type.h \ -- ccan/build_assert/build_assert.h \ -- ccan/array_size/array_size.h \ -- ccan/minmax/minmax.h \ -- ccan/short_types/short_types.h \ -- ccan/endian/endian.h -- --noinst_LIBRARIES += libutil.a --libutil_a_SOURCES = \ -- util/parse-options.c \ -- util/parse-options.h \ -- util/usage.c \ -- util/size.c \ -- util/main.c \ -- util/help.c \ -- util/strbuf.c \ -- util/wrapper.c \ -- util/bitmap.c \ -- util/abspath.c \ -- util/iomem.c \ -- util/util.h \ -- util/strbuf.h \ -- util/size.h \ -- util/main.h \ -- util/filter.h \ -- util/bitmap.h -- --nobase_include_HEADERS = \ -- daxctl/libdaxctl.h \ -- cxl/libcxl.h \ -- cxl/cxl_mem.h -diff -up ndctl-71.1/autogen.sh /dev/null ---- ndctl-71.1/autogen.sh 2020-12-22 16:44:57.000000000 -0500 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,28 +0,0 @@ --#!/bin/sh -e -- --if [ -f .git/hooks/pre-commit.sample -a ! -f .git/hooks/pre-commit ] ; then -- cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \ -- chmod +x .git/hooks/pre-commit && \ -- echo "Activated pre-commit hook." --fi -- --$(dirname $0)/git-version-gen --reconf_args='' --[ -n "$*" ] && reconf_args="$*" --autoreconf --install --symlink $reconf_args -- --libdir() { -- echo $(cd $1/$(gcc -print-multi-os-directory); pwd) --} -- --args="--prefix=/usr \ ----sysconfdir=/etc \ ----libdir=$(libdir /usr/lib)" -- --echo --echo "----------------------------------------------------------------" --echo "Initialized build system. For a common configuration please run:" --echo "----------------------------------------------------------------" --echo --echo "./configure CFLAGS='-g -O2' $args" --echo -diff -up ndctl-71.1/configure.ac /dev/null ---- ndctl-71.1/configure.ac 2022-10-07 18:39:13.083886312 -0400 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,254 +0,0 @@ --AC_PREREQ(2.60) --m4_include([version.m4]) --AC_INIT([ndctl], -- GIT_VERSION, -- [nvdimm@lists.linux.dev], -- [ndctl], -- [https://github.com/pmem/ndctl]) --AC_CONFIG_SRCDIR([ndctl/lib/libndctl.c]) --AC_CONFIG_AUX_DIR([build-aux]) --AM_INIT_AUTOMAKE([ -- foreign -- 1.11 -- -Wall -- -Wno-portability -- silent-rules -- tar-pax -- no-dist-gzip -- dist-xz -- subdir-objects --]) --AC_PROG_CC_STDC --AC_USE_SYSTEM_EXTENSIONS --AC_SYS_LARGEFILE --AC_CONFIG_MACRO_DIR([m4]) --AM_SILENT_RULES([yes]) --LT_INIT([ -- disable-static -- pic-only --]) --AC_PREFIX_DEFAULT([/usr]) -- --AC_PROG_SED --AC_PROG_MKDIR_P --AC_PROG_LN_S -- --AC_ARG_ENABLE([docs], -- AS_HELP_STRING([--disable-docs], -- [disable documentation build @<:@default=enabled@:>@]), -- [], enable_docs=yes) --AS_IF([test "x$enable_docs" = "xyes"], [ -- AC_DEFINE(ENABLE_DOCS, [1], [Documentation / man pages.]) --]) --AM_CONDITIONAL([ENABLE_DOCS], [test "x$enable_docs" = "xyes"]) -- --AC_ARG_ENABLE([asciidoctor], -- AS_HELP_STRING([--enable-asciidoctor], -- [use asciidoctor for documentation build]), -- [], enable_asciidoctor=yes) --AM_CONDITIONAL([USE_ASCIIDOCTOR], [test "x$enable_asciidoctor" = "xyes"]) --if test "x$enable_asciidoctor" = "xyes"; then -- asciidoc="asciidoctor" --else -- asciidoc="asciidoc" --fi --AC_CHECK_PROG(ASCIIDOC, [$asciidoc], [$(which $asciidoc)], [missing]) --if test "x$ASCIIDOC" = xmissing -a "x$enable_docs" = "xyes"; then -- AC_MSG_ERROR([$asciidoc needed to build documentation]) --fi --AC_SUBST([ASCIIDOC]) -- --if test x"$asciidoc" = x"asciidoc"; then --AC_CHECK_PROG(XMLTO, [xmlto], [$(which xmlto)], [missing]) --if test "x$XMLTO" = xmissing -a "x$enable_docs" = "xyes"; then -- AC_MSG_ERROR([xmlto needed to build documentation]) --fi --AC_SUBST([XMLTO]) --fi -- --AC_C_TYPEOF --AC_DEFINE([HAVE_STATEMENT_EXPR], 1, [Define to 1 if you have statement expressions.]) -- --AC_C_BIGENDIAN( -- AC_DEFINE(HAVE_BIG_ENDIAN, 1, [Define to 1 if big-endian-arch]), -- AC_DEFINE(HAVE_LITTLE_ENDIAN, 1, [Define to 1 if little-endian-arch]), -- [], []) -- --AC_ARG_ENABLE([logging], -- AS_HELP_STRING([--disable-logging], [disable system logging @<:@default=enabled@:>@]), -- [], enable_logging=yes) --AS_IF([test "x$enable_logging" = "xyes"], [ -- AC_DEFINE(ENABLE_LOGGING, [1], [System logging.]) --]) -- --AC_ARG_ENABLE([debug], -- AS_HELP_STRING([--enable-debug], [enable debug messages @<:@default=disabled@:>@]), -- [], [enable_debug=no]) --AS_IF([test "x$enable_debug" = "xyes"], [ -- AC_DEFINE(ENABLE_DEBUG, [1], [Debug messages.]) --]) -- --AC_ARG_ENABLE([destructive], -- AS_HELP_STRING([--enable-destructive], [enable destructive functional tests @<:@default=disabled@:>@]), -- [], [enable_destructive=no]) --AS_IF([test "x$enable_destructive" = "xyes"], -- [AC_DEFINE([ENABLE_DESTRUCTIVE], [1], [destructive functional tests support])]) --AM_CONDITIONAL([ENABLE_DESTRUCTIVE], [test "x$enable_destructive" = "xyes"]) -- --AC_ARG_ENABLE([test], -- AS_HELP_STRING([--enable-test], [enable ndctl test command @<:@default=disabled@:>@]), -- [], [enable_test=$enable_destructive]) --AS_IF([test "x$enable_test" = "xyes"], -- [AC_DEFINE([ENABLE_TEST], [1], [ndctl test support])]) --AM_CONDITIONAL([ENABLE_TEST], [test "x$enable_test" = "xyes"]) -- --AC_CHECK_DECLS([BUS_MCEERR_AR], [enable_bus_mc_err=yes], [], [[#include ]]) --AC_CHECK_DECLS([MAP_SHARED_VALIDATE], [kernel_map_shared_validate=yes], [], [[#include ]]) --AC_CHECK_DECLS([MAP_SYNC], [kernel_map_sync=yes], [], [[#include ]]) --AS_UNSET([ac_cv_have_decl_MAP_SHARED_VALIDATE]) --AS_UNSET([ac_cv_have_decl_MAP_SYNC]) --AC_CHECK_DECLS([MAP_SHARED_VALIDATE], [enable_map_shared_validate=yes], [], [[#include ]]) --AC_CHECK_DECLS([MAP_SYNC], [enable_map_sync=yes], [], [[#include ]]) -- --if test "x$kernel_map_shared_validate" = "xyes" -a "x$enable_map_shared_validate" != "xyes" ; then -- AC_MSG_WARN([MAP_SHARED_VALIDATE supported by kernel but not by , consider installing glibc-2.28 or later.]) --fi --if test "x$kernel_map_shared_validate" != "xyes" -a "x$enable_map_shared_validate" != "xyes" ; then -- AC_MSG_WARN([MAP_SHARED_VALIDATE not supported by kernel, consider installing kernel-4.15 or later.]) --fi --if test "x$kernel_map_sync" = "xyes" -a "x$enable_map_sync" != "xyes" ; then -- AC_MSG_WARN([MAP_SYNC supported by kernel but not by , consider installing glibc-2.28 or later.]) --fi --if test "x$kernel_map_sync" != "xyes" -a "x$enable_map_sync" != "xyes" ; then -- AC_MSG_WARN([MAP_SYNC not supported by kernel or architecture, consider installing kernel-4.15 or later.]) --fi -- --AS_IF([test "x$enable_bus_mc_err" = "xyes" -a "x$enable_map_sync" = "xyes" -a "x$enable_map_shared_validate" = "xyes"], -- [AC_DEFINE([ENABLE_POISON], [1], [ndctl test poison support])]) --AM_CONDITIONAL([ENABLE_POISON], -- [test "x$enable_bus_mc_err" = "xyes" -a "x$enable_map_sync" = "xyes" -a "x$enable_map_shared_validate" = "xyes"]) -- --PKG_CHECK_MODULES([KMOD], [libkmod]) --PKG_CHECK_MODULES([UDEV], [libudev]) --PKG_CHECK_MODULES([UUID], [uuid], -- [AC_DEFINE([HAVE_UUID], [1], [Define to 1 if using libuuid])]) --PKG_CHECK_MODULES([JSON], [json-c]) -- --AC_ARG_WITH([bash], -- AS_HELP_STRING([--with-bash], -- [Enable bash auto-completion. @<:@default=yes@:>@]), -- [], -- [with_bash=yes]) -- --if test "x$with_bash" = "xyes"; then -- PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], -- [BASH_COMPLETION_DIR=$($PKG_CONFIG --variable=completionsdir bash-completion)], []) --fi -- --AC_SUBST([BASH_COMPLETION_DIR]) --AM_CONDITIONAL([ENABLE_BASH_COMPLETION], [test "x$with_bash" = "xyes"]) -- --AC_ARG_ENABLE([local], -- AS_HELP_STRING([--disable-local], [build against kernel ndctl.h @<:@default=system@:>@]), -- [], [enable_local=yes]) -- --AC_CHECK_HEADERS_ONCE([linux/version.h]) -- --AC_CHECK_FUNCS([ \ -- __secure_getenv \ -- secure_getenv\ --]) -- --AC_ARG_WITH([systemd], -- AS_HELP_STRING([--with-systemd], -- [Enable systemd functionality (monitor). @<:@default=yes@:>@]), -- [], [with_systemd=yes]) -- --if test "x$with_systemd" = "xyes"; then -- PKG_CHECK_MODULES([SYSTEMD], [systemd], -- [systemd_unitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)], []) --fi -- --AC_SUBST([systemd_unitdir]) --AM_CONDITIONAL([ENABLE_SYSTEMD_UNITS], [test "x$with_systemd" = "xyes"]) -- --ndctl_monitorconfdir=${sysconfdir}/ndctl --ndctl_monitorconf=monitor.conf --AC_SUBST([ndctl_monitorconfdir]) --AC_SUBST([ndctl_monitorconf]) -- --daxctl_modprobe_datadir=${datadir}/daxctl --daxctl_modprobe_data=daxctl.conf --AC_SUBST([daxctl_modprobe_datadir]) --AC_SUBST([daxctl_modprobe_data]) -- --AC_ARG_WITH([keyutils], -- AS_HELP_STRING([--with-keyutils], -- [Enable keyutils functionality (security). @<:@default=yes@:>@]), [], [with_keyutils=yes]) -- --if test "x$with_keyutils" = "xyes"; then -- AC_CHECK_HEADERS([keyutils.h],,[ -- AC_MSG_ERROR([keyutils.h not found, consider installing the keyutils library development package (variously named keyutils-libs-devel, keyutils-devel, or libkeyutils-dev).]) -- ]) --fi --AS_IF([test "x$with_keyutils" = "xyes"], -- [AC_DEFINE([ENABLE_KEYUTILS], [1], [Enable keyutils support])]) --AM_CONDITIONAL([ENABLE_KEYUTILS], [test "x$with_keyutils" = "xyes"]) -- --ndctl_keysdir=${sysconfdir}/ndctl/keys --ndctl_keysreadme=keys.readme --AC_SUBST([ndctl_keysdir]) --AC_SUBST([ndctl_keysreadme]) -- --my_CFLAGS="\ ---Wall \ ---Wchar-subscripts \ ---Wformat-security \ ---Wmissing-declarations \ ---Wmissing-prototypes \ ---Wnested-externs \ ---Wshadow \ ---Wsign-compare \ ---Wstrict-prototypes \ ---Wtype-limits \ ---Wmaybe-uninitialized \ ---Wdeclaration-after-statement \ ---Wunused-result \ ---D_FORTIFY_SOURCE=2 \ ---O2 --" --AC_SUBST([my_CFLAGS]) -- --AC_CONFIG_HEADERS(config.h) --AC_CONFIG_FILES([ -- Makefile -- daxctl/lib/Makefile -- cxl/lib/Makefile -- ndctl/lib/Makefile -- ndctl/Makefile -- daxctl/Makefile -- cxl/Makefile -- test/Makefile -- Documentation/ndctl/Makefile -- Documentation/daxctl/Makefile -- Documentation/cxl/Makefile -- Documentation/cxl/lib/Makefile --]) -- --AC_OUTPUT --AC_MSG_RESULT([ -- $PACKAGE $VERSION -- ===== -- -- prefix: ${prefix} -- sysconfdir: ${sysconfdir} -- libdir: ${libdir} -- includedir: ${includedir} -- -- compiler: ${CC} -- cflags: ${CFLAGS} -- ldflags: ${LDFLAGS} -- -- logging: ${enable_logging} -- debug: ${enable_debug} --]) -diff -up ndctl-71.1/cxl/Makefile.am /dev/null ---- ndctl-71.1/cxl/Makefile.am 2022-10-07 18:39:13.131886476 -0400 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,25 +0,0 @@ --include $(top_srcdir)/Makefile.am.in -- --bin_PROGRAMS = cxl -- --DISTCLEANFILES = config.h --BUILT_SOURCES = config.h --config.h: $(srcdir)/Makefile.am -- $(AM_V_GEN) echo "/* Autogenerated by cxl/Makefile.am */" >$@ -- --cxl_SOURCES =\ -- cxl.c \ -- list.c \ -- memdev.c \ -- ../util/json.c \ -- json.c \ -- filter.c \ -- filter.h \ -- builtin.h -- --cxl_LDADD =\ -- lib/libcxl.la \ -- ../libutil.a \ -- $(UUID_LIBS) \ -- $(KMOD_LIBS) \ -- $(JSON_LIBS) -diff -up ndctl-71.1/cxl/lib/Makefile.am /dev/null ---- ndctl-71.1/cxl/lib/Makefile.am 2022-10-07 18:39:13.041886169 -0400 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,32 +0,0 @@ --include $(top_srcdir)/Makefile.am.in -- --%.pc: %.pc.in Makefile -- $(SED_PROCESS) -- --pkginclude_HEADERS = ../libcxl.h ../cxl_mem.h --lib_LTLIBRARIES = libcxl.la -- --libcxl_la_SOURCES =\ -- ../libcxl.h \ -- private.h \ -- ../../util/sysfs.c \ -- ../../util/sysfs.h \ -- ../../util/log.c \ -- ../../util/log.h \ -- libcxl.c -- --libcxl_la_LIBADD =\ -- $(UUID_LIBS) \ -- $(KMOD_LIBS) -- --EXTRA_DIST += libcxl.sym -- --libcxl_la_LDFLAGS = $(AM_LDFLAGS) \ -- -version-info $(LIBCXL_CURRENT):$(LIBCXL_REVISION):$(LIBCXL_AGE) \ -- -Wl,--version-script=$(top_srcdir)/cxl/lib/libcxl.sym --libcxl_la_DEPENDENCIES = libcxl.sym -- --pkgconfigdir = $(libdir)/pkgconfig --pkgconfig_DATA = libcxl.pc --EXTRA_DIST += libcxl.pc.in --CLEANFILES += libcxl.pc -diff -up ndctl-71.1/daxctl/Makefile.am /dev/null ---- ndctl-71.1/daxctl/Makefile.am 2022-10-07 18:39:13.132886479 -0400 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,33 +0,0 @@ --include $(top_srcdir)/Makefile.am.in -- --bin_PROGRAMS = daxctl -- --DISTCLEANFILES = config.h --BUILT_SOURCES = config.h --config.h: $(srcdir)/Makefile.am -- $(AM_V_GEN) echo "/* Autogenerated by daxctl/Makefile.am */" >$@ && \ -- echo '#define DAXCTL_MODPROBE_DATA \ -- "$(daxctl_modprobe_datadir)/$(daxctl_modprobe_data)"' >>$@ && \ -- echo '#define DAXCTL_MODPROBE_INSTALL \ -- "$(sysconfdir)/modprobe.d/$(daxctl_modprobe_data)"' >>$@ -- --daxctl_SOURCES =\ -- daxctl.c \ -- acpi.c \ -- list.c \ -- migrate.c \ -- device.c \ -- ../util/json.c \ -- ../util/json.h \ -- json.c \ -- json.h \ -- filter.c \ -- filter.h \ -- builtin.h -- --daxctl_LDADD =\ -- lib/libdaxctl.la \ -- ../libutil.a \ -- $(UUID_LIBS) \ -- $(KMOD_LIBS) \ -- $(JSON_LIBS) -diff -up ndctl-71.1/daxctl/lib/Makefile.am /dev/null ---- ndctl-71.1/daxctl/lib/Makefile.am 2020-12-22 16:44:57.000000000 -0500 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,36 +0,0 @@ --include $(top_srcdir)/Makefile.am.in -- --%.pc: %.pc.in Makefile -- $(SED_PROCESS) -- --pkginclude_HEADERS = ../libdaxctl.h --lib_LTLIBRARIES = libdaxctl.la -- --libdaxctl_la_SOURCES =\ -- ../libdaxctl.h \ -- libdaxctl-private.h \ -- ../../util/iomem.c \ -- ../../util/iomem.h \ -- ../../util/sysfs.c \ -- ../../util/sysfs.h \ -- ../../util/log.c \ -- ../../util/log.h \ -- libdaxctl.c -- --libdaxctl_la_LIBADD =\ -- $(UUID_LIBS) \ -- $(KMOD_LIBS) -- --daxctl_modprobe_data_DATA = daxctl.conf -- --EXTRA_DIST += libdaxctl.sym daxctl.conf -- --libdaxctl_la_LDFLAGS = $(AM_LDFLAGS) \ -- -version-info $(LIBDAXCTL_CURRENT):$(LIBDAXCTL_REVISION):$(LIBDAXCTL_AGE) \ -- -Wl,--version-script=$(top_srcdir)/daxctl/lib/libdaxctl.sym --libdaxctl_la_DEPENDENCIES = libdaxctl.sym -- --pkgconfigdir = $(libdir)/pkgconfig --pkgconfig_DATA = libdaxctl.pc --EXTRA_DIST += libdaxctl.pc.in --CLEANFILES += libdaxctl.pc -diff -up ndctl-71.1/ndctl.spec.in.orig ndctl-71.1/ndctl.spec.in ---- ndctl-71.1/ndctl.spec.in.orig 2022-10-07 18:39:13.183886653 -0400 -+++ ndctl-71.1/ndctl.spec.in 2022-10-07 18:44:39.333997092 -0400 -@@ -6,21 +6,16 @@ License: GPLv2 - Url: https://github.com/pmem/ndctl - Source0: https://github.com/pmem/%{name}/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz - --%define with_meson MESON - Requires: LNAME%{?_isa} = %{version}-%{release} - Requires: DAX_LNAME%{?_isa} = %{version}-%{release} - Requires: CXL_LNAME%{?_isa} = %{version}-%{release} - BuildRequires: autoconf - %if 0%{?rhel} < 9 - BuildRequires: asciidoc --%if !%{with_meson} --%define asciidoc --disable-asciidoctor --%endif -+%define asciidoctor -Dasciidoctor=disabled - %else --%if %{with_meson} --%define asciidoctor -Dasciidoctor=enabled --%endif - BuildRequires: rubygem-asciidoctor -+%define asciidoctor -Dasciidoctor=enabled - %endif - BuildRequires: xmlto - BuildRequires: automake -@@ -34,9 +29,7 @@ BuildRequires: pkgconfig(bash-completion - BuildRequires: pkgconfig(systemd) - BuildRequires: keyutils-libs-devel - --%if %{with_meson} - BuildRequires: meson --%endif - - %description - Utility library for managing the "libnvdimm" subsystem. The "libnvdimm" -@@ -125,30 +118,14 @@ libcxl is a library for enumerating and - %setup -q ndctl-%{version} - - %build --%if %{with_meson} - %meson %{?asciidoctor} -Dversion-tag=%{version} - %meson_build --%else --echo %{version} > version --./autogen.sh --%configure --disable-static --disable-silent-rules %{?asciidoc} --make %{?_smp_mflags} --%endif - - %install --%if %{with_meson} - %meson_install --%else --%make_install --find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' --%endif - - %check --%if %{with_meson} - %meson_test --%else --make check --%endif - - %ldconfig_scriptlets -n LNAME - -diff -up ndctl-71.1/ndctl/Makefile.am /dev/null ---- ndctl-71.1/ndctl/Makefile.am 2022-10-07 18:39:13.135886489 -0400 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,83 +0,0 @@ --include $(top_srcdir)/Makefile.am.in -- --bin_PROGRAMS = ndctl -- --DISTCLEANFILES = config.h --BUILT_SOURCES = config.h --config.h: $(srcdir)/Makefile.am -- $(AM_V_GEN) echo "/* Autogenerated by ndctl/Makefile.am */" >$@ && \ -- echo '#define NDCTL_CONF_FILE \ -- "$(ndctl_monitorconfdir)/$(ndctl_monitorconf)"' >>$@ -- $(AM_V_GEN) echo '#define NDCTL_KEYS_DIR "$(ndctl_keysdir)"' >>$@ -- --ndctl_SOURCES = ndctl.c \ -- builtin.h \ -- bus.c \ -- create-nfit.c \ -- namespace.c \ -- check.c \ -- region.c \ -- dimm.c \ -- ../util/log.c \ -- ../daxctl/filter.c \ -- ../daxctl/filter.h \ -- filter.c \ -- filter.h \ -- list.c \ -- ../util/json.c \ -- ../util/json.h \ -- ../daxctl/json.c \ -- ../daxctl/json.h \ -- json.c \ -- json.h \ -- json-smart.c \ -- keys.h \ -- inject-error.c \ -- inject-smart.c \ -- monitor.c \ -- namespace.h \ -- action.h \ -- ../nfit.h \ -- ../test.h \ -- firmware-update.h -- --if ENABLE_KEYUTILS --ndctl_SOURCES += keys.c \ -- load-keys.c --keys_configdir = $(ndctl_keysdir) --keys_config_DATA = $(ndctl_keysreadme) --endif -- --EXTRA_DIST += keys.readme monitor.conf ndctl-monitor.service -- --if ENABLE_DESTRUCTIVE --ndctl_SOURCES += ../test/pmem_namespaces.c --ndctl_SOURCES += bat.c --endif -- --ndctl_LDADD =\ -- lib/libndctl.la \ -- ../daxctl/lib/libdaxctl.la \ -- ../libutil.a \ -- $(UUID_LIBS) \ -- $(KMOD_LIBS) \ -- $(JSON_LIBS) -- --if ENABLE_KEYUTILS --ndctl_LDADD += -lkeyutils --endif -- --if ENABLE_TEST --ndctl_SOURCES += ../test/libndctl.c \ -- ../test/dsm-fail.c \ -- ../util/sysfs.c \ -- ../test/core.c \ -- test.c --endif -- --monitor_configdir = $(ndctl_monitorconfdir) --monitor_config_DATA = $(ndctl_monitorconf) -- --if ENABLE_SYSTEMD_UNITS --systemd_unit_DATA = ndctl-monitor.service --endif -diff -up ndctl-71.1/ndctl/lib/Makefile.am /dev/null ---- ndctl-71.1/ndctl/lib/Makefile.am 2020-12-22 16:44:57.000000000 -0500 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,52 +0,0 @@ --include $(top_srcdir)/Makefile.am.in -- --%.pc: %.pc.in Makefile -- $(SED_PROCESS) -- --pkginclude_HEADERS = ../libndctl.h ../ndctl.h --lib_LTLIBRARIES = libndctl.la -- --libndctl_la_SOURCES =\ -- ../libndctl.h \ -- private.h \ -- ../../util/list.h \ -- ../../util/log.c \ -- ../../util/log.h \ -- ../../util/sysfs.c \ -- ../../util/sysfs.h \ -- ../../util/fletcher.h \ -- dimm.c \ -- inject.c \ -- nfit.c \ -- smart.c \ -- intel.c \ -- hpe1.c \ -- msft.c \ -- hyperv.c \ -- papr.c \ -- ars.c \ -- firmware.c \ -- libndctl.c \ -- intel.h \ -- hpe1.h \ -- msft.h \ -- hyperv.h \ -- ../../ndctl/libndctl-nfit.h -- --libndctl_la_LIBADD =\ -- ../../daxctl/lib/libdaxctl.la \ -- $(UDEV_LIBS) \ -- $(UUID_LIBS) \ -- $(KMOD_LIBS) -- --EXTRA_DIST += libndctl.sym -- --libndctl_la_LDFLAGS = $(AM_LDFLAGS) \ -- -version-info $(LIBNDCTL_CURRENT):$(LIBNDCTL_REVISION):$(LIBNDCTL_AGE) \ -- -Wl,--version-script=$(top_srcdir)/ndctl/lib/libndctl.sym --libndctl_la_DEPENDENCIES = libndctl.sym -- --pkgconfigdir = $(libdir)/pkgconfig --pkgconfig_DATA = libndctl.pc --EXTRA_DIST += libndctl.pc.in --CLEANFILES += libndctl.pc -diff -up ndctl-71.1/rhel/meson.build.orig ndctl-71.1/rhel/meson.build ---- ndctl-71.1/rhel/meson.build.orig 2022-10-07 18:39:13.184886656 -0400 -+++ ndctl-71.1/rhel/meson.build 2022-10-07 18:41:13.892297627 -0400 -@@ -7,8 +7,7 @@ rhel_spec1 = vcs_tag( - - rhel_spec2 = custom_target('ndctl.spec', - command : [ -- 'sed', '-e', 's,MESON,1,g', -- '-e', 's,DAX_DNAME,daxctl-devel,g', -+ 'sed', '-e', 's,DAX_DNAME,daxctl-devel,g', - '-e', 's,CXL_DNAME,cxl-devel,g', - '-e', 's,DNAME,ndctl-devel,g', - '-e', '/^%defattr.*/d', -diff -up ndctl-71.1/sles/meson.build.orig ndctl-71.1/sles/meson.build ---- ndctl-71.1/sles/meson.build.orig 2022-10-07 18:39:13.184886656 -0400 -+++ ndctl-71.1/sles/meson.build 2022-10-07 18:41:13.893297631 -0400 -@@ -18,8 +18,7 @@ sles_spec2 = custom_target('ndctl.spec.i - - sles_spec3 = custom_target('ndctl.spec', - command : [ -- 'sed', '-e', 's,MESON,1,g', -- '-e', 's,DAX_DNAME,libdaxctl-devel,g', -+ 'sed', '-e', 's,DAX_DNAME,libdaxctl-devel,g', - '-e', 's,CXL_DNAME,libcxl-devel,g', - '-e', 's,DNAME,libndctl-devel,g', - '-e', 's,%license,%doc,g', -diff -up ndctl-71.1/test/Makefile.am /dev/null ---- ndctl-71.1/test/Makefile.am 2022-10-07 18:39:13.146886527 -0400 -+++ /dev/null 2022-07-27 11:30:34.495212588 -0400 -@@ -1,169 +0,0 @@ --include $(top_srcdir)/Makefile.am.in -- --TESTS =\ -- libndctl \ -- dsm-fail \ -- create.sh \ -- clear.sh \ -- pmem-errors.sh \ -- daxdev-errors.sh \ -- multi-dax.sh \ -- btt-check.sh \ -- label-compat.sh \ -- sector-mode.sh \ -- inject-error.sh \ -- btt-errors.sh \ -- hugetlb \ -- btt-pad-compat.sh \ -- firmware-update.sh \ -- ack-shutdown-count-set \ -- rescan-partitions.sh \ -- inject-smart.sh \ -- monitor.sh \ -- max_available_extent_ns.sh \ -- pfn-meta-errors.sh \ -- track-uuid.sh -- --EXTRA_DIST += $(TESTS) common \ -- btt-pad-compat.xxd \ -- nmem1.bin nmem2.bin nmem3.bin nmem4.bin -- --check_PROGRAMS =\ -- libndctl \ -- dsm-fail \ -- dax-errors \ -- smart-notify \ -- smart-listen \ -- hugetlb \ -- daxdev-errors \ -- ack-shutdown-count-set \ -- list-smart-dimm -- --if ENABLE_DESTRUCTIVE --TESTS +=\ -- pmem-ns \ -- sub-section.sh \ -- dax-dev \ -- dax-ext4.sh \ -- dax-xfs.sh \ -- align.sh \ -- device-dax \ -- revoke-devmem \ -- device-dax-fio.sh \ -- daxctl-devices.sh \ -- daxctl-create.sh \ -- dm.sh \ -- mmap.sh -- --if ENABLE_KEYUTILS --TESTS += security.sh --endif -- --check_PROGRAMS +=\ -- pmem-ns \ -- dax-dev \ -- dax-pmd \ -- device-dax \ -- revoke-devmem \ -- mmap --endif -- --LIBNDCTL_LIB =\ -- ../ndctl/lib/libndctl.la \ -- ../daxctl/lib/libdaxctl.la -- --testcore =\ -- core.c \ -- ../util/log.c \ -- ../util/sysfs.c -- --libndctl_SOURCES = libndctl.c $(testcore) --libndctl_LDADD = $(LIBNDCTL_LIB) $(UUID_LIBS) $(KMOD_LIBS) -- --namespace_core =\ -- ../ndctl/namespace.c \ -- ../ndctl/filter.c \ -- ../ndctl/check.c \ -- ../util/json.c \ -- ../ndctl/json.c \ -- ../daxctl/filter.c \ -- ../daxctl/json.c -- --dsm_fail_SOURCES =\ -- dsm-fail.c \ -- $(testcore) \ -- $(namespace_core) -- --dsm_fail_LDADD = $(LIBNDCTL_LIB) \ -- $(KMOD_LIBS) \ -- $(JSON_LIBS) \ -- $(UUID_LIBS) \ -- ../libutil.a -- --ack_shutdown_count_set_SOURCES =\ -- ack-shutdown-count-set.c \ -- $(testcore) -- --ack_shutdown_count_set_LDADD = $(LIBNDCTL_LIB) $(KMOD_LIBS) -- --pmem_ns_SOURCES = pmem_namespaces.c $(testcore) --pmem_ns_LDADD = $(LIBNDCTL_LIB) $(KMOD_LIBS) $(UUID_LIBS) -- --dax_dev_SOURCES = dax-dev.c $(testcore) --dax_dev_LDADD = $(LIBNDCTL_LIB) $(KMOD_LIBS) -- --dax_pmd_SOURCES = dax-pmd.c \ -- $(testcore) -- --hugetlb_SOURCES = hugetlb.c \ -- dax-pmd.c -- --mmap_SOURCES = mmap.c --dax_errors_SOURCES = dax-errors.c --daxdev_errors_SOURCES = daxdev-errors.c \ -- ../util/log.c \ -- ../util/sysfs.c --daxdev_errors_LDADD = $(LIBNDCTL_LIB) --device_dax_SOURCES = \ -- device-dax.c \ -- dax-dev.c \ -- dax-pmd.c \ -- $(testcore) \ -- $(namespace_core) -- --if ENABLE_POISON --dax_pmd_SOURCES += dax-poison.c --hugetlb_SOURCES += dax-poison.c --device_dax_SOURCES += dax-poison.c --endif -- --device_dax_LDADD = \ -- $(LIBNDCTL_LIB) \ -- $(KMOD_LIBS) \ -- $(JSON_LIBS) \ -- $(UUID_LIBS) \ -- ../libutil.a -- --revoke_devmem_SOURCES = \ -- revoke-devmem.c \ -- dax-dev.c \ -- $(testcore) -- --revoke_devmem_LDADD = $(LIBNDCTL_LIB) -- --smart_notify_SOURCES = smart-notify.c --smart_notify_LDADD = $(LIBNDCTL_LIB) --smart_listen_SOURCES = smart-listen.c --smart_listen_LDADD = $(LIBNDCTL_LIB) -- --list_smart_dimm_SOURCES = \ -- list-smart-dimm.c \ -- ../ndctl/filter.c \ -- ../util/json.c \ -- ../ndctl/json.c -- --list_smart_dimm_LDADD = \ -- $(LIBNDCTL_LIB) \ -- $(JSON_LIBS) \ -- $(UUID_LIBS) \ -- ../libutil.a diff --git a/SOURCES/0085-ndctl-build-Default-asciidoctor-to-enabled.patch b/SOURCES/0085-ndctl-build-Default-asciidoctor-to-enabled.patch deleted file mode 100644 index da73810..0000000 --- a/SOURCES/0085-ndctl-build-Default-asciidoctor-to-enabled.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 3a8d6e4bc90e899f751b881dc949e79daeeb04bb Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Fri, 7 Jan 2022 11:31:06 -0800 -Subject: [PATCH 085/217] ndctl/build: Default asciidoctor to enabled - -The autotools build infra previously defaulted asciidoctor to enabled, do -the same for Meson. - -Link: https://lore.kernel.org/r/164158386600.302694.5479584050156277551.stgit@dwillia2-desk3.amr.corp.intel.com -Reported-by: Vishal Verma -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - meson_options.txt | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/meson_options.txt b/meson_options.txt -index 95312bf..aa4a6dc 100644 ---- a/meson_options.txt -+++ b/meson_options.txt -@@ -1,7 +1,7 @@ - option('version-tag', type : 'string', - description : 'override the git version string') - option('docs', type : 'feature', value : 'enabled') --option('asciidoctor', type : 'feature', value : 'disabled') -+option('asciidoctor', type : 'feature', value : 'enabled') - option('systemd', type : 'feature', value : 'enabled') - option('keyutils', type : 'feature', value : 'enabled', - description : 'enable nvdimm device passphrase management') --- -2.27.0 - diff --git a/SOURCES/0086-ndctl-update-README.md-for-meson-build.patch b/SOURCES/0086-ndctl-update-README.md-for-meson-build.patch deleted file mode 100644 index 5daeb48..0000000 --- a/SOURCES/0086-ndctl-update-README.md-for-meson-build.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 351badda9e5b6454e56f31992e9325c4656680bd Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Fri, 14 Jan 2022 18:32:29 -0700 -Subject: [PATCH 086/217] ndctl: update README.md for meson build - -Update the README to replace the autotools build and test instructions -with meson equivalents. Also provide an example for setting meson -configuration options by illustrating the destructive unit tests use -case. - -Link: https://lore.kernel.org/r/20220115013229.1604139-1-vishal.l.verma@intel.com -Cc: Dan Williams -Reported-by: Alison Schofield -Reported-by: Jane Chu -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - README.md | 33 ++++++++++++++++++++++----------- - 1 file changed, 22 insertions(+), 11 deletions(-) - -diff --git a/README.md b/README.md -index 6f36a6d..f3fe65b 100644 ---- a/README.md -+++ b/README.md -@@ -9,11 +9,14 @@ Build - ===== - - ``` --./autogen.sh --./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64 --make --make check --sudo make install -+meson setup build; -+meson compile -C build; -+``` -+ -+Optionally, to install: -+ -+``` -+meson install -C build - ``` - - There are a number of packages required for the build steps that may not -@@ -34,7 +37,7 @@ https://nvdimm.wiki.kernel.org/start - - Unit Tests - ========== --The unit tests run by `make check` require the nfit_test.ko module to be -+The unit tests run by `meson test` require the nfit_test.ko module to be - loaded. To build and install nfit_test.ko: - - 1. Obtain the kernel source. For example, -@@ -78,8 +81,16 @@ loaded. To build and install nfit_test.ko: - sudo make modules_install - ``` - --1. Now run `make check` in the ndctl source directory, or `ndctl test`, -- if ndctl was built with `--enable-test`. -+1. Now run `meson test -C build` in the ndctl source directory, or `ndctl test`, -+ if ndctl was built with `-Dtest=enabled` as a configuration option to meson. -+ -+1. To run the 'destructive' set of tests that may clobber existing pmem -+ configurations and data, configure meson with the destructive option after the -+ `meson setup` step: -+ -+ ``` -+ meson configure -Dtest=enabled -Ddestructive=enabled build; -+ ``` - - Troubleshooting - =============== -@@ -87,9 +98,9 @@ Troubleshooting - The unit tests will validate that the environment is set up correctly - before they try to run. If the platform is misconfigured, i.e. the unit - test modules are not available, or the test versions of the modules are --superseded by the "in-tree/production" version of the modules `make --check` will skip tests and report a message like the following in --test/test-suite.log: -+superseded by the "in-tree/production" version of the modules `meson -+test` will skip tests and report a message like the following in -+`build/meson-logs/testlog.txt` - - ``` - SKIP: libndctl --- -2.27.0 - diff --git a/SOURCES/0087-test-Add-suite-identifiers-to-tests.patch b/SOURCES/0087-test-Add-suite-identifiers-to-tests.patch deleted file mode 100644 index 685d590..0000000 --- a/SOURCES/0087-test-Add-suite-identifiers-to-tests.patch +++ /dev/null @@ -1,122 +0,0 @@ -From a61377ecf015929de27a665d0b5c937315f9e4aa Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:51:54 -0800 -Subject: [PATCH 087/217] test: Add 'suite' identifiers to tests - -In preparation for adding CXL tests, and in anticipation of wanting to only -run the CXL tests, label each test with a suite id. - -Link: https://lore.kernel.org/r/164298551461.3021641.4591877842309963514.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/meson.build | 73 ++++++++++++++++++++++++------------------------ - 1 file changed, 37 insertions(+), 36 deletions(-) - -diff --git a/test/meson.build b/test/meson.build -index 94287aa..07a5bb6 100644 ---- a/test/meson.build -+++ b/test/meson.build -@@ -152,28 +152,28 @@ pfn_meta_errors = find_program('pfn-meta-errors.sh') - track_uuid = find_program('track-uuid.sh') - - tests = [ -- [ 'libndctl', libndctl ], -- [ 'dsm-fail', dsm_fail ], -- [ 'create.sh', create ], -- [ 'clear.sh', clear ], -- [ 'pmem-errors.sh', pmem_errors ], -- [ 'daxdev-errors.sh', daxdev_errors_sh ], -- [ 'multi-dax.sh', multi_dax ], -- [ 'btt-check.sh', btt_check ], -- [ 'label-compat.sh', label_compat ], -- [ 'sector-mode.sh', sector_mode ], -- [ 'inject-error.sh', inject_error ], -- [ 'btt-errors.sh', btt_errors ], -- [ 'hugetlb', hugetlb ], -- [ 'btt-pad-compat.sh', btt_pad_compat ], -- [ 'firmware-update.sh', firmware_update ], -- [ 'ack-shutdown-count-set', ack_shutdown_count ], -- [ 'rescan-partitions.sh', rescan_partitions ], -- [ 'inject-smart.sh', inject_smart ], -- [ 'monitor.sh', monitor ], -- [ 'max_extent_ns', max_extent ], -- [ 'pfn-meta-errors.sh', pfn_meta_errors ], -- [ 'track-uuid.sh', track_uuid ], -+ [ 'libndctl', libndctl, 'ndctl' ], -+ [ 'dsm-fail', dsm_fail, 'ndctl' ], -+ [ 'create.sh', create, 'ndctl' ], -+ [ 'clear.sh', clear, 'ndctl' ], -+ [ 'pmem-errors.sh', pmem_errors, 'ndctl' ], -+ [ 'daxdev-errors.sh', daxdev_errors_sh, 'dax' ], -+ [ 'multi-dax.sh', multi_dax, 'dax' ], -+ [ 'btt-check.sh', btt_check, 'ndctl' ], -+ [ 'label-compat.sh', label_compat, 'ndctl' ], -+ [ 'sector-mode.sh', sector_mode, 'ndctl' ], -+ [ 'inject-error.sh', inject_error, 'ndctl' ], -+ [ 'btt-errors.sh', btt_errors, 'ndctl' ], -+ [ 'hugetlb', hugetlb, 'ndctl' ], -+ [ 'btt-pad-compat.sh', btt_pad_compat, 'ndctl' ], -+ [ 'firmware-update.sh', firmware_update, 'ndctl' ], -+ [ 'ack-shutdown-count-set', ack_shutdown_count, 'ndctl' ], -+ [ 'rescan-partitions.sh', rescan_partitions, 'ndctl' ], -+ [ 'inject-smart.sh', inject_smart, 'ndctl' ], -+ [ 'monitor.sh', monitor, 'ndctl' ], -+ [ 'max_extent_ns', max_extent, 'ndctl' ], -+ [ 'pfn-meta-errors.sh', pfn_meta_errors, 'ndctl' ], -+ [ 'track-uuid.sh', track_uuid, 'ndctl' ], - ] - - if get_option('destructive').enabled() -@@ -188,26 +188,26 @@ if get_option('destructive').enabled() - mmap_test = find_program('mmap.sh') - - tests += [ -- [ 'pmem-ns', pmem_ns ], -- [ 'sub-section.sh', sub_section ], -- [ 'dax-dev', dax_dev ], -- [ 'dax-ext4.sh', dax_ext4 ], -- [ 'dax-xfs.sh', dax_xfs ], -- [ 'align.sh', align ], -- [ 'device-dax', device_dax ], -- [ 'revoke-devmem', revoke_devmem ], -- [ 'device-dax-fio.sh', device_dax_fio ], -- [ 'daxctl-devices.sh', daxctl_devices ], -- [ 'daxctl-create.sh', daxctl_create ], -- [ 'dm.sh', dm ], -- [ 'mmap.sh', mmap_test ], -+ [ 'pmem-ns', pmem_ns, 'ndctl' ], -+ [ 'sub-section.sh', sub_section, 'dax' ], -+ [ 'dax-dev', dax_dev, 'dax' ], -+ [ 'dax-ext4.sh', dax_ext4, 'dax' ], -+ [ 'dax-xfs.sh', dax_xfs, 'dax' ], -+ [ 'align.sh', align, 'ndctl' ], -+ [ 'device-dax', device_dax, 'dax' ], -+ [ 'revoke-devmem', revoke_devmem, 'dax' ], -+ [ 'device-dax-fio.sh', device_dax_fio, 'dax' ], -+ [ 'daxctl-devices.sh', daxctl_devices, 'dax' ], -+ [ 'daxctl-create.sh', daxctl_create, 'dax' ], -+ [ 'dm.sh', dm, 'dax' ], -+ [ 'mmap.sh', mmap_test, 'dax' ], - ] - endif - - if get_option('keyutils').enabled() - security = find_program('security.sh') - tests += [ -- [ 'security.sh', security ] -+ [ 'security.sh', security, 'ndctl' ] - ] - endif - -@@ -226,6 +226,7 @@ foreach t : tests - dax_dev, - mmap, - ], -+ suite: t[2], - timeout : 0, - env : [ - 'NDCTL=@0@'.format(ndctl_tool.full_path()), --- -2.27.0 - diff --git a/SOURCES/0088-ndctl-Rename-util_filter-to-ndctl_filter.patch b/SOURCES/0088-ndctl-Rename-util_filter-to-ndctl_filter.patch deleted file mode 100644 index 8f05501..0000000 --- a/SOURCES/0088-ndctl-Rename-util_filter-to-ndctl_filter.patch +++ /dev/null @@ -1,287 +0,0 @@ -From d7c5fa695a91d66485ca1febd6f29c3a483e20f6 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:52:00 -0800 -Subject: [PATCH 088/217] ndctl: Rename util_filter to ndctl_filter - -In preparation for introducing a cxl_filter_walk() implementation rename -the current filter_walk infrastructure with an ndctl_ prefix. - -Link: https://lore.kernel.org/r/164298552014.3021641.16369576632179722489.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - ndctl/filter.c | 4 ++-- - ndctl/filter.h | 21 +++++++++++---------- - ndctl/list.c | 14 +++++++------- - ndctl/monitor.c | 12 ++++++------ - test/list-smart-dimm.c | 12 ++++++------ - 5 files changed, 32 insertions(+), 31 deletions(-) - -diff -up ndctl-71.1/ndctl/filter.c.orig ndctl-71.1/ndctl/filter.c ---- ndctl-71.1/ndctl/filter.c.orig 2022-10-07 17:54:40.799788014 -0400 -+++ ndctl-71.1/ndctl/filter.c 2022-10-07 17:54:52.592828166 -0400 -@@ -338,8 +338,8 @@ const char *util_nsmode_name(enum ndctl_ - return modes[mode]; - } - --int util_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx, -- struct util_filter_params *param) -+int ndctl_filter_walk(struct ndctl_ctx *ctx, struct ndctl_filter_ctx *fctx, -+ struct ndctl_filter_params *param) - { - struct ndctl_bus *bus; - unsigned int type = 0; -diff -up ndctl-71.1/ndctl/filter.h.orig ndctl-71.1/ndctl/filter.h ---- ndctl-71.1/ndctl/filter.h.orig 2022-10-07 17:54:40.799788014 -0400 -+++ ndctl-71.1/ndctl/filter.h 2022-10-07 17:54:52.593828169 -0400 -@@ -31,7 +31,7 @@ const char *util_nsmode_name(enum ndctl_ - - struct json_object; - --/* json object hierarchy for the util_filter_walk() performed by cmd_list() */ -+/* json object hierarchy for the ndctl_filter_walk() performed by cmd_list() */ - struct list_filter_arg { - struct json_object *jnamespaces; - struct json_object *jregions; -@@ -50,19 +50,20 @@ struct monitor_filter_arg { - }; - - /* -- * struct util_filter_ctx - control and callbacks for util_filter_walk() -+ * struct ndctl_filter_ctx - control and callbacks for ndctl_filter_walk() - * ->filter_bus() and ->filter_region() return bool because the - * child-object filter routines can not be called if the parent context - * is not established. ->filter_dimm() and ->filter_namespace() are leaf - * objects, so no child dependencies to check. - */ --struct util_filter_ctx { -- bool (*filter_bus)(struct ndctl_bus *bus, struct util_filter_ctx *ctx); -- void (*filter_dimm)(struct ndctl_dimm *dimm, struct util_filter_ctx *ctx); -+struct ndctl_filter_ctx { -+ bool (*filter_bus)(struct ndctl_bus *bus, struct ndctl_filter_ctx *ctx); -+ void (*filter_dimm)(struct ndctl_dimm *dimm, -+ struct ndctl_filter_ctx *ctx); - bool (*filter_region)(struct ndctl_region *region, -- struct util_filter_ctx *ctx); -+ struct ndctl_filter_ctx *ctx); - void (*filter_namespace)(struct ndctl_namespace *ndns, -- struct util_filter_ctx *ctx); -+ struct ndctl_filter_ctx *ctx); - union { - void *arg; - struct list_filter_arg *list; -@@ -70,7 +71,7 @@ struct util_filter_ctx { - }; - }; - --struct util_filter_params { -+struct ndctl_filter_params { - const char *bus; - const char *region; - const char *type; -@@ -81,6 +82,6 @@ struct util_filter_params { - }; - - struct ndctl_ctx; --int util_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx, -- struct util_filter_params *param); -+int ndctl_filter_walk(struct ndctl_ctx *ctx, struct ndctl_filter_ctx *fctx, -+ struct ndctl_filter_params *param); - #endif /* _NDCTL_UTIL_FILTER_H_ */ -diff -up ndctl-71.1/ndctl/list.c.orig ndctl-71.1/ndctl/list.c ---- ndctl-71.1/ndctl/list.c.orig 2022-10-07 17:54:40.806788038 -0400 -+++ ndctl-71.1/ndctl/list.c 2022-10-07 17:54:52.593828169 -0400 -@@ -55,7 +55,7 @@ static unsigned long listopts_to_flags(v - return flags; - } - --static struct util_filter_params param; -+static struct ndctl_filter_params param; - - static int did_fail; - -@@ -234,7 +234,7 @@ static struct json_object *region_to_jso - } - - static void filter_namespace(struct ndctl_namespace *ndns, -- struct util_filter_ctx *ctx) -+ struct ndctl_filter_ctx *ctx) - { - struct json_object *jndns; - struct list_filter_arg *lfa = ctx->list; -@@ -272,7 +272,7 @@ static void filter_namespace(struct ndct - } - - static bool filter_region(struct ndctl_region *region, -- struct util_filter_ctx *ctx) -+ struct ndctl_filter_ctx *ctx) - { - struct list_filter_arg *lfa = ctx->list; - struct json_object *jbus = lfa->jbus; -@@ -318,7 +318,7 @@ static bool filter_region(struct ndctl_r - return true; - } - --static void filter_dimm(struct ndctl_dimm *dimm, struct util_filter_ctx *ctx) -+static void filter_dimm(struct ndctl_dimm *dimm, struct ndctl_filter_ctx *ctx) - { - struct list_filter_arg *lfa = ctx->list; - struct json_object *jdimm; -@@ -367,7 +367,7 @@ static void filter_dimm(struct ndctl_dim - json_object_array_add(lfa->jdimms, jdimm); - } - --static bool filter_bus(struct ndctl_bus *bus, struct util_filter_ctx *ctx) -+static bool filter_bus(struct ndctl_bus *bus, struct ndctl_filter_ctx *ctx) - { - struct list_filter_arg *lfa = ctx->list; - -@@ -489,7 +489,7 @@ int cmd_list(int argc, const char **argv - NULL - }; - bool lint = !!secure_getenv("NDCTL_LIST_LINT"); -- struct util_filter_ctx fctx = { 0 }; -+ struct ndctl_filter_ctx fctx = { 0 }; - struct list_filter_arg lfa = { 0 }; - int i, rc; - -@@ -544,7 +544,7 @@ int cmd_list(int argc, const char **argv - fctx.list = &lfa; - lfa.flags = listopts_to_flags(); - -- rc = util_filter_walk(ctx, &fctx, ¶m); -+ rc = ndctl_filter_walk(ctx, &fctx, ¶m); - if (rc) - return rc; - -diff -up ndctl-71.1/ndctl/monitor.c.orig ndctl-71.1/ndctl/monitor.c ---- ndctl-71.1/ndctl/monitor.c.orig 2022-10-07 17:54:40.824788100 -0400 -+++ ndctl-71.1/ndctl/monitor.c 2022-10-07 17:55:08.025880711 -0400 -@@ -48,7 +48,7 @@ struct monitor_dimm { - struct list_node list; - }; - --static struct util_filter_params param; -+static struct ndctl_filter_params param; - - static int did_fail; - -@@ -263,12 +263,12 @@ out: - } - - static bool filter_region(struct ndctl_region *region, -- struct util_filter_ctx *fctx) -+ struct ndctl_filter_ctx *fctx) - { - return true; - } - --static void filter_dimm(struct ndctl_dimm *dimm, struct util_filter_ctx *fctx) -+static void filter_dimm(struct ndctl_dimm *dimm, struct ndctl_filter_ctx *fctx) - { - struct monitor_dimm *mdimm; - struct monitor_filter_arg *mfa = fctx->monitor; -@@ -316,7 +316,7 @@ static void filter_dimm(struct ndctl_dim - return; - } - --static bool filter_bus(struct ndctl_bus *bus, struct util_filter_ctx *fctx) -+static bool filter_bus(struct ndctl_bus *bus, struct ndctl_filter_ctx *fctx) - { - return true; - } -@@ -481,7 +481,7 @@ static void parse_config(const char **ar - } - - static int read_config_file(struct ndctl_ctx *ctx, struct monitor *_monitor, -- struct util_filter_params *_param) -+ struct ndctl_filter_params *_param) - { - FILE *f; - size_t len = 0; -@@ -603,7 +603,7 @@ int cmd_monitor(int argc, const char **a - NULL - }; - const char *prefix = "./"; -- struct util_filter_ctx fctx = { 0 }; -+ struct ndctl_filter_ctx fctx = { 0 }; - struct monitor_filter_arg mfa = { 0 }; - int i, rc; - -@@ -667,7 +667,7 @@ int cmd_monitor(int argc, const char **a - mfa.maxfd_dimm = -1; - mfa.flags = 0; - -- rc = util_filter_walk(ctx, &fctx, ¶m); -+ rc = ndctl_filter_walk(ctx, &fctx, ¶m); - if (rc) - goto out; - -diff -up ndctl-71.1/test/list-smart-dimm.c.orig ndctl-71.1/test/list-smart-dimm.c ---- ndctl-71.1/test/list-smart-dimm.c.orig 2022-10-07 17:54:40.813788062 -0400 -+++ ndctl-71.1/test/list-smart-dimm.c 2022-10-07 17:54:52.595828176 -0400 -@@ -11,7 +11,7 @@ - #include - #include - --struct util_filter_params param; -+struct ndctl_filter_params param; - static int did_fail; - static int jflag = JSON_C_TO_STRING_PRETTY; - -@@ -23,12 +23,12 @@ do { \ - } while (0) - - static bool filter_region(struct ndctl_region *region, -- struct util_filter_ctx *ctx) -+ struct ndctl_filter_ctx *ctx) - { - return true; - } - --static void filter_dimm(struct ndctl_dimm *dimm, struct util_filter_ctx *ctx) -+static void filter_dimm(struct ndctl_dimm *dimm, struct ndctl_filter_ctx *ctx) - { - struct list_filter_arg *lfa = ctx->list; - struct json_object *jdimm; -@@ -57,7 +57,7 @@ static void filter_dimm(struct ndctl_dim - json_object_array_add(lfa->jdimms, jdimm); - } - --static bool filter_bus(struct ndctl_bus *bus, struct util_filter_ctx *ctx) -+static bool filter_bus(struct ndctl_bus *bus, struct ndctl_filter_ctx *ctx) - { - return true; - } -@@ -89,7 +89,7 @@ int main(int argc, const char *argv[]) - "list-smart-dimm []", - NULL - }; -- struct util_filter_ctx fctx = { 0 }; -+ struct ndctl_filter_ctx fctx = { 0 }; - struct list_filter_arg lfa = { 0 }; - - rc = ndctl_new(&ctx); -@@ -108,7 +108,7 @@ int main(int argc, const char *argv[]) - fctx.list = &lfa; - lfa.flags = 0; - -- rc = util_filter_walk(ctx, &fctx, ¶m); -+ rc = ndctl_filter_walk(ctx, &fctx, ¶m); - if (rc) - return rc; - -diff -up ndctl-71.1/util/filter.c.orig ndctl-71.1/util/filter.c ---- ndctl-71.1/util/filter.c.orig 2022-10-07 17:55:48.192017464 -0400 -+++ ndctl-71.1/util/filter.c 2022-10-07 17:55:54.474038852 -0400 -@@ -394,8 +394,8 @@ const char *util_nsmode_name(enum ndctl_ - return modes[mode]; - } - --int util_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx, -- struct util_filter_params *param) -+int ndctl_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx, -+ struct util_filter_params *param) - { - struct ndctl_bus *bus; - unsigned int type = 0; diff --git a/SOURCES/0089-build-Add-tags.patch b/SOURCES/0089-build-Add-tags.patch deleted file mode 100644 index 322fc83..0000000 --- a/SOURCES/0089-build-Add-tags.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 6dafb0baf8fda14f25e0a764fe8f89d8a4727b0c Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:52:05 -0800 -Subject: [PATCH 089/217] build: Add tags - -Copy the systemd approach to generating tags with a file listing from git. - -Link: https://lore.kernel.org/r/164298552547.3021641.2951502977152843738.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - meson.build | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - -diff --git a/meson.build b/meson.build -index b22fb2e..68f3d0c 100644 ---- a/meson.build -+++ b/meson.build -@@ -82,6 +82,7 @@ project_source_root = meson.current_source_dir() - # Cleanup the leftover config.h files to avoid conflicts with the meson - # generated config.h - git = find_program('git', required : false) -+env = find_program('env') - if git.found() - run_command('clean_config.sh', - env : 'GIT_DIR=@0@/.git'.format(project_source_root), -@@ -111,6 +112,24 @@ else - ) - endif - -+if git.found() -+ all_files = run_command( -+ env, '-u', 'GIT_WORK_TREE', -+ git, '--git-dir=@0@/.git'.format(project_source_root), -+ 'ls-files', ':/*.[ch]', -+ check : false) -+ if all_files.returncode() == 0 -+ all_files = files(all_files.stdout().split()) -+ custom_target( -+ 'tags', -+ output : 'tags', -+ command : [env, 'etags', '-o', '@0@/TAGS'.format(project_source_root)] + all_files) -+ run_target( -+ 'ctags', -+ command : [env, 'ctags', '-o', '@0@/tags'.format(project_source_root)] + all_files) -+ endif -+endif -+ - versiondep = declare_dependency( - compile_args: ['-include', 'version.h'], - sources: version_h --- -2.27.0 - diff --git a/SOURCES/0090-json-Add-support-for-json_object_new_uint64.patch b/SOURCES/0090-json-Add-support-for-json_object_new_uint64.patch deleted file mode 100644 index 23d8d39..0000000 --- a/SOURCES/0090-json-Add-support-for-json_object_new_uint64.patch +++ /dev/null @@ -1,194 +0,0 @@ -From 691cd249750b505753680d2a766280698ce25b75 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:52:10 -0800 -Subject: [PATCH 090/217] json: Add support for json_object_new_uint64() - -Recent versions of json-c add a proper u64 type. However since ndctl still -needs to build against older json-c add build infrastructure to fallback to -s64. - -Link: https://lore.kernel.org/r/164298553057.3021641.17232869374733997747.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - config.h.meson | 3 +++ - cxl/json.c | 6 +++--- - daxctl/json.c | 2 +- - meson.build | 6 ++++++ - ndctl/dimm.c | 2 +- - ndctl/json.c | 10 +++++----- - util/json.c | 2 +- - util/json.h | 13 ++++++++++++- - 8 files changed, 32 insertions(+), 12 deletions(-) - -diff -up ndctl-71.1/config.h.meson.orig ndctl-71.1/config.h.meson ---- ndctl-71.1/config.h.meson.orig 2022-10-07 17:40:36.698914113 -0400 -+++ ndctl-71.1/config.h.meson 2022-10-07 17:41:24.043075305 -0400 -@@ -88,6 +88,9 @@ - /* Define to 1 if you have the `__secure_getenv' function. */ - #mesondefine HAVE___SECURE_GETENV - -+/* Define to 1 if you have json_object_new_uint64 in json-c */ -+#mesondefine HAVE_JSON_U64 -+ - /* Define to the sub-directory where libtool stores uninstalled libraries. */ - #mesondefine LT_OBJDIR - -diff -up ndctl-71.1/cxl/json.c.orig ndctl-71.1/cxl/json.c ---- ndctl-71.1/cxl/json.c.orig 2022-10-07 17:40:36.668914011 -0400 -+++ ndctl-71.1/cxl/json.c 2022-10-07 17:41:24.043075305 -0400 -@@ -159,17 +159,17 @@ static struct json_object *util_cxl_memd - } - - field = cxl_cmd_health_info_get_dirty_shutdowns(cmd); -- jobj = json_object_new_int64(field); -+ jobj = util_json_new_u64(field); - if (jobj) - json_object_object_add(jhealth, "dirty_shutdowns", jobj); - - field = cxl_cmd_health_info_get_volatile_errors(cmd); -- jobj = json_object_new_int64(field); -+ jobj = util_json_new_u64(field); - if (jobj) - json_object_object_add(jhealth, "volatile_errors", jobj); - - field = cxl_cmd_health_info_get_pmem_errors(cmd); -- jobj = json_object_new_int64(field); -+ jobj = util_json_new_u64(field); - if (jobj) - json_object_object_add(jhealth, "pmem_errors", jobj); - -diff -up ndctl-71.1/daxctl/json.c.orig ndctl-71.1/daxctl/json.c ---- ndctl-71.1/daxctl/json.c.orig 2022-10-07 17:40:36.671914021 -0400 -+++ ndctl-71.1/daxctl/json.c 2022-10-07 17:41:24.043075305 -0400 -@@ -190,7 +190,7 @@ struct json_object *util_daxctl_region_t - - align = daxctl_region_get_align(region); - if (align < ULONG_MAX) { -- jobj = json_object_new_int64(align); -+ jobj = util_json_new_u64(align); - if (!jobj) - goto err; - json_object_object_add(jregion, "align", jobj); -diff -up ndctl-71.1/meson.build.orig ndctl-71.1/meson.build ---- ndctl-71.1/meson.build.orig 2022-10-07 17:40:36.720914188 -0400 -+++ ndctl-71.1/meson.build 2022-10-07 17:41:24.044075308 -0400 -@@ -240,6 +240,12 @@ foreach ident : ['secure_getenv', '__sec - conf.set10('HAVE_' + ident.to_upper(), cc.has_function(ident)) - endforeach - -+conf.set10('HAVE_JSON_U64', -+ cc.has_function('json_object_new_uint64', -+ prefix : '''#include ''', -+ dependencies : json, -+ ) -+) - - ndctlconf_dir = sysconfdir / 'ndctl' - ndctlconf = ndctlconf_dir / 'monitor.conf' -diff -up ndctl-71.1/ndctl/dimm.c.orig ndctl-71.1/ndctl/dimm.c ---- ndctl-71.1/ndctl/dimm.c.orig 2022-10-07 17:40:36.673914028 -0400 -+++ ndctl-71.1/ndctl/dimm.c 2022-10-07 17:41:24.044075308 -0400 -@@ -168,7 +168,7 @@ static struct json_object *dump_label_js - break; - json_object_object_add(jlabel, "isetcookie", jobj); - -- jobj = json_object_new_int64(le64_to_cpu(nslabel.lbasize)); -+ jobj = util_json_new_u64(le64_to_cpu(nslabel.lbasize)); - if (!jobj) - break; - json_object_object_add(jlabel, "lbasize", jobj); -diff -up ndctl-71.1/ndctl/json.c.orig ndctl-71.1/ndctl/json.c ---- ndctl-71.1/ndctl/json.c.orig 2022-10-07 17:40:36.675914034 -0400 -+++ ndctl-71.1/ndctl/json.c 2022-10-07 17:41:24.044075308 -0400 -@@ -357,7 +357,7 @@ static struct json_object *util_##type## - int64_t align; \ - \ - align = get_elem(arg, i); \ -- jobj = json_object_new_int64(align); \ -+ jobj = util_json_new_u64(align); \ - if (!jobj) \ - goto err; \ - json_object_array_add(arr, jobj); \ -@@ -550,7 +550,7 @@ struct json_object *util_region_badblock - if (!jbb) - goto err_array; - -- jobj = json_object_new_int64(bb->offset); -+ jobj = util_json_new_u64(bb->offset); - if (!jobj) - goto err; - json_object_object_add(jbb, "offset", jobj); -@@ -604,7 +604,7 @@ static struct json_object *util_namespac - if (!jbb) - goto err_array; - -- jobj = json_object_new_int64(bb->offset); -+ jobj = util_json_new_u64(bb->offset); - if (!jobj) - goto err; - json_object_object_add(jbb, "offset", jobj); -@@ -682,7 +682,7 @@ static struct json_object *dev_badblocks - if (!jbb) - goto err_array; - -- jobj = json_object_new_int64(offset); -+ jobj = util_json_new_u64(offset); - if (!jobj) - goto err; - json_object_object_add(jbb, "offset", jobj); -@@ -972,7 +972,7 @@ struct json_object *util_namespace_to_js - } - - if (align) { -- jobj = json_object_new_int64(align); -+ jobj = util_json_new_u64(align); - if (!jobj) - goto err; - json_object_object_add(jndns, "align", jobj); -diff -up ndctl-71.1/util/json.c.orig ndctl-71.1/util/json.c ---- ndctl-71.1/util/json.c.orig 2022-10-07 17:40:36.682914058 -0400 -+++ ndctl-71.1/util/json.c 2022-10-07 17:41:24.045075312 -0400 -@@ -82,7 +82,7 @@ struct json_object *util_json_object_siz - struct json_object *util_json_object_hex(unsigned long long val, - unsigned long flags) - { -- struct json_object *jobj = json_object_new_int64(val); -+ struct json_object *jobj = util_json_new_u64(val); - - if (jobj && (flags & UTIL_JSON_HUMAN)) - json_object_set_serializer(jobj, display_hex, NULL, NULL); -diff -up ndctl-71.1/util/json.h.orig ndctl-71.1/util/json.h ---- ndctl-71.1/util/json.h.orig 2022-10-07 17:40:36.683914062 -0400 -+++ ndctl-71.1/util/json.h 2022-10-07 17:41:24.046075315 -0400 -@@ -4,6 +4,7 @@ - #define __UTIL_JSON_H__ - #include - #include -+#include - - enum util_json_flags { - UTIL_JSON_IDLE = (1 << 0), -@@ -19,11 +20,21 @@ enum util_json_flags { - UTIL_JSON_HEALTH = (1 << 10), - }; - --struct json_object; - void util_display_json_array(FILE *f_out, struct json_object *jarray, - unsigned long flags); - struct json_object *util_json_object_size(unsigned long long size, - unsigned long flags); - struct json_object *util_json_object_hex(unsigned long long val, - unsigned long flags); -+#if HAVE_JSON_U64 -+static inline struct json_object *util_json_new_u64(unsigned long long val) -+{ -+ return json_object_new_uint64(val); -+} -+#else /* fallback to signed */ -+static inline struct json_object *util_json_new_u64(unsigned long long val) -+{ -+ return json_object_new_int64(val); -+} -+#endif /* HAVE_JSON_U64 */ - #endif /* __UTIL_JSON_H__ */ diff --git a/SOURCES/0091-cxl-json-Cleanup-object-leak-false-positive.patch b/SOURCES/0091-cxl-json-Cleanup-object-leak-false-positive.patch deleted file mode 100644 index d48fa1a..0000000 --- a/SOURCES/0091-cxl-json-Cleanup-object-leak-false-positive.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 8f457dc414ec27178828c86533910958542ce73d Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:52:15 -0800 -Subject: [PATCH 091/217] cxl/json: Cleanup object leak false positive - -As written it is a leak of the json object to return if devname is NULL. -However, the devname can not be NULL because the memdev would not have been -enumerated. Drop the error checking. - -Link: https://lore.kernel.org/r/164298553566.3021641.11858634436119663877.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/json.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/cxl/json.c b/cxl/json.c -index 97ed76b..3ef9f76 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -190,7 +190,7 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - struct json_object *jdev, *jobj; - - jdev = json_object_new_object(); -- if (!devname || !jdev) -+ if (!jdev) - return NULL; - - jobj = json_object_new_string(devname); --- -2.27.0 - diff --git a/SOURCES/0092-cxl-list-Support-multiple-memdev-device-name-filter-.patch b/SOURCES/0092-cxl-list-Support-multiple-memdev-device-name-filter-.patch deleted file mode 100644 index b9680b2..0000000 --- a/SOURCES/0092-cxl-list-Support-multiple-memdev-device-name-filter-.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0ce0152d8e29f85325a3a59f94051228540abf6a Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:52:20 -0800 -Subject: [PATCH 092/217] cxl/list: Support multiple memdev device name filter - arguments - -Similar to 'ndctl list', allow for a syntax like: - - cxl list -m "$(seq -s ' ' 2 5)" - -...to filter the output to just those 4 memdevs. - -Link: https://lore.kernel.org/r/164298554075.3021641.17678360870961637912.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 21 ++++++++++++++++++- - cxl/filter.c | 38 ++++++++++++++++++++++++---------- - 2 files changed, 47 insertions(+), 12 deletions(-) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index c8d10fb..686e0ea 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -30,7 +30,7 @@ OPTIONS - ------- - -m:: - --memdev=:: -- Specify a cxl memory device name to filter the listing. For example: -+ Specify CXL memory device name(s), or device id(s), to filter the listing. For example: - ---- - # cxl list --memdev=mem0 - { -@@ -38,6 +38,25 @@ OPTIONS - "pmem_size":268435456, - "ram_size":0, - } -+ -+# cxl list -m "0 mem1 2" -+[ -+ { -+ "memdev":"mem0", -+ "pmem_size":268435456, -+ "ram_size":0 -+ }, -+ { -+ "memdev":"mem2", -+ "pmem_size":268435456, -+ "ram_size":268435456 -+ }, -+ { -+ "memdev":"mem1", -+ "pmem_size":268435456, -+ "ram_size":268435456 -+ } -+] - ---- - - -M:: -diff --git a/cxl/filter.c b/cxl/filter.c -index 21322ed..efafaf5 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -2,24 +2,40 @@ - // Copyright (C) 2015-2020 Intel Corporation. All rights reserved. - #include - #include -+#include - #include - #include "filter.h" - - struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, -- const char *ident) -+ const char *__ident) - { -- int memdev_id; -+ char *ident, *save; -+ const char *name; -+ int memdev_id; - -- if (!ident || strcmp(ident, "all") == 0) -- return memdev; -+ if (!__ident) -+ return memdev; - -- if (strcmp(ident, cxl_memdev_get_devname(memdev)) == 0) -- return memdev; -+ ident = strdup(__ident); -+ if (!ident) -+ return NULL; - -- if ((sscanf(ident, "%d", &memdev_id) == 1 -- || sscanf(ident, "mem%d", &memdev_id) == 1) -- && cxl_memdev_get_id(memdev) == memdev_id) -- return memdev; -+ for (name = strtok_r(ident, " ", &save); name; -+ name = strtok_r(NULL, " ", &save)) { -+ if (strcmp(name, "all") == 0) -+ break; - -- return NULL; -+ if ((sscanf(name, "%d", &memdev_id) == 1 || -+ sscanf(name, "mem%d", &memdev_id) == 1) && -+ cxl_memdev_get_id(memdev) == memdev_id) -+ break; -+ -+ if (strcmp(name, cxl_memdev_get_devname(memdev)) == 0) -+ break; -+ } -+ -+ free(ident); -+ if (name) -+ return memdev; -+ return NULL; - } --- -2.27.0 - diff --git a/SOURCES/0093-cxl-list-Support-comma-separated-lists.patch b/SOURCES/0093-cxl-list-Support-comma-separated-lists.patch deleted file mode 100644 index 6b55952..0000000 --- a/SOURCES/0093-cxl-list-Support-comma-separated-lists.patch +++ /dev/null @@ -1,55 +0,0 @@ -From a36b8b815d2e8bfd8438b44d4775bdf3ffc3a6d8 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:52:26 -0800 -Subject: [PATCH 093/217] cxl/list: Support comma separated lists - -In addition to supporting a syntax like: - - cxl list -m "0 1 2" - -...support: - - cxl list -m 0,1,2 - -Link: https://lore.kernel.org/r/164298554612.3021641.3315920699556984273.stgit@dwillia2-desk3.amr.corp.intel.com -Reported-by: Vishal Verma -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/filter.c | 13 +++++++++++-- - 1 file changed, 11 insertions(+), 2 deletions(-) - -diff --git a/cxl/filter.c b/cxl/filter.c -index efafaf5..405b653 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -6,6 +6,15 @@ - #include - #include "filter.h" - -+static const char *which_sep(const char *filter) -+{ -+ if (strchr(filter, ' ')) -+ return " "; -+ if (strchr(filter, ',')) -+ return ","; -+ return " "; -+} -+ - struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, - const char *__ident) - { -@@ -20,8 +29,8 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, - if (!ident) - return NULL; - -- for (name = strtok_r(ident, " ", &save); name; -- name = strtok_r(NULL, " ", &save)) { -+ for (name = strtok_r(ident, which_sep(__ident), &save); name; -+ name = strtok_r(NULL, which_sep(__ident), &save)) { - if (strcmp(name, "all") == 0) - break; - --- -2.27.0 - diff --git a/SOURCES/0094-cxl-list-Introduce-cxl_filter_walk.patch b/SOURCES/0094-cxl-list-Introduce-cxl_filter_walk.patch deleted file mode 100644 index b3aec86..0000000 --- a/SOURCES/0094-cxl-list-Introduce-cxl_filter_walk.patch +++ /dev/null @@ -1,292 +0,0 @@ -From f833845ce72490e4c80b3ccc9972d5329f69a381 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:52:31 -0800 -Subject: [PATCH 094/217] cxl/list: Introduce cxl_filter_walk() - -In preparation for introducing more objects and filtering options for 'cxl -list' introduce cxl_filter_walk() to centralize CXL topology walks. It -fills the same role as ndctl_filter_walk() as a way to distribute topology -interrogation beyond 'cxl list' to other commands, and serve as the -template for CXL object hierarchy in JSON output payloads. - -Use the common dbg() logger for log messages. - -Link: https://lore.kernel.org/r/164298555121.3021641.16127840206319352254.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 2 + - cxl/filter.c | 50 ++++++++++++++++ - cxl/filter.h | 18 +++++- - cxl/list.c | 102 +++++++-------------------------- - cxl/meson.build | 1 + - 5 files changed, 90 insertions(+), 83 deletions(-) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 686e0ea..4d409ba 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -15,6 +15,8 @@ SYNOPSIS - Walk the CXL capable device hierarchy in the system and list all device - instances along with some of their major attributes. - -+Options can be specified to limit the output to specific objects. -+ - EXAMPLE - ------- - ---- -diff --git a/cxl/filter.c b/cxl/filter.c -index 405b653..d1ff4b6 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -1,10 +1,16 @@ - // SPDX-License-Identifier: GPL-2.0 - // Copyright (C) 2015-2020 Intel Corporation. All rights reserved. -+#include - #include - #include - #include -+#include -+#include - #include -+#include -+ - #include "filter.h" -+#include "json.h" - - static const char *which_sep(const char *filter) - { -@@ -48,3 +54,47 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, - return memdev; - return NULL; - } -+ -+static unsigned long params_to_flags(struct cxl_filter_params *param) -+{ -+ unsigned long flags = 0; -+ -+ if (param->idle) -+ flags |= UTIL_JSON_IDLE; -+ if (param->human) -+ flags |= UTIL_JSON_HUMAN; -+ if (param->health) -+ flags |= UTIL_JSON_HEALTH; -+ return flags; -+} -+ -+int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) -+{ -+ struct json_object *jplatform = json_object_new_array(); -+ unsigned long flags = params_to_flags(p); -+ struct cxl_memdev *memdev; -+ -+ if (!jplatform) { -+ dbg(p, "platform object allocation failure\n"); -+ return -ENOMEM; -+ } -+ -+ cxl_memdev_foreach(ctx, memdev) { -+ struct json_object *jdev; -+ -+ if (!util_cxl_memdev_filter(memdev, p->memdev_filter)) -+ continue; -+ if (p->memdevs) { -+ jdev = util_cxl_memdev_to_json(memdev, flags); -+ if (!jdev) { -+ dbg(p, "memdev object allocation failure\n"); -+ continue; -+ } -+ json_object_array_add(jplatform, jdev); -+ } -+ } -+ -+ util_display_json_array(stdout, jplatform, flags); -+ -+ return 0; -+} -diff --git a/cxl/filter.h b/cxl/filter.h -index da80033..664b74b 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -1,7 +1,21 @@ - /* SPDX-License-Identifier: GPL-2.0 */ --/* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */ -+/* Copyright (C) 2021 Intel Corporation. All rights reserved. */ - #ifndef _CXL_UTIL_FILTER_H_ - #define _CXL_UTIL_FILTER_H_ -+ -+#include -+#include -+ -+struct cxl_filter_params { -+ const char *memdev_filter; -+ bool memdevs; -+ bool idle; -+ bool human; -+ bool health; -+ struct log_ctx ctx; -+}; -+ - struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, -- const char *ident); -+ const char *ident); -+int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *param); - #endif /* _CXL_UTIL_FILTER_H_ */ -diff --git a/cxl/list.c b/cxl/list.c -index 7f7a04d..1730307 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -9,60 +9,27 @@ - #include - #include - #include --#include - --#include "json.h" - #include "filter.h" - --static struct { -- bool memdevs; -- bool idle; -- bool human; -- bool health; --} list; -- --static unsigned long listopts_to_flags(void) --{ -- unsigned long flags = 0; -- -- if (list.idle) -- flags |= UTIL_JSON_IDLE; -- if (list.human) -- flags |= UTIL_JSON_HUMAN; -- if (list.health) -- flags |= UTIL_JSON_HEALTH; -- return flags; --} -- --static struct { -- const char *memdev; --} param; -- --static int did_fail; -- --#define fail(fmt, ...) \ --do { \ -- did_fail = 1; \ -- fprintf(stderr, "cxl-%s:%s:%d: " fmt, \ -- VERSION, __func__, __LINE__, ##__VA_ARGS__); \ --} while (0) -+static struct cxl_filter_params param; - - static int num_list_flags(void) - { -- return list.memdevs; -+ return param.memdevs; - } - - int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - { - const struct option options[] = { -- OPT_STRING('m', "memdev", ¶m.memdev, "memory device name", -+ OPT_STRING('m', "memdev", ¶m.memdev_filter, "memory device name", - "filter by CXL memory device name"), -- OPT_BOOLEAN('M', "memdevs", &list.memdevs, -+ OPT_BOOLEAN('M', "memdevs", ¶m.memdevs, - "include CXL memory device info"), -- OPT_BOOLEAN('i', "idle", &list.idle, "include idle devices"), -- OPT_BOOLEAN('u', "human", &list.human, -+ OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"), -+ OPT_BOOLEAN('u', "human", ¶m.human, - "use human friendly number formats "), -- OPT_BOOLEAN('H', "health", &list.health, -+ OPT_BOOLEAN('H', "health", ¶m.health, - "include memory device health information "), - OPT_END(), - }; -@@ -70,9 +37,6 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - "cxl list []", - NULL - }; -- struct json_object *jdevs = NULL; -- unsigned long list_flags; -- struct cxl_memdev *memdev; - int i; - - argc = parse_options(argc, argv, options, u, 0); -@@ -83,46 +47,22 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - usage_with_options(u, options); - - if (num_list_flags() == 0) { -- /* -- * TODO: We likely want to list regions by default if nothing -- * was explicitly asked for. But until we have region support, -- * print this error asking for devices explicitly. -- * Once region support is added, this TODO can be removed. -- */ -- error("please specify entities to list, e.g. using -m/-M\n"); -- usage_with_options(u, options); -- } -- -- list_flags = listopts_to_flags(); -- -- cxl_memdev_foreach(ctx, memdev) { -- struct json_object *jdev = NULL; -- -- if (!util_cxl_memdev_filter(memdev, param.memdev)) -- continue; -- -- if (list.memdevs) { -- if (!jdevs) { -- jdevs = json_object_new_array(); -- if (!jdevs) { -- fail("\n"); -- continue; -- } -- } -- -- jdev = util_cxl_memdev_to_json(memdev, list_flags); -- if (!jdev) { -- fail("\n"); -- continue; -- } -- json_object_array_add(jdevs, jdev); -+ if (param.memdev_filter) -+ param.memdevs = true; -+ else { -+ /* -+ * TODO: We likely want to list regions by default if -+ * nothing was explicitly asked for. But until we have -+ * region support, print this error asking for devices -+ * explicitly. Once region support is added, this TODO -+ * can be removed. -+ */ -+ error("please specify entities to list, e.g. using -m/-M\n"); -+ usage_with_options(u, options); - } - } - -- if (jdevs) -- util_display_json_array(stdout, jdevs, list_flags); -+ log_init(¶m.ctx, "cxl list", "CXL_LIST_LOG"); - -- if (did_fail) -- return -ENOMEM; -- return 0; -+ return cxl_filter_walk(ctx, ¶m); - } -diff --git a/cxl/meson.build b/cxl/meson.build -index 805924b..fc7ee71 100644 ---- a/cxl/meson.build -+++ b/cxl/meson.build -@@ -3,6 +3,7 @@ cxl_src = [ - 'list.c', - 'memdev.c', - '../util/json.c', -+ '../util/log.c', - 'json.c', - 'filter.c', - ] --- -2.27.0 - diff --git a/SOURCES/0095-cxl-list-Emit-device-serial-numbers.patch b/SOURCES/0095-cxl-list-Emit-device-serial-numbers.patch deleted file mode 100644 index 78899ef..0000000 --- a/SOURCES/0095-cxl-list-Emit-device-serial-numbers.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 2d1b8cea119ca2bb0eec8ebb2dfb1b6c4d844ddd Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:52:36 -0800 -Subject: [PATCH 095/217] cxl/list: Emit device serial numbers - -Starting with the v5.17 kernel the CXL driver emits the mandatory device -serial number for each memory device. Include it in the memory device -listing. - -Link: https://lore.kernel.org/r/164298555630.3021641.3246226448369816200.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 15 +++++++++------ - cxl/json.c | 11 ++++++++++- - cxl/lib/libcxl.c | 11 +++++++++++ - cxl/lib/libcxl.sym | 5 +++++ - cxl/lib/private.h | 1 + - cxl/libcxl.h | 1 + - 6 files changed, 37 insertions(+), 7 deletions(-) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 4d409ba..bd0207e 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -41,22 +41,25 @@ OPTIONS - "ram_size":0, - } - --# cxl list -m "0 mem1 2" -+# cxl list -M --memdev="0 mem3 5" - [ - { - "memdev":"mem0", - "pmem_size":268435456, -- "ram_size":0 -+ "ram_size":0, -+ "serial":0 - }, - { -- "memdev":"mem2", -+ "memdev":"mem3", - "pmem_size":268435456, -- "ram_size":268435456 -+ "ram_size":268435456, -+ "serial":2 - }, - { -- "memdev":"mem1", -+ "memdev":"mem5", - "pmem_size":268435456, -- "ram_size":268435456 -+ "ram_size":268435456, -+ "serial":4 - } - ] - ---- -diff --git a/cxl/json.c b/cxl/json.c -index 3ef9f76..d8e65df 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -1,5 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0 --// Copyright (C) 2015-2020 Intel Corporation. All rights reserved. -+// Copyright (C) 2015-2021 Intel Corporation. All rights reserved. -+#include - #include - #include - #include -@@ -188,6 +189,7 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - { - const char *devname = cxl_memdev_get_devname(memdev); - struct json_object *jdev, *jobj; -+ unsigned long long serial; - - jdev = json_object_new_object(); - if (!jdev) -@@ -210,5 +212,12 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - if (jobj) - json_object_object_add(jdev, "health", jobj); - } -+ -+ serial = cxl_memdev_get_serial(memdev); -+ if (serial < ULLONG_MAX) { -+ jobj = util_json_object_hex(serial, flags); -+ if (jobj) -+ json_object_object_add(jdev, "serial", jobj); -+ } - return jdev; - } -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 3390eb9..8d3cf80 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -296,6 +296,12 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) - if (memdev->lsa_size == ULLONG_MAX) - goto err_read; - -+ sprintf(path, "%s/serial", cxlmem_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ memdev->serial = ULLONG_MAX; -+ else -+ memdev->serial = strtoull(buf, NULL, 0); -+ - memdev->dev_path = strdup(cxlmem_base); - if (!memdev->dev_path) - goto err_read; -@@ -371,6 +377,11 @@ CXL_EXPORT int cxl_memdev_get_id(struct cxl_memdev *memdev) - return memdev->id; - } - -+CXL_EXPORT unsigned long long cxl_memdev_get_serial(struct cxl_memdev *memdev) -+{ -+ return memdev->serial; -+} -+ - CXL_EXPORT const char *cxl_memdev_get_devname(struct cxl_memdev *memdev) - { - return devpath_to_devname(memdev->dev_path); -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 077d104..4411035 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -73,3 +73,8 @@ global: - local: - *; - }; -+ -+LIBCXL_2 { -+global: -+ cxl_memdev_get_serial; -+} LIBCXL_1; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index a1b8b50..28f7e16 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -31,6 +31,7 @@ struct cxl_memdev { - size_t lsa_size; - struct kmod_module *module; - struct cxl_nvdimm_bridge *bridge; -+ unsigned long long serial; - }; - - enum cxl_cmd_query_status { -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 89d35ba..bcdede8 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -35,6 +35,7 @@ struct cxl_memdev; - struct cxl_memdev *cxl_memdev_get_first(struct cxl_ctx *ctx); - struct cxl_memdev *cxl_memdev_get_next(struct cxl_memdev *memdev); - int cxl_memdev_get_id(struct cxl_memdev *memdev); -+unsigned long long cxl_memdev_get_serial(struct cxl_memdev *memdev); - const char *cxl_memdev_get_devname(struct cxl_memdev *memdev); - int cxl_memdev_get_major(struct cxl_memdev *memdev); - int cxl_memdev_get_minor(struct cxl_memdev *memdev); --- -2.27.0 - diff --git a/SOURCES/0096-cxl-list-Add-filter-by-serial-support.patch b/SOURCES/0096-cxl-list-Add-filter-by-serial-support.patch deleted file mode 100644 index c11c22d..0000000 --- a/SOURCES/0096-cxl-list-Add-filter-by-serial-support.patch +++ /dev/null @@ -1,163 +0,0 @@ -From d7854adcd1e517d2372ec51f4a1ede2d549975e8 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:52:41 -0800 -Subject: [PATCH 096/217] cxl/list: Add filter by serial support - -Given that serial numbers are intended to be unique device identifiers, -enable them as a memdev filter option. - -Link: https://lore.kernel.org/r/164298556167.3021641.5470955268978068465.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 4 ++++ - cxl/filter.c | 38 ++++++++++++++++++++++++++++++---- - cxl/filter.h | 4 +++- - cxl/list.c | 4 +++- - cxl/memdev.c | 2 +- - 5 files changed, 45 insertions(+), 7 deletions(-) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index bd0207e..224c972 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -64,6 +64,10 @@ OPTIONS - ] - ---- - -+-s:: -+--serial=:: -+ Specify CXL memory device serial number(s) to filter the listing -+ - -M:: - --memdevs:: - Include CXL memory devices in the listing -diff --git a/cxl/filter.c b/cxl/filter.c -index d1ff4b6..26efc65 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -21,15 +21,45 @@ static const char *which_sep(const char *filter) - return " "; - } - -+static struct cxl_memdev * -+util_cxl_memdev_serial_filter(struct cxl_memdev *memdev, const char *__serials) -+{ -+ unsigned long long serial = 0; -+ char *serials, *save, *end; -+ const char *arg; -+ -+ if (!__serials) -+ return memdev; -+ -+ serials = strdup(__serials); -+ if (!serials) -+ return NULL; -+ -+ for (arg = strtok_r(serials, which_sep(__serials), &save); arg; -+ arg = strtok_r(NULL, which_sep(__serials), &save)) { -+ serial = strtoull(arg, &end, 0); -+ if (!arg[0] || end[0] != 0) -+ continue; -+ if (cxl_memdev_get_serial(memdev) == serial) -+ break; -+ } -+ -+ free(serials); -+ if (arg) -+ return memdev; -+ return NULL; -+} -+ - struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, -- const char *__ident) -+ const char *__ident, -+ const char *serials) - { - char *ident, *save; - const char *name; - int memdev_id; - - if (!__ident) -- return memdev; -+ return util_cxl_memdev_serial_filter(memdev, serials); - - ident = strdup(__ident); - if (!ident) -@@ -51,7 +81,7 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, - - free(ident); - if (name) -- return memdev; -+ return util_cxl_memdev_serial_filter(memdev, serials); - return NULL; - } - -@@ -82,7 +112,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - cxl_memdev_foreach(ctx, memdev) { - struct json_object *jdev; - -- if (!util_cxl_memdev_filter(memdev, p->memdev_filter)) -+ if (!util_cxl_memdev_filter(memdev, p->memdev_filter, p->serial_filter)) - continue; - if (p->memdevs) { - jdev = util_cxl_memdev_to_json(memdev, flags); -diff --git a/cxl/filter.h b/cxl/filter.h -index 664b74b..12d9344 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -8,6 +8,7 @@ - - struct cxl_filter_params { - const char *memdev_filter; -+ const char *serial_filter; - bool memdevs; - bool idle; - bool human; -@@ -16,6 +17,7 @@ struct cxl_filter_params { - }; - - struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, -- const char *ident); -+ const char *__ident, -+ const char *serials); - int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *param); - #endif /* _CXL_UTIL_FILTER_H_ */ -diff --git a/cxl/list.c b/cxl/list.c -index 1730307..6bc48df 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -24,6 +24,8 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - const struct option options[] = { - OPT_STRING('m', "memdev", ¶m.memdev_filter, "memory device name", - "filter by CXL memory device name"), -+ OPT_STRING('s', "serial", ¶m.serial_filter, "memory device serial", -+ "filter by CXL memory device serial number"), - OPT_BOOLEAN('M', "memdevs", ¶m.memdevs, - "include CXL memory device info"), - OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"), -@@ -47,7 +49,7 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - usage_with_options(u, options); - - if (num_list_flags() == 0) { -- if (param.memdev_filter) -+ if (param.memdev_filter || param.serial_filter) - param.memdevs = true; - else { - /* -diff --git a/cxl/memdev.c b/cxl/memdev.c -index d063d51..b9141be 100644 ---- a/cxl/memdev.c -+++ b/cxl/memdev.c -@@ -248,7 +248,7 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - continue; - - cxl_memdev_foreach (ctx, memdev) { -- if (!util_cxl_memdev_filter(memdev, argv[i])) -+ if (!util_cxl_memdev_filter(memdev, argv[i], NULL)) - continue; - - if (action == action_write) { --- -2.27.0 - diff --git a/SOURCES/0097-cxl-lib-Rename-nvdimm-bridge-to-pmem.patch b/SOURCES/0097-cxl-lib-Rename-nvdimm-bridge-to-pmem.patch deleted file mode 100644 index f9431b1..0000000 --- a/SOURCES/0097-cxl-lib-Rename-nvdimm-bridge-to-pmem.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 0be46d9c6638903978d16388c765a1907d5970bc Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:52:47 -0800 -Subject: [PATCH 097/217] cxl/lib: Rename nvdimm bridge to pmem - -The kernel has 2 object classes for connecting CXL to NVDIMM. There is an -'nvdimm-bridge' object (one per root CXL port) that represents a CXL NVDIMM -Bus, and there are 'pmem' object that represent CXL NVDIMM DIMM devices. -The object that the library is currently calling an nvdimm-bridge is -actually the 'pmem' object. Rename accordingly. - -The exported function cxl_memdev_nvdimm_bridge_active() is not renamed, but -since it is a cxl_memdev operation and 'struct cxl_pmem' is an -implementation detail it is fine as is. - -Link: https://lore.kernel.org/r/164298556712.3021641.15612755067301105130.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 56 +++++++++++++++++++++++------------------------ - cxl/lib/private.h | 4 ++-- - 2 files changed, 30 insertions(+), 30 deletions(-) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 8d3cf80..9839f26 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -45,11 +45,11 @@ struct cxl_ctx { - void *private_data; - }; - --static void free_bridge(struct cxl_nvdimm_bridge *bridge) -+static void free_pmem(struct cxl_pmem *pmem) - { -- free(bridge->dev_buf); -- free(bridge->dev_path); -- free(bridge); -+ free(pmem->dev_buf); -+ free(pmem->dev_path); -+ free(pmem); - } - - static void free_memdev(struct cxl_memdev *memdev, struct list_head *head) -@@ -57,7 +57,7 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head) - if (head) - list_del_from(head, &memdev->list); - kmod_module_unref(memdev->module); -- free_bridge(memdev->bridge); -+ free_pmem(memdev->pmem); - free(memdev->firmware_version); - free(memdev->dev_buf); - free(memdev->dev_path); -@@ -213,36 +213,36 @@ CXL_EXPORT void cxl_set_log_priority(struct cxl_ctx *ctx, int priority) - ctx->ctx.log_priority = priority; - } - --static void *add_cxl_bridge(void *parent, int id, const char *br_base) -+static void *add_cxl_pmem(void *parent, int id, const char *br_base) - { - const char *devname = devpath_to_devname(br_base); - struct cxl_memdev *memdev = parent; - struct cxl_ctx *ctx = memdev->ctx; -- struct cxl_nvdimm_bridge *bridge; -+ struct cxl_pmem *pmem; - -- dbg(ctx, "%s: bridge_base: \'%s\'\n", devname, br_base); -+ dbg(ctx, "%s: pmem_base: \'%s\'\n", devname, br_base); - -- bridge = calloc(1, sizeof(*bridge)); -- if (!bridge) -+ pmem = calloc(1, sizeof(*pmem)); -+ if (!pmem) - goto err_dev; -- bridge->id = id; -+ pmem->id = id; - -- bridge->dev_path = strdup(br_base); -- if (!bridge->dev_path) -+ pmem->dev_path = strdup(br_base); -+ if (!pmem->dev_path) - goto err_read; - -- bridge->dev_buf = calloc(1, strlen(br_base) + 50); -- if (!bridge->dev_buf) -+ pmem->dev_buf = calloc(1, strlen(br_base) + 50); -+ if (!pmem->dev_buf) - goto err_read; -- bridge->buf_len = strlen(br_base) + 50; -+ pmem->buf_len = strlen(br_base) + 50; - -- memdev->bridge = bridge; -- return bridge; -+ memdev->pmem = pmem; -+ return pmem; - - err_read: -- free(bridge->dev_buf); -- free(bridge->dev_path); -- free(bridge); -+ free(pmem->dev_buf); -+ free(pmem->dev_path); -+ free(pmem); - err_dev: - return NULL; - } -@@ -319,7 +319,7 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) - goto err_read; - memdev->buf_len = strlen(cxlmem_base) + 50; - -- sysfs_device_parse(ctx, cxlmem_base, "pmem", memdev, add_cxl_bridge); -+ sysfs_device_parse(ctx, cxlmem_base, "pmem", memdev, add_cxl_pmem); - - cxl_memdev_foreach(ctx, memdev_dup) - if (memdev_dup->id == memdev->id) { -@@ -430,18 +430,18 @@ static int is_enabled(const char *drvpath) - CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev) - { - struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -- struct cxl_nvdimm_bridge *bridge = memdev->bridge; -+ struct cxl_pmem *pmem = memdev->pmem; - char *path; - int len; - -- if (!bridge) -+ if (!pmem) - return 0; - -- path = bridge->dev_buf; -- len = bridge->buf_len; -+ path = pmem->dev_buf; -+ len = pmem->buf_len; - -- if (snprintf(path, len, "%s/driver", bridge->dev_path) >= len) { -- err(ctx, "%s: nvdimm bridge buffer too small!\n", -+ if (snprintf(path, len, "%s/driver", pmem->dev_path) >= len) { -+ err(ctx, "%s: nvdimm pmem buffer too small!\n", - cxl_memdev_get_devname(memdev)); - return 0; - } -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 28f7e16..7c81e24 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -10,7 +10,7 @@ - - #define CXL_EXPORT __attribute__ ((visibility("default"))) - --struct cxl_nvdimm_bridge { -+struct cxl_pmem { - int id; - void *dev_buf; - size_t buf_len; -@@ -30,7 +30,7 @@ struct cxl_memdev { - int payload_max; - size_t lsa_size; - struct kmod_module *module; -- struct cxl_nvdimm_bridge *bridge; -+ struct cxl_pmem *pmem; - unsigned long long serial; - }; - --- -2.27.0 - diff --git a/SOURCES/0098-cxl-list-Cleanup-options-definitions.patch b/SOURCES/0098-cxl-list-Cleanup-options-definitions.patch deleted file mode 100644 index f8cebbe..0000000 --- a/SOURCES/0098-cxl-list-Cleanup-options-definitions.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 5d20a4d2cca923e63cb1604da51788c0fd078ce1 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:52:52 -0800 -Subject: [PATCH 098/217] cxl/list: Cleanup options definitions - -Clarify which options take lists by adding a "(s)" to the object name, and -move the option block out of cmd_list() to reduce the column-80 collisions. - -Link: https://lore.kernel.org/r/164298557263.3021641.8121105326167408001.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/list.c | 30 ++++++++++++++++-------------- - 1 file changed, 16 insertions(+), 14 deletions(-) - -diff --git a/cxl/list.c b/cxl/list.c -index 6bc48df..7e2744d 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -19,22 +19,24 @@ static int num_list_flags(void) - return param.memdevs; - } - -+static const struct option options[] = { -+ OPT_STRING('m', "memdev", ¶m.memdev_filter, "memory device name(s)", -+ "filter by CXL memory device name(s)"), -+ OPT_STRING('s', "serial", ¶m.serial_filter, -+ "memory device serial(s)", -+ "filter by CXL memory device serial number(s)"), -+ OPT_BOOLEAN('M', "memdevs", ¶m.memdevs, -+ "include CXL memory device info"), -+ OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"), -+ OPT_BOOLEAN('u', "human", ¶m.human, -+ "use human friendly number formats "), -+ OPT_BOOLEAN('H', "health", ¶m.health, -+ "include memory device health information "), -+ OPT_END(), -+}; -+ - int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - { -- const struct option options[] = { -- OPT_STRING('m', "memdev", ¶m.memdev_filter, "memory device name", -- "filter by CXL memory device name"), -- OPT_STRING('s', "serial", ¶m.serial_filter, "memory device serial", -- "filter by CXL memory device serial number"), -- OPT_BOOLEAN('M', "memdevs", ¶m.memdevs, -- "include CXL memory device info"), -- OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"), -- OPT_BOOLEAN('u', "human", ¶m.human, -- "use human friendly number formats "), -- OPT_BOOLEAN('H', "health", ¶m.health, -- "include memory device health information "), -- OPT_END(), -- }; - const char * const u[] = { - "cxl list []", - NULL --- -2.27.0 - diff --git a/SOURCES/0099-Documentation-Enhance-libcxl-memdev-API-documentatio.patch b/SOURCES/0099-Documentation-Enhance-libcxl-memdev-API-documentatio.patch deleted file mode 100644 index c989e88..0000000 --- a/SOURCES/0099-Documentation-Enhance-libcxl-memdev-API-documentatio.patch +++ /dev/null @@ -1,170 +0,0 @@ -From 7b9ed7e065c6de029385d40de1f7cb0aed3a9108 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:52:57 -0800 -Subject: [PATCH 099/217] Documentation: Enhance libcxl memdev API - documentation - -In preparation for adding documentation for more objects, organize the -current into subsections and flesh out descriptions for the current APIs. - -Link: https://lore.kernel.org/r/164298557771.3021641.14904324834528700206.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/copyright.txt | 2 +- - Documentation/cxl/lib/libcxl.txt | 111 +++++++++++++++++++++++++++---- - 2 files changed, 99 insertions(+), 14 deletions(-) - -diff --git a/Documentation/copyright.txt b/Documentation/copyright.txt -index a9380e1..af9caf7 100644 ---- a/Documentation/copyright.txt -+++ b/Documentation/copyright.txt -@@ -2,7 +2,7 @@ - - COPYRIGHT - --------- --Copyright (C) 2016 - 2020, Intel Corporation. License GPLv2: GNU GPL -+Copyright (C) 2016 - 2022, Intel Corporation. License GPLv2: GNU GPL - version 2 . This is free software: - you are free to change and redistribute it. There is NO WARRANTY, to - the extent permitted by law. -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 2539369..c127326 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -20,27 +20,100 @@ libcxl provides interfaces to interact with CXL devices in Linux, using sysfs - interfaces for most kernel interactions, and the ioctl() interface for command - submission. - --The starting point for all library interfaces is a 'cxl_ctx' object, returned --by linklibcxl:cxl_new[3]. CXL 'Type 3' memory devices are children of the --cxl_ctx object, and can be iterated through using an iterator API. -+The starting point for all library interfaces is a 'cxl_ctx' object, -+returned by linklibcxl:cxl_new[3]. CXL 'Type 3' memory devices and other -+CXL device objects are descendants of the cxl_ctx object, and can be -+iterated via an object an iterator API of the form -+cxl__foreach(, ). - --Library level interfaces that are agnostic to any device, or a specific --subclass of operations have the prefix 'cxl_' -+MEMDEVS -+------- -+The object representing a CXL memory expander (Type 3 device) is 'struct -+cxl_memdev'. Library interfaces related to these devices have the prefix -+'cxl_memdev_'. These interfaces are mostly associated with sysfs -+interactions (unless otherwise noted in their respective documentation -+sections). They are typically used to retrieve data published by the -+kernel, or to send data or trigger kernel operations for a given device. - --The object representing a CXL Type 3 device is 'cxl_memdev'. Library interfaces --related to these devices have the prefix 'cxl_memdev_'. These interfaces are --mostly associated with sysfs interactions (unless otherwise noted in their --respective documentation pages). They are typically used to retrieve data --published by the kernel, or to send data or trigger kernel operations for a --given device. -+=== MEMDEV: Enumeration -+---- -+struct cxl_memdev *cxl_memdev_get_first(struct cxl_ctx *ctx); -+struct cxl_memdev *cxl_memdev_get_next(struct cxl_memdev *memdev); -+struct cxl_ctx *cxl_memdev_get_ctx(struct cxl_memdev *memdev); -+ -+#define cxl_memdev_foreach(ctx, memdev) \ -+ for (memdev = cxl_memdev_get_first(ctx); \ -+ memdev != NULL; \ -+ memdev = cxl_memdev_get_next(memdev)) -+ -+---- -+ -+CXL memdev instances are enumerated from the global library context -+'struct cxl_ctx'. By default a memdev only offers a portal to submit -+memory device commands, see the port, decoder, and endpoint APIs to -+determine what if any CXL Memory Resources are reachable given a -+specific memdev. -+ -+=== MEMDEV: Attributes -+---- -+int cxl_memdev_get_id(struct cxl_memdev *memdev); -+unsigned long long cxl_memdev_get_serial(struct cxl_memdev *memdev); -+const char *cxl_memdev_get_devname(struct cxl_memdev *memdev); -+int cxl_memdev_get_major(struct cxl_memdev *memdev); -+int cxl_memdev_get_minor(struct cxl_memdev *memdev); -+unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev); -+unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev); -+const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev); -+size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev); -+int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev); -+---- -+ -+A memdev is given a kernel device name of the form "mem%d" where an id -+(cxl_memdev_get_id()) is dynamically allocated as devices are -+discovered. Note that there are no guarantees that ids / kernel device -+names for memdevs are stable from one boot to the next, devices are -+enumerated asynchronously. If a stable identifier is use -+cxl_memdev_get_serial() which returns a value according to the 'Device -+Serial Number Extended Capability' in the PCIe 5.0 Base Specification. -+ -+The character device node for command submission can be found by default -+at /dev/cxl/mem%d, or created with a major / minor returned from -+cxl_memdev_get_{major,minor}(). -+ -+The 'pmem_size' and 'ram_size' attributes return the current -+provisioning of DPA (Device Physical Address / local capacity) in the -+device. -+ -+=== MEMDEV: Commands -+---- -+struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode); -+struct cxl_cmd *cxl_cmd_new_identify(struct cxl_memdev *memdev); -+struct cxl_cmd *cxl_cmd_new_get_health_info(struct cxl_memdev *memdev); -+struct cxl_cmd *cxl_cmd_new_read_label(struct cxl_memdev *memdev, -+ unsigned int offset, unsigned int length); -+struct cxl_cmd *cxl_cmd_new_write_label(struct cxl_memdev *memdev, void *buf, -+ unsigned int offset, unsigned int length); -+int cxl_memdev_zero_label(struct cxl_memdev *memdev, size_t length, -+ size_t offset); -+int cxl_memdev_read_label(struct cxl_memdev *memdev, void *buf, size_t length, -+ size_t offset); -+int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf, size_t length, -+ size_t offset); -+ -+---- - - A 'cxl_cmd' is a reference counted object which is used to perform 'Mailbox' - commands as described in the CXL Specification. A 'cxl_cmd' object is tied to a - 'cxl_memdev'. Associated library interfaces have the prefix 'cxl_cmd_'. Within - this sub-class of interfaces, there are: - -- * 'cxl_cmd_new_*' interfaces that allocate a new cxl_cmd object for a given -- command type. -+ * 'cxl_cmd_new_*()' interfaces that allocate a new cxl_cmd object for a given -+ command type targeted at a given memdev. As part of the command -+ instantiation process the library validates that the command is -+ supported by the memory device, otherwise it returns NULL to indicate -+ 'no support'. The libcxl command id is translated by the kernel into -+ a CXL standard opcode. See the potential command ids in -+ /usr/include/linux/cxl_mem.h. - - * 'cxl_cmd_submit' which submits the command via ioctl() - -@@ -49,6 +122,18 @@ this sub-class of interfaces, there are: - - * 'cxl_cmd_get_*' interfaces to get general command related information. - -+cxl_cmd_new_raw() supports so called 'RAW' commands where the command id -+is 'RAW' and it carries an unmodified CXL memory device command payload -+associated with the 'opcode' argument. Given the kernel does minimal -+input validation on these commands typically raw commands are not -+supported by the kernel outside debug build scenarios. libcxl is limited -+to supporting commands that appear in the CXL standard / public -+specifications. -+ -+cxl_memdev{read,write,zero}_label() are helpers for marshaling multiple -+label access commands over an arbitrary extent of the device's label -+area. -+ - include::../../copyright.txt[] - - SEE ALSO --- -2.27.0 - diff --git a/SOURCES/0100-cxl-list-Add-bus-objects.patch b/SOURCES/0100-cxl-list-Add-bus-objects.patch deleted file mode 100644 index 25dd088..0000000 --- a/SOURCES/0100-cxl-list-Add-bus-objects.patch +++ /dev/null @@ -1,739 +0,0 @@ -From 9dce91c303720a336c55ecdc2e01e423589b85b2 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:53:02 -0800 -Subject: [PATCH 100/217] cxl/list: Add bus objects - -A 'struct cxl_bus' represents a CXL.mem domain. It is the root of a -Host-managed Device Memory (HDM) hierarchy. When memory devices are enabled -for CXL operation they appear underneath a bus in a 'cxl list -BM' listing, -otherwise they display as disconnected. - -A 'bus' is identical to the kernel's CXL root port object, but given the -confusion between CXL root ports, and PCIe root ports, the 'bus' name is -less ambiguous. It also serves a similar role in the object hierarchy as a -'struct ndctl_bus' object. It is also the case that the "root" name will -appear as the kernel device-name, so the association will be clear. - -Link: https://lore.kernel.org/r/164298558278.3021641.16323855851736615358.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .clang-format | 1 + - Documentation/cxl/cxl-list.txt | 88 ++++++++++++++++--- - Documentation/cxl/lib/libcxl.txt | 30 +++++++ - cxl/filter.c | 117 ++++++++++++++++++++++++- - cxl/filter.h | 2 + - cxl/json.c | 21 +++++ - cxl/json.h | 5 +- - cxl/lib/libcxl.c | 142 +++++++++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 5 ++ - cxl/lib/private.h | 14 +++ - cxl/libcxl.h | 11 +++ - cxl/list.c | 19 +++-- - 12 files changed, 431 insertions(+), 24 deletions(-) - -diff --git a/.clang-format b/.clang-format -index d2e77d0..1154c76 100644 ---- a/.clang-format -+++ b/.clang-format -@@ -78,6 +78,7 @@ ExperimentalAutoDetectBinPacking: false - # | sort -u) - ForEachMacros: - - 'cxl_memdev_foreach' -+ - 'cxl_bus_foreach' - - 'daxctl_dev_foreach' - - 'daxctl_mapping_foreach' - - 'daxctl_region_foreach' -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 224c972..be131ae 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -15,17 +15,60 @@ SYNOPSIS - Walk the CXL capable device hierarchy in the system and list all device - instances along with some of their major attributes. - --Options can be specified to limit the output to specific objects. -+Options can be specified to limit the output to specific objects. When a -+single object type is specified the return json object is an array of -+just those objects, when multiple objects types are specified the -+returned the returned object may be an array of arrays with the inner -+array named for the given object type. -+ -+Filters can by specifed as either a single identidier, a space separated -+quoted string, or a comma separated list. When multiple filter -+identifiers are specified within a filter string, like "-m -+mem0,mem1,mem2", they are combined as an 'OR' filter. When multiple -+filter string types are specified, like "-m mem0,mem1,mem2 -p port10", -+they are combined as an 'AND' filter. So, "-m mem0,mem1,mem2 -p port10" -+would only list objects that are beneath port10 AND map mem0, mem1, OR -+mem2. -+ -+The --human option in addition to reformatting some fields to more human -+friendly strings also unwraps the array to reduce the number of lines of -+output. - - EXAMPLE - ------- - ---- - # cxl list --memdevs --{ -- "memdev":"mem0", -- "pmem_size":268435456, -- "ram_size":0, --} -+[ -+ { -+ "memdev":"mem0", -+ "pmem_size":268435456, -+ "ram_size":0, -+ "serial":0 -+ } -+] -+ -+# cxl list -BMu -+[ -+ { -+ "anon memdevs":[ -+ { -+ "memdev":"mem0", -+ "pmem_size":"256.00 MiB (268.44 MB)", -+ "ram_size":0, -+ "serial":"0" -+ } -+ ] -+ }, -+ { -+ "buses":[ -+ { -+ "bus":"root0", -+ "provider":"ACPI.CXL" -+ } -+ ] -+ } -+] -+ - ---- - - OPTIONS -@@ -34,13 +77,6 @@ OPTIONS - --memdev=:: - Specify CXL memory device name(s), or device id(s), to filter the listing. For example: - ---- --# cxl list --memdev=mem0 --{ -- "memdev":"mem0", -- "pmem_size":268435456, -- "ram_size":0, --} -- - # cxl list -M --memdev="0 mem3 5" - [ - { -@@ -114,6 +150,32 @@ OPTIONS - ] - ---- - -+-B:: -+--buses:: -+ Include 'bus' / CXL root object(s) in the listing. Typically, on ACPI -+ systems the bus object is a singleton associated with the ACPI0017 -+ device, but there are test scenerios where there may be multiple CXL -+ memory hierarchies. -+---- -+# cxl list -B -+[ -+ { -+ "bus":"root3", -+ "provider":"cxl_test" -+ }, -+ { -+ "bus":"root0", -+ "provider":"ACPI.CXL" -+ } -+] -+---- -+ -+-b:: -+--bus=:: -+ Specify CXL root device name(s), device id(s), and / or CXL bus provider -+ names to filter the listing. The supported provider names are "ACPI.CXL" -+ and "cxl_test". -+ - include::human-option.txt[] - - include::verbose-option.txt[] -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index c127326..84af66a 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -134,6 +134,36 @@ cxl_memdev{read,write,zero}_label() are helpers for marshaling multiple - label access commands over an arbitrary extent of the device's label - area. - -+BUSES -+----- -+The CXL Memory space is CPU and Device coherent. The address ranges that -+support coherent access are described by platform firmware and -+communicated to the operating system via a CXL root object 'struct -+cxl_bus'. -+ -+=== BUS: Enumeration -+---- -+struct cxl_bus *cxl_bus_get_first(struct cxl_ctx *ctx); -+struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus); -+ -+#define cxl_bus_foreach(ctx, bus) \ -+ for (bus = cxl_bus_get_first(ctx); bus != NULL; \ -+ bus = cxl_bus_get_next(bus)) -+---- -+ -+=== BUS: Attributes -+---- -+const char *cxl_bus_get_provider(struct cxl_bus *bus); -+const char *cxl_bus_get_devname(struct cxl_bus *bus); -+int cxl_bus_get_id(struct cxl_bus *bus); -+---- -+ -+The provider name of a bus is a persistent name that is independent of -+discovery order. The possible provider names are 'ACPI.CXL' and -+'cxl_test'. The devname and id attributes, like other objects, are just -+the kernel device names that are subject to change based on discovery -+order. -+ - include::../../copyright.txt[] - - SEE ALSO -diff --git a/cxl/filter.c b/cxl/filter.c -index 26efc65..5f4844b 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -1,5 +1,5 @@ - // SPDX-License-Identifier: GPL-2.0 --// Copyright (C) 2015-2020 Intel Corporation. All rights reserved. -+// Copyright (C) 2015-2022 Intel Corporation. All rights reserved. - #include - #include - #include -@@ -21,6 +21,43 @@ static const char *which_sep(const char *filter) - return " "; - } - -+static struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus, -+ const char *__ident) -+{ -+ char *ident, *save; -+ const char *arg; -+ int bus_id; -+ -+ if (!__ident) -+ return bus; -+ -+ ident = strdup(__ident); -+ if (!ident) -+ return NULL; -+ -+ for (arg = strtok_r(ident, which_sep(__ident), &save); arg; -+ arg = strtok_r(NULL, which_sep(__ident), &save)) { -+ if (strcmp(arg, "all") == 0) -+ break; -+ -+ if ((sscanf(arg, "%d", &bus_id) == 1 || -+ sscanf(arg, "root%d", &bus_id) == 1) && -+ cxl_bus_get_id(bus) == bus_id) -+ break; -+ -+ if (strcmp(arg, cxl_bus_get_devname(bus)) == 0) -+ break; -+ -+ if (strcmp(arg, cxl_bus_get_provider(bus)) == 0) -+ break; -+ } -+ -+ free(ident); -+ if (arg) -+ return bus; -+ return NULL; -+} -+ - static struct cxl_memdev * - util_cxl_memdev_serial_filter(struct cxl_memdev *memdev, const char *__serials) - { -@@ -98,21 +135,67 @@ static unsigned long params_to_flags(struct cxl_filter_params *param) - return flags; - } - -+static void splice_array(struct cxl_filter_params *p, struct json_object *jobjs, -+ struct json_object *platform, -+ const char *container_name, bool do_container) -+{ -+ size_t count; -+ -+ if (!json_object_array_length(jobjs)) { -+ json_object_put(jobjs); -+ return; -+ } -+ -+ if (do_container) { -+ struct json_object *container = json_object_new_object(); -+ -+ if (!container) { -+ err(p, "failed to list: %s\n", container_name); -+ return; -+ } -+ -+ json_object_object_add(container, container_name, jobjs); -+ json_object_array_add(platform, container); -+ return; -+ } -+ -+ for (count = json_object_array_length(jobjs); count; count--) { -+ struct json_object *jobj = json_object_array_get_idx(jobjs, 0); -+ -+ json_object_get(jobj); -+ json_object_array_del_idx(jobjs, 0, 1); -+ json_object_array_add(platform, jobj); -+ } -+ json_object_put(jobjs); -+} -+ - int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - { - struct json_object *jplatform = json_object_new_array(); -+ struct json_object *jdevs = NULL, *jbuses = NULL; - unsigned long flags = params_to_flags(p); - struct cxl_memdev *memdev; -+ int top_level_objs = 0; -+ struct cxl_bus *bus; - - if (!jplatform) { - dbg(p, "platform object allocation failure\n"); - return -ENOMEM; - } - -+ jdevs = json_object_new_array(); -+ if (!jdevs) -+ goto err; -+ -+ jbuses = json_object_new_array(); -+ if (!jbuses) -+ goto err; -+ - cxl_memdev_foreach(ctx, memdev) { - struct json_object *jdev; - -- if (!util_cxl_memdev_filter(memdev, p->memdev_filter, p->serial_filter)) -+ if (!util_cxl_memdev_filter(memdev, p->memdev_filter, -+ p->serial_filter)) - continue; - if (p->memdevs) { - jdev = util_cxl_memdev_to_json(memdev, flags); -@@ -120,11 +203,39 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - dbg(p, "memdev object allocation failure\n"); - continue; - } -- json_object_array_add(jplatform, jdev); -+ json_object_array_add(jdevs, jdev); -+ } -+ } -+ -+ cxl_bus_foreach(ctx, bus) { -+ struct json_object *jbus; -+ -+ if (!util_cxl_bus_filter(bus, p->bus_filter)) -+ continue; -+ if (p->buses) { -+ jbus = util_cxl_bus_to_json(bus, flags); -+ if (!jbus) { -+ dbg(p, "bus object allocation failure\n"); -+ continue; -+ } -+ json_object_array_add(jbuses, jbus); - } - } - -+ if (json_object_array_length(jdevs)) -+ top_level_objs++; -+ if (json_object_array_length(jbuses)) -+ top_level_objs++; -+ -+ splice_array(p, jdevs, jplatform, "anon memdevs", top_level_objs > 1); -+ splice_array(p, jbuses, jplatform, "buses", top_level_objs > 1); -+ - util_display_json_array(stdout, jplatform, flags); - - return 0; -+err: -+ json_object_put(jdevs); -+ json_object_put(jbuses); -+ json_object_put(jplatform); -+ return -ENOMEM; - } -diff --git a/cxl/filter.h b/cxl/filter.h -index 12d9344..d41e757 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -9,7 +9,9 @@ - struct cxl_filter_params { - const char *memdev_filter; - const char *serial_filter; -+ const char *bus_filter; - bool memdevs; -+ bool buses; - bool idle; - bool human; - bool health; -diff --git a/cxl/json.c b/cxl/json.c -index d8e65df..a584594 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -221,3 +221,24 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - } - return jdev; - } -+ -+struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus, -+ unsigned long flags) -+{ -+ const char *devname = cxl_bus_get_devname(bus); -+ struct json_object *jbus, *jobj; -+ -+ jbus = json_object_new_object(); -+ if (!jbus) -+ return NULL; -+ -+ jobj = json_object_new_string(devname); -+ if (jobj) -+ json_object_object_add(jbus, "bus", jobj); -+ -+ jobj = json_object_new_string(cxl_bus_get_provider(bus)); -+ if (jobj) -+ json_object_object_add(jbus, "provider", jobj); -+ -+ return jbus; -+} -diff --git a/cxl/json.h b/cxl/json.h -index 3abcfe6..4abf6e5 100644 ---- a/cxl/json.h -+++ b/cxl/json.h -@@ -1,8 +1,11 @@ - /* SPDX-License-Identifier: GPL-2.0 */ --/* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */ -+/* Copyright (C) 2015-2022 Intel Corporation. All rights reserved. */ - #ifndef __CXL_UTIL_JSON_H__ - #define __CXL_UTIL_JSON_H__ - struct cxl_memdev; - struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - unsigned long flags); -+struct cxl_bus; -+struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus, -+ unsigned long flags); - #endif /* __CXL_UTIL_JSON_H__ */ -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 9839f26..8548a45 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -40,7 +40,9 @@ struct cxl_ctx { - int refcount; - void *userdata; - int memdevs_init; -+ int buses_init; - struct list_head memdevs; -+ struct list_head buses; - struct kmod_ctx *kmod_ctx; - void *private_data; - }; -@@ -64,6 +66,21 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head) - free(memdev); - } - -+static void __free_port(struct cxl_port *port, struct list_head *head) -+{ -+ if (head) -+ list_del_from(head, &port->list); -+ free(port->dev_buf); -+ free(port->dev_path); -+ free(port->uport); -+} -+ -+static void free_bus(struct cxl_bus *bus, struct list_head *head) -+{ -+ __free_port(&bus->port, head); -+ free(bus); -+} -+ - /** - * cxl_get_userdata - retrieve stored data pointer from library context - * @ctx: cxl library context -@@ -130,6 +147,7 @@ CXL_EXPORT int cxl_new(struct cxl_ctx **ctx) - dbg(c, "log_priority=%d\n", c->ctx.log_priority); - *ctx = c; - list_head_init(&c->memdevs); -+ list_head_init(&c->buses); - c->kmod_ctx = kmod_ctx; - - return 0; -@@ -160,6 +178,7 @@ CXL_EXPORT struct cxl_ctx *cxl_ref(struct cxl_ctx *ctx) - CXL_EXPORT void cxl_unref(struct cxl_ctx *ctx) - { - struct cxl_memdev *memdev, *_d; -+ struct cxl_bus *bus, *_b; - - if (ctx == NULL) - return; -@@ -170,6 +189,9 @@ CXL_EXPORT void cxl_unref(struct cxl_ctx *ctx) - list_for_each_safe(&ctx->memdevs, memdev, _d, list) - free_memdev(memdev, &ctx->memdevs); - -+ list_for_each_safe(&ctx->buses, bus, _b, port.list) -+ free_bus(bus, &ctx->buses); -+ - kmod_unref(ctx->kmod_ctx); - info(ctx, "context %p released\n", ctx); - free(ctx); -@@ -449,6 +471,126 @@ CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev) - return is_enabled(path); - } - -+static int cxl_port_init(struct cxl_port *port, struct cxl_ctx *ctx, int id, -+ const char *cxlport_base) -+{ -+ char *path = calloc(1, strlen(cxlport_base) + 100); -+ size_t rc; -+ -+ if (!path) -+ return -ENOMEM; -+ -+ port->id = id; -+ port->ctx = ctx; -+ -+ port->dev_path = strdup(cxlport_base); -+ if (!port->dev_path) -+ goto err; -+ -+ port->dev_buf = calloc(1, strlen(cxlport_base) + 50); -+ if (!port->dev_buf) -+ goto err; -+ port->buf_len = strlen(cxlport_base) + 50; -+ -+ rc = snprintf(port->dev_buf, port->buf_len, "%s/uport", cxlport_base); -+ if (rc >= port->buf_len) -+ goto err; -+ port->uport = realpath(port->dev_buf, NULL); -+ if (!port->uport) -+ goto err; -+ -+ return 0; -+err: -+ free(port->dev_path); -+ free(port->dev_buf); -+ free(path); -+ return -ENOMEM; -+} -+ -+static void *add_cxl_bus(void *parent, int id, const char *cxlbus_base) -+{ -+ const char *devname = devpath_to_devname(cxlbus_base); -+ struct cxl_bus *bus, *bus_dup; -+ struct cxl_ctx *ctx = parent; -+ struct cxl_port *port; -+ int rc; -+ -+ dbg(ctx, "%s: base: \'%s\'\n", devname, cxlbus_base); -+ -+ bus = calloc(1, sizeof(*bus)); -+ if (!bus) -+ return NULL; -+ -+ port = &bus->port; -+ rc = cxl_port_init(port, ctx, id, cxlbus_base); -+ if (rc) -+ goto err; -+ -+ cxl_bus_foreach(ctx, bus_dup) -+ if (bus_dup->port.id == bus->port.id) { -+ free_bus(bus, NULL); -+ return bus_dup; -+ } -+ -+ list_add(&ctx->buses, &port->list); -+ return bus; -+ -+err: -+ free(bus); -+ return NULL; -+} -+ -+static void cxl_buses_init(struct cxl_ctx *ctx) -+{ -+ if (ctx->buses_init) -+ return; -+ -+ ctx->buses_init = 1; -+ -+ sysfs_device_parse(ctx, "/sys/bus/cxl/devices", "root", ctx, -+ add_cxl_bus); -+} -+ -+CXL_EXPORT struct cxl_bus *cxl_bus_get_first(struct cxl_ctx *ctx) -+{ -+ cxl_buses_init(ctx); -+ -+ return list_top(&ctx->buses, struct cxl_bus, port.list); -+} -+ -+CXL_EXPORT struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus) -+{ -+ struct cxl_ctx *ctx = bus->port.ctx; -+ -+ return list_next(&ctx->buses, bus, port.list); -+} -+ -+CXL_EXPORT const char *cxl_bus_get_devname(struct cxl_bus *bus) -+{ -+ struct cxl_port *port = &bus->port; -+ -+ return devpath_to_devname(port->dev_path); -+} -+ -+CXL_EXPORT int cxl_bus_get_id(struct cxl_bus *bus) -+{ -+ struct cxl_port *port = &bus->port; -+ -+ return port->id; -+} -+ -+CXL_EXPORT const char *cxl_bus_get_provider(struct cxl_bus *bus) -+{ -+ struct cxl_port *port = &bus->port; -+ const char *devname = devpath_to_devname(port->uport); -+ -+ if (strcmp(devname, "ACPI0017:00") == 0) -+ return "ACPI.CXL"; -+ if (strcmp(devname, "cxl_acpi.0") == 0) -+ return "cxl_test"; -+ return devname; -+} -+ - CXL_EXPORT void cxl_cmd_unref(struct cxl_cmd *cmd) - { - if (!cmd) -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 4411035..781ff99 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -77,4 +77,9 @@ local: - LIBCXL_2 { - global: - cxl_memdev_get_serial; -+ cxl_bus_get_first; -+ cxl_bus_get_next; -+ cxl_bus_get_provider; -+ cxl_bus_get_devname; -+ cxl_bus_get_id; - } LIBCXL_1; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 7c81e24..0758d05 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -34,6 +34,20 @@ struct cxl_memdev { - unsigned long long serial; - }; - -+struct cxl_port { -+ int id; -+ void *dev_buf; -+ size_t buf_len; -+ char *dev_path; -+ char *uport; -+ struct cxl_ctx *ctx; -+ struct list_node list; -+}; -+ -+struct cxl_bus { -+ struct cxl_port port; -+}; -+ - enum cxl_cmd_query_status { - CXL_CMD_QUERY_NOT_RUN = 0, - CXL_CMD_QUERY_OK, -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index bcdede8..da66eb2 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -57,6 +57,17 @@ int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf, size_t length, - memdev != NULL; \ - memdev = cxl_memdev_get_next(memdev)) - -+struct cxl_bus; -+struct cxl_bus *cxl_bus_get_first(struct cxl_ctx *ctx); -+struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus); -+const char *cxl_bus_get_provider(struct cxl_bus *bus); -+const char *cxl_bus_get_devname(struct cxl_bus *bus); -+int cxl_bus_get_id(struct cxl_bus *bus); -+ -+#define cxl_bus_foreach(ctx, bus) \ -+ for (bus = cxl_bus_get_first(ctx); bus != NULL; \ -+ bus = cxl_bus_get_next(bus)) -+ - struct cxl_cmd; - const char *cxl_cmd_get_devname(struct cxl_cmd *cmd); - struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode); -diff --git a/cxl/list.c b/cxl/list.c -index 7e2744d..9500e61 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -1,5 +1,5 @@ - // SPDX-License-Identifier: GPL-2.0 --/* Copyright (C) 2020-2021 Intel Corporation. All rights reserved. */ -+/* Copyright (C) 2020-2022 Intel Corporation. All rights reserved. */ - #include - #include - #include -@@ -14,11 +14,6 @@ - - static struct cxl_filter_params param; - --static int num_list_flags(void) --{ -- return param.memdevs; --} -- - static const struct option options[] = { - OPT_STRING('m', "memdev", ¶m.memdev_filter, "memory device name(s)", - "filter by CXL memory device name(s)"), -@@ -27,6 +22,9 @@ static const struct option options[] = { - "filter by CXL memory device serial number(s)"), - OPT_BOOLEAN('M', "memdevs", ¶m.memdevs, - "include CXL memory device info"), -+ OPT_STRING('b', "bus", ¶m.bus_filter, "bus device name", -+ "filter by CXL bus device name(s)"), -+ OPT_BOOLEAN('B', "buses", ¶m.buses, "include CXL bus info"), - OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"), - OPT_BOOLEAN('u', "human", ¶m.human, - "use human friendly number formats "), -@@ -35,6 +33,11 @@ static const struct option options[] = { - OPT_END(), - }; - -+static int num_list_flags(void) -+{ -+ return !!param.memdevs + !!param.buses; -+} -+ - int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - { - const char * const u[] = { -@@ -53,7 +56,9 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - if (num_list_flags() == 0) { - if (param.memdev_filter || param.serial_filter) - param.memdevs = true; -- else { -+ if (param.bus_filter) -+ param.buses = true; -+ if (num_list_flags() == 0) { - /* - * TODO: We likely want to list regions by default if - * nothing was explicitly asked for. But until we have --- -2.27.0 - diff --git a/SOURCES/0101-util-json-Warn-on-stderr-about-empty-list-results.patch b/SOURCES/0101-util-json-Warn-on-stderr-about-empty-list-results.patch deleted file mode 100644 index b8fcc87..0000000 --- a/SOURCES/0101-util-json-Warn-on-stderr-about-empty-list-results.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 91f78bbcda7fc644041dfabfa679c6a627f90e76 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:53:08 -0800 -Subject: [PATCH 101/217] util/json: Warn on stderr about empty list results - -Help interactive users notice something is wrong with the list parameters -by warning that no devices matched the specified filter settings. - -Link: https://lore.kernel.org/r/164298558814.3021641.13051269428355986099.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - util/json.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/util/json.c b/util/json.c -index bd5f8fc..f8cc81f 100644 ---- a/util/json.c -+++ b/util/json.c -@@ -3,6 +3,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -95,9 +96,11 @@ void util_display_json_array(FILE *f_out, struct json_object *jarray, - int len = json_object_array_length(jarray); - int jflag = JSON_C_TO_STRING_PRETTY; - -- if (json_object_array_length(jarray) > 1 || !(flags & UTIL_JSON_HUMAN)) -+ if (len > 1 || !(flags & UTIL_JSON_HUMAN)) { -+ if (len == 0) -+ warning("no matching devices found\n"); - fprintf(f_out, "%s\n", json_object_to_json_string_ext(jarray, jflag)); -- else if (len) { -+ } else if (len) { - struct json_object *jobj; - - jobj = json_object_array_get_idx(jarray, 0); --- -2.27.0 - diff --git a/SOURCES/0102-util-sysfs-Uplevel-modalias-lookup-helper-to-util.patch b/SOURCES/0102-util-sysfs-Uplevel-modalias-lookup-helper-to-util.patch deleted file mode 100644 index 6d8dd93..0000000 --- a/SOURCES/0102-util-sysfs-Uplevel-modalias-lookup-helper-to-util.patch +++ /dev/null @@ -1,165 +0,0 @@ -From ecd7e6e7aabfa2592f3f739a725d135eb43d6314 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:53:13 -0800 -Subject: [PATCH 102/217] util/sysfs: Uplevel modalias lookup helper to util/ - -The to_module() helper looks up modules relative to a modalias. Uplevel -this to share with libcxl. - -Link: https://lore.kernel.org/r/164298559346.3021641.11059026790676662837.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - ndctl/lib/libndctl.c | 33 +++++---------------------------- - util/sysfs.c | 27 +++++++++++++++++++++++++++ - util/sysfs.h | 8 ++++++++ - 3 files changed, 40 insertions(+), 28 deletions(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index 47a234c..1374ad9 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -1668,7 +1668,6 @@ static enum ndctl_fwa_result fwa_result_to_result(const char *result) - static int ndctl_bind(struct ndctl_ctx *ctx, struct kmod_module *module, - const char *devname); - static int ndctl_unbind(struct ndctl_ctx *ctx, const char *devpath); --static struct kmod_module *to_module(struct ndctl_ctx *ctx, const char *alias); - - static int populate_dimm_attributes(struct ndctl_dimm *dimm, - const char *dimm_base, -@@ -1878,7 +1877,7 @@ static void *add_dimm(void *parent, int id, const char *dimm_base) - sprintf(path, "%s/modalias", dimm_base); - if (sysfs_read_attr(ctx, path, buf) < 0) - goto err_read; -- dimm->module = to_module(ctx, buf); -+ dimm->module = util_modalias_to_module(ctx, buf); - - dimm->handle = -1; - dimm->phys_id = -1; -@@ -2597,7 +2596,7 @@ static void *add_region(void *parent, int id, const char *region_base) - sprintf(path, "%s/modalias", region_base); - if (sysfs_read_attr(ctx, path, buf) < 0) - goto err_read; -- region->module = to_module(ctx, buf); -+ region->module = util_modalias_to_module(ctx, buf); - - sprintf(path, "%s/numa_node", region_base); - if ((rc = sysfs_read_attr(ctx, path, buf)) == 0) -@@ -3885,28 +3884,6 @@ NDCTL_EXPORT struct ndctl_ctx *ndctl_mapping_get_ctx( - return ndctl_mapping_get_bus(mapping)->ctx; - } - --static struct kmod_module *to_module(struct ndctl_ctx *ctx, const char *alias) --{ -- struct kmod_list *list = NULL; -- struct kmod_module *mod; -- int rc; -- -- if (!ctx->kmod_ctx) -- return NULL; -- -- rc = kmod_module_new_from_lookup(ctx->kmod_ctx, alias, &list); -- if (rc < 0 || !list) { -- dbg(ctx, "failed to find module for alias: %s %d list: %s\n", -- alias, rc, list ? "populated" : "empty"); -- return NULL; -- } -- mod = kmod_module_get_module(list); -- dbg(ctx, "alias: %s module: %s\n", alias, kmod_module_get_name(mod)); -- kmod_module_unref_list(list); -- -- return mod; --} -- - static char *get_block_device(struct ndctl_ctx *ctx, const char *block_path) - { - char *bdev_name = NULL; -@@ -4069,7 +4046,7 @@ static void *add_namespace(void *parent, int id, const char *ndns_base) - sprintf(path, "%s/modalias", ndns_base); - if (sysfs_read_attr(ctx, path, buf) < 0) - goto err_read; -- ndns->module = to_module(ctx, buf); -+ ndns->module = util_modalias_to_module(ctx, buf); - - ndctl_namespace_foreach(region, ndns_dup) - if (ndns_dup->id == ndns->id) { -@@ -5182,7 +5159,7 @@ static void *add_btt(void *parent, int id, const char *btt_base) - sprintf(path, "%s/modalias", btt_base); - if (sysfs_read_attr(ctx, path, buf) < 0) - goto err_read; -- btt->module = to_module(ctx, buf); -+ btt->module = util_modalias_to_module(ctx, buf); - - sprintf(path, "%s/uuid", btt_base); - if (sysfs_read_attr(ctx, path, buf) < 0) -@@ -5533,7 +5510,7 @@ static void *__add_pfn(struct ndctl_pfn *pfn, const char *pfn_base) - sprintf(path, "%s/modalias", pfn_base); - if (sysfs_read_attr(ctx, path, buf) < 0) - goto err_read; -- pfn->module = to_module(ctx, buf); -+ pfn->module = util_modalias_to_module(ctx, buf); - - sprintf(path, "%s/uuid", pfn_base); - if (sysfs_read_attr(ctx, path, buf) < 0) -diff --git a/util/sysfs.c b/util/sysfs.c -index cfbab7d..23330cb 100644 ---- a/util/sysfs.c -+++ b/util/sysfs.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -118,3 +119,29 @@ int __sysfs_device_parse(struct log_ctx *ctx, const char *base_path, - - return add_errors; - } -+ -+struct kmod_module *__util_modalias_to_module(struct kmod_ctx *kmod_ctx, -+ const char *alias, -+ struct log_ctx *log) -+{ -+ struct kmod_list *list = NULL; -+ struct kmod_module *mod; -+ int rc; -+ -+ if (!kmod_ctx) -+ return NULL; -+ -+ rc = kmod_module_new_from_lookup(kmod_ctx, alias, &list); -+ if (rc < 0 || !list) { -+ log_dbg(log, -+ "failed to find module for alias: %s %d list: %s\n", -+ alias, rc, list ? "populated" : "empty"); -+ return NULL; -+ } -+ mod = kmod_module_get_module(list); -+ log_dbg(log, "alias: %s module: %s\n", alias, -+ kmod_module_get_name(mod)); -+ kmod_module_unref_list(list); -+ -+ return mod; -+} -diff --git a/util/sysfs.h b/util/sysfs.h -index 6485a73..bdee4f5 100644 ---- a/util/sysfs.h -+++ b/util/sysfs.h -@@ -27,4 +27,12 @@ static inline const char *devpath_to_devname(const char *devpath) - { - return strrchr(devpath, '/') + 1; - } -+ -+struct kmod_ctx; -+struct kmod_module; -+struct kmod_module *__util_modalias_to_module(struct kmod_ctx *kmod_ctx, -+ const char *alias, -+ struct log_ctx *log); -+#define util_modalias_to_module(ctx, buf) \ -+ __util_modalias_to_module((ctx)->kmod_ctx, buf, &(ctx)->ctx) - #endif /* __UTIL_SYSFS_H__ */ --- -2.27.0 - diff --git a/SOURCES/0103-cxl-list-Add-port-enumeration.patch b/SOURCES/0103-cxl-list-Add-port-enumeration.patch deleted file mode 100644 index 832d485..0000000 --- a/SOURCES/0103-cxl-list-Add-port-enumeration.patch +++ /dev/null @@ -1,862 +0,0 @@ -From fef3f05ca8cdfd8d783162042d5cf20325c8b64b Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:53:18 -0800 -Subject: [PATCH 103/217] cxl/list: Add port enumeration - -Between a cxl_bus (root port) and an endpoint there can be an arbitrary -level of switches. Add enumeration for these ports at each level of the -hierarchy. - -However, given the CXL root ports are also "ports" infer that if the port -filter argument is the word "root" or "root%d" then include root ports in -the listing. The keyword "switch" is also provided to filter only the ports -beneath the root that are not endpoint ports. - -Link: https://lore.kernel.org/r/164298559854.3021641.17724828997703051001.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .clang-format | 1 + - Documentation/cxl/cxl-list.txt | 24 ++++ - Documentation/cxl/lib/libcxl.txt | 42 ++++++ - cxl/filter.c | 224 ++++++++++++++++++++++++++++++- - cxl/filter.h | 4 + - cxl/json.c | 23 ++++ - cxl/json.h | 3 + - cxl/lib/libcxl.c | 160 +++++++++++++++++++++- - cxl/lib/libcxl.sym | 12 ++ - cxl/lib/private.h | 11 ++ - cxl/libcxl.h | 19 +++ - cxl/list.c | 17 ++- - 12 files changed, 534 insertions(+), 6 deletions(-) - -diff --git a/.clang-format b/.clang-format -index 1154c76..391cd34 100644 ---- a/.clang-format -+++ b/.clang-format -@@ -79,6 +79,7 @@ ExperimentalAutoDetectBinPacking: false - ForEachMacros: - - 'cxl_memdev_foreach' - - 'cxl_bus_foreach' -+ - 'cxl_port_foreach' - - 'daxctl_dev_foreach' - - 'daxctl_mapping_foreach' - - 'daxctl_region_foreach' -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index be131ae..3076deb 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -176,6 +176,30 @@ OPTIONS - names to filter the listing. The supported provider names are "ACPI.CXL" - and "cxl_test". - -+-P:: -+--ports:: -+ Include port objects (CXL / PCIe root ports + Upstream Switch Ports) in -+ the listing. -+ -+-p:: -+--port=:: -+ Specify CXL Port device name(s), device id(s), and or port type -+ names to filter the listing. The supported port type names are "root" -+ and "switch". Note that since a bus object is also a port, the following -+ two syntaxes are equivalent: -+---- -+# cxl list -B -+# cxl list -P -p root -+---- -+ By default, only 'switch' ports are listed. -+ -+-S:: -+--single:: -+ Specify whether the listing should emit all the objects that are -+ descendants of a port that matches the port filter, or only direct -+ descendants of the individual ports that match the filter. By default -+ all descendant objects are listed. -+ - include::human-option.txt[] - - include::verbose-option.txt[] -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 84af66a..804e9ca 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -164,6 +164,48 @@ discovery order. The possible provider names are 'ACPI.CXL' and - the kernel device names that are subject to change based on discovery - order. - -+PORTS -+----- -+CXL ports track the PCIe hierarchy between a platform firmware CXL root -+object, through CXL / PCIe Host Bridges, CXL / PCIe Root Ports, and CXL -+/ PCIe Switch Ports. -+ -+=== PORT: Enumeration -+---- -+struct cxl_port *cxl_bus_get_port(struct cxl_bus *bus); -+struct cxl_port *cxl_port_get_first(struct cxl_port *parent); -+struct cxl_port *cxl_port_get_next(struct cxl_port *port); -+struct cxl_port *cxl_port_get_parent(struct cxl_port *port); -+struct cxl_bus *cxl_port_get_bus(struct cxl_port *port); -+struct cxl_ctx *cxl_port_get_ctx(struct cxl_port *port); -+ -+#define cxl_port_foreach(parent, port) \ -+ for (port = cxl_port_get_first(parent); port != NULL; \ -+ port = cxl_port_get_next(port)) -+---- -+A bus object encapsulates a CXL port object. Use cxl_bus_get_port() to -+use generic port APIs on root objects. -+ -+Ports are hierarchical. All but the a root object have another CXL port -+as a parent object retrievable via cxl_port_get_parent(). -+ -+The root port of a hiearchy can be retrieved via any port instance in -+that hierarchy via cxl_port_get_bus(). -+ -+=== PORT: Attributes -+---- -+const char *cxl_port_get_devname(struct cxl_port *port); -+int cxl_port_get_id(struct cxl_port *port); -+int cxl_port_is_enabled(struct cxl_port *port); -+bool cxl_port_is_root(struct cxl_port *port); -+bool cxl_port_is_switch(struct cxl_port *port); -+---- -+The port type is communicated via cxl_port_is_(). An 'enabled' port -+is one that has succeeded in discovering the CXL component registers in -+the host device and has enumerated its downstream ports. In order for a -+memdev to be enabled for CXL memory operation all CXL ports in its -+ancestry must also be enabled. -+ - include::../../copyright.txt[] - - SEE ALSO -diff --git a/cxl/filter.c b/cxl/filter.c -index 5f4844b..8b79db3 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -21,6 +21,101 @@ static const char *which_sep(const char *filter) - return " "; - } - -+bool cxl_filter_has(const char *__filter, const char *needle) -+{ -+ char *filter, *save; -+ const char *arg; -+ -+ if (!needle) -+ return true; -+ -+ if (!__filter) -+ return false; -+ -+ filter = strdup(__filter); -+ if (!filter) -+ return false; -+ -+ for (arg = strtok_r(filter, which_sep(__filter), &save); arg; -+ arg = strtok_r(NULL, which_sep(__filter), &save)) -+ if (strstr(arg, needle)) -+ break; -+ -+ free(filter); -+ if (arg) -+ return true; -+ return false; -+} -+ -+static struct cxl_port *__util_cxl_port_filter(struct cxl_port *port, -+ const char *__ident) -+{ -+ char *ident, *save; -+ const char *arg; -+ int port_id; -+ -+ if (!__ident) -+ return port; -+ -+ ident = strdup(__ident); -+ if (!ident) -+ return NULL; -+ -+ for (arg = strtok_r(ident, which_sep(__ident), &save); arg; -+ arg = strtok_r(NULL, which_sep(__ident), &save)) { -+ if (strcmp(arg, "all") == 0) -+ break; -+ -+ if (strcmp(arg, "root") == 0 && cxl_port_is_root(port)) -+ break; -+ -+ if (strcmp(arg, "switch") == 0 && cxl_port_is_switch(port)) -+ break; -+ -+ if ((sscanf(arg, "%d", &port_id) == 1 || -+ sscanf(arg, "port%d", &port_id) == 1) && -+ cxl_port_get_id(port) == port_id) -+ break; -+ -+ if (strcmp(arg, cxl_port_get_devname(port)) == 0) -+ break; -+ } -+ -+ free(ident); -+ if (arg) -+ return port; -+ return NULL; -+} -+ -+enum cxl_port_filter_mode { -+ CXL_PF_SINGLE, -+ CXL_PF_ANCESTRY, -+}; -+ -+static enum cxl_port_filter_mode pf_mode(struct cxl_filter_params *p) -+{ -+ if (p->single) -+ return CXL_PF_SINGLE; -+ return CXL_PF_ANCESTRY; -+} -+ -+static struct cxl_port *util_cxl_port_filter(struct cxl_port *port, -+ const char *ident, -+ enum cxl_port_filter_mode mode) -+{ -+ struct cxl_port *iter = port; -+ -+ while (iter) { -+ if (__util_cxl_port_filter(iter, ident)) -+ return port; -+ if (mode == CXL_PF_SINGLE) -+ return NULL; -+ iter = cxl_port_get_parent(iter); -+ } -+ -+ return NULL; -+} -+ - static struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus, - const char *__ident) - { -@@ -58,6 +153,31 @@ static struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus, - return NULL; - } - -+static struct cxl_port *util_cxl_port_filter_by_bus(struct cxl_port *port, -+ const char *__ident) -+{ -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ struct cxl_bus *bus; -+ -+ if (!__ident) -+ return port; -+ -+ if (cxl_port_is_root(port)) { -+ bus = cxl_port_to_bus(port); -+ bus = util_cxl_bus_filter(bus, __ident); -+ return bus ? port : NULL; -+ } -+ -+ cxl_bus_foreach(ctx, bus) { -+ if (!util_cxl_bus_filter(bus, __ident)) -+ continue; -+ if (bus == cxl_port_get_bus(port)) -+ return port; -+ } -+ -+ return NULL; -+} -+ - static struct cxl_memdev * - util_cxl_memdev_serial_filter(struct cxl_memdev *memdev, const char *__serials) - { -@@ -169,10 +289,82 @@ static void splice_array(struct cxl_filter_params *p, struct json_object *jobjs, - json_object_put(jobjs); - } - -+static bool cond_add_put_array(struct json_object *jobj, const char *key, -+ struct json_object *array) -+{ -+ if (jobj && array && json_object_array_length(array) > 0) { -+ json_object_object_add(jobj, key, array); -+ return true; -+ } else { -+ json_object_put(array); -+ return false; -+ } -+} -+ -+static bool cond_add_put_array_suffix(struct json_object *jobj, const char *key, -+ const char *suffix, -+ struct json_object *array) -+{ -+ char *name; -+ bool rc; -+ -+ if (asprintf(&name, "%s:%s", key, suffix) < 0) -+ return false; -+ rc = cond_add_put_array(jobj, name, array); -+ free(name); -+ return rc; -+} -+ -+static struct json_object *pick_array(struct json_object *child, -+ struct json_object *container) -+{ -+ if (child) -+ return child; -+ if (container) -+ return container; -+ return NULL; -+} -+ -+static void walk_child_ports(struct cxl_port *parent_port, -+ struct cxl_filter_params *p, -+ struct json_object *jports, -+ unsigned long flags) -+{ -+ struct cxl_port *port; -+ -+ cxl_port_foreach(parent_port, port) { -+ const char *devname = cxl_port_get_devname(port); -+ struct json_object *jport = NULL; -+ struct json_object *jchildports = NULL; -+ -+ if (!util_cxl_port_filter(port, p->port_filter, pf_mode(p))) -+ goto walk_children; -+ if (!util_cxl_port_filter_by_bus(port, p->bus_filter)) -+ goto walk_children; -+ if (!p->idle && !cxl_port_is_enabled(port)) -+ continue; -+ if (p->ports) -+ jport = util_cxl_port_to_json(port, flags); -+ if (!jport) -+ continue; -+ json_object_array_add(jports, jport); -+ jchildports = json_object_new_array(); -+ if (!jchildports) { -+ err(p, "%s: failed to enumerate child ports\n", -+ devname); -+ continue; -+ } -+walk_children: -+ walk_child_ports(port, p, pick_array(jchildports, jports), -+ flags); -+ cond_add_put_array_suffix(jport, "ports", devname, jchildports); -+ } -+} -+ - int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - { -+ struct json_object *jdevs = NULL, *jbuses = NULL, *jports = NULL; - struct json_object *jplatform = json_object_new_array(); -- struct json_object *jdevs = NULL, *jbuses = NULL; - unsigned long flags = params_to_flags(p); - struct cxl_memdev *memdev; - int top_level_objs = 0; -@@ -191,6 +383,10 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - if (!jbuses) - goto err; - -+ jports = json_object_new_array(); -+ if (!jports) -+ goto err; -+ - cxl_memdev_foreach(ctx, memdev) { - struct json_object *jdev; - -@@ -208,10 +404,15 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - } - - cxl_bus_foreach(ctx, bus) { -- struct json_object *jbus; -+ struct json_object *jbus = NULL; -+ struct json_object *jchildports = NULL; -+ struct cxl_port *port = cxl_bus_get_port(bus); -+ const char *devname = cxl_bus_get_devname(bus); - - if (!util_cxl_bus_filter(bus, p->bus_filter)) -- continue; -+ goto walk_children; -+ if (!util_cxl_port_filter(port, p->port_filter, pf_mode(p))) -+ goto walk_children; - if (p->buses) { - jbus = util_cxl_bus_to_json(bus, flags); - if (!jbus) { -@@ -219,16 +420,32 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - continue; - } - json_object_array_add(jbuses, jbus); -+ if (p->ports) { -+ jchildports = json_object_new_array(); -+ if (!jchildports) { -+ err(p, -+ "%s: failed to enumerate child ports\n", -+ devname); -+ continue; -+ } -+ } - } -+walk_children: -+ walk_child_ports(port, p, pick_array(jchildports, jports), -+ flags); -+ cond_add_put_array_suffix(jbus, "ports", devname, jchildports); - } - - if (json_object_array_length(jdevs)) - top_level_objs++; - if (json_object_array_length(jbuses)) - top_level_objs++; -+ if (json_object_array_length(jports)) -+ top_level_objs++; - - splice_array(p, jdevs, jplatform, "anon memdevs", top_level_objs > 1); - splice_array(p, jbuses, jplatform, "buses", top_level_objs > 1); -+ splice_array(p, jports, jplatform, "ports", top_level_objs > 1); - - util_display_json_array(stdout, jplatform, flags); - -@@ -236,6 +453,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - err: - json_object_put(jdevs); - json_object_put(jbuses); -+ json_object_put(jports); - json_object_put(jplatform); - return -ENOMEM; - } -diff --git a/cxl/filter.h b/cxl/filter.h -index d41e757..0d83304 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -10,7 +10,10 @@ struct cxl_filter_params { - const char *memdev_filter; - const char *serial_filter; - const char *bus_filter; -+ const char *port_filter; -+ bool single; - bool memdevs; -+ bool ports; - bool buses; - bool idle; - bool human; -@@ -22,4 +25,5 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, - const char *__ident, - const char *serials); - int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *param); -+bool cxl_filter_has(const char *needle, const char *__filter); - #endif /* _CXL_UTIL_FILTER_H_ */ -diff --git a/cxl/json.c b/cxl/json.c -index a584594..d9f864e 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -242,3 +242,26 @@ struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus, - - return jbus; - } -+ -+struct json_object *util_cxl_port_to_json(struct cxl_port *port, -+ unsigned long flags) -+{ -+ const char *devname = cxl_port_get_devname(port); -+ struct json_object *jport, *jobj; -+ -+ jport = json_object_new_object(); -+ if (!jport) -+ return NULL; -+ -+ jobj = json_object_new_string(devname); -+ if (jobj) -+ json_object_object_add(jport, "port", jobj); -+ -+ if (!cxl_port_is_enabled(port)) { -+ jobj = json_object_new_string("disabled"); -+ if (jobj) -+ json_object_object_add(jport, "state", jobj); -+ } -+ -+ return jport; -+} -diff --git a/cxl/json.h b/cxl/json.h -index 4abf6e5..36653db 100644 ---- a/cxl/json.h -+++ b/cxl/json.h -@@ -8,4 +8,7 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - struct cxl_bus; - struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus, - unsigned long flags); -+struct cxl_port; -+struct json_object *util_cxl_port_to_json(struct cxl_port *port, -+ unsigned long flags); - #endif /* __CXL_UTIL_JSON_H__ */ -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 8548a45..03eff3c 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -66,15 +66,27 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head) - free(memdev); - } - -+static void free_port(struct cxl_port *port, struct list_head *head); - static void __free_port(struct cxl_port *port, struct list_head *head) - { -+ struct cxl_port *child, *_c; -+ - if (head) - list_del_from(head, &port->list); -+ list_for_each_safe(&port->child_ports, child, _c, list) -+ free_port(child, &port->child_ports); -+ kmod_module_unref(port->module); - free(port->dev_buf); - free(port->dev_path); - free(port->uport); - } - -+static void free_port(struct cxl_port *port, struct list_head *head) -+{ -+ __free_port(port, head); -+ free(port); -+} -+ - static void free_bus(struct cxl_bus *bus, struct list_head *head) - { - __free_port(&bus->port, head); -@@ -471,10 +483,12 @@ CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev) - return is_enabled(path); - } - --static int cxl_port_init(struct cxl_port *port, struct cxl_ctx *ctx, int id, -+static int cxl_port_init(struct cxl_port *port, struct cxl_port *parent_port, -+ enum cxl_port_type type, struct cxl_ctx *ctx, int id, - const char *cxlport_base) - { - char *path = calloc(1, strlen(cxlport_base) + 100); -+ char buf[SYSFS_ATTR_SIZE]; - size_t rc; - - if (!path) -@@ -482,6 +496,10 @@ static int cxl_port_init(struct cxl_port *port, struct cxl_ctx *ctx, int id, - - port->id = id; - port->ctx = ctx; -+ port->type = type; -+ port->parent = parent_port; -+ -+ list_head_init(&port->child_ports); - - port->dev_path = strdup(cxlport_base); - if (!port->dev_path) -@@ -499,6 +517,10 @@ static int cxl_port_init(struct cxl_port *port, struct cxl_ctx *ctx, int id, - if (!port->uport) - goto err; - -+ sprintf(path, "%s/modalias", cxlport_base); -+ if (sysfs_read_attr(ctx, path, buf) == 0) -+ port->module = util_modalias_to_module(ctx, buf); -+ - return 0; - err: - free(port->dev_path); -@@ -507,6 +529,135 @@ err: - return -ENOMEM; - } - -+static void *add_cxl_port(void *parent, int id, const char *cxlport_base) -+{ -+ const char *devname = devpath_to_devname(cxlport_base); -+ struct cxl_port *port, *port_dup; -+ struct cxl_port *parent_port = parent; -+ struct cxl_ctx *ctx = cxl_port_get_ctx(parent_port); -+ int rc; -+ -+ dbg(ctx, "%s: base: \'%s\'\n", devname, cxlport_base); -+ -+ port = calloc(1, sizeof(*port)); -+ if (!port) -+ return NULL; -+ -+ rc = cxl_port_init(port, parent_port, CXL_PORT_SWITCH, ctx, id, -+ cxlport_base); -+ if (rc) -+ goto err; -+ -+ cxl_port_foreach(parent_port, port_dup) -+ if (port_dup->id == port->id) { -+ free_port(port, NULL); -+ return port_dup; -+ } -+ -+ list_add(&parent_port->child_ports, &port->list); -+ return port; -+ -+err: -+ free(port); -+ return NULL; -+ -+} -+ -+static void cxl_ports_init(struct cxl_port *port) -+{ -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ -+ if (port->ports_init) -+ return; -+ -+ port->ports_init = 1; -+ -+ sysfs_device_parse(ctx, port->dev_path, "port", port, add_cxl_port); -+} -+ -+CXL_EXPORT struct cxl_ctx *cxl_port_get_ctx(struct cxl_port *port) -+{ -+ return port->ctx; -+} -+ -+CXL_EXPORT struct cxl_port *cxl_port_get_first(struct cxl_port *port) -+{ -+ cxl_ports_init(port); -+ -+ return list_top(&port->child_ports, struct cxl_port, list); -+} -+ -+CXL_EXPORT struct cxl_port *cxl_port_get_next(struct cxl_port *port) -+{ -+ struct cxl_port *parent_port = port->parent; -+ -+ return list_next(&parent_port->child_ports, port, list); -+} -+ -+CXL_EXPORT const char *cxl_port_get_devname(struct cxl_port *port) -+{ -+ return devpath_to_devname(port->dev_path); -+} -+ -+CXL_EXPORT int cxl_port_get_id(struct cxl_port *port) -+{ -+ return port->id; -+} -+ -+CXL_EXPORT struct cxl_port *cxl_port_get_parent(struct cxl_port *port) -+{ -+ return port->parent; -+} -+ -+CXL_EXPORT bool cxl_port_is_root(struct cxl_port *port) -+{ -+ return port->type == CXL_PORT_ROOT; -+} -+ -+CXL_EXPORT bool cxl_port_is_switch(struct cxl_port *port) -+{ -+ return port->type == CXL_PORT_SWITCH; -+} -+ -+CXL_EXPORT struct cxl_bus *cxl_port_get_bus(struct cxl_port *port) -+{ -+ struct cxl_bus *bus; -+ -+ if (!cxl_port_is_enabled(port)) -+ return NULL; -+ -+ if (port->bus) -+ return port->bus; -+ -+ while (port->parent) -+ port = port->parent; -+ -+ bus = container_of(port, typeof(*bus), port); -+ port->bus = bus; -+ return bus; -+} -+ -+CXL_EXPORT int cxl_port_is_enabled(struct cxl_port *port) -+{ -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ char *path = port->dev_buf; -+ int len = port->buf_len; -+ -+ if (snprintf(path, len, "%s/driver", port->dev_path) >= len) { -+ err(ctx, "%s: buffer too small!\n", cxl_port_get_devname(port)); -+ return 0; -+ } -+ -+ return is_enabled(path); -+} -+ -+CXL_EXPORT struct cxl_bus *cxl_port_to_bus(struct cxl_port *port) -+{ -+ if (!cxl_port_is_root(port)) -+ return NULL; -+ return container_of(port, struct cxl_bus, port); -+} -+ - static void *add_cxl_bus(void *parent, int id, const char *cxlbus_base) - { - const char *devname = devpath_to_devname(cxlbus_base); -@@ -522,7 +673,7 @@ static void *add_cxl_bus(void *parent, int id, const char *cxlbus_base) - return NULL; - - port = &bus->port; -- rc = cxl_port_init(port, ctx, id, cxlbus_base); -+ rc = cxl_port_init(port, NULL, CXL_PORT_ROOT, ctx, id, cxlbus_base); - if (rc) - goto err; - -@@ -579,6 +730,11 @@ CXL_EXPORT int cxl_bus_get_id(struct cxl_bus *bus) - return port->id; - } - -+CXL_EXPORT struct cxl_port *cxl_bus_get_port(struct cxl_bus *bus) -+{ -+ return &bus->port; -+} -+ - CXL_EXPORT const char *cxl_bus_get_provider(struct cxl_bus *bus) - { - struct cxl_port *port = &bus->port; -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 781ff99..a7e923f 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -82,4 +82,16 @@ global: - cxl_bus_get_provider; - cxl_bus_get_devname; - cxl_bus_get_id; -+ cxl_bus_get_port; -+ cxl_port_get_first; -+ cxl_port_get_next; -+ cxl_port_get_devname; -+ cxl_port_get_id; -+ cxl_port_get_ctx; -+ cxl_port_is_enabled; -+ cxl_port_get_parent; -+ cxl_port_is_root; -+ cxl_port_is_switch; -+ cxl_port_to_bus; -+ cxl_port_get_bus; - } LIBCXL_1; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 0758d05..637f90d 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -34,14 +34,25 @@ struct cxl_memdev { - unsigned long long serial; - }; - -+enum cxl_port_type { -+ CXL_PORT_ROOT, -+ CXL_PORT_SWITCH, -+}; -+ - struct cxl_port { - int id; - void *dev_buf; - size_t buf_len; - char *dev_path; - char *uport; -+ int ports_init; - struct cxl_ctx *ctx; -+ struct cxl_bus *bus; -+ enum cxl_port_type type; -+ struct cxl_port *parent; -+ struct kmod_module *module; - struct list_node list; -+ struct list_head child_ports; - }; - - struct cxl_bus { -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index da66eb2..efbb397 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -5,6 +5,7 @@ - - #include - #include -+#include - - #ifdef HAVE_UUID - #include -@@ -63,11 +64,29 @@ struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus); - const char *cxl_bus_get_provider(struct cxl_bus *bus); - const char *cxl_bus_get_devname(struct cxl_bus *bus); - int cxl_bus_get_id(struct cxl_bus *bus); -+struct cxl_port *cxl_bus_get_port(struct cxl_bus *bus); - - #define cxl_bus_foreach(ctx, bus) \ - for (bus = cxl_bus_get_first(ctx); bus != NULL; \ - bus = cxl_bus_get_next(bus)) - -+struct cxl_port; -+struct cxl_port *cxl_port_get_first(struct cxl_port *parent); -+struct cxl_port *cxl_port_get_next(struct cxl_port *port); -+const char *cxl_port_get_devname(struct cxl_port *port); -+int cxl_port_get_id(struct cxl_port *port); -+struct cxl_ctx *cxl_port_get_ctx(struct cxl_port *port); -+int cxl_port_is_enabled(struct cxl_port *port); -+struct cxl_port *cxl_port_get_parent(struct cxl_port *port); -+bool cxl_port_is_root(struct cxl_port *port); -+bool cxl_port_is_switch(struct cxl_port *port); -+struct cxl_bus *cxl_port_to_bus(struct cxl_port *port); -+struct cxl_bus *cxl_port_get_bus(struct cxl_port *port); -+ -+#define cxl_port_foreach(parent, port) \ -+ for (port = cxl_port_get_first(parent); port != NULL; \ -+ port = cxl_port_get_next(port)) -+ - struct cxl_cmd; - const char *cxl_cmd_get_devname(struct cxl_cmd *cmd); - struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode); -diff --git a/cxl/list.c b/cxl/list.c -index 9500e61..1ef91b4 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -25,6 +25,11 @@ static const struct option options[] = { - OPT_STRING('b', "bus", ¶m.bus_filter, "bus device name", - "filter by CXL bus device name(s)"), - OPT_BOOLEAN('B', "buses", ¶m.buses, "include CXL bus info"), -+ OPT_STRING('p', "port", ¶m.port_filter, "port device name", -+ "filter by CXL port device name(s)"), -+ OPT_BOOLEAN('P', "ports", ¶m.ports, "include CXL port info"), -+ OPT_BOOLEAN('S', "single", ¶m.single, -+ "skip listing descendant objects"), - OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"), - OPT_BOOLEAN('u', "human", ¶m.human, - "use human friendly number formats "), -@@ -35,7 +40,7 @@ static const struct option options[] = { - - static int num_list_flags(void) - { -- return !!param.memdevs + !!param.buses; -+ return !!param.memdevs + !!param.buses + !!param.ports; - } - - int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) -@@ -53,11 +58,18 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - if (argc) - usage_with_options(u, options); - -+ if (param.single && !param.port_filter) { -+ error("-S/--single expects a port filter: -p/--port=\n"); -+ usage_with_options(u, options); -+ } -+ - if (num_list_flags() == 0) { - if (param.memdev_filter || param.serial_filter) - param.memdevs = true; - if (param.bus_filter) - param.buses = true; -+ if (param.port_filter) -+ param.ports = true; - if (num_list_flags() == 0) { - /* - * TODO: We likely want to list regions by default if -@@ -73,5 +85,8 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - - log_init(¶m.ctx, "cxl list", "CXL_LIST_LOG"); - -+ if (cxl_filter_has(param.port_filter, "root") && param.ports) -+ param.buses = true; -+ - return cxl_filter_walk(ctx, ¶m); - } --- -2.27.0 - diff --git a/SOURCES/0104-cxl-list-Add-debug-option.patch b/SOURCES/0104-cxl-list-Add-debug-option.patch deleted file mode 100644 index 8cfb023..0000000 --- a/SOURCES/0104-cxl-list-Add-debug-option.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 2a43dce3913b392a13a5ee918c8ee831a25d720e Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:53:24 -0800 -Subject: [PATCH 104/217] cxl/list: Add --debug option - -Add an option to turn on libray and cxl_filter_walk() messages. Gate it -based on the global ENABLE_DEBUG configuration setting. - -Link: https://lore.kernel.org/r/164298560409.3021641.11040422738199381922.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 6 ++++-- - cxl/filter.c | 3 +++ - cxl/list.c | 9 +++++++++ - 3 files changed, 16 insertions(+), 2 deletions(-) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 3076deb..42b6de6 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -200,9 +200,11 @@ OPTIONS - descendants of the individual ports that match the filter. By default - all descendant objects are listed. - --include::human-option.txt[] -+--debug:: -+ If the cxl tool was built with debug enabled, turn on debug -+ messages. - --include::verbose-option.txt[] -+include::human-option.txt[] - - include::../copyright.txt[] - -diff --git a/cxl/filter.c b/cxl/filter.c -index 8b79db3..32171a4 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -387,6 +387,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - if (!jports) - goto err; - -+ dbg(p, "walk memdevs\n"); - cxl_memdev_foreach(ctx, memdev) { - struct json_object *jdev; - -@@ -403,6 +404,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - } - } - -+ dbg(p, "walk buses\n"); - cxl_bus_foreach(ctx, bus) { - struct json_object *jbus = NULL; - struct json_object *jchildports = NULL; -@@ -431,6 +433,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - } - } - walk_children: -+ dbg(p, "walk ports\n"); - walk_child_ports(port, p, pick_array(jchildports, jports), - flags); - cond_add_put_array_suffix(jbus, "ports", devname, jchildports); -diff --git a/cxl/list.c b/cxl/list.c -index 1ef91b4..01ab19b 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -13,6 +13,7 @@ - #include "filter.h" - - static struct cxl_filter_params param; -+static bool debug; - - static const struct option options[] = { - OPT_STRING('m', "memdev", ¶m.memdev_filter, "memory device name(s)", -@@ -35,6 +36,9 @@ static const struct option options[] = { - "use human friendly number formats "), - OPT_BOOLEAN('H', "health", ¶m.health, - "include memory device health information "), -+#ifdef ENABLE_DEBUG -+ OPT_BOOLEAN(0, "debug", &debug, "debug list walk"), -+#endif - OPT_END(), - }; - -@@ -84,9 +88,14 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - } - - log_init(¶m.ctx, "cxl list", "CXL_LIST_LOG"); -+ if (debug) { -+ cxl_set_log_priority(ctx, LOG_DEBUG); -+ param.ctx.log_priority = LOG_DEBUG; -+ } - - if (cxl_filter_has(param.port_filter, "root") && param.ports) - param.buses = true; - -+ dbg(¶m, "walk topology\n"); - return cxl_filter_walk(ctx, ¶m); - } --- -2.27.0 - diff --git a/SOURCES/0105-cxl-list-Add-endpoints.patch b/SOURCES/0105-cxl-list-Add-endpoints.patch deleted file mode 100644 index 959ca13..0000000 --- a/SOURCES/0105-cxl-list-Add-endpoints.patch +++ /dev/null @@ -1,746 +0,0 @@ -From 7eb06a5293531854e7a28666e955106094d3552b Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:53:29 -0800 -Subject: [PATCH 105/217] cxl/list: Add endpoints - -Endpoints are port-like objects that represent the HDM decoders at terminal -end of a decode chain. Unlike port decoders that route to downstream ports, -endpoint decoders route to endpoint DPA (Device Physical Address) ranges. - -Link: https://lore.kernel.org/r/164298560917.3021641.13753578554905796298.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .clang-format | 1 + - Documentation/cxl/cxl-list.txt | 16 ++++ - Documentation/cxl/lib/libcxl.txt | 31 ++++++- - cxl/filter.c | 147 ++++++++++++++++++++++++++++--- - cxl/filter.h | 2 + - cxl/json.c | 20 ++++- - cxl/json.h | 2 + - cxl/lib/libcxl.c | 107 ++++++++++++++++++++++ - cxl/lib/libcxl.sym | 9 ++ - cxl/lib/private.h | 10 +++ - cxl/libcxl.h | 15 ++++ - cxl/list.c | 13 ++- - 12 files changed, 355 insertions(+), 18 deletions(-) - -diff --git a/.clang-format b/.clang-format -index 391cd34..106bc5e 100644 ---- a/.clang-format -+++ b/.clang-format -@@ -80,6 +80,7 @@ ForEachMacros: - - 'cxl_memdev_foreach' - - 'cxl_bus_foreach' - - 'cxl_port_foreach' -+ - 'cxl_endpoint_foreach' - - 'daxctl_dev_foreach' - - 'daxctl_mapping_foreach' - - 'daxctl_region_foreach' -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 42b6de6..d342da2 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -190,6 +190,12 @@ OPTIONS - ---- - # cxl list -B - # cxl list -P -p root -+---- -+ Additionally, endpoint objects are also ports so the following commands -+ are also equivalent. -+---- -+# cxl list -E -+# cxl list -P -p endpoint - ---- - By default, only 'switch' ports are listed. - -@@ -200,6 +206,16 @@ OPTIONS - descendants of the individual ports that match the filter. By default - all descendant objects are listed. - -+-E:: -+--endpoints:: -+ Include endpoint objects (CXL Memory Device decoders) in the -+ listing. -+ -+-e:: -+--endpoint:: -+ Specify CXL endpoint device name(s), or device id(s) to filter -+ the emitted endpoint(s). -+ - --debug:: - If the cxl tool was built with debug enabled, turn on debug - messages. -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 804e9ca..eebab37 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -199,12 +199,41 @@ int cxl_port_get_id(struct cxl_port *port); - int cxl_port_is_enabled(struct cxl_port *port); - bool cxl_port_is_root(struct cxl_port *port); - bool cxl_port_is_switch(struct cxl_port *port); -+bool cxl_port_is_endpoint(struct cxl_port *port); - ---- - The port type is communicated via cxl_port_is_(). An 'enabled' port - is one that has succeeded in discovering the CXL component registers in - the host device and has enumerated its downstream ports. In order for a - memdev to be enabled for CXL memory operation all CXL ports in its --ancestry must also be enabled. -+ancestry must also be enabled including a root port, an arbitrary number -+of intervening switch ports, and a terminal endpoint port. -+ -+ENDPOINTS -+--------- -+CXL endpoint objects encapsulate the set of host-managed device-memory -+(HDM) decoders in a physical memory device. The endpoint is the last hop -+in a decoder chain that translate SPA to DPA (system-physical-address to -+device-local-physical-address). -+ -+=== ENDPOINT: Enumeration -+---- -+struct cxl_endpoint *cxl_endpoint_get_first(struct cxl_port *parent); -+struct cxl_endpoint *cxl_endpoint_get_next(struct cxl_endpoint *endpoint); -+struct cxl_ctx *cxl_endpoint_get_ctx(struct cxl_endpoint *endpoint); -+struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint); -+struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint); -+ -+#define cxl_endpoint_foreach(port, endpoint) \ -+ for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \ -+ endpoint = cxl_endpoint_get_next(endpoint)) -+---- -+ -+=== ENDPOINT: Attributes -+---- -+const char *cxl_endpoint_get_devname(struct cxl_endpoint *endpoint); -+int cxl_endpoint_get_id(struct cxl_endpoint *endpoint); -+int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint); -+---- - - include::../../copyright.txt[] - -diff --git a/cxl/filter.c b/cxl/filter.c -index 32171a4..5d80d1b 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -47,8 +47,42 @@ bool cxl_filter_has(const char *__filter, const char *needle) - return false; - } - -+static struct cxl_endpoint * -+util_cxl_endpoint_filter(struct cxl_endpoint *endpoint, const char *__ident) -+{ -+ char *ident, *save; -+ const char *arg; -+ int endpoint_id; -+ -+ if (!__ident) -+ return endpoint; -+ -+ ident = strdup(__ident); -+ if (!ident) -+ return NULL; -+ -+ for (arg = strtok_r(ident, which_sep(__ident), &save); arg; -+ arg = strtok_r(NULL, which_sep(__ident), &save)) { -+ if (strcmp(arg, "all") == 0) -+ break; -+ -+ if ((sscanf(arg, "%d", &endpoint_id) == 1 || -+ sscanf(arg, "endpoint%d", &endpoint_id) == 1) && -+ cxl_endpoint_get_id(endpoint) == endpoint_id) -+ break; -+ -+ if (strcmp(arg, cxl_endpoint_get_devname(endpoint)) == 0) -+ break; -+ } -+ -+ free(ident); -+ if (arg) -+ return endpoint; -+ return NULL; -+} -+ - static struct cxl_port *__util_cxl_port_filter(struct cxl_port *port, -- const char *__ident) -+ const char *__ident) - { - char *ident, *save; - const char *arg; -@@ -72,6 +106,9 @@ static struct cxl_port *__util_cxl_port_filter(struct cxl_port *port, - if (strcmp(arg, "switch") == 0 && cxl_port_is_switch(port)) - break; - -+ if (strcmp(arg, "endpoint") == 0 && cxl_port_is_endpoint(port)) -+ break; -+ - if ((sscanf(arg, "%d", &port_id) == 1 || - sscanf(arg, "port%d", &port_id) == 1) && - cxl_port_get_id(port) == port_id) -@@ -116,6 +153,24 @@ static struct cxl_port *util_cxl_port_filter(struct cxl_port *port, - return NULL; - } - -+static struct cxl_endpoint * -+util_cxl_endpoint_filter_by_port(struct cxl_endpoint *endpoint, -+ const char *ident, -+ enum cxl_port_filter_mode mode) -+{ -+ struct cxl_port *iter = cxl_endpoint_get_port(endpoint); -+ -+ if (util_cxl_port_filter(iter, ident, CXL_PF_SINGLE)) -+ return endpoint; -+ iter = cxl_port_get_parent(iter); -+ if (!iter) -+ return NULL; -+ if (util_cxl_port_filter(iter, ident, mode)) -+ return endpoint; -+ -+ return NULL; -+} -+ - static struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus, - const char *__ident) - { -@@ -325,10 +380,34 @@ static struct json_object *pick_array(struct json_object *child, - return NULL; - } - -+static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p, -+ struct json_object *jeps, unsigned long flags) -+{ -+ struct cxl_endpoint *endpoint; -+ -+ cxl_endpoint_foreach(port, endpoint) { -+ struct cxl_port *ep_port = cxl_endpoint_get_port(endpoint); -+ struct json_object *jendpoint; -+ -+ if (!util_cxl_endpoint_filter(endpoint, p->endpoint_filter)) -+ continue; -+ if (!util_cxl_port_filter_by_bus(ep_port, p->bus_filter)) -+ continue; -+ if (!util_cxl_endpoint_filter_by_port(endpoint, p->port_filter, -+ pf_mode(p))) -+ continue; -+ if (!p->idle && !cxl_endpoint_is_enabled(endpoint)) -+ continue; -+ jendpoint = util_cxl_endpoint_to_json(endpoint, flags); -+ if (jendpoint) -+ json_object_array_add(jeps, jendpoint); -+ } -+} -+ - static void walk_child_ports(struct cxl_port *parent_port, - struct cxl_filter_params *p, - struct json_object *jports, -- unsigned long flags) -+ struct json_object *jeps, unsigned long flags) - { - struct cxl_port *port; - -@@ -336,6 +415,7 @@ static void walk_child_ports(struct cxl_port *parent_port, - const char *devname = cxl_port_get_devname(port); - struct json_object *jport = NULL; - struct json_object *jchildports = NULL; -+ struct json_object *jchildendpoints = NULL; - - if (!util_cxl_port_filter(port, p->port_filter, pf_mode(p))) - goto walk_children; -@@ -343,21 +423,41 @@ static void walk_child_ports(struct cxl_port *parent_port, - goto walk_children; - if (!p->idle && !cxl_port_is_enabled(port)) - continue; -- if (p->ports) -+ if (p->ports) { - jport = util_cxl_port_to_json(port, flags); -- if (!jport) -- continue; -- json_object_array_add(jports, jport); -- jchildports = json_object_new_array(); -- if (!jchildports) { -- err(p, "%s: failed to enumerate child ports\n", -- devname); -- continue; -+ if (!jport) { -+ err(p, "%s: failed to list\n", devname); -+ continue; -+ } -+ json_object_array_add(jports, jport); -+ jchildports = json_object_new_array(); -+ if (!jchildports) { -+ err(p, "%s: failed to enumerate child ports\n", -+ devname); -+ continue; -+ } -+ } -+ -+ if (p->ports && p->endpoints) { -+ jchildendpoints = json_object_new_array(); -+ if (!jchildendpoints) { -+ err(p, -+ "%s: failed to enumerate child endpoints\n", -+ devname); -+ continue; -+ } - } -+ - walk_children: -+ if (p->endpoints) -+ walk_endpoints(port, p, pick_array(jchildendpoints, jeps), -+ flags); -+ - walk_child_ports(port, p, pick_array(jchildports, jports), -- flags); -+ pick_array(jchildendpoints, jeps), flags); - cond_add_put_array_suffix(jport, "ports", devname, jchildports); -+ cond_add_put_array_suffix(jport, "endpoints", devname, -+ jchildendpoints); - } - } - -@@ -366,6 +466,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - struct json_object *jdevs = NULL, *jbuses = NULL, *jports = NULL; - struct json_object *jplatform = json_object_new_array(); - unsigned long flags = params_to_flags(p); -+ struct json_object *jeps = NULL; - struct cxl_memdev *memdev; - int top_level_objs = 0; - struct cxl_bus *bus; -@@ -387,6 +488,10 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - if (!jports) - goto err; - -+ jeps = json_object_new_array(); -+ if (!jeps) -+ goto err; -+ - dbg(p, "walk memdevs\n"); - cxl_memdev_foreach(ctx, memdev) { - struct json_object *jdev; -@@ -408,6 +513,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - cxl_bus_foreach(ctx, bus) { - struct json_object *jbus = NULL; - struct json_object *jchildports = NULL; -+ struct json_object *jchildeps = NULL; - struct cxl_port *port = cxl_bus_get_port(bus); - const char *devname = cxl_bus_get_devname(bus); - -@@ -431,12 +537,23 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - continue; - } - } -+ if (p->endpoints) { -+ jchildeps = json_object_new_array(); -+ if (!jchildeps) { -+ err(p, -+ "%s: failed to enumerate child endpoints\n", -+ devname); -+ continue; -+ } -+ } - } - walk_children: - dbg(p, "walk ports\n"); - walk_child_ports(port, p, pick_array(jchildports, jports), -- flags); -+ pick_array(jchildeps, jeps), flags); - cond_add_put_array_suffix(jbus, "ports", devname, jchildports); -+ cond_add_put_array_suffix(jbus, "endpoints", devname, -+ jchildeps); - } - - if (json_object_array_length(jdevs)) -@@ -445,10 +562,13 @@ walk_children: - top_level_objs++; - if (json_object_array_length(jports)) - top_level_objs++; -+ if (json_object_array_length(jeps)) -+ top_level_objs++; - - splice_array(p, jdevs, jplatform, "anon memdevs", top_level_objs > 1); - splice_array(p, jbuses, jplatform, "buses", top_level_objs > 1); - splice_array(p, jports, jplatform, "ports", top_level_objs > 1); -+ splice_array(p, jeps, jplatform, "endpoints", top_level_objs > 1); - - util_display_json_array(stdout, jplatform, flags); - -@@ -457,6 +577,7 @@ err: - json_object_put(jdevs); - json_object_put(jbuses); - json_object_put(jports); -+ json_object_put(jeps); - json_object_put(jplatform); - return -ENOMEM; - } -diff --git a/cxl/filter.h b/cxl/filter.h -index 0d83304..bbd341c 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -11,7 +11,9 @@ struct cxl_filter_params { - const char *serial_filter; - const char *bus_filter; - const char *port_filter; -+ const char *endpoint_filter; - bool single; -+ bool endpoints; - bool memdevs; - bool ports; - bool buses; -diff --git a/cxl/json.c b/cxl/json.c -index d9f864e..08f6192 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -243,8 +243,9 @@ struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus, - return jbus; - } - --struct json_object *util_cxl_port_to_json(struct cxl_port *port, -- unsigned long flags) -+static struct json_object *__util_cxl_port_to_json(struct cxl_port *port, -+ const char *name_key, -+ unsigned long flags) - { - const char *devname = cxl_port_get_devname(port); - struct json_object *jport, *jobj; -@@ -255,7 +256,7 @@ struct json_object *util_cxl_port_to_json(struct cxl_port *port, - - jobj = json_object_new_string(devname); - if (jobj) -- json_object_object_add(jport, "port", jobj); -+ json_object_object_add(jport, name_key, jobj); - - if (!cxl_port_is_enabled(port)) { - jobj = json_object_new_string("disabled"); -@@ -265,3 +266,16 @@ struct json_object *util_cxl_port_to_json(struct cxl_port *port, - - return jport; - } -+ -+struct json_object *util_cxl_port_to_json(struct cxl_port *port, -+ unsigned long flags) -+{ -+ return __util_cxl_port_to_json(port, "port", flags); -+} -+ -+struct json_object *util_cxl_endpoint_to_json(struct cxl_endpoint *endpoint, -+ unsigned long flags) -+{ -+ return __util_cxl_port_to_json(cxl_endpoint_get_port(endpoint), -+ "endpoint", flags); -+} -diff --git a/cxl/json.h b/cxl/json.h -index 36653db..8f45190 100644 ---- a/cxl/json.h -+++ b/cxl/json.h -@@ -11,4 +11,6 @@ struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus, - struct cxl_port; - struct json_object *util_cxl_port_to_json(struct cxl_port *port, - unsigned long flags); -+struct json_object *util_cxl_endpoint_to_json(struct cxl_endpoint *endpoint, -+ unsigned long flags); - #endif /* __CXL_UTIL_JSON_H__ */ -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 03eff3c..a25e715 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -67,14 +67,18 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head) - } - - static void free_port(struct cxl_port *port, struct list_head *head); -+static void free_endpoint(struct cxl_endpoint *endpoint, struct list_head *head); - static void __free_port(struct cxl_port *port, struct list_head *head) - { - struct cxl_port *child, *_c; -+ struct cxl_endpoint *endpoint, *_e; - - if (head) - list_del_from(head, &port->list); - list_for_each_safe(&port->child_ports, child, _c, list) - free_port(child, &port->child_ports); -+ list_for_each_safe(&port->endpoints, endpoint, _e, port.list) -+ free_endpoint(endpoint, &port->endpoints); - kmod_module_unref(port->module); - free(port->dev_buf); - free(port->dev_path); -@@ -87,6 +91,12 @@ static void free_port(struct cxl_port *port, struct list_head *head) - free(port); - } - -+static void free_endpoint(struct cxl_endpoint *endpoint, struct list_head *head) -+{ -+ __free_port(&endpoint->port, head); -+ free(endpoint); -+} -+ - static void free_bus(struct cxl_bus *bus, struct list_head *head) - { - __free_port(&bus->port, head); -@@ -500,6 +510,7 @@ static int cxl_port_init(struct cxl_port *port, struct cxl_port *parent_port, - port->parent = parent_port; - - list_head_init(&port->child_ports); -+ list_head_init(&port->endpoints); - - port->dev_path = strdup(cxlport_base); - if (!port->dev_path) -@@ -529,6 +540,97 @@ err: - return -ENOMEM; - } - -+static void *add_cxl_endpoint(void *parent, int id, const char *cxlep_base) -+{ -+ const char *devname = devpath_to_devname(cxlep_base); -+ struct cxl_endpoint *endpoint, *endpoint_dup; -+ struct cxl_port *port = parent; -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ int rc; -+ -+ dbg(ctx, "%s: base: \'%s\'\n", devname, cxlep_base); -+ -+ endpoint = calloc(1, sizeof(*endpoint)); -+ if (!endpoint) -+ return NULL; -+ -+ rc = cxl_port_init(&endpoint->port, port, CXL_PORT_ENDPOINT, ctx, id, -+ cxlep_base); -+ if (rc) -+ goto err; -+ -+ cxl_endpoint_foreach(port, endpoint_dup) -+ if (endpoint_dup->port.id == endpoint->port.id) { -+ free_endpoint(endpoint, NULL); -+ return endpoint_dup; -+ } -+ -+ list_add(&port->endpoints, &endpoint->port.list); -+ return endpoint; -+ -+err: -+ free(endpoint); -+ return NULL; -+ -+} -+ -+static void cxl_endpoints_init(struct cxl_port *port) -+{ -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ -+ if (port->endpoints_init) -+ return; -+ -+ port->endpoints_init = 1; -+ -+ sysfs_device_parse(ctx, port->dev_path, "endpoint", port, -+ add_cxl_endpoint); -+} -+ -+CXL_EXPORT struct cxl_ctx *cxl_endpoint_get_ctx(struct cxl_endpoint *endpoint) -+{ -+ return endpoint->port.ctx; -+} -+ -+CXL_EXPORT struct cxl_endpoint *cxl_endpoint_get_first(struct cxl_port *port) -+{ -+ cxl_endpoints_init(port); -+ -+ return list_top(&port->endpoints, struct cxl_endpoint, port.list); -+} -+ -+CXL_EXPORT struct cxl_endpoint *cxl_endpoint_get_next(struct cxl_endpoint *endpoint) -+{ -+ struct cxl_port *port = endpoint->port.parent; -+ -+ return list_next(&port->endpoints, endpoint, port.list); -+} -+ -+CXL_EXPORT const char *cxl_endpoint_get_devname(struct cxl_endpoint *endpoint) -+{ -+ return devpath_to_devname(endpoint->port.dev_path); -+} -+ -+CXL_EXPORT int cxl_endpoint_get_id(struct cxl_endpoint *endpoint) -+{ -+ return endpoint->port.id; -+} -+ -+CXL_EXPORT struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint) -+{ -+ return endpoint->port.parent; -+} -+ -+CXL_EXPORT struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint) -+{ -+ return &endpoint->port; -+} -+ -+CXL_EXPORT int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint) -+{ -+ return cxl_port_is_enabled(&endpoint->port); -+} -+ - static void *add_cxl_port(void *parent, int id, const char *cxlport_base) - { - const char *devname = devpath_to_devname(cxlport_base); -@@ -619,6 +721,11 @@ CXL_EXPORT bool cxl_port_is_switch(struct cxl_port *port) - return port->type == CXL_PORT_SWITCH; - } - -+CXL_EXPORT bool cxl_port_is_endpoint(struct cxl_port *port) -+{ -+ return port->type == CXL_PORT_ENDPOINT; -+} -+ - CXL_EXPORT struct cxl_bus *cxl_port_get_bus(struct cxl_port *port) - { - struct cxl_bus *bus; -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index a7e923f..7a51a0c 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -93,5 +93,14 @@ global: - cxl_port_is_root; - cxl_port_is_switch; - cxl_port_to_bus; -+ cxl_port_is_endpoint; - cxl_port_get_bus; -+ cxl_endpoint_get_first; -+ cxl_endpoint_get_next; -+ cxl_endpoint_get_devname; -+ cxl_endpoint_get_id; -+ cxl_endpoint_get_ctx; -+ cxl_endpoint_is_enabled; -+ cxl_endpoint_get_parent; -+ cxl_endpoint_get_port; - } LIBCXL_1; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 637f90d..cedd2f2 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -17,6 +17,7 @@ struct cxl_pmem { - char *dev_path; - }; - -+struct cxl_endpoint; - struct cxl_memdev { - int id, major, minor; - void *dev_buf; -@@ -32,11 +33,13 @@ struct cxl_memdev { - struct kmod_module *module; - struct cxl_pmem *pmem; - unsigned long long serial; -+ struct cxl_endpoint *endpoint; - }; - - enum cxl_port_type { - CXL_PORT_ROOT, - CXL_PORT_SWITCH, -+ CXL_PORT_ENDPOINT, - }; - - struct cxl_port { -@@ -46,6 +49,7 @@ struct cxl_port { - char *dev_path; - char *uport; - int ports_init; -+ int endpoints_init; - struct cxl_ctx *ctx; - struct cxl_bus *bus; - enum cxl_port_type type; -@@ -53,12 +57,18 @@ struct cxl_port { - struct kmod_module *module; - struct list_node list; - struct list_head child_ports; -+ struct list_head endpoints; - }; - - struct cxl_bus { - struct cxl_port port; - }; - -+struct cxl_endpoint { -+ struct cxl_port port; -+ struct cxl_memdev *memdev; -+}; -+ - enum cxl_cmd_query_status { - CXL_CMD_QUERY_NOT_RUN = 0, - CXL_CMD_QUERY_OK, -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index efbb397..f6ba9a1 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -81,12 +81,27 @@ struct cxl_port *cxl_port_get_parent(struct cxl_port *port); - bool cxl_port_is_root(struct cxl_port *port); - bool cxl_port_is_switch(struct cxl_port *port); - struct cxl_bus *cxl_port_to_bus(struct cxl_port *port); -+bool cxl_port_is_endpoint(struct cxl_port *port); - struct cxl_bus *cxl_port_get_bus(struct cxl_port *port); - - #define cxl_port_foreach(parent, port) \ - for (port = cxl_port_get_first(parent); port != NULL; \ - port = cxl_port_get_next(port)) - -+struct cxl_endpoint; -+struct cxl_endpoint *cxl_endpoint_get_first(struct cxl_port *parent); -+struct cxl_endpoint *cxl_endpoint_get_next(struct cxl_endpoint *endpoint); -+const char *cxl_endpoint_get_devname(struct cxl_endpoint *endpoint); -+int cxl_endpoint_get_id(struct cxl_endpoint *endpoint); -+struct cxl_ctx *cxl_endpoint_get_ctx(struct cxl_endpoint *endpoint); -+int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint); -+struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint); -+struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint); -+ -+#define cxl_endpoint_foreach(port, endpoint) \ -+ for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \ -+ endpoint = cxl_endpoint_get_next(endpoint)) -+ - struct cxl_cmd; - const char *cxl_cmd_get_devname(struct cxl_cmd *cmd); - struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode); -diff --git a/cxl/list.c b/cxl/list.c -index 01ab19b..b15e01c 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -31,6 +31,11 @@ static const struct option options[] = { - OPT_BOOLEAN('P', "ports", ¶m.ports, "include CXL port info"), - OPT_BOOLEAN('S', "single", ¶m.single, - "skip listing descendant objects"), -+ OPT_STRING('e', "endpoint", ¶m.endpoint_filter, -+ "endpoint device name", -+ "filter by CXL endpoint device name(s)"), -+ OPT_BOOLEAN('E', "endpoints", ¶m.endpoints, -+ "include CXL endpoint info"), - OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"), - OPT_BOOLEAN('u', "human", ¶m.human, - "use human friendly number formats "), -@@ -44,7 +49,8 @@ static const struct option options[] = { - - static int num_list_flags(void) - { -- return !!param.memdevs + !!param.buses + !!param.ports; -+ return !!param.memdevs + !!param.buses + !!param.ports + -+ !!param.endpoints; - } - - int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) -@@ -74,6 +80,8 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - param.buses = true; - if (param.port_filter) - param.ports = true; -+ if (param.endpoint_filter) -+ param.endpoints = true; - if (num_list_flags() == 0) { - /* - * TODO: We likely want to list regions by default if -@@ -96,6 +104,9 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - if (cxl_filter_has(param.port_filter, "root") && param.ports) - param.buses = true; - -+ if (cxl_filter_has(param.port_filter, "endpoint") && param.ports) -+ param.endpoints = true; -+ - dbg(¶m, "walk topology\n"); - return cxl_filter_walk(ctx, ¶m); - } --- -2.27.0 - diff --git a/SOURCES/0106-cxl-list-Add-host-entries-for-port-like-objects.patch b/SOURCES/0106-cxl-list-Add-host-entries-for-port-like-objects.patch deleted file mode 100644 index 313b105..0000000 --- a/SOURCES/0106-cxl-list-Add-host-entries-for-port-like-objects.patch +++ /dev/null @@ -1,154 +0,0 @@ -From f39735be3c1157fdfa7dd5c781048a411ebe4dc5 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:53:34 -0800 -Subject: [PATCH 106/217] cxl/list: Add 'host' entries for port-like objects - -Add the device name of the "host" device for a given CXL port object. The -kernel calls this the 'uport' attribute. - -Link: https://lore.kernel.org/r/164298561473.3021641.16508989603599026269.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 9 +++++++++ - Documentation/cxl/lib/libcxl.txt | 5 +++++ - cxl/json.c | 4 ++++ - cxl/lib/libcxl.c | 10 ++++++++++ - cxl/lib/libcxl.sym | 2 ++ - cxl/libcxl.h | 2 ++ - 6 files changed, 32 insertions(+) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index d342da2..30b6161 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -210,6 +210,15 @@ OPTIONS - --endpoints:: - Include endpoint objects (CXL Memory Device decoders) in the - listing. -+---- -+# cxl list -E -+[ -+ { -+ "endpoint":"endpoint2", -+ "host":"mem0" -+ } -+] -+---- - - -e:: - --endpoint:: -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index eebab37..e4b372d 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -178,6 +178,7 @@ struct cxl_port *cxl_port_get_next(struct cxl_port *port); - struct cxl_port *cxl_port_get_parent(struct cxl_port *port); - struct cxl_bus *cxl_port_get_bus(struct cxl_port *port); - struct cxl_ctx *cxl_port_get_ctx(struct cxl_port *port); -+const char *cxl_port_get_host(struct cxl_port *port); - - #define cxl_port_foreach(parent, port) \ - for (port = cxl_port_get_first(parent); port != NULL; \ -@@ -192,6 +193,9 @@ as a parent object retrievable via cxl_port_get_parent(). - The root port of a hiearchy can be retrieved via any port instance in - that hierarchy via cxl_port_get_bus(). - -+The host of a port is the corresponding device name of the PCIe Root -+Port, or Switch Upstream Port with CXL capabilities. -+ - === PORT: Attributes - ---- - const char *cxl_port_get_devname(struct cxl_port *port); -@@ -222,6 +226,7 @@ struct cxl_endpoint *cxl_endpoint_get_next(struct cxl_endpoint *endpoint); - struct cxl_ctx *cxl_endpoint_get_ctx(struct cxl_endpoint *endpoint); - struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint); - struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint); -+const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint); - - #define cxl_endpoint_foreach(port, endpoint) \ - for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \ -diff --git a/cxl/json.c b/cxl/json.c -index 08f6192..af3b4fe 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -258,6 +258,10 @@ static struct json_object *__util_cxl_port_to_json(struct cxl_port *port, - if (jobj) - json_object_object_add(jport, name_key, jobj); - -+ jobj = json_object_new_string(cxl_port_get_host(port)); -+ if (jobj) -+ json_object_object_add(jport, "host", jobj); -+ - if (!cxl_port_is_enabled(port)) { - jobj = json_object_new_string("disabled"); - if (jobj) -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index a25e715..5f48202 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -626,6 +626,11 @@ CXL_EXPORT struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint) - return &endpoint->port; - } - -+CXL_EXPORT const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint) -+{ -+ return cxl_port_get_host(&endpoint->port); -+} -+ - CXL_EXPORT int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint) - { - return cxl_port_is_enabled(&endpoint->port); -@@ -744,6 +749,11 @@ CXL_EXPORT struct cxl_bus *cxl_port_get_bus(struct cxl_port *port) - return bus; - } - -+CXL_EXPORT const char *cxl_port_get_host(struct cxl_port *port) -+{ -+ return devpath_to_devname(port->uport); -+} -+ - CXL_EXPORT int cxl_port_is_enabled(struct cxl_port *port) - { - struct cxl_ctx *ctx = cxl_port_get_ctx(port); -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 7a51a0c..dc2863e 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -95,6 +95,7 @@ global: - cxl_port_to_bus; - cxl_port_is_endpoint; - cxl_port_get_bus; -+ cxl_port_get_host; - cxl_endpoint_get_first; - cxl_endpoint_get_next; - cxl_endpoint_get_devname; -@@ -103,4 +104,5 @@ global: - cxl_endpoint_is_enabled; - cxl_endpoint_get_parent; - cxl_endpoint_get_port; -+ cxl_endpoint_get_host; - } LIBCXL_1; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index f6ba9a1..a60777e 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -83,6 +83,7 @@ bool cxl_port_is_switch(struct cxl_port *port); - struct cxl_bus *cxl_port_to_bus(struct cxl_port *port); - bool cxl_port_is_endpoint(struct cxl_port *port); - struct cxl_bus *cxl_port_get_bus(struct cxl_port *port); -+const char *cxl_port_get_host(struct cxl_port *port); - - #define cxl_port_foreach(parent, port) \ - for (port = cxl_port_get_first(parent); port != NULL; \ -@@ -97,6 +98,7 @@ struct cxl_ctx *cxl_endpoint_get_ctx(struct cxl_endpoint *endpoint); - int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint); - struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint); - struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint); -+const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint); - - #define cxl_endpoint_foreach(port, endpoint) \ - for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \ --- -2.27.0 - diff --git a/SOURCES/0107-cxl-list-Add-host-entries-for-memdevs.patch b/SOURCES/0107-cxl-list-Add-host-entries-for-memdevs.patch deleted file mode 100644 index 244428c..0000000 --- a/SOURCES/0107-cxl-list-Add-host-entries-for-memdevs.patch +++ /dev/null @@ -1,175 +0,0 @@ -From eec8c953a840a1cbdca63352c64cec3e48e86afe Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:53:39 -0800 -Subject: [PATCH 107/217] cxl/list: Add 'host' entries for memdevs - -For debugging CXL port connectivity issues it will be useful to have the -PCI device name for the memory expander in the 'memdev' listing. - -Link: https://lore.kernel.org/r/164298561980.3021641.9636572507721689266.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 3 ++- - Documentation/cxl/lib/libcxl.txt | 4 ++++ - cxl/json.c | 5 +++++ - cxl/lib/libcxl.c | 24 ++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 1 + - cxl/lib/private.h | 1 + - cxl/libcxl.h | 1 + - 7 files changed, 38 insertions(+), 1 deletion(-) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 30b6161..9c21ab7 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -43,7 +43,8 @@ EXAMPLE - "memdev":"mem0", - "pmem_size":268435456, - "ram_size":0, -- "serial":0 -+ "serial":0, -+ "host":"0000:35:00.0" - } - ] - -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index e4b372d..91fd33e 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -40,6 +40,7 @@ kernel, or to send data or trigger kernel operations for a given device. - struct cxl_memdev *cxl_memdev_get_first(struct cxl_ctx *ctx); - struct cxl_memdev *cxl_memdev_get_next(struct cxl_memdev *memdev); - struct cxl_ctx *cxl_memdev_get_ctx(struct cxl_memdev *memdev); -+const char *cxl_memdev_get_host(struct cxl_memdev *memdev) - - #define cxl_memdev_foreach(ctx, memdev) \ - for (memdev = cxl_memdev_get_first(ctx); \ -@@ -54,6 +55,9 @@ memory device commands, see the port, decoder, and endpoint APIs to - determine what if any CXL Memory Resources are reachable given a - specific memdev. - -+The host of a memdev is the PCIe Endpoint device that registered its CXL -+capabilities with the Linux CXL core. -+ - === MEMDEV: Attributes - ---- - int cxl_memdev_get_id(struct cxl_memdev *memdev); -diff --git a/cxl/json.c b/cxl/json.c -index af3b4fe..1868686 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -219,6 +219,11 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - if (jobj) - json_object_object_add(jdev, "serial", jobj); - } -+ -+ jobj = json_object_new_string(cxl_memdev_get_host(memdev)); -+ if (jobj) -+ json_object_object_add(jdev, "host", jobj); -+ - return jdev; - } - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 5f48202..c4ddc7d 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -63,6 +63,7 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head) - free(memdev->firmware_version); - free(memdev->dev_buf); - free(memdev->dev_path); -+ free(memdev->host); - free(memdev); - } - -@@ -297,6 +298,7 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) - char *path = calloc(1, strlen(cxlmem_base) + 100); - struct cxl_ctx *ctx = parent; - struct cxl_memdev *memdev, *memdev_dup; -+ char *host, *rpath = NULL; - char buf[SYSFS_ATTR_SIZE]; - struct stat st; - -@@ -350,6 +352,22 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) - if (!memdev->dev_path) - goto err_read; - -+ rpath = realpath(cxlmem_base, NULL); -+ if (!rpath) -+ goto err_read; -+ host = strrchr(rpath, '/'); -+ if (host) { -+ host[0] = '\0'; -+ host = strrchr(rpath, '/'); -+ } -+ if (!host) -+ goto err_read; -+ memdev->host = strdup(host + 1); -+ if (!memdev->host) -+ goto err_read; -+ free(rpath); -+ rpath = NULL; -+ - sprintf(path, "%s/firmware_version", cxlmem_base); - if (sysfs_read_attr(ctx, path, buf) < 0) - goto err_read; -@@ -381,6 +399,7 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) - free(memdev->dev_buf); - free(memdev->dev_path); - free(memdev); -+ free(rpath); - err_dev: - free(path); - return NULL; -@@ -431,6 +450,11 @@ CXL_EXPORT const char *cxl_memdev_get_devname(struct cxl_memdev *memdev) - return devpath_to_devname(memdev->dev_path); - } - -+CXL_EXPORT const char *cxl_memdev_get_host(struct cxl_memdev *memdev) -+{ -+ return memdev->host; -+} -+ - CXL_EXPORT int cxl_memdev_get_major(struct cxl_memdev *memdev) - { - return memdev->major; -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index dc2863e..8f0688a 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -77,6 +77,7 @@ local: - LIBCXL_2 { - global: - cxl_memdev_get_serial; -+ cxl_memdev_get_host; - cxl_bus_get_first; - cxl_bus_get_next; - cxl_bus_get_provider; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index cedd2f2..b097bdf 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -22,6 +22,7 @@ struct cxl_memdev { - int id, major, minor; - void *dev_buf; - size_t buf_len; -+ char *host; - char *dev_path; - char *firmware_version; - struct cxl_ctx *ctx; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index a60777e..5487b55 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -38,6 +38,7 @@ struct cxl_memdev *cxl_memdev_get_next(struct cxl_memdev *memdev); - int cxl_memdev_get_id(struct cxl_memdev *memdev); - unsigned long long cxl_memdev_get_serial(struct cxl_memdev *memdev); - const char *cxl_memdev_get_devname(struct cxl_memdev *memdev); -+const char *cxl_memdev_get_host(struct cxl_memdev *memdev); - int cxl_memdev_get_major(struct cxl_memdev *memdev); - int cxl_memdev_get_minor(struct cxl_memdev *memdev); - struct cxl_ctx *cxl_memdev_get_ctx(struct cxl_memdev *memdev); --- -2.27.0 - diff --git a/SOURCES/0108-cxl-list-Move-enabled-memdevs-underneath-their-endpo.patch b/SOURCES/0108-cxl-list-Move-enabled-memdevs-underneath-their-endpo.patch deleted file mode 100644 index aa72462..0000000 --- a/SOURCES/0108-cxl-list-Move-enabled-memdevs-underneath-their-endpo.patch +++ /dev/null @@ -1,499 +0,0 @@ -From 41d6769393f449008abf934e815f137360889633 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:53:45 -0800 -Subject: [PATCH 108/217] cxl/list: Move enabled memdevs underneath their - endpoint - -When a memdev is enabled it means that the kernel was able to validate a -CXL connection from the CXL root, through intervening switches, and to the -endpoint. Reflect that state by listing memdevs as child objects of -endpoints, or aggregated into an array if individual endpoints are not -listed. - -Link: https://lore.kernel.org/r/164298562531.3021641.10620937879296964476.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 11 ++- - Documentation/cxl/lib/libcxl.txt | 2 + - cxl/filter.c | 130 ++++++++++++++++++++++++------- - cxl/json.c | 6 ++ - cxl/lib/libcxl.c | 97 +++++++++++++++++++++++ - cxl/lib/libcxl.sym | 3 + - cxl/libcxl.h | 4 + - 7 files changed, 223 insertions(+), 30 deletions(-) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 9c21ab7..1751868 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -19,7 +19,16 @@ Options can be specified to limit the output to specific objects. When a - single object type is specified the return json object is an array of - just those objects, when multiple objects types are specified the - returned the returned object may be an array of arrays with the inner --array named for the given object type. -+array named for the given object type. The top-level arrays are ellided -+when the objects can nest under a higher object-type in the hierararchy. -+The potential top-level array names and their nesting properties are: -+ -+"anon memdevs":: (disabled memory devices) do not nest -+"buses":: do not nest -+"ports":: nest under buses -+"endpoints":: nest under ports or buses (if ports are not emitted) -+"memdevs":: nest under endpoints or ports (if endpoints are not -+ emitted) or buses (if endpoints and ports are not emitted) - - Filters can by specifed as either a single identidier, a space separated - quoted string, or a comma separated list. When multiple filter -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 91fd33e..73b0fb9 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -41,6 +41,7 @@ struct cxl_memdev *cxl_memdev_get_first(struct cxl_ctx *ctx); - struct cxl_memdev *cxl_memdev_get_next(struct cxl_memdev *memdev); - struct cxl_ctx *cxl_memdev_get_ctx(struct cxl_memdev *memdev); - const char *cxl_memdev_get_host(struct cxl_memdev *memdev) -+struct cxl_memdev *cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint); - - #define cxl_memdev_foreach(ctx, memdev) \ - for (memdev = cxl_memdev_get_first(ctx); \ -@@ -231,6 +232,7 @@ struct cxl_ctx *cxl_endpoint_get_ctx(struct cxl_endpoint *endpoint); - struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint); - struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint); - const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint); -+struct cxl_endpoint *cxl_memdev_get_endpoint(struct cxl_memdev *memdev); - - #define cxl_endpoint_foreach(port, endpoint) \ - for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \ -diff --git a/cxl/filter.c b/cxl/filter.c -index 5d80d1b..2130816 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -381,13 +381,16 @@ static struct json_object *pick_array(struct json_object *child, - } - - static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p, -- struct json_object *jeps, unsigned long flags) -+ struct json_object *jeps, struct json_object *jdevs, -+ unsigned long flags) - { - struct cxl_endpoint *endpoint; - - cxl_endpoint_foreach(port, endpoint) { - struct cxl_port *ep_port = cxl_endpoint_get_port(endpoint); -- struct json_object *jendpoint; -+ const char *devname = cxl_endpoint_get_devname(endpoint); -+ struct json_object *jendpoint = NULL; -+ struct cxl_memdev *memdev; - - if (!util_cxl_endpoint_filter(endpoint, p->endpoint_filter)) - continue; -@@ -398,24 +401,54 @@ static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p, - continue; - if (!p->idle && !cxl_endpoint_is_enabled(endpoint)) - continue; -- jendpoint = util_cxl_endpoint_to_json(endpoint, flags); -- if (jendpoint) -+ if (p->endpoints) { -+ jendpoint = util_cxl_endpoint_to_json(endpoint, flags); -+ if (!jendpoint) { -+ err(p, "%s: failed to list\n", devname); -+ continue; -+ } - json_object_array_add(jeps, jendpoint); -+ } -+ if (p->memdevs) { -+ struct json_object *jobj; -+ -+ memdev = cxl_endpoint_get_memdev(endpoint); -+ if (!memdev) -+ continue; -+ if (!util_cxl_memdev_filter(memdev, p->memdev_filter, -+ p->serial_filter)) -+ continue; -+ if (!p->idle && !cxl_memdev_is_enabled(memdev)) -+ continue; -+ jobj = util_cxl_memdev_to_json(memdev, flags); -+ if (!jobj) { -+ err(p, "failed to json serialize %s\n", -+ cxl_memdev_get_devname(memdev)); -+ continue; -+ } -+ if (p->endpoints) -+ json_object_object_add(jendpoint, "memdev", -+ jobj); -+ else -+ json_object_array_add(jdevs, jobj); -+ } - } - } - - static void walk_child_ports(struct cxl_port *parent_port, - struct cxl_filter_params *p, - struct json_object *jports, -- struct json_object *jeps, unsigned long flags) -+ struct json_object *jeps, -+ struct json_object *jdevs, unsigned long flags) - { - struct cxl_port *port; - - cxl_port_foreach(parent_port, port) { - const char *devname = cxl_port_get_devname(port); - struct json_object *jport = NULL; -+ struct json_object *jchilddevs = NULL; - struct json_object *jchildports = NULL; -- struct json_object *jchildendpoints = NULL; -+ struct json_object *jchildeps = NULL; - - if (!util_cxl_port_filter(port, p->port_filter, pf_mode(p))) - goto walk_children; -@@ -436,28 +469,41 @@ static void walk_child_ports(struct cxl_port *parent_port, - devname); - continue; - } -- } - -- if (p->ports && p->endpoints) { -- jchildendpoints = json_object_new_array(); -- if (!jchildendpoints) { -- err(p, -- "%s: failed to enumerate child endpoints\n", -- devname); -- continue; -+ if (p->memdevs && !p->endpoints) { -+ jchilddevs = json_object_new_array(); -+ if (!jchilddevs) { -+ err(p, -+ "%s: failed to enumerate child memdevs\n", -+ devname); -+ continue; -+ } -+ } -+ -+ if (p->endpoints) { -+ jchildeps = json_object_new_array(); -+ if (!jchildeps) { -+ err(p, -+ "%s: failed to enumerate child endpoints\n", -+ devname); -+ continue; -+ } - } - } - - walk_children: -- if (p->endpoints) -- walk_endpoints(port, p, pick_array(jchildendpoints, jeps), -- flags); -+ if (p->endpoints || p->memdevs) -+ walk_endpoints(port, p, pick_array(jchildeps, jeps), -+ pick_array(jchilddevs, jdevs), flags); - - walk_child_ports(port, p, pick_array(jchildports, jports), -- pick_array(jchildendpoints, jeps), flags); -+ pick_array(jchildeps, jeps), -+ pick_array(jchilddevs, jdevs), flags); - cond_add_put_array_suffix(jport, "ports", devname, jchildports); - cond_add_put_array_suffix(jport, "endpoints", devname, -- jchildendpoints); -+ jchildeps); -+ cond_add_put_array_suffix(jport, "memdevs", devname, -+ jchilddevs); - } - } - -@@ -466,6 +512,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - struct json_object *jdevs = NULL, *jbuses = NULL, *jports = NULL; - struct json_object *jplatform = json_object_new_array(); - unsigned long flags = params_to_flags(p); -+ struct json_object *janondevs = NULL; - struct json_object *jeps = NULL; - struct cxl_memdev *memdev; - int top_level_objs = 0; -@@ -476,8 +523,8 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - return -ENOMEM; - } - -- jdevs = json_object_new_array(); -- if (!jdevs) -+ janondevs = json_object_new_array(); -+ if (!janondevs) - goto err; - - jbuses = json_object_new_array(); -@@ -492,20 +539,28 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - if (!jeps) - goto err; - -+ jdevs = json_object_new_array(); -+ if (!jdevs) -+ goto err; -+ - dbg(p, "walk memdevs\n"); - cxl_memdev_foreach(ctx, memdev) { -- struct json_object *jdev; -+ struct json_object *janondev; - - if (!util_cxl_memdev_filter(memdev, p->memdev_filter, - p->serial_filter)) - continue; -+ if (cxl_memdev_is_enabled(memdev)) -+ continue; -+ if (!p->idle) -+ continue; - if (p->memdevs) { -- jdev = util_cxl_memdev_to_json(memdev, flags); -- if (!jdev) { -+ janondev = util_cxl_memdev_to_json(memdev, flags); -+ if (!janondev) { - dbg(p, "memdev object allocation failure\n"); - continue; - } -- json_object_array_add(jdevs, jdev); -+ json_object_array_add(janondevs, janondev); - } - } - -@@ -513,6 +568,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - cxl_bus_foreach(ctx, bus) { - struct json_object *jbus = NULL; - struct json_object *jchildports = NULL; -+ struct json_object *jchilddevs = NULL; - struct json_object *jchildeps = NULL; - struct cxl_port *port = cxl_bus_get_port(bus); - const char *devname = cxl_bus_get_devname(bus); -@@ -546,17 +602,29 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - continue; - } - } -+ -+ if (p->memdevs && !p->ports && !p->endpoints) { -+ jchilddevs = json_object_new_array(); -+ if (!jchilddevs) { -+ err(p, -+ "%s: failed to enumerate child memdevs\n", -+ devname); -+ continue; -+ } -+ } - } - walk_children: - dbg(p, "walk ports\n"); - walk_child_ports(port, p, pick_array(jchildports, jports), -- pick_array(jchildeps, jeps), flags); -+ pick_array(jchildeps, jeps), -+ pick_array(jchilddevs, jdevs), flags); - cond_add_put_array_suffix(jbus, "ports", devname, jchildports); - cond_add_put_array_suffix(jbus, "endpoints", devname, - jchildeps); -+ cond_add_put_array_suffix(jbus, "memdevs", devname, jchilddevs); - } - -- if (json_object_array_length(jdevs)) -+ if (json_object_array_length(janondevs)) - top_level_objs++; - if (json_object_array_length(jbuses)) - top_level_objs++; -@@ -564,20 +632,24 @@ walk_children: - top_level_objs++; - if (json_object_array_length(jeps)) - top_level_objs++; -+ if (json_object_array_length(jdevs)) -+ top_level_objs++; - -- splice_array(p, jdevs, jplatform, "anon memdevs", top_level_objs > 1); -+ splice_array(p, janondevs, jplatform, "anon memdevs", top_level_objs > 1); - splice_array(p, jbuses, jplatform, "buses", top_level_objs > 1); - splice_array(p, jports, jplatform, "ports", top_level_objs > 1); - splice_array(p, jeps, jplatform, "endpoints", top_level_objs > 1); -+ splice_array(p, jdevs, jplatform, "memdevs", top_level_objs > 1); - - util_display_json_array(stdout, jplatform, flags); - - return 0; - err: -- json_object_put(jdevs); -+ json_object_put(janondevs); - json_object_put(jbuses); - json_object_put(jports); - json_object_put(jeps); -+ json_object_put(jdevs); - json_object_put(jplatform); - return -ENOMEM; - } -diff --git a/cxl/json.c b/cxl/json.c -index 1868686..b809332 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -224,6 +224,12 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - if (jobj) - json_object_object_add(jdev, "host", jobj); - -+ if (!cxl_memdev_is_enabled(memdev)) { -+ jobj = json_object_new_string("disabled"); -+ if (jobj) -+ json_object_object_add(jdev, "state", jobj); -+ } -+ - return jdev; - } - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index c4ddc7d..4523ca6 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -480,6 +480,60 @@ CXL_EXPORT const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev - return memdev->firmware_version; - } - -+static struct cxl_endpoint *cxl_port_find_endpoint(struct cxl_port *parent_port, -+ struct cxl_memdev *memdev) -+{ -+ struct cxl_endpoint *endpoint; -+ struct cxl_port *port; -+ -+ cxl_port_foreach(parent_port, port) { -+ cxl_endpoint_foreach(port, endpoint) -+ if (strcmp(cxl_endpoint_get_host(endpoint), -+ cxl_memdev_get_devname(memdev)) == 0) -+ return endpoint; -+ endpoint = cxl_port_find_endpoint(port, memdev); -+ if (endpoint) -+ return endpoint; -+ } -+ -+ return NULL; -+} -+ -+CXL_EXPORT struct cxl_endpoint * -+cxl_memdev_get_endpoint(struct cxl_memdev *memdev) -+{ -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ struct cxl_endpoint *endpoint = NULL; -+ struct cxl_bus *bus; -+ -+ if (memdev->endpoint) -+ return memdev->endpoint; -+ -+ if (!cxl_memdev_is_enabled(memdev)) -+ return NULL; -+ -+ cxl_bus_foreach (ctx, bus) { -+ struct cxl_port *port = cxl_bus_get_port(bus); -+ -+ endpoint = cxl_port_find_endpoint(port, memdev); -+ if (endpoint) -+ break; -+ } -+ -+ if (!endpoint) -+ return NULL; -+ -+ if (endpoint->memdev && endpoint->memdev != memdev) -+ err(ctx, "%s assigned to %s not %s\n", -+ cxl_endpoint_get_devname(endpoint), -+ cxl_memdev_get_devname(endpoint->memdev), -+ cxl_memdev_get_devname(memdev)); -+ memdev->endpoint = endpoint; -+ endpoint->memdev = memdev; -+ -+ return endpoint; -+} -+ - CXL_EXPORT size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev) - { - return memdev->lsa_size; -@@ -495,6 +549,21 @@ static int is_enabled(const char *drvpath) - return 1; - } - -+CXL_EXPORT int cxl_memdev_is_enabled(struct cxl_memdev *memdev) -+{ -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ char *path = memdev->dev_buf; -+ int len = memdev->buf_len; -+ -+ if (snprintf(path, len, "%s/driver", memdev->dev_path) >= len) { -+ err(ctx, "%s: buffer too small!\n", -+ cxl_memdev_get_devname(memdev)); -+ return 0; -+ } -+ -+ return is_enabled(path); -+} -+ - CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev) - { - struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -@@ -660,6 +729,34 @@ CXL_EXPORT int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint) - return cxl_port_is_enabled(&endpoint->port); - } - -+CXL_EXPORT struct cxl_memdev * -+cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint) -+{ -+ struct cxl_ctx *ctx = cxl_endpoint_get_ctx(endpoint); -+ struct cxl_memdev *memdev; -+ -+ if (endpoint->memdev) -+ return endpoint->memdev; -+ -+ if (!cxl_endpoint_is_enabled(endpoint)) -+ return NULL; -+ -+ cxl_memdev_foreach(ctx, memdev) -+ if (strcmp(cxl_memdev_get_devname(memdev), -+ cxl_endpoint_get_host(endpoint)) == 0) { -+ if (memdev->endpoint && memdev->endpoint != endpoint) -+ err(ctx, "%s assigned to %s not %s\n", -+ cxl_memdev_get_devname(memdev), -+ cxl_endpoint_get_devname(memdev->endpoint), -+ cxl_endpoint_get_devname(endpoint)); -+ endpoint->memdev = memdev; -+ memdev->endpoint = endpoint; -+ return memdev; -+ } -+ -+ return NULL; -+} -+ - static void *add_cxl_port(void *parent, int id, const char *cxlport_base) - { - const char *devname = devpath_to_devname(cxlport_base); -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 8f0688a..321acac 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -106,4 +106,7 @@ global: - cxl_endpoint_get_parent; - cxl_endpoint_get_port; - cxl_endpoint_get_host; -+ cxl_endpoint_get_memdev; -+ cxl_memdev_get_endpoint; -+ cxl_memdev_is_enabled; - } LIBCXL_1; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 5487b55..790ece8 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -46,6 +46,8 @@ unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev); - unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev); - const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev); - size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev); -+struct cxl_endpoint; -+struct cxl_endpoint *cxl_memdev_get_endpoint(struct cxl_memdev *memdev); - int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev); - int cxl_memdev_zero_label(struct cxl_memdev *memdev, size_t length, - size_t offset); -@@ -100,6 +102,8 @@ int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint); - struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint); - struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint); - const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint); -+struct cxl_memdev *cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint); -+int cxl_memdev_is_enabled(struct cxl_memdev *memdev); - - #define cxl_endpoint_foreach(port, endpoint) \ - for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \ --- -2.27.0 - diff --git a/SOURCES/0109-cxl-list-Filter-memdev-by-ancestry.patch b/SOURCES/0109-cxl-list-Filter-memdev-by-ancestry.patch deleted file mode 100644 index f6f94da..0000000 --- a/SOURCES/0109-cxl-list-Filter-memdev-by-ancestry.patch +++ /dev/null @@ -1,329 +0,0 @@ -From b90fc91e1034668cfde06f0fd8a7293df8b7690d Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:53:50 -0800 -Subject: [PATCH 109/217] cxl/list: Filter memdev by ancestry - -Whenever a memdev filter is specified limit output of buses, ports and -endpoints to those that are in the memdev's ancestry. - -Link: https://lore.kernel.org/r/164298563039.3021641.5253222797042241091.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 19 +++++++++ - Documentation/cxl/lib/libcxl.txt | 11 +++++ - cxl/filter.c | 69 ++++++++++++++++++++++++++++++++ - cxl/lib/libcxl.c | 36 +++++++++++++++++ - cxl/lib/libcxl.sym | 5 +++ - cxl/libcxl.h | 4 ++ - 6 files changed, 144 insertions(+) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 1751868..bac27c7 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -39,6 +39,25 @@ they are combined as an 'AND' filter. So, "-m mem0,mem1,mem2 -p port10" - would only list objects that are beneath port10 AND map mem0, mem1, OR - mem2. - -+Given that many topology queries seek to answer questions relative to a -+given memdev, buses, ports, and endpoints can be filtered by one or more -+memdevs. For example: -+---- -+# cxl list -P -p switch,endpoint -m mem0 -+[ -+ { -+ "port":"port1", -+ "host":"ACPI0016:00", -+ "endpoints:port1":[ -+ { -+ "endpoint":"endpoint2", -+ "host":"mem0" -+ } -+ ] -+ } -+] -+---- -+ - The --human option in addition to reformatting some fields to more human - friendly strings also unwraps the array to reduce the number of lines of - output. -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 73b0fb9..b0253d7 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -150,11 +150,18 @@ cxl_bus'. - ---- - struct cxl_bus *cxl_bus_get_first(struct cxl_ctx *ctx); - struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus); -+struct cxl_ctx *cxl_bus_get_ctx(struct cxl_bus *bus); -+struct cxl_bus *cxl_memdev_get_bus(struct cxl_memdev *memdev); -+struct cxl_bus *cxl_endpoint_get_bus(struct cxl_endpoint *endpoint); - - #define cxl_bus_foreach(ctx, bus) \ - for (bus = cxl_bus_get_first(ctx); bus != NULL; \ - bus = cxl_bus_get_next(bus)) - ---- -+When a memdev is active it has established a CXL port hierarchy between -+itself and the root of its associated CXL topology. The -+cxl_{memdev,endpoint}_get_bus() helpers walk that topology to retrieve -+the associated bus object. - - === BUS: Attributes - ---- -@@ -209,6 +216,7 @@ int cxl_port_is_enabled(struct cxl_port *port); - bool cxl_port_is_root(struct cxl_port *port); - bool cxl_port_is_switch(struct cxl_port *port); - bool cxl_port_is_endpoint(struct cxl_port *port); -+bool cxl_port_hosts_memdev(struct cxl_port *port, struct cxl_memdev *memdev); - ---- - The port type is communicated via cxl_port_is_(). An 'enabled' port - is one that has succeeded in discovering the CXL component registers in -@@ -217,6 +225,9 @@ memdev to be enabled for CXL memory operation all CXL ports in its - ancestry must also be enabled including a root port, an arbitrary number - of intervening switch ports, and a terminal endpoint port. - -+cxl_port_hosts_memdev() returns true if the port's host appears in the -+memdev host's device topology ancestry. -+ - ENDPOINTS - --------- - CXL endpoint objects encapsulate the set of host-managed device-memory -diff --git a/cxl/filter.c b/cxl/filter.c -index 2130816..6dc61a1 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -297,6 +297,66 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, - return NULL; - } - -+static struct cxl_bus *util_cxl_bus_filter_by_memdev(struct cxl_bus *bus, -+ const char *ident, -+ const char *serial) -+{ -+ struct cxl_ctx *ctx = cxl_bus_get_ctx(bus); -+ struct cxl_memdev *memdev; -+ -+ if (!ident && !serial) -+ return bus; -+ -+ cxl_memdev_foreach(ctx, memdev) { -+ if (!util_cxl_memdev_filter(memdev, ident, serial)) -+ continue; -+ if (cxl_memdev_get_bus(memdev) == bus) -+ return bus; -+ } -+ -+ return NULL; -+} -+ -+static struct cxl_endpoint * -+util_cxl_endpoint_filter_by_memdev(struct cxl_endpoint *endpoint, -+ const char *ident, const char *serial) -+{ -+ struct cxl_ctx *ctx = cxl_endpoint_get_ctx(endpoint); -+ struct cxl_memdev *memdev; -+ -+ if (!ident && !serial) -+ return endpoint; -+ -+ cxl_memdev_foreach(ctx, memdev) { -+ if (!util_cxl_memdev_filter(memdev, ident, serial)) -+ continue; -+ if (cxl_memdev_get_endpoint(memdev) == endpoint) -+ return endpoint; -+ } -+ -+ return NULL; -+} -+ -+static struct cxl_port *util_cxl_port_filter_by_memdev(struct cxl_port *port, -+ const char *ident, -+ const char *serial) -+{ -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ struct cxl_memdev *memdev; -+ -+ if (!ident && !serial) -+ return port; -+ -+ cxl_memdev_foreach(ctx, memdev) { -+ if (!util_cxl_memdev_filter(memdev, ident, serial)) -+ continue; -+ if (cxl_port_hosts_memdev(port, memdev)) -+ return port; -+ } -+ -+ return NULL; -+} -+ - static unsigned long params_to_flags(struct cxl_filter_params *param) - { - unsigned long flags = 0; -@@ -399,6 +459,9 @@ static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p, - if (!util_cxl_endpoint_filter_by_port(endpoint, p->port_filter, - pf_mode(p))) - continue; -+ if (!util_cxl_endpoint_filter_by_memdev( -+ endpoint, p->memdev_filter, p->serial_filter)) -+ continue; - if (!p->idle && !cxl_endpoint_is_enabled(endpoint)) - continue; - if (p->endpoints) { -@@ -450,6 +513,9 @@ static void walk_child_ports(struct cxl_port *parent_port, - struct json_object *jchildports = NULL; - struct json_object *jchildeps = NULL; - -+ if (!util_cxl_port_filter_by_memdev(port, p->memdev_filter, -+ p->serial_filter)) -+ continue; - if (!util_cxl_port_filter(port, p->port_filter, pf_mode(p))) - goto walk_children; - if (!util_cxl_port_filter_by_bus(port, p->bus_filter)) -@@ -573,6 +639,9 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - struct cxl_port *port = cxl_bus_get_port(bus); - const char *devname = cxl_bus_get_devname(bus); - -+ if (!util_cxl_bus_filter_by_memdev(bus, p->memdev_filter, -+ p->serial_filter)) -+ continue; - if (!util_cxl_bus_filter(bus, p->bus_filter)) - goto walk_children; - if (!util_cxl_port_filter(port, p->port_filter, pf_mode(p))) -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 4523ca6..0065f6b 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -455,6 +455,15 @@ CXL_EXPORT const char *cxl_memdev_get_host(struct cxl_memdev *memdev) - return memdev->host; - } - -+CXL_EXPORT struct cxl_bus *cxl_memdev_get_bus(struct cxl_memdev *memdev) -+{ -+ struct cxl_endpoint *endpoint = cxl_memdev_get_endpoint(memdev); -+ -+ if (!endpoint) -+ return NULL; -+ return cxl_endpoint_get_bus(endpoint); -+} -+ - CXL_EXPORT int cxl_memdev_get_major(struct cxl_memdev *memdev) - { - return memdev->major; -@@ -724,6 +733,13 @@ CXL_EXPORT const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint) - return cxl_port_get_host(&endpoint->port); - } - -+CXL_EXPORT struct cxl_bus *cxl_endpoint_get_bus(struct cxl_endpoint *endpoint) -+{ -+ struct cxl_port *port = &endpoint->port; -+ -+ return cxl_port_get_bus(port); -+} -+ - CXL_EXPORT int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint) - { - return cxl_port_is_enabled(&endpoint->port); -@@ -875,6 +891,21 @@ CXL_EXPORT const char *cxl_port_get_host(struct cxl_port *port) - return devpath_to_devname(port->uport); - } - -+CXL_EXPORT bool cxl_port_hosts_memdev(struct cxl_port *port, -+ struct cxl_memdev *memdev) -+{ -+ struct cxl_endpoint *endpoint = cxl_memdev_get_endpoint(memdev); -+ struct cxl_port *iter; -+ -+ if (!endpoint) -+ return false; -+ -+ iter = cxl_endpoint_get_port(endpoint); -+ while (iter && iter != port) -+ iter = iter->parent; -+ return iter != NULL; -+} -+ - CXL_EXPORT int cxl_port_is_enabled(struct cxl_port *port) - { - struct cxl_ctx *ctx = cxl_port_get_ctx(port); -@@ -985,6 +1016,11 @@ CXL_EXPORT const char *cxl_bus_get_provider(struct cxl_bus *bus) - return devname; - } - -+CXL_EXPORT struct cxl_ctx *cxl_bus_get_ctx(struct cxl_bus *bus) -+{ -+ return cxl_port_get_ctx(&bus->port); -+} -+ - CXL_EXPORT void cxl_cmd_unref(struct cxl_cmd *cmd) - { - if (!cmd) -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 321acac..29f3498 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -84,6 +84,7 @@ global: - cxl_bus_get_devname; - cxl_bus_get_id; - cxl_bus_get_port; -+ cxl_bus_get_ctx; - cxl_port_get_first; - cxl_port_get_next; - cxl_port_get_devname; -@@ -97,6 +98,8 @@ global: - cxl_port_is_endpoint; - cxl_port_get_bus; - cxl_port_get_host; -+ cxl_port_get_bus; -+ cxl_port_hosts_memdev; - cxl_endpoint_get_first; - cxl_endpoint_get_next; - cxl_endpoint_get_devname; -@@ -107,6 +110,8 @@ global: - cxl_endpoint_get_port; - cxl_endpoint_get_host; - cxl_endpoint_get_memdev; -+ cxl_endpoint_get_bus; - cxl_memdev_get_endpoint; - cxl_memdev_is_enabled; -+ cxl_memdev_get_bus; - } LIBCXL_1; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 790ece8..e7b675e 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -39,6 +39,7 @@ int cxl_memdev_get_id(struct cxl_memdev *memdev); - unsigned long long cxl_memdev_get_serial(struct cxl_memdev *memdev); - const char *cxl_memdev_get_devname(struct cxl_memdev *memdev); - const char *cxl_memdev_get_host(struct cxl_memdev *memdev); -+struct cxl_bus *cxl_memdev_get_bus(struct cxl_memdev *memdev); - int cxl_memdev_get_major(struct cxl_memdev *memdev); - int cxl_memdev_get_minor(struct cxl_memdev *memdev); - struct cxl_ctx *cxl_memdev_get_ctx(struct cxl_memdev *memdev); -@@ -68,6 +69,7 @@ const char *cxl_bus_get_provider(struct cxl_bus *bus); - const char *cxl_bus_get_devname(struct cxl_bus *bus); - int cxl_bus_get_id(struct cxl_bus *bus); - struct cxl_port *cxl_bus_get_port(struct cxl_bus *bus); -+struct cxl_ctx *cxl_bus_get_ctx(struct cxl_bus *bus); - - #define cxl_bus_foreach(ctx, bus) \ - for (bus = cxl_bus_get_first(ctx); bus != NULL; \ -@@ -87,6 +89,7 @@ struct cxl_bus *cxl_port_to_bus(struct cxl_port *port); - bool cxl_port_is_endpoint(struct cxl_port *port); - struct cxl_bus *cxl_port_get_bus(struct cxl_port *port); - const char *cxl_port_get_host(struct cxl_port *port); -+bool cxl_port_hosts_memdev(struct cxl_port *port, struct cxl_memdev *memdev); - - #define cxl_port_foreach(parent, port) \ - for (port = cxl_port_get_first(parent); port != NULL; \ -@@ -102,6 +105,7 @@ int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint); - struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint); - struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint); - const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint); -+struct cxl_bus *cxl_endpoint_get_bus(struct cxl_endpoint *endpoint); - struct cxl_memdev *cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint); - int cxl_memdev_is_enabled(struct cxl_memdev *memdev); - --- -2.27.0 - diff --git a/SOURCES/0110-cxl-memdev-Use-a-local-logger-for-debug.patch b/SOURCES/0110-cxl-memdev-Use-a-local-logger-for-debug.patch deleted file mode 100644 index 1af0f57..0000000 --- a/SOURCES/0110-cxl-memdev-Use-a-local-logger-for-debug.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 5e1c1ab5bf6b6257552ad9fa242483ec1c1de006 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:53:55 -0800 -Subject: [PATCH 110/217] cxl/memdev: Use a local logger for debug - -The "fail()" macro skips some of the nicer features of the centralized -logger. Add one to supplement the library logger. - -Link: https://lore.kernel.org/r/164298563547.3021641.16504008034705274247.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/memdev.c | 48 ++++++++++++++++++++++++------------------------ - 1 file changed, 24 insertions(+), 24 deletions(-) - -diff --git a/cxl/memdev.c b/cxl/memdev.c -index b9141be..327c260 100644 ---- a/cxl/memdev.c -+++ b/cxl/memdev.c -@@ -26,11 +26,7 @@ static struct parameters { - bool verbose; - } param; - --#define fail(fmt, ...) \ --do { \ -- fprintf(stderr, "cxl-%s:%s:%d: " fmt, \ -- VERSION, __func__, __LINE__, ##__VA_ARGS__); \ --} while (0) -+static struct log_ctx ml; - - #define BASE_OPTIONS() \ - OPT_BOOLEAN('v',"verbose", ¶m.verbose, "turn on debug") -@@ -79,7 +75,7 @@ static int action_zero(struct cxl_memdev *memdev, struct action_context *actx) - size = cxl_memdev_get_label_size(memdev); - - if (cxl_memdev_nvdimm_bridge_active(memdev)) { -- fprintf(stderr, -+ log_err(&ml, - "%s: has active nvdimm bridge, abort label write\n", - cxl_memdev_get_devname(memdev)); - return -EBUSY; -@@ -87,7 +83,7 @@ static int action_zero(struct cxl_memdev *memdev, struct action_context *actx) - - rc = cxl_memdev_zero_label(memdev, size, param.offset); - if (rc < 0) -- fprintf(stderr, "%s: label zeroing failed: %s\n", -+ log_err(&ml, "%s: label zeroing failed: %s\n", - cxl_memdev_get_devname(memdev), strerror(-rc)); - - return rc; -@@ -100,7 +96,7 @@ static int action_write(struct cxl_memdev *memdev, struct action_context *actx) - int rc; - - if (cxl_memdev_nvdimm_bridge_active(memdev)) { -- fprintf(stderr, -+ log_err(&ml, - "%s: has active nvdimm bridge, abort label write\n", - cxl_memdev_get_devname(memdev)); - return -EBUSY; -@@ -114,7 +110,7 @@ static int action_write(struct cxl_memdev *memdev, struct action_context *actx) - fseek(actx->f_in, 0L, SEEK_SET); - - if (size > label_size) { -- fprintf(stderr, -+ log_err(&ml, - "File size (%zu) greater than label area size (%zu), aborting\n", - size, label_size); - return -EINVAL; -@@ -133,7 +129,7 @@ static int action_write(struct cxl_memdev *memdev, struct action_context *actx) - - rc = cxl_memdev_write_label(memdev, buf, size, param.offset); - if (rc < 0) -- fprintf(stderr, "%s: label write failed: %s\n", -+ log_err(&ml, "%s: label write failed: %s\n", - cxl_memdev_get_devname(memdev), strerror(-rc)); - - out: -@@ -158,7 +154,7 @@ static int action_read(struct cxl_memdev *memdev, struct action_context *actx) - - rc = cxl_memdev_read_label(memdev, buf, size, param.offset); - if (rc < 0) { -- fprintf(stderr, "%s: label read failed: %s\n", -+ log_err(&ml, "%s: label read failed: %s\n", - cxl_memdev_get_devname(memdev), strerror(-rc)); - goto out; - } -@@ -188,6 +184,7 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - }; - unsigned long id; - -+ log_init(&ml, "cxl memdev", "CXL_MEMDEV_LOG"); - argc = parse_options(argc, argv, options, u, 0); - - if (argc == 0) -@@ -200,8 +197,8 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - } - - if (sscanf(argv[i], "mem%lu", &id) != 1) { -- fprintf(stderr, "'%s' is not a valid memdev name\n", -- argv[i]); -+ log_err(&ml, "'%s' is not a valid memdev name\n", -+ argv[i]); - err++; - } - } -@@ -216,8 +213,8 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - else { - actx.f_out = fopen(param.outfile, "w+"); - if (!actx.f_out) { -- fprintf(stderr, "failed to open: %s: (%s)\n", -- param.outfile, strerror(errno)); -+ log_err(&ml, "failed to open: %s: (%s)\n", -+ param.outfile, strerror(errno)); - rc = -errno; - goto out; - } -@@ -228,15 +225,18 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - } else { - actx.f_in = fopen(param.infile, "r"); - if (!actx.f_in) { -- fprintf(stderr, "failed to open: %s: (%s)\n", -- param.infile, strerror(errno)); -+ log_err(&ml, "failed to open: %s: (%s)\n", param.infile, -+ strerror(errno)); - rc = -errno; - goto out_close_fout; - } - } - -- if (param.verbose) -+ if (param.verbose) { - cxl_set_log_priority(ctx, LOG_DEBUG); -+ ml.log_priority = LOG_DEBUG; -+ } else -+ ml.log_priority = LOG_INFO; - - rc = 0; - err = 0; -@@ -299,8 +299,8 @@ int cmd_write_labels(int argc, const char **argv, struct cxl_ctx *ctx) - int count = memdev_action(argc, argv, ctx, action_write, write_options, - "cxl write-labels [-i ]"); - -- fprintf(stderr, "wrote %d mem%s\n", count >= 0 ? count : 0, -- count > 1 ? "s" : ""); -+ log_info(&ml, "wrote %d mem%s\n", count >= 0 ? count : 0, -+ count > 1 ? "s" : ""); - return count >= 0 ? 0 : EXIT_FAILURE; - } - -@@ -309,8 +309,8 @@ int cmd_read_labels(int argc, const char **argv, struct cxl_ctx *ctx) - int count = memdev_action(argc, argv, ctx, action_read, read_options, - "cxl read-labels [..] [-o ]"); - -- fprintf(stderr, "read %d mem%s\n", count >= 0 ? count : 0, -- count > 1 ? "s" : ""); -+ log_info(&ml, "read %d mem%s\n", count >= 0 ? count : 0, -+ count > 1 ? "s" : ""); - return count >= 0 ? 0 : EXIT_FAILURE; - } - -@@ -319,7 +319,7 @@ int cmd_zero_labels(int argc, const char **argv, struct cxl_ctx *ctx) - int count = memdev_action(argc, argv, ctx, action_zero, zero_options, - "cxl zero-labels [..] []"); - -- fprintf(stderr, "zeroed %d mem%s\n", count >= 0 ? count : 0, -- count > 1 ? "s" : ""); -+ log_info(&ml, "zeroed %d mem%s\n", count >= 0 ? count : 0, -+ count > 1 ? "s" : ""); - return count >= 0 ? 0 : EXIT_FAILURE; - } --- -2.27.0 - diff --git a/SOURCES/0111-cxl-memdev-Cleanup-memdev-filter.patch b/SOURCES/0111-cxl-memdev-Cleanup-memdev-filter.patch deleted file mode 100644 index 94688bd..0000000 --- a/SOURCES/0111-cxl-memdev-Cleanup-memdev-filter.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 6cab8e0186e73af75f0a15ce87c4db20ef0089df Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:54:01 -0800 -Subject: [PATCH 111/217] cxl/memdev: Cleanup memdev filter - -util_cxl_memdev_filter() already handles the difference between 'mem%d', -'%d', and 'all' for the identifier format. Drop the duplicate / incomplete -format checking. - -If the checking for bad formats was dropped too then this command could -support "0,1,2" syntax in addition to "0 1 2" like 'cxl list'. However, it is -not clear that's worthwhile since 'list' is ok to be imprecise, but memdev -commands need to be stricter. - -Link: https://lore.kernel.org/r/164298564100.3021641.9410483964085163708.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/memdev.c | 18 +++++++----------- - 1 file changed, 7 insertions(+), 11 deletions(-) - -diff --git a/cxl/memdev.c b/cxl/memdev.c -index 327c260..4cca8b8 100644 ---- a/cxl/memdev.c -+++ b/cxl/memdev.c -@@ -191,16 +191,16 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - usage_with_options(u, options); - for (i = 0; i < argc; i++) { - if (strcmp(argv[i], "all") == 0) { -- argv[0] = "all"; - argc = 1; - break; - } -+ if (sscanf(argv[i], "mem%lu", &id) == 1) -+ continue; -+ if (sscanf(argv[i], "%lu", &id) == 1) -+ continue; - -- if (sscanf(argv[i], "mem%lu", &id) != 1) { -- log_err(&ml, "'%s' is not a valid memdev name\n", -- argv[i]); -- err++; -- } -+ log_err(&ml, "'%s' is not a valid memdev name\n", argv[i]); -+ err++; - } - - if (err == argc) { -@@ -243,11 +243,7 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - count = 0; - - for (i = 0; i < argc; i++) { -- if (sscanf(argv[i], "mem%lu", &id) != 1 -- && strcmp(argv[i], "all") != 0) -- continue; -- -- cxl_memdev_foreach (ctx, memdev) { -+ cxl_memdev_foreach(ctx, memdev) { - if (!util_cxl_memdev_filter(memdev, argv[i], NULL)) - continue; - --- -2.27.0 - diff --git a/SOURCES/0112-cxl-memdev-Add-serial-support-for-memdev-related-com.patch b/SOURCES/0112-cxl-memdev-Add-serial-support-for-memdev-related-com.patch deleted file mode 100644 index 4c95292..0000000 --- a/SOURCES/0112-cxl-memdev-Add-serial-support-for-memdev-related-com.patch +++ /dev/null @@ -1,133 +0,0 @@ -From c09c507e5a608718ac96af088fdc8cb441b09d0b Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:54:06 -0800 -Subject: [PATCH 112/217] cxl/memdev: Add serial support for memdev-related - commands - -Allow for a "-s, --serial" option to turn the argument list into serial -identifiers. - -Link: https://lore.kernel.org/r/164298564631.3021641.5552442288217413180.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/memdev-option.txt | 5 ++++ - Documentation/cxl/meson.build | 4 ++- - cxl/memdev.c | 45 +++++++++++++++++++++-------- - 3 files changed, 41 insertions(+), 13 deletions(-) - -diff --git a/Documentation/cxl/memdev-option.txt b/Documentation/cxl/memdev-option.txt -index e778582..64348be 100644 ---- a/Documentation/cxl/memdev-option.txt -+++ b/Documentation/cxl/memdev-option.txt -@@ -2,3 +2,8 @@ - A 'memX' device name, or a memdev id number. Restrict the operation to - the specified memdev(s). The keyword 'all' can be specified to indicate - the lack of any restriction. -+ -+-S:: -+--serial:: -+ Rather an a memdev id number, interpret the argument(s) -+ as a list of serial numbers. -diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build -index 64ce13f..0a6346b 100644 ---- a/Documentation/cxl/meson.build -+++ b/Documentation/cxl/meson.build -@@ -19,7 +19,9 @@ else - endif - - filedeps = [ -- '../copyright.txt', -+ '../copyright.txt', -+ 'memdev-option.txt', -+ 'labels-options.txt', - ] - - cxl_manpages = [ -diff --git a/cxl/memdev.c b/cxl/memdev.c -index 4cca8b8..ef5343a 100644 ---- a/cxl/memdev.c -+++ b/cxl/memdev.c -@@ -24,12 +24,14 @@ static struct parameters { - unsigned len; - unsigned offset; - bool verbose; -+ bool serial; - } param; - - static struct log_ctx ml; - - #define BASE_OPTIONS() \ --OPT_BOOLEAN('v',"verbose", ¶m.verbose, "turn on debug") -+OPT_BOOLEAN('v',"verbose", ¶m.verbose, "turn on debug"), \ -+OPT_BOOLEAN('S', "serial", ¶m.serial, "user serials numbers to id memdevs") - - #define READ_OPTIONS() \ - OPT_STRING('o', "output", ¶m.outfile, "output-file", \ -@@ -172,8 +174,9 @@ out: - } - - static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, -- int (*action)(struct cxl_memdev *memdev, struct action_context *actx), -- const struct option *options, const char *usage) -+ int (*action)(struct cxl_memdev *memdev, -+ struct action_context *actx), -+ const struct option *options, const char *usage) - { - struct cxl_memdev *memdev, *single = NULL; - struct action_context actx = { 0 }; -@@ -190,16 +193,25 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - if (argc == 0) - usage_with_options(u, options); - for (i = 0; i < argc; i++) { -- if (strcmp(argv[i], "all") == 0) { -- argc = 1; -- break; -+ if (param.serial) { -+ char *end; -+ -+ strtoull(argv[i], &end, 0); -+ if (end[0] == 0) -+ continue; -+ } else { -+ if (strcmp(argv[i], "all") == 0) { -+ argc = 1; -+ break; -+ } -+ if (sscanf(argv[i], "mem%lu", &id) == 1) -+ continue; -+ if (sscanf(argv[i], "%lu", &id) == 1) -+ continue; - } -- if (sscanf(argv[i], "mem%lu", &id) == 1) -- continue; -- if (sscanf(argv[i], "%lu", &id) == 1) -- continue; - -- log_err(&ml, "'%s' is not a valid memdev name\n", argv[i]); -+ log_err(&ml, "'%s' is not a valid memdev %s\n", argv[i], -+ param.serial ? "serial number" : "name"); - err++; - } - -@@ -244,7 +256,16 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - - for (i = 0; i < argc; i++) { - cxl_memdev_foreach(ctx, memdev) { -- if (!util_cxl_memdev_filter(memdev, argv[i], NULL)) -+ const char *memdev_filter = NULL; -+ const char *serial_filter = NULL; -+ -+ if (param.serial) -+ serial_filter = argv[i]; -+ else -+ memdev_filter = argv[i]; -+ -+ if (!util_cxl_memdev_filter(memdev, memdev_filter, -+ serial_filter)) - continue; - - if (action == action_write) { --- -2.27.0 - diff --git a/SOURCES/0113-cxl-list-Add-numa_node-to-memdev-listings.patch b/SOURCES/0113-cxl-list-Add-numa_node-to-memdev-listings.patch deleted file mode 100644 index 682d429..0000000 --- a/SOURCES/0113-cxl-list-Add-numa_node-to-memdev-listings.patch +++ /dev/null @@ -1,136 +0,0 @@ -From ca582b2003a2335eafac382e71afdf0a6caaef18 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:54:11 -0800 -Subject: [PATCH 113/217] cxl/list: Add 'numa_node' to memdev listings - -If the kernel exports a valid numa_node, >= 0, include it in memdev objects -listings. - -Link: https://lore.kernel.org/r/164298565156.3021641.14097226245654611710.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/lib/libcxl.txt | 4 ++++ - cxl/json.c | 8 ++++++++ - cxl/lib/libcxl.c | 11 +++++++++++ - cxl/lib/libcxl.sym | 1 + - cxl/lib/private.h | 1 + - cxl/libcxl.h | 1 + - 6 files changed, 26 insertions(+) - -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index b0253d7..de88d19 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -71,6 +71,7 @@ unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev); - const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev); - size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev); - int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev); -+int cxl_memdev_get_numa_node(struct cxl_memdev *memdev); - ---- - - A memdev is given a kernel device name of the form "mem%d" where an id -@@ -89,6 +90,9 @@ The 'pmem_size' and 'ram_size' attributes return the current - provisioning of DPA (Device Physical Address / local capacity) in the - device. - -+cxl_memdev_get_numa_node() returns the affinitized CPU node number if -+available or -1 otherwise. -+ - === MEMDEV: Commands - ---- - struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode); -diff --git a/cxl/json.c b/cxl/json.c -index b809332..51918d6 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -190,6 +190,7 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - const char *devname = cxl_memdev_get_devname(memdev); - struct json_object *jdev, *jobj; - unsigned long long serial; -+ int numa_node; - - jdev = json_object_new_object(); - if (!jdev) -@@ -220,6 +221,13 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - json_object_object_add(jdev, "serial", jobj); - } - -+ numa_node = cxl_memdev_get_numa_node(memdev); -+ if (numa_node >= 0) { -+ jobj = json_object_new_int(numa_node); -+ if (jobj) -+ json_object_object_add(jdev, "numa_node", jobj); -+ } -+ - jobj = json_object_new_string(cxl_memdev_get_host(memdev)); - if (jobj) - json_object_object_add(jdev, "host", jobj); -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 0065f6b..14c7db8 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -348,6 +348,12 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) - else - memdev->serial = strtoull(buf, NULL, 0); - -+ sprintf(path, "%s/numa_node", cxlmem_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ memdev->numa_node = -1; -+ else -+ memdev->numa_node = strtol(buf, NULL, 0); -+ - memdev->dev_path = strdup(cxlmem_base); - if (!memdev->dev_path) - goto err_read; -@@ -445,6 +451,11 @@ CXL_EXPORT unsigned long long cxl_memdev_get_serial(struct cxl_memdev *memdev) - return memdev->serial; - } - -+CXL_EXPORT int cxl_memdev_get_numa_node(struct cxl_memdev *memdev) -+{ -+ return memdev->numa_node; -+} -+ - CXL_EXPORT const char *cxl_memdev_get_devname(struct cxl_memdev *memdev) - { - return devpath_to_devname(memdev->dev_path); -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 29f3498..b13a2d6 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -77,6 +77,7 @@ local: - LIBCXL_2 { - global: - cxl_memdev_get_serial; -+ cxl_memdev_get_numa_node; - cxl_memdev_get_host; - cxl_bus_get_first; - cxl_bus_get_next; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index b097bdf..c00bb36 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -20,6 +20,7 @@ struct cxl_pmem { - struct cxl_endpoint; - struct cxl_memdev { - int id, major, minor; -+ int numa_node; - void *dev_buf; - size_t buf_len; - char *host; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index e7b675e..be656ed 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -37,6 +37,7 @@ struct cxl_memdev *cxl_memdev_get_first(struct cxl_ctx *ctx); - struct cxl_memdev *cxl_memdev_get_next(struct cxl_memdev *memdev); - int cxl_memdev_get_id(struct cxl_memdev *memdev); - unsigned long long cxl_memdev_get_serial(struct cxl_memdev *memdev); -+int cxl_memdev_get_numa_node(struct cxl_memdev *memdev); - const char *cxl_memdev_get_devname(struct cxl_memdev *memdev); - const char *cxl_memdev_get_host(struct cxl_memdev *memdev); - struct cxl_bus *cxl_memdev_get_bus(struct cxl_memdev *memdev); --- -2.27.0 - diff --git a/SOURCES/0114-util-Implement-common-bind-unbind-helpers.patch b/SOURCES/0114-util-Implement-common-bind-unbind-helpers.patch deleted file mode 100644 index 6b421a2..0000000 --- a/SOURCES/0114-util-Implement-common-bind-unbind-helpers.patch +++ /dev/null @@ -1,329 +0,0 @@ -From e31fc778998b4d02ffec68e61869aaeccfd99be8 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:54:17 -0800 -Subject: [PATCH 114/217] util: Implement common bind/unbind helpers - -Refactor ndctl_{bind,unbind}() into util_{bind,unbind}() for libcxl to -reuse. - -daxctl can not join the party for now as it needs to play games with -'new_id'. - -Link: https://lore.kernel.org/r/164298565707.3021641.7763459936156744907.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - ndctl/lib/libndctl.c | 103 +++++-------------------------------------- - util/sysfs.c | 76 +++++++++++++++++++++++++++++++ - util/sysfs.h | 8 ++++ - 3 files changed, 96 insertions(+), 91 deletions(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index 1374ad9..98d184b 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -1665,10 +1665,6 @@ static enum ndctl_fwa_result fwa_result_to_result(const char *result) - return NDCTL_FWA_RESULT_INVALID; - } - --static int ndctl_bind(struct ndctl_ctx *ctx, struct kmod_module *module, -- const char *devname); --static int ndctl_unbind(struct ndctl_ctx *ctx, const char *devpath); -- - static int populate_dimm_attributes(struct ndctl_dimm *dimm, - const char *dimm_base, - const char *bus_prefix) -@@ -2305,7 +2301,7 @@ NDCTL_EXPORT int ndctl_dimm_disable(struct ndctl_dimm *dimm) - if (!ndctl_dimm_is_enabled(dimm)) - return 0; - -- ndctl_unbind(ctx, dimm->dimm_path); -+ util_unbind(dimm->dimm_path, ctx); - - if (ndctl_dimm_is_enabled(dimm)) { - err(ctx, "%s: failed to disable\n", devname); -@@ -2324,7 +2320,7 @@ NDCTL_EXPORT int ndctl_dimm_enable(struct ndctl_dimm *dimm) - if (ndctl_dimm_is_enabled(dimm)) - return 0; - -- ndctl_bind(ctx, dimm->module, devname); -+ util_bind(devname, dimm->module, "nd", ctx); - - if (!ndctl_dimm_is_enabled(dimm)) { - err(ctx, "%s: failed to enable\n", devname); -@@ -3573,7 +3569,7 @@ NDCTL_EXPORT int ndctl_region_enable(struct ndctl_region *region) - if (ndctl_region_is_enabled(region)) - return 0; - -- ndctl_bind(ctx, region->module, devname); -+ util_bind(devname, region->module, "nd", ctx); - - if (!ndctl_region_is_enabled(region)) { - err(ctx, "%s: failed to enable\n", devname); -@@ -3610,7 +3606,7 @@ static int ndctl_region_disable(struct ndctl_region *region, int cleanup) - if (!ndctl_region_is_enabled(region)) - return 0; - -- ndctl_unbind(ctx, region->region_path); -+ util_unbind(region->region_path, ctx); - - if (ndctl_region_is_enabled(region)) { - err(ctx, "%s: failed to disable\n", devname); -@@ -4373,81 +4369,6 @@ NDCTL_EXPORT struct badblock *ndctl_namespace_get_first_badblock( - return badblocks_iter_first(&ndns->bb_iter, ctx, path); - } - --static int ndctl_bind(struct ndctl_ctx *ctx, struct kmod_module *module, -- const char *devname) --{ -- DIR *dir; -- int rc = 0; -- char path[200]; -- struct dirent *de; -- const int len = sizeof(path); -- -- if (!devname) { -- err(ctx, "missing devname\n"); -- return -EINVAL; -- } -- -- if (module) { -- rc = kmod_module_probe_insert_module(module, -- KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, -- NULL); -- if (rc < 0) { -- err(ctx, "%s: insert failure: %d\n", __func__, rc); -- return rc; -- } -- } -- -- if (snprintf(path, len, "/sys/bus/nd/drivers") >= len) { -- err(ctx, "%s: buffer too small!\n", devname); -- return -ENXIO; -- } -- -- dir = opendir(path); -- if (!dir) { -- err(ctx, "%s: opendir(\"%s\") failed\n", devname, path); -- return -ENXIO; -- } -- -- while ((de = readdir(dir)) != NULL) { -- char *drv_path; -- -- if (de->d_ino == 0) -- continue; -- if (de->d_name[0] == '.') -- continue; -- if (asprintf(&drv_path, "%s/%s/bind", path, de->d_name) < 0) { -- err(ctx, "%s: path allocation failure\n", devname); -- continue; -- } -- -- rc = sysfs_write_attr_quiet(ctx, drv_path, devname); -- free(drv_path); -- if (rc == 0) -- break; -- } -- closedir(dir); -- -- if (rc) { -- dbg(ctx, "%s: bind failed\n", devname); -- return -ENXIO; -- } -- return 0; --} -- --static int ndctl_unbind(struct ndctl_ctx *ctx, const char *devpath) --{ -- const char *devname = devpath_to_devname(devpath); -- char path[200]; -- const int len = sizeof(path); -- -- if (snprintf(path, len, "%s/driver/unbind", devpath) >= len) { -- err(ctx, "%s: buffer too small!\n", devname); -- return -ENXIO; -- } -- -- return sysfs_write_attr(ctx, path, devname); --} -- - static void *add_btt(void *parent, int id, const char *btt_base); - static void *add_pfn(void *parent, int id, const char *pfn_base); - static void *add_dax(void *parent, int id, const char *dax_base); -@@ -4533,7 +4454,7 @@ NDCTL_EXPORT int ndctl_namespace_enable(struct ndctl_namespace *ndns) - if (ndctl_namespace_is_enabled(ndns)) - return 0; - -- rc = ndctl_bind(ctx, ndns->module, devname); -+ rc = util_bind(devname, ndns->module, "nd", ctx); - - /* - * Rescan now as successfully enabling a namespace device leads -@@ -4581,7 +4502,7 @@ NDCTL_EXPORT int ndctl_namespace_disable(struct ndctl_namespace *ndns) - if (!ndctl_namespace_is_enabled(ndns)) - return 0; - -- ndctl_unbind(ctx, ndns->ndns_path); -+ util_unbind(ndns->ndns_path, ctx); - - if (ndctl_namespace_is_enabled(ndns)) { - err(ctx, "%s: failed to disable\n", devname); -@@ -5420,7 +5341,7 @@ NDCTL_EXPORT int ndctl_btt_enable(struct ndctl_btt *btt) - if (ndctl_btt_is_enabled(btt)) - return 0; - -- ndctl_bind(ctx, btt->module, devname); -+ util_bind(devname, btt->module, "nd", ctx); - - if (!ndctl_btt_is_enabled(btt)) { - err(ctx, "%s: failed to enable\n", devname); -@@ -5457,7 +5378,7 @@ NDCTL_EXPORT int ndctl_btt_delete(struct ndctl_btt *btt) - return 0; - } - -- ndctl_unbind(ctx, btt->btt_path); -+ util_unbind(btt->btt_path, ctx); - - rc = ndctl_btt_set_namespace(btt, NULL); - if (rc) { -@@ -5908,7 +5829,7 @@ NDCTL_EXPORT int ndctl_pfn_enable(struct ndctl_pfn *pfn) - if (ndctl_pfn_is_enabled(pfn)) - return 0; - -- ndctl_bind(ctx, pfn->module, devname); -+ util_bind(devname, pfn->module, "nd", ctx); - - if (!ndctl_pfn_is_enabled(pfn)) { - err(ctx, "%s: failed to enable\n", devname); -@@ -5945,7 +5866,7 @@ NDCTL_EXPORT int ndctl_pfn_delete(struct ndctl_pfn *pfn) - return 0; - } - -- ndctl_unbind(ctx, pfn->pfn_path); -+ util_unbind(pfn->pfn_path, ctx); - - rc = ndctl_pfn_set_namespace(pfn, NULL); - if (rc) { -@@ -6101,7 +6022,7 @@ NDCTL_EXPORT int ndctl_dax_enable(struct ndctl_dax *dax) - if (ndctl_dax_is_enabled(dax)) - return 0; - -- ndctl_bind(ctx, pfn->module, devname); -+ util_bind(devname, pfn->module, "nd", ctx); - - if (!ndctl_dax_is_enabled(dax)) { - err(ctx, "%s: failed to enable\n", devname); -@@ -6132,7 +6053,7 @@ NDCTL_EXPORT int ndctl_dax_delete(struct ndctl_dax *dax) - return 0; - } - -- ndctl_unbind(ctx, pfn->pfn_path); -+ util_unbind(pfn->pfn_path, ctx); - - rc = ndctl_dax_set_namespace(dax, NULL); - if (rc) { -diff --git a/util/sysfs.c b/util/sysfs.c -index 23330cb..968683b 100644 ---- a/util/sysfs.c -+++ b/util/sysfs.c -@@ -145,3 +145,79 @@ struct kmod_module *__util_modalias_to_module(struct kmod_ctx *kmod_ctx, - - return mod; - } -+ -+int __util_bind(const char *devname, struct kmod_module *module, -+ const char *bus, struct log_ctx *ctx) -+{ -+ DIR *dir; -+ int rc = 0; -+ char path[200]; -+ struct dirent *de; -+ const int len = sizeof(path); -+ -+ if (!devname) { -+ log_err(ctx, "missing devname\n"); -+ return -EINVAL; -+ } -+ -+ if (module) { -+ rc = kmod_module_probe_insert_module(module, -+ KMOD_PROBE_APPLY_BLACKLIST, -+ NULL, NULL, NULL, NULL); -+ if (rc < 0) { -+ log_err(ctx, "%s: insert failure: %d\n", __func__, rc); -+ return rc; -+ } -+ } -+ -+ if (snprintf(path, len, "/sys/bus/%s/drivers", bus) >= len) { -+ log_err(ctx, "%s: buffer too small!\n", devname); -+ return -ENXIO; -+ } -+ -+ dir = opendir(path); -+ if (!dir) { -+ log_err(ctx, "%s: opendir(\"%s\") failed\n", devname, path); -+ return -ENXIO; -+ } -+ -+ while ((de = readdir(dir)) != NULL) { -+ char *drv_path; -+ -+ if (de->d_ino == 0) -+ continue; -+ if (de->d_name[0] == '.') -+ continue; -+ -+ if (asprintf(&drv_path, "%s/%s/bind", path, de->d_name) < 0) { -+ log_err(ctx, "%s: path allocation failure\n", devname); -+ continue; -+ } -+ -+ rc = __sysfs_write_attr_quiet(ctx, drv_path, devname); -+ free(drv_path); -+ if (rc == 0) -+ break; -+ } -+ closedir(dir); -+ -+ if (rc) { -+ log_dbg(ctx, "%s: bind failed\n", devname); -+ return -ENXIO; -+ } -+ return 0; -+} -+ -+int __util_unbind(const char *devpath, struct log_ctx *ctx) -+{ -+ const char *devname = devpath_to_devname(devpath); -+ char path[200]; -+ const int len = sizeof(path); -+ -+ if (snprintf(path, len, "%s/driver/unbind", devpath) >= len) { -+ log_err(ctx, "%s: buffer too small!\n", devname); -+ return -ENXIO; -+ } -+ -+ return __sysfs_write_attr(ctx, path, devname); -+} -diff --git a/util/sysfs.h b/util/sysfs.h -index bdee4f5..4c95c70 100644 ---- a/util/sysfs.h -+++ b/util/sysfs.h -@@ -35,4 +35,12 @@ struct kmod_module *__util_modalias_to_module(struct kmod_ctx *kmod_ctx, - struct log_ctx *log); - #define util_modalias_to_module(ctx, buf) \ - __util_modalias_to_module((ctx)->kmod_ctx, buf, &(ctx)->ctx) -+ -+int __util_bind(const char *devname, struct kmod_module *module, const char *bus, -+ struct log_ctx *ctx); -+#define util_bind(n, m, b, c) __util_bind(n, m, b, &(c)->ctx) -+ -+int __util_unbind(const char *devpath, struct log_ctx *ctx); -+#define util_unbind(p, c) __util_unbind(p, &(c)->ctx) -+ - #endif /* __UTIL_SYSFS_H__ */ --- -2.27.0 - diff --git a/SOURCES/0115-cxl-memdev-Enable-disable-support.patch b/SOURCES/0115-cxl-memdev-Enable-disable-support.patch deleted file mode 100644 index 965fbb2..0000000 --- a/SOURCES/0115-cxl-memdev-Enable-disable-support.patch +++ /dev/null @@ -1,379 +0,0 @@ -From 782694f9aeff6e146cfd00b31822995790546175 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:54:22 -0800 -Subject: [PATCH 115/217] cxl/memdev: Enable / disable support - -Introduce the 'cxl {enable,disable}-memdev' commands. When a memdev is -disabled the ports in the topology may be unregistered. CXL memory regions -require each endpoint in the interleave to attach to the cxl_mem driver -before regions are activated. - -Note that this starts out with the deliberate bug that it has false -positive detection of active memdevs. The fix for that bug requires kernel -support to detect the device's active participation in a region, until then -require all disable attempts to specify the --force override. This way -there are never any releases of cxl-cli that lack disable-memdev safety. - -Link: https://lore.kernel.org/r/164298566245.3021641.12696907310209056878.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-disable-memdev.txt | 37 +++++++++++++++ - Documentation/cxl/cxl-enable-memdev.txt | 34 ++++++++++++++ - Documentation/cxl/lib/libcxl.txt | 23 +++++++++ - Documentation/cxl/meson.build | 2 + - cxl/builtin.h | 2 + - cxl/cxl.c | 2 + - cxl/lib/libcxl.c | 58 +++++++++++++++++++++++ - cxl/lib/libcxl.sym | 2 + - cxl/libcxl.h | 2 + - cxl/memdev.c | 60 +++++++++++++++++++++++- - 10 files changed, 221 insertions(+), 1 deletion(-) - create mode 100644 Documentation/cxl/cxl-disable-memdev.txt - create mode 100644 Documentation/cxl/cxl-enable-memdev.txt - -diff --git a/Documentation/cxl/cxl-disable-memdev.txt b/Documentation/cxl/cxl-disable-memdev.txt -new file mode 100644 -index 0000000..edd5385 ---- /dev/null -+++ b/Documentation/cxl/cxl-disable-memdev.txt -@@ -0,0 +1,37 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-disable-memdev(1) -+===================== -+ -+NAME -+---- -+cxl-disable-memdev - deactivate / hot-remove a given CXL memdev -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl disable-memdev' [..] [] -+ -+ -+OPTIONS -+------- -+:: -+include::memdev-option.txt[] -+ -+-f:: -+--force:: -+ DANGEROUS: Override the safety measure that blocks attempts to disable -+ a device if the tool determines the memdev is in active usage. Recall -+ that CXL memory ranges might have been established by platform -+ firmware and disabling an active device is akin to force removing -+ memory from a running system. -+ -+-v:: -+ Turn on verbose debug messages in the library (if libcxl was built with -+ logging and debug enabled). -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-enable-memdev[1] -diff --git a/Documentation/cxl/cxl-enable-memdev.txt b/Documentation/cxl/cxl-enable-memdev.txt -new file mode 100644 -index 0000000..088d5e0 ---- /dev/null -+++ b/Documentation/cxl/cxl-enable-memdev.txt -@@ -0,0 +1,34 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-enable-memdev(1) -+==================== -+ -+NAME -+---- -+cxl-enable-memdev - activate / hot-add a given CXL memdev -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl enable-memdev' [..] [] -+ -+A memdev typically autoenables at initial device discovery. However, if -+it was manually disabled this command can trigger the kernel to activate -+it again. This involves detecting the state of the HDM (Host Managed -+Device Memory) Decoders and validating that CXL.mem is enabled for each -+port in the device's hierarchy. -+ -+OPTIONS -+------- -+:: -+include::memdev-option.txt[] -+ -+-v:: -+ Turn on verbose debug messages in the library (if libcxl was built with -+ logging and debug enabled). -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-disable-memdev[1] -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index de88d19..49edb71 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -93,6 +93,29 @@ device. - cxl_memdev_get_numa_node() returns the affinitized CPU node number if - available or -1 otherwise. - -+=== MEMDEV: Control -+---- -+int cxl_memdev_disable_invalidate(struct cxl_memdev *memdev); -+int cxl_memdev_enable(struct cxl_memdev *memdev); -+---- -+When a memory device is disabled it unregisters its associated endpoints -+and potentially intervening switch ports if there are no other memdevs -+pinning that port active. That means that any existing port objects that -+the library has previously returned are in valid and need to be re-read. -+Callers must be careful to re-retrieve port objects after -+cxl_memdev_disable_invalidate(). Any usage of a previously obtained port -+object after a cxl_memdev_disable_invalidate() call is a use-after-free -+programming error. It follows that after cxl_memdev_enable() new ports -+may appear in the topology that were not previously enumerable. -+ -+NOTE: cxl_memdev_disable_invalidate() will force disable the memdev -+regardless of whether the memory provided by the device is in active use -+by the operating system. Callers take responisbility for assuring that -+it is safe to disable the memory device. Otherwise, this call can be as -+destructive as ripping a DIMM out of a running system. Like all other -+libcxl calls that mutate the system state or divulge security sensitive -+information this call requires root / CAP_SYS_ADMIN. -+ - === MEMDEV: Commands - ---- - struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode); -diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build -index 0a6346b..7618c97 100644 ---- a/Documentation/cxl/meson.build -+++ b/Documentation/cxl/meson.build -@@ -30,6 +30,8 @@ cxl_manpages = [ - 'cxl-read-labels.txt', - 'cxl-write-labels.txt', - 'cxl-zero-labels.txt', -+ 'cxl-enable-memdev.txt', -+ 'cxl-disable-memdev.txt', - ] - - foreach man : cxl_manpages -diff --git a/cxl/builtin.h b/cxl/builtin.h -index 78eca6e..621c85c 100644 ---- a/cxl/builtin.h -+++ b/cxl/builtin.h -@@ -10,4 +10,6 @@ int cmd_read_labels(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_zero_labels(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_init_labels(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_check_labels(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_disable_memdev(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_enable_memdev(int argc, const char **argv, struct cxl_ctx *ctx); - #endif /* _CXL_BUILTIN_H_ */ -diff --git a/cxl/cxl.c b/cxl/cxl.c -index 4b1661d..78d2e9a 100644 ---- a/cxl/cxl.c -+++ b/cxl/cxl.c -@@ -64,6 +64,8 @@ static struct cmd_struct commands[] = { - { "zero-labels", .c_fn = cmd_zero_labels }, - { "read-labels", .c_fn = cmd_read_labels }, - { "write-labels", .c_fn = cmd_write_labels }, -+ { "disable-memdev", .c_fn = cmd_disable_memdev }, -+ { "enable-memdev", .c_fn = cmd_enable_memdev }, - }; - - int main(int argc, const char **argv) -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 14c7db8..2fdaf71 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -500,6 +500,64 @@ CXL_EXPORT const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev - return memdev->firmware_version; - } - -+CXL_EXPORT int cxl_memdev_disable_invalidate(struct cxl_memdev *memdev) -+{ -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ const char *devname = cxl_memdev_get_devname(memdev); -+ struct cxl_port *port, *_p, *bus_port; -+ struct cxl_bus *bus; -+ -+ if (!cxl_memdev_is_enabled(memdev)) -+ return 0; -+ -+ bus = cxl_memdev_get_bus(memdev); -+ if (!bus) { -+ err(ctx, "%s: failed to invalidate\n", devname); -+ return -ENXIO; -+ } -+ -+ util_unbind(memdev->dev_path, ctx); -+ -+ if (cxl_memdev_is_enabled(memdev)) { -+ err(ctx, "%s: failed to disable\n", devname); -+ return -EBUSY; -+ } -+ -+ /* -+ * The state of all ports is now indeterminate, delete them all -+ * and start over. -+ */ -+ bus_port = cxl_bus_get_port(bus); -+ list_for_each_safe(&bus_port->child_ports, port, _p, list) -+ free_port(port, &bus_port->child_ports); -+ bus_port->ports_init = 0; -+ memdev->endpoint = NULL; -+ -+ dbg(ctx, "%s: disabled\n", devname); -+ -+ return 0; -+} -+ -+CXL_EXPORT int cxl_memdev_enable(struct cxl_memdev *memdev) -+{ -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ const char *devname = cxl_memdev_get_devname(memdev); -+ -+ if (cxl_memdev_is_enabled(memdev)) -+ return 0; -+ -+ util_bind(devname, memdev->module, "cxl", ctx); -+ -+ if (!cxl_memdev_is_enabled(memdev)) { -+ err(ctx, "%s: failed to enable\n", devname); -+ return -ENXIO; -+ } -+ -+ dbg(ctx, "%s: enabled\n", devname); -+ -+ return 0; -+} -+ - static struct cxl_endpoint *cxl_port_find_endpoint(struct cxl_port *parent_port, - struct cxl_memdev *memdev) - { -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index b13a2d6..f235e99 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -115,4 +115,6 @@ global: - cxl_memdev_get_endpoint; - cxl_memdev_is_enabled; - cxl_memdev_get_bus; -+ cxl_memdev_disable_invalidate; -+ cxl_memdev_enable; - } LIBCXL_1; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index be656ed..53f68dd 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -48,6 +48,8 @@ unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev); - unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev); - const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev); - size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev); -+int cxl_memdev_disable_invalidate(struct cxl_memdev *memdev); -+int cxl_memdev_enable(struct cxl_memdev *memdev); - struct cxl_endpoint; - struct cxl_endpoint *cxl_memdev_get_endpoint(struct cxl_memdev *memdev); - int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev); -diff --git a/cxl/memdev.c b/cxl/memdev.c -index ef5343a..90b33e1 100644 ---- a/cxl/memdev.c -+++ b/cxl/memdev.c -@@ -25,13 +25,14 @@ static struct parameters { - unsigned offset; - bool verbose; - bool serial; -+ bool force; - } param; - - static struct log_ctx ml; - - #define BASE_OPTIONS() \ - OPT_BOOLEAN('v',"verbose", ¶m.verbose, "turn on debug"), \ --OPT_BOOLEAN('S', "serial", ¶m.serial, "user serials numbers to id memdevs") -+OPT_BOOLEAN('S', "serial", ¶m.serial, "use serial numbers to id memdevs") - - #define READ_OPTIONS() \ - OPT_STRING('o', "output", ¶m.outfile, "output-file", \ -@@ -46,6 +47,10 @@ OPT_UINTEGER('s', "size", ¶m.len, "number of label bytes to operate"), \ - OPT_UINTEGER('O', "offset", ¶m.offset, \ - "offset into the label area to start operation") - -+#define DISABLE_OPTIONS() \ -+OPT_BOOLEAN('f', "force", ¶m.force, \ -+ "DANGEROUS: override active memdev safety checks") -+ - static const struct option read_options[] = { - BASE_OPTIONS(), - LABEL_OPTIONS(), -@@ -66,6 +71,37 @@ static const struct option zero_options[] = { - OPT_END(), - }; - -+static const struct option disable_options[] = { -+ BASE_OPTIONS(), -+ DISABLE_OPTIONS(), -+ OPT_END(), -+}; -+ -+static const struct option enable_options[] = { -+ BASE_OPTIONS(), -+ OPT_END(), -+}; -+ -+static int action_disable(struct cxl_memdev *memdev, struct action_context *actx) -+{ -+ if (!cxl_memdev_is_enabled(memdev)) -+ return 0; -+ -+ if (!param.force) { -+ /* TODO: actually detect rather than assume active */ -+ log_err(&ml, "%s is part of an active region\n", -+ cxl_memdev_get_devname(memdev)); -+ return -EBUSY; -+ } -+ -+ return cxl_memdev_disable_invalidate(memdev); -+} -+ -+static int action_enable(struct cxl_memdev *memdev, struct action_context *actx) -+{ -+ return cxl_memdev_enable(memdev); -+} -+ - static int action_zero(struct cxl_memdev *memdev, struct action_context *actx) - { - size_t size; -@@ -340,3 +376,25 @@ int cmd_zero_labels(int argc, const char **argv, struct cxl_ctx *ctx) - count > 1 ? "s" : ""); - return count >= 0 ? 0 : EXIT_FAILURE; - } -+ -+int cmd_disable_memdev(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ int count = memdev_action( -+ argc, argv, ctx, action_disable, disable_options, -+ "cxl disable-memdev [..] []"); -+ -+ log_info(&ml, "disabled %d mem%s\n", count >= 0 ? count : 0, -+ count > 1 ? "s" : ""); -+ return count >= 0 ? 0 : EXIT_FAILURE; -+} -+ -+int cmd_enable_memdev(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ int count = memdev_action( -+ argc, argv, ctx, action_enable, enable_options, -+ "cxl enable-memdev [..] []"); -+ -+ log_info(&ml, "enabled %d mem%s\n", count >= 0 ? count : 0, -+ count > 1 ? "s" : ""); -+ return count >= 0 ? 0 : EXIT_FAILURE; -+} --- -2.27.0 - diff --git a/SOURCES/0116-cxl-list-Add-decoder-support.patch b/SOURCES/0116-cxl-list-Add-decoder-support.patch deleted file mode 100644 index 61d626d..0000000 --- a/SOURCES/0116-cxl-list-Add-decoder-support.patch +++ /dev/null @@ -1,1108 +0,0 @@ -From 46564977afb733a92526c688fe106e19b139ddfc Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:54:27 -0800 -Subject: [PATCH 116/217] cxl/list: Add decoder support - -Decoder objects exist at each level of a CXL port topology and map a -physical address range a set of interleaved ports at each level of the -hierarchy. Typically end users mostly care about the root-level decoders -which enumerate the potential CXL address space in the system, and the -endpoint decoders that indicate which address ranges a given device -contributes resources. Intermediate switch-level decoders are typically -only useful for debugging decode problems. - -$ cxl list -D -d 3.1 -u -{ - "decoder":"decoder3.1", - "resource":"0x8030000000", - "size":"512.00 MiB (536.87 MB)", - "volatile_capable":true -} - -Link: https://lore.kernel.org/r/164298566760.3021641.3999006903066004615.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .clang-format | 1 + - Documentation/cxl/cxl-list.txt | 18 ++- - Documentation/cxl/lib/libcxl.txt | 70 ++++++++- - cxl/filter.c | 194 +++++++++++++++++++++++-- - cxl/filter.h | 2 + - cxl/json.c | 62 ++++++++ - cxl/json.h | 2 + - cxl/lib/libcxl.c | 239 ++++++++++++++++++++++++++++--- - cxl/lib/libcxl.sym | 14 ++ - cxl/lib/private.h | 31 +++- - cxl/libcxl.h | 28 ++++ - cxl/list.c | 9 +- - util/json.h | 1 + - 13 files changed, 643 insertions(+), 28 deletions(-) - -diff --git a/.clang-format b/.clang-format -index 106bc5e..16e28ac 100644 ---- a/.clang-format -+++ b/.clang-format -@@ -80,6 +80,7 @@ ForEachMacros: - - 'cxl_memdev_foreach' - - 'cxl_bus_foreach' - - 'cxl_port_foreach' -+ - 'cxl_decoder_foreach' - - 'cxl_endpoint_foreach' - - 'daxctl_dev_foreach' - - 'daxctl_mapping_foreach' -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index bac27c7..84872b9 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -5,7 +5,7 @@ cxl-list(1) - - NAME - ---- --cxl-list - List CXL capable memory devices, and their attributes in json. -+cxl-list - List platform CXL objects, and their attributes, in json. - - SYNOPSIS - -------- -@@ -29,6 +29,10 @@ The potential top-level array names and their nesting properties are: - "endpoints":: nest under ports or buses (if ports are not emitted) - "memdevs":: nest under endpoints or ports (if endpoints are not - emitted) or buses (if endpoints and ports are not emitted) -+"root decoders":: nest under buses -+"port decoders":: nest under ports, or buses (if ports are not emitted) -+"endpoint decoders":: nest under endpoints, or ports (if endpoints are -+ not emitted) or buses (if endpoints and ports are not emitted) - - Filters can by specifed as either a single identidier, a space separated - quoted string, or a comma separated list. When multiple filter -@@ -254,6 +258,18 @@ OPTIONS - Specify CXL endpoint device name(s), or device id(s) to filter - the emitted endpoint(s). - -+-D:: -+--decoders:: -+ Include decoder objects (CXL Memory decode capability instances -+ in buses, ports, and endpoints) in the listing. -+ -+-d:: -+--decoder:: -+ Specify CXL decoder device name(s), device id(s), or decoder type names -+ to filter the emitted decoder(s). The format for a decoder name is -+ "decoder.". The possible decoder type names are -+ "root", "switch", or "endpoint", similar to the port filter syntax. -+ - --debug:: - If the cxl tool was built with debug enabled, turn on debug - messages. -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 49edb71..73af3d0 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -179,6 +179,7 @@ struct cxl_bus *cxl_bus_get_first(struct cxl_ctx *ctx); - struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus); - struct cxl_ctx *cxl_bus_get_ctx(struct cxl_bus *bus); - struct cxl_bus *cxl_memdev_get_bus(struct cxl_memdev *memdev); -+struct cxl_bus *cxl_port_get_bus(struct cxl_port *port); - struct cxl_bus *cxl_endpoint_get_bus(struct cxl_endpoint *endpoint); - - #define cxl_bus_foreach(ctx, bus) \ -@@ -215,9 +216,9 @@ struct cxl_port *cxl_bus_get_port(struct cxl_bus *bus); - struct cxl_port *cxl_port_get_first(struct cxl_port *parent); - struct cxl_port *cxl_port_get_next(struct cxl_port *port); - struct cxl_port *cxl_port_get_parent(struct cxl_port *port); --struct cxl_bus *cxl_port_get_bus(struct cxl_port *port); - struct cxl_ctx *cxl_port_get_ctx(struct cxl_port *port); - const char *cxl_port_get_host(struct cxl_port *port); -+struct cxl_port *cxl_decoder_get_port(struct cxl_decoder *decoder); - - #define cxl_port_foreach(parent, port) \ - for (port = cxl_port_get_first(parent); port != NULL; \ -@@ -284,6 +285,73 @@ int cxl_endpoint_get_id(struct cxl_endpoint *endpoint); - int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint); - ---- - -+DECODERS -+-------- -+Decoder objects are associated with the "HDM Decoder Capability" -+published in Port devices and CXL capable PCIe endpoints. The kernel -+additionally models platform firmware described CXL memory ranges (like -+the ACPI CEDT.CFMWS) as static decoder objects. They route System -+Physical Addresses through a port topology to an endpoint decoder that -+does the final translation from SPA to DPA (system-physical-address to -+device-local-physical-address). -+ -+=== DECODER: Enumeration -+---- -+struct cxl_decoder *cxl_decoder_get_first(struct cxl_port *port); -+struct cxl_decoder *cxl_decoder_get_next(struct cxl_decoder *decoder); -+struct cxl_ctx *cxl_decoder_get_ctx(struct cxl_decoder *decoder); -+ -+#define cxl_decoder_foreach(port, decoder) \ -+ for (decoder = cxl_decoder_get_first(port); decoder != NULL; \ -+ decoder = cxl_decoder_get_next(decoder)) -+---- -+The definition of a CXL port in libcxl is an object that hosts one or -+more CXL decoder objects. -+ -+=== DECODER: Attributes -+---- -+unsigned long long cxl_decoder_get_resource(struct cxl_decoder *decoder); -+unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder); -+const char *cxl_decoder_get_devname(struct cxl_decoder *decoder); -+int cxl_decoder_get_id(struct cxl_decoder *decoder); -+ -+enum cxl_decoder_target_type { -+ CXL_DECODER_TTYPE_UNKNOWN, -+ CXL_DECODER_TTYPE_EXPANDER, -+ CXL_DECODER_TTYPE_ACCELERATOR, -+}; -+ -+cxl_decoder_get_target_type(struct cxl_decoder *decoder); -+bool cxl_decoder_is_pmem_capable(struct cxl_decoder *decoder); -+bool cxl_decoder_is_volatile_capable(struct cxl_decoder *decoder); -+bool cxl_decoder_is_mem_capable(struct cxl_decoder *decoder); -+bool cxl_decoder_is_accelmem_capable(struct cxl_decoder *decoder); -+bool cxl_decoder_is_locked(struct cxl_decoder *decoder); -+---- -+The kernel protects the enumeration of the physical address layout of -+the system. Without CAP_SYS_ADMIN cxl_decoder_get_resource() returns -+ULLONG_MAX to indicate that the address information was not retrievable. -+Otherwise, cxl_decoder_get_resource() returns the currently programmed -+value of the base of the decoder's decode range. A zero-sized decoder -+indicates a disabled decoder. -+ -+Root level decoders only support limited set of memory types in their -+address range. The cxl_decoder_is__capable() helpers identify -+what is supported. Switch level decoders, in contrast are capable of -+routing any memory type, i.e. they just forward along the memory type -+support from their parent port. Endpoint decoders follow the -+capabilities of their host memory device. -+ -+The capabilities of a decoder are not to be confused with their type / -+mode. The type ultimately depends on the endpoint. For example an -+accelerator requires all decoders in its ancestry to be set to -+CXL_DECODER_TTYPE_ACCELERATOR, and conversely plain memory expander -+devices require CXL_DECODER_TTYPE_EXPANDER. -+ -+Platform firmware may setup the CXL decode hierarchy before the OS -+boots, and may additionally require that the OS not change the decode -+settings. This property is indicated by the cxl_decoder_is_locked() API. -+ - include::../../copyright.txt[] - - SEE ALSO -diff --git a/cxl/filter.c b/cxl/filter.c -index 6dc61a1..dc052f6 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -171,6 +171,17 @@ util_cxl_endpoint_filter_by_port(struct cxl_endpoint *endpoint, - return NULL; - } - -+static struct cxl_decoder * -+util_cxl_decoder_filter_by_port(struct cxl_decoder *decoder, const char *ident, -+ enum cxl_port_filter_mode mode) -+{ -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ -+ if (util_cxl_port_filter(port, ident, mode)) -+ return decoder; -+ return NULL; -+} -+ - static struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus, - const char *__ident) - { -@@ -233,6 +244,16 @@ static struct cxl_port *util_cxl_port_filter_by_bus(struct cxl_port *port, - return NULL; - } - -+static struct cxl_decoder * -+util_cxl_decoder_filter_by_bus(struct cxl_decoder *decoder, const char *__ident) -+{ -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ -+ if (!util_cxl_port_filter_by_bus(port, __ident)) -+ return NULL; -+ return decoder; -+} -+ - static struct cxl_memdev * - util_cxl_memdev_serial_filter(struct cxl_memdev *memdev, const char *__serials) - { -@@ -357,6 +378,49 @@ static struct cxl_port *util_cxl_port_filter_by_memdev(struct cxl_port *port, - return NULL; - } - -+static struct cxl_decoder *util_cxl_decoder_filter(struct cxl_decoder *decoder, -+ const char *__ident) -+{ -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ int pid, did; -+ char *ident, *save; -+ const char *name; -+ -+ if (!__ident) -+ return decoder; -+ -+ ident = strdup(__ident); -+ if (!ident) -+ return NULL; -+ -+ for (name = strtok_r(ident, which_sep(__ident), &save); name; -+ name = strtok_r(NULL, which_sep(__ident), &save)) { -+ if (strcmp(name, "all") == 0) -+ break; -+ -+ if (strcmp(name, "root") == 0 && cxl_port_is_root(port)) -+ break; -+ if (strcmp(name, "switch") == 0 && cxl_port_is_switch(port)) -+ break; -+ if (strcmp(name, "endpoint") == 0 && cxl_port_is_endpoint(port)) -+ break; -+ -+ if ((sscanf(name, "%d.%d", &pid, &did) == 2 || -+ sscanf(name, "decoder%d.%d", &pid, &did) == 2) && -+ cxl_port_get_id(port) == pid && -+ cxl_decoder_get_id(decoder) == did) -+ break; -+ -+ if (strcmp(name, cxl_decoder_get_devname(decoder)) == 0) -+ break; -+ } -+ -+ free(ident); -+ if (name) -+ return decoder; -+ return NULL; -+} -+ - static unsigned long params_to_flags(struct cxl_filter_params *param) - { - unsigned long flags = 0; -@@ -440,15 +504,44 @@ static struct json_object *pick_array(struct json_object *child, - return NULL; - } - -+static void walk_decoders(struct cxl_port *port, struct cxl_filter_params *p, -+ struct json_object *jdecoders, unsigned long flags) -+{ -+ struct cxl_decoder *decoder; -+ -+ cxl_decoder_foreach(port, decoder) { -+ struct json_object *jdecoder; -+ -+ if (!p->decoders) -+ continue; -+ if (!util_cxl_decoder_filter(decoder, p->decoder_filter)) -+ continue; -+ if (!util_cxl_decoder_filter_by_bus(decoder, p->bus_filter)) -+ continue; -+ if (!util_cxl_decoder_filter_by_port(decoder, p->port_filter, -+ pf_mode(p))) -+ continue; -+ if (!p->idle && cxl_decoder_get_size(decoder) == 0) -+ continue; -+ jdecoder = util_cxl_decoder_to_json(decoder, flags); -+ if (!decoder) { -+ dbg(p, "decoder object allocation failure\n"); -+ continue; -+ } -+ json_object_array_add(jdecoders, jdecoder); -+ } -+} -+ - static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p, - struct json_object *jeps, struct json_object *jdevs, -- unsigned long flags) -+ struct json_object *jdecoders, unsigned long flags) - { - struct cxl_endpoint *endpoint; - - cxl_endpoint_foreach(port, endpoint) { - struct cxl_port *ep_port = cxl_endpoint_get_port(endpoint); - const char *devname = cxl_endpoint_get_devname(endpoint); -+ struct json_object *jchilddecoders = NULL; - struct json_object *jendpoint = NULL; - struct cxl_memdev *memdev; - -@@ -495,14 +588,31 @@ static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p, - else - json_object_array_add(jdevs, jobj); - } -+ -+ if (p->decoders && p->endpoints) { -+ jchilddecoders = json_object_new_array(); -+ if (!jchilddecoders) { -+ err(p, -+ "%s: failed to enumerate child decoders\n", -+ devname); -+ continue; -+ } -+ } -+ -+ if (!p->decoders) -+ continue; -+ walk_decoders(cxl_endpoint_get_port(endpoint), p, -+ pick_array(jchilddecoders, jdecoders), flags); -+ cond_add_put_array_suffix(jendpoint, "decoders", devname, -+ jchilddecoders); - } - } - --static void walk_child_ports(struct cxl_port *parent_port, -- struct cxl_filter_params *p, -- struct json_object *jports, -- struct json_object *jeps, -- struct json_object *jdevs, unsigned long flags) -+static void -+walk_child_ports(struct cxl_port *parent_port, struct cxl_filter_params *p, -+ struct json_object *jports, struct json_object *jportdecoders, -+ struct json_object *jeps, struct json_object *jepdecoders, -+ struct json_object *jdevs, unsigned long flags) - { - struct cxl_port *port; - -@@ -512,6 +622,7 @@ static void walk_child_ports(struct cxl_port *parent_port, - struct json_object *jchilddevs = NULL; - struct json_object *jchildports = NULL; - struct json_object *jchildeps = NULL; -+ struct json_object *jchilddecoders = NULL; - - if (!util_cxl_port_filter_by_memdev(port, p->memdev_filter, - p->serial_filter)) -@@ -555,19 +666,37 @@ static void walk_child_ports(struct cxl_port *parent_port, - continue; - } - } -+ -+ if (p->decoders) { -+ jchilddecoders = json_object_new_array(); -+ if (!jchilddecoders) { -+ err(p, -+ "%s: failed to enumerate child decoders\n", -+ devname); -+ continue; -+ } -+ } - } - - walk_children: -- if (p->endpoints || p->memdevs) -+ if (p->endpoints || p->memdevs || p->decoders) - walk_endpoints(port, p, pick_array(jchildeps, jeps), -- pick_array(jchilddevs, jdevs), flags); -+ pick_array(jchilddevs, jdevs), -+ pick_array(jchilddecoders, jepdecoders), -+ flags); - -+ walk_decoders(port, p, -+ pick_array(jchilddecoders, jportdecoders), flags); - walk_child_ports(port, p, pick_array(jchildports, jports), -+ pick_array(jchilddecoders, jportdecoders), - pick_array(jchildeps, jeps), -+ pick_array(jchilddecoders, jepdecoders), - pick_array(jchilddevs, jdevs), flags); - cond_add_put_array_suffix(jport, "ports", devname, jchildports); - cond_add_put_array_suffix(jport, "endpoints", devname, - jchildeps); -+ cond_add_put_array_suffix(jport, "decoders", devname, -+ jchilddecoders); - cond_add_put_array_suffix(jport, "memdevs", devname, - jchilddevs); - } -@@ -578,6 +707,9 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - struct json_object *jdevs = NULL, *jbuses = NULL, *jports = NULL; - struct json_object *jplatform = json_object_new_array(); - unsigned long flags = params_to_flags(p); -+ struct json_object *jportdecoders = NULL; -+ struct json_object *jbusdecoders = NULL; -+ struct json_object *jepdecoders = NULL; - struct json_object *janondevs = NULL; - struct json_object *jeps = NULL; - struct cxl_memdev *memdev; -@@ -609,6 +741,18 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - if (!jdevs) - goto err; - -+ jbusdecoders = json_object_new_array(); -+ if (!jbusdecoders) -+ goto err; -+ -+ jportdecoders = json_object_new_array(); -+ if (!jportdecoders) -+ goto err; -+ -+ jepdecoders = json_object_new_array(); -+ if (!jepdecoders) -+ goto err; -+ - dbg(p, "walk memdevs\n"); - cxl_memdev_foreach(ctx, memdev) { - struct json_object *janondev; -@@ -633,6 +777,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - dbg(p, "walk buses\n"); - cxl_bus_foreach(ctx, bus) { - struct json_object *jbus = NULL; -+ struct json_object *jchilddecoders = NULL; - struct json_object *jchildports = NULL; - struct json_object *jchilddevs = NULL; - struct json_object *jchildeps = NULL; -@@ -681,15 +826,33 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - continue; - } - } -+ if (p->decoders) { -+ jchilddecoders = json_object_new_array(); -+ if (!jchilddecoders) { -+ err(p, -+ "%s: failed to enumerate child decoders\n", -+ devname); -+ continue; -+ } -+ } -+ - } - walk_children: -+ dbg(p, "walk decoders\n"); -+ walk_decoders(port, p, pick_array(jchilddecoders, jbusdecoders), -+ flags); -+ - dbg(p, "walk ports\n"); - walk_child_ports(port, p, pick_array(jchildports, jports), -+ pick_array(jchilddecoders, jportdecoders), - pick_array(jchildeps, jeps), -+ pick_array(jchilddecoders, jepdecoders), - pick_array(jchilddevs, jdevs), flags); - cond_add_put_array_suffix(jbus, "ports", devname, jchildports); - cond_add_put_array_suffix(jbus, "endpoints", devname, - jchildeps); -+ cond_add_put_array_suffix(jbus, "decoders", devname, -+ jchilddecoders); - cond_add_put_array_suffix(jbus, "memdevs", devname, jchilddevs); - } - -@@ -703,12 +866,24 @@ walk_children: - top_level_objs++; - if (json_object_array_length(jdevs)) - top_level_objs++; -+ if (json_object_array_length(jbusdecoders)) -+ top_level_objs++; -+ if (json_object_array_length(jportdecoders)) -+ top_level_objs++; -+ if (json_object_array_length(jepdecoders)) -+ top_level_objs++; - - splice_array(p, janondevs, jplatform, "anon memdevs", top_level_objs > 1); - splice_array(p, jbuses, jplatform, "buses", top_level_objs > 1); - splice_array(p, jports, jplatform, "ports", top_level_objs > 1); - splice_array(p, jeps, jplatform, "endpoints", top_level_objs > 1); - splice_array(p, jdevs, jplatform, "memdevs", top_level_objs > 1); -+ splice_array(p, jbusdecoders, jplatform, "root decoders", -+ top_level_objs > 1); -+ splice_array(p, jportdecoders, jplatform, "port decoders", -+ top_level_objs > 1); -+ splice_array(p, jepdecoders, jplatform, "endpoint decoders", -+ top_level_objs > 1); - - util_display_json_array(stdout, jplatform, flags); - -@@ -719,6 +894,9 @@ err: - json_object_put(jports); - json_object_put(jeps); - json_object_put(jdevs); -+ json_object_put(jbusdecoders); -+ json_object_put(jportdecoders); -+ json_object_put(jepdecoders); - json_object_put(jplatform); - return -ENOMEM; - } -diff --git a/cxl/filter.h b/cxl/filter.h -index bbd341c..5d7bf45 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -12,8 +12,10 @@ struct cxl_filter_params { - const char *bus_filter; - const char *port_filter; - const char *endpoint_filter; -+ const char *decoder_filter; - bool single; - bool endpoints; -+ bool decoders; - bool memdevs; - bool ports; - bool buses; -diff --git a/cxl/json.c b/cxl/json.c -index 51918d6..548bc52 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -262,6 +262,68 @@ struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus, - return jbus; - } - -+struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, -+ unsigned long flags) -+{ -+ const char *devname = cxl_decoder_get_devname(decoder); -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ struct json_object *jdecoder, *jobj; -+ u64 val; -+ -+ jdecoder = json_object_new_object(); -+ if (!jdecoder) -+ return NULL; -+ -+ jobj = json_object_new_string(devname); -+ if (jobj) -+ json_object_object_add(jdecoder, "decoder", jobj); -+ -+ val = cxl_decoder_get_resource(decoder); -+ if (val < ULLONG_MAX) { -+ jobj = util_json_object_hex(val, flags); -+ if (jobj) -+ json_object_object_add(jdecoder, "resource", jobj); -+ } -+ -+ val = cxl_decoder_get_size(decoder); -+ if (val < ULLONG_MAX) { -+ jobj = util_json_object_size(val, flags); -+ if (jobj) -+ json_object_object_add(jdecoder, "size", jobj); -+ } -+ -+ if (val == 0) { -+ jobj = json_object_new_string("disabled"); -+ if (jobj) -+ json_object_object_add(jdecoder, "state", jobj); -+ } -+ -+ if (cxl_port_is_root(port) && cxl_decoder_is_mem_capable(decoder)) { -+ if (cxl_decoder_is_pmem_capable(decoder)) { -+ jobj = json_object_new_boolean(true); -+ if (jobj) -+ json_object_object_add(jdecoder, "pmem_capable", -+ jobj); -+ } -+ if (cxl_decoder_is_volatile_capable(decoder)) { -+ jobj = json_object_new_boolean(true); -+ if (jobj) -+ json_object_object_add( -+ jdecoder, "volatile_capable", jobj); -+ } -+ } -+ -+ if (cxl_port_is_root(port) && -+ cxl_decoder_is_accelmem_capable(decoder)) { -+ jobj = json_object_new_boolean(true); -+ if (jobj) -+ json_object_object_add(jdecoder, "accelmem_capable", -+ jobj); -+ } -+ -+ return jdecoder; -+} -+ - static struct json_object *__util_cxl_port_to_json(struct cxl_port *port, - const char *name_key, - unsigned long flags) -diff --git a/cxl/json.h b/cxl/json.h -index 8f45190..fcca2e6 100644 ---- a/cxl/json.h -+++ b/cxl/json.h -@@ -13,4 +13,6 @@ struct json_object *util_cxl_port_to_json(struct cxl_port *port, - unsigned long flags); - struct json_object *util_cxl_endpoint_to_json(struct cxl_endpoint *endpoint, - unsigned long flags); -+struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, -+ unsigned long flags); - #endif /* __CXL_UTIL_JSON_H__ */ -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 2fdaf71..5e30923 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -63,16 +63,26 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head) - free(memdev->firmware_version); - free(memdev->dev_buf); - free(memdev->dev_path); -- free(memdev->host); -+ free(memdev->host_path); - free(memdev); - } - -+static void free_decoder(struct cxl_decoder *decoder, struct list_head *head) -+{ -+ if (head) -+ list_del_from(head, &decoder->list); -+ free(decoder->dev_buf); -+ free(decoder->dev_path); -+ free(decoder); -+} -+ - static void free_port(struct cxl_port *port, struct list_head *head); - static void free_endpoint(struct cxl_endpoint *endpoint, struct list_head *head); - static void __free_port(struct cxl_port *port, struct list_head *head) - { - struct cxl_port *child, *_c; - struct cxl_endpoint *endpoint, *_e; -+ struct cxl_decoder *decoder, *_d; - - if (head) - list_del_from(head, &port->list); -@@ -80,6 +90,8 @@ static void __free_port(struct cxl_port *port, struct list_head *head) - free_port(child, &port->child_ports); - list_for_each_safe(&port->endpoints, endpoint, _e, port.list) - free_endpoint(endpoint, &port->endpoints); -+ list_for_each_safe(&port->decoders, decoder, _d, list) -+ free_decoder(decoder, &port->decoders); - kmod_module_unref(port->module); - free(port->dev_buf); - free(port->dev_path); -@@ -298,9 +310,9 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) - char *path = calloc(1, strlen(cxlmem_base) + 100); - struct cxl_ctx *ctx = parent; - struct cxl_memdev *memdev, *memdev_dup; -- char *host, *rpath = NULL; - char buf[SYSFS_ATTR_SIZE]; - struct stat st; -+ char *host; - - if (!path) - return NULL; -@@ -358,21 +370,13 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) - if (!memdev->dev_path) - goto err_read; - -- rpath = realpath(cxlmem_base, NULL); -- if (!rpath) -+ memdev->host_path = realpath(cxlmem_base, NULL); -+ if (!memdev->host_path) - goto err_read; -- host = strrchr(rpath, '/'); -- if (host) { -- host[0] = '\0'; -- host = strrchr(rpath, '/'); -- } -+ host = strrchr(memdev->host_path, '/'); - if (!host) - goto err_read; -- memdev->host = strdup(host + 1); -- if (!memdev->host) -- goto err_read; -- free(rpath); -- rpath = NULL; -+ host[0] = '\0'; - - sprintf(path, "%s/firmware_version", cxlmem_base); - if (sysfs_read_attr(ctx, path, buf) < 0) -@@ -404,8 +408,8 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) - free(memdev->firmware_version); - free(memdev->dev_buf); - free(memdev->dev_path); -+ free(memdev->host_path); - free(memdev); -- free(rpath); - err_dev: - free(path); - return NULL; -@@ -463,7 +467,7 @@ CXL_EXPORT const char *cxl_memdev_get_devname(struct cxl_memdev *memdev) - - CXL_EXPORT const char *cxl_memdev_get_host(struct cxl_memdev *memdev) - { -- return memdev->host; -+ return devpath_to_devname(memdev->host_path); - } - - CXL_EXPORT struct cxl_bus *cxl_memdev_get_bus(struct cxl_memdev *memdev) -@@ -679,9 +683,11 @@ static int cxl_port_init(struct cxl_port *port, struct cxl_port *parent_port, - port->ctx = ctx; - port->type = type; - port->parent = parent_port; -+ port->type = type; - - list_head_init(&port->child_ports); - list_head_init(&port->endpoints); -+ list_head_init(&port->decoders); - - port->dev_path = strdup(cxlport_base); - if (!port->dev_path) -@@ -842,6 +848,207 @@ cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint) - return NULL; - } - -+static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) -+{ -+ const char *devname = devpath_to_devname(cxldecoder_base); -+ char *path = calloc(1, strlen(cxldecoder_base) + 100); -+ struct cxl_decoder *decoder, *decoder_dup; -+ struct cxl_port *port = parent; -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ char buf[SYSFS_ATTR_SIZE]; -+ size_t i; -+ -+ dbg(ctx, "%s: base: \'%s\'\n", devname, cxldecoder_base); -+ -+ if (!path) -+ return NULL; -+ -+ decoder = calloc(1, sizeof(*decoder)); -+ if (!decoder) -+ goto err; -+ -+ decoder->id = id; -+ decoder->ctx = ctx; -+ decoder->port = port; -+ -+ decoder->dev_path = strdup(cxldecoder_base); -+ if (!decoder->dev_path) -+ goto err; -+ -+ decoder->dev_buf = calloc(1, strlen(cxldecoder_base) + 50); -+ if (!decoder->dev_buf) -+ goto err; -+ decoder->buf_len = strlen(cxldecoder_base) + 50; -+ -+ sprintf(path, "%s/start", cxldecoder_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ decoder->start = ULLONG_MAX; -+ else -+ decoder->start = strtoull(buf, NULL, 0); -+ -+ sprintf(path, "%s/size", cxldecoder_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ decoder->size = ULLONG_MAX; -+ else -+ decoder->size = strtoull(buf, NULL, 0); -+ -+ switch (port->type) { -+ case CXL_PORT_SWITCH: -+ case CXL_PORT_ENDPOINT: -+ decoder->pmem_capable = true; -+ decoder->volatile_capable = true; -+ decoder->mem_capable = true; -+ decoder->accelmem_capable = true; -+ sprintf(path, "%s/locked", cxldecoder_base); -+ if (sysfs_read_attr(ctx, path, buf) == 0) -+ decoder->locked = !!strtoul(buf, NULL, 0); -+ sprintf(path, "%s/target_type", cxldecoder_base); -+ if (sysfs_read_attr(ctx, path, buf) == 0) { -+ if (strcmp(buf, "accelerator") == 0) -+ decoder->target_type = -+ CXL_DECODER_TTYPE_ACCELERATOR; -+ if (strcmp(buf, "expander") == 0) -+ decoder->target_type = -+ CXL_DECODER_TTYPE_EXPANDER; -+ } -+ break; -+ case CXL_PORT_ROOT: { -+ struct cxl_decoder_flag { -+ char *name; -+ bool *flag; -+ } flags[] = { -+ { "cap_type2", &decoder->accelmem_capable }, -+ { "cap_type3", &decoder->mem_capable }, -+ { "cap_ram", &decoder->volatile_capable }, -+ { "cap_pmem", &decoder->pmem_capable }, -+ { "locked", &decoder->locked }, -+ }; -+ -+ for (i = 0; i < ARRAY_SIZE(flags); i++) { -+ struct cxl_decoder_flag *flag = &flags[i]; -+ -+ sprintf(path, "%s/%s", cxldecoder_base, flag->name); -+ if (sysfs_read_attr(ctx, path, buf) == 0) -+ *(flag->flag) = !!strtoul(buf, NULL, 0); -+ } -+ break; -+ } -+ } -+ -+ cxl_decoder_foreach(port, decoder_dup) -+ if (decoder_dup->id == decoder->id) { -+ free_decoder(decoder, NULL); -+ return decoder_dup; -+ } -+ -+ list_add(&port->decoders, &decoder->list); -+ -+ return decoder; -+err: -+ free(decoder->dev_path); -+ free(decoder->dev_buf); -+ free(decoder); -+ free(path); -+ return NULL; -+} -+ -+static void cxl_decoders_init(struct cxl_port *port) -+{ -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ char *decoder_fmt; -+ -+ if (port->decoders_init) -+ return; -+ -+ if (asprintf(&decoder_fmt, "decoder%d.", cxl_port_get_id(port)) < 0) { -+ err(ctx, "%s: failed to add decoder(s)\n", -+ cxl_port_get_devname(port)); -+ return; -+ } -+ -+ port->decoders_init = 1; -+ -+ sysfs_device_parse(ctx, port->dev_path, decoder_fmt, port, -+ add_cxl_decoder); -+ -+ free(decoder_fmt); -+} -+ -+CXL_EXPORT struct cxl_decoder *cxl_decoder_get_first(struct cxl_port *port) -+{ -+ cxl_decoders_init(port); -+ -+ return list_top(&port->decoders, struct cxl_decoder, list); -+} -+ -+CXL_EXPORT struct cxl_decoder *cxl_decoder_get_next(struct cxl_decoder *decoder) -+{ -+ struct cxl_port *port = decoder->port; -+ -+ return list_next(&port->decoders, decoder, list); -+} -+ -+CXL_EXPORT struct cxl_ctx *cxl_decoder_get_ctx(struct cxl_decoder *decoder) -+{ -+ return decoder->ctx; -+} -+ -+CXL_EXPORT int cxl_decoder_get_id(struct cxl_decoder *decoder) -+{ -+ return decoder->id; -+} -+ -+CXL_EXPORT struct cxl_port *cxl_decoder_get_port(struct cxl_decoder *decoder) -+{ -+ return decoder->port; -+} -+ -+CXL_EXPORT unsigned long long cxl_decoder_get_resource(struct cxl_decoder *decoder) -+{ -+ return decoder->start; -+} -+ -+CXL_EXPORT unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder) -+{ -+ return decoder->size; -+} -+ -+CXL_EXPORT enum cxl_decoder_target_type -+cxl_decoder_get_target_type(struct cxl_decoder *decoder) -+{ -+ return decoder->target_type; -+} -+ -+CXL_EXPORT bool cxl_decoder_is_pmem_capable(struct cxl_decoder *decoder) -+{ -+ return decoder->pmem_capable; -+} -+ -+CXL_EXPORT bool cxl_decoder_is_volatile_capable(struct cxl_decoder *decoder) -+{ -+ return decoder->volatile_capable; -+} -+ -+CXL_EXPORT bool cxl_decoder_is_mem_capable(struct cxl_decoder *decoder) -+{ -+ return decoder->mem_capable; -+} -+ -+CXL_EXPORT bool cxl_decoder_is_accelmem_capable(struct cxl_decoder *decoder) -+{ -+ return decoder->accelmem_capable; -+} -+ -+CXL_EXPORT bool cxl_decoder_is_locked(struct cxl_decoder *decoder) -+{ -+ return decoder->locked; -+} -+ -+CXL_EXPORT const char *cxl_decoder_get_devname(struct cxl_decoder *decoder) -+{ -+ return devpath_to_devname(decoder->dev_path); -+} -+ - static void *add_cxl_port(void *parent, int id, const char *cxlport_base) - { - const char *devname = devpath_to_devname(cxlport_base); -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index f235e99..22babb7 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -117,4 +117,18 @@ global: - cxl_memdev_get_bus; - cxl_memdev_disable_invalidate; - cxl_memdev_enable; -+ cxl_decoder_get_first; -+ cxl_decoder_get_next; -+ cxl_decoder_get_ctx; -+ cxl_decoder_get_id; -+ cxl_decoder_get_port; -+ cxl_decoder_get_resource; -+ cxl_decoder_get_size; -+ cxl_decoder_get_devname; -+ cxl_decoder_get_target_type; -+ cxl_decoder_is_pmem_capable; -+ cxl_decoder_is_volatile_capable; -+ cxl_decoder_is_mem_capable; -+ cxl_decoder_is_accelmem_capable; -+ cxl_decoder_is_locked; - } LIBCXL_1; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index c00bb36..1743a24 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -23,7 +23,7 @@ struct cxl_memdev { - int numa_node; - void *dev_buf; - size_t buf_len; -- char *host; -+ char *host_path; - char *dev_path; - char *firmware_version; - struct cxl_ctx *ctx; -@@ -52,6 +52,7 @@ struct cxl_port { - char *uport; - int ports_init; - int endpoints_init; -+ int decoders_init; - struct cxl_ctx *ctx; - struct cxl_bus *bus; - enum cxl_port_type type; -@@ -60,6 +61,7 @@ struct cxl_port { - struct list_node list; - struct list_head child_ports; - struct list_head endpoints; -+ struct list_head decoders; - }; - - struct cxl_bus { -@@ -71,6 +73,33 @@ struct cxl_endpoint { - struct cxl_memdev *memdev; - }; - -+struct cxl_target { -+ struct list_node list; -+ struct cxl_decoder *decoder; -+ char *dev_path; -+ int id, position; -+}; -+ -+struct cxl_decoder { -+ struct cxl_port *port; -+ struct list_node list; -+ struct cxl_ctx *ctx; -+ u64 start; -+ u64 size; -+ void *dev_buf; -+ size_t buf_len; -+ char *dev_path; -+ int nr_targets; -+ int id; -+ bool pmem_capable; -+ bool volatile_capable; -+ bool mem_capable; -+ bool accelmem_capable; -+ bool locked; -+ enum cxl_decoder_target_type target_type; -+ struct list_head targets; -+}; -+ - enum cxl_cmd_query_status { - CXL_CMD_QUERY_NOT_RUN = 0, - CXL_CMD_QUERY_OK, -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 53f68dd..439ed93 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -98,6 +98,34 @@ bool cxl_port_hosts_memdev(struct cxl_port *port, struct cxl_memdev *memdev); - for (port = cxl_port_get_first(parent); port != NULL; \ - port = cxl_port_get_next(port)) - -+struct cxl_decoder; -+struct cxl_decoder *cxl_decoder_get_first(struct cxl_port *port); -+struct cxl_decoder *cxl_decoder_get_next(struct cxl_decoder *decoder); -+unsigned long long cxl_decoder_get_resource(struct cxl_decoder *decoder); -+unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder); -+const char *cxl_decoder_get_devname(struct cxl_decoder *decoder); -+struct cxl_ctx *cxl_decoder_get_ctx(struct cxl_decoder *decoder); -+int cxl_decoder_get_id(struct cxl_decoder *decoder); -+struct cxl_port *cxl_decoder_get_port(struct cxl_decoder *decoder); -+ -+enum cxl_decoder_target_type { -+ CXL_DECODER_TTYPE_UNKNOWN, -+ CXL_DECODER_TTYPE_EXPANDER, -+ CXL_DECODER_TTYPE_ACCELERATOR, -+}; -+ -+enum cxl_decoder_target_type -+cxl_decoder_get_target_type(struct cxl_decoder *decoder); -+bool cxl_decoder_is_pmem_capable(struct cxl_decoder *decoder); -+bool cxl_decoder_is_volatile_capable(struct cxl_decoder *decoder); -+bool cxl_decoder_is_mem_capable(struct cxl_decoder *decoder); -+bool cxl_decoder_is_accelmem_capable(struct cxl_decoder *decoder); -+bool cxl_decoder_is_locked(struct cxl_decoder *decoder); -+ -+#define cxl_decoder_foreach(port, decoder) \ -+ for (decoder = cxl_decoder_get_first(port); decoder != NULL; \ -+ decoder = cxl_decoder_get_next(decoder)) -+ - struct cxl_endpoint; - struct cxl_endpoint *cxl_endpoint_get_first(struct cxl_port *parent); - struct cxl_endpoint *cxl_endpoint_get_next(struct cxl_endpoint *endpoint); -diff --git a/cxl/list.c b/cxl/list.c -index b15e01c..d70192a 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -36,6 +36,11 @@ static const struct option options[] = { - "filter by CXL endpoint device name(s)"), - OPT_BOOLEAN('E', "endpoints", ¶m.endpoints, - "include CXL endpoint info"), -+ OPT_STRING('d', "decoder", ¶m.decoder_filter, -+ "decoder device name", -+ "filter by CXL decoder device name(s) / class"), -+ OPT_BOOLEAN('D', "decoders", ¶m.decoders, -+ "include CXL decoder info"), - OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"), - OPT_BOOLEAN('u', "human", ¶m.human, - "use human friendly number formats "), -@@ -50,7 +55,7 @@ static const struct option options[] = { - static int num_list_flags(void) - { - return !!param.memdevs + !!param.buses + !!param.ports + -- !!param.endpoints; -+ !!param.endpoints + !!param.decoders; - } - - int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) -@@ -82,6 +87,8 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - param.ports = true; - if (param.endpoint_filter) - param.endpoints = true; -+ if (param.decoder_filter) -+ param.decoders = true; - if (num_list_flags() == 0) { - /* - * TODO: We likely want to list regions by default if -diff --git a/util/json.h b/util/json.h -index 061f0d4..e026df1 100644 ---- a/util/json.h -+++ b/util/json.h -@@ -18,6 +18,7 @@ enum util_json_flags { - UTIL_JSON_FIRMWARE = (1 << 8), - UTIL_JSON_DAX_MAPPINGS = (1 << 9), - UTIL_JSON_HEALTH = (1 << 10), -+ UTIL_JSON_TARGETS = (1 << 11), - }; - - void util_display_json_array(FILE *f_out, struct json_object *jarray, --- -2.27.0 - diff --git a/SOURCES/0117-cxl-list-Extend-decoder-objects-with-target-informat.patch b/SOURCES/0117-cxl-list-Extend-decoder-objects-with-target-informat.patch deleted file mode 100644 index 2490b20..0000000 --- a/SOURCES/0117-cxl-list-Extend-decoder-objects-with-target-informat.patch +++ /dev/null @@ -1,537 +0,0 @@ -From 1279d1989ef77085d214a193c1458b624039c612 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:54:34 -0800 -Subject: [PATCH 117/217] cxl/list: Extend decoder objects with target - information - -A target combines information about a dport along with its position in the -intereleave order. With targets enumerated decoders can also be filtered be -memory devices by seeing which decoders have a dport in the memory-device's -ancestry. - -$ cxl list -D -d 3.1 -T -u -{ - "decoder":"decoder3.1", - "resource":"0x8030000000", - "size":"512.00 MiB (536.87 MB)", - "volatile_capable":true, - "nr_targets":2, - "targets":[ - { - "target":"cxl_host_bridge.1", - "position":1, - "id":"0x1" - }, - { - "target":"cxl_host_bridge.0", - "position":0, - "id":"0" - } - ] -} - -Link: https://lore.kernel.org/r/164298567435.3021641.3771899644901785666.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .clang-format | 1 + - Documentation/cxl/cxl-list.txt | 8 ++- - Documentation/cxl/lib/libcxl.txt | 58 ++++++++++++++++ - cxl/filter.c | 25 +++++++ - cxl/filter.h | 1 + - cxl/json.c | 46 +++++++++++++ - cxl/lib/libcxl.c | 115 +++++++++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 10 +++ - cxl/libcxl.h | 19 +++++ - cxl/list.c | 2 + - 10 files changed, 283 insertions(+), 2 deletions(-) - -diff --git a/.clang-format b/.clang-format -index 16e28ac..47fb657 100644 ---- a/.clang-format -+++ b/.clang-format -@@ -81,6 +81,7 @@ ForEachMacros: - - 'cxl_bus_foreach' - - 'cxl_port_foreach' - - 'cxl_decoder_foreach' -+ - 'cxl_target_foreach' - - 'cxl_endpoint_foreach' - - 'daxctl_dev_foreach' - - 'daxctl_mapping_foreach' -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 84872b9..20ff2cb 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -44,8 +44,8 @@ would only list objects that are beneath port10 AND map mem0, mem1, OR - mem2. - - Given that many topology queries seek to answer questions relative to a --given memdev, buses, ports, and endpoints can be filtered by one or more --memdevs. For example: -+given memdev, buses, ports, endpoints, and decoders can be filtered by -+one or more memdevs. For example: - ---- - # cxl list -P -p switch,endpoint -m mem0 - [ -@@ -270,6 +270,10 @@ OPTIONS - "decoder.". The possible decoder type names are - "root", "switch", or "endpoint", similar to the port filter syntax. - -+-T:: -+--targets:: -+ Extend decoder listings with downstream port target information. -+ - --debug:: - If the cxl tool was built with debug enabled, turn on debug - messages. -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 73af3d0..bd92fef 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -300,6 +300,7 @@ device-local-physical-address). - struct cxl_decoder *cxl_decoder_get_first(struct cxl_port *port); - struct cxl_decoder *cxl_decoder_get_next(struct cxl_decoder *decoder); - struct cxl_ctx *cxl_decoder_get_ctx(struct cxl_decoder *decoder); -+struct cxl_decoder *cxl_target_get_decoder(struct cxl_target *target); - - #define cxl_decoder_foreach(port, decoder) \ - for (decoder = cxl_decoder_get_first(port); decoder != NULL; \ -@@ -314,6 +315,7 @@ unsigned long long cxl_decoder_get_resource(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder); - const char *cxl_decoder_get_devname(struct cxl_decoder *decoder); - int cxl_decoder_get_id(struct cxl_decoder *decoder); -+int cxl_decoder_get_nr_targets(struct cxl_decoder *decoder); - - enum cxl_decoder_target_type { - CXL_DECODER_TTYPE_UNKNOWN, -@@ -352,6 +354,62 @@ Platform firmware may setup the CXL decode hierarchy before the OS - boots, and may additionally require that the OS not change the decode - settings. This property is indicated by the cxl_decoder_is_locked() API. - -+==== TARGETS -+A root or switch level decoder takes an SPA (system-physical-address) as -+input and routes it to a downstream port. Which downstream port depends -+on the downstream port's position in the interleave. A 'struct -+cxl_target' object represents the properties of a given downstream port -+relative to its interleave configuration. -+ -+===== TARGET: Enumeration -+---- -+struct cxl_target *cxl_decoder_get_target_by_memdev(struct cxl_decoder *decoder, -+ struct cxl_memdev *memdev); -+struct cxl_target * -+cxl_decoder_get_target_by_position(struct cxl_decoder *decoder, int position); -+struct cxl_target *cxl_target_get_first(struct cxl_decoder *decoder); -+struct cxl_target *cxl_target_get_next(struct cxl_target *target); -+ -+#define cxl_target_foreach(decoder, target) \ -+ for (target = cxl_target_get_first(decoder); target != NULL; \ -+ target = cxl_target_get_next(target)) -+---- -+Target objects can only be enumerated if the decoder has been -+configured, for switch decoders. For root decoders they are always -+available since the root decoder target mapping is static. The -+cxl_decoder_get_target_by_memdev() helper walks the topology to validate -+if the given memory device is capable of receiving cycles from this -+upstream decoder. It does not validate if the memory device is currently -+configured to participate in that decode. -+ -+===== TARGET: Attributes -+---- -+int cxl_target_get_position(struct cxl_target *target); -+unsigned long cxl_target_get_id(struct cxl_target *target); -+const char *cxl_target_get_devname(struct cxl_target *target); -+bool cxl_target_maps_memdev(struct cxl_target *target, -+ struct cxl_memdev *memdev); -+---- -+The position of a decoder along with the interleave granularity dictate -+which address in the decoder's resource range map to which port. -+ -+The target id is an identifier that the CXL port uses to reference this -+downstream port. For CXL / PCIe downstream switch ports the id is -+defined by the PCIe Link Capability Port Number field. For root decoders -+the id is specified by platform firmware specific mechanism. For -+ACPI.CXL defined root ports the id comes from the CEDT.CHBS / ACPI0016 -+_UID. -+ -+The device name of a target is the name of the host device for the -+downstream port. For CXL / PCIe downstream ports the devname is -+downstream switch port PCI device. For CXL root ports the devname is a -+platform firmware object for the host bridge like a ACPI0016 device -+instance. -+ -+The cxl_target_maps_memdev() helper is the companion of -+cxl_decoder_get_target_by_memdev() to determine which downstream ports / -+targets are capable of mapping which memdevs. -+ - include::../../copyright.txt[] - - SEE ALSO -diff --git a/cxl/filter.c b/cxl/filter.c -index dc052f6..05ede91 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -421,6 +421,26 @@ static struct cxl_decoder *util_cxl_decoder_filter(struct cxl_decoder *decoder, - return NULL; - } - -+static struct cxl_decoder * -+util_cxl_decoder_filter_by_memdev(struct cxl_decoder *decoder, -+ const char *ident, const char *serial) -+{ -+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ struct cxl_memdev *memdev; -+ -+ if (!ident && !serial) -+ return decoder; -+ -+ cxl_memdev_foreach(ctx, memdev) { -+ if (!util_cxl_memdev_filter(memdev, ident, serial)) -+ continue; -+ if (cxl_decoder_get_target_by_memdev(decoder, memdev)) -+ return decoder; -+ } -+ -+ return NULL; -+} -+ - static unsigned long params_to_flags(struct cxl_filter_params *param) - { - unsigned long flags = 0; -@@ -431,6 +451,8 @@ static unsigned long params_to_flags(struct cxl_filter_params *param) - flags |= UTIL_JSON_HUMAN; - if (param->health) - flags |= UTIL_JSON_HEALTH; -+ if (param->targets) -+ flags |= UTIL_JSON_TARGETS; - return flags; - } - -@@ -521,6 +543,9 @@ static void walk_decoders(struct cxl_port *port, struct cxl_filter_params *p, - if (!util_cxl_decoder_filter_by_port(decoder, p->port_filter, - pf_mode(p))) - continue; -+ if (!util_cxl_decoder_filter_by_memdev( -+ decoder, p->memdev_filter, p->serial_filter)) -+ continue; - if (!p->idle && cxl_decoder_get_size(decoder) == 0) - continue; - jdecoder = util_cxl_decoder_to_json(decoder, flags); -diff --git a/cxl/filter.h b/cxl/filter.h -index 5d7bf45..6fd469f 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -16,6 +16,7 @@ struct cxl_filter_params { - bool single; - bool endpoints; - bool decoders; -+ bool targets; - bool memdevs; - bool ports; - bool buses; -diff --git a/cxl/json.c b/cxl/json.c -index 548bc52..3a37909 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -268,6 +268,8 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - const char *devname = cxl_decoder_get_devname(decoder); - struct cxl_port *port = cxl_decoder_get_port(decoder); - struct json_object *jdecoder, *jobj; -+ struct json_object *jtargets; -+ struct cxl_target *target; - u64 val; - - jdecoder = json_object_new_object(); -@@ -321,7 +323,51 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - jobj); - } - -+ /* Endpoints don't have targets, they *are* targets */ -+ if (cxl_port_is_endpoint(port)) -+ return jdecoder; -+ -+ val = cxl_decoder_get_nr_targets(decoder); -+ jobj = json_object_new_int(val); -+ if (jobj) -+ json_object_object_add(jdecoder, "nr_targets", jobj); -+ -+ if (!(flags & UTIL_JSON_TARGETS) || -+ !cxl_decoder_get_nr_targets(decoder)) -+ return jdecoder; -+ -+ jtargets = json_object_new_array(); -+ if (!jtargets) -+ return jdecoder; -+ -+ cxl_target_foreach(decoder, target) { -+ struct json_object *jtarget = json_object_new_object(); -+ -+ if (!jtarget) -+ continue; -+ -+ devname = cxl_target_get_devname(target); -+ jobj = json_object_new_string(devname); -+ if (jobj) -+ json_object_object_add(jtarget, "target", jobj); -+ -+ val = cxl_target_get_position(target); -+ jobj = json_object_new_int(val); -+ if (jobj) -+ json_object_object_add(jtarget, "position", jobj); -+ -+ val = cxl_target_get_id(target); -+ jobj = util_json_object_hex(val, flags); -+ if (jobj) -+ json_object_object_add(jtarget, "id", jobj); -+ -+ json_object_array_add(jtargets, jtarget); -+ } -+ -+ json_object_object_add(jdecoder, "targets", jtargets); -+ - return jdecoder; -+ - } - - static struct json_object *__util_cxl_port_to_json(struct cxl_port *port, -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 5e30923..877f42c 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -67,10 +67,22 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head) - free(memdev); - } - -+static void free_target(struct cxl_target *target, struct list_head *head) -+{ -+ if (head) -+ list_del_from(head, &target->list); -+ free(target->dev_path); -+ free(target); -+} -+ - static void free_decoder(struct cxl_decoder *decoder, struct list_head *head) - { -+ struct cxl_target *target, *_t; -+ - if (head) - list_del_from(head, &decoder->list); -+ list_for_each_safe(&decoder->targets, target, _t, list) -+ free_target(target, &decoder->targets); - free(decoder->dev_buf); - free(decoder->dev_path); - free(decoder); -@@ -856,6 +868,7 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - struct cxl_port *port = parent; - struct cxl_ctx *ctx = cxl_port_get_ctx(port); - char buf[SYSFS_ATTR_SIZE]; -+ char *target_id, *save; - size_t i; - - dbg(ctx, "%s: base: \'%s\'\n", devname, cxldecoder_base); -@@ -870,6 +883,7 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - decoder->id = id; - decoder->ctx = ctx; - decoder->port = port; -+ list_head_init(&decoder->targets); - - decoder->dev_path = strdup(cxldecoder_base); - if (!decoder->dev_path) -@@ -935,6 +949,36 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - } - } - -+ sprintf(path, "%s/target_list", cxldecoder_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ buf[0] = '\0'; -+ -+ for (i = 0, target_id = strtok_r(buf, ",", &save); target_id; -+ target_id = strtok_r(NULL, ",", &save), i++) { -+ int did = strtoul(target_id, NULL, 0); -+ struct cxl_target *target = calloc(1, sizeof(*target)); -+ -+ if (!target) -+ break; -+ -+ target->id = did; -+ target->position = i; -+ target->decoder = decoder; -+ sprintf(port->dev_buf, "%s/dport%d", port->dev_path, did); -+ target->dev_path = realpath(port->dev_buf, NULL); -+ if (!target->dev_path) { -+ free(target); -+ break; -+ } -+ dbg(ctx, "%s: target%ld %s\n", devname, i, target->dev_path); -+ list_add(&decoder->targets, &target->list); -+ } -+ -+ if (target_id) -+ err(ctx, "%s: failed to parse target%ld\n", -+ devpath_to_devname(cxldecoder_base), i); -+ decoder->nr_targets = i; -+ - cxl_decoder_foreach(port, decoder_dup) - if (decoder_dup->id == decoder->id) { - free_decoder(decoder, NULL); -@@ -1044,11 +1088,82 @@ CXL_EXPORT bool cxl_decoder_is_locked(struct cxl_decoder *decoder) - return decoder->locked; - } - -+CXL_EXPORT int cxl_decoder_get_nr_targets(struct cxl_decoder *decoder) -+{ -+ return decoder->nr_targets; -+} -+ - CXL_EXPORT const char *cxl_decoder_get_devname(struct cxl_decoder *decoder) - { - return devpath_to_devname(decoder->dev_path); - } - -+CXL_EXPORT struct cxl_target *cxl_target_get_first(struct cxl_decoder *decoder) -+{ -+ return list_top(&decoder->targets, struct cxl_target, list); -+} -+ -+CXL_EXPORT struct cxl_decoder *cxl_target_get_decoder(struct cxl_target *target) -+{ -+ return target->decoder; -+} -+ -+CXL_EXPORT struct cxl_target *cxl_target_get_next(struct cxl_target *target) -+{ -+ struct cxl_decoder *decoder = cxl_target_get_decoder(target); -+ -+ return list_next(&decoder->targets, target, list); -+} -+ -+CXL_EXPORT const char *cxl_target_get_devname(struct cxl_target *target) -+{ -+ return devpath_to_devname(target->dev_path); -+} -+ -+CXL_EXPORT unsigned long cxl_target_get_id(struct cxl_target *target) -+{ -+ return target->id; -+} -+ -+CXL_EXPORT int cxl_target_get_position(struct cxl_target *target) -+{ -+ return target->position; -+} -+ -+CXL_EXPORT bool cxl_target_maps_memdev(struct cxl_target *target, -+ struct cxl_memdev *memdev) -+{ -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ -+ dbg(ctx, "memdev: %s target: %s\n", memdev->host_path, -+ target->dev_path); -+ -+ return !!strstr(memdev->host_path, target->dev_path); -+} -+ -+CXL_EXPORT struct cxl_target * -+cxl_decoder_get_target_by_memdev(struct cxl_decoder *decoder, -+ struct cxl_memdev *memdev) -+{ -+ struct cxl_target *target; -+ -+ cxl_target_foreach(decoder, target) -+ if (cxl_target_maps_memdev(target, memdev)) -+ return target; -+ return NULL; -+} -+ -+CXL_EXPORT struct cxl_target * -+cxl_decoder_get_target_by_position(struct cxl_decoder *decoder, int position) -+{ -+ struct cxl_target *target; -+ -+ cxl_target_foreach(decoder, target) -+ if (target->position == position) -+ return target; -+ return NULL; -+} -+ - static void *add_cxl_port(void *parent, int id, const char *cxlport_base) - { - const char *devname = devpath_to_devname(cxlport_base); -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 22babb7..cb33180 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -125,10 +125,20 @@ global: - cxl_decoder_get_resource; - cxl_decoder_get_size; - cxl_decoder_get_devname; -+ cxl_decoder_get_target_by_memdev; -+ cxl_decoder_get_target_by_position; -+ cxl_decoder_get_nr_targets; - cxl_decoder_get_target_type; - cxl_decoder_is_pmem_capable; - cxl_decoder_is_volatile_capable; - cxl_decoder_is_mem_capable; - cxl_decoder_is_accelmem_capable; - cxl_decoder_is_locked; -+ cxl_target_get_first; -+ cxl_target_get_next; -+ cxl_target_get_decoder; -+ cxl_target_get_position; -+ cxl_target_get_id; -+ cxl_target_get_devname; -+ cxl_target_maps_memdev; - } LIBCXL_1; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 439ed93..abda0e5 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -104,6 +104,11 @@ struct cxl_decoder *cxl_decoder_get_next(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_resource(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder); - const char *cxl_decoder_get_devname(struct cxl_decoder *decoder); -+struct cxl_target *cxl_decoder_get_target_by_memdev(struct cxl_decoder *decoder, -+ struct cxl_memdev *memdev); -+struct cxl_target * -+cxl_decoder_get_target_by_position(struct cxl_decoder *decoder, int position); -+int cxl_decoder_get_nr_targets(struct cxl_decoder *decoder); - struct cxl_ctx *cxl_decoder_get_ctx(struct cxl_decoder *decoder); - int cxl_decoder_get_id(struct cxl_decoder *decoder); - struct cxl_port *cxl_decoder_get_port(struct cxl_decoder *decoder); -@@ -126,6 +131,20 @@ bool cxl_decoder_is_locked(struct cxl_decoder *decoder); - for (decoder = cxl_decoder_get_first(port); decoder != NULL; \ - decoder = cxl_decoder_get_next(decoder)) - -+struct cxl_target; -+struct cxl_target *cxl_target_get_first(struct cxl_decoder *decoder); -+struct cxl_target *cxl_target_get_next(struct cxl_target *target); -+struct cxl_decoder *cxl_target_get_decoder(struct cxl_target *target); -+int cxl_target_get_position(struct cxl_target *target); -+unsigned long cxl_target_get_id(struct cxl_target *target); -+const char *cxl_target_get_devname(struct cxl_target *target); -+bool cxl_target_maps_memdev(struct cxl_target *target, -+ struct cxl_memdev *memdev); -+ -+#define cxl_target_foreach(decoder, target) \ -+ for (target = cxl_target_get_first(decoder); target != NULL; \ -+ target = cxl_target_get_next(target)) -+ - struct cxl_endpoint; - struct cxl_endpoint *cxl_endpoint_get_first(struct cxl_port *parent); - struct cxl_endpoint *cxl_endpoint_get_next(struct cxl_endpoint *endpoint); -diff --git a/cxl/list.c b/cxl/list.c -index d70192a..27c963a 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -41,6 +41,8 @@ static const struct option options[] = { - "filter by CXL decoder device name(s) / class"), - OPT_BOOLEAN('D', "decoders", ¶m.decoders, - "include CXL decoder info"), -+ OPT_BOOLEAN('T', "targets", ¶m.targets, -+ "include CXL target data with decoders"), - OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"), - OPT_BOOLEAN('u', "human", ¶m.human, - "use human friendly number formats "), --- -2.27.0 - diff --git a/SOURCES/0118-cxl-list-Use-physical_node-for-root-port-attachment-.patch b/SOURCES/0118-cxl-list-Use-physical_node-for-root-port-attachment-.patch deleted file mode 100644 index c216a82..0000000 --- a/SOURCES/0118-cxl-list-Use-physical_node-for-root-port-attachment-.patch +++ /dev/null @@ -1,156 +0,0 @@ -From 5fb1b8a1630115f3aa3cd6bb7bc9ba5122867f66 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:54:39 -0800 -Subject: [PATCH 118/217] cxl/list: Use 'physical_node' for root port - attachment detection - -Platform firmware objects like ACPI0016 link from /sys/bus/acpi to -/sys/bus/pci via a 'physical_node' attribute. Consider that link when -attempting to link memdevs to root ports. - -Emit it in the the target listing as the 'alias' for the listed target -device. - -Link: https://lore.kernel.org/r/164298567943.3021641.12696733268157328279.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/lib/libcxl.txt | 6 ++++++ - cxl/json.c | 8 ++++++++ - cxl/lib/libcxl.c | 16 +++++++++++++++- - cxl/lib/libcxl.sym | 1 + - cxl/lib/private.h | 1 + - cxl/libcxl.h | 1 + - 6 files changed, 32 insertions(+), 1 deletion(-) - -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index bd92fef..a68a58b 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -389,6 +389,7 @@ unsigned long cxl_target_get_id(struct cxl_target *target); - const char *cxl_target_get_devname(struct cxl_target *target); - bool cxl_target_maps_memdev(struct cxl_target *target, - struct cxl_memdev *memdev); -+const char *cxl_target_get_physical_node(struct cxl_target *target); - ---- - The position of a decoder along with the interleave granularity dictate - which address in the decoder's resource range map to which port. -@@ -410,6 +411,11 @@ The cxl_target_maps_memdev() helper is the companion of - cxl_decoder_get_target_by_memdev() to determine which downstream ports / - targets are capable of mapping which memdevs. - -+Some platform firmware implementations define an alias / companion -+device to represent the root of a PCI device hierarchy. The -+cxl_target_get_physical_node() helper returns the device name of that -+companion object in the PCI hierarchy. -+ - include::../../copyright.txt[] - - SEE ALSO -diff --git a/cxl/json.c b/cxl/json.c -index 3a37909..d81aed8 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -342,6 +342,7 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - - cxl_target_foreach(decoder, target) { - struct json_object *jtarget = json_object_new_object(); -+ const char *phys_node; - - if (!jtarget) - continue; -@@ -351,6 +352,13 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - if (jobj) - json_object_object_add(jtarget, "target", jobj); - -+ phys_node = cxl_target_get_physical_node(target); -+ if (phys_node) { -+ jobj = json_object_new_string(phys_node); -+ if (jobj) -+ json_object_object_add(jtarget, "alias", jobj); -+ } -+ - val = cxl_target_get_position(target); - jobj = json_object_new_int(val); - if (jobj) -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 877f42c..7bf7949 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -72,6 +72,7 @@ static void free_target(struct cxl_target *target, struct list_head *head) - if (head) - list_del_from(head, &target->list); - free(target->dev_path); -+ free(target->phys_path); - free(target); - } - -@@ -970,7 +971,11 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - free(target); - break; - } -- dbg(ctx, "%s: target%ld %s\n", devname, i, target->dev_path); -+ sprintf(port->dev_buf, "%s/dport%d/physical_node", port->dev_path, did); -+ target->phys_path = realpath(port->dev_buf, NULL); -+ dbg(ctx, "%s: target%ld %s phys_path: %s\n", devname, i, -+ target->dev_path, -+ target->phys_path ? target->phys_path : "none"); - list_add(&decoder->targets, &target->list); - } - -@@ -1138,9 +1143,18 @@ CXL_EXPORT bool cxl_target_maps_memdev(struct cxl_target *target, - dbg(ctx, "memdev: %s target: %s\n", memdev->host_path, - target->dev_path); - -+ if (target->phys_path) -+ return !!strstr(memdev->host_path, target->phys_path); - return !!strstr(memdev->host_path, target->dev_path); - } - -+CXL_EXPORT const char *cxl_target_get_physical_node(struct cxl_target *target) -+{ -+ if (!target->phys_path) -+ return NULL; -+ return devpath_to_devname(target->phys_path); -+} -+ - CXL_EXPORT struct cxl_target * - cxl_decoder_get_target_by_memdev(struct cxl_decoder *decoder, - struct cxl_memdev *memdev) -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index cb33180..ce01298 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -141,4 +141,5 @@ global: - cxl_target_get_id; - cxl_target_get_devname; - cxl_target_maps_memdev; -+ cxl_target_get_physical_node; - } LIBCXL_1; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 1743a24..7e7742d 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -77,6 +77,7 @@ struct cxl_target { - struct list_node list; - struct cxl_decoder *decoder; - char *dev_path; -+ char *phys_path; - int id, position; - }; - -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index abda0e5..0e484cc 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -140,6 +140,7 @@ unsigned long cxl_target_get_id(struct cxl_target *target); - const char *cxl_target_get_devname(struct cxl_target *target); - bool cxl_target_maps_memdev(struct cxl_target *target, - struct cxl_memdev *memdev); -+const char *cxl_target_get_physical_node(struct cxl_target *target); - - #define cxl_target_foreach(decoder, target) \ - for (target = cxl_target_get_first(decoder); target != NULL; \ --- -2.27.0 - diff --git a/SOURCES/0119-cxl-list-Reuse-the-target-option-for-ports.patch b/SOURCES/0119-cxl-list-Reuse-the-target-option-for-ports.patch deleted file mode 100644 index c32c697..0000000 --- a/SOURCES/0119-cxl-list-Reuse-the-target-option-for-ports.patch +++ /dev/null @@ -1,457 +0,0 @@ -From d87cee2dd4756f7e067bdadc78a0632dd666cc64 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:54:44 -0800 -Subject: [PATCH 119/217] cxl/list: Reuse the --target option for ports - -It is useful to be able to dump the dport-id to host-device-name. Rather -than introduce a new option, just interpret --target as "list dports" for -port objects. - -$ cxl list -BTu -b ACPI.CXL -{ - "bus":"root0", - "provider":"ACPI.CXL", - "nr_dports":1, - "dports":[ - { - "dport":"ACPI0016:00", - "alias":"pci0000:34", - "id":"0" - } - ] -} - -Link: https://lore.kernel.org/r/164298568481.3021641.4632086646702812643.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .clang-format | 1 + - Documentation/cxl/cxl-list.txt | 18 ++++- - Documentation/cxl/lib/libcxl.txt | 27 ++++++++ - cxl/json.c | 56 +++++++++++++++- - cxl/lib/libcxl.c | 109 ++++++++++++++++++++++++++++++- - cxl/lib/libcxl.sym | 7 ++ - cxl/lib/private.h | 13 ++++ - cxl/libcxl.h | 12 ++++ - cxl/list.c | 2 +- - 9 files changed, 240 insertions(+), 5 deletions(-) - -diff --git a/.clang-format b/.clang-format -index 47fb657..c753487 100644 ---- a/.clang-format -+++ b/.clang-format -@@ -82,6 +82,7 @@ ForEachMacros: - - 'cxl_port_foreach' - - 'cxl_decoder_foreach' - - 'cxl_target_foreach' -+ - 'cxl_dport_foreach' - - 'cxl_endpoint_foreach' - - 'daxctl_dev_foreach' - - 'daxctl_mapping_foreach' -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 20ff2cb..e1299d9 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -272,7 +272,23 @@ OPTIONS - - -T:: - --targets:: -- Extend decoder listings with downstream port target information. -+ Extend decoder listings with downstream port target information, and / -+ or port and bus listings with the downstream port information. -+---- -+# cxl list -BTu -b ACPI.CXL -+{ -+ "bus":"root0", -+ "provider":"ACPI.CXL", -+ "nr_dports":1, -+ "dports":[ -+ { -+ "dport":"ACPI0016:00", -+ "alias":"pci0000:34", -+ "id":"0" -+ } -+ ] -+} -+---- - - --debug:: - If the cxl tool was built with debug enabled, turn on debug -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index a68a58b..2e8570d 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -245,6 +245,7 @@ bool cxl_port_is_root(struct cxl_port *port); - bool cxl_port_is_switch(struct cxl_port *port); - bool cxl_port_is_endpoint(struct cxl_port *port); - bool cxl_port_hosts_memdev(struct cxl_port *port, struct cxl_memdev *memdev); -+int cxl_port_get_nr_dports(struct cxl_port *port); - ---- - The port type is communicated via cxl_port_is_(). An 'enabled' port - is one that has succeeded in discovering the CXL component registers in -@@ -256,6 +257,32 @@ of intervening switch ports, and a terminal endpoint port. - cxl_port_hosts_memdev() returns true if the port's host appears in the - memdev host's device topology ancestry. - -+==== DPORTS -+A CXL dport object represents a CXL / PCIe Switch Downstream Port, or a -+CXL / PCIe host bridge. -+ -+===== DPORT: Enumeration -+---- -+struct cxl_dport *cxl_dport_get_first(struct cxl_port *port); -+struct cxl_dport *cxl_dport_get_next(struct cxl_dport *dport); -+ -+#define cxl_dport_foreach(port, dport) \ -+ for (dport = cxl_dport_get_first(port); dport != NULL; \ -+ dport = cxl_dport_get_next(dport)) -+ -+---- -+ -+===== DPORT: Attributes -+---- -+const char *cxl_dport_get_devname(struct cxl_dport *dport); -+const char *cxl_dport_get_physical_node(struct cxl_dport *dport); -+int cxl_dport_get_id(struct cxl_dport *dport); -+---- -+The id of a dport is the hardware idenfifier used by an upstream port to -+reference a downstream port. The physical node of a dport is only -+available for platform firmware defined downstream ports and alias the -+companion object, like a PCI host bridge, in the PCI device hierarchy. -+ - ENDPOINTS - --------- - CXL endpoint objects encapsulate the set of host-managed device-memory -diff --git a/cxl/json.c b/cxl/json.c -index d81aed8..4fb5eec 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -241,6 +241,58 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - return jdev; - } - -+static struct json_object *util_cxl_dports_to_json(struct json_object *jport, -+ struct cxl_port *port, -+ unsigned long flags) -+{ -+ struct json_object *jobj, *jdports; -+ struct cxl_dport *dport; -+ int val; -+ -+ val = cxl_port_get_nr_dports(port); -+ if (!val || !(flags & UTIL_JSON_TARGETS)) -+ return jport; -+ -+ jobj = json_object_new_int(val); -+ if (jobj) -+ json_object_object_add(jport, "nr_dports", jobj); -+ -+ jdports = json_object_new_array(); -+ if (!jdports) -+ return jport; -+ -+ cxl_dport_foreach(port, dport) { -+ struct json_object *jdport; -+ const char *phys_node; -+ -+ jdport = json_object_new_object(); -+ if (!jdport) -+ continue; -+ -+ jobj = json_object_new_string(cxl_dport_get_devname(dport)); -+ if (jobj) -+ json_object_object_add(jdport, "dport", jobj); -+ -+ phys_node = cxl_dport_get_physical_node(dport); -+ if (phys_node) { -+ jobj = json_object_new_string(phys_node); -+ if (jobj) -+ json_object_object_add(jdport, "alias", jobj); -+ } -+ -+ val = cxl_dport_get_id(dport); -+ jobj = util_json_object_hex(val, flags); -+ if (jobj) -+ json_object_object_add(jdport, "id", jobj); -+ -+ json_object_array_add(jdports, jdport); -+ } -+ -+ json_object_object_add(jport, "dports", jdports); -+ -+ return jport; -+} -+ - struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus, - unsigned long flags) - { -@@ -259,7 +311,7 @@ struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus, - if (jobj) - json_object_object_add(jbus, "provider", jobj); - -- return jbus; -+ return util_cxl_dports_to_json(jbus, cxl_bus_get_port(bus), flags); - } - - struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, -@@ -403,7 +455,7 @@ static struct json_object *__util_cxl_port_to_json(struct cxl_port *port, - json_object_object_add(jport, "state", jobj); - } - -- return jport; -+ return util_cxl_dports_to_json(jport, port, flags); - } - - struct json_object *util_cxl_port_to_json(struct cxl_port *port, -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 7bf7949..d7a3f10 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -89,13 +89,24 @@ static void free_decoder(struct cxl_decoder *decoder, struct list_head *head) - free(decoder); - } - -+static void free_dport(struct cxl_dport *dport, struct list_head *head) -+{ -+ if (head) -+ list_del_from(head, &dport->list); -+ free(dport->dev_buf); -+ free(dport->dev_path); -+ free(dport->phys_path); -+ free(dport); -+} -+ - static void free_port(struct cxl_port *port, struct list_head *head); - static void free_endpoint(struct cxl_endpoint *endpoint, struct list_head *head); - static void __free_port(struct cxl_port *port, struct list_head *head) - { -- struct cxl_port *child, *_c; - struct cxl_endpoint *endpoint, *_e; - struct cxl_decoder *decoder, *_d; -+ struct cxl_dport *dport, *_dp; -+ struct cxl_port *child, *_c; - - if (head) - list_del_from(head, &port->list); -@@ -105,6 +116,8 @@ static void __free_port(struct cxl_port *port, struct list_head *head) - free_endpoint(endpoint, &port->endpoints); - list_for_each_safe(&port->decoders, decoder, _d, list) - free_decoder(decoder, &port->decoders); -+ list_for_each_safe(&port->dports, dport, _dp, list) -+ free_dport(dport , &port->dports); - kmod_module_unref(port->module); - free(port->dev_buf); - free(port->dev_path); -@@ -701,6 +714,7 @@ static int cxl_port_init(struct cxl_port *port, struct cxl_port *parent_port, - list_head_init(&port->child_ports); - list_head_init(&port->endpoints); - list_head_init(&port->decoders); -+ list_head_init(&port->dports); - - port->dev_path = strdup(cxlport_base); - if (!port->dev_path) -@@ -1332,6 +1346,99 @@ CXL_EXPORT struct cxl_bus *cxl_port_to_bus(struct cxl_port *port) - return container_of(port, struct cxl_bus, port); - } - -+static void *add_cxl_dport(void *parent, int id, const char *cxldport_base) -+{ -+ const char *devname = devpath_to_devname(cxldport_base); -+ struct cxl_dport *dport, *dport_dup; -+ struct cxl_port *port = parent; -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ -+ dbg(ctx, "%s: base: \'%s\'\n", devname, cxldport_base); -+ -+ dport = calloc(1, sizeof(*dport)); -+ if (!dport) -+ return NULL; -+ -+ dport->id = id; -+ dport->port = port; -+ -+ dport->dev_path = realpath(cxldport_base, NULL); -+ if (!dport->dev_path) -+ goto err; -+ -+ dport->dev_buf = calloc(1, strlen(cxldport_base) + 50); -+ if (!dport->dev_buf) -+ goto err; -+ dport->buf_len = strlen(cxldport_base) + 50; -+ -+ sprintf(dport->dev_buf, "%s/physical_node", cxldport_base); -+ dport->phys_path = realpath(dport->dev_buf, NULL); -+ -+ cxl_dport_foreach(port, dport_dup) -+ if (dport_dup->id == dport->id) { -+ free_dport(dport, NULL); -+ return dport_dup; -+ } -+ -+ port->nr_dports++; -+ list_add(&port->dports, &dport->list); -+ return dport; -+ -+err: -+ free_dport(dport, NULL); -+ return NULL; -+} -+ -+static void cxl_dports_init(struct cxl_port *port) -+{ -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ -+ if (port->dports_init) -+ return; -+ -+ port->dports_init = 1; -+ -+ sysfs_device_parse(ctx, port->dev_path, "dport", port, add_cxl_dport); -+} -+ -+CXL_EXPORT int cxl_port_get_nr_dports(struct cxl_port *port) -+{ -+ if (!port->dports_init) -+ cxl_dports_init(port); -+ return port->nr_dports; -+} -+ -+CXL_EXPORT struct cxl_dport *cxl_dport_get_first(struct cxl_port *port) -+{ -+ cxl_dports_init(port); -+ -+ return list_top(&port->dports, struct cxl_dport, list); -+} -+ -+CXL_EXPORT struct cxl_dport *cxl_dport_get_next(struct cxl_dport *dport) -+{ -+ struct cxl_port *port = dport->port; -+ -+ return list_next(&port->dports, dport, list); -+} -+ -+CXL_EXPORT const char *cxl_dport_get_devname(struct cxl_dport *dport) -+{ -+ return devpath_to_devname(dport->dev_path); -+} -+ -+CXL_EXPORT const char *cxl_dport_get_physical_node(struct cxl_dport *dport) -+{ -+ if (!dport->phys_path) -+ return NULL; -+ return devpath_to_devname(dport->phys_path); -+} -+ -+CXL_EXPORT int cxl_dport_get_id(struct cxl_dport *dport) -+{ -+ return dport->id; -+} -+ - static void *add_cxl_bus(void *parent, int id, const char *cxlbus_base) - { - const char *devname = devpath_to_devname(cxlbus_base); -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index ce01298..0190b13 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -101,6 +101,8 @@ global: - cxl_port_get_host; - cxl_port_get_bus; - cxl_port_hosts_memdev; -+ cxl_port_get_nr_dports; -+ cxl_port_get_next_all; - cxl_endpoint_get_first; - cxl_endpoint_get_next; - cxl_endpoint_get_devname; -@@ -142,4 +144,9 @@ global: - cxl_target_get_devname; - cxl_target_maps_memdev; - cxl_target_get_physical_node; -+ cxl_dport_get_first; -+ cxl_dport_get_next; -+ cxl_dport_get_devname; -+ cxl_dport_get_physical_node; -+ cxl_dport_get_id; - } LIBCXL_1; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 7e7742d..f483c30 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -38,6 +38,16 @@ struct cxl_memdev { - struct cxl_endpoint *endpoint; - }; - -+struct cxl_dport { -+ int id; -+ void *dev_buf; -+ size_t buf_len; -+ char *dev_path; -+ char *phys_path; -+ struct cxl_port *port; -+ struct list_node list; -+}; -+ - enum cxl_port_type { - CXL_PORT_ROOT, - CXL_PORT_SWITCH, -@@ -53,6 +63,8 @@ struct cxl_port { - int ports_init; - int endpoints_init; - int decoders_init; -+ int dports_init; -+ int nr_dports; - struct cxl_ctx *ctx; - struct cxl_bus *bus; - enum cxl_port_type type; -@@ -62,6 +74,7 @@ struct cxl_port { - struct list_head child_ports; - struct list_head endpoints; - struct list_head decoders; -+ struct list_head dports; - }; - - struct cxl_bus { -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 0e484cc..07f4a31 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -93,11 +93,23 @@ bool cxl_port_is_endpoint(struct cxl_port *port); - struct cxl_bus *cxl_port_get_bus(struct cxl_port *port); - const char *cxl_port_get_host(struct cxl_port *port); - bool cxl_port_hosts_memdev(struct cxl_port *port, struct cxl_memdev *memdev); -+int cxl_port_get_nr_dports(struct cxl_port *port); - - #define cxl_port_foreach(parent, port) \ - for (port = cxl_port_get_first(parent); port != NULL; \ - port = cxl_port_get_next(port)) - -+struct cxl_dport; -+struct cxl_dport *cxl_dport_get_first(struct cxl_port *port); -+struct cxl_dport *cxl_dport_get_next(struct cxl_dport *dport); -+const char *cxl_dport_get_devname(struct cxl_dport *dport); -+const char *cxl_dport_get_physical_node(struct cxl_dport *dport); -+int cxl_dport_get_id(struct cxl_dport *dport); -+ -+#define cxl_dport_foreach(port, dport) \ -+ for (dport = cxl_dport_get_first(port); dport != NULL; \ -+ dport = cxl_dport_get_next(dport)) -+ - struct cxl_decoder; - struct cxl_decoder *cxl_decoder_get_first(struct cxl_port *port); - struct cxl_decoder *cxl_decoder_get_next(struct cxl_decoder *decoder); -diff --git a/cxl/list.c b/cxl/list.c -index 27c963a..de96ff9 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -42,7 +42,7 @@ static const struct option options[] = { - OPT_BOOLEAN('D', "decoders", ¶m.decoders, - "include CXL decoder info"), - OPT_BOOLEAN('T', "targets", ¶m.targets, -- "include CXL target data with decoders"), -+ "include CXL target data with decoders or ports"), - OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"), - OPT_BOOLEAN('u', "human", ¶m.human, - "use human friendly number formats "), --- -2.27.0 - diff --git a/SOURCES/0120-cxl-list-Support-filtering-memdevs-by-decoders.patch b/SOURCES/0120-cxl-list-Support-filtering-memdevs-by-decoders.patch deleted file mode 100644 index 58ab116..0000000 --- a/SOURCES/0120-cxl-list-Support-filtering-memdevs-by-decoders.patch +++ /dev/null @@ -1,205 +0,0 @@ -From aa022d33418021da81a51bc9656931c54043b10b Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:54:50 -0800 -Subject: [PATCH 120/217] cxl/list: Support filtering memdevs by decoders - -In order to filter memdevs by decoders all the ports in the hierarchy need -to be iterated, so introduce cxl_port_foreach_all() that starts at the bus -and does a depth first iteration of all the descendant ports. - -Link: https://lore.kernel.org/r/164298569017.3021641.15558596583530530035.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .clang-format | 1 + - Documentation/cxl/cxl-list.txt | 13 +++++++++ - Documentation/cxl/lib/libcxl.txt | 11 ++++++++ - cxl/filter.c | 48 ++++++++++++++++++++++++++++++++ - cxl/lib/libcxl.c | 13 +++++++++ - cxl/libcxl.h | 6 ++++ - 6 files changed, 92 insertions(+) - -diff --git a/.clang-format b/.clang-format -index c753487..6aabcb6 100644 ---- a/.clang-format -+++ b/.clang-format -@@ -84,6 +84,7 @@ ForEachMacros: - - 'cxl_target_foreach' - - 'cxl_dport_foreach' - - 'cxl_endpoint_foreach' -+ - 'cxl_port_foreach_all' - - 'daxctl_dev_foreach' - - 'daxctl_mapping_foreach' - - 'daxctl_region_foreach' -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index e1299d9..04e831e 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -61,6 +61,19 @@ one or more memdevs. For example: - } - ] - ---- -+Additionally, when provisioning new interleave configurations it is -+useful to know which memdevs can be referenced by a given decoder like a -+root decoder: -+---- -+# cxl list -Mu -d decoder0.0 -+{ -+ "memdev":"mem0", -+ "pmem_size":"256.00 MiB (268.44 MB)", -+ "ram_size":0, -+ "serial":"0", -+ "host":"0000:35:00.0" -+} -+---- - - The --human option in addition to reformatting some fields to more human - friendly strings also unwraps the array to reduce the number of lines of -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 2e8570d..5ad3027 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -219,10 +219,18 @@ struct cxl_port *cxl_port_get_parent(struct cxl_port *port); - struct cxl_ctx *cxl_port_get_ctx(struct cxl_port *port); - const char *cxl_port_get_host(struct cxl_port *port); - struct cxl_port *cxl_decoder_get_port(struct cxl_decoder *decoder); -+struct cxl_port *cxl_port_get_next_all(struct cxl_port *port, -+ const struct cxl_port *top); - - #define cxl_port_foreach(parent, port) \ - for (port = cxl_port_get_first(parent); port != NULL; \ - port = cxl_port_get_next(port)) -+ -+#define cxl_port_foreach_all(top, port) \ -+ for (port = cxl_port_get_first(top); port != NULL; \ -+ port = cxl_port_get_next_all(port, top)) -+ -+ - ---- - A bus object encapsulates a CXL port object. Use cxl_bus_get_port() to - use generic port APIs on root objects. -@@ -236,6 +244,9 @@ that hierarchy via cxl_port_get_bus(). - The host of a port is the corresponding device name of the PCIe Root - Port, or Switch Upstream Port with CXL capabilities. - -+The cxl_port_foreach_all() helper does a depth first iteration of all -+ports beneath the 'top' port argument. -+ - === PORT: Attributes - ---- - const char *cxl_port_get_devname(struct cxl_port *port); -diff --git a/cxl/filter.c b/cxl/filter.c -index 05ede91..c972545 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -441,6 +441,51 @@ util_cxl_decoder_filter_by_memdev(struct cxl_decoder *decoder, - return NULL; - } - -+static bool __memdev_filter_by_decoder(struct cxl_memdev *memdev, -+ struct cxl_port *port, const char *ident) -+{ -+ struct cxl_decoder *decoder; -+ struct cxl_endpoint *endpoint; -+ -+ cxl_decoder_foreach(port, decoder) { -+ if (!util_cxl_decoder_filter(decoder, ident)) -+ continue; -+ if (cxl_decoder_get_target_by_memdev(decoder, memdev)) -+ return true; -+ } -+ -+ cxl_endpoint_foreach(port, endpoint) -+ if (__memdev_filter_by_decoder( -+ memdev, cxl_endpoint_get_port(endpoint), ident)) -+ return true; -+ return false; -+} -+ -+static struct cxl_memdev * -+util_cxl_memdev_filter_by_decoder(struct cxl_memdev *memdev, const char *ident) -+{ -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ struct cxl_bus *bus; -+ -+ if (!ident) -+ return memdev; -+ -+ cxl_bus_foreach(ctx, bus) { -+ struct cxl_port *port, *top; -+ -+ port = cxl_bus_get_port(bus); -+ if (__memdev_filter_by_decoder(memdev, port, ident)) -+ return memdev; -+ -+ top = port; -+ cxl_port_foreach_all(top, port) -+ if (__memdev_filter_by_decoder(memdev, port, ident)) -+ return memdev; -+ } -+ -+ return NULL; -+} -+ - static unsigned long params_to_flags(struct cxl_filter_params *param) - { - unsigned long flags = 0; -@@ -599,6 +644,9 @@ static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p, - if (!util_cxl_memdev_filter(memdev, p->memdev_filter, - p->serial_filter)) - continue; -+ if (!util_cxl_memdev_filter_by_decoder( -+ memdev, p->decoder_filter)) -+ continue; - if (!p->idle && !cxl_memdev_is_enabled(memdev)) - continue; - jobj = util_cxl_memdev_to_json(memdev, flags); -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index d7a3f10..4ebb8b9 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -1257,6 +1257,19 @@ CXL_EXPORT struct cxl_port *cxl_port_get_next(struct cxl_port *port) - return list_next(&parent_port->child_ports, port, list); - } - -+CXL_EXPORT struct cxl_port *cxl_port_get_next_all(struct cxl_port *port, -+ const struct cxl_port *top) -+{ -+ struct cxl_port *child, *iter = port; -+ -+ child = cxl_port_get_first(iter); -+ if (child) -+ return child; -+ while (!cxl_port_get_next(iter) && iter->parent && iter->parent != top) -+ iter = iter->parent; -+ return cxl_port_get_next(iter); -+} -+ - CXL_EXPORT const char *cxl_port_get_devname(struct cxl_port *port) - { - return devpath_to_devname(port->dev_path); -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 07f4a31..874c381 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -94,11 +94,17 @@ struct cxl_bus *cxl_port_get_bus(struct cxl_port *port); - const char *cxl_port_get_host(struct cxl_port *port); - bool cxl_port_hosts_memdev(struct cxl_port *port, struct cxl_memdev *memdev); - int cxl_port_get_nr_dports(struct cxl_port *port); -+struct cxl_port *cxl_port_get_next_all(struct cxl_port *port, -+ const struct cxl_port *top); - - #define cxl_port_foreach(parent, port) \ - for (port = cxl_port_get_first(parent); port != NULL; \ - port = cxl_port_get_next(port)) - -+#define cxl_port_foreach_all(top, port) \ -+ for (port = cxl_port_get_first(top); port != NULL; \ -+ port = cxl_port_get_next_all(port, top)) -+ - struct cxl_dport; - struct cxl_dport *cxl_dport_get_first(struct cxl_port *port); - struct cxl_dport *cxl_dport_get_next(struct cxl_dport *dport); --- -2.27.0 - diff --git a/SOURCES/0121-cxl-list-Support-filtering-memdevs-by-ports.patch b/SOURCES/0121-cxl-list-Support-filtering-memdevs-by-ports.patch deleted file mode 100644 index 55721ff..0000000 --- a/SOURCES/0121-cxl-list-Support-filtering-memdevs-by-ports.patch +++ /dev/null @@ -1,200 +0,0 @@ -From 15cae420681c5e8efad2b4cbaf0470960e2eba52 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:54:55 -0800 -Subject: [PATCH 121/217] cxl/list: Support filtering memdevs by ports - -The ability to filter memdevs by decoders falls short when the decoder does -not have its target list programmed. So, introduce a by port filter to show -the potential memdevs that can be targeted by the decoder. - -Link: https://lore.kernel.org/r/164298569568.3021641.888802471376117408.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 3 +- - Documentation/cxl/lib/libcxl.txt | 7 ++++- - cxl/filter.c | 50 ++++++++++++++++++++++++++++++++ - cxl/lib/libcxl.c | 23 +++++++++++++++ - cxl/lib/libcxl.sym | 2 ++ - cxl/libcxl.h | 3 ++ - 6 files changed, 86 insertions(+), 2 deletions(-) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 04e831e..90e6d9f 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -63,7 +63,8 @@ one or more memdevs. For example: - ---- - Additionally, when provisioning new interleave configurations it is - useful to know which memdevs can be referenced by a given decoder like a --root decoder: -+root decoder, or mapped by a given port if the decoders are not -+configured. - ---- - # cxl list -Mu -d decoder0.0 - { -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 5ad3027..a0fcee9 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -276,11 +276,12 @@ CXL / PCIe host bridge. - ---- - struct cxl_dport *cxl_dport_get_first(struct cxl_port *port); - struct cxl_dport *cxl_dport_get_next(struct cxl_dport *dport); -+struct cxl_dport *cxl_port_get_dport_by_memdev(struct cxl_port *port, -+ struct cxl_memdev *memdev); - - #define cxl_dport_foreach(port, dport) \ - for (dport = cxl_dport_get_first(port); dport != NULL; \ - dport = cxl_dport_get_next(dport)) -- - ---- - - ===== DPORT: Attributes -@@ -288,12 +289,16 @@ struct cxl_dport *cxl_dport_get_next(struct cxl_dport *dport); - const char *cxl_dport_get_devname(struct cxl_dport *dport); - const char *cxl_dport_get_physical_node(struct cxl_dport *dport); - int cxl_dport_get_id(struct cxl_dport *dport); -+bool cxl_dport_maps_memdev(struct cxl_dport *dport, struct cxl_memdev *memdev); - ---- - The id of a dport is the hardware idenfifier used by an upstream port to - reference a downstream port. The physical node of a dport is only - available for platform firmware defined downstream ports and alias the - companion object, like a PCI host bridge, in the PCI device hierarchy. - -+The cxl_dport_maps_memdev() helper checks if a dport is an ancestor of a -+given memdev. -+ - ENDPOINTS - --------- - CXL endpoint objects encapsulate the set of host-managed device-memory -diff --git a/cxl/filter.c b/cxl/filter.c -index c972545..c691edf 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -486,6 +486,53 @@ util_cxl_memdev_filter_by_decoder(struct cxl_memdev *memdev, const char *ident) - return NULL; - } - -+static bool __memdev_filter_by_port(struct cxl_memdev *memdev, -+ struct cxl_port *port, -+ const char *port_ident) -+{ -+ struct cxl_endpoint *endpoint; -+ -+ if (util_cxl_port_filter(port, port_ident, CXL_PF_SINGLE) && -+ cxl_port_get_dport_by_memdev(port, memdev)) -+ return true; -+ -+ cxl_endpoint_foreach(port, endpoint) -+ if (__memdev_filter_by_port(memdev, -+ cxl_endpoint_get_port(endpoint), -+ port_ident)) -+ return true; -+ return false; -+} -+ -+static struct cxl_memdev * -+util_cxl_memdev_filter_by_port(struct cxl_memdev *memdev, const char *bus_ident, -+ const char *port_ident) -+{ -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ struct cxl_bus *bus; -+ -+ if (!bus_ident && !port_ident) -+ return memdev; -+ -+ cxl_bus_foreach(ctx, bus) { -+ struct cxl_port *port, *top; -+ -+ port = cxl_bus_get_port(bus); -+ if (util_cxl_bus_filter(bus, bus_ident)) -+ if (__memdev_filter_by_port(memdev, port, -+ cxl_bus_get_devname(bus))) -+ return memdev; -+ if (__memdev_filter_by_port(memdev, port, port_ident)) -+ return memdev; -+ top = port; -+ cxl_port_foreach_all(top, port) -+ if (__memdev_filter_by_port(memdev, port, port_ident)) -+ return memdev; -+ } -+ -+ return NULL; -+} -+ - static unsigned long params_to_flags(struct cxl_filter_params *param) - { - unsigned long flags = 0; -@@ -647,6 +694,9 @@ static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p, - if (!util_cxl_memdev_filter_by_decoder( - memdev, p->decoder_filter)) - continue; -+ if (!util_cxl_memdev_filter_by_port( -+ memdev, p->bus_filter, p->port_filter)) -+ continue; - if (!p->idle && !cxl_memdev_is_enabled(memdev)) - continue; - jobj = util_cxl_memdev_to_json(memdev, flags); -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 4ebb8b9..dcfc826 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -1452,6 +1452,29 @@ CXL_EXPORT int cxl_dport_get_id(struct cxl_dport *dport) - return dport->id; - } - -+CXL_EXPORT bool cxl_dport_maps_memdev(struct cxl_dport *dport, -+ struct cxl_memdev *memdev) -+{ -+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -+ -+ dbg(ctx, "memdev: %s dport: %s\n", memdev->host_path, dport->dev_path); -+ -+ if (dport->phys_path) -+ return !!strstr(memdev->host_path, dport->phys_path); -+ return !!strstr(memdev->host_path, dport->dev_path); -+} -+ -+CXL_EXPORT struct cxl_dport * -+cxl_port_get_dport_by_memdev(struct cxl_port *port, struct cxl_memdev *memdev) -+{ -+ struct cxl_dport *dport; -+ -+ cxl_dport_foreach(port, dport) -+ if (cxl_dport_maps_memdev(dport, memdev)) -+ return dport; -+ return NULL; -+} -+ - static void *add_cxl_bus(void *parent, int id, const char *cxlbus_base) - { - const char *devname = devpath_to_devname(cxlbus_base); -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 0190b13..2c8358e 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -149,4 +149,6 @@ global: - cxl_dport_get_devname; - cxl_dport_get_physical_node; - cxl_dport_get_id; -+ cxl_port_get_dport_by_memdev; -+ cxl_dport_maps_memdev; - } LIBCXL_1; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 874c381..c8d07bb 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -111,6 +111,9 @@ struct cxl_dport *cxl_dport_get_next(struct cxl_dport *dport); - const char *cxl_dport_get_devname(struct cxl_dport *dport); - const char *cxl_dport_get_physical_node(struct cxl_dport *dport); - int cxl_dport_get_id(struct cxl_dport *dport); -+bool cxl_dport_maps_memdev(struct cxl_dport *dport, struct cxl_memdev *memdev); -+struct cxl_dport *cxl_port_get_dport_by_memdev(struct cxl_port *port, -+ struct cxl_memdev *memdev); - - #define cxl_dport_foreach(port, dport) \ - for (dport = cxl_dport_get_first(port); dport != NULL; \ --- -2.27.0 - diff --git a/SOURCES/0122-cxl-port-Add-disable-enable-port-command.patch b/SOURCES/0122-cxl-port-Add-disable-enable-port-command.patch deleted file mode 100644 index 975156d..0000000 --- a/SOURCES/0122-cxl-port-Add-disable-enable-port-command.patch +++ /dev/null @@ -1,734 +0,0 @@ -From 1cfb7570369ae6bed832bde908435d38fa990f9d Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:55:01 -0800 -Subject: [PATCH 122/217] cxl/port: Add {disable,enable}-port command - -The {disable,enable}-port commands are used for debugging port enumeration -corner cases and testing the kernel CXL device hotplug implementation. - -In addition to unbinding the port from its driver, which also kicks of -unregistration of descendent ports, the disable operation also flushes the -kernels delayed workqueue for memory device removal. - -Link: https://lore.kernel.org/r/164298570117.3021641.14546710754812021284.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-disable-port.txt | 46 +++++ - Documentation/cxl/cxl-enable-port.txt | 43 +++++ - Documentation/cxl/lib/libcxl.txt | 11 ++ - Documentation/cxl/meson.build | 2 + - cxl/builtin.h | 2 + - cxl/cxl.c | 2 + - cxl/filter.c | 21 +- - cxl/filter.h | 13 ++ - cxl/lib/libcxl.c | 95 +++++++++- - cxl/lib/libcxl.sym | 3 + - cxl/libcxl.h | 3 + - cxl/meson.build | 1 + - cxl/port.c | 253 +++++++++++++++++++++++++ - 13 files changed, 471 insertions(+), 24 deletions(-) - create mode 100644 Documentation/cxl/cxl-disable-port.txt - create mode 100644 Documentation/cxl/cxl-enable-port.txt - create mode 100644 cxl/port.c - -diff --git a/Documentation/cxl/cxl-disable-port.txt b/Documentation/cxl/cxl-disable-port.txt -new file mode 100644 -index 0000000..de13c07 ---- /dev/null -+++ b/Documentation/cxl/cxl-disable-port.txt -@@ -0,0 +1,46 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-disable-port(1) -+=================== -+ -+NAME -+---- -+cxl-disable-port - activate / hot-add a given CXL port -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl disable-port' [..] [] -+ -+For test and debug scenarios, disable a CXL port and any memory devices -+dependent on this port being active for CXL.mem operation. -+ -+OPTIONS -+------- -+-e:: -+--endpoint:: -+ Toggle from treating the port arguments as Switch Port identifiers to -+ Endpoint Port identifiers. -+ -+ -+-f:: -+--force:: -+ DANGEROUS: Override the safety measure that blocks attempts to disable a -+ port if the tool determines a descendent memdev is in active usage. -+ Recall that CXL memory ranges might have been established by platform -+ firmware and disabling an active device is akin to force removing memory -+ from a running system. -+ -+ Toggle from treating the port arguments as Switch Port identifiers to -+ Endpoint Port identifiers. -+ -+--debug:: -+ If the cxl tool was built with debug disabled, turn on debug -+ messages. -+ -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-disable-port[1] -diff --git a/Documentation/cxl/cxl-enable-port.txt b/Documentation/cxl/cxl-enable-port.txt -new file mode 100644 -index 0000000..9a37cef ---- /dev/null -+++ b/Documentation/cxl/cxl-enable-port.txt -@@ -0,0 +1,43 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-enable-port(1) -+================== -+ -+NAME -+---- -+cxl-enable-port - activate / hot-add a given CXL port -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl enable-port' [..] [] -+ -+A port typically autoenables at initial device discovery. However, if it -+was manually disabled this command can trigger the kernel to activate it -+again. This involves detecting the state of the HDM (Host Managed Device -+Memory) Decoders and validating that CXL.mem is enabled for each port in -+the device's hierarchy. -+ -+OPTIONS -+------- -+-e:: -+--endpoint:: -+ Toggle from treating the port arguments as Switch Port identifiers to -+ Endpoint Port identifiers. -+ -+-m:: -+--enable-memdevs:: -+ Try to enable descendant memdevs after enabling the port. Recall that a -+ memdev is only enabled after all CXL ports in its device topology -+ ancestry are enabled. -+ -+--debug:: -+ If the cxl tool was built with debug enabled, turn on debug -+ messages. -+ -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-disable-port[1] -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index a0fcee9..27eb29e 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -247,6 +247,16 @@ Port, or Switch Upstream Port with CXL capabilities. - The cxl_port_foreach_all() helper does a depth first iteration of all - ports beneath the 'top' port argument. - -+=== PORT: Control -+--- -+int cxl_port_disable_invalidate(struct cxl_port *port); -+int cxl_port_enable(struct cxl_port *port); -+--- -+cxl_port_disable_invalidate() is a violent operation that disables -+entire sub-tree of CXL Memory Device and Ports, only use it for test / -+debug scenarios, or ensuring that all impacted devices are deactivated -+first. -+ - === PORT: Attributes - ---- - const char *cxl_port_get_devname(struct cxl_port *port); -@@ -315,6 +325,7 @@ struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint); - struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint); - const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint); - struct cxl_endpoint *cxl_memdev_get_endpoint(struct cxl_memdev *memdev); -+struct cxl_endpoint *cxl_port_to_endpoint(struct cxl_port *port); - - #define cxl_endpoint_foreach(port, endpoint) \ - for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \ -diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build -index 7618c97..96f4666 100644 ---- a/Documentation/cxl/meson.build -+++ b/Documentation/cxl/meson.build -@@ -32,6 +32,8 @@ cxl_manpages = [ - 'cxl-zero-labels.txt', - 'cxl-enable-memdev.txt', - 'cxl-disable-memdev.txt', -+ 'cxl-enable-port.txt', -+ 'cxl-disable-port.txt', - ] - - foreach man : cxl_manpages -diff --git a/cxl/builtin.h b/cxl/builtin.h -index 621c85c..3123d5e 100644 ---- a/cxl/builtin.h -+++ b/cxl/builtin.h -@@ -12,4 +12,6 @@ int cmd_init_labels(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_check_labels(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_disable_memdev(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_enable_memdev(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_disable_port(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_enable_port(int argc, const char **argv, struct cxl_ctx *ctx); - #endif /* _CXL_BUILTIN_H_ */ -diff --git a/cxl/cxl.c b/cxl/cxl.c -index 78d2e9a..c20c569 100644 ---- a/cxl/cxl.c -+++ b/cxl/cxl.c -@@ -66,6 +66,8 @@ static struct cmd_struct commands[] = { - { "write-labels", .c_fn = cmd_write_labels }, - { "disable-memdev", .c_fn = cmd_disable_memdev }, - { "enable-memdev", .c_fn = cmd_enable_memdev }, -+ { "disable-port", .c_fn = cmd_disable_port }, -+ { "enable-port", .c_fn = cmd_enable_port }, - }; - - int main(int argc, const char **argv) -diff --git a/cxl/filter.c b/cxl/filter.c -index c691edf..f6a23b7 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -47,8 +47,8 @@ bool cxl_filter_has(const char *__filter, const char *needle) - return false; - } - --static struct cxl_endpoint * --util_cxl_endpoint_filter(struct cxl_endpoint *endpoint, const char *__ident) -+struct cxl_endpoint *util_cxl_endpoint_filter(struct cxl_endpoint *endpoint, -+ const char *__ident) - { - char *ident, *save; - const char *arg; -@@ -124,11 +124,6 @@ static struct cxl_port *__util_cxl_port_filter(struct cxl_port *port, - return NULL; - } - --enum cxl_port_filter_mode { -- CXL_PF_SINGLE, -- CXL_PF_ANCESTRY, --}; -- - static enum cxl_port_filter_mode pf_mode(struct cxl_filter_params *p) - { - if (p->single) -@@ -136,9 +131,8 @@ static enum cxl_port_filter_mode pf_mode(struct cxl_filter_params *p) - return CXL_PF_ANCESTRY; - } - --static struct cxl_port *util_cxl_port_filter(struct cxl_port *port, -- const char *ident, -- enum cxl_port_filter_mode mode) -+struct cxl_port *util_cxl_port_filter(struct cxl_port *port, const char *ident, -+ enum cxl_port_filter_mode mode) - { - struct cxl_port *iter = port; - -@@ -358,9 +352,9 @@ util_cxl_endpoint_filter_by_memdev(struct cxl_endpoint *endpoint, - return NULL; - } - --static struct cxl_port *util_cxl_port_filter_by_memdev(struct cxl_port *port, -- const char *ident, -- const char *serial) -+struct cxl_port *util_cxl_port_filter_by_memdev(struct cxl_port *port, -+ const char *ident, -+ const char *serial) - { - struct cxl_ctx *ctx = cxl_port_get_ctx(port); - struct cxl_memdev *memdev; -@@ -958,7 +952,6 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - continue; - } - } -- - } - walk_children: - dbg(p, "walk decoders\n"); -diff --git a/cxl/filter.h b/cxl/filter.h -index 6fd469f..850df70 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -29,6 +29,19 @@ struct cxl_filter_params { - struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, - const char *__ident, - const char *serials); -+struct cxl_port *util_cxl_port_filter_by_memdev(struct cxl_port *port, -+ const char *ident, -+ const char *serial); -+ -+enum cxl_port_filter_mode { -+ CXL_PF_SINGLE, -+ CXL_PF_ANCESTRY, -+}; -+ -+struct cxl_port *util_cxl_port_filter(struct cxl_port *port, const char *ident, -+ enum cxl_port_filter_mode mode); -+struct cxl_endpoint *util_cxl_endpoint_filter(struct cxl_endpoint *endpoint, -+ const char *__ident); - int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *param); - bool cxl_filter_has(const char *needle, const char *__filter); - #endif /* _CXL_UTIL_FILTER_H_ */ -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index dcfc826..1a7dccb 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -258,6 +258,11 @@ CXL_EXPORT void cxl_unref(struct cxl_ctx *ctx) - free(ctx); - } - -+static int cxl_flush(struct cxl_ctx *ctx) -+{ -+ return sysfs_write_attr(ctx, "/sys/bus/cxl/flush", "1\n"); -+} -+ - /** - * cxl_set_log_fn - override default log routine - * @ctx: cxl library context -@@ -530,11 +535,31 @@ CXL_EXPORT const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev - return memdev->firmware_version; - } - -+static void bus_invalidate(struct cxl_bus *bus) -+{ -+ struct cxl_ctx *ctx = cxl_bus_get_ctx(bus); -+ struct cxl_port *bus_port, *port, *_p; -+ struct cxl_memdev *memdev; -+ -+ /* -+ * Something happend to cause the state of all ports to be -+ * indeterminate, delete them all and start over. -+ */ -+ cxl_memdev_foreach(ctx, memdev) -+ if (cxl_memdev_get_bus(memdev) == bus) -+ memdev->endpoint = NULL; -+ -+ bus_port = cxl_bus_get_port(bus); -+ list_for_each_safe(&bus_port->child_ports, port, _p, list) -+ free_port(port, &bus_port->child_ports); -+ bus_port->ports_init = 0; -+ cxl_flush(ctx); -+} -+ - CXL_EXPORT int cxl_memdev_disable_invalidate(struct cxl_memdev *memdev) - { - struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); - const char *devname = cxl_memdev_get_devname(memdev); -- struct cxl_port *port, *_p, *bus_port; - struct cxl_bus *bus; - - if (!cxl_memdev_is_enabled(memdev)) -@@ -553,15 +578,7 @@ CXL_EXPORT int cxl_memdev_disable_invalidate(struct cxl_memdev *memdev) - return -EBUSY; - } - -- /* -- * The state of all ports is now indeterminate, delete them all -- * and start over. -- */ -- bus_port = cxl_bus_get_port(bus); -- list_for_each_safe(&bus_port->child_ports, port, _p, list) -- free_port(port, &bus_port->child_ports); -- bus_port->ports_init = 0; -- memdev->endpoint = NULL; -+ bus_invalidate(bus); - - dbg(ctx, "%s: disabled\n", devname); - -@@ -1352,6 +1369,57 @@ CXL_EXPORT int cxl_port_is_enabled(struct cxl_port *port) - return is_enabled(path); - } - -+CXL_EXPORT int cxl_port_disable_invalidate(struct cxl_port *port) -+{ -+ const char *devname = cxl_port_get_devname(port); -+ struct cxl_bus *bus = cxl_port_get_bus(port); -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ -+ if (cxl_port_is_root(port)) { -+ err(ctx, "%s: can not be disabled through this interface\n", -+ devname); -+ return -EINVAL; -+ } -+ -+ if (!bus) { -+ err(ctx, "%s: failed to invalidate\n", devname); -+ return -ENXIO; -+ } -+ -+ util_unbind(port->dev_path, ctx); -+ -+ if (cxl_port_is_enabled(port)) { -+ err(ctx, "%s: failed to disable\n", devname); -+ return -EBUSY; -+ } -+ -+ dbg(ctx, "%s: disabled\n", devname); -+ -+ bus_invalidate(bus); -+ -+ return 0; -+} -+ -+CXL_EXPORT int cxl_port_enable(struct cxl_port *port) -+{ -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ const char *devname = cxl_port_get_devname(port); -+ -+ if (cxl_port_is_enabled(port)) -+ return 0; -+ -+ util_bind(devname, port->module, "cxl", ctx); -+ -+ if (!cxl_port_is_enabled(port)) { -+ err(ctx, "%s: failed to enable\n", devname); -+ return -ENXIO; -+ } -+ -+ dbg(ctx, "%s: enabled\n", devname); -+ -+ return 0; -+} -+ - CXL_EXPORT struct cxl_bus *cxl_port_to_bus(struct cxl_port *port) - { - if (!cxl_port_is_root(port)) -@@ -1359,6 +1427,13 @@ CXL_EXPORT struct cxl_bus *cxl_port_to_bus(struct cxl_port *port) - return container_of(port, struct cxl_bus, port); - } - -+CXL_EXPORT struct cxl_endpoint *cxl_port_to_endpoint(struct cxl_port *port) -+{ -+ if (!cxl_port_is_endpoint(port)) -+ return NULL; -+ return container_of(port, struct cxl_endpoint, port); -+} -+ - static void *add_cxl_dport(void *parent, int id, const char *cxldport_base) - { - const char *devname = devpath_to_devname(cxldport_base); -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 2c8358e..67c7fd5 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -97,11 +97,14 @@ global: - cxl_port_is_switch; - cxl_port_to_bus; - cxl_port_is_endpoint; -+ cxl_port_to_endpoint; - cxl_port_get_bus; - cxl_port_get_host; - cxl_port_get_bus; - cxl_port_hosts_memdev; - cxl_port_get_nr_dports; -+ cxl_port_disable_invalidate; -+ cxl_port_enable; - cxl_port_get_next_all; - cxl_endpoint_get_first; - cxl_endpoint_get_next; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index c8d07bb..1aac396 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -90,10 +90,13 @@ bool cxl_port_is_root(struct cxl_port *port); - bool cxl_port_is_switch(struct cxl_port *port); - struct cxl_bus *cxl_port_to_bus(struct cxl_port *port); - bool cxl_port_is_endpoint(struct cxl_port *port); -+struct cxl_endpoint *cxl_port_to_endpoint(struct cxl_port *port); - struct cxl_bus *cxl_port_get_bus(struct cxl_port *port); - const char *cxl_port_get_host(struct cxl_port *port); - bool cxl_port_hosts_memdev(struct cxl_port *port, struct cxl_memdev *memdev); - int cxl_port_get_nr_dports(struct cxl_port *port); -+int cxl_port_disable_invalidate(struct cxl_port *port); -+int cxl_port_enable(struct cxl_port *port); - struct cxl_port *cxl_port_get_next_all(struct cxl_port *port, - const struct cxl_port *top); - -diff --git a/cxl/meson.build b/cxl/meson.build -index fc7ee71..87cfea7 100644 ---- a/cxl/meson.build -+++ b/cxl/meson.build -@@ -1,6 +1,7 @@ - cxl_src = [ - 'cxl.c', - 'list.c', -+ 'port.c', - 'memdev.c', - '../util/json.c', - '../util/log.c', -diff --git a/cxl/port.c b/cxl/port.c -new file mode 100644 -index 0000000..46a8f32 ---- /dev/null -+++ b/cxl/port.c -@@ -0,0 +1,253 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* Copyright (C) 2020-2022 Intel Corporation. All rights reserved. */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "filter.h" -+ -+static struct parameters { -+ bool debug; -+ bool force; -+ bool memdevs; -+ bool endpoint; -+} param; -+ -+static struct log_ctx pl; -+ -+#define BASE_OPTIONS() \ -+OPT_BOOLEAN(0, "debug", ¶m.debug, "turn on debug"), \ -+OPT_BOOLEAN('e', "endpoint", ¶m.endpoint, \ -+ "target endpoints instead of switch ports") -+ -+#define ENABLE_OPTIONS() \ -+OPT_BOOLEAN('m', "enable-memdevs", ¶m.memdevs, \ -+ "enable downstream memdev(s)") -+ -+#define DISABLE_OPTIONS() \ -+OPT_BOOLEAN('f', "force", ¶m.force, \ -+ "DANGEROUS: override active memdev safety checks") -+ -+static const struct option disable_options[] = { -+ BASE_OPTIONS(), -+ DISABLE_OPTIONS(), -+ OPT_END(), -+}; -+ -+static const struct option enable_options[] = { -+ BASE_OPTIONS(), -+ ENABLE_OPTIONS(), -+ OPT_END(), -+}; -+ -+static int action_disable(struct cxl_port *port) -+{ -+ const char *devname = cxl_port_get_devname(port); -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ struct cxl_memdev *memdev; -+ int active_memdevs = 0; -+ -+ if (!cxl_port_is_enabled(port)) { -+ log_dbg(&pl, "%s already disabled\n", devname); -+ return 0; -+ } -+ -+ if (param.endpoint) { -+ struct cxl_endpoint *endpoint = cxl_port_to_endpoint(port); -+ -+ if (cxl_endpoint_get_memdev(endpoint)) -+ active_memdevs++; -+ } -+ -+ cxl_memdev_foreach(ctx, memdev) { -+ if (!cxl_port_get_dport_by_memdev(port, memdev)) -+ continue; -+ if (cxl_memdev_is_enabled(memdev)) -+ active_memdevs++; -+ } -+ -+ if (active_memdevs && !param.force) { -+ /* -+ * TODO: actually detect rather than assume active just -+ * because the memdev is enabled -+ */ -+ log_err(&pl, -+ "%s hosts %d memdev%s which %s part of an active region\n", -+ devname, active_memdevs, active_memdevs > 1 ? "s" : "", -+ active_memdevs > 1 ? "are" : "is"); -+ log_err(&pl, -+ "See 'cxl list -M -p %s' to see impacted device%s\n", -+ devname, active_memdevs > 1 ? "s" : ""); -+ return -EBUSY; -+ } -+ -+ return cxl_port_disable_invalidate(port); -+} -+ -+static int action_enable(struct cxl_port *port) -+{ -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ struct cxl_memdev *memdev; -+ int rc; -+ -+ rc = cxl_port_enable(port); -+ if (rc || !param.memdevs) -+ return rc; -+ -+ cxl_memdev_foreach(ctx, memdev) -+ if (cxl_port_get_dport_by_memdev(port, memdev)) -+ cxl_memdev_enable(memdev); -+ return 0; -+} -+ -+static struct cxl_port *find_cxl_port(struct cxl_ctx *ctx, const char *ident) -+{ -+ struct cxl_bus *bus; -+ struct cxl_port *port; -+ -+ cxl_bus_foreach(ctx, bus) -+ cxl_port_foreach_all(cxl_bus_get_port(bus), port) -+ if (util_cxl_port_filter(port, ident, CXL_PF_SINGLE)) -+ return port; -+ return NULL; -+} -+ -+static struct cxl_endpoint *find_cxl_endpoint(struct cxl_ctx *ctx, -+ const char *ident) -+{ -+ struct cxl_bus *bus; -+ struct cxl_port *port; -+ struct cxl_endpoint *endpoint; -+ -+ cxl_bus_foreach(ctx, bus) -+ cxl_port_foreach_all(cxl_bus_get_port(bus), port) -+ cxl_endpoint_foreach(port, endpoint) -+ if (util_cxl_endpoint_filter(endpoint, ident)) -+ return endpoint; -+ return NULL; -+} -+ -+ -+ -+static int port_action(int argc, const char **argv, struct cxl_ctx *ctx, -+ int (*action)(struct cxl_port *port), -+ const struct option *options, const char *usage) -+{ -+ int i, rc = 0, count = 0, err = 0; -+ const char * const u[] = { -+ usage, -+ NULL -+ }; -+ unsigned long id; -+ -+ log_init(&pl, "cxl port", "CXL_PORT_LOG"); -+ argc = parse_options(argc, argv, options, u, 0); -+ -+ if (argc == 0) -+ usage_with_options(u, options); -+ for (i = 0; i < argc; i++) { -+ const char *fmt; -+ -+ if (strcmp(argv[i], "all") == 0) { -+ argc = 1; -+ break; -+ } -+ -+ if (param.endpoint) -+ fmt = "endpoint%lu"; -+ else -+ fmt = "port%lu"; -+ -+ if (sscanf(argv[i], fmt, &id) == 1) -+ continue; -+ if (sscanf(argv[i], "%lu", &id) == 1) -+ continue; -+ -+ log_err(&pl, "'%s' is not a valid %s identifer\n", argv[i], -+ param.endpoint ? "endpoint" : "port"); -+ err++; -+ } -+ -+ if (err == argc) { -+ usage_with_options(u, options); -+ return -EINVAL; -+ } -+ -+ if (param.debug) { -+ cxl_set_log_priority(ctx, LOG_DEBUG); -+ pl.log_priority = LOG_DEBUG; -+ } else -+ pl.log_priority = LOG_INFO; -+ -+ rc = 0; -+ err = 0; -+ count = 0; -+ -+ for (i = 0; i < argc; i++) { -+ struct cxl_port *port; -+ -+ if (param.endpoint) { -+ struct cxl_endpoint *endpoint; -+ -+ endpoint = find_cxl_endpoint(ctx, argv[i]); -+ if (!endpoint) { -+ log_dbg(&pl, "endpoint: %s not found\n", -+ argv[i]); -+ continue; -+ } -+ port = cxl_endpoint_get_port(endpoint); -+ } else { -+ port = find_cxl_port(ctx, argv[i]); -+ if (!port) { -+ log_dbg(&pl, "port: %s not found\n", argv[i]); -+ continue; -+ } -+ } -+ -+ log_dbg(&pl, "run action on port: %s\n", -+ cxl_port_get_devname(port)); -+ rc = action(port); -+ if (rc == 0) -+ count++; -+ else if (rc && !err) -+ err = rc; -+ } -+ rc = err; -+ -+ /* -+ * count if some actions succeeded, 0 if none were attempted, -+ * negative error code otherwise. -+ */ -+ if (count > 0) -+ return count; -+ return rc; -+ } -+ -+ int cmd_disable_port(int argc, const char **argv, struct cxl_ctx *ctx) -+ { -+ int count = port_action( -+ argc, argv, ctx, action_disable, disable_options, -+ "cxl disable-port [..] []"); -+ -+ log_info(&pl, "disabled %d port%s\n", count >= 0 ? count : 0, -+ count > 1 ? "s" : ""); -+ return count >= 0 ? 0 : EXIT_FAILURE; -+ } -+ -+ int cmd_enable_port(int argc, const char **argv, struct cxl_ctx *ctx) -+ { -+ int count = port_action( -+ argc, argv, ctx, action_enable, enable_options, -+ "cxl enable-port [..] []"); -+ -+ log_info(&pl, "enabled %d port%s\n", count >= 0 ? count : 0, -+ count > 1 ? "s" : ""); -+ return count >= 0 ? 0 : EXIT_FAILURE; -+ } --- -2.27.0 - diff --git a/SOURCES/0123-cxl-list-Filter-dports-and-targets-by-memdevs.patch b/SOURCES/0123-cxl-list-Filter-dports-and-targets-by-memdevs.patch deleted file mode 100644 index 377dccf..0000000 --- a/SOURCES/0123-cxl-list-Filter-dports-and-targets-by-memdevs.patch +++ /dev/null @@ -1,340 +0,0 @@ -From f9ebf984e7eb93a044f48c4089485051751face8 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Sun, 23 Jan 2022 16:55:06 -0800 -Subject: [PATCH 123/217] cxl/list: Filter dports and targets by memdevs - -Trim dport / target information by the memdev filter. This is useful when -validating connectivity and decoder programming. - -Link: https://lore.kernel.org/r/164298570626.3021641.18034728333613142555.stgit@dwillia2-desk3.amr.corp.intel.com -Reported-by: Ben Widawsky -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/lib/libcxl.txt | 1 + - cxl/filter.c | 51 ++++++++++++++++++++++++++++++++ - cxl/filter.h | 6 ++++ - cxl/json.c | 51 +++++++++++++++++++++----------- - cxl/json.h | 7 +++++ - cxl/lib/libcxl.c | 5 ++++ - cxl/lib/libcxl.sym | 1 + - cxl/libcxl.h | 1 + - 8 files changed, 105 insertions(+), 18 deletions(-) - -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 27eb29e..4392b47 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -221,6 +221,7 @@ const char *cxl_port_get_host(struct cxl_port *port); - struct cxl_port *cxl_decoder_get_port(struct cxl_decoder *decoder); - struct cxl_port *cxl_port_get_next_all(struct cxl_port *port, - const struct cxl_port *top); -+struct cxl_port *cxl_dport_get_port(struct cxl_dport *dport); - - #define cxl_port_foreach(parent, port) \ - for (port = cxl_port_get_first(parent); port != NULL; \ -diff --git a/cxl/filter.c b/cxl/filter.c -index f6a23b7..925bf3a 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -435,6 +435,48 @@ util_cxl_decoder_filter_by_memdev(struct cxl_decoder *decoder, - return NULL; - } - -+struct cxl_target *util_cxl_target_filter_by_memdev(struct cxl_target *target, -+ const char *ident, -+ const char *serial) -+{ -+ struct cxl_decoder *decoder = cxl_target_get_decoder(target); -+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ struct cxl_memdev *memdev; -+ -+ if (!ident && !serial) -+ return target; -+ -+ cxl_memdev_foreach(ctx, memdev) { -+ if (!util_cxl_memdev_filter(memdev, ident, serial)) -+ continue; -+ if (cxl_target_maps_memdev(target, memdev)) -+ return target; -+ } -+ -+ return NULL; -+} -+ -+struct cxl_dport *util_cxl_dport_filter_by_memdev(struct cxl_dport *dport, -+ const char *ident, -+ const char *serial) -+{ -+ struct cxl_port *port = cxl_dport_get_port(dport); -+ struct cxl_ctx *ctx = cxl_port_get_ctx(port); -+ struct cxl_memdev *memdev; -+ -+ if (!ident && !serial) -+ return dport; -+ -+ cxl_memdev_foreach (ctx, memdev) { -+ if (!util_cxl_memdev_filter(memdev, ident, serial)) -+ continue; -+ if (cxl_dport_maps_memdev(dport, memdev)) -+ return dport; -+ } -+ -+ return NULL; -+} -+ - static bool __memdev_filter_by_decoder(struct cxl_memdev *memdev, - struct cxl_port *port, const char *ident) - { -@@ -639,6 +681,9 @@ static void walk_decoders(struct cxl_port *port, struct cxl_filter_params *p, - dbg(p, "decoder object allocation failure\n"); - continue; - } -+ util_cxl_targets_append_json(jdecoder, decoder, -+ p->memdev_filter, p->serial_filter, -+ flags); - json_object_array_add(jdecoders, jdecoder); - } - } -@@ -756,6 +801,9 @@ walk_child_ports(struct cxl_port *parent_port, struct cxl_filter_params *p, - err(p, "%s: failed to list\n", devname); - continue; - } -+ util_cxl_dports_append_json(jport, port, -+ p->memdev_filter, -+ p->serial_filter, flags); - json_object_array_add(jports, jport); - jchildports = json_object_new_array(); - if (!jchildports) { -@@ -914,6 +962,9 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - dbg(p, "bus object allocation failure\n"); - continue; - } -+ util_cxl_dports_append_json(jbus, port, -+ p->memdev_filter, -+ p->serial_filter, flags); - json_object_array_add(jbuses, jbus); - if (p->ports) { - jchildports = json_object_new_array(); -diff --git a/cxl/filter.h b/cxl/filter.h -index 850df70..5deabb3 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -42,6 +42,12 @@ struct cxl_port *util_cxl_port_filter(struct cxl_port *port, const char *ident, - enum cxl_port_filter_mode mode); - struct cxl_endpoint *util_cxl_endpoint_filter(struct cxl_endpoint *endpoint, - const char *__ident); -+struct cxl_target *util_cxl_target_filter_by_memdev(struct cxl_target *target, -+ const char *ident, -+ const char *serial); -+struct cxl_dport *util_cxl_dport_filter_by_memdev(struct cxl_dport *dport, -+ const char *ident, -+ const char *serial); - int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *param); - bool cxl_filter_has(const char *needle, const char *__filter); - #endif /* _CXL_UTIL_FILTER_H_ */ -diff --git a/cxl/json.c b/cxl/json.c -index 4fb5eec..f3b536e 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -8,6 +8,7 @@ - #include - #include - -+#include "filter.h" - #include "json.h" - - static struct json_object *util_cxl_memdev_health_to_json( -@@ -241,9 +242,9 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - return jdev; - } - --static struct json_object *util_cxl_dports_to_json(struct json_object *jport, -- struct cxl_port *port, -- unsigned long flags) -+void util_cxl_dports_append_json(struct json_object *jport, -+ struct cxl_port *port, const char *ident, -+ const char *serial, unsigned long flags) - { - struct json_object *jobj, *jdports; - struct cxl_dport *dport; -@@ -251,7 +252,7 @@ static struct json_object *util_cxl_dports_to_json(struct json_object *jport, - - val = cxl_port_get_nr_dports(port); - if (!val || !(flags & UTIL_JSON_TARGETS)) -- return jport; -+ return; - - jobj = json_object_new_int(val); - if (jobj) -@@ -259,12 +260,15 @@ static struct json_object *util_cxl_dports_to_json(struct json_object *jport, - - jdports = json_object_new_array(); - if (!jdports) -- return jport; -+ return; - - cxl_dport_foreach(port, dport) { - struct json_object *jdport; - const char *phys_node; - -+ if (!util_cxl_dport_filter_by_memdev(dport, ident, serial)) -+ continue; -+ - jdport = json_object_new_object(); - if (!jdport) - continue; -@@ -289,8 +293,6 @@ static struct json_object *util_cxl_dports_to_json(struct json_object *jport, - } - - json_object_object_add(jport, "dports", jdports); -- -- return jport; - } - - struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus, -@@ -311,7 +313,7 @@ struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus, - if (jobj) - json_object_object_add(jbus, "provider", jobj); - -- return util_cxl_dports_to_json(jbus, cxl_bus_get_port(bus), flags); -+ return jbus; - } - - struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, -@@ -320,8 +322,6 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - const char *devname = cxl_decoder_get_devname(decoder); - struct cxl_port *port = cxl_decoder_get_port(decoder); - struct json_object *jdecoder, *jobj; -- struct json_object *jtargets; -- struct cxl_target *target; - u64 val; - - jdecoder = json_object_new_object(); -@@ -375,9 +375,22 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - jobj); - } - -+ return jdecoder; -+} -+ -+void util_cxl_targets_append_json(struct json_object *jdecoder, -+ struct cxl_decoder *decoder, -+ const char *ident, const char *serial, -+ unsigned long flags) -+{ -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ struct json_object *jobj, *jtargets; -+ struct cxl_target *target; -+ int val; -+ - /* Endpoints don't have targets, they *are* targets */ - if (cxl_port_is_endpoint(port)) -- return jdecoder; -+ return; - - val = cxl_decoder_get_nr_targets(decoder); - jobj = json_object_new_int(val); -@@ -386,16 +399,21 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - - if (!(flags & UTIL_JSON_TARGETS) || - !cxl_decoder_get_nr_targets(decoder)) -- return jdecoder; -+ return; - - jtargets = json_object_new_array(); - if (!jtargets) -- return jdecoder; -+ return; - - cxl_target_foreach(decoder, target) { -- struct json_object *jtarget = json_object_new_object(); -+ struct json_object *jtarget; - const char *phys_node; -+ const char *devname; -+ -+ if (!util_cxl_target_filter_by_memdev(target, ident, serial)) -+ continue; - -+ jtarget = json_object_new_object(); - if (!jtarget) - continue; - -@@ -425,9 +443,6 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - } - - json_object_object_add(jdecoder, "targets", jtargets); -- -- return jdecoder; -- - } - - static struct json_object *__util_cxl_port_to_json(struct cxl_port *port, -@@ -455,7 +470,7 @@ static struct json_object *__util_cxl_port_to_json(struct cxl_port *port, - json_object_object_add(jport, "state", jobj); - } - -- return util_cxl_dports_to_json(jport, port, flags); -+ return jport; - } - - struct json_object *util_cxl_port_to_json(struct cxl_port *port, -diff --git a/cxl/json.h b/cxl/json.h -index fcca2e6..9a5a845 100644 ---- a/cxl/json.h -+++ b/cxl/json.h -@@ -15,4 +15,11 @@ struct json_object *util_cxl_endpoint_to_json(struct cxl_endpoint *endpoint, - unsigned long flags); - struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - unsigned long flags); -+void util_cxl_targets_append_json(struct json_object *jdecoder, -+ struct cxl_decoder *decoder, -+ const char *ident, const char *serial, -+ unsigned long flags); -+void util_cxl_dports_append_json(struct json_object *jport, -+ struct cxl_port *port, const char *ident, -+ const char *serial, unsigned long flags); - #endif /* __CXL_UTIL_JSON_H__ */ -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 1a7dccb..e0b443f 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -1527,6 +1527,11 @@ CXL_EXPORT int cxl_dport_get_id(struct cxl_dport *dport) - return dport->id; - } - -+CXL_EXPORT struct cxl_port *cxl_dport_get_port(struct cxl_dport *dport) -+{ -+ return dport->port; -+} -+ - CXL_EXPORT bool cxl_dport_maps_memdev(struct cxl_dport *dport, - struct cxl_memdev *memdev) - { -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 67c7fd5..e56a2bf 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -152,6 +152,7 @@ global: - cxl_dport_get_devname; - cxl_dport_get_physical_node; - cxl_dport_get_id; -+ cxl_dport_get_port; - cxl_port_get_dport_by_memdev; - cxl_dport_maps_memdev; - } LIBCXL_1; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 1aac396..3b2293b 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -113,6 +113,7 @@ struct cxl_dport *cxl_dport_get_first(struct cxl_port *port); - struct cxl_dport *cxl_dport_get_next(struct cxl_dport *dport); - const char *cxl_dport_get_devname(struct cxl_dport *dport); - const char *cxl_dport_get_physical_node(struct cxl_dport *dport); -+struct cxl_port *cxl_dport_get_port(struct cxl_dport *dport); - int cxl_dport_get_id(struct cxl_dport *dport); - bool cxl_dport_maps_memdev(struct cxl_dport *dport, struct cxl_memdev *memdev); - struct cxl_dport *cxl_port_get_dport_by_memdev(struct cxl_port *port, --- -2.27.0 - diff --git a/SOURCES/0124-ndctl-test-make-inject-smart.sh-more-tolerant-of-dec.patch b/SOURCES/0124-ndctl-test-make-inject-smart.sh-more-tolerant-of-dec.patch deleted file mode 100644 index 9208ab9..0000000 --- a/SOURCES/0124-ndctl-test-make-inject-smart.sh-more-tolerant-of-dec.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 4921c0c2040ffbe10facd320f6a718a3d42ad815 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 17 Feb 2022 22:42:29 -0700 -Subject: [PATCH 124/217] ndctl/test: make inject-smart.sh more tolerant of - decimal fields - -Some combinations of json-c/jq/other libraries seem to produce differing -outputs for the final jq-filtered smart fields, in that some have a -decimal "42.0" numeric field, where as in other combinations it is a -simple "42" (still a numeric field, not string). - -This shouldn't matter in practice, but for this contrived test case, we -need to make sure that "42" is treated the same as "42.0" - -Normalize all fields before comparing them to "%0.0f" so that the -comparison doesn't result in superfluous failures. - -Reported-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/inject-smart.sh | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/test/inject-smart.sh b/test/inject-smart.sh -index 8b91360..046322b 100755 ---- a/test/inject-smart.sh -+++ b/test/inject-smart.sh -@@ -105,13 +105,13 @@ get_field() - json="$($NDCTL list -b $bus -d $dimm -H)" - val="$(jq -r ".[].dimms[].health.$smart_listing" <<< $json)" - val="$(translate_val $val)" -- echo $val -+ printf "%0.0f\n" "$val" - } - - verify() - { - local field="$1" -- local val="$2" -+ local val="$(printf "%0.0f\n" "$2")" - - [[ "$val" == "$(get_field $field)" ]] - } --- -2.27.0 - diff --git a/SOURCES/0125-libndctl-papr-Add-support-for-reporting-shutdown-cou.patch b/SOURCES/0125-libndctl-papr-Add-support-for-reporting-shutdown-cou.patch deleted file mode 100644 index 851293a..0000000 --- a/SOURCES/0125-libndctl-papr-Add-support-for-reporting-shutdown-cou.patch +++ /dev/null @@ -1,136 +0,0 @@ -From aa990008f48f21121474a411d829f24e832c89a2 Mon Sep 17 00:00:00 2001 -From: Vaibhav Jain -Date: Tue, 25 Jan 2022 00:26:05 +0530 -Subject: [PATCH 125/217] libndctl/papr: Add support for reporting - shutdown-count - -Add support for reporting dirty-shutdown-count (DSC) for PAPR based -NVDIMMs. The sysfs attribute exposing this value is located at -nmemX/papr/dirty_shutdown. - -This counter is also returned in payload for PAPR_PDSM_HEALTH as newly -introduced member 'dimm_dsc' in 'struct nd_papr_pdsm_health'. Presence -of 'DSC' is indicated by the PDSM_DIMM_DSC_VALID extension flag. - -The patch implements 'ndctl_dimm_ops.smart_get_shutdown_count' -callback in implemented as papr_smart_get_shutdown_count(). - -Kernel side changes to support reporting DSC have been merged to linux kernel -via patch proposed at [1]. With updated kernel 'ndctl list -DH' reports -following output on PPC64: - -$ sudo ndctl list -DH -[ - { - "dev":"nmem0", - "health":{ - "health_state":"ok", - "life_used_percentage":50, - "shutdown_state":"clean", - "shutdown_count":10 - } - } -] - -[1] http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20210624080621.252038-1-vaibhav@linux.ibm.com - -Link: https://lore.kernel.org/r/20220124185605.1465681-1-vaibhav@linux.ibm.com -Signed-off-by: Vaibhav Jain -Signed-off-by: Vishal Verma ---- - ndctl/lib/libndctl.c | 6 +++++- - ndctl/lib/papr.c | 23 +++++++++++++++++++++++ - ndctl/lib/papr_pdsm.h | 6 ++++++ - 3 files changed, 34 insertions(+), 1 deletion(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index 47a234c..5979a92 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -1819,8 +1819,12 @@ static int add_papr_dimm(struct ndctl_dimm *dimm, const char *dimm_base) - - /* Allocate monitor mode fd */ - dimm->health_eventfd = open(path, O_RDONLY|O_CLOEXEC); -- rc = 0; -+ /* Get the dirty shutdown counter value */ -+ sprintf(path, "%s/papr/dirty_shutdown", dimm_base); -+ if (sysfs_read_attr(ctx, path, buf) == 0) -+ dimm->dirty_shutdown = strtoll(buf, NULL, 0); - -+ rc = 0; - } else if (strcmp(buf, "nvdimm_test") == 0) { - /* probe via common populate_dimm_attributes() */ - rc = populate_dimm_attributes(dimm, dimm_base, "papr"); -diff --git a/ndctl/lib/papr.c b/ndctl/lib/papr.c -index 43b8412..46cf9c1 100644 ---- a/ndctl/lib/papr.c -+++ b/ndctl/lib/papr.c -@@ -165,6 +165,9 @@ static unsigned int papr_smart_get_flags(struct ndctl_cmd *cmd) - if (health.extension_flags & PDSM_DIMM_HEALTH_RUN_GAUGE_VALID) - flags |= ND_SMART_USED_VALID; - -+ if (health.extension_flags & PDSM_DIMM_DSC_VALID) -+ flags |= ND_SMART_SHUTDOWN_COUNT_VALID; -+ - return flags; - } - -@@ -236,6 +239,25 @@ static unsigned int papr_smart_get_life_used(struct ndctl_cmd *cmd) - (100 - health.dimm_fuel_gauge) : 0; - } - -+static unsigned int papr_smart_get_shutdown_count(struct ndctl_cmd *cmd) -+{ -+ -+ struct nd_papr_pdsm_health health; -+ -+ /* Ignore in case of error or invalid pdsm */ -+ if (!cmd_is_valid(cmd) || -+ to_pdsm(cmd)->cmd_status != 0 || -+ to_pdsm_cmd(cmd) != PAPR_PDSM_HEALTH) -+ return 0; -+ -+ /* get the payload from command */ -+ health = to_payload(cmd)->health; -+ -+ return (health.extension_flags & PDSM_DIMM_DSC_VALID) ? -+ (health.dimm_dsc) : 0; -+ -+} -+ - struct ndctl_dimm_ops * const papr_dimm_ops = &(struct ndctl_dimm_ops) { - .cmd_is_supported = papr_cmd_is_supported, - .smart_get_flags = papr_smart_get_flags, -@@ -245,4 +267,5 @@ struct ndctl_dimm_ops * const papr_dimm_ops = &(struct ndctl_dimm_ops) { - .smart_get_health = papr_smart_get_health, - .smart_get_shutdown_state = papr_smart_get_shutdown_state, - .smart_get_life_used = papr_smart_get_life_used, -+ .smart_get_shutdown_count = papr_smart_get_shutdown_count, - }; -diff --git a/ndctl/lib/papr_pdsm.h b/ndctl/lib/papr_pdsm.h -index 1bac8a7..f45b1e4 100644 ---- a/ndctl/lib/papr_pdsm.h -+++ b/ndctl/lib/papr_pdsm.h -@@ -75,6 +75,9 @@ - /* Indicate that the 'dimm_fuel_gauge' field is valid */ - #define PDSM_DIMM_HEALTH_RUN_GAUGE_VALID 1 - -+/* Indicate that the 'dimm_dsc' field is valid */ -+#define PDSM_DIMM_DSC_VALID 2 -+ - /* - * Struct exchanged between kernel & ndctl in for PAPR_PDSM_HEALTH - * Various flags indicate the health status of the dimm. -@@ -103,6 +106,9 @@ struct nd_papr_pdsm_health { - - /* Extension flag PDSM_DIMM_HEALTH_RUN_GAUGE_VALID */ - __u16 dimm_fuel_gauge; -+ -+ /* Extension flag PDSM_DIMM_DSC_VALID */ -+ __u64 dimm_dsc; - }; - __u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE]; - }; --- -2.27.0 - diff --git a/SOURCES/0126-libndctl-intel-Indicate-supported-smart-inject-types.patch b/SOURCES/0126-libndctl-intel-Indicate-supported-smart-inject-types.patch deleted file mode 100644 index d22c569..0000000 --- a/SOURCES/0126-libndctl-intel-Indicate-supported-smart-inject-types.patch +++ /dev/null @@ -1,161 +0,0 @@ -From edcd9b7e10b3b33a9660e412a2db1beab30936d3 Mon Sep 17 00:00:00 2001 -From: Vaibhav Jain -Date: Tue, 25 Jan 2022 02:07:35 +0530 -Subject: [PATCH 126/217] libndctl, intel: Indicate supported smart-inject - types - -Presently the inject-smart code assumes support for injecting all -smart-errors namely media-temperature, controller-temperature, -spares-remaining, fatal-health and unsafe-shutdown. This assumption -may break in case of other non-Intel NVDIMM types namely PAPR NVDIMMs -which presently only have support for injecting unsafe-shutdown and -fatal health events. - -Trying to inject-smart errors on PAPR NVDIMMs causes problems as -smart_inject() prematurely exits when trying to inject -media-temperature smart-error errors out. - -To fix this issue the patch proposes extending the definition of -dimm_op 'smart_inject_supported' to return bitmap of flags indicating -the type of smart-error injections supported by an NVDIMM. These types -are indicated by the newly introduced defines ND_SMART_INJECT_* . A -dimm-ops provide can return an bitmap composed of these flags back -from its implementation of 'smart_inject_supported' to indicate to -dimm_inject_smart() which type of smart-error injection it -supports. In case of an error the dimm-op is still expected to return -a negative error code back to the caller. - -The patch updates intel_dimm_smart_inject_supported() to return a -bitmap composed of all ND_SMART_INJECT_* flags to indicate support for -all smart-error types. - -Finally the patch also updates smart_inject() to test for specific -ND_START_INJECT_* flags before sending a smart-inject command via -dimm-provider. - -Link: https://lore.kernel.org/r/20220124203735.1490186-1-vaibhav@linux.ibm.com -Reviewed-by: Ira Weiny -Signed-off-by: Vaibhav Jain -Signed-off-by: Vishal Verma ---- - ndctl/inject-smart.c | 31 ++++++++++++++++++++++++------- - ndctl/lib/intel.c | 7 ++++++- - ndctl/libndctl.h | 8 ++++++++ - 3 files changed, 38 insertions(+), 8 deletions(-) - -diff --git a/ndctl/inject-smart.c b/ndctl/inject-smart.c -index 2b9d7e8..bd8c01e 100644 ---- a/ndctl/inject-smart.c -+++ b/ndctl/inject-smart.c -@@ -395,18 +395,26 @@ out: - } \ - } - --static int smart_inject(struct ndctl_dimm *dimm) -+static int smart_inject(struct ndctl_dimm *dimm, unsigned int inject_types) - { - const char *name = ndctl_dimm_get_devname(dimm); - struct ndctl_cmd *si_cmd = NULL; - int rc = -EOPNOTSUPP; - -- send_inject_val(media_temperature) -- send_inject_val(ctrl_temperature) -- send_inject_val(spares) -- send_inject_bool(fatal) -- send_inject_bool(unsafe_shutdown) -+ if (inject_types & ND_SMART_INJECT_MEDIA_TEMPERATURE) -+ send_inject_val(media_temperature); - -+ if (inject_types & ND_SMART_INJECT_CTRL_TEMPERATURE) -+ send_inject_val(ctrl_temperature); -+ -+ if (inject_types & ND_SMART_INJECT_SPARES_REMAINING) -+ send_inject_val(spares); -+ -+ if (inject_types & ND_SMART_INJECT_HEALTH_STATE) -+ send_inject_bool(fatal); -+ -+ if (inject_types & ND_SMART_INJECT_UNCLEAN_SHUTDOWN) -+ send_inject_bool(unsafe_shutdown); - out: - ndctl_cmd_unref(si_cmd); - return rc; -@@ -417,6 +425,7 @@ static int dimm_inject_smart(struct ndctl_dimm *dimm) - struct json_object *jhealth; - struct json_object *jdimms; - struct json_object *jdimm; -+ unsigned int supported_types; - int rc; - - rc = ndctl_dimm_smart_inject_supported(dimm); -@@ -433,6 +442,14 @@ static int dimm_inject_smart(struct ndctl_dimm *dimm) - error("%s: smart injection not supported by either platform firmware or the kernel.", - ndctl_dimm_get_devname(dimm)); - return rc; -+ default: -+ if (rc < 0) { -+ error("%s: Unknown error %d while checking for smart injection support", -+ ndctl_dimm_get_devname(dimm), rc); -+ return rc; -+ } -+ supported_types = rc; -+ break; - } - - if (sctx.op_mask & (1 << OP_SET)) { -@@ -441,7 +458,7 @@ static int dimm_inject_smart(struct ndctl_dimm *dimm) - goto out; - } - if (sctx.op_mask & (1 << OP_INJECT)) { -- rc = smart_inject(dimm); -+ rc = smart_inject(dimm, supported_types); - if (rc) - goto out; - } -diff --git a/ndctl/lib/intel.c b/ndctl/lib/intel.c -index a3df26e..1314854 100644 ---- a/ndctl/lib/intel.c -+++ b/ndctl/lib/intel.c -@@ -455,7 +455,12 @@ static int intel_dimm_smart_inject_supported(struct ndctl_dimm *dimm) - return -EIO; - } - -- return 0; -+ /* Indicate all smart injection types are supported */ -+ return ND_SMART_INJECT_SPARES_REMAINING | -+ ND_SMART_INJECT_MEDIA_TEMPERATURE | -+ ND_SMART_INJECT_CTRL_TEMPERATURE | -+ ND_SMART_INJECT_HEALTH_STATE | -+ ND_SMART_INJECT_UNCLEAN_SHUTDOWN; - } - - static const char *intel_cmd_desc(int fn) -diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h -index b59026c..4d5cdbf 100644 ---- a/ndctl/libndctl.h -+++ b/ndctl/libndctl.h -@@ -69,6 +69,13 @@ extern "C" { - #define ND_EVENT_HEALTH_STATE (1 << 3) - #define ND_EVENT_UNCLEAN_SHUTDOWN (1 << 4) - -+/* Flags indicating support for various smart injection types */ -+#define ND_SMART_INJECT_SPARES_REMAINING (1 << 0) -+#define ND_SMART_INJECT_MEDIA_TEMPERATURE (1 << 1) -+#define ND_SMART_INJECT_CTRL_TEMPERATURE (1 << 2) -+#define ND_SMART_INJECT_HEALTH_STATE (1 << 3) -+#define ND_SMART_INJECT_UNCLEAN_SHUTDOWN (1 << 4) -+ - size_t ndctl_min_namespace_size(void); - size_t ndctl_sizeof_namespace_index(void); - size_t ndctl_sizeof_namespace_label(void); -@@ -311,6 +318,7 @@ int ndctl_cmd_smart_inject_spares(struct ndctl_cmd *cmd, bool enable, - unsigned int spares); - int ndctl_cmd_smart_inject_fatal(struct ndctl_cmd *cmd, bool enable); - int ndctl_cmd_smart_inject_unsafe_shutdown(struct ndctl_cmd *cmd, bool enable); -+/* Returns a bitmap of ND_SMART_INJECT_* supported */ - int ndctl_dimm_smart_inject_supported(struct ndctl_dimm *dimm); - - struct ndctl_cmd *ndctl_dimm_cmd_new_vendor_specific(struct ndctl_dimm *dimm, --- -2.27.0 - diff --git a/SOURCES/0127-libndctl-papr-Add-limited-support-for-inject-smart.patch b/SOURCES/0127-libndctl-papr-Add-limited-support-for-inject-smart.patch deleted file mode 100644 index 8a379b1..0000000 --- a/SOURCES/0127-libndctl-papr-Add-limited-support-for-inject-smart.patch +++ /dev/null @@ -1,180 +0,0 @@ -From 9ef460eb7fd1b1f286955b18db8c18cd1a640e77 Mon Sep 17 00:00:00 2001 -From: Vaibhav Jain -Date: Tue, 25 Jan 2022 02:08:04 +0530 -Subject: [PATCH 127/217] libndctl/papr: Add limited support for inject-smart - -Implements support for ndctl inject-smart command by providing an -implementation of 'smart_inject*' dimm-ops callbacks. Presently only -support for injecting unsafe-shutdown and fatal-health states is -available. - -The patch also introduce various PAPR PDSM structures that are used to -communicate the inject-smart errors to the papr_scm kernel -module. This is done via SMART_INJECT PDSM which sends a payload of -type 'struct nd_papr_pdsm_smart_inject'. - -With the patch following output from ndctl inject-smart command is -expected for PAPR NVDIMMs: - -$ sudo ndctl inject-smart -fU nmem0 -[ - { - "dev":"nmem0", - "flag_failed_flush":true, - "flag_smart_event":true, - "health":{ - "health_state":"fatal", - "shutdown_state":"dirty", - "shutdown_count":0 - } - } -] - -$ sudo ndctl inject-smart -N nmem0 -[ - { - "dev":"nmem0", - "health":{ - "health_state":"ok", - "shutdown_state":"clean", - "shutdown_count":0 - } - } -] - -The patch depends on the kernel PAPR PDSM implementation for -PDSM_SMART_INJECT posted at [1]. - -[1] : https://lore.kernel.org/nvdimm/20220124202204.1488346-1-vaibhav@linux.ibm.com/ - -Link: https://lore.kernel.org/r/20220124203804.1490254-1-vaibhav@linux.ibm.com -Reviewed-by: Ira Weiny -Signed-off-by: Shivaprasad G Bhat -Signed-off-by: Vaibhav Jain -Signed-off-by: Vishal Verma ---- - ndctl/lib/papr.c | 61 +++++++++++++++++++++++++++++++++++++++++++ - ndctl/lib/papr_pdsm.h | 17 ++++++++++++ - 2 files changed, 78 insertions(+) - -diff --git a/ndctl/lib/papr.c b/ndctl/lib/papr.c -index 46cf9c1..7a1d559 100644 ---- a/ndctl/lib/papr.c -+++ b/ndctl/lib/papr.c -@@ -221,6 +221,41 @@ static unsigned int papr_smart_get_shutdown_state(struct ndctl_cmd *cmd) - return health.dimm_bad_shutdown; - } - -+static int papr_smart_inject_supported(struct ndctl_dimm *dimm) -+{ -+ if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_CALL)) -+ return -EOPNOTSUPP; -+ -+ if (!test_dimm_dsm(dimm, PAPR_PDSM_SMART_INJECT)) -+ return -EIO; -+ -+ return ND_SMART_INJECT_HEALTH_STATE | ND_SMART_INJECT_UNCLEAN_SHUTDOWN; -+} -+ -+static int papr_smart_inject_valid(struct ndctl_cmd *cmd) -+{ -+ if (cmd->type != ND_CMD_CALL || -+ to_pdsm(cmd)->cmd_status != 0 || -+ to_pdsm_cmd(cmd) != PAPR_PDSM_SMART_INJECT) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static struct ndctl_cmd *papr_new_smart_inject(struct ndctl_dimm *dimm) -+{ -+ struct ndctl_cmd *cmd; -+ -+ cmd = allocate_cmd(dimm, PAPR_PDSM_SMART_INJECT, -+ sizeof(struct nd_papr_pdsm_smart_inject)); -+ if (!cmd) -+ return NULL; -+ /* Set the input payload size */ -+ to_ndcmd(cmd)->nd_size_in = ND_PDSM_HDR_SIZE + -+ sizeof(struct nd_papr_pdsm_smart_inject); -+ return cmd; -+} -+ - static unsigned int papr_smart_get_life_used(struct ndctl_cmd *cmd) - { - struct nd_papr_pdsm_health health; -@@ -255,11 +290,37 @@ static unsigned int papr_smart_get_shutdown_count(struct ndctl_cmd *cmd) - - return (health.extension_flags & PDSM_DIMM_DSC_VALID) ? - (health.dimm_dsc) : 0; -+} -+ -+static int papr_cmd_smart_inject_fatal(struct ndctl_cmd *cmd, bool enable) -+{ -+ if (papr_smart_inject_valid(cmd) < 0) -+ return -EINVAL; -+ -+ to_payload(cmd)->inject.flags |= PDSM_SMART_INJECT_HEALTH_FATAL; -+ to_payload(cmd)->inject.fatal_enable = enable; - -+ return 0; -+} -+ -+static int papr_cmd_smart_inject_unsafe_shutdown(struct ndctl_cmd *cmd, -+ bool enable) -+{ -+ if (papr_smart_inject_valid(cmd) < 0) -+ return -EINVAL; -+ -+ to_payload(cmd)->inject.flags |= PDSM_SMART_INJECT_BAD_SHUTDOWN; -+ to_payload(cmd)->inject.unsafe_shutdown_enable = enable; -+ -+ return 0; - } - - struct ndctl_dimm_ops * const papr_dimm_ops = &(struct ndctl_dimm_ops) { - .cmd_is_supported = papr_cmd_is_supported, -+ .new_smart_inject = papr_new_smart_inject, -+ .smart_inject_supported = papr_smart_inject_supported, -+ .smart_inject_fatal = papr_cmd_smart_inject_fatal, -+ .smart_inject_unsafe_shutdown = papr_cmd_smart_inject_unsafe_shutdown, - .smart_get_flags = papr_smart_get_flags, - .get_firmware_status = papr_get_firmware_status, - .xlat_firmware_status = papr_xlat_firmware_status, -diff --git a/ndctl/lib/papr_pdsm.h b/ndctl/lib/papr_pdsm.h -index f45b1e4..20ac20f 100644 ---- a/ndctl/lib/papr_pdsm.h -+++ b/ndctl/lib/papr_pdsm.h -@@ -121,12 +121,29 @@ struct nd_papr_pdsm_health { - enum papr_pdsm { - PAPR_PDSM_MIN = 0x0, - PAPR_PDSM_HEALTH, -+ PAPR_PDSM_SMART_INJECT, - PAPR_PDSM_MAX, - }; -+/* Flags for injecting specific smart errors */ -+#define PDSM_SMART_INJECT_HEALTH_FATAL (1 << 0) -+#define PDSM_SMART_INJECT_BAD_SHUTDOWN (1 << 1) -+ -+struct nd_papr_pdsm_smart_inject { -+ union { -+ struct { -+ /* One or more of PDSM_SMART_INJECT_ */ -+ __u32 flags; -+ __u8 fatal_enable; -+ __u8 unsafe_shutdown_enable; -+ }; -+ __u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE]; -+ }; -+}; - - /* Maximal union that can hold all possible payload types */ - union nd_pdsm_payload { - struct nd_papr_pdsm_health health; -+ struct nd_papr_pdsm_smart_inject inject; - __u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE]; - } __attribute__((packed)); - --- -2.27.0 - diff --git a/SOURCES/0128-ndtest-ack-shutdown-count-Skip-the-test-on-ndtest.patch b/SOURCES/0128-ndtest-ack-shutdown-count-Skip-the-test-on-ndtest.patch deleted file mode 100644 index fbf92a7..0000000 --- a/SOURCES/0128-ndtest-ack-shutdown-count-Skip-the-test-on-ndtest.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 6e85cac1958f920f231b94ff570ac0e434595b7d Mon Sep 17 00:00:00 2001 -From: Shivaprasad G Bhat -Date: Tue, 25 Jan 2022 02:34:25 +0530 -Subject: [PATCH 128/217] ndtest/ack-shutdown-count: Skip the test on ndtest - -The PAPR has non-latched dirty shutdown implementation. -The test is enabling/disabling the LSS latch which is -irrelavent from PAPR pov. Skip the test. - -Link: https://lore.kernel.org/r/20220124210425.1493410-1-vaibhav@linux.ibm.com -Signed-off-by: Shivaprasad G Bhat -Signed-off-by: Vishal Verma ---- - test/ack-shutdown-count-set.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/test/ack-shutdown-count-set.c b/test/ack-shutdown-count-set.c -index a9e95c6..f091a40 100644 ---- a/test/ack-shutdown-count-set.c -+++ b/test/ack-shutdown-count-set.c -@@ -117,6 +117,7 @@ static int test_ack_shutdown_count_set(int loglevel, struct ndctl_test *test, - - int main(int argc, char *argv[]) - { -+ char *test_env = getenv("NDCTL_TEST_FAMILY"); - struct ndctl_test *test = ndctl_test_new(0); - struct ndctl_ctx *ctx; - int rc; -@@ -126,6 +127,9 @@ int main(int argc, char *argv[]) - return EXIT_FAILURE; - } - -+ if (test_env && strcmp(test_env, "PAPR") == 0) -+ return ndctl_test_result(test, 77); -+ - rc = ndctl_new(&ctx); - if (rc) - return ndctl_test_result(test, rc); --- -2.27.0 - diff --git a/SOURCES/0129-ndctl-libndctl-Update-nvdimm-flags-after-smart-injec.patch b/SOURCES/0129-ndctl-libndctl-Update-nvdimm-flags-after-smart-injec.patch deleted file mode 100644 index 9ebc6cc..0000000 --- a/SOURCES/0129-ndctl-libndctl-Update-nvdimm-flags-after-smart-injec.patch +++ /dev/null @@ -1,218 +0,0 @@ -From c5ccbf29c54b5a3d9cb1c138c06c8d5ac3ee80c2 Mon Sep 17 00:00:00 2001 -From: Vaibhav Jain -Date: Tue, 22 Feb 2022 17:45:19 +0530 -Subject: [PATCH 129/217] ndctl,libndctl: Update nvdimm flags after - smart-inject - -Presently after performing an inject-smart command the nvdimm flags reported are -out of date as shown below where no 'smart_notify' or 'flush_fail' flags were -reported even though they are set after injecting the smart error: - -$ sudo ndctl inject-smart -fU nmem0 -[ - { - "dev":"nmem0", - "health":{ - "health_state":"fatal", - "shutdown_state":"dirty", - "shutdown_count":0 - } - } -] -$ sudo cat /sys/class/nd/ndctl0/device/nmem0/papr/flags -flush_fail smart_notify - -This happens because nvdimm flags are only parsed once during its probe -and not refreshed even after a inject-smart operation makes them out of -date. To fix this the patch forces an update of nvdimm flags via newly -introduced export from libndctl named ndctl_dimm_refresh_flags() thats called -from dimm_inject_smart() after inject-smart command is successfully -submitted. This ensures that correct nvdimm flags are displayed later in that -function. With this implemented correct nvdimm flags are reported after a -inject-smart operation: - -$ sudo ndctl inject-smart -fU nmem0 -[ - { - "dev":"nmem0", - "flag_failed_flush":true, - "flag_smart_event":true, - "health":{ - "health_state":"fatal", - "shutdown_state":"dirty", - "shutdown_count":0 - } - } -] - -The patch refactors populate_dimm_attributes() to move the nvdimm flags -parsing code to the newly introduced ndctl_dimm_refresh_flags() -export. Since reading nvdimm flags requires constructing path using -'bus_prefix' which is only available during add_dimm(), the patch -introduces a new member 'struct ndctl_dimm.bus_prefix' to cache its -value. During ndctl_dimm_refresh_flags() the cached bus_prefix is used to -read the contents of the nvdimm flag file and pass it on to the appropriate -flag parsing function. Finally dimm_inject_smart() is updated to issue call to -ndctl_dimm_refresh_flags() before generating json output of the nvdimm status - -Link: https://lore.kernel.org/r/20220222121519.1674117-1-vaibhav@linux.ibm.com -Signed-off-by: Vaibhav Jain -Signed-off-by: Shivaprasad G Bhat -Signed-off-by: Vishal Verma ---- - ndctl/inject-smart.c | 4 +++ - ndctl/lib/libndctl.c | 55 +++++++++++++++++++++++++++++++----------- - ndctl/lib/libndctl.sym | 4 +++ - ndctl/lib/private.h | 1 + - ndctl/libndctl.h | 1 + - 5 files changed, 51 insertions(+), 14 deletions(-) - -diff -up ndctl-71.1/ndctl/inject-smart.c.orig ndctl-71.1/ndctl/inject-smart.c ---- ndctl-71.1/ndctl/inject-smart.c.orig 2022-10-07 16:40:24.610615979 -0400 -+++ ndctl-71.1/ndctl/inject-smart.c 2022-10-07 16:40:35.031651459 -0400 -@@ -467,6 +467,10 @@ static int dimm_inject_smart(struct ndct - jdimms = json_object_new_array(); - if (!jdimms) - goto out; -+ -+ /* Ensure the dimm flags are upto date before reporting them */ -+ ndctl_dimm_refresh_flags(dimm); -+ - jdimm = util_dimm_to_json(dimm, sctx.flags); - if (!jdimm) - goto out; -diff -up ndctl-71.1/ndctl/lib/libndctl.c.orig ndctl-71.1/ndctl/lib/libndctl.c ---- ndctl-71.1/ndctl/lib/libndctl.c.orig 2022-10-07 16:40:24.608615972 -0400 -+++ ndctl-71.1/ndctl/lib/libndctl.c 2022-10-07 16:40:35.032651462 -0400 -@@ -588,6 +588,7 @@ static void free_dimm(struct ndctl_dimm - free(dimm->unique_id); - free(dimm->dimm_buf); - free(dimm->dimm_path); -+ free(dimm->bus_prefix); - if (dimm->module) - kmod_module_unref(dimm->module); - if (dimm->health_eventfd > -1) -@@ -1645,14 +1646,34 @@ static enum ndctl_fwa_result fwa_result_ - return NDCTL_FWA_RESULT_INVALID; - } - -+NDCTL_EXPORT void ndctl_dimm_refresh_flags(struct ndctl_dimm *dimm) -+{ -+ struct ndctl_ctx *ctx = dimm->bus->ctx; -+ char *path = dimm->dimm_buf; -+ char buf[SYSFS_ATTR_SIZE]; -+ -+ /* Construct path to dimm flags sysfs file */ -+ sprintf(path, "%s/%s/flags", dimm->dimm_path, dimm->bus_prefix); -+ -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ return; -+ -+ /* Reset the flags */ -+ dimm->flags.flags = 0; -+ if (ndctl_bus_has_nfit(dimm->bus)) -+ parse_nfit_mem_flags(dimm, buf); -+ else if (ndctl_bus_is_papr_scm(dimm->bus)) -+ parse_papr_flags(dimm, buf); -+} -+ - static int populate_dimm_attributes(struct ndctl_dimm *dimm, -- const char *dimm_base, -- const char *bus_prefix) -+ const char *dimm_base) - { - int i, rc = -1; - char buf[SYSFS_ATTR_SIZE]; - struct ndctl_ctx *ctx = dimm->bus->ctx; - char *path = calloc(1, strlen(dimm_base) + 100); -+ const char *bus_prefix = dimm->bus_prefix; - - if (!path) - return -ENOMEM; -@@ -1736,16 +1757,10 @@ static int populate_dimm_attributes(stru - } - - sprintf(path, "%s/%s/flags", dimm_base, bus_prefix); -- if (sysfs_read_attr(ctx, path, buf) == 0) { -- if (ndctl_bus_has_nfit(dimm->bus)) -- parse_nfit_mem_flags(dimm, buf); -- else if (ndctl_bus_is_papr_scm(dimm->bus)) { -- dimm->cmd_family = NVDIMM_FAMILY_PAPR; -- parse_papr_flags(dimm, buf); -- } -- } -- - dimm->health_eventfd = open(path, O_RDONLY|O_CLOEXEC); -+ -+ ndctl_dimm_refresh_flags(dimm); -+ - rc = 0; - err_read: - -@@ -1801,8 +1816,9 @@ static int add_papr_dimm(struct ndctl_di - - rc = 0; - } else if (strcmp(buf, "nvdimm_test") == 0) { -+ dimm->cmd_family = NVDIMM_FAMILY_PAPR; - /* probe via common populate_dimm_attributes() */ -- rc = populate_dimm_attributes(dimm, dimm_base, "papr"); -+ rc = populate_dimm_attributes(dimm, dimm_base); - } - out: - free(path); -@@ -1899,9 +1915,20 @@ static void *add_dimm(void *parent, int - dimm->formats = formats; - /* Check if the given dimm supports nfit */ - if (ndctl_bus_has_nfit(bus)) { -- rc = populate_dimm_attributes(dimm, dimm_base, "nfit"); -+ dimm->bus_prefix = strdup("nfit"); -+ if (!dimm->bus_prefix) { -+ rc = -ENOMEM; -+ goto out; -+ } -+ rc = populate_dimm_attributes(dimm, dimm_base); -+ - } else if (ndctl_bus_has_of_node(bus)) { -- rc = add_papr_dimm(dimm, dimm_base); -+ dimm->bus_prefix = strdup("papr"); -+ if (!dimm->bus_prefix) { -+ rc = -ENOMEM; -+ goto out; -+ } -+ rc = add_papr_dimm(dimm, dimm_base); - } - - if (rc == -ENODEV) { -diff -up ndctl-71.1/ndctl/lib/libndctl.sym.orig ndctl-71.1/ndctl/lib/libndctl.sym ---- ndctl-71.1/ndctl/lib/libndctl.sym.orig 2022-10-07 16:40:24.344615073 -0400 -+++ ndctl-71.1/ndctl/lib/libndctl.sym 2022-10-07 16:40:35.032651462 -0400 -@@ -456,3 +456,7 @@ LIBNDCTL_26 { - ndctl_bus_nfit_translate_spa; - ndctl_dimm_sizeof_namespace_index; - } LIBNDCTL_25; -+ -+LIBNDCTL_27 { -+ ndctl_dimm_refresh_flags; -+} LIBNDCTL_26; -diff -up ndctl-71.1/ndctl/lib/private.h.orig ndctl-71.1/ndctl/lib/private.h ---- ndctl-71.1/ndctl/lib/private.h.orig 2022-10-07 16:40:24.455615451 -0400 -+++ ndctl-71.1/ndctl/lib/private.h 2022-10-07 16:40:35.032651462 -0400 -@@ -75,6 +75,7 @@ struct ndctl_dimm { - char *unique_id; - char *dimm_path; - char *dimm_buf; -+ char *bus_prefix; - int health_eventfd; - int buf_len; - int id; -diff -up ndctl-71.1/ndctl/libndctl.h.orig ndctl-71.1/ndctl/libndctl.h ---- ndctl-71.1/ndctl/libndctl.h.orig 2022-10-07 16:40:24.611615982 -0400 -+++ ndctl-71.1/ndctl/libndctl.h 2022-10-07 16:40:35.033651466 -0400 -@@ -221,6 +221,7 @@ int ndctl_dimm_is_active(struct ndctl_di - int ndctl_dimm_is_enabled(struct ndctl_dimm *dimm); - int ndctl_dimm_disable(struct ndctl_dimm *dimm); - int ndctl_dimm_enable(struct ndctl_dimm *dimm); -+void ndctl_dimm_refresh_flags(struct ndctl_dimm *dimm); - - struct ndctl_cmd; - struct ndctl_cmd *ndctl_bus_cmd_new_ars_cap(struct ndctl_bus *bus, diff --git a/SOURCES/0132-libcxl-add-GET_PARTITION_INFO-mailbox-command-and-ac.patch b/SOURCES/0132-libcxl-add-GET_PARTITION_INFO-mailbox-command-and-ac.patch deleted file mode 100644 index c0dfe6d..0000000 --- a/SOURCES/0132-libcxl-add-GET_PARTITION_INFO-mailbox-command-and-ac.patch +++ /dev/null @@ -1,202 +0,0 @@ -From 4f588b964dccf72030b1c432ed5dd8e2856f9d38 Mon Sep 17 00:00:00 2001 -From: Alison Schofield -Date: Tue, 22 Feb 2022 11:56:03 -0800 -Subject: [PATCH 132/217] libcxl: add GET_PARTITION_INFO mailbox command and - accessors - -The CXL PMEM provisioning model depends upon the values reported -in the CXL GET_PARTITION_INFO mailbox command when changing the -partitioning between volatile and persistent capacity. - -Add libcxl APIs to create a new GET_PARTITION_INFO mailbox command, -the command output data structure (privately), and accessor APIs to -return the fields in the partition info output. - -Per the CXL 2.0 specification, devices report partition capacities -as multiples of 256MB. Define and use a capacity multiplier to -convert the raw data into bytes for user consumption. Use byte -format as the norm for all capacity values produced or consumed -using CXL Mailbox commands. - -Link: https://lore.kernel.org/r/6cd7fffe1a95c9a1bc2239cb342067df564401a5.1645558189.git.alison.schofield@intel.com -Reviewed-by: Dan Williams -Signed-off-by: Alison Schofield -Signed-off-by: Vishal Verma ---- - Documentation/cxl/lib/libcxl.txt | 1 + - cxl/lib/libcxl.c | 66 ++++++++++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 5 +++ - cxl/lib/private.h | 10 +++++ - cxl/libcxl.h | 5 +++ - util/size.h | 1 + - 6 files changed, 88 insertions(+) - -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 4392b47..a6986ab 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -131,6 +131,7 @@ int cxl_memdev_read_label(struct cxl_memdev *memdev, void *buf, size_t length, - size_t offset); - int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf, size_t length, - size_t offset); -+struct cxl_cmd *cxl_cmd_new_get_partition(struct cxl_memdev *memdev); - - ---- - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index e0b443f..4557a71 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -1985,6 +1985,11 @@ static int cxl_cmd_validate_status(struct cxl_cmd *cmd, u32 id) - return 0; - } - -+static uint64_t cxl_capacity_to_bytes(leint64_t size) -+{ -+ return le64_to_cpu(size) * CXL_CAPACITY_MULTIPLIER; -+} -+ - /* Helpers for health_info fields (no endian conversion) */ - #define cmd_get_field_u8(cmd, n, N, field) \ - do { \ -@@ -2371,6 +2376,67 @@ CXL_EXPORT ssize_t cxl_cmd_read_label_get_payload(struct cxl_cmd *cmd, - return length; - } - -+CXL_EXPORT struct cxl_cmd *cxl_cmd_new_get_partition(struct cxl_memdev *memdev) -+{ -+ return cxl_cmd_new_generic(memdev, -+ CXL_MEM_COMMAND_ID_GET_PARTITION_INFO); -+} -+ -+static struct cxl_cmd_get_partition * -+cmd_to_get_partition(struct cxl_cmd *cmd) -+{ -+ if (cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_GET_PARTITION_INFO)) -+ return NULL; -+ -+ if (!cmd) -+ return NULL; -+ return cmd->output_payload; -+} -+ -+CXL_EXPORT unsigned long long -+cxl_cmd_partition_get_active_volatile_size(struct cxl_cmd *cmd) -+{ -+ struct cxl_cmd_get_partition *c; -+ -+ c = cmd_to_get_partition(cmd); -+ if (!c) -+ return ULLONG_MAX; -+ return cxl_capacity_to_bytes(c->active_volatile); -+} -+ -+CXL_EXPORT unsigned long long -+cxl_cmd_partition_get_active_persistent_size(struct cxl_cmd *cmd) -+{ -+ struct cxl_cmd_get_partition *c; -+ -+ c = cmd_to_get_partition(cmd); -+ if (!c) -+ return ULLONG_MAX; -+ return cxl_capacity_to_bytes(c->active_persistent); -+} -+ -+CXL_EXPORT unsigned long long -+cxl_cmd_partition_get_next_volatile_size(struct cxl_cmd *cmd) -+{ -+ struct cxl_cmd_get_partition *c; -+ -+ c = cmd_to_get_partition(cmd); -+ if (!c) -+ return ULLONG_MAX; -+ return cxl_capacity_to_bytes(c->next_volatile); -+} -+ -+CXL_EXPORT unsigned long long -+cxl_cmd_partition_get_next_persistent_size(struct cxl_cmd *cmd) -+{ -+ struct cxl_cmd_get_partition *c; -+ -+ c = cmd_to_get_partition(cmd); -+ if (!c) -+ return ULLONG_MAX; -+ return cxl_capacity_to_bytes(c->next_persistent); -+} -+ - CXL_EXPORT int cxl_cmd_submit(struct cxl_cmd *cmd) - { - struct cxl_memdev *memdev = cmd->memdev; -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index e56a2bf..509e62d 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -155,4 +155,9 @@ global: - cxl_dport_get_port; - cxl_port_get_dport_by_memdev; - cxl_dport_maps_memdev; -+ cxl_cmd_new_get_partition; -+ cxl_cmd_partition_get_active_volatile_size; -+ cxl_cmd_partition_get_active_persistent_size; -+ cxl_cmd_partition_get_next_volatile_size; -+ cxl_cmd_partition_get_next_persistent_size; - } LIBCXL_1; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index f483c30..7f3a562 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - - #define CXL_EXPORT __attribute__ ((visibility("default"))) - -@@ -185,6 +186,15 @@ struct cxl_cmd_get_health_info { - le32 pmem_errors; - } __attribute__((packed)); - -+struct cxl_cmd_get_partition { -+ le64 active_volatile; -+ le64 active_persistent; -+ le64 next_volatile; -+ le64 next_persistent; -+} __attribute__((packed)); -+ -+#define CXL_CAPACITY_MULTIPLIER SZ_256M -+ - /* CXL 2.0 8.2.9.5.3 Byte 0 Health Status */ - #define CXL_CMD_HEALTH_INFO_STATUS_MAINTENANCE_NEEDED_MASK BIT(0) - #define CXL_CMD_HEALTH_INFO_STATUS_PERFORMANCE_DEGRADED_MASK BIT(1) -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 3b2293b..2c0a8d1 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -242,6 +242,11 @@ ssize_t cxl_cmd_read_label_get_payload(struct cxl_cmd *cmd, void *buf, - unsigned int length); - struct cxl_cmd *cxl_cmd_new_write_label(struct cxl_memdev *memdev, - void *buf, unsigned int offset, unsigned int length); -+struct cxl_cmd *cxl_cmd_new_get_partition(struct cxl_memdev *memdev); -+unsigned long long cxl_cmd_partition_get_active_volatile_size(struct cxl_cmd *cmd); -+unsigned long long cxl_cmd_partition_get_active_persistent_size(struct cxl_cmd *cmd); -+unsigned long long cxl_cmd_partition_get_next_volatile_size(struct cxl_cmd *cmd); -+unsigned long long cxl_cmd_partition_get_next_persistent_size(struct cxl_cmd *cmd); - - #ifdef __cplusplus - } /* extern "C" */ -diff --git a/util/size.h b/util/size.h -index a0f3593..e72467f 100644 ---- a/util/size.h -+++ b/util/size.h -@@ -15,6 +15,7 @@ - #define SZ_4M 0x00400000 - #define SZ_16M 0x01000000 - #define SZ_64M 0x04000000 -+#define SZ_256M 0x10000000 - #define SZ_1G 0x40000000 - #define SZ_1T 0x10000000000ULL - --- -2.27.0 - diff --git a/SOURCES/0133-libcxl-add-accessors-for-capacity-fields-of-the-IDEN.patch b/SOURCES/0133-libcxl-add-accessors-for-capacity-fields-of-the-IDEN.patch deleted file mode 100644 index e63b977..0000000 --- a/SOURCES/0133-libcxl-add-accessors-for-capacity-fields-of-the-IDEN.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 50b9d77232d41a33c2109894ae93ddad877c1747 Mon Sep 17 00:00:00 2001 -From: Alison Schofield -Date: Tue, 22 Feb 2022 11:56:04 -0800 -Subject: [PATCH 133/217] libcxl: add accessors for capacity fields of the - IDENTIFY command - -The CXL PMEM provisioning model depends upon the values reported -in the CXL IDENTIFY mailbox command when changing the partitioning -between volatile and persistent capacity. - -Add accessors to the libcxl API to retrieve the total, volatile only, -and persistent only capacities from the IDENTIFY command. - -The fields are specified in multiples of 256MB per the CXL 2.0 spec. -Use the capacity multiplier to convert the raw data into bytes for user -consumption. - -Link: https://lore.kernel.org/r/58dec40b15a68f134466f61421751994735e55c1.1645558189.git.alison.schofield@intel.com -Reviewed-by: Dan Williams -Signed-off-by: Alison Schofield -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 3 +++ - cxl/libcxl.h | 3 +++ - 3 files changed, 50 insertions(+) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 4557a71..9413384 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -2277,6 +2277,17 @@ CXL_EXPORT struct cxl_cmd *cxl_cmd_new_identify(struct cxl_memdev *memdev) - return cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_IDENTIFY); - } - -+static struct cxl_cmd_identify * -+cmd_to_identify(struct cxl_cmd *cmd) -+{ -+ if (cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_IDENTIFY)) -+ return NULL; -+ -+ if (!cmd) -+ return NULL; -+ return cmd->output_payload; -+} -+ - CXL_EXPORT int cxl_cmd_identify_get_fw_rev(struct cxl_cmd *cmd, char *fw_rev, - int fw_len) - { -@@ -2321,6 +2332,39 @@ CXL_EXPORT unsigned int cxl_cmd_identify_get_label_size(struct cxl_cmd *cmd) - return le32_to_cpu(id->lsa_size); - } - -+CXL_EXPORT unsigned long long -+cxl_cmd_identify_get_total_size(struct cxl_cmd *cmd) -+{ -+ struct cxl_cmd_identify *c; -+ -+ c = cmd_to_identify(cmd); -+ if (!c) -+ return ULLONG_MAX; -+ return cxl_capacity_to_bytes(c->total_capacity); -+} -+ -+CXL_EXPORT unsigned long long -+cxl_cmd_identify_get_volatile_only_size(struct cxl_cmd *cmd) -+{ -+ struct cxl_cmd_identify *c; -+ -+ c = cmd_to_identify(cmd); -+ if (!c) -+ return ULLONG_MAX; -+ return cxl_capacity_to_bytes(c->volatile_capacity); -+} -+ -+CXL_EXPORT unsigned long long -+cxl_cmd_identify_get_persistent_only_size(struct cxl_cmd *cmd) -+{ -+ struct cxl_cmd_identify *c; -+ -+ c = cmd_to_identify(cmd); -+ if (!c) -+ return ULLONG_MAX; -+ return cxl_capacity_to_bytes(c->persistent_capacity); -+} -+ - CXL_EXPORT struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, - int opcode) - { -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 509e62d..5ac6e9b 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -160,4 +160,7 @@ global: - cxl_cmd_partition_get_active_persistent_size; - cxl_cmd_partition_get_next_volatile_size; - cxl_cmd_partition_get_next_persistent_size; -+ cxl_cmd_identify_get_total_size; -+ cxl_cmd_identify_get_volatile_only_size; -+ cxl_cmd_identify_get_persistent_only_size; - } LIBCXL_1; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 2c0a8d1..6e18e84 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -201,6 +201,9 @@ int cxl_cmd_get_mbox_status(struct cxl_cmd *cmd); - int cxl_cmd_get_out_size(struct cxl_cmd *cmd); - struct cxl_cmd *cxl_cmd_new_identify(struct cxl_memdev *memdev); - int cxl_cmd_identify_get_fw_rev(struct cxl_cmd *cmd, char *fw_rev, int fw_len); -+unsigned long long cxl_cmd_identify_get_total_size(struct cxl_cmd *cmd); -+unsigned long long cxl_cmd_identify_get_volatile_only_size(struct cxl_cmd *cmd); -+unsigned long long cxl_cmd_identify_get_persistent_only_size(struct cxl_cmd *cmd); - unsigned long long cxl_cmd_identify_get_partition_align(struct cxl_cmd *cmd); - unsigned int cxl_cmd_identify_get_label_size(struct cxl_cmd *cmd); - struct cxl_cmd *cxl_cmd_new_get_health_info(struct cxl_memdev *memdev); --- -2.27.0 - diff --git a/SOURCES/0134-libcxl-return-the-partition-alignment-field-in-bytes.patch b/SOURCES/0134-libcxl-return-the-partition-alignment-field-in-bytes.patch deleted file mode 100644 index 621186b..0000000 --- a/SOURCES/0134-libcxl-return-the-partition-alignment-field-in-bytes.patch +++ /dev/null @@ -1,53 +0,0 @@ -From ac0066a6095e9ed0910fc560277ec693d3b507fa Mon Sep 17 00:00:00 2001 -From: Alison Schofield -Date: Tue, 22 Feb 2022 11:56:05 -0800 -Subject: [PATCH 134/217] libcxl: return the partition alignment field in bytes - -Per the CXL specification, the partition alignment field reports -the alignment value in multiples of 256MB. In the libcxl API, values -for all capacity fields are defined to return bytes. - -Update the partition alignment accessor to return bytes so that it -is in sync with other capacity related fields. - -Since this is early in the development cycle, the expectation is that -no third party consumers of this library have come to depend on the -encoded capacity field. If that is not the case, the original format -can be restored, and a new _bytes version introduced. - -Link: https://lore.kernel.org/r/6b937b09b61ddf95e069fd7acfda0c5bbb845be8.1645558189.git.alison.schofield@intel.com -Reviewed-by: Dan Williams -Signed-off-by: Alison Schofield -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 13 +++++-------- - 1 file changed, 5 insertions(+), 8 deletions(-) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 9413384..c05c13c 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -2308,15 +2308,12 @@ CXL_EXPORT int cxl_cmd_identify_get_fw_rev(struct cxl_cmd *cmd, char *fw_rev, - CXL_EXPORT unsigned long long cxl_cmd_identify_get_partition_align( - struct cxl_cmd *cmd) - { -- struct cxl_cmd_identify *id = -- (struct cxl_cmd_identify *)cmd->send_cmd->out.payload; -- -- if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_IDENTIFY) -- return -EINVAL; -- if (cmd->status < 0) -- return cmd->status; -+ struct cxl_cmd_identify *c; - -- return le64_to_cpu(id->partition_align); -+ c = cmd_to_identify(cmd); -+ if (!c) -+ return ULLONG_MAX; -+ return cxl_capacity_to_bytes(c->partition_align); - } - - CXL_EXPORT unsigned int cxl_cmd_identify_get_label_size(struct cxl_cmd *cmd) --- -2.27.0 - diff --git a/SOURCES/0135-cxl-add-memdev-partition-information-to-cxl-list.patch b/SOURCES/0135-cxl-add-memdev-partition-information-to-cxl-list.patch deleted file mode 100644 index c8220a3..0000000 --- a/SOURCES/0135-cxl-add-memdev-partition-information-to-cxl-list.patch +++ /dev/null @@ -1,267 +0,0 @@ -From 033b94ad7346a82504cffba3d87650b60945c1eb Mon Sep 17 00:00:00 2001 -From: Alison Schofield -Date: Tue, 22 Feb 2022 11:56:06 -0800 -Subject: [PATCH 135/217] cxl: add memdev partition information to cxl-list - -The CXL PMEM provisioning model depends upon the values reported in -both the CXL IDENTIFY and GET_PARTITION_INFO mailbox commands when -changing the partitioning between volatile and persistent capacity. - -Add an option to the 'cxl list' command to display partition information. - -Include the partitioning related fields from the IDENTIFY command: -total, volatile_only, persistent_only, and partition_alignment sizes. -When the partition_alignment size is greater than zero, indicating -partitionable capacity, include the active and next size fields of -GET_PARTITION_INFO. - -Example: - "partition_info":{ - "total_size":273535729664, - "volatile_only_size":0, - "persistent_only_size":0, - "partition_alignment_size":268435456 - "active_volatile_size":273535729664, - "active_persistent_size":0, - "next_volatile_size":0, - "next_persistent_size":0, - } - -Link: https://lore.kernel.org/r/70cc57379d2c49692036b1daa158a122aa19c126.1645558189.git.alison.schofield@intel.com -Reviewed-by: Dan Williams -Signed-off-by: Alison Schofield -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 23 +++++++ - cxl/filter.c | 2 + - cxl/filter.h | 1 + - cxl/json.c | 120 +++++++++++++++++++++++++++++++++ - cxl/list.c | 2 + - util/json.h | 1 + - 6 files changed, 149 insertions(+) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 90e6d9f..f6aba0c 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -196,6 +196,29 @@ OPTIONS - } - ] - ---- -+-I:: -+--partition:: -+ Include partition information in the memdev listing. Example listing: -+---- -+# cxl list -m mem0 -I -+[ -+ { -+ "memdev":"mem0", -+ "pmem_size":0, -+ "ram_size":273535729664, -+ "partition_info":{ -+ "total_size":273535729664, -+ "volatile_only_size":0, -+ "persistent_only_size":0, -+ "partition_alignment_size":268435456 -+ "active_volatile_size":273535729664, -+ "active_persistent_size":0, -+ "next_volatile_size":0, -+ "next_persistent_size":0, -+ } -+ } -+] -+---- - - -B:: - --buses:: -diff --git a/cxl/filter.c b/cxl/filter.c -index 925bf3a..b339642 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -581,6 +581,8 @@ static unsigned long params_to_flags(struct cxl_filter_params *param) - flags |= UTIL_JSON_HEALTH; - if (param->targets) - flags |= UTIL_JSON_TARGETS; -+ if (param->partition) -+ flags |= UTIL_JSON_PARTITION; - return flags; - } - -diff --git a/cxl/filter.h b/cxl/filter.h -index 5deabb3..697b777 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -23,6 +23,7 @@ struct cxl_filter_params { - bool idle; - bool human; - bool health; -+ bool partition; - struct log_ctx ctx; - }; - -diff --git a/cxl/json.c b/cxl/json.c -index f3b536e..fdc6f73 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -185,6 +185,121 @@ err_jobj: - return NULL; - } - -+/* -+ * Present complete view of memdev partition by presenting fields from -+ * both GET_PARTITION_INFO and IDENTIFY mailbox commands. -+ */ -+static struct json_object *util_cxl_memdev_partition_to_json(struct cxl_memdev *memdev, -+ unsigned long flags) -+{ -+ struct json_object *jobj = NULL; -+ struct json_object *jpart; -+ unsigned long long cap; -+ struct cxl_cmd *cmd; -+ int rc; -+ -+ jpart = json_object_new_object(); -+ if (!jpart) -+ return NULL; -+ if (!memdev) -+ goto err_jobj; -+ -+ /* Retrieve partition info in the IDENTIFY mbox cmd */ -+ cmd = cxl_cmd_new_identify(memdev); -+ if (!cmd) -+ goto err_jobj; -+ -+ rc = cxl_cmd_submit(cmd); -+ if (rc < 0) -+ goto err_identify; -+ rc = cxl_cmd_get_mbox_status(cmd); -+ if (rc != 0) -+ goto err_identify; -+ -+ cap = cxl_cmd_identify_get_total_size(cmd); -+ if (cap != ULLONG_MAX) { -+ jobj = util_json_object_size(cap, flags); -+ if (jobj) -+ json_object_object_add(jpart, "total_size", jobj); -+ } -+ cap = cxl_cmd_identify_get_volatile_only_size(cmd); -+ if (cap != ULLONG_MAX) { -+ jobj = util_json_object_size(cap, flags); -+ if (jobj) -+ json_object_object_add(jpart, -+ "volatile_only_size", jobj); -+ } -+ cap = cxl_cmd_identify_get_persistent_only_size(cmd); -+ if (cap != ULLONG_MAX) { -+ jobj = util_json_object_size(cap, flags); -+ if (jobj) -+ json_object_object_add(jpart, -+ "persistent_only_size", jobj); -+ } -+ cap = cxl_cmd_identify_get_partition_align(cmd); -+ jobj = util_json_object_size(cap, flags); -+ if (jobj) -+ json_object_object_add(jpart, "partition_alignment_size", jobj); -+ -+ cxl_cmd_unref(cmd); -+ -+ /* Return now if there is no partition info to get. */ -+ if (!cap) -+ return jpart; -+ -+ /* Retrieve partition info in GET_PARTITION_INFO mbox cmd */ -+ cmd = cxl_cmd_new_get_partition(memdev); -+ if (!cmd) -+ return jpart; -+ -+ rc = cxl_cmd_submit(cmd); -+ if (rc < 0) -+ goto err_get; -+ rc = cxl_cmd_get_mbox_status(cmd); -+ if (rc != 0) -+ goto err_get; -+ -+ cap = cxl_cmd_partition_get_active_volatile_size(cmd); -+ if (cap != ULLONG_MAX) { -+ jobj = util_json_object_size(cap, flags); -+ if (jobj) -+ json_object_object_add(jpart, -+ "active_volatile_size", jobj); -+ } -+ cap = cxl_cmd_partition_get_active_persistent_size(cmd); -+ if (cap != ULLONG_MAX) { -+ jobj = util_json_object_size(cap, flags); -+ if (jobj) -+ json_object_object_add(jpart, -+ "active_persistent_size", jobj); -+ } -+ cap = cxl_cmd_partition_get_next_volatile_size(cmd); -+ if (cap != ULLONG_MAX) { -+ jobj = util_json_object_size(cap, flags); -+ if (jobj) -+ json_object_object_add(jpart, -+ "next_volatile_size", jobj); -+ } -+ cap = cxl_cmd_partition_get_next_persistent_size(cmd); -+ if (cap != ULLONG_MAX) { -+ jobj = util_json_object_size(cap, flags); -+ if (jobj) -+ json_object_object_add(jpart, -+ "next_persistent_size", jobj); -+ } -+ -+err_get: -+ cxl_cmd_unref(cmd); -+ return jpart; -+ -+err_identify: -+ cxl_cmd_unref(cmd); -+ -+err_jobj: -+ json_object_put(jpart); -+ return NULL; -+} -+ - struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - unsigned long flags) - { -@@ -239,6 +354,11 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, - json_object_object_add(jdev, "state", jobj); - } - -+ if (flags & UTIL_JSON_PARTITION) { -+ jobj = util_cxl_memdev_partition_to_json(memdev, flags); -+ if (jobj) -+ json_object_object_add(jdev, "partition_info", jobj); -+ } - return jdev; - } - -diff --git a/cxl/list.c b/cxl/list.c -index de96ff9..1e9d441 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -48,6 +48,8 @@ static const struct option options[] = { - "use human friendly number formats "), - OPT_BOOLEAN('H', "health", ¶m.health, - "include memory device health information "), -+ OPT_BOOLEAN('I', "partition", ¶m.partition, -+ "include memory device partition information "), - #ifdef ENABLE_DEBUG - OPT_BOOLEAN(0, "debug", &debug, "debug list walk"), - #endif -diff --git a/util/json.h b/util/json.h -index e026df1..73bb9f0 100644 ---- a/util/json.h -+++ b/util/json.h -@@ -19,6 +19,7 @@ enum util_json_flags { - UTIL_JSON_DAX_MAPPINGS = (1 << 9), - UTIL_JSON_HEALTH = (1 << 10), - UTIL_JSON_TARGETS = (1 << 11), -+ UTIL_JSON_PARTITION = (1 << 12), - }; - - void util_display_json_array(FILE *f_out, struct json_object *jarray, --- -2.27.0 - diff --git a/SOURCES/0136-libcxl-add-interfaces-for-SET_PARTITION_INFO-mailbox.patch b/SOURCES/0136-libcxl-add-interfaces-for-SET_PARTITION_INFO-mailbox.patch deleted file mode 100644 index fc4253b..0000000 --- a/SOURCES/0136-libcxl-add-interfaces-for-SET_PARTITION_INFO-mailbox.patch +++ /dev/null @@ -1,154 +0,0 @@ -From b424b4bfd555654fc41996e964bdd0495f585793 Mon Sep 17 00:00:00 2001 -From: Alison Schofield -Date: Tue, 22 Feb 2022 11:56:07 -0800 -Subject: [PATCH 136/217] libcxl: add interfaces for SET_PARTITION_INFO mailbox - command - -The CXL PMEM provisioning model depends upon the CXL mailbox command -SET_PARTITION_INFO to change a device's partitioning between volatile -and persistent capacity. - -Add interfaces to libcxl to allocate and send a SET_PARTITION_INFO -mailbox command as defined in the CXL 2.0 specification. - -Link: https://lore.kernel.org/r/978c1cf78f3dd22f6070e51a241bc63cac9297de.1645558189.git.alison.schofield@intel.com -Reviewed-by: Dan Williams -Signed-off-by: Alison Schofield -Signed-off-by: Vishal Verma ---- - Documentation/cxl/lib/libcxl.txt | 11 +++++++++++ - cxl/lib/libcxl.c | 28 ++++++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 2 ++ - cxl/lib/private.h | 8 ++++++++ - cxl/libcxl.h | 10 ++++++++++ - 5 files changed, 59 insertions(+) - -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index a6986ab..7b223cb 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -132,6 +132,8 @@ int cxl_memdev_read_label(struct cxl_memdev *memdev, void *buf, size_t length, - int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf, size_t length, - size_t offset); - struct cxl_cmd *cxl_cmd_new_get_partition(struct cxl_memdev *memdev); -+struct cxl_cmd *cxl_cmd_new_set_partition(struct cxl_memdev *memdev, -+ unsigned long long volatile_size); - - ---- - -@@ -148,6 +150,8 @@ this sub-class of interfaces, there are: - a CXL standard opcode. See the potential command ids in - /usr/include/linux/cxl_mem.h. - -+ * 'cxl_cmd__set_' interfaces that set specific fields in a cxl_cmd -+ - * 'cxl_cmd_submit' which submits the command via ioctl() - - * 'cxl_cmd__get_' interfaces that get specific fields out of the -@@ -167,6 +171,13 @@ cxl_memdev{read,write,zero}_label() are helpers for marshaling multiple - label access commands over an arbitrary extent of the device's label - area. - -+cxl_cmd_partition_set_mode() supports selecting NEXTBOOT or IMMEDIATE -+mode. When CXL_SETPART_IMMEDIATE mode is set, it is the caller’s -+responsibility to avoid immediate changes to partitioning when the -+device is in use. When CXL_SETPART_NEXTBOOT mode is set, the change -+in partitioning shall become the “next” configuration, to become -+active on the next device reset. -+ - BUSES - ----- - The CXL Memory space is CPU and Device coherent. The address ranges that -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index c05c13c..daa2bbc 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -2478,6 +2478,34 @@ cxl_cmd_partition_get_next_persistent_size(struct cxl_cmd *cmd) - return cxl_capacity_to_bytes(c->next_persistent); - } - -+CXL_EXPORT int cxl_cmd_partition_set_mode(struct cxl_cmd *cmd, -+ enum cxl_setpartition_mode mode) -+{ -+ struct cxl_cmd_set_partition *setpart = cmd->input_payload; -+ -+ if (mode == CXL_SETPART_IMMEDIATE) -+ setpart->flags = CXL_CMD_SET_PARTITION_FLAG_IMMEDIATE; -+ else -+ setpart->flags = !CXL_CMD_SET_PARTITION_FLAG_IMMEDIATE; -+ -+ return 0; -+} -+ -+CXL_EXPORT struct cxl_cmd *cxl_cmd_new_set_partition(struct cxl_memdev *memdev, -+ unsigned long long volatile_size) -+{ -+ struct cxl_cmd_set_partition *setpart; -+ struct cxl_cmd *cmd; -+ -+ cmd = cxl_cmd_new_generic(memdev, -+ CXL_MEM_COMMAND_ID_SET_PARTITION_INFO); -+ -+ setpart = cmd->input_payload; -+ setpart->volatile_size = cpu_to_le64(volatile_size) -+ / CXL_CAPACITY_MULTIPLIER; -+ return cmd; -+} -+ - CXL_EXPORT int cxl_cmd_submit(struct cxl_cmd *cmd) - { - struct cxl_memdev *memdev = cmd->memdev; -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 5ac6e9b..aab1112 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -163,4 +163,6 @@ global: - cxl_cmd_identify_get_total_size; - cxl_cmd_identify_get_volatile_only_size; - cxl_cmd_identify_get_persistent_only_size; -+ cxl_cmd_new_set_partition; -+ cxl_cmd_partition_set_mode; - } LIBCXL_1; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 7f3a562..c6d88f7 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -195,6 +195,14 @@ struct cxl_cmd_get_partition { - - #define CXL_CAPACITY_MULTIPLIER SZ_256M - -+struct cxl_cmd_set_partition { -+ le64 volatile_size; -+ u8 flags; -+} __attribute__((packed)); -+ -+/* CXL 2.0 8.2.9.5.2 Set Partition Info */ -+#define CXL_CMD_SET_PARTITION_FLAG_IMMEDIATE BIT(0) -+ - /* CXL 2.0 8.2.9.5.3 Byte 0 Health Status */ - #define CXL_CMD_HEALTH_INFO_STATUS_MAINTENANCE_NEEDED_MASK BIT(0) - #define CXL_CMD_HEALTH_INFO_STATUS_PERFORMANCE_DEGRADED_MASK BIT(1) -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 6e18e84..0063d31 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -250,6 +250,16 @@ unsigned long long cxl_cmd_partition_get_active_volatile_size(struct cxl_cmd *cm - unsigned long long cxl_cmd_partition_get_active_persistent_size(struct cxl_cmd *cmd); - unsigned long long cxl_cmd_partition_get_next_volatile_size(struct cxl_cmd *cmd); - unsigned long long cxl_cmd_partition_get_next_persistent_size(struct cxl_cmd *cmd); -+struct cxl_cmd *cxl_cmd_new_set_partition(struct cxl_memdev *memdev, -+ unsigned long long volatile_size); -+ -+enum cxl_setpartition_mode { -+ CXL_SETPART_NEXTBOOT, -+ CXL_SETPART_IMMEDIATE, -+}; -+ -+int cxl_cmd_partition_set_mode(struct cxl_cmd *cmd, -+ enum cxl_setpartition_mode mode); - - #ifdef __cplusplus - } /* extern "C" */ --- -2.27.0 - diff --git a/SOURCES/0137-cxl-add-command-cxl-set-partition.patch b/SOURCES/0137-cxl-add-command-cxl-set-partition.patch deleted file mode 100644 index 664bd5e..0000000 --- a/SOURCES/0137-cxl-add-command-cxl-set-partition.patch +++ /dev/null @@ -1,400 +0,0 @@ -From e2d5cbab4a4b530b679172ae7ca59cc506d1d4cc Mon Sep 17 00:00:00 2001 -From: Alison Schofield -Date: Tue, 22 Feb 2022 11:56:08 -0800 -Subject: [PATCH 137/217] cxl: add command 'cxl set-partition' - -CXL devices may support both volatile and persistent memory capacity. -The amount of device capacity set aside for each type is typically -established at the factory, but some devices also allow for dynamic -re-partitioning. Add a command for this purpose. - - usage: cxl set-partition [..] [] - - -v, --verbose turn on debug - -S, --serial use serial numbers to id memdevs - -t, --type 'pmem' or 'volatile' (Default: 'pmem') - -s, --size size in bytes (Default: all available capacity) - -a, --align auto-align --size per device's requirement - -Link: https://lore.kernel.org/r/e7accc7ba93def81b48304cf5fb483345757410d.1645558189.git.alison.schofield@intel.com -Reviewed-by: Dan Williams -Signed-off-by: Alison Schofield -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-set-partition.txt | 68 ++++++++ - Documentation/cxl/meson.build | 1 + - cxl/builtin.h | 1 + - cxl/cxl.c | 1 + - cxl/memdev.c | 206 ++++++++++++++++++++++++ - 5 files changed, 277 insertions(+) - create mode 100644 Documentation/cxl/cxl-set-partition.txt - -diff --git a/Documentation/cxl/cxl-set-partition.txt b/Documentation/cxl/cxl-set-partition.txt -new file mode 100644 -index 0000000..1e548af ---- /dev/null -+++ b/Documentation/cxl/cxl-set-partition.txt -@@ -0,0 +1,68 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-set-partition(1) -+==================== -+ -+NAME -+---- -+cxl-set-partition - set the partitioning between volatile and persistent capacity on a CXL memdev -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl set-partition [ [..] []' -+ -+DESCRIPTION -+----------- -+CXL devices may support both volatile and persistent memory capacity. -+The amount of device capacity set aside for each type is typically -+established at the factory, but some devices also allow for dynamic -+re-partitioning. -+ -+Use this command to partition a device into volatile and persistent -+capacity. The change in partitioning becomes the “next” configuration, -+to become active on the next device reset. -+ -+Use "cxl list -m -I" to examine the partitioning capabilities -+of a device. A partition_alignment_size value of zero means there is -+no available capacity and therefore the partitions cannot be changed. -+ -+Using this command to change the size of the persistent capacity shall -+result in the loss of data stored. -+ -+OPTIONS -+------- -+:: -+include::memdev-option.txt[] -+ -+-t:: -+--type=:: -+ Type of partition, 'pmem' or 'volatile', to modify. -+ Default: 'pmem' -+ -+-s:: -+--size=:: -+ Size of the partition in bytes. Size must align to the -+ devices alignment requirement. Use 'cxl list -m -I' -+ to find 'partition_alignment_size', or, use the --align option. -+ Default: All available capacity is assigned to . -+ -+-a:: -+--align:: -+ Select this option to allow the automatic alignment of --size -+ to meet device alignment requirements. When using this option, -+ specify the minimum --size of the --type partition needed. When -+ this option is omitted, the command fails if --size is not -+ properly aligned. Use 'cxl list -m -I' to examine the -+ partition_alignment_size. -+ -+-v:: -+ Turn on verbose debug messages in the library (if libcxl was built with -+ logging and debug enabled). -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-list[1], -+CXL-2.0 8.2.9.5.2 -diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build -index 96f4666..e927644 100644 ---- a/Documentation/cxl/meson.build -+++ b/Documentation/cxl/meson.build -@@ -34,6 +34,7 @@ cxl_manpages = [ - 'cxl-disable-memdev.txt', - 'cxl-enable-port.txt', - 'cxl-disable-port.txt', -+ 'cxl-set-partition.txt', - ] - - foreach man : cxl_manpages -diff --git a/cxl/builtin.h b/cxl/builtin.h -index 3123d5e..7bbad98 100644 ---- a/cxl/builtin.h -+++ b/cxl/builtin.h -@@ -14,4 +14,5 @@ int cmd_disable_memdev(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_enable_memdev(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_disable_port(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_enable_port(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_set_partition(int argc, const char **argv, struct cxl_ctx *ctx); - #endif /* _CXL_BUILTIN_H_ */ -diff --git a/cxl/cxl.c b/cxl/cxl.c -index c20c569..ab4bbec 100644 ---- a/cxl/cxl.c -+++ b/cxl/cxl.c -@@ -68,6 +68,7 @@ static struct cmd_struct commands[] = { - { "enable-memdev", .c_fn = cmd_enable_memdev }, - { "disable-port", .c_fn = cmd_disable_port }, - { "enable-port", .c_fn = cmd_enable_port }, -+ { "set-partition", .c_fn = cmd_set_partition }, - }; - - int main(int argc, const char **argv) -diff --git a/cxl/memdev.c b/cxl/memdev.c -index 90b33e1..91d914d 100644 ---- a/cxl/memdev.c -+++ b/cxl/memdev.c -@@ -6,11 +6,14 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include - #include - -+#include "json.h" - #include "filter.h" - - struct action_context { -@@ -26,10 +29,18 @@ static struct parameters { - bool verbose; - bool serial; - bool force; -+ bool align; -+ const char *type; -+ const char *size; - } param; - - static struct log_ctx ml; - -+enum cxl_setpart_type { -+ CXL_SETPART_PMEM, -+ CXL_SETPART_VOLATILE, -+}; -+ - #define BASE_OPTIONS() \ - OPT_BOOLEAN('v',"verbose", ¶m.verbose, "turn on debug"), \ - OPT_BOOLEAN('S', "serial", ¶m.serial, "use serial numbers to id memdevs") -@@ -51,6 +62,14 @@ OPT_UINTEGER('O', "offset", ¶m.offset, \ - OPT_BOOLEAN('f', "force", ¶m.force, \ - "DANGEROUS: override active memdev safety checks") - -+#define SET_PARTITION_OPTIONS() \ -+OPT_STRING('t', "type", ¶m.type, "type", \ -+ "'pmem' or 'volatile' (Default: 'pmem')"), \ -+OPT_STRING('s', "size", ¶m.size, "size", \ -+ "size in bytes (Default: all available capacity)"), \ -+OPT_BOOLEAN('a', "align", ¶m.align, \ -+ "auto-align --size per device's requirement") -+ - static const struct option read_options[] = { - BASE_OPTIONS(), - LABEL_OPTIONS(), -@@ -82,6 +101,12 @@ static const struct option enable_options[] = { - OPT_END(), - }; - -+static const struct option set_partition_options[] = { -+ BASE_OPTIONS(), -+ SET_PARTITION_OPTIONS(), -+ OPT_END(), -+}; -+ - static int action_disable(struct cxl_memdev *memdev, struct action_context *actx) - { - if (!cxl_memdev_is_enabled(memdev)) -@@ -209,6 +234,176 @@ out: - return rc; - } - -+static unsigned long long -+partition_align(const char *devname, enum cxl_setpart_type type, -+ unsigned long long volatile_size, unsigned long long alignment, -+ unsigned long long available) -+{ -+ if (IS_ALIGNED(volatile_size, alignment)) -+ return volatile_size; -+ -+ if (!param.align) { -+ log_err(&ml, "%s: size %lld is not partition aligned %lld\n", -+ devname, volatile_size, alignment); -+ return ULLONG_MAX; -+ } -+ -+ /* Align based on partition type to fulfill users size request */ -+ if (type == CXL_SETPART_PMEM) -+ volatile_size = ALIGN_DOWN(volatile_size, alignment); -+ else -+ volatile_size = ALIGN(volatile_size, alignment); -+ -+ /* Fail if the align pushes size over the available limit. */ -+ if (volatile_size > available) { -+ log_err(&ml, "%s: aligned partition size %lld exceeds available size %lld\n", -+ devname, volatile_size, available); -+ volatile_size = ULLONG_MAX; -+ } -+ -+ return volatile_size; -+} -+ -+static unsigned long long -+param_size_to_volatile_size(const char *devname, enum cxl_setpart_type type, -+ unsigned long long size, unsigned long long available) -+{ -+ /* User omits size option. Apply all available capacity to type. */ -+ if (size == ULLONG_MAX) { -+ if (type == CXL_SETPART_PMEM) -+ return 0; -+ return available; -+ } -+ -+ /* User includes a size option. Apply it to type */ -+ if (size > available) { -+ log_err(&ml, "%s: %lld exceeds available capacity %lld\n", -+ devname, size, available); -+ return ULLONG_MAX; -+ } -+ if (type == CXL_SETPART_PMEM) -+ return available - size; -+ return size; -+} -+ -+/* -+ * Return the volatile_size to use in the CXL set paritition -+ * command, or ULLONG_MAX if unable to validate the partition -+ * request. -+ */ -+static unsigned long long -+validate_partition(struct cxl_memdev *memdev, enum cxl_setpart_type type, -+ unsigned long long size) -+{ -+ unsigned long long total_cap, volatile_only, persistent_only; -+ const char *devname = cxl_memdev_get_devname(memdev); -+ unsigned long long volatile_size = ULLONG_MAX; -+ unsigned long long available, alignment; -+ struct cxl_cmd *cmd; -+ int rc; -+ -+ cmd = cxl_cmd_new_identify(memdev); -+ if (!cmd) -+ return ULLONG_MAX; -+ rc = cxl_cmd_submit(cmd); -+ if (rc < 0) -+ goto out; -+ rc = cxl_cmd_get_mbox_status(cmd); -+ if (rc != 0) -+ goto out; -+ -+ alignment = cxl_cmd_identify_get_partition_align(cmd); -+ if (alignment == 0) { -+ log_err(&ml, "%s: no available capacity\n", devname); -+ goto out; -+ } -+ -+ /* Calculate the actual available capacity */ -+ total_cap = cxl_cmd_identify_get_total_size(cmd); -+ volatile_only = cxl_cmd_identify_get_volatile_only_size(cmd); -+ persistent_only = cxl_cmd_identify_get_persistent_only_size(cmd); -+ available = total_cap - volatile_only - persistent_only; -+ -+ /* Translate the users size request into an aligned volatile_size */ -+ volatile_size = param_size_to_volatile_size(devname, type, size, -+ available); -+ if (volatile_size == ULLONG_MAX) -+ goto out; -+ -+ volatile_size = partition_align(devname, type, volatile_size, alignment, -+ available); -+ -+out: -+ cxl_cmd_unref(cmd); -+ return volatile_size; -+} -+ -+static int action_setpartition(struct cxl_memdev *memdev, -+ struct action_context *actx) -+{ -+ const char *devname = cxl_memdev_get_devname(memdev); -+ enum cxl_setpart_type type = CXL_SETPART_PMEM; -+ unsigned long long size = ULLONG_MAX; -+ struct json_object *jmemdev; -+ struct cxl_cmd *cmd; -+ int rc; -+ -+ if (param.type) { -+ if (strcmp(param.type, "pmem") == 0) -+ /* default */; -+ else if (strcmp(param.type, "volatile") == 0) -+ type = CXL_SETPART_VOLATILE; -+ else { -+ log_err(&ml, "invalid type '%s'\n", param.type); -+ return -EINVAL; -+ } -+ } -+ -+ if (param.size) { -+ size = parse_size64(param.size); -+ if (size == ULLONG_MAX) { -+ log_err(&ml, "%s: failed to parse size option '%s'\n", -+ devname, param.size); -+ return -EINVAL; -+ } -+ } -+ -+ size = validate_partition(memdev, type, size); -+ if (size == ULLONG_MAX) -+ return -EINVAL; -+ -+ cmd = cxl_cmd_new_set_partition(memdev, size); -+ if (!cmd) { -+ rc = -ENXIO; -+ goto out_err; -+ } -+ -+ rc = cxl_cmd_submit(cmd); -+ if (rc < 0) { -+ log_err(&ml, "cmd submission failed: %s\n", strerror(-rc)); -+ goto out_cmd; -+ } -+ -+ rc = cxl_cmd_get_mbox_status(cmd); -+ if (rc != 0) { -+ log_err(&ml, "%s: mbox status: %d\n", __func__, rc); -+ rc = -ENXIO; -+ } -+ -+out_cmd: -+ cxl_cmd_unref(cmd); -+out_err: -+ if (rc) -+ log_err(&ml, "%s error: %s\n", devname, strerror(-rc)); -+ -+ jmemdev = util_cxl_memdev_to_json(memdev, UTIL_JSON_PARTITION); -+ if (jmemdev) -+ printf("%s\n", json_object_to_json_string_ext(jmemdev, -+ JSON_C_TO_STRING_PRETTY)); -+ -+ return rc; -+} -+ - static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - int (*action)(struct cxl_memdev *memdev, - struct action_context *actx), -@@ -398,3 +593,14 @@ int cmd_enable_memdev(int argc, const char **argv, struct cxl_ctx *ctx) - count > 1 ? "s" : ""); - return count >= 0 ? 0 : EXIT_FAILURE; - } -+ -+int cmd_set_partition(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ int count = memdev_action(argc, argv, ctx, action_setpartition, -+ set_partition_options, -+ "cxl set-partition [..] []"); -+ log_info(&ml, "set_partition %d mem%s\n", count >= 0 ? count : 0, -+ count > 1 ? "s" : ""); -+ -+ return count >= 0 ? 0 : EXIT_FAILURE; -+} --- -2.27.0 - diff --git a/SOURCES/0138-Update-ndctl.spec-to-allow-flatpak-builds.patch b/SOURCES/0138-Update-ndctl.spec-to-allow-flatpak-builds.patch deleted file mode 100644 index c094600..0000000 --- a/SOURCES/0138-Update-ndctl.spec-to-allow-flatpak-builds.patch +++ /dev/null @@ -1,41 +0,0 @@ -From cd41a4dc6af9b48045b0aa46669d560faeb134e2 Mon Sep 17 00:00:00 2001 -From: Jay W -Date: Tue, 15 Feb 2022 00:45:00 +0000 -Subject: [PATCH 138/217] Update ndctl.spec to allow flatpak builds - -This will allow ndctl to be build as dependency for some flatpak builds -on fedora systems. -See also: https://docs.fedoraproject.org/en-US/flatpak/troubleshooting/#_uncompressed_manual_pages - -Link: https://github.com/pmem/ndctl/pull/192 -Signed-off-by: Vishal Verma ---- - ndctl.spec.in | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/ndctl.spec.in b/ndctl.spec.in -index 9ca831e..cfcafa2 100644 ---- a/ndctl.spec.in -+++ b/ndctl.spec.in -@@ -38,6 +38,9 @@ subsystem defines a kernel device model and control message interface for - platform NVDIMM resources like those defined by the ACPI 6+ NFIT (NVDIMM - Firmware Interface Table). - -+%if 0%{?flatpak} -+%global _udevrulesdir %{_prefix}/lib/udev/rules.d -+%endif - - %package -n DNAME - Summary: Development files for libndctl -@@ -231,7 +234,7 @@ fi - %{_libdir}/libcxl.so - %{_libdir}/pkgconfig/libcxl.pc - %{_mandir}/man3/cxl* --%{_mandir}/man3/libcxl.3.gz -+%{_mandir}/man3/libcxl.3* - - - %changelog --- -2.27.0 - diff --git a/SOURCES/0139-daxctl-provide-safe-versions-of-iteration-API.patch b/SOURCES/0139-daxctl-provide-safe-versions-of-iteration-API.patch deleted file mode 100644 index ca0b342..0000000 --- a/SOURCES/0139-daxctl-provide-safe-versions-of-iteration-API.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 3e4a66f0dfb02046f6d3375d637840b6da9c71d1 Mon Sep 17 00:00:00 2001 -From: michalbiesek -Date: Mon, 2 Dec 2019 11:21:03 +0100 -Subject: [PATCH 139/217] daxctl: provide safe versions of iteration API - -Add support for safe iterate through regions and devices - -Link: https://github.com/pmem/ndctl/pull/132 -Signed-off-by: Michal Biesek -Signed-off-by: Vishal Verma ---- - daxctl/libdaxctl.h | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/daxctl/libdaxctl.h b/daxctl/libdaxctl.h -index 6b6c71f..6876037 100644 ---- a/daxctl/libdaxctl.h -+++ b/daxctl/libdaxctl.h -@@ -93,12 +93,25 @@ int daxctl_memory_online_no_movable(struct daxctl_memory *mem); - dev != NULL; \ - dev = daxctl_dev_get_next(dev)) - -+#define daxctl_dev_foreach_safe(region, dev, _dev) \ -+ for (dev = daxctl_dev_get_first(region), \ -+ _dev = dev ? daxctl_dev_get_next(dev) : NULL; \ -+ dev != NULL; \ -+ dev = _dev, \ -+ _dev = _dev ? daxctl_dev_get_next(_dev) : NULL) - - #define daxctl_region_foreach(ctx, region) \ - for (region = daxctl_region_get_first(ctx); \ - region != NULL; \ - region = daxctl_region_get_next(region)) - -+#define daxctl_region_foreach_safe(ctx, region, _region) \ -+ for (region = daxctl_region_get_first(ctx), \ -+ _region = region ? daxctl_region_get_next(region) : NULL; \ -+ region != NULL; \ -+ region = _region, \ -+ _region = _region ? daxctl_region_get_next(_region) : NULL) -+ - struct daxctl_mapping; - struct daxctl_mapping *daxctl_mapping_get_first(struct daxctl_dev *dev); - struct daxctl_mapping *daxctl_mapping_get_next(struct daxctl_mapping *mapping); --- -2.27.0 - diff --git a/SOURCES/0140-util-size.h-fix-build-for-older-compilers.patch b/SOURCES/0140-util-size.h-fix-build-for-older-compilers.patch deleted file mode 100644 index 3ddc3e4..0000000 --- a/SOURCES/0140-util-size.h-fix-build-for-older-compilers.patch +++ /dev/null @@ -1,216 +0,0 @@ -From 10653a171bc0ca145236d2c75e5c5422caeb8b55 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Wed, 23 Feb 2022 22:28:05 -0700 -Subject: [PATCH 140/217] util/size.h: fix build for older compilers - -Add a fallback for older compilers that lack __builtin_add_overflow() -and friends. Commit 7aa7c7be6e80 ("util: add the struct_size() helper from the -kernel") which added these helpers from the kernel neglected to copy -over the fallback code. - -Link: https://lore.kernel.org/r/20220224052805.2462449-1-vishal.l.verma@intel.com -Fixes: 7aa7c7be6e80 ("util: add the struct_size() helper from the kernel") -Reported-by: Joao Martins -Reviewed-by: Joao Martins -Signed-off-by: Vishal Verma ---- - util/size.h | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 159 insertions(+), 4 deletions(-) - -diff --git a/util/size.h b/util/size.h -index e72467f..1cb0669 100644 ---- a/util/size.h -+++ b/util/size.h -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - - #define SZ_1K 0x00000400 - #define SZ_4K 0x00001000 -@@ -43,23 +44,177 @@ static inline bool is_power_of_2(unsigned long long v) - * alias for __builtin_add_overflow, but add type checks similar to - * below. - */ --#define check_add_overflow(a, b, d) (({ \ -+#define is_signed_type(type) (((type)(-1)) < (type)1) -+#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type))) -+#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T))) -+#define type_min(T) ((T)((T)-type_max(T)-(T)1)) -+ -+#if GCC_VERSION >= 50100 -+#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 -+#endif -+ -+#if __clang__ && \ -+ __has_builtin(__builtin_mul_overflow) && \ -+ __has_builtin(__builtin_add_overflow) -+#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 -+#endif -+ -+#if COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW -+ -+#define check_add_overflow(a, b, d) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - typeof(d) __d = (d); \ - (void) (&__a == &__b); \ - (void) (&__a == __d); \ - __builtin_add_overflow(__a, __b, __d); \ --})) -+}) -+ -+#define check_sub_overflow(a, b, d) ({ \ -+ typeof(a) __a = (a); \ -+ typeof(b) __b = (b); \ -+ typeof(d) __d = (d); \ -+ (void) (&__a == &__b); \ -+ (void) (&__a == __d); \ -+ __builtin_sub_overflow(__a, __b, __d); \ -+}) - --#define check_mul_overflow(a, b, d) (({ \ -+#define check_mul_overflow(a, b, d) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - typeof(d) __d = (d); \ - (void) (&__a == &__b); \ - (void) (&__a == __d); \ - __builtin_mul_overflow(__a, __b, __d); \ --})) -+}) -+ -+ -+#else /* !COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */ -+ -+/* Checking for unsigned overflow is relatively easy without causing UB. */ -+#define __unsigned_add_overflow(a, b, d) ({ \ -+ typeof(a) __a = (a); \ -+ typeof(b) __b = (b); \ -+ typeof(d) __d = (d); \ -+ (void) (&__a == &__b); \ -+ (void) (&__a == __d); \ -+ *__d = __a + __b; \ -+ *__d < __a; \ -+}) -+#define __unsigned_sub_overflow(a, b, d) ({ \ -+ typeof(a) __a = (a); \ -+ typeof(b) __b = (b); \ -+ typeof(d) __d = (d); \ -+ (void) (&__a == &__b); \ -+ (void) (&__a == __d); \ -+ *__d = __a - __b; \ -+ __a < __b; \ -+}) -+/* -+ * If one of a or b is a compile-time constant, this avoids a division. -+ */ -+#define __unsigned_mul_overflow(a, b, d) ({ \ -+ typeof(a) __a = (a); \ -+ typeof(b) __b = (b); \ -+ typeof(d) __d = (d); \ -+ (void) (&__a == &__b); \ -+ (void) (&__a == __d); \ -+ *__d = __a * __b; \ -+ __builtin_constant_p(__b) ? \ -+ __b > 0 && __a > type_max(typeof(__a)) / __b : \ -+ __a > 0 && __b > type_max(typeof(__b)) / __a; \ -+}) -+ -+/* -+ * For signed types, detecting overflow is much harder, especially if -+ * we want to avoid UB. But the interface of these macros is such that -+ * we must provide a result in *d, and in fact we must produce the -+ * result promised by gcc's builtins, which is simply the possibly -+ * wrapped-around value. Fortunately, we can just formally do the -+ * operations in the widest relevant unsigned type (u64) and then -+ * truncate the result - gcc is smart enough to generate the same code -+ * with and without the (u64) casts. -+ */ -+ -+/* -+ * Adding two signed integers can overflow only if they have the same -+ * sign, and overflow has happened iff the result has the opposite -+ * sign. -+ */ -+#define __signed_add_overflow(a, b, d) ({ \ -+ typeof(a) __a = (a); \ -+ typeof(b) __b = (b); \ -+ typeof(d) __d = (d); \ -+ (void) (&__a == &__b); \ -+ (void) (&__a == __d); \ -+ *__d = (u64)__a + (u64)__b; \ -+ (((~(__a ^ __b)) & (*__d ^ __a)) \ -+ & type_min(typeof(__a))) != 0; \ -+}) -+ -+/* -+ * Subtraction is similar, except that overflow can now happen only -+ * when the signs are opposite. In this case, overflow has happened if -+ * the result has the opposite sign of a. -+ */ -+#define __signed_sub_overflow(a, b, d) ({ \ -+ typeof(a) __a = (a); \ -+ typeof(b) __b = (b); \ -+ typeof(d) __d = (d); \ -+ (void) (&__a == &__b); \ -+ (void) (&__a == __d); \ -+ *__d = (u64)__a - (u64)__b; \ -+ ((((__a ^ __b)) & (*__d ^ __a)) \ -+ & type_min(typeof(__a))) != 0; \ -+}) -+ -+/* -+ * Signed multiplication is rather hard. gcc always follows C99, so -+ * division is truncated towards 0. This means that we can write the -+ * overflow check like this: -+ * -+ * (a > 0 && (b > MAX/a || b < MIN/a)) || -+ * (a < -1 && (b > MIN/a || b < MAX/a) || -+ * (a == -1 && b == MIN) -+ * -+ * The redundant casts of -1 are to silence an annoying -Wtype-limits -+ * (included in -Wextra) warning: When the type is u8 or u16, the -+ * __b_c_e in check_mul_overflow obviously selects -+ * __unsigned_mul_overflow, but unfortunately gcc still parses this -+ * code and warns about the limited range of __b. -+ */ -+ -+#define __signed_mul_overflow(a, b, d) ({ \ -+ typeof(a) __a = (a); \ -+ typeof(b) __b = (b); \ -+ typeof(d) __d = (d); \ -+ typeof(a) __tmax = type_max(typeof(a)); \ -+ typeof(a) __tmin = type_min(typeof(a)); \ -+ (void) (&__a == &__b); \ -+ (void) (&__a == __d); \ -+ *__d = (u64)__a * (u64)__b; \ -+ (__b > 0 && (__a > __tmax/__b || __a < __tmin/__b)) || \ -+ (__b < (typeof(__b))-1 && (__a > __tmin/__b || __a < __tmax/__b)) || \ -+ (__b == (typeof(__b))-1 && __a == __tmin); \ -+}) -+ -+ -+#define check_add_overflow(a, b, d) \ -+ __builtin_choose_expr(is_signed_type(typeof(a)), \ -+ __signed_add_overflow(a, b, d), \ -+ __unsigned_add_overflow(a, b, d)) -+ -+#define check_sub_overflow(a, b, d) \ -+ __builtin_choose_expr(is_signed_type(typeof(a)), \ -+ __signed_sub_overflow(a, b, d), \ -+ __unsigned_sub_overflow(a, b, d)) -+ -+#define check_mul_overflow(a, b, d) \ -+ __builtin_choose_expr(is_signed_type(typeof(a)), \ -+ __signed_mul_overflow(a, b, d), \ -+ __unsigned_mul_overflow(a, b, d)) -+ -+#endif - - /* - * Compute a*b+c, returning SIZE_MAX on overflow. Internal helper for --- -2.27.0 - diff --git a/SOURCES/0141-build-Automate-rpmbuild.sh.patch b/SOURCES/0141-build-Automate-rpmbuild.sh.patch deleted file mode 100644 index efba327..0000000 --- a/SOURCES/0141-build-Automate-rpmbuild.sh.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 55f36387ee8a88c489863103347ae275b1bc9191 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 23 Feb 2022 18:41:45 -0800 -Subject: [PATCH 141/217] build: Automate rpmbuild.sh - -Prior to the meson conversion rpmbuild.sh with no arguments would find a -pre-created ndctl.spec file relative to the script. Restore that -behavior by looking for the script in the build/ directory, and try to -create it if not there. - -Yes, this fails if someone picks a directory other than build/ for the -output directory, but build/ is conventional. - -Another regression from autotools is the loss of support for building -"dirty" rpms i.e. rpms from git source trees with uncommitted changes. -At least provide a coherent error message for that case. - -Link: https://lore.kernel.org/r/164567050589.2266739.68846452427328787.stgit@dwillia2-desk3.amr.corp.intel.com -Reported-by: Jane Chu -Reported-by: Vishal Verma -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - rpmbuild.sh | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/rpmbuild.sh b/rpmbuild.sh -index b1f4d9e..d9823e5 100755 ---- a/rpmbuild.sh -+++ b/rpmbuild.sh -@@ -4,6 +4,15 @@ spec=${1:-$(dirname $0)/rhel/ndctl.spec)} - - pushd $(dirname $0) >/dev/null - [ ! -d ~/rpmbuild/SOURCES ] && echo "rpmdev tree not found" && exit 1 -+if ./git-version | grep -q dirty; then -+ echo "Uncommitted changes detected, commit or undo them to proceed" -+ git status -uno --short -+ exit 1 -+fi -+if [ ! -f $spec ]; then -+ meson compile -C build rhel/ndctl.spec -+ spec=$(dirname $0)/build/rhel/ndctl.spec -+fi - ./make-git-snapshot.sh - popd > /dev/null - rpmbuild --nocheck -ba $spec --- -2.27.0 - diff --git a/SOURCES/0142-util-size.h-Fix-build-error-for-GCC-10.patch b/SOURCES/0142-util-size.h-Fix-build-error-for-GCC-10.patch deleted file mode 100644 index 61ac801..0000000 --- a/SOURCES/0142-util-size.h-Fix-build-error-for-GCC-10.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 3b5fb8b6428dfaab39bab58d67412427f514c1f4 Mon Sep 17 00:00:00 2001 -From: Vaibhav Jain -Date: Sat, 26 Feb 2022 17:09:55 +0530 -Subject: [PATCH 142/217] util/size.h: Fix build error for GCC < 10 - -Building with GCC 8.4.1 results in following build error for 'util/size.c': - -../util/size.h:57:16: error: missing binary operator before token "(" - __has_builtin(__builtin_mul_overflow) && \ - -This is caused due to missing '__has_builtin' preprocessor operator in GCC -versions < 10.0.0. The patch updates the check for CLANG's availability of -__builtin_{mul,add}_overflow to prevent preprocessor from evaluating the -expression "___has_builtin(__builtin_mul_overflow) && -__has_builtin(__builtin_add_overflow)". - -Link: https://lore.kernel.org/r/20220226113955.526036-1-vaibhav@linux.ibm.com -Fixes:10653a171bc0("util/size.h: fix build for older compilers") -Reported-by: Tarun Sahu -Reviewed-by: Joao Martins -Signed-off-by: Vaibhav Jain -Signed-off-by: Vishal Verma ---- - util/size.h | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/util/size.h b/util/size.h -index 1cb0669..02baa77 100644 ---- a/util/size.h -+++ b/util/size.h -@@ -53,11 +53,12 @@ static inline bool is_power_of_2(unsigned long long v) - #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 - #endif - --#if __clang__ && \ -- __has_builtin(__builtin_mul_overflow) && \ -+#if __clang__ -+#if __has_builtin(__builtin_mul_overflow) && \ - __has_builtin(__builtin_add_overflow) - #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 - #endif -+#endif - - #if COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW - --- -2.27.0 - diff --git a/SOURCES/0143-libcxl-Remove-extraneous-NULL-checks-when-validating.patch b/SOURCES/0143-libcxl-Remove-extraneous-NULL-checks-when-validating.patch deleted file mode 100644 index dfbb32a..0000000 --- a/SOURCES/0143-libcxl-Remove-extraneous-NULL-checks-when-validating.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 4b381a31345930d08ab9adb87087bb765f624506 Mon Sep 17 00:00:00 2001 -From: Alison Schofield -Date: Thu, 3 Mar 2022 15:16:57 -0800 -Subject: [PATCH 143/217] libcxl: Remove extraneous NULL checks when validating - cmd status - -When a cxl_cmd_new_*() function is executed the returned command -pointer is always checked for NULL. Remove extraneous NULL checks -later in the command validation path. - -Coverity pointed these out as 'check_after_deref' issues. - -Link: https://lore.kernel.org/r/20220303231657.1053594-1-alison.schofield@intel.com -Fixes: 4f588b964dcc ("libcxl: add GET_PARTITION_INFO mailbox command and accessors") -Fixes: 50b9d77232d4 ("libcxl: add accessors for capacity fields of the IDENTIFY command") -Reviewed-by: Dan Williams -Signed-off-by: Alison Schofield -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index daa2bbc..f111d86 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -2283,8 +2283,6 @@ cmd_to_identify(struct cxl_cmd *cmd) - if (cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_IDENTIFY)) - return NULL; - -- if (!cmd) -- return NULL; - return cmd->output_payload; - } - -@@ -2429,8 +2427,6 @@ cmd_to_get_partition(struct cxl_cmd *cmd) - if (cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_GET_PARTITION_INFO)) - return NULL; - -- if (!cmd) -- return NULL; - return cmd->output_payload; - } - --- -2.27.0 - diff --git a/SOURCES/0144-libdaxctl-free-resource-allocated-with-asprintf.patch b/SOURCES/0144-libdaxctl-free-resource-allocated-with-asprintf.patch deleted file mode 100644 index 9398893..0000000 --- a/SOURCES/0144-libdaxctl-free-resource-allocated-with-asprintf.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 057ca6fc2ce63625236bf00e795e0847e6508ed8 Mon Sep 17 00:00:00 2001 -From: Alison Schofield -Date: Thu, 3 Mar 2022 16:01:33 -0800 -Subject: [PATCH 144/217] libdaxctl: free resource allocated with asprintf() - -Static analysis reported this resource leak. - -Link: https://lore.kernel.org/r/20220304000133.1053883-1-alison.schofield@intel.com -Fixes: d07508a0cc3c ("libdaxctl: add daxctl_region_create_dev()") -Signed-off-by: Alison Schofield -Signed-off-by: Vishal Verma ---- - daxctl/lib/libdaxctl.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c -index f173bbb..5703992 100644 ---- a/daxctl/lib/libdaxctl.c -+++ b/daxctl/lib/libdaxctl.c -@@ -624,10 +624,9 @@ DAXCTL_EXPORT int daxctl_region_create_dev(struct daxctl_region *region) - } - - rc = sysfs_write_attr(ctx, path, num_devices); -- if (rc) -- return rc; -+ free(num_devices); - -- return 0; -+ return rc; - } - - DAXCTL_EXPORT int daxctl_region_destroy_dev(struct daxctl_region *region, --- -2.27.0 - diff --git a/SOURCES/0145-cxl-list-tidy-the-error-path-in-add_cxl_decoder.patch b/SOURCES/0145-cxl-list-tidy-the-error-path-in-add_cxl_decoder.patch deleted file mode 100644 index 2de4130..0000000 --- a/SOURCES/0145-cxl-list-tidy-the-error-path-in-add_cxl_decoder.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 367593e7b602fd490baf22a26887c09877e75c14 Mon Sep 17 00:00:00 2001 -From: Alison Schofield -Date: Thu, 3 Mar 2022 16:54:23 -0800 -Subject: [PATCH 145/217] cxl/list: tidy the error path in add_cxl_decoder() - -Static analysis reported this NULL pointer dereference during -cleanup on error in add_cxl_decoder(). - -Link: https://lore.kernel.org/r/20220304005423.1054282-1-alison.schofield@intel.com -Fixes: 46564977afb7 ("cxl/list: Add decoder support") -Signed-off-by: Alison Schofield -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index f111d86..1782f42 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -919,11 +919,11 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - - decoder->dev_path = strdup(cxldecoder_base); - if (!decoder->dev_path) -- goto err; -+ goto err_decoder; - - decoder->dev_buf = calloc(1, strlen(cxldecoder_base) + 50); - if (!decoder->dev_buf) -- goto err; -+ goto err_decoder; - decoder->buf_len = strlen(cxldecoder_base) + 50; - - sprintf(path, "%s/start", cxldecoder_base); -@@ -1024,10 +1024,12 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - list_add(&port->decoders, &decoder->list); - - return decoder; --err: -+ -+err_decoder: - free(decoder->dev_path); - free(decoder->dev_buf); - free(decoder); -+err: - free(path); - return NULL; - } --- -2.27.0 - diff --git a/SOURCES/0146-cxl-list-always-free-the-path-var-in-add_cxl_decoder.patch b/SOURCES/0146-cxl-list-always-free-the-path-var-in-add_cxl_decoder.patch deleted file mode 100644 index 6b1d419..0000000 --- a/SOURCES/0146-cxl-list-always-free-the-path-var-in-add_cxl_decoder.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 7564aeeae7bc8c3813bd80676769bd11a1055ca0 Mon Sep 17 00:00:00 2001 -From: Alison Schofield -Date: Thu, 3 Mar 2022 17:36:43 -0800 -Subject: [PATCH 146/217] cxl/list: always free the path var in - add_cxl_decoder() - -Static analysis reported a resource leak where the 'path' variable was -not always freed before returns. - -Link: https://lore.kernel.org/r/20220304013643.1054605-1-alison.schofield@intel.com -Fixes: 46564977afb7 ("cxl/list: Add decoder support") -Signed-off-by: Alison Schofield -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 1782f42..59e1644 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -1018,11 +1018,13 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - cxl_decoder_foreach(port, decoder_dup) - if (decoder_dup->id == decoder->id) { - free_decoder(decoder, NULL); -+ free(path); - return decoder_dup; - } - - list_add(&port->decoders, &decoder->list); - -+ free(path); - return decoder; - - err_decoder: --- -2.27.0 - diff --git a/SOURCES/0147-scripts-docsurgeon-Fix-document-header-for-section-1.patch b/SOURCES/0147-scripts-docsurgeon-Fix-document-header-for-section-1.patch deleted file mode 100644 index a4395b3..0000000 --- a/SOURCES/0147-scripts-docsurgeon-Fix-document-header-for-section-1.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 633205122bc5a54b56ac6d961f9fc4aac917b0fd Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Fri, 4 Mar 2022 13:02:51 -0700 -Subject: [PATCH 147/217] scripts/docsurgeon: Fix document header for section 1 - man pages - -Document header generation for section 1 man pages (cxl-foo commands) was -missing the section number in parenthesis, i.e. it would generate: - - cxl-foo - ======= - -instead of: - - cxl-foo(1) - ========== - -resulting in asciidoc(tor) warnings. - -Signed-off-by: Vishal Verma ---- - scripts/docsurgeon | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/scripts/docsurgeon b/scripts/docsurgeon -index ca0ad78..1421ef7 100755 ---- a/scripts/docsurgeon -+++ b/scripts/docsurgeon -@@ -244,7 +244,7 @@ gen_cli() - - # Start template generation - printf "%s\n" "$copyright_cli" > "$tmp" -- gen_header "$name" >> "$tmp" -+ gen_header "$name($_arg_section)" >> "$tmp" - gen_section_name "$name" >> "$tmp" - gen_section_synopsis_1 "$name" >> "$tmp" - gen_section "DESCRIPTION" >> "$tmp" --- -2.27.0 - diff --git a/SOURCES/0148-ndctl-release-v73.patch b/SOURCES/0148-ndctl-release-v73.patch deleted file mode 100644 index c301cf0..0000000 --- a/SOURCES/0148-ndctl-release-v73.patch +++ /dev/null @@ -1,156 +0,0 @@ -From dd58d43458943d20ff063850670bf54a5242c9c5 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Sun, 6 Mar 2022 23:39:25 -0700 -Subject: [PATCH 148/217] ndctl: release v73 - -This release incorporates functionality up to the 5.17 kernel. - -Highlights include full CXL topology walk and filtering in cxl-list, a -new cxl-cli command to set memdev partitioning info, several unit test -fixes, conversion of the build system to meson, smart error injection -enhancements for 'papr' NVDIMMs, and RPM spec fixes to support config -file migration, and flatpak builds. - -Commands: - cxl-list: full topology walk and filtering - cxl-set-partition: new command to set memdev partitions - cxl{enable,disable}-port: new commands - cxl{enable,disable}-memdev: new commands - -Tests: - Deprecate BLK aperture support - inject-smart.sh: increase tolerance for decimal formatted fields - -APIs: - ndctl_dimm_refresh_flags - cxl_bus_get_ctx - cxl_bus_get_devname - cxl_bus_get_first - cxl_bus_get_id - cxl_bus_get_next - cxl_bus_get_port - cxl_bus_get_provider - cxl_cmd_identify_get_persistent_only_size - cxl_cmd_identify_get_total_size - cxl_cmd_identify_get_volatile_only_size - cxl_cmd_new_get_partition - cxl_cmd_new_set_partition - cxl_cmd_partition_get_active_persistent_size - cxl_cmd_partition_get_active_volatile_size - cxl_cmd_partition_get_next_persistent_size - cxl_cmd_partition_get_next_volatile_size - cxl_cmd_partition_set_mode - cxl_decoder_get_ctx - cxl_decoder_get_devname - cxl_decoder_get_first - cxl_decoder_get_id - cxl_decoder_get_next - cxl_decoder_get_nr_targets - cxl_decoder_get_port - cxl_decoder_get_resource - cxl_decoder_get_size - cxl_decoder_get_target_by_memdev - cxl_decoder_get_target_by_position - cxl_decoder_get_target_type - cxl_decoder_is_accelmem_capable - cxl_decoder_is_locked - cxl_decoder_is_mem_capable - cxl_decoder_is_pmem_capable - cxl_decoder_is_volatile_capable - cxl_dport_get_devname - cxl_dport_get_first - cxl_dport_get_id - cxl_dport_get_next - cxl_dport_get_physical_node - cxl_dport_get_port - cxl_dport_maps_memdev - cxl_endpoint_get_bus - cxl_endpoint_get_ctx - cxl_endpoint_get_devname - cxl_endpoint_get_first - cxl_endpoint_get_host - cxl_endpoint_get_id - cxl_endpoint_get_memdev - cxl_endpoint_get_next - cxl_endpoint_get_parent - cxl_endpoint_get_port - cxl_endpoint_is_enabled - cxl_memdev_disable_invalidate - cxl_memdev_enable - cxl_memdev_get_bus - cxl_memdev_get_endpoint - cxl_memdev_get_host - cxl_memdev_get_numa_node - cxl_memdev_get_serial - cxl_memdev_is_enabled - cxl_port_disable_invalidate - cxl_port_enable - cxl_port_get_bus - cxl_port_get_bus - cxl_port_get_ctx - cxl_port_get_devname - cxl_port_get_dport_by_memdev - cxl_port_get_first - cxl_port_get_host - cxl_port_get_id - cxl_port_get_next - cxl_port_get_next_all - cxl_port_get_nr_dports - cxl_port_get_parent - cxl_port_hosts_memdev - cxl_port_is_enabled - cxl_port_is_endpoint - cxl_port_is_root - cxl_port_is_switch - cxl_port_to_bus - cxl_port_to_endpoint - cxl_target_get_decoder - cxl_target_get_devname - cxl_target_get_first - cxl_target_get_id - cxl_target_get_next - cxl_target_get_physical_node - cxl_target_get_position - cxl_target_maps_memdev ---- - meson.build | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/meson.build b/meson.build -index f25ec6c..42e11aa 100644 ---- a/meson.build -+++ b/meson.build -@@ -1,5 +1,5 @@ - project('ndctl', 'c', -- version : '72', -+ version : '73', - license : [ - 'GPL-2.0', - 'LGPL-2.1', -@@ -270,17 +270,17 @@ config_h = configure_file( - ) - add_project_arguments('-include', 'config.h', language : 'c') - --LIBNDCTL_CURRENT=25 --LIBNDCTL_REVISION=1 --LIBNDCTL_AGE=19 -+LIBNDCTL_CURRENT=26 -+LIBNDCTL_REVISION=0 -+LIBNDCTL_AGE=20 - - LIBDAXCTL_CURRENT=6 --LIBDAXCTL_REVISION=0 -+LIBDAXCTL_REVISION=1 - LIBDAXCTL_AGE=5 - --LIBCXL_CURRENT=1 -+LIBCXL_CURRENT=2 - LIBCXL_REVISION=0 --LIBCXL_AGE=0 -+LIBCXL_AGE=1 - - root_inc = include_directories(['.', 'ndctl', ]) - --- -2.27.0 - diff --git a/SOURCES/0150-build-Fix-Wall-and-O2-warnings.patch b/SOURCES/0150-build-Fix-Wall-and-O2-warnings.patch deleted file mode 100644 index ee212ab..0000000 --- a/SOURCES/0150-build-Fix-Wall-and-O2-warnings.patch +++ /dev/null @@ -1,49 +0,0 @@ -From cbe337d6a0ee7d4f0ff9a5c19d14fb5e250df220 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Wed, 9 Mar 2022 15:36:52 -0800 -Subject: [PATCH 150/217] build: Fix '-Wall' and '-O2' warnings - -Stop specifying '-Wall and '-O2' in cc_flags, and rely on the buildtype -and warning_level options. Fixup the '-D_FORTIFY_SOURCE=2' option to -optionally be enabled for optimizated builds rather then forcing -O2. - -Link: https://github.com/pmem/ndctl/issues/195 -Link: https://lore.kernel.org/r/164686901240.2874657.8473455139820858036.stgit@dwillia2-desk3.amr.corp.intel.com -Fixes: 4e5faa1726d2 ("build: Add meson build infrastructure") -Reported-by: Steve Scargall -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - meson.build | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/meson.build b/meson.build -index 17ca65a..4dbb80d 100644 ---- a/meson.build -+++ b/meson.build -@@ -57,7 +57,6 @@ sed -e s,@VERSION@,@0@,g - '''.format(meson.project_version(), prefixdir, libdir, includedir).split() - - cc_flags = [ -- '-Wall', - '-Wchar-subscripts', - '-Wformat-security', - '-Wmissing-declarations', -@@ -70,9 +69,12 @@ cc_flags = [ - '-Wmaybe-uninitialized', - '-Wdeclaration-after-statement', - '-Wunused-result', -- '-D_FORTIFY_SOURCE=2', -- '-O2', - ] -+ -+if get_option('optimization') != '0' -+ cc_flags += [ '-D_FORTIFY_SOURCE=2' ] -+endif -+ - cc = meson.get_compiler('c') - add_project_arguments(cc.get_supported_arguments(cc_flags), language : 'c') - --- -2.27.0 - diff --git a/SOURCES/0151-build-Fix-test-timeouts.patch b/SOURCES/0151-build-Fix-test-timeouts.patch deleted file mode 100644 index 9b5ea02..0000000 --- a/SOURCES/0151-build-Fix-test-timeouts.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 900cfd8e062975215fb522ca47cc6239a5269628 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 10 Mar 2022 19:35:19 -0800 -Subject: [PATCH 151/217] build: Fix test timeouts - -Older versions of meson, like the version that ships in CentOS Stream -interpret a timeout of 0 as immediately fail, rather than infinite test -run. Specify a 10 minute timeout by default instead. - -Link: https://lore.kernel.org/r/164696971934.3344888.14976446737826853353.stgit@dwillia2-desk3.amr.corp.intel.com -Fixes: 4e5faa1726d2 ("build: Add meson build infrastructure") -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/meson.build | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/test/meson.build b/test/meson.build -index 07a5bb6..7ccd451 100644 ---- a/test/meson.build -+++ b/test/meson.build -@@ -227,7 +227,7 @@ foreach t : tests - mmap, - ], - suite: t[2], -- timeout : 0, -+ timeout : 600, - env : [ - 'NDCTL=@0@'.format(ndctl_tool.full_path()), - 'DAXCTL=@0@'.format(daxctl_tool.full_path()), --- -2.27.0 - diff --git a/SOURCES/0155-build-Move-utility-helpers-to-libutil.a.patch b/SOURCES/0155-build-Move-utility-helpers-to-libutil.a.patch deleted file mode 100644 index d19ecb1..0000000 --- a/SOURCES/0155-build-Move-utility-helpers-to-libutil.a.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 6d0e543f8bf01219b793cf4d7a603d3dfd7844ed Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 28 Apr 2022 15:10:05 -0700 -Subject: [PATCH 155/217] build: Move utility helpers to libutil.a - -Stop listing util/json.c and util/log.c per command, just add them to -the common libutil.a object. - -Link: https://lore.kernel.org/r/165118380572.1676208.16232543117821121022.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/meson.build | 2 -- - daxctl/meson.build | 1 - - ndctl/meson.build | 2 -- - util/meson.build | 2 ++ - 4 files changed, 2 insertions(+), 5 deletions(-) - -diff -up ndctl-71.1/cxl/meson.build.orig ndctl-71.1/cxl/meson.build ---- ndctl-71.1/cxl/meson.build.orig 2022-10-07 16:54:43.451540066 -0400 -+++ ndctl-71.1/cxl/meson.build 2022-10-07 16:55:35.330716698 -0400 -@@ -3,8 +3,6 @@ cxl_src = [ - 'list.c', - 'port.c', - 'memdev.c', -- '../util/json.c', -- '../util/log.c', - 'json.c', - 'filter.c', - ] -diff -up ndctl-71.1/daxctl/meson.build.orig ndctl-71.1/daxctl/meson.build ---- ndctl-71.1/daxctl/meson.build.orig 2022-10-07 16:54:43.333539664 -0400 -+++ ndctl-71.1/daxctl/meson.build 2022-10-07 16:55:35.330716698 -0400 -@@ -4,7 +4,6 @@ daxctl_src = [ - 'list.c', - 'migrate.c', - 'device.c', -- '../util/json.c', - 'json.c', - 'filter.c', - ] -diff -up ndctl-71.1/ndctl/meson.build.orig ndctl-71.1/ndctl/meson.build ---- ndctl-71.1/ndctl/meson.build.orig 2022-10-07 16:54:43.333539664 -0400 -+++ ndctl-71.1/ndctl/meson.build 2022-10-07 16:55:35.330716698 -0400 -@@ -6,11 +6,9 @@ ndctl_src = [ - 'check.c', - 'region.c', - 'dimm.c', -- '../util/log.c', - '../daxctl/filter.c', - 'filter.c', - 'list.c', -- '../util/json.c', - '../daxctl/json.c', - 'json.c', - 'json-smart.c', -diff -up ndctl-71.1/util/meson.build.orig ndctl-71.1/util/meson.build ---- ndctl-71.1/util/meson.build.orig 2022-10-07 16:54:43.334539667 -0400 -+++ ndctl-71.1/util/meson.build 2022-10-07 16:55:35.330716698 -0400 -@@ -2,6 +2,8 @@ util = static_library('util', [ - 'parse-options.c', - 'usage.c', - 'size.c', -+ 'json.c', -+ 'log.c', - 'main.c', - 'help.c', - 'strbuf.c', diff --git a/SOURCES/0156-util-Use-SZ_-size-macros-in-display-size.patch b/SOURCES/0156-util-Use-SZ_-size-macros-in-display-size.patch deleted file mode 100644 index 04592cc..0000000 --- a/SOURCES/0156-util-Use-SZ_-size-macros-in-display-size.patch +++ /dev/null @@ -1,60 +0,0 @@ -From e1c629bb3e01e3df24c189c0ecabde37788139a2 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 28 Apr 2022 15:10:11 -0700 -Subject: [PATCH 156/217] util: Use SZ_ size macros in display size - -In preparation for adding "Terabyte" support, cleanup the "1024" -multiplication with the SZ_* macros. - -Link: https://lore.kernel.org/r/165118381109.1676208.8857362319985041575.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - util/json.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - -diff --git a/util/json.c b/util/json.c -index f8cc81f..ebdf8d9 100644 ---- a/util/json.c -+++ b/util/json.c -@@ -5,6 +5,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -27,24 +28,24 @@ static int display_size(struct json_object *jobj, struct printbuf *pbuf, - * If prefix == JEDEC, we mean prefixes like kilo,mega,giga etc. - */ - -- if (bytes < 5000*1024) -+ if (bytes < 5000*SZ_1K) - snprintf(buf, sizeof(buf), "%lld", bytes); - else { - /* IEC */ -- if (bytes < 2*1024LL*1024LL*1024LL) { -- long cMiB = (bytes * 200LL / (1LL<<20) +1) /2; -+ if (bytes < 2L*SZ_1G) { -+ long cMiB = (bytes * 200LL / SZ_1M+1) /2; - - c = snprintf(buf, sizeof(buf), "\"%ld.%02ld MiB", - cMiB/100 , cMiB % 100); - } else { -- long cGiB = (bytes * 200LL / (1LL<<30) +1) /2; -+ long cGiB = (bytes * 200LL / SZ_1G+1) /2; - - c = snprintf(buf, sizeof(buf), "\"%ld.%02ld GiB", - cGiB/100 , cGiB % 100); - } - - /* JEDEC */ -- if (bytes < 2*1024LL*1024LL*1024LL) { -+ if (bytes < 2L*SZ_1G) { - long cMB = (bytes / (1000000LL / 200LL) + 1) / 2; - - snprintf(buf + c, sizeof(buf) - c, " (%ld.%02ld MB)\"", --- -2.27.0 - diff --git a/SOURCES/0157-util-Pretty-print-terabytes.patch b/SOURCES/0157-util-Pretty-print-terabytes.patch deleted file mode 100644 index d00eb34..0000000 --- a/SOURCES/0157-util-Pretty-print-terabytes.patch +++ /dev/null @@ -1,61 +0,0 @@ -From e8b5b191a55b7be671abf2c6d5d10db6edd8c1fb Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 28 Apr 2022 15:10:16 -0700 -Subject: [PATCH 157/217] util: Pretty print terabytes - -CXL capacities are such that gigabytes are too small of a unit for -displaying capacities. Add terabyte support to the display_size() -helper. - -Link: https://lore.kernel.org/r/165118381648.1676208.1686584406206186723.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - util/json.c | 15 +++++++++++++-- - 1 file changed, 13 insertions(+), 2 deletions(-) - -diff --git a/util/json.c b/util/json.c -index ebdf8d9..1d5c6bc 100644 ---- a/util/json.c -+++ b/util/json.c -@@ -37,11 +37,16 @@ static int display_size(struct json_object *jobj, struct printbuf *pbuf, - - c = snprintf(buf, sizeof(buf), "\"%ld.%02ld MiB", - cMiB/100 , cMiB % 100); -- } else { -+ } else if (bytes < 2*SZ_1T) { - long cGiB = (bytes * 200LL / SZ_1G+1) /2; - - c = snprintf(buf, sizeof(buf), "\"%ld.%02ld GiB", - cGiB/100 , cGiB % 100); -+ } else { -+ long cTiB = (bytes * 200LL / SZ_1T+1) /2; -+ -+ c = snprintf(buf, sizeof(buf), "\"%ld.%02ld TiB", -+ cTiB/100 , cTiB % 100); - } - - /* JEDEC */ -@@ -50,12 +55,18 @@ static int display_size(struct json_object *jobj, struct printbuf *pbuf, - - snprintf(buf + c, sizeof(buf) - c, " (%ld.%02ld MB)\"", - cMB/100, cMB % 100); -- } else { -+ } else if (bytes < 2*SZ_1T) { - long cGB = (bytes / (1000000000LL/200LL) + 1) / 2; - - snprintf(buf + c, sizeof(buf) - c, " (%ld.%02ld GB)\"", - cGB/100 , cGB % 100); -+ } else { -+ long cTB = (bytes / (1000000000000LL/200LL) + 1) / 2; -+ -+ snprintf(buf + c, sizeof(buf) - c, " (%ld.%02ld TB)\"", -+ cTB/100 , cTB % 100); - } -+ - } - - return printbuf_memappend(pbuf, buf, strlen(buf)); --- -2.27.0 - diff --git a/SOURCES/0158-cxl-port-Fix-disable-port-man-page.patch b/SOURCES/0158-cxl-port-Fix-disable-port-man-page.patch deleted file mode 100644 index 6d559b8..0000000 --- a/SOURCES/0158-cxl-port-Fix-disable-port-man-page.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 3ead5b8c5464c208cdbf11c0844b519518845e3e Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 28 Apr 2022 15:10:22 -0700 -Subject: [PATCH 158/217] cxl/port: Fix disable-port man page - -The man page was copied from the enable-port. Fix up some enable-port -leftovers, and duplicated --endpoint option description. - -Link: https://lore.kernel.org/r/165118382203.1676208.17234717366569348622.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-disable-port.txt | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) - -diff --git a/Documentation/cxl/cxl-disable-port.txt b/Documentation/cxl/cxl-disable-port.txt -index de13c07..ac56f20 100644 ---- a/Documentation/cxl/cxl-disable-port.txt -+++ b/Documentation/cxl/cxl-disable-port.txt -@@ -5,7 +5,7 @@ cxl-disable-port(1) - - NAME - ---- --cxl-disable-port - activate / hot-add a given CXL port -+cxl-disable-port - disable / hot-remove a given CXL port and descendants - - SYNOPSIS - -------- -@@ -22,7 +22,6 @@ OPTIONS - Toggle from treating the port arguments as Switch Port identifiers to - Endpoint Port identifiers. - -- - -f:: - --force:: - DANGEROUS: Override the safety measure that blocks attempts to disable a -@@ -31,9 +30,6 @@ OPTIONS - firmware and disabling an active device is akin to force removing memory - from a running system. - -- Toggle from treating the port arguments as Switch Port identifiers to -- Endpoint Port identifiers. -- - --debug:: - If the cxl tool was built with debug disabled, turn on debug - messages. --- -2.27.0 - diff --git a/SOURCES/0159-cxl-bus-Add-bus-disable-support.patch b/SOURCES/0159-cxl-bus-Add-bus-disable-support.patch deleted file mode 100644 index 48ccaa7..0000000 --- a/SOURCES/0159-cxl-bus-Add-bus-disable-support.patch +++ /dev/null @@ -1,384 +0,0 @@ -From 8a35aa8fd3e1db06228329a0ca900ce246ca329e Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 28 Apr 2022 15:10:27 -0700 -Subject: [PATCH 159/217] cxl/bus: Add bus disable support - -Route requests to disable the root back to unbinding the platform firmware -device, ACPI0017 for ACPI.CXL platforms. - -Link: https://lore.kernel.org/r/165118382738.1676208.16851880881648171660.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-disable-bus.txt | 37 ++++++ - Documentation/cxl/lib/libcxl.txt | 12 ++ - Documentation/cxl/meson.build | 1 + - cxl/builtin.h | 1 + - cxl/bus.c | 159 ++++++++++++++++++++++++++ - cxl/cxl.c | 1 + - cxl/filter.c | 3 +- - cxl/filter.h | 1 + - cxl/lib/libcxl.c | 15 +++ - cxl/lib/libcxl.sym | 1 + - cxl/libcxl.h | 1 + - cxl/meson.build | 1 + - 12 files changed, 231 insertions(+), 2 deletions(-) - create mode 100644 Documentation/cxl/cxl-disable-bus.txt - create mode 100644 cxl/bus.c - -diff --git a/Documentation/cxl/cxl-disable-bus.txt b/Documentation/cxl/cxl-disable-bus.txt -new file mode 100644 -index 0000000..65f695c ---- /dev/null -+++ b/Documentation/cxl/cxl-disable-bus.txt -@@ -0,0 +1,37 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-disable-bus(1) -+=================== -+ -+NAME -+---- -+cxl-disable-bus - Shutdown an entire tree of CXL devices -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl disable-bus' [..] [] -+ -+For test and debug scenarios, disable a CXL bus and any associated -+memory devices from CXL.mem operations. -+ -+OPTIONS -+------- -+-f:: -+--force:: -+ DANGEROUS: Override the safety measure that blocks attempts to disable a -+ bus if the tool determines a descendent memdev is in active usage. -+ Recall that CXL memory ranges might have been established by platform -+ firmware and disabling an active device is akin to force removing memory -+ from a running system. -+ -+--debug:: -+ If the cxl tool was built with debug disabled, turn on debug -+ messages. -+ -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-disable-port[1] -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 7b223cb..f8f0e66 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -216,6 +216,18 @@ discovery order. The possible provider names are 'ACPI.CXL' and - the kernel device names that are subject to change based on discovery - order. - -+=== BUS: Control -+---- -+int cxl_bus_disable_invalidate(struct cxl_bus *bus); -+---- -+ -+An entire CXL topology can be torn down with this API. Like other -+_invalidate APIs callers must assume that all library objects have been -+freed. This one goes one step further and also frees the @bus argument. -+This may crash the system and is only useful in kernel driver -+development scenarios. -+ -+ - PORTS - ----- - CXL ports track the PCIe hierarchy between a platform firmware CXL root -diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build -index e927644..974a5a4 100644 ---- a/Documentation/cxl/meson.build -+++ b/Documentation/cxl/meson.build -@@ -34,6 +34,7 @@ cxl_manpages = [ - 'cxl-disable-memdev.txt', - 'cxl-enable-port.txt', - 'cxl-disable-port.txt', -+ 'cxl-disable-bus.txt', - 'cxl-set-partition.txt', - ] - -diff --git a/cxl/builtin.h b/cxl/builtin.h -index 7bbad98..a437bc3 100644 ---- a/cxl/builtin.h -+++ b/cxl/builtin.h -@@ -15,4 +15,5 @@ int cmd_enable_memdev(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_disable_port(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_enable_port(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_set_partition(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_disable_bus(int argc, const char **argv, struct cxl_ctx *ctx); - #endif /* _CXL_BUILTIN_H_ */ -diff --git a/cxl/bus.c b/cxl/bus.c -new file mode 100644 -index 0000000..3321295 ---- /dev/null -+++ b/cxl/bus.c -@@ -0,0 +1,159 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* Copyright (C) 2020-2022 Intel Corporation. All rights reserved. */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "filter.h" -+ -+static struct parameters { -+ bool debug; -+ bool force; -+} param; -+ -+static struct log_ctx bl; -+ -+#define BASE_OPTIONS() \ -+OPT_BOOLEAN(0, "debug", ¶m.debug, "turn on debug") -+ -+#define DISABLE_OPTIONS() \ -+OPT_BOOLEAN('f', "force", ¶m.force, \ -+ "DANGEROUS: override active memdev safety checks") -+ -+static const struct option disable_options[] = { -+ BASE_OPTIONS(), -+ DISABLE_OPTIONS(), -+ OPT_END(), -+}; -+ -+static int action_disable(struct cxl_bus *bus) -+{ -+ const char *devname = cxl_bus_get_devname(bus); -+ struct cxl_ctx *ctx = cxl_bus_get_ctx(bus); -+ struct cxl_memdev *memdev; -+ int active_memdevs = 0; -+ -+ cxl_memdev_foreach(ctx, memdev) -+ if (bus == cxl_memdev_get_bus(memdev)) -+ active_memdevs++; -+ -+ if (active_memdevs && !param.force) { -+ /* -+ * TODO: actually detect rather than assume active just -+ * because the memdev is enabled -+ */ -+ log_err(&bl, -+ "%s hosts %d memdev%s which %s part of an active region\n", -+ devname, active_memdevs, active_memdevs > 1 ? "s" : "", -+ active_memdevs > 1 ? "are" : "is"); -+ log_err(&bl, -+ "See 'cxl list -M -b %s' to see impacted device%s\n", -+ devname, active_memdevs > 1 ? "s" : ""); -+ return -EBUSY; -+ } -+ -+ return cxl_bus_disable_invalidate(bus); -+} -+ -+static struct cxl_bus *find_cxl_bus(struct cxl_ctx *ctx, const char *ident) -+{ -+ struct cxl_bus *bus; -+ -+ cxl_bus_foreach(ctx, bus) -+ if (util_cxl_bus_filter(bus, ident)) -+ return bus; -+ return NULL; -+} -+ -+static int bus_action(int argc, const char **argv, struct cxl_ctx *ctx, -+ int (*action)(struct cxl_bus *bus), -+ const struct option *options, const char *usage) -+{ -+ int i, rc = 0, count = 0, err = 0; -+ const char * const u[] = { -+ usage, -+ NULL -+ }; -+ unsigned long id; -+ -+ log_init(&bl, "cxl bus", "CXL_PORT_LOG"); -+ argc = parse_options(argc, argv, options, u, 0); -+ -+ if (argc == 0) -+ usage_with_options(u, options); -+ for (i = 0; i < argc; i++) { -+ if (strcmp(argv[i], "all") == 0) { -+ argv[0] = "all"; -+ argc = 1; -+ break; -+ } -+ -+ if (sscanf(argv[i], "root%lu", &id) == 1) -+ continue; -+ if (sscanf(argv[i], "%lu", &id) == 1) -+ continue; -+ -+ log_err(&bl, "'%s' is not a valid bus identifer\n", argv[i]); -+ err++; -+ } -+ -+ if (err == argc) { -+ usage_with_options(u, options); -+ return -EINVAL; -+ } -+ -+ if (param.debug) { -+ cxl_set_log_priority(ctx, LOG_DEBUG); -+ bl.log_priority = LOG_DEBUG; -+ } else -+ bl.log_priority = LOG_INFO; -+ -+ rc = 0; -+ err = 0; -+ count = 0; -+ -+ for (i = 0; i < argc; i++) { -+ struct cxl_bus *bus; -+ -+ bus = find_cxl_bus(ctx, argv[i]); -+ if (!bus) { -+ log_dbg(&bl, "bus: %s not found\n", argv[i]); -+ continue; -+ } -+ -+ log_dbg(&bl, "run action on bus: %s\n", -+ cxl_bus_get_devname(bus)); -+ rc = action(bus); -+ if (rc == 0) -+ count++; -+ else if (rc && !err) -+ err = rc; -+ } -+ rc = err; -+ -+ /* -+ * count if some actions succeeded, 0 if none were attempted, -+ * negative error code otherwise. -+ */ -+ if (count > 0) -+ return count; -+ return rc; -+} -+ -+ int cmd_disable_bus(int argc, const char **argv, struct cxl_ctx *ctx) -+ { -+ int count = bus_action( -+ argc, argv, ctx, action_disable, disable_options, -+ "cxl disable-bus [..] []"); -+ -+ log_info(&bl, "disabled %d bus%s\n", count >= 0 ? count : 0, -+ count > 1 ? "s" : ""); -+ return count >= 0 ? 0 : EXIT_FAILURE; -+ } -diff --git a/cxl/cxl.c b/cxl/cxl.c -index ab4bbec..aa4ce61 100644 ---- a/cxl/cxl.c -+++ b/cxl/cxl.c -@@ -69,6 +69,7 @@ static struct cmd_struct commands[] = { - { "disable-port", .c_fn = cmd_disable_port }, - { "enable-port", .c_fn = cmd_enable_port }, - { "set-partition", .c_fn = cmd_set_partition }, -+ { "disable-bus", .c_fn = cmd_disable_bus }, - }; - - int main(int argc, const char **argv) -diff --git a/cxl/filter.c b/cxl/filter.c -index b339642..c6ab9eb 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -176,8 +176,7 @@ util_cxl_decoder_filter_by_port(struct cxl_decoder *decoder, const char *ident, - return NULL; - } - --static struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus, -- const char *__ident) -+struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus, const char *__ident) - { - char *ident, *save; - const char *arg; -diff --git a/cxl/filter.h b/cxl/filter.h -index 697b777..9557943 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -41,6 +41,7 @@ enum cxl_port_filter_mode { - - struct cxl_port *util_cxl_port_filter(struct cxl_port *port, const char *ident, - enum cxl_port_filter_mode mode); -+struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus, const char *__ident); - struct cxl_endpoint *util_cxl_endpoint_filter(struct cxl_endpoint *endpoint, - const char *__ident); - struct cxl_target *util_cxl_target_filter_by_memdev(struct cxl_target *target, -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 59e1644..0e8dd20 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -556,6 +556,21 @@ static void bus_invalidate(struct cxl_bus *bus) - cxl_flush(ctx); - } - -+CXL_EXPORT int cxl_bus_disable_invalidate(struct cxl_bus *bus) -+{ -+ struct cxl_ctx *ctx = cxl_bus_get_ctx(bus); -+ struct cxl_port *port = cxl_bus_get_port(bus); -+ int rc; -+ -+ rc = util_unbind(port->uport, ctx); -+ if (rc) -+ return rc; -+ -+ free_bus(bus, &ctx->buses); -+ cxl_flush(ctx); -+ return 0; -+} -+ - CXL_EXPORT int cxl_memdev_disable_invalidate(struct cxl_memdev *memdev) - { - struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index aab1112..dffcb60 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -86,6 +86,7 @@ global: - cxl_bus_get_id; - cxl_bus_get_port; - cxl_bus_get_ctx; -+ cxl_bus_disable_invalidate; - cxl_port_get_first; - cxl_port_get_next; - cxl_port_get_devname; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 0063d31..0007f4d 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -73,6 +73,7 @@ const char *cxl_bus_get_devname(struct cxl_bus *bus); - int cxl_bus_get_id(struct cxl_bus *bus); - struct cxl_port *cxl_bus_get_port(struct cxl_bus *bus); - struct cxl_ctx *cxl_bus_get_ctx(struct cxl_bus *bus); -+int cxl_bus_disable_invalidate(struct cxl_bus *bus); - - #define cxl_bus_foreach(ctx, bus) \ - for (bus = cxl_bus_get_first(ctx); bus != NULL; \ -diff --git a/cxl/meson.build b/cxl/meson.build -index 671c8e1..d63dcb1 100644 ---- a/cxl/meson.build -+++ b/cxl/meson.build -@@ -2,6 +2,7 @@ cxl_src = [ - 'cxl.c', - 'list.c', - 'port.c', -+ 'bus.c', - 'memdev.c', - 'json.c', - 'filter.c', --- -2.27.0 - diff --git a/SOURCES/0160-cxl-list-Auto-enable-single-mode-for-port-listings.patch b/SOURCES/0160-cxl-list-Auto-enable-single-mode-for-port-listings.patch deleted file mode 100644 index 5afc6bf..0000000 --- a/SOURCES/0160-cxl-list-Auto-enable-single-mode-for-port-listings.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 2124f62aad2fcc00def36d119cfcdee22a7961e9 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 28 Apr 2022 15:10:32 -0700 -Subject: [PATCH 160/217] cxl/list: Auto-enable 'single' mode for port listings - -The --single parameter instructs the filter code to gate listing of -ancestor ports. However, that behavior can be inferred by attempts to list -a port without the --ports option, i.e. make: - - cxl list -p $port - -...equivalent to: - - cxl list -P -S -p $port - -Link: https://lore.kernel.org/r/165118383246.1676208.2097194779584921177.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/list.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/cxl/list.c b/cxl/list.c -index 1e9d441..940782d 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -104,6 +104,7 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - error("please specify entities to list, e.g. using -m/-M\n"); - usage_with_options(u, options); - } -+ param.single = true; - } - - log_init(¶m.ctx, "cxl list", "CXL_LIST_LOG"); --- -2.27.0 - diff --git a/SOURCES/0161-cxl-memdev-Fix-bus_invalidate-crash.patch b/SOURCES/0161-cxl-memdev-Fix-bus_invalidate-crash.patch deleted file mode 100644 index be34f7c..0000000 --- a/SOURCES/0161-cxl-memdev-Fix-bus_invalidate-crash.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 2dbe3b45879ad614968a75392cb1ef9907d8648d Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 28 Apr 2022 15:10:37 -0700 -Subject: [PATCH 161/217] cxl/memdev: Fix bus_invalidate() crash - -bus_invalidate() attempts to limit the invalidation of memdevs to a single -bus scope. However, the ordering of bus_invalidate() leads to a use after -free. Unconditionally invalidate memdevs (disconnect memdevs from their -endpoints) and resotre on next lookup. Otherwise the following command -results in the following backtrace with cxl_test: - - cxl disable-memdev 5,1 --force - -#2 0x00007ffff7fb97d4 in snprintf (__fmt=0x7ffff7fbc3ed "%s/driver", __n=98, - __s=0x574d545619f7bae2 ) - at /usr/include/bits/stdio2.h:71 -#3 cxl_port_is_enabled (port=port@entry=0x422eb0) at ../cxl/lib/libcxl.c:1379 -#4 0x00007ffff7fb99a9 in cxl_port_get_bus (port=0x422eb0) at ../cxl/lib/libcxl.c:1339 -#5 0x00007ffff7fba3d0 in bus_invalidate (bus=bus@entry=0x421740) at ../cxl/lib/libcxl.c:549 -#6 0x00007ffff7fba4e7 in cxl_memdev_disable_invalidate (memdev=0x416fd0) at ../cxl/lib/libcxl.c:596 -#7 0x000000000040624e in memdev_action (argc=, argv=, ctx=0x4152a0, - action=action@entry=0x406b70 , options=options@entry=0x40fca0 , - usage=usage@entry=0x40f4b0 "cxl disable-memdev [..] []") - at ../cxl/memdev.c:506 -#8 0x0000000000406d57 in cmd_disable_memdev (argc=, argv=, - -Link: https://lore.kernel.org/r/165118383756.1676208.5717187278816036969.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 0e8dd20..374b0f1 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -546,8 +546,7 @@ static void bus_invalidate(struct cxl_bus *bus) - * indeterminate, delete them all and start over. - */ - cxl_memdev_foreach(ctx, memdev) -- if (cxl_memdev_get_bus(memdev) == bus) -- memdev->endpoint = NULL; -+ memdev->endpoint = NULL; - - bus_port = cxl_bus_get_port(bus); - list_for_each_safe(&bus_port->child_ports, port, _p, list) --- -2.27.0 - diff --git a/SOURCES/0162-cxl-list-Add-support-for-filtering-by-host-identifie.patch b/SOURCES/0162-cxl-list-Add-support-for-filtering-by-host-identifie.patch deleted file mode 100644 index 41d4ac3..0000000 --- a/SOURCES/0162-cxl-list-Add-support-for-filtering-by-host-identifie.patch +++ /dev/null @@ -1,73 +0,0 @@ -From cf0e0586bf45fd7e4ab17ce2b234bf68995daca3 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 28 Apr 2022 15:10:42 -0700 -Subject: [PATCH 162/217] cxl/list: Add support for filtering by host - identifiers - -Accept host device names as valid filters for memdevs, ports, and -endpoints. - -# cxl list -u -m 7 -{ - "memdev":"mem7", - "pmem_size":"256.00 MiB (268.44 MB)", - "ram_size":"256.00 MiB (268.44 MB)", - "serial":"0x6", - "numa_node":0, - "host":"cxl_mem.6" -} - -# cxl list -u -m cxl_mem.6 -{ - "memdev":"mem7", - "pmem_size":"256.00 MiB (268.44 MB)", - "ram_size":"256.00 MiB (268.44 MB)", - "serial":"0x6", - "numa_node":0, - "host":"cxl_mem.6" -} - -Link: https://lore.kernel.org/r/165118384289.1676208.4779565283924668304.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/filter.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/cxl/filter.c b/cxl/filter.c -index c6ab9eb..66fd742 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -73,6 +73,9 @@ struct cxl_endpoint *util_cxl_endpoint_filter(struct cxl_endpoint *endpoint, - - if (strcmp(arg, cxl_endpoint_get_devname(endpoint)) == 0) - break; -+ -+ if (strcmp(arg, cxl_endpoint_get_host(endpoint)) == 0) -+ break; - } - - free(ident); -@@ -116,6 +119,9 @@ static struct cxl_port *__util_cxl_port_filter(struct cxl_port *port, - - if (strcmp(arg, cxl_port_get_devname(port)) == 0) - break; -+ -+ if (strcmp(arg, cxl_port_get_host(port)) == 0) -+ break; - } - - free(ident); -@@ -303,6 +309,9 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, - - if (strcmp(name, cxl_memdev_get_devname(memdev)) == 0) - break; -+ -+ if (strcmp(name, cxl_memdev_get_host(memdev)) == 0) -+ break; - } - - free(ident); --- -2.27.0 - diff --git a/SOURCES/0163-cxl-port-Relax-port-identifier-validation.patch b/SOURCES/0163-cxl-port-Relax-port-identifier-validation.patch deleted file mode 100644 index 7d90528..0000000 --- a/SOURCES/0163-cxl-port-Relax-port-identifier-validation.patch +++ /dev/null @@ -1,92 +0,0 @@ -From e32631009a97e4cb72e4afb8eec09f89c3317eb9 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 28 Apr 2022 15:10:48 -0700 -Subject: [PATCH 163/217] cxl/port: Relax port identifier validation - -Now that util_cxl_port_filter() accepts port host identifiers it is no -longer possible to pre-validate that the port arguments follow the "port%d" -format. Instead, let all inputs through and warn if the filter fails to -identify a port. - -Link: https://lore.kernel.org/r/165118384845.1676208.7570620216888371408.stgit@dwillia2-desk3.amr.corp.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/port.c | 30 ++++-------------------------- - 1 file changed, 4 insertions(+), 26 deletions(-) - -diff --git a/cxl/port.c b/cxl/port.c -index 46a8f32..89f3916 100644 ---- a/cxl/port.c -+++ b/cxl/port.c -@@ -145,7 +145,6 @@ static int port_action(int argc, const char **argv, struct cxl_ctx *ctx, - usage, - NULL - }; -- unsigned long id; - - log_init(&pl, "cxl port", "CXL_PORT_LOG"); - argc = parse_options(argc, argv, options, u, 0); -@@ -153,31 +152,10 @@ static int port_action(int argc, const char **argv, struct cxl_ctx *ctx, - if (argc == 0) - usage_with_options(u, options); - for (i = 0; i < argc; i++) { -- const char *fmt; -- - if (strcmp(argv[i], "all") == 0) { - argc = 1; - break; - } -- -- if (param.endpoint) -- fmt = "endpoint%lu"; -- else -- fmt = "port%lu"; -- -- if (sscanf(argv[i], fmt, &id) == 1) -- continue; -- if (sscanf(argv[i], "%lu", &id) == 1) -- continue; -- -- log_err(&pl, "'%s' is not a valid %s identifer\n", argv[i], -- param.endpoint ? "endpoint" : "port"); -- err++; -- } -- -- if (err == argc) { -- usage_with_options(u, options); -- return -EINVAL; - } - - if (param.debug) { -@@ -187,7 +165,6 @@ static int port_action(int argc, const char **argv, struct cxl_ctx *ctx, - pl.log_priority = LOG_INFO; - - rc = 0; -- err = 0; - count = 0; - - for (i = 0; i < argc; i++) { -@@ -198,15 +175,16 @@ static int port_action(int argc, const char **argv, struct cxl_ctx *ctx, - - endpoint = find_cxl_endpoint(ctx, argv[i]); - if (!endpoint) { -- log_dbg(&pl, "endpoint: %s not found\n", -- argv[i]); -+ log_notice(&pl, "endpoint: %s not found\n", -+ argv[i]); - continue; - } - port = cxl_endpoint_get_port(endpoint); - } else { - port = find_cxl_port(ctx, argv[i]); - if (!port) { -- log_dbg(&pl, "port: %s not found\n", argv[i]); -+ log_notice(&pl, "port: %s not found\n", -+ argv[i]); - continue; - } - } --- -2.27.0 - diff --git a/SOURCES/0165-cxl-test-Add-topology-enumeration-and-hotplug-test.patch b/SOURCES/0165-cxl-test-Add-topology-enumeration-and-hotplug-test.patch deleted file mode 100644 index c45213e..0000000 --- a/SOURCES/0165-cxl-test-Add-topology-enumeration-and-hotplug-test.patch +++ /dev/null @@ -1,236 +0,0 @@ -From ef85ab79e7a45d19ca329c6e4cad9881a5a904e9 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 28 Apr 2022 15:10:54 -0700 -Subject: [PATCH 165/217] cxl/test: Add topology enumeration and hotplug test - -Test the re-plug of memdevs, switch ports, root ports, and bus objects. - -Link: https://lore.kernel.org/r/165118385401.1676208.9224280236045777443.stgit@dwillia2-desk3.amr.corp.intel.com -Cc: Luis Chamberlain -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/common | 12 ++++ - test/cxl-topology.sh | 166 +++++++++++++++++++++++++++++++++++++++++++ - test/meson.build | 2 + - 3 files changed, 180 insertions(+) - create mode 100644 test/cxl-topology.sh - -diff --git a/test/common b/test/common -index fb48795..65615cc 100644 ---- a/test/common -+++ b/test/common -@@ -27,6 +27,18 @@ if [ -z $DAXCTL ]; then - fi - fi - -+# CXL -+if [ -z $CXL ]; then -+ if [ -f "../cxl/cxl" ] && [ -x "../cxl/cxl" ]; then -+ export CXL=../cxl/cxl -+ elif [ -f "./cxl/cxl" ] && [ -x "./cxl/cxl" ]; then -+ export CXL=./cxl/cxl -+ else -+ echo "Couldn't find a cxl binary" -+ exit 1 -+ fi -+fi -+ - if [ -z $TEST_PATH ]; then - export TEST_PATH=. - fi -diff --git a/test/cxl-topology.sh b/test/cxl-topology.sh -new file mode 100644 -index 0000000..ff11614 ---- /dev/null -+++ b/test/cxl-topology.sh -@@ -0,0 +1,166 @@ -+#!/bin/bash -+# SPDX-License-Identifier: GPL-2.0 -+# Copyright (C) 2022 Intel Corporation. All rights reserved. -+ -+. $(dirname $0)/common -+ -+rc=1 -+ -+set -ex -+ -+trap 'err $LINENO' ERR -+ -+check_prereq "jq" -+ -+modprobe -r cxl_test -+modprobe cxl_test -+udevadm settle -+ -+# THEORY OF OPERATION: Validate the hard coded assumptions of the -+# cxl_test.ko module that defines its topology in -+# tools/testing/cxl/test/cxl.c. If that model ever changes then the -+# paired update must be made to this test. -+ -+# collect cxl_test root device id -+json=$($CXL list -b cxl_test) -+count=$(jq "length" <<< $json) -+((count == 1)) || err "$LINENO" -+root=$(jq -r ".[] | .bus" <<< $json) -+ -+ -+# validate 2 host bridges under a root port -+port_sort="sort_by(.port | .[4:] | tonumber)" -+json=$($CXL list -b cxl_test -BP) -+count=$(jq ".[] | .[\"ports:$root\"] | length" <<< $json) -+((count == 2)) || err "$LINENO" -+ -+bridge[0]=$(jq -r ".[] | .[\"ports:$root\"] | $port_sort | .[0].port" <<< $json) -+bridge[1]=$(jq -r ".[] | .[\"ports:$root\"] | $port_sort | .[1].port" <<< $json) -+ -+ -+# validate 2 root ports per host bridge -+json=$($CXL list -b cxl_test -T -p ${bridge[0]}) -+count=$(jq ".[] | .dports | length" <<< $json) -+((count == 2)) || err "$LINENO" -+ -+json=$($CXL list -b cxl_test -T -p ${bridge[1]}) -+count=$(jq ".[] | .dports | length" <<< $json) -+((count == 2)) || err "$LINENO" -+ -+ -+# validate 2 switches per-root port -+json=$($CXL list -b cxl_test -P -p ${bridge[0]}) -+count=$(jq ".[] | .[\"ports:${bridge[0]}\"] | length" <<< $json) -+((count == 2)) || err "$LINENO" -+ -+switch[0]=$(jq -r ".[] | .[\"ports:${bridge[0]}\"] | $port_sort | .[0].host" <<< $json) -+switch[1]=$(jq -r ".[] | .[\"ports:${bridge[0]}\"] | $port_sort | .[1].host" <<< $json) -+ -+json=$($CXL list -b cxl_test -P -p ${bridge[1]}) -+count=$(jq ".[] | .[\"ports:${bridge[1]}\"] | length" <<< $json) -+((count == 2)) || err "$LINENO" -+ -+switch[2]=$(jq -r ".[] | .[\"ports:${bridge[1]}\"] | $port_sort | .[0].host" <<< $json) -+switch[3]=$(jq -r ".[] | .[\"ports:${bridge[1]}\"] | $port_sort | .[1].host" <<< $json) -+ -+ -+# check that all 8 cxl_test memdevs are enabled by default and have a -+# pmem size of 256M -+json=$($CXL list -b cxl_test -M) -+count=$(jq "map(select(.pmem_size == $((256 << 20)))) | length" <<< $json) -+((count == 8)) || err "$LINENO" -+ -+ -+# validate the expected properties of the 4 root decoders -+json=$($CXL list -b cxl_test -D -d root) -+port_id=${root:4} -+port_id_len=${#port_id} -+decoder_sort="sort_by(.decoder | .[$((8+port_id_len)):] | tonumber)" -+count=$(jq "[ $decoder_sort | .[0] | -+ select(.volatile_capable == true) | -+ select(.size == $((256 << 20))) | -+ select(.nr_targets == 1) ] | length" <<< $json) -+((count == 1)) || err "$LINENO" -+ -+count=$(jq "[ $decoder_sort | .[1] | -+ select(.volatile_capable == true) | -+ select(.size == $((512 << 20))) | -+ select(.nr_targets == 2) ] | length" <<< $json) -+((count == 1)) || err "$LINENO" -+ -+count=$(jq "[ $decoder_sort | .[2] | -+ select(.pmem_capable == true) | -+ select(.size == $((256 << 20))) | -+ select(.nr_targets == 1) ] | length" <<< $json) -+((count == 1)) || err "$LINENO" -+ -+count=$(jq "[ $decoder_sort | .[3] | -+ select(.pmem_capable == true) | -+ select(.size == $((512 << 20))) | -+ select(.nr_targets == 2) ] | length" <<< $json) -+((count == 1)) || err "$LINENO" -+ -+# check that switch ports disappear after all of their memdevs have been -+# disabled, and return when the memdevs are enabled. -+for s in ${switch[@]} -+do -+ json=$($CXL list -M -p $s) -+ count=$(jq "length" <<< $json) -+ ((count == 2)) || err "$LINENO" -+ -+ mem[0]=$(jq -r ".[0] | .memdev" <<< $json) -+ mem[1]=$(jq -r ".[1] | .memdev" <<< $json) -+ -+ $CXL disable-memdev ${mem[0]} --force -+ json=$($CXL list -p $s) -+ count=$(jq "length" <<< $json) -+ ((count == 1)) || err "$LINENO" -+ -+ $CXL disable-memdev ${mem[1]} --force -+ json=$($CXL list -p $s) -+ count=$(jq "length" <<< $json) -+ ((count == 0)) || err "$LINENO" -+ -+ $CXL enable-memdev ${mem[0]} -+ $CXL enable-memdev ${mem[1]} -+ -+ json=$($CXL list -p $s) -+ count=$(jq "length" <<< $json) -+ ((count == 1)) || err "$LINENO" -+ -+ $CXL disable-port $s --force -+ json=$($CXL list -p $s) -+ count=$(jq "length" <<< $json) -+ ((count == 0)) || err "$LINENO" -+ -+ $CXL enable-memdev ${mem[0]} ${mem[1]} -+ json=$($CXL list -p $s) -+ count=$(jq "length" <<< $json) -+ ((count == 1)) || err "$LINENO" -+done -+ -+ -+# validate host bridge tear down -+for b in ${bridge[@]} -+do -+ $CXL disable-port $b -f -+ json=$($CXL list -M -i -p $b) -+ count=$(jq "map(select(.state == \"disabled\")) | length" <<< $json) -+ ((count == 4)) || err "$LINENO" -+ -+ $CXL enable-port $b -m -+ json=$($CXL list -M -p $b) -+ count=$(jq "length" <<< $json) -+ ((count == 4)) || err "$LINENO" -+done -+ -+ -+# validate that the bus can be disabled without issue -+$CXL disable-bus $root -f -+ -+ -+# validate no WARN or lockdep report during the run -+log=$(journalctl -r -k --since "-$((SECONDS+1))s") -+grep -q "Call Trace" <<< $log && err "$LINENO" -+ -+modprobe -r cxl_test -diff --git a/test/meson.build b/test/meson.build -index 7ccd451..210dcb0 100644 ---- a/test/meson.build -+++ b/test/meson.build -@@ -150,6 +150,7 @@ monitor = find_program('monitor.sh') - max_extent = find_program('max_available_extent_ns.sh') - pfn_meta_errors = find_program('pfn-meta-errors.sh') - track_uuid = find_program('track-uuid.sh') -+cxl_topo = find_program('cxl-topology.sh') - - tests = [ - [ 'libndctl', libndctl, 'ndctl' ], -@@ -174,6 +175,7 @@ tests = [ - [ 'max_extent_ns', max_extent, 'ndctl' ], - [ 'pfn-meta-errors.sh', pfn_meta_errors, 'ndctl' ], - [ 'track-uuid.sh', track_uuid, 'ndctl' ], -+ [ 'cxl-topology.sh', cxl_topo, 'cxl' ], - ] - - if get_option('destructive').enabled() --- -2.27.0 - diff --git a/SOURCES/0167-daxctl-Fix-kernel-option-typo-in-Soft-Reservation-th.patch b/SOURCES/0167-daxctl-Fix-kernel-option-typo-in-Soft-Reservation-th.patch deleted file mode 100644 index 459a951..0000000 --- a/SOURCES/0167-daxctl-Fix-kernel-option-typo-in-Soft-Reservation-th.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 4bd100a8c97cfd9592be74af2e4699a2ab6d2f34 Mon Sep 17 00:00:00 2001 -From: Michal Suchanek -Date: Thu, 10 Mar 2022 14:30:35 +0100 -Subject: [PATCH 167/217] daxctl: Fix kernel option typo in "Soft Reservation" - theory of operation - -Link: https://lore.kernel.org/r/20220310133035.GA106666@kunlun.suse.cz -Fixes: 8f4e42c ("daxctl: Add "Soft Reservation" theory of operation") -Signed-off-by: Michal Suchanek -Signed-off-by: Vishal Verma ---- - Documentation/daxctl/daxctl-reconfigure-device.txt | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/Documentation/daxctl/daxctl-reconfigure-device.txt b/Documentation/daxctl/daxctl-reconfigure-device.txt -index 385c0c5..09691d2 100644 ---- a/Documentation/daxctl/daxctl-reconfigure-device.txt -+++ b/Documentation/daxctl/daxctl-reconfigure-device.txt -@@ -91,8 +91,8 @@ details. - Outside of the NUMA performance details linked above the other method to - detect the presence of "Soft Reserved" memory is to dump /proc/iomem and - look for "Soft Reserved" ranges. If the kernel was not built with --CONFIG_EFI_SOFTRESERVE, predates the introduction of --CONFIG_EFI_SOFTRESERVE (v5.5), or was booted with the efi=nosoftreserve -+CONFIG_EFI_SOFT_RESERVE, predates the introduction of -+CONFIG_EFI_SOFT_RESERVE (v5.5), or was booted with the efi=nosoftreserve - command line then device-dax will not attach and the expectation is that - the memory shows up as a memory-only NUMA node. Otherwise the memory - shows up as a device-dax instance and DAXCTL(1) can be used to --- -2.27.0 - diff --git a/SOURCES/0168-meson-make-modprobedatadir-an-option.patch b/SOURCES/0168-meson-make-modprobedatadir-an-option.patch deleted file mode 100644 index f6d1551..0000000 --- a/SOURCES/0168-meson-make-modprobedatadir-an-option.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 524ad09d5eda320b299468324a2f94fc1802ef00 Mon Sep 17 00:00:00 2001 -From: Michal Suchanek -Date: Thu, 10 Mar 2022 14:30:55 +0100 -Subject: [PATCH 168/217] meson: make modprobedatadir an option - -The modprobe.d directory location is hardcoded. - -Link: https://lore.kernel.org/r/20220310133055.GA106731@kunlun.suse.cz -Fixes: 4e5faa1 ("build: Add meson build infrastructure") -Signed-off-by: Michal Suchanek -Signed-off-by: Vishal Verma ---- - contrib/meson.build | 5 ++++- - meson_options.txt | 2 ++ - 2 files changed, 6 insertions(+), 1 deletion(-) - -diff -up ndctl-71.1/contrib/meson.build.orig ndctl-71.1/contrib/meson.build ---- ndctl-71.1/contrib/meson.build.orig 2022-10-07 16:42:24.750025016 -0400 -+++ ndctl-71.1/contrib/meson.build 2022-10-07 16:42:39.374074806 -0400 -@@ -24,5 +24,8 @@ if bashcompletiondir != 'no' - install_data('ndctl', rename : 'cxl', install_dir : bashcompletiondir) - endif - --modprobedatadir = get_option('sysconfdir') + '/modprobe.d/' -+modprobedatadir = get_option('modprobedatadir') -+if modprobedatadir == '' -+ modprobedatadir = get_option('modprobedatadir') -+endif - install_data('nvdimm-security.conf', install_dir : modprobedatadir) -diff -up ndctl-71.1/meson_options.txt.orig ndctl-71.1/meson_options.txt ---- ndctl-71.1/meson_options.txt.orig 2022-10-07 16:42:39.375074810 -0400 -+++ ndctl-71.1/meson_options.txt 2022-10-07 16:43:10.553180961 -0400 -@@ -23,3 +23,5 @@ option('pkgconfiglibdir', type : 'string - description : 'directory for standard pkg-config files') - option('bashcompletiondir', type : 'string', - description : '''${datadir}/bash-completion/completions''') -+option('modprobedatadir', type : 'string', -+ description : '''${sysconfdir}/modprobe.d/''') diff --git a/SOURCES/0169-namespace-action-Drop-more-zero-namespace-checks.patch b/SOURCES/0169-namespace-action-Drop-more-zero-namespace-checks.patch deleted file mode 100644 index 5186339..0000000 --- a/SOURCES/0169-namespace-action-Drop-more-zero-namespace-checks.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 2f3851912624e9ede3132cd3749b4f60a348b1d4 Mon Sep 17 00:00:00 2001 -From: Michal Suchanek -Date: Thu, 10 Mar 2022 14:31:06 +0100 -Subject: [PATCH 169/217] namespace-action: Drop more zero namespace checks - -With seed namespaces caught early on with -commit 9bd2994 ("ndctl/namespace: Skip seed namespaces when processing all namespaces.") -commit 07011a3 ("ndctl/namespace: Suppress -ENXIO when processing all namespaces.") -the function-specific checks are no longer needed and can be dropped. - -Reverts commit fb13dfb ("zero_info_block: skip seed devices") -Reverts commit fe626a8 ("ndctl/namespace: Fix disable-namespace accounting relative to seed devices") - -Link: https://lore.kernel.org/r/20220310133106.GA106734@kunlun.suse.cz -Fixes: 80e0d88 ("namespace-action: Drop zero namespace checks.") -Fixes: fb13dfb ("zero_info_block: skip seed devices") -Fixes: fe626a8 ("ndctl/namespace: Fix disable-namespace accounting relative to seed devices") -Signed-off-by: Michal Suchanek -Signed-off-by: Vishal Verma ---- - ndctl/lib/libndctl.c | 7 +------ - ndctl/namespace.c | 11 ++++------- - ndctl/region.c | 2 +- - 3 files changed, 6 insertions(+), 14 deletions(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index ccca8b5..110d8a5 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -4593,7 +4593,6 @@ NDCTL_EXPORT int ndctl_namespace_disable_safe(struct ndctl_namespace *ndns) - const char *bdev = NULL; - int fd, active = 0; - char path[50]; -- unsigned long long size = ndctl_namespace_get_size(ndns); - - if (pfn && ndctl_pfn_is_enabled(pfn)) - bdev = ndctl_pfn_get_block_device(pfn); -@@ -4630,11 +4629,7 @@ NDCTL_EXPORT int ndctl_namespace_disable_safe(struct ndctl_namespace *ndns) - devname); - return -EBUSY; - } else { -- if (size == 0) -- /* No disable necessary due to no capacity allocated */ -- return 1; -- else -- ndctl_namespace_disable_invalidate(ndns); -+ ndctl_namespace_disable_invalidate(ndns); - } - - return 0; -diff --git a/ndctl/namespace.c b/ndctl/namespace.c -index 257b58c..722f13a 100644 ---- a/ndctl/namespace.c -+++ b/ndctl/namespace.c -@@ -1054,9 +1054,6 @@ static int zero_info_block(struct ndctl_namespace *ndns) - void *buf = NULL, *read_buf = NULL; - char path[50]; - -- if (ndctl_namespace_get_size(ndns) == 0) -- return 1; -- - ndctl_namespace_set_raw_mode(ndns, 1); - rc = ndctl_namespace_enable(ndns); - if (rc < 0) { -@@ -1130,7 +1127,7 @@ static int namespace_prep_reconfig(struct ndctl_region *region, - } - - rc = ndctl_namespace_disable_safe(ndns); -- if (rc < 0) -+ if (rc) - return rc; - - ndctl_namespace_set_enforce_mode(ndns, NDCTL_NS_MODE_RAW); -@@ -1426,7 +1423,7 @@ static int dax_clear_badblocks(struct ndctl_dax *dax) - return -ENXIO; - - rc = ndctl_namespace_disable_safe(ndns); -- if (rc < 0) { -+ if (rc) { - error("%s: unable to disable namespace: %s\n", devname, - strerror(-rc)); - return rc; -@@ -1450,7 +1447,7 @@ static int pfn_clear_badblocks(struct ndctl_pfn *pfn) - return -ENXIO; - - rc = ndctl_namespace_disable_safe(ndns); -- if (rc < 0) { -+ if (rc) { - error("%s: unable to disable namespace: %s\n", devname, - strerror(-rc)); - return rc; -@@ -1473,7 +1470,7 @@ static int raw_clear_badblocks(struct ndctl_namespace *ndns) - return -ENXIO; - - rc = ndctl_namespace_disable_safe(ndns); -- if (rc < 0) { -+ if (rc) { - error("%s: unable to disable namespace: %s\n", devname, - strerror(-rc)); - return rc; -diff --git a/ndctl/region.c b/ndctl/region.c -index e499546..33828b0 100644 ---- a/ndctl/region.c -+++ b/ndctl/region.c -@@ -71,7 +71,7 @@ static int region_action(struct ndctl_region *region, enum device_action mode) - case ACTION_DISABLE: - ndctl_namespace_foreach(region, ndns) { - rc = ndctl_namespace_disable_safe(ndns); -- if (rc < 0) -+ if (rc) - return rc; - } - rc = ndctl_region_disable_invalidate(region); --- -2.27.0 - diff --git a/SOURCES/0170-ndctl-dimm-Flush-invalidated-labels-after-overwrite.patch b/SOURCES/0170-ndctl-dimm-Flush-invalidated-labels-after-overwrite.patch deleted file mode 100644 index 5eeba2f..0000000 --- a/SOURCES/0170-ndctl-dimm-Flush-invalidated-labels-after-overwrite.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 8186ec87dcd1b347ab0ee27ec5e87bda8c9a67e2 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 28 Apr 2022 16:54:48 -0700 -Subject: [PATCH 170/217] ndctl/dimm: Flush invalidated labels after overwrite - -Similar to "ndctl write-labels", after "ndctl sanitize-dimm --overwrite" -the kernel may contain a cached copy of the label area that has been -invalidated by the overwrite. Toggle the enabled state of the dimm-device -to trigger the kernel to release the cached copy. - -Link: https://lore.kernel.org/all/165118817010.1772793.5101398830527716084.stgit@dwillia2-desk3.amr.corp.intel.com/ -Link: https://lore.kernel.org/r/165119008839.1783158.3766085644383173318.stgit@dwillia2-desk3.amr.corp.intel.com -Cc: Jeff Moyer -Cc: Dave Jiang -Acked-by: Jeff Moyer -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - ndctl/dimm.c | 34 ++++++++++++++++++++++------------ - 1 file changed, 22 insertions(+), 12 deletions(-) - -diff --git a/ndctl/dimm.c b/ndctl/dimm.c -index d9718a3..ac7c527 100644 ---- a/ndctl/dimm.c -+++ b/ndctl/dimm.c -@@ -354,6 +354,23 @@ static int rw_bin(FILE *f, struct ndctl_cmd *cmd, ssize_t size, - return 0; - } - -+static int revalidate_labels(struct ndctl_dimm *dimm) -+{ -+ int rc; -+ -+ /* -+ * If the dimm is already disabled the kernel is not holding a cached -+ * copy of the label space. -+ */ -+ if (!ndctl_dimm_is_enabled(dimm)) -+ return 0; -+ -+ rc = ndctl_dimm_disable(dimm); -+ if (rc) -+ return rc; -+ return ndctl_dimm_enable(dimm); -+} -+ - static int action_write(struct ndctl_dimm *dimm, struct action_context *actx) - { - struct ndctl_cmd *cmd_read, *cmd_write; -@@ -377,18 +394,10 @@ static int action_write(struct ndctl_dimm *dimm, struct action_context *actx) - - size = ndctl_cmd_cfg_read_get_size(cmd_read); - rc = rw_bin(actx->f_in, cmd_write, size, param.offset, WRITE); -- -- /* -- * If the dimm is already disabled the kernel is not holding a cached -- * copy of the label space. -- */ -- if (!ndctl_dimm_is_enabled(dimm)) -- goto out; -- -- rc = ndctl_dimm_disable(dimm); - if (rc) - goto out; -- rc = ndctl_dimm_enable(dimm); -+ -+ rc = revalidate_labels(dimm); - - out: - ndctl_cmd_unref(cmd_read); -@@ -1043,7 +1052,7 @@ static int action_security_freeze(struct ndctl_dimm *dimm, - static int action_sanitize_dimm(struct ndctl_dimm *dimm, - struct action_context *actx) - { -- int rc; -+ int rc = 0; - enum ndctl_key_type key_type; - - if (ndctl_dimm_get_security(dimm) < 0) { -@@ -1085,9 +1094,10 @@ static int action_sanitize_dimm(struct ndctl_dimm *dimm, - rc = ndctl_dimm_overwrite_key(dimm); - if (rc < 0) - return rc; -+ rc = revalidate_labels(dimm); - } - -- return 0; -+ return rc; - } - - static int action_wait_overwrite(struct ndctl_dimm *dimm, --- -2.27.0 - diff --git a/SOURCES/0171-libcxl-fix-a-segfault-when-memdev-pmem-is-absent.patch b/SOURCES/0171-libcxl-fix-a-segfault-when-memdev-pmem-is-absent.patch deleted file mode 100644 index b793e8b..0000000 --- a/SOURCES/0171-libcxl-fix-a-segfault-when-memdev-pmem-is-absent.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 50e7a021314aa0365c9c85a359a31f26313fe93b Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 2 Jun 2022 09:44:27 -0600 -Subject: [PATCH 171/217] libcxl: fix a segfault when memdev->pmem is absent - -A CXL memdev may not have any persistent capacity, and in this case it -is possible that a 'pmem' object never gets instantiated. Such a -scenario would cause free_pmem () to dereference a NULL pointer and -segfault. - -Fix this by only proceeding in free_pmem() if 'pmem' was valid. - -Link: https://lore.kernel.org/r/20220602154427.462852-1-vishal.l.verma@intel.com -Fixes: cd1aed6cefe8 ("libcxl: add representation for an nvdimm bridge object") -Cc: Dan Williams -Reported-by: Steven Garcia -Tested-by: Steven Garcia -Reviewed-by: Alison Schofield -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 374b0f1..c988ce2 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -49,9 +49,11 @@ struct cxl_ctx { - - static void free_pmem(struct cxl_pmem *pmem) - { -- free(pmem->dev_buf); -- free(pmem->dev_path); -- free(pmem); -+ if (pmem) { -+ free(pmem->dev_buf); -+ free(pmem->dev_path); -+ free(pmem); -+ } - } - - static void free_memdev(struct cxl_memdev *memdev, struct list_head *head) --- -2.27.0 - diff --git a/SOURCES/0172-ndctl-bus-Handle-missing-scrub-commands-more-gracefu.patch b/SOURCES/0172-ndctl-bus-Handle-missing-scrub-commands-more-gracefu.patch deleted file mode 100644 index 7973f8d..0000000 --- a/SOURCES/0172-ndctl-bus-Handle-missing-scrub-commands-more-gracefu.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 3e17210345482ec9795f1046c766564d3b8a0795 Mon Sep 17 00:00:00 2001 -From: Tarun Sahu -Date: Mon, 2 May 2022 12:34:54 +0530 -Subject: [PATCH 172/217] ndctl/bus: Handle missing scrub commands more - gracefully - -Buses that don't have nfit support return "No such file or directory" -for start-scrub/wait-scrub command. - -Presently, non-nfit support buses do not support start-scrub/ wait-scrub -operation. This patch is to handle these commands more gracefully by -returning" Operation not supported". - -This has been tested on PPC64le lpar with nvdimm that does not support -scrub. - -Previously: - $ ./ndctl start-scrub ndbus0 - error starting scrub: No such file or directory - -Now: - $ ./ndctl start-scrub ndbus0 - error starting scrub: Operation not supported - -- Invalid ndbus - $ sudo ./ndctl start-scrub ndbus5 - error starting scrub: No such device or address - -Link: https://lore.kernel.org/r/20220502070454.179153-1-tsahu@linux.ibm.com -Tested-by: Vaibhav Jain -Reviewed-by: Vaibhav Jain -Signed-off-by: Tarun Sahu -Signed-off-by: Vishal Verma ---- - ndctl/lib/libndctl.c | 18 ++++++++++++++---- - 1 file changed, 14 insertions(+), 4 deletions(-) - -diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c -index 110d8a5..ad54f06 100644 ---- a/ndctl/lib/libndctl.c -+++ b/ndctl/lib/libndctl.c -@@ -938,10 +938,14 @@ static void *add_bus(void *parent, int id, const char *ctl_base) - if (!bus->wait_probe_path) - goto err_read; - -- sprintf(path, "%s/device/nfit/scrub", ctl_base); -- bus->scrub_path = strdup(path); -- if (!bus->scrub_path) -- goto err_read; -+ if (ndctl_bus_has_nfit(bus)) { -+ sprintf(path, "%s/device/nfit/scrub", ctl_base); -+ bus->scrub_path = strdup(path); -+ if (!bus->scrub_path) -+ goto err_read; -+ } else { -+ bus->scrub_path = NULL; -+ } - - sprintf(path, "%s/device/firmware/activate", ctl_base); - if (sysfs_read_attr(ctx, path, buf) < 0) -@@ -1377,6 +1381,9 @@ NDCTL_EXPORT int ndctl_bus_start_scrub(struct ndctl_bus *bus) - struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus); - int rc; - -+ if (bus->scrub_path == NULL) -+ return -EOPNOTSUPP; -+ - rc = sysfs_write_attr(ctx, bus->scrub_path, "1\n"); - - /* -@@ -1447,6 +1454,9 @@ NDCTL_EXPORT int ndctl_bus_poll_scrub_completion(struct ndctl_bus *bus, - char in_progress; - int fd = 0, rc; - -+ if (bus->scrub_path == NULL) -+ return -EOPNOTSUPP; -+ - fd = open(bus->scrub_path, O_RDONLY|O_CLOEXEC); - if (fd < 0) - return -errno; --- -2.27.0 - diff --git a/SOURCES/0173-util-wrapper.c-Fix-gcc-warning-in-xrealloc.patch b/SOURCES/0173-util-wrapper.c-Fix-gcc-warning-in-xrealloc.patch deleted file mode 100644 index 98e1e95..0000000 --- a/SOURCES/0173-util-wrapper.c-Fix-gcc-warning-in-xrealloc.patch +++ /dev/null @@ -1,58 +0,0 @@ -From bbb2cb56f08d95ecf2c7c047a33cc3dd64eb7fde Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Thu, 16 Jun 2022 13:35:29 -0600 -Subject: [PATCH 173/217] util/wrapper.c: Fix gcc warning in xrealloc() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -A GCC update (12.1.1) now produces a warning in the xrealloc() wrapper -(originally copied from git, and used in strbuf operations): - - ../util/wrapper.c: In function ‘xrealloc’: - ../util/wrapper.c:34:31: warning: pointer ‘ptr’ may be used after ‘realloc’ [-Wuse-after-free] - 34 | ret = realloc(ptr, 1); - | ^~~~~~~~~~~~~~~ - -Pull in an updated definition for xrealloc() from the git project to fix this. - -Link: https://lore.kernel.org/r/20220616193529.56513-1-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - util/wrapper.c | 18 +++++++++--------- - 1 file changed, 9 insertions(+), 9 deletions(-) - -diff --git a/util/wrapper.c b/util/wrapper.c -index 026a54f..6adfde6 100644 ---- a/util/wrapper.c -+++ b/util/wrapper.c -@@ -25,15 +25,15 @@ char *xstrdup(const char *str) - - void *xrealloc(void *ptr, size_t size) - { -- void *ret = realloc(ptr, size); -- if (!ret && !size) -- ret = realloc(ptr, 1); -- if (!ret) { -- ret = realloc(ptr, size); -- if (!ret && !size) -- ret = realloc(ptr, 1); -- if (!ret) -- die("Out of memory, realloc failed"); -+ void *ret; -+ -+ if (!size) { -+ free(ptr); -+ return malloc(1); - } -+ -+ ret = realloc(ptr, size); -+ if (!ret) -+ die("Out of memory, realloc failed"); - return ret; - } --- -2.27.0 - diff --git a/SOURCES/0174-libcxl-Fix-memory-leakage-in-cxl_port_init.patch b/SOURCES/0174-libcxl-Fix-memory-leakage-in-cxl_port_init.patch deleted file mode 100644 index e572d19..0000000 --- a/SOURCES/0174-libcxl-Fix-memory-leakage-in-cxl_port_init.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 29a9e9daa67e2b68bb2433c31fdbc82e86b5f0fe Mon Sep 17 00:00:00 2001 -From: Shivaprasad G Bhat -Date: Mon, 18 Jul 2022 13:53:35 +0530 -Subject: [PATCH 174/217] libcxl: Fix memory leakage in cxl_port_init() - -The local variable 'path' is not freed in cxl_port_init() for success case. -The patch fixes that. - -Link: https://lore.kernel.org/r/165813258358.95191.6678871197554236554.stgit@LAPTOP-TBQTPII8 -Reviewed-by: Dan Williams -Signed-off-by: Shivaprasad G Bhat -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index c988ce2..bf3568d 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -769,6 +769,7 @@ static int cxl_port_init(struct cxl_port *port, struct cxl_port *parent_port, - if (sysfs_read_attr(ctx, path, buf) == 0) - port->module = util_modalias_to_module(ctx, buf); - -+ free(path); - return 0; - err: - free(port->dev_path); --- -2.27.0 - diff --git a/SOURCES/0175-cxl-list-Reformat-option-list.patch b/SOURCES/0175-cxl-list-Reformat-option-list.patch deleted file mode 100644 index 7c87aa8..0000000 --- a/SOURCES/0175-cxl-list-Reformat-option-list.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 6a843797767868279a5197699a53154bbed5eb2a Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 14 Jul 2022 10:01:52 -0700 -Subject: [PATCH 175/217] cxl/list: Reformat option list - -Cleanup some spurious spaces and let clang-format re-layout the options. - -Link: https://lore.kernel.org/r/165781811294.1555691.6271986101970794441.stgit@dwillia2-xfh.jf.intel.com -Reviewed-by: Davidlohr Bueso -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/list.c | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - -diff --git a/cxl/list.c b/cxl/list.c -index 940782d..1b5f583 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -36,8 +36,7 @@ static const struct option options[] = { - "filter by CXL endpoint device name(s)"), - OPT_BOOLEAN('E', "endpoints", ¶m.endpoints, - "include CXL endpoint info"), -- OPT_STRING('d', "decoder", ¶m.decoder_filter, -- "decoder device name", -+ OPT_STRING('d', "decoder", ¶m.decoder_filter, "decoder device name", - "filter by CXL decoder device name(s) / class"), - OPT_BOOLEAN('D', "decoders", ¶m.decoders, - "include CXL decoder info"), -@@ -45,11 +44,11 @@ static const struct option options[] = { - "include CXL target data with decoders or ports"), - OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"), - OPT_BOOLEAN('u', "human", ¶m.human, -- "use human friendly number formats "), -+ "use human friendly number formats"), - OPT_BOOLEAN('H', "health", ¶m.health, -- "include memory device health information "), -+ "include memory device health information"), - OPT_BOOLEAN('I', "partition", ¶m.partition, -- "include memory device partition information "), -+ "include memory device partition information"), - #ifdef ENABLE_DEBUG - OPT_BOOLEAN(0, "debug", &debug, "debug list walk"), - #endif --- -2.27.0 - diff --git a/SOURCES/0176-cxl-list-Emit-endpoint-decoders-filtered-by-memdev.patch b/SOURCES/0176-cxl-list-Emit-endpoint-decoders-filtered-by-memdev.patch deleted file mode 100644 index f41a7a4..0000000 --- a/SOURCES/0176-cxl-list-Emit-endpoint-decoders-filtered-by-memdev.patch +++ /dev/null @@ -1,46 +0,0 @@ -From b4262c8e65a4f5aa931b5451535084297968949d Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 14 Jul 2022 10:01:58 -0700 -Subject: [PATCH 176/217] cxl/list: Emit endpoint decoders filtered by memdev - -For example, dump all the endpoint decoders from memdev 'mem8'. - - cxl list -Di -m 8 -d endpoint - -Link: https://lore.kernel.org/r/165781811836.1555691.1997564050287016121.stgit@dwillia2-xfh.jf.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/filter.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/cxl/filter.c b/cxl/filter.c -index 66fd742..2f88a9d 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -428,7 +428,9 @@ util_cxl_decoder_filter_by_memdev(struct cxl_decoder *decoder, - const char *ident, const char *serial) - { - struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ struct cxl_endpoint *endpoint; - struct cxl_memdev *memdev; -+ struct cxl_port *port; - - if (!ident && !serial) - return decoder; -@@ -438,6 +440,12 @@ util_cxl_decoder_filter_by_memdev(struct cxl_decoder *decoder, - continue; - if (cxl_decoder_get_target_by_memdev(decoder, memdev)) - return decoder; -+ port = cxl_decoder_get_port(decoder); -+ if (!port || !cxl_port_is_endpoint(port)) -+ continue; -+ endpoint = cxl_port_to_endpoint(port); -+ if (cxl_endpoint_get_memdev(endpoint) == memdev) -+ return decoder; - } - - return NULL; --- -2.27.0 - diff --git a/SOURCES/0177-cxl-list-Hide-0s-in-disabled-decoder-listings.patch b/SOURCES/0177-cxl-list-Hide-0s-in-disabled-decoder-listings.patch deleted file mode 100644 index b2e2690..0000000 --- a/SOURCES/0177-cxl-list-Hide-0s-in-disabled-decoder-listings.patch +++ /dev/null @@ -1,59 +0,0 @@ -From f649df38298043f68e73bc730ccb824de045f42d Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 14 Jul 2022 10:02:04 -0700 -Subject: [PATCH 177/217] cxl/list: Hide 0s in disabled decoder listings - -Trim some redundant information from decoder listings when they are -disabled. - -Link: https://lore.kernel.org/r/165781812427.1555691.5252994293073680408.stgit@dwillia2-xfh.jf.intel.com -Reviewed-by: Davidlohr Bueso -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/json.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/cxl/json.c b/cxl/json.c -index fdc6f73..a213fda 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -442,7 +442,7 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - const char *devname = cxl_decoder_get_devname(decoder); - struct cxl_port *port = cxl_decoder_get_port(decoder); - struct json_object *jdecoder, *jobj; -- u64 val; -+ u64 val, size; - - jdecoder = json_object_new_object(); - if (!jdecoder) -@@ -452,21 +452,21 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - if (jobj) - json_object_object_add(jdecoder, "decoder", jobj); - -+ size = cxl_decoder_get_size(decoder); - val = cxl_decoder_get_resource(decoder); -- if (val < ULLONG_MAX) { -+ if (size && val < ULLONG_MAX) { - jobj = util_json_object_hex(val, flags); - if (jobj) - json_object_object_add(jdecoder, "resource", jobj); - } - -- val = cxl_decoder_get_size(decoder); -- if (val < ULLONG_MAX) { -- jobj = util_json_object_size(val, flags); -+ if (size && size < ULLONG_MAX) { -+ jobj = util_json_object_size(size, flags); - if (jobj) - json_object_object_add(jdecoder, "size", jobj); - } - -- if (val == 0) { -+ if (size == 0) { - jobj = json_object_new_string("disabled"); - if (jobj) - json_object_object_add(jdecoder, "state", jobj); --- -2.27.0 - diff --git a/SOURCES/0178-cxl-list-Add-DPA-span-to-endpoint-decoder-listings.patch b/SOURCES/0178-cxl-list-Add-DPA-span-to-endpoint-decoder-listings.patch deleted file mode 100644 index cac3194..0000000 --- a/SOURCES/0178-cxl-list-Add-DPA-span-to-endpoint-decoder-listings.patch +++ /dev/null @@ -1,167 +0,0 @@ -From bbc0da95d12b3c890cc323a34b48cf489d4b467a Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 14 Jul 2022 10:02:09 -0700 -Subject: [PATCH 178/217] cxl/list: Add DPA span to endpoint decoder listings - -Optionally include in decoder listings the device local address space for -endpoint decoders with active / allocated capacity. - -Link: https://lore.kernel.org/r/165781812967.1555691.4685129673233918478.stgit@dwillia2-xfh.jf.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/lib/libcxl.txt | 2 ++ - cxl/json.c | 18 +++++++++++++ - cxl/lib/libcxl.c | 43 +++++++++++++++++++++++++++++++- - cxl/lib/libcxl.sym | 6 +++++ - cxl/lib/private.h | 2 ++ - cxl/libcxl.h | 2 ++ - 6 files changed, 72 insertions(+), 1 deletion(-) - -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index f8f0e66..2aef489 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -392,6 +392,8 @@ more CXL decoder objects. - ---- - unsigned long long cxl_decoder_get_resource(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder); -+unsigned long long cxl_decoder_get_dpa_resource(struct cxl_decoder *decoder); -+unsigned long long cxl_decoder_get_dpa_size(struct cxl_decoder *decoder); - const char *cxl_decoder_get_devname(struct cxl_decoder *decoder); - int cxl_decoder_get_id(struct cxl_decoder *decoder); - int cxl_decoder_get_nr_targets(struct cxl_decoder *decoder); -diff --git a/cxl/json.c b/cxl/json.c -index a213fda..3f52d3b 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -472,6 +472,24 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - json_object_object_add(jdecoder, "state", jobj); - } - -+ if (cxl_port_is_endpoint(port)) { -+ size = cxl_decoder_get_dpa_size(decoder); -+ val = cxl_decoder_get_dpa_resource(decoder); -+ if (size && val < ULLONG_MAX) { -+ jobj = util_json_object_hex(val, flags); -+ if (jobj) -+ json_object_object_add(jdecoder, "dpa_resource", -+ jobj); -+ } -+ -+ if (size && size < ULLONG_MAX) { -+ jobj = util_json_object_size(size, flags); -+ if (jobj) -+ json_object_object_add(jdecoder, "dpa_size", -+ jobj); -+ } -+ } -+ - if (cxl_port_is_root(port) && cxl_decoder_is_mem_capable(decoder)) { - if (cxl_decoder_is_pmem_capable(decoder)) { - jobj = json_object_new_boolean(true); -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index bf3568d..6f4d64d 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -956,8 +956,19 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - decoder->size = strtoull(buf, NULL, 0); - - switch (port->type) { -- case CXL_PORT_SWITCH: - case CXL_PORT_ENDPOINT: -+ sprintf(path, "%s/dpa_resource", cxldecoder_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ decoder->dpa_resource = ULLONG_MAX; -+ else -+ decoder->dpa_resource = strtoull(buf, NULL, 0); -+ sprintf(path, "%s/dpa_size", cxldecoder_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ decoder->dpa_size = ULLONG_MAX; -+ else -+ decoder->dpa_size = strtoull(buf, NULL, 0); -+ -+ case CXL_PORT_SWITCH: - decoder->pmem_capable = true; - decoder->volatile_capable = true; - decoder->mem_capable = true; -@@ -1114,6 +1125,36 @@ CXL_EXPORT unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder) - return decoder->size; - } - -+CXL_EXPORT unsigned long long -+cxl_decoder_get_dpa_resource(struct cxl_decoder *decoder) -+{ -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ -+ if (!cxl_port_is_endpoint(port)) { -+ err(ctx, "%s: not an endpoint decoder\n", -+ cxl_decoder_get_devname(decoder)); -+ return ULLONG_MAX; -+ } -+ -+ return decoder->dpa_resource; -+} -+ -+CXL_EXPORT unsigned long long -+cxl_decoder_get_dpa_size(struct cxl_decoder *decoder) -+{ -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ -+ if (!cxl_port_is_endpoint(port)) { -+ err(ctx, "%s: not an endpoint decoder\n", -+ cxl_decoder_get_devname(decoder)); -+ return ULLONG_MAX; -+ } -+ -+ return decoder->dpa_size; -+} -+ - CXL_EXPORT enum cxl_decoder_target_type - cxl_decoder_get_target_type(struct cxl_decoder *decoder) - { -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index dffcb60..8e2fc75 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -167,3 +167,9 @@ global: - cxl_cmd_new_set_partition; - cxl_cmd_partition_set_mode; - } LIBCXL_1; -+ -+LIBCXL_3 { -+global: -+ cxl_decoder_get_dpa_resource; -+ cxl_decoder_get_dpa_size; -+} LIBCXL_2; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index c6d88f7..24a2ae6 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -101,6 +101,8 @@ struct cxl_decoder { - struct cxl_ctx *ctx; - u64 start; - u64 size; -+ u64 dpa_resource; -+ u64 dpa_size; - void *dev_buf; - size_t buf_len; - char *dev_path; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 0007f4d..76aebe3 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -129,6 +129,8 @@ struct cxl_decoder *cxl_decoder_get_first(struct cxl_port *port); - struct cxl_decoder *cxl_decoder_get_next(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_resource(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder); -+unsigned long long cxl_decoder_get_dpa_resource(struct cxl_decoder *decoder); -+unsigned long long cxl_decoder_get_dpa_size(struct cxl_decoder *decoder); - const char *cxl_decoder_get_devname(struct cxl_decoder *decoder); - struct cxl_target *cxl_decoder_get_target_by_memdev(struct cxl_decoder *decoder, - struct cxl_memdev *memdev); --- -2.27.0 - diff --git a/SOURCES/0179-ccan-list-Import-latest-list-helpers.patch b/SOURCES/0179-ccan-list-Import-latest-list-helpers.patch deleted file mode 100644 index 62bc153..0000000 --- a/SOURCES/0179-ccan-list-Import-latest-list-helpers.patch +++ /dev/null @@ -1,459 +0,0 @@ -From aaf1059e1c96b8052851030d4db971708e98e4d8 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 14 Jul 2022 10:02:15 -0700 -Subject: [PATCH 179/217] ccan/list: Import latest list helpers - -Pick up the definition of list_add_{before,after} and other updates from -ccan at commit 52b86922f846 ("ccan/base64: fix GCC warning."). - -Link: https://lore.kernel.org/r/165781813572.1555691.15909358688944168922.stgit@dwillia2-xfh.jf.intel.com -Reported-by: Ira Weiny -Reviewed-by: Ira Weiny -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - ccan/list/list.h | 258 ++++++++++++++++++++++++++++++++++++++------- - ndctl/lib/inject.c | 1 - - util/list.h | 40 ------- - 3 files changed, 222 insertions(+), 77 deletions(-) - delete mode 100644 util/list.h - -diff --git a/ccan/list/list.h b/ccan/list/list.h -index 3ebd1b2..15f5fb7 100644 ---- a/ccan/list/list.h -+++ b/ccan/list/list.h -@@ -95,8 +95,8 @@ struct list_node *list_check_node(const struct list_node *n, - #define list_debug(h, loc) list_check((h), loc) - #define list_debug_node(n, loc) list_check_node((n), loc) - #else --#define list_debug(h, loc) (h) --#define list_debug_node(n, loc) (n) -+#define list_debug(h, loc) ((void)loc, h) -+#define list_debug_node(n, loc) ((void)loc, n) - #endif - - /** -@@ -111,7 +111,7 @@ struct list_node *list_check_node(const struct list_node *n, - * Example: - * static struct list_head my_list = LIST_HEAD_INIT(my_list); - */ --#define LIST_HEAD_INIT(name) { { &name.n, &name.n } } -+#define LIST_HEAD_INIT(name) { { &(name).n, &(name).n } } - - /** - * LIST_HEAD - define and initialize an empty list_head -@@ -145,6 +145,48 @@ static inline void list_head_init(struct list_head *h) - h->n.next = h->n.prev = &h->n; - } - -+/** -+ * list_node_init - initialize a list_node -+ * @n: the list_node to link to itself. -+ * -+ * You don't need to use this normally! But it lets you list_del(@n) -+ * safely. -+ */ -+static inline void list_node_init(struct list_node *n) -+{ -+ n->next = n->prev = n; -+} -+ -+/** -+ * list_add_after - add an entry after an existing node in a linked list -+ * @h: the list_head to add the node to (for debugging) -+ * @p: the existing list_node to add the node after -+ * @n: the new list_node to add to the list. -+ * -+ * The existing list_node must already be a member of the list. -+ * The new list_node does not need to be initialized; it will be overwritten. -+ * -+ * Example: -+ * struct child c1, c2, c3; -+ * LIST_HEAD(h); -+ * -+ * list_add_tail(&h, &c1.list); -+ * list_add_tail(&h, &c3.list); -+ * list_add_after(&h, &c1.list, &c2.list); -+ */ -+#define list_add_after(h, p, n) list_add_after_(h, p, n, LIST_LOC) -+static inline void list_add_after_(struct list_head *h, -+ struct list_node *p, -+ struct list_node *n, -+ const char *abortstr) -+{ -+ n->next = p->next; -+ n->prev = p; -+ p->next->prev = n; -+ p->next = n; -+ (void)list_debug(h, abortstr); -+} -+ - /** - * list_add - add an entry at the start of a linked list. - * @h: the list_head to add the node to -@@ -163,10 +205,34 @@ static inline void list_add_(struct list_head *h, - struct list_node *n, - const char *abortstr) - { -- n->next = h->n.next; -- n->prev = &h->n; -- h->n.next->prev = n; -- h->n.next = n; -+ list_add_after_(h, &h->n, n, abortstr); -+} -+ -+/** -+ * list_add_before - add an entry before an existing node in a linked list -+ * @h: the list_head to add the node to (for debugging) -+ * @p: the existing list_node to add the node before -+ * @n: the new list_node to add to the list. -+ * -+ * The existing list_node must already be a member of the list. -+ * The new list_node does not need to be initialized; it will be overwritten. -+ * -+ * Example: -+ * list_head_init(&h); -+ * list_add_tail(&h, &c1.list); -+ * list_add_tail(&h, &c3.list); -+ * list_add_before(&h, &c3.list, &c2.list); -+ */ -+#define list_add_before(h, p, n) list_add_before_(h, p, n, LIST_LOC) -+static inline void list_add_before_(struct list_head *h, -+ struct list_node *p, -+ struct list_node *n, -+ const char *abortstr) -+{ -+ n->next = p; -+ n->prev = p->prev; -+ p->prev->next = n; -+ p->prev = n; - (void)list_debug(h, abortstr); - } - -@@ -185,11 +251,7 @@ static inline void list_add_tail_(struct list_head *h, - struct list_node *n, - const char *abortstr) - { -- n->next = &h->n; -- n->prev = h->n.prev; -- h->n.prev->next = n; -- h->n.prev = n; -- (void)list_debug(h, abortstr); -+ list_add_before_(h, &h->n, n, abortstr); - } - - /** -@@ -229,6 +291,21 @@ static inline bool list_empty_nodebug(const struct list_head *h) - } - #endif - -+/** -+ * list_empty_nocheck - is a list empty? -+ * @h: the list_head -+ * -+ * If the list is empty, returns true. This doesn't perform any -+ * debug check for list consistency, so it can be called without -+ * locks, racing with the list being modified. This is ok for -+ * checks where an incorrect result is not an issue (optimized -+ * bail out path for example). -+ */ -+static inline bool list_empty_nocheck(const struct list_head *h) -+{ -+ return h->n.next == &h->n; -+} -+ - /** - * list_del - delete an entry from an (unknown) linked list. - * @n: the list_node to delete from the list. -@@ -237,7 +314,7 @@ static inline bool list_empty_nodebug(const struct list_head *h) - * another list, but not deleted again. - * - * See also: -- * list_del_from() -+ * list_del_from(), list_del_init() - * - * Example: - * list_del(&child->list); -@@ -255,6 +332,27 @@ static inline void list_del_(struct list_node *n, const char* abortstr) - #endif - } - -+/** -+ * list_del_init - delete a node, and reset it so it can be deleted again. -+ * @n: the list_node to be deleted. -+ * -+ * list_del(@n) or list_del_init() again after this will be safe, -+ * which can be useful in some cases. -+ * -+ * See also: -+ * list_del_from(), list_del() -+ * -+ * Example: -+ * list_del_init(&child->list); -+ * parent->num_children--; -+ */ -+#define list_del_init(n) list_del_init_(n, LIST_LOC) -+static inline void list_del_init_(struct list_node *n, const char *abortstr) -+{ -+ list_del_(n, abortstr); -+ list_node_init(n); -+} -+ - /** - * list_del_from - delete an entry from a known linked list. - * @h: the list_head the node is in. -@@ -285,6 +383,39 @@ static inline void list_del_from(struct list_head *h, struct list_node *n) - list_del(n); - } - -+/** -+ * list_swap - swap out an entry from an (unknown) linked list for a new one. -+ * @o: the list_node to replace from the list. -+ * @n: the list_node to insert in place of the old one. -+ * -+ * Note that this leaves @o in an undefined state; it can be added to -+ * another list, but not deleted/swapped again. -+ * -+ * See also: -+ * list_del() -+ * -+ * Example: -+ * struct child x1, x2; -+ * LIST_HEAD(xh); -+ * -+ * list_add(&xh, &x1.list); -+ * list_swap(&x1.list, &x2.list); -+ */ -+#define list_swap(o, n) list_swap_(o, n, LIST_LOC) -+static inline void list_swap_(struct list_node *o, -+ struct list_node *n, -+ const char* abortstr) -+{ -+ (void)list_debug_node(o, abortstr); -+ *n = *o; -+ n->next->prev = n; -+ n->prev->next = n; -+#ifdef CCAN_LIST_DEBUG -+ /* Catch use-after-del. */ -+ o->next = o->prev = NULL; -+#endif -+} -+ - /** - * list_entry - convert a list_node back into the structure containing it. - * @n: the list_node -@@ -406,9 +537,29 @@ static inline const void *list_tail_(const struct list_head *h, size_t off) - * printf("Name: %s\n", child->name); - */ - #define list_for_each_rev(h, i, member) \ -- for (i = container_of_var(list_debug(h, LIST_LOC)->n.prev, i, member); \ -- &i->member != &(h)->n; \ -- i = container_of_var(i->member.prev, i, member)) -+ list_for_each_rev_off(h, i, list_off_var_(i, member)) -+ -+/** -+ * list_for_each_rev_safe - iterate through a list backwards, -+ * maybe during deletion -+ * @h: the list_head -+ * @i: the structure containing the list_node -+ * @nxt: the structure containing the list_node -+ * @member: the list_node member of the structure -+ * -+ * This is a convenient wrapper to iterate @i over the entire list backwards. -+ * It's a for loop, so you can break and continue as normal. The extra -+ * variable * @nxt is used to hold the next element, so you can delete @i -+ * from the list. -+ * -+ * Example: -+ * struct child *next; -+ * list_for_each_rev_safe(&parent->children, child, next, list) { -+ * printf("Name: %s\n", child->name); -+ * } -+ */ -+#define list_for_each_rev_safe(h, i, nxt, member) \ -+ list_for_each_rev_safe_off(h, i, nxt, list_off_var_(i, member)) - - /** - * list_for_each_safe - iterate through a list, maybe during deletion -@@ -422,7 +573,6 @@ static inline const void *list_tail_(const struct list_head *h, size_t off) - * @nxt is used to hold the next element, so you can delete @i from the list. - * - * Example: -- * struct child *next; - * list_for_each_safe(&parent->children, child, next, list) { - * list_del(&child->list); - * parent->num_children--; -@@ -537,10 +687,28 @@ static inline void list_prepend_list_(struct list_head *to, - list_head_init(from); - } - -+/* internal macros, do not use directly */ -+#define list_for_each_off_dir_(h, i, off, dir) \ -+ for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \ -+ (off)); \ -+ list_node_from_off_((void *)i, (off)) != &(h)->n; \ -+ i = list_node_to_off_(list_node_from_off_((void *)i, (off))->dir, \ -+ (off))) -+ -+#define list_for_each_safe_off_dir_(h, i, nxt, off, dir) \ -+ for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \ -+ (off)), \ -+ nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \ -+ (off)); \ -+ list_node_from_off_(i, (off)) != &(h)->n; \ -+ i = nxt, \ -+ nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \ -+ (off))) -+ - /** - * list_for_each_off - iterate through a list of memory regions. - * @h: the list_head -- * @i: the pointer to a memory region wich contains list node data. -+ * @i: the pointer to a memory region which contains list node data. - * @off: offset(relative to @i) at which list node data resides. - * - * This is a low-level wrapper to iterate @i over the entire list, used to -@@ -548,12 +716,12 @@ static inline void list_prepend_list_(struct list_head *to, - * so you can break and continue as normal. - * - * WARNING! Being the low-level macro that it is, this wrapper doesn't know -- * nor care about the type of @i. The only assumtion made is that @i points -+ * nor care about the type of @i. The only assumption made is that @i points - * to a chunk of memory that at some @offset, relative to @i, contains a -- * properly filled `struct node_list' which in turn contains pointers to -- * memory chunks and it's turtles all the way down. Whith all that in mind -+ * properly filled `struct list_node' which in turn contains pointers to -+ * memory chunks and it's turtles all the way down. With all that in mind - * remember that given the wrong pointer/offset couple this macro will -- * happilly churn all you memory untill SEGFAULT stops it, in other words -+ * happily churn all you memory until SEGFAULT stops it, in other words - * caveat emptor. - * - * It is worth mentioning that one of legitimate use-cases for that wrapper -@@ -567,17 +735,24 @@ static inline void list_prepend_list_(struct list_head *to, - * printf("Name: %s\n", child->name); - */ - #define list_for_each_off(h, i, off) \ -- for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.next, \ -- (off)); \ -- list_node_from_off_((void *)i, (off)) != &(h)->n; \ -- i = list_node_to_off_(list_node_from_off_((void *)i, (off))->next, \ -- (off))) -+ list_for_each_off_dir_((h),(i),(off),next) -+ -+/** -+ * list_for_each_rev_off - iterate through a list of memory regions backwards -+ * @h: the list_head -+ * @i: the pointer to a memory region which contains list node data. -+ * @off: offset(relative to @i) at which list node data resides. -+ * -+ * See list_for_each_off for details -+ */ -+#define list_for_each_rev_off(h, i, off) \ -+ list_for_each_off_dir_((h),(i),(off),prev) - - /** - * list_for_each_safe_off - iterate through a list of memory regions, maybe - * during deletion - * @h: the list_head -- * @i: the pointer to a memory region wich contains list node data. -+ * @i: the pointer to a memory region which contains list node data. - * @nxt: the structure containing the list_node - * @off: offset(relative to @i) at which list node data resides. - * -@@ -590,15 +765,26 @@ static inline void list_prepend_list_(struct list_head *to, - * printf("Name: %s\n", child->name); - */ - #define list_for_each_safe_off(h, i, nxt, off) \ -- for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.next, \ -- (off)), \ -- nxt = list_node_to_off_(list_node_from_off_(i, (off))->next, \ -- (off)); \ -- list_node_from_off_(i, (off)) != &(h)->n; \ -- i = nxt, \ -- nxt = list_node_to_off_(list_node_from_off_(i, (off))->next, \ -- (off))) -+ list_for_each_safe_off_dir_((h),(i),(nxt),(off),next) - -+/** -+ * list_for_each_rev_safe_off - iterate backwards through a list of -+ * memory regions, maybe during deletion -+ * @h: the list_head -+ * @i: the pointer to a memory region which contains list node data. -+ * @nxt: the structure containing the list_node -+ * @off: offset(relative to @i) at which list node data resides. -+ * -+ * For details see `list_for_each_rev_off' and `list_for_each_rev_safe' -+ * descriptions. -+ * -+ * Example: -+ * list_for_each_rev_safe_off(&parent->children, child, -+ * next, offsetof(struct child, list)) -+ * printf("Name: %s\n", child->name); -+ */ -+#define list_for_each_rev_safe_off(h, i, nxt, off) \ -+ list_for_each_safe_off_dir_((h),(i),(nxt),(off),prev) - - /* Other -off variants. */ - #define list_entry_off(n, type, off) \ -diff --git a/ndctl/lib/inject.c b/ndctl/lib/inject.c -index d61c02c..3486ffe 100644 ---- a/ndctl/lib/inject.c -+++ b/ndctl/lib/inject.c -@@ -2,7 +2,6 @@ - // Copyright (C) 2014-2020, Intel Corporation. All rights reserved. - #include - #include --#include - #include - #include - #include -diff --git a/util/list.h b/util/list.h -deleted file mode 100644 -index 1ea9c59..0000000 ---- a/util/list.h -+++ /dev/null -@@ -1,40 +0,0 @@ --/* SPDX-License-Identifier: GPL-2.0 */ --/* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */ --#ifndef _NDCTL_LIST_H_ --#define _NDCTL_LIST_H_ -- --#include -- --/** -- * list_add_after - add an entry after the given node in the linked list. -- * @h: the list_head to add the node to -- * @l: the list_node after which to add to -- * @n: the list_node to add to the list. -- * -- * The list_node does not need to be initialized; it will be overwritten. -- * Example: -- * struct child *child = malloc(sizeof(*child)); -- * -- * child->name = "geoffrey"; -- * list_add_after(&parent->children, &child1->list, &child->list); -- * parent->num_children++; -- */ --#define list_add_after(h, l, n) list_add_after_(h, l, n, LIST_LOC) --static inline void list_add_after_(struct list_head *h, -- struct list_node *l, -- struct list_node *n, -- const char *abortstr) --{ -- if (l->next == &h->n) { -- /* l is the last element, this becomes a list_add_tail */ -- list_add_tail(h, n); -- return; -- } -- n->next = l->next; -- n->prev = l; -- l->next->prev = n; -- l->next = n; -- (void)list_debug(h, abortstr); --} -- --#endif /* _NDCTL_LIST_H_ */ --- -2.27.0 - diff --git a/SOURCES/0180-cxl-lib-Maintain-decoders-in-id-order.patch b/SOURCES/0180-cxl-lib-Maintain-decoders-in-id-order.patch deleted file mode 100644 index ae034b9..0000000 --- a/SOURCES/0180-cxl-lib-Maintain-decoders-in-id-order.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 06ae7118aaa74aa2139004fa12b4910bc15236de Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 14 Jul 2022 10:02:21 -0700 -Subject: [PATCH 180/217] cxl/lib: Maintain decoders in id order - -Given that decoder instance order is fundamental to the DPA translation -sequence for endpoint decoders, enforce that cxl_decoder_for_each() returns -decoders in instance order. Otherwise, they show up in readddir() order -which is not predictable. - -Add a list_add_sorted() to generically handle inserting into a sorted list. - -Link: https://lore.kernel.org/r/165781814167.1555691.14895625637451030942.stgit@dwillia2-xfh.jf.intel.com -Reviewed-by: Davidlohr Bueso -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 8 +++++++- - util/list.h | 39 +++++++++++++++++++++++++++++++++++++++ - 2 files changed, 46 insertions(+), 1 deletion(-) - create mode 100644 util/list.h - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 6f4d64d..ea597f6 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -19,6 +19,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -909,6 +910,11 @@ cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint) - return NULL; - } - -+static int decoder_id_cmp(struct cxl_decoder *d1, struct cxl_decoder *d2) -+{ -+ return d1->id - d2->id; -+} -+ - static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - { - const char *devname = devpath_to_devname(cxldecoder_base); -@@ -1050,7 +1056,7 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - return decoder_dup; - } - -- list_add(&port->decoders, &decoder->list); -+ list_add_sorted(&port->decoders, decoder, list, decoder_id_cmp); - - free(path); - return decoder; -diff --git a/util/list.h b/util/list.h -new file mode 100644 -index 0000000..cb77271 ---- /dev/null -+++ b/util/list.h -@@ -0,0 +1,39 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright (C) 2022 Intel Corporation. All rights reserved. */ -+#ifndef _NDCTL_LIST_H_ -+#define _NDCTL_LIST_H_ -+ -+#include -+ -+#define list_add_sorted(head, n, node, cmp) \ -+ do { \ -+ struct list_head *__head = (head); \ -+ typeof(n) __iter, __next; \ -+ typeof(n) __new = (n); \ -+ \ -+ if (list_empty(__head)) { \ -+ list_add(__head, &__new->node); \ -+ break; \ -+ } \ -+ \ -+ list_for_each (__head, __iter, node) { \ -+ if (cmp(__new, __iter) < 0) { \ -+ list_add_before(__head, &__iter->node, \ -+ &__new->node); \ -+ break; \ -+ } \ -+ __next = list_next(__head, __iter, node); \ -+ if (!__next) { \ -+ list_add_after(__head, &__iter->node, \ -+ &__new->node); \ -+ break; \ -+ } \ -+ if (cmp(__new, __next) < 0) { \ -+ list_add_before(__head, &__next->node, \ -+ &__new->node); \ -+ break; \ -+ } \ -+ } \ -+ } while (0) -+ -+#endif /* _NDCTL_LIST_H_ */ --- -2.27.0 - diff --git a/SOURCES/0181-cxl-memdev-Fix-json-for-multi-device-partitioning.patch b/SOURCES/0181-cxl-memdev-Fix-json-for-multi-device-partitioning.patch deleted file mode 100644 index 21692ff..0000000 --- a/SOURCES/0181-cxl-memdev-Fix-json-for-multi-device-partitioning.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 8ed95d22504d7b2b258d1800878e32c162badf8c Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 14 Jul 2022 10:02:27 -0700 -Subject: [PATCH 181/217] cxl/memdev: Fix json for multi-device partitioning - -In the case when someone partitions several devices at once, collect all -the affected memdevs into a json array. - -With the move to use util_display_json_array() that also requires a set of -flags to be specifiied. Apply the UTIL_JSON_HUMAN flag for all interactive -command result output to bring this command in line with other tools. - -Link: https://lore.kernel.org/r/165781814737.1555691.889129128205037941.stgit@dwillia2-xfh.jf.intel.com -Cc: Alison Schofield -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/memdev.c | 26 +++++++++++++++++++++----- - 1 file changed, 21 insertions(+), 5 deletions(-) - -diff --git a/cxl/memdev.c b/cxl/memdev.c -index 91d914d..9fcd8ae 100644 ---- a/cxl/memdev.c -+++ b/cxl/memdev.c -@@ -19,6 +19,7 @@ - struct action_context { - FILE *f_out; - FILE *f_in; -+ struct json_object *jdevs; - }; - - static struct parameters { -@@ -339,12 +340,13 @@ out: - } - - static int action_setpartition(struct cxl_memdev *memdev, -- struct action_context *actx) -+ struct action_context *actx) - { - const char *devname = cxl_memdev_get_devname(memdev); - enum cxl_setpart_type type = CXL_SETPART_PMEM; - unsigned long long size = ULLONG_MAX; - struct json_object *jmemdev; -+ unsigned long flags; - struct cxl_cmd *cmd; - int rc; - -@@ -396,10 +398,12 @@ out_err: - if (rc) - log_err(&ml, "%s error: %s\n", devname, strerror(-rc)); - -- jmemdev = util_cxl_memdev_to_json(memdev, UTIL_JSON_PARTITION); -- if (jmemdev) -- printf("%s\n", json_object_to_json_string_ext(jmemdev, -- JSON_C_TO_STRING_PRETTY)); -+ flags = UTIL_JSON_PARTITION; -+ if (actx->f_out == stdout && isatty(1)) -+ flags |= UTIL_JSON_HUMAN; -+ jmemdev = util_cxl_memdev_to_json(memdev, flags); -+ if (actx->jdevs && jmemdev) -+ json_object_array_add(actx->jdevs, jmemdev); - - return rc; - } -@@ -446,6 +450,9 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - err++; - } - -+ if (action == action_setpartition) -+ actx.jdevs = json_object_new_array(); -+ - if (err == argc) { - usage_with_options(u, options); - return -EINVAL; -@@ -528,6 +535,15 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - if (actx.f_in != stdin) - fclose(actx.f_in); - -+ if (actx.jdevs) { -+ unsigned long flags = 0; -+ -+ if (actx.f_out == stdout && isatty(1)) -+ flags |= UTIL_JSON_HUMAN; -+ util_display_json_array(actx.f_out, actx.jdevs, flags); -+ } -+ -+ - out_close_fout: - if (actx.f_out != stdout) - fclose(actx.f_out); --- -2.27.0 - diff --git a/SOURCES/0182-cxl-list-Emit-mode-for-endpoint-decoder-objects.patch b/SOURCES/0182-cxl-list-Emit-mode-for-endpoint-decoder-objects.patch deleted file mode 100644 index 3a37ca9..0000000 --- a/SOURCES/0182-cxl-list-Emit-mode-for-endpoint-decoder-objects.patch +++ /dev/null @@ -1,181 +0,0 @@ -From d2a7fc7fb87396eb267cf6c8948468f7e56bea89 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 14 Jul 2022 10:02:33 -0700 -Subject: [PATCH 182/217] cxl/list: Emit 'mode' for endpoint decoder objects - -The 'mode' property of an endpoint decoder indicates the access -properties of the DPA (device physical address) mapped into HPA (host -physical address) by the decoder. Where the modes are 'none' -(decoder-disabled), 'ram' (voltaile memory), 'pmem' (persistent memory), -and 'mixed' (an unexpected, but possible, case where the decoder -straddles a mode / partition boundary). - -Link: https://lore.kernel.org/r/165781815306.1555691.17541956592287631419.stgit@dwillia2-xfh.jf.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/lib/libcxl.txt | 9 +++++++++ - cxl/json.c | 8 ++++++++ - cxl/lib/libcxl.c | 30 ++++++++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 1 + - cxl/lib/private.h | 1 + - cxl/libcxl.h | 23 +++++++++++++++++++++++ - 6 files changed, 72 insertions(+) - -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 2aef489..90fe338 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -405,6 +405,15 @@ enum cxl_decoder_target_type { - }; - - cxl_decoder_get_target_type(struct cxl_decoder *decoder); -+ -+enum cxl_decoder_mode { -+ CXL_DECODER_MODE_NONE, -+ CXL_DECODER_MODE_MIXED, -+ CXL_DECODER_MODE_PMEM, -+ CXL_DECODER_MODE_RAM, -+}; -+enum cxl_decoder_mode cxl_decoder_get_mode(struct cxl_decoder *decoder); -+ - bool cxl_decoder_is_pmem_capable(struct cxl_decoder *decoder); - bool cxl_decoder_is_volatile_capable(struct cxl_decoder *decoder); - bool cxl_decoder_is_mem_capable(struct cxl_decoder *decoder); -diff --git a/cxl/json.c b/cxl/json.c -index 3f52d3b..ae9c812 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -473,6 +473,8 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - } - - if (cxl_port_is_endpoint(port)) { -+ enum cxl_decoder_mode mode = cxl_decoder_get_mode(decoder); -+ - size = cxl_decoder_get_dpa_size(decoder); - val = cxl_decoder_get_dpa_resource(decoder); - if (size && val < ULLONG_MAX) { -@@ -488,6 +490,12 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - json_object_object_add(jdecoder, "dpa_size", - jobj); - } -+ -+ if (mode > CXL_DECODER_MODE_NONE) { -+ jobj = json_object_new_string(cxl_decoder_mode_name(mode)); -+ if (jobj) -+ json_object_object_add(jdecoder, "mode", jobj); -+ } - } - - if (cxl_port_is_root(port) && cxl_decoder_is_mem_capable(decoder)) { -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index ea597f6..b802e5d 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -961,6 +961,21 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - else - decoder->size = strtoull(buf, NULL, 0); - -+ sprintf(path, "%s/mode", cxldecoder_base); -+ if (sysfs_read_attr(ctx, path, buf) == 0) { -+ if (strcmp(buf, "ram") == 0) -+ decoder->mode = CXL_DECODER_MODE_RAM; -+ else if (strcmp(buf, "pmem") == 0) -+ decoder->mode = CXL_DECODER_MODE_PMEM; -+ else if (strcmp(buf, "mixed") == 0) -+ decoder->mode = CXL_DECODER_MODE_MIXED; -+ else if (strcmp(buf, "none") == 0) -+ decoder->mode = CXL_DECODER_MODE_NONE; -+ else -+ decoder->mode = CXL_DECODER_MODE_MIXED; -+ } else -+ decoder->mode = CXL_DECODER_MODE_NONE; -+ - switch (port->type) { - case CXL_PORT_ENDPOINT: - sprintf(path, "%s/dpa_resource", cxldecoder_base); -@@ -1161,6 +1176,21 @@ cxl_decoder_get_dpa_size(struct cxl_decoder *decoder) - return decoder->dpa_size; - } - -+CXL_EXPORT enum cxl_decoder_mode -+cxl_decoder_get_mode(struct cxl_decoder *decoder) -+{ -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ -+ if (!cxl_port_is_endpoint(port)) { -+ err(ctx, "%s: not an endpoint decoder\n", -+ cxl_decoder_get_devname(decoder)); -+ return CXL_DECODER_MODE_NONE; -+ } -+ -+ return decoder->mode; -+} -+ - CXL_EXPORT enum cxl_decoder_target_type - cxl_decoder_get_target_type(struct cxl_decoder *decoder) - { -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 8e2fc75..88c5a7e 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -172,4 +172,5 @@ LIBCXL_3 { - global: - cxl_decoder_get_dpa_resource; - cxl_decoder_get_dpa_size; -+ cxl_decoder_get_mode; - } LIBCXL_2; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 24a2ae6..f6d4573 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -108,6 +108,7 @@ struct cxl_decoder { - char *dev_path; - int nr_targets; - int id; -+ enum cxl_decoder_mode mode; - bool pmem_capable; - bool volatile_capable; - bool mem_capable; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 76aebe3..1436dc4 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -127,10 +127,33 @@ struct cxl_dport *cxl_port_get_dport_by_memdev(struct cxl_port *port, - struct cxl_decoder; - struct cxl_decoder *cxl_decoder_get_first(struct cxl_port *port); - struct cxl_decoder *cxl_decoder_get_next(struct cxl_decoder *decoder); -+struct cxl_decoder *cxl_decoder_get_last(struct cxl_port *port); -+struct cxl_decoder *cxl_decoder_get_prev(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_resource(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_dpa_resource(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_dpa_size(struct cxl_decoder *decoder); -+enum cxl_decoder_mode { -+ CXL_DECODER_MODE_NONE, -+ CXL_DECODER_MODE_MIXED, -+ CXL_DECODER_MODE_PMEM, -+ CXL_DECODER_MODE_RAM, -+}; -+static inline const char *cxl_decoder_mode_name(enum cxl_decoder_mode mode) -+{ -+ static const char *names[] = { -+ [CXL_DECODER_MODE_NONE] = "none", -+ [CXL_DECODER_MODE_MIXED] = "mixed", -+ [CXL_DECODER_MODE_PMEM] = "pmem", -+ [CXL_DECODER_MODE_RAM] = "ram", -+ }; -+ -+ if (mode < CXL_DECODER_MODE_NONE || mode > CXL_DECODER_MODE_RAM) -+ mode = CXL_DECODER_MODE_NONE; -+ return names[mode]; -+} -+ -+enum cxl_decoder_mode cxl_decoder_get_mode(struct cxl_decoder *decoder); - const char *cxl_decoder_get_devname(struct cxl_decoder *decoder); - struct cxl_target *cxl_decoder_get_target_by_memdev(struct cxl_decoder *decoder, - struct cxl_memdev *memdev); --- -2.27.0 - diff --git a/SOURCES/0183-cxl-set-partition-Accept-ram-as-an-alias-for-volatil.patch b/SOURCES/0183-cxl-set-partition-Accept-ram-as-an-alias-for-volatil.patch deleted file mode 100644 index 64a5fcc..0000000 --- a/SOURCES/0183-cxl-set-partition-Accept-ram-as-an-alias-for-volatil.patch +++ /dev/null @@ -1,56 +0,0 @@ -From b1c29cfa125f6da219bfcec732a8290bb124cdce Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 14 Jul 2022 10:02:38 -0700 -Subject: [PATCH 183/217] cxl/set-partition: Accept 'ram' as an alias for - 'volatile' - -'ram' is a more convenient shorthand for volatile memory. - -Link: https://lore.kernel.org/r/165781815878.1555691.12251226240559355924.stgit@dwillia2-xfh.jf.intel.com -Cc: Alison Schofield -Reviewed-by: Davidlohr Bueso -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-set-partition.txt | 2 +- - cxl/memdev.c | 4 +++- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/Documentation/cxl/cxl-set-partition.txt b/Documentation/cxl/cxl-set-partition.txt -index 1e548af..f0126da 100644 ---- a/Documentation/cxl/cxl-set-partition.txt -+++ b/Documentation/cxl/cxl-set-partition.txt -@@ -37,7 +37,7 @@ include::memdev-option.txt[] - - -t:: - --type=:: -- Type of partition, 'pmem' or 'volatile', to modify. -+ Type of partition, 'pmem' or 'ram' (volatile), to modify. - Default: 'pmem' - - -s:: -diff --git a/cxl/memdev.c b/cxl/memdev.c -index 9fcd8ae..1cecad2 100644 ---- a/cxl/memdev.c -+++ b/cxl/memdev.c -@@ -65,7 +65,7 @@ OPT_BOOLEAN('f', "force", ¶m.force, \ - - #define SET_PARTITION_OPTIONS() \ - OPT_STRING('t', "type", ¶m.type, "type", \ -- "'pmem' or 'volatile' (Default: 'pmem')"), \ -+ "'pmem' or 'ram' (volatile) (Default: 'pmem')"), \ - OPT_STRING('s', "size", ¶m.size, "size", \ - "size in bytes (Default: all available capacity)"), \ - OPT_BOOLEAN('a', "align", ¶m.align, \ -@@ -355,6 +355,8 @@ static int action_setpartition(struct cxl_memdev *memdev, - /* default */; - else if (strcmp(param.type, "volatile") == 0) - type = CXL_SETPART_VOLATILE; -+ else if (strcmp(param.type, "ram") == 0) -+ type = CXL_SETPART_VOLATILE; - else { - log_err(&ml, "invalid type '%s'\n", param.type); - return -EINVAL; --- -2.27.0 - diff --git a/SOURCES/0184-cxl-memdev-Add-reserve-free-dpa-commands.patch b/SOURCES/0184-cxl-memdev-Add-reserve-free-dpa-commands.patch deleted file mode 100644 index 11f218f..0000000 --- a/SOURCES/0184-cxl-memdev-Add-reserve-free-dpa-commands.patch +++ /dev/null @@ -1,763 +0,0 @@ -From 6624f4fdf7ba43039111c996dfd3982b4fdc43bc Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 14 Jul 2022 10:02:44 -0700 -Subject: [PATCH 184/217] cxl/memdev: Add {reserve,free}-dpa commands - -Add helper commands for managing allocations of DPA (device physical -address) capacity on a set of CXL memory devices. - -The main convenience this command affords is automatically picking the next -decoder to allocate per-memdev. - -For example, to allocate 256MiB from all endpoints that are covered by a -given root decoder, and collect those resulting endpoint-decoders into an -array: - - readarray -t mem < <(cxl list -M -d $decoder | jq -r ".[].memdev") - readarray -t endpoint < <(cxl reserve-dpa -t pmem ${mem[*]} -s $((256<<20)) | - jq -r ".[] | .decoder.decoder") - -Link: https://lore.kernel.org/r/165781816425.1555691.17958897857798325111.stgit@dwillia2-xfh.jf.intel.com -Signed-off-by: Dan Williams -[vishal: fix typo pointed out by Jonathan] -Signed-off-by: Vishal Verma ---- - .clang-format | 1 + - Documentation/cxl/cxl-free-dpa.txt | 53 +++++ - Documentation/cxl/cxl-reserve-dpa.txt | 67 ++++++ - Documentation/cxl/lib/libcxl.txt | 2 + - Documentation/cxl/meson.build | 2 + - cxl/builtin.h | 2 + - cxl/cxl.c | 2 + - cxl/filter.c | 4 +- - cxl/filter.h | 2 + - cxl/lib/libcxl.c | 86 ++++++++ - cxl/lib/libcxl.sym | 4 + - cxl/libcxl.h | 9 + - cxl/memdev.c | 280 +++++++++++++++++++++++++- - 13 files changed, 511 insertions(+), 3 deletions(-) - create mode 100644 Documentation/cxl/cxl-free-dpa.txt - create mode 100644 Documentation/cxl/cxl-reserve-dpa.txt - -diff --git a/.clang-format b/.clang-format -index 6aabcb6..7254a1b 100644 ---- a/.clang-format -+++ b/.clang-format -@@ -81,6 +81,7 @@ ForEachMacros: - - 'cxl_bus_foreach' - - 'cxl_port_foreach' - - 'cxl_decoder_foreach' -+ - 'cxl_decoder_foreach_reverse' - - 'cxl_target_foreach' - - 'cxl_dport_foreach' - - 'cxl_endpoint_foreach' -diff --git a/Documentation/cxl/cxl-free-dpa.txt b/Documentation/cxl/cxl-free-dpa.txt -new file mode 100644 -index 0000000..73fb048 ---- /dev/null -+++ b/Documentation/cxl/cxl-free-dpa.txt -@@ -0,0 +1,53 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-free-dpa(1) -+=============== -+ -+NAME -+---- -+cxl-free-dpa - release device-physical address space -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl free-dpa' [..] [] -+ -+The CXL region provisioning process proceeds in multiple steps. One of -+the steps is identifying and reserving the DPA span that each member of -+the interleave-set (region) contributes in advance of attaching that -+allocation to a region. For development, test, and debug purposes this -+command is a helper to find the last allocated decoder on a device and -+zero-out / free its DPA allocation. -+ -+OPTIONS -+------- -+:: -+include::memdev-option.txt[] -+ -+-d:: -+--decoder:: -+ Specify the decoder to free. The CXL specification -+ mandates that DPA must be released in the reverse order it was -+ allocated. See linkcxl:cxl-reserve-dpa[1] -+ -+-t:: -+--type:: -+ Constrain the search for "last allocated decoder" to decoders targeting -+ the given partition. -+ -+-f:: -+--force:: -+ The kernel enforces CXL DPA ordering constraints on deallocation events, -+ and the tool anticipates those and fails operations that are expected to -+ fail without sending them to the kernel. For test purposes, continue to -+ attempt "expected to fail" operations to exercise the driver. -+ -+-v:: -+ Turn on verbose debug messages in the library (if libcxl was built with -+ logging and debug enabled). -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-reserve-dpa[1] -diff --git a/Documentation/cxl/cxl-reserve-dpa.txt b/Documentation/cxl/cxl-reserve-dpa.txt -new file mode 100644 -index 0000000..5e79ef2 ---- /dev/null -+++ b/Documentation/cxl/cxl-reserve-dpa.txt -@@ -0,0 +1,67 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-reserve-dpa(1) -+================== -+ -+NAME -+---- -+cxl-reserve-dpa - allocate device-physical address space -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl reserve-dpa' [..] [] -+ -+The CXL region provisioning process proceeds in multiple steps. One of -+the steps is identifying and reserving the DPA span that each member of -+the interleave-set (region) contributes in advance of attaching that -+allocation to a region. For development, test, and debug purposes this -+command is a helper to find the next available decoder on endpoint -+(memdev) and mark a span of DPA as busy. -+ -+OPTIONS -+------- -+:: -+include::memdev-option.txt[] -+ -+-d:: -+--decoder:: -+ Specify the decoder to attempt the allocation. The CXL specification -+ mandates that allocations must be ordered by DPA and decoder instance. -+ I.e. the lowest DPA allocation on the device is covered by decoder0, and -+ the last / highest DPA allocation is covered by the last decoder. This -+ ordering is enforced by the kernel. By default the tool picks the 'next -+ available' decoder. -+ -+-t:: -+--type:: -+ Select the partition for the allocation. CXL devices implement a -+ partition that divdes 'ram' and 'pmem' capacity, where 'pmem' capacity -+ consumes the higher DPA capacity above the partition boundary. The type -+ defaults to 'pmem'. Note that given CXL DPA allocation constraints, once -+ any 'pmem' allocation is established then all remaining 'ram' capacity -+ becomes reserved (skipped). -+ -+-f:: -+--force:: -+ The kernel enforces CXL DPA allocation ordering constraints, and -+ the tool anticipates those and fails operations that are expected to -+ fail without sending them to the kernel. For test purposes, continue to -+ attempt "expected to fail" operations to exercise the driver. -+ -+-s:: -+--size:: -+ Specify the size of the allocation. This option supports the suffixes -+ "k" or "K" for KiB, "m" or "M" for MiB, "g" or "G" for GiB and "t" or -+ "T" for TiB. This defaults to "all available capacity of the specified -+ type". -+ -+-v:: -+ Turn on verbose debug messages in the library (if libcxl was built with -+ logging and debug enabled). -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-free-dpa[1] -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 90fe338..7a38ce4 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -394,6 +394,7 @@ unsigned long long cxl_decoder_get_resource(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_dpa_resource(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_dpa_size(struct cxl_decoder *decoder); -+int cxl_decoder_set_dpa_size(struct cxl_decoder *decoder, unsigned long long size); - const char *cxl_decoder_get_devname(struct cxl_decoder *decoder); - int cxl_decoder_get_id(struct cxl_decoder *decoder); - int cxl_decoder_get_nr_targets(struct cxl_decoder *decoder); -@@ -413,6 +414,7 @@ enum cxl_decoder_mode { - CXL_DECODER_MODE_RAM, - }; - enum cxl_decoder_mode cxl_decoder_get_mode(struct cxl_decoder *decoder); -+int cxl_decoder_set_mode(struct cxl_decoder *decoder, enum cxl_decoder_mode mode); - - bool cxl_decoder_is_pmem_capable(struct cxl_decoder *decoder); - bool cxl_decoder_is_volatile_capable(struct cxl_decoder *decoder); -diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build -index 974a5a4..d019dfc 100644 ---- a/Documentation/cxl/meson.build -+++ b/Documentation/cxl/meson.build -@@ -36,6 +36,8 @@ cxl_manpages = [ - 'cxl-disable-port.txt', - 'cxl-disable-bus.txt', - 'cxl-set-partition.txt', -+ 'cxl-reserve-dpa.txt', -+ 'cxl-free-dpa.txt', - ] - - foreach man : cxl_manpages -diff --git a/cxl/builtin.h b/cxl/builtin.h -index a437bc3..9e6fc62 100644 ---- a/cxl/builtin.h -+++ b/cxl/builtin.h -@@ -12,6 +12,8 @@ int cmd_init_labels(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_check_labels(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_disable_memdev(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_enable_memdev(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_reserve_dpa(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_free_dpa(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_disable_port(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_enable_port(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_set_partition(int argc, const char **argv, struct cxl_ctx *ctx); -diff --git a/cxl/cxl.c b/cxl/cxl.c -index aa4ce61..ef4cda9 100644 ---- a/cxl/cxl.c -+++ b/cxl/cxl.c -@@ -66,6 +66,8 @@ static struct cmd_struct commands[] = { - { "write-labels", .c_fn = cmd_write_labels }, - { "disable-memdev", .c_fn = cmd_disable_memdev }, - { "enable-memdev", .c_fn = cmd_enable_memdev }, -+ { "reserve-dpa", .c_fn = cmd_reserve_dpa }, -+ { "free-dpa", .c_fn = cmd_free_dpa }, - { "disable-port", .c_fn = cmd_disable_port }, - { "enable-port", .c_fn = cmd_enable_port }, - { "set-partition", .c_fn = cmd_set_partition }, -diff --git a/cxl/filter.c b/cxl/filter.c -index 2f88a9d..e5fab19 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -380,8 +380,8 @@ struct cxl_port *util_cxl_port_filter_by_memdev(struct cxl_port *port, - return NULL; - } - --static struct cxl_decoder *util_cxl_decoder_filter(struct cxl_decoder *decoder, -- const char *__ident) -+struct cxl_decoder *util_cxl_decoder_filter(struct cxl_decoder *decoder, -+ const char *__ident) - { - struct cxl_port *port = cxl_decoder_get_port(decoder); - int pid, did; -diff --git a/cxl/filter.h b/cxl/filter.h -index 9557943..c913daf 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -50,6 +50,8 @@ struct cxl_target *util_cxl_target_filter_by_memdev(struct cxl_target *target, - struct cxl_dport *util_cxl_dport_filter_by_memdev(struct cxl_dport *dport, - const char *ident, - const char *serial); -+struct cxl_decoder *util_cxl_decoder_filter(struct cxl_decoder *decoder, -+ const char *__ident); - int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *param); - bool cxl_filter_has(const char *needle, const char *__filter); - #endif /* _CXL_UTIL_FILTER_H_ */ -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index b802e5d..e52896f 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -1121,6 +1121,20 @@ CXL_EXPORT struct cxl_decoder *cxl_decoder_get_next(struct cxl_decoder *decoder) - return list_next(&port->decoders, decoder, list); - } - -+CXL_EXPORT struct cxl_decoder *cxl_decoder_get_last(struct cxl_port *port) -+{ -+ cxl_decoders_init(port); -+ -+ return list_tail(&port->decoders, struct cxl_decoder, list); -+} -+ -+CXL_EXPORT struct cxl_decoder *cxl_decoder_get_prev(struct cxl_decoder *decoder) -+{ -+ struct cxl_port *port = decoder->port; -+ -+ return list_prev(&port->decoders, decoder, list); -+} -+ - CXL_EXPORT struct cxl_ctx *cxl_decoder_get_ctx(struct cxl_decoder *decoder) - { - return decoder->ctx; -@@ -1176,6 +1190,78 @@ cxl_decoder_get_dpa_size(struct cxl_decoder *decoder) - return decoder->dpa_size; - } - -+CXL_EXPORT int cxl_decoder_set_dpa_size(struct cxl_decoder *decoder, -+ unsigned long long size) -+{ -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ char *path = decoder->dev_buf; -+ int len = decoder->buf_len, rc; -+ char buf[SYSFS_ATTR_SIZE]; -+ -+ if (!cxl_port_is_endpoint(port)) { -+ err(ctx, "%s: not an endpoint decoder\n", -+ cxl_decoder_get_devname(decoder)); -+ return -EINVAL; -+ } -+ -+ if (snprintf(path, len, "%s/dpa_size", decoder->dev_path) >= len) { -+ err(ctx, "%s: buffer too small!\n", -+ cxl_decoder_get_devname(decoder)); -+ return -ENOMEM; -+ } -+ -+ sprintf(buf, "%#llx\n", size); -+ rc = sysfs_write_attr(ctx, path, buf); -+ if (rc < 0) -+ return rc; -+ -+ decoder->dpa_size = size; -+ return 0; -+} -+ -+CXL_EXPORT int cxl_decoder_set_mode(struct cxl_decoder *decoder, -+ enum cxl_decoder_mode mode) -+{ -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ char *path = decoder->dev_buf; -+ int len = decoder->buf_len, rc; -+ char buf[SYSFS_ATTR_SIZE]; -+ -+ if (!cxl_port_is_endpoint(port)) { -+ err(ctx, "%s: not an endpoint decoder\n", -+ cxl_decoder_get_devname(decoder)); -+ return -EINVAL; -+ } -+ -+ switch (mode) { -+ case CXL_DECODER_MODE_PMEM: -+ sprintf(buf, "pmem"); -+ break; -+ case CXL_DECODER_MODE_RAM: -+ sprintf(buf, "ram"); -+ break; -+ default: -+ err(ctx, "%s: unsupported mode: %d\n", -+ cxl_decoder_get_devname(decoder), mode); -+ return -EINVAL; -+ } -+ -+ if (snprintf(path, len, "%s/mode", decoder->dev_path) >= len) { -+ err(ctx, "%s: buffer too small!\n", -+ cxl_decoder_get_devname(decoder)); -+ return -ENOMEM; -+ } -+ -+ rc = sysfs_write_attr(ctx, path, buf); -+ if (rc < 0) -+ return rc; -+ -+ decoder->mode = mode; -+ return 0; -+} -+ - CXL_EXPORT enum cxl_decoder_mode - cxl_decoder_get_mode(struct cxl_decoder *decoder) - { -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 88c5a7e..7712de0 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -173,4 +173,8 @@ global: - cxl_decoder_get_dpa_resource; - cxl_decoder_get_dpa_size; - cxl_decoder_get_mode; -+ cxl_decoder_get_last; -+ cxl_decoder_get_prev; -+ cxl_decoder_set_dpa_size; -+ cxl_decoder_set_mode; - } LIBCXL_2; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 1436dc4..33a216e 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -139,6 +139,7 @@ enum cxl_decoder_mode { - CXL_DECODER_MODE_PMEM, - CXL_DECODER_MODE_RAM, - }; -+ - static inline const char *cxl_decoder_mode_name(enum cxl_decoder_mode mode) - { - static const char *names[] = { -@@ -154,6 +155,10 @@ static inline const char *cxl_decoder_mode_name(enum cxl_decoder_mode mode) - } - - enum cxl_decoder_mode cxl_decoder_get_mode(struct cxl_decoder *decoder); -+int cxl_decoder_set_mode(struct cxl_decoder *decoder, -+ enum cxl_decoder_mode mode); -+int cxl_decoder_set_dpa_size(struct cxl_decoder *decoder, -+ unsigned long long size); - const char *cxl_decoder_get_devname(struct cxl_decoder *decoder); - struct cxl_target *cxl_decoder_get_target_by_memdev(struct cxl_decoder *decoder, - struct cxl_memdev *memdev); -@@ -182,6 +187,10 @@ bool cxl_decoder_is_locked(struct cxl_decoder *decoder); - for (decoder = cxl_decoder_get_first(port); decoder != NULL; \ - decoder = cxl_decoder_get_next(decoder)) - -+#define cxl_decoder_foreach_reverse(port, decoder) \ -+ for (decoder = cxl_decoder_get_last(port); decoder != NULL; \ -+ decoder = cxl_decoder_get_prev(decoder)) -+ - struct cxl_target; - struct cxl_target *cxl_target_get_first(struct cxl_decoder *decoder); - struct cxl_target *cxl_target_get_next(struct cxl_target *target); -diff --git a/cxl/memdev.c b/cxl/memdev.c -index 1cecad2..e42f554 100644 ---- a/cxl/memdev.c -+++ b/cxl/memdev.c -@@ -33,6 +33,7 @@ static struct parameters { - bool align; - const char *type; - const char *size; -+ const char *decoder_filter; - } param; - - static struct log_ctx ml; -@@ -71,6 +72,19 @@ OPT_STRING('s', "size", ¶m.size, "size", \ - OPT_BOOLEAN('a', "align", ¶m.align, \ - "auto-align --size per device's requirement") - -+#define RESERVE_DPA_OPTIONS() \ -+OPT_STRING('s', "size", ¶m.size, "size", \ -+ "size in bytes (Default: all available capacity)") -+ -+#define DPA_OPTIONS() \ -+OPT_STRING('d', "decoder", ¶m.decoder_filter, \ -+ "decoder instance id", \ -+ "override the automatic decoder selection"), \ -+OPT_STRING('t', "type", ¶m.type, "type", \ -+ "'pmem' or 'ram' (volatile) (Default: 'pmem')"), \ -+OPT_BOOLEAN('f', "force", ¶m.force, \ -+ "Attempt 'expected to fail' operations") -+ - static const struct option read_options[] = { - BASE_OPTIONS(), - LABEL_OPTIONS(), -@@ -108,6 +122,242 @@ static const struct option set_partition_options[] = { - OPT_END(), - }; - -+static const struct option reserve_dpa_options[] = { -+ BASE_OPTIONS(), -+ RESERVE_DPA_OPTIONS(), -+ DPA_OPTIONS(), -+ OPT_END(), -+}; -+ -+static const struct option free_dpa_options[] = { -+ BASE_OPTIONS(), -+ DPA_OPTIONS(), -+ OPT_END(), -+}; -+ -+enum reserve_dpa_mode { -+ DPA_ALLOC, -+ DPA_FREE, -+}; -+ -+static int __reserve_dpa(struct cxl_memdev *memdev, -+ enum reserve_dpa_mode alloc_mode, -+ struct action_context *actx) -+{ -+ struct cxl_decoder *decoder, *auto_target = NULL, *target = NULL; -+ struct cxl_endpoint *endpoint = cxl_memdev_get_endpoint(memdev); -+ const char *devname = cxl_memdev_get_devname(memdev); -+ unsigned long long avail_dpa, size; -+ enum cxl_decoder_mode mode; -+ struct cxl_port *port; -+ char buf[256]; -+ int rc; -+ -+ if (param.type) { -+ if (strcmp(param.type, "ram") == 0) -+ mode = CXL_DECODER_MODE_RAM; -+ else if (strcmp(param.type, "volatile") == 0) -+ mode = CXL_DECODER_MODE_RAM; -+ else if (strcmp(param.type, "ram") == 0) -+ mode = CXL_DECODER_MODE_RAM; -+ else if (strcmp(param.type, "pmem") == 0) -+ mode = CXL_DECODER_MODE_PMEM; -+ else { -+ log_err(&ml, "%s: unsupported type: %s\n", devname, -+ param.type); -+ return -EINVAL; -+ } -+ } else -+ mode = CXL_DECODER_MODE_RAM; -+ -+ if (!endpoint) { -+ log_err(&ml, "%s: CXL operation disabled\n", devname); -+ return -ENXIO; -+ } -+ -+ port = cxl_endpoint_get_port(endpoint); -+ -+ if (mode == CXL_DECODER_MODE_RAM) -+ avail_dpa = cxl_memdev_get_ram_size(memdev); -+ else -+ avail_dpa = cxl_memdev_get_pmem_size(memdev); -+ -+ cxl_decoder_foreach(port, decoder) { -+ size = cxl_decoder_get_dpa_size(decoder); -+ if (size == ULLONG_MAX) -+ continue; -+ if (cxl_decoder_get_mode(decoder) != mode) -+ continue; -+ -+ if (size > avail_dpa) { -+ log_err(&ml, "%s: capacity accounting error\n", -+ devname); -+ return -ENXIO; -+ } -+ avail_dpa -= size; -+ } -+ -+ if (!param.size) -+ if (alloc_mode == DPA_ALLOC) { -+ size = avail_dpa; -+ if (!avail_dpa) { -+ log_err(&ml, "%s: no available capacity\n", -+ devname); -+ return -ENOSPC; -+ } -+ } else -+ size = 0; -+ else { -+ size = parse_size64(param.size); -+ if (size == ULLONG_MAX) { -+ log_err(&ml, "%s: failed to parse size option '%s'\n", -+ devname, param.size); -+ return -EINVAL; -+ } -+ if (size > avail_dpa) { -+ log_err(&ml, "%s: '%s' exceeds available capacity\n", -+ devname, param.size); -+ if (!param.force) -+ return -ENOSPC; -+ } -+ } -+ -+ /* -+ * Find next free decoder, assumes cxl_decoder_foreach() is in -+ * hardware instance-id order -+ */ -+ if (alloc_mode == DPA_ALLOC) -+ cxl_decoder_foreach(port, decoder) { -+ /* first 0-dpa_size is our target */ -+ if (cxl_decoder_get_dpa_size(decoder) == 0) { -+ auto_target = decoder; -+ break; -+ } -+ } -+ else -+ cxl_decoder_foreach_reverse(port, decoder) { -+ /* nothing to free? */ -+ if (!cxl_decoder_get_dpa_size(decoder)) -+ continue; -+ /* -+ * Active decoders can't be freed, and by definition all -+ * previous decoders must also be active -+ */ -+ if (cxl_decoder_get_size(decoder)) -+ break; -+ /* first dpa_size > 0 + disabled decoder is our target */ -+ if (cxl_decoder_get_dpa_size(decoder) < ULLONG_MAX) { -+ auto_target = decoder; -+ break; -+ } -+ } -+ -+ if (param.decoder_filter) { -+ unsigned long id; -+ char *end; -+ -+ id = strtoul(param.decoder_filter, &end, 0); -+ /* allow for standalone ordinal decoder ids */ -+ if (*end == '\0') -+ rc = snprintf(buf, sizeof(buf), "decoder%d.%ld", -+ cxl_port_get_id(port), id); -+ else -+ rc = snprintf(buf, sizeof(buf), "%s", -+ param.decoder_filter); -+ -+ if (rc >= (int)sizeof(buf)) { -+ log_err(&ml, "%s: decoder filter '%s' too long\n", -+ devname, param.decoder_filter); -+ return -EINVAL; -+ } -+ -+ if (alloc_mode == DPA_ALLOC) -+ cxl_decoder_foreach(port, decoder) { -+ target = util_cxl_decoder_filter(decoder, buf); -+ if (target) -+ break; -+ } -+ else -+ cxl_decoder_foreach_reverse(port, decoder) { -+ target = util_cxl_decoder_filter(decoder, buf); -+ if (target) -+ break; -+ } -+ -+ if (!target) { -+ log_err(&ml, "%s: no match for decoder: '%s'\n", -+ devname, param.decoder_filter); -+ return -ENXIO; -+ } -+ -+ if (target != auto_target) { -+ log_err(&ml, "%s: %s is out of sequence\n", devname, -+ cxl_decoder_get_devname(target)); -+ if (!param.force) -+ return -EINVAL; -+ } -+ } -+ -+ if (!target) -+ target = auto_target; -+ -+ if (!target) { -+ log_err(&ml, "%s: no suitable decoder found\n", devname); -+ return -ENXIO; -+ } -+ -+ if (cxl_decoder_get_mode(target) != mode) { -+ rc = cxl_decoder_set_dpa_size(target, 0); -+ if (rc) { -+ log_err(&ml, -+ "%s: %s: failed to clear allocation to set mode\n", -+ devname, cxl_decoder_get_devname(target)); -+ return rc; -+ } -+ rc = cxl_decoder_set_mode(target, mode); -+ if (rc) { -+ log_err(&ml, "%s: %s: failed to set %s mode\n", devname, -+ cxl_decoder_get_devname(target), -+ mode == CXL_DECODER_MODE_PMEM ? "pmem" : "ram"); -+ return rc; -+ } -+ } -+ -+ rc = cxl_decoder_set_dpa_size(target, size); -+ if (rc) -+ log_err(&ml, "%s: %s: failed to set dpa allocation\n", devname, -+ cxl_decoder_get_devname(target)); -+ else { -+ struct json_object *jdev, *jdecoder; -+ unsigned long flags = 0; -+ -+ if (actx->f_out == stdout && isatty(1)) -+ flags |= UTIL_JSON_HUMAN; -+ jdev = util_cxl_memdev_to_json(memdev, flags); -+ jdecoder = util_cxl_decoder_to_json(target, flags); -+ if (!jdev || !jdecoder) { -+ json_object_put(jdev); -+ json_object_put(jdecoder); -+ } else { -+ json_object_object_add(jdev, "decoder", jdecoder); -+ json_object_array_add(actx->jdevs, jdev); -+ } -+ } -+ return rc; -+} -+ -+static int action_reserve_dpa(struct cxl_memdev *memdev, -+ struct action_context *actx) -+{ -+ return __reserve_dpa(memdev, DPA_ALLOC, actx); -+} -+ -+static int action_free_dpa(struct cxl_memdev *memdev, -+ struct action_context *actx) -+{ -+ return __reserve_dpa(memdev, DPA_FREE, actx); -+} -+ - static int action_disable(struct cxl_memdev *memdev, struct action_context *actx) - { - if (!cxl_memdev_is_enabled(memdev)) -@@ -452,7 +702,8 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - err++; - } - -- if (action == action_setpartition) -+ if (action == action_setpartition || action == action_reserve_dpa || -+ action == action_free_dpa) - actx.jdevs = json_object_new_array(); - - if (err == argc) { -@@ -495,6 +746,8 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - count = 0; - - for (i = 0; i < argc; i++) { -+ bool found = false; -+ - cxl_memdev_foreach(ctx, memdev) { - const char *memdev_filter = NULL; - const char *serial_filter = NULL; -@@ -507,6 +760,7 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - if (!util_cxl_memdev_filter(memdev, memdev_filter, - serial_filter)) - continue; -+ found = true; - - if (action == action_write) { - single = memdev; -@@ -519,6 +773,8 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, - else if (rc && !err) - err = rc; - } -+ if (!found) -+ log_info(&ml, "no memdev matches %s\n", argv[i]); - } - rc = err; - -@@ -622,3 +878,25 @@ int cmd_set_partition(int argc, const char **argv, struct cxl_ctx *ctx) - - return count >= 0 ? 0 : EXIT_FAILURE; - } -+ -+int cmd_reserve_dpa(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ int count = memdev_action( -+ argc, argv, ctx, action_reserve_dpa, reserve_dpa_options, -+ "cxl reserve-dpa [..] []"); -+ log_info(&ml, "reservation completed on %d mem device%s\n", -+ count >= 0 ? count : 0, count > 1 ? "s" : ""); -+ -+ return count >= 0 ? 0 : EXIT_FAILURE; -+} -+ -+int cmd_free_dpa(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ int count = memdev_action( -+ argc, argv, ctx, action_free_dpa, free_dpa_options, -+ "cxl free-dpa [..] []"); -+ log_info(&ml, "reservation release completed on %d mem device%s\n", -+ count >= 0 ? count : 0, count > 1 ? "s" : ""); -+ -+ return count >= 0 ? 0 : EXIT_FAILURE; -+} --- -2.27.0 - diff --git a/SOURCES/0185-cxl-test-Update-CXL-memory-parameters.patch b/SOURCES/0185-cxl-test-Update-CXL-memory-parameters.patch deleted file mode 100644 index c6c6b07..0000000 --- a/SOURCES/0185-cxl-test-Update-CXL-memory-parameters.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 74a8134ef2dfa3c22c7e22b0bfd30b6a5cdf678b Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 14 Jul 2022 10:02:49 -0700 -Subject: [PATCH 185/217] cxl/test: Update CXL memory parameters - -In support of testing CXL region configurations cxl_test changed the size -of its root decoders and endpoints. Use the size of the first root decoder -to determine if this is an updated kernel. - -Link: https://lore.kernel.org/r/165781816971.1555691.18362747345754213762.stgit@dwillia2-xfh.jf.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/cxl-topology.sh | 32 +++++++++++++++++++++----------- - 1 file changed, 21 insertions(+), 11 deletions(-) - -diff --git a/test/cxl-topology.sh b/test/cxl-topology.sh -index ff11614..2583005 100644 ---- a/test/cxl-topology.sh -+++ b/test/cxl-topology.sh -@@ -64,14 +64,9 @@ switch[2]=$(jq -r ".[] | .[\"ports:${bridge[1]}\"] | $port_sort | .[0].host" <<< - switch[3]=$(jq -r ".[] | .[\"ports:${bridge[1]}\"] | $port_sort | .[1].host" <<< $json) - - --# check that all 8 cxl_test memdevs are enabled by default and have a --# pmem size of 256M --json=$($CXL list -b cxl_test -M) --count=$(jq "map(select(.pmem_size == $((256 << 20)))) | length" <<< $json) --((count == 8)) || err "$LINENO" -- -- - # validate the expected properties of the 4 root decoders -+# use the size of the first decoder to determine the cxl_test version / -+# properties - json=$($CXL list -b cxl_test -D -d root) - port_id=${root:4} - port_id_len=${#port_id} -@@ -80,26 +75,41 @@ count=$(jq "[ $decoder_sort | .[0] | - select(.volatile_capable == true) | - select(.size == $((256 << 20))) | - select(.nr_targets == 1) ] | length" <<< $json) --((count == 1)) || err "$LINENO" -+ -+if [ $count -eq 1 ]; then -+ decoder_base_size=$((256 << 20)) -+ pmem_size=$((256 << 20)) -+else -+ decoder_base_size=$((1 << 30)) -+ pmem_size=$((1 << 30)) -+fi - - count=$(jq "[ $decoder_sort | .[1] | - select(.volatile_capable == true) | -- select(.size == $((512 << 20))) | -+ select(.size == $((decoder_base_size * 2))) | - select(.nr_targets == 2) ] | length" <<< $json) - ((count == 1)) || err "$LINENO" - - count=$(jq "[ $decoder_sort | .[2] | - select(.pmem_capable == true) | -- select(.size == $((256 << 20))) | -+ select(.size == $decoder_base_size) | - select(.nr_targets == 1) ] | length" <<< $json) - ((count == 1)) || err "$LINENO" - - count=$(jq "[ $decoder_sort | .[3] | - select(.pmem_capable == true) | -- select(.size == $((512 << 20))) | -+ select(.size == $((decoder_base_size * 2))) | - select(.nr_targets == 2) ] | length" <<< $json) - ((count == 1)) || err "$LINENO" - -+ -+# check that all 8 cxl_test memdevs are enabled by default and have a -+# pmem size of 256M, or 1G -+json=$($CXL list -b cxl_test -M) -+count=$(jq "map(select(.pmem_size == $pmem_size)) | length" <<< $json) -+((count == 8)) || err "$LINENO" -+ -+ - # check that switch ports disappear after all of their memdevs have been - # disabled, and return when the memdevs are enabled. - for s in ${switch[@]} --- -2.27.0 - diff --git a/SOURCES/0186-cxl-test-Checkout-region-setup-teardown.patch b/SOURCES/0186-cxl-test-Checkout-region-setup-teardown.patch deleted file mode 100644 index a226737..0000000 --- a/SOURCES/0186-cxl-test-Checkout-region-setup-teardown.patch +++ /dev/null @@ -1,169 +0,0 @@ -From eef9685245d172a80e9a5dfd830942824e7d40b4 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Thu, 14 Jul 2022 10:02:55 -0700 -Subject: [PATCH 186/217] cxl/test: Checkout region setup/teardown - -Exercise the fundamental region provisioning sysfs mechanisms of discovering -available DPA capacity, allocating DPA to a region, and programming HDM -decoders. - -Link: https://lore.kernel.org/r/165781817516.1555691.3557156570639615515.stgit@dwillia2-xfh.jf.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/cxl-region-sysfs.sh | 122 +++++++++++++++++++++++++++++++++++++++ - test/meson.build | 2 + - 2 files changed, 124 insertions(+) - create mode 100644 test/cxl-region-sysfs.sh - -diff --git a/test/cxl-region-sysfs.sh b/test/cxl-region-sysfs.sh -new file mode 100644 -index 0000000..2582edb ---- /dev/null -+++ b/test/cxl-region-sysfs.sh -@@ -0,0 +1,122 @@ -+#!/bin/bash -+# SPDX-License-Identifier: GPL-2.0 -+# Copyright (C) 2022 Intel Corporation. All rights reserved. -+ -+. $(dirname $0)/common -+ -+rc=1 -+ -+set -ex -+ -+trap 'err $LINENO' ERR -+ -+check_prereq "jq" -+ -+modprobe -r cxl_test -+modprobe cxl_test -+udevadm settle -+ -+# THEORY OF OPERATION: Create a x8 interleave across the pmem capacity -+# of the 8 endpoints defined by cxl_test, commit the decoders (which -+# just stubs out the actual hardware programming aspect, but updates the -+# driver state), and then tear it all down again. As with other cxl_test -+# tests if the CXL topology in tools/testing/cxl/test/cxl.c ever changes -+# then the paired update must be made to this test. -+ -+# find the root decoder that spans both test host-bridges and support pmem -+decoder=$($CXL list -b cxl_test -D -d root | jq -r ".[] | -+ select(.pmem_capable == true) | -+ select(.nr_targets == 2) | -+ .decoder") -+ -+# find the memdevs mapped by that decoder -+readarray -t mem < <($CXL list -M -d $decoder | jq -r ".[].memdev") -+ -+# ask cxl reserve-dpa to allocate pmem capacity from each of those memdevs -+readarray -t endpoint < <($CXL reserve-dpa -t pmem ${mem[*]} -s $((256<<20)) | -+ jq -r ".[] | .decoder.decoder") -+ -+# instantiate an empty region -+region=$(cat /sys/bus/cxl/devices/$decoder/create_pmem_region) -+echo $region > /sys/bus/cxl/devices/$decoder/create_pmem_region -+uuidgen > /sys/bus/cxl/devices/$region/uuid -+ -+# setup interleave geometry -+nr_targets=${#endpoint[@]} -+echo $nr_targets > /sys/bus/cxl/devices/$region/interleave_ways -+g=$(cat /sys/bus/cxl/devices/$decoder/interleave_granularity) -+echo $g > /sys/bus/cxl/devices/$region/interleave_granularity -+echo $((nr_targets * (256<<20))) > /sys/bus/cxl/devices/$region/size -+ -+# grab the list of memdevs grouped by host-bridge interleave position -+port_dev0=$($CXL list -T -d $decoder | jq -r ".[] | -+ .targets | .[] | select(.position == 0) | .target") -+port_dev1=$($CXL list -T -d $decoder | jq -r ".[] | -+ .targets | .[] | select(.position == 1) | .target") -+readarray -t mem_sort0 < <($CXL list -M -p $port_dev0 | jq -r ".[] | .memdev") -+readarray -t mem_sort1 < <($CXL list -M -p $port_dev1 | jq -r ".[] | .memdev") -+ -+# TODO: add a cxl list option to list memdevs in valid region provisioning -+# order, hardcode for now. -+mem_sort=() -+mem_sort[0]=${mem_sort0[0]} -+mem_sort[1]=${mem_sort1[0]} -+mem_sort[2]=${mem_sort0[2]} -+mem_sort[3]=${mem_sort1[2]} -+mem_sort[4]=${mem_sort0[1]} -+mem_sort[5]=${mem_sort1[1]} -+mem_sort[6]=${mem_sort0[3]} -+mem_sort[7]=${mem_sort1[3]} -+ -+# TODO: use this alternative memdev ordering to validate a negative test for -+# specifying invalid positions of memdevs -+#mem_sort[2]=${mem_sort0[0]} -+#mem_sort[1]=${mem_sort1[0]} -+#mem_sort[0]=${mem_sort0[2]} -+#mem_sort[3]=${mem_sort1[2]} -+#mem_sort[4]=${mem_sort0[1]} -+#mem_sort[5]=${mem_sort1[1]} -+#mem_sort[6]=${mem_sort0[3]} -+#mem_sort[7]=${mem_sort1[3]} -+ -+# re-generate the list of endpoint decoders in region position programming order -+endpoint=() -+for i in ${mem_sort[@]} -+do -+ readarray -O ${#endpoint[@]} -t endpoint < <($CXL list -Di -d endpoint -m $i | jq -r ".[] | -+ select(.mode == \"pmem\") | .decoder") -+done -+ -+# attach all endpoint decoders to the region -+pos=0 -+for i in ${endpoint[@]} -+do -+ echo $i > /sys/bus/cxl/devices/$region/target$pos -+ pos=$((pos+1)) -+done -+echo "$region added ${#endpoint[@]} targets: ${endpoint[@]}" -+ -+# walk up the topology and commit all decoders -+echo 1 > /sys/bus/cxl/devices/$region/commit -+ -+# walk down the topology and de-commit all decoders -+echo 0 > /sys/bus/cxl/devices/$region/commit -+ -+# remove endpoints from the region -+pos=0 -+for i in ${endpoint[@]} -+do -+ echo "" > /sys/bus/cxl/devices/$region/target$pos -+ pos=$((pos+1)) -+done -+ -+# release DPA capacity -+readarray -t endpoint < <($CXL free-dpa -t pmem ${mem[*]} | -+ jq -r ".[] | .decoder.decoder") -+echo "$region released ${#endpoint[@]} targets: ${endpoint[@]}" -+ -+# validate no WARN or lockdep report during the run -+log=$(journalctl -r -k --since "-$((SECONDS+1))s") -+grep -q "Call Trace" <<< $log && err "$LINENO" -+ -+modprobe -r cxl_test -diff --git a/test/meson.build b/test/meson.build -index 210dcb0..3203d9c 100644 ---- a/test/meson.build -+++ b/test/meson.build -@@ -151,6 +151,7 @@ max_extent = find_program('max_available_extent_ns.sh') - pfn_meta_errors = find_program('pfn-meta-errors.sh') - track_uuid = find_program('track-uuid.sh') - cxl_topo = find_program('cxl-topology.sh') -+cxl_sysfs = find_program('cxl-region-sysfs.sh') - - tests = [ - [ 'libndctl', libndctl, 'ndctl' ], -@@ -176,6 +177,7 @@ tests = [ - [ 'pfn-meta-errors.sh', pfn_meta_errors, 'ndctl' ], - [ 'track-uuid.sh', track_uuid, 'ndctl' ], - [ 'cxl-topology.sh', cxl_topo, 'cxl' ], -+ [ 'cxl-region-sysfs.sh', cxl_sysfs, 'cxl' ], - ] - - if get_option('destructive').enabled() --- -2.27.0 - diff --git a/SOURCES/0187-cxl-test-add-a-test-to-read-write-zero-labels.patch b/SOURCES/0187-cxl-test-add-a-test-to-read-write-zero-labels.patch deleted file mode 100644 index f8c2f05..0000000 --- a/SOURCES/0187-cxl-test-add-a-test-to-read-write-zero-labels.patch +++ /dev/null @@ -1,121 +0,0 @@ -From f149f539e874415c0ec19b43a2c9bf2c56f3aa80 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Wed, 13 Jul 2022 14:37:58 -0600 -Subject: [PATCH 187/217] cxl/test: add a test to {read,write,zero}-labels - -Add a unit test to test writing, reading, and zeroing LSA aread for -cxl_test based memdevs using ndctl commands, and reading using cxl-cli -commands to exercise that route as much as possible. - -Note that writing using cxl-cli requires a bit more enabling to enable, -as the corresponding nvdimm-bridge object will need to be disabled -first. - -Link: https://lore.kernel.org/r/20220713203758.519892-1-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/cxl-labels.sh | 69 ++++++++++++++++++++++++++++++++++++++++++++++ - test/meson.build | 2 ++ - 2 files changed, 71 insertions(+) - create mode 100644 test/cxl-labels.sh - -diff --git a/test/cxl-labels.sh b/test/cxl-labels.sh -new file mode 100644 -index 0000000..e782e2d ---- /dev/null -+++ b/test/cxl-labels.sh -@@ -0,0 +1,69 @@ -+#!/bin/bash -+# SPDX-License-Identifier: GPL-2.0 -+# Copyright (C) 2022 Intel Corporation. All rights reserved. -+ -+. $(dirname $0)/common -+ -+rc=1 -+ -+set -ex -+ -+trap 'err $LINENO' ERR -+ -+check_prereq "jq" -+ -+modprobe -r cxl_test -+modprobe cxl_test -+udevadm settle -+ -+test_label_ops() -+{ -+ nmem="$1" -+ lsa=$(mktemp /tmp/lsa-$nmem.XXXX) -+ lsa_read=$(mktemp /tmp/lsa-read-$nmem.XXXX) -+ -+ # determine LSA size -+ "$NDCTL" read-labels -o "$lsa_read" "$nmem" -+ lsa_size=$(stat -c %s "$lsa_read") -+ -+ dd "if=/dev/urandom" "of=$lsa" "bs=$lsa_size" "count=1" -+ "$NDCTL" write-labels -i "$lsa" "$nmem" -+ "$NDCTL" read-labels -o "$lsa_read" "$nmem" -+ -+ # compare what was written vs read -+ diff "$lsa" "$lsa_read" -+ -+ # zero the LSA and test -+ "$NDCTL" zero-labels "$nmem" -+ dd "if=/dev/zero" "of=$lsa" "bs=$lsa_size" "count=1" -+ "$NDCTL" read-labels -o "$lsa_read" "$nmem" -+ diff "$lsa" "$lsa_read" -+ -+ # cleanup -+ rm "$lsa" "$lsa_read" -+} -+ -+test_label_ops_cxl() -+{ -+ mem="$1" -+ lsa_read=$(mktemp /tmp/lsa-read-$mem.XXXX) -+ -+ "$CXL" read-labels -o "$lsa_read" "$mem" -+ rm "$lsa_read" -+} -+ -+# test reading labels directly through cxl-cli -+readarray -t mems < <("$CXL" list -b cxl_test -Mi | jq -r '.[].memdev') -+ -+for mem in ${mems[@]}; do -+ test_label_ops_cxl "$mem" -+done -+ -+# find nmem devices corresponding to cxl memdevs -+readarray -t nmems < <("$NDCTL" list -b cxl_test -Di | jq -r '.[].dev') -+ -+for nmem in ${nmems[@]}; do -+ test_label_ops "$nmem" -+done -+ -+modprobe -r cxl_test -diff --git a/test/meson.build b/test/meson.build -index 3203d9c..b382f46 100644 ---- a/test/meson.build -+++ b/test/meson.build -@@ -152,6 +152,7 @@ pfn_meta_errors = find_program('pfn-meta-errors.sh') - track_uuid = find_program('track-uuid.sh') - cxl_topo = find_program('cxl-topology.sh') - cxl_sysfs = find_program('cxl-region-sysfs.sh') -+cxl_labels = find_program('cxl-labels.sh') - - tests = [ - [ 'libndctl', libndctl, 'ndctl' ], -@@ -178,6 +179,7 @@ tests = [ - [ 'track-uuid.sh', track_uuid, 'ndctl' ], - [ 'cxl-topology.sh', cxl_topo, 'cxl' ], - [ 'cxl-region-sysfs.sh', cxl_sysfs, 'cxl' ], -+ [ 'cxl-labels.sh', cxl_labels, 'cxl' ], - ] - - if get_option('destructive').enabled() --- -2.27.0 - diff --git a/SOURCES/0188-cxl-list-Clarify-B-vs-P-p-root.patch b/SOURCES/0188-cxl-list-Clarify-B-vs-P-p-root.patch deleted file mode 100644 index d2c5f2c..0000000 --- a/SOURCES/0188-cxl-list-Clarify-B-vs-P-p-root.patch +++ /dev/null @@ -1,93 +0,0 @@ -From db55c5254d932d8d1be1fc082ea7a919def47a5d Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Tue, 26 Jul 2022 18:54:54 -0700 -Subject: [PATCH 188/217] cxl/list: Clarify "-B" vs "-P -p root" - -Matthew notes that 'cxl list' documentation claims that 'cxl list -B' and -'cxl list -P -p root' are equivalent. Which they are not: - -$ cxl list -B -[ - { - "bus":"root0", - "provider":"ACPI.CXL" - } -] - -$ cxl list -P -p root -[ - { - "bus":"root0", - "provider":"ACPI.CXL", - "ports:root0":[ - { - "port":"port1", - "host":"ACPI0016:00" - } - ] - } -] - -Clarify that '--single' needs to be appended to '-P -p root' to make it -equivalent to 'cxl list -B'. This is due to the behavior that listing ports -includes all descendants of a port that matches the filter. In the case of -'-P -p root' that results in all enabled ports. - -$ cxl list -P -p root -S -[ - { - "bus":"root0", - "provider":"ACPI.CXL" - } -] - -Link: https://lore.kernel.org/r/165888675979.3375698.5785835464908538946.stgit@dwillia2-xfh.jf.intel.com -Cc: Adam Manzanares -Reported-by: Matthew Ho -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 20 ++++++++++++++------ - 1 file changed, 14 insertions(+), 6 deletions(-) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index f6aba0c..088ea70 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -255,19 +255,27 @@ OPTIONS - --port=:: - Specify CXL Port device name(s), device id(s), and or port type - names to filter the listing. The supported port type names are "root" -- and "switch". Note that since a bus object is also a port, the following -- two syntaxes are equivalent: -+ and "switch". Note that a bus object is also a port, so the -+ following two syntaxes are equivalent: - ---- - # cxl list -B --# cxl list -P -p root -+# cxl list -P -p root -S - ---- -- Additionally, endpoint objects are also ports so the following commands -- are also equivalent. -+ ...where the '-S/--single' is required since descendant ports are always -+ included in a port listing and '-S/--single' stops after listing the -+ bus. Additionally, endpoint objects are ports so the following commands -+ are equivalent, and no '-S/--single' is required as endpoint ports are -+ terminal: - ---- - # cxl list -E - # cxl list -P -p endpoint - ---- -- By default, only 'switch' ports are listed. -+ By default, only 'switch' ports are listed, i.e. -+---- -+# cxl list -P -+# cxl list -P -p switch -+---- -+ ...are equivalent. - - -S:: - --single:: --- -2.27.0 - diff --git a/SOURCES/0189-libcxl-add-a-depth-attribute-to-cxl_port.patch b/SOURCES/0189-libcxl-add-a-depth-attribute-to-cxl_port.patch deleted file mode 100644 index c818aad..0000000 --- a/SOURCES/0189-libcxl-add-a-depth-attribute-to-cxl_port.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0a43bfdf030b4a84fce562462944a9a44888afaa Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Mon, 15 Aug 2022 13:22:04 -0600 -Subject: [PATCH 189/217] libcxl: add a depth attribute to cxl_port - -Add a depth attribute to the cxl_port structure, that can be used for -calculating its distance from the root port, and will be needed for -interleave granularity calculations during region creation. - -Link: https://lore.kernel.org/r/20220815192214.545800-2-vishal.l.verma@intel.com -Suggested-by: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 1 + - cxl/lib/private.h | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index e52896f..145c6ba 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -744,6 +744,7 @@ static int cxl_port_init(struct cxl_port *port, struct cxl_port *parent_port, - port->type = type; - port->parent = parent_port; - port->type = type; -+ port->depth = parent_port ? parent_port->depth + 1 : 0; - - list_head_init(&port->child_ports); - list_head_init(&port->endpoints); -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index f6d4573..832a815 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -66,6 +66,7 @@ struct cxl_port { - int decoders_init; - int dports_init; - int nr_dports; -+ int depth; - struct cxl_ctx *ctx; - struct cxl_bus *bus; - enum cxl_port_type type; --- -2.27.0 - diff --git a/SOURCES/0190-cxl-port-Consolidate-the-debug-option-in-cxl-port-ma.patch b/SOURCES/0190-cxl-port-Consolidate-the-debug-option-in-cxl-port-ma.patch deleted file mode 100644 index 5b5d585..0000000 --- a/SOURCES/0190-cxl-port-Consolidate-the-debug-option-in-cxl-port-ma.patch +++ /dev/null @@ -1,82 +0,0 @@ -From a951e6ddaec82dc0c33fb4e665e20f8fe4ce9caf Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Mon, 15 Aug 2022 13:22:05 -0600 -Subject: [PATCH 190/217] cxl/port: Consolidate the debug option in cxl-port - man pages - -In preparation for additional commands that implement the --debug -option, consolidate the option description from the cxl-port man pages -into an include. - -The port man pages also mentioned the debug option requiring a build -with debug enabled, which wasn't true - so remove that part. - -Link: https://lore.kernel.org/r/20220815192214.545800-3-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-disable-port.txt | 5 +---- - Documentation/cxl/cxl-enable-port.txt | 5 +---- - Documentation/cxl/debug-option.txt | 4 ++++ - Documentation/cxl/meson.build | 1 + - 4 files changed, 7 insertions(+), 8 deletions(-) - create mode 100644 Documentation/cxl/debug-option.txt - -diff --git a/Documentation/cxl/cxl-disable-port.txt b/Documentation/cxl/cxl-disable-port.txt -index ac56f20..7a22efc 100644 ---- a/Documentation/cxl/cxl-disable-port.txt -+++ b/Documentation/cxl/cxl-disable-port.txt -@@ -30,10 +30,7 @@ OPTIONS - firmware and disabling an active device is akin to force removing memory - from a running system. - ----debug:: -- If the cxl tool was built with debug disabled, turn on debug -- messages. -- -+include::debug-option.txt[] - - include::../copyright.txt[] - -diff --git a/Documentation/cxl/cxl-enable-port.txt b/Documentation/cxl/cxl-enable-port.txt -index 9a37cef..50b53d1 100644 ---- a/Documentation/cxl/cxl-enable-port.txt -+++ b/Documentation/cxl/cxl-enable-port.txt -@@ -31,10 +31,7 @@ OPTIONS - memdev is only enabled after all CXL ports in its device topology - ancestry are enabled. - ----debug:: -- If the cxl tool was built with debug enabled, turn on debug -- messages. -- -+include::debug-option.txt[] - - include::../copyright.txt[] - -diff --git a/Documentation/cxl/debug-option.txt b/Documentation/cxl/debug-option.txt -new file mode 100644 -index 0000000..70b922f ---- /dev/null -+++ b/Documentation/cxl/debug-option.txt -@@ -0,0 +1,4 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+--debug:: -+ Turn on additional debug messages including library debug. -diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build -index d019dfc..423be90 100644 ---- a/Documentation/cxl/meson.build -+++ b/Documentation/cxl/meson.build -@@ -22,6 +22,7 @@ filedeps = [ - '../copyright.txt', - 'memdev-option.txt', - 'labels-options.txt', -+ 'debug-option.txt', - ] - - cxl_manpages = [ --- -2.27.0 - diff --git a/SOURCES/0191-cxl-memdev-refactor-decoder-mode-string-parsing.patch b/SOURCES/0191-cxl-memdev-refactor-decoder-mode-string-parsing.patch deleted file mode 100644 index f49514a..0000000 --- a/SOURCES/0191-cxl-memdev-refactor-decoder-mode-string-parsing.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 14565442634cfab0aac8823129a175be572fb11e Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Mon, 15 Aug 2022 13:22:06 -0600 -Subject: [PATCH 191/217] cxl/memdev: refactor decoder mode string parsing - -In preparation for create-region to use a similar decoder mode string -to enum operation, break out the mode string parsing into its own inline -helper in libcxl.h, and call it from memdev.c:__reserve_dpa(). - -Link: https://lore.kernel.org/r/20220815192214.545800-4-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/libcxl.h | 13 +++++++++++++ - cxl/memdev.c | 11 ++--------- - 2 files changed, 15 insertions(+), 9 deletions(-) - -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 33a216e..c1f8d14 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -4,6 +4,7 @@ - #define _LIBCXL_H_ - - #include -+#include - #include - #include - -@@ -154,6 +155,18 @@ static inline const char *cxl_decoder_mode_name(enum cxl_decoder_mode mode) - return names[mode]; - } - -+static inline enum cxl_decoder_mode -+cxl_decoder_mode_from_ident(const char *ident) -+{ -+ if (strcmp(ident, "ram") == 0) -+ return CXL_DECODER_MODE_RAM; -+ else if (strcmp(ident, "volatile") == 0) -+ return CXL_DECODER_MODE_RAM; -+ else if (strcmp(ident, "pmem") == 0) -+ return CXL_DECODER_MODE_PMEM; -+ return CXL_DECODER_MODE_NONE; -+} -+ - enum cxl_decoder_mode cxl_decoder_get_mode(struct cxl_decoder *decoder); - int cxl_decoder_set_mode(struct cxl_decoder *decoder, - enum cxl_decoder_mode mode); -diff --git a/cxl/memdev.c b/cxl/memdev.c -index e42f554..0b3ad02 100644 ---- a/cxl/memdev.c -+++ b/cxl/memdev.c -@@ -154,15 +154,8 @@ static int __reserve_dpa(struct cxl_memdev *memdev, - int rc; - - if (param.type) { -- if (strcmp(param.type, "ram") == 0) -- mode = CXL_DECODER_MODE_RAM; -- else if (strcmp(param.type, "volatile") == 0) -- mode = CXL_DECODER_MODE_RAM; -- else if (strcmp(param.type, "ram") == 0) -- mode = CXL_DECODER_MODE_RAM; -- else if (strcmp(param.type, "pmem") == 0) -- mode = CXL_DECODER_MODE_PMEM; -- else { -+ mode = cxl_decoder_mode_from_ident(param.type); -+ if (mode == CXL_DECODER_MODE_NONE) { - log_err(&ml, "%s: unsupported type: %s\n", devname, - param.type); - return -EINVAL; --- -2.27.0 - diff --git a/SOURCES/0192-libcxl-Introduce-libcxl-region-and-mapping-objects.patch b/SOURCES/0192-libcxl-Introduce-libcxl-region-and-mapping-objects.patch deleted file mode 100644 index 9a4ca60..0000000 --- a/SOURCES/0192-libcxl-Introduce-libcxl-region-and-mapping-objects.patch +++ /dev/null @@ -1,651 +0,0 @@ -From d25dc6d7956bc022d7e4c4453416c52368df291d Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Mon, 15 Aug 2022 13:22:07 -0600 -Subject: [PATCH 192/217] libcxl: Introduce libcxl region and mapping objects - -Add a cxl_region object to libcxl that represents a CXL region. CXL -regions are made up of one or more cxl_memdev 'targets'. The -relationship between a target and a region is conveyed with a -cxl_memdev_mapping object. - -CXL regions are childeren of root decoders, and are organized as such. -Mapping objects are childeren of a CXL region. Introduce the two -classes of objects themselves, and common accessors related to them. - -Link: https://lore.kernel.org/r/20220815192214.545800-5-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - .clang-format | 2 + - cxl/lib/libcxl.c | 442 ++++++++++++++++++++++++++++++++++++++++++++- - cxl/lib/libcxl.sym | 20 ++ - cxl/lib/private.h | 35 ++++ - cxl/libcxl.h | 41 +++++ - 5 files changed, 530 insertions(+), 10 deletions(-) - -diff --git a/.clang-format b/.clang-format -index 7254a1b..b6169e1 100644 ---- a/.clang-format -+++ b/.clang-format -@@ -86,6 +86,8 @@ ForEachMacros: - - 'cxl_dport_foreach' - - 'cxl_endpoint_foreach' - - 'cxl_port_foreach_all' -+ - 'cxl_region_foreach' -+ - 'cxl_region_foreach_safe' - - 'daxctl_dev_foreach' - - 'daxctl_mapping_foreach' - - 'daxctl_region_foreach' -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 145c6ba..ad98188 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -79,6 +79,38 @@ static void free_target(struct cxl_target *target, struct list_head *head) - free(target); - } - -+static void free_region(struct cxl_region *region, struct list_head *head) -+{ -+ struct cxl_memdev_mapping *mapping, *_m; -+ -+ list_for_each_safe(®ion->mappings, mapping, _m, list) { -+ list_del_from(®ion->mappings, &mapping->list); -+ free(mapping); -+ } -+ if (head) -+ list_del_from(head, ®ion->list); -+ kmod_module_unref(region->module); -+ free(region->dev_buf); -+ free(region->dev_path); -+ free(region); -+} -+ -+static void free_stale_regions(struct cxl_decoder *decoder) -+{ -+ struct cxl_region *region, *_r; -+ -+ list_for_each_safe(&decoder->stale_regions, region, _r, list) -+ free_region(region, &decoder->stale_regions); -+} -+ -+static void free_regions(struct cxl_decoder *decoder) -+{ -+ struct cxl_region *region, *_r; -+ -+ list_for_each_safe(&decoder->regions, region, _r, list) -+ free_region(region, &decoder->regions); -+} -+ - static void free_decoder(struct cxl_decoder *decoder, struct list_head *head) - { - struct cxl_target *target, *_t; -@@ -87,6 +119,8 @@ static void free_decoder(struct cxl_decoder *decoder, struct list_head *head) - list_del_from(head, &decoder->list); - list_for_each_safe(&decoder->targets, target, _t, list) - free_target(target, &decoder->targets); -+ free_regions(decoder); -+ free_stale_regions(decoder); - free(decoder->dev_buf); - free(decoder->dev_path); - free(decoder); -@@ -304,6 +338,402 @@ CXL_EXPORT void cxl_set_log_priority(struct cxl_ctx *ctx, int priority) - ctx->ctx.log_priority = priority; - } - -+static int is_enabled(const char *drvpath) -+{ -+ struct stat st; -+ -+ if (lstat(drvpath, &st) < 0 || !S_ISLNK(st.st_mode)) -+ return 0; -+ else -+ return 1; -+} -+ -+CXL_EXPORT int cxl_region_is_enabled(struct cxl_region *region) -+{ -+ struct cxl_ctx *ctx = cxl_region_get_ctx(region); -+ char *path = region->dev_buf; -+ int len = region->buf_len; -+ -+ if (snprintf(path, len, "%s/driver", region->dev_path) >= len) { -+ err(ctx, "%s: buffer too small!\n", cxl_region_get_devname(region)); -+ return 0; -+ } -+ -+ return is_enabled(path); -+} -+ -+CXL_EXPORT int cxl_region_disable(struct cxl_region *region) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ struct cxl_ctx *ctx = cxl_region_get_ctx(region); -+ -+ util_unbind(region->dev_path, ctx); -+ -+ if (cxl_region_is_enabled(region)) { -+ err(ctx, "%s: failed to disable\n", devname); -+ return -EBUSY; -+ } -+ -+ dbg(ctx, "%s: disabled\n", devname); -+ -+ return 0; -+} -+ -+CXL_EXPORT int cxl_region_enable(struct cxl_region *region) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ struct cxl_ctx *ctx = cxl_region_get_ctx(region); -+ char *path = region->dev_buf; -+ int len = region->buf_len; -+ char buf[SYSFS_ATTR_SIZE]; -+ u64 resource = ULLONG_MAX; -+ -+ if (cxl_region_is_enabled(region)) -+ return 0; -+ -+ util_bind(devname, region->module, "cxl", ctx); -+ -+ if (!cxl_region_is_enabled(region)) { -+ err(ctx, "%s: failed to enable\n", devname); -+ return -ENXIO; -+ } -+ -+ /* -+ * Currently 'resource' is the only attr that may change after enabling. -+ * Just refresh it here. If there are additional resources that need -+ * to be refreshed here later, split these out into a common helper -+ * for this and add_cxl_region() -+ */ -+ if (snprintf(path, len, "%s/resource", region->dev_path) >= len) { -+ err(ctx, "%s: buffer too small!\n", devname); -+ return 0; -+ } -+ -+ if (sysfs_read_attr(ctx, path, buf) == 0) -+ resource = strtoull(buf, NULL, 0); -+ -+ if (resource < ULLONG_MAX) -+ region->start = resource; -+ -+ dbg(ctx, "%s: enabled\n", devname); -+ -+ return 0; -+} -+ -+static void *add_cxl_region(void *parent, int id, const char *cxlregion_base) -+{ -+ const char *devname = devpath_to_devname(cxlregion_base); -+ char *path = calloc(1, strlen(cxlregion_base) + 100); -+ struct cxl_region *region, *region_dup, *_r; -+ struct cxl_decoder *decoder = parent; -+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ char buf[SYSFS_ATTR_SIZE]; -+ u64 resource = ULLONG_MAX; -+ -+ dbg(ctx, "%s: base: \'%s\'\n", devname, cxlregion_base); -+ -+ if (!path) -+ return NULL; -+ -+ region = calloc(1, sizeof(*region)); -+ if (!region) -+ goto err; -+ -+ region->id = id; -+ region->ctx = ctx; -+ region->decoder = decoder; -+ list_head_init(®ion->mappings); -+ -+ region->dev_path = strdup(cxlregion_base); -+ if (!region->dev_path) -+ goto err; -+ -+ region->dev_buf = calloc(1, strlen(cxlregion_base) + 50); -+ if (!region->dev_buf) -+ goto err; -+ region->buf_len = strlen(cxlregion_base) + 50; -+ -+ sprintf(path, "%s/size", cxlregion_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ region->size = ULLONG_MAX; -+ else -+ region->size = strtoull(buf, NULL, 0); -+ -+ sprintf(path, "%s/resource", cxlregion_base); -+ if (sysfs_read_attr(ctx, path, buf) == 0) -+ resource = strtoull(buf, NULL, 0); -+ -+ if (resource < ULLONG_MAX) -+ region->start = resource; -+ -+ sprintf(path, "%s/uuid", cxlregion_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ goto err; -+ if (strlen(buf) && uuid_parse(buf, region->uuid) < 0) { -+ dbg(ctx, "%s:%s\n", path, buf); -+ goto err; -+ } -+ -+ sprintf(path, "%s/interleave_granularity", cxlregion_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ region->interleave_granularity = UINT_MAX; -+ else -+ region->interleave_granularity = strtoul(buf, NULL, 0); -+ -+ sprintf(path, "%s/interleave_ways", cxlregion_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ region->interleave_ways = UINT_MAX; -+ else -+ region->interleave_ways = strtoul(buf, NULL, 0); -+ -+ sprintf(path, "%s/commit", cxlregion_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ region->decode_state = CXL_DECODE_UNKNOWN; -+ else -+ region->decode_state = strtoul(buf, NULL, 0); -+ -+ sprintf(path, "%s/modalias", cxlregion_base); -+ if (sysfs_read_attr(ctx, path, buf) == 0) -+ region->module = util_modalias_to_module(ctx, buf); -+ -+ cxl_region_foreach_safe(decoder, region_dup, _r) -+ if (region_dup->id == region->id) { -+ list_del_from(&decoder->regions, ®ion_dup->list); -+ list_add_tail(&decoder->stale_regions, -+ ®ion_dup->list); -+ break; -+ } -+ -+ list_add(&decoder->regions, ®ion->list); -+ -+ return region; -+err: -+ free(region->dev_path); -+ free(region->dev_buf); -+ free(region); -+ free(path); -+ return NULL; -+} -+ -+static void cxl_regions_init(struct cxl_decoder *decoder) -+{ -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ -+ if (decoder->regions_init) -+ return; -+ -+ /* Only root port decoders may have child regions */ -+ if (!cxl_port_is_root(port)) -+ return; -+ -+ decoder->regions_init = 1; -+ -+ sysfs_device_parse(ctx, decoder->dev_path, "region", decoder, -+ add_cxl_region); -+} -+ -+CXL_EXPORT struct cxl_region *cxl_region_get_first(struct cxl_decoder *decoder) -+{ -+ cxl_regions_init(decoder); -+ -+ return list_top(&decoder->regions, struct cxl_region, list); -+} -+ -+CXL_EXPORT struct cxl_region *cxl_region_get_next(struct cxl_region *region) -+{ -+ struct cxl_decoder *decoder = region->decoder; -+ -+ return list_next(&decoder->regions, region, list); -+} -+ -+CXL_EXPORT struct cxl_ctx *cxl_region_get_ctx(struct cxl_region *region) -+{ -+ return region->ctx; -+} -+ -+CXL_EXPORT struct cxl_decoder *cxl_region_get_decoder(struct cxl_region *region) -+{ -+ return region->decoder; -+} -+ -+CXL_EXPORT int cxl_region_get_id(struct cxl_region *region) -+{ -+ return region->id; -+} -+ -+CXL_EXPORT const char *cxl_region_get_devname(struct cxl_region *region) -+{ -+ return devpath_to_devname(region->dev_path); -+} -+ -+CXL_EXPORT void cxl_region_get_uuid(struct cxl_region *region, uuid_t uu) -+{ -+ memcpy(uu, region->uuid, sizeof(uuid_t)); -+} -+ -+CXL_EXPORT unsigned long long cxl_region_get_size(struct cxl_region *region) -+{ -+ return region->size; -+} -+ -+CXL_EXPORT unsigned long long cxl_region_get_resource(struct cxl_region *region) -+{ -+ return region->start; -+} -+ -+CXL_EXPORT unsigned int -+cxl_region_get_interleave_ways(struct cxl_region *region) -+{ -+ return region->interleave_ways; -+} -+ -+CXL_EXPORT int cxl_region_decode_is_committed(struct cxl_region *region) -+{ -+ return (region->decode_state == CXL_DECODE_COMMIT) ? 1 : 0; -+} -+ -+CXL_EXPORT unsigned int -+cxl_region_get_interleave_granularity(struct cxl_region *region) -+{ -+ return region->interleave_granularity; -+} -+ -+static struct cxl_decoder *__cxl_port_match_decoder(struct cxl_port *port, -+ const char *ident) -+{ -+ struct cxl_decoder *decoder; -+ -+ cxl_decoder_foreach(port, decoder) -+ if (strcmp(cxl_decoder_get_devname(decoder), ident) == 0) -+ return decoder; -+ -+ return NULL; -+} -+ -+static struct cxl_decoder *cxl_port_find_decoder(struct cxl_port *port, -+ const char *ident) -+{ -+ struct cxl_decoder *decoder; -+ struct cxl_endpoint *ep; -+ -+ /* First, check decoders directly under @port */ -+ decoder = __cxl_port_match_decoder(port, ident); -+ if (decoder) -+ return decoder; -+ -+ /* Next, iterate over the endpoints under @port */ -+ cxl_endpoint_foreach(port, ep) { -+ decoder = __cxl_port_match_decoder(cxl_endpoint_get_port(ep), -+ ident); -+ if (decoder) -+ return decoder; -+ } -+ -+ return NULL; -+} -+ -+static struct cxl_decoder *cxl_decoder_get_by_name(struct cxl_ctx *ctx, -+ const char *ident) -+{ -+ struct cxl_bus *bus; -+ -+ cxl_bus_foreach(ctx, bus) { -+ struct cxl_decoder *decoder; -+ struct cxl_port *port, *top; -+ -+ port = cxl_bus_get_port(bus); -+ decoder = cxl_port_find_decoder(port, ident); -+ if (decoder) -+ return decoder; -+ -+ top = port; -+ cxl_port_foreach_all (top, port) { -+ decoder = cxl_port_find_decoder(port, ident); -+ if (decoder) -+ return decoder; -+ } -+ } -+ -+ return NULL; -+} -+ -+static void cxl_mappings_init(struct cxl_region *region) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ struct cxl_ctx *ctx = cxl_region_get_ctx(region); -+ char *mapping_path, buf[SYSFS_ATTR_SIZE]; -+ unsigned int i; -+ -+ if (region->mappings_init) -+ return; -+ region->mappings_init = 1; -+ -+ mapping_path = calloc(1, strlen(region->dev_path) + 100); -+ if (!mapping_path) { -+ err(ctx, "%s: allocation failure\n", devname); -+ return; -+ } -+ -+ for (i = 0; i < region->interleave_ways; i++) { -+ struct cxl_memdev_mapping *mapping; -+ struct cxl_decoder *decoder; -+ -+ sprintf(mapping_path, "%s/target%d", region->dev_path, i); -+ if (sysfs_read_attr(ctx, mapping_path, buf) < 0) { -+ err(ctx, "%s: failed to read target%d\n", devname, i); -+ continue; -+ } -+ -+ decoder = cxl_decoder_get_by_name(ctx, buf); -+ if (!decoder) { -+ err(ctx, "%s target%d: %s lookup failure\n", -+ devname, i, buf); -+ continue; -+ } -+ -+ mapping = calloc(1, sizeof(*mapping)); -+ if (!mapping) { -+ err(ctx, "%s target%d: allocation failure\n", devname, i); -+ continue; -+ } -+ -+ mapping->region = region; -+ mapping->decoder = decoder; -+ mapping->position = i; -+ list_add(®ion->mappings, &mapping->list); -+ } -+ free(mapping_path); -+} -+ -+CXL_EXPORT struct cxl_memdev_mapping * -+cxl_mapping_get_first(struct cxl_region *region) -+{ -+ cxl_mappings_init(region); -+ -+ return list_top(®ion->mappings, struct cxl_memdev_mapping, list); -+} -+ -+CXL_EXPORT struct cxl_memdev_mapping * -+cxl_mapping_get_next(struct cxl_memdev_mapping *mapping) -+{ -+ struct cxl_region *region = mapping->region; -+ -+ return list_next(®ion->mappings, mapping, list); -+} -+ -+CXL_EXPORT struct cxl_decoder * -+cxl_mapping_get_decoder(struct cxl_memdev_mapping *mapping) -+{ -+ return mapping->decoder; -+} -+ -+CXL_EXPORT unsigned int -+cxl_mapping_get_position(struct cxl_memdev_mapping *mapping) -+{ -+ return mapping->position; -+} -+ - static void *add_cxl_pmem(void *parent, int id, const char *br_base) - { - const char *devname = devpath_to_devname(br_base); -@@ -681,16 +1111,6 @@ CXL_EXPORT size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev) - return memdev->lsa_size; - } - --static int is_enabled(const char *drvpath) --{ -- struct stat st; -- -- if (lstat(drvpath, &st) < 0 || !S_ISLNK(st.st_mode)) -- return 0; -- else -- return 1; --} -- - CXL_EXPORT int cxl_memdev_is_enabled(struct cxl_memdev *memdev) - { - struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); -@@ -940,6 +1360,8 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - decoder->ctx = ctx; - decoder->port = port; - list_head_init(&decoder->targets); -+ list_head_init(&decoder->regions); -+ list_head_init(&decoder->stale_regions); - - decoder->dev_path = strdup(cxldecoder_base); - if (!decoder->dev_path) -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 7712de0..e410298 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -177,4 +177,24 @@ global: - cxl_decoder_get_prev; - cxl_decoder_set_dpa_size; - cxl_decoder_set_mode; -+ cxl_region_get_first; -+ cxl_region_get_next; -+ cxl_region_decode_is_committed; -+ cxl_region_is_enabled; -+ cxl_region_disable; -+ cxl_region_enable; -+ cxl_region_get_ctx; -+ cxl_region_get_decoder; -+ cxl_region_get_id; -+ cxl_region_get_devname; -+ cxl_region_get_uuid; -+ cxl_region_get_size; -+ cxl_region_get_resource; -+ cxl_region_get_interleave_ways; -+ cxl_region_get_interleave_granularity; -+ cxl_mapping_get_first; -+ cxl_mapping_get_next; -+ cxl_mapping_get_decoder; -+ cxl_mapping_get_region; -+ cxl_mapping_get_position; - } LIBCXL_2; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 832a815..5e2fdd5 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -116,7 +116,42 @@ struct cxl_decoder { - bool accelmem_capable; - bool locked; - enum cxl_decoder_target_type target_type; -+ int regions_init; - struct list_head targets; -+ struct list_head regions; -+ struct list_head stale_regions; -+}; -+ -+enum cxl_decode_state { -+ CXL_DECODE_UNKNOWN = -1, -+ CXL_DECODE_RESET = 0, -+ CXL_DECODE_COMMIT, -+}; -+ -+struct cxl_region { -+ struct cxl_decoder *decoder; -+ struct list_node list; -+ int mappings_init; -+ struct cxl_ctx *ctx; -+ void *dev_buf; -+ size_t buf_len; -+ char *dev_path; -+ int id; -+ uuid_t uuid; -+ u64 start; -+ u64 size; -+ unsigned int interleave_ways; -+ unsigned int interleave_granularity; -+ enum cxl_decode_state decode_state; -+ struct kmod_module *module; -+ struct list_head mappings; -+}; -+ -+struct cxl_memdev_mapping { -+ struct cxl_region *region; -+ struct cxl_decoder *decoder; -+ unsigned int position; -+ struct list_node list; - }; - - enum cxl_cmd_query_status { -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index c1f8d14..19d94e4 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -237,6 +237,47 @@ int cxl_memdev_is_enabled(struct cxl_memdev *memdev); - for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \ - endpoint = cxl_endpoint_get_next(endpoint)) - -+struct cxl_region; -+struct cxl_region *cxl_region_get_first(struct cxl_decoder *decoder); -+struct cxl_region *cxl_region_get_next(struct cxl_region *region); -+int cxl_region_decode_is_committed(struct cxl_region *region); -+int cxl_region_is_enabled(struct cxl_region *region); -+int cxl_region_disable(struct cxl_region *region); -+int cxl_region_enable(struct cxl_region *region); -+struct cxl_ctx *cxl_region_get_ctx(struct cxl_region *region); -+struct cxl_decoder *cxl_region_get_decoder(struct cxl_region *region); -+int cxl_region_get_id(struct cxl_region *region); -+const char *cxl_region_get_devname(struct cxl_region *region); -+void cxl_region_get_uuid(struct cxl_region *region, uuid_t uu); -+unsigned long long cxl_region_get_size(struct cxl_region *region); -+unsigned long long cxl_region_get_resource(struct cxl_region *region); -+unsigned int cxl_region_get_interleave_ways(struct cxl_region *region); -+unsigned int cxl_region_get_interleave_granularity(struct cxl_region *region); -+ -+#define cxl_region_foreach(decoder, region) \ -+ for (region = cxl_region_get_first(decoder); region != NULL; \ -+ region = cxl_region_get_next(region)) -+ -+#define cxl_region_foreach_safe(decoder, region, _region) \ -+ for (region = cxl_region_get_first(decoder), \ -+ _region = region ? cxl_region_get_next(region) : NULL; \ -+ region != NULL; \ -+ region = _region, \ -+ _region = _region ? cxl_region_get_next(_region) : NULL) -+ -+struct cxl_memdev_mapping; -+struct cxl_memdev_mapping *cxl_mapping_get_first(struct cxl_region *region); -+struct cxl_memdev_mapping * -+cxl_mapping_get_next(struct cxl_memdev_mapping *mapping); -+struct cxl_decoder *cxl_mapping_get_decoder(struct cxl_memdev_mapping *mapping); -+struct cxl_region *cxl_mapping_get_region(struct cxl_memdev_mapping *mapping); -+unsigned int cxl_mapping_get_position(struct cxl_memdev_mapping *mapping); -+ -+#define cxl_mapping_foreach(region, mapping) \ -+ for (mapping = cxl_mapping_get_first(region); \ -+ mapping != NULL; \ -+ mapping = cxl_mapping_get_next(mapping)) -+ - struct cxl_cmd; - const char *cxl_cmd_get_devname(struct cxl_cmd *cmd); - struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode); --- -2.27.0 - diff --git a/SOURCES/0193-cxl-cli-add-region-listing-support.patch b/SOURCES/0193-cxl-cli-add-region-listing-support.patch deleted file mode 100644 index e2642a2..0000000 --- a/SOURCES/0193-cxl-cli-add-region-listing-support.patch +++ /dev/null @@ -1,548 +0,0 @@ -From c0f2b36c481119e06eaec60dda17a42100a81ebc Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Mon, 15 Aug 2022 13:22:08 -0600 -Subject: [PATCH 193/217] cxl-cli: add region listing support - -Add cxl_region -> json and cxl_mapping -> json emitter helpers, and -teach cxl_filter_walk about cxl_regions. With these in place, 'cxl-list' -can now emit json objects for CXL regions. They can be top-level objects -if requested by themselves, or nested under root-decoders, if listed -along with decoders. Allow a plain 'cxl list' command to imply -'--regions'. - -Link: https://lore.kernel.org/r/20220815192214.545800-6-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 13 ++- - cxl/filter.c | 158 +++++++++++++++++++++++++++++++-- - cxl/filter.h | 4 + - cxl/json.c | 114 ++++++++++++++++++++++++ - cxl/json.h | 5 ++ - cxl/list.c | 25 +++--- - 6 files changed, 295 insertions(+), 24 deletions(-) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index 088ea70..b88940a 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -317,8 +317,9 @@ OPTIONS - - -T:: - --targets:: -- Extend decoder listings with downstream port target information, and / -- or port and bus listings with the downstream port information. -+ Extend decoder listings with downstream port target information, port -+ and bus listings with the downstream port information, and / or regions -+ with mapping information. - ---- - # cxl list -BTu -b ACPI.CXL - { -@@ -335,6 +336,14 @@ OPTIONS - } - ---- - -+-R:: -+--regions:: -+ Include region objects in the listing. -+ -+-r:: -+--region:: -+ Specify CXL region device name(s), or device id(s), to filter the listing. -+ - --debug:: - If the cxl tool was built with debug enabled, turn on debug - messages. -diff --git a/cxl/filter.c b/cxl/filter.c -index e5fab19..38ece55 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -585,6 +585,73 @@ util_cxl_memdev_filter_by_port(struct cxl_memdev *memdev, const char *bus_ident, - return NULL; - } - -+static struct cxl_region * -+util_cxl_region_filter_by_bus(struct cxl_region *region, const char *__ident) -+{ -+ struct cxl_decoder *decoder = cxl_region_get_decoder(region); -+ -+ if (!util_cxl_decoder_filter_by_bus(decoder, __ident)) -+ return NULL; -+ return region; -+} -+ -+static struct cxl_region * -+util_cxl_region_filter_by_port(struct cxl_region *region, const char *__ident) -+{ -+ struct cxl_decoder *decoder = cxl_region_get_decoder(region); -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ -+ if (!util_cxl_port_filter(port, __ident ,CXL_PF_ANCESTRY)) -+ return NULL; -+ return region; -+} -+ -+static struct cxl_region * -+util_cxl_region_filter_by_decoder(struct cxl_region *region, -+ const char *__ident) -+{ -+ struct cxl_decoder *decoder = cxl_region_get_decoder(region); -+ -+ if (!util_cxl_decoder_filter(decoder, __ident)) -+ return NULL; -+ return region; -+} -+ -+struct cxl_region *util_cxl_region_filter(struct cxl_region *region, -+ const char *__ident) -+{ -+ char *ident, *save; -+ const char *name; -+ int id; -+ -+ if (!__ident) -+ return region; -+ -+ ident = strdup(__ident); -+ if (!ident) -+ return NULL; -+ -+ for (name = strtok_r(ident, which_sep(__ident), &save); name; -+ name = strtok_r(NULL, which_sep(__ident), &save)) { -+ if (strcmp(name, "all") == 0) -+ break; -+ -+ if ((sscanf(name, "%d", &id) == 1 || -+ sscanf(name, "region%d", &id) == 1) && -+ cxl_region_get_id(region) == id) -+ break; -+ -+ if (strcmp(name, cxl_region_get_devname(region)) == 0) -+ break; -+ } -+ -+ free(ident); -+ if (name) -+ return region; -+ return NULL; -+ -+} -+ - static unsigned long params_to_flags(struct cxl_filter_params *param) - { - unsigned long flags = 0; -@@ -672,26 +739,57 @@ static struct json_object *pick_array(struct json_object *child, - return NULL; - } - -+static void walk_regions(struct cxl_decoder *decoder, -+ struct json_object *jregions, -+ struct cxl_filter_params *p, -+ unsigned long flags) -+{ -+ struct json_object *jregion; -+ struct cxl_region *region; -+ -+ cxl_region_foreach(decoder, region) { -+ if (!util_cxl_region_filter(region, p->region_filter)) -+ continue; -+ if (!util_cxl_region_filter_by_bus(region, p->bus_filter)) -+ continue; -+ if (!util_cxl_region_filter_by_port(region, p->port_filter)) -+ continue; -+ if (!util_cxl_region_filter_by_decoder(region, p->decoder_filter)) -+ continue; -+ if (!p->idle && !cxl_region_is_enabled(region)) -+ continue; -+ jregion = util_cxl_region_to_json(region, flags); -+ if (!jregion) -+ continue; -+ json_object_array_add(jregions, jregion); -+ } -+ -+ return; -+} -+ - static void walk_decoders(struct cxl_port *port, struct cxl_filter_params *p, -- struct json_object *jdecoders, unsigned long flags) -+ struct json_object *jdecoders, -+ struct json_object *jregions, unsigned long flags) - { - struct cxl_decoder *decoder; - - cxl_decoder_foreach(port, decoder) { -+ const char *devname = cxl_decoder_get_devname(decoder); -+ struct json_object *jchildregions = NULL; - struct json_object *jdecoder; - - if (!p->decoders) -- continue; -+ goto walk_children; - if (!util_cxl_decoder_filter(decoder, p->decoder_filter)) -- continue; -+ goto walk_children; - if (!util_cxl_decoder_filter_by_bus(decoder, p->bus_filter)) -- continue; -+ goto walk_children; - if (!util_cxl_decoder_filter_by_port(decoder, p->port_filter, - pf_mode(p))) -- continue; -+ goto walk_children; - if (!util_cxl_decoder_filter_by_memdev( - decoder, p->memdev_filter, p->serial_filter)) -- continue; -+ goto walk_children; - if (!p->idle && cxl_decoder_get_size(decoder) == 0) - continue; - jdecoder = util_cxl_decoder_to_json(decoder, flags); -@@ -702,7 +800,27 @@ static void walk_decoders(struct cxl_port *port, struct cxl_filter_params *p, - util_cxl_targets_append_json(jdecoder, decoder, - p->memdev_filter, p->serial_filter, - flags); -+ -+ if (p->regions) { -+ jchildregions = json_object_new_array(); -+ if (!jchildregions) { -+ err(p, "failed to allocate region object\n"); -+ return; -+ } -+ } -+ - json_object_array_add(jdecoders, jdecoder); -+ -+walk_children: -+ if (!p->regions) -+ continue; -+ if (!cxl_port_is_root(port)) -+ continue; -+ walk_regions(decoder, -+ pick_array(jchildregions, jregions), -+ p, flags); -+ cond_add_put_array_suffix(jdecoder, "regions", devname, -+ jchildregions); - } - } - -@@ -782,7 +900,7 @@ static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p, - if (!p->decoders) - continue; - walk_decoders(cxl_endpoint_get_port(endpoint), p, -- pick_array(jchilddecoders, jdecoders), flags); -+ pick_array(jchilddecoders, jdecoders), NULL, flags); - cond_add_put_array_suffix(jendpoint, "decoders", devname, - jchilddecoders); - } -@@ -869,7 +987,8 @@ walk_children: - flags); - - walk_decoders(port, p, -- pick_array(jchilddecoders, jportdecoders), flags); -+ pick_array(jchilddecoders, jportdecoders), NULL, -+ flags); - walk_child_ports(port, p, pick_array(jchildports, jports), - pick_array(jchilddecoders, jportdecoders), - pick_array(jchildeps, jeps), -@@ -894,6 +1013,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - struct json_object *jbusdecoders = NULL; - struct json_object *jepdecoders = NULL; - struct json_object *janondevs = NULL; -+ struct json_object *jregions = NULL; - struct json_object *jeps = NULL; - struct cxl_memdev *memdev; - int top_level_objs = 0; -@@ -936,6 +1056,10 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - if (!jepdecoders) - goto err; - -+ jregions = json_object_new_array(); -+ if (!jregions) -+ goto err; -+ - dbg(p, "walk memdevs\n"); - cxl_memdev_foreach(ctx, memdev) { - struct json_object *janondev; -@@ -964,6 +1088,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - struct json_object *jchildports = NULL; - struct json_object *jchilddevs = NULL; - struct json_object *jchildeps = NULL; -+ struct json_object *jchildregions = NULL; - struct cxl_port *port = cxl_bus_get_port(bus); - const char *devname = cxl_bus_get_devname(bus); - -@@ -1021,11 +1146,20 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p) - continue; - } - } -+ if (p->regions && !p->decoders) { -+ jchildregions = json_object_new_array(); -+ if (!jchildregions) { -+ err(p, -+ "%s: failed to enumerate child regions\n", -+ devname); -+ continue; -+ } -+ } - } - walk_children: - dbg(p, "walk decoders\n"); - walk_decoders(port, p, pick_array(jchilddecoders, jbusdecoders), -- flags); -+ pick_array(jchildregions, jregions), flags); - - dbg(p, "walk ports\n"); - walk_child_ports(port, p, pick_array(jchildports, jports), -@@ -1038,6 +1172,8 @@ walk_children: - jchildeps); - cond_add_put_array_suffix(jbus, "decoders", devname, - jchilddecoders); -+ cond_add_put_array_suffix(jbus, "regions", devname, -+ jchildregions); - cond_add_put_array_suffix(jbus, "memdevs", devname, jchilddevs); - } - -@@ -1057,6 +1193,8 @@ walk_children: - top_level_objs++; - if (json_object_array_length(jepdecoders)) - top_level_objs++; -+ if (json_object_array_length(jregions)) -+ top_level_objs++; - - splice_array(p, janondevs, jplatform, "anon memdevs", top_level_objs > 1); - splice_array(p, jbuses, jplatform, "buses", top_level_objs > 1); -@@ -1069,6 +1207,7 @@ walk_children: - top_level_objs > 1); - splice_array(p, jepdecoders, jplatform, "endpoint decoders", - top_level_objs > 1); -+ splice_array(p, jregions, jplatform, "regions", top_level_objs > 1); - - util_display_json_array(stdout, jplatform, flags); - -@@ -1082,6 +1221,7 @@ err: - json_object_put(jbusdecoders); - json_object_put(jportdecoders); - json_object_put(jepdecoders); -+ json_object_put(jregions); - json_object_put(jplatform); - return -ENOMEM; - } -diff --git a/cxl/filter.h b/cxl/filter.h -index c913daf..609433c 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -13,9 +13,11 @@ struct cxl_filter_params { - const char *port_filter; - const char *endpoint_filter; - const char *decoder_filter; -+ const char *region_filter; - bool single; - bool endpoints; - bool decoders; -+ bool regions; - bool targets; - bool memdevs; - bool ports; -@@ -33,6 +35,8 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, - struct cxl_port *util_cxl_port_filter_by_memdev(struct cxl_port *port, - const char *ident, - const char *serial); -+struct cxl_region *util_cxl_region_filter(struct cxl_region *region, -+ const char *__ident); - - enum cxl_port_filter_mode { - CXL_PF_SINGLE, -diff --git a/cxl/json.c b/cxl/json.c -index ae9c812..70cf286 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -524,6 +524,120 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - return jdecoder; - } - -+void util_cxl_mappings_append_json(struct json_object *jregion, -+ struct cxl_region *region, -+ unsigned long flags) -+{ -+ struct json_object *jobj, *jmappings; -+ struct cxl_memdev_mapping *mapping; -+ unsigned int val, nr_mappings; -+ const char *devname; -+ -+ nr_mappings = cxl_region_get_interleave_ways(region); -+ if (!nr_mappings || (nr_mappings == UINT_MAX)) -+ return; -+ -+ if (!(flags & UTIL_JSON_TARGETS)) -+ return; -+ -+ jmappings = json_object_new_array(); -+ if (!jmappings) -+ return; -+ -+ cxl_mapping_foreach(region, mapping) { -+ struct json_object *jmapping; -+ struct cxl_decoder *decoder; -+ -+ jmapping = json_object_new_object(); -+ if (!jmapping) -+ continue; -+ -+ val = cxl_mapping_get_position(mapping); -+ if (val < UINT_MAX) { -+ jobj = json_object_new_int(val); -+ if (jobj) -+ json_object_object_add(jmapping, "position", -+ jobj); -+ } -+ -+ decoder = cxl_mapping_get_decoder(mapping); -+ if (!decoder) -+ continue; -+ -+ devname = cxl_decoder_get_devname(decoder); -+ jobj = json_object_new_string(devname); -+ if (jobj) -+ json_object_object_add(jmapping, "decoder", jobj); -+ -+ json_object_array_add(jmappings, jmapping); -+ } -+ -+ json_object_object_add(jregion, "mappings", jmappings); -+} -+ -+struct json_object *util_cxl_region_to_json(struct cxl_region *region, -+ unsigned long flags) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ struct json_object *jregion, *jobj; -+ u64 val; -+ -+ jregion = json_object_new_object(); -+ if (!jregion) -+ return NULL; -+ -+ jobj = json_object_new_string(devname); -+ if (jobj) -+ json_object_object_add(jregion, "region", jobj); -+ -+ val = cxl_region_get_resource(region); -+ if (val < ULLONG_MAX) { -+ jobj = util_json_object_hex(val, flags); -+ if (jobj) -+ json_object_object_add(jregion, "resource", jobj); -+ } -+ -+ val = cxl_region_get_size(region); -+ if (val < ULLONG_MAX) { -+ jobj = util_json_object_size(val, flags); -+ if (jobj) -+ json_object_object_add(jregion, "size", jobj); -+ } -+ -+ val = cxl_region_get_interleave_ways(region); -+ if (val < INT_MAX) { -+ jobj = json_object_new_int(val); -+ if (jobj) -+ json_object_object_add(jregion, -+ "interleave_ways", jobj); -+ } -+ -+ val = cxl_region_get_interleave_granularity(region); -+ if (val < INT_MAX) { -+ jobj = json_object_new_int(val); -+ if (jobj) -+ json_object_object_add(jregion, -+ "interleave_granularity", jobj); -+ } -+ -+ if (cxl_region_decode_is_committed(region)) -+ jobj = json_object_new_string("commit"); -+ else -+ jobj = json_object_new_string("reset"); -+ if (jobj) -+ json_object_object_add(jregion, "decode_state", jobj); -+ -+ if (!cxl_region_is_enabled(region)) { -+ jobj = json_object_new_string("disabled"); -+ if (jobj) -+ json_object_object_add(jregion, "state", jobj); -+ } -+ -+ util_cxl_mappings_append_json(jregion, region, flags); -+ -+ return jregion; -+} -+ - void util_cxl_targets_append_json(struct json_object *jdecoder, - struct cxl_decoder *decoder, - const char *ident, const char *serial, -diff --git a/cxl/json.h b/cxl/json.h -index 9a5a845..eb7572b 100644 ---- a/cxl/json.h -+++ b/cxl/json.h -@@ -15,6 +15,11 @@ struct json_object *util_cxl_endpoint_to_json(struct cxl_endpoint *endpoint, - unsigned long flags); - struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - unsigned long flags); -+struct json_object *util_cxl_region_to_json(struct cxl_region *region, -+ unsigned long flags); -+void util_cxl_mappings_append_json(struct json_object *jregion, -+ struct cxl_region *region, -+ unsigned long flags); - void util_cxl_targets_append_json(struct json_object *jdecoder, - struct cxl_decoder *decoder, - const char *ident, const char *serial, -diff --git a/cxl/list.c b/cxl/list.c -index 1b5f583..88ca9d9 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -41,7 +41,10 @@ static const struct option options[] = { - OPT_BOOLEAN('D', "decoders", ¶m.decoders, - "include CXL decoder info"), - OPT_BOOLEAN('T', "targets", ¶m.targets, -- "include CXL target data with decoders or ports"), -+ "include CXL target data with decoders, ports, or regions"), -+ OPT_STRING('r', "region", ¶m.region_filter, "region name", -+ "filter by CXL region name(s)"), -+ OPT_BOOLEAN('R', "regions", ¶m.regions, "include CXL regions"), - OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"), - OPT_BOOLEAN('u', "human", ¶m.human, - "use human friendly number formats"), -@@ -58,7 +61,7 @@ static const struct option options[] = { - static int num_list_flags(void) - { - return !!param.memdevs + !!param.buses + !!param.ports + -- !!param.endpoints + !!param.decoders; -+ !!param.endpoints + !!param.decoders + !!param.regions; - } - - int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) -@@ -92,18 +95,14 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - param.endpoints = true; - if (param.decoder_filter) - param.decoders = true; -- if (num_list_flags() == 0) { -- /* -- * TODO: We likely want to list regions by default if -- * nothing was explicitly asked for. But until we have -- * region support, print this error asking for devices -- * explicitly. Once region support is added, this TODO -- * can be removed. -- */ -- error("please specify entities to list, e.g. using -m/-M\n"); -- usage_with_options(u, options); -- } - param.single = true; -+ if (param.region_filter) -+ param.regions = true; -+ } -+ -+ /* List regions by default */ -+ if (num_list_flags() == 0) { -+ param.regions = true; - } - - log_init(¶m.ctx, "cxl list", "CXL_LIST_LOG"); --- -2.27.0 - diff --git a/SOURCES/0194-libcxl-add-low-level-APIs-for-region-creation.patch b/SOURCES/0194-libcxl-add-low-level-APIs-for-region-creation.patch deleted file mode 100644 index f040988..0000000 --- a/SOURCES/0194-libcxl-add-low-level-APIs-for-region-creation.patch +++ /dev/null @@ -1,644 +0,0 @@ -From cafe4b2d4970b0d7f2193abb9cb32f58c03cbe3b Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Mon, 15 Aug 2022 13:22:09 -0600 -Subject: [PATCH 194/217] libcxl: add low level APIs for region creation - -Add libcxl APIs to create a region under a given root decoder, and to -set different attributes for the new region. These allow setting the -size, interleave_ways, interleave_granularity, uuid, and the target -devices for the newly minted cxl_region object. - -Link: https://lore.kernel.org/r/20220815192214.545800-7-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/lib/libcxl.txt | 69 ++++++ - cxl/lib/libcxl.c | 381 ++++++++++++++++++++++++++++++- - cxl/lib/libcxl.sym | 16 ++ - cxl/lib/private.h | 2 + - cxl/libcxl.h | 23 +- - 5 files changed, 488 insertions(+), 3 deletions(-) - -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 7a38ce4..50b0c9c 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -508,6 +508,75 @@ device to represent the root of a PCI device hierarchy. The - cxl_target_get_physical_node() helper returns the device name of that - companion object in the PCI hierarchy. - -+==== REGIONS -+A CXL region is composed of one or more slices of CXL memdevs, with configurable -+interleave settings - both the number of interleave ways, and the interleave -+granularity. In terms of hierarchy, it is the child of a CXL root decoder. A root -+decoder (recall that this corresponds to an ACPI CEDT.CFMWS 'window'), may have -+multiple child regions, but a region is strictly tied to one root decoder. -+ -+The slices that compose a region are called mappings. A mapping is a -+tuple of 'memdev', 'endpoint decoder', and the 'position'. -+ -+===== REGION: Enumeration -+---- -+struct cxl_region *cxl_region_get_first(struct cxl_decoder *decoder); -+struct cxl_region *cxl_region_get_next(struct cxl_region *region); -+ -+#define cxl_region_foreach(decoder, region) \ -+ for (region = cxl_region_get_first(decoder); region != NULL; \ -+ region = cxl_region_get_next(region)) -+ -+#define cxl_region_foreach_safe(decoder, region, _region) \ -+ for (region = cxl_region_get_first(decoder), \ -+ _region = region ? cxl_region_get_next(region) : NULL; \ -+ region != NULL; \ -+ region = _region, \ -+ _region = _region ? cxl_region_get_next(_region) : NULL) -+---- -+ -+===== REGION: Attributes -+---- -+int cxl_region_get_id(struct cxl_region *region); -+const char *cxl_region_get_devname(struct cxl_region *region); -+void cxl_region_get_uuid(struct cxl_region *region, uuid_t uu); -+unsigned long long cxl_region_get_size(struct cxl_region *region); -+unsigned long long cxl_region_get_resource(struct cxl_region *region); -+unsigned int cxl_region_get_interleave_ways(struct cxl_region *region); -+unsigned int cxl_region_get_interleave_granularity(struct cxl_region *region); -+struct cxl_decoder *cxl_region_get_target_decoder(struct cxl_region *region, -+ int position); -+int cxl_region_set_size(struct cxl_region *region, unsigned long long size); -+int cxl_region_set_uuid(struct cxl_region *region, uuid_t uu); -+int cxl_region_set_interleave_ways(struct cxl_region *region, -+ unsigned int ways); -+int cxl_region_set_interleave_granularity(struct cxl_region *region, -+ unsigned int granularity); -+int cxl_region_set_target(struct cxl_region *region, int position, -+ struct cxl_decoder *decoder); -+int cxl_region_clear_target(struct cxl_region *region, int position); -+int cxl_region_clear_all_targets(struct cxl_region *region); -+int cxl_region_decode_commit(struct cxl_region *region); -+int cxl_region_decode_reset(struct cxl_region *region); -+---- -+ -+A region's resource attribute is the Host Physical Address at which the region's -+address space starts. The region's address space is a subset of the parent root -+decoder's address space. -+ -+The interleave ways is the number of component memdevs participating in the -+region. -+ -+The interleave granularity depends on the root decoder's granularity, and must -+follow the interleave math rules defined in the CXL spec. -+ -+Regions have a list of targets 0..N, which are programmed with the name of an -+endpoint decoder under each participating memdev. -+ -+The 'decode_commit' and 'decode_reset' attributes reserve and free DPA space -+on a given memdev by allocating an endpoint decoder, and programming it based -+on the region's interleave geometry. -+ - include::../../copyright.txt[] - - SEE ALSO -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index ad98188..fd2ea4f 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -420,6 +421,40 @@ CXL_EXPORT int cxl_region_enable(struct cxl_region *region) - return 0; - } - -+static int cxl_region_delete_name(struct cxl_decoder *decoder, -+ const char *devname) -+{ -+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ char *path = decoder->dev_buf; -+ int rc; -+ -+ sprintf(path, "%s/delete_region", decoder->dev_path); -+ rc = sysfs_write_attr(ctx, path, devname); -+ if (rc != 0) { -+ err(ctx, "error deleting region: %s\n", strerror(-rc)); -+ return rc; -+ } -+ return 0; -+} -+ -+CXL_EXPORT int cxl_region_delete(struct cxl_region *region) -+{ -+ struct cxl_decoder *decoder = cxl_region_get_decoder(region); -+ const char *devname = cxl_region_get_devname(region); -+ int rc; -+ -+ if (cxl_region_is_enabled(region)) -+ return -EBUSY; -+ -+ rc = cxl_region_delete_name(decoder, devname); -+ if (rc != 0) -+ return rc; -+ -+ decoder->regions_init = 0; -+ free_region(region, &decoder->regions); -+ return 0; -+} -+ - static void *add_cxl_region(void *parent, int id, const char *cxlregion_base) - { - const char *devname = devpath_to_devname(cxlregion_base); -@@ -599,6 +634,258 @@ cxl_region_get_interleave_granularity(struct cxl_region *region) - return region->interleave_granularity; - } - -+CXL_EXPORT struct cxl_decoder * -+cxl_region_get_target_decoder(struct cxl_region *region, int position) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ struct cxl_ctx *ctx = cxl_region_get_ctx(region); -+ int len = region->buf_len, rc; -+ char *path = region->dev_buf; -+ struct cxl_decoder *decoder; -+ char buf[SYSFS_ATTR_SIZE]; -+ -+ if (snprintf(path, len, "%s/target%d", region->dev_path, position) >= -+ len) { -+ err(ctx, "%s: buffer too small!\n", devname); -+ return NULL; -+ } -+ -+ rc = sysfs_read_attr(ctx, path, buf); -+ if (rc < 0) { -+ err(ctx, "%s: error reading target%d: %s\n", devname, -+ position, strerror(-rc)); -+ return NULL; -+ } -+ -+ decoder = cxl_decoder_get_by_name(ctx, buf); -+ if (!decoder) { -+ err(ctx, "%s: error locating decoder for target%d\n", devname, -+ position); -+ return NULL; -+ } -+ return decoder; -+} -+ -+CXL_EXPORT int cxl_region_set_size(struct cxl_region *region, -+ unsigned long long size) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ struct cxl_ctx *ctx = cxl_region_get_ctx(region); -+ int len = region->buf_len, rc; -+ char *path = region->dev_buf; -+ char buf[SYSFS_ATTR_SIZE]; -+ -+ if (size == 0) { -+ dbg(ctx, "%s: cannot use %s to delete a region\n", __func__, -+ devname); -+ return -EINVAL; -+ } -+ -+ if (snprintf(path, len, "%s/size", region->dev_path) >= len) { -+ err(ctx, "%s: buffer too small!\n", devname); -+ return -ENXIO; -+ } -+ -+ sprintf(buf, "%#llx\n", size); -+ rc = sysfs_write_attr(ctx, path, buf); -+ if (rc < 0) -+ return rc; -+ -+ region->size = size; -+ -+ return 0; -+} -+ -+CXL_EXPORT int cxl_region_set_uuid(struct cxl_region *region, uuid_t uu) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ struct cxl_ctx *ctx = cxl_region_get_ctx(region); -+ int len = region->buf_len, rc; -+ char *path = region->dev_buf; -+ char uuid[SYSFS_ATTR_SIZE]; -+ -+ if (snprintf(path, len, "%s/uuid", region->dev_path) >= len) { -+ err(ctx, "%s: buffer too small!\n", devname); -+ return -ENXIO; -+ } -+ -+ uuid_unparse(uu, uuid); -+ rc = sysfs_write_attr(ctx, path, uuid); -+ if (rc != 0) -+ return rc; -+ memcpy(region->uuid, uu, sizeof(uuid_t)); -+ return 0; -+} -+ -+CXL_EXPORT int cxl_region_set_interleave_ways(struct cxl_region *region, -+ unsigned int ways) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ struct cxl_ctx *ctx = cxl_region_get_ctx(region); -+ int len = region->buf_len, rc; -+ char *path = region->dev_buf; -+ char buf[SYSFS_ATTR_SIZE]; -+ -+ if (snprintf(path, len, "%s/interleave_ways", -+ region->dev_path) >= len) { -+ err(ctx, "%s: buffer too small!\n", devname); -+ return -ENXIO; -+ } -+ -+ sprintf(buf, "%u\n", ways); -+ rc = sysfs_write_attr(ctx, path, buf); -+ if (rc < 0) -+ return rc; -+ -+ region->interleave_ways = ways; -+ -+ return 0; -+} -+ -+CXL_EXPORT int cxl_region_set_interleave_granularity(struct cxl_region *region, -+ unsigned int granularity) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ struct cxl_ctx *ctx = cxl_region_get_ctx(region); -+ int len = region->buf_len, rc; -+ char *path = region->dev_buf; -+ char buf[SYSFS_ATTR_SIZE]; -+ -+ if (snprintf(path, len, "%s/interleave_granularity", -+ region->dev_path) >= len) { -+ err(ctx, "%s: buffer too small!\n", devname); -+ return -ENXIO; -+ } -+ -+ sprintf(buf, "%u\n", granularity); -+ rc = sysfs_write_attr(ctx, path, buf); -+ if (rc < 0) -+ return rc; -+ -+ region->interleave_granularity = granularity; -+ -+ return 0; -+} -+ -+static int region_write_target(struct cxl_region *region, int position, -+ struct cxl_decoder *decoder) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ struct cxl_ctx *ctx = cxl_region_get_ctx(region); -+ int len = region->buf_len, rc; -+ char *path = region->dev_buf; -+ const char *dec_name = ""; -+ -+ if (decoder) -+ dec_name = cxl_decoder_get_devname(decoder); -+ -+ if (snprintf(path, len, "%s/target%d", region->dev_path, position) >= -+ len) { -+ err(ctx, "%s: buffer too small!\n", devname); -+ return -ENXIO; -+ } -+ -+ rc = sysfs_write_attr(ctx, path, dec_name); -+ if (rc < 0) -+ return rc; -+ -+ return 0; -+} -+ -+CXL_EXPORT int cxl_region_set_target(struct cxl_region *region, int position, -+ struct cxl_decoder *decoder) -+{ -+ if (!decoder) -+ return -ENXIO; -+ -+ return region_write_target(region, position, decoder); -+} -+ -+CXL_EXPORT int cxl_region_clear_target(struct cxl_region *region, int position) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ struct cxl_ctx *ctx = cxl_region_get_ctx(region); -+ int rc; -+ -+ if (cxl_region_is_enabled(region)) { -+ err(ctx, "%s: can't clear targets on an active region\n", -+ devname); -+ return -EBUSY; -+ } -+ -+ rc = region_write_target(region, position, NULL); -+ if (rc) { -+ err(ctx, "%s: error clearing target%d: %s\n", -+ devname, position, strerror(-rc)); -+ return rc; -+ } -+ -+ return 0; -+} -+ -+CXL_EXPORT int cxl_region_clear_all_targets(struct cxl_region *region) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ struct cxl_ctx *ctx = cxl_region_get_ctx(region); -+ unsigned int ways, i; -+ int rc; -+ -+ if (cxl_region_is_enabled(region)) { -+ err(ctx, "%s: can't clear targets on an active region\n", -+ devname); -+ return -EBUSY; -+ } -+ -+ ways = cxl_region_get_interleave_ways(region); -+ if (ways == 0 || ways == UINT_MAX) -+ return -ENXIO; -+ -+ for (i = 0; i < ways; i++) { -+ rc = region_write_target(region, i, NULL); -+ if (rc) { -+ err(ctx, "%s: error clearing target%d: %s\n", -+ devname, i, strerror(-rc)); -+ return rc; -+ } -+ } -+ -+ return 0; -+} -+ -+static int set_region_decode(struct cxl_region *region, -+ enum cxl_decode_state decode_state) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ struct cxl_ctx *ctx = cxl_region_get_ctx(region); -+ int len = region->buf_len, rc; -+ char *path = region->dev_buf; -+ char buf[SYSFS_ATTR_SIZE]; -+ -+ if (snprintf(path, len, "%s/commit", region->dev_path) >= len) { -+ err(ctx, "%s: buffer too small!\n", devname); -+ return -ENXIO; -+ } -+ -+ sprintf(buf, "%d\n", decode_state); -+ rc = sysfs_write_attr(ctx, path, buf); -+ if (rc < 0) -+ return rc; -+ -+ region->decode_state = decode_state; -+ -+ return 0; -+} -+ -+CXL_EXPORT int cxl_region_decode_commit(struct cxl_region *region) -+{ -+ return set_region_decode(region, CXL_DECODE_COMMIT); -+} -+ -+CXL_EXPORT int cxl_region_decode_reset(struct cxl_region *region) -+{ -+ return set_region_decode(region, CXL_DECODE_RESET); -+} -+ - static struct cxl_decoder *__cxl_port_match_decoder(struct cxl_port *port, - const char *ident) - { -@@ -633,8 +920,8 @@ static struct cxl_decoder *cxl_port_find_decoder(struct cxl_port *port, - return NULL; - } - --static struct cxl_decoder *cxl_decoder_get_by_name(struct cxl_ctx *ctx, -- const char *ident) -+CXL_EXPORT struct cxl_decoder *cxl_decoder_get_by_name(struct cxl_ctx *ctx, -+ const char *ident) - { - struct cxl_bus *bus; - -@@ -1399,6 +1686,18 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - } else - decoder->mode = CXL_DECODER_MODE_NONE; - -+ sprintf(path, "%s/interleave_granularity", cxldecoder_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ decoder->interleave_granularity = UINT_MAX; -+ else -+ decoder->interleave_granularity = strtoul(buf, NULL, 0); -+ -+ sprintf(path, "%s/interleave_ways", cxldecoder_base); -+ if (sysfs_read_attr(ctx, path, buf) < 0) -+ decoder->interleave_ways = UINT_MAX; -+ else -+ decoder->interleave_ways = strtoul(buf, NULL, 0); -+ - switch (port->type) { - case CXL_PORT_ENDPOINT: - sprintf(path, "%s/dpa_resource", cxldecoder_base); -@@ -1731,6 +2030,66 @@ CXL_EXPORT bool cxl_decoder_is_locked(struct cxl_decoder *decoder) - return decoder->locked; - } - -+CXL_EXPORT unsigned int -+cxl_decoder_get_interleave_granularity(struct cxl_decoder *decoder) -+{ -+ return decoder->interleave_granularity; -+} -+ -+CXL_EXPORT unsigned int -+cxl_decoder_get_interleave_ways(struct cxl_decoder *decoder) -+{ -+ return decoder->interleave_ways; -+} -+ -+CXL_EXPORT struct cxl_region * -+cxl_decoder_create_pmem_region(struct cxl_decoder *decoder) -+{ -+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ char *path = decoder->dev_buf; -+ char buf[SYSFS_ATTR_SIZE]; -+ struct cxl_region *region; -+ int rc; -+ -+ sprintf(path, "%s/create_pmem_region", decoder->dev_path); -+ rc = sysfs_read_attr(ctx, path, buf); -+ if (rc < 0) { -+ err(ctx, "failed to read new region name: %s\n", -+ strerror(-rc)); -+ return NULL; -+ } -+ -+ rc = sysfs_write_attr(ctx, path, buf); -+ if (rc < 0) { -+ err(ctx, "failed to write new region name: %s\n", -+ strerror(-rc)); -+ return NULL; -+ } -+ -+ /* Force a re-init of regions so that the new one can be discovered */ -+ decoder->regions_init = 0; -+ -+ /* create_region was successful, walk to the new region */ -+ cxl_region_foreach(decoder, region) { -+ const char *devname = cxl_region_get_devname(region); -+ -+ if (strcmp(devname, buf) == 0) -+ goto found; -+ } -+ -+ /* -+ * If walking to the region we just created failed, something has gone -+ * very wrong. Attempt to delete it to avoid leaving a dangling region -+ * id behind. -+ */ -+ err(ctx, "failed to add new region to libcxl\n"); -+ cxl_region_delete_name(decoder, buf); -+ return NULL; -+ -+ found: -+ return region; -+} -+ - CXL_EXPORT int cxl_decoder_get_nr_targets(struct cxl_decoder *decoder) - { - return decoder->nr_targets; -@@ -1741,6 +2100,24 @@ CXL_EXPORT const char *cxl_decoder_get_devname(struct cxl_decoder *decoder) - return devpath_to_devname(decoder->dev_path); - } - -+CXL_EXPORT struct cxl_memdev * -+cxl_decoder_get_memdev(struct cxl_decoder *decoder) -+{ -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ struct cxl_endpoint *ep; -+ -+ if (!port) -+ return NULL; -+ if (!cxl_port_is_endpoint(port)) -+ return NULL; -+ -+ ep = container_of(port, struct cxl_endpoint, port); -+ if (!ep) -+ return NULL; -+ -+ return cxl_endpoint_get_memdev(ep); -+} -+ - CXL_EXPORT struct cxl_target *cxl_target_get_first(struct cxl_decoder *decoder) - { - return list_top(&decoder->targets, struct cxl_target, list); -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index e410298..cb23a0b 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -140,6 +140,7 @@ global: - cxl_decoder_is_mem_capable; - cxl_decoder_is_accelmem_capable; - cxl_decoder_is_locked; -+ cxl_decoder_create_pmem_region; - cxl_target_get_first; - cxl_target_get_next; - cxl_target_get_decoder; -@@ -183,6 +184,7 @@ global: - cxl_region_is_enabled; - cxl_region_disable; - cxl_region_enable; -+ cxl_region_delete; - cxl_region_get_ctx; - cxl_region_get_decoder; - cxl_region_get_id; -@@ -192,9 +194,23 @@ global: - cxl_region_get_resource; - cxl_region_get_interleave_ways; - cxl_region_get_interleave_granularity; -+ cxl_region_get_target_decoder; -+ cxl_region_set_size; -+ cxl_region_set_uuid; -+ cxl_region_set_interleave_ways; -+ cxl_region_set_interleave_granularity; -+ cxl_region_set_target; -+ cxl_region_clear_target; -+ cxl_region_clear_all_targets; -+ cxl_region_decode_commit; -+ cxl_region_decode_reset; - cxl_mapping_get_first; - cxl_mapping_get_next; - cxl_mapping_get_decoder; - cxl_mapping_get_region; - cxl_mapping_get_position; -+ cxl_decoder_get_by_name; -+ cxl_decoder_get_memdev; -+ cxl_decoder_get_interleave_granularity; -+ cxl_decoder_get_interleave_ways; - } LIBCXL_2; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 5e2fdd5..8bc9620 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -110,6 +110,8 @@ struct cxl_decoder { - int nr_targets; - int id; - enum cxl_decoder_mode mode; -+ unsigned int interleave_ways; -+ unsigned int interleave_granularity; - bool pmem_capable; - bool volatile_capable; - bool mem_capable; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 19d94e4..69d9c09 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -195,7 +195,13 @@ bool cxl_decoder_is_volatile_capable(struct cxl_decoder *decoder); - bool cxl_decoder_is_mem_capable(struct cxl_decoder *decoder); - bool cxl_decoder_is_accelmem_capable(struct cxl_decoder *decoder); - bool cxl_decoder_is_locked(struct cxl_decoder *decoder); -- -+unsigned int -+cxl_decoder_get_interleave_granularity(struct cxl_decoder *decoder); -+unsigned int cxl_decoder_get_interleave_ways(struct cxl_decoder *decoder); -+struct cxl_region *cxl_decoder_create_pmem_region(struct cxl_decoder *decoder); -+struct cxl_decoder *cxl_decoder_get_by_name(struct cxl_ctx *ctx, -+ const char *ident); -+struct cxl_memdev *cxl_decoder_get_memdev(struct cxl_decoder *decoder); - #define cxl_decoder_foreach(port, decoder) \ - for (decoder = cxl_decoder_get_first(port); decoder != NULL; \ - decoder = cxl_decoder_get_next(decoder)) -@@ -244,6 +250,7 @@ int cxl_region_decode_is_committed(struct cxl_region *region); - int cxl_region_is_enabled(struct cxl_region *region); - int cxl_region_disable(struct cxl_region *region); - int cxl_region_enable(struct cxl_region *region); -+int cxl_region_delete(struct cxl_region *region); - struct cxl_ctx *cxl_region_get_ctx(struct cxl_region *region); - struct cxl_decoder *cxl_region_get_decoder(struct cxl_region *region); - int cxl_region_get_id(struct cxl_region *region); -@@ -253,6 +260,20 @@ unsigned long long cxl_region_get_size(struct cxl_region *region); - unsigned long long cxl_region_get_resource(struct cxl_region *region); - unsigned int cxl_region_get_interleave_ways(struct cxl_region *region); - unsigned int cxl_region_get_interleave_granularity(struct cxl_region *region); -+struct cxl_decoder *cxl_region_get_target_decoder(struct cxl_region *region, -+ int position); -+int cxl_region_set_size(struct cxl_region *region, unsigned long long size); -+int cxl_region_set_uuid(struct cxl_region *region, uuid_t uu); -+int cxl_region_set_interleave_ways(struct cxl_region *region, -+ unsigned int ways); -+int cxl_region_set_interleave_granularity(struct cxl_region *region, -+ unsigned int granularity); -+int cxl_region_set_target(struct cxl_region *region, int position, -+ struct cxl_decoder *decoder); -+int cxl_region_clear_target(struct cxl_region *region, int position); -+int cxl_region_clear_all_targets(struct cxl_region *region); -+int cxl_region_decode_commit(struct cxl_region *region); -+int cxl_region_decode_reset(struct cxl_region *region); - - #define cxl_region_foreach(decoder, region) \ - for (region = cxl_region_get_first(decoder); region != NULL; \ --- -2.27.0 - diff --git a/SOURCES/0195-cxl-add-a-create-region-command.patch b/SOURCES/0195-cxl-add-a-create-region-command.patch deleted file mode 100644 index 839722c..0000000 --- a/SOURCES/0195-cxl-add-a-create-region-command.patch +++ /dev/null @@ -1,829 +0,0 @@ -From 21b089025178442baa7b59823a7fd264b4c075a8 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Mon, 15 Aug 2022 13:22:10 -0600 -Subject: [PATCH 195/217] cxl: add a 'create-region' command - -Add a 'create-region' command to cxl-cli that walks the platform's CXL -hierarchy to find an appropriate root decoder based on any options -provided, and uses libcxl APIs to create a 'region' that is comprehended -by libnvdimm and ndctl. - -Link: https://lore.kernel.org/r/20220815192214.545800-8-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/bus-option.txt | 5 + - Documentation/cxl/cxl-create-region.txt | 112 +++++ - Documentation/cxl/meson.build | 2 + - Documentation/cxl/region-description.txt | 7 + - cxl/builtin.h | 1 + - cxl/cxl.c | 1 + - cxl/filter.h | 4 +- - cxl/json.c | 9 + - cxl/meson.build | 1 + - cxl/region.c | 550 +++++++++++++++++++++++ - 10 files changed, 691 insertions(+), 1 deletion(-) - create mode 100644 Documentation/cxl/bus-option.txt - create mode 100644 Documentation/cxl/cxl-create-region.txt - create mode 100644 Documentation/cxl/region-description.txt - create mode 100644 cxl/region.c - -diff --git a/Documentation/cxl/bus-option.txt b/Documentation/cxl/bus-option.txt -new file mode 100644 -index 0000000..02e2f08 ---- /dev/null -+++ b/Documentation/cxl/bus-option.txt -@@ -0,0 +1,5 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+-b:: -+--bus=:: -+ Restrict the operation to the specified bus. -diff --git a/Documentation/cxl/cxl-create-region.txt b/Documentation/cxl/cxl-create-region.txt -new file mode 100644 -index 0000000..6b740d5 ---- /dev/null -+++ b/Documentation/cxl/cxl-create-region.txt -@@ -0,0 +1,112 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-create-region(1) -+==================== -+ -+NAME -+---- -+cxl-create-region - Assemble a CXL region by setting up attributes of its -+constituent CXL memdevs. -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl create-region []' -+ -+include::region-description.txt[] -+ -+For create-region, a size can optionally be specified, but if not, the maximum -+possible size for each memdev will be used up to the available decode capacity -+in the system for the given memory type. For persistent regions a UUID can -+optionally be specified, but if not, one will be generated. -+ -+If the region-creation operation is successful, a region object will be -+emitted on stdout in JSON format (see examples). If the specified arguments -+cannot be satisfied with a legal configuration, then an appropriate error will -+be emitted on stderr. -+ -+EXAMPLE -+------- -+---- -+#cxl create - region - m - d decoder0 .1 - w 2 - g 1024 mem0 mem1 -+{ -+ "region":"region0", -+ "resource":"0xc90000000", -+ "size":"512.00 MiB (536.87 MB)", -+ "interleave_ways":2, -+ "interleave_granularity":1024, -+ "mappings":[ -+ { -+ "position":1, -+ "decoder":"decoder4.0" -+ }, -+ { -+ "position":0, -+ "decoder":"decoder3.0" -+ } -+ ] -+} -+created 1 region -+---- -+ -+OPTIONS -+------- -+:: -+The CXL targets that should be used to form the region. The number of -+'target' arguments must match the '--ways' option (if provided). The -+targets are memdev names such as 'mem0', 'mem1' etc. -+ -+include::bus-option.txt[] -+ -+-m:: -+--memdevs:: -+ Indicate that the non-option arguments for 'target(s)' refer to memdev -+ names. Currently this is the only option supported, and must be -+ specified. -+ -+-s:: -+--size=:: -+ Specify the total size for the new region. This is optional, and by -+ default, the maximum possible size will be used. The maximum possible -+ size is gated by both the contiguous free HPA space remaining in the -+ root decoder, and the available DPA space in the component memdevs. -+ -+-t:: -+--type=:: -+ Specify the region type - 'pmem' or 'ram'. Defaults to 'pmem'. -+ -+-U:: -+--uuid=:: -+ Specify a UUID for the new region. This shouldn't usually need to be -+ specified, as one will be generated by default. -+ -+-w:: -+--ways=:: -+ The number of interleave ways for the new region's interleave. This -+ should be equal to the number of memdevs specified in --memdevs, if -+ --memdevs is being supplied. If --ways is not specified, it will be -+ determined based on the number of memdev targets provided. -+ -+-g:: -+--granularity=:: -+ The interleave granularity for the new region. Must match the selected -+ root decoder's (if provided) granularity. If the root decoder is -+ interleaved across more than one host-bridge then this value must match -+ that granularity. Otherwise, for non-interleaved decode windows, any -+ granularity can be specified as long as all devices support that setting. -+ -+-d:: -+--decoder=:: -+ The root decoder that the region should be created under. If not -+ supplied, the first cross-host bridge (if available), decoder that -+ supports the largest interleave will be chosen. -+ -+include::human-option.txt[] -+ -+include::debug-option.txt[] -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-list[1], -diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build -index 423be90..340cdee 100644 ---- a/Documentation/cxl/meson.build -+++ b/Documentation/cxl/meson.build -@@ -23,6 +23,7 @@ filedeps = [ - 'memdev-option.txt', - 'labels-options.txt', - 'debug-option.txt', -+ 'region-description.txt', - ] - - cxl_manpages = [ -@@ -39,6 +40,7 @@ cxl_manpages = [ - 'cxl-set-partition.txt', - 'cxl-reserve-dpa.txt', - 'cxl-free-dpa.txt', -+ 'cxl-create-region.txt', - ] - - foreach man : cxl_manpages -diff --git a/Documentation/cxl/region-description.txt b/Documentation/cxl/region-description.txt -new file mode 100644 -index 0000000..d7e3077 ---- /dev/null -+++ b/Documentation/cxl/region-description.txt -@@ -0,0 +1,7 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+DESCRIPTION -+----------- -+A CXL region is composed of one or more slices of CXL memdevs, with configurable -+interleave settings - both the number of interleave ways, and the interleave -+granularity. -diff --git a/cxl/builtin.h b/cxl/builtin.h -index 9e6fc62..843bada 100644 ---- a/cxl/builtin.h -+++ b/cxl/builtin.h -@@ -18,4 +18,5 @@ int cmd_disable_port(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_enable_port(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_set_partition(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_disable_bus(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_create_region(int argc, const char **argv, struct cxl_ctx *ctx); - #endif /* _CXL_BUILTIN_H_ */ -diff --git a/cxl/cxl.c b/cxl/cxl.c -index ef4cda9..f0afcfe 100644 ---- a/cxl/cxl.c -+++ b/cxl/cxl.c -@@ -72,6 +72,7 @@ static struct cmd_struct commands[] = { - { "enable-port", .c_fn = cmd_enable_port }, - { "set-partition", .c_fn = cmd_set_partition }, - { "disable-bus", .c_fn = cmd_disable_bus }, -+ { "create-region", .c_fn = cmd_create_region }, - }; - - int main(int argc, const char **argv) -diff --git a/cxl/filter.h b/cxl/filter.h -index 609433c..d22d8b1 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -35,8 +35,10 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev, - struct cxl_port *util_cxl_port_filter_by_memdev(struct cxl_port *port, - const char *ident, - const char *serial); --struct cxl_region *util_cxl_region_filter(struct cxl_region *region, -+struct cxl_decoder *util_cxl_decoder_filter(struct cxl_decoder *decoder, - const char *__ident); -+struct cxl_region *util_cxl_region_filter(struct cxl_region *region, -+ const char *__ident); - - enum cxl_port_filter_mode { - CXL_PF_SINGLE, -diff --git a/cxl/json.c b/cxl/json.c -index 70cf286..9dc99df 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -547,6 +547,7 @@ void util_cxl_mappings_append_json(struct json_object *jregion, - cxl_mapping_foreach(region, mapping) { - struct json_object *jmapping; - struct cxl_decoder *decoder; -+ struct cxl_memdev *memdev; - - jmapping = json_object_new_object(); - if (!jmapping) -@@ -564,6 +565,14 @@ void util_cxl_mappings_append_json(struct json_object *jregion, - if (!decoder) - continue; - -+ memdev = cxl_decoder_get_memdev(decoder); -+ if (memdev) { -+ devname = cxl_memdev_get_devname(memdev); -+ jobj = json_object_new_string(devname); -+ if (jobj) -+ json_object_object_add(jmapping, "memdev", jobj); -+ } -+ - devname = cxl_decoder_get_devname(decoder); - jobj = json_object_new_string(devname); - if (jobj) -diff --git a/cxl/meson.build b/cxl/meson.build -index d63dcb1..f2474aa 100644 ---- a/cxl/meson.build -+++ b/cxl/meson.build -@@ -3,6 +3,7 @@ cxl_src = [ - 'list.c', - 'port.c', - 'bus.c', -+ 'region.c', - 'memdev.c', - 'json.c', - 'filter.c', -diff --git a/cxl/region.c b/cxl/region.c -new file mode 100644 -index 0000000..2791ac9 ---- /dev/null -+++ b/cxl/region.c -@@ -0,0 +1,550 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* Copyright (C) 2020-2022 Intel Corporation. All rights reserved. */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "filter.h" -+#include "json.h" -+ -+static struct region_params { -+ const char *bus; -+ const char *size; -+ const char *ways; -+ const char *granularity; -+ const char *type; -+ const char *root_decoder; -+ const char *region; -+ bool memdevs; -+ bool force; -+ bool human; -+ bool debug; -+} param; -+ -+struct parsed_params { -+ u64 size; -+ u64 ep_min_size; -+ unsigned int ways; -+ unsigned int granularity; -+ const char **targets; -+ int num_targets; -+ struct cxl_decoder *root_decoder; -+ enum cxl_decoder_mode mode; -+}; -+ -+enum region_actions { -+ ACTION_CREATE, -+}; -+ -+static struct log_ctx rl; -+ -+#define BASE_OPTIONS() \ -+OPT_STRING('b', "bus", ¶m.bus, "bus name", \ -+ "Limit operation to the specified bus"), \ -+OPT_STRING('d', "decoder", ¶m.root_decoder, "root decoder name", \ -+ "Limit to / use the specified root decoder"), \ -+OPT_BOOLEAN(0, "debug", ¶m.debug, "turn on debug") -+ -+#define CREATE_OPTIONS() \ -+OPT_STRING('s', "size", ¶m.size, \ -+ "size in bytes or with a K/M/G etc. suffix", \ -+ "total size desired for the resulting region."), \ -+OPT_STRING('w', "ways", ¶m.ways, \ -+ "number of interleave ways", \ -+ "number of memdevs participating in the regions interleave set"), \ -+OPT_STRING('g', "granularity", \ -+ ¶m.granularity, "interleave granularity", \ -+ "granularity of the interleave set"), \ -+OPT_STRING('t', "type", ¶m.type, \ -+ "region type", "region type - 'pmem' or 'ram'"), \ -+OPT_BOOLEAN('m', "memdevs", ¶m.memdevs, \ -+ "non-option arguments are memdevs"), \ -+OPT_BOOLEAN('u', "human", ¶m.human, "use human friendly number formats") -+ -+static const struct option create_options[] = { -+ BASE_OPTIONS(), -+ CREATE_OPTIONS(), -+ OPT_END(), -+}; -+ -+ -+ -+static int parse_create_options(int argc, const char **argv, -+ struct parsed_params *p) -+{ -+ int i; -+ -+ if (!param.root_decoder) { -+ log_err(&rl, "no root decoder specified\n"); -+ return -EINVAL; -+ } -+ -+ if (param.type) { -+ p->mode = cxl_decoder_mode_from_ident(param.type); -+ if (p->mode == CXL_DECODER_MODE_NONE) { -+ log_err(&rl, "unsupported type: %s\n", param.type); -+ return -EINVAL; -+ } -+ } else { -+ p->mode = CXL_DECODER_MODE_PMEM; -+ } -+ -+ if (param.size) { -+ p->size = parse_size64(param.size); -+ if (p->size == ULLONG_MAX) { -+ log_err(&rl, "Invalid size: %s\n", param.size); -+ return -EINVAL; -+ } -+ } -+ -+ if (param.ways) { -+ unsigned long ways = strtoul(param.ways, NULL, 0); -+ -+ if (ways == ULONG_MAX || (int)ways <= 0) { -+ log_err(&rl, "Invalid interleave ways: %s\n", -+ param.ways); -+ return -EINVAL; -+ } -+ p->ways = ways; -+ } else if (argc) { -+ p->ways = argc; -+ } else { -+ log_err(&rl, -+ "couldn't determine interleave ways from options or arguments\n"); -+ return -EINVAL; -+ } -+ -+ if (param.granularity) { -+ unsigned long granularity = strtoul(param.granularity, NULL, 0); -+ -+ if (granularity == ULONG_MAX || (int)granularity <= 0) { -+ log_err(&rl, "Invalid interleave granularity: %s\n", -+ param.granularity); -+ return -EINVAL; -+ } -+ p->granularity = granularity; -+ } -+ -+ -+ if (argc > (int)p->ways) { -+ for (i = p->ways; i < argc; i++) -+ log_err(&rl, "extra argument: %s\n", p->targets[i]); -+ return -EINVAL; -+ } -+ -+ if (argc < (int)p->ways) { -+ log_err(&rl, -+ "too few target arguments (%d) for interleave ways (%u)\n", -+ argc, p->ways); -+ return -EINVAL; -+ } -+ -+ if (p->size && p->ways) { -+ if (p->size % p->ways) { -+ log_err(&rl, -+ "size (%lu) is not an integral multiple of interleave-ways (%u)\n", -+ p->size, p->ways); -+ return -EINVAL; -+ } -+ } -+ -+ /* -+ * For all practical purposes, -m is the default target type, but -+ * hold off on actively making that decision until a second target -+ * option is available. -+ */ -+ if (!param.memdevs) { -+ log_err(&rl, -+ "must specify option for target object types (-m)\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int parse_region_options(int argc, const char **argv, -+ struct cxl_ctx *ctx, enum region_actions action, -+ const struct option *options, -+ struct parsed_params *p, const char *usage) -+{ -+ const char * const u[] = { -+ usage, -+ NULL -+ }; -+ -+ argc = parse_options(argc, argv, options, u, 0); -+ p->targets = argv; -+ p->num_targets = argc; -+ -+ if (param.debug) { -+ cxl_set_log_priority(ctx, LOG_DEBUG); -+ rl.log_priority = LOG_DEBUG; -+ } else -+ rl.log_priority = LOG_INFO; -+ -+ switch(action) { -+ case ACTION_CREATE: -+ return parse_create_options(argc, argv, p); -+ default: -+ return 0; -+ } -+} -+ -+/** -+ * validate_memdev() - match memdev with the target provided, -+ * and determine its size contribution -+ * @memdev: cxl_memdev being tested for a match against the named target -+ * @target: target memdev -+ * @p: params structure -+ * -+ * This is called for each memdev in the system, and only returns 'true' if -+ * the memdev name matches the target argument being tested. Additionally, -+ * it sets an ep_min_size attribute that always contains the size of the -+ * smallest target in the provided list. This is used during the automatic -+ * size determination later, to ensure that all targets contribute equally -+ * to the region in case of unevenly sized memdevs. -+ */ -+static bool validate_memdev(struct cxl_memdev *memdev, const char *target, -+ struct parsed_params *p) -+{ -+ const char *devname = cxl_memdev_get_devname(memdev); -+ u64 size; -+ -+ if (strcmp(devname, target) != 0) -+ return false; -+ -+ size = cxl_memdev_get_pmem_size(memdev); -+ if (!p->ep_min_size) -+ p->ep_min_size = size; -+ else -+ p->ep_min_size = min(p->ep_min_size, size); -+ -+ return true; -+} -+ -+static int validate_config_memdevs(struct cxl_ctx *ctx, struct parsed_params *p) -+{ -+ unsigned int i, matched = 0; -+ -+ for (i = 0; i < p->ways; i++) { -+ struct cxl_memdev *memdev; -+ -+ cxl_memdev_foreach(ctx, memdev) -+ if (validate_memdev(memdev, p->targets[i], p)) -+ matched++; -+ } -+ if (matched != p->ways) { -+ log_err(&rl, -+ "one or more memdevs not found in CXL topology\n"); -+ return -ENXIO; -+ } -+ -+ return 0; -+} -+ -+static int validate_decoder(struct cxl_decoder *decoder, -+ struct parsed_params *p) -+{ -+ const char *devname = cxl_decoder_get_devname(decoder); -+ -+ switch(p->mode) { -+ case CXL_DECODER_MODE_RAM: -+ if (!cxl_decoder_is_volatile_capable(decoder)) { -+ log_err(&rl, "%s is not volatile capable\n", devname); -+ return -EINVAL; -+ } -+ break; -+ case CXL_DECODER_MODE_PMEM: -+ if (!cxl_decoder_is_pmem_capable(decoder)) { -+ log_err(&rl, "%s is not pmem capable\n", devname); -+ return -EINVAL; -+ } -+ break; -+ default: -+ log_err(&rl, "unknown type: %s\n", param.type); -+ return -EINVAL; -+ } -+ -+ /* TODO check if the interleave config is possible under this decoder */ -+ -+ return 0; -+} -+ -+static int create_region_validate_config(struct cxl_ctx *ctx, -+ struct parsed_params *p) -+{ -+ struct cxl_bus *bus; -+ int rc; -+ -+ cxl_bus_foreach(ctx, bus) { -+ struct cxl_decoder *decoder; -+ struct cxl_port *port; -+ -+ if (!util_cxl_bus_filter(bus, param.bus)) -+ continue; -+ -+ port = cxl_bus_get_port(bus); -+ if (!cxl_port_is_root(port)) -+ continue; -+ -+ cxl_decoder_foreach (port, decoder) { -+ if (util_cxl_decoder_filter(decoder, -+ param.root_decoder)) { -+ p->root_decoder = decoder; -+ goto found; -+ } -+ } -+ } -+ -+found: -+ if (p->root_decoder == NULL) { -+ log_err(&rl, "%s not found in CXL topology\n", -+ param.root_decoder); -+ return -ENXIO; -+ } -+ -+ rc = validate_decoder(p->root_decoder, p); -+ if (rc) -+ return rc; -+ -+ return validate_config_memdevs(ctx, p); -+} -+ -+static struct cxl_decoder * -+cxl_memdev_target_find_decoder(struct cxl_ctx *ctx, const char *memdev_name) -+{ -+ struct cxl_endpoint *ep = NULL; -+ struct cxl_decoder *decoder; -+ struct cxl_memdev *memdev; -+ struct cxl_port *port; -+ -+ cxl_memdev_foreach(ctx, memdev) { -+ const char *devname = cxl_memdev_get_devname(memdev); -+ -+ if (strcmp(devname, memdev_name) != 0) -+ continue; -+ -+ ep = cxl_memdev_get_endpoint(memdev); -+ } -+ -+ if (!ep) { -+ log_err(&rl, "could not get an endpoint for %s\n", -+ memdev_name); -+ return NULL; -+ } -+ -+ port = cxl_endpoint_get_port(ep); -+ if (!port) { -+ log_err(&rl, "could not get a port for %s\n", -+ memdev_name); -+ return NULL; -+ } -+ -+ cxl_decoder_foreach(port, decoder) -+ if (cxl_decoder_get_size(decoder) == 0) -+ return decoder; -+ -+ log_err(&rl, "could not get a free decoder for %s\n", memdev_name); -+ return NULL; -+} -+ -+#define try(prefix, op, dev, p) \ -+do { \ -+ int __rc = prefix##_##op(dev, p); \ -+ if (__rc) { \ -+ log_err(&rl, "%s: " #op " failed: %s\n", \ -+ prefix##_get_devname(dev), \ -+ strerror(abs(__rc))); \ -+ rc = __rc; \ -+ goto err_delete; \ -+ } \ -+} while (0) -+ -+static int cxl_region_determine_granularity(struct cxl_region *region, -+ struct parsed_params *p) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ unsigned int granularity, ways; -+ -+ /* Default granularity will be the root decoder's granularity */ -+ granularity = cxl_decoder_get_interleave_granularity(p->root_decoder); -+ if (granularity == 0 || granularity == UINT_MAX) { -+ log_err(&rl, "%s: unable to determine root decoder granularity\n", -+ devname); -+ return -ENXIO; -+ } -+ -+ /* If no user-supplied granularity, just use the default */ -+ if (!p->granularity) -+ return granularity; -+ -+ ways = cxl_decoder_get_interleave_ways(p->root_decoder); -+ if (ways == 0 || ways == UINT_MAX) { -+ log_err(&rl, "%s: unable to determine root decoder ways\n", -+ devname); -+ return -ENXIO; -+ } -+ -+ /* For ways == 1, any user-supplied granularity is fine */ -+ if (ways == 1) -+ return p->granularity; -+ -+ /* -+ * For ways > 1, only allow the same granularity as the selected -+ * root decoder -+ */ -+ if (p->granularity == granularity) -+ return granularity; -+ -+ log_err(&rl, -+ "%s: For an x%d root, only root decoder granularity (%d) permitted\n", -+ devname, ways, granularity); -+ return -EINVAL; -+} -+ -+static int create_region(struct cxl_ctx *ctx, int *count, -+ struct parsed_params *p) -+{ -+ unsigned long flags = UTIL_JSON_TARGETS; -+ struct json_object *jregion; -+ unsigned int i, granularity; -+ struct cxl_region *region; -+ const char *devname; -+ uuid_t uuid; -+ u64 size; -+ int rc; -+ -+ rc = create_region_validate_config(ctx, p); -+ if (rc) -+ return rc; -+ -+ if (p->size) { -+ size = p->size; -+ } else if (p->ep_min_size) { -+ size = p->ep_min_size * p->ways; -+ } else { -+ log_err(&rl, "%s: unable to determine region size\n", __func__); -+ return -ENXIO; -+ } -+ -+ if (p->mode == CXL_DECODER_MODE_PMEM) { -+ region = cxl_decoder_create_pmem_region(p->root_decoder); -+ if (!region) { -+ log_err(&rl, "failed to create region under %s\n", -+ param.root_decoder); -+ return -ENXIO; -+ } -+ } else { -+ log_err(&rl, "region type '%s' not supported yet\n", -+ param.type); -+ return -EOPNOTSUPP; -+ } -+ -+ devname = cxl_region_get_devname(region); -+ -+ rc = cxl_region_determine_granularity(region, p); -+ if (rc < 0) -+ goto err_delete; -+ granularity = rc; -+ -+ uuid_generate(uuid); -+ try(cxl_region, set_interleave_granularity, region, granularity); -+ try(cxl_region, set_interleave_ways, region, p->ways); -+ try(cxl_region, set_uuid, region, uuid); -+ try(cxl_region, set_size, region, size); -+ -+ for (i = 0; i < p->ways; i++) { -+ struct cxl_decoder *ep_decoder = NULL; -+ -+ ep_decoder = cxl_memdev_target_find_decoder(ctx, p->targets[i]); -+ if (!ep_decoder) { -+ rc = -ENXIO; -+ goto err_delete; -+ } -+ if (cxl_decoder_get_mode(ep_decoder) != p->mode) { -+ /* -+ * The memdev_target_find_decoder() helper returns a free -+ * decoder whose size has been checked for 0. -+ * Thus it is safe to change the mode here if needed. -+ */ -+ try(cxl_decoder, set_dpa_size, ep_decoder, 0); -+ try(cxl_decoder, set_mode, ep_decoder, p->mode); -+ } -+ try(cxl_decoder, set_dpa_size, ep_decoder, size/p->ways); -+ rc = cxl_region_set_target(region, i, ep_decoder); -+ if (rc) { -+ log_err(&rl, "%s: failed to set target%d to %s\n", -+ devname, i, p->targets[i]); -+ goto err_delete; -+ } -+ } -+ -+ rc = cxl_region_decode_commit(region); -+ if (rc) { -+ log_err(&rl, "%s: failed to commit decode: %s\n", devname, -+ strerror(-rc)); -+ goto err_delete; -+ } -+ -+ rc = cxl_region_enable(region); -+ if (rc) { -+ log_err(&rl, "%s: failed to enable: %s\n", devname, -+ strerror(-rc)); -+ goto err_delete; -+ } -+ *count = 1; -+ -+ if (isatty(1)) -+ flags |= UTIL_JSON_HUMAN; -+ jregion = util_cxl_region_to_json(region, flags); -+ if (jregion) -+ printf("%s\n", json_object_to_json_string_ext(jregion, -+ JSON_C_TO_STRING_PRETTY)); -+ -+ return 0; -+ -+err_delete: -+ cxl_region_delete(region); -+ return rc; -+} -+ -+static int region_action(int argc, const char **argv, struct cxl_ctx *ctx, -+ enum region_actions action, -+ const struct option *options, struct parsed_params *p, -+ int *count, const char *u) -+{ -+ int rc = -ENXIO; -+ -+ log_init(&rl, "cxl region", "CXL_REGION_LOG"); -+ rc = parse_region_options(argc, argv, ctx, action, options, p, u); -+ if (rc) -+ return rc; -+ -+ if (action == ACTION_CREATE) -+ return create_region(ctx, count, p); -+ -+ return rc; -+} -+ -+int cmd_create_region(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ const char *u = "cxl create-region ... []"; -+ struct parsed_params p = { 0 }; -+ int rc, count = 0; -+ -+ rc = region_action(argc, argv, ctx, ACTION_CREATE, create_options, &p, -+ &count, u); -+ log_info(&rl, "created %d region%s\n", count, count == 1 ? "" : "s"); -+ return rc == 0 ? 0 : EXIT_FAILURE; -+} --- -2.27.0 - diff --git a/SOURCES/0196-cxl-add-commands-to-enable-disable-destroy-region.patch b/SOURCES/0196-cxl-add-commands-to-enable-disable-destroy-region.patch deleted file mode 100644 index 279a4ca..0000000 --- a/SOURCES/0196-cxl-add-commands-to-enable-disable-destroy-region.patch +++ /dev/null @@ -1,459 +0,0 @@ -From 93122376250a8a5cfae635e9729c34dfaa0fd116 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Mon, 15 Aug 2022 13:22:11 -0600 -Subject: [PATCH 196/217] cxl: add commands to {enable,disable,destroy}-region - -With a template from cxl-create-region in place, add its friends: - - cxl enable-region - cxl disable-region - cxl destroy-region - -Link: https://lore.kernel.org/r/20220815192214.545800-9-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-destroy-region.txt | 41 +++++ - Documentation/cxl/cxl-disable-region.txt | 36 +++++ - Documentation/cxl/cxl-enable-region.txt | 36 +++++ - Documentation/cxl/decoder-option.txt | 6 + - Documentation/cxl/meson.build | 4 + - cxl/builtin.h | 3 + - cxl/cxl.c | 3 + - cxl/region.c | 193 ++++++++++++++++++++++- - 8 files changed, 321 insertions(+), 1 deletion(-) - create mode 100644 Documentation/cxl/cxl-destroy-region.txt - create mode 100644 Documentation/cxl/cxl-disable-region.txt - create mode 100644 Documentation/cxl/cxl-enable-region.txt - create mode 100644 Documentation/cxl/decoder-option.txt - -diff --git a/Documentation/cxl/cxl-destroy-region.txt b/Documentation/cxl/cxl-destroy-region.txt -new file mode 100644 -index 0000000..74f4093 ---- /dev/null -+++ b/Documentation/cxl/cxl-destroy-region.txt -@@ -0,0 +1,41 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-destroy-region(1) -+===================== -+ -+NAME -+---- -+cxl-destroy-region - destroy specified region(s). -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl destroy-region []' -+ -+include::region-description.txt[] -+ -+EXAMPLE -+------- -+---- -+# cxl destroy-region all -+destroyed 2 regions -+---- -+ -+OPTIONS -+------- -+include::bus-option.txt[] -+ -+-f:: -+--force:: -+ Force a destroy operation even if the region is active. -+ This will attempt to disable the region first. -+ -+include::decoder-option.txt[] -+ -+include::debug-option.txt[] -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-list[1], linkcxl:cxl-create-region[1] -diff --git a/Documentation/cxl/cxl-disable-region.txt b/Documentation/cxl/cxl-disable-region.txt -new file mode 100644 -index 0000000..6a39aee ---- /dev/null -+++ b/Documentation/cxl/cxl-disable-region.txt -@@ -0,0 +1,36 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-disable-region(1) -+===================== -+ -+NAME -+---- -+cxl-disable-region - disable specified region(s). -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl disable-region []' -+ -+include::region-description.txt[] -+ -+EXAMPLE -+------- -+---- -+# cxl disable-region all -+disabled 2 regions -+---- -+ -+OPTIONS -+------- -+include::bus-option.txt[] -+ -+include::decoder-option.txt[] -+ -+include::debug-option.txt[] -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-list[1], linkcxl:cxl-enable-region[1] -diff --git a/Documentation/cxl/cxl-enable-region.txt b/Documentation/cxl/cxl-enable-region.txt -new file mode 100644 -index 0000000..f6ef00f ---- /dev/null -+++ b/Documentation/cxl/cxl-enable-region.txt -@@ -0,0 +1,36 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+cxl-enable-region(1) -+===================== -+ -+NAME -+---- -+cxl-enable-region - enable specified region(s). -+ -+SYNOPSIS -+-------- -+[verse] -+'cxl enable-region []' -+ -+include::region-description.txt[] -+ -+EXAMPLE -+------- -+---- -+# cxl enable-region all -+enabled 2 regions -+---- -+ -+OPTIONS -+------- -+include::bus-option.txt[] -+ -+include::decoder-option.txt[] -+ -+include::debug-option.txt[] -+ -+include::../copyright.txt[] -+ -+SEE ALSO -+-------- -+linkcxl:cxl-list[1], linkcxl:cxl-disable-region[1] -diff --git a/Documentation/cxl/decoder-option.txt b/Documentation/cxl/decoder-option.txt -new file mode 100644 -index 0000000..e638d6e ---- /dev/null -+++ b/Documentation/cxl/decoder-option.txt -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+-d:: -+--decoder=:: -+ The root decoder to limit the operation to. Only regions that are -+ children of the specified decoder will be acted upon. -diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build -index 340cdee..147ea71 100644 ---- a/Documentation/cxl/meson.build -+++ b/Documentation/cxl/meson.build -@@ -24,6 +24,7 @@ filedeps = [ - 'labels-options.txt', - 'debug-option.txt', - 'region-description.txt', -+ 'decoder-option.txt', - ] - - cxl_manpages = [ -@@ -41,6 +42,9 @@ cxl_manpages = [ - 'cxl-reserve-dpa.txt', - 'cxl-free-dpa.txt', - 'cxl-create-region.txt', -+ 'cxl-disable-region.txt', -+ 'cxl-enable-region.txt', -+ 'cxl-destroy-region.txt', - ] - - foreach man : cxl_manpages -diff --git a/cxl/builtin.h b/cxl/builtin.h -index 843bada..b28c221 100644 ---- a/cxl/builtin.h -+++ b/cxl/builtin.h -@@ -19,4 +19,7 @@ int cmd_enable_port(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_set_partition(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_disable_bus(int argc, const char **argv, struct cxl_ctx *ctx); - int cmd_create_region(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_enable_region(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_disable_region(int argc, const char **argv, struct cxl_ctx *ctx); -+int cmd_destroy_region(int argc, const char **argv, struct cxl_ctx *ctx); - #endif /* _CXL_BUILTIN_H_ */ -diff --git a/cxl/cxl.c b/cxl/cxl.c -index f0afcfe..dd1be7a 100644 ---- a/cxl/cxl.c -+++ b/cxl/cxl.c -@@ -73,6 +73,9 @@ static struct cmd_struct commands[] = { - { "set-partition", .c_fn = cmd_set_partition }, - { "disable-bus", .c_fn = cmd_disable_bus }, - { "create-region", .c_fn = cmd_create_region }, -+ { "enable-region", .c_fn = cmd_enable_region }, -+ { "disable-region", .c_fn = cmd_disable_region }, -+ { "destroy-region", .c_fn = cmd_destroy_region }, - }; - - int main(int argc, const char **argv) -diff --git a/cxl/region.c b/cxl/region.c -index 2791ac9..b22d3c8 100644 ---- a/cxl/region.c -+++ b/cxl/region.c -@@ -45,6 +45,9 @@ struct parsed_params { - - enum region_actions { - ACTION_CREATE, -+ ACTION_ENABLE, -+ ACTION_DISABLE, -+ ACTION_DESTROY, - }; - - static struct log_ctx rl; -@@ -78,7 +81,22 @@ static const struct option create_options[] = { - OPT_END(), - }; - -+static const struct option enable_options[] = { -+ BASE_OPTIONS(), -+ OPT_END(), -+}; - -+static const struct option disable_options[] = { -+ BASE_OPTIONS(), -+ OPT_END(), -+}; -+ -+static const struct option destroy_options[] = { -+ BASE_OPTIONS(), -+ OPT_BOOLEAN('f', "force", ¶m.force, -+ "destroy region even if currently active"), -+ OPT_END(), -+}; - - static int parse_create_options(int argc, const char **argv, - struct parsed_params *p) -@@ -519,12 +537,122 @@ err_delete: - return rc; - } - -+static int destroy_region(struct cxl_region *region) -+{ -+ const char *devname = cxl_region_get_devname(region); -+ unsigned int ways, i; -+ int rc; -+ -+ /* First, unbind/disable the region if needed */ -+ if (cxl_region_is_enabled(region)) { -+ if (param.force) { -+ rc = cxl_region_disable(region); -+ if (rc) { -+ log_err(&rl, "%s: error disabling region: %s\n", -+ devname, strerror(-rc)); -+ return rc; -+ } -+ } else { -+ log_err(&rl, "%s active. Disable it or use --force\n", -+ devname); -+ return -EBUSY; -+ } -+ } -+ -+ /* Reset the region decode in preparation for removal */ -+ rc = cxl_region_decode_reset(region); -+ if (rc) { -+ log_err(&rl, "%s: failed to reset decode: %s\n", devname, -+ strerror(-rc)); -+ return rc; -+ } -+ -+ /* Reset all endpoint decoders and region targets */ -+ ways = cxl_region_get_interleave_ways(region); -+ if (ways == 0 || ways == UINT_MAX) { -+ log_err(&rl, "%s: error getting interleave ways\n", devname); -+ return -ENXIO; -+ } -+ -+ for (i = 0; i < ways; i++) { -+ struct cxl_decoder *ep_decoder; -+ -+ ep_decoder = cxl_region_get_target_decoder(region, i); -+ if (!ep_decoder) -+ return -ENXIO; -+ -+ rc = cxl_region_clear_target(region, i); -+ if (rc) { -+ log_err(&rl, "%s: clearing target%d failed: %s\n", -+ devname, i, strerror(abs(rc))); -+ return rc; -+ } -+ -+ rc = cxl_decoder_set_dpa_size(ep_decoder, 0); -+ if (rc) { -+ log_err(&rl, "%s: set_dpa_size failed: %s\n", -+ cxl_decoder_get_devname(ep_decoder), -+ strerror(abs(rc))); -+ return rc; -+ } -+ } -+ -+ /* Finally, delete the region */ -+ return cxl_region_delete(region); -+} -+ -+static int do_region_xable(struct cxl_region *region, enum region_actions action) -+{ -+ switch (action) { -+ case ACTION_ENABLE: -+ return cxl_region_enable(region); -+ case ACTION_DISABLE: -+ return cxl_region_disable(region); -+ case ACTION_DESTROY: -+ return destroy_region(region); -+ default: -+ return -EINVAL; -+ } -+} -+ -+static int decoder_region_action(struct parsed_params *p, -+ struct cxl_decoder *decoder, -+ enum region_actions action, int *count) -+{ -+ struct cxl_region *region, *_r; -+ int rc = 0, err_rc = 0; -+ -+ cxl_region_foreach_safe (decoder, region, _r) { -+ int i, match = 0; -+ -+ for (i = 0; i < p->num_targets; i++) { -+ if (util_cxl_region_filter(region, p->targets[i])) { -+ match = 1; -+ break; -+ } -+ } -+ if (!match) -+ continue; -+ -+ rc = do_region_xable(region, action); -+ if (rc == 0) { -+ *count += 1; -+ } else { -+ log_err(&rl, "%s: failed: %s\n", -+ cxl_region_get_devname(region), strerror(-rc)); -+ err_rc = rc; -+ } -+ } -+ return err_rc ? err_rc : rc; -+} -+ - static int region_action(int argc, const char **argv, struct cxl_ctx *ctx, - enum region_actions action, - const struct option *options, struct parsed_params *p, - int *count, const char *u) - { -- int rc = -ENXIO; -+ int rc = 0, err_rc = 0; -+ struct cxl_bus *bus; - - log_init(&rl, "cxl region", "CXL_REGION_LOG"); - rc = parse_region_options(argc, argv, ctx, action, options, p, u); -@@ -534,6 +662,33 @@ static int region_action(int argc, const char **argv, struct cxl_ctx *ctx, - if (action == ACTION_CREATE) - return create_region(ctx, count, p); - -+ cxl_bus_foreach(ctx, bus) { -+ struct cxl_decoder *decoder; -+ struct cxl_port *port; -+ -+ if (!util_cxl_bus_filter(bus, param.bus)) -+ continue; -+ -+ port = cxl_bus_get_port(bus); -+ if (!cxl_port_is_root(port)) -+ continue; -+ -+ cxl_decoder_foreach (port, decoder) { -+ decoder = util_cxl_decoder_filter(decoder, -+ param.root_decoder); -+ if (!decoder) -+ continue; -+ rc = decoder_region_action(p, decoder, action, count); -+ if (rc) -+ err_rc = rc; -+ } -+ } -+ -+ if (err_rc) { -+ log_err(&rl, "one or more failures, last failure: %s\n", -+ strerror(-err_rc)); -+ return err_rc; -+ } - return rc; - } - -@@ -548,3 +703,39 @@ int cmd_create_region(int argc, const char **argv, struct cxl_ctx *ctx) - log_info(&rl, "created %d region%s\n", count, count == 1 ? "" : "s"); - return rc == 0 ? 0 : EXIT_FAILURE; - } -+ -+int cmd_enable_region(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ const char *u = "cxl enable-region ... []"; -+ struct parsed_params p = { 0 }; -+ int rc, count = 0; -+ -+ rc = region_action(argc, argv, ctx, ACTION_ENABLE, enable_options, &p, -+ &count, u); -+ log_info(&rl, "enabled %d region%s\n", count, count == 1 ? "" : "s"); -+ return rc == 0 ? 0 : EXIT_FAILURE; -+} -+ -+int cmd_disable_region(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ const char *u = "cxl disable-region ... []"; -+ struct parsed_params p = { 0 }; -+ int rc, count = 0; -+ -+ rc = region_action(argc, argv, ctx, ACTION_DISABLE, disable_options, &p, -+ &count, u); -+ log_info(&rl, "disabled %d region%s\n", count, count == 1 ? "" : "s"); -+ return rc == 0 ? 0 : EXIT_FAILURE; -+} -+ -+int cmd_destroy_region(int argc, const char **argv, struct cxl_ctx *ctx) -+{ -+ const char *u = "cxl destroy-region ... []"; -+ struct parsed_params p = { 0 }; -+ int rc, count = 0; -+ -+ rc = region_action(argc, argv, ctx, ACTION_DESTROY, destroy_options, &p, -+ &count, u); -+ log_info(&rl, "destroyed %d region%s\n", count, count == 1 ? "" : "s"); -+ return rc == 0 ? 0 : EXIT_FAILURE; -+} --- -2.27.0 - diff --git a/SOURCES/0197-cxl-list-make-memdevs-and-regions-the-default-listin.patch b/SOURCES/0197-cxl-list-make-memdevs-and-regions-the-default-listin.patch deleted file mode 100644 index d102e83..0000000 --- a/SOURCES/0197-cxl-list-make-memdevs-and-regions-the-default-listin.patch +++ /dev/null @@ -1,39 +0,0 @@ -From fade1a8039446ed1aa8656f49121886c71d221a4 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Mon, 15 Aug 2022 13:22:12 -0600 -Subject: [PATCH 197/217] cxl/list: make memdevs and regions the default - listing - -Instead of only listing regions by default (which can often be empty if -no regions have been configured), change the default listing mode to -both memdevs and regions. This will allow a plain 'cxl-list' to be a -quick health check of whether all the expected memdevs have enumerated -correctly, and see any regions that have been configured. - -Link: https://lore.kernel.org/r/20220815192214.545800-10-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/list.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/cxl/list.c b/cxl/list.c -index 88ca9d9..5f604ec 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -100,9 +100,10 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - param.regions = true; - } - -- /* List regions by default */ -+ /* List regions and memdevs by default */ - if (num_list_flags() == 0) { - param.regions = true; -+ param.memdevs = true; - } - - log_init(¶m.ctx, "cxl list", "CXL_LIST_LOG"); --- -2.27.0 - diff --git a/SOURCES/0198-test-add-a-cxl-create-region-test.patch b/SOURCES/0198-test-add-a-cxl-create-region-test.patch deleted file mode 100644 index 2001fad..0000000 --- a/SOURCES/0198-test-add-a-cxl-create-region-test.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 11ca099b52ec339b7464946db144e60399ffa344 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Mon, 15 Aug 2022 13:22:13 -0600 -Subject: [PATCH 198/217] test: add a cxl-create-region test - -Add a unit test to exercise the cxl-create-region command with different -combinations of memdevs and decoders, using cxl_test based mocked -devices. - -Link: https://lore.kernel.org/r/20220815192214.545800-11-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/cxl-create-region.sh | 125 ++++++++++++++++++++++++++++++++++++++ - test/meson.build | 2 + - 2 files changed, 127 insertions(+) - create mode 100644 test/cxl-create-region.sh - -diff --git a/test/cxl-create-region.sh b/test/cxl-create-region.sh -new file mode 100644 -index 0000000..66df38f ---- /dev/null -+++ b/test/cxl-create-region.sh -@@ -0,0 +1,125 @@ -+#!/bin/bash -+# SPDX-License-Identifier: GPL-2.0 -+# Copyright (C) 2022 Intel Corporation. All rights reserved. -+ -+. $(dirname $0)/common -+ -+rc=1 -+ -+set -ex -+ -+trap 'err $LINENO' ERR -+ -+check_prereq "jq" -+ -+modprobe -r cxl_test -+modprobe cxl_test -+udevadm settle -+ -+destroy_regions() -+{ -+ if [[ "$*" ]]; then -+ $CXL destroy-region -f -b cxl_test "$@" -+ else -+ $CXL destroy-region -f -b cxl_test all -+ fi -+} -+ -+create_x1_region() -+{ -+ mem="$1" -+ -+ # find a pmem capable root decoder for this mem -+ decoder=$($CXL list -b cxl_test -D -d root -m "$mem" | -+ jq -r ".[] | -+ select(.pmem_capable == true) | -+ select(.nr_targets == 1) | -+ .decoder") -+ -+ if [[ ! $decoder ]]; then -+ echo "no suitable decoder found for $mem, skipping" -+ return -+ fi -+ -+ # create region -+ region=$($CXL create-region -d "$decoder" -m "$mem" | jq -r ".region") -+ -+ if [[ ! $region ]]; then -+ echo "create-region failed for $decoder / $mem" -+ err "$LINENO" -+ fi -+ -+ # cycle disable/enable -+ $CXL disable-region --bus=cxl_test "$region" -+ $CXL enable-region --bus=cxl_test "$region" -+ -+ # cycle destroying and creating the same region -+ destroy_regions "$region" -+ region=$($CXL create-region -d "$decoder" -m "$mem" | jq -r ".region") -+ -+ if [[ ! $region ]]; then -+ echo "create-region failed for $decoder / $mem" -+ err "$LINENO" -+ fi -+ destroy_regions "$region" -+} -+ -+create_subregions() -+{ -+ slice=$((256 << 20)) -+ mem="$1" -+ -+ # find a pmem capable root decoder for this mem -+ decoder=$($CXL list -b cxl_test -D -d root -m "$mem" | -+ jq -r ".[] | -+ select(.pmem_capable == true) | -+ select(.nr_targets == 1) | -+ .decoder") -+ -+ if [[ ! $decoder ]]; then -+ echo "no suitable decoder found for $mem, skipping" -+ return -+ fi -+ -+ size="$($CXL list -m "$mem" | jq -r '.[].pmem_size')" -+ if [[ ! $size ]]; then -+ echo "$mem: unable to determine size" -+ err "$LINENO" -+ fi -+ -+ num_regions=$((size / slice)) -+ -+ declare -a regions -+ for (( i = 0; i < num_regions; i++ )); do -+ regions[$i]=$($CXL create-region -d "$decoder" -m "$mem" -s "$slice" | jq -r ".region") -+ if [[ ! ${regions[$i]} ]]; then -+ echo "create sub-region failed for $decoder / $mem" -+ err "$LINENO" -+ fi -+ udevadm settle -+ done -+ -+ echo "created $num_regions subregions:" -+ for (( i = 0; i < num_regions; i++ )); do -+ echo "${regions[$i]}" -+ done -+ -+ for (( i = (num_regions - 1); i >= 0; i-- )); do -+ destroy_regions "${regions[$i]}" -+ done -+} -+ -+# test reading labels directly through cxl-cli -+readarray -t mems < <("$CXL" list -b cxl_test -M | jq -r '.[].memdev') -+ -+for mem in ${mems[@]}; do -+ create_x1_region "$mem" -+done -+ -+# test multiple subregions under the same decoder, using slices of the same memdev -+# to test out back-to-back pmem DPA allocations on memdevs -+for mem in ${mems[@]}; do -+ create_subregions "$mem" -+done -+ -+modprobe -r cxl_test -diff --git a/test/meson.build b/test/meson.build -index b382f46..5953c28 100644 ---- a/test/meson.build -+++ b/test/meson.build -@@ -153,6 +153,7 @@ track_uuid = find_program('track-uuid.sh') - cxl_topo = find_program('cxl-topology.sh') - cxl_sysfs = find_program('cxl-region-sysfs.sh') - cxl_labels = find_program('cxl-labels.sh') -+cxl_create_region = find_program('cxl-create-region.sh') - - tests = [ - [ 'libndctl', libndctl, 'ndctl' ], -@@ -180,6 +181,7 @@ tests = [ - [ 'cxl-topology.sh', cxl_topo, 'cxl' ], - [ 'cxl-region-sysfs.sh', cxl_sysfs, 'cxl' ], - [ 'cxl-labels.sh', cxl_labels, 'cxl' ], -+ [ 'cxl-create-region.sh', cxl_create_region, 'cxl' ], - ] - - if get_option('destructive').enabled() --- -2.27.0 - diff --git a/SOURCES/0199-cxl-decoder-add-a-max_available_extent-attribute.patch b/SOURCES/0199-cxl-decoder-add-a-max_available_extent-attribute.patch deleted file mode 100644 index c56487e..0000000 --- a/SOURCES/0199-cxl-decoder-add-a-max_available_extent-attribute.patch +++ /dev/null @@ -1,240 +0,0 @@ -From bf0c44e79c0db04b0c1eea884022dfbdc011b979 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Mon, 15 Aug 2022 13:22:14 -0600 -Subject: [PATCH 199/217] cxl/decoder: add a max_available_extent attribute - -Add a max_available_extent attribute to cxl_decoder. In order to aid in -its calculation, change the order of regions in the root decoder's list -to be sorted by start HPA of the region. - -Additionally, emit this attribute in decoder listings, and consult it -for available space before creating a new region. - -Link: https://lore.kernel.org/r/20220815192214.545800-12-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/json.c | 8 +++++ - cxl/lib/libcxl.c | 84 +++++++++++++++++++++++++++++++++++++++++++++- - cxl/lib/libcxl.sym | 1 + - cxl/lib/private.h | 1 + - cxl/libcxl.h | 3 ++ - cxl/region.c | 14 +++++++- - 6 files changed, 109 insertions(+), 2 deletions(-) - -diff --git a/cxl/json.c b/cxl/json.c -index 9dc99df..9cec58b 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -499,6 +499,14 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - } - - if (cxl_port_is_root(port) && cxl_decoder_is_mem_capable(decoder)) { -+ size = cxl_decoder_get_max_available_extent(decoder); -+ if (size < ULLONG_MAX) { -+ jobj = util_json_object_size(size, flags); -+ if (jobj) -+ json_object_object_add(jdecoder, -+ "max_available_extent", -+ jobj); -+ } - if (cxl_decoder_is_pmem_capable(decoder)) { - jobj = json_object_new_boolean(true); - if (jobj) -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index fd2ea4f..c7dc2b0 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -455,6 +455,16 @@ CXL_EXPORT int cxl_region_delete(struct cxl_region *region) - return 0; - } - -+static int region_start_cmp(struct cxl_region *r1, struct cxl_region *r2) -+{ -+ if (r1->start == r2->start) -+ return 0; -+ else if (r1->start < r2->start) -+ return -1; -+ else -+ return 1; -+} -+ - static void *add_cxl_region(void *parent, int id, const char *cxlregion_base) - { - const char *devname = devpath_to_devname(cxlregion_base); -@@ -539,7 +549,7 @@ static void *add_cxl_region(void *parent, int id, const char *cxlregion_base) - break; - } - -- list_add(&decoder->regions, ®ion->list); -+ list_add_sorted(&decoder->regions, region, list, region_start_cmp); - - return region; - err: -@@ -1618,6 +1628,70 @@ cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint) - return NULL; - } - -+static bool cxl_region_is_configured(struct cxl_region *region) -+{ -+ return region->size && (region->decode_state != CXL_DECODE_RESET); -+} -+ -+/** -+ * cxl_decoder_calc_max_available_extent() - calculate max available free space -+ * @decoder - the root decoder to calculate the free extents for -+ * -+ * The add_cxl_region() function adds regions to the parent decoder's list -+ * sorted by the region's start HPAs. It can also be assumed that regions have -+ * no overlapped / aliased HPA space. Therefore, calculating each extent is as -+ * simple as walking the region list in order, and subtracting the previous -+ * region's end HPA from the next region's start HPA (and taking into account -+ * the decoder's start and end HPAs as well). -+ */ -+static unsigned long long -+cxl_decoder_calc_max_available_extent(struct cxl_decoder *decoder) -+{ -+ u64 prev_end, decoder_end, cur_extent, max_extent = 0; -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ struct cxl_region *region; -+ -+ if (!cxl_port_is_root(port)) { -+ err(ctx, "%s: not a root decoder\n", -+ cxl_decoder_get_devname(decoder)); -+ return ULLONG_MAX; -+ } -+ -+ /* -+ * Preload prev_end with an imaginary region that ends just before -+ * the decoder's start, so that the extent calculation for the -+ * first region Just Works -+ */ -+ prev_end = decoder->start - 1; -+ -+ cxl_region_foreach(decoder, region) { -+ if (!cxl_region_is_configured(region)) -+ continue; -+ -+ /* -+ * region->start - prev_end would get the difference in -+ * addresses, but a difference of 1 in addresses implies -+ * an extent of 0. Hence the '-1'. -+ */ -+ cur_extent = region->start - prev_end - 1; -+ max_extent = max(max_extent, cur_extent); -+ prev_end = region->start + region->size - 1; -+ } -+ -+ /* -+ * Finally, consider the extent after the last region, up to the end -+ * of the decoder's address space, if any. If there were no regions, -+ * this simply reduces to decoder->size. -+ * Subtracting two addrs gets us a 'size' directly, no need for +/- 1. -+ */ -+ decoder_end = decoder->start + decoder->size - 1; -+ cur_extent = decoder_end - prev_end; -+ max_extent = max(max_extent, cur_extent); -+ -+ return max_extent; -+} -+ - static int decoder_id_cmp(struct cxl_decoder *d1, struct cxl_decoder *d2) - { - return d1->id - d2->id; -@@ -1748,6 +1822,8 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) - if (sysfs_read_attr(ctx, path, buf) == 0) - *(flag->flag) = !!strtoul(buf, NULL, 0); - } -+ decoder->max_available_extent = -+ cxl_decoder_calc_max_available_extent(decoder); - break; - } - } -@@ -1912,6 +1988,12 @@ cxl_decoder_get_dpa_size(struct cxl_decoder *decoder) - return decoder->dpa_size; - } - -+CXL_EXPORT unsigned long long -+cxl_decoder_get_max_available_extent(struct cxl_decoder *decoder) -+{ -+ return decoder->max_available_extent; -+} -+ - CXL_EXPORT int cxl_decoder_set_dpa_size(struct cxl_decoder *decoder, - unsigned long long size) - { -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index cb23a0b..549f88d 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -213,4 +213,5 @@ global: - cxl_decoder_get_memdev; - cxl_decoder_get_interleave_granularity; - cxl_decoder_get_interleave_ways; -+ cxl_decoder_get_max_available_extent; - } LIBCXL_2; -diff --git a/cxl/lib/private.h b/cxl/lib/private.h -index 8bc9620..437eade 100644 ---- a/cxl/lib/private.h -+++ b/cxl/lib/private.h -@@ -104,6 +104,7 @@ struct cxl_decoder { - u64 size; - u64 dpa_resource; - u64 dpa_size; -+ u64 max_available_extent; - void *dev_buf; - size_t buf_len; - char *dev_path; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 69d9c09..61c7fc4 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -134,6 +134,9 @@ unsigned long long cxl_decoder_get_resource(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_dpa_resource(struct cxl_decoder *decoder); - unsigned long long cxl_decoder_get_dpa_size(struct cxl_decoder *decoder); -+unsigned long long -+cxl_decoder_get_max_available_extent(struct cxl_decoder *decoder); -+ - enum cxl_decoder_mode { - CXL_DECODER_MODE_NONE, - CXL_DECODER_MODE_MIXED, -diff --git a/cxl/region.c b/cxl/region.c -index b22d3c8..a30313c 100644 ---- a/cxl/region.c -+++ b/cxl/region.c -@@ -438,9 +438,9 @@ static int create_region(struct cxl_ctx *ctx, int *count, - struct json_object *jregion; - unsigned int i, granularity; - struct cxl_region *region; -+ u64 size, max_extent; - const char *devname; - uuid_t uuid; -- u64 size; - int rc; - - rc = create_region_validate_config(ctx, p); -@@ -455,6 +455,18 @@ static int create_region(struct cxl_ctx *ctx, int *count, - log_err(&rl, "%s: unable to determine region size\n", __func__); - return -ENXIO; - } -+ max_extent = cxl_decoder_get_max_available_extent(p->root_decoder); -+ if (max_extent == ULLONG_MAX) { -+ log_err(&rl, "%s: unable to determine max extent\n", -+ cxl_decoder_get_devname(p->root_decoder)); -+ return -EINVAL; -+ } -+ if (size > max_extent) { -+ log_err(&rl, -+ "%s: region size %#lx exceeds max available space\n", -+ cxl_decoder_get_devname(p->root_decoder), size); -+ return -ENOSPC; -+ } - - if (p->mode == CXL_DECODER_MODE_PMEM) { - region = cxl_decoder_create_pmem_region(p->root_decoder); --- -2.27.0 - diff --git a/SOURCES/0200-cxl-Add-list-verbose-option-to-the-cxl-command.patch b/SOURCES/0200-cxl-Add-list-verbose-option-to-the-cxl-command.patch deleted file mode 100644 index e13bb11..0000000 --- a/SOURCES/0200-cxl-Add-list-verbose-option-to-the-cxl-command.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 8b61e8e75443d79d22bf6e74e6b0e36acdd605c3 Mon Sep 17 00:00:00 2001 -From: Matthew Ho -Date: Fri, 12 Aug 2022 15:15:53 -0700 -Subject: [PATCH 200/217] cxl: Add list verbose option to the cxl command - -This adds the new subcommands cxl list -v, cxl list -vv, and cxl list -vvv. - -cxl list -v is now equivalent to cxl list -RMBDPT, cxl list -vv is -equivalent to cxl list -RMBDPTi, and cxl list -vvv is equivalent to -cxl list -RMBDPTiHI. These additions make it easier to list all of the CXL -devices without having to remember which subcommand must be appended for each -type of device. - -Link: https://lore.kernel.org/r/20220812221553.92278-1-sunfishho12@gmail.com -Reviewed-by: Adam Manzanares -Reviewed-by: Dan Williams -Acked-by: Davidlohr Bueso -Signed-off-by: Matthew Ho -Signed-off-by: Vishal Verma ---- - Documentation/cxl/cxl-list.txt | 18 ++++++++++++++++++ - cxl/filter.h | 1 + - cxl/list.c | 21 +++++++++++++++++++++ - 3 files changed, 40 insertions(+) - -diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt -index b88940a..14a2b4b 100644 ---- a/Documentation/cxl/cxl-list.txt -+++ b/Documentation/cxl/cxl-list.txt -@@ -344,6 +344,24 @@ OPTIONS - --region:: - Specify CXL region device name(s), or device id(s), to filter the listing. - -+-v:: -+--verbose:: -+ Increase verbosity of the output. This can be specified -+ multiple times to be even more verbose on the -+ informational and miscellaneous output, and can be used -+ to override omitted flags for showing specific -+ information. Note that cxl list --verbose --verbose is -+ equivalent to cxl list -vv. -+ - *-v* -+ Enable --memdevs, --regions, --buses, -+ --ports, --decoders, and --targets. -+ - *-vv* -+ Everything *-v* provides, plus include disabled -+ devices with --idle. -+ - *-vvv* -+ Everything *-vv* provides, plus enable -+ --health and --partition. -+ - --debug:: - If the cxl tool was built with debug enabled, turn on debug - messages. -diff --git a/cxl/filter.h b/cxl/filter.h -index d22d8b1..256df49 100644 ---- a/cxl/filter.h -+++ b/cxl/filter.h -@@ -26,6 +26,7 @@ struct cxl_filter_params { - bool human; - bool health; - bool partition; -+ int verbose; - struct log_ctx ctx; - }; - -diff --git a/cxl/list.c b/cxl/list.c -index 5f604ec..8c48fbb 100644 ---- a/cxl/list.c -+++ b/cxl/list.c -@@ -52,6 +52,8 @@ static const struct option options[] = { - "include memory device health information"), - OPT_BOOLEAN('I', "partition", ¶m.partition, - "include memory device partition information"), -+ OPT_INCR('v', "verbose", ¶m.verbose, -+ "increase output detail"), - #ifdef ENABLE_DEBUG - OPT_BOOLEAN(0, "debug", &debug, "debug list walk"), - #endif -@@ -106,6 +108,25 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx) - param.memdevs = true; - } - -+ switch(param.verbose){ -+ default: -+ case 3: -+ param.health = true; -+ param.partition = true; -+ /* fallthrough */ -+ case 2: -+ param.idle = true; -+ /* fallthrough */ -+ case 1: -+ param.buses = true; -+ param.ports = true; -+ param.decoders = true; -+ param.targets = true; -+ /*fallthrough*/ -+ case 0: -+ break; -+ } -+ - log_init(¶m.ctx, "cxl list", "CXL_LIST_LOG"); - if (debug) { - cxl_set_log_priority(ctx, LOG_DEBUG); --- -2.27.0 - diff --git a/SOURCES/0201-cxl-test-Validate-endpoint-interleave-geometry.patch b/SOURCES/0201-cxl-test-Validate-endpoint-interleave-geometry.patch deleted file mode 100644 index bd1f867..0000000 --- a/SOURCES/0201-cxl-test-Validate-endpoint-interleave-geometry.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 05a60dc4992bc4698ceff8e6737192ed818e7e34 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Fri, 5 Aug 2022 13:37:56 -0700 -Subject: [PATCH 201/217] cxl/test: Validate endpoint interleave geometry - -Check that endpoint interleave geometry settings are updated once the -endpoint decoders are associated with a region. - -Link: https://lore.kernel.org/r/165973187660.1528532.13832323649814892720.stgit@dwillia2-xfh.jf.intel.com -Reported-by: Jonathan Cameron -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/cxl-region-sysfs.sh | 20 ++++++++++++++++++-- - 1 file changed, 18 insertions(+), 2 deletions(-) - -diff --git a/test/cxl-region-sysfs.sh b/test/cxl-region-sysfs.sh -index 2582edb..110e037 100644 ---- a/test/cxl-region-sysfs.sh -+++ b/test/cxl-region-sysfs.sh -@@ -44,8 +44,8 @@ uuidgen > /sys/bus/cxl/devices/$region/uuid - # setup interleave geometry - nr_targets=${#endpoint[@]} - echo $nr_targets > /sys/bus/cxl/devices/$region/interleave_ways --g=$(cat /sys/bus/cxl/devices/$decoder/interleave_granularity) --echo $g > /sys/bus/cxl/devices/$region/interleave_granularity -+r_ig=$(cat /sys/bus/cxl/devices/$decoder/interleave_granularity) -+echo $r_ig > /sys/bus/cxl/devices/$region/interleave_granularity - echo $((nr_targets * (256<<20))) > /sys/bus/cxl/devices/$region/size - - # grab the list of memdevs grouped by host-bridge interleave position -@@ -96,6 +96,22 @@ do - done - echo "$region added ${#endpoint[@]} targets: ${endpoint[@]}" - -+# validate all endpoint decoders have the correct setting -+region_size=$(cat /sys/bus/cxl/devices/$region/size) -+region_base=$(cat /sys/bus/cxl/devices/$region/resource) -+for i in ${endpoint[@]} -+do -+ iw=$(cat /sys/bus/cxl/devices/$i/interleave_ways) -+ ig=$(cat /sys/bus/cxl/devices/$i/interleave_granularity) -+ [ $iw -ne $nr_targets ] && err "$LINENO: decoder: $i iw: $iw targets: $nr_targets" -+ [ $ig -ne $r_ig] && err "$LINENO: decoder: $i ig: $ig root ig: $r_ig" -+ -+ sz=$(cat /sys/bus/cxl/devices/$i/size) -+ res=$(cat /sys/bus/cxl/devices/$i/start) -+ [ $sz -ne $region_size ] && err "$LINENO: decoder: $i sz: $sz region_size: $region_size" -+ [ $res -ne $region_base ] && err "$LINENO: decoder: $i base: $res region_base: $region_base" -+done -+ - # walk up the topology and commit all decoders - echo 1 > /sys/bus/cxl/devices/$region/commit - --- -2.27.0 - diff --git a/SOURCES/0202-cxl-list-Add-interleave-parameters-to-decoder-listin.patch b/SOURCES/0202-cxl-list-Add-interleave-parameters-to-decoder-listin.patch deleted file mode 100644 index 178b93b..0000000 --- a/SOURCES/0202-cxl-list-Add-interleave-parameters-to-decoder-listin.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0ee9ca3f6423a2af8ade983f596274f6fcfe66d6 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Fri, 5 Aug 2022 13:38:03 -0700 -Subject: [PATCH 202/217] cxl/list: Add interleave parameters to decoder - listings - -Emit interleave_ways and interleave_granularity in decoder output. - -Link: https://lore.kernel.org/r/165973188300.1528532.222988685552982872.stgit@dwillia2-xfh.jf.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/json.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/cxl/json.c b/cxl/json.c -index 9cec58b..ada1dbe 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -466,6 +466,26 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - json_object_object_add(jdecoder, "size", jobj); - } - -+ val = cxl_decoder_get_interleave_ways(decoder); -+ if (val < UINT_MAX) { -+ jobj = json_object_new_int(val); -+ if (jobj) -+ json_object_object_add(jdecoder, "interleave_ways", -+ jobj); -+ -+ /* granularity is a don't care if not interleaving */ -+ if (val > 1) { -+ val = cxl_decoder_get_interleave_granularity(decoder); -+ if (val < UINT_MAX) { -+ jobj = json_object_new_int(val); -+ if (jobj) -+ json_object_object_add( -+ jdecoder, -+ "interleave_granularity", jobj); -+ } -+ } -+ } -+ - if (size == 0) { - jobj = json_object_new_string("disabled"); - if (jobj) --- -2.27.0 - diff --git a/SOURCES/0203-cxl-list-Add-region-to-decoder-listings.patch b/SOURCES/0203-cxl-list-Add-region-to-decoder-listings.patch deleted file mode 100644 index 40e819a..0000000 --- a/SOURCES/0203-cxl-list-Add-region-to-decoder-listings.patch +++ /dev/null @@ -1,140 +0,0 @@ -From dba61cf8bb9bb96cde8dcf2c9a2dcc663074698b Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Fri, 5 Aug 2022 13:38:08 -0700 -Subject: [PATCH 203/217] cxl/list: Add region to decoder listings - -While decoders can be matched with regions by physical address, or filtered -by region, it is also useful to get a plain listing of the association. - -Link: https://lore.kernel.org/r/165973188860.1528532.17427805440366364536.stgit@dwillia2-xfh.jf.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/lib/libcxl.txt | 7 +++++++ - cxl/json.c | 8 ++++++++ - cxl/lib/libcxl.c | 34 ++++++++++++++++++++++++++++++++ - cxl/lib/libcxl.sym | 1 + - cxl/libcxl.h | 1 + - 5 files changed, 51 insertions(+) - -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 50b0c9c..6756d2f 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -398,6 +398,7 @@ int cxl_decoder_set_dpa_size(struct cxl_decoder *decoder, unsigned long long siz - const char *cxl_decoder_get_devname(struct cxl_decoder *decoder); - int cxl_decoder_get_id(struct cxl_decoder *decoder); - int cxl_decoder_get_nr_targets(struct cxl_decoder *decoder); -+struct cxl_region *cxl_decoder_get_region(struct cxl_decoder *decoder); - - enum cxl_decoder_target_type { - CXL_DECODER_TTYPE_UNKNOWN, -@@ -446,6 +447,12 @@ Platform firmware may setup the CXL decode hierarchy before the OS - boots, and may additionally require that the OS not change the decode - settings. This property is indicated by the cxl_decoder_is_locked() API. - -+When a decoder is associated with a region cxl_decoder_get_region() -+returns that region object. Note that it is only applicable to switch -+and endpoint decoders as root decoders have a 1:N relationship with -+regions. Use cxl_region_foreach() for the similar functionality for -+root decoders. -+ - ==== TARGETS - A root or switch level decoder takes an SPA (system-physical-address) as - input and routes it to a downstream port. Which downstream port depends -diff --git a/cxl/json.c b/cxl/json.c -index ada1dbe..c3d9299 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -442,6 +442,7 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - const char *devname = cxl_decoder_get_devname(decoder); - struct cxl_port *port = cxl_decoder_get_port(decoder); - struct json_object *jdecoder, *jobj; -+ struct cxl_region *region; - u64 val, size; - - jdecoder = json_object_new_object(); -@@ -486,6 +487,13 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, - } - } - -+ region = cxl_decoder_get_region(decoder); -+ if (region) { -+ jobj = json_object_new_string(cxl_region_get_devname(region)); -+ if (jobj) -+ json_object_object_add(jdecoder, "region", jobj); -+ } -+ - if (size == 0) { - jobj = json_object_new_string("disabled"); - if (jobj) -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index c7dc2b0..ff85b23 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -2124,6 +2124,40 @@ cxl_decoder_get_interleave_ways(struct cxl_decoder *decoder) - return decoder->interleave_ways; - } - -+CXL_EXPORT struct cxl_region * -+cxl_decoder_get_region(struct cxl_decoder *decoder) -+{ -+ struct cxl_port *port = cxl_decoder_get_port(decoder); -+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder); -+ char *path = decoder->dev_buf; -+ char buf[SYSFS_ATTR_SIZE]; -+ struct cxl_region *region; -+ struct cxl_decoder *iter; -+ int rc; -+ -+ if (cxl_port_is_root(port)) -+ return NULL; -+ -+ sprintf(path, "%s/region", decoder->dev_path); -+ rc = sysfs_read_attr(ctx, path, buf); -+ if (rc < 0) { -+ err(ctx, "failed to read region name: %s\n", strerror(-rc)); -+ return NULL; -+ } -+ -+ if (strcmp(buf, "") == 0) -+ return NULL; -+ -+ while (!cxl_port_is_root(port)) -+ port = cxl_port_get_parent(port); -+ -+ cxl_decoder_foreach(port, iter) -+ cxl_region_foreach(iter, region) -+ if (strcmp(cxl_region_get_devname(region), buf) == 0) -+ return region; -+ return NULL; -+} -+ - CXL_EXPORT struct cxl_region * - cxl_decoder_create_pmem_region(struct cxl_decoder *decoder) - { -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 549f88d..385a8f0 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -214,4 +214,5 @@ global: - cxl_decoder_get_interleave_granularity; - cxl_decoder_get_interleave_ways; - cxl_decoder_get_max_available_extent; -+ cxl_decoder_get_region; - } LIBCXL_2; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 61c7fc4..2498fa1 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -201,6 +201,7 @@ bool cxl_decoder_is_locked(struct cxl_decoder *decoder); - unsigned int - cxl_decoder_get_interleave_granularity(struct cxl_decoder *decoder); - unsigned int cxl_decoder_get_interleave_ways(struct cxl_decoder *decoder); -+struct cxl_region *cxl_decoder_get_region(struct cxl_decoder *decoder); - struct cxl_region *cxl_decoder_create_pmem_region(struct cxl_decoder *decoder); - struct cxl_decoder *cxl_decoder_get_by_name(struct cxl_ctx *ctx, - const char *ident); --- -2.27.0 - diff --git a/SOURCES/0204-cxl-list-Filter-decoders-by-region.patch b/SOURCES/0204-cxl-list-Filter-decoders-by-region.patch deleted file mode 100644 index 021622a..0000000 --- a/SOURCES/0204-cxl-list-Filter-decoders-by-region.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 81ad0ed44690596a846ac39da0b2fd966973fc21 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Fri, 5 Aug 2022 13:38:14 -0700 -Subject: [PATCH 204/217] cxl/list: Filter decoders by region - -With a region name in hand, it is useful to be able to filter all the -decoders in the topology that are mapping that region. - -Link: https://lore.kernel.org/r/165973189465.1528532.9072953032089147905.stgit@dwillia2-xfh.jf.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/filter.c | 23 +++++++++++++++++++++++ - 1 file changed, 23 insertions(+) - -diff --git a/cxl/filter.c b/cxl/filter.c -index 38ece55..9a3de8c 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -652,6 +652,26 @@ struct cxl_region *util_cxl_region_filter(struct cxl_region *region, - - } - -+static struct cxl_decoder * -+util_cxl_decoder_filter_by_region(struct cxl_decoder *decoder, -+ const char *__ident) -+{ -+ struct cxl_region *region; -+ -+ if (!__ident) -+ return decoder; -+ -+ region = cxl_decoder_get_region(decoder); -+ if (!region) -+ return NULL; -+ -+ region = util_cxl_region_filter(region, __ident); -+ if (!region) -+ return NULL; -+ -+ return decoder; -+} -+ - static unsigned long params_to_flags(struct cxl_filter_params *param) - { - unsigned long flags = 0; -@@ -790,6 +810,9 @@ static void walk_decoders(struct cxl_port *port, struct cxl_filter_params *p, - if (!util_cxl_decoder_filter_by_memdev( - decoder, p->memdev_filter, p->serial_filter)) - goto walk_children; -+ if (!util_cxl_decoder_filter_by_region(decoder, -+ p->region_filter)) -+ goto walk_children; - if (!p->idle && cxl_decoder_get_size(decoder) == 0) - continue; - jdecoder = util_cxl_decoder_to_json(decoder, flags); --- -2.27.0 - diff --git a/SOURCES/0205-cxl-list-Add-depth-to-port-listings.patch b/SOURCES/0205-cxl-list-Add-depth-to-port-listings.patch deleted file mode 100644 index 69f483b..0000000 --- a/SOURCES/0205-cxl-list-Add-depth-to-port-listings.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 2ceddb91d3a0d70a59242b3a9dab401be6e5c825 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Fri, 5 Aug 2022 13:38:20 -0700 -Subject: [PATCH 205/217] cxl/list: Add 'depth' to port listings - -Simplify the task of determining how deep a port is in the hierarchy by -just emitting what libcxl already counted. This is useful for validating -interleave math. - -Link: https://lore.kernel.org/r/165973190022.1528532.6351628365510289908.stgit@dwillia2-xfh.jf.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - Documentation/cxl/lib/libcxl.txt | 1 + - cxl/json.c | 4 ++++ - cxl/lib/libcxl.c | 5 +++++ - cxl/lib/libcxl.sym | 1 + - cxl/libcxl.h | 1 + - 5 files changed, 12 insertions(+) - -diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt -index 6756d2f..fd2962a 100644 ---- a/Documentation/cxl/lib/libcxl.txt -+++ b/Documentation/cxl/lib/libcxl.txt -@@ -290,6 +290,7 @@ int cxl_port_is_enabled(struct cxl_port *port); - bool cxl_port_is_root(struct cxl_port *port); - bool cxl_port_is_switch(struct cxl_port *port); - bool cxl_port_is_endpoint(struct cxl_port *port); -+int cxl_port_get_depth(struct cxl_port *port); - bool cxl_port_hosts_memdev(struct cxl_port *port, struct cxl_memdev *memdev); - int cxl_port_get_nr_dports(struct cxl_port *port); - ---- -diff --git a/cxl/json.c b/cxl/json.c -index c3d9299..63c1751 100644 ---- a/cxl/json.c -+++ b/cxl/json.c -@@ -769,6 +769,10 @@ static struct json_object *__util_cxl_port_to_json(struct cxl_port *port, - if (jobj) - json_object_object_add(jport, "host", jobj); - -+ jobj = json_object_new_int(cxl_port_get_depth(port)); -+ if (jobj) -+ json_object_object_add(jport, "depth", jobj); -+ - if (!cxl_port_is_enabled(port)) { - jobj = json_object_new_string("disabled"); - if (jobj) -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index ff85b23..021d59f 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -2417,6 +2417,11 @@ CXL_EXPORT bool cxl_port_is_endpoint(struct cxl_port *port) - return port->type == CXL_PORT_ENDPOINT; - } - -+CXL_EXPORT int cxl_port_get_depth(struct cxl_port *port) -+{ -+ return port->depth; -+} -+ - CXL_EXPORT struct cxl_bus *cxl_port_get_bus(struct cxl_port *port) - { - struct cxl_bus *bus; -diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym -index 385a8f0..8bb91e0 100644 ---- a/cxl/lib/libcxl.sym -+++ b/cxl/lib/libcxl.sym -@@ -96,6 +96,7 @@ global: - cxl_port_get_parent; - cxl_port_is_root; - cxl_port_is_switch; -+ cxl_port_get_depth; - cxl_port_to_bus; - cxl_port_is_endpoint; - cxl_port_to_endpoint; -diff --git a/cxl/libcxl.h b/cxl/libcxl.h -index 2498fa1..9fe4e99 100644 ---- a/cxl/libcxl.h -+++ b/cxl/libcxl.h -@@ -90,6 +90,7 @@ int cxl_port_is_enabled(struct cxl_port *port); - struct cxl_port *cxl_port_get_parent(struct cxl_port *port); - bool cxl_port_is_root(struct cxl_port *port); - bool cxl_port_is_switch(struct cxl_port *port); -+int cxl_port_get_depth(struct cxl_port *port); - struct cxl_bus *cxl_port_to_bus(struct cxl_port *port); - bool cxl_port_is_endpoint(struct cxl_port *port); - struct cxl_endpoint *cxl_port_to_endpoint(struct cxl_port *port); --- -2.27.0 - diff --git a/SOURCES/0206-cxl-test-Validate-switch-port-settings-in-cxl-region.patch b/SOURCES/0206-cxl-test-Validate-switch-port-settings-in-cxl-region.patch deleted file mode 100644 index e8ceadf..0000000 --- a/SOURCES/0206-cxl-test-Validate-switch-port-settings-in-cxl-region.patch +++ /dev/null @@ -1,63 +0,0 @@ -From bcc9897b38be91df38f81fb3105d2351f7941377 Mon Sep 17 00:00:00 2001 -From: Dan Williams -Date: Fri, 5 Aug 2022 13:38:26 -0700 -Subject: [PATCH 206/217] cxl/test: Validate switch port settings in - cxl-region-sysfs.sh - -A recent kernel fix to add the missing update of endpoint decoder HPA range -settings regressed switch decoder HPA range settings. Add validation for -switch port settings to avoid regressions like that going forward. - -Link: https://lore.kernel.org/r/165973190625.1528532.12244196912617964754.stgit@dwillia2-xfh.jf.intel.com -Signed-off-by: Dan Williams -Signed-off-by: Vishal Verma ---- - test/cxl-region-sysfs.sh | 32 ++++++++++++++++++++++++++++++++ - 1 file changed, 32 insertions(+) - -diff --git a/test/cxl-region-sysfs.sh b/test/cxl-region-sysfs.sh -index 110e037..ae0f556 100644 ---- a/test/cxl-region-sysfs.sh -+++ b/test/cxl-region-sysfs.sh -@@ -112,6 +112,38 @@ do - [ $res -ne $region_base ] && err "$LINENO: decoder: $i base: $res region_base: $region_base" - done - -+# validate all switch decoders have the correct settings -+nr_switches=$((nr_targets/2)) -+nr_host_bridges=$((nr_switches/2)) -+nr_switch_decoders=$((nr_switches + nr_host_bridges)) -+ -+json=$($CXL list -D -r $region -d switch) -+readarray -t switch_decoders < <(echo $json | jq -r ".[].decoder") -+ -+[ ${#switch_decoders[@]} -ne $nr_switch_decoders ] && err \ -+"$LINENO: expected $nr_switch_decoders got ${#switch_decoders[@]} switch decoders" -+ -+for i in ${switch_decoders[@]} -+do -+ decoder=$(echo $json | jq -r ".[] | select(.decoder == \"$i\")") -+ id=${i#decoder} -+ port_id=${id%.*} -+ depth=$($CXL list -p $port_id -S | jq -r ".[].depth") -+ iw=$(echo $decoder | jq -r ".interleave_ways") -+ ig=$(echo $decoder | jq -r ".interleave_granularity") -+ -+ [ $iw -ne 2 ] && err "$LINENO: decoder: $i iw: $iw targets: 2" -+ [ $ig -ne $((r_ig << depth)) ] && err \ -+ "$LINENO: decoder: $i ig: $ig switch_ig: $((r_ig << depth))" -+ -+ res=$(echo $decoder | jq -r ".resource") -+ sz=$(echo $decoder | jq -r ".size") -+ [ $sz -ne $region_size ] && err \ -+ "$LINENO: decoder: $i sz: $sz region_size: $region_size" -+ [ $res -ne $region_base ] && err \ -+ "$LINENO: decoder: $i base: $res region_base: $region_base" -+done -+ - # walk up the topology and commit all decoders - echo 1 > /sys/bus/cxl/devices/$region/commit - --- -2.27.0 - diff --git a/SOURCES/0207-meson-fix-modprobedatadir-default-value.patch b/SOURCES/0207-meson-fix-modprobedatadir-default-value.patch deleted file mode 100644 index 64cf175..0000000 --- a/SOURCES/0207-meson-fix-modprobedatadir-default-value.patch +++ /dev/null @@ -1,34 +0,0 @@ -From ed56d6053c532f43a8bbd109a87e754a43def845 Mon Sep 17 00:00:00 2001 -From: Miguel Bernal Marin -Date: Thu, 11 Aug 2022 19:36:53 -0500 -Subject: [PATCH 207/217] meson: fix modprobedatadir default value - -The modprobedatadir is now set as a meson option, but without a -default value. - -Set the default value if modprobedatadir is not set. - -Link: https://lore.kernel.org/r/20220812003653.53992-1-miguel.bernal.marin@linux.intel.com -Fixes: 524ad09d5eda ("meson: make modprobedatadir an option") -Reviewed-by: Dan Williams -Signed-off-by: Miguel Bernal Marin -Signed-off-by: Vishal Verma ---- - contrib/meson.build | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/contrib/meson.build b/contrib/meson.build -index ad63a50..48aa7c0 100644 ---- a/contrib/meson.build -+++ b/contrib/meson.build -@@ -26,6 +26,6 @@ endif - - modprobedatadir = get_option('modprobedatadir') - if modprobedatadir == '' -- modprobedatadir = get_option('modprobedatadir') -+ modprobedatadir = sysconfdir + '/modprobe.d/' - endif - install_data('nvdimm-security.conf', install_dir : modprobedatadir) --- -2.27.0 - diff --git a/SOURCES/0208-ndctl-move-developer-scripts-from-contrib-to-scripts.patch b/SOURCES/0208-ndctl-move-developer-scripts-from-contrib-to-scripts.patch deleted file mode 100644 index 757548b..0000000 --- a/SOURCES/0208-ndctl-move-developer-scripts-from-contrib-to-scripts.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 6f8695fdda4aa8889d2f335e785efb9bfeaef6c5 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Wed, 15 Jun 2022 16:48:09 -0600 -Subject: [PATCH 208/217] ndctl: move developer scripts from contrib/ to - scripts/ - -Allow for scripts/ to be the defacto location for scripts and tooling -that may be useful for developers of ndctl, but isn't distributed or -installed. Move such scripts currently in contrib/ to scripts/. - -Link: https://lore.kernel.org/r/20220615224813.523053-2-vishal.l.verma@intel.com -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - {contrib => scripts}/daxctl-qemu-hmat-setup | 0 - {contrib => scripts}/do_abidiff | 0 - {contrib => scripts}/prepare-release.sh | 2 +- - 3 files changed, 1 insertion(+), 1 deletion(-) - rename {contrib => scripts}/daxctl-qemu-hmat-setup (100%) - rename {contrib => scripts}/do_abidiff (100%) - rename {contrib => scripts}/prepare-release.sh (99%) - -diff --git a/contrib/daxctl-qemu-hmat-setup b/scripts/daxctl-qemu-hmat-setup -similarity index 100% -rename from contrib/daxctl-qemu-hmat-setup -rename to scripts/daxctl-qemu-hmat-setup -diff --git a/contrib/do_abidiff b/scripts/do_abidiff -similarity index 100% -rename from contrib/do_abidiff -rename to scripts/do_abidiff -diff --git a/contrib/prepare-release.sh b/scripts/prepare-release.sh -similarity index 99% -rename from contrib/prepare-release.sh -rename to scripts/prepare-release.sh -index fb5cfe3..97ab964 100755 ---- a/contrib/prepare-release.sh -+++ b/scripts/prepare-release.sh -@@ -186,7 +186,7 @@ check_libtool_vers "libdaxctl" - gen_lists ${last_ref}..HEAD~1 - - # For ABI diff purposes, use the latest fixes tag --contrib/do_abidiff ${last_fix}..HEAD -+scripts/do_abidiff ${last_fix}..HEAD - - # once everything passes, update the git-version - sed -i -e "s/DEF_VER=[0-9]\+.*/DEF_VER=${next_ref#v}/" git-version --- -2.27.0 - diff --git a/SOURCES/0209-ndctl-remove-obsolete-m4-directory.patch b/SOURCES/0209-ndctl-remove-obsolete-m4-directory.patch deleted file mode 100644 index a2be5f8..0000000 --- a/SOURCES/0209-ndctl-remove-obsolete-m4-directory.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 426fa7f6c0ad7db9c6b18ef9b2247be224e0ea01 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Wed, 15 Jun 2022 16:48:10 -0600 -Subject: [PATCH 209/217] ndctl: remove obsolete m4 directory - -With the conversion to meson, the m4 directory, which may have held -symlinks to libtool.m4 and friends, is no longer needed. Remove it. - -Link: https://lore.kernel.org/r/20220615224813.523053-3-vishal.l.verma@intel.com -Cc: Dan Williams -Signed-off-by: Vishal Verma ---- - m4/.gitignore | 6 ------ - 1 file changed, 6 deletions(-) - delete mode 100644 m4/.gitignore - -diff --git a/m4/.gitignore b/m4/.gitignore -deleted file mode 100644 -index 8bab51c..0000000 ---- a/m4/.gitignore -+++ /dev/null -@@ -1,6 +0,0 @@ --libtool.m4 --ltoptions.m4 --ltsugar.m4 --ltversion.m4 --lt~obsolete.m4 -- --- -2.27.0 - diff --git a/SOURCES/0210-ndctl-update-.gitignore.patch b/SOURCES/0210-ndctl-update-.gitignore.patch deleted file mode 100644 index d2d81d4..0000000 --- a/SOURCES/0210-ndctl-update-.gitignore.patch +++ /dev/null @@ -1,32 +0,0 @@ -From fcc3f6fa2989fbd2ce210c282fabf0bf3821d834 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Wed, 15 Jun 2022 16:48:11 -0600 -Subject: [PATCH 210/217] ndctl: update .gitignore - -Add a few files and dirs to .gitignore: - - cscope.* (since we already ignore 'tags') - - release/ (created by scripts/prepare_release) - - scripts/docsurgeon_parser.sh (parser generated by argbash) - -Link: https://lore.kernel.org/r/20220615224813.523053-4-vishal.l.verma@intel.com -Signed-off-by: Vishal Verma ---- - .gitignore | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/.gitignore b/.gitignore -index aa0ce8e..eeb275f 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -1,5 +1,8 @@ - build/ -+release/ - rhel/ndctl.spec - sles/ndctl.spec - *.swp - tags -+cscope.* -+scripts/docsurgeon_parser.sh --- -2.27.0 - diff --git a/SOURCES/0211-scripts-fix-contrib-do_abidiff-for-updated-fedpkg.patch b/SOURCES/0211-scripts-fix-contrib-do_abidiff-for-updated-fedpkg.patch deleted file mode 100644 index b29688b..0000000 --- a/SOURCES/0211-scripts-fix-contrib-do_abidiff-for-updated-fedpkg.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 411651adc693e55a521ba312e1e64876519b0379 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Wed, 15 Jun 2022 16:48:12 -0600 -Subject: [PATCH 211/217] scripts: fix contrib/do_abidiff for updated fedpkg - -A recent fedpkg update wants --name instead of --module-name. - -Link: https://lore.kernel.org/r/20220615224813.523053-5-vishal.l.verma@intel.com -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - scripts/do_abidiff | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/scripts/do_abidiff b/scripts/do_abidiff -index 0bd7a16..e8c3a65 100755 ---- a/scripts/do_abidiff -+++ b/scripts/do_abidiff -@@ -29,7 +29,7 @@ build_rpm() - version="$(./git-version)" - release="f$(basename $(readlink -f /etc/mock/default.cfg) | cut -d- -f2)" - git archive --format=tar --prefix="ndctl-${version}/" HEAD | gzip > ndctl-${version}.tar.gz -- fedpkg --release $release --module-name ndctl mockbuild -+ fedpkg --release $release --name=ndctl mockbuild - [ "$?" -eq 0 ] || err "error building $ref" - mkdir -p release/rel_${ref}/ - cp results_ndctl/*/*/*.x86_64.rpm release/rel_${ref}/ --- -2.27.0 - diff --git a/SOURCES/0212-scripts-update-release-helper-scripts-for-meson-and-.patch b/SOURCES/0212-scripts-update-release-helper-scripts-for-meson-and-.patch deleted file mode 100644 index 86805c8..0000000 --- a/SOURCES/0212-scripts-update-release-helper-scripts-for-meson-and-.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 9ce0fa95778a76d2334848e2629d111c4d636515 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Wed, 15 Jun 2022 16:48:13 -0600 -Subject: [PATCH 212/217] scripts: update release helper scripts for meson and - cxl - -The prepare-release.sh and do_abidiff scripts perform sanity checking -for library versioning and also guard against accidental ABI breakage -by comparing the current release with the previous using 'abipkgdiff' -from libabigail. Teach the scripts about libcxl, so that it too can -participate in the above checks. - -Additionally, move the checks over to the new meson regime. This does -break any checking for the older autotools based build, but that should -be okay. - -Link: https://lore.kernel.org/r/20220615224813.523053-6-vishal.l.verma@intel.com -Cc: Dan Williams -Signed-off-by: Vishal Verma ---- - scripts/do_abidiff | 3 ++- - scripts/prepare-release.sh | 3 ++- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/scripts/do_abidiff b/scripts/do_abidiff -index e8c3a65..ec3e344 100755 ---- a/scripts/do_abidiff -+++ b/scripts/do_abidiff -@@ -53,7 +53,7 @@ do_diff() - local old_lib="$(find . -regex "./release/rel_${old}/${pkg}-libs-[0-9]+.*" | head -1)" - local new_lib="$(find . -regex "./release/rel_${new}/${pkg}-libs-[0-9]+.*" | head -1)" - -- [ -n "$pkg" ] || err "specify a package for diff (ndctl, daxctl)" -+ [ -n "$pkg" ] || err "specify a package for diff (ndctl, daxctl, cxl)" - [ -n "$old_base" ] || err "$pkg: old_base empty, possible build failure" - [ -n "$new_base" ] || err "$pkg: new_base empty, possible build failure" - -@@ -75,3 +75,4 @@ build_rpm $old > release/buildlog_$old 2>&1 - build_rpm $new > release/buildlog_$new 2>&1 - do_diff ndctl - do_diff daxctl -+do_diff cxl -diff --git a/scripts/prepare-release.sh b/scripts/prepare-release.sh -index 97ab964..8901b50 100755 ---- a/scripts/prepare-release.sh -+++ b/scripts/prepare-release.sh -@@ -100,7 +100,7 @@ gen_lists() - } - - # Check libtool versions in Makefile.am.in --# $1: lib name (currently libndctl or libdaxctl) -+# $1: lib name (currently libndctl, libdaxctl, or libcxl) - check_libtool_vers() - { - local lib="$1" -@@ -181,6 +181,7 @@ next_fix=$(next_fix "$last_fix") - - check_libtool_vers "libndctl" - check_libtool_vers "libdaxctl" -+check_libtool_vers "libcxl" - - # HEAD~1 because HEAD would be the release commit - gen_lists ${last_ref}..HEAD~1 --- -2.27.0 - diff --git a/SOURCES/0213-meson.build-be-specific-for-library-path.patch b/SOURCES/0213-meson.build-be-specific-for-library-path.patch deleted file mode 100644 index 4be2083..0000000 --- a/SOURCES/0213-meson.build-be-specific-for-library-path.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 9a993ce24fdd5de45774b65211570dd514cdf61d Mon Sep 17 00:00:00 2001 -From: Luis Chamberlain -Date: Wed, 17 Aug 2022 18:23:04 -0700 -Subject: [PATCH 213/217] meson.build: be specific for library path - -If you run the typical configure script on a typical linux software -project say with ./configure --prefix=/usr/ then the libdir defaults -to /usr/lib/ however this is not true with meson. - -With meson the current libdir path follows the one set by the prefix, -and so with the current setup with prefix forced by default to /usr/ -we end up with libdir set to /usr/ as well and so libraries built -and installed also placed into /usr/ as well, not /usr/lib/ as we -would typically expect. - -So you if you use today's defaults you end up with the libraries placed -into /usr/ and then a simple error such as: - -cxl: error while loading shared libraries: libcxl.so.1: cannot open shared object file: No such file or directory - -Folks may have overlooked this as their old library is still usable. - -Fix this by forcing the default library path to /usr/lib, and so -requiring users to set both prefix and libdir if they want to -customize both. - -Link: https://lore.kernel.org/r/Yv2UeCIcA00lJC5j@bombadil.infradead.org -Signed-off-by: Luis Chamberlain -Signed-off-by: Vishal Verma ---- - meson.build | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/meson.build b/meson.build -index aecf461..802b38c 100644 ---- a/meson.build -+++ b/meson.build -@@ -9,6 +9,7 @@ project('ndctl', 'c', - default_options : [ - 'c_std=gnu99', - 'prefix=/usr', -+ 'libdir=/usr/lib', - 'sysconfdir=/etc', - 'localstatedir=/var', - ], --- -2.27.0 - diff --git a/SOURCES/0214-cxl-region-fix-a-dereferecnce-after-NULL-check.patch b/SOURCES/0214-cxl-region-fix-a-dereferecnce-after-NULL-check.patch deleted file mode 100644 index a0ca7a7..0000000 --- a/SOURCES/0214-cxl-region-fix-a-dereferecnce-after-NULL-check.patch +++ /dev/null @@ -1,39 +0,0 @@ -From cc2766399882001880a899e723c7bd968e60f100 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Tue, 23 Aug 2022 01:45:25 -0600 -Subject: [PATCH 214/217] cxl/region: fix a dereferecnce after NULL check - -A NULL check in region_action() implies that 'decoder' might be NULL, but -later we dereference it during cxl_decoder_foreach(). The NULL check is -valid because it was the filter result being checked, however, while -doing this, the original 'decoder' variable was being clobbered. - -Check the filter results independently of the original decoder variable. - -Link: https://lore.kernel.org/r/20220823074527.404435-2-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/region.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/cxl/region.c b/cxl/region.c -index a30313c..334fcc2 100644 ---- a/cxl/region.c -+++ b/cxl/region.c -@@ -686,9 +686,8 @@ static int region_action(int argc, const char **argv, struct cxl_ctx *ctx, - continue; - - cxl_decoder_foreach (port, decoder) { -- decoder = util_cxl_decoder_filter(decoder, -- param.root_decoder); -- if (!decoder) -+ if (!util_cxl_decoder_filter(decoder, -+ param.root_decoder)) - continue; - rc = decoder_region_action(p, decoder, action, count); - if (rc) --- -2.27.0 - diff --git a/SOURCES/0215-libcxl-fox-a-resource-leak-and-a-forward-NULL-check.patch b/SOURCES/0215-libcxl-fox-a-resource-leak-and-a-forward-NULL-check.patch deleted file mode 100644 index ac370ce..0000000 --- a/SOURCES/0215-libcxl-fox-a-resource-leak-and-a-forward-NULL-check.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 4750c7f50050195bbd427da69037645916a59b24 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Tue, 23 Aug 2022 01:45:26 -0600 -Subject: [PATCH 215/217] libcxl: fox a resource leak and a forward NULL check - -Static analysis reports a couple of issues in add_cxl_region(). Firstly, -'path' wasn't freed in the success case, only in the error case. -Secondly, the error handling after 'calloc()'ing the region object -erroneously jumped to the error path which tried to free the region object. - -Add a new error label to just free 'path' and return for this exit case. - -Link: https://lore.kernel.org/r/20220823074527.404435-3-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/lib/libcxl.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c -index 021d59f..e8c5d44 100644 ---- a/cxl/lib/libcxl.c -+++ b/cxl/lib/libcxl.c -@@ -482,7 +482,7 @@ static void *add_cxl_region(void *parent, int id, const char *cxlregion_base) - - region = calloc(1, sizeof(*region)); - if (!region) -- goto err; -+ goto err_path; - - region->id = id; - region->ctx = ctx; -@@ -551,11 +551,13 @@ static void *add_cxl_region(void *parent, int id, const char *cxlregion_base) - - list_add_sorted(&decoder->regions, region, list, region_start_cmp); - -+ free(path); - return region; - err: - free(region->dev_path); - free(region->dev_buf); - free(region); -+err_path: - free(path); - return NULL; - } --- -2.27.0 - diff --git a/SOURCES/0216-cxl-filter-Fix-an-uninitialized-pointer-dereference.patch b/SOURCES/0216-cxl-filter-Fix-an-uninitialized-pointer-dereference.patch deleted file mode 100644 index 44ed9a6..0000000 --- a/SOURCES/0216-cxl-filter-Fix-an-uninitialized-pointer-dereference.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 934d2b34b616566163d80f5844b371ecf88d646a Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Tue, 23 Aug 2022 01:45:27 -0600 -Subject: [PATCH 216/217] cxl/filter: Fix an uninitialized pointer dereference - -Static analysis points out that there was a chance that 'jdecoder' could -be used while uninitialized in walk_decoders(). Initialize it to NULL to -avoid this. - -Link: https://lore.kernel.org/r/20220823074527.404435-4-vishal.l.verma@intel.com -Cc: Dan Williams -Reviewed-by: Dan Williams -Signed-off-by: Vishal Verma ---- - cxl/filter.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/cxl/filter.c b/cxl/filter.c -index 9a3de8c..56c6599 100644 ---- a/cxl/filter.c -+++ b/cxl/filter.c -@@ -796,7 +796,7 @@ static void walk_decoders(struct cxl_port *port, struct cxl_filter_params *p, - cxl_decoder_foreach(port, decoder) { - const char *devname = cxl_decoder_get_devname(decoder); - struct json_object *jchildregions = NULL; -- struct json_object *jdecoder; -+ struct json_object *jdecoder = NULL; - - if (!p->decoders) - goto walk_children; --- -2.27.0 - diff --git a/SOURCES/0217-ndctl-release-v74.patch b/SOURCES/0217-ndctl-release-v74.patch deleted file mode 100644 index bdec84c..0000000 --- a/SOURCES/0217-ndctl-release-v74.patch +++ /dev/null @@ -1,133 +0,0 @@ -From c9c9db39354ea0c3f737378186318e9b7908e3a7 Mon Sep 17 00:00:00 2001 -From: Vishal Verma -Date: Tue, 23 Aug 2022 18:44:35 -0600 -Subject: [PATCH 217/217] ndctl: release v74 - -This release incorporates functionality up to the 6.0 kernel. - -Highlights include CXL region management, enhancements to cxl-list, -cxl_test based unit tests for topology enumeration, and region and -label operations, misc build fixes, iniparser include resolution, -fixes in config parsing for ndctl-monitor, and misc documentation -and unit test updates. - -Commands: - cxl-create-region: new command (also {enable,disable,destroy}-region) - cxl-list: add -v / -vv etc. options for verbosity control - cxl-list: new filtering options, endpoint decoder DPA listings - cxl-list: add decoder interleave settings, and mode - cxl-list: add port depth - cxl-list: Auto-enable 'single' mode for port listings - cxl-set-partition: Accept 'ram' as an alias for 'volatile' - cxl-disable-bus: new command - cxl-{reserve,free}-dpa: new commands - ndctl-xable-namespace: zero namespace fixes - ndctl-monitor: fix config parsing - daxctl-reconfigure-device: fix systemd escaping for policy config - -Tests: - cxl-topology.sh: new test for CXL topology enumeration - cxl-region-sysfs.sh: new test for the low-level CXL region ABI - cxl-create-region.sh: new test for region management - cxl-labels.sh: new test for label management commands - -APIs: - cxl_bus_disable_invalidate - cxl_decoder_create_pmem_region - cxl_decoder_get_by_name - cxl_decoder_get_dpa_resource - cxl_decoder_get_dpa_size - cxl_decoder_get_interleave_granularity - cxl_decoder_get_interleave_ways - cxl_decoder_get_last - cxl_decoder_get_max_available_extent - cxl_decoder_get_memdev - cxl_decoder_get_mode - cxl_decoder_get_prev - cxl_decoder_get_region - cxl_decoder_set_dpa_size - cxl_decoder_set_mode - cxl_mapping_get_decoder - cxl_mapping_get_first - cxl_mapping_get_next - cxl_mapping_get_position - cxl_mapping_get_region - cxl_port_get_depth - cxl_region_clear_all_targets - cxl_region_clear_target - cxl_region_decode_commit - cxl_region_decode_is_committed - cxl_region_decode_reset - cxl_region_delete - cxl_region_disable - cxl_region_enable - cxl_region_get_ctx - cxl_region_get_decoder - cxl_region_get_devname - cxl_region_get_first - cxl_region_get_id - cxl_region_get_interleave_granularity - cxl_region_get_interleave_ways - cxl_region_get_next - cxl_region_get_resource - cxl_region_get_size - cxl_region_get_target_decoder - cxl_region_get_uuid - cxl_region_is_enabled - cxl_region_set_interleave_granularity - cxl_region_set_interleave_ways - cxl_region_set_size - cxl_region_set_target - cxl_region_set_uuid ---- - git-version | 2 +- - meson.build | 8 ++++---- - 2 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/git-version b/git-version -index bdea9a9..7d76fa1 100755 ---- a/git-version -+++ b/git-version -@@ -19,7 +19,7 @@ dirty() { - fi - } - --DEF_VER=72 -+DEF_VER=74 - - LF=' - ' -diff --git a/meson.build b/meson.build -index 802b38c..20a646d 100644 ---- a/meson.build -+++ b/meson.build -@@ -1,5 +1,5 @@ - project('ndctl', 'c', -- version : '73', -+ version : '74', - license : [ - 'GPL-2.0', - 'LGPL-2.1', -@@ -292,16 +292,16 @@ config_h = configure_file( - add_project_arguments('-include', 'config.h', language : 'c') - - LIBNDCTL_CURRENT=26 --LIBNDCTL_REVISION=0 -+LIBNDCTL_REVISION=1 - LIBNDCTL_AGE=20 - - LIBDAXCTL_CURRENT=6 - LIBDAXCTL_REVISION=1 - LIBDAXCTL_AGE=5 - --LIBCXL_CURRENT=2 -+LIBCXL_CURRENT=3 - LIBCXL_REVISION=0 --LIBCXL_AGE=1 -+LIBCXL_AGE=2 - - root_inc = include_directories(['.', 'ndctl', ]) - --- -2.27.0 - diff --git a/SPECS/ndctl.spec b/SPECS/ndctl.spec index a83ad1c..0b03753 100644 --- a/SPECS/ndctl.spec +++ b/SPECS/ndctl.spec @@ -1,206 +1,17 @@ Name: ndctl -Version: 71.1 -Release: 8%{?dist} +Version: 78 +Release: 2%{?dist} Summary: Manage "libnvdimm" subsystem devices (Non-volatile Memory) License: GPLv2 Url: https://github.com/pmem/ndctl Source0: https://github.com/pmem/%{name}/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz - -Patch0: 0003-ndctl-test-Fix-btt-expect-table-compile-warning.patch -Patch1: 0004-ndctl-test-Cleanup-unnecessary-out-label.patch -Patch2: 0005-ndctl-test-Fix-device-dax-mremap-test.patch -Patch3: 0006-ndctl-test-Exercise-soft_offline_page-corner-cases.patch -Patch4: 0007-msft-Add-xlat_firmware_status-for-JEDEC-Byte-Address.patch -Patch5: 0008-ndctl-namespace-Fix-disable-namespace-accounting-rel.patch -Patch6: 0009-zero_info_block-skip-seed-devices.patch -Patch7: 0010-ndctl-update-.gitignore.patch -Patch8: 0011-ndctl-test-add-checking-the-presence-of-jq-command-a.patch -Patch9: 0012-Expose-ndctl_bus_nfit_translate_spa-as-a-public-func.patch -Patch10: 0013-test-libndctl-Use-ndctl_region_set_ro-to-change-disk.patch -Patch11: 0014-daxctl-fail-reconfigure-device-based-on-kernel-onlin.patch -Patch12: 0015-libdaxctl-add-an-API-to-check-if-a-device-is-active.patch -Patch13: 0016-libndctl-check-for-active-system-ram-before-disablin.patch -Patch14: 0017-daxctl-emit-counts-of-total-and-online-memblocks.patch -Patch15: 0018-libndctl-Unify-adding-dimms-for-papr-and-nfit-famili.patch -Patch16: 0019-test-Don-t-skip-tests-if-nfit-modules-are-missing.patch -Patch17: 0020-papr-Add-support-to-parse-save_fail-flag-for-dimm.patch -Patch18: 0021-Use-page-size-as-alignment-value.patch -Patch19: 0022-libndctl-Remove-redundant-checks-and-assignments.patch -Patch20: 0023-ndctl-Update-nvdimm-mailing-list-address.patch -Patch21: 0024-libndctl-papr-Fix-probe-for-papr-scm-compatible-nvdi.patch -Patch22: 0025-ndctl-scrub-Stop-translating-return-values.patch -Patch23: 0026-ndctl-scrub-Reread-scrub-engine-status-at-start.patch -Patch24: 0027-ndctl-dimm-Fix-label-index-block-calculations.patch -Patch25: 0028-ndctl-namespace-Skip-seed-namespaces-when-processing.patch -Patch26: 0029-ndctl-namespace-Suppress-ENXIO-when-processing-all-n.patch -Patch27: 0030-namespace-action-Drop-zero-namespace-checks.patch -Patch28: 0031-ndctl-add-.clang-format.patch -Patch29: 0032-cxl-add-a-cxl-utility-and-libcxl-library.patch -Patch30: 0033-cxl-add-a-local-copy-of-the-cxl_mem-UAPI-header.patch -Patch31: 0034-util-add-the-struct_size-helper-from-the-kernel.patch -Patch32: 0035-libcxl-add-support-for-command-query-and-submission.patch -Patch33: 0036-libcxl-add-support-for-the-Identify-Device-command.patch -Patch34: 0037-libcxl-add-GET_HEALTH_INFO-mailbox-command-and-acces.patch -Patch35: 0038-libcxl-add-support-for-the-GET_LSA-command.patch -Patch36: 0039-libcxl-add-label_size-to-cxl_memdev-and-an-API-to-re.patch -Patch37: 0040-libcxl-add-representation-for-an-nvdimm-bridge-objec.patch -Patch38: 0041-libcxl-add-interfaces-for-label-operations.patch -Patch39: 0042-cxl-add-commands-to-read-write-and-zero-labels.patch -Patch40: 0043-Documentation-cxl-add-library-API-documentation.patch -Patch41: 0044-ndctl-Add-CXL-packages-to-the-RPM-spec.patch -Patch42: 0045-cxl-cli-add-bash-completion.patch -Patch43: 0046-cxl-add-health-information-to-cxl-list.patch -Patch44: 0047-ndctl-install-bash-completion-symlinks.patch -Patch45: 0048-scripts-Add-a-man-page-template-generator.patch -Patch46: 0049-daxctl-Add-Soft-Reservation-theory-of-operation.patch -Patch47: 0061-libcxl-fix-potential-NULL-dereference-in-cxl_memdev_.patch -Patch48: 0064-ndctl-release-v72.patch -Patch49: 0067-ndctl-add-repology-graphic-to-README.md.patch -Patch50: 0068-Documentation-ndctl-fix-self-reference-of-ndctl-disa.patch -Patch51: 0069-ndctl-docs-Clarify-update-firwmware-activation-overf.patch -Patch52: 0070-ndctl-test-Prepare-for-BLK-aperture-support-removal.patch -Patch53: 0071-ndctl-test-Move-reset-to-function-in-common.patch -Patch54: 0072-ndctl-test-Initialize-the-label-area-by-default.patch -Patch55: 0073-ndctl-test-Skip-BLK-flags-checks.patch -Patch56: 0074-ndctl-test-Move-sector-mode-to-a-different-region.patch -Patch57: 0075-ndctl-Deprecate-BLK-aperture-support.patch -Patch58: 0076-ndctl-test-Fix-support-for-missing-dax_pmem_compat-m.patch -Patch59: 0077-util-Distribute-filter-and-json-helpers-to-per-tool-.patch -Patch60: 0078-Documentation-Drop-attrs.adoc-include.patch -Patch61: 0079-build-Drop-unnecessary-tool-config.h-includes.patch -Patch62: 0080-test-Prepare-out-of-line-builds.patch -Patch63: 0081-ndctl-Drop-executable-bit-for-bash-completion-script.patch -Patch64: 0082-build-Add-meson-build-infrastructure.patch -Patch65: 0083-build-Add-meson-rpmbuild-support.patch -Patch66: 0084-ndctl-Jettison-autotools.patch -Patch67: 0085-ndctl-build-Default-asciidoctor-to-enabled.patch -Patch68: 0086-ndctl-update-README.md-for-meson-build.patch -Patch69: 0087-test-Add-suite-identifiers-to-tests.patch -Patch70: 0088-ndctl-Rename-util_filter-to-ndctl_filter.patch -Patch71: 0089-build-Add-tags.patch -Patch72: 0090-json-Add-support-for-json_object_new_uint64.patch -Patch73: 0091-cxl-json-Cleanup-object-leak-false-positive.patch -Patch74: 0092-cxl-list-Support-multiple-memdev-device-name-filter-.patch -Patch75: 0093-cxl-list-Support-comma-separated-lists.patch -Patch76: 0094-cxl-list-Introduce-cxl_filter_walk.patch -Patch77: 0095-cxl-list-Emit-device-serial-numbers.patch -Patch78: 0096-cxl-list-Add-filter-by-serial-support.patch -Patch79: 0097-cxl-lib-Rename-nvdimm-bridge-to-pmem.patch -Patch80: 0098-cxl-list-Cleanup-options-definitions.patch -Patch81: 0099-Documentation-Enhance-libcxl-memdev-API-documentatio.patch -Patch82: 0100-cxl-list-Add-bus-objects.patch -Patch83: 0101-util-json-Warn-on-stderr-about-empty-list-results.patch -Patch84: 0102-util-sysfs-Uplevel-modalias-lookup-helper-to-util.patch -Patch85: 0103-cxl-list-Add-port-enumeration.patch -Patch86: 0104-cxl-list-Add-debug-option.patch -Patch87: 0105-cxl-list-Add-endpoints.patch -Patch88: 0106-cxl-list-Add-host-entries-for-port-like-objects.patch -Patch89: 0107-cxl-list-Add-host-entries-for-memdevs.patch -Patch90: 0108-cxl-list-Move-enabled-memdevs-underneath-their-endpo.patch -Patch91: 0109-cxl-list-Filter-memdev-by-ancestry.patch -Patch92: 0110-cxl-memdev-Use-a-local-logger-for-debug.patch -Patch93: 0111-cxl-memdev-Cleanup-memdev-filter.patch -Patch94: 0112-cxl-memdev-Add-serial-support-for-memdev-related-com.patch -Patch95: 0113-cxl-list-Add-numa_node-to-memdev-listings.patch -Patch96: 0114-util-Implement-common-bind-unbind-helpers.patch -Patch97: 0115-cxl-memdev-Enable-disable-support.patch -Patch98: 0116-cxl-list-Add-decoder-support.patch -Patch99: 0117-cxl-list-Extend-decoder-objects-with-target-informat.patch -Patch100: 0118-cxl-list-Use-physical_node-for-root-port-attachment-.patch -Patch101: 0119-cxl-list-Reuse-the-target-option-for-ports.patch -Patch102: 0120-cxl-list-Support-filtering-memdevs-by-decoders.patch -Patch103: 0121-cxl-list-Support-filtering-memdevs-by-ports.patch -Patch104: 0122-cxl-port-Add-disable-enable-port-command.patch -Patch105: 0123-cxl-list-Filter-dports-and-targets-by-memdevs.patch -Patch106: 0124-ndctl-test-make-inject-smart.sh-more-tolerant-of-dec.patch -Patch107: 0125-libndctl-papr-Add-support-for-reporting-shutdown-cou.patch -Patch108: 0126-libndctl-intel-Indicate-supported-smart-inject-types.patch -Patch109: 0127-libndctl-papr-Add-limited-support-for-inject-smart.patch -Patch110: 0128-ndtest-ack-shutdown-count-Skip-the-test-on-ndtest.patch -Patch111: 0129-ndctl-libndctl-Update-nvdimm-flags-after-smart-injec.patch -Patch112: 0132-libcxl-add-GET_PARTITION_INFO-mailbox-command-and-ac.patch -Patch113: 0133-libcxl-add-accessors-for-capacity-fields-of-the-IDEN.patch -Patch114: 0134-libcxl-return-the-partition-alignment-field-in-bytes.patch -Patch115: 0135-cxl-add-memdev-partition-information-to-cxl-list.patch -Patch116: 0136-libcxl-add-interfaces-for-SET_PARTITION_INFO-mailbox.patch -Patch117: 0137-cxl-add-command-cxl-set-partition.patch -Patch118: 0138-Update-ndctl.spec-to-allow-flatpak-builds.patch -Patch119: 0139-daxctl-provide-safe-versions-of-iteration-API.patch -Patch120: 0140-util-size.h-fix-build-for-older-compilers.patch -Patch121: 0141-build-Automate-rpmbuild.sh.patch -Patch122: 0142-util-size.h-Fix-build-error-for-GCC-10.patch -Patch123: 0143-libcxl-Remove-extraneous-NULL-checks-when-validating.patch -Patch124: 0144-libdaxctl-free-resource-allocated-with-asprintf.patch -Patch125: 0145-cxl-list-tidy-the-error-path-in-add_cxl_decoder.patch -Patch126: 0146-cxl-list-always-free-the-path-var-in-add_cxl_decoder.patch -Patch127: 0147-scripts-docsurgeon-Fix-document-header-for-section-1.patch -Patch128: 0148-ndctl-release-v73.patch -Patch130: 0150-build-Fix-Wall-and-O2-warnings.patch -Patch131: 0151-build-Fix-test-timeouts.patch -Patch132: 0155-build-Move-utility-helpers-to-libutil.a.patch -Patch133: 0156-util-Use-SZ_-size-macros-in-display-size.patch -Patch134: 0157-util-Pretty-print-terabytes.patch -Patch135: 0158-cxl-port-Fix-disable-port-man-page.patch -Patch136: 0159-cxl-bus-Add-bus-disable-support.patch -Patch137: 0160-cxl-list-Auto-enable-single-mode-for-port-listings.patch -Patch138: 0161-cxl-memdev-Fix-bus_invalidate-crash.patch -Patch139: 0162-cxl-list-Add-support-for-filtering-by-host-identifie.patch -Patch140: 0163-cxl-port-Relax-port-identifier-validation.patch -Patch142: 0165-cxl-test-Add-topology-enumeration-and-hotplug-test.patch -Patch143: 0167-daxctl-Fix-kernel-option-typo-in-Soft-Reservation-th.patch -Patch144: 0168-meson-make-modprobedatadir-an-option.patch -Patch145: 0169-namespace-action-Drop-more-zero-namespace-checks.patch -Patch146: 0170-ndctl-dimm-Flush-invalidated-labels-after-overwrite.patch -Patch147: 0171-libcxl-fix-a-segfault-when-memdev-pmem-is-absent.patch -Patch148: 0172-ndctl-bus-Handle-missing-scrub-commands-more-gracefu.patch -Patch149: 0173-util-wrapper.c-Fix-gcc-warning-in-xrealloc.patch -Patch150: 0174-libcxl-Fix-memory-leakage-in-cxl_port_init.patch -Patch151: 0175-cxl-list-Reformat-option-list.patch -Patch152: 0176-cxl-list-Emit-endpoint-decoders-filtered-by-memdev.patch -Patch153: 0177-cxl-list-Hide-0s-in-disabled-decoder-listings.patch -Patch154: 0178-cxl-list-Add-DPA-span-to-endpoint-decoder-listings.patch -Patch155: 0179-ccan-list-Import-latest-list-helpers.patch -Patch156: 0180-cxl-lib-Maintain-decoders-in-id-order.patch -Patch157: 0181-cxl-memdev-Fix-json-for-multi-device-partitioning.patch -Patch158: 0182-cxl-list-Emit-mode-for-endpoint-decoder-objects.patch -Patch159: 0183-cxl-set-partition-Accept-ram-as-an-alias-for-volatil.patch -Patch160: 0184-cxl-memdev-Add-reserve-free-dpa-commands.patch -Patch161: 0185-cxl-test-Update-CXL-memory-parameters.patch -Patch162: 0186-cxl-test-Checkout-region-setup-teardown.patch -Patch163: 0187-cxl-test-add-a-test-to-read-write-zero-labels.patch -Patch164: 0188-cxl-list-Clarify-B-vs-P-p-root.patch -Patch165: 0189-libcxl-add-a-depth-attribute-to-cxl_port.patch -Patch166: 0190-cxl-port-Consolidate-the-debug-option-in-cxl-port-ma.patch -Patch167: 0191-cxl-memdev-refactor-decoder-mode-string-parsing.patch -Patch168: 0192-libcxl-Introduce-libcxl-region-and-mapping-objects.patch -Patch169: 0193-cxl-cli-add-region-listing-support.patch -Patch170: 0194-libcxl-add-low-level-APIs-for-region-creation.patch -Patch171: 0195-cxl-add-a-create-region-command.patch -Patch172: 0196-cxl-add-commands-to-enable-disable-destroy-region.patch -Patch173: 0197-cxl-list-make-memdevs-and-regions-the-default-listin.patch -Patch174: 0198-test-add-a-cxl-create-region-test.patch -Patch175: 0199-cxl-decoder-add-a-max_available_extent-attribute.patch -Patch176: 0200-cxl-Add-list-verbose-option-to-the-cxl-command.patch -Patch177: 0201-cxl-test-Validate-endpoint-interleave-geometry.patch -Patch178: 0202-cxl-list-Add-interleave-parameters-to-decoder-listin.patch -Patch179: 0203-cxl-list-Add-region-to-decoder-listings.patch -Patch180: 0204-cxl-list-Filter-decoders-by-region.patch -Patch181: 0205-cxl-list-Add-depth-to-port-listings.patch -Patch182: 0206-cxl-test-Validate-switch-port-settings-in-cxl-region.patch -Patch183: 0207-meson-fix-modprobedatadir-default-value.patch -Patch184: 0208-ndctl-move-developer-scripts-from-contrib-to-scripts.patch -Patch185: 0209-ndctl-remove-obsolete-m4-directory.patch -Patch186: 0210-ndctl-update-.gitignore.patch -Patch187: 0211-scripts-fix-contrib-do_abidiff-for-updated-fedpkg.patch -Patch188: 0212-scripts-update-release-helper-scripts-for-meson-and-.patch -Patch189: 0213-meson.build-be-specific-for-library-path.patch -Patch190: 0214-cxl-region-fix-a-dereferecnce-after-NULL-check.patch -Patch191: 0215-libcxl-fox-a-resource-leak-and-a-forward-NULL-check.patch -Patch192: 0216-cxl-filter-Fix-an-uninitialized-pointer-dereference.patch -Patch193: 0217-ndctl-release-v74.patch +Patch0: 0001-test-daxctl-devices.sh-increase-the-namespace-size.patch +Patch1: 0002-ndctl-vendor-iniparser.patch +Patch2: 0003-ndctl-check-the-old-directory-for-monitor.conf.patch Requires: ndctl-libs%{?_isa} = %{version}-%{release} Requires: daxctl-libs%{?_isa} = %{version}-%{release} +Requires: cxl-libs%{?_isa} = %{version}-%{release} BuildRequires: make BuildRequires: autoconf %if 0%{?rhel} < 9 @@ -208,7 +19,10 @@ BuildRequires: asciidoc %define asciidoc -Dasciidoctor=disabled %else BuildRequires: rubygem-asciidoctor +BuildRequires: libtraceevent-devel +BuildRequires: libtracefs-devel %define asciidoc -Dasciidoctor=enabled +%define libtracefs -Dlibtracefs=enabled %endif BuildRequires: xmlto BuildRequires: meson @@ -291,6 +105,7 @@ Libraries for %{name}. %package -n daxctl-libs Summary: Management library for "Device DAX" devices License: LGPLv2 +Requires: ndctl-libs%{?_isa} = %{version}-%{release} %description -n daxctl-libs Device DAX is a facility for establishing DAX mappings of performance / @@ -300,6 +115,7 @@ control API for these devices. %package -n cxl-libs Summary: Management library for CXL devices License: LGPLv2 +Requires: daxctl-libs%{?_isa} = %{version}-%{release} %description -n cxl-libs libcxl is a library for enumerating and communicating with CXL devices. @@ -309,7 +125,7 @@ libcxl is a library for enumerating and communicating with CXL devices. %autosetup -p1 ndctl-%{version} %build -%meson %{?asciidoc} -Dversion-tag=%{version} +%meson %{?asciidoc} %{?libtracefs} -Dversion-tag=%{version} %meson_build %install @@ -319,44 +135,57 @@ libcxl is a library for enumerating and communicating with CXL devices. %ldconfig_scriptlets -n daxctl-libs +%ldconfig_scriptlets -n cxl-libs + %define bashcompdir %(pkg-config --variable=completionsdir bash-completion) %files -%license LICENSES/preferred/GPL-2.0 LICENSES/other/MIT LICENSES/other/CC0-1.0 +%license LICENSES/preferred/GPL-2.0 LICENSES/other/MIT LICENSES/other/CC0-1.0 LICENSES/other/iniparser-MIT %{_bindir}/ndctl %{_mandir}/man1/ndctl* -%{bashcompdir}/ +%{bashcompdir}/ndctl %{_unitdir}/ndctl-monitor.service + +%dir %{_sysconfdir}/ndctl +%dir %{_sysconfdir}/ndctl/keys %{_sysconfdir}/ndctl/keys/keys.readme %{_sysconfdir}/modprobe.d/nvdimm-security.conf +%dir %{_sysconfdir}/ndctl.conf.d %config(noreplace) %{_sysconfdir}/ndctl/monitor.conf +%config(noreplace) %{_sysconfdir}/ndctl.conf.d/ndctl.conf %files -n daxctl -%license LICENSES/preferred/GPL-2.0 LICENSES/other/MIT LICENSES/other/CC0-1.0 +%license LICENSES/preferred/GPL-2.0 LICENSES/other/MIT LICENSES/other/CC0-1.0 LICENSES/other/iniparser-MIT %{_bindir}/daxctl %{_mandir}/man1/daxctl* -%{_datadir}/daxctl/daxctl.conf +%{_datadir}/daxctl +%{bashcompdir}/daxctl +%{_unitdir}/daxdev-reconfigure@.service +%config %{_udevrulesdir}/90-daxctl-device.rules +%dir %{_sysconfdir}/daxctl.conf.d/ +%config(noreplace) %{_sysconfdir}/daxctl.conf.d/daxctl.example.conf %files -n cxl-cli -%license LICENSES/preferred/GPL-2.0 LICENSES/other/MIT LICENSES/other/CC0-1.0 +%license LICENSES/preferred/GPL-2.0 LICENSES/other/MIT LICENSES/other/CC0-1.0 LICENSES/other/iniparser-MIT %{_bindir}/cxl %{_mandir}/man1/cxl* %{bashcompdir}/cxl +%{_unitdir}/cxl-monitor.service %files -n ndctl-libs %doc README.md -%license LICENSES/preferred/LGPL-2.1 LICENSES/other/MIT LICENSES/other/CC0-1.0 +%license LICENSES/preferred/LGPL-2.1 LICENSES/other/MIT LICENSES/other/CC0-1.0 LICENSES/other/iniparser-MIT %{_libdir}/libndctl.so.* %files -n daxctl-libs %doc README.md -%license LICENSES/preferred/LGPL-2.1 LICENSES/other/MIT LICENSES/other/CC0-1.0 +%license LICENSES/preferred/LGPL-2.1 LICENSES/other/MIT LICENSES/other/CC0-1.0 LICENSES/other/iniparser-MIT %{_libdir}/libdaxctl.so.* %files -n cxl-libs %doc README.md -%license LICENSES/preferred/LGPL-2.1 LICENSES/other/MIT LICENSES/other/CC0-1.0 +%license LICENSES/preferred/LGPL-2.1 LICENSES/other/MIT LICENSES/other/CC0-1.0 LICENSES/other/iniparser-MIT %{_libdir}/libcxl.so.* %files -n ndctl-devel @@ -381,6 +210,18 @@ libcxl is a library for enumerating and communicating with CXL devices. %changelog +* Fri Jul 26 2024 Jeff Moyer - 78-2 +- Add explicit package version requirements. (Jeff Moyer) +- Related: RHEL-29151 + +* Wed Nov 15 2023 Jeff Moyer - 78-1 +- Rebase to v78 +- Add support for legacy monitor.conf file location +- Fix a test failure. +- Resolves: RHEL-10382 +- Resolves: RHEL-8204 +- Resolves: RHEL-29151 + * Thu Oct 13 2022 Jeff Moyer - 71.1-8 - Backport changes up to v74, excluding the config file changes. (Jeff Moyer) This includes support for the CXL commands, and adds the following