Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * (C) Copyright 2020 Hewlett Packard Enterprise Development LP
0007  * Copyright (c) 2004-2008 Silicon Graphics, Inc.  All Rights Reserved.
0008  */
0009 
0010 /*
0011  * Cross Partition (XP) base.
0012  *
0013  *  XP provides a base from which its users can interact
0014  *  with XPC, yet not be dependent on XPC.
0015  *
0016  */
0017 
0018 #include <linux/module.h>
0019 #include <linux/device.h>
0020 #include "xp.h"
0021 
0022 /* define the XP debug device structures to be used with dev_dbg() et al */
0023 
0024 static struct device_driver xp_dbg_name = {
0025     .name = "xp"
0026 };
0027 
0028 static struct device xp_dbg_subname = {
0029     .init_name = "",        /* set to "" */
0030     .driver = &xp_dbg_name
0031 };
0032 
0033 struct device *xp = &xp_dbg_subname;
0034 
0035 /* max #of partitions possible */
0036 short xp_max_npartitions;
0037 EXPORT_SYMBOL_GPL(xp_max_npartitions);
0038 
0039 short xp_partition_id;
0040 EXPORT_SYMBOL_GPL(xp_partition_id);
0041 
0042 u8 xp_region_size;
0043 EXPORT_SYMBOL_GPL(xp_region_size);
0044 
0045 unsigned long (*xp_pa) (void *addr);
0046 EXPORT_SYMBOL_GPL(xp_pa);
0047 
0048 unsigned long (*xp_socket_pa) (unsigned long gpa);
0049 EXPORT_SYMBOL_GPL(xp_socket_pa);
0050 
0051 enum xp_retval (*xp_remote_memcpy) (unsigned long dst_gpa,
0052                     const unsigned long src_gpa, size_t len);
0053 EXPORT_SYMBOL_GPL(xp_remote_memcpy);
0054 
0055 int (*xp_cpu_to_nasid) (int cpuid);
0056 EXPORT_SYMBOL_GPL(xp_cpu_to_nasid);
0057 
0058 enum xp_retval (*xp_expand_memprotect) (unsigned long phys_addr,
0059                     unsigned long size);
0060 EXPORT_SYMBOL_GPL(xp_expand_memprotect);
0061 enum xp_retval (*xp_restrict_memprotect) (unsigned long phys_addr,
0062                       unsigned long size);
0063 EXPORT_SYMBOL_GPL(xp_restrict_memprotect);
0064 
0065 /*
0066  * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
0067  * users of XPC.
0068  */
0069 struct xpc_registration xpc_registrations[XPC_MAX_NCHANNELS];
0070 EXPORT_SYMBOL_GPL(xpc_registrations);
0071 
0072 /*
0073  * Initialize the XPC interface to NULL to indicate that XPC isn't loaded.
0074  */
0075 struct xpc_interface xpc_interface = { };
0076 EXPORT_SYMBOL_GPL(xpc_interface);
0077 
0078 /*
0079  * XPC calls this when it (the XPC module) has been loaded.
0080  */
0081 void
0082 xpc_set_interface(void (*connect) (int),
0083           void (*disconnect) (int),
0084           enum xp_retval (*send) (short, int, u32, void *, u16),
0085           enum xp_retval (*send_notify) (short, int, u32, void *, u16,
0086                           xpc_notify_func, void *),
0087           void (*received) (short, int, void *),
0088           enum xp_retval (*partid_to_nasids) (short, void *))
0089 {
0090     xpc_interface.connect = connect;
0091     xpc_interface.disconnect = disconnect;
0092     xpc_interface.send = send;
0093     xpc_interface.send_notify = send_notify;
0094     xpc_interface.received = received;
0095     xpc_interface.partid_to_nasids = partid_to_nasids;
0096 }
0097 EXPORT_SYMBOL_GPL(xpc_set_interface);
0098 
0099 /*
0100  * XPC calls this when it (the XPC module) is being unloaded.
0101  */
0102 void
0103 xpc_clear_interface(void)
0104 {
0105     memset(&xpc_interface, 0, sizeof(xpc_interface));
0106 }
0107 EXPORT_SYMBOL_GPL(xpc_clear_interface);
0108 
0109 /*
0110  * Register for automatic establishment of a channel connection whenever
0111  * a partition comes up.
0112  *
0113  * Arguments:
0114  *
0115  *  ch_number - channel # to register for connection.
0116  *  func - function to call for asynchronous notification of channel
0117  *         state changes (i.e., connection, disconnection, error) and
0118  *         the arrival of incoming messages.
0119  *      key - pointer to optional user-defined value that gets passed back
0120  *        to the user on any callouts made to func.
0121  *  payload_size - size in bytes of the XPC message's payload area which
0122  *             contains a user-defined message. The user should make
0123  *             this large enough to hold their largest message.
0124  *  nentries - max #of XPC message entries a message queue can contain.
0125  *         The actual number, which is determined when a connection
0126  *         is established and may be less then requested, will be
0127  *         passed to the user via the xpConnected callout.
0128  *  assigned_limit - max number of kthreads allowed to be processing
0129  *           messages (per connection) at any given instant.
0130  *  idle_limit - max number of kthreads allowed to be idle at any given
0131  *           instant.
0132  */
0133 enum xp_retval
0134 xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
0135         u16 nentries, u32 assigned_limit, u32 idle_limit)
0136 {
0137     struct xpc_registration *registration;
0138 
0139     DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS);
0140     DBUG_ON(payload_size == 0 || nentries == 0);
0141     DBUG_ON(func == NULL);
0142     DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
0143 
0144     if (XPC_MSG_SIZE(payload_size) > XPC_MSG_MAX_SIZE)
0145         return xpPayloadTooBig;
0146 
0147     registration = &xpc_registrations[ch_number];
0148 
0149     if (mutex_lock_interruptible(&registration->mutex) != 0)
0150         return xpInterrupted;
0151 
0152     /* if XPC_CHANNEL_REGISTERED(ch_number) */
0153     if (registration->func != NULL) {
0154         mutex_unlock(&registration->mutex);
0155         return xpAlreadyRegistered;
0156     }
0157 
0158     /* register the channel for connection */
0159     registration->entry_size = XPC_MSG_SIZE(payload_size);
0160     registration->nentries = nentries;
0161     registration->assigned_limit = assigned_limit;
0162     registration->idle_limit = idle_limit;
0163     registration->key = key;
0164     registration->func = func;
0165 
0166     mutex_unlock(&registration->mutex);
0167 
0168     if (xpc_interface.connect)
0169         xpc_interface.connect(ch_number);
0170 
0171     return xpSuccess;
0172 }
0173 EXPORT_SYMBOL_GPL(xpc_connect);
0174 
0175 /*
0176  * Remove the registration for automatic connection of the specified channel
0177  * when a partition comes up.
0178  *
0179  * Before returning this xpc_disconnect() will wait for all connections on the
0180  * specified channel have been closed/torndown. So the caller can be assured
0181  * that they will not be receiving any more callouts from XPC to their
0182  * function registered via xpc_connect().
0183  *
0184  * Arguments:
0185  *
0186  *  ch_number - channel # to unregister.
0187  */
0188 void
0189 xpc_disconnect(int ch_number)
0190 {
0191     struct xpc_registration *registration;
0192 
0193     DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS);
0194 
0195     registration = &xpc_registrations[ch_number];
0196 
0197     /*
0198      * We've decided not to make this a down_interruptible(), since we
0199      * figured XPC's users will just turn around and call xpc_disconnect()
0200      * again anyways, so we might as well wait, if need be.
0201      */
0202     mutex_lock(&registration->mutex);
0203 
0204     /* if !XPC_CHANNEL_REGISTERED(ch_number) */
0205     if (registration->func == NULL) {
0206         mutex_unlock(&registration->mutex);
0207         return;
0208     }
0209 
0210     /* remove the connection registration for the specified channel */
0211     registration->func = NULL;
0212     registration->key = NULL;
0213     registration->nentries = 0;
0214     registration->entry_size = 0;
0215     registration->assigned_limit = 0;
0216     registration->idle_limit = 0;
0217 
0218     if (xpc_interface.disconnect)
0219         xpc_interface.disconnect(ch_number);
0220 
0221     mutex_unlock(&registration->mutex);
0222 
0223     return;
0224 }
0225 EXPORT_SYMBOL_GPL(xpc_disconnect);
0226 
0227 static int __init
0228 xp_init(void)
0229 {
0230     enum xp_retval ret;
0231     int ch_number;
0232 
0233     /* initialize the connection registration mutex */
0234     for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++)
0235         mutex_init(&xpc_registrations[ch_number].mutex);
0236 
0237     if (is_uv_system())
0238         ret = xp_init_uv();
0239     else
0240         ret = 0;
0241 
0242     if (ret != xpSuccess)
0243         return ret;
0244 
0245     return 0;
0246 }
0247 
0248 module_init(xp_init);
0249 
0250 static void __exit
0251 xp_exit(void)
0252 {
0253     if (is_uv_system())
0254         xp_exit_uv();
0255 }
0256 
0257 module_exit(xp_exit);
0258 
0259 MODULE_AUTHOR("Silicon Graphics, Inc.");
0260 MODULE_DESCRIPTION("Cross Partition (XP) base");
0261 MODULE_LICENSE("GPL");