2022-05-31 18:04:11 +08:00
// SPDX-License-Identifier: GPL-2.0
/*
* acpi . c - Architecture - Specific Low - Level ACPI Boot Support
*
* Author : Jianmin Lv < lvjianmin @ loongson . cn >
* Huacai Chen < chenhuacai @ loongson . cn >
* Copyright ( C ) 2020 - 2022 Loongson Technology Corporation Limited
*/
# include <linux/init.h>
# include <linux/acpi.h>
# include <linux/irq.h>
# include <linux/irqdomain.h>
# include <linux/memblock.h>
# include <linux/serial_core.h>
# include <asm/io.h>
2022-05-31 18:04:12 +08:00
# include <asm/numa.h>
2022-05-31 18:04:11 +08:00
# include <asm/loongson.h>
int acpi_disabled ;
EXPORT_SYMBOL ( acpi_disabled ) ;
int acpi_noirq ;
int acpi_pci_disabled ;
EXPORT_SYMBOL ( acpi_pci_disabled ) ;
int acpi_strict = 1 ; /* We have no workarounds on LoongArch */
int num_processors ;
int disabled_cpus ;
u64 acpi_saved_sp ;
# define MAX_CORE_PIC 256
# define PREFIX "ACPI: "
void __init __iomem * __acpi_map_table ( unsigned long phys , unsigned long size )
{
if ( ! phys | | ! size )
return NULL ;
return early_memremap ( phys , size ) ;
}
void __init __acpi_unmap_table ( void __iomem * map , unsigned long size )
{
if ( ! map | | ! size )
return ;
early_memunmap ( map , size ) ;
}
2022-09-02 22:33:42 +08:00
void __iomem * acpi_os_ioremap ( acpi_physical_address phys , acpi_size size )
2022-05-31 18:04:11 +08:00
{
if ( ! memblock_is_memory ( phys ) )
return ioremap ( phys , size ) ;
else
return ioremap_cache ( phys , size ) ;
}
void __init acpi_boot_table_init ( void )
{
/*
* If acpi_disabled , bail out
*/
if ( acpi_disabled )
return ;
/*
* Initialize the ACPI boot - time table parser .
*/
if ( acpi_table_init ( ) ) {
disable_acpi ( ) ;
return ;
}
}
LoongArch: Fix the !CONFIG_SMP build
1, We assume arch/loongarch/include/asm/smp.h be included in include/
linux/smp.h is valid and the reverse inclusion isn't. So remove the
<linux/smp.h> in arch/loongarch/include/asm/smp.h.
2, arch/loongarch/include/asm/smp.h is only needed when CONFIG_SMP,
and setup.c include it only because it need plat_smp_setup(). So,
reorganize setup.c & smp.h, and then remove <asm/smp.h> in setup.c.
3, Fix cacheinfo.c and percpu.h build error by adding the missing header
files when !CONFIG_SMP.
4, Fix acpi.c build error by adding CONFIG_SMP guards.
5, Move irq_stat definition from smp.c to irq.c and fix its declaration.
6, Select CONFIG_SMP for CONFIG_NUMA, similar as other architectures do.
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2022-06-05 16:19:53 +08:00
# ifdef CONFIG_SMP
2022-05-31 18:04:12 +08:00
static int set_processor_mask ( u32 id , u32 flags )
{
int cpu , cpuid = id ;
if ( num_processors > = nr_cpu_ids ) {
pr_warn ( PREFIX " nr_cpus/possible_cpus limit of %i reached. "
" processor 0x%x ignored. \n " , nr_cpu_ids , cpuid ) ;
return - ENODEV ;
}
if ( cpuid = = loongson_sysconf . boot_cpu_id )
cpu = 0 ;
else
cpu = cpumask_next_zero ( - 1 , cpu_present_mask ) ;
if ( flags & ACPI_MADT_ENABLED ) {
num_processors + + ;
set_cpu_possible ( cpu , true ) ;
set_cpu_present ( cpu , true ) ;
__cpu_number_map [ cpuid ] = cpu ;
__cpu_logical_map [ cpu ] = cpuid ;
} else
disabled_cpus + + ;
return cpu ;
}
LoongArch: Fix the !CONFIG_SMP build
1, We assume arch/loongarch/include/asm/smp.h be included in include/
linux/smp.h is valid and the reverse inclusion isn't. So remove the
<linux/smp.h> in arch/loongarch/include/asm/smp.h.
2, arch/loongarch/include/asm/smp.h is only needed when CONFIG_SMP,
and setup.c include it only because it need plat_smp_setup(). So,
reorganize setup.c & smp.h, and then remove <asm/smp.h> in setup.c.
3, Fix cacheinfo.c and percpu.h build error by adding the missing header
files when !CONFIG_SMP.
4, Fix acpi.c build error by adding CONFIG_SMP guards.
5, Move irq_stat definition from smp.c to irq.c and fix its declaration.
6, Select CONFIG_SMP for CONFIG_NUMA, similar as other architectures do.
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2022-06-05 16:19:53 +08:00
# endif
2022-05-31 18:04:12 +08:00
2022-07-19 10:53:13 +08:00
static int __init
acpi_parse_processor ( union acpi_subtable_headers * header , const unsigned long end )
{
struct acpi_madt_core_pic * processor = NULL ;
processor = ( struct acpi_madt_core_pic * ) header ;
if ( BAD_MADT_ENTRY ( processor , end ) )
return - EINVAL ;
acpi_table_print_madt_entry ( & header - > common ) ;
# ifdef CONFIG_SMP
set_processor_mask ( processor - > core_id , processor - > flags ) ;
# endif
return 0 ;
}
static int __init
acpi_parse_eio_master ( union acpi_subtable_headers * header , const unsigned long end )
{
static int core = 0 ;
struct acpi_madt_eio_pic * eiointc = NULL ;
eiointc = ( struct acpi_madt_eio_pic * ) header ;
if ( BAD_MADT_ENTRY ( eiointc , end ) )
return - EINVAL ;
core = eiointc - > node * CORES_PER_EIO_NODE ;
set_bit ( core , & ( loongson_sysconf . cores_io_master ) ) ;
return 0 ;
}
2022-05-31 18:04:11 +08:00
static void __init acpi_process_madt ( void )
{
LoongArch: Fix the !CONFIG_SMP build
1, We assume arch/loongarch/include/asm/smp.h be included in include/
linux/smp.h is valid and the reverse inclusion isn't. So remove the
<linux/smp.h> in arch/loongarch/include/asm/smp.h.
2, arch/loongarch/include/asm/smp.h is only needed when CONFIG_SMP,
and setup.c include it only because it need plat_smp_setup(). So,
reorganize setup.c & smp.h, and then remove <asm/smp.h> in setup.c.
3, Fix cacheinfo.c and percpu.h build error by adding the missing header
files when !CONFIG_SMP.
4, Fix acpi.c build error by adding CONFIG_SMP guards.
5, Move irq_stat definition from smp.c to irq.c and fix its declaration.
6, Select CONFIG_SMP for CONFIG_NUMA, similar as other architectures do.
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2022-06-05 16:19:53 +08:00
# ifdef CONFIG_SMP
2022-05-31 18:04:12 +08:00
int i ;
for ( i = 0 ; i < NR_CPUS ; i + + ) {
__cpu_number_map [ i ] = - 1 ;
__cpu_logical_map [ i ] = - 1 ;
}
LoongArch: Fix the !CONFIG_SMP build
1, We assume arch/loongarch/include/asm/smp.h be included in include/
linux/smp.h is valid and the reverse inclusion isn't. So remove the
<linux/smp.h> in arch/loongarch/include/asm/smp.h.
2, arch/loongarch/include/asm/smp.h is only needed when CONFIG_SMP,
and setup.c include it only because it need plat_smp_setup(). So,
reorganize setup.c & smp.h, and then remove <asm/smp.h> in setup.c.
3, Fix cacheinfo.c and percpu.h build error by adding the missing header
files when !CONFIG_SMP.
4, Fix acpi.c build error by adding CONFIG_SMP guards.
5, Move irq_stat definition from smp.c to irq.c and fix its declaration.
6, Select CONFIG_SMP for CONFIG_NUMA, similar as other architectures do.
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2022-06-05 16:19:53 +08:00
# endif
2022-07-19 10:53:13 +08:00
acpi_table_parse_madt ( ACPI_MADT_TYPE_CORE_PIC ,
acpi_parse_processor , MAX_CORE_PIC ) ;
acpi_table_parse_madt ( ACPI_MADT_TYPE_EIO_PIC ,
acpi_parse_eio_master , MAX_IO_PICS ) ;
2022-05-31 18:04:12 +08:00
2022-05-31 18:04:11 +08:00
loongson_sysconf . nr_cpus = num_processors ;
}
int __init acpi_boot_init ( void )
{
/*
* If acpi_disabled , bail out
*/
if ( acpi_disabled )
return - 1 ;
loongson_sysconf . boot_cpu_id = read_csr_cpuid ( ) ;
/*
* Process the Multiple APIC Description Table ( MADT ) , if present
*/
acpi_process_madt ( ) ;
/* Do not enable ACPI SPCR console by default */
acpi_parse_spcr ( earlycon_acpi_spcr_enable , false ) ;
return 0 ;
}
2022-05-31 18:04:12 +08:00
# ifdef CONFIG_ACPI_NUMA
static __init int setup_node ( int pxm )
{
return acpi_map_pxm_to_node ( pxm ) ;
}
/*
* Callback for SLIT parsing . pxm_to_node ( ) returns NUMA_NO_NODE for
* I / O localities since SRAT does not list them . I / O localities are
* not supported at this point .
*/
unsigned int numa_distance_cnt ;
static inline unsigned int get_numa_distances_cnt ( struct acpi_table_slit * slit )
{
return slit - > locality_count ;
}
void __init numa_set_distance ( int from , int to , int distance )
{
if ( ( u8 ) distance ! = distance | | ( from = = to & & distance ! = LOCAL_DISTANCE ) ) {
pr_warn_once ( " Warning: invalid distance parameter, from=%d to=%d distance=%d \n " ,
from , to , distance ) ;
return ;
}
node_distances [ from ] [ to ] = distance ;
}
/* Callback for Proximity Domain -> CPUID mapping */
void __init
acpi_numa_processor_affinity_init ( struct acpi_srat_cpu_affinity * pa )
{
int pxm , node ;
if ( srat_disabled ( ) )
return ;
if ( pa - > header . length ! = sizeof ( struct acpi_srat_cpu_affinity ) ) {
bad_srat ( ) ;
return ;
}
if ( ( pa - > flags & ACPI_SRAT_CPU_ENABLED ) = = 0 )
return ;
pxm = pa - > proximity_domain_lo ;
if ( acpi_srat_revision > = 2 ) {
pxm | = ( pa - > proximity_domain_hi [ 0 ] < < 8 ) ;
pxm | = ( pa - > proximity_domain_hi [ 1 ] < < 16 ) ;
pxm | = ( pa - > proximity_domain_hi [ 2 ] < < 24 ) ;
}
node = setup_node ( pxm ) ;
if ( node < 0 ) {
pr_err ( " SRAT: Too many proximity domains %x \n " , pxm ) ;
bad_srat ( ) ;
return ;
}
if ( pa - > apic_id > = CONFIG_NR_CPUS ) {
pr_info ( " SRAT: PXM %u -> CPU 0x%02x -> Node %u skipped apicid that is too big \n " ,
pxm , pa - > apic_id , node ) ;
return ;
}
early_numa_add_cpu ( pa - > apic_id , node ) ;
set_cpuid_to_node ( pa - > apic_id , node ) ;
node_set ( node , numa_nodes_parsed ) ;
pr_info ( " SRAT: PXM %u -> CPU 0x%02x -> Node %u \n " , pxm , pa - > apic_id , node ) ;
}
void __init acpi_numa_arch_fixup ( void ) { }
# endif
2022-05-31 18:04:11 +08:00
void __init arch_reserve_mem_area ( acpi_physical_address addr , size_t size )
{
memblock_reserve ( addr , size ) ;
}
2022-05-31 18:04:12 +08:00
# ifdef CONFIG_ACPI_HOTPLUG_CPU
# include <acpi/processor.h>
2022-05-31 18:04:12 +08:00
static int __ref acpi_map_cpu2node ( acpi_handle handle , int cpu , int physid )
{
# ifdef CONFIG_ACPI_NUMA
int nid ;
nid = acpi_get_node ( handle ) ;
if ( nid ! = NUMA_NO_NODE ) {
set_cpuid_to_node ( physid , nid ) ;
node_set ( nid , numa_nodes_parsed ) ;
set_cpu_numa_node ( cpu , nid ) ;
cpumask_set_cpu ( cpu , cpumask_of_node ( nid ) ) ;
}
# endif
return 0 ;
}
2022-05-31 18:04:12 +08:00
int acpi_map_cpu ( acpi_handle handle , phys_cpuid_t physid , u32 acpi_id , int * pcpu )
{
int cpu ;
cpu = set_processor_mask ( physid , ACPI_MADT_ENABLED ) ;
if ( cpu < 0 ) {
pr_info ( PREFIX " Unable to map lapic to logical cpu number \n " ) ;
return cpu ;
}
2022-05-31 18:04:12 +08:00
acpi_map_cpu2node ( handle , cpu , physid ) ;
2022-05-31 18:04:12 +08:00
* pcpu = cpu ;
return 0 ;
}
EXPORT_SYMBOL ( acpi_map_cpu ) ;
int acpi_unmap_cpu ( int cpu )
{
2022-05-31 18:04:12 +08:00
# ifdef CONFIG_ACPI_NUMA
set_cpuid_to_node ( cpu_logical_map ( cpu ) , NUMA_NO_NODE ) ;
# endif
2022-05-31 18:04:12 +08:00
set_cpu_present ( cpu , false ) ;
num_processors - - ;
pr_info ( " cpu%d hot remove! \n " , cpu ) ;
return 0 ;
}
EXPORT_SYMBOL ( acpi_unmap_cpu ) ;
# endif /* CONFIG_ACPI_HOTPLUG_CPU */