@@ -489,8 +489,9 @@ int __weak page_is_ram(unsigned long pfn)
489
489
}
490
490
EXPORT_SYMBOL_GPL (page_is_ram );
491
491
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 )
494
495
{
495
496
struct resource res ;
496
497
int type = 0 ; int other = 0 ;
@@ -499,7 +500,7 @@ static int __region_intersects(resource_size_t start, size_t size,
499
500
res .start = start ;
500
501
res .end = start + size - 1 ;
501
502
502
- for (p = iomem_resource . child ; p ; p = p -> sibling ) {
503
+ for (p = parent -> child ; p ; p = p -> sibling ) {
503
504
bool is_type = (((p -> flags & flags ) == flags ) &&
504
505
((desc == IORES_DESC_NONE ) ||
505
506
(desc == p -> desc )));
@@ -543,7 +544,7 @@ int region_intersects(resource_size_t start, size_t size, unsigned long flags,
543
544
int ret ;
544
545
545
546
read_lock (& resource_lock );
546
- ret = __region_intersects (start , size , flags , desc );
547
+ ret = __region_intersects (& iomem_resource , start , size , flags , desc );
547
548
read_unlock (& resource_lock );
548
549
549
550
return ret ;
@@ -1780,62 +1781,139 @@ void resource_list_free(struct list_head *head)
1780
1781
}
1781
1782
EXPORT_SYMBOL (resource_list_free );
1782
1783
1783
- #ifdef CONFIG_DEVICE_PRIVATE
1784
- static struct resource * __request_free_mem_region (struct device * dev ,
1785
- 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 )
1819
+ {
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 )
1786
1839
{
1787
- resource_size_t end , addr ;
1840
+ resource_size_t addr ;
1788
1841
struct resource * res ;
1789
1842
struct region_devres * dr = NULL ;
1790
1843
1791
- size = ALIGN (size , 1UL << PA_SECTION_SHIFT );
1792
- end = min_t (unsigned long , base -> end , (1UL << MAX_PHYSMEM_BITS ) - 1 );
1793
- addr = end - size + 1UL ;
1844
+ size = ALIGN (size , align );
1794
1845
1795
1846
res = alloc_resource (GFP_KERNEL );
1796
1847
if (!res )
1797
1848
return ERR_PTR (- ENOMEM );
1798
1849
1799
- if (dev ) {
1850
+ if (dev && ( flags & GFR_REQUEST_REGION ) ) {
1800
1851
dr = devres_alloc (devm_region_release ,
1801
1852
sizeof (struct region_devres ), GFP_KERNEL );
1802
1853
if (!dr ) {
1803
1854
free_resource (res );
1804
1855
return ERR_PTR (- ENOMEM );
1805
1856
}
1857
+ } else if (dev ) {
1858
+ if (devm_add_action_or_reset (dev , remove_free_mem_region , res ))
1859
+ return ERR_PTR (- ENOMEM );
1806
1860
}
1807
1861
1808
1862
write_lock (& resource_lock );
1809
- for (; addr > size && addr >= base -> start ; addr -= size ) {
1810
- if (__region_intersects (addr , size , 0 , IORES_DESC_NONE ) !=
1811
- 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 )
1812
1868
continue ;
1813
1869
1814
- if (__request_region_locked (res , & iomem_resource , addr , size ,
1815
- name , 0 ))
1816
- break ;
1870
+ if (flags & GFR_REQUEST_REGION ) {
1871
+ if (__request_region_locked (res , & iomem_resource , addr ,
1872
+ size , name , 0 ))
1873
+ break ;
1817
1874
1818
- if (dev ) {
1819
- dr -> parent = & iomem_resource ;
1820
- dr -> start = addr ;
1821
- dr -> n = size ;
1822
- devres_add (dev , dr );
1823
- }
1875
+ if (dev ) {
1876
+ dr -> parent = & iomem_resource ;
1877
+ dr -> start = addr ;
1878
+ dr -> n = size ;
1879
+ devres_add (dev , dr );
1880
+ }
1824
1881
1825
- res -> desc = IORES_DESC_DEVICE_PRIVATE_MEMORY ;
1826
- 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
+ }
1827
1907
1828
- /*
1829
- * A driver is claiming this region so revoke any mappings.
1830
- */
1831
- revoke_iomem (res );
1832
1908
return res ;
1833
1909
}
1834
1910
write_unlock (& resource_lock );
1835
1911
1836
- free_resource ( res );
1837
- if ( dr )
1912
+ if ( flags & GFR_REQUEST_REGION ) {
1913
+ free_resource ( res );
1838
1914
devres_free (dr );
1915
+ } else if (dev )
1916
+ devm_release_action (dev , remove_free_mem_region , res );
1839
1917
1840
1918
return ERR_PTR (- ERANGE );
1841
1919
}
@@ -1854,18 +1932,48 @@ static struct resource *__request_free_mem_region(struct device *dev,
1854
1932
struct resource * devm_request_free_mem_region (struct device * dev ,
1855
1933
struct resource * base , unsigned long size )
1856
1934
{
1857
- 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 );
1858
1940
}
1859
1941
EXPORT_SYMBOL_GPL (devm_request_free_mem_region );
1860
1942
1861
1943
struct resource * request_free_mem_region (struct resource * base ,
1862
1944
unsigned long size , const char * name )
1863
1945
{
1864
- 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 );
1865
1950
}
1866
1951
EXPORT_SYMBOL_GPL (request_free_mem_region );
1867
1952
1868
- #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 */
1869
1977
1870
1978
static int __init strict_iomem (char * str )
1871
1979
{
0 commit comments