History

Merge tag 'cxl-for-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl

Pull cxl updates from Dan Williams: "Compute Express Link (CXL) updates for 6.0: - Introduce a 'struct cxl_region' object with support for provisioning and assembling persistent memory regions. - Introduce alloc_free_mem_region() to accompany the existing request_free_mem_region() as a method to allocate physical memory capacity out of an existing resource. - Export insert_resource_expand_to_fit() for the CXL subsystem to late-publish CXL platform windows in iomem_resource. - Add a polled mode PCI DOE (Data Object Exchange) driver service and use it in cxl_pci to retrieve the CDAT (Coherent Device Attribute Table)" * tag 'cxl-for-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl: (74 commits) cxl/hdm: Fix skip allocations vs multiple pmem allocations cxl/region: Disallow region granularity != window granularity cxl/region: Fix x1 interleave to greater than x1 interleave routing cxl/region: Move HPA setup to cxl_region_attach() cxl/region: Fix decoder interleave programming Documentation: cxl: remove dangling kernel-doc reference cxl/region: describe targets and nr_targets members of cxl_region_params cxl/regions: add padding for cxl_rr_ep_add nested lists cxl/region: Fix IS_ERR() vs NULL check cxl/region: Fix region reference target accounting cxl/region: Fix region commit uninitialized variable warning cxl/region: Fix port setup uninitialized variable warnings cxl/region: Stop initializing interleave granularity cxl/hdm: Fix DPA reservation vs cxl_endpoint_decoder lifetime cxl/acpi: Minimize granularity for x1 interleaves cxl/region: Delete 'region' attribute from root decoders cxl/acpi: Autoload driver for 'cxl_acpi' test devices cxl/region: decrement ->nr_targets on error in cxl_region_attach() cxl/region: prevent underflow in ways_to_cxl() cxl/region: uninitialized variable in alloc_hpa() ...

Linus Torvalds committed 4 years ago

Commit c2356982 parents 5e2e738 1cd8a2539 files · +5498 −576Browse files

Showing the changes to kernel (1 of 39 files). Show all

Unified · Split

kernel/resource.c+150−35
@@ -489,8 +489,9 @@ int __weak page_is_ram(unsigned long pfn) · 488 unmodified lines
489489 }
490490 EXPORT_SYMBOL_GPL(page_is_ram);
491491
492−static int __region_intersects(resource_size_t start, size_t size,
493− unsigned long flags, unsigned long desc)
492+static int __region_intersects(struct resource *parent, resource_size_t start,
493+ size_t size, unsigned long flags,
494+ unsigned long desc)
494495 {
495496 struct resource res;
496497 int type = 0; int other = 0;
@@ -499,7 +500,7 @@ static int __region_intersects(resource_size_t start, size_t size, · 2 unmodified lines
499500 res.start = start;
500501 res.end = start + size - 1;
501502
502− for (p = iomem_resource.child; p ; p = p->sibling) {
503+ for (p = parent->child; p ; p = p->sibling) {
503504 bool is_type = (((p->flags & flags) == flags) &&
504505 ((desc == IORES_DESC_NONE) ||
505506 (desc == p->desc)));
@@ -543,7 +544,7 @@ int region_intersects(resource_size_t start, size_t size, unsigned long flags, · 37 unmodified lines
543544 int ret;
544545
545546 read_lock(&resource_lock);
546− ret = __region_intersects(start, size, flags, desc);
547+ ret = __region_intersects(&iomem_resource, start, size, flags, desc);
547548 read_unlock(&resource_lock);
548549
549550 return ret;
@@ -891,6 +892,13 @@ void insert_resource_expand_to_fit(struct resource *root, struct resource *new) · 341 unmodified lines
891892 }
892893 write_unlock(&resource_lock);
893894 }
895+/*
896+ * Not for general consumption, only early boot memory map parsing, PCI
897+ * resource discovery, and late discovery of CXL resources are expected
898+ * to use this interface. The former are built-in and only the latter,
899+ * CXL, is a module.
900+ */
901+EXPORT_SYMBOL_NS_GPL(insert_resource_expand_to_fit, CXL);
894902
895903 /**
896904 * remove_resource - Remove a resource in the resource tree
@@ -1773,62 +1781,139 @@ void resource_list_free(struct list_head *head) · 876 unmodified lines
17731781 }
17741782 EXPORT_SYMBOL(resource_list_free);
17751783
1776−#ifdef CONFIG_DEVICE_PRIVATE
1777−static struct resource *__request_free_mem_region(struct device *dev,
1778− struct resource *base, unsigned long size, const char *name)
1784+#ifdef CONFIG_GET_FREE_REGION
1785+#define GFR_DESCENDING (1UL << 0)
1786+#define GFR_REQUEST_REGION (1UL << 1)
1787+#define GFR_DEFAULT_ALIGN (1UL << PA_SECTION_SHIFT)
1788+
1789+static resource_size_t gfr_start(struct resource *base, resource_size_t size,
1790+ resource_size_t align, unsigned long flags)
1791+{
1792+ if (flags & GFR_DESCENDING) {
1793+ resource_size_t end;
1794+
1795+ end = min_t(resource_size_t, base->end,
1796+ (1ULL << MAX_PHYSMEM_BITS) - 1);
1797+ return end - size + 1;
1798+ }
1799+
1800+ return ALIGN(base->start, align);
1801+}
1802+
1803+static bool gfr_continue(struct resource *base, resource_size_t addr,
1804+ resource_size_t size, unsigned long flags)
1805+{
1806+ if (flags & GFR_DESCENDING)
1807+ return addr > size && addr >= base->start;
1808+ /*
1809+ * In the ascend case be careful that the last increment by
1810+ * @size did not wrap 0.
1811+ */
1812+ return addr > addr - size &&
1813+ addr <= min_t(resource_size_t, base->end,
1814+ (1ULL << MAX_PHYSMEM_BITS) - 1);
1815+}
1816+
1817+static resource_size_t gfr_next(resource_size_t addr, resource_size_t size,
1818+ unsigned long flags)
17791819 {
1780− resource_size_t end, addr;
1820+ if (flags & GFR_DESCENDING)
1821+ return addr - size;
1822+ return addr + size;
1823+}
1824+
1825+static void remove_free_mem_region(void *_res)
1826+{
1827+ struct resource *res = _res;
1828+
1829+ if (res->parent)
1830+ remove_resource(res);
1831+ free_resource(res);
1832+}
1833+
1834+static struct resource *
1835+get_free_mem_region(struct device *dev, struct resource *base,
1836+ resource_size_t size, const unsigned long align,
1837+ const char *name, const unsigned long desc,
1838+ const unsigned long flags)
1839+{
1840+ resource_size_t addr;
17811841 struct resource *res;
17821842 struct region_devres *dr = NULL;
17831843
1784− size = ALIGN(size, 1UL << PA_SECTION_SHIFT);
1785− end = min_t(unsigned long, base->end, (1UL << MAX_PHYSMEM_BITS) - 1);
1786− addr = end - size + 1UL;
1844+ size = ALIGN(size, align);
17871845
17881846 res = alloc_resource(GFP_KERNEL);
17891847 if (!res)
17901848 return ERR_PTR(-ENOMEM);
17911849
1792− if (dev) {
1850+ if (dev && (flags & GFR_REQUEST_REGION)) {
17931851 dr = devres_alloc(devm_region_release,
17941852 sizeof(struct region_devres), GFP_KERNEL);
17951853 if (!dr) {
17961854 free_resource(res);
17971855 return ERR_PTR(-ENOMEM);
17981856 }
1857+ } else if (dev) {
1858+ if (devm_add_action_or_reset(dev, remove_free_mem_region, res))
1859+ return ERR_PTR(-ENOMEM);
17991860 }
18001861
18011862 write_lock(&resource_lock);
1802− for (; addr > size && addr >= base->start; addr -= size) {
1803− if (__region_intersects(addr, size, 0, IORES_DESC_NONE) !=
1804− REGION_DISJOINT)
1863+ for (addr = gfr_start(base, size, align, flags);
1864+ gfr_continue(base, addr, size, flags);
1865+ addr = gfr_next(addr, size, flags)) {
1866+ if (__region_intersects(base, addr, size, 0, IORES_DESC_NONE) !=
1867+ REGION_DISJOINT)
18051868 continue;
18061869
1807− if (__request_region_locked(res, &iomem_resource, addr, size,
1808− name, 0))
1809− break;
1870+ if (flags & GFR_REQUEST_REGION) {
1871+ if (__request_region_locked(res, &iomem_resource, addr,
1872+ size, name, 0))
1873+ break;
18101874
1811− if (dev) {
1812− dr->parent = &iomem_resource;
1813− dr->start = addr;
1814− dr->n = size;
1815− devres_add(dev, dr);
1816− }
1875+ if (dev) {
1876+ dr->parent = &iomem_resource;
1877+ dr->start = addr;
1878+ dr->n = size;
1879+ devres_add(dev, dr);
1880+ }
18171881
1818− res->desc = IORES_DESC_DEVICE_PRIVATE_MEMORY;
1819− write_unlock(&resource_lock);
1882+ res->desc = desc;
1883+ write_unlock(&resource_lock);
1884+
1885+
1886+ /*
1887+ * A driver is claiming this region so revoke any
1888+ * mappings.
1889+ */
1890+ revoke_iomem(res);
1891+ } else {
1892+ res->start = addr;
1893+ res->end = addr + size - 1;
1894+ res->name = name;
1895+ res->desc = desc;
1896+ res->flags = IORESOURCE_MEM;
1897+
1898+ /*
1899+ * Only succeed if the resource hosts an exclusive
1900+ * range after the insert
1901+ */
1902+ if (__insert_resource(base, res) || res->child)
1903+ break;
1904+
1905+ write_unlock(&resource_lock);
1906+ }
18201907
1821− /*
1822− * A driver is claiming this region so revoke any mappings.
1823− */
1824− revoke_iomem(res);
18251908 return res;
18261909 }
18271910 write_unlock(&resource_lock);
18281911
1829− free_resource(res);
1830− if (dr)
1912+ if (flags & GFR_REQUEST_REGION) {
1913+ free_resource(res);
18311914 devres_free(dr);
1915+ } else if (dev)
1916+ devm_release_action(dev, remove_free_mem_region, res);
18321917
18331918 return ERR_PTR(-ERANGE);
18341919 }
@@ -1847,18 +1932,48 @@ static struct resource *__request_free_mem_region(struct device *dev, · 12 unmodified lines
18471932 struct resource *devm_request_free_mem_region(struct device *dev,
18481933 struct resource *base, unsigned long size)
18491934 {
1850− return __request_free_mem_region(dev, base, size, dev_name(dev));
1935+ unsigned long flags = GFR_DESCENDING | GFR_REQUEST_REGION;
1936+
1937+ return get_free_mem_region(dev, base, size, GFR_DEFAULT_ALIGN,
1938+ dev_name(dev),
1939+ IORES_DESC_DEVICE_PRIVATE_MEMORY, flags);
18511940 }
18521941 EXPORT_SYMBOL_GPL(devm_request_free_mem_region);
18531942
18541943 struct resource *request_free_mem_region(struct resource *base,
18551944 unsigned long size, const char *name)
18561945 {
1857− return __request_free_mem_region(NULL, base, size, name);
1946+ unsigned long flags = GFR_DESCENDING | GFR_REQUEST_REGION;
1947+
1948+ return get_free_mem_region(NULL, base, size, GFR_DEFAULT_ALIGN, name,
1949+ IORES_DESC_DEVICE_PRIVATE_MEMORY, flags);
18581950 }
18591951 EXPORT_SYMBOL_GPL(request_free_mem_region);
18601952
1861−#endif /* CONFIG_DEVICE_PRIVATE */
1953+/**
1954+ * alloc_free_mem_region - find a free region relative to @base
1955+ * @base: resource that will parent the new resource
1956+ * @size: size in bytes of memory to allocate from @base
1957+ * @align: alignment requirements for the allocation
1958+ * @name: resource name
1959+ *
1960+ * Buses like CXL, that can dynamically instantiate new memory regions,
1961+ * need a method to allocate physical address space for those regions.
1962+ * Allocate and insert a new resource to cover a free, unclaimed by a
1963+ * descendant of @base, range in the span of @base.
1964+ */
1965+struct resource *alloc_free_mem_region(struct resource *base,
1966+ unsigned long size, unsigned long align,
1967+ const char *name)
1968+{
1969+ /* Default of ascending direction and insert resource */
1970+ unsigned long flags = 0;
1971+
1972+ return get_free_mem_region(NULL, base, size, align, name,
1973+ IORES_DESC_NONE, flags);
1974+}
1975+EXPORT_SYMBOL_NS_GPL(alloc_free_mem_region, CXL);
1976+#endif /* CONFIG_GET_FREE_REGION */
18621977
18631978 static int __init strict_iomem(char *str)
18641979 {