2019-05-27 08:55:15 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2006-11-23 00:46:51 +01:00
/*
* PS3 SMP routines .
*
* Copyright ( C ) 2006 Sony Computer Entertainment Inc .
* Copyright 2006 Sony Corp .
*/
# include <linux/kernel.h>
# include <linux/smp.h>
# include <asm/machdep.h>
# include <asm/udbg.h>
# include "platform.h"
# if defined(DEBUG)
2007-06-16 07:19:23 +10:00
# define DBG udbg_printf
2006-11-23 00:46:51 +01:00
# else
2007-06-16 07:19:23 +10:00
# define DBG pr_debug
2006-11-23 00:46:51 +01:00
# endif
/**
2007-06-16 07:17:42 +10:00
* ps3_ipi_virqs - a per cpu array of virqs for ipi use
2006-11-23 00:46:51 +01:00
*/
# define MSG_COUNT 4
2009-06-24 15:13:45 +09:00
static DEFINE_PER_CPU ( unsigned int [ MSG_COUNT ] , ps3_ipi_virqs ) ;
2006-11-23 00:46:51 +01:00
2011-05-10 19:29:10 +00:00
static void ps3_smp_message_pass ( int cpu , int msg )
2006-11-23 00:46:51 +01:00
{
int result ;
unsigned int virq ;
if ( msg > = MSG_COUNT ) {
DBG ( " %s:%d: bad msg: %d \n " , __func__ , __LINE__ , msg ) ;
return ;
}
2011-05-10 19:29:10 +00:00
virq = per_cpu ( ps3_ipi_virqs , cpu ) [ msg ] ;
2006-11-23 00:46:51 +01:00
result = ps3_send_event_locally ( virq ) ;
if ( result )
DBG ( " %s:%d: ps3_send_event_locally(%d, %d) failed "
2011-05-10 19:29:10 +00:00
" (%d) \n " , __func__ , __LINE__ , cpu , msg , result ) ;
2006-11-23 00:46:51 +01:00
}
2015-04-04 19:28:50 +11:00
static void __init ps3_smp_probe ( void )
2006-11-23 00:46:51 +01:00
{
2011-11-08 12:38:21 +00:00
int cpu ;
2006-11-23 00:46:51 +01:00
2011-11-08 12:38:21 +00:00
for ( cpu = 0 ; cpu < 2 ; cpu + + ) {
int result ;
unsigned int * virqs = per_cpu ( ps3_ipi_virqs , cpu ) ;
int i ;
2006-11-23 00:46:51 +01:00
2011-11-08 12:38:21 +00:00
DBG ( " -> %s:%d: (%d) \n " , __func__ , __LINE__ , cpu ) ;
2006-11-23 00:46:51 +01:00
2011-11-08 12:38:21 +00:00
/*
* Check assumptions on ps3_ipi_virqs [ ] indexing . If this
* check fails , then a different mapping of PPC_MSG_
* to index needs to be setup .
*/
2006-11-23 00:46:51 +01:00
2011-11-08 12:38:21 +00:00
BUILD_BUG_ON ( PPC_MSG_CALL_FUNCTION ! = 0 ) ;
BUILD_BUG_ON ( PPC_MSG_RESCHEDULE ! = 1 ) ;
2014-02-26 05:37:43 +05:30
BUILD_BUG_ON ( PPC_MSG_TICK_BROADCAST ! = 2 ) ;
2016-12-20 04:30:08 +10:00
BUILD_BUG_ON ( PPC_MSG_NMI_IPI ! = 3 ) ;
2006-11-23 00:46:51 +01:00
2011-11-08 12:38:21 +00:00
for ( i = 0 ; i < MSG_COUNT ; i + + ) {
result = ps3_event_receive_port_setup ( cpu , & virqs [ i ] ) ;
2006-11-23 00:46:51 +01:00
2011-11-08 12:38:21 +00:00
if ( result )
continue ;
2006-11-23 00:46:51 +01:00
2011-11-08 12:38:21 +00:00
DBG ( " %s:%d: (%d, %d) => virq %u \n " ,
__func__ , __LINE__ , cpu , i , virqs [ i ] ) ;
2006-11-23 00:46:51 +01:00
2011-11-08 12:38:21 +00:00
result = smp_request_message_ipi ( virqs [ i ] , i ) ;
2006-11-23 00:46:51 +01:00
2011-11-08 12:38:21 +00:00
if ( result )
2016-09-06 21:53:24 +10:00
virqs [ i ] = 0 ;
2011-11-08 12:38:21 +00:00
else
ps3_register_ipi_irq ( cpu , virqs [ i ] ) ;
}
2006-11-23 00:46:51 +01:00
2016-12-20 04:30:08 +10:00
ps3_register_ipi_debug_brk ( cpu , virqs [ PPC_MSG_NMI_IPI ] ) ;
2006-11-23 00:46:51 +01:00
2011-11-08 12:38:21 +00:00
DBG ( " <- %s:%d: (%d) \n " , __func__ , __LINE__ , cpu ) ;
}
2006-11-23 00:46:51 +01:00
}
void ps3_smp_cleanup_cpu ( int cpu )
{
2007-06-16 07:17:42 +10:00
unsigned int * virqs = per_cpu ( ps3_ipi_virqs , cpu ) ;
2006-11-23 00:46:51 +01:00
int i ;
DBG ( " -> %s:%d: (%d) \n " , __func__ , __LINE__ , cpu ) ;
2007-05-01 07:01:01 +10:00
2006-11-23 00:46:51 +01:00
for ( i = 0 ; i < MSG_COUNT ; i + + ) {
2007-06-16 07:19:32 +10:00
/* Can't call free_irq from interrupt context. */
2007-05-01 07:01:01 +10:00
ps3_event_receive_port_destroy ( virqs [ i ] ) ;
2016-09-06 21:53:24 +10:00
virqs [ i ] = 0 ;
2006-11-23 00:46:51 +01:00
}
2007-05-01 07:01:01 +10:00
2006-11-23 00:46:51 +01:00
DBG ( " <- %s:%d: (%d) \n " , __func__ , __LINE__ , cpu ) ;
}
static struct smp_ops_t ps3_smp_ops = {
. probe = ps3_smp_probe ,
. message_pass = ps3_smp_message_pass ,
. kick_cpu = smp_generic_kick_cpu ,
} ;
void smp_init_ps3 ( void )
{
DBG ( " -> %s \n " , __func__ ) ;
smp_ops = & ps3_smp_ops ;
DBG ( " <- %s \n " , __func__ ) ;
}