2005-03-23 19:46:00 -07: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 14:46:56 -05:00
* Copyright ( c ) 2004 - 2008 Silicon Graphics , Inc . All Rights Reserved .
2005-03-23 19:46:00 -07:00
*/
/*
* Cross Partition ( XP ) base .
*
* XP provides a base from which its users can interact
* with XPC , yet not be dependent on XPC .
*
*/
# include <linux/module.h>
2008-07-29 22:34:04 -07:00
# include <linux/device.h>
2008-04-22 14:46:56 -05:00
# include "xp.h"
2005-03-23 19:46:00 -07:00
2008-07-29 22:34:04 -07:00
/* define the XP debug device structures to be used with dev_dbg() et al */
2008-04-22 14:50:17 -05:00
2008-07-29 22:34:04 -07:00
struct device_driver xp_dbg_name = {
. name = " xp "
} ;
struct device xp_dbg_subname = {
2009-01-06 10:44:37 -08:00
. init_name = " " , /* set to "" */
2008-07-29 22:34:04 -07:00
. driver = & xp_dbg_name
} ;
struct device * xp = & xp_dbg_subname ;
/* max #of partitions possible */
short xp_max_npartitions ;
EXPORT_SYMBOL_GPL ( xp_max_npartitions ) ;
2005-03-23 19:46:00 -07:00
2008-07-29 22:34:16 -07:00
short xp_partition_id ;
EXPORT_SYMBOL_GPL ( xp_partition_id ) ;
u8 xp_region_size ;
EXPORT_SYMBOL_GPL ( xp_region_size ) ;
2008-07-29 22:34:16 -07:00
unsigned long ( * xp_pa ) ( void * addr ) ;
EXPORT_SYMBOL_GPL ( xp_pa ) ;
enum xp_retval ( * xp_remote_memcpy ) ( unsigned long dst_gpa ,
const unsigned long src_gpa , size_t len ) ;
2008-07-29 22:34:05 -07:00
EXPORT_SYMBOL_GPL ( xp_remote_memcpy ) ;
2008-07-29 22:34:16 -07:00
int ( * xp_cpu_to_nasid ) ( int cpuid ) ;
EXPORT_SYMBOL_GPL ( xp_cpu_to_nasid ) ;
2008-11-05 17:27:22 -06:00
enum xp_retval ( * xp_expand_memprotect ) ( unsigned long phys_addr ,
unsigned long size ) ;
EXPORT_SYMBOL_GPL ( xp_expand_memprotect ) ;
enum xp_retval ( * xp_restrict_memprotect ) ( unsigned long phys_addr ,
unsigned long size ) ;
EXPORT_SYMBOL_GPL ( xp_restrict_memprotect ) ;
2005-03-23 19:46:00 -07:00
/*
* xpc_registrations [ ] keeps track of xpc_connect ( ) ' s done by the kernel - level
* users of XPC .
*/
2008-07-29 22:34:04 -07:00
struct xpc_registration xpc_registrations [ XPC_MAX_NCHANNELS ] ;
2008-04-22 14:50:17 -05:00
EXPORT_SYMBOL_GPL ( xpc_registrations ) ;
2005-03-23 19:46:00 -07:00
/*
* Initialize the XPC interface to indicate that XPC isn ' t loaded .
*/
2008-05-12 14:02:02 -07:00
static enum xp_retval
2008-04-22 14:48:01 -05:00
xpc_notloaded ( void )
{
2008-05-12 14:02:02 -07:00
return xpNotLoaded ;
2008-04-22 14:48:01 -05:00
}
2005-03-23 19:46:00 -07:00
struct xpc_interface xpc_interface = {
2008-04-22 14:48:01 -05:00
( void ( * ) ( int ) ) xpc_notloaded ,
( void ( * ) ( int ) ) xpc_notloaded ,
2008-07-29 22:34:08 -07:00
( enum xp_retval ( * ) ( short , int , u32 , void * , u16 ) ) xpc_notloaded ,
( enum xp_retval ( * ) ( short , int , u32 , void * , u16 , xpc_notify_func ,
void * ) ) xpc_notloaded ,
2008-05-12 14:02:03 -07:00
( void ( * ) ( short , int , void * ) ) xpc_notloaded ,
( enum xp_retval ( * ) ( short , void * ) ) xpc_notloaded
2005-03-23 19:46:00 -07:00
} ;
2008-04-22 14:50:17 -05:00
EXPORT_SYMBOL_GPL ( xpc_interface ) ;
2005-03-23 19:46:00 -07:00
/*
* XPC calls this when it ( the XPC module ) has been loaded .
*/
void
2008-04-22 14:48:01 -05:00
xpc_set_interface ( void ( * connect ) ( int ) ,
void ( * disconnect ) ( int ) ,
2008-07-29 22:34:08 -07:00
enum xp_retval ( * send ) ( short , int , u32 , void * , u16 ) ,
enum xp_retval ( * send_notify ) ( short , int , u32 , void * , u16 ,
2008-04-22 14:48:01 -05:00
xpc_notify_func , void * ) ,
2008-05-12 14:02:03 -07:00
void ( * received ) ( short , int , void * ) ,
enum xp_retval ( * partid_to_nasids ) ( short , void * ) )
2005-03-23 19:46:00 -07:00
{
xpc_interface . connect = connect ;
xpc_interface . disconnect = disconnect ;
xpc_interface . send = send ;
xpc_interface . send_notify = send_notify ;
xpc_interface . received = received ;
xpc_interface . partid_to_nasids = partid_to_nasids ;
}
2008-04-22 14:50:17 -05:00
EXPORT_SYMBOL_GPL ( xpc_set_interface ) ;
2005-03-23 19:46:00 -07:00
/*
* XPC calls this when it ( the XPC module ) is being unloaded .
*/
void
xpc_clear_interface ( void )
{
2008-04-22 14:48:01 -05:00
xpc_interface . connect = ( void ( * ) ( int ) ) xpc_notloaded ;
xpc_interface . disconnect = ( void ( * ) ( int ) ) xpc_notloaded ;
2008-07-29 22:34:08 -07:00
xpc_interface . send = ( enum xp_retval ( * ) ( short , int , u32 , void * , u16 ) )
2008-04-22 14:48:01 -05:00
xpc_notloaded ;
2008-07-29 22:34:08 -07:00
xpc_interface . send_notify = ( enum xp_retval ( * ) ( short , int , u32 , void * ,
u16 , xpc_notify_func ,
void * ) ) xpc_notloaded ;
2008-05-12 14:02:03 -07:00
xpc_interface . received = ( void ( * ) ( short , int , void * ) )
2008-04-22 14:48:01 -05:00
xpc_notloaded ;
2008-05-12 14:02:03 -07:00
xpc_interface . partid_to_nasids = ( enum xp_retval ( * ) ( short , void * ) )
2008-04-22 14:48:01 -05:00
xpc_notloaded ;
2005-03-23 19:46:00 -07:00
}
2008-04-22 14:50:17 -05:00
EXPORT_SYMBOL_GPL ( xpc_clear_interface ) ;
2005-03-23 19:46:00 -07:00
/*
* Register for automatic establishment of a channel connection whenever
* a partition comes up .
*
* Arguments :
*
* ch_number - channel # to register for connection .
* func - function to call for asynchronous notification of channel
* state changes ( i . e . , connection , disconnection , error ) and
* the arrival of incoming messages .
* key - pointer to optional user - defined value that gets passed back
* to the user on any callouts made to func .
* payload_size - size in bytes of the XPC message ' s payload area which
* contains a user - defined message . The user should make
* this large enough to hold their largest message .
* nentries - max # of XPC message entries a message queue can contain .
* The actual number , which is determined when a connection
* is established and may be less then requested , will be
2008-05-12 14:02:02 -07:00
* passed to the user via the xpConnected callout .
2005-03-23 19:46:00 -07:00
* assigned_limit - max number of kthreads allowed to be processing
* messages ( per connection ) at any given instant .
* idle_limit - max number of kthreads allowed to be idle at any given
* instant .
*/
2008-05-12 14:02:02 -07:00
enum xp_retval
2005-03-23 19:46:00 -07:00
xpc_connect ( int ch_number , xpc_channel_func func , void * key , u16 payload_size ,
2008-04-22 14:48:01 -05:00
u16 nentries , u32 assigned_limit , u32 idle_limit )
2005-03-23 19:46:00 -07:00
{
struct xpc_registration * registration ;
2008-07-29 22:34:04 -07:00
DBUG_ON ( ch_number < 0 | | ch_number > = XPC_MAX_NCHANNELS ) ;
2005-03-23 19:46:00 -07:00
DBUG_ON ( payload_size = = 0 | | nentries = = 0 ) ;
DBUG_ON ( func = = NULL ) ;
DBUG_ON ( assigned_limit = = 0 | | idle_limit > assigned_limit ) ;
2008-07-29 22:34:19 -07:00
if ( XPC_MSG_SIZE ( payload_size ) > XPC_MSG_MAX_SIZE )
return xpPayloadTooBig ;
2005-03-23 19:46:00 -07:00
registration = & xpc_registrations [ ch_number ] ;
2008-04-22 14:50:17 -05:00
if ( mutex_lock_interruptible ( & registration - > mutex ) ! = 0 )
2008-05-12 14:02:02 -07:00
return xpInterrupted ;
2005-03-23 19:46:00 -07:00
/* if XPC_CHANNEL_REGISTERED(ch_number) */
if ( registration - > func ! = NULL ) {
2006-01-17 12:52:21 -05:00
mutex_unlock ( & registration - > mutex ) ;
2008-05-12 14:02:02 -07:00
return xpAlreadyRegistered ;
2005-03-23 19:46:00 -07:00
}
/* register the channel for connection */
2008-07-29 22:34:19 -07:00
registration - > entry_size = XPC_MSG_SIZE ( payload_size ) ;
2005-03-23 19:46:00 -07:00
registration - > nentries = nentries ;
registration - > assigned_limit = assigned_limit ;
registration - > idle_limit = idle_limit ;
registration - > key = key ;
registration - > func = func ;
2006-01-17 12:52:21 -05:00
mutex_unlock ( & registration - > mutex ) ;
2005-03-23 19:46:00 -07:00
xpc_interface . connect ( ch_number ) ;
2008-05-12 14:02:02 -07:00
return xpSuccess ;
2005-03-23 19:46:00 -07:00
}
2008-04-22 14:50:17 -05:00
EXPORT_SYMBOL_GPL ( xpc_connect ) ;
2005-03-23 19:46:00 -07:00
/*
* Remove the registration for automatic connection of the specified channel
* when a partition comes up .
*
* Before returning this xpc_disconnect ( ) will wait for all connections on the
* specified channel have been closed / torndown . So the caller can be assured
* that they will not be receiving any more callouts from XPC to their
* function registered via xpc_connect ( ) .
*
* Arguments :
*
* ch_number - channel # to unregister .
*/
void
xpc_disconnect ( int ch_number )
{
struct xpc_registration * registration ;
2008-07-29 22:34:04 -07:00
DBUG_ON ( ch_number < 0 | | ch_number > = XPC_MAX_NCHANNELS ) ;
2005-03-23 19:46:00 -07:00
registration = & xpc_registrations [ ch_number ] ;
/*
* We ' ve decided not to make this a down_interruptible ( ) , since we
* figured XPC ' s users will just turn around and call xpc_disconnect ( )
* again anyways , so we might as well wait , if need be .
*/
2006-01-17 12:52:21 -05:00
mutex_lock ( & registration - > mutex ) ;
2005-03-23 19:46:00 -07:00
/* if !XPC_CHANNEL_REGISTERED(ch_number) */
if ( registration - > func = = NULL ) {
2006-01-17 12:52:21 -05:00
mutex_unlock ( & registration - > mutex ) ;
2005-03-23 19:46:00 -07:00
return ;
}
/* remove the connection registration for the specified channel */
registration - > func = NULL ;
registration - > key = NULL ;
registration - > nentries = 0 ;
2008-07-29 22:34:19 -07:00
registration - > entry_size = 0 ;
2005-03-23 19:46:00 -07:00
registration - > assigned_limit = 0 ;
registration - > idle_limit = 0 ;
xpc_interface . disconnect ( ch_number ) ;
2006-01-17 12:52:21 -05:00
mutex_unlock ( & registration - > mutex ) ;
2005-03-23 19:46:00 -07:00
return ;
}
2008-04-22 14:50:17 -05:00
EXPORT_SYMBOL_GPL ( xpc_disconnect ) ;
2005-03-23 19:46:00 -07:00
int __init
xp_init ( void )
{
2008-07-29 22:34:04 -07:00
enum xp_retval ret ;
int ch_number ;
2005-03-23 19:46:00 -07:00
2009-04-21 12:24:53 -07:00
/* initialize the connection registration mutex */
for ( ch_number = 0 ; ch_number < XPC_MAX_NCHANNELS ; ch_number + + )
mutex_init ( & xpc_registrations [ ch_number ] . mutex ) ;
2008-07-29 22:34:04 -07:00
if ( is_shub ( ) )
ret = xp_init_sn2 ( ) ;
else if ( is_uv ( ) )
ret = xp_init_uv ( ) ;
2008-04-22 14:50:17 -05:00
else
2009-04-21 12:24:53 -07:00
ret = 0 ;
2008-07-29 22:34:04 -07:00
if ( ret ! = xpSuccess )
2009-04-21 12:24:53 -07:00
return ret ;
2005-03-23 19:46:00 -07:00
return 0 ;
}
2008-04-22 14:48:01 -05:00
module_init ( xp_init ) ;
2005-03-23 19:46:00 -07:00
void __exit
xp_exit ( void )
{
2008-07-29 22:34:04 -07:00
if ( is_shub ( ) )
xp_exit_sn2 ( ) ;
else if ( is_uv ( ) )
xp_exit_uv ( ) ;
2005-03-23 19:46:00 -07:00
}
2008-04-22 14:48:01 -05:00
module_exit ( xp_exit ) ;
2005-03-23 19:46:00 -07:00
MODULE_AUTHOR ( " Silicon Graphics, Inc. " ) ;
MODULE_DESCRIPTION ( " Cross Partition (XP) base " ) ;
MODULE_LICENSE ( " GPL " ) ;