smp.c (2540B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * PS3 SMP routines. 4 * 5 * Copyright (C) 2006 Sony Computer Entertainment Inc. 6 * Copyright 2006 Sony Corp. 7 */ 8 9#include <linux/kernel.h> 10#include <linux/smp.h> 11 12#include <asm/machdep.h> 13#include <asm/udbg.h> 14 15#include "platform.h" 16 17#if defined(DEBUG) 18#define DBG udbg_printf 19#else 20#define DBG pr_debug 21#endif 22 23/** 24 * ps3_ipi_virqs - a per cpu array of virqs for ipi use 25 */ 26 27#define MSG_COUNT 4 28static DEFINE_PER_CPU(unsigned int [MSG_COUNT], ps3_ipi_virqs); 29 30static void ps3_smp_message_pass(int cpu, int msg) 31{ 32 int result; 33 unsigned int virq; 34 35 if (msg >= MSG_COUNT) { 36 DBG("%s:%d: bad msg: %d\n", __func__, __LINE__, msg); 37 return; 38 } 39 40 virq = per_cpu(ps3_ipi_virqs, cpu)[msg]; 41 result = ps3_send_event_locally(virq); 42 43 if (result) 44 DBG("%s:%d: ps3_send_event_locally(%d, %d) failed" 45 " (%d)\n", __func__, __LINE__, cpu, msg, result); 46} 47 48static void __init ps3_smp_probe(void) 49{ 50 int cpu; 51 52 for (cpu = 0; cpu < 2; cpu++) { 53 int result; 54 unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu); 55 int i; 56 57 DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); 58 59 /* 60 * Check assumptions on ps3_ipi_virqs[] indexing. If this 61 * check fails, then a different mapping of PPC_MSG_ 62 * to index needs to be setup. 63 */ 64 65 BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION != 0); 66 BUILD_BUG_ON(PPC_MSG_RESCHEDULE != 1); 67 BUILD_BUG_ON(PPC_MSG_TICK_BROADCAST != 2); 68 BUILD_BUG_ON(PPC_MSG_NMI_IPI != 3); 69 70 for (i = 0; i < MSG_COUNT; i++) { 71 result = ps3_event_receive_port_setup(cpu, &virqs[i]); 72 73 if (result) 74 continue; 75 76 DBG("%s:%d: (%d, %d) => virq %u\n", 77 __func__, __LINE__, cpu, i, virqs[i]); 78 79 result = smp_request_message_ipi(virqs[i], i); 80 81 if (result) 82 virqs[i] = 0; 83 else 84 ps3_register_ipi_irq(cpu, virqs[i]); 85 } 86 87 ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_NMI_IPI]); 88 89 DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); 90 } 91} 92 93void ps3_smp_cleanup_cpu(int cpu) 94{ 95 unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu); 96 int i; 97 98 DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); 99 100 for (i = 0; i < MSG_COUNT; i++) { 101 /* Can't call free_irq from interrupt context. */ 102 ps3_event_receive_port_destroy(virqs[i]); 103 virqs[i] = 0; 104 } 105 106 DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); 107} 108 109static struct smp_ops_t ps3_smp_ops = { 110 .probe = ps3_smp_probe, 111 .message_pass = ps3_smp_message_pass, 112 .kick_cpu = smp_generic_kick_cpu, 113}; 114 115void __init smp_init_ps3(void) 116{ 117 DBG(" -> %s\n", __func__); 118 smp_ops = &ps3_smp_ops; 119 DBG(" <- %s\n", __func__); 120}