Skip to content

Commit 71610ab

Browse files
bibo-maochenhuacai
authored andcommitted
LoongArch: Remove clock setting during cpu hotplug stage
On physical machine we can save power by disabling clock of hot removed cpu. However as different platforms require different methods to configure clocks, the code is platform-specific, and probably belongs to firmware/pmu or cpu regulator, rather than generic arch/loongarch code. Also, there is no such register on QEMU virt machine since the clock/frequency regulation is not emulated. This patch removes the hard-coded clock register accesses in generic LoongArch cpu hotplug flow. Reviewed-by: WANG Xuerui <[email protected]> Signed-off-by: Bibo Mao <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent f62b762 commit 71610ab

File tree

2 files changed

+13
-101
lines changed

2 files changed

+13
-101
lines changed

arch/loongarch/kernel/smp.c

Lines changed: 13 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -278,116 +278,29 @@ void loongson3_cpu_die(unsigned int cpu)
278278
mb();
279279
}
280280

281-
/*
282-
* The target CPU should go to XKPRANGE (uncached area) and flush
283-
* ICache/DCache/VCache before the control CPU can safely disable its clock.
284-
*/
285-
static void loongson3_play_dead(int *state_addr)
281+
void play_dead(void)
286282
{
287-
register int val;
288-
register void *addr;
283+
register uint64_t addr;
289284
register void (*init_fn)(void);
290285

291-
__asm__ __volatile__(
292-
" li.d %[addr], 0x8000000000000000\n"
293-
"1: cacop 0x8, %[addr], 0 \n" /* flush ICache */
294-
" cacop 0x8, %[addr], 1 \n"
295-
" cacop 0x8, %[addr], 2 \n"
296-
" cacop 0x8, %[addr], 3 \n"
297-
" cacop 0x9, %[addr], 0 \n" /* flush DCache */
298-
" cacop 0x9, %[addr], 1 \n"
299-
" cacop 0x9, %[addr], 2 \n"
300-
" cacop 0x9, %[addr], 3 \n"
301-
" addi.w %[sets], %[sets], -1 \n"
302-
" addi.d %[addr], %[addr], 0x40 \n"
303-
" bnez %[sets], 1b \n"
304-
" li.d %[addr], 0x8000000000000000\n"
305-
"2: cacop 0xa, %[addr], 0 \n" /* flush VCache */
306-
" cacop 0xa, %[addr], 1 \n"
307-
" cacop 0xa, %[addr], 2 \n"
308-
" cacop 0xa, %[addr], 3 \n"
309-
" cacop 0xa, %[addr], 4 \n"
310-
" cacop 0xa, %[addr], 5 \n"
311-
" cacop 0xa, %[addr], 6 \n"
312-
" cacop 0xa, %[addr], 7 \n"
313-
" cacop 0xa, %[addr], 8 \n"
314-
" cacop 0xa, %[addr], 9 \n"
315-
" cacop 0xa, %[addr], 10 \n"
316-
" cacop 0xa, %[addr], 11 \n"
317-
" cacop 0xa, %[addr], 12 \n"
318-
" cacop 0xa, %[addr], 13 \n"
319-
" cacop 0xa, %[addr], 14 \n"
320-
" cacop 0xa, %[addr], 15 \n"
321-
" addi.w %[vsets], %[vsets], -1 \n"
322-
" addi.d %[addr], %[addr], 0x40 \n"
323-
" bnez %[vsets], 2b \n"
324-
" li.w %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */
325-
" st.w %[val], %[state_addr], 0 \n"
326-
" dbar 0 \n"
327-
" cacop 0x11, %[state_addr], 0 \n" /* flush entry of *state_addr */
328-
: [addr] "=&r" (addr), [val] "=&r" (val)
329-
: [state_addr] "r" (state_addr),
330-
[sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
331-
[vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
332-
286+
idle_task_exit();
333287
local_irq_enable();
334-
change_csr_ecfg(ECFG0_IM, ECFGF_IPI);
288+
set_csr_ecfg(ECFGF_IPI);
289+
__this_cpu_write(cpu_state, CPU_DEAD);
290+
291+
__smp_mb();
292+
do {
293+
__asm__ __volatile__("idle 0\n\t");
294+
addr = iocsr_read64(LOONGARCH_IOCSR_MBUF0);
295+
} while (addr == 0);
335296

336-
__asm__ __volatile__(
337-
" idle 0 \n"
338-
" li.w $t0, 0x1020 \n"
339-
" iocsrrd.d %[init_fn], $t0 \n" /* Get init PC */
340-
: [init_fn] "=&r" (addr)
341-
: /* No Input */
342-
: "a0");
343-
init_fn = __va(addr);
297+
init_fn = (void *)TO_CACHE(addr);
298+
iocsr_write32(0xffffffff, LOONGARCH_IOCSR_IPI_CLEAR);
344299

345300
init_fn();
346301
unreachable();
347302
}
348303

349-
void play_dead(void)
350-
{
351-
int *state_addr;
352-
unsigned int cpu = smp_processor_id();
353-
void (*play_dead_uncached)(int *s);
354-
355-
idle_task_exit();
356-
play_dead_uncached = (void *)TO_UNCACHE(__pa((unsigned long)loongson3_play_dead));
357-
state_addr = &per_cpu(cpu_state, cpu);
358-
mb();
359-
play_dead_uncached(state_addr);
360-
}
361-
362-
static int loongson3_enable_clock(unsigned int cpu)
363-
{
364-
uint64_t core_id = cpu_data[cpu].core;
365-
uint64_t package_id = cpu_data[cpu].package;
366-
367-
LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
368-
369-
return 0;
370-
}
371-
372-
static int loongson3_disable_clock(unsigned int cpu)
373-
{
374-
uint64_t core_id = cpu_data[cpu].core;
375-
uint64_t package_id = cpu_data[cpu].package;
376-
377-
LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
378-
379-
return 0;
380-
}
381-
382-
static int register_loongson3_notifier(void)
383-
{
384-
return cpuhp_setup_state_nocalls(CPUHP_LOONGARCH_SOC_PREPARE,
385-
"loongarch/loongson:prepare",
386-
loongson3_enable_clock,
387-
loongson3_disable_clock);
388-
}
389-
early_initcall(register_loongson3_notifier);
390-
391304
#endif
392305

393306
/*

include/linux/cpuhotplug.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ enum cpuhp_state {
130130
CPUHP_ZCOMP_PREPARE,
131131
CPUHP_TIMERS_PREPARE,
132132
CPUHP_MIPS_SOC_PREPARE,
133-
CPUHP_LOONGARCH_SOC_PREPARE,
134133
CPUHP_BP_PREPARE_DYN,
135134
CPUHP_BP_PREPARE_DYN_END = CPUHP_BP_PREPARE_DYN + 20,
136135
CPUHP_BRINGUP_CPU,

0 commit comments

Comments
 (0)