2005-03-24 05:50:00 +03:00
/*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*
2008-04-22 23:46:56 +04:00
* Copyright ( c ) 2004 - 2008 Silicon Graphics , Inc . All Rights Reserved .
2005-03-24 05:50:00 +03:00
*/
/*
* Cross Partition Communication ( XPC ) partition support .
*
* This is the part of XPC that detects the presence / absence of
* other partitions . It provides a heartbeat and monitors the
* heartbeats of other partitions .
*
*/
# include <linux/kernel.h>
# include <linux/sysctl.h>
# include <linux/cache.h>
# include <linux/mmzone.h>
# include <linux/nodemask.h>
# include <asm/sn/intr.h>
# include <asm/sn/sn_sal.h>
# include <asm/sn/nodepda.h>
# include <asm/sn/addrs.h>
2008-04-22 23:46:56 +04:00
# include "xpc.h"
2005-03-24 05:50:00 +03:00
/* XPC is exiting flag */
int xpc_exiting ;
2005-10-25 23:09:51 +04:00
/* this partition's reserved page pointers */
2005-03-24 05:50:00 +03:00
struct xpc_rsvd_page * xpc_rsvd_page ;
2005-10-25 23:09:51 +04:00
static u64 * xpc_part_nasids ;
2008-07-30 09:34:07 +04:00
u64 * xpc_mach_nasids ;
2005-03-24 05:50:00 +03:00
2008-07-30 09:34:13 +04:00
static int xpc_sizeof_nasid_mask ; /* actual size in bytes of nasid mask */
int xpc_nasid_mask_words ; /* actual size in words of nasid mask */
2005-10-25 23:09:51 +04:00
2008-07-30 09:34:04 +04:00
struct xpc_partition * xpc_partitions ;
2005-03-24 05:50:00 +03:00
2006-02-17 13:18:43 +03:00
/*
* Guarantee that the kmalloc ' d memory is cacheline aligned .
*/
2006-08-09 00:03:29 +04:00
void *
2006-02-17 13:18:43 +03:00
xpc_kmalloc_cacheline_aligned ( size_t size , gfp_t flags , void * * base )
{
/* see if kmalloc will give us cachline aligned memory by default */
* base = kmalloc ( size , flags ) ;
2008-04-22 23:50:17 +04:00
if ( * base = = NULL )
2006-02-17 13:18:43 +03:00
return NULL ;
2008-04-22 23:50:17 +04:00
if ( ( u64 ) * base = = L1_CACHE_ALIGN ( ( u64 ) * base ) )
2006-02-17 13:18:43 +03:00
return * base ;
2008-04-22 23:50:17 +04:00
2006-02-17 13:18:43 +03:00
kfree ( * base ) ;
/* nope, we'll have to do it ourselves */
* base = kmalloc ( size + L1_CACHE_BYTES , flags ) ;
2008-04-22 23:50:17 +04:00
if ( * base = = NULL )
2006-02-17 13:18:43 +03:00
return NULL ;
2008-04-22 23:50:17 +04:00
2008-04-22 23:48:01 +04:00
return ( void * ) L1_CACHE_ALIGN ( ( u64 ) * base ) ;
2006-02-17 13:18:43 +03:00
}
2005-03-24 05:50:00 +03:00
/*
* Given a nasid , get the physical address of the partition ' s reserved page
* for that nasid . This function returns 0 on any error .
*/
static u64
2005-10-25 23:11:53 +04:00
xpc_get_rsvd_page_pa ( int nasid )
2005-03-24 05:50:00 +03:00
{
2008-07-30 09:34:05 +04:00
enum xp_retval ret ;
2005-03-24 05:50:00 +03:00
s64 status ;
u64 cookie = 0 ;
u64 rp_pa = nasid ; /* seed with nasid */
u64 len = 0 ;
2005-10-25 23:11:53 +04:00
u64 buf = buf ;
u64 buf_len = 0 ;
void * buf_base = NULL ;
2005-03-24 05:50:00 +03:00
while ( 1 ) {
status = sn_partition_reserved_page_pa ( buf , & cookie , & rp_pa ,
2008-04-22 23:48:01 +04:00
& len ) ;
2005-03-24 05:50:00 +03:00
dev_dbg ( xpc_part , " SAL returned with status=%li, cookie= "
" 0x%016lx, address=0x%016lx, len=0x%016lx \n " ,
status , cookie , rp_pa , len ) ;
2008-04-22 23:50:17 +04:00
if ( status ! = SALRET_MORE_PASSES )
2005-03-24 05:50:00 +03:00
break ;
2008-07-30 09:34:14 +04:00
/* !!! L1_CACHE_ALIGN() is only a sn2-bte_copy requirement */
2005-10-25 23:11:53 +04:00
if ( L1_CACHE_ALIGN ( len ) > buf_len ) {
2006-04-20 21:11:09 +04:00
kfree ( buf_base ) ;
2005-10-25 23:11:53 +04:00
buf_len = L1_CACHE_ALIGN ( len ) ;
2008-04-22 23:48:01 +04:00
buf = ( u64 ) xpc_kmalloc_cacheline_aligned ( buf_len ,
GFP_KERNEL ,
& buf_base ) ;
2005-10-25 23:11:53 +04:00
if ( buf_base = = NULL ) {
dev_err ( xpc_part , " unable to kmalloc "
" len=0x%016lx \n " , buf_len ) ;
status = SALRET_ERROR ;
break ;
}
2005-03-24 05:50:00 +03:00
}
2008-07-30 09:34:05 +04:00
ret = xp_remote_memcpy ( ( void * ) buf , ( void * ) rp_pa , buf_len ) ;
if ( ret ! = xpSuccess ) {
dev_dbg ( xpc_part , " xp_remote_memcpy failed %d \n " , ret ) ;
2005-03-24 05:50:00 +03:00
status = SALRET_ERROR ;
break ;
}
}
2006-04-20 21:11:09 +04:00
kfree ( buf_base ) ;
2005-10-25 23:11:53 +04:00
2008-04-22 23:50:17 +04:00
if ( status ! = SALRET_OK )
2005-03-24 05:50:00 +03:00
rp_pa = 0 ;
2008-04-22 23:50:17 +04:00
2005-03-24 05:50:00 +03:00
dev_dbg ( xpc_part , " reserved page at phys address 0x%016lx \n " , rp_pa ) ;
return rp_pa ;
}
/*
* Fill the partition reserved page with the information needed by
* other partitions to discover we are alive and establish initial
* communications .
*/
struct xpc_rsvd_page *
2008-07-30 09:34:05 +04:00
xpc_setup_rsvd_page ( void )
2005-03-24 05:50:00 +03:00
{
struct xpc_rsvd_page * rp ;
2008-07-30 09:34:05 +04:00
u64 rp_pa ;
2008-07-30 09:34:07 +04:00
unsigned long new_stamp ;
2005-03-24 05:50:00 +03:00
/* get the local reserved page's address */
2005-10-25 23:11:53 +04:00
preempt_disable ( ) ;
rp_pa = xpc_get_rsvd_page_pa ( cpuid_to_nasid ( smp_processor_id ( ) ) ) ;
preempt_enable ( ) ;
2005-03-24 05:50:00 +03:00
if ( rp_pa = = 0 ) {
dev_err ( xpc_part , " SAL failed to locate the reserved page \n " ) ;
return NULL ;
}
2008-04-22 23:48:01 +04:00
rp = ( struct xpc_rsvd_page * ) __va ( rp_pa ) ;
2005-03-24 05:50:00 +03:00
2008-07-30 09:34:05 +04:00
if ( rp - > SAL_version < 3 ) {
/* SAL_versions < 3 had a SAL_partid defined as a u8 */
rp - > SAL_partid & = 0xff ;
}
BUG_ON ( rp - > SAL_partid ! = sn_partition_id ) ;
if ( rp - > SAL_partid < 0 | | rp - > SAL_partid > = xp_max_npartitions ) {
dev_err ( xpc_part , " the reserved page's partid of %d is outside "
" supported range (< 0 || >= %d) \n " , rp - > SAL_partid ,
xp_max_npartitions ) ;
2005-03-24 05:50:00 +03:00
return NULL ;
}
rp - > version = XPC_RP_VERSION ;
2008-07-30 09:34:05 +04:00
rp - > max_npartitions = xp_max_npartitions ;
2005-03-24 05:50:00 +03:00
2005-10-25 23:09:51 +04:00
/* establish the actual sizes of the nasid masks */
if ( rp - > SAL_version = = 1 ) {
/* SAL_version 1 didn't set the nasids_size field */
2008-07-30 09:34:05 +04:00
rp - > SAL_nasids_size = 128 ;
2005-10-25 23:09:51 +04:00
}
2008-07-30 09:34:13 +04:00
xpc_sizeof_nasid_mask = rp - > SAL_nasids_size ;
xpc_nasid_mask_words = DIV_ROUND_UP ( xpc_sizeof_nasid_mask ,
BYTES_PER_WORD ) ;
2005-10-25 23:09:51 +04:00
/* setup the pointers to the various items in the reserved page */
xpc_part_nasids = XPC_RP_PART_NASIDS ( rp ) ;
xpc_mach_nasids = XPC_RP_MACH_NASIDS ( rp ) ;
2005-03-24 05:50:00 +03:00
2008-07-30 09:34:05 +04:00
if ( xpc_rsvd_page_init ( rp ) ! = xpSuccess )
return NULL ;
2005-03-24 05:50:00 +03:00
/*
2008-07-30 09:34:05 +04:00
* Set timestamp of when reserved page was setup by XPC .
2005-03-24 05:50:00 +03:00
* This signifies to the remote partition that our reserved
* page is initialized .
*/
2008-07-30 09:34:07 +04:00
new_stamp = jiffies ;
if ( new_stamp = = 0 | | new_stamp = = rp - > stamp )
new_stamp + + ;
rp - > stamp = new_stamp ;
2005-03-24 05:50:00 +03:00
return rp ;
}
/*
2005-10-25 23:09:51 +04:00
* Get a copy of a portion of the remote partition ' s rsvd page .
2005-03-24 05:50:00 +03:00
*
* remote_rp points to a buffer that is cacheline aligned for BTE copies and
2005-10-25 23:09:51 +04:00
* is large enough to contain a copy of their reserved page header and
* part_nasids mask .
2005-03-24 05:50:00 +03:00
*/
2008-07-30 09:34:07 +04:00
enum xp_retval
2005-03-24 05:50:00 +03:00
xpc_get_remote_rp ( int nasid , u64 * discovered_nasids ,
2008-04-22 23:48:01 +04:00
struct xpc_rsvd_page * remote_rp , u64 * remote_rp_pa )
2005-03-24 05:50:00 +03:00
{
2008-07-30 09:34:05 +04:00
int i ;
enum xp_retval ret ;
2005-03-24 05:50:00 +03:00
/* get the reserved page's physical address */
2005-10-25 23:11:53 +04:00
* remote_rp_pa = xpc_get_rsvd_page_pa ( nasid ) ;
2008-04-22 23:50:17 +04:00
if ( * remote_rp_pa = = 0 )
2008-05-13 01:02:02 +04:00
return xpNoRsvdPageAddr ;
2005-03-24 05:50:00 +03:00
2005-10-25 23:09:51 +04:00
/* pull over the reserved page header and part_nasids mask */
2008-07-30 09:34:05 +04:00
ret = xp_remote_memcpy ( remote_rp , ( void * ) * remote_rp_pa ,
2008-07-30 09:34:13 +04:00
XPC_RP_HEADER_SIZE + xpc_sizeof_nasid_mask ) ;
2008-07-30 09:34:05 +04:00
if ( ret ! = xpSuccess )
return ret ;
2005-03-24 05:50:00 +03:00
if ( discovered_nasids ! = NULL ) {
2005-10-25 23:09:51 +04:00
u64 * remote_part_nasids = XPC_RP_PART_NASIDS ( remote_rp ) ;
2008-07-30 09:34:13 +04:00
for ( i = 0 ; i < xpc_nasid_mask_words ; i + + )
2005-10-25 23:09:51 +04:00
discovered_nasids [ i ] | = remote_part_nasids [ i ] ;
2005-03-24 05:50:00 +03:00
}
2008-07-30 09:34:07 +04:00
/* see if the reserved page has been set up by XPC */
if ( remote_rp - > stamp = = 0 )
2008-07-30 09:34:05 +04:00
return xpRsvdPageNotSet ;
2005-03-24 05:50:00 +03:00
if ( XPC_VERSION_MAJOR ( remote_rp - > version ) ! =
2008-04-22 23:48:01 +04:00
XPC_VERSION_MAJOR ( XPC_RP_VERSION ) ) {
2008-05-13 01:02:02 +04:00
return xpBadVersion ;
2005-03-24 05:50:00 +03:00
}
2008-07-30 09:34:09 +04:00
/* check that both remote and local partids are valid for each side */
2008-07-30 09:34:07 +04:00
if ( remote_rp - > SAL_partid < 0 | |
remote_rp - > SAL_partid > = xp_max_npartitions | |
remote_rp - > max_npartitions < = sn_partition_id ) {
2008-07-30 09:34:05 +04:00
return xpInvalidPartid ;
2008-07-30 09:34:07 +04:00
}
if ( remote_rp - > SAL_partid = = sn_partition_id )
return xpLocalPartid ;
2008-07-30 09:34:05 +04:00
2008-05-13 01:02:02 +04:00
return xpSuccess ;
2005-03-24 05:50:00 +03:00
}
2005-09-01 23:01:37 +04:00
/*
2008-07-30 09:34:09 +04:00
* See if the other side has responded to a partition deactivate request
* from us . Though we requested the remote partition to deactivate with regard
* to us , we really only need to wait for the other side to disengage from us .
2005-09-01 23:01:37 +04:00
*/
int
xpc_partition_disengaged ( struct xpc_partition * part )
{
2008-05-13 01:02:03 +04:00
short partid = XPC_PARTID ( part ) ;
2005-09-01 23:01:37 +04:00
int disengaged ;
2008-07-30 09:34:09 +04:00
disengaged = ! xpc_partition_engaged ( partid ) ;
if ( part - > disengage_timeout ) {
2005-09-01 23:01:37 +04:00
if ( ! disengaged ) {
2008-07-30 09:34:09 +04:00
if ( time_is_after_jiffies ( part - > disengage_timeout ) ) {
2005-09-01 23:01:37 +04:00
/* timelimit hasn't been reached yet */
return 0 ;
}
/*
2008-07-30 09:34:09 +04:00
* Other side hasn ' t responded to our deactivate
2005-09-01 23:01:37 +04:00
* request in a timely fashion , so assume it ' s dead .
*/
2008-07-30 09:34:09 +04:00
dev_info ( xpc_part , " deactivate request to remote "
" partition %d timed out \n " , partid ) ;
xpc_disengage_timedout = 1 ;
xpc_assume_partition_disengaged ( partid ) ;
2005-09-01 23:01:37 +04:00
disengaged = 1 ;
}
2008-07-30 09:34:09 +04:00
part - > disengage_timeout = 0 ;
2005-09-01 23:01:37 +04:00
/* cancel the timer function, provided it's not us */
2008-07-30 09:34:09 +04:00
if ( ! in_interrupt ( ) )
del_singleshot_timer_sync ( & part - > disengage_timer ) ;
2005-09-01 23:01:37 +04:00
DBUG_ON ( part - > act_state ! = XPC_P_DEACTIVATING & &
2008-04-22 23:48:01 +04:00
part - > act_state ! = XPC_P_INACTIVE ) ;
2008-04-22 23:50:17 +04:00
if ( part - > act_state ! = XPC_P_INACTIVE )
2005-09-01 23:01:37 +04:00
xpc_wakeup_channel_mgr ( part ) ;
2008-07-30 09:34:09 +04:00
xpc_cancel_partition_deactivation_request ( part ) ;
2005-09-01 23:01:37 +04:00
}
return disengaged ;
}
2005-03-24 05:50:00 +03:00
/*
* Mark specified partition as active .
*/
2008-05-13 01:02:02 +04:00
enum xp_retval
2005-03-24 05:50:00 +03:00
xpc_mark_partition_active ( struct xpc_partition * part )
{
unsigned long irq_flags ;
2008-05-13 01:02:02 +04:00
enum xp_retval ret ;
2005-03-24 05:50:00 +03:00
dev_dbg ( xpc_part , " setting partition %d to ACTIVE \n " , XPC_PARTID ( part ) ) ;
spin_lock_irqsave ( & part - > act_lock , irq_flags ) ;
if ( part - > act_state = = XPC_P_ACTIVATING ) {
part - > act_state = XPC_P_ACTIVE ;
2008-05-13 01:02:02 +04:00
ret = xpSuccess ;
2005-03-24 05:50:00 +03:00
} else {
2008-05-13 01:02:02 +04:00
DBUG_ON ( part - > reason = = xpSuccess ) ;
2005-03-24 05:50:00 +03:00
ret = part - > reason ;
}
spin_unlock_irqrestore ( & part - > act_lock , irq_flags ) ;
return ret ;
}
/*
2008-07-30 09:34:09 +04:00
* Start the process of deactivating the specified partition .
2005-03-24 05:50:00 +03:00
*/
void
xpc_deactivate_partition ( const int line , struct xpc_partition * part ,
2008-05-13 01:02:02 +04:00
enum xp_retval reason )
2005-03-24 05:50:00 +03:00
{
unsigned long irq_flags ;
spin_lock_irqsave ( & part - > act_lock , irq_flags ) ;
if ( part - > act_state = = XPC_P_INACTIVE ) {
XPC_SET_REASON ( part , reason , line ) ;
spin_unlock_irqrestore ( & part - > act_lock , irq_flags ) ;
2008-05-13 01:02:02 +04:00
if ( reason = = xpReactivating ) {
2005-03-24 05:50:00 +03:00
/* we interrupt ourselves to reactivate partition */
2008-07-30 09:34:09 +04:00
xpc_request_partition_reactivation ( part ) ;
2005-03-24 05:50:00 +03:00
}
return ;
}
if ( part - > act_state = = XPC_P_DEACTIVATING ) {
2008-05-13 01:02:02 +04:00
if ( ( part - > reason = = xpUnloading & & reason ! = xpUnloading ) | |
reason = = xpReactivating ) {
2005-03-24 05:50:00 +03:00
XPC_SET_REASON ( part , reason , line ) ;
}
spin_unlock_irqrestore ( & part - > act_lock , irq_flags ) ;
return ;
}
part - > act_state = XPC_P_DEACTIVATING ;
XPC_SET_REASON ( part , reason , line ) ;
spin_unlock_irqrestore ( & part - > act_lock , irq_flags ) ;
2008-07-30 09:34:09 +04:00
/* ask remote partition to deactivate with regard to us */
xpc_request_partition_deactivation ( part ) ;
2005-03-24 05:50:00 +03:00
2008-07-30 09:34:09 +04:00
/* set a timelimit on the disengage phase of the deactivation request */
part - > disengage_timeout = jiffies + ( xpc_disengage_timelimit * HZ ) ;
part - > disengage_timer . expires = part - > disengage_timeout ;
add_timer ( & part - > disengage_timer ) ;
2005-03-24 05:50:00 +03:00
2005-10-25 23:07:43 +04:00
dev_dbg ( xpc_part , " bringing partition %d down, reason = %d \n " ,
XPC_PARTID ( part ) , reason ) ;
2005-03-24 05:50:00 +03:00
2005-09-01 23:01:37 +04:00
xpc_partition_going_down ( part , reason ) ;
2005-03-24 05:50:00 +03:00
}
/*
2005-09-01 23:01:37 +04:00
* Mark specified partition as inactive .
2005-03-24 05:50:00 +03:00
*/
void
xpc_mark_partition_inactive ( struct xpc_partition * part )
{
unsigned long irq_flags ;
dev_dbg ( xpc_part , " setting partition %d to INACTIVE \n " ,
XPC_PARTID ( part ) ) ;
spin_lock_irqsave ( & part - > act_lock , irq_flags ) ;
part - > act_state = XPC_P_INACTIVE ;
spin_unlock_irqrestore ( & part - > act_lock , irq_flags ) ;
part - > remote_rp_pa = 0 ;
}
/*
* SAL has provided a partition and machine mask . The partition mask
* contains a bit for each even nasid in our partition . The machine
* mask contains a bit for each even nasid in the entire machine .
*
* Using those two bit arrays , we can determine which nasids are
* known in the machine . Each should also have a reserved page
* initialized if they are available for partitioning .
*/
void
xpc_discovery ( void )
{
void * remote_rp_base ;
struct xpc_rsvd_page * remote_rp ;
2005-09-01 23:01:37 +04:00
u64 remote_rp_pa ;
2005-03-24 05:50:00 +03:00
int region ;
2005-10-25 23:09:51 +04:00
int region_size ;
2005-03-24 05:50:00 +03:00
int max_regions ;
int nasid ;
struct xpc_rsvd_page * rp ;
u64 * discovered_nasids ;
2008-05-13 01:02:02 +04:00
enum xp_retval ret ;
2005-03-24 05:50:00 +03:00
2005-10-25 23:09:51 +04:00
remote_rp = xpc_kmalloc_cacheline_aligned ( XPC_RP_HEADER_SIZE +
2008-07-30 09:34:13 +04:00
xpc_sizeof_nasid_mask ,
2008-04-22 23:48:01 +04:00
GFP_KERNEL , & remote_rp_base ) ;
2008-04-22 23:50:17 +04:00
if ( remote_rp = = NULL )
2005-03-24 05:50:00 +03:00
return ;
2008-04-22 23:50:17 +04:00
2008-07-30 09:34:13 +04:00
discovered_nasids = kzalloc ( sizeof ( u64 ) * xpc_nasid_mask_words ,
2008-04-22 23:48:01 +04:00
GFP_KERNEL ) ;
2005-03-24 05:50:00 +03:00
if ( discovered_nasids = = NULL ) {
kfree ( remote_rp_base ) ;
return ;
}
2008-04-22 23:48:01 +04:00
rp = ( struct xpc_rsvd_page * ) xpc_rsvd_page ;
2005-03-24 05:50:00 +03:00
/*
* The term ' region ' in this context refers to the minimum number of
* nodes that can comprise an access protection grouping . The access
* protection is in regards to memory , IOI and IPI .
*/
2005-10-25 23:09:51 +04:00
max_regions = 64 ;
region_size = sn_region_size ;
switch ( region_size ) {
case 128 :
max_regions * = 2 ;
case 64 :
max_regions * = 2 ;
case 32 :
max_regions * = 2 ;
region_size = 16 ;
DBUG_ON ( ! is_shub2 ( ) ) ;
}
2005-03-24 05:50:00 +03:00
for ( region = 0 ; region < max_regions ; region + + ) {
2008-04-22 23:50:17 +04:00
if ( xpc_exiting )
2005-03-24 05:50:00 +03:00
break ;
dev_dbg ( xpc_part , " searching region %d \n " , region ) ;
2005-10-25 23:09:51 +04:00
for ( nasid = ( region * region_size * 2 ) ;
2008-04-22 23:48:01 +04:00
nasid < ( ( region + 1 ) * region_size * 2 ) ; nasid + = 2 ) {
2005-03-24 05:50:00 +03:00
2008-04-22 23:50:17 +04:00
if ( xpc_exiting )
2005-03-24 05:50:00 +03:00
break ;
dev_dbg ( xpc_part , " checking nasid %d \n " , nasid ) ;
2005-10-25 23:09:51 +04:00
if ( XPC_NASID_IN_ARRAY ( nasid , xpc_part_nasids ) ) {
2005-03-24 05:50:00 +03:00
dev_dbg ( xpc_part , " PROM indicates Nasid %d is "
" part of the local partition; skipping "
" region \n " , nasid ) ;
break ;
}
2005-10-25 23:09:51 +04:00
if ( ! ( XPC_NASID_IN_ARRAY ( nasid , xpc_mach_nasids ) ) ) {
2005-03-24 05:50:00 +03:00
dev_dbg ( xpc_part , " PROM indicates Nasid %d was "
" not on Numa-Link network at reset \n " ,
nasid ) ;
continue ;
}
if ( XPC_NASID_IN_ARRAY ( nasid , discovered_nasids ) ) {
dev_dbg ( xpc_part , " Nasid %d is part of a "
" partition which was previously "
" discovered \n " , nasid ) ;
continue ;
}
2008-07-30 09:34:07 +04:00
/* pull over the rsvd page header & part_nasids mask */
2005-03-24 05:50:00 +03:00
ret = xpc_get_remote_rp ( nasid , discovered_nasids ,
2008-04-22 23:48:01 +04:00
remote_rp , & remote_rp_pa ) ;
2008-05-13 01:02:02 +04:00
if ( ret ! = xpSuccess ) {
2005-03-24 05:50:00 +03:00
dev_dbg ( xpc_part , " unable to get reserved page "
" from nasid %d, reason=%d \n " , nasid ,
ret ) ;
2008-05-13 01:02:02 +04:00
if ( ret = = xpLocalPartid )
2005-03-24 05:50:00 +03:00
break ;
2008-04-22 23:50:17 +04:00
2005-03-24 05:50:00 +03:00
continue ;
}
2008-07-30 09:34:09 +04:00
xpc_request_partition_activation ( remote_rp ,
remote_rp_pa , nasid ) ;
2005-03-24 05:50:00 +03:00
}
}
kfree ( discovered_nasids ) ;
kfree ( remote_rp_base ) ;
}
/*
* Given a partid , get the nasids owned by that partition from the
2005-04-05 00:14:00 +04:00
* remote partition ' s reserved page .
2005-03-24 05:50:00 +03:00
*/
2008-05-13 01:02:02 +04:00
enum xp_retval
2008-05-13 01:02:03 +04:00
xpc_initiate_partid_to_nasids ( short partid , void * nasid_mask )
2005-03-24 05:50:00 +03:00
{
struct xpc_partition * part ;
u64 part_nasid_pa ;
part = & xpc_partitions [ partid ] ;
2008-04-22 23:50:17 +04:00
if ( part - > remote_rp_pa = = 0 )
2008-05-13 01:02:02 +04:00
return xpPartitionDown ;
2005-03-24 05:50:00 +03:00
2008-07-30 09:34:13 +04:00
memset ( nasid_mask , 0 , xpc_sizeof_nasid_mask ) ;
2005-10-25 23:09:51 +04:00
2008-04-22 23:48:01 +04:00
part_nasid_pa = ( u64 ) XPC_RP_PART_NASIDS ( part - > remote_rp_pa ) ;
2005-03-24 05:50:00 +03:00
2008-07-30 09:34:05 +04:00
return xp_remote_memcpy ( nasid_mask , ( void * ) part_nasid_pa ,
2008-07-30 09:34:13 +04:00
xpc_sizeof_nasid_mask ) ;
2005-03-24 05:50:00 +03:00
}