Netdev List
 help / color / mirror / Atom feed
From: Dimitri Sivanich <sivanich@hpe.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Steve Wahl <steve.wahl@hpe.com>,
	"Anderson, Russ" <russ.anderson@hpe.com>,
	Robin Holt <robinmholt@gmail.com>, Arnd Bergmann <arnd@arndb.de>,
	Kees Cook <kees@kernel.org>, Russell King <linux@armlinux.org.uk>,
	Andrew Morton <akpm@linux-foundation.org>,
	"David Hildenbrand (Arm)" <david@kernel.org>,
	"Lorenzo Stoakes (Oracle)" <ljs@kernel.org>,
	Muhammad Usama Anjum <usama.anjum@arm.com>,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	Dimitri Sivanich <sivanich@hpe.com>
Subject: [PATCH 1/2] misc: sgi-xp: Remove SGI XP drivers
Date: Fri, 31 Jul 2026 09:30:24 -0500	[thread overview]
Message-ID: <amyxgPYeowzWt_8W@hpe.com> (raw)
In-Reply-To: <amywpyZgGWyhzBjZ@hpe.com>

Working XP drivers require the GRU driver.  The GRU driver is being
removed, so remove XP as well.

Signed-off-by: Dimitri Sivanich <sivanich@hpe.com>
---
 MAINTAINERS                         |    6 -
 drivers/misc/Kconfig                |   13 -
 drivers/misc/Makefile               |    1 -
 drivers/misc/sgi-xp/Makefile        |   13 -
 drivers/misc/sgi-xp/xp.h            |  341 ------
 drivers/misc/sgi-xp/xp_main.c       |  261 ----
 drivers/misc/sgi-xp/xp_uv.c         |  151 ---
 drivers/misc/sgi-xp/xpc.h           |  732 ------------
 drivers/misc/sgi-xp/xpc_channel.c   | 1011 ----------------
 drivers/misc/sgi-xp/xpc_main.c      | 1309 --------------------
 drivers/misc/sgi-xp/xpc_partition.c |  545 ---------
 drivers/misc/sgi-xp/xpc_uv.c        | 1728 ---------------------------
 drivers/misc/sgi-xp/xpnet.c         |  599 ----------
 13 files changed, 6710 deletions(-)
 delete mode 100644 drivers/misc/sgi-xp/Makefile
 delete mode 100644 drivers/misc/sgi-xp/xp.h
 delete mode 100644 drivers/misc/sgi-xp/xp_main.c
 delete mode 100644 drivers/misc/sgi-xp/xp_uv.c
 delete mode 100644 drivers/misc/sgi-xp/xpc.h
 delete mode 100644 drivers/misc/sgi-xp/xpc_channel.c
 delete mode 100644 drivers/misc/sgi-xp/xpc_main.c
 delete mode 100644 drivers/misc/sgi-xp/xpc_partition.c
 delete mode 100644 drivers/misc/sgi-xp/xpc_uv.c
 delete mode 100644 drivers/misc/sgi-xp/xpnet.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 62d53465ef9b..0267f5e3ce5e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -24623,12 +24623,6 @@ M:	Dimitri Sivanich <dimitri.sivanich@hpe.com>
 S:	Maintained
 F:	drivers/misc/sgi-gru/
 
-SGI XP/XPC/XPNET DRIVER
-M:	Robin Holt <robinmholt@gmail.com>
-M:	Steve Wahl <steve.wahl@hpe.com>
-S:	Maintained
-F:	drivers/misc/sgi-xp/
-
 SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS
 M:	D. Wythe <alibuda@linux.alibaba.com>
 M:	Dust Li <dust.li@linux.alibaba.com>
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 390256ed91f4..18b09ca716ca 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -185,19 +185,6 @@ config ENCLOSURE_SERVICES
 	  driver (SCSI/ATA) which supports enclosures
 	  or a SCSI enclosure device (SES) to use these services.
 
-config SGI_XP
-	tristate "Support communication between SGI SSIs"
-	depends on NET
-	depends on X86_UV && SMP
-	depends on X86_64 || BROKEN
-	select SGI_GRU if X86_64 && SMP
-	help
-	  An SGI machine can be divided into multiple Single System
-	  Images which act independently of each other and have
-	  hardware based memory protection from the others.  Enabling
-	  this feature will allow for direct communication between SSIs
-	  based on a network adapter and DMA messaging.
-
 config SMPRO_ERRMON
 	tristate "Ampere Computing SMPro error monitor driver"
 	depends on MFD_SMPRO || COMPILE_TEST
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index fed47c7672b9..0e74b550b938 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -22,7 +22,6 @@ obj-$(CONFIG_QCOM_FASTRPC)	+= fastrpc.o
 obj-$(CONFIG_SENSORS_BH1770)	+= bh1770glc.o
 obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
 obj-$(CONFIG_KGDB_TESTS)	+= kgdbts.o
-obj-$(CONFIG_SGI_XP)		+= sgi-xp/
 obj-$(CONFIG_SGI_GRU)		+= sgi-gru/
 obj-$(CONFIG_SMPRO_ERRMON)	+= smpro-errmon.o
 obj-$(CONFIG_SMPRO_MISC)	+= smpro-misc.o
diff --git a/drivers/misc/sgi-xp/Makefile b/drivers/misc/sgi-xp/Makefile
deleted file mode 100644
index 34c55a4045af..000000000000
--- a/drivers/misc/sgi-xp/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for SGI's XP devices.
-#
-
-obj-$(CONFIG_SGI_XP)		+= xp.o
-xp-y				:= xp_main.o xp_uv.o
-
-obj-$(CONFIG_SGI_XP)		+= xpc.o
-xpc-y				:= xpc_main.o xpc_channel.o xpc_partition.o \
-				   xpc_uv.o
-
-obj-$(CONFIG_SGI_XP)		+= xpnet.o
diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h
deleted file mode 100644
index 3185711beb07..000000000000
--- a/drivers/misc/sgi-xp/xp.h
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * 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.
- *
- * (C) Copyright 2020 Hewlett Packard Enterprise Development LP
- * Copyright (C) 2004-2008 Silicon Graphics, Inc. All rights reserved.
- */
-
-/*
- * External Cross Partition (XP) structures and defines.
- */
-
-#ifndef _DRIVERS_MISC_SGIXP_XP_H
-#define _DRIVERS_MISC_SGIXP_XP_H
-
-#include <linux/mutex.h>
-
-#if defined CONFIG_X86_UV
-#include <asm/uv/uv.h>
-#endif
-
-#ifdef USE_DBUG_ON
-#define DBUG_ON(condition)	BUG_ON(condition)
-#else
-#define DBUG_ON(condition)
-#endif
-
-/*
- * Define the maximum number of partitions the system can possibly support.
- * It is based on the maximum number of hardware partitionable regions. 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, IPI and IOI.
- *
- * The maximum number of hardware partitionable regions is equal to the
- * maximum number of nodes in the entire system divided by the minimum number
- * of nodes that comprise an access protection grouping.
- */
-#define XP_MAX_NPARTITIONS_SN2	64
-#define XP_MAX_NPARTITIONS_UV	256
-
-/*
- * XPC establishes channel connections between the local partition and any
- * other partition that is currently up. Over these channels, kernel-level
- * `users' can communicate with their counterparts on the other partitions.
- *
- * If the need for additional channels arises, one can simply increase
- * XPC_MAX_NCHANNELS accordingly. If the day should come where that number
- * exceeds the absolute MAXIMUM number of channels possible (eight), then one
- * will need to make changes to the XPC code to accommodate for this.
- *
- * The absolute maximum number of channels possible is limited to eight for
- * performance reasons on sn2 hardware. The internal cross partition structures
- * require sixteen bytes per channel, and eight allows all of this
- * interface-shared info to fit in one 128-byte cacheline.
- */
-#define XPC_MEM_CHANNEL		0	/* memory channel number */
-#define	XPC_NET_CHANNEL		1	/* network channel number */
-
-#define XPC_MAX_NCHANNELS	2	/* max #of channels allowed */
-
-#if XPC_MAX_NCHANNELS > 8
-#error	XPC_MAX_NCHANNELS exceeds absolute MAXIMUM possible.
-#endif
-
-/*
- * Define macro, XPC_MSG_SIZE(), is provided for the user
- * that wants to fit as many msg entries as possible in a given memory size
- * (e.g. a memory page).
- */
-#define XPC_MSG_MAX_SIZE	128
-#define XPC_MSG_HDR_MAX_SIZE	16
-#define XPC_MSG_PAYLOAD_MAX_SIZE (XPC_MSG_MAX_SIZE - XPC_MSG_HDR_MAX_SIZE)
-
-#define XPC_MSG_SIZE(_payload_size) \
-				ALIGN(XPC_MSG_HDR_MAX_SIZE + (_payload_size), \
-				      is_uv_system() ? 64 : 128)
-
-
-/*
- * Define the return values and values passed to user's callout functions.
- * (It is important to add new value codes at the end just preceding
- * xpUnknownReason, which must have the highest numerical value.)
- */
-enum xp_retval {
-	xpSuccess = 0,
-
-	xpNotConnected,		/*  1: channel is not connected */
-	xpConnected,		/*  2: channel connected (opened) */
-	xpRETIRED1,		/*  3: (formerly xpDisconnected) */
-
-	xpMsgReceived,		/*  4: message received */
-	xpMsgDelivered,		/*  5: message delivered and acknowledged */
-
-	xpRETIRED2,		/*  6: (formerly xpTransferFailed) */
-
-	xpNoWait,		/*  7: operation would require wait */
-	xpRetry,		/*  8: retry operation */
-	xpTimeout,		/*  9: timeout in xpc_allocate_msg_wait() */
-	xpInterrupted,		/* 10: interrupted wait */
-
-	xpUnequalMsgSizes,	/* 11: message size disparity between sides */
-	xpInvalidAddress,	/* 12: invalid address */
-
-	xpNoMemory,		/* 13: no memory available for XPC structures */
-	xpLackOfResources,	/* 14: insufficient resources for operation */
-	xpUnregistered,		/* 15: channel is not registered */
-	xpAlreadyRegistered,	/* 16: channel is already registered */
-
-	xpPartitionDown,	/* 17: remote partition is down */
-	xpNotLoaded,		/* 18: XPC module is not loaded */
-	xpUnloading,		/* 19: this side is unloading XPC module */
-
-	xpBadMagic,		/* 20: XPC MAGIC string not found */
-
-	xpReactivating,		/* 21: remote partition was reactivated */
-
-	xpUnregistering,	/* 22: this side is unregistering channel */
-	xpOtherUnregistering,	/* 23: other side is unregistering channel */
-
-	xpCloneKThread,		/* 24: cloning kernel thread */
-	xpCloneKThreadFailed,	/* 25: cloning kernel thread failed */
-
-	xpNoHeartbeat,		/* 26: remote partition has no heartbeat */
-
-	xpPioReadError,		/* 27: PIO read error */
-	xpPhysAddrRegFailed,	/* 28: registration of phys addr range failed */
-
-	xpRETIRED3,		/* 29: (formerly xpBteDirectoryError) */
-	xpRETIRED4,		/* 30: (formerly xpBtePoisonError) */
-	xpRETIRED5,		/* 31: (formerly xpBteWriteError) */
-	xpRETIRED6,		/* 32: (formerly xpBteAccessError) */
-	xpRETIRED7,		/* 33: (formerly xpBtePWriteError) */
-	xpRETIRED8,		/* 34: (formerly xpBtePReadError) */
-	xpRETIRED9,		/* 35: (formerly xpBteTimeOutError) */
-	xpRETIRED10,		/* 36: (formerly xpBteXtalkError) */
-	xpRETIRED11,		/* 37: (formerly xpBteNotAvailable) */
-	xpRETIRED12,		/* 38: (formerly xpBteUnmappedError) */
-
-	xpBadVersion,		/* 39: bad version number */
-	xpVarsNotSet,		/* 40: the XPC variables are not set up */
-	xpNoRsvdPageAddr,	/* 41: unable to get rsvd page's phys addr */
-	xpInvalidPartid,	/* 42: invalid partition ID */
-	xpLocalPartid,		/* 43: local partition ID */
-
-	xpOtherGoingDown,	/* 44: other side going down, reason unknown */
-	xpSystemGoingDown,	/* 45: system is going down, reason unknown */
-	xpSystemHalt,		/* 46: system is being halted */
-	xpSystemReboot,		/* 47: system is being rebooted */
-	xpSystemPoweroff,	/* 48: system is being powered off */
-
-	xpDisconnecting,	/* 49: channel disconnecting (closing) */
-
-	xpOpenCloseError,	/* 50: channel open/close protocol error */
-
-	xpDisconnected,		/* 51: channel disconnected (closed) */
-
-	xpBteCopyError,		/* 52: bte_copy() returned error */
-	xpSalError,		/* 53: sn SAL error */
-	xpRsvdPageNotSet,	/* 54: the reserved page is not set up */
-	xpPayloadTooBig,	/* 55: payload too large for message slot */
-
-	xpUnsupported,		/* 56: unsupported functionality or resource */
-	xpNeedMoreInfo,		/* 57: more info is needed by SAL */
-
-	xpGruCopyError,		/* 58: gru_copy_gru() returned error */
-	xpGruSendMqError,	/* 59: gru send message queue related error */
-
-	xpBadChannelNumber,	/* 60: invalid channel number */
-	xpBadMsgType,		/* 61: invalid message type */
-	xpBiosError,		/* 62: BIOS error */
-
-	xpUnknownReason		/* 63: unknown reason - must be last in enum */
-};
-
-/*
- * Define the callout function type used by XPC to update the user on
- * connection activity and state changes via the user function registered
- * by xpc_connect().
- *
- * Arguments:
- *
- *	reason - reason code.
- *	partid - partition ID associated with condition.
- *	ch_number - channel # associated with condition.
- *	data - pointer to optional data.
- *	key - pointer to optional user-defined value provided as the "key"
- *	      argument to xpc_connect().
- *
- * A reason code of xpConnected indicates that a connection has been
- * established to the specified partition on the specified channel. The data
- * argument indicates the max number of entries allowed in the message queue.
- *
- * A reason code of xpMsgReceived indicates that a XPC message arrived from
- * the specified partition on the specified channel. The data argument
- * specifies the address of the message's payload. The user must call
- * xpc_received() when finished with the payload.
- *
- * All other reason codes indicate failure. The data argmument is NULL.
- * When a failure reason code is received, one can assume that the channel
- * is not connected.
- */
-typedef void (*xpc_channel_func) (enum xp_retval reason, short partid,
-				  int ch_number, void *data, void *key);
-
-/*
- * Define the callout function type used by XPC to notify the user of
- * messages received and delivered via the user function registered by
- * xpc_send_notify().
- *
- * Arguments:
- *
- *	reason - reason code.
- *	partid - partition ID associated with condition.
- *	ch_number - channel # associated with condition.
- *	key - pointer to optional user-defined value provided as the "key"
- *	      argument to xpc_send_notify().
- *
- * A reason code of xpMsgDelivered indicates that the message was delivered
- * to the intended recipient and that they have acknowledged its receipt by
- * calling xpc_received().
- *
- * All other reason codes indicate failure.
- *
- * NOTE: The user defined function must be callable by an interrupt handler
- *       and thus cannot block.
- */
-typedef void (*xpc_notify_func) (enum xp_retval reason, short partid,
-				 int ch_number, void *key);
-
-/*
- * The following is a registration entry. There is a global array of these,
- * one per channel. It is used to record the connection registration made
- * by the users of XPC. As long as a registration entry exists, for any
- * partition that comes up, XPC will attempt to establish a connection on
- * that channel. Notification that a connection has been made will occur via
- * the xpc_channel_func function.
- *
- * The 'func' field points to the function to call when aynchronous
- * notification is required for such events as: a connection established/lost,
- * or an incoming message received, or an error condition encountered. A
- * non-NULL 'func' field indicates that there is an active registration for
- * the channel.
- */
-struct xpc_registration {
-	struct mutex mutex;
-	xpc_channel_func func;	/* function to call */
-	void *key;		/* pointer to user's key */
-	u16 nentries;		/* #of msg entries in local msg queue */
-	u16 entry_size;		/* message queue's message entry size */
-	u32 assigned_limit;	/* limit on #of assigned kthreads */
-	u32 idle_limit;		/* limit on #of idle kthreads */
-} ____cacheline_aligned;
-
-#define XPC_CHANNEL_REGISTERED(_c)	(xpc_registrations[_c].func != NULL)
-
-/* the following are valid xpc_send() or xpc_send_notify() flags */
-#define XPC_WAIT	0	/* wait flag */
-#define XPC_NOWAIT	1	/* no wait flag */
-
-struct xpc_interface {
-	void (*connect) (int);
-	void (*disconnect) (int);
-	enum xp_retval (*send) (short, int, u32, void *, u16);
-	enum xp_retval (*send_notify) (short, int, u32, void *, u16,
-					xpc_notify_func, void *);
-	void (*received) (short, int, void *);
-	enum xp_retval (*partid_to_nasids) (short, void *);
-};
-
-extern struct xpc_interface xpc_interface;
-
-extern void xpc_set_interface(void (*)(int),
-			      void (*)(int),
-			      enum xp_retval (*)(short, int, u32, void *, u16),
-			      enum xp_retval (*)(short, int, u32, void *, u16,
-						 xpc_notify_func, void *),
-			      void (*)(short, int, void *),
-			      enum xp_retval (*)(short, void *));
-extern void xpc_clear_interface(void);
-
-extern enum xp_retval xpc_connect(int, xpc_channel_func, void *, u16,
-				   u16, u32, u32);
-extern void xpc_disconnect(int);
-
-static inline enum xp_retval
-xpc_send(short partid, int ch_number, u32 flags, void *payload,
-	 u16 payload_size)
-{
-	if (!xpc_interface.send)
-		return xpNotLoaded;
-
-	return xpc_interface.send(partid, ch_number, flags, payload,
-				  payload_size);
-}
-
-static inline enum xp_retval
-xpc_send_notify(short partid, int ch_number, u32 flags, void *payload,
-		u16 payload_size, xpc_notify_func func, void *key)
-{
-	if (!xpc_interface.send_notify)
-		return xpNotLoaded;
-
-	return xpc_interface.send_notify(partid, ch_number, flags, payload,
-					 payload_size, func, key);
-}
-
-static inline void
-xpc_received(short partid, int ch_number, void *payload)
-{
-	if (xpc_interface.received)
-		xpc_interface.received(partid, ch_number, payload);
-}
-
-static inline enum xp_retval
-xpc_partid_to_nasids(short partid, void *nasids)
-{
-	if (!xpc_interface.partid_to_nasids)
-		return xpNotLoaded;
-
-	return xpc_interface.partid_to_nasids(partid, nasids);
-}
-
-extern short xp_max_npartitions;
-extern short xp_partition_id;
-extern u8 xp_region_size;
-
-extern unsigned long (*xp_pa) (void *);
-extern unsigned long (*xp_socket_pa) (unsigned long);
-extern enum xp_retval (*xp_remote_memcpy) (unsigned long, const unsigned long,
-		       size_t);
-extern int (*xp_cpu_to_nasid) (int);
-extern enum xp_retval (*xp_expand_memprotect) (unsigned long, unsigned long);
-extern enum xp_retval (*xp_restrict_memprotect) (unsigned long, unsigned long);
-
-extern struct device *xp;
-extern enum xp_retval xp_init_uv(void);
-extern void xp_exit_uv(void);
-
-#endif /* _DRIVERS_MISC_SGIXP_XP_H */
diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c
deleted file mode 100644
index 87d156c15f35..000000000000
--- a/drivers/misc/sgi-xp/xp_main.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * 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.
- *
- * (C) Copyright 2020 Hewlett Packard Enterprise Development LP
- * Copyright (c) 2004-2008 Silicon Graphics, Inc.  All Rights Reserved.
- */
-
-/*
- * 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>
-#include <linux/device.h>
-#include "xp.h"
-
-/* define the XP debug device structures to be used with dev_dbg() et al */
-
-static struct device_driver xp_dbg_name = {
-	.name = "xp"
-};
-
-static struct device xp_dbg_subname = {
-	.init_name = "",		/* set to "" */
-	.driver = &xp_dbg_name
-};
-
-struct device *xp = &xp_dbg_subname;
-
-/* max #of partitions possible */
-short xp_max_npartitions;
-EXPORT_SYMBOL_GPL(xp_max_npartitions);
-
-short xp_partition_id;
-EXPORT_SYMBOL_GPL(xp_partition_id);
-
-u8 xp_region_size;
-EXPORT_SYMBOL_GPL(xp_region_size);
-
-unsigned long (*xp_pa) (void *addr);
-EXPORT_SYMBOL_GPL(xp_pa);
-
-unsigned long (*xp_socket_pa) (unsigned long gpa);
-EXPORT_SYMBOL_GPL(xp_socket_pa);
-
-enum xp_retval (*xp_remote_memcpy) (unsigned long dst_gpa,
-				    const unsigned long src_gpa, size_t len);
-EXPORT_SYMBOL_GPL(xp_remote_memcpy);
-
-int (*xp_cpu_to_nasid) (int cpuid);
-EXPORT_SYMBOL_GPL(xp_cpu_to_nasid);
-
-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);
-
-/*
- * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
- * users of XPC.
- */
-struct xpc_registration xpc_registrations[XPC_MAX_NCHANNELS];
-EXPORT_SYMBOL_GPL(xpc_registrations);
-
-/*
- * Initialize the XPC interface to NULL to indicate that XPC isn't loaded.
- */
-struct xpc_interface xpc_interface = { };
-EXPORT_SYMBOL_GPL(xpc_interface);
-
-/*
- * XPC calls this when it (the XPC module) has been loaded.
- */
-void
-xpc_set_interface(void (*connect) (int),
-		  void (*disconnect) (int),
-		  enum xp_retval (*send) (short, int, u32, void *, u16),
-		  enum xp_retval (*send_notify) (short, int, u32, void *, u16,
-						  xpc_notify_func, void *),
-		  void (*received) (short, int, void *),
-		  enum xp_retval (*partid_to_nasids) (short, void *))
-{
-	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;
-}
-EXPORT_SYMBOL_GPL(xpc_set_interface);
-
-/*
- * XPC calls this when it (the XPC module) is being unloaded.
- */
-void
-xpc_clear_interface(void)
-{
-	memset(&xpc_interface, 0, sizeof(xpc_interface));
-}
-EXPORT_SYMBOL_GPL(xpc_clear_interface);
-
-/*
- * 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
- *		   passed to the user via the xpConnected callout.
- *	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.
- */
-enum xp_retval
-xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
-	    u16 nentries, u32 assigned_limit, u32 idle_limit)
-{
-	struct xpc_registration *registration;
-
-	DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS);
-	DBUG_ON(payload_size == 0 || nentries == 0);
-	DBUG_ON(func == NULL);
-	DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
-
-	if (XPC_MSG_SIZE(payload_size) > XPC_MSG_MAX_SIZE)
-		return xpPayloadTooBig;
-
-	registration = &xpc_registrations[ch_number];
-
-	if (mutex_lock_interruptible(&registration->mutex) != 0)
-		return xpInterrupted;
-
-	/* if XPC_CHANNEL_REGISTERED(ch_number) */
-	if (registration->func != NULL) {
-		mutex_unlock(&registration->mutex);
-		return xpAlreadyRegistered;
-	}
-
-	/* register the channel for connection */
-	registration->entry_size = XPC_MSG_SIZE(payload_size);
-	registration->nentries = nentries;
-	registration->assigned_limit = assigned_limit;
-	registration->idle_limit = idle_limit;
-	registration->key = key;
-	registration->func = func;
-
-	mutex_unlock(&registration->mutex);
-
-	if (xpc_interface.connect)
-		xpc_interface.connect(ch_number);
-
-	return xpSuccess;
-}
-EXPORT_SYMBOL_GPL(xpc_connect);
-
-/*
- * 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;
-
-	DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS);
-
-	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.
-	 */
-	mutex_lock(&registration->mutex);
-
-	/* if !XPC_CHANNEL_REGISTERED(ch_number) */
-	if (registration->func == NULL) {
-		mutex_unlock(&registration->mutex);
-		return;
-	}
-
-	/* remove the connection registration for the specified channel */
-	registration->func = NULL;
-	registration->key = NULL;
-	registration->nentries = 0;
-	registration->entry_size = 0;
-	registration->assigned_limit = 0;
-	registration->idle_limit = 0;
-
-	if (xpc_interface.disconnect)
-		xpc_interface.disconnect(ch_number);
-
-	mutex_unlock(&registration->mutex);
-
-	return;
-}
-EXPORT_SYMBOL_GPL(xpc_disconnect);
-
-static int __init
-xp_init(void)
-{
-	enum xp_retval ret;
-	int ch_number;
-
-	/* initialize the connection registration mutex */
-	for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++)
-		mutex_init(&xpc_registrations[ch_number].mutex);
-
-	if (is_uv_system())
-		ret = xp_init_uv();
-	else
-		ret = 0;
-
-	if (ret != xpSuccess)
-		return ret;
-
-	return 0;
-}
-
-module_init(xp_init);
-
-static void __exit
-xp_exit(void)
-{
-	if (is_uv_system())
-		xp_exit_uv();
-}
-
-module_exit(xp_exit);
-
-MODULE_AUTHOR("Silicon Graphics, Inc.");
-MODULE_DESCRIPTION("Cross Partition (XP) base");
-MODULE_LICENSE("GPL");
diff --git a/drivers/misc/sgi-xp/xp_uv.c b/drivers/misc/sgi-xp/xp_uv.c
deleted file mode 100644
index 3faa7eadf679..000000000000
--- a/drivers/misc/sgi-xp/xp_uv.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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.
- *
- * (C) Copyright 2020 Hewlett Packard Enterprise Development LP
- * Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
- */
-
-/*
- * Cross Partition (XP) uv-based functions.
- *
- *      Architecture specific implementation of common functions.
- *
- */
-
-#include <linux/device.h>
-#include <asm/uv/uv_hub.h>
-#if defined CONFIG_X86_64
-#include <asm/uv/bios.h>
-#endif
-#include "../sgi-gru/grukservices.h"
-#include "xp.h"
-
-/*
- * Convert a virtual memory address to a physical memory address.
- */
-static unsigned long
-xp_pa_uv(void *addr)
-{
-	return uv_gpa(addr);
-}
-
-/*
- * Convert a global physical to socket physical address.
- */
-static unsigned long
-xp_socket_pa_uv(unsigned long gpa)
-{
-	return uv_gpa_to_soc_phys_ram(gpa);
-}
-
-static enum xp_retval
-xp_remote_mmr_read(unsigned long dst_gpa, const unsigned long src_gpa,
-		   size_t len)
-{
-	int ret;
-	unsigned long *dst_va = __va(uv_gpa_to_soc_phys_ram(dst_gpa));
-
-	BUG_ON(!uv_gpa_in_mmr_space(src_gpa));
-	BUG_ON(len != 8);
-
-	ret = gru_read_gpa(dst_va, src_gpa);
-	if (ret == 0)
-		return xpSuccess;
-
-	dev_err(xp, "gru_read_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx "
-		"len=%ld\n", dst_gpa, src_gpa, len);
-	return xpGruCopyError;
-}
-
-
-static enum xp_retval
-xp_remote_memcpy_uv(unsigned long dst_gpa, const unsigned long src_gpa,
-		    size_t len)
-{
-	int ret;
-
-	if (uv_gpa_in_mmr_space(src_gpa))
-		return xp_remote_mmr_read(dst_gpa, src_gpa, len);
-
-	ret = gru_copy_gpa(dst_gpa, src_gpa, len);
-	if (ret == 0)
-		return xpSuccess;
-
-	dev_err(xp, "gru_copy_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx "
-		"len=%ld\n", dst_gpa, src_gpa, len);
-	return xpGruCopyError;
-}
-
-static int
-xp_cpu_to_nasid_uv(int cpuid)
-{
-	/* ??? Is this same as sn2 nasid in mach/part bitmaps set up by SAL? */
-	return UV_PNODE_TO_NASID(uv_cpu_to_pnode(cpuid));
-}
-
-static enum xp_retval
-xp_expand_memprotect_uv(unsigned long phys_addr, unsigned long size)
-{
-	int ret;
-
-#if defined CONFIG_X86_64
-	ret = uv_bios_change_memprotect(phys_addr, size, UV_MEMPROT_ALLOW_RW);
-	if (ret != BIOS_STATUS_SUCCESS) {
-		dev_err(xp, "uv_bios_change_memprotect(,, "
-			"UV_MEMPROT_ALLOW_RW) failed, ret=%d\n", ret);
-		return xpBiosError;
-	}
-#else
-	#error not a supported configuration
-#endif
-	return xpSuccess;
-}
-
-static enum xp_retval
-xp_restrict_memprotect_uv(unsigned long phys_addr, unsigned long size)
-{
-	int ret;
-
-#if defined CONFIG_X86_64
-	ret = uv_bios_change_memprotect(phys_addr, size,
-					UV_MEMPROT_RESTRICT_ACCESS);
-	if (ret != BIOS_STATUS_SUCCESS) {
-		dev_err(xp, "uv_bios_change_memprotect(,, "
-			"UV_MEMPROT_RESTRICT_ACCESS) failed, ret=%d\n", ret);
-		return xpBiosError;
-	}
-#else
-	#error not a supported configuration
-#endif
-	return xpSuccess;
-}
-
-enum xp_retval
-xp_init_uv(void)
-{
-	WARN_ON(!is_uv_system());
-	if (!is_uv_system())
-		return xpUnsupported;
-
-	xp_max_npartitions = XP_MAX_NPARTITIONS_UV;
-#ifdef CONFIG_X86
-	xp_partition_id = sn_partition_id;
-	xp_region_size = sn_region_size;
-#endif
-	xp_pa = xp_pa_uv;
-	xp_socket_pa = xp_socket_pa_uv;
-	xp_remote_memcpy = xp_remote_memcpy_uv;
-	xp_cpu_to_nasid = xp_cpu_to_nasid_uv;
-	xp_expand_memprotect = xp_expand_memprotect_uv;
-	xp_restrict_memprotect = xp_restrict_memprotect_uv;
-
-	return xpSuccess;
-}
-
-void
-xp_exit_uv(void)
-{
-	WARN_ON(!is_uv_system());
-}
diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h
deleted file mode 100644
index 225f2bb84e39..000000000000
--- a/drivers/misc/sgi-xp/xpc.h
+++ /dev/null
@@ -1,732 +0,0 @@
-/*
- * 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.
- *
- * Copyright (c) 2004-2009 Silicon Graphics, Inc.  All Rights Reserved.
- */
-
-/*
- * Cross Partition Communication (XPC) structures and macros.
- */
-
-#ifndef _DRIVERS_MISC_SGIXP_XPC_H
-#define _DRIVERS_MISC_SGIXP_XPC_H
-
-#include <linux/wait.h>
-#include <linux/completion.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include "xp.h"
-
-/*
- * XPC Version numbers consist of a major and minor number. XPC can always
- * talk to versions with same major #, and never talk to versions with a
- * different major #.
- */
-#define _XPC_VERSION(_maj, _min)	(((_maj) << 4) | ((_min) & 0xf))
-#define XPC_VERSION_MAJOR(_v)		((_v) >> 4)
-#define XPC_VERSION_MINOR(_v)		((_v) & 0xf)
-
-/* define frequency of the heartbeat and frequency how often it's checked */
-#define XPC_HB_DEFAULT_INTERVAL		5	/* incr HB every x secs */
-#define XPC_HB_CHECK_DEFAULT_INTERVAL	20	/* check HB every x secs */
-
-/* define the process name of HB checker and the CPU it is pinned to */
-#define XPC_HB_CHECK_THREAD_NAME	"xpc_hb"
-#define XPC_HB_CHECK_CPU		0
-
-/* define the process name of the discovery thread */
-#define XPC_DISCOVERY_THREAD_NAME	"xpc_discovery"
-
-/*
- * the reserved page
- *
- *   SAL reserves one page of memory per partition for XPC. Though a full page
- *   in length (16384 bytes), its starting address is not page aligned, but it
- *   is cacheline aligned. The reserved page consists of the following:
- *
- *   reserved page header
- *
- *     The first two 64-byte cachelines of the reserved page contain the
- *     header (struct xpc_rsvd_page). Before SAL initialization has completed,
- *     SAL has set up the following fields of the reserved page header:
- *     SAL_signature, SAL_version, SAL_partid, and SAL_nasids_size. The
- *     other fields are set up by XPC. (xpc_rsvd_page points to the local
- *     partition's reserved page.)
- *
- *   part_nasids mask
- *   mach_nasids mask
- *
- *     SAL also sets up two bitmaps (or masks), one that reflects the actual
- *     nasids in this partition (part_nasids), and the other that reflects
- *     the actual nasids in the entire machine (mach_nasids). We're only
- *     interested in the even numbered nasids (which contain the processors
- *     and/or memory), so we only need half as many bits to represent the
- *     nasids. When mapping nasid to bit in a mask (or bit to nasid) be sure
- *     to either divide or multiply by 2. The part_nasids mask is located
- *     starting at the first cacheline following the reserved page header. The
- *     mach_nasids mask follows right after the part_nasids mask. The size in
- *     bytes of each mask is reflected by the reserved page header field
- *     'SAL_nasids_size'. (Local partition's mask pointers are xpc_part_nasids
- *     and xpc_mach_nasids.)
- *
- *     Immediately following the mach_nasids mask are the XPC variables
- *     required by other partitions. First are those that are generic to all
- *     partitions (vars), followed on the next available cacheline by those
- *     which are partition specific (vars part). These are setup by XPC.
- *
- * Note: Until 'ts_jiffies' is set non-zero, the partition XPC code has not been
- *       initialized.
- */
-struct xpc_rsvd_page {
-	u64 SAL_signature;	/* SAL: unique signature */
-	u64 SAL_version;	/* SAL: version */
-	short SAL_partid;	/* SAL: partition ID */
-	short max_npartitions;	/* value of XPC_MAX_PARTITIONS */
-	u8 version;
-	u8 pad1[3];		/* align to next u64 in 1st 64-byte cacheline */
-	unsigned long ts_jiffies; /* timestamp when rsvd pg was setup by XPC */
-	union {
-		struct {
-			unsigned long heartbeat_gpa; /* phys addr */
-			unsigned long activate_gru_mq_desc_gpa; /* phys addr */
-		} uv;
-	} sn;
-	u64 pad2[9];		/* align to last u64 in 2nd 64-byte cacheline */
-	u64 SAL_nasids_size;	/* SAL: size of each nasid mask in bytes */
-};
-
-#define XPC_RP_VERSION _XPC_VERSION(3, 0) /* version 3.0 of the reserved page */
-
-/* the reserved page sizes and offsets */
-
-#define XPC_RP_HEADER_SIZE	L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))
-
-#define XPC_RP_PART_NASIDS(_rp) ((unsigned long *)((u8 *)(_rp) + \
-				 XPC_RP_HEADER_SIZE))
-#define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + \
-				 xpc_nasid_mask_nlongs)
-
-
-/*
- * The following structure describes the partition's heartbeat info which
- * will be periodically read by other partitions to determine whether this
- * XPC is still 'alive'.
- */
-struct xpc_heartbeat_uv {
-	unsigned long value;
-	unsigned long offline;	/* if 0, heartbeat should be changing */
-};
-
-/*
- * Info pertinent to a GRU message queue using a watch list for irq generation.
- */
-struct xpc_gru_mq_uv {
-	void *address;		/* address of GRU message queue */
-	unsigned int order;	/* size of GRU message queue as a power of 2 */
-	int irq;		/* irq raised when message is received in mq */
-	int mmr_blade;		/* blade where watchlist was allocated from */
-	unsigned long mmr_offset; /* offset of irq mmr located on mmr_blade */
-	unsigned long mmr_value; /* value of irq mmr located on mmr_blade */
-	int watchlist_num;	/* number of watchlist allocatd by BIOS */
-	void *gru_mq_desc;	/* opaque structure used by the GRU driver */
-};
-
-/*
- * The activate_mq is used to send/receive GRU messages that affect XPC's
- * partition active state and channel state. This is uv only.
- */
-struct xpc_activate_mq_msghdr_uv {
-	unsigned int gru_msg_hdr; /* FOR GRU INTERNAL USE ONLY */
-	short partid;		/* sender's partid */
-	u8 act_state;		/* sender's act_state at time msg sent */
-	u8 type;		/* message's type */
-	unsigned long rp_ts_jiffies; /* timestamp of sender's rp setup by XPC */
-};
-
-/* activate_mq defined message types */
-#define XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV		0
-
-#define XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV		1
-#define XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV		2
-
-#define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV	3
-#define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV		4
-#define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV	5
-#define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV		6
-#define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV	7
-
-#define XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV		8
-#define XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV		9
-
-struct xpc_activate_mq_msg_uv {
-	struct xpc_activate_mq_msghdr_uv hdr;
-};
-
-struct xpc_activate_mq_msg_activate_req_uv {
-	struct xpc_activate_mq_msghdr_uv hdr;
-	unsigned long rp_gpa;
-	unsigned long heartbeat_gpa;
-	unsigned long activate_gru_mq_desc_gpa;
-};
-
-struct xpc_activate_mq_msg_deactivate_req_uv {
-	struct xpc_activate_mq_msghdr_uv hdr;
-	enum xp_retval reason;
-};
-
-struct xpc_activate_mq_msg_chctl_closerequest_uv {
-	struct xpc_activate_mq_msghdr_uv hdr;
-	short ch_number;
-	enum xp_retval reason;
-};
-
-struct xpc_activate_mq_msg_chctl_closereply_uv {
-	struct xpc_activate_mq_msghdr_uv hdr;
-	short ch_number;
-};
-
-struct xpc_activate_mq_msg_chctl_openrequest_uv {
-	struct xpc_activate_mq_msghdr_uv hdr;
-	short ch_number;
-	short entry_size;	/* size of notify_mq's GRU messages */
-	short local_nentries;	/* ??? Is this needed? What is? */
-};
-
-struct xpc_activate_mq_msg_chctl_openreply_uv {
-	struct xpc_activate_mq_msghdr_uv hdr;
-	short ch_number;
-	short remote_nentries;	/* ??? Is this needed? What is? */
-	short local_nentries;	/* ??? Is this needed? What is? */
-	unsigned long notify_gru_mq_desc_gpa;
-};
-
-struct xpc_activate_mq_msg_chctl_opencomplete_uv {
-	struct xpc_activate_mq_msghdr_uv hdr;
-	short ch_number;
-};
-
-/*
- * Functions registered by add_timer() or called by kernel_thread() only
- * allow for a single 64-bit argument. The following macros can be used to
- * pack and unpack two (32-bit, 16-bit or 8-bit) arguments into or out from
- * the passed argument.
- */
-#define XPC_PACK_ARGS(_arg1, _arg2) \
-			((((u64)_arg1) & 0xffffffff) | \
-			((((u64)_arg2) & 0xffffffff) << 32))
-
-#define XPC_UNPACK_ARG1(_args)	(((u64)_args) & 0xffffffff)
-#define XPC_UNPACK_ARG2(_args)	((((u64)_args) >> 32) & 0xffffffff)
-
-/*
- * Define a structure that contains arguments associated with opening and
- * closing a channel.
- */
-struct xpc_openclose_args {
-	u16 reason;		/* reason why channel is closing */
-	u16 entry_size;		/* sizeof each message entry */
-	u16 remote_nentries;	/* #of message entries in remote msg queue */
-	u16 local_nentries;	/* #of message entries in local msg queue */
-	unsigned long local_msgqueue_pa; /* phys addr of local message queue */
-};
-
-#define XPC_OPENCLOSE_ARGS_SIZE \
-	      L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * \
-	      XPC_MAX_NCHANNELS)
-
-
-/*
- * Structures to define a fifo singly-linked list.
- */
-
-struct xpc_fifo_entry_uv {
-	struct xpc_fifo_entry_uv *next;
-};
-
-struct xpc_fifo_head_uv {
-	struct xpc_fifo_entry_uv *first;
-	struct xpc_fifo_entry_uv *last;
-	spinlock_t lock;
-	int n_entries;
-};
-
-/*
- * The format of a uv XPC notify_mq GRU message is as follows:
- *
- * A user-defined message resides in the payload area. The max size of the
- * payload is defined by the user via xpc_connect().
- *
- * The size of a message (payload and header) sent via the GRU must be either 1
- * or 2 GRU_CACHE_LINE_BYTES in length.
- */
-
-struct xpc_notify_mq_msghdr_uv {
-	union {
-		unsigned int gru_msg_hdr;	/* FOR GRU INTERNAL USE ONLY */
-		struct xpc_fifo_entry_uv next;	/* FOR XPC INTERNAL USE ONLY */
-	} u;
-	short partid;		/* FOR XPC INTERNAL USE ONLY */
-	u8 ch_number;		/* FOR XPC INTERNAL USE ONLY */
-	u8 size;		/* FOR XPC INTERNAL USE ONLY */
-	unsigned int msg_slot_number;	/* FOR XPC INTERNAL USE ONLY */
-};
-
-struct xpc_notify_mq_msg_uv {
-	struct xpc_notify_mq_msghdr_uv hdr;
-	unsigned long payload;
-};
-
-/* struct xpc_notify_sn2 type of notification */
-
-#define	XPC_N_CALL	0x01	/* notify function provided by user */
-
-/*
- * Define uv's version of the notify entry. It additionally is used to allocate
- * a msg slot on the remote partition into which is copied a sent message.
- */
-struct xpc_send_msg_slot_uv {
-	struct xpc_fifo_entry_uv next;
-	unsigned int msg_slot_number;
-	xpc_notify_func func;	/* user's notify function */
-	void *key;		/* pointer to user's key */
-};
-
-/*
- * Define the structure that manages all the stuff required by a channel. In
- * particular, they are used to manage the messages sent across the channel.
- *
- * This structure is private to a partition, and is NOT shared across the
- * partition boundary.
- *
- * There is an array of these structures for each remote partition. It is
- * allocated at the time a partition becomes active. The array contains one
- * of these structures for each potential channel connection to that partition.
- */
-
-struct xpc_channel_uv {
-	void *cached_notify_gru_mq_desc; /* remote partition's notify mq's */
-					 /* gru mq descriptor */
-
-	struct xpc_send_msg_slot_uv *send_msg_slots;
-	void *recv_msg_slots;	/* each slot will hold a xpc_notify_mq_msg_uv */
-				/* structure plus the user's payload */
-
-	struct xpc_fifo_head_uv msg_slot_free_list;
-	struct xpc_fifo_head_uv recv_msg_list;	/* deliverable payloads */
-};
-
-struct xpc_channel {
-	short partid;		/* ID of remote partition connected */
-	spinlock_t lock;	/* lock for updating this structure */
-	unsigned int flags;	/* general flags */
-
-	enum xp_retval reason;	/* reason why channel is disconnect'g */
-	int reason_line;	/* line# disconnect initiated from */
-
-	u16 number;		/* channel # */
-
-	u16 entry_size;		/* sizeof each msg entry */
-	u16 local_nentries;	/* #of msg entries in local msg queue */
-	u16 remote_nentries;	/* #of msg entries in remote msg queue */
-
-	atomic_t references;	/* #of external references to queues */
-
-	atomic_t n_on_msg_allocate_wq;	/* #on msg allocation wait queue */
-	wait_queue_head_t msg_allocate_wq;	/* msg allocation wait queue */
-
-	u8 delayed_chctl_flags;	/* chctl flags received, but delayed */
-				/* action until channel disconnected */
-
-	atomic_t n_to_notify;	/* #of msg senders to notify */
-
-	xpc_channel_func func;	/* user's channel function */
-	void *key;		/* pointer to user's key */
-
-	struct completion wdisconnect_wait;    /* wait for channel disconnect */
-
-	/* kthread management related fields */
-
-	atomic_t kthreads_assigned;	/* #of kthreads assigned to channel */
-	u32 kthreads_assigned_limit;	/* limit on #of kthreads assigned */
-	atomic_t kthreads_idle;	/* #of kthreads idle waiting for work */
-	u32 kthreads_idle_limit;	/* limit on #of kthreads idle */
-	atomic_t kthreads_active;	/* #of kthreads actively working */
-
-	wait_queue_head_t idle_wq;	/* idle kthread wait queue */
-
-	union {
-		struct xpc_channel_uv uv;
-	} sn;
-
-} ____cacheline_aligned;
-
-/* struct xpc_channel flags */
-
-#define	XPC_C_WASCONNECTED	0x00000001	/* channel was connected */
-
-#define XPC_C_ROPENCOMPLETE	0x00000002    /* remote open channel complete */
-#define XPC_C_OPENCOMPLETE	0x00000004     /* local open channel complete */
-#define	XPC_C_ROPENREPLY	0x00000008	/* remote open channel reply */
-#define	XPC_C_OPENREPLY		0x00000010	/* local open channel reply */
-#define	XPC_C_ROPENREQUEST	0x00000020     /* remote open channel request */
-#define	XPC_C_OPENREQUEST	0x00000040	/* local open channel request */
-
-#define	XPC_C_SETUP		0x00000080 /* channel's msgqueues are alloc'd */
-#define	XPC_C_CONNECTEDCALLOUT	0x00000100     /* connected callout initiated */
-#define	XPC_C_CONNECTEDCALLOUT_MADE \
-				0x00000200     /* connected callout completed */
-#define	XPC_C_CONNECTED		0x00000400	/* local channel is connected */
-#define	XPC_C_CONNECTING	0x00000800	/* channel is being connected */
-
-#define	XPC_C_RCLOSEREPLY	0x00001000	/* remote close channel reply */
-#define	XPC_C_CLOSEREPLY	0x00002000	/* local close channel reply */
-#define	XPC_C_RCLOSEREQUEST	0x00004000    /* remote close channel request */
-#define	XPC_C_CLOSEREQUEST	0x00008000     /* local close channel request */
-
-#define	XPC_C_DISCONNECTED	0x00010000	/* channel is disconnected */
-#define	XPC_C_DISCONNECTING	0x00020000   /* channel is being disconnected */
-#define	XPC_C_DISCONNECTINGCALLOUT \
-				0x00040000 /* disconnecting callout initiated */
-#define	XPC_C_DISCONNECTINGCALLOUT_MADE \
-				0x00080000 /* disconnecting callout completed */
-#define	XPC_C_WDISCONNECT	0x00100000  /* waiting for channel disconnect */
-
-/*
- * The channel control flags (chctl) union consists of a 64-bit variable which
- * is divided up into eight bytes, ordered from right to left. Byte zero
- * pertains to channel 0, byte one to channel 1, and so on. Each channel's byte
- * can have one or more of the chctl flags set in it.
- */
-
-union xpc_channel_ctl_flags {
-	u64 all_flags;
-	u8 flags[XPC_MAX_NCHANNELS];
-};
-
-/* chctl flags */
-#define	XPC_CHCTL_CLOSEREQUEST	0x01
-#define	XPC_CHCTL_CLOSEREPLY	0x02
-#define	XPC_CHCTL_OPENREQUEST	0x04
-#define	XPC_CHCTL_OPENREPLY	0x08
-#define XPC_CHCTL_OPENCOMPLETE	0x10
-#define	XPC_CHCTL_MSGREQUEST	0x20
-
-#define XPC_OPENCLOSE_CHCTL_FLAGS \
-			(XPC_CHCTL_CLOSEREQUEST | XPC_CHCTL_CLOSEREPLY | \
-			 XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY | \
-			 XPC_CHCTL_OPENCOMPLETE)
-#define XPC_MSG_CHCTL_FLAGS	XPC_CHCTL_MSGREQUEST
-
-static inline int
-xpc_any_openclose_chctl_flags_set(union xpc_channel_ctl_flags *chctl)
-{
-	int ch_number;
-
-	for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++) {
-		if (chctl->flags[ch_number] & XPC_OPENCLOSE_CHCTL_FLAGS)
-			return 1;
-	}
-	return 0;
-}
-
-static inline int
-xpc_any_msg_chctl_flags_set(union xpc_channel_ctl_flags *chctl)
-{
-	int ch_number;
-
-	for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++) {
-		if (chctl->flags[ch_number] & XPC_MSG_CHCTL_FLAGS)
-			return 1;
-	}
-	return 0;
-}
-
-struct xpc_partition_uv {
-	unsigned long heartbeat_gpa; /* phys addr of partition's heartbeat */
-	struct xpc_heartbeat_uv cached_heartbeat; /* cached copy of */
-						  /* partition's heartbeat */
-	unsigned long activate_gru_mq_desc_gpa;	/* phys addr of parititon's */
-						/* activate mq's gru mq */
-						/* descriptor */
-	void *cached_activate_gru_mq_desc; /* cached copy of partition's */
-					   /* activate mq's gru mq descriptor */
-	struct mutex cached_activate_gru_mq_desc_mutex;
-	spinlock_t flags_lock;	/* protect updating of flags */
-	unsigned int flags;	/* general flags */
-	u8 remote_act_state;	/* remote partition's act_state */
-	u8 act_state_req;	/* act_state request from remote partition */
-	enum xp_retval reason;	/* reason for deactivate act_state request */
-};
-
-/* struct xpc_partition_uv flags */
-
-#define XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV	0x00000001
-#define XPC_P_ENGAGED_UV			0x00000002
-
-/* struct xpc_partition_uv act_state change requests */
-
-#define XPC_P_ASR_ACTIVATE_UV		0x01
-#define XPC_P_ASR_REACTIVATE_UV		0x02
-#define XPC_P_ASR_DEACTIVATE_UV		0x03
-
-struct xpc_partition {
-
-	/* XPC HB infrastructure */
-
-	u8 remote_rp_version;	/* version# of partition's rsvd pg */
-	unsigned long remote_rp_ts_jiffies; /* timestamp when rsvd pg setup */
-	unsigned long remote_rp_pa;	/* phys addr of partition's rsvd pg */
-	u64 last_heartbeat;	/* HB at last read */
-	u32 activate_IRQ_rcvd;	/* IRQs since activation */
-	spinlock_t act_lock;	/* protect updating of act_state */
-	u8 act_state;		/* from XPC HB viewpoint */
-	enum xp_retval reason;	/* reason partition is deactivating */
-	int reason_line;	/* line# deactivation initiated from */
-
-	unsigned long disengage_timeout;	/* timeout in jiffies */
-	struct timer_list disengage_timer;
-
-	/* XPC infrastructure referencing and teardown control */
-
-	u8 setup_state;		/* infrastructure setup state */
-	wait_queue_head_t teardown_wq;	/* kthread waiting to teardown infra */
-	atomic_t references;	/* #of references to infrastructure */
-
-	u8 nchannels;		/* #of defined channels supported */
-	atomic_t nchannels_active;  /* #of channels that are not DISCONNECTED */
-	atomic_t nchannels_engaged;  /* #of channels engaged with remote part */
-	struct xpc_channel *channels;	/* array of channel structures */
-
-	/* fields used for managing channel avialability and activity */
-
-	union xpc_channel_ctl_flags chctl; /* chctl flags yet to be processed */
-	spinlock_t chctl_lock;	/* chctl flags lock */
-
-	void *remote_openclose_args_base;  /* base address of kmalloc'd space */
-	struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */
-							  /* args */
-
-	/* channel manager related fields */
-
-	atomic_t channel_mgr_requests;	/* #of requests to activate chan mgr */
-	wait_queue_head_t channel_mgr_wq;	/* channel mgr's wait queue */
-
-	union {
-		struct xpc_partition_uv uv;
-	} sn;
-
-} ____cacheline_aligned;
-
-struct xpc_arch_operations {
-	int (*setup_partitions) (void);
-	void (*teardown_partitions) (void);
-	void (*process_activate_IRQ_rcvd) (void);
-	enum xp_retval (*get_partition_rsvd_page_pa)
-		(void *, u64 *, unsigned long *, size_t *);
-	int (*setup_rsvd_page) (struct xpc_rsvd_page *);
-
-	void (*allow_hb) (short);
-	void (*disallow_hb) (short);
-	void (*disallow_all_hbs) (void);
-	void (*increment_heartbeat) (void);
-	void (*offline_heartbeat) (void);
-	void (*online_heartbeat) (void);
-	void (*heartbeat_init) (void);
-	void (*heartbeat_exit) (void);
-	enum xp_retval (*get_remote_heartbeat) (struct xpc_partition *);
-
-	void (*request_partition_activation) (struct xpc_rsvd_page *,
-						 unsigned long, int);
-	void (*request_partition_reactivation) (struct xpc_partition *);
-	void (*request_partition_deactivation) (struct xpc_partition *);
-	void (*cancel_partition_deactivation_request) (struct xpc_partition *);
-	enum xp_retval (*setup_ch_structures) (struct xpc_partition *);
-	void (*teardown_ch_structures) (struct xpc_partition *);
-
-	enum xp_retval (*make_first_contact) (struct xpc_partition *);
-
-	u64 (*get_chctl_all_flags) (struct xpc_partition *);
-	void (*send_chctl_closerequest) (struct xpc_channel *, unsigned long *);
-	void (*send_chctl_closereply) (struct xpc_channel *, unsigned long *);
-	void (*send_chctl_openrequest) (struct xpc_channel *, unsigned long *);
-	void (*send_chctl_openreply) (struct xpc_channel *, unsigned long *);
-	void (*send_chctl_opencomplete) (struct xpc_channel *, unsigned long *);
-	void (*process_msg_chctl_flags) (struct xpc_partition *, int);
-
-	enum xp_retval (*save_remote_msgqueue_pa) (struct xpc_channel *,
-						      unsigned long);
-
-	enum xp_retval (*setup_msg_structures) (struct xpc_channel *);
-	void (*teardown_msg_structures) (struct xpc_channel *);
-
-	void (*indicate_partition_engaged) (struct xpc_partition *);
-	void (*indicate_partition_disengaged) (struct xpc_partition *);
-	void (*assume_partition_disengaged) (short);
-	int (*partition_engaged) (short);
-	int (*any_partition_engaged) (void);
-
-	int (*n_of_deliverable_payloads) (struct xpc_channel *);
-	enum xp_retval (*send_payload) (struct xpc_channel *, u32, void *,
-					   u16, u8, xpc_notify_func, void *);
-	void *(*get_deliverable_payload) (struct xpc_channel *);
-	void (*received_payload) (struct xpc_channel *, void *);
-	void (*notify_senders_of_disconnect) (struct xpc_channel *);
-};
-
-/* struct xpc_partition act_state values (for XPC HB) */
-
-#define	XPC_P_AS_INACTIVE	0x00	/* partition is not active */
-#define XPC_P_AS_ACTIVATION_REQ	0x01	/* created thread to activate */
-#define XPC_P_AS_ACTIVATING	0x02	/* activation thread started */
-#define XPC_P_AS_ACTIVE		0x03	/* xpc_partition_up() was called */
-#define XPC_P_AS_DEACTIVATING	0x04	/* partition deactivation initiated */
-
-#define XPC_DEACTIVATE_PARTITION(_p, _reason) \
-			xpc_deactivate_partition(__LINE__, (_p), (_reason))
-
-/* struct xpc_partition setup_state values */
-
-#define XPC_P_SS_UNSET		0x00	/* infrastructure was never setup */
-#define XPC_P_SS_SETUP		0x01	/* infrastructure is setup */
-#define XPC_P_SS_WTEARDOWN	0x02	/* waiting to teardown infrastructure */
-#define XPC_P_SS_TORNDOWN	0x03	/* infrastructure is torndown */
-
-/* number of seconds to wait for other partitions to disengage */
-#define XPC_DISENGAGE_DEFAULT_TIMELIMIT		90
-
-/* interval in seconds to print 'waiting deactivation' messages */
-#define XPC_DEACTIVATE_PRINTMSG_INTERVAL	10
-
-#define XPC_PARTID(_p)	((short)((_p) - &xpc_partitions[0]))
-
-/* found in xp_main.c */
-extern struct xpc_registration xpc_registrations[];
-
-/* found in xpc_main.c */
-extern struct device *xpc_part;
-extern struct device *xpc_chan;
-extern struct xpc_arch_operations xpc_arch_ops;
-extern int xpc_disengage_timelimit;
-extern int xpc_disengage_timedout;
-extern int xpc_activate_IRQ_rcvd;
-extern spinlock_t xpc_activate_IRQ_rcvd_lock;
-extern wait_queue_head_t xpc_activate_IRQ_wq;
-extern void *xpc_kzalloc_cacheline_aligned(size_t, gfp_t, void **);
-extern void xpc_activate_partition(struct xpc_partition *);
-extern void xpc_activate_kthreads(struct xpc_channel *, int);
-extern void xpc_create_kthreads(struct xpc_channel *, int, int);
-extern void xpc_disconnect_wait(int);
-
-/* found in xpc_uv.c */
-extern int xpc_init_uv(void);
-extern void xpc_exit_uv(void);
-
-/* found in xpc_partition.c */
-extern int xpc_exiting;
-extern int xpc_nasid_mask_nlongs;
-extern struct xpc_rsvd_page *xpc_rsvd_page;
-extern unsigned long *xpc_mach_nasids;
-extern struct xpc_partition *xpc_partitions;
-extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **);
-extern int xpc_setup_rsvd_page(void);
-extern void xpc_teardown_rsvd_page(void);
-extern int xpc_identify_activate_IRQ_sender(void);
-extern int xpc_partition_disengaged(struct xpc_partition *);
-extern int xpc_partition_disengaged_from_timer(struct xpc_partition *part);
-extern enum xp_retval xpc_mark_partition_active(struct xpc_partition *);
-extern void xpc_mark_partition_inactive(struct xpc_partition *);
-extern void xpc_discovery(void);
-extern enum xp_retval xpc_get_remote_rp(int, unsigned long *,
-					struct xpc_rsvd_page *,
-					unsigned long *);
-extern void xpc_deactivate_partition(const int, struct xpc_partition *,
-				     enum xp_retval);
-extern enum xp_retval xpc_initiate_partid_to_nasids(short, void *);
-
-/* found in xpc_channel.c */
-extern void xpc_initiate_connect(int);
-extern void xpc_initiate_disconnect(int);
-extern enum xp_retval xpc_allocate_msg_wait(struct xpc_channel *);
-extern enum xp_retval xpc_initiate_send(short, int, u32, void *, u16);
-extern enum xp_retval xpc_initiate_send_notify(short, int, u32, void *, u16,
-					       xpc_notify_func, void *);
-extern void xpc_initiate_received(short, int, void *);
-extern void xpc_process_sent_chctl_flags(struct xpc_partition *);
-extern void xpc_connected_callout(struct xpc_channel *);
-extern void xpc_deliver_payload(struct xpc_channel *);
-extern void xpc_disconnect_channel(const int, struct xpc_channel *,
-				   enum xp_retval, unsigned long *);
-extern void xpc_disconnect_callout(struct xpc_channel *, enum xp_retval);
-extern void xpc_partition_going_down(struct xpc_partition *, enum xp_retval);
-
-static inline void
-xpc_wakeup_channel_mgr(struct xpc_partition *part)
-{
-	if (atomic_inc_return(&part->channel_mgr_requests) == 1)
-		wake_up(&part->channel_mgr_wq);
-}
-
-/*
- * These next two inlines are used to keep us from tearing down a channel's
- * msg queues while a thread may be referencing them.
- */
-static inline void
-xpc_msgqueue_ref(struct xpc_channel *ch)
-{
-	atomic_inc(&ch->references);
-}
-
-static inline void
-xpc_msgqueue_deref(struct xpc_channel *ch)
-{
-	s32 refs = atomic_dec_return(&ch->references);
-
-	DBUG_ON(refs < 0);
-	if (refs == 0)
-		xpc_wakeup_channel_mgr(&xpc_partitions[ch->partid]);
-}
-
-#define XPC_DISCONNECT_CHANNEL(_ch, _reason, _irqflgs) \
-		xpc_disconnect_channel(__LINE__, _ch, _reason, _irqflgs)
-
-/*
- * These two inlines are used to keep us from tearing down a partition's
- * setup infrastructure while a thread may be referencing it.
- */
-static inline void
-xpc_part_deref(struct xpc_partition *part)
-{
-	s32 refs = atomic_dec_return(&part->references);
-
-	DBUG_ON(refs < 0);
-	if (refs == 0 && part->setup_state == XPC_P_SS_WTEARDOWN)
-		wake_up(&part->teardown_wq);
-}
-
-static inline int
-xpc_part_ref(struct xpc_partition *part)
-{
-	int setup;
-
-	atomic_inc(&part->references);
-	setup = (part->setup_state == XPC_P_SS_SETUP);
-	if (!setup)
-		xpc_part_deref(part);
-
-	return setup;
-}
-
-/*
- * The following macro is to be used for the setting of the reason and
- * reason_line fields in both the struct xpc_channel and struct xpc_partition
- * structures.
- */
-#define XPC_SET_REASON(_p, _reason, _line) \
-	{ \
-		(_p)->reason = _reason; \
-		(_p)->reason_line = _line; \
-	}
-
-#endif /* _DRIVERS_MISC_SGIXP_XPC_H */
diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c
deleted file mode 100644
index 8e6607fc8a67..000000000000
--- a/drivers/misc/sgi-xp/xpc_channel.c
+++ /dev/null
@@ -1,1011 +0,0 @@
-/*
- * 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.
- *
- * Copyright (c) 2004-2009 Silicon Graphics, Inc.  All Rights Reserved.
- */
-
-/*
- * Cross Partition Communication (XPC) channel support.
- *
- *	This is the part of XPC that manages the channels and
- *	sends/receives messages across them to/from other partitions.
- *
- */
-
-#include <linux/device.h>
-#include "xpc.h"
-
-/*
- * Process a connect message from a remote partition.
- *
- * Note: xpc_process_connect() is expecting to be called with the
- * spin_lock_irqsave held and will leave it locked upon return.
- */
-static void
-xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
-{
-	enum xp_retval ret;
-
-	lockdep_assert_held(&ch->lock);
-
-	if (!(ch->flags & XPC_C_OPENREQUEST) ||
-	    !(ch->flags & XPC_C_ROPENREQUEST)) {
-		/* nothing more to do for now */
-		return;
-	}
-	DBUG_ON(!(ch->flags & XPC_C_CONNECTING));
-
-	if (!(ch->flags & XPC_C_SETUP)) {
-		spin_unlock_irqrestore(&ch->lock, *irq_flags);
-		ret = xpc_arch_ops.setup_msg_structures(ch);
-		spin_lock_irqsave(&ch->lock, *irq_flags);
-
-		if (ret != xpSuccess)
-			XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags);
-		else
-			ch->flags |= XPC_C_SETUP;
-
-		if (ch->flags & XPC_C_DISCONNECTING)
-			return;
-	}
-
-	if (!(ch->flags & XPC_C_OPENREPLY)) {
-		ch->flags |= XPC_C_OPENREPLY;
-		xpc_arch_ops.send_chctl_openreply(ch, irq_flags);
-	}
-
-	if (!(ch->flags & XPC_C_ROPENREPLY))
-		return;
-
-	if (!(ch->flags & XPC_C_OPENCOMPLETE)) {
-		ch->flags |= (XPC_C_OPENCOMPLETE | XPC_C_CONNECTED);
-		xpc_arch_ops.send_chctl_opencomplete(ch, irq_flags);
-	}
-
-	if (!(ch->flags & XPC_C_ROPENCOMPLETE))
-		return;
-
-	dev_info(xpc_chan, "channel %d to partition %d connected\n",
-		 ch->number, ch->partid);
-
-	ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP);	/* clear all else */
-}
-
-/*
- * spin_lock_irqsave() is expected to be held on entry.
- */
-static void
-xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
-{
-	struct xpc_partition *part = &xpc_partitions[ch->partid];
-	u32 channel_was_connected = (ch->flags & XPC_C_WASCONNECTED);
-
-	lockdep_assert_held(&ch->lock);
-
-	if (!(ch->flags & XPC_C_DISCONNECTING))
-		return;
-
-	DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
-
-	/* make sure all activity has settled down first */
-
-	if (atomic_read(&ch->kthreads_assigned) > 0 ||
-	    atomic_read(&ch->references) > 0) {
-		return;
-	}
-	DBUG_ON((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
-		!(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE));
-
-	if (part->act_state == XPC_P_AS_DEACTIVATING) {
-		/* can't proceed until the other side disengages from us */
-		if (xpc_arch_ops.partition_engaged(ch->partid))
-			return;
-
-	} else {
-
-		/* as long as the other side is up do the full protocol */
-
-		if (!(ch->flags & XPC_C_RCLOSEREQUEST))
-			return;
-
-		if (!(ch->flags & XPC_C_CLOSEREPLY)) {
-			ch->flags |= XPC_C_CLOSEREPLY;
-			xpc_arch_ops.send_chctl_closereply(ch, irq_flags);
-		}
-
-		if (!(ch->flags & XPC_C_RCLOSEREPLY))
-			return;
-	}
-
-	/* wake those waiting for notify completion */
-	if (atomic_read(&ch->n_to_notify) > 0) {
-		/* we do callout while holding ch->lock, callout can't block */
-		xpc_arch_ops.notify_senders_of_disconnect(ch);
-	}
-
-	/* both sides are disconnected now */
-
-	if (ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE) {
-		spin_unlock_irqrestore(&ch->lock, *irq_flags);
-		xpc_disconnect_callout(ch, xpDisconnected);
-		spin_lock_irqsave(&ch->lock, *irq_flags);
-	}
-
-	DBUG_ON(atomic_read(&ch->n_to_notify) != 0);
-
-	/* it's now safe to free the channel's message queues */
-	xpc_arch_ops.teardown_msg_structures(ch);
-
-	ch->func = NULL;
-	ch->key = NULL;
-	ch->entry_size = 0;
-	ch->local_nentries = 0;
-	ch->remote_nentries = 0;
-	ch->kthreads_assigned_limit = 0;
-	ch->kthreads_idle_limit = 0;
-
-	/*
-	 * Mark the channel disconnected and clear all other flags, including
-	 * XPC_C_SETUP (because of call to
-	 * xpc_arch_ops.teardown_msg_structures()) but not including
-	 * XPC_C_WDISCONNECT (if it was set).
-	 */
-	ch->flags = (XPC_C_DISCONNECTED | (ch->flags & XPC_C_WDISCONNECT));
-
-	atomic_dec(&part->nchannels_active);
-
-	if (channel_was_connected) {
-		dev_info(xpc_chan, "channel %d to partition %d disconnected, "
-			 "reason=%d\n", ch->number, ch->partid, ch->reason);
-	}
-
-	if (ch->flags & XPC_C_WDISCONNECT) {
-		/* we won't lose the CPU since we're holding ch->lock */
-		complete(&ch->wdisconnect_wait);
-	} else if (ch->delayed_chctl_flags) {
-		if (part->act_state != XPC_P_AS_DEACTIVATING) {
-			/* time to take action on any delayed chctl flags */
-			spin_lock(&part->chctl_lock);
-			part->chctl.flags[ch->number] |=
-			    ch->delayed_chctl_flags;
-			spin_unlock(&part->chctl_lock);
-		}
-		ch->delayed_chctl_flags = 0;
-	}
-}
-
-/*
- * Process a change in the channel's remote connection state.
- */
-static void
-xpc_process_openclose_chctl_flags(struct xpc_partition *part, int ch_number,
-				  u8 chctl_flags)
-{
-	unsigned long irq_flags;
-	struct xpc_openclose_args *args =
-	    &part->remote_openclose_args[ch_number];
-	struct xpc_channel *ch = &part->channels[ch_number];
-	enum xp_retval reason;
-	enum xp_retval ret;
-	int create_kthread = 0;
-
-	spin_lock_irqsave(&ch->lock, irq_flags);
-
-again:
-
-	if ((ch->flags & XPC_C_DISCONNECTED) &&
-	    (ch->flags & XPC_C_WDISCONNECT)) {
-		/*
-		 * Delay processing chctl flags until thread waiting disconnect
-		 * has had a chance to see that the channel is disconnected.
-		 */
-		ch->delayed_chctl_flags |= chctl_flags;
-		goto out;
-	}
-
-	if (chctl_flags & XPC_CHCTL_CLOSEREQUEST) {
-
-		dev_dbg(xpc_chan, "XPC_CHCTL_CLOSEREQUEST (reason=%d) received "
-			"from partid=%d, channel=%d\n", args->reason,
-			ch->partid, ch->number);
-
-		/*
-		 * If RCLOSEREQUEST is set, we're probably waiting for
-		 * RCLOSEREPLY. We should find it and a ROPENREQUEST packed
-		 * with this RCLOSEREQUEST in the chctl_flags.
-		 */
-
-		if (ch->flags & XPC_C_RCLOSEREQUEST) {
-			DBUG_ON(!(ch->flags & XPC_C_DISCONNECTING));
-			DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
-			DBUG_ON(!(ch->flags & XPC_C_CLOSEREPLY));
-			DBUG_ON(ch->flags & XPC_C_RCLOSEREPLY);
-
-			DBUG_ON(!(chctl_flags & XPC_CHCTL_CLOSEREPLY));
-			chctl_flags &= ~XPC_CHCTL_CLOSEREPLY;
-			ch->flags |= XPC_C_RCLOSEREPLY;
-
-			/* both sides have finished disconnecting */
-			xpc_process_disconnect(ch, &irq_flags);
-			DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
-			goto again;
-		}
-
-		if (ch->flags & XPC_C_DISCONNECTED) {
-			if (!(chctl_flags & XPC_CHCTL_OPENREQUEST)) {
-				if (part->chctl.flags[ch_number] &
-				    XPC_CHCTL_OPENREQUEST) {
-
-					DBUG_ON(ch->delayed_chctl_flags != 0);
-					spin_lock(&part->chctl_lock);
-					part->chctl.flags[ch_number] |=
-					    XPC_CHCTL_CLOSEREQUEST;
-					spin_unlock(&part->chctl_lock);
-				}
-				goto out;
-			}
-
-			XPC_SET_REASON(ch, 0, 0);
-			ch->flags &= ~XPC_C_DISCONNECTED;
-
-			atomic_inc(&part->nchannels_active);
-			ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST);
-		}
-
-		chctl_flags &= ~(XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY |
-		    XPC_CHCTL_OPENCOMPLETE);
-
-		/*
-		 * The meaningful CLOSEREQUEST connection state fields are:
-		 *      reason = reason connection is to be closed
-		 */
-
-		ch->flags |= XPC_C_RCLOSEREQUEST;
-
-		if (!(ch->flags & XPC_C_DISCONNECTING)) {
-			reason = args->reason;
-			if (reason <= xpSuccess || reason > xpUnknownReason)
-				reason = xpUnknownReason;
-			else if (reason == xpUnregistering)
-				reason = xpOtherUnregistering;
-
-			XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
-
-			DBUG_ON(chctl_flags & XPC_CHCTL_CLOSEREPLY);
-			goto out;
-		}
-
-		xpc_process_disconnect(ch, &irq_flags);
-	}
-
-	if (chctl_flags & XPC_CHCTL_CLOSEREPLY) {
-
-		dev_dbg(xpc_chan, "XPC_CHCTL_CLOSEREPLY received from partid="
-			"%d, channel=%d\n", ch->partid, ch->number);
-
-		if (ch->flags & XPC_C_DISCONNECTED) {
-			DBUG_ON(part->act_state != XPC_P_AS_DEACTIVATING);
-			goto out;
-		}
-
-		DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
-
-		if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
-			if (part->chctl.flags[ch_number] &
-			    XPC_CHCTL_CLOSEREQUEST) {
-
-				DBUG_ON(ch->delayed_chctl_flags != 0);
-				spin_lock(&part->chctl_lock);
-				part->chctl.flags[ch_number] |=
-				    XPC_CHCTL_CLOSEREPLY;
-				spin_unlock(&part->chctl_lock);
-			}
-			goto out;
-		}
-
-		ch->flags |= XPC_C_RCLOSEREPLY;
-
-		if (ch->flags & XPC_C_CLOSEREPLY) {
-			/* both sides have finished disconnecting */
-			xpc_process_disconnect(ch, &irq_flags);
-		}
-	}
-
-	if (chctl_flags & XPC_CHCTL_OPENREQUEST) {
-
-		dev_dbg(xpc_chan, "XPC_CHCTL_OPENREQUEST (entry_size=%d, "
-			"local_nentries=%d) received from partid=%d, "
-			"channel=%d\n", args->entry_size, args->local_nentries,
-			ch->partid, ch->number);
-
-		if (part->act_state == XPC_P_AS_DEACTIVATING ||
-		    (ch->flags & XPC_C_ROPENREQUEST)) {
-			goto out;
-		}
-
-		if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) {
-			ch->delayed_chctl_flags |= XPC_CHCTL_OPENREQUEST;
-			goto out;
-		}
-		DBUG_ON(!(ch->flags & (XPC_C_DISCONNECTED |
-				       XPC_C_OPENREQUEST)));
-		DBUG_ON(ch->flags & (XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
-				     XPC_C_OPENREPLY | XPC_C_CONNECTED));
-
-		/*
-		 * The meaningful OPENREQUEST connection state fields are:
-		 *      entry_size = size of channel's messages in bytes
-		 *      local_nentries = remote partition's local_nentries
-		 */
-		if (args->entry_size == 0 || args->local_nentries == 0) {
-			/* assume OPENREQUEST was delayed by mistake */
-			goto out;
-		}
-
-		ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING);
-		ch->remote_nentries = args->local_nentries;
-
-		if (ch->flags & XPC_C_OPENREQUEST) {
-			if (args->entry_size != ch->entry_size) {
-				XPC_DISCONNECT_CHANNEL(ch, xpUnequalMsgSizes,
-						       &irq_flags);
-				goto out;
-			}
-		} else {
-			ch->entry_size = args->entry_size;
-
-			XPC_SET_REASON(ch, 0, 0);
-			ch->flags &= ~XPC_C_DISCONNECTED;
-
-			atomic_inc(&part->nchannels_active);
-		}
-
-		xpc_process_connect(ch, &irq_flags);
-	}
-
-	if (chctl_flags & XPC_CHCTL_OPENREPLY) {
-
-		dev_dbg(xpc_chan, "XPC_CHCTL_OPENREPLY (local_msgqueue_pa="
-			"0x%lx, local_nentries=%d, remote_nentries=%d) "
-			"received from partid=%d, channel=%d\n",
-			args->local_msgqueue_pa, args->local_nentries,
-			args->remote_nentries, ch->partid, ch->number);
-
-		if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED))
-			goto out;
-
-		if (!(ch->flags & XPC_C_OPENREQUEST)) {
-			XPC_DISCONNECT_CHANNEL(ch, xpOpenCloseError,
-					       &irq_flags);
-			goto out;
-		}
-
-		DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
-		DBUG_ON(ch->flags & XPC_C_CONNECTED);
-
-		/*
-		 * The meaningful OPENREPLY connection state fields are:
-		 *      local_msgqueue_pa = physical address of remote
-		 *                          partition's local_msgqueue
-		 *      local_nentries = remote partition's local_nentries
-		 *      remote_nentries = remote partition's remote_nentries
-		 */
-		DBUG_ON(args->local_msgqueue_pa == 0);
-		DBUG_ON(args->local_nentries == 0);
-		DBUG_ON(args->remote_nentries == 0);
-
-		ret = xpc_arch_ops.save_remote_msgqueue_pa(ch,
-						      args->local_msgqueue_pa);
-		if (ret != xpSuccess) {
-			XPC_DISCONNECT_CHANNEL(ch, ret, &irq_flags);
-			goto out;
-		}
-		ch->flags |= XPC_C_ROPENREPLY;
-
-		if (args->local_nentries < ch->remote_nentries) {
-			dev_dbg(xpc_chan, "XPC_CHCTL_OPENREPLY: new "
-				"remote_nentries=%d, old remote_nentries=%d, "
-				"partid=%d, channel=%d\n",
-				args->local_nentries, ch->remote_nentries,
-				ch->partid, ch->number);
-
-			ch->remote_nentries = args->local_nentries;
-		}
-		if (args->remote_nentries < ch->local_nentries) {
-			dev_dbg(xpc_chan, "XPC_CHCTL_OPENREPLY: new "
-				"local_nentries=%d, old local_nentries=%d, "
-				"partid=%d, channel=%d\n",
-				args->remote_nentries, ch->local_nentries,
-				ch->partid, ch->number);
-
-			ch->local_nentries = args->remote_nentries;
-		}
-
-		xpc_process_connect(ch, &irq_flags);
-	}
-
-	if (chctl_flags & XPC_CHCTL_OPENCOMPLETE) {
-
-		dev_dbg(xpc_chan, "XPC_CHCTL_OPENCOMPLETE received from "
-			"partid=%d, channel=%d\n", ch->partid, ch->number);
-
-		if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED))
-			goto out;
-
-		if (!(ch->flags & XPC_C_OPENREQUEST) ||
-		    !(ch->flags & XPC_C_OPENREPLY)) {
-			XPC_DISCONNECT_CHANNEL(ch, xpOpenCloseError,
-					       &irq_flags);
-			goto out;
-		}
-
-		DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
-		DBUG_ON(!(ch->flags & XPC_C_ROPENREPLY));
-		DBUG_ON(!(ch->flags & XPC_C_CONNECTED));
-
-		ch->flags |= XPC_C_ROPENCOMPLETE;
-
-		xpc_process_connect(ch, &irq_flags);
-		create_kthread = 1;
-	}
-
-out:
-	spin_unlock_irqrestore(&ch->lock, irq_flags);
-
-	if (create_kthread)
-		xpc_create_kthreads(ch, 1, 0);
-}
-
-/*
- * Attempt to establish a channel connection to a remote partition.
- */
-static enum xp_retval
-xpc_connect_channel(struct xpc_channel *ch)
-{
-	unsigned long irq_flags;
-	struct xpc_registration *registration = &xpc_registrations[ch->number];
-
-	if (mutex_trylock(&registration->mutex) == 0)
-		return xpRetry;
-
-	if (!XPC_CHANNEL_REGISTERED(ch->number)) {
-		mutex_unlock(&registration->mutex);
-		return xpUnregistered;
-	}
-
-	spin_lock_irqsave(&ch->lock, irq_flags);
-
-	DBUG_ON(ch->flags & XPC_C_CONNECTED);
-	DBUG_ON(ch->flags & XPC_C_OPENREQUEST);
-
-	if (ch->flags & XPC_C_DISCONNECTING) {
-		spin_unlock_irqrestore(&ch->lock, irq_flags);
-		mutex_unlock(&registration->mutex);
-		return ch->reason;
-	}
-
-	/* add info from the channel connect registration to the channel */
-
-	ch->kthreads_assigned_limit = registration->assigned_limit;
-	ch->kthreads_idle_limit = registration->idle_limit;
-	DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
-	DBUG_ON(atomic_read(&ch->kthreads_idle) != 0);
-	DBUG_ON(atomic_read(&ch->kthreads_active) != 0);
-
-	ch->func = registration->func;
-	DBUG_ON(registration->func == NULL);
-	ch->key = registration->key;
-
-	ch->local_nentries = registration->nentries;
-
-	if (ch->flags & XPC_C_ROPENREQUEST) {
-		if (registration->entry_size != ch->entry_size) {
-			/* the local and remote sides aren't the same */
-
-			/*
-			 * Because XPC_DISCONNECT_CHANNEL() can block we're
-			 * forced to up the registration sema before we unlock
-			 * the channel lock. But that's okay here because we're
-			 * done with the part that required the registration
-			 * sema. XPC_DISCONNECT_CHANNEL() requires that the
-			 * channel lock be locked and will unlock and relock
-			 * the channel lock as needed.
-			 */
-			mutex_unlock(&registration->mutex);
-			XPC_DISCONNECT_CHANNEL(ch, xpUnequalMsgSizes,
-					       &irq_flags);
-			spin_unlock_irqrestore(&ch->lock, irq_flags);
-			return xpUnequalMsgSizes;
-		}
-	} else {
-		ch->entry_size = registration->entry_size;
-
-		XPC_SET_REASON(ch, 0, 0);
-		ch->flags &= ~XPC_C_DISCONNECTED;
-
-		atomic_inc(&xpc_partitions[ch->partid].nchannels_active);
-	}
-
-	mutex_unlock(&registration->mutex);
-
-	/* initiate the connection */
-
-	ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING);
-	xpc_arch_ops.send_chctl_openrequest(ch, &irq_flags);
-
-	xpc_process_connect(ch, &irq_flags);
-
-	spin_unlock_irqrestore(&ch->lock, irq_flags);
-
-	return xpSuccess;
-}
-
-void
-xpc_process_sent_chctl_flags(struct xpc_partition *part)
-{
-	unsigned long irq_flags;
-	union xpc_channel_ctl_flags chctl;
-	struct xpc_channel *ch;
-	int ch_number;
-	u32 ch_flags;
-
-	chctl.all_flags = xpc_arch_ops.get_chctl_all_flags(part);
-
-	/*
-	 * Initiate channel connections for registered channels.
-	 *
-	 * For each connected channel that has pending messages activate idle
-	 * kthreads and/or create new kthreads as needed.
-	 */
-
-	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
-		ch = &part->channels[ch_number];
-
-		/*
-		 * Process any open or close related chctl flags, and then deal
-		 * with connecting or disconnecting the channel as required.
-		 */
-
-		if (chctl.flags[ch_number] & XPC_OPENCLOSE_CHCTL_FLAGS) {
-			xpc_process_openclose_chctl_flags(part, ch_number,
-							chctl.flags[ch_number]);
-		}
-
-		ch_flags = ch->flags;	/* need an atomic snapshot of flags */
-
-		if (ch_flags & XPC_C_DISCONNECTING) {
-			spin_lock_irqsave(&ch->lock, irq_flags);
-			xpc_process_disconnect(ch, &irq_flags);
-			spin_unlock_irqrestore(&ch->lock, irq_flags);
-			continue;
-		}
-
-		if (part->act_state == XPC_P_AS_DEACTIVATING)
-			continue;
-
-		if (!(ch_flags & XPC_C_CONNECTED)) {
-			if (!(ch_flags & XPC_C_OPENREQUEST)) {
-				DBUG_ON(ch_flags & XPC_C_SETUP);
-				(void)xpc_connect_channel(ch);
-			}
-			continue;
-		}
-
-		/*
-		 * Process any message related chctl flags, this may involve
-		 * the activation of kthreads to deliver any pending messages
-		 * sent from the other partition.
-		 */
-
-		if (chctl.flags[ch_number] & XPC_MSG_CHCTL_FLAGS)
-			xpc_arch_ops.process_msg_chctl_flags(part, ch_number);
-	}
-}
-
-/*
- * XPC's heartbeat code calls this function to inform XPC that a partition is
- * going down.  XPC responds by tearing down the XPartition Communication
- * infrastructure used for the just downed partition.
- *
- * XPC's heartbeat code will never call this function and xpc_partition_up()
- * at the same time. Nor will it ever make multiple calls to either function
- * at the same time.
- */
-void
-xpc_partition_going_down(struct xpc_partition *part, enum xp_retval reason)
-{
-	unsigned long irq_flags;
-	int ch_number;
-	struct xpc_channel *ch;
-
-	dev_dbg(xpc_chan, "deactivating partition %d, reason=%d\n",
-		XPC_PARTID(part), reason);
-
-	if (!xpc_part_ref(part)) {
-		/* infrastructure for this partition isn't currently set up */
-		return;
-	}
-
-	/* disconnect channels associated with the partition going down */
-
-	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
-		ch = &part->channels[ch_number];
-
-		xpc_msgqueue_ref(ch);
-		spin_lock_irqsave(&ch->lock, irq_flags);
-
-		XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
-
-		spin_unlock_irqrestore(&ch->lock, irq_flags);
-		xpc_msgqueue_deref(ch);
-	}
-
-	xpc_wakeup_channel_mgr(part);
-
-	xpc_part_deref(part);
-}
-
-/*
- * Called by XP at the time of channel connection registration to cause
- * XPC to establish connections to all currently active partitions.
- */
-void
-xpc_initiate_connect(int ch_number)
-{
-	short partid;
-	struct xpc_partition *part;
-
-	DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS);
-
-	for (partid = 0; partid < xp_max_npartitions; partid++) {
-		part = &xpc_partitions[partid];
-
-		if (xpc_part_ref(part)) {
-			/*
-			 * Initiate the establishment of a connection on the
-			 * newly registered channel to the remote partition.
-			 */
-			xpc_wakeup_channel_mgr(part);
-			xpc_part_deref(part);
-		}
-	}
-}
-
-void
-xpc_connected_callout(struct xpc_channel *ch)
-{
-	/* let the registerer know that a connection has been established */
-
-	if (ch->func != NULL) {
-		dev_dbg(xpc_chan, "ch->func() called, reason=xpConnected, "
-			"partid=%d, channel=%d\n", ch->partid, ch->number);
-
-		ch->func(xpConnected, ch->partid, ch->number,
-			 (void *)(u64)ch->local_nentries, ch->key);
-
-		dev_dbg(xpc_chan, "ch->func() returned, reason=xpConnected, "
-			"partid=%d, channel=%d\n", ch->partid, ch->number);
-	}
-}
-
-/*
- * Called by XP at the time of channel connection unregistration to cause
- * XPC to teardown all current connections for the specified channel.
- *
- * Before returning xpc_initiate_disconnect() will wait until 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 the
- * function they registered via xpc_connect().
- *
- * Arguments:
- *
- *	ch_number - channel # to unregister.
- */
-void
-xpc_initiate_disconnect(int ch_number)
-{
-	unsigned long irq_flags;
-	short partid;
-	struct xpc_partition *part;
-	struct xpc_channel *ch;
-
-	DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS);
-
-	/* initiate the channel disconnect for every active partition */
-	for (partid = 0; partid < xp_max_npartitions; partid++) {
-		part = &xpc_partitions[partid];
-
-		if (xpc_part_ref(part)) {
-			ch = &part->channels[ch_number];
-			xpc_msgqueue_ref(ch);
-
-			spin_lock_irqsave(&ch->lock, irq_flags);
-
-			if (!(ch->flags & XPC_C_DISCONNECTED)) {
-				ch->flags |= XPC_C_WDISCONNECT;
-
-				XPC_DISCONNECT_CHANNEL(ch, xpUnregistering,
-						       &irq_flags);
-			}
-
-			spin_unlock_irqrestore(&ch->lock, irq_flags);
-
-			xpc_msgqueue_deref(ch);
-			xpc_part_deref(part);
-		}
-	}
-
-	xpc_disconnect_wait(ch_number);
-}
-
-/*
- * To disconnect a channel, and reflect it back to all who may be waiting.
- *
- * An OPEN is not allowed until XPC_C_DISCONNECTING is cleared by
- * xpc_process_disconnect(), and if set, XPC_C_WDISCONNECT is cleared by
- * xpc_disconnect_wait().
- *
- * THE CHANNEL IS TO BE LOCKED BY THE CALLER AND WILL REMAIN LOCKED UPON RETURN.
- */
-void
-xpc_disconnect_channel(const int line, struct xpc_channel *ch,
-		       enum xp_retval reason, unsigned long *irq_flags)
-{
-	u32 channel_was_connected = (ch->flags & XPC_C_CONNECTED);
-
-	lockdep_assert_held(&ch->lock);
-
-	if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED))
-		return;
-
-	DBUG_ON(!(ch->flags & (XPC_C_CONNECTING | XPC_C_CONNECTED)));
-
-	dev_dbg(xpc_chan, "reason=%d, line=%d, partid=%d, channel=%d\n",
-		reason, line, ch->partid, ch->number);
-
-	XPC_SET_REASON(ch, reason, line);
-
-	ch->flags |= (XPC_C_CLOSEREQUEST | XPC_C_DISCONNECTING);
-	/* some of these may not have been set */
-	ch->flags &= ~(XPC_C_OPENREQUEST | XPC_C_OPENREPLY |
-		       XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
-		       XPC_C_CONNECTING | XPC_C_CONNECTED);
-
-	xpc_arch_ops.send_chctl_closerequest(ch, irq_flags);
-
-	if (channel_was_connected)
-		ch->flags |= XPC_C_WASCONNECTED;
-
-	spin_unlock_irqrestore(&ch->lock, *irq_flags);
-
-	/* wake all idle kthreads so they can exit */
-	if (atomic_read(&ch->kthreads_idle) > 0) {
-		wake_up_all(&ch->idle_wq);
-
-	} else if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
-		   !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
-		/* start a kthread that will do the xpDisconnecting callout */
-		xpc_create_kthreads(ch, 1, 1);
-	}
-
-	/* wake those waiting to allocate an entry from the local msg queue */
-	if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
-		wake_up(&ch->msg_allocate_wq);
-
-	spin_lock_irqsave(&ch->lock, *irq_flags);
-}
-
-void
-xpc_disconnect_callout(struct xpc_channel *ch, enum xp_retval reason)
-{
-	/*
-	 * Let the channel's registerer know that the channel is being
-	 * disconnected. We don't want to do this if the registerer was never
-	 * informed of a connection being made.
-	 */
-
-	if (ch->func != NULL) {
-		dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, "
-			"channel=%d\n", reason, ch->partid, ch->number);
-
-		ch->func(reason, ch->partid, ch->number, NULL, ch->key);
-
-		dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, "
-			"channel=%d\n", reason, ch->partid, ch->number);
-	}
-}
-
-/*
- * Wait for a message entry to become available for the specified channel,
- * but don't wait any longer than 1 jiffy.
- */
-enum xp_retval
-xpc_allocate_msg_wait(struct xpc_channel *ch)
-{
-	enum xp_retval ret;
-	DEFINE_WAIT(wait);
-
-	if (ch->flags & XPC_C_DISCONNECTING) {
-		DBUG_ON(ch->reason == xpInterrupted);
-		return ch->reason;
-	}
-
-	atomic_inc(&ch->n_on_msg_allocate_wq);
-	prepare_to_wait(&ch->msg_allocate_wq, &wait, TASK_INTERRUPTIBLE);
-	ret = schedule_timeout(1);
-	finish_wait(&ch->msg_allocate_wq, &wait);
-	atomic_dec(&ch->n_on_msg_allocate_wq);
-
-	if (ch->flags & XPC_C_DISCONNECTING) {
-		ret = ch->reason;
-		DBUG_ON(ch->reason == xpInterrupted);
-	} else if (ret == 0) {
-		ret = xpTimeout;
-	} else {
-		ret = xpInterrupted;
-	}
-
-	return ret;
-}
-
-/*
- * Send a message that contains the user's payload on the specified channel
- * connected to the specified partition.
- *
- * NOTE that this routine can sleep waiting for a message entry to become
- * available. To not sleep, pass in the XPC_NOWAIT flag.
- *
- * Once sent, this routine will not wait for the message to be received, nor
- * will notification be given when it does happen.
- *
- * Arguments:
- *
- *	partid - ID of partition to which the channel is connected.
- *	ch_number - channel # to send message on.
- *	flags - see xp.h for valid flags.
- *	payload - pointer to the payload which is to be sent.
- *	payload_size - size of the payload in bytes.
- */
-enum xp_retval
-xpc_initiate_send(short partid, int ch_number, u32 flags, void *payload,
-		  u16 payload_size)
-{
-	struct xpc_partition *part = &xpc_partitions[partid];
-	enum xp_retval ret = xpUnknownReason;
-
-	dev_dbg(xpc_chan, "payload=0x%p, partid=%d, channel=%d\n", payload,
-		partid, ch_number);
-
-	DBUG_ON(partid < 0 || partid >= xp_max_npartitions);
-	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
-	DBUG_ON(payload == NULL);
-
-	if (xpc_part_ref(part)) {
-		ret = xpc_arch_ops.send_payload(&part->channels[ch_number],
-				  flags, payload, payload_size, 0, NULL, NULL);
-		xpc_part_deref(part);
-	}
-
-	return ret;
-}
-
-/*
- * Send a message that contains the user's payload on the specified channel
- * connected to the specified partition.
- *
- * NOTE that this routine can sleep waiting for a message entry to become
- * available. To not sleep, pass in the XPC_NOWAIT flag.
- *
- * This routine will not wait for the message to be sent or received.
- *
- * Once the remote end of the channel has received the message, the function
- * passed as an argument to xpc_initiate_send_notify() will be called. This
- * allows the sender to free up or re-use any buffers referenced by the
- * message, but does NOT mean the message has been processed at the remote
- * end by a receiver.
- *
- * If this routine returns an error, the caller's function will NOT be called.
- *
- * Arguments:
- *
- *	partid - ID of partition to which the channel is connected.
- *	ch_number - channel # to send message on.
- *	flags - see xp.h for valid flags.
- *	payload - pointer to the payload which is to be sent.
- *	payload_size - size of the payload in bytes.
- *	func - function to call with asynchronous notification of message
- *		  receipt. THIS FUNCTION MUST BE NON-BLOCKING.
- *	key - user-defined key to be passed to the function when it's called.
- */
-enum xp_retval
-xpc_initiate_send_notify(short partid, int ch_number, u32 flags, void *payload,
-			 u16 payload_size, xpc_notify_func func, void *key)
-{
-	struct xpc_partition *part = &xpc_partitions[partid];
-	enum xp_retval ret = xpUnknownReason;
-
-	dev_dbg(xpc_chan, "payload=0x%p, partid=%d, channel=%d\n", payload,
-		partid, ch_number);
-
-	DBUG_ON(partid < 0 || partid >= xp_max_npartitions);
-	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
-	DBUG_ON(payload == NULL);
-	DBUG_ON(func == NULL);
-
-	if (xpc_part_ref(part)) {
-		ret = xpc_arch_ops.send_payload(&part->channels[ch_number],
-			  flags, payload, payload_size, XPC_N_CALL, func, key);
-		xpc_part_deref(part);
-	}
-	return ret;
-}
-
-/*
- * Deliver a message's payload to its intended recipient.
- */
-void
-xpc_deliver_payload(struct xpc_channel *ch)
-{
-	void *payload;
-
-	payload = xpc_arch_ops.get_deliverable_payload(ch);
-	if (payload != NULL) {
-
-		/*
-		 * This ref is taken to protect the payload itself from being
-		 * freed before the user is finished with it, which the user
-		 * indicates by calling xpc_initiate_received().
-		 */
-		xpc_msgqueue_ref(ch);
-
-		atomic_inc(&ch->kthreads_active);
-
-		if (ch->func != NULL) {
-			dev_dbg(xpc_chan, "ch->func() called, payload=0x%p "
-				"partid=%d channel=%d\n", payload, ch->partid,
-				ch->number);
-
-			/* deliver the message to its intended recipient */
-			ch->func(xpMsgReceived, ch->partid, ch->number, payload,
-				 ch->key);
-
-			dev_dbg(xpc_chan, "ch->func() returned, payload=0x%p "
-				"partid=%d channel=%d\n", payload, ch->partid,
-				ch->number);
-		}
-
-		atomic_dec(&ch->kthreads_active);
-	}
-}
-
-/*
- * Acknowledge receipt of a delivered message's payload.
- *
- * This function, although called by users, does not call xpc_part_ref() to
- * ensure that the partition infrastructure is in place. It relies on the
- * fact that we called xpc_msgqueue_ref() in xpc_deliver_payload().
- *
- * Arguments:
- *
- *	partid - ID of partition to which the channel is connected.
- *	ch_number - channel # message received on.
- *	payload - pointer to the payload area allocated via
- *			xpc_initiate_send() or xpc_initiate_send_notify().
- */
-void
-xpc_initiate_received(short partid, int ch_number, void *payload)
-{
-	struct xpc_partition *part = &xpc_partitions[partid];
-	struct xpc_channel *ch;
-
-	DBUG_ON(partid < 0 || partid >= xp_max_npartitions);
-	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
-
-	ch = &part->channels[ch_number];
-	xpc_arch_ops.received_payload(ch, payload);
-
-	/* the call to xpc_msgqueue_ref() was done by xpc_deliver_payload()  */
-	xpc_msgqueue_deref(ch);
-}
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
deleted file mode 100644
index 15b6a8e35681..000000000000
--- a/drivers/misc/sgi-xp/xpc_main.c
+++ /dev/null
@@ -1,1309 +0,0 @@
-/*
- * 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.
- *
- * (C) Copyright 2020 Hewlett Packard Enterprise Development LP
- * Copyright (c) 2004-2009 Silicon Graphics, Inc.  All Rights Reserved.
- */
-
-/*
- * Cross Partition Communication (XPC) support - standard version.
- *
- *	XPC provides a message passing capability that crosses partition
- *	boundaries. This module is made up of two parts:
- *
- *	    partition	This part detects the presence/absence of other
- *			partitions. It provides a heartbeat and monitors
- *			the heartbeats of other partitions.
- *
- *	    channel	This part manages the channels and sends/receives
- *			messages across them to/from other partitions.
- *
- *	There are a couple of additional functions residing in XP, which
- *	provide an interface to XPC for its users.
- *
- *
- *	Caveats:
- *
- *	  . Currently on sn2, we have no way to determine which nasid an IRQ
- *	    came from. Thus, xpc_send_IRQ_sn2() does a remote amo write
- *	    followed by an IPI. The amo indicates where data is to be pulled
- *	    from, so after the IPI arrives, the remote partition checks the amo
- *	    word. The IPI can actually arrive before the amo however, so other
- *	    code must periodically check for this case. Also, remote amo
- *	    operations do not reliably time out. Thus we do a remote PIO read
- *	    solely to know whether the remote partition is down and whether we
- *	    should stop sending IPIs to it. This remote PIO read operation is
- *	    set up in a special nofault region so SAL knows to ignore (and
- *	    cleanup) any errors due to the remote amo write, PIO read, and/or
- *	    PIO write operations.
- *
- *	    If/when new hardware solves this IPI problem, we should abandon
- *	    the current approach.
- *
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/sysctl.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/reboot.h>
-#include <linux/kdebug.h>
-#include <linux/kthread.h>
-#include "xpc.h"
-
-#ifdef CONFIG_X86_64
-#include <asm/traps.h>
-#endif
-
-/* define two XPC debug device structures to be used with dev_dbg() et al */
-
-static struct device_driver xpc_dbg_name = {
-	.name = "xpc"
-};
-
-static struct device xpc_part_dbg_subname = {
-	.init_name = "",	/* set to "part" at xpc_init() time */
-	.driver = &xpc_dbg_name
-};
-
-static struct device xpc_chan_dbg_subname = {
-	.init_name = "",	/* set to "chan" at xpc_init() time */
-	.driver = &xpc_dbg_name
-};
-
-struct device *xpc_part = &xpc_part_dbg_subname;
-struct device *xpc_chan = &xpc_chan_dbg_subname;
-
-static int xpc_kdebug_ignore;
-
-/* systune related variables for /proc/sys directories */
-
-static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
-static int xpc_hb_min_interval = 1;
-static int xpc_hb_max_interval = 10;
-
-static int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_INTERVAL;
-static int xpc_hb_check_min_interval = 10;
-static int xpc_hb_check_max_interval = 120;
-
-int xpc_disengage_timelimit = XPC_DISENGAGE_DEFAULT_TIMELIMIT;
-static int xpc_disengage_min_timelimit;	/* = 0 */
-static int xpc_disengage_max_timelimit = 120;
-
-static const struct ctl_table xpc_sys_xpc_hb[] = {
-	{
-	 .procname = "hb_interval",
-	 .data = &xpc_hb_interval,
-	 .maxlen = sizeof(int),
-	 .mode = 0644,
-	 .proc_handler = proc_dointvec_minmax,
-	 .extra1 = &xpc_hb_min_interval,
-	 .extra2 = &xpc_hb_max_interval},
-	{
-	 .procname = "hb_check_interval",
-	 .data = &xpc_hb_check_interval,
-	 .maxlen = sizeof(int),
-	 .mode = 0644,
-	 .proc_handler = proc_dointvec_minmax,
-	 .extra1 = &xpc_hb_check_min_interval,
-	 .extra2 = &xpc_hb_check_max_interval},
-};
-static const struct ctl_table xpc_sys_xpc[] = {
-	{
-	 .procname = "disengage_timelimit",
-	 .data = &xpc_disengage_timelimit,
-	 .maxlen = sizeof(int),
-	 .mode = 0644,
-	 .proc_handler = proc_dointvec_minmax,
-	 .extra1 = &xpc_disengage_min_timelimit,
-	 .extra2 = &xpc_disengage_max_timelimit},
-};
-
-static struct ctl_table_header *xpc_sysctl;
-static struct ctl_table_header *xpc_sysctl_hb;
-
-/* non-zero if any remote partition disengage was timed out */
-int xpc_disengage_timedout;
-
-/* #of activate IRQs received and not yet processed */
-int xpc_activate_IRQ_rcvd;
-DEFINE_SPINLOCK(xpc_activate_IRQ_rcvd_lock);
-
-/* IRQ handler notifies this wait queue on receipt of an IRQ */
-DECLARE_WAIT_QUEUE_HEAD(xpc_activate_IRQ_wq);
-
-static unsigned long xpc_hb_check_timeout;
-static struct timer_list xpc_hb_timer;
-
-/* notification that the xpc_hb_checker thread has exited */
-static DECLARE_COMPLETION(xpc_hb_checker_exited);
-
-/* notification that the xpc_discovery thread has exited */
-static DECLARE_COMPLETION(xpc_discovery_exited);
-
-static void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *);
-
-static int xpc_system_reboot(struct notifier_block *, unsigned long, void *);
-static struct notifier_block xpc_reboot_notifier = {
-	.notifier_call = xpc_system_reboot,
-};
-
-static int xpc_system_die(struct notifier_block *, unsigned long, void *);
-static struct notifier_block xpc_die_notifier = {
-	.notifier_call = xpc_system_die,
-};
-
-struct xpc_arch_operations xpc_arch_ops;
-
-/*
- * Timer function to enforce the timelimit on the partition disengage.
- */
-static void
-xpc_timeout_partition_disengage(struct timer_list *t)
-{
-	struct xpc_partition *part = timer_container_of(part, t,
-							disengage_timer);
-
-	DBUG_ON(time_is_after_jiffies(part->disengage_timeout));
-
-	xpc_partition_disengaged_from_timer(part);
-
-	DBUG_ON(part->disengage_timeout != 0);
-	DBUG_ON(xpc_arch_ops.partition_engaged(XPC_PARTID(part)));
-}
-
-/*
- * Timer to produce the heartbeat.  The timer structures function is
- * already set when this is initially called.  A tunable is used to
- * specify when the next timeout should occur.
- */
-static void
-xpc_hb_beater(struct timer_list *unused)
-{
-	xpc_arch_ops.increment_heartbeat();
-
-	if (time_is_before_eq_jiffies(xpc_hb_check_timeout))
-		wake_up_interruptible(&xpc_activate_IRQ_wq);
-
-	xpc_hb_timer.expires = jiffies + (xpc_hb_interval * HZ);
-	add_timer(&xpc_hb_timer);
-}
-
-static void
-xpc_start_hb_beater(void)
-{
-	xpc_arch_ops.heartbeat_init();
-	timer_setup(&xpc_hb_timer, xpc_hb_beater, 0);
-	xpc_hb_beater(NULL);
-}
-
-static void
-xpc_stop_hb_beater(void)
-{
-	timer_delete_sync(&xpc_hb_timer);
-	xpc_arch_ops.heartbeat_exit();
-}
-
-/*
- * At periodic intervals, scan through all active partitions and ensure
- * their heartbeat is still active.  If not, the partition is deactivated.
- */
-static void
-xpc_check_remote_hb(void)
-{
-	struct xpc_partition *part;
-	short partid;
-	enum xp_retval ret;
-
-	for (partid = 0; partid < xp_max_npartitions; partid++) {
-
-		if (xpc_exiting)
-			break;
-
-		if (partid == xp_partition_id)
-			continue;
-
-		part = &xpc_partitions[partid];
-
-		if (part->act_state == XPC_P_AS_INACTIVE ||
-		    part->act_state == XPC_P_AS_DEACTIVATING) {
-			continue;
-		}
-
-		ret = xpc_arch_ops.get_remote_heartbeat(part);
-		if (ret != xpSuccess)
-			XPC_DEACTIVATE_PARTITION(part, ret);
-	}
-}
-
-/*
- * This thread is responsible for nearly all of the partition
- * activation/deactivation.
- */
-static int
-xpc_hb_checker(void *ignore)
-{
-	int force_IRQ = 0;
-
-	/* this thread was marked active by xpc_hb_init() */
-
-	set_cpus_allowed_ptr(current, cpumask_of(XPC_HB_CHECK_CPU));
-
-	/* set our heartbeating to other partitions into motion */
-	xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ);
-	xpc_start_hb_beater();
-
-	while (!xpc_exiting) {
-
-		dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have "
-			"been received\n",
-			(int)(xpc_hb_check_timeout - jiffies),
-			xpc_activate_IRQ_rcvd);
-
-		/* checking of remote heartbeats is skewed by IRQ handling */
-		if (time_is_before_eq_jiffies(xpc_hb_check_timeout)) {
-			xpc_hb_check_timeout = jiffies +
-			    (xpc_hb_check_interval * HZ);
-
-			dev_dbg(xpc_part, "checking remote heartbeats\n");
-			xpc_check_remote_hb();
-		}
-
-		/* check for outstanding IRQs */
-		if (xpc_activate_IRQ_rcvd > 0 || force_IRQ != 0) {
-			force_IRQ = 0;
-			dev_dbg(xpc_part, "processing activate IRQs "
-				"received\n");
-			xpc_arch_ops.process_activate_IRQ_rcvd();
-		}
-
-		/* wait for IRQ or timeout */
-		(void)wait_event_interruptible(xpc_activate_IRQ_wq,
-					       (time_is_before_eq_jiffies(
-						xpc_hb_check_timeout) ||
-						xpc_activate_IRQ_rcvd > 0 ||
-						xpc_exiting));
-	}
-
-	xpc_stop_hb_beater();
-
-	dev_dbg(xpc_part, "heartbeat checker is exiting\n");
-
-	/* mark this thread as having exited */
-	complete(&xpc_hb_checker_exited);
-	return 0;
-}
-
-/*
- * This thread will attempt to discover other partitions to activate
- * based on info provided by SAL. This new thread is short lived and
- * will exit once discovery is complete.
- */
-static int
-xpc_initiate_discovery(void *ignore)
-{
-	xpc_discovery();
-
-	dev_dbg(xpc_part, "discovery thread is exiting\n");
-
-	/* mark this thread as having exited */
-	complete(&xpc_discovery_exited);
-	return 0;
-}
-
-/*
- * The first kthread assigned to a newly activated partition is the one
- * created by XPC HB with which it calls xpc_activating(). XPC hangs on to
- * that kthread until the partition is brought down, at which time that kthread
- * returns back to XPC HB. (The return of that kthread will signify to XPC HB
- * that XPC has dismantled all communication infrastructure for the associated
- * partition.) This kthread becomes the channel manager for that partition.
- *
- * Each active partition has a channel manager, who, besides connecting and
- * disconnecting channels, will ensure that each of the partition's connected
- * channels has the required number of assigned kthreads to get the work done.
- */
-static void
-xpc_channel_mgr(struct xpc_partition *part)
-{
-	while (part->act_state != XPC_P_AS_DEACTIVATING ||
-	       atomic_read(&part->nchannels_active) > 0 ||
-	       !xpc_partition_disengaged(part)) {
-
-		xpc_process_sent_chctl_flags(part);
-
-		/*
-		 * Wait until we've been requested to activate kthreads or
-		 * all of the channel's message queues have been torn down or
-		 * a signal is pending.
-		 *
-		 * The channel_mgr_requests is set to 1 after being awakened,
-		 * This is done to prevent the channel mgr from making one pass
-		 * through the loop for each request, since he will
-		 * be servicing all the requests in one pass. The reason it's
-		 * set to 1 instead of 0 is so that other kthreads will know
-		 * that the channel mgr is running and won't bother trying to
-		 * wake him up.
-		 */
-		atomic_dec(&part->channel_mgr_requests);
-		(void)wait_event_interruptible(part->channel_mgr_wq,
-				(atomic_read(&part->channel_mgr_requests) > 0 ||
-				 part->chctl.all_flags != 0 ||
-				 (part->act_state == XPC_P_AS_DEACTIVATING &&
-				 atomic_read(&part->nchannels_active) == 0 &&
-				 xpc_partition_disengaged(part))));
-		atomic_set(&part->channel_mgr_requests, 1);
-	}
-}
-
-/*
- * Guarantee that the kzalloc'd memory is cacheline aligned.
- */
-void *
-xpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
-{
-	/* see if kzalloc will give us cachline aligned memory by default */
-	*base = kzalloc(size, flags);
-	if (*base == NULL)
-		return NULL;
-
-	if ((u64)*base == L1_CACHE_ALIGN((u64)*base))
-		return *base;
-
-	kfree(*base);
-
-	/* nope, we'll have to do it ourselves */
-	*base = kzalloc(size + L1_CACHE_BYTES, flags);
-	if (*base == NULL)
-		return NULL;
-
-	return (void *)L1_CACHE_ALIGN((u64)*base);
-}
-
-/*
- * Setup the channel structures necessary to support XPartition Communication
- * between the specified remote partition and the local one.
- */
-static enum xp_retval
-xpc_setup_ch_structures(struct xpc_partition *part)
-{
-	enum xp_retval ret;
-	int ch_number;
-	struct xpc_channel *ch;
-	short partid = XPC_PARTID(part);
-
-	/*
-	 * Allocate all of the channel structures as a contiguous chunk of
-	 * memory.
-	 */
-	DBUG_ON(part->channels != NULL);
-	part->channels = kzalloc_objs(struct xpc_channel, XPC_MAX_NCHANNELS);
-	if (part->channels == NULL) {
-		dev_err(xpc_chan, "can't get memory for channels\n");
-		return xpNoMemory;
-	}
-
-	/* allocate the remote open and close args */
-
-	part->remote_openclose_args =
-	    xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE,
-					  GFP_KERNEL, &part->
-					  remote_openclose_args_base);
-	if (part->remote_openclose_args == NULL) {
-		dev_err(xpc_chan, "can't get memory for remote connect args\n");
-		ret = xpNoMemory;
-		goto out_1;
-	}
-
-	part->chctl.all_flags = 0;
-	spin_lock_init(&part->chctl_lock);
-
-	atomic_set(&part->channel_mgr_requests, 1);
-	init_waitqueue_head(&part->channel_mgr_wq);
-
-	part->nchannels = XPC_MAX_NCHANNELS;
-
-	atomic_set(&part->nchannels_active, 0);
-	atomic_set(&part->nchannels_engaged, 0);
-
-	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
-		ch = &part->channels[ch_number];
-
-		ch->partid = partid;
-		ch->number = ch_number;
-		ch->flags = XPC_C_DISCONNECTED;
-
-		atomic_set(&ch->kthreads_assigned, 0);
-		atomic_set(&ch->kthreads_idle, 0);
-		atomic_set(&ch->kthreads_active, 0);
-
-		atomic_set(&ch->references, 0);
-		atomic_set(&ch->n_to_notify, 0);
-
-		spin_lock_init(&ch->lock);
-		init_completion(&ch->wdisconnect_wait);
-
-		atomic_set(&ch->n_on_msg_allocate_wq, 0);
-		init_waitqueue_head(&ch->msg_allocate_wq);
-		init_waitqueue_head(&ch->idle_wq);
-	}
-
-	ret = xpc_arch_ops.setup_ch_structures(part);
-	if (ret != xpSuccess)
-		goto out_2;
-
-	/*
-	 * With the setting of the partition setup_state to XPC_P_SS_SETUP,
-	 * we're declaring that this partition is ready to go.
-	 */
-	part->setup_state = XPC_P_SS_SETUP;
-
-	return xpSuccess;
-
-	/* setup of ch structures failed */
-out_2:
-	kfree(part->remote_openclose_args_base);
-	part->remote_openclose_args = NULL;
-out_1:
-	kfree(part->channels);
-	part->channels = NULL;
-	return ret;
-}
-
-/*
- * Teardown the channel structures necessary to support XPartition Communication
- * between the specified remote partition and the local one.
- */
-static void
-xpc_teardown_ch_structures(struct xpc_partition *part)
-{
-	DBUG_ON(atomic_read(&part->nchannels_engaged) != 0);
-	DBUG_ON(atomic_read(&part->nchannels_active) != 0);
-
-	/*
-	 * Make this partition inaccessible to local processes by marking it
-	 * as no longer setup. Then wait before proceeding with the teardown
-	 * until all existing references cease.
-	 */
-	DBUG_ON(part->setup_state != XPC_P_SS_SETUP);
-	part->setup_state = XPC_P_SS_WTEARDOWN;
-
-	wait_event(part->teardown_wq, (atomic_read(&part->references) == 0));
-
-	/* now we can begin tearing down the infrastructure */
-
-	xpc_arch_ops.teardown_ch_structures(part);
-
-	kfree(part->remote_openclose_args_base);
-	part->remote_openclose_args = NULL;
-	kfree(part->channels);
-	part->channels = NULL;
-
-	part->setup_state = XPC_P_SS_TORNDOWN;
-}
-
-/*
- * When XPC HB determines that a partition has come up, it will create a new
- * kthread and that kthread will call this function to attempt to set up the
- * basic infrastructure used for Cross Partition Communication with the newly
- * upped partition.
- *
- * The kthread that was created by XPC HB and which setup the XPC
- * infrastructure will remain assigned to the partition becoming the channel
- * manager for that partition until the partition is deactivating, at which
- * time the kthread will teardown the XPC infrastructure and then exit.
- */
-static int
-xpc_activating(void *__partid)
-{
-	short partid = (u64)__partid;
-	struct xpc_partition *part = &xpc_partitions[partid];
-	unsigned long irq_flags;
-
-	DBUG_ON(partid < 0 || partid >= xp_max_npartitions);
-
-	spin_lock_irqsave(&part->act_lock, irq_flags);
-
-	if (part->act_state == XPC_P_AS_DEACTIVATING) {
-		part->act_state = XPC_P_AS_INACTIVE;
-		spin_unlock_irqrestore(&part->act_lock, irq_flags);
-		part->remote_rp_pa = 0;
-		return 0;
-	}
-
-	/* indicate the thread is activating */
-	DBUG_ON(part->act_state != XPC_P_AS_ACTIVATION_REQ);
-	part->act_state = XPC_P_AS_ACTIVATING;
-
-	XPC_SET_REASON(part, 0, 0);
-	spin_unlock_irqrestore(&part->act_lock, irq_flags);
-
-	dev_dbg(xpc_part, "activating partition %d\n", partid);
-
-	xpc_arch_ops.allow_hb(partid);
-
-	if (xpc_setup_ch_structures(part) == xpSuccess) {
-		(void)xpc_part_ref(part);	/* this will always succeed */
-
-		if (xpc_arch_ops.make_first_contact(part) == xpSuccess) {
-			xpc_mark_partition_active(part);
-			xpc_channel_mgr(part);
-			/* won't return until partition is deactivating */
-		}
-
-		xpc_part_deref(part);
-		xpc_teardown_ch_structures(part);
-	}
-
-	xpc_arch_ops.disallow_hb(partid);
-	xpc_mark_partition_inactive(part);
-
-	if (part->reason == xpReactivating) {
-		/* interrupting ourselves results in activating partition */
-		xpc_arch_ops.request_partition_reactivation(part);
-	}
-
-	return 0;
-}
-
-void
-xpc_activate_partition(struct xpc_partition *part)
-{
-	short partid = XPC_PARTID(part);
-	unsigned long irq_flags;
-	struct task_struct *kthread;
-
-	spin_lock_irqsave(&part->act_lock, irq_flags);
-
-	DBUG_ON(part->act_state != XPC_P_AS_INACTIVE);
-
-	part->act_state = XPC_P_AS_ACTIVATION_REQ;
-	XPC_SET_REASON(part, xpCloneKThread, __LINE__);
-
-	spin_unlock_irqrestore(&part->act_lock, irq_flags);
-
-	kthread = kthread_run(xpc_activating, (void *)((u64)partid), "xpc%02d",
-			      partid);
-	if (IS_ERR(kthread)) {
-		spin_lock_irqsave(&part->act_lock, irq_flags);
-		part->act_state = XPC_P_AS_INACTIVE;
-		XPC_SET_REASON(part, xpCloneKThreadFailed, __LINE__);
-		spin_unlock_irqrestore(&part->act_lock, irq_flags);
-	}
-}
-
-void
-xpc_activate_kthreads(struct xpc_channel *ch, int needed)
-{
-	int idle = atomic_read(&ch->kthreads_idle);
-	int assigned = atomic_read(&ch->kthreads_assigned);
-	int wakeup;
-
-	DBUG_ON(needed <= 0);
-
-	if (idle > 0) {
-		wakeup = (needed > idle) ? idle : needed;
-		needed -= wakeup;
-
-		dev_dbg(xpc_chan, "wakeup %d idle kthreads, partid=%d, "
-			"channel=%d\n", wakeup, ch->partid, ch->number);
-
-		/* only wakeup the requested number of kthreads */
-		wake_up_nr(&ch->idle_wq, wakeup);
-	}
-
-	if (needed <= 0)
-		return;
-
-	if (needed + assigned > ch->kthreads_assigned_limit) {
-		needed = ch->kthreads_assigned_limit - assigned;
-		if (needed <= 0)
-			return;
-	}
-
-	dev_dbg(xpc_chan, "create %d new kthreads, partid=%d, channel=%d\n",
-		needed, ch->partid, ch->number);
-
-	xpc_create_kthreads(ch, needed, 0);
-}
-
-/*
- * This function is where XPC's kthreads wait for messages to deliver.
- */
-static void
-xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch)
-{
-	int (*n_of_deliverable_payloads) (struct xpc_channel *) =
-		xpc_arch_ops.n_of_deliverable_payloads;
-
-	do {
-		/* deliver messages to their intended recipients */
-
-		while (n_of_deliverable_payloads(ch) > 0 &&
-		       !(ch->flags & XPC_C_DISCONNECTING)) {
-			xpc_deliver_payload(ch);
-		}
-
-		if (atomic_inc_return(&ch->kthreads_idle) >
-		    ch->kthreads_idle_limit) {
-			/* too many idle kthreads on this channel */
-			atomic_dec(&ch->kthreads_idle);
-			break;
-		}
-
-		dev_dbg(xpc_chan, "idle kthread calling "
-			"wait_event_interruptible_exclusive()\n");
-
-		(void)wait_event_interruptible_exclusive(ch->idle_wq,
-				(n_of_deliverable_payloads(ch) > 0 ||
-				 (ch->flags & XPC_C_DISCONNECTING)));
-
-		atomic_dec(&ch->kthreads_idle);
-
-	} while (!(ch->flags & XPC_C_DISCONNECTING));
-}
-
-static int
-xpc_kthread_start(void *args)
-{
-	short partid = XPC_UNPACK_ARG1(args);
-	u16 ch_number = XPC_UNPACK_ARG2(args);
-	struct xpc_partition *part = &xpc_partitions[partid];
-	struct xpc_channel *ch;
-	int n_needed;
-	unsigned long irq_flags;
-	int (*n_of_deliverable_payloads) (struct xpc_channel *) =
-		xpc_arch_ops.n_of_deliverable_payloads;
-
-	dev_dbg(xpc_chan, "kthread starting, partid=%d, channel=%d\n",
-		partid, ch_number);
-
-	ch = &part->channels[ch_number];
-
-	if (!(ch->flags & XPC_C_DISCONNECTING)) {
-
-		/* let registerer know that connection has been established */
-
-		spin_lock_irqsave(&ch->lock, irq_flags);
-		if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) {
-			ch->flags |= XPC_C_CONNECTEDCALLOUT;
-			spin_unlock_irqrestore(&ch->lock, irq_flags);
-
-			xpc_connected_callout(ch);
-
-			spin_lock_irqsave(&ch->lock, irq_flags);
-			ch->flags |= XPC_C_CONNECTEDCALLOUT_MADE;
-			spin_unlock_irqrestore(&ch->lock, irq_flags);
-
-			/*
-			 * It is possible that while the callout was being
-			 * made that the remote partition sent some messages.
-			 * If that is the case, we may need to activate
-			 * additional kthreads to help deliver them. We only
-			 * need one less than total #of messages to deliver.
-			 */
-			n_needed = n_of_deliverable_payloads(ch) - 1;
-			if (n_needed > 0 && !(ch->flags & XPC_C_DISCONNECTING))
-				xpc_activate_kthreads(ch, n_needed);
-
-		} else {
-			spin_unlock_irqrestore(&ch->lock, irq_flags);
-		}
-
-		xpc_kthread_waitmsgs(part, ch);
-	}
-
-	/* let registerer know that connection is disconnecting */
-
-	spin_lock_irqsave(&ch->lock, irq_flags);
-	if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
-	    !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
-		ch->flags |= XPC_C_DISCONNECTINGCALLOUT;
-		spin_unlock_irqrestore(&ch->lock, irq_flags);
-
-		xpc_disconnect_callout(ch, xpDisconnecting);
-
-		spin_lock_irqsave(&ch->lock, irq_flags);
-		ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE;
-	}
-	spin_unlock_irqrestore(&ch->lock, irq_flags);
-
-	if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
-	    atomic_dec_return(&part->nchannels_engaged) == 0) {
-		xpc_arch_ops.indicate_partition_disengaged(part);
-	}
-
-	xpc_msgqueue_deref(ch);
-
-	dev_dbg(xpc_chan, "kthread exiting, partid=%d, channel=%d\n",
-		partid, ch_number);
-
-	xpc_part_deref(part);
-	return 0;
-}
-
-/*
- * For each partition that XPC has established communications with, there is
- * a minimum of one kernel thread assigned to perform any operation that
- * may potentially sleep or block (basically the callouts to the asynchronous
- * functions registered via xpc_connect()).
- *
- * Additional kthreads are created and destroyed by XPC as the workload
- * demands.
- *
- * A kthread is assigned to one of the active channels that exists for a given
- * partition.
- */
-void
-xpc_create_kthreads(struct xpc_channel *ch, int needed,
-		    int ignore_disconnecting)
-{
-	unsigned long irq_flags;
-	u64 args = XPC_PACK_ARGS(ch->partid, ch->number);
-	struct xpc_partition *part = &xpc_partitions[ch->partid];
-	struct task_struct *kthread;
-	void (*indicate_partition_disengaged) (struct xpc_partition *) =
-		xpc_arch_ops.indicate_partition_disengaged;
-
-	while (needed-- > 0) {
-
-		/*
-		 * The following is done on behalf of the newly created
-		 * kthread. That kthread is responsible for doing the
-		 * counterpart to the following before it exits.
-		 */
-		if (ignore_disconnecting) {
-			if (!atomic_inc_not_zero(&ch->kthreads_assigned)) {
-				/* kthreads assigned had gone to zero */
-				BUG_ON(!(ch->flags &
-					 XPC_C_DISCONNECTINGCALLOUT_MADE));
-				break;
-			}
-
-		} else if (ch->flags & XPC_C_DISCONNECTING) {
-			break;
-
-		} else if (atomic_inc_return(&ch->kthreads_assigned) == 1 &&
-			   atomic_inc_return(&part->nchannels_engaged) == 1) {
-			xpc_arch_ops.indicate_partition_engaged(part);
-		}
-		(void)xpc_part_ref(part);
-		xpc_msgqueue_ref(ch);
-
-		kthread = kthread_run(xpc_kthread_start, (void *)args,
-				      "xpc%02dc%d", ch->partid, ch->number);
-		if (IS_ERR(kthread)) {
-			/* the fork failed */
-
-			/*
-			 * NOTE: if (ignore_disconnecting &&
-			 * !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) is true,
-			 * then we'll deadlock if all other kthreads assigned
-			 * to this channel are blocked in the channel's
-			 * registerer, because the only thing that will unblock
-			 * them is the xpDisconnecting callout that this
-			 * failed kthread_run() would have made.
-			 */
-
-			if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
-			    atomic_dec_return(&part->nchannels_engaged) == 0) {
-				indicate_partition_disengaged(part);
-			}
-			xpc_msgqueue_deref(ch);
-			xpc_part_deref(part);
-
-			if (atomic_read(&ch->kthreads_assigned) <
-			    ch->kthreads_idle_limit) {
-				/*
-				 * Flag this as an error only if we have an
-				 * insufficient #of kthreads for the channel
-				 * to function.
-				 */
-				spin_lock_irqsave(&ch->lock, irq_flags);
-				XPC_DISCONNECT_CHANNEL(ch, xpLackOfResources,
-						       &irq_flags);
-				spin_unlock_irqrestore(&ch->lock, irq_flags);
-			}
-			break;
-		}
-	}
-}
-
-void
-xpc_disconnect_wait(int ch_number)
-{
-	unsigned long irq_flags;
-	short partid;
-	struct xpc_partition *part;
-	struct xpc_channel *ch;
-	int wakeup_channel_mgr;
-
-	/* now wait for all callouts to the caller's function to cease */
-	for (partid = 0; partid < xp_max_npartitions; partid++) {
-		part = &xpc_partitions[partid];
-
-		if (!xpc_part_ref(part))
-			continue;
-
-		ch = &part->channels[ch_number];
-
-		if (!(ch->flags & XPC_C_WDISCONNECT)) {
-			xpc_part_deref(part);
-			continue;
-		}
-
-		wait_for_completion(&ch->wdisconnect_wait);
-
-		spin_lock_irqsave(&ch->lock, irq_flags);
-		DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
-		wakeup_channel_mgr = 0;
-
-		if (ch->delayed_chctl_flags) {
-			if (part->act_state != XPC_P_AS_DEACTIVATING) {
-				spin_lock(&part->chctl_lock);
-				part->chctl.flags[ch->number] |=
-				    ch->delayed_chctl_flags;
-				spin_unlock(&part->chctl_lock);
-				wakeup_channel_mgr = 1;
-			}
-			ch->delayed_chctl_flags = 0;
-		}
-
-		ch->flags &= ~XPC_C_WDISCONNECT;
-		spin_unlock_irqrestore(&ch->lock, irq_flags);
-
-		if (wakeup_channel_mgr)
-			xpc_wakeup_channel_mgr(part);
-
-		xpc_part_deref(part);
-	}
-}
-
-static int
-xpc_setup_partitions(void)
-{
-	short partid;
-	struct xpc_partition *part;
-
-	xpc_partitions = kzalloc_objs(struct xpc_partition, xp_max_npartitions);
-	if (xpc_partitions == NULL) {
-		dev_err(xpc_part, "can't get memory for partition structure\n");
-		return -ENOMEM;
-	}
-
-	/*
-	 * The first few fields of each entry of xpc_partitions[] need to
-	 * be initialized now so that calls to xpc_connect() and
-	 * xpc_disconnect() can be made prior to the activation of any remote
-	 * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE
-	 * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING
-	 * PARTITION HAS BEEN ACTIVATED.
-	 */
-	for (partid = 0; partid < xp_max_npartitions; partid++) {
-		part = &xpc_partitions[partid];
-
-		DBUG_ON((u64)part != L1_CACHE_ALIGN((u64)part));
-
-		part->activate_IRQ_rcvd = 0;
-		spin_lock_init(&part->act_lock);
-		part->act_state = XPC_P_AS_INACTIVE;
-		XPC_SET_REASON(part, 0, 0);
-
-		timer_setup(&part->disengage_timer,
-			    xpc_timeout_partition_disengage, 0);
-
-		part->setup_state = XPC_P_SS_UNSET;
-		init_waitqueue_head(&part->teardown_wq);
-		atomic_set(&part->references, 0);
-	}
-
-	return xpc_arch_ops.setup_partitions();
-}
-
-static void
-xpc_teardown_partitions(void)
-{
-	xpc_arch_ops.teardown_partitions();
-	kfree(xpc_partitions);
-}
-
-static void
-xpc_do_exit(enum xp_retval reason)
-{
-	short partid;
-	int active_part_count, printed_waiting_msg = 0;
-	struct xpc_partition *part;
-	unsigned long printmsg_time, disengage_timeout = 0;
-
-	/* a 'rmmod XPC' and a 'reboot' cannot both end up here together */
-	DBUG_ON(xpc_exiting == 1);
-
-	/*
-	 * Let the heartbeat checker thread and the discovery thread
-	 * (if one is running) know that they should exit. Also wake up
-	 * the heartbeat checker thread in case it's sleeping.
-	 */
-	xpc_exiting = 1;
-	wake_up_interruptible(&xpc_activate_IRQ_wq);
-
-	/* wait for the discovery thread to exit */
-	wait_for_completion(&xpc_discovery_exited);
-
-	/* wait for the heartbeat checker thread to exit */
-	wait_for_completion(&xpc_hb_checker_exited);
-
-	/* sleep for a 1/3 of a second or so */
-	(void)msleep_interruptible(300);
-
-	/* wait for all partitions to become inactive */
-
-	printmsg_time = jiffies + (XPC_DEACTIVATE_PRINTMSG_INTERVAL * HZ);
-	xpc_disengage_timedout = 0;
-
-	do {
-		active_part_count = 0;
-
-		for (partid = 0; partid < xp_max_npartitions; partid++) {
-			part = &xpc_partitions[partid];
-
-			if (xpc_partition_disengaged(part) &&
-			    part->act_state == XPC_P_AS_INACTIVE) {
-				continue;
-			}
-
-			active_part_count++;
-
-			XPC_DEACTIVATE_PARTITION(part, reason);
-
-			if (part->disengage_timeout > disengage_timeout)
-				disengage_timeout = part->disengage_timeout;
-		}
-
-		if (xpc_arch_ops.any_partition_engaged()) {
-			if (time_is_before_jiffies(printmsg_time)) {
-				dev_info(xpc_part, "waiting for remote "
-					 "partitions to deactivate, timeout in "
-					 "%ld seconds\n", (disengage_timeout -
-					 jiffies) / HZ);
-				printmsg_time = jiffies +
-				    (XPC_DEACTIVATE_PRINTMSG_INTERVAL * HZ);
-				printed_waiting_msg = 1;
-			}
-
-		} else if (active_part_count > 0) {
-			if (printed_waiting_msg) {
-				dev_info(xpc_part, "waiting for local partition"
-					 " to deactivate\n");
-				printed_waiting_msg = 0;
-			}
-
-		} else {
-			if (!xpc_disengage_timedout) {
-				dev_info(xpc_part, "all partitions have "
-					 "deactivated\n");
-			}
-			break;
-		}
-
-		/* sleep for a 1/3 of a second or so */
-		(void)msleep_interruptible(300);
-
-	} while (1);
-
-	DBUG_ON(xpc_arch_ops.any_partition_engaged());
-
-	xpc_teardown_rsvd_page();
-
-	if (reason == xpUnloading) {
-		(void)unregister_die_notifier(&xpc_die_notifier);
-		(void)unregister_reboot_notifier(&xpc_reboot_notifier);
-	}
-
-	/* clear the interface to XPC's functions */
-	xpc_clear_interface();
-
-	if (xpc_sysctl)
-		unregister_sysctl_table(xpc_sysctl);
-	if (xpc_sysctl_hb)
-		unregister_sysctl_table(xpc_sysctl_hb);
-
-	xpc_teardown_partitions();
-
-	if (is_uv_system())
-		xpc_exit_uv();
-}
-
-/*
- * This function is called when the system is being rebooted.
- */
-static int
-xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
-{
-	enum xp_retval reason;
-
-	switch (event) {
-	case SYS_RESTART:
-		reason = xpSystemReboot;
-		break;
-	case SYS_HALT:
-		reason = xpSystemHalt;
-		break;
-	case SYS_POWER_OFF:
-		reason = xpSystemPoweroff;
-		break;
-	default:
-		reason = xpSystemGoingDown;
-	}
-
-	xpc_do_exit(reason);
-	return NOTIFY_DONE;
-}
-
-/* Used to only allow one cpu to complete disconnect */
-static unsigned int xpc_die_disconnecting;
-
-/*
- * Notify other partitions to deactivate from us by first disengaging from all
- * references to our memory.
- */
-static void
-xpc_die_deactivate(void)
-{
-	struct xpc_partition *part;
-	short partid;
-	int any_engaged;
-	long keep_waiting;
-	long wait_to_print;
-
-	if (cmpxchg(&xpc_die_disconnecting, 0, 1))
-		return;
-
-	/* keep xpc_hb_checker thread from doing anything (just in case) */
-	xpc_exiting = 1;
-
-	xpc_arch_ops.disallow_all_hbs();   /*indicate we're deactivated */
-
-	for (partid = 0; partid < xp_max_npartitions; partid++) {
-		part = &xpc_partitions[partid];
-
-		if (xpc_arch_ops.partition_engaged(partid) ||
-		    part->act_state != XPC_P_AS_INACTIVE) {
-			xpc_arch_ops.request_partition_deactivation(part);
-			xpc_arch_ops.indicate_partition_disengaged(part);
-		}
-	}
-
-	/*
-	 * Though we requested that all other partitions deactivate from us,
-	 * we only wait until they've all disengaged or we've reached the
-	 * defined timelimit.
-	 *
-	 * Given that one iteration through the following while-loop takes
-	 * approximately 200 microseconds, calculate the #of loops to take
-	 * before bailing and the #of loops before printing a waiting message.
-	 */
-	keep_waiting = xpc_disengage_timelimit * 1000 * 5;
-	wait_to_print = XPC_DEACTIVATE_PRINTMSG_INTERVAL * 1000 * 5;
-
-	while (1) {
-		any_engaged = xpc_arch_ops.any_partition_engaged();
-		if (!any_engaged) {
-			dev_info(xpc_part, "all partitions have deactivated\n");
-			break;
-		}
-
-		if (!keep_waiting--) {
-			for (partid = 0; partid < xp_max_npartitions;
-			     partid++) {
-				if (xpc_arch_ops.partition_engaged(partid)) {
-					dev_info(xpc_part, "deactivate from "
-						 "remote partition %d timed "
-						 "out\n", partid);
-				}
-			}
-			break;
-		}
-
-		if (!wait_to_print--) {
-			dev_info(xpc_part, "waiting for remote partitions to "
-				 "deactivate, timeout in %ld seconds\n",
-				 keep_waiting / (1000 * 5));
-			wait_to_print = XPC_DEACTIVATE_PRINTMSG_INTERVAL *
-			    1000 * 5;
-		}
-
-		udelay(200);
-	}
-}
-
-/*
- * This function is called when the system is being restarted or halted due
- * to some sort of system failure. If this is the case we need to notify the
- * other partitions to disengage from all references to our memory.
- * This function can also be called when our heartbeater could be offlined
- * for a time. In this case we need to notify other partitions to not worry
- * about the lack of a heartbeat.
- */
-static int
-xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args)
-{
-	struct die_args *die_args = _die_args;
-
-	switch (event) {
-	case DIE_TRAP:
-		if (die_args->trapnr == X86_TRAP_DF)
-			xpc_die_deactivate();
-
-		if (((die_args->trapnr == X86_TRAP_MF) ||
-		     (die_args->trapnr == X86_TRAP_XF)) &&
-		    !user_mode(die_args->regs))
-			xpc_die_deactivate();
-
-		break;
-	case DIE_INT3:
-	case DIE_DEBUG:
-		break;
-	case DIE_OOPS:
-	case DIE_GPF:
-	default:
-		xpc_die_deactivate();
-	}
-
-	return NOTIFY_DONE;
-}
-
-static int __init
-xpc_init(void)
-{
-	int ret;
-	struct task_struct *kthread;
-
-	dev_set_name(xpc_part, "part");
-	dev_set_name(xpc_chan, "chan");
-
-	if (is_uv_system()) {
-		ret = xpc_init_uv();
-
-	} else {
-		ret = -ENODEV;
-	}
-
-	if (ret != 0)
-		return ret;
-
-	ret = xpc_setup_partitions();
-	if (ret != 0) {
-		dev_err(xpc_part, "can't get memory for partition structure\n");
-		goto out_1;
-	}
-
-	xpc_sysctl = register_sysctl("xpc", xpc_sys_xpc);
-	xpc_sysctl_hb = register_sysctl("xpc/hb", xpc_sys_xpc_hb);
-
-	/*
-	 * Fill the partition reserved page with the information needed by
-	 * other partitions to discover we are alive and establish initial
-	 * communications.
-	 */
-	ret = xpc_setup_rsvd_page();
-	if (ret != 0) {
-		dev_err(xpc_part, "can't setup our reserved page\n");
-		goto out_2;
-	}
-
-	/* add ourselves to the reboot_notifier_list */
-	ret = register_reboot_notifier(&xpc_reboot_notifier);
-	if (ret != 0)
-		dev_warn(xpc_part, "can't register reboot notifier\n");
-
-	/* add ourselves to the die_notifier list */
-	ret = register_die_notifier(&xpc_die_notifier);
-	if (ret != 0)
-		dev_warn(xpc_part, "can't register die notifier\n");
-
-	/*
-	 * The real work-horse behind xpc.  This processes incoming
-	 * interrupts and monitors remote heartbeats.
-	 */
-	kthread = kthread_run(xpc_hb_checker, NULL, XPC_HB_CHECK_THREAD_NAME);
-	if (IS_ERR(kthread)) {
-		dev_err(xpc_part, "failed while forking hb check thread\n");
-		ret = -EBUSY;
-		goto out_3;
-	}
-
-	/*
-	 * Startup a thread that will attempt to discover other partitions to
-	 * activate based on info provided by SAL. This new thread is short
-	 * lived and will exit once discovery is complete.
-	 */
-	kthread = kthread_run(xpc_initiate_discovery, NULL,
-			      XPC_DISCOVERY_THREAD_NAME);
-	if (IS_ERR(kthread)) {
-		dev_err(xpc_part, "failed while forking discovery thread\n");
-
-		/* mark this new thread as a non-starter */
-		complete(&xpc_discovery_exited);
-
-		xpc_do_exit(xpUnloading);
-		return -EBUSY;
-	}
-
-	/* set the interface to point at XPC's functions */
-	xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect,
-			  xpc_initiate_send, xpc_initiate_send_notify,
-			  xpc_initiate_received, xpc_initiate_partid_to_nasids);
-
-	return 0;
-
-	/* initialization was not successful */
-out_3:
-	xpc_teardown_rsvd_page();
-
-	(void)unregister_die_notifier(&xpc_die_notifier);
-	(void)unregister_reboot_notifier(&xpc_reboot_notifier);
-out_2:
-	if (xpc_sysctl_hb)
-		unregister_sysctl_table(xpc_sysctl_hb);
-	if (xpc_sysctl)
-		unregister_sysctl_table(xpc_sysctl);
-
-	xpc_teardown_partitions();
-out_1:
-	if (is_uv_system())
-		xpc_exit_uv();
-	return ret;
-}
-
-module_init(xpc_init);
-
-static void __exit
-xpc_exit(void)
-{
-	xpc_do_exit(xpUnloading);
-}
-
-module_exit(xpc_exit);
-
-MODULE_AUTHOR("Silicon Graphics, Inc.");
-MODULE_DESCRIPTION("Cross Partition Communication (XPC) support");
-MODULE_LICENSE("GPL");
-
-module_param(xpc_hb_interval, int, 0);
-MODULE_PARM_DESC(xpc_hb_interval, "Number of seconds between "
-		 "heartbeat increments.");
-
-module_param(xpc_hb_check_interval, int, 0);
-MODULE_PARM_DESC(xpc_hb_check_interval, "Number of seconds between "
-		 "heartbeat checks.");
-
-module_param(xpc_disengage_timelimit, int, 0);
-MODULE_PARM_DESC(xpc_disengage_timelimit, "Number of seconds to wait "
-		 "for disengage to complete.");
-
-module_param(xpc_kdebug_ignore, int, 0);
-MODULE_PARM_DESC(xpc_kdebug_ignore, "Should lack of heartbeat be ignored by "
-		 "other partitions when dropping into kdebug.");
diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c
deleted file mode 100644
index d0467010558c..000000000000
--- a/drivers/misc/sgi-xp/xpc_partition.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * 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.
- *
- * (C) Copyright 2020 Hewlett Packard Enterprise Development LP
- * Copyright (c) 2004-2008 Silicon Graphics, Inc.  All Rights Reserved.
- */
-
-/*
- * 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/device.h>
-#include <linux/hardirq.h>
-#include <linux/slab.h>
-#include "xpc.h"
-#include <asm/uv/uv_hub.h>
-
-/* XPC is exiting flag */
-int xpc_exiting;
-
-/* this partition's reserved page pointers */
-struct xpc_rsvd_page *xpc_rsvd_page;
-static unsigned long *xpc_part_nasids;
-unsigned long *xpc_mach_nasids;
-
-static int xpc_nasid_mask_nbytes;	/* #of bytes in nasid mask */
-int xpc_nasid_mask_nlongs;	/* #of longs in nasid mask */
-
-struct xpc_partition *xpc_partitions;
-
-/*
- * Guarantee that the kmalloc'd memory is cacheline aligned.
- */
-void *
-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);
-	if (*base == NULL)
-		return NULL;
-
-	if ((u64)*base == L1_CACHE_ALIGN((u64)*base))
-		return *base;
-
-	kfree(*base);
-
-	/* nope, we'll have to do it ourselves */
-	*base = kmalloc(size + L1_CACHE_BYTES, flags);
-	if (*base == NULL)
-		return NULL;
-
-	return (void *)L1_CACHE_ALIGN((u64)*base);
-}
-
-/*
- * Given a nasid, get the physical address of the  partition's reserved page
- * for that nasid. This function returns 0 on any error.
- */
-static unsigned long
-xpc_get_rsvd_page_pa(int nasid)
-{
-	enum xp_retval ret;
-	u64 cookie = 0;
-	unsigned long rp_pa = nasid;	/* seed with nasid */
-	size_t len = 0;
-	size_t buf_len = 0;
-	void *buf = NULL;
-	void *buf_base = NULL;
-	enum xp_retval (*get_partition_rsvd_page_pa)
-		(void *, u64 *, unsigned long *, size_t *) =
-		xpc_arch_ops.get_partition_rsvd_page_pa;
-
-	while (1) {
-
-		/* !!! rp_pa will need to be _gpa on UV.
-		 * ??? So do we save it into the architecture specific parts
-		 * ??? of the xpc_partition structure? Do we rename this
-		 * ??? function or have two versions? Rename rp_pa for UV to
-		 * ??? rp_gpa?
-		 */
-		ret = get_partition_rsvd_page_pa(buf, &cookie, &rp_pa, &len);
-
-		dev_dbg(xpc_part, "SAL returned with ret=%d, cookie=0x%016lx, "
-			"address=0x%016lx, len=0x%016lx\n", ret,
-			(unsigned long)cookie, rp_pa, len);
-
-		if (ret != xpNeedMoreInfo)
-			break;
-
-		if (len > buf_len) {
-			kfree(buf_base);
-			buf_len = L1_CACHE_ALIGN(len);
-			buf = xpc_kmalloc_cacheline_aligned(buf_len, GFP_KERNEL,
-							    &buf_base);
-			if (buf_base == NULL) {
-				dev_err(xpc_part, "unable to kmalloc "
-					"len=0x%016lx\n", buf_len);
-				ret = xpNoMemory;
-				break;
-			}
-		}
-
-		ret = xp_remote_memcpy(xp_pa(buf), rp_pa, len);
-		if (ret != xpSuccess) {
-			dev_dbg(xpc_part, "xp_remote_memcpy failed %d\n", ret);
-			break;
-		}
-	}
-
-	kfree(buf_base);
-
-	if (ret != xpSuccess)
-		rp_pa = 0;
-
-	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.
- */
-int
-xpc_setup_rsvd_page(void)
-{
-	int ret;
-	struct xpc_rsvd_page *rp;
-	unsigned long rp_pa;
-	unsigned long new_ts_jiffies;
-
-	/* get the local reserved page's address */
-
-	preempt_disable();
-	rp_pa = xpc_get_rsvd_page_pa(xp_cpu_to_nasid(smp_processor_id()));
-	preempt_enable();
-	if (rp_pa == 0) {
-		dev_err(xpc_part, "SAL failed to locate the reserved page\n");
-		return -ESRCH;
-	}
-	rp = (struct xpc_rsvd_page *)__va(xp_socket_pa(rp_pa));
-
-	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 != xp_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);
-		return -EINVAL;
-	}
-
-	rp->version = XPC_RP_VERSION;
-	rp->max_npartitions = xp_max_npartitions;
-
-	/* establish the actual sizes of the nasid masks */
-	if (rp->SAL_version == 1) {
-		/* SAL_version 1 didn't set the nasids_size field */
-		rp->SAL_nasids_size = 128;
-	}
-	xpc_nasid_mask_nbytes = rp->SAL_nasids_size;
-	xpc_nasid_mask_nlongs = BITS_TO_LONGS(rp->SAL_nasids_size *
-					      BITS_PER_BYTE);
-
-	/* 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);
-
-	ret = xpc_arch_ops.setup_rsvd_page(rp);
-	if (ret != 0)
-		return ret;
-
-	/*
-	 * Set timestamp of when reserved page was setup by XPC.
-	 * This signifies to the remote partition that our reserved
-	 * page is initialized.
-	 */
-	new_ts_jiffies = jiffies;
-	if (new_ts_jiffies == 0 || new_ts_jiffies == rp->ts_jiffies)
-		new_ts_jiffies++;
-	rp->ts_jiffies = new_ts_jiffies;
-
-	xpc_rsvd_page = rp;
-	return 0;
-}
-
-void
-xpc_teardown_rsvd_page(void)
-{
-	/* a zero timestamp indicates our rsvd page is not initialized */
-	xpc_rsvd_page->ts_jiffies = 0;
-}
-
-/*
- * Get a copy of a portion of the remote partition's rsvd page.
- *
- * remote_rp points to a buffer that is cacheline aligned for BTE copies and
- * is large enough to contain a copy of their reserved page header and
- * part_nasids mask.
- */
-enum xp_retval
-xpc_get_remote_rp(int nasid, unsigned long *discovered_nasids,
-		  struct xpc_rsvd_page *remote_rp, unsigned long *remote_rp_pa)
-{
-	int l;
-	enum xp_retval ret;
-
-	/* get the reserved page's physical address */
-
-	*remote_rp_pa = xpc_get_rsvd_page_pa(nasid);
-	if (*remote_rp_pa == 0)
-		return xpNoRsvdPageAddr;
-
-	/* pull over the reserved page header and part_nasids mask */
-	ret = xp_remote_memcpy(xp_pa(remote_rp), *remote_rp_pa,
-			       XPC_RP_HEADER_SIZE + xpc_nasid_mask_nbytes);
-	if (ret != xpSuccess)
-		return ret;
-
-	if (discovered_nasids != NULL) {
-		unsigned long *remote_part_nasids =
-		    XPC_RP_PART_NASIDS(remote_rp);
-
-		for (l = 0; l < xpc_nasid_mask_nlongs; l++)
-			discovered_nasids[l] |= remote_part_nasids[l];
-	}
-
-	/* zero timestamp indicates the reserved page has not been setup */
-	if (remote_rp->ts_jiffies == 0)
-		return xpRsvdPageNotSet;
-
-	if (XPC_VERSION_MAJOR(remote_rp->version) !=
-	    XPC_VERSION_MAJOR(XPC_RP_VERSION)) {
-		return xpBadVersion;
-	}
-
-	/* check that both remote and local partids are valid for each side */
-	if (remote_rp->SAL_partid < 0 ||
-	    remote_rp->SAL_partid >= xp_max_npartitions ||
-	    remote_rp->max_npartitions <= xp_partition_id) {
-		return xpInvalidPartid;
-	}
-
-	if (remote_rp->SAL_partid == xp_partition_id)
-		return xpLocalPartid;
-
-	return xpSuccess;
-}
-
-/*
- * 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.
- */
-static int __xpc_partition_disengaged(struct xpc_partition *part,
-				      bool from_timer)
-{
-	short partid = XPC_PARTID(part);
-	int disengaged;
-
-	disengaged = !xpc_arch_ops.partition_engaged(partid);
-	if (part->disengage_timeout) {
-		if (!disengaged) {
-			if (time_is_after_jiffies(part->disengage_timeout)) {
-				/* timelimit hasn't been reached yet */
-				return 0;
-			}
-
-			/*
-			 * Other side hasn't responded to our deactivate
-			 * request in a timely fashion, so assume it's dead.
-			 */
-
-			dev_info(xpc_part, "deactivate request to remote "
-				 "partition %d timed out\n", partid);
-			xpc_disengage_timedout = 1;
-			xpc_arch_ops.assume_partition_disengaged(partid);
-			disengaged = 1;
-		}
-		part->disengage_timeout = 0;
-
-		/* Cancel the timer function if not called from it */
-		if (!from_timer)
-			timer_delete_sync(&part->disengage_timer);
-
-		DBUG_ON(part->act_state != XPC_P_AS_DEACTIVATING &&
-			part->act_state != XPC_P_AS_INACTIVE);
-		if (part->act_state != XPC_P_AS_INACTIVE)
-			xpc_wakeup_channel_mgr(part);
-
-		xpc_arch_ops.cancel_partition_deactivation_request(part);
-	}
-	return disengaged;
-}
-
-int xpc_partition_disengaged(struct xpc_partition *part)
-{
-	return __xpc_partition_disengaged(part, false);
-}
-
-int xpc_partition_disengaged_from_timer(struct xpc_partition *part)
-{
-	return __xpc_partition_disengaged(part, true);
-}
-
-/*
- * Mark specified partition as active.
- */
-enum xp_retval
-xpc_mark_partition_active(struct xpc_partition *part)
-{
-	unsigned long irq_flags;
-	enum xp_retval ret;
-
-	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_AS_ACTIVATING) {
-		part->act_state = XPC_P_AS_ACTIVE;
-		ret = xpSuccess;
-	} else {
-		DBUG_ON(part->reason == xpSuccess);
-		ret = part->reason;
-	}
-	spin_unlock_irqrestore(&part->act_lock, irq_flags);
-
-	return ret;
-}
-
-/*
- * Start the process of deactivating the specified partition.
- */
-void
-xpc_deactivate_partition(const int line, struct xpc_partition *part,
-			 enum xp_retval reason)
-{
-	unsigned long irq_flags;
-
-	spin_lock_irqsave(&part->act_lock, irq_flags);
-
-	if (part->act_state == XPC_P_AS_INACTIVE) {
-		XPC_SET_REASON(part, reason, line);
-		spin_unlock_irqrestore(&part->act_lock, irq_flags);
-		if (reason == xpReactivating) {
-			/* we interrupt ourselves to reactivate partition */
-			xpc_arch_ops.request_partition_reactivation(part);
-		}
-		return;
-	}
-	if (part->act_state == XPC_P_AS_DEACTIVATING) {
-		if ((part->reason == xpUnloading && reason != xpUnloading) ||
-		    reason == xpReactivating) {
-			XPC_SET_REASON(part, reason, line);
-		}
-		spin_unlock_irqrestore(&part->act_lock, irq_flags);
-		return;
-	}
-
-	part->act_state = XPC_P_AS_DEACTIVATING;
-	XPC_SET_REASON(part, reason, line);
-
-	spin_unlock_irqrestore(&part->act_lock, irq_flags);
-
-	/* ask remote partition to deactivate with regard to us */
-	xpc_arch_ops.request_partition_deactivation(part);
-
-	/* 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);
-
-	dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n",
-		XPC_PARTID(part), reason);
-
-	xpc_partition_going_down(part, reason);
-}
-
-/*
- * Mark specified partition as inactive.
- */
-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_AS_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;
-	unsigned long remote_rp_pa;
-	int region;
-	int region_size;
-	int max_regions;
-	int nasid;
-	unsigned long *discovered_nasids;
-	enum xp_retval ret;
-
-	remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE +
-						  xpc_nasid_mask_nbytes,
-						  GFP_KERNEL, &remote_rp_base);
-	if (remote_rp == NULL)
-		return;
-
-	discovered_nasids = kcalloc(xpc_nasid_mask_nlongs, sizeof(long),
-				    GFP_KERNEL);
-	if (discovered_nasids == NULL) {
-		kfree(remote_rp_base);
-		return;
-	}
-
-	/*
-	 * 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.
-	 */
-	region_size = xp_region_size;
-
-	if (is_uv_system())
-		max_regions = 256;
-	else {
-		max_regions = 64;
-
-		switch (region_size) {
-		case 128:
-			max_regions *= 2;
-			fallthrough;
-		case 64:
-			max_regions *= 2;
-			fallthrough;
-		case 32:
-			max_regions *= 2;
-			region_size = 16;
-		}
-	}
-
-	for (region = 0; region < max_regions; region++) {
-
-		if (xpc_exiting)
-			break;
-
-		dev_dbg(xpc_part, "searching region %d\n", region);
-
-		for (nasid = (region * region_size * 2);
-		     nasid < ((region + 1) * region_size * 2); nasid += 2) {
-
-			if (xpc_exiting)
-				break;
-
-			dev_dbg(xpc_part, "checking nasid %d\n", nasid);
-
-			if (test_bit(nasid / 2, xpc_part_nasids)) {
-				dev_dbg(xpc_part, "PROM indicates Nasid %d is "
-					"part of the local partition; skipping "
-					"region\n", nasid);
-				break;
-			}
-
-			if (!(test_bit(nasid / 2, xpc_mach_nasids))) {
-				dev_dbg(xpc_part, "PROM indicates Nasid %d was "
-					"not on Numa-Link network at reset\n",
-					nasid);
-				continue;
-			}
-
-			if (test_bit(nasid / 2, discovered_nasids)) {
-				dev_dbg(xpc_part, "Nasid %d is part of a "
-					"partition which was previously "
-					"discovered\n", nasid);
-				continue;
-			}
-
-			/* pull over the rsvd page header & part_nasids mask */
-
-			ret = xpc_get_remote_rp(nasid, discovered_nasids,
-						remote_rp, &remote_rp_pa);
-			if (ret != xpSuccess) {
-				dev_dbg(xpc_part, "unable to get reserved page "
-					"from nasid %d, reason=%d\n", nasid,
-					ret);
-
-				if (ret == xpLocalPartid)
-					break;
-
-				continue;
-			}
-
-			xpc_arch_ops.request_partition_activation(remote_rp,
-							 remote_rp_pa, nasid);
-		}
-	}
-
-	kfree(discovered_nasids);
-	kfree(remote_rp_base);
-}
-
-/*
- * Given a partid, get the nasids owned by that partition from the
- * remote partition's reserved page.
- */
-enum xp_retval
-xpc_initiate_partid_to_nasids(short partid, void *nasid_mask)
-{
-	struct xpc_partition *part;
-	unsigned long part_nasid_pa;
-
-	part = &xpc_partitions[partid];
-	if (part->remote_rp_pa == 0)
-		return xpPartitionDown;
-
-	memset(nasid_mask, 0, xpc_nasid_mask_nbytes);
-
-	part_nasid_pa = (unsigned long)XPC_RP_PART_NASIDS(part->remote_rp_pa);
-
-	return xp_remote_memcpy(xp_pa(nasid_mask), part_nasid_pa,
-				xpc_nasid_mask_nbytes);
-}
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
deleted file mode 100644
index 772c78726893..000000000000
--- a/drivers/misc/sgi-xp/xpc_uv.c
+++ /dev/null
@@ -1,1728 +0,0 @@
-/*
- * 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.
- *
- * Copyright (c) 2008-2009 Silicon Graphics, Inc.  All Rights Reserved.
- */
-
-/*
- * Cross Partition Communication (XPC) uv-based functions.
- *
- *     Architecture specific implementation of common functions.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/cpu.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/numa.h>
-#include <asm/uv/uv_hub.h>
-#include <asm/uv/bios.h>
-#include <asm/uv/uv_irq.h>
-#include "../sgi-gru/gru.h"
-#include "../sgi-gru/grukservices.h"
-#include "xpc.h"
-
-static struct xpc_heartbeat_uv *xpc_heartbeat_uv;
-
-#define XPC_ACTIVATE_MSG_SIZE_UV	(1 * GRU_CACHE_LINE_BYTES)
-#define XPC_ACTIVATE_MQ_SIZE_UV		(4 * XP_MAX_NPARTITIONS_UV * \
-					 XPC_ACTIVATE_MSG_SIZE_UV)
-#define XPC_ACTIVATE_IRQ_NAME		"xpc_activate"
-
-#define XPC_NOTIFY_MSG_SIZE_UV		(2 * GRU_CACHE_LINE_BYTES)
-#define XPC_NOTIFY_MQ_SIZE_UV		(4 * XP_MAX_NPARTITIONS_UV * \
-					 XPC_NOTIFY_MSG_SIZE_UV)
-#define XPC_NOTIFY_IRQ_NAME		"xpc_notify"
-
-static int xpc_mq_node = NUMA_NO_NODE;
-
-static struct xpc_gru_mq_uv *xpc_activate_mq_uv;
-static struct xpc_gru_mq_uv *xpc_notify_mq_uv;
-
-static int
-xpc_setup_partitions_uv(void)
-{
-	short partid;
-	struct xpc_partition_uv *part_uv;
-
-	for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
-		part_uv = &xpc_partitions[partid].sn.uv;
-
-		mutex_init(&part_uv->cached_activate_gru_mq_desc_mutex);
-		spin_lock_init(&part_uv->flags_lock);
-		part_uv->remote_act_state = XPC_P_AS_INACTIVE;
-	}
-	return 0;
-}
-
-static void
-xpc_teardown_partitions_uv(void)
-{
-	short partid;
-	struct xpc_partition_uv *part_uv;
-	unsigned long irq_flags;
-
-	for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
-		part_uv = &xpc_partitions[partid].sn.uv;
-
-		if (part_uv->cached_activate_gru_mq_desc != NULL) {
-			mutex_lock(&part_uv->cached_activate_gru_mq_desc_mutex);
-			spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
-			part_uv->flags &= ~XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV;
-			spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
-			kfree(part_uv->cached_activate_gru_mq_desc);
-			part_uv->cached_activate_gru_mq_desc = NULL;
-			mutex_unlock(&part_uv->
-				     cached_activate_gru_mq_desc_mutex);
-		}
-	}
-}
-
-static int
-xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name)
-{
-	int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
-
-	mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset,
-			UV_AFFINITY_CPU);
-	if (mq->irq < 0)
-		return mq->irq;
-
-	mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset);
-
-	return 0;
-}
-
-static void
-xpc_release_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq)
-{
-	uv_teardown_irq(mq->irq);
-}
-
-static int
-xpc_gru_mq_watchlist_alloc_uv(struct xpc_gru_mq_uv *mq)
-{
-	int ret;
-
-	ret = uv_bios_mq_watchlist_alloc(uv_gpa(mq->address),
-					 mq->order, &mq->mmr_offset);
-	if (ret < 0) {
-		dev_err(xpc_part, "uv_bios_mq_watchlist_alloc() failed, "
-			"ret=%d\n", ret);
-		return ret;
-	}
-
-	mq->watchlist_num = ret;
-	return 0;
-}
-
-static void
-xpc_gru_mq_watchlist_free_uv(struct xpc_gru_mq_uv *mq)
-{
-	int ret;
-	int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
-
-	ret = uv_bios_mq_watchlist_free(mmr_pnode, mq->watchlist_num);
-	BUG_ON(ret != BIOS_STATUS_SUCCESS);
-}
-
-static struct xpc_gru_mq_uv *
-xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name,
-		     irq_handler_t irq_handler)
-{
-	enum xp_retval xp_ret;
-	int ret;
-	int nid;
-	int nasid;
-	int pg_order;
-	struct page *page;
-	struct xpc_gru_mq_uv *mq;
-	struct uv_IO_APIC_route_entry *mmr_value;
-
-	mq = kmalloc_obj(struct xpc_gru_mq_uv);
-	if (mq == NULL) {
-		dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() "
-			"a xpc_gru_mq_uv structure\n");
-		ret = -ENOMEM;
-		goto out_0;
-	}
-
-	mq->gru_mq_desc = kzalloc_obj(struct gru_message_queue_desc);
-	if (mq->gru_mq_desc == NULL) {
-		dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() "
-			"a gru_message_queue_desc structure\n");
-		ret = -ENOMEM;
-		goto out_1;
-	}
-
-	pg_order = get_order(mq_size);
-	mq->order = pg_order + PAGE_SHIFT;
-	mq_size = 1UL << mq->order;
-
-	mq->mmr_blade = uv_cpu_to_blade_id(cpu);
-
-	nid = cpu_to_node(cpu);
-	page = __alloc_pages_node(nid,
-				      GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE,
-				      pg_order);
-	if (page == NULL) {
-		dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "
-			"bytes of memory on nid=%d for GRU mq\n", mq_size, nid);
-		ret = -ENOMEM;
-		goto out_2;
-	}
-	mq->address = page_address(page);
-
-	/* enable generation of irq when GRU mq operation occurs to this mq */
-	ret = xpc_gru_mq_watchlist_alloc_uv(mq);
-	if (ret != 0)
-		goto out_3;
-
-	ret = xpc_get_gru_mq_irq_uv(mq, cpu, irq_name);
-	if (ret != 0)
-		goto out_4;
-
-	ret = request_irq(mq->irq, irq_handler, 0, irq_name, NULL);
-	if (ret != 0) {
-		dev_err(xpc_part, "request_irq(irq=%d) returned error=%d\n",
-			mq->irq, -ret);
-		goto out_5;
-	}
-
-	nasid = UV_PNODE_TO_NASID(uv_cpu_to_pnode(cpu));
-
-	mmr_value = (struct uv_IO_APIC_route_entry *)&mq->mmr_value;
-	ret = gru_create_message_queue(mq->gru_mq_desc, mq->address, mq_size,
-				     nasid, mmr_value->vector, mmr_value->dest);
-	if (ret != 0) {
-		dev_err(xpc_part, "gru_create_message_queue() returned "
-			"error=%d\n", ret);
-		ret = -EINVAL;
-		goto out_6;
-	}
-
-	/* allow other partitions to access this GRU mq */
-	xp_ret = xp_expand_memprotect(xp_pa(mq->address), mq_size);
-	if (xp_ret != xpSuccess) {
-		ret = -EACCES;
-		goto out_6;
-	}
-
-	return mq;
-
-	/* something went wrong */
-out_6:
-	free_irq(mq->irq, NULL);
-out_5:
-	xpc_release_gru_mq_irq_uv(mq);
-out_4:
-	xpc_gru_mq_watchlist_free_uv(mq);
-out_3:
-	free_pages((unsigned long)mq->address, pg_order);
-out_2:
-	kfree(mq->gru_mq_desc);
-out_1:
-	kfree(mq);
-out_0:
-	return ERR_PTR(ret);
-}
-
-static void
-xpc_destroy_gru_mq_uv(struct xpc_gru_mq_uv *mq)
-{
-	unsigned int mq_size;
-	int pg_order;
-	int ret;
-
-	/* disallow other partitions to access GRU mq */
-	mq_size = 1UL << mq->order;
-	ret = xp_restrict_memprotect(xp_pa(mq->address), mq_size);
-	BUG_ON(ret != xpSuccess);
-
-	/* unregister irq handler and release mq irq/vector mapping */
-	free_irq(mq->irq, NULL);
-	xpc_release_gru_mq_irq_uv(mq);
-
-	/* disable generation of irq when GRU mq op occurs to this mq */
-	xpc_gru_mq_watchlist_free_uv(mq);
-
-	pg_order = mq->order - PAGE_SHIFT;
-	free_pages((unsigned long)mq->address, pg_order);
-
-	kfree(mq);
-}
-
-static enum xp_retval
-xpc_send_gru_msg(struct gru_message_queue_desc *gru_mq_desc, void *msg,
-		 size_t msg_size)
-{
-	enum xp_retval xp_ret;
-	int ret;
-
-	while (1) {
-		ret = gru_send_message_gpa(gru_mq_desc, msg, msg_size);
-		if (ret == MQE_OK) {
-			xp_ret = xpSuccess;
-			break;
-		}
-
-		if (ret == MQE_QUEUE_FULL) {
-			dev_dbg(xpc_chan, "gru_send_message_gpa() returned "
-				"error=MQE_QUEUE_FULL\n");
-			/* !!! handle QLimit reached; delay & try again */
-			/* ??? Do we add a limit to the number of retries? */
-			(void)msleep_interruptible(10);
-		} else if (ret == MQE_CONGESTION) {
-			dev_dbg(xpc_chan, "gru_send_message_gpa() returned "
-				"error=MQE_CONGESTION\n");
-			/* !!! handle LB Overflow; simply try again */
-			/* ??? Do we add a limit to the number of retries? */
-		} else {
-			/* !!! Currently this is MQE_UNEXPECTED_CB_ERR */
-			dev_err(xpc_chan, "gru_send_message_gpa() returned "
-				"error=%d\n", ret);
-			xp_ret = xpGruSendMqError;
-			break;
-		}
-	}
-	return xp_ret;
-}
-
-static void
-xpc_process_activate_IRQ_rcvd_uv(void)
-{
-	unsigned long irq_flags;
-	short partid;
-	struct xpc_partition *part;
-	u8 act_state_req;
-
-	DBUG_ON(xpc_activate_IRQ_rcvd == 0);
-
-	spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-	for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
-		part = &xpc_partitions[partid];
-
-		if (part->sn.uv.act_state_req == 0)
-			continue;
-
-		xpc_activate_IRQ_rcvd--;
-		BUG_ON(xpc_activate_IRQ_rcvd < 0);
-
-		act_state_req = part->sn.uv.act_state_req;
-		part->sn.uv.act_state_req = 0;
-		spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-
-		if (act_state_req == XPC_P_ASR_ACTIVATE_UV) {
-			if (part->act_state == XPC_P_AS_INACTIVE)
-				xpc_activate_partition(part);
-			else if (part->act_state == XPC_P_AS_DEACTIVATING)
-				XPC_DEACTIVATE_PARTITION(part, xpReactivating);
-
-		} else if (act_state_req == XPC_P_ASR_REACTIVATE_UV) {
-			if (part->act_state == XPC_P_AS_INACTIVE)
-				xpc_activate_partition(part);
-			else
-				XPC_DEACTIVATE_PARTITION(part, xpReactivating);
-
-		} else if (act_state_req == XPC_P_ASR_DEACTIVATE_UV) {
-			XPC_DEACTIVATE_PARTITION(part, part->sn.uv.reason);
-
-		} else {
-			BUG();
-		}
-
-		spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-		if (xpc_activate_IRQ_rcvd == 0)
-			break;
-	}
-	spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-
-}
-
-static void
-xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
-			      struct xpc_activate_mq_msghdr_uv *msg_hdr,
-			      int part_setup,
-			      int *wakeup_hb_checker)
-{
-	unsigned long irq_flags;
-	struct xpc_partition_uv *part_uv = &part->sn.uv;
-	struct xpc_openclose_args *args;
-
-	part_uv->remote_act_state = msg_hdr->act_state;
-
-	switch (msg_hdr->type) {
-	case XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV:
-		/* syncing of remote_act_state was just done above */
-		break;
-
-	case XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV: {
-		struct xpc_activate_mq_msg_activate_req_uv *msg;
-
-		/*
-		 * ??? Do we deal here with ts_jiffies being different
-		 * ??? if act_state != XPC_P_AS_INACTIVE instead of
-		 * ??? below?
-		 */
-		msg = container_of(msg_hdr, struct
-				   xpc_activate_mq_msg_activate_req_uv, hdr);
-
-		spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-		if (part_uv->act_state_req == 0)
-			xpc_activate_IRQ_rcvd++;
-		part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV;
-		part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */
-		part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies;
-		part_uv->heartbeat_gpa = msg->heartbeat_gpa;
-
-		if (msg->activate_gru_mq_desc_gpa !=
-		    part_uv->activate_gru_mq_desc_gpa) {
-			spin_lock(&part_uv->flags_lock);
-			part_uv->flags &= ~XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV;
-			spin_unlock(&part_uv->flags_lock);
-			part_uv->activate_gru_mq_desc_gpa =
-			    msg->activate_gru_mq_desc_gpa;
-		}
-		spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-
-		(*wakeup_hb_checker)++;
-		break;
-	}
-	case XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV: {
-		struct xpc_activate_mq_msg_deactivate_req_uv *msg;
-
-		msg = container_of(msg_hdr, struct
-				   xpc_activate_mq_msg_deactivate_req_uv, hdr);
-
-		spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-		if (part_uv->act_state_req == 0)
-			xpc_activate_IRQ_rcvd++;
-		part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
-		part_uv->reason = msg->reason;
-		spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-
-		(*wakeup_hb_checker)++;
-		return;
-	}
-	case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: {
-		struct xpc_activate_mq_msg_chctl_closerequest_uv *msg;
-
-		if (!part_setup)
-			break;
-
-		msg = container_of(msg_hdr, struct
-				   xpc_activate_mq_msg_chctl_closerequest_uv,
-				   hdr);
-		args = &part->remote_openclose_args[msg->ch_number];
-		args->reason = msg->reason;
-
-		spin_lock_irqsave(&part->chctl_lock, irq_flags);
-		part->chctl.flags[msg->ch_number] |= XPC_CHCTL_CLOSEREQUEST;
-		spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
-
-		xpc_wakeup_channel_mgr(part);
-		break;
-	}
-	case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: {
-		struct xpc_activate_mq_msg_chctl_closereply_uv *msg;
-
-		if (!part_setup)
-			break;
-
-		msg = container_of(msg_hdr, struct
-				   xpc_activate_mq_msg_chctl_closereply_uv,
-				   hdr);
-
-		spin_lock_irqsave(&part->chctl_lock, irq_flags);
-		part->chctl.flags[msg->ch_number] |= XPC_CHCTL_CLOSEREPLY;
-		spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
-
-		xpc_wakeup_channel_mgr(part);
-		break;
-	}
-	case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: {
-		struct xpc_activate_mq_msg_chctl_openrequest_uv *msg;
-
-		if (!part_setup)
-			break;
-
-		msg = container_of(msg_hdr, struct
-				   xpc_activate_mq_msg_chctl_openrequest_uv,
-				   hdr);
-		args = &part->remote_openclose_args[msg->ch_number];
-		args->entry_size = msg->entry_size;
-		args->local_nentries = msg->local_nentries;
-
-		spin_lock_irqsave(&part->chctl_lock, irq_flags);
-		part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREQUEST;
-		spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
-
-		xpc_wakeup_channel_mgr(part);
-		break;
-	}
-	case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: {
-		struct xpc_activate_mq_msg_chctl_openreply_uv *msg;
-
-		if (!part_setup)
-			break;
-
-		msg = container_of(msg_hdr, struct
-				   xpc_activate_mq_msg_chctl_openreply_uv, hdr);
-		args = &part->remote_openclose_args[msg->ch_number];
-		args->remote_nentries = msg->remote_nentries;
-		args->local_nentries = msg->local_nentries;
-		args->local_msgqueue_pa = msg->notify_gru_mq_desc_gpa;
-
-		spin_lock_irqsave(&part->chctl_lock, irq_flags);
-		part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREPLY;
-		spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
-
-		xpc_wakeup_channel_mgr(part);
-		break;
-	}
-	case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV: {
-		struct xpc_activate_mq_msg_chctl_opencomplete_uv *msg;
-
-		if (!part_setup)
-			break;
-
-		msg = container_of(msg_hdr, struct
-				xpc_activate_mq_msg_chctl_opencomplete_uv, hdr);
-		spin_lock_irqsave(&part->chctl_lock, irq_flags);
-		part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENCOMPLETE;
-		spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
-
-		xpc_wakeup_channel_mgr(part);
-	}
-		fallthrough;
-	case XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV:
-		spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
-		part_uv->flags |= XPC_P_ENGAGED_UV;
-		spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
-		break;
-
-	case XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV:
-		spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
-		part_uv->flags &= ~XPC_P_ENGAGED_UV;
-		spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
-		break;
-
-	default:
-		dev_err(xpc_part, "received unknown activate_mq msg type=%d "
-			"from partition=%d\n", msg_hdr->type, XPC_PARTID(part));
-
-		/* get hb checker to deactivate from the remote partition */
-		spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-		if (part_uv->act_state_req == 0)
-			xpc_activate_IRQ_rcvd++;
-		part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
-		part_uv->reason = xpBadMsgType;
-		spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-
-		(*wakeup_hb_checker)++;
-		return;
-	}
-
-	if (msg_hdr->rp_ts_jiffies != part->remote_rp_ts_jiffies &&
-	    part->remote_rp_ts_jiffies != 0) {
-		/*
-		 * ??? Does what we do here need to be sensitive to
-		 * ??? act_state or remote_act_state?
-		 */
-		spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-		if (part_uv->act_state_req == 0)
-			xpc_activate_IRQ_rcvd++;
-		part_uv->act_state_req = XPC_P_ASR_REACTIVATE_UV;
-		spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-
-		(*wakeup_hb_checker)++;
-	}
-}
-
-static irqreturn_t
-xpc_handle_activate_IRQ_uv(int irq, void *dev_id)
-{
-	struct xpc_activate_mq_msghdr_uv *msg_hdr;
-	short partid;
-	struct xpc_partition *part;
-	int wakeup_hb_checker = 0;
-	int part_referenced;
-
-	while (1) {
-		msg_hdr = gru_get_next_message(xpc_activate_mq_uv->gru_mq_desc);
-		if (msg_hdr == NULL)
-			break;
-
-		partid = msg_hdr->partid;
-		if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) {
-			dev_err(xpc_part, "xpc_handle_activate_IRQ_uv() "
-				"received invalid partid=0x%x in message\n",
-				partid);
-		} else {
-			part = &xpc_partitions[partid];
-
-			part_referenced = xpc_part_ref(part);
-			xpc_handle_activate_mq_msg_uv(part, msg_hdr,
-						      part_referenced,
-						      &wakeup_hb_checker);
-			if (part_referenced)
-				xpc_part_deref(part);
-		}
-
-		gru_free_message(xpc_activate_mq_uv->gru_mq_desc, msg_hdr);
-	}
-
-	if (wakeup_hb_checker)
-		wake_up_interruptible(&xpc_activate_IRQ_wq);
-
-	return IRQ_HANDLED;
-}
-
-static enum xp_retval
-xpc_cache_remote_gru_mq_desc_uv(struct gru_message_queue_desc *gru_mq_desc,
-				unsigned long gru_mq_desc_gpa)
-{
-	enum xp_retval ret;
-
-	ret = xp_remote_memcpy(uv_gpa(gru_mq_desc), gru_mq_desc_gpa,
-			       sizeof(struct gru_message_queue_desc));
-	if (ret == xpSuccess)
-		gru_mq_desc->mq = NULL;
-
-	return ret;
-}
-
-static enum xp_retval
-xpc_send_activate_IRQ_uv(struct xpc_partition *part, void *msg, size_t msg_size,
-			 int msg_type)
-{
-	struct xpc_activate_mq_msghdr_uv *msg_hdr = msg;
-	struct xpc_partition_uv *part_uv = &part->sn.uv;
-	struct gru_message_queue_desc *gru_mq_desc;
-	unsigned long irq_flags;
-	enum xp_retval ret;
-
-	DBUG_ON(msg_size > XPC_ACTIVATE_MSG_SIZE_UV);
-
-	msg_hdr->type = msg_type;
-	msg_hdr->partid = xp_partition_id;
-	msg_hdr->act_state = part->act_state;
-	msg_hdr->rp_ts_jiffies = xpc_rsvd_page->ts_jiffies;
-
-	mutex_lock(&part_uv->cached_activate_gru_mq_desc_mutex);
-again:
-	if (!(part_uv->flags & XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV)) {
-		gru_mq_desc = part_uv->cached_activate_gru_mq_desc;
-		if (gru_mq_desc == NULL) {
-			gru_mq_desc = kmalloc_obj(struct gru_message_queue_desc,
-						  GFP_ATOMIC);
-			if (gru_mq_desc == NULL) {
-				ret = xpNoMemory;
-				goto done;
-			}
-			part_uv->cached_activate_gru_mq_desc = gru_mq_desc;
-		}
-
-		ret = xpc_cache_remote_gru_mq_desc_uv(gru_mq_desc,
-						      part_uv->
-						      activate_gru_mq_desc_gpa);
-		if (ret != xpSuccess)
-			goto done;
-
-		spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
-		part_uv->flags |= XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV;
-		spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
-	}
-
-	/* ??? Is holding a spin_lock (ch->lock) during this call a bad idea? */
-	ret = xpc_send_gru_msg(part_uv->cached_activate_gru_mq_desc, msg,
-			       msg_size);
-	if (ret != xpSuccess) {
-		smp_rmb();	/* ensure a fresh copy of part_uv->flags */
-		if (!(part_uv->flags & XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV))
-			goto again;
-	}
-done:
-	mutex_unlock(&part_uv->cached_activate_gru_mq_desc_mutex);
-	return ret;
-}
-
-static void
-xpc_send_activate_IRQ_part_uv(struct xpc_partition *part, void *msg,
-			      size_t msg_size, int msg_type)
-{
-	enum xp_retval ret;
-
-	ret = xpc_send_activate_IRQ_uv(part, msg, msg_size, msg_type);
-	if (unlikely(ret != xpSuccess))
-		XPC_DEACTIVATE_PARTITION(part, ret);
-}
-
-static void
-xpc_send_activate_IRQ_ch_uv(struct xpc_channel *ch, unsigned long *irq_flags,
-			 void *msg, size_t msg_size, int msg_type)
-{
-	struct xpc_partition *part = &xpc_partitions[ch->partid];
-	enum xp_retval ret;
-
-	ret = xpc_send_activate_IRQ_uv(part, msg, msg_size, msg_type);
-	if (unlikely(ret != xpSuccess)) {
-		if (irq_flags != NULL)
-			spin_unlock_irqrestore(&ch->lock, *irq_flags);
-
-		XPC_DEACTIVATE_PARTITION(part, ret);
-
-		if (irq_flags != NULL)
-			spin_lock_irqsave(&ch->lock, *irq_flags);
-	}
-}
-
-static void
-xpc_send_local_activate_IRQ_uv(struct xpc_partition *part, int act_state_req)
-{
-	unsigned long irq_flags;
-	struct xpc_partition_uv *part_uv = &part->sn.uv;
-
-	/*
-	 * !!! Make our side think that the remote partition sent an activate
-	 * !!! mq message our way by doing what the activate IRQ handler would
-	 * !!! do had one really been sent.
-	 */
-
-	spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-	if (part_uv->act_state_req == 0)
-		xpc_activate_IRQ_rcvd++;
-	part_uv->act_state_req = act_state_req;
-	spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-
-	wake_up_interruptible(&xpc_activate_IRQ_wq);
-}
-
-static enum xp_retval
-xpc_get_partition_rsvd_page_pa_uv(void *buf, u64 *cookie, unsigned long *rp_pa,
-				  size_t *len)
-{
-	s64 status;
-	enum xp_retval ret;
-
-	status = uv_bios_reserved_page_pa((u64)buf, cookie, (u64 *)rp_pa,
-					  (u64 *)len);
-	if (status == BIOS_STATUS_SUCCESS)
-		ret = xpSuccess;
-	else if (status == BIOS_STATUS_MORE_PASSES)
-		ret = xpNeedMoreInfo;
-	else
-		ret = xpBiosError;
-
-	return ret;
-}
-
-static int
-xpc_setup_rsvd_page_uv(struct xpc_rsvd_page *rp)
-{
-	xpc_heartbeat_uv =
-	    &xpc_partitions[sn_partition_id].sn.uv.cached_heartbeat;
-	rp->sn.uv.heartbeat_gpa = uv_gpa(xpc_heartbeat_uv);
-	rp->sn.uv.activate_gru_mq_desc_gpa =
-	    uv_gpa(xpc_activate_mq_uv->gru_mq_desc);
-	return 0;
-}
-
-static void
-xpc_allow_hb_uv(short partid)
-{
-}
-
-static void
-xpc_disallow_hb_uv(short partid)
-{
-}
-
-static void
-xpc_disallow_all_hbs_uv(void)
-{
-}
-
-static void
-xpc_increment_heartbeat_uv(void)
-{
-	xpc_heartbeat_uv->value++;
-}
-
-static void
-xpc_offline_heartbeat_uv(void)
-{
-	xpc_increment_heartbeat_uv();
-	xpc_heartbeat_uv->offline = 1;
-}
-
-static void
-xpc_online_heartbeat_uv(void)
-{
-	xpc_increment_heartbeat_uv();
-	xpc_heartbeat_uv->offline = 0;
-}
-
-static void
-xpc_heartbeat_init_uv(void)
-{
-	xpc_heartbeat_uv->value = 1;
-	xpc_heartbeat_uv->offline = 0;
-}
-
-static void
-xpc_heartbeat_exit_uv(void)
-{
-	xpc_offline_heartbeat_uv();
-}
-
-static enum xp_retval
-xpc_get_remote_heartbeat_uv(struct xpc_partition *part)
-{
-	struct xpc_partition_uv *part_uv = &part->sn.uv;
-	enum xp_retval ret;
-
-	ret = xp_remote_memcpy(uv_gpa(&part_uv->cached_heartbeat),
-			       part_uv->heartbeat_gpa,
-			       sizeof(struct xpc_heartbeat_uv));
-	if (ret != xpSuccess)
-		return ret;
-
-	if (part_uv->cached_heartbeat.value == part->last_heartbeat &&
-	    !part_uv->cached_heartbeat.offline) {
-
-		ret = xpNoHeartbeat;
-	} else {
-		part->last_heartbeat = part_uv->cached_heartbeat.value;
-	}
-	return ret;
-}
-
-static void
-xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp,
-				    unsigned long remote_rp_gpa, int nasid)
-{
-	short partid = remote_rp->SAL_partid;
-	struct xpc_partition *part = &xpc_partitions[partid];
-	struct xpc_activate_mq_msg_activate_req_uv msg;
-
-	part->remote_rp_pa = remote_rp_gpa; /* !!! _pa here is really _gpa */
-	part->remote_rp_ts_jiffies = remote_rp->ts_jiffies;
-	part->sn.uv.heartbeat_gpa = remote_rp->sn.uv.heartbeat_gpa;
-	part->sn.uv.activate_gru_mq_desc_gpa =
-	    remote_rp->sn.uv.activate_gru_mq_desc_gpa;
-
-	/*
-	 * ??? Is it a good idea to make this conditional on what is
-	 * ??? potentially stale state information?
-	 */
-	if (part->sn.uv.remote_act_state == XPC_P_AS_INACTIVE) {
-		msg.rp_gpa = uv_gpa(xpc_rsvd_page);
-		msg.heartbeat_gpa = xpc_rsvd_page->sn.uv.heartbeat_gpa;
-		msg.activate_gru_mq_desc_gpa =
-		    xpc_rsvd_page->sn.uv.activate_gru_mq_desc_gpa;
-		xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
-					   XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV);
-	}
-
-	if (part->act_state == XPC_P_AS_INACTIVE)
-		xpc_send_local_activate_IRQ_uv(part, XPC_P_ASR_ACTIVATE_UV);
-}
-
-static void
-xpc_request_partition_reactivation_uv(struct xpc_partition *part)
-{
-	xpc_send_local_activate_IRQ_uv(part, XPC_P_ASR_ACTIVATE_UV);
-}
-
-static void
-xpc_request_partition_deactivation_uv(struct xpc_partition *part)
-{
-	struct xpc_activate_mq_msg_deactivate_req_uv msg;
-
-	/*
-	 * ??? Is it a good idea to make this conditional on what is
-	 * ??? potentially stale state information?
-	 */
-	if (part->sn.uv.remote_act_state != XPC_P_AS_DEACTIVATING &&
-	    part->sn.uv.remote_act_state != XPC_P_AS_INACTIVE) {
-
-		msg.reason = part->reason;
-		xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
-					 XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV);
-	}
-}
-
-static void
-xpc_cancel_partition_deactivation_request_uv(struct xpc_partition *part)
-{
-	/* nothing needs to be done */
-	return;
-}
-
-static void
-xpc_init_fifo_uv(struct xpc_fifo_head_uv *head)
-{
-	head->first = NULL;
-	head->last = NULL;
-	spin_lock_init(&head->lock);
-	head->n_entries = 0;
-}
-
-static void *
-xpc_get_fifo_entry_uv(struct xpc_fifo_head_uv *head)
-{
-	unsigned long irq_flags;
-	struct xpc_fifo_entry_uv *first;
-
-	spin_lock_irqsave(&head->lock, irq_flags);
-	first = head->first;
-	if (head->first != NULL) {
-		head->first = first->next;
-		if (head->first == NULL)
-			head->last = NULL;
-
-		head->n_entries--;
-		BUG_ON(head->n_entries < 0);
-
-		first->next = NULL;
-	}
-	spin_unlock_irqrestore(&head->lock, irq_flags);
-	return first;
-}
-
-static void
-xpc_put_fifo_entry_uv(struct xpc_fifo_head_uv *head,
-		      struct xpc_fifo_entry_uv *last)
-{
-	unsigned long irq_flags;
-
-	last->next = NULL;
-	spin_lock_irqsave(&head->lock, irq_flags);
-	if (head->last != NULL)
-		head->last->next = last;
-	else
-		head->first = last;
-	head->last = last;
-	head->n_entries++;
-	spin_unlock_irqrestore(&head->lock, irq_flags);
-}
-
-static int
-xpc_n_of_fifo_entries_uv(struct xpc_fifo_head_uv *head)
-{
-	return head->n_entries;
-}
-
-/*
- * Setup the channel structures that are uv specific.
- */
-static enum xp_retval
-xpc_setup_ch_structures_uv(struct xpc_partition *part)
-{
-	struct xpc_channel_uv *ch_uv;
-	int ch_number;
-
-	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
-		ch_uv = &part->channels[ch_number].sn.uv;
-
-		xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
-		xpc_init_fifo_uv(&ch_uv->recv_msg_list);
-	}
-
-	return xpSuccess;
-}
-
-/*
- * Teardown the channel structures that are uv specific.
- */
-static void
-xpc_teardown_ch_structures_uv(struct xpc_partition *part)
-{
-	/* nothing needs to be done */
-	return;
-}
-
-static enum xp_retval
-xpc_make_first_contact_uv(struct xpc_partition *part)
-{
-	struct xpc_activate_mq_msg_uv msg;
-
-	/*
-	 * We send a sync msg to get the remote partition's remote_act_state
-	 * updated to our current act_state which at this point should
-	 * be XPC_P_AS_ACTIVATING.
-	 */
-	xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
-				      XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV);
-
-	while (!((part->sn.uv.remote_act_state == XPC_P_AS_ACTIVATING) ||
-		 (part->sn.uv.remote_act_state == XPC_P_AS_ACTIVE))) {
-
-		dev_dbg(xpc_part, "waiting to make first contact with "
-			"partition %d\n", XPC_PARTID(part));
-
-		/* wait a 1/4 of a second or so */
-		(void)msleep_interruptible(250);
-
-		if (part->act_state == XPC_P_AS_DEACTIVATING)
-			return part->reason;
-	}
-
-	return xpSuccess;
-}
-
-static u64
-xpc_get_chctl_all_flags_uv(struct xpc_partition *part)
-{
-	unsigned long irq_flags;
-	union xpc_channel_ctl_flags chctl;
-
-	spin_lock_irqsave(&part->chctl_lock, irq_flags);
-	chctl = part->chctl;
-	if (chctl.all_flags != 0)
-		part->chctl.all_flags = 0;
-
-	spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
-	return chctl.all_flags;
-}
-
-static enum xp_retval
-xpc_allocate_send_msg_slot_uv(struct xpc_channel *ch)
-{
-	struct xpc_channel_uv *ch_uv = &ch->sn.uv;
-	struct xpc_send_msg_slot_uv *msg_slot;
-	unsigned long irq_flags;
-	int nentries;
-	int entry;
-	size_t nbytes;
-
-	for (nentries = ch->local_nentries; nentries > 0; nentries--) {
-		nbytes = nentries * sizeof(struct xpc_send_msg_slot_uv);
-		ch_uv->send_msg_slots = kzalloc(nbytes, GFP_KERNEL);
-		if (ch_uv->send_msg_slots == NULL)
-			continue;
-
-		for (entry = 0; entry < nentries; entry++) {
-			msg_slot = &ch_uv->send_msg_slots[entry];
-
-			msg_slot->msg_slot_number = entry;
-			xpc_put_fifo_entry_uv(&ch_uv->msg_slot_free_list,
-					      &msg_slot->next);
-		}
-
-		spin_lock_irqsave(&ch->lock, irq_flags);
-		if (nentries < ch->local_nentries)
-			ch->local_nentries = nentries;
-		spin_unlock_irqrestore(&ch->lock, irq_flags);
-		return xpSuccess;
-	}
-
-	return xpNoMemory;
-}
-
-static enum xp_retval
-xpc_allocate_recv_msg_slot_uv(struct xpc_channel *ch)
-{
-	struct xpc_channel_uv *ch_uv = &ch->sn.uv;
-	struct xpc_notify_mq_msg_uv *msg_slot;
-	unsigned long irq_flags;
-	int nentries;
-	int entry;
-	size_t nbytes;
-
-	for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
-		nbytes = nentries * ch->entry_size;
-		ch_uv->recv_msg_slots = kzalloc(nbytes, GFP_KERNEL);
-		if (ch_uv->recv_msg_slots == NULL)
-			continue;
-
-		for (entry = 0; entry < nentries; entry++) {
-			msg_slot = ch_uv->recv_msg_slots +
-			    entry * ch->entry_size;
-
-			msg_slot->hdr.msg_slot_number = entry;
-		}
-
-		spin_lock_irqsave(&ch->lock, irq_flags);
-		if (nentries < ch->remote_nentries)
-			ch->remote_nentries = nentries;
-		spin_unlock_irqrestore(&ch->lock, irq_flags);
-		return xpSuccess;
-	}
-
-	return xpNoMemory;
-}
-
-/*
- * Allocate msg_slots associated with the channel.
- */
-static enum xp_retval
-xpc_setup_msg_structures_uv(struct xpc_channel *ch)
-{
-	static enum xp_retval ret;
-	struct xpc_channel_uv *ch_uv = &ch->sn.uv;
-
-	DBUG_ON(ch->flags & XPC_C_SETUP);
-
-	ch_uv->cached_notify_gru_mq_desc = kmalloc_obj(struct gru_message_queue_desc);
-	if (ch_uv->cached_notify_gru_mq_desc == NULL)
-		return xpNoMemory;
-
-	ret = xpc_allocate_send_msg_slot_uv(ch);
-	if (ret == xpSuccess) {
-
-		ret = xpc_allocate_recv_msg_slot_uv(ch);
-		if (ret != xpSuccess) {
-			kfree(ch_uv->send_msg_slots);
-			xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
-		}
-	}
-	return ret;
-}
-
-/*
- * Free up msg_slots and clear other stuff that were setup for the specified
- * channel.
- */
-static void
-xpc_teardown_msg_structures_uv(struct xpc_channel *ch)
-{
-	struct xpc_channel_uv *ch_uv = &ch->sn.uv;
-
-	lockdep_assert_held(&ch->lock);
-
-	kfree(ch_uv->cached_notify_gru_mq_desc);
-	ch_uv->cached_notify_gru_mq_desc = NULL;
-
-	if (ch->flags & XPC_C_SETUP) {
-		xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
-		kfree(ch_uv->send_msg_slots);
-		xpc_init_fifo_uv(&ch_uv->recv_msg_list);
-		kfree(ch_uv->recv_msg_slots);
-	}
-}
-
-static void
-xpc_send_chctl_closerequest_uv(struct xpc_channel *ch, unsigned long *irq_flags)
-{
-	struct xpc_activate_mq_msg_chctl_closerequest_uv msg;
-
-	msg.ch_number = ch->number;
-	msg.reason = ch->reason;
-	xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
-				    XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV);
-}
-
-static void
-xpc_send_chctl_closereply_uv(struct xpc_channel *ch, unsigned long *irq_flags)
-{
-	struct xpc_activate_mq_msg_chctl_closereply_uv msg;
-
-	msg.ch_number = ch->number;
-	xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
-				    XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV);
-}
-
-static void
-xpc_send_chctl_openrequest_uv(struct xpc_channel *ch, unsigned long *irq_flags)
-{
-	struct xpc_activate_mq_msg_chctl_openrequest_uv msg;
-
-	msg.ch_number = ch->number;
-	msg.entry_size = ch->entry_size;
-	msg.local_nentries = ch->local_nentries;
-	xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
-				    XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV);
-}
-
-static void
-xpc_send_chctl_openreply_uv(struct xpc_channel *ch, unsigned long *irq_flags)
-{
-	struct xpc_activate_mq_msg_chctl_openreply_uv msg;
-
-	msg.ch_number = ch->number;
-	msg.local_nentries = ch->local_nentries;
-	msg.remote_nentries = ch->remote_nentries;
-	msg.notify_gru_mq_desc_gpa = uv_gpa(xpc_notify_mq_uv->gru_mq_desc);
-	xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
-				    XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV);
-}
-
-static void
-xpc_send_chctl_opencomplete_uv(struct xpc_channel *ch, unsigned long *irq_flags)
-{
-	struct xpc_activate_mq_msg_chctl_opencomplete_uv msg;
-
-	msg.ch_number = ch->number;
-	xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
-				    XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV);
-}
-
-static void
-xpc_send_chctl_local_msgrequest_uv(struct xpc_partition *part, int ch_number)
-{
-	unsigned long irq_flags;
-
-	spin_lock_irqsave(&part->chctl_lock, irq_flags);
-	part->chctl.flags[ch_number] |= XPC_CHCTL_MSGREQUEST;
-	spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
-
-	xpc_wakeup_channel_mgr(part);
-}
-
-static enum xp_retval
-xpc_save_remote_msgqueue_pa_uv(struct xpc_channel *ch,
-			       unsigned long gru_mq_desc_gpa)
-{
-	struct xpc_channel_uv *ch_uv = &ch->sn.uv;
-
-	DBUG_ON(ch_uv->cached_notify_gru_mq_desc == NULL);
-	return xpc_cache_remote_gru_mq_desc_uv(ch_uv->cached_notify_gru_mq_desc,
-					       gru_mq_desc_gpa);
-}
-
-static void
-xpc_indicate_partition_engaged_uv(struct xpc_partition *part)
-{
-	struct xpc_activate_mq_msg_uv msg;
-
-	xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
-				      XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV);
-}
-
-static void
-xpc_indicate_partition_disengaged_uv(struct xpc_partition *part)
-{
-	struct xpc_activate_mq_msg_uv msg;
-
-	xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
-				      XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV);
-}
-
-static void
-xpc_assume_partition_disengaged_uv(short partid)
-{
-	struct xpc_partition_uv *part_uv = &xpc_partitions[partid].sn.uv;
-	unsigned long irq_flags;
-
-	spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
-	part_uv->flags &= ~XPC_P_ENGAGED_UV;
-	spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
-}
-
-static int
-xpc_partition_engaged_uv(short partid)
-{
-	return (xpc_partitions[partid].sn.uv.flags & XPC_P_ENGAGED_UV) != 0;
-}
-
-static int
-xpc_any_partition_engaged_uv(void)
-{
-	struct xpc_partition_uv *part_uv;
-	short partid;
-
-	for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
-		part_uv = &xpc_partitions[partid].sn.uv;
-		if ((part_uv->flags & XPC_P_ENGAGED_UV) != 0)
-			return 1;
-	}
-	return 0;
-}
-
-static enum xp_retval
-xpc_allocate_msg_slot_uv(struct xpc_channel *ch, u32 flags,
-			 struct xpc_send_msg_slot_uv **address_of_msg_slot)
-{
-	enum xp_retval ret;
-	struct xpc_send_msg_slot_uv *msg_slot;
-	struct xpc_fifo_entry_uv *entry;
-
-	while (1) {
-		entry = xpc_get_fifo_entry_uv(&ch->sn.uv.msg_slot_free_list);
-		if (entry != NULL)
-			break;
-
-		if (flags & XPC_NOWAIT)
-			return xpNoWait;
-
-		ret = xpc_allocate_msg_wait(ch);
-		if (ret != xpInterrupted && ret != xpTimeout)
-			return ret;
-	}
-
-	msg_slot = container_of(entry, struct xpc_send_msg_slot_uv, next);
-	*address_of_msg_slot = msg_slot;
-	return xpSuccess;
-}
-
-static void
-xpc_free_msg_slot_uv(struct xpc_channel *ch,
-		     struct xpc_send_msg_slot_uv *msg_slot)
-{
-	xpc_put_fifo_entry_uv(&ch->sn.uv.msg_slot_free_list, &msg_slot->next);
-
-	/* wakeup anyone waiting for a free msg slot */
-	if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
-		wake_up(&ch->msg_allocate_wq);
-}
-
-static void
-xpc_notify_sender_uv(struct xpc_channel *ch,
-		     struct xpc_send_msg_slot_uv *msg_slot,
-		     enum xp_retval reason)
-{
-	xpc_notify_func func = msg_slot->func;
-
-	if (func != NULL && cmpxchg(&msg_slot->func, func, NULL) == func) {
-
-		atomic_dec(&ch->n_to_notify);
-
-		dev_dbg(xpc_chan, "msg_slot->func() called, msg_slot=0x%p "
-			"msg_slot_number=%d partid=%d channel=%d\n", msg_slot,
-			msg_slot->msg_slot_number, ch->partid, ch->number);
-
-		func(reason, ch->partid, ch->number, msg_slot->key);
-
-		dev_dbg(xpc_chan, "msg_slot->func() returned, msg_slot=0x%p "
-			"msg_slot_number=%d partid=%d channel=%d\n", msg_slot,
-			msg_slot->msg_slot_number, ch->partid, ch->number);
-	}
-}
-
-static void
-xpc_handle_notify_mq_ack_uv(struct xpc_channel *ch,
-			    struct xpc_notify_mq_msg_uv *msg)
-{
-	struct xpc_send_msg_slot_uv *msg_slot;
-	int entry = msg->hdr.msg_slot_number % ch->local_nentries;
-
-	msg_slot = &ch->sn.uv.send_msg_slots[entry];
-
-	BUG_ON(msg_slot->msg_slot_number != msg->hdr.msg_slot_number);
-	msg_slot->msg_slot_number += ch->local_nentries;
-
-	if (msg_slot->func != NULL)
-		xpc_notify_sender_uv(ch, msg_slot, xpMsgDelivered);
-
-	xpc_free_msg_slot_uv(ch, msg_slot);
-}
-
-static void
-xpc_handle_notify_mq_msg_uv(struct xpc_partition *part,
-			    struct xpc_notify_mq_msg_uv *msg)
-{
-	struct xpc_partition_uv *part_uv = &part->sn.uv;
-	struct xpc_channel *ch;
-	struct xpc_channel_uv *ch_uv;
-	struct xpc_notify_mq_msg_uv *msg_slot;
-	unsigned long irq_flags;
-	int ch_number = msg->hdr.ch_number;
-
-	if (unlikely(ch_number >= part->nchannels)) {
-		dev_err(xpc_part, "xpc_handle_notify_IRQ_uv() received invalid "
-			"channel number=0x%x in message from partid=%d\n",
-			ch_number, XPC_PARTID(part));
-
-		/* get hb checker to deactivate from the remote partition */
-		spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-		if (part_uv->act_state_req == 0)
-			xpc_activate_IRQ_rcvd++;
-		part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
-		part_uv->reason = xpBadChannelNumber;
-		spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
-
-		wake_up_interruptible(&xpc_activate_IRQ_wq);
-		return;
-	}
-
-	ch = &part->channels[ch_number];
-	xpc_msgqueue_ref(ch);
-
-	if (!(ch->flags & XPC_C_CONNECTED)) {
-		xpc_msgqueue_deref(ch);
-		return;
-	}
-
-	/* see if we're really dealing with an ACK for a previously sent msg */
-	if (msg->hdr.size == 0) {
-		xpc_handle_notify_mq_ack_uv(ch, msg);
-		xpc_msgqueue_deref(ch);
-		return;
-	}
-
-	/* we're dealing with a normal message sent via the notify_mq */
-	ch_uv = &ch->sn.uv;
-
-	msg_slot = ch_uv->recv_msg_slots +
-	    (msg->hdr.msg_slot_number % ch->remote_nentries) * ch->entry_size;
-
-	BUG_ON(msg_slot->hdr.size != 0);
-
-	memcpy(msg_slot, msg, msg->hdr.size);
-
-	xpc_put_fifo_entry_uv(&ch_uv->recv_msg_list, &msg_slot->hdr.u.next);
-
-	if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) {
-		/*
-		 * If there is an existing idle kthread get it to deliver
-		 * the payload, otherwise we'll have to get the channel mgr
-		 * for this partition to create a kthread to do the delivery.
-		 */
-		if (atomic_read(&ch->kthreads_idle) > 0)
-			wake_up_nr(&ch->idle_wq, 1);
-		else
-			xpc_send_chctl_local_msgrequest_uv(part, ch->number);
-	}
-	xpc_msgqueue_deref(ch);
-}
-
-static irqreturn_t
-xpc_handle_notify_IRQ_uv(int irq, void *dev_id)
-{
-	struct xpc_notify_mq_msg_uv *msg;
-	short partid;
-	struct xpc_partition *part;
-
-	while ((msg = gru_get_next_message(xpc_notify_mq_uv->gru_mq_desc)) !=
-	       NULL) {
-
-		partid = msg->hdr.partid;
-		if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) {
-			dev_err(xpc_part, "xpc_handle_notify_IRQ_uv() received "
-				"invalid partid=0x%x in message\n", partid);
-		} else {
-			part = &xpc_partitions[partid];
-
-			if (xpc_part_ref(part)) {
-				xpc_handle_notify_mq_msg_uv(part, msg);
-				xpc_part_deref(part);
-			}
-		}
-
-		gru_free_message(xpc_notify_mq_uv->gru_mq_desc, msg);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int
-xpc_n_of_deliverable_payloads_uv(struct xpc_channel *ch)
-{
-	return xpc_n_of_fifo_entries_uv(&ch->sn.uv.recv_msg_list);
-}
-
-static void
-xpc_process_msg_chctl_flags_uv(struct xpc_partition *part, int ch_number)
-{
-	struct xpc_channel *ch = &part->channels[ch_number];
-	int ndeliverable_payloads;
-
-	xpc_msgqueue_ref(ch);
-
-	ndeliverable_payloads = xpc_n_of_deliverable_payloads_uv(ch);
-
-	if (ndeliverable_payloads > 0 &&
-	    (ch->flags & XPC_C_CONNECTED) &&
-	    (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE)) {
-
-		xpc_activate_kthreads(ch, ndeliverable_payloads);
-	}
-
-	xpc_msgqueue_deref(ch);
-}
-
-static enum xp_retval
-xpc_send_payload_uv(struct xpc_channel *ch, u32 flags, void *payload,
-		    u16 payload_size, u8 notify_type, xpc_notify_func func,
-		    void *key)
-{
-	enum xp_retval ret = xpSuccess;
-	struct xpc_send_msg_slot_uv *msg_slot = NULL;
-	struct xpc_notify_mq_msg_uv *msg;
-	u8 msg_buffer[XPC_NOTIFY_MSG_SIZE_UV];
-	size_t msg_size;
-
-	DBUG_ON(notify_type != XPC_N_CALL);
-
-	msg_size = sizeof(struct xpc_notify_mq_msghdr_uv) + payload_size;
-	if (msg_size > ch->entry_size)
-		return xpPayloadTooBig;
-
-	xpc_msgqueue_ref(ch);
-
-	if (ch->flags & XPC_C_DISCONNECTING) {
-		ret = ch->reason;
-		goto out_1;
-	}
-	if (!(ch->flags & XPC_C_CONNECTED)) {
-		ret = xpNotConnected;
-		goto out_1;
-	}
-
-	ret = xpc_allocate_msg_slot_uv(ch, flags, &msg_slot);
-	if (ret != xpSuccess)
-		goto out_1;
-
-	if (func != NULL) {
-		atomic_inc(&ch->n_to_notify);
-
-		msg_slot->key = key;
-		smp_wmb(); /* a non-NULL func must hit memory after the key */
-		msg_slot->func = func;
-
-		if (ch->flags & XPC_C_DISCONNECTING) {
-			ret = ch->reason;
-			goto out_2;
-		}
-	}
-
-	msg = (struct xpc_notify_mq_msg_uv *)&msg_buffer;
-	msg->hdr.partid = xp_partition_id;
-	msg->hdr.ch_number = ch->number;
-	msg->hdr.size = msg_size;
-	msg->hdr.msg_slot_number = msg_slot->msg_slot_number;
-	memcpy(&msg->payload, payload, payload_size);
-
-	ret = xpc_send_gru_msg(ch->sn.uv.cached_notify_gru_mq_desc, msg,
-			       msg_size);
-	if (ret == xpSuccess)
-		goto out_1;
-
-	XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret);
-out_2:
-	if (func != NULL) {
-		/*
-		 * Try to NULL the msg_slot's func field. If we fail, then
-		 * xpc_notify_senders_of_disconnect_uv() beat us to it, in which
-		 * case we need to pretend we succeeded to send the message
-		 * since the user will get a callout for the disconnect error
-		 * by xpc_notify_senders_of_disconnect_uv(), and to also get an
-		 * error returned here will confuse them. Additionally, since
-		 * in this case the channel is being disconnected we don't need
-		 * to put the msg_slot back on the free list.
-		 */
-		if (cmpxchg(&msg_slot->func, func, NULL) != func) {
-			ret = xpSuccess;
-			goto out_1;
-		}
-
-		msg_slot->key = NULL;
-		atomic_dec(&ch->n_to_notify);
-	}
-	xpc_free_msg_slot_uv(ch, msg_slot);
-out_1:
-	xpc_msgqueue_deref(ch);
-	return ret;
-}
-
-/*
- * Tell the callers of xpc_send_notify() that the status of their payloads
- * is unknown because the channel is now disconnecting.
- *
- * We don't worry about putting these msg_slots on the free list since the
- * msg_slots themselves are about to be kfree'd.
- */
-static void
-xpc_notify_senders_of_disconnect_uv(struct xpc_channel *ch)
-{
-	struct xpc_send_msg_slot_uv *msg_slot;
-	int entry;
-
-	DBUG_ON(!(ch->flags & XPC_C_DISCONNECTING));
-
-	for (entry = 0; entry < ch->local_nentries; entry++) {
-
-		if (atomic_read(&ch->n_to_notify) == 0)
-			break;
-
-		msg_slot = &ch->sn.uv.send_msg_slots[entry];
-		if (msg_slot->func != NULL)
-			xpc_notify_sender_uv(ch, msg_slot, ch->reason);
-	}
-}
-
-/*
- * Get the next deliverable message's payload.
- */
-static void *
-xpc_get_deliverable_payload_uv(struct xpc_channel *ch)
-{
-	struct xpc_fifo_entry_uv *entry;
-	struct xpc_notify_mq_msg_uv *msg;
-	void *payload = NULL;
-
-	if (!(ch->flags & XPC_C_DISCONNECTING)) {
-		entry = xpc_get_fifo_entry_uv(&ch->sn.uv.recv_msg_list);
-		if (entry != NULL) {
-			msg = container_of(entry, struct xpc_notify_mq_msg_uv,
-					   hdr.u.next);
-			payload = &msg->payload;
-		}
-	}
-	return payload;
-}
-
-static void
-xpc_received_payload_uv(struct xpc_channel *ch, void *payload)
-{
-	struct xpc_notify_mq_msg_uv *msg;
-	enum xp_retval ret;
-
-	msg = container_of(payload, struct xpc_notify_mq_msg_uv, payload);
-
-	/* return an ACK to the sender of this message */
-
-	msg->hdr.partid = xp_partition_id;
-	msg->hdr.size = 0;	/* size of zero indicates this is an ACK */
-
-	ret = xpc_send_gru_msg(ch->sn.uv.cached_notify_gru_mq_desc, msg,
-			       sizeof(struct xpc_notify_mq_msghdr_uv));
-	if (ret != xpSuccess)
-		XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret);
-}
-
-static const struct xpc_arch_operations xpc_arch_ops_uv = {
-	.setup_partitions = xpc_setup_partitions_uv,
-	.teardown_partitions = xpc_teardown_partitions_uv,
-	.process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv,
-	.get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv,
-	.setup_rsvd_page = xpc_setup_rsvd_page_uv,
-
-	.allow_hb = xpc_allow_hb_uv,
-	.disallow_hb = xpc_disallow_hb_uv,
-	.disallow_all_hbs = xpc_disallow_all_hbs_uv,
-	.increment_heartbeat = xpc_increment_heartbeat_uv,
-	.offline_heartbeat = xpc_offline_heartbeat_uv,
-	.online_heartbeat = xpc_online_heartbeat_uv,
-	.heartbeat_init = xpc_heartbeat_init_uv,
-	.heartbeat_exit = xpc_heartbeat_exit_uv,
-	.get_remote_heartbeat = xpc_get_remote_heartbeat_uv,
-
-	.request_partition_activation =
-		xpc_request_partition_activation_uv,
-	.request_partition_reactivation =
-		xpc_request_partition_reactivation_uv,
-	.request_partition_deactivation =
-		xpc_request_partition_deactivation_uv,
-	.cancel_partition_deactivation_request =
-		xpc_cancel_partition_deactivation_request_uv,
-
-	.setup_ch_structures = xpc_setup_ch_structures_uv,
-	.teardown_ch_structures = xpc_teardown_ch_structures_uv,
-
-	.make_first_contact = xpc_make_first_contact_uv,
-
-	.get_chctl_all_flags = xpc_get_chctl_all_flags_uv,
-	.send_chctl_closerequest = xpc_send_chctl_closerequest_uv,
-	.send_chctl_closereply = xpc_send_chctl_closereply_uv,
-	.send_chctl_openrequest = xpc_send_chctl_openrequest_uv,
-	.send_chctl_openreply = xpc_send_chctl_openreply_uv,
-	.send_chctl_opencomplete = xpc_send_chctl_opencomplete_uv,
-	.process_msg_chctl_flags = xpc_process_msg_chctl_flags_uv,
-
-	.save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_uv,
-
-	.setup_msg_structures = xpc_setup_msg_structures_uv,
-	.teardown_msg_structures = xpc_teardown_msg_structures_uv,
-
-	.indicate_partition_engaged = xpc_indicate_partition_engaged_uv,
-	.indicate_partition_disengaged = xpc_indicate_partition_disengaged_uv,
-	.assume_partition_disengaged = xpc_assume_partition_disengaged_uv,
-	.partition_engaged = xpc_partition_engaged_uv,
-	.any_partition_engaged = xpc_any_partition_engaged_uv,
-
-	.n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_uv,
-	.send_payload = xpc_send_payload_uv,
-	.get_deliverable_payload = xpc_get_deliverable_payload_uv,
-	.received_payload = xpc_received_payload_uv,
-	.notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv,
-};
-
-static int
-xpc_init_mq_node(int nid)
-{
-	int cpu;
-
-	cpus_read_lock();
-
-	for_each_cpu(cpu, cpumask_of_node(nid)) {
-		xpc_activate_mq_uv =
-			xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, nid,
-					     XPC_ACTIVATE_IRQ_NAME,
-					     xpc_handle_activate_IRQ_uv);
-		if (!IS_ERR(xpc_activate_mq_uv))
-			break;
-	}
-	if (IS_ERR(xpc_activate_mq_uv)) {
-		cpus_read_unlock();
-		return PTR_ERR(xpc_activate_mq_uv);
-	}
-
-	for_each_cpu(cpu, cpumask_of_node(nid)) {
-		xpc_notify_mq_uv =
-			xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, nid,
-					     XPC_NOTIFY_IRQ_NAME,
-					     xpc_handle_notify_IRQ_uv);
-		if (!IS_ERR(xpc_notify_mq_uv))
-			break;
-	}
-	if (IS_ERR(xpc_notify_mq_uv)) {
-		xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
-		cpus_read_unlock();
-		return PTR_ERR(xpc_notify_mq_uv);
-	}
-
-	cpus_read_unlock();
-	return 0;
-}
-
-int
-xpc_init_uv(void)
-{
-	int nid;
-	int ret = 0;
-
-	xpc_arch_ops = xpc_arch_ops_uv;
-
-	if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) {
-		dev_err(xpc_part, "xpc_notify_mq_msghdr_uv is larger than %d\n",
-			XPC_MSG_HDR_MAX_SIZE);
-		return -E2BIG;
-	}
-
-	if (xpc_mq_node < 0)
-		for_each_online_node(nid) {
-			ret = xpc_init_mq_node(nid);
-
-			if (!ret)
-				break;
-		}
-	else
-		ret = xpc_init_mq_node(xpc_mq_node);
-
-	if (ret < 0)
-		dev_err(xpc_part, "xpc_init_mq_node() returned error=%d\n",
-			-ret);
-
-	return ret;
-}
-
-void
-xpc_exit_uv(void)
-{
-	xpc_destroy_gru_mq_uv(xpc_notify_mq_uv);
-	xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
-}
-
-module_param(xpc_mq_node, int, 0);
-MODULE_PARM_DESC(xpc_mq_node, "Node number on which to allocate message queues.");
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
deleted file mode 100644
index 1533b72d57b1..000000000000
--- a/drivers/misc/sgi-xp/xpnet.c
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * 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.
- *
- * (C) Copyright 2020 Hewlett Packard Enterprise Development LP
- * Copyright (C) 1999-2009 Silicon Graphics, Inc. All rights reserved.
- */
-
-/*
- * Cross Partition Network Interface (XPNET) support
- *
- *	XPNET provides a virtual network layered on top of the Cross
- *	Partition communication layer.
- *
- *	XPNET provides direct point-to-point and broadcast-like support
- *	for an ethernet-like device.  The ethernet broadcast medium is
- *	replaced with a point-to-point message structure which passes
- *	pointers to a DMA-capable block that a remote partition should
- *	retrieve and pass to the upper level networking layer.
- *
- */
-
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include "xp.h"
-
-/*
- * The message payload transferred by XPC.
- *
- * buf_pa is the physical address where the DMA should pull from.
- *
- * NOTE: for performance reasons, buf_pa should _ALWAYS_ begin on a
- * cacheline boundary.  To accomplish this, we record the number of
- * bytes from the beginning of the first cacheline to the first useful
- * byte of the skb (leadin_ignore) and the number of bytes from the
- * last useful byte of the skb to the end of the last cacheline
- * (tailout_ignore).
- *
- * size is the number of bytes to transfer which includes the skb->len
- * (useful bytes of the senders skb) plus the leadin and tailout
- */
-struct xpnet_message {
-	u16 version;		/* Version for this message */
-	u16 embedded_bytes;	/* #of bytes embedded in XPC message */
-	u32 magic;		/* Special number indicating this is xpnet */
-	unsigned long buf_pa;	/* phys address of buffer to retrieve */
-	u32 size;		/* #of bytes in buffer */
-	u8 leadin_ignore;	/* #of bytes to ignore at the beginning */
-	u8 tailout_ignore;	/* #of bytes to ignore at the end */
-	unsigned char data;	/* body of small packets */
-};
-
-/*
- * Determine the size of our message, the cacheline aligned size,
- * and then the number of message will request from XPC.
- *
- * XPC expects each message to exist in an individual cacheline.
- */
-#define XPNET_MSG_SIZE		XPC_MSG_PAYLOAD_MAX_SIZE
-#define XPNET_MSG_DATA_MAX	\
-		(XPNET_MSG_SIZE - offsetof(struct xpnet_message, data))
-#define XPNET_MSG_NENTRIES	(PAGE_SIZE / XPC_MSG_MAX_SIZE)
-
-#define XPNET_MAX_KTHREADS	(XPNET_MSG_NENTRIES + 1)
-#define XPNET_MAX_IDLE_KTHREADS	(XPNET_MSG_NENTRIES + 1)
-
-/*
- * Version number of XPNET implementation. XPNET can always talk to versions
- * with same major #, and never talk to versions with a different version.
- */
-#define _XPNET_VERSION(_major, _minor)	(((_major) << 4) | (_minor))
-#define XPNET_VERSION_MAJOR(_v)		((_v) >> 4)
-#define XPNET_VERSION_MINOR(_v)		((_v) & 0xf)
-
-#define	XPNET_VERSION _XPNET_VERSION(1, 0)	/* version 1.0 */
-#define	XPNET_VERSION_EMBED _XPNET_VERSION(1, 1)	/* version 1.1 */
-#define XPNET_MAGIC	0x88786984	/* "XNET" */
-
-#define XPNET_VALID_MSG(_m)						     \
-   ((XPNET_VERSION_MAJOR(_m->version) == XPNET_VERSION_MAJOR(XPNET_VERSION)) \
-    && (msg->magic == XPNET_MAGIC))
-
-#define XPNET_DEVICE_NAME		"xp0"
-
-/*
- * When messages are queued with xpc_send_notify, a kmalloc'd buffer
- * of the following type is passed as a notification cookie.  When the
- * notification function is called, we use the cookie to decide
- * whether all outstanding message sends have completed.  The skb can
- * then be released.
- */
-struct xpnet_pending_msg {
-	struct sk_buff *skb;
-	atomic_t use_count;
-};
-
-static struct net_device *xpnet_device;
-
-/*
- * When we are notified of other partitions activating, we add them to
- * our bitmask of partitions to which we broadcast.
- */
-static unsigned long *xpnet_broadcast_partitions;
-/* protect above */
-static DEFINE_SPINLOCK(xpnet_broadcast_lock);
-
-/*
- * Since the Block Transfer Engine (BTE) is being used for the transfer
- * and it relies upon cache-line size transfers, we need to reserve at
- * least one cache-line for head and tail alignment.  The BTE is
- * limited to 8MB transfers.
- *
- * Testing has shown that changing MTU to greater than 64KB has no effect
- * on TCP as the two sides negotiate a Max Segment Size that is limited
- * to 64K.  Other protocols May use packets greater than this, but for
- * now, the default is 64KB.
- */
-#define XPNET_MAX_MTU (0x800000UL - L1_CACHE_BYTES)
-/* 68 comes from min TCP+IP+MAC header */
-#define XPNET_MIN_MTU 68
-/* 32KB has been determined to be the ideal */
-#define XPNET_DEF_MTU (0x8000UL)
-
-/*
- * The partid is encapsulated in the MAC address beginning in the following
- * octet and it consists of two octets.
- */
-#define XPNET_PARTID_OCTET	2
-
-/* Define the XPNET debug device structures to be used with dev_dbg() et al */
-
-static struct device_driver xpnet_dbg_name = {
-	.name = "xpnet"
-};
-
-static struct device xpnet_dbg_subname = {
-	.init_name = "",	/* set to "" */
-	.driver = &xpnet_dbg_name
-};
-
-static struct device *xpnet = &xpnet_dbg_subname;
-
-/*
- * Packet was recevied by XPC and forwarded to us.
- */
-static void
-xpnet_receive(short partid, int channel, struct xpnet_message *msg)
-{
-	struct sk_buff *skb;
-	void *dst;
-	enum xp_retval ret;
-
-	if (!XPNET_VALID_MSG(msg)) {
-		/*
-		 * Packet with a different XPC version.  Ignore.
-		 */
-		xpc_received(partid, channel, (void *)msg);
-
-		xpnet_device->stats.rx_errors++;
-
-		return;
-	}
-	dev_dbg(xpnet, "received 0x%lx, %d, %d, %d\n", msg->buf_pa, msg->size,
-		msg->leadin_ignore, msg->tailout_ignore);
-
-	/* reserve an extra cache line */
-	skb = dev_alloc_skb(msg->size + L1_CACHE_BYTES);
-	if (!skb) {
-		dev_err(xpnet, "failed on dev_alloc_skb(%d)\n",
-			msg->size + L1_CACHE_BYTES);
-
-		xpc_received(partid, channel, (void *)msg);
-
-		xpnet_device->stats.rx_errors++;
-
-		return;
-	}
-
-	/*
-	 * The allocated skb has some reserved space.
-	 * In order to use xp_remote_memcpy(), we need to get the
-	 * skb->data pointer moved forward.
-	 */
-	skb_reserve(skb, (L1_CACHE_BYTES - ((u64)skb->data &
-					    (L1_CACHE_BYTES - 1)) +
-			  msg->leadin_ignore));
-
-	/*
-	 * Update the tail pointer to indicate data actually
-	 * transferred.
-	 */
-	skb_put(skb, (msg->size - msg->leadin_ignore - msg->tailout_ignore));
-
-	/*
-	 * Move the data over from the other side.
-	 */
-	if ((XPNET_VERSION_MINOR(msg->version) == 1) &&
-	    (msg->embedded_bytes != 0)) {
-		dev_dbg(xpnet, "copying embedded message. memcpy(0x%p, 0x%p, "
-			"%lu)\n", skb->data, &msg->data,
-			(size_t)msg->embedded_bytes);
-
-		skb_copy_to_linear_data(skb, &msg->data,
-					(size_t)msg->embedded_bytes);
-	} else {
-		dst = (void *)((u64)skb->data & ~(L1_CACHE_BYTES - 1));
-		dev_dbg(xpnet, "transferring buffer to the skb->data area;\n\t"
-			"xp_remote_memcpy(0x%p, 0x%p, %u)\n", dst,
-					  (void *)msg->buf_pa, msg->size);
-
-		ret = xp_remote_memcpy(xp_pa(dst), msg->buf_pa, msg->size);
-		if (ret != xpSuccess) {
-			/*
-			 * !!! Need better way of cleaning skb.  Currently skb
-			 * !!! appears in_use and we can't just call
-			 * !!! dev_kfree_skb.
-			 */
-			dev_err(xpnet, "xp_remote_memcpy(0x%p, 0x%p, 0x%x) "
-				"returned error=0x%x\n", dst,
-				(void *)msg->buf_pa, msg->size, ret);
-
-			xpc_received(partid, channel, (void *)msg);
-
-			xpnet_device->stats.rx_errors++;
-
-			return;
-		}
-	}
-
-	dev_dbg(xpnet, "<skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
-		"skb->end=0x%p skb->len=%d\n", (void *)skb->head,
-		(void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb),
-		skb->len);
-
-	skb->protocol = eth_type_trans(skb, xpnet_device);
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
-
-	dev_dbg(xpnet, "passing skb to network layer\n"
-		"\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p "
-		"skb->end=0x%p skb->len=%d\n",
-		(void *)skb->head, (void *)skb->data, skb_tail_pointer(skb),
-		skb_end_pointer(skb), skb->len);
-
-	xpnet_device->stats.rx_packets++;
-	xpnet_device->stats.rx_bytes += skb->len + ETH_HLEN;
-
-	netif_rx(skb);
-	xpc_received(partid, channel, (void *)msg);
-}
-
-/*
- * This is the handler which XPC calls during any sort of change in
- * state or message reception on a connection.
- */
-static void
-xpnet_connection_activity(enum xp_retval reason, short partid, int channel,
-			  void *data, void *key)
-{
-	DBUG_ON(partid < 0 || partid >= xp_max_npartitions);
-	DBUG_ON(channel != XPC_NET_CHANNEL);
-
-	switch (reason) {
-	case xpMsgReceived:	/* message received */
-		DBUG_ON(data == NULL);
-
-		xpnet_receive(partid, channel, (struct xpnet_message *)data);
-		break;
-
-	case xpConnected:	/* connection completed to a partition */
-		spin_lock_bh(&xpnet_broadcast_lock);
-		__set_bit(partid, xpnet_broadcast_partitions);
-		spin_unlock_bh(&xpnet_broadcast_lock);
-
-		netif_carrier_on(xpnet_device);
-
-		dev_dbg(xpnet, "%s connected to partition %d\n",
-			xpnet_device->name, partid);
-		break;
-
-	default:
-		spin_lock_bh(&xpnet_broadcast_lock);
-		__clear_bit(partid, xpnet_broadcast_partitions);
-		spin_unlock_bh(&xpnet_broadcast_lock);
-
-		if (bitmap_empty(xpnet_broadcast_partitions,
-				 xp_max_npartitions)) {
-			netif_carrier_off(xpnet_device);
-		}
-
-		dev_dbg(xpnet, "%s disconnected from partition %d\n",
-			xpnet_device->name, partid);
-		break;
-	}
-}
-
-static int
-xpnet_dev_open(struct net_device *dev)
-{
-	enum xp_retval ret;
-
-	dev_dbg(xpnet, "calling xpc_connect(%d, 0x%p, NULL, %ld, %ld, %ld, "
-		"%ld)\n", XPC_NET_CHANNEL, xpnet_connection_activity,
-		(unsigned long)XPNET_MSG_SIZE,
-		(unsigned long)XPNET_MSG_NENTRIES,
-		(unsigned long)XPNET_MAX_KTHREADS,
-		(unsigned long)XPNET_MAX_IDLE_KTHREADS);
-
-	ret = xpc_connect(XPC_NET_CHANNEL, xpnet_connection_activity, NULL,
-			  XPNET_MSG_SIZE, XPNET_MSG_NENTRIES,
-			  XPNET_MAX_KTHREADS, XPNET_MAX_IDLE_KTHREADS);
-	if (ret != xpSuccess) {
-		dev_err(xpnet, "ifconfig up of %s failed on XPC connect, "
-			"ret=%d\n", dev->name, ret);
-
-		return -ENOMEM;
-	}
-
-	dev_dbg(xpnet, "ifconfig up of %s; XPC connected\n", dev->name);
-
-	return 0;
-}
-
-static int
-xpnet_dev_stop(struct net_device *dev)
-{
-	xpc_disconnect(XPC_NET_CHANNEL);
-
-	dev_dbg(xpnet, "ifconfig down of %s; XPC disconnected\n", dev->name);
-
-	return 0;
-}
-
-/*
- * Notification that the other end has received the message and
- * DMA'd the skb information.  At this point, they are done with
- * our side.  When all recipients are done processing, we
- * release the skb and then release our pending message structure.
- */
-static void
-xpnet_send_completed(enum xp_retval reason, short partid, int channel,
-		     void *__qm)
-{
-	struct xpnet_pending_msg *queued_msg = (struct xpnet_pending_msg *)__qm;
-
-	DBUG_ON(queued_msg == NULL);
-
-	dev_dbg(xpnet, "message to %d notified with reason %d\n",
-		partid, reason);
-
-	if (atomic_dec_return(&queued_msg->use_count) == 0) {
-		dev_dbg(xpnet, "all acks for skb->head=-x%p\n",
-			(void *)queued_msg->skb->head);
-
-		dev_kfree_skb_any(queued_msg->skb);
-		kfree(queued_msg);
-	}
-}
-
-static void
-xpnet_send(struct sk_buff *skb, struct xpnet_pending_msg *queued_msg,
-	   u64 start_addr, u64 end_addr, u16 embedded_bytes, int dest_partid)
-{
-	u8 msg_buffer[XPNET_MSG_SIZE];
-	struct xpnet_message *msg = (struct xpnet_message *)&msg_buffer;
-	u16 msg_size = sizeof(struct xpnet_message);
-	enum xp_retval ret;
-
-	msg->embedded_bytes = embedded_bytes;
-	if (unlikely(embedded_bytes != 0)) {
-		msg->version = XPNET_VERSION_EMBED;
-		dev_dbg(xpnet, "calling memcpy(0x%p, 0x%p, 0x%lx)\n",
-			&msg->data, skb->data, (size_t)embedded_bytes);
-		skb_copy_from_linear_data(skb, &msg->data,
-					  (size_t)embedded_bytes);
-		msg_size += embedded_bytes - 1;
-	} else {
-		msg->version = XPNET_VERSION;
-	}
-	msg->magic = XPNET_MAGIC;
-	msg->size = end_addr - start_addr;
-	msg->leadin_ignore = (u64)skb->data - start_addr;
-	msg->tailout_ignore = end_addr - (u64)skb_tail_pointer(skb);
-	msg->buf_pa = xp_pa((void *)start_addr);
-
-	dev_dbg(xpnet, "sending XPC message to %d:%d\n"
-		"msg->buf_pa=0x%lx, msg->size=%u, "
-		"msg->leadin_ignore=%u, msg->tailout_ignore=%u\n",
-		dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size,
-		msg->leadin_ignore, msg->tailout_ignore);
-
-	atomic_inc(&queued_msg->use_count);
-
-	ret = xpc_send_notify(dest_partid, XPC_NET_CHANNEL, XPC_NOWAIT, msg,
-			      msg_size, xpnet_send_completed, queued_msg);
-	if (unlikely(ret != xpSuccess))
-		atomic_dec(&queued_msg->use_count);
-}
-
-/*
- * Network layer has formatted a packet (skb) and is ready to place it
- * "on the wire".  Prepare and send an xpnet_message to all partitions
- * which have connected with us and are targets of this packet.
- *
- * MAC-NOTE:  For the XPNET driver, the MAC address contains the
- * destination partid.  If the destination partid octets are 0xffff,
- * this packet is to be broadcast to all connected partitions.
- */
-static netdev_tx_t
-xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct xpnet_pending_msg *queued_msg;
-	u64 start_addr, end_addr;
-	short dest_partid;
-	u16 embedded_bytes = 0;
-
-	dev_dbg(xpnet, ">skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
-		"skb->end=0x%p skb->len=%d\n", (void *)skb->head,
-		(void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb),
-		skb->len);
-
-	if (skb->data[0] == 0x33) {
-		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;	/* nothing needed to be done */
-	}
-
-	/*
-	 * The xpnet_pending_msg tracks how many outstanding
-	 * xpc_send_notifies are relying on this skb.  When none
-	 * remain, release the skb.
-	 */
-	queued_msg = kmalloc_obj(struct xpnet_pending_msg, GFP_ATOMIC);
-	if (queued_msg == NULL) {
-		dev_warn(xpnet, "failed to kmalloc %ld bytes; dropping "
-			 "packet\n", sizeof(struct xpnet_pending_msg));
-
-		dev->stats.tx_errors++;
-		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	/* get the beginning of the first cacheline and end of last */
-	start_addr = ((u64)skb->data & ~(L1_CACHE_BYTES - 1));
-	end_addr = L1_CACHE_ALIGN((u64)skb_tail_pointer(skb));
-
-	/* calculate how many bytes to embed in the XPC message */
-	if (unlikely(skb->len <= XPNET_MSG_DATA_MAX)) {
-		/* skb->data does fit so embed */
-		embedded_bytes = skb->len;
-	}
-
-	/*
-	 * Since the send occurs asynchronously, we set the count to one
-	 * and begin sending.  Any sends that happen to complete before
-	 * we are done sending will not free the skb.  We will be left
-	 * with that task during exit.  This also handles the case of
-	 * a packet destined for a partition which is no longer up.
-	 */
-	atomic_set(&queued_msg->use_count, 1);
-	queued_msg->skb = skb;
-
-	if (skb->data[0] == 0xff) {
-		/* we are being asked to broadcast to all partitions */
-		for_each_set_bit(dest_partid, xpnet_broadcast_partitions,
-			     xp_max_npartitions) {
-
-			xpnet_send(skb, queued_msg, start_addr, end_addr,
-				   embedded_bytes, dest_partid);
-		}
-	} else {
-		dest_partid = (short)skb->data[XPNET_PARTID_OCTET + 1];
-		dest_partid |= (short)skb->data[XPNET_PARTID_OCTET + 0] << 8;
-
-		if (dest_partid >= 0 &&
-		    dest_partid < xp_max_npartitions &&
-		    test_bit(dest_partid, xpnet_broadcast_partitions) != 0) {
-
-			xpnet_send(skb, queued_msg, start_addr, end_addr,
-				   embedded_bytes, dest_partid);
-		}
-	}
-
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
-
-	if (atomic_dec_return(&queued_msg->use_count) == 0) {
-		dev_kfree_skb(skb);
-		kfree(queued_msg);
-	}
-
-	return NETDEV_TX_OK;
-}
-
-/*
- * Deal with transmit timeouts coming from the network layer.
- */
-static void
-xpnet_dev_tx_timeout(struct net_device *dev, unsigned int txqueue)
-{
-	dev->stats.tx_errors++;
-}
-
-static const struct net_device_ops xpnet_netdev_ops = {
-	.ndo_open		= xpnet_dev_open,
-	.ndo_stop		= xpnet_dev_stop,
-	.ndo_start_xmit		= xpnet_dev_hard_start_xmit,
-	.ndo_tx_timeout		= xpnet_dev_tx_timeout,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-static int __init
-xpnet_init(void)
-{
-	u8 addr[ETH_ALEN];
-	int result;
-
-	if (!is_uv_system())
-		return -ENODEV;
-
-	dev_info(xpnet, "registering network device %s\n", XPNET_DEVICE_NAME);
-
-	xpnet_broadcast_partitions = bitmap_zalloc(xp_max_npartitions,
-						   GFP_KERNEL);
-	if (xpnet_broadcast_partitions == NULL)
-		return -ENOMEM;
-
-	/*
-	 * use ether_setup() to init the majority of our device
-	 * structure and then override the necessary pieces.
-	 */
-	xpnet_device = alloc_netdev(0, XPNET_DEVICE_NAME, NET_NAME_UNKNOWN,
-				    ether_setup);
-	if (xpnet_device == NULL) {
-		bitmap_free(xpnet_broadcast_partitions);
-		return -ENOMEM;
-	}
-
-	netif_carrier_off(xpnet_device);
-
-	xpnet_device->netdev_ops = &xpnet_netdev_ops;
-	xpnet_device->mtu = XPNET_DEF_MTU;
-	xpnet_device->min_mtu = XPNET_MIN_MTU;
-	xpnet_device->max_mtu = XPNET_MAX_MTU;
-
-	memset(addr, 0, sizeof(addr));
-	/*
-	 * Multicast assumes the LSB of the first octet is set for multicast
-	 * MAC addresses.  We chose the first octet of the MAC to be unlikely
-	 * to collide with any vendor's officially issued MAC.
-	 */
-	addr[0] = 0x02;     /* locally administered, no OUI */
-
-	addr[XPNET_PARTID_OCTET + 1] = xp_partition_id;
-	addr[XPNET_PARTID_OCTET + 0] = (xp_partition_id >> 8);
-	eth_hw_addr_set(xpnet_device, addr);
-
-	/*
-	 * ether_setup() sets this to a multicast device.  We are
-	 * really not supporting multicast at this time.
-	 */
-	xpnet_device->flags &= ~IFF_MULTICAST;
-
-	/*
-	 * No need to checksum as it is a DMA transfer.  The BTE will
-	 * report an error if the data is not retrievable and the
-	 * packet will be dropped.
-	 */
-	xpnet_device->features = NETIF_F_HW_CSUM;
-
-	result = register_netdev(xpnet_device);
-	if (result != 0) {
-		free_netdev(xpnet_device);
-		bitmap_free(xpnet_broadcast_partitions);
-	}
-
-	return result;
-}
-
-module_init(xpnet_init);
-
-static void __exit
-xpnet_exit(void)
-{
-	dev_info(xpnet, "unregistering network device %s\n",
-		 xpnet_device[0].name);
-
-	unregister_netdev(xpnet_device);
-	free_netdev(xpnet_device);
-	bitmap_free(xpnet_broadcast_partitions);
-}
-
-module_exit(xpnet_exit);
-
-MODULE_AUTHOR("Silicon Graphics, Inc.");
-MODULE_DESCRIPTION("Cross Partition Network adapter (XPNET)");
-MODULE_LICENSE("GPL");
-- 
2.43.0


  reply	other threads:[~2026-07-31 14:30 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-31 14:26 [PATCH 0/2] Remove the sgi-gru and sgi-xp drivers Dimitri Sivanich
2026-07-31 14:30 ` Dimitri Sivanich [this message]
2026-07-31 14:37 ` [PATCH 2/2] misc: sgi-gru: Remove SGI GRU driver Dimitri Sivanich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=amyxgPYeowzWt_8W@hpe.com \
    --to=sivanich@hpe.com \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=david@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=kees@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=ljs@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=robinmholt@gmail.com \
    --cc=russ.anderson@hpe.com \
    --cc=steve.wahl@hpe.com \
    --cc=usama.anjum@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox